source: trunk/src/kernel/qfont_pm.cpp@ 20

Last change on this file since 20 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 14.0 KB
Line 
1/****************************************************************************
2** $Id: qfont_pm.cpp 8 2005-11-16 19:36:46Z dmik $
3**
4** Implementation of QFont, QFontMetrics and QFontInfo classes for OS/2
5**
6** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
7** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
8** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qfont.h"
39#include "qfontdata_p.h"
40#include "qfontengine_p.h"
41#include "qfontmetrics.h"
42#include "qfontinfo.h"
43
44#include "qwidget.h"
45#include "qpainter.h"
46#include "qdict.h"
47#include "qcache.h"
48#include <limits.h>
49#include "qt_os2.h"
50#include "qapplication_p.h"
51#include "qapplication.h"
52#include "qpaintdevicemetrics.h"
53#include <private/qunicodetables_p.h>
54#include <qfontdatabase.h>
55
56
57QString qt_pm_default_family( uint styleHint )
58{
59 switch( styleHint ) {
60 case QFont::Times:
61 return QString::fromLatin1("Times New Roman");
62 case QFont::Courier:
63 return QString::fromLatin1("Courier");
64 case QFont::Decorative:
65 return QString::fromLatin1("Times New Roman");
66 case QFont::Helvetica:
67 return QString::fromLatin1("Helvetica");
68 case QFont::System:
69//@@TODO (dmik): check for OS/2 ver and return the appropriate system font
70// (i.e. "System Proportional" for ver <= Warp 3)
71 return QString::fromLatin1("WarpSans");
72 default:
73 // the family to be used when no StyleHint is set (in accordance
74 // with the font matching algorithm stated in QFont docs)
75 return QString::fromLatin1("Helvetica");
76 }
77//@@TODO (dmik): should we also add default font substitutions to
78// initFontSubst()?
79}
80
81//@@TODO (dmik): remove
82//extern HDC shared_dc; // common dc for all fonts
83
84//@@TODO (dmik): remove?
85//// ### maybe move to qapplication_win
86//QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/)
87//{
88// QString family = QT_WA_INLINE( QString::fromUcs2((ushort*)lf.lfFaceName),
89// QString::fromLocal8Bit((char*)lf.lfFaceName) );
90// QFont qf(family);
91// qf.setItalic(lf.lfItalic);
92// if (lf.lfWeight != FW_DONTCARE) {
93// int weight;
94// if ( lf.lfWeight < 400 )
95// weight = QFont::Light;
96// else if ( lf.lfWeight < 600 )
97// weight = QFont::Normal;
98// else if ( lf.lfWeight < 700 )
99// weight = QFont::DemiBold;
100// else if ( lf.lfWeight < 800 )
101// weight = QFont::Bold;
102// else
103// weight = QFont::Black;
104// qf.setWeight(weight);
105// }
106// int lfh = QABS( lf.lfHeight );
107// Q_ASSERT(shared_dc);
108// qf.setPointSizeFloat( lfh * 72.0 / GetDeviceCaps(shared_dc,LOGPIXELSY) );
109// qf.setUnderline(FALSE);
110// qf.setOverline(FALSE);
111// qf.setStrikeOut(FALSE);
112// return qf;
113//}
114
115
116//@@TODO (dmik): need these two funcs?
117//static inline float pixelSize( const QFontDef &request, QPaintDevice *paintdevice,
118// int )
119//{
120// float pSize;
121// if ( request.pointSize != -1 ) {
122// if ( paintdevice ) {
123// pSize = request.pointSize *
124// QPaintDeviceMetrics( paintdevice ).logicalDpiY() / 720.;
125// } else {
126// LONG dpi;
127// DevQueryCaps( GpiQueryDevice( qt_display_ps() ),
128// CAPS_VERTICAL_FONT_RES, 1, &val );
129// pSize = (request.pointSize*dpi + 360) / 720;
130// }
131// } else {
132// pSize = request.pixelSize;
133// }
134// return pSize;
135//}
136//
137//static inline float pointSize( const QFontDef &fd, QPaintDevice *paintdevice,
138// int )
139//{
140// float pSize;
141// if ( fd.pointSize == -1 ) {
142// if ( paintdevice ) {
143// pSize = fd.pixelSize * 720. /
144// QPaintDeviceMetrics( paintdevice ).logicalDpiY();
145// } else {
146// LONG dpi;
147// DevQueryCaps( GpiQueryDevice( qt_display_ps() ),
148// CAPS_VERTICAL_FONT_RES, 1, &val );
149// pSize = fd.pixelSize * 72.0 / dpi;
150// }
151// } else {
152// pSize = fd.pointSize;
153// }
154// return pSize;
155//}
156
157/*****************************************************************************
158 QFont member functions
159 *****************************************************************************/
160
161QFont::Script QFontPrivate::defaultScript = QFont::UnknownScript;
162
163void QFont::initialize()
164{
165 if ( QFontCache::instance )
166 return;
167//@@TODO (dmik): remove
168// shared_dc = CreateCompatibleDC( qt_display_dc() );
169//#if defined(QT_CHECK_RANGE)
170// if ( !shared_dc )
171// qSystemWarning( "QFont::initialize() (qfont_win.cpp, 163): couldn't create device context" );
172//#endif
173 new QFontCache();
174
175 // #########
176 QFontPrivate::defaultScript = QFont::Latin;
177}
178
179void QFont::cleanup()
180{
181 delete QFontCache::instance;
182//@@TODO (dmik): remove
183// DeleteDC( shared_dc );
184// shared_dc = 0;
185}
186
187void QFontPrivate::load( QFont::Script script )
188{
189 // NOTE: the OS/2 implementation of this function is similar to
190 // X11 and Windows implementations (which are identical). if they
191 // change, probably, changes should come here as well...
192
193#ifdef QT_CHECK_STATE
194 // sanity checks
195 if (!QFontCache::instance)
196 qWarning("Must construct a QApplication before a QFont");
197 Q_ASSERT( script >= 0 && script < QFont::LastPrivateScript );
198#endif // QT_CHECK_STATE
199
200 QFontDef req = request;
201 int dpi;
202 if ( paintdevice ) {
203 dpi = QPaintDeviceMetrics( paintdevice ).logicalDpiY();
204 } else {
205 DevQueryCaps( GpiQueryDevice( qt_display_ps() ),
206 CAPS_VERTICAL_FONT_RES, 1, (PLONG) &dpi );
207 }
208 if (req.pointSize != -1)
209 req.pixelSize = (req.pointSize * dpi + 360) / 720;
210 else // assuming (req.pixelSize != -1)
211 req.pointSize = 0;
212
213 if ( ! engineData ) {
214 QFontCache::Key key( req, QFont::NoScript, (int)paintdevice );
215
216 // look for the requested font in the engine data cache
217 engineData = QFontCache::instance->findEngineData( key );
218
219 if ( ! engineData) {
220 // create a new one
221 engineData = new QFontEngineData;
222 QFontCache::instance->insertEngineData( key, engineData );
223 } else {
224 engineData->ref();
225 }
226 }
227
228 // the cached engineData could have already loaded the engine we want
229//@@TODO (dmik): remove?
230// if ( engineData->engines[script] ) return;
231 if ( engineData->engine ) return;
232
233 // load the font
234 QFontEngine *engine = 0;
235 // double scale = 1.0; // ### TODO: fix the scale calculations
236
237 // list of families to try
238 QStringList family_list;
239
240 if (!req.family.isEmpty()) {
241 family_list = QStringList::split( ',', req.family );
242
243 // append the substitute list for each family in family_list
244 QStringList subs_list;
245 QStringList::ConstIterator it = family_list.begin(), end = family_list.end();
246 for ( ; it != end; ++it )
247 subs_list += QFont::substitutes( *it );
248 family_list += subs_list;
249
250//@@TODO (dmik): need something here?
251 // append the default fallback font for the specified script
252 // family_list << ... ; ###########
253
254 // add the family corresponding to font's styleHint
255 QString hintFamily = qt_pm_default_family( request.styleHint );
256 if ( ! family_list.contains( hintFamily ) )
257 family_list << hintFamily;
258
259//@@TODO (dmik): should we also add QFont::lastResortFamily() and
260// QFont::lastResortFont() to the list as stated in QFont docs about the
261// font matching algorithm? Also it's not clear why QApplication font is
262// below added to the list.
263
264 // add the default family
265 QString defaultFamily = QApplication::font().family();
266 if ( ! family_list.contains( defaultFamily ) )
267 family_list << defaultFamily;
268
269 // add QFont::defaultFamily() to the list, for compatibility with
270 // previous versions
271 family_list << QApplication::font().defaultFamily();
272 }
273
274 // null family means find the first font matching the specified script
275 family_list << QString::null;
276
277 QStringList::ConstIterator it = family_list.begin(), end = family_list.end();
278 for ( ; ! engine && it != end; ++it ) {
279 req.family = *it;
280
281 engine = QFontDatabase::findFont( script, this, req );
282 if ( engine ) {
283 if ( engine->type() != QFontEngine::Box )
284 break;
285
286 if ( ! req.family.isEmpty() )
287 engine = 0;
288
289 continue;
290 }
291 }
292
293 engine->ref();
294//@@TODO (dmik): remove?
295// engineData->engines[script] = engine;
296 engineData->engine = engine;
297}
298
299//@@TODO (dmik): do we actually need any handle?
300//PFATTRS QFont::handle() const
301//{
302// QFontEngine *engine = d->engineForScript( QFont::NoScript );
303// return &engine->fa;
304//}
305
306void QFont::selectTo( HPS hps ) const
307{
308 QFontEngine *engine = d->engineForScript( QFont::NoScript );
309#ifdef QT_CHECK_STATE
310 Q_ASSERT( engine != 0 );
311#endif // QT_CHECK_STATE
312 engine->selectTo( hps );
313}
314
315QString QFont::rawName() const
316{
317//@@TODO (dmik): use szFacename here?
318 return family();
319}
320
321void QFont::setRawName( const QString &name )
322{
323 setFamily( name );
324}
325
326
327bool QFont::dirty() const
328{
329 return !d->engineData;
330}
331
332
333QString QFont::defaultFamily() const
334{
335 return qt_pm_default_family( d->request.styleHint );
336}
337
338QString QFont::lastResortFamily() const
339{
340 return qt_pm_default_family( QFont::AnyStyle );
341}
342
343QString QFont::lastResortFont() const
344{
345 return QString::fromLatin1("System Proportional");
346}
347
348
349
350/*****************************************************************************
351 QFontMetrics member functions
352 *****************************************************************************/
353
354//@@TODO (dmik): remove
355//#define IS_TRUETYPE (QT_WA_INLINE( engine->tm.w.tmPitchAndFamily, engine->tm.a.tmPitchAndFamily ) & TMPF_TRUETYPE)
356//#define TMX engine->tm.w
357//#define TMW engine->tm.w
358//#define TMA engine->tm.a
359
360//@@TODO (dmik): do we need a separate (other than in qfont.cpp)
361// implementation of this func?
362//int QFontMetrics::leftBearing(QChar ch) const
363//{
364//#ifdef Q_OS_TEMP
365// return 0;
366//#else
367// QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
368//#ifdef QT_CHECK_STATE
369// Q_ASSERT( engine != 0 );
370//#endif // QT_CHECK_STATE
371//
372// if ( IS_TRUETYPE ) {
373// ABC abc;
374// QT_WA( {
375// uint ch16 = ch.unicode();
376// GetCharABCWidths(engine->dc(),ch16,ch16,&abc);
377// } , {
378// uint ch8;
379// if ( ch.row() || ch.cell() > 127 ) {
380// QCString w = QString(ch).local8Bit();
381// if ( w.length() != 1 )
382// return 0;
383// ch8 = (uchar)w[0];
384// } else {
385// ch8 = ch.cell();
386// }
387// GetCharABCWidthsA(engine->dc(),ch8,ch8,&abc);
388// } );
389// return abc.abcA;
390// } else {
391// QT_WA( {
392// uint ch16 = ch.unicode();
393// ABCFLOAT abc;
394// GetCharABCWidthsFloat(engine->dc(),ch16,ch16,&abc);
395// return int(abc.abcfA);
396// } , {
397// return 0;
398// } );
399// }
400// return 0;
401//#endif
402//}
403
404
405//@@TODO (dmik): do we need a separate (other than in qfont.cpp)
406// implementation of this func?
407//int QFontMetrics::rightBearing(QChar ch) const
408//{
409// return 0;
410//#ifdef Q_OS_TEMP
411// return 0;
412//#else
413// QFontEngine *engine = d->engineForScript( (QFont::Script) fscript );
414//#ifdef QT_CHECK_STATE
415// Q_ASSERT( engine != 0 );
416//#endif // QT_CHECK_STATE
417//
418// if ( IS_TRUETYPE ) {
419// ABC abc;
420// QT_WA( {
421// uint ch16 = ch.unicode();
422// GetCharABCWidths(engine->dc(),ch16,ch16,&abc);
423// return abc.abcC;
424// } , {
425// uint ch8;
426// if ( ch.row() || ch.cell() > 127 ) {
427// QCString w = QString(ch).local8Bit();
428// if ( w.length() != 1 )
429// return 0;
430// ch8 = (uchar)w[0];
431// } else {
432// ch8 = ch.cell();
433// }
434// GetCharABCWidthsA(engine->dc(),ch8,ch8,&abc);
435// } );
436// return abc.abcC;
437// } else {
438// QT_WA( {
439// uint ch16 = ch.unicode();
440// ABCFLOAT abc;
441// GetCharABCWidthsFloat(engine->dc(),ch16,ch16,&abc);
442// return int(abc.abcfC);
443// } , {
444// return -TMW.tmOverhang;
445// } );
446// }
447//
448// return 0;
449//#endif
450//}
451
452
453int QFontMetrics::width( QChar ch ) const
454{
455 if ( ::category( ch ) == QChar::Mark_NonSpacing )
456 return 0;
457
458 QFont::Script script;
459 SCRIPT_FOR_CHAR( script, ch );
460
461 QFontEngine *engine = d->engineForScript( script );
462#ifdef QT_CHECK_STATE
463 Q_ASSERT( engine != 0 );
464#endif // QT_CHECK_STATE
465
466 if ( painter )
467 painter->setNativeXForm( FALSE /* assumeYNegation */);
468
469 glyph_t glyphs[8];
470 advance_t advances[8];
471
472 int nglyphs = 7;
473 engine->stringToCMap( &ch, 1, glyphs, advances, &nglyphs, FALSE );
474
475 if ( painter )
476 painter->clearNativeXForm();
477
478 return advances[0];
479}
480
481
482int QFontMetrics::charWidth( const QString &str, int pos ) const
483{
484 if ( pos < 0 || pos > (int)str.length() )
485 return 0;
486
487 if ( painter )
488 painter->setNativeXForm( FALSE /* assumeYNegation */);
489
490 QTextEngine layout( str, d );
491 layout.itemize( QTextEngine::WidthOnly );
492 int w = layout.width( pos, 1 );
493
494 if ( painter )
495 painter->clearNativeXForm();
496
497 return w;
498}
Note: See TracBrowser for help on using the repository browser.