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