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