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