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