1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #if _WIN32_WINNT < 0x0500
43 #undef _WIN32_WINNT
44 #define _WIN32_WINNT 0x0500
45 #endif
46 
47 #include "qfontengine_p.h"
48 #include "qtextengine_p.h"
49 #include <qglobal.h>
50 #include "qt_windows.h"
51 #include <private/qapplication_p.h>
52 
53 #include <private/qsystemlibrary_p.h>
54 #include <qpaintdevice.h>
55 #include <qpainter.h>
56 #include <limits.h>
57 
58 #include <qendian.h>
59 #include <qmath.h>
60 #include <qthreadstorage.h>
61 
62 #include <private/qunicodetables_p.h>
63 #include <qbitmap.h>
64 
65 #include <private/qpainter_p.h>
66 #include "qpaintengine.h"
67 #include "qvarlengtharray.h"
68 #include <private/qpaintengine_raster_p.h>
69 #include <private/qnativeimage_p.h>
70 
71 #if defined(Q_WS_WINCE)
72 #include "qguifunctions_wince.h"
73 #endif
74 
75 //### mingw needed define
76 #ifndef TT_PRIM_CSPLINE
77 #define TT_PRIM_CSPLINE 3
78 #endif
79 
80 #ifdef MAKE_TAG
81 #undef MAKE_TAG
82 #endif
83 // GetFontData expects the tags in little endian ;(
84 #define MAKE_TAG(ch1, ch2, ch3, ch4) (\
85     (((quint32)(ch4)) << 24) | \
86     (((quint32)(ch3)) << 16) | \
87     (((quint32)(ch2)) << 8) | \
88     ((quint32)(ch1)) \
89    )
90 
91 // common DC for all fonts
92 
93 QT_BEGIN_NAMESPACE
94 
95 class QtHDC
96 {
97     HDC _hdc;
98 public:
QtHDC()99     QtHDC()
100     {
101         HDC displayDC = GetDC(0);
102         _hdc = CreateCompatibleDC(displayDC);
103         ReleaseDC(0, displayDC);
104     }
~QtHDC()105     ~QtHDC()
106     {
107         if (_hdc)
108             DeleteDC(_hdc);
109     }
hdc() const110     HDC hdc() const
111     {
112         return _hdc;
113     }
114 };
115 
116 #ifndef QT_NO_THREAD
Q_GLOBAL_STATIC(QThreadStorage<QtHDC * >,local_shared_dc)117 Q_GLOBAL_STATIC(QThreadStorage<QtHDC *>, local_shared_dc)
118 HDC shared_dc()
119 {
120     QtHDC *&hdc = local_shared_dc()->localData();
121     if (!hdc)
122         hdc = new QtHDC;
123     return hdc->hdc();
124 }
125 #else
shared_dc()126 HDC shared_dc()
127 {
128     return 0;
129 }
130 #endif
131 
132 #ifndef Q_WS_WINCE
133 typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT);
134 static PtrGetCharWidthI ptrGetCharWidthI = 0;
135 static bool resolvedGetCharWidthI = false;
136 
resolveGetCharWidthI()137 static void resolveGetCharWidthI()
138 {
139     if (resolvedGetCharWidthI)
140         return;
141 
142     QSystemLibrary gdi32(QLatin1String("gdi32"));
143     ptrGetCharWidthI = (PtrGetCharWidthI)gdi32.resolve("GetCharWidthI");
144 
145     resolvedGetCharWidthI = true;
146 }
147 #endif // !defined(Q_WS_WINCE)
148 
149 // defined in qtextengine_win.cpp
150 typedef void *SCRIPT_CACHE;
151 typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *);
152 extern fScriptFreeCache ScriptFreeCache;
153 
getUInt(unsigned char * p)154 static inline quint32 getUInt(unsigned char *p)
155 {
156     quint32 val;
157     val = *p++ << 24;
158     val |= *p++ << 16;
159     val |= *p++ << 8;
160     val |= *p;
161 
162     return val;
163 }
164 
getUShort(unsigned char * p)165 static inline quint16 getUShort(unsigned char *p)
166 {
167     quint16 val;
168     val = *p++ << 8;
169     val |= *p;
170 
171     return val;
172 }
173 
174 // general font engine
175 
lineThickness() const176 QFixed QFontEngineWin::lineThickness() const
177 {
178     if(lineWidth > 0)
179         return lineWidth;
180 
181     return QFontEngine::lineThickness();
182 }
183 
getOutlineTextMetric(HDC hdc)184 static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
185 {
186     int size;
187     size = GetOutlineTextMetrics(hdc, 0, 0);
188     OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size);
189     GetOutlineTextMetrics(hdc, size, otm);
190     return otm;
191 }
192 
hasCFFTable() const193 bool QFontEngineWin::hasCFFTable() const
194 {
195     HDC hdc = shared_dc();
196     SelectObject(hdc, hfont);
197     return GetFontData(hdc, MAKE_TAG('C', 'F', 'F', ' '), 0, 0, 0) != GDI_ERROR;
198 }
199 
hasCMapTable() const200 bool QFontEngineWin::hasCMapTable() const
201 {
202     HDC hdc = shared_dc();
203     SelectObject(hdc, hfont);
204     return GetFontData(hdc, MAKE_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR;
205 }
206 
getCMap()207 void QFontEngineWin::getCMap()
208 {
209     ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable();
210 
211     cffTable = hasCFFTable();
212 
213     HDC hdc = shared_dc();
214     SelectObject(hdc, hfont);
215     bool symb = false;
216     if (ttf) {
217         cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
218         cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
219                        cmapTable.size(), &symb, &cmapSize);
220     }
221     if (!cmap) {
222         ttf = false;
223         symb = false;
224     }
225     symbol = symb;
226     designToDevice = 1;
227     _faceId.index = 0;
228     if(cmap) {
229         OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
230         designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight);
231         unitsPerEm = otm->otmEMSquare;
232         x_height = (int)otm->otmsXHeight;
233         loadKerningPairs(designToDevice);
234         _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1();
235         lineWidth = otm->otmsUnderscoreSize;
236         fsType = otm->otmfsType;
237         free(otm);
238     } else {
239         unitsPerEm = tm.tmHeight;
240     }
241 }
242 
243 
getChar(const QChar * str,int & i,const int len)244 inline unsigned int getChar(const QChar *str, int &i, const int len)
245 {
246     uint ucs4 = str[i].unicode();
247     if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()) {
248         ++i;
249         ucs4 = QChar::surrogateToUcs4(ucs4, str[i].unicode());
250     }
251     return ucs4;
252 }
253 
getGlyphIndexes(const QChar * str,int numChars,QGlyphLayout * glyphs,bool mirrored) const254 int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, bool mirrored) const
255 {
256     int i = 0;
257     int glyph_pos = 0;
258     if (mirrored) {
259 #if defined(Q_WS_WINCE)
260         {
261 #else
262         if (symbol) {
263             for (; i < numChars; ++i, ++glyph_pos) {
264                 unsigned int uc = getChar(str, i, numChars);
265                 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
266                 if (!glyphs->glyphs[glyph_pos] && uc < 0x100)
267                     glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
268             }
269         } else if (ttf) {
270             for (; i < numChars; ++i, ++glyph_pos) {
271                 unsigned int uc = getChar(str, i, numChars);
272                 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, QChar::mirroredChar(uc));
273             }
274         } else {
275 #endif
276             wchar_t first = tm.tmFirstChar;
277             wchar_t last = tm.tmLastChar;
278 
279             for (; i < numChars; ++i, ++glyph_pos) {
280                 uint ucs = QChar::mirroredChar(getChar(str, i, numChars));
281                 if (
282 #ifdef Q_WS_WINCE
283                     tm.tmFirstChar > 60000 || // see line 375
284 #endif
285                         ucs >= first && ucs <= last)
286                     glyphs->glyphs[glyph_pos] = ucs;
287                 else
288                     glyphs->glyphs[glyph_pos] = 0;
289             }
290         }
291     } else {
292 #if defined(Q_WS_WINCE)
293         {
294 #else
295         if (symbol) {
296             for (; i < numChars; ++i, ++glyph_pos) {
297                 unsigned int uc = getChar(str, i, numChars);
298                 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
299                 if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
300                     glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
301             }
302         } else if (ttf) {
303             for (; i < numChars; ++i, ++glyph_pos) {
304                 unsigned int uc = getChar(str, i, numChars);
305                 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
306             }
307         } else {
308 #endif
309             wchar_t first = tm.tmFirstChar;
310             wchar_t last = tm.tmLastChar;
311 
312             for (; i < numChars; ++i, ++glyph_pos) {
313                 uint uc = getChar(str, i, numChars);
314                 if (
315 #ifdef Q_WS_WINCE
316                     tm.tmFirstChar > 60000 || // see comment in QFontEngineWin
317 #endif
318                         uc >= first && uc <= last)
319                     glyphs->glyphs[glyph_pos] = uc;
320                 else
321                     glyphs->glyphs[glyph_pos] = 0;
322             }
323         }
324     }
325     glyphs->numGlyphs = glyph_pos;
326     return glyph_pos;
327 }
328 
329 
330 QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont, LOGFONT lf)
331 {
332     //qDebug("regular windows font engine created: font='%s', size=%d", name, lf.lfHeight);
333 
334     _name = name;
335 
336     cmap = 0;
337     cmapSize = 0;
338     hfont = _hfont;
339     logfont = lf;
340     HDC hdc = shared_dc();
341     SelectObject(hdc, hfont);
342     this->stockFont = stockFont;
343     fontDef.pixelSize = -lf.lfHeight;
344 
345     lbearing = SHRT_MIN;
346     rbearing = SHRT_MIN;
347     synthesized_flags = -1;
348     lineWidth = -1;
349     x_height = -1;
350 
351     BOOL res = GetTextMetrics(hdc, &tm);
352     fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
353     if (!res) {
354         qErrnoWarning("QFontEngineWin: GetTextMetrics failed");
355         ZeroMemory(&tm, sizeof(TEXTMETRIC));
356     }
357 
358     cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000;
359     getCMap();
360 
361     widthCache = 0;
362     widthCacheSize = 0;
363     designAdvances = 0;
364     designAdvancesSize = 0;
365 
366 #ifndef Q_WS_WINCE
367     if (!resolvedGetCharWidthI)
368         resolveGetCharWidthI();
369 #endif
370 }
371 
372 QFontEngineWin::~QFontEngineWin()
373 {
374     if (designAdvances)
375         free(designAdvances);
376 
377     if (widthCache)
378         free(widthCache);
379 
380     // make sure we aren't by accident still selected
381     SelectObject(shared_dc(), (HFONT)GetStockObject(SYSTEM_FONT));
382 
383     if (!stockFont) {
384         if (!DeleteObject(hfont))
385             qErrnoWarning("QFontEngineWin: failed to delete non-stock font...");
386     }
387 }
388 
389 HGDIOBJ QFontEngineWin::selectDesignFont() const
390 {
391     LOGFONT f = logfont;
392     f.lfHeight = unitsPerEm;
393     f.lfWidth = 0;
394     HFONT designFont = CreateFontIndirect(&f);
395     return SelectObject(shared_dc(), designFont);
396 }
397 
398 bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
399 {
400     if (*nglyphs < len) {
401         *nglyphs = len;
402         return false;
403     }
404 
405     *nglyphs = getGlyphIndexes(str, len, glyphs, flags & QTextEngine::RightToLeft);
406 
407     if (flags & QTextEngine::GlyphIndicesOnly)
408         return true;
409 
410     recalcAdvances(glyphs, flags);
411     return true;
412 }
413 
414 inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
415 {
416 #if defined(Q_WS_WINCE)
417     GetCharWidth32(hdc, glyph, glyph, &width);
418 #else
419     if (ptrGetCharWidthI)
420         ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
421 #endif
422 }
423 
424 void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
425 {
426     HGDIOBJ oldFont = 0;
427     HDC hdc = shared_dc();
428     if (ttf && (flags & QTextEngine::DesignMetrics)) {
429         for(int i = 0; i < glyphs->numGlyphs; i++) {
430             unsigned int glyph = glyphs->glyphs[i];
431             if(int(glyph) >= designAdvancesSize) {
432                 int newSize = (glyph + 256) >> 8 << 8;
433                 designAdvances = q_check_ptr((QFixed *)realloc(designAdvances,
434                             newSize*sizeof(QFixed)));
435                 for(int i = designAdvancesSize; i < newSize; ++i)
436                     designAdvances[i] = -1000000;
437                 designAdvancesSize = newSize;
438             }
439             if (designAdvances[glyph] < -999999) {
440                 if (!oldFont)
441                     oldFont = selectDesignFont();
442 
443                 int width = 0;
444                 calculateTTFGlyphWidth(hdc, glyph, width);
445                 designAdvances[glyph] = QFixed(width) / designToDevice;
446             }
447             glyphs->advances_x[i] = designAdvances[glyph];
448             glyphs->advances_y[i] = 0;
449         }
450         if(oldFont)
451             DeleteObject(SelectObject(hdc, oldFont));
452     } else {
453         for(int i = 0; i < glyphs->numGlyphs; i++) {
454             unsigned int glyph = glyphs->glyphs[i];
455 
456             glyphs->advances_y[i] = 0;
457 
458             if (glyph >= widthCacheSize) {
459                 int newSize = (glyph + 256) >> 8 << 8;
460                 widthCache = q_check_ptr((unsigned char *)realloc(widthCache,
461                             newSize*sizeof(QFixed)));
462                 memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize);
463                 widthCacheSize = newSize;
464             }
465             glyphs->advances_x[i] = widthCache[glyph];
466             // font-width cache failed
467             if (glyphs->advances_x[i] == 0) {
468                 int width = 0;
469                 if (!oldFont)
470                     oldFont = SelectObject(hdc, hfont);
471 
472                 if (!ttf) {
473                     QChar ch[2] = { ushort(glyph), 0 };
474                     int chrLen = 1;
475                     if (glyph > 0xffff) {
476                         ch[0] = QChar::highSurrogate(glyph);
477                         ch[1] = QChar::lowSurrogate(glyph);
478                         ++chrLen;
479                     }
480                     SIZE size = {0, 0};
481                     GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size);
482                     width = size.cx;
483                 } else {
484                     calculateTTFGlyphWidth(hdc, glyph, width);
485                 }
486                 glyphs->advances_x[i] = width;
487                 // if glyph's within cache range, store it for later
488                 if (width > 0 && width < 0x100)
489                     widthCache[glyph] = width;
490             }
491         }
492 
493         if (oldFont)
494             SelectObject(hdc, oldFont);
495     }
496 }
497 
498 glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs)
499 {
500     if (glyphs.numGlyphs == 0)
501         return glyph_metrics_t();
502 
503     QFixed w = 0;
504     for (int i = 0; i < glyphs.numGlyphs; ++i)
505         w += glyphs.effectiveAdvance(i);
506 
507     return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0);
508 }
509 
510 #ifndef Q_WS_WINCE
511 bool QFontEngineWin::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const
512 {
513     Q_ASSERT(metrics != 0);
514 
515     HDC hdc = shared_dc();
516 
517     GLYPHMETRICS gm;
518     DWORD res = 0;
519     MAT2 mat;
520     mat.eM11.value = mat.eM22.value = 1;
521     mat.eM11.fract = mat.eM22.fract = 0;
522     mat.eM21.value = mat.eM12.value = 0;
523     mat.eM21.fract = mat.eM12.fract = 0;
524 
525     if (t.type() > QTransform::TxTranslate) {
526         // We need to set the transform using the HDC's world
527         // matrix rather than using the MAT2 above, because the
528         // results provided when transforming via MAT2 does not
529         // match the glyphs that are drawn using a WorldTransform
530         XFORM xform;
531         xform.eM11 = t.m11();
532         xform.eM12 = t.m12();
533         xform.eM21 = t.m21();
534         xform.eM22 = t.m22();
535         xform.eDx = 0;
536         xform.eDy = 0;
537         SetGraphicsMode(hdc, GM_ADVANCED);
538         SetWorldTransform(hdc, &xform);
539     }
540 
541     uint format = GGO_METRICS;
542     if (ttf)
543         format |= GGO_GLYPH_INDEX;
544     res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat);
545 
546     if (t.type() > QTransform::TxTranslate) {
547         XFORM xform;
548         xform.eM11 = xform.eM22 = 1;
549         xform.eM12 = xform.eM21 = xform.eDx = xform.eDy = 0;
550         SetWorldTransform(hdc, &xform);
551         SetGraphicsMode(hdc, GM_COMPATIBLE);
552     }
553 
554     if (res != GDI_ERROR) {
555         *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y,
556                                   (int)gm.gmBlackBoxX, (int)gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY);
557         return true;
558     } else {
559         return false;
560     }
561 }
562 #endif
563 
564 glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t)
565 {
566 #ifndef Q_WS_WINCE
567     HDC hdc = shared_dc();
568     SelectObject(hdc, hfont);
569 
570     glyph_metrics_t glyphMetrics;
571     bool success = getOutlineMetrics(glyph, t, &glyphMetrics);
572 
573     if (!ttf && !success) {
574         // Bitmap fonts
575         wchar_t ch = glyph;
576         ABCFLOAT abc;
577         GetCharABCWidthsFloat(hdc, ch, ch, &abc);
578         int width = qRound(abc.abcfB);
579 
580         return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t);
581     }
582 
583     return glyphMetrics;
584 #else
585     HDC hdc = shared_dc();
586     HGDIOBJ oldFont = SelectObject(hdc, hfont);
587 
588     ABC abc;
589     int width;
590     int advance;
591 #ifdef GWES_MGTT    // true type fonts
592     if (GetCharABCWidths(hdc, glyph, glyph, &abc)) {
593         width = qAbs(abc.abcA) + abc.abcB + qAbs(abc.abcC);
594         advance = abc.abcA + abc.abcB + abc.abcC;
595     }
596     else
597 #endif
598 #if defined(GWES_MGRAST) || defined(GWES_MGRAST2)   // raster fonts
599     if (GetCharWidth32(hdc, glyph, glyph, &width)) {
600         advance = width;
601     }
602     else
603 #endif
604     {   // fallback
605         width = tm.tmMaxCharWidth;
606         advance = width;
607     }
608 
609     SelectObject(hdc, oldFont);
610     return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t);
611 #endif
612 }
613 
614 QFixed QFontEngineWin::ascent() const
615 {
616     return tm.tmAscent;
617 }
618 
619 QFixed QFontEngineWin::descent() const
620 {
621     // ### we substract 1 to even out the historical +1 in QFontMetrics's
622     // ### height=asc+desc+1 equation. Fix in Qt5.
623     return tm.tmDescent - 1;
624 }
625 
626 QFixed QFontEngineWin::leading() const
627 {
628     return tm.tmExternalLeading;
629 }
630 
631 
632 QFixed QFontEngineWin::xHeight() const
633 {
634     if(x_height >= 0)
635         return x_height;
636     return QFontEngine::xHeight();
637 }
638 
639 QFixed QFontEngineWin::averageCharWidth() const
640 {
641     return tm.tmAveCharWidth;
642 }
643 
644 qreal QFontEngineWin::maxCharWidth() const
645 {
646     return tm.tmMaxCharWidth;
647 }
648 
649 enum { max_font_count = 256 };
650 static const ushort char_table[] = {
651         40,
652         67,
653         70,
654         75,
655         86,
656         88,
657         89,
658         91,
659         102,
660         114,
661         124,
662         127,
663         205,
664         645,
665         884,
666         922,
667         1070,
668         12386,
669         0
670 };
671 
672 static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
673 
674 #ifndef Q_CC_MINGW
675 void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
676 {
677     HDC hdc = shared_dc();
678     SelectObject(hdc, hfont);
679 
680 #ifndef Q_WS_WINCE
681     if (ttf)
682 #endif
683 
684     {
685         ABC abcWidths;
686         GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths);
687         if (leftBearing)
688             *leftBearing = abcWidths.abcA;
689         if (rightBearing)
690             *rightBearing = abcWidths.abcC;
691     }
692 
693 #ifndef Q_WS_WINCE
694     else {
695         QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing);
696     }
697 #endif
698 }
699 #endif // Q_CC_MINGW
700 
701 qreal QFontEngineWin::minLeftBearing() const
702 {
703     if (lbearing == SHRT_MIN)
704         minRightBearing(); // calculates both
705 
706     return lbearing;
707 }
708 
709 qreal QFontEngineWin::minRightBearing() const
710 {
711 #ifdef Q_WS_WINCE
712     if (rbearing == SHRT_MIN) {
713         int ml = 0;
714         int mr = 0;
715         HDC hdc = shared_dc();
716         SelectObject(hdc, hfont);
717         if (ttf) {
718             ABC *abc = 0;
719             int n = tm.tmLastChar - tm.tmFirstChar;
720             if (n <= max_font_count) {
721                 abc = new ABC[n+1];
722                 GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
723             } else {
724                 abc = new ABC[char_table_entries+1];
725                 for(int i = 0; i < char_table_entries; i++)
726                     GetCharABCWidths(hdc, char_table[i], char_table[i], abc+i);
727                 n = char_table_entries;
728             }
729             ml = abc[0].abcA;
730             mr = abc[0].abcC;
731             for (int i = 1; i < n; i++) {
732                 if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) {
733                     ml = qMin(ml,abc[i].abcA);
734                     mr = qMin(mr,abc[i].abcC);
735                 }
736             }
737             delete [] abc;
738         }
739         lbearing = ml;
740         rbearing = mr;
741     }
742 
743     return rbearing;
744 #else
745     if (rbearing == SHRT_MIN) {
746         int ml = 0;
747         int mr = 0;
748         HDC hdc = shared_dc();
749         SelectObject(hdc, hfont);
750         if (ttf) {
751             ABC *abc = 0;
752             int n = tm.tmLastChar - tm.tmFirstChar;
753             if (n <= max_font_count) {
754                 abc = new ABC[n+1];
755                 GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
756             } else {
757                 abc = new ABC[char_table_entries+1];
758                 for(int i = 0; i < char_table_entries; i++)
759                     GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i);
760                 n = char_table_entries;
761             }
762             ml = abc[0].abcA;
763             mr = abc[0].abcC;
764             for (int i = 1; i < n; i++) {
765                 if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) {
766                     ml = qMin(ml,abc[i].abcA);
767                     mr = qMin(mr,abc[i].abcC);
768                 }
769             }
770             delete [] abc;
771         } else {
772             ABCFLOAT *abc = 0;
773             int n = tm.tmLastChar - tm.tmFirstChar+1;
774             if (n <= max_font_count) {
775                 abc = new ABCFLOAT[n];
776                 GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
777             } else {
778                 abc = new ABCFLOAT[char_table_entries];
779                 for(int i = 0; i < char_table_entries; i++)
780                     GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i);
781                 n = char_table_entries;
782             }
783             float fml = abc[0].abcfA;
784             float fmr = abc[0].abcfC;
785             for (int i=1; i<n; i++) {
786                 if (abc[i].abcfA + abc[i].abcfB + abc[i].abcfC != 0) {
787                     fml = qMin(fml,abc[i].abcfA);
788                     fmr = qMin(fmr,abc[i].abcfC);
789                 }
790             }
791             ml = int(fml - 0.9999);
792             mr = int(fmr - 0.9999);
793             delete [] abc;
794         }
795         lbearing = ml;
796         rbearing = mr;
797     }
798 
799     return rbearing;
800 #endif
801 }
802 
803 
804 const char *QFontEngineWin::name() const
805 {
806     return 0;
807 }
808 
809 bool QFontEngineWin::canRender(const QChar *string,  int len)
810 {
811     if (symbol) {
812         for (int i = 0; i < len; ++i) {
813             unsigned int uc = getChar(string, i, len);
814             if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0) {
815                 if (uc < 0x100) {
816                     if (getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000) == 0)
817                         return false;
818                 } else {
819                     return false;
820                 }
821             }
822         }
823     } else if (ttf) {
824         for (int i = 0; i < len; ++i) {
825             unsigned int uc = getChar(string, i, len);
826             if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0)
827                 return false;
828         }
829     } else {
830         while(len--) {
831             if (tm.tmFirstChar > string->unicode() || tm.tmLastChar < string->unicode())
832                 return false;
833         }
834     }
835     return true;
836 }
837 
838 QFontEngine::Type QFontEngineWin::type() const
839 {
840     return QFontEngine::Win;
841 }
842 
843 static inline double qt_fixed_to_double(const FIXED &p) {
844     return ((p.value << 16) + p.fract) / 65536.0;
845 }
846 
847 static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) {
848     return QPointF(qt_fixed_to_double(pt.x) * scale, -qt_fixed_to_double(pt.y) * scale);
849 }
850 
851 #ifndef GGO_UNHINTED
852 #define GGO_UNHINTED 0x0100
853 #endif
854 
855 static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
856                            QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1)
857 {
858 #if defined(Q_WS_WINCE)
859     Q_UNUSED(glyph);
860     Q_UNUSED(hdc);
861 #endif
862     MAT2 mat;
863     mat.eM11.value = mat.eM22.value = 1;
864     mat.eM11.fract = mat.eM22.fract = 0;
865     mat.eM21.value = mat.eM12.value = 0;
866     mat.eM21.fract = mat.eM12.fract = 0;
867 
868     GLYPHMETRICS gMetric;
869     memset(&gMetric, 0, sizeof(GLYPHMETRICS));
870 
871 #ifndef Q_OS_WINCE
872     if (metric) {
873         // If metrics requested, retrieve first using GGO_METRICS, because the returned
874         // values are incorrect for OpenType PS fonts if obtained at the same time as the
875         // glyph paths themselves (ie. with GGO_NATIVE as the format).
876         uint format = GGO_METRICS;
877         if (ttf)
878             format |= GGO_GLYPH_INDEX;
879         int res = GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat);
880         if (res == GDI_ERROR) {
881             return false;
882         }
883         // #### obey scale
884         *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y,
885                                   (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY,
886                                   gMetric.gmCellIncX, gMetric.gmCellIncY);
887     }
888 #endif
889 
890     uint glyphFormat = GGO_NATIVE;
891 
892     if (ttf)
893         glyphFormat |= GGO_GLYPH_INDEX;
894 
895     int bufferSize = GDI_ERROR;
896 #if !defined(Q_WS_WINCE)
897     bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
898 #endif
899     if ((DWORD)bufferSize == GDI_ERROR) {
900         return false;
901     }
902 
903     void *dataBuffer = new char[bufferSize];
904     DWORD ret = GDI_ERROR;
905 #if !defined(Q_WS_WINCE)
906     ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat);
907 #endif
908     if (ret == GDI_ERROR) {
909         delete [](char *)dataBuffer;
910         return false;
911     }
912 
913 #ifdef Q_OS_WINCE
914     if (metric) {
915         // #### obey scale
916         *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y,
917                                   (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY,
918                                   gMetric.gmCellIncX, gMetric.gmCellIncY);
919     }
920 #endif
921 
922     int offset = 0;
923     int headerOffset = 0;
924     TTPOLYGONHEADER *ttph = 0;
925 
926     QPointF oset = position.toPointF();
927     while (headerOffset < bufferSize) {
928         ttph = (TTPOLYGONHEADER*)((char *)dataBuffer + headerOffset);
929 
930         QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale));
931         path->moveTo(lastPoint + oset);
932         offset += sizeof(TTPOLYGONHEADER);
933         TTPOLYCURVE *curve;
934         while (offset<int(headerOffset + ttph->cb)) {
935             curve = (TTPOLYCURVE*)((char*)(dataBuffer) + offset);
936             switch (curve->wType) {
937             case TT_PRIM_LINE: {
938                 for (int i=0; i<curve->cpfx; ++i) {
939                     QPointF p = qt_to_qpointf(curve->apfx[i], scale) + oset;
940                     path->lineTo(p);
941                 }
942                 break;
943             }
944             case TT_PRIM_QSPLINE: {
945                 const QPainterPath::Element &elm = path->elementAt(path->elementCount()-1);
946                 QPointF prev(elm.x, elm.y);
947                 QPointF endPoint;
948                 for (int i=0; i<curve->cpfx - 1; ++i) {
949                     QPointF p1 = qt_to_qpointf(curve->apfx[i], scale) + oset;
950                     QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale) + oset;
951                     if (i < curve->cpfx - 2) {
952                         endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2);
953                     } else {
954                         endPoint = p2;
955                     }
956 
957                     path->quadTo(p1, endPoint);
958                     prev = endPoint;
959                 }
960 
961                 break;
962             }
963             case TT_PRIM_CSPLINE: {
964                 for (int i=0; i<curve->cpfx; ) {
965                     QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
966                     QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
967                     QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
968                     path->cubicTo(p2, p3, p4);
969                 }
970                 break;
971             }
972             default:
973                 qWarning("QFontEngineWin::addOutlineToPath, unhandled switch case");
974             }
975             offset += sizeof(TTPOLYCURVE) + (curve->cpfx-1) * sizeof(POINTFX);
976         }
977         path->closeSubpath();
978         headerOffset += ttph->cb;
979     }
980     delete [] (char*)dataBuffer;
981 
982     return true;
983 }
984 
985 void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
986                                      QPainterPath *path, QTextItem::RenderFlags)
987 {
988     LOGFONT lf = logfont;
989     // The sign must be negative here to make sure we match against character height instead of
990     // hinted cell height. This ensures that we get linear matching, and we need this for
991     // paths since we later on apply a scaling transform to the glyph outline to get the
992     // font at the correct pixel size.
993     lf.lfHeight = -unitsPerEm;
994     lf.lfWidth = 0;
995     HFONT hf = CreateFontIndirect(&lf);
996     HDC hdc = shared_dc();
997     HGDIOBJ oldfont = SelectObject(hdc, hf);
998 
999     for(int i = 0; i < nglyphs; ++i) {
1000         if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0,
1001                             qreal(fontDef.pixelSize) / unitsPerEm)) {
1002             // Some windows fonts, like "Modern", are vector stroke
1003             // fonts, which are reported as TMPF_VECTOR but do not
1004             // support GetGlyphOutline, and thus we set this bit so
1005             // that addOutLineToPath can check it and return safely...
1006             hasOutline = false;
1007             break;
1008         }
1009     }
1010     DeleteObject(SelectObject(hdc, oldfont));
1011 }
1012 
1013 void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
1014                                       QPainterPath *path, QTextItem::RenderFlags flags)
1015 {
1016 #if !defined(Q_WS_WINCE)
1017     if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) {
1018         hasOutline = true;
1019         QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
1020         if (hasOutline)  {
1021             // has_outline is set to false if addGlyphToPath gets
1022             // false from GetGlyphOutline, meaning its not an outline
1023             // font.
1024             return;
1025         }
1026     }
1027 #endif
1028     QFontEngine::addBitmapFontToPath(x, y, glyphs, path, flags);
1029 }
1030 
1031 QFontEngine::FaceId QFontEngineWin::faceId() const
1032 {
1033     return _faceId;
1034 }
1035 
1036 QT_BEGIN_INCLUDE_NAMESPACE
1037 #include <qdebug.h>
1038 QT_END_INCLUDE_NAMESPACE
1039 
1040 int QFontEngineWin::synthesized() const
1041 {
1042     if(synthesized_flags == -1) {
1043         synthesized_flags = 0;
1044         if(ttf) {
1045             const DWORD HEAD = MAKE_TAG('h', 'e', 'a', 'd');
1046             HDC hdc = shared_dc();
1047             SelectObject(hdc, hfont);
1048             uchar data[4];
1049             GetFontData(hdc, HEAD, 44, &data, 4);
1050             USHORT macStyle = getUShort(data);
1051             if (tm.tmItalic && !(macStyle & 2))
1052                 synthesized_flags = SynthesizedItalic;
1053             if (fontDef.stretch != 100 && ttf)
1054                 synthesized_flags |= SynthesizedStretch;
1055             if (tm.tmWeight >= 500 && !(macStyle & 1))
1056                 synthesized_flags |= SynthesizedBold;
1057             //qDebug() << "font is" << _name <<
1058             //    "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags;
1059         }
1060     }
1061     return synthesized_flags;
1062 }
1063 
1064 QFixed QFontEngineWin::emSquareSize() const
1065 {
1066     return unitsPerEm;
1067 }
1068 
1069 QFontEngine::Properties QFontEngineWin::properties() const
1070 {
1071     LOGFONT lf = logfont;
1072     lf.lfHeight = unitsPerEm;
1073     HFONT hf = CreateFontIndirect(&lf);
1074     HDC hdc = shared_dc();
1075     HGDIOBJ oldfont = SelectObject(hdc, hf);
1076     OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
1077     Properties p;
1078     p.emSquare = unitsPerEm;
1079     p.italicAngle = otm->otmItalicAngle;
1080     p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1();
1081     p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1();
1082     p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(p.postscriptName);
1083     p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top,
1084                            otm->otmrcFontBox.right - otm->otmrcFontBox.left,
1085                            otm->otmrcFontBox.top - otm->otmrcFontBox.bottom);
1086     p.ascent = otm->otmAscent;
1087     p.descent = -otm->otmDescent;
1088     p.leading = (int)otm->otmLineGap;
1089     p.capHeight = 0;
1090     p.lineWidth = otm->otmsUnderscoreSize;
1091     free(otm);
1092     DeleteObject(SelectObject(hdc, oldfont));
1093     return p;
1094 }
1095 
1096 void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
1097 {
1098     LOGFONT lf = logfont;
1099     lf.lfHeight = unitsPerEm;
1100     int flags = synthesized();
1101     if(flags & SynthesizedItalic)
1102         lf.lfItalic = false;
1103     lf.lfWidth = 0;
1104     HFONT hf = CreateFontIndirect(&lf);
1105     HDC hdc = shared_dc();
1106     HGDIOBJ oldfont = SelectObject(hdc, hf);
1107     QFixedPoint p;
1108     p.x = 0;
1109     p.y = 0;
1110     addGlyphToPath(glyph, p, hdc, path, ttf, metrics);
1111     DeleteObject(SelectObject(hdc, oldfont));
1112 }
1113 
1114 bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) const
1115 {
1116     if (!ttf && !cffTable)
1117         return false;
1118     HDC hdc = shared_dc();
1119     SelectObject(hdc, hfont);
1120     DWORD t = qbswap<quint32>(tag);
1121     *length = GetFontData(hdc, t, 0, buffer, *length);
1122     return *length != GDI_ERROR;
1123 }
1124 
1125 #if !defined(CLEARTYPE_QUALITY)
1126 #    define CLEARTYPE_QUALITY       5
1127 #endif
1128 
1129 extern bool qt_cleartype_enabled;
1130 
1131 QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin,
1132                                            const QTransform &t, QImage::Format mask_format)
1133 {
1134     Q_UNUSED(mask_format)
1135     glyph_metrics_t gm = boundingBox(glyph);
1136 
1137 //     printf(" -> for glyph %4x\n", glyph);
1138 
1139     int gx = gm.x.toInt();
1140     int gy = gm.y.toInt();
1141     int iw = gm.width.toInt();
1142     int ih = gm.height.toInt();
1143 
1144     if (iw <= 0 || iw <= 0)
1145         return 0;
1146 
1147     bool has_transformation = t.type() > QTransform::TxTranslate;
1148 
1149 #ifndef Q_WS_WINCE
1150     unsigned int options = ttf ? ETO_GLYPH_INDEX : 0;
1151     XFORM xform;
1152 
1153     if (has_transformation) {
1154         xform.eM11 = t.m11();
1155         xform.eM12 = t.m12();
1156         xform.eM21 = t.m21();
1157         xform.eM22 = t.m22();
1158         xform.eDx = margin;
1159         xform.eDy = margin;
1160 
1161         QtHDC qthdc;
1162         HDC hdc = qthdc.hdc();
1163 
1164         SetGraphicsMode(hdc, GM_ADVANCED);
1165         SetWorldTransform(hdc, &xform);
1166         HGDIOBJ old_font = SelectObject(hdc, font);
1167 
1168         int ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0);
1169         GLYPHMETRICS tgm;
1170         MAT2 mat;
1171         memset(&mat, 0, sizeof(mat));
1172         mat.eM11.value = mat.eM22.value = 1;
1173 
1174         if (GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat) == GDI_ERROR) {
1175             qWarning("QWinFontEngine: unable to query transformed glyph metrics...");
1176             return 0;
1177         }
1178 
1179         iw = tgm.gmBlackBoxX;
1180         ih = tgm.gmBlackBoxY;
1181 
1182         xform.eDx -= tgm.gmptGlyphOrigin.x;
1183         xform.eDy += tgm.gmptGlyphOrigin.y;
1184 
1185         SetGraphicsMode(hdc, GM_COMPATIBLE);
1186         SelectObject(hdc, old_font);
1187     }
1188 #else // else winc
1189     unsigned int options = 0;
1190 #ifdef DEBUG
1191     Q_ASSERT(!has_transformation);
1192 #else
1193     Q_UNUSED(has_transformation);
1194 #endif
1195 #endif
1196 
1197     QNativeImage *ni = new QNativeImage(iw + 2 * margin + 4,
1198                                         ih + 2 * margin + 4,
1199                                         QNativeImage::systemFormat(), !qt_cleartype_enabled);
1200 
1201     /*If cleartype is enabled we use the standard system format even on Windows CE
1202       and not the special textbuffer format we have to use if cleartype is disabled*/
1203 
1204     ni->image.fill(0xffffffff);
1205 
1206     HDC hdc = ni->hdc;
1207 
1208     SelectObject(hdc, GetStockObject(NULL_BRUSH));
1209     SelectObject(hdc, GetStockObject(BLACK_PEN));
1210     SetTextColor(hdc, RGB(0,0,0));
1211     SetBkMode(hdc, TRANSPARENT);
1212     SetTextAlign(hdc, TA_BASELINE);
1213 
1214     HGDIOBJ old_font = SelectObject(hdc, font);
1215 
1216 #ifndef Q_OS_WINCE
1217     if (has_transformation) {
1218         SetGraphicsMode(hdc, GM_ADVANCED);
1219         SetWorldTransform(hdc, &xform);
1220         ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0);
1221     } else
1222 #endif
1223     {
1224         ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0);
1225     }
1226 
1227     SelectObject(hdc, old_font);
1228     return ni;
1229 }
1230 
1231 
1232 extern uint qt_pow_gamma[256];
1233 
1234 QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform)
1235 {
1236     HFONT font = hfont;
1237     if (qt_cleartype_enabled) {
1238         LOGFONT lf = logfont;
1239         lf.lfQuality = ANTIALIASED_QUALITY;
1240         font = CreateFontIndirect(&lf);
1241     }
1242     QImage::Format mask_format = QNativeImage::systemFormat();
1243 #ifndef Q_OS_WINCE
1244     mask_format = QImage::Format_RGB32;
1245 #endif
1246 
1247     QNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format);
1248     if (mask == 0)
1249         return QImage();
1250 
1251     QImage indexed(mask->width(), mask->height(), QImage::Format_Indexed8);
1252 
1253     // ### This part is kinda pointless, but we'll crash later if we don't because some
1254     // code paths expects there to be colortables for index8-bit...
1255     QVector<QRgb> colors(256);
1256     for (int i=0; i<256; ++i)
1257         colors[i] = qRgba(0, 0, 0, i);
1258     indexed.setColorTable(colors);
1259 
1260     // Copy data... Cannot use QPainter here as GDI has messed up the
1261     // Alpha channel of the ni.image pixels...
1262     for (int y=0; y<mask->height(); ++y) {
1263         uchar *dest = indexed.scanLine(y);
1264         if (mask->image.format() == QImage::Format_RGB16) {
1265             const qint16 *src = (qint16 *) ((const QImage &) mask->image).scanLine(y);
1266             for (int x=0; x<mask->width(); ++x)
1267                 dest[x] = 255 - qGray(src[x]);
1268         } else {
1269             const uint *src = (uint *) ((const QImage &) mask->image).scanLine(y);
1270             for (int x=0; x<mask->width(); ++x) {
1271 #ifdef Q_OS_WINCE
1272                 dest[x] = 255 - qGray(src[x]);
1273 #else
1274                 if (QNativeImage::systemFormat() == QImage::Format_RGB16)
1275                     dest[x] = 255 - qGray(src[x]);
1276                 else
1277                     dest[x] = 255 - (qt_pow_gamma[qGray(src[x])] * 255. / 2047.);
1278 #endif
1279             }
1280         }
1281     }
1282 
1283     // Cleanup...
1284     delete mask;
1285     if (qt_cleartype_enabled) {
1286         DeleteObject(font);
1287     }
1288 
1289     return indexed;
1290 }
1291 
1292 #define SPI_GETFONTSMOOTHINGCONTRAST           0x200C
1293 #define SPI_SETFONTSMOOTHINGCONTRAST           0x200D
1294 
1295 QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t)
1296 {
1297     HFONT font = hfont;
1298 
1299     int contrast;
1300     SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0);
1301     SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0);
1302 
1303     QNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32);
1304     SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) contrast, 0);
1305 
1306     if (mask == 0)
1307         return QImage();
1308 
1309     // Gracefully handle the odd case when the display is 16-bit
1310     const QImage source = mask->image.depth() == 32
1311                           ? mask->image
1312                           : mask->image.convertToFormat(QImage::Format_RGB32);
1313 
1314     QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32);
1315     for (int y=0; y<mask->height(); ++y) {
1316         uint *dest = (uint *) rgbMask.scanLine(y);
1317         const uint *src = (uint *) source.scanLine(y);
1318         for (int x=0; x<mask->width(); ++x) {
1319             dest[x] = 0xffffffff - (0x00ffffff & src[x]);
1320         }
1321     }
1322 
1323     delete mask;
1324 
1325     return rgbMask;
1326 }
1327 
1328 // From qfontdatabase_win.cpp
1329 extern QFontEngine *qt_load_font_engine_win(const QFontDef &request);
1330 QFontEngine *QFontEngineWin::cloneWithSize(qreal pixelSize) const
1331 {
1332     QFontDef request = fontDef;
1333     QString actualFontName = request.family;
1334     if (!uniqueFamilyName.isEmpty())
1335         request.family = uniqueFamilyName;
1336     request.pixelSize = pixelSize;
1337 
1338     QFontEngine *fontEngine = qt_load_font_engine_win(request);
1339     if (fontEngine != NULL)
1340         fontEngine->fontDef.family = actualFontName;
1341 
1342     return fontEngine;
1343 }
1344 
1345 // -------------------------------------- Multi font engine
1346 
1347 QFontEngineMultiWin::QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks)
1348         : QFontEngineMulti(fallbacks.size()+1),
1349           fallbacks(fallbacks)
1350 {
1351     engines[0] = first;
1352     first->ref.ref();
1353     fontDef = engines[0]->fontDef;
1354     cache_cost = first->cache_cost;
1355 }
1356 
1357 void QFontEngineMultiWin::loadEngine(int at)
1358 {
1359     Q_ASSERT(at < engines.size());
1360     Q_ASSERT(engines.at(at) == 0);
1361 
1362     QString fam = fallbacks.at(at-1);
1363 
1364     LOGFONT lf = static_cast<QFontEngineWin *>(engines.at(0))->logfont;
1365     memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded
1366     HFONT hfont = CreateFontIndirect(&lf);
1367 
1368     bool stockFont = false;
1369     if (hfont == 0) {
1370         hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
1371         stockFont = true;
1372     }
1373     engines[at] = new QFontEngineWin(fam, hfont, stockFont, lf);
1374     engines[at]->ref.ref();
1375     engines[at]->fontDef = fontDef;
1376 
1377     // TODO: increase cost in QFontCache for the font engine loaded here
1378 }
1379 
1380 QT_END_NAMESPACE
1381