src/gui/text/qfontengine_x11.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 "qbitmap.h"
       
    43 
       
    44 // #define FONTENGINE_DEBUG
       
    45 
       
    46 #include <qapplication.h>
       
    47 #include <qbytearray.h>
       
    48 #include <qdebug.h>
       
    49 #include <qtextcodec.h>
       
    50 #include <qthread.h>
       
    51 
       
    52 #include "qfontdatabase.h"
       
    53 #include "qpaintdevice.h"
       
    54 #include "qpainter.h"
       
    55 #include "qvarlengtharray.h"
       
    56 #include "qwidget.h"
       
    57 #include "qsettings.h"
       
    58 #include "qfile.h"
       
    59 
       
    60 #include <private/qpaintengine_x11_p.h>
       
    61 #include "qfont.h"
       
    62 #include "qfont_p.h"
       
    63 #include "qfontengine_p.h"
       
    64 #include <qhash.h>
       
    65 
       
    66 #include <private/qpainter_p.h>
       
    67 #include <private/qunicodetables_p.h>
       
    68 
       
    69 #include <private/qt_x11_p.h>
       
    70 #include <private/qpixmap_x11_p.h>
       
    71 #include "qx11info_x11.h"
       
    72 #include "qfontengine_x11_p.h"
       
    73 
       
    74 #include <limits.h>
       
    75 
       
    76 #include <ft2build.h>
       
    77 #if defined(FT_LCD_FILTER_H)
       
    78 #include FT_LCD_FILTER_H
       
    79 #endif
       
    80 
       
    81 #if defined(FC_LCD_FILTER)
       
    82 
       
    83 #ifndef FC_LCD_FILTER_NONE
       
    84 #define FC_LCD_FILTER_NONE FC_LCD_NONE
       
    85 #endif
       
    86 
       
    87 #ifndef FC_LCD_FILTER_DEFAULT
       
    88 #define FC_LCD_FILTER_DEFAULT FC_LCD_DEFAULT
       
    89 #endif
       
    90 
       
    91 #ifndef FC_LCD_FILTER_LIGHT
       
    92 #define FC_LCD_FILTER_LIGHT FC_LCD_LIGHT
       
    93 #endif
       
    94 
       
    95 #ifndef FC_LCD_FILTER_LEGACY
       
    96 #define FC_LCD_FILTER_LEGACY FC_LCD_LEGACY
       
    97 #endif
       
    98 
       
    99 #endif
       
   100 
       
   101 QT_BEGIN_NAMESPACE
       
   102 
       
   103 
       
   104 // ------------------------------------------------------------------
       
   105 // Multi XLFD engine
       
   106 // ------------------------------------------------------------------
       
   107 
       
   108 QFontEngineMultiXLFD::QFontEngineMultiXLFD(const QFontDef &r, const QList<int> &l, int s)
       
   109     : QFontEngineMulti(l.size()), encodings(l), screen(s), request(r)
       
   110 {
       
   111     loadEngine(0);
       
   112     fontDef = engines[0]->fontDef;
       
   113 }
       
   114 
       
   115 QFontEngineMultiXLFD::~QFontEngineMultiXLFD()
       
   116 { }
       
   117 
       
   118 void QFontEngineMultiXLFD::loadEngine(int at)
       
   119 {
       
   120     Q_ASSERT(at < engines.size());
       
   121     Q_ASSERT(engines.at(at) == 0);
       
   122     const int encoding = encodings.at(at);
       
   123     QFontEngine *fontEngine = QFontDatabase::loadXlfd(0, QUnicodeTables::Common, request, encoding);
       
   124     Q_ASSERT(fontEngine != 0);
       
   125     fontEngine->ref.ref();
       
   126     engines[at] = fontEngine;
       
   127 }
       
   128 
       
   129 // ------------------------------------------------------------------
       
   130 // Xlfd font engine
       
   131 // ------------------------------------------------------------------
       
   132 
       
   133 #ifndef QT_NO_FREETYPE
       
   134 
       
   135 static QStringList *qt_fontpath = 0;
       
   136 
       
   137 static QStringList fontPath()
       
   138 {
       
   139     if (qt_fontpath)
       
   140         return *qt_fontpath;
       
   141 
       
   142     // append qsettings fontpath
       
   143     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
       
   144     settings.beginGroup(QLatin1String("Qt"));
       
   145 
       
   146     QStringList fontpath;
       
   147 
       
   148     int npaths;
       
   149     char** font_path;
       
   150     font_path = XGetFontPath(X11->display, &npaths);
       
   151     bool xfsconfig_read = false;
       
   152     for (int i=0; i<npaths; i++) {
       
   153         // If we're using xfs, append font paths from /etc/X11/fs/config
       
   154         // can't hurt, and chances are we'll get all fonts that way.
       
   155         if (((font_path[i])[0] != '/') && !xfsconfig_read) {
       
   156             // We're using xfs -> read its config
       
   157             bool finished = false;
       
   158             QFile f(QLatin1String("/etc/X11/fs/config"));
       
   159             if (!f.exists())
       
   160                 f.setFileName(QLatin1String("/usr/X11R6/lib/X11/fs/config"));
       
   161             if (!f.exists())
       
   162                 f.setFileName(QLatin1String("/usr/X11/lib/X11/fs/config"));
       
   163             if (f.exists()) {
       
   164                 f.open(QIODevice::ReadOnly);
       
   165                 while (f.error()==QFile::NoError && !finished) {
       
   166                     QString fs = QString::fromLocal8Bit(f.readLine(1024));
       
   167                     fs=fs.trimmed();
       
   168                     if (fs.left(9)==QLatin1String("catalogue") && fs.contains(QLatin1Char('='))) {
       
   169                         fs = fs.mid(fs.indexOf(QLatin1Char('=')) + 1).trimmed();
       
   170                         bool end = false;
       
   171                         while (f.error()==QFile::NoError && !end) {
       
   172                             if (fs[int(fs.length())-1] == QLatin1Char(','))
       
   173                                 fs = fs.left(fs.length()-1);
       
   174                             else
       
   175                                 end = true;
       
   176 
       
   177                             fs = fs.left(fs.indexOf(QLatin1String(":unscaled")));
       
   178                             if (fs[0] != QLatin1Char('#'))
       
   179                                 fontpath += fs;
       
   180                             fs = QLatin1String(f.readLine(1024));
       
   181                             fs = fs.trimmed();
       
   182                             if (fs.isEmpty())
       
   183                                 end = true;
       
   184                         }
       
   185                         finished = true;
       
   186                     }
       
   187                 }
       
   188                 f.close();
       
   189             }
       
   190             xfsconfig_read = true;
       
   191         } else {
       
   192             QString fs = QString::fromLocal8Bit(font_path[i]);
       
   193             fontpath += fs.left(fs.indexOf(QLatin1String(":unscaled")));
       
   194         }
       
   195     }
       
   196     XFreeFontPath(font_path);
       
   197 
       
   198     // append qsettings fontpath
       
   199     QStringList fp = settings.value(QLatin1String("fontPath")).toStringList();
       
   200     if (!fp.isEmpty())
       
   201         fontpath += fp;
       
   202 
       
   203     qt_fontpath = new QStringList(fontpath);
       
   204     return fontpath;
       
   205 }
       
   206 
       
   207 static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **freetype, int *synth)
       
   208 {
       
   209     *freetype = 0;
       
   210     *synth = 0;
       
   211 
       
   212     QByteArray xname = _xname.toLower();
       
   213 
       
   214     int pos = 0;
       
   215     int minus = 0;
       
   216     while (minus < 5 && (pos = xname.indexOf('-', pos + 1)))
       
   217         ++minus;
       
   218     QByteArray searchname = xname.left(pos);
       
   219     while (minus < 12 && (pos = xname.indexOf('-', pos + 1)))
       
   220         ++minus;
       
   221     QByteArray encoding = xname.mid(pos + 1);
       
   222     //qDebug("xname='%s', searchname='%s', encoding='%s'", xname.data(), searchname.data(), encoding.data());
       
   223     QStringList fontpath = fontPath();
       
   224     QFontEngine::FaceId face_id;
       
   225     face_id.index = 0;
       
   226 
       
   227     QByteArray best_mapping;
       
   228 
       
   229     for (QStringList::ConstIterator it = fontpath.constBegin(); it != fontpath.constEnd(); ++it) {
       
   230         if (!(*it).startsWith(QLatin1Char('/')))
       
   231             continue; // not a path name, a font server
       
   232         QString fontmapname;
       
   233         int num = 0;
       
   234         // search font.dir and font.scale for the right file
       
   235         while (num < 2) {
       
   236             if (num == 0)
       
   237                 fontmapname = (*it) + QLatin1String("/fonts.scale");
       
   238             else
       
   239                 fontmapname = (*it) + QLatin1String("/fonts.dir");
       
   240             ++num;
       
   241             //qWarning(fontmapname);
       
   242             QFile fontmap(fontmapname);
       
   243             if (!fontmap.open(QIODevice::ReadOnly))
       
   244                 continue;
       
   245             while (!fontmap.atEnd()) {
       
   246                 QByteArray mapping = fontmap.readLine();
       
   247                 QByteArray lmapping = mapping.toLower();
       
   248 
       
   249                 //qWarning(xfontname);
       
   250                 //qWarning(mapping);
       
   251                 if (!lmapping.contains(searchname))
       
   252                     continue;
       
   253                 int index = mapping.indexOf(' ');
       
   254                 QByteArray ffn = mapping.mid(0,index);
       
   255                 // remove bitmap formats freetype can't handle
       
   256                 if (ffn.contains(".spd") || ffn.contains(".phont"))
       
   257                     continue;
       
   258                 bool best_match = false;
       
   259                 if (!best_mapping.isEmpty()) {
       
   260                     if (lmapping.contains("-0-0-0-0-")) { // scalable font
       
   261                         best_match = true;
       
   262                         goto found;
       
   263                     }
       
   264                     if (lmapping.contains(encoding) && !best_mapping.toLower().contains(encoding))
       
   265                         goto found;
       
   266                     continue;
       
   267                 }
       
   268 
       
   269             found:
       
   270                 int colon = ffn.lastIndexOf(':');
       
   271                 if (colon != -1) {
       
   272                     QByteArray s = ffn.left(colon);
       
   273                     ffn = ffn.mid(colon + 1);
       
   274                     if (s.contains("ds="))
       
   275                         *synth |= QFontEngine::SynthesizedBold;
       
   276                     if (s.contains("ai="))
       
   277                         *synth |= QFontEngine::SynthesizedItalic;
       
   278                 }
       
   279                 face_id.filename = (*it).toLocal8Bit() + '/' + ffn;
       
   280                 best_mapping = mapping;
       
   281                 if (best_match)
       
   282                     goto end;
       
   283             }
       
   284         }
       
   285     }
       
   286 end:
       
   287 //     qDebug("fontfile for %s is from '%s'\n    got %s synth=%d", xname.data(),
       
   288 //            best_mapping.data(), face_id.filename.data(), *synth);
       
   289     *freetype = QFreetypeFace::getFace(face_id);
       
   290     if (!*freetype) {
       
   291         face_id.index = 0;
       
   292         face_id.filename = QByteArray();
       
   293     }
       
   294     return face_id;
       
   295 }
       
   296 
       
   297 #endif // QT_NO_FREETYPE
       
   298 
       
   299 // defined in qfontdatabase_x11.cpp
       
   300 extern int qt_mib_for_xlfd_encoding(const char *encoding);
       
   301 extern int qt_xlfd_encoding_id(const char *encoding);
       
   302 
       
   303 static inline XCharStruct *charStruct(XFontStruct *xfs, uint ch)
       
   304 {
       
   305     XCharStruct *xcs = 0;
       
   306     unsigned char r = ch>>8;
       
   307     unsigned char c = ch&0xff;
       
   308     if (xfs->per_char &&
       
   309          r >= xfs->min_byte1 &&
       
   310          r <= xfs->max_byte1 &&
       
   311          c >= xfs->min_char_or_byte2 &&
       
   312          c <= xfs->max_char_or_byte2) {
       
   313         xcs = xfs->per_char + ((r - xfs->min_byte1) *
       
   314                                (xfs->max_char_or_byte2 -
       
   315                                 xfs->min_char_or_byte2 + 1)) +
       
   316               (c - xfs->min_char_or_byte2);
       
   317         if (xcs->width == 0 && xcs->ascent == 0 &&  xcs->descent == 0)
       
   318             xcs = 0;
       
   319     }
       
   320     return xcs;
       
   321 }
       
   322 
       
   323 QFontEngineXLFD::QFontEngineXLFD(XFontStruct *fs, const QByteArray &name, int mib)
       
   324     : _fs(fs), _name(name), _codec(0), _cmap(mib)
       
   325 {
       
   326     if (_cmap) _codec = QTextCodec::codecForMib(_cmap);
       
   327 
       
   328     cache_cost = (((fs->max_byte1 - fs->min_byte1) *
       
   329                    (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) +
       
   330                   fs->max_char_or_byte2 - fs->min_char_or_byte2);
       
   331     cache_cost = ((fs->max_bounds.ascent + fs->max_bounds.descent) *
       
   332                   (fs->max_bounds.width * cache_cost / 8));
       
   333     lbearing = SHRT_MIN;
       
   334     rbearing = SHRT_MIN;
       
   335     face_id.index = -1;
       
   336     freetype = 0;
       
   337     synth = 0;
       
   338 }
       
   339 
       
   340 QFontEngineXLFD::~QFontEngineXLFD()
       
   341 {
       
   342     XFreeFont(QX11Info::display(), _fs);
       
   343     _fs = 0;
       
   344 #ifndef QT_NO_FREETYPE
       
   345     if (freetype)
       
   346         freetype->release(face_id);
       
   347 #endif
       
   348 }
       
   349 
       
   350 bool QFontEngineXLFD::stringToCMap(const QChar *s, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
       
   351 {
       
   352     if (*nglyphs < len) {
       
   353         *nglyphs = len;
       
   354         return false;
       
   355     }
       
   356 
       
   357     // filter out surrogates, we can't handle them anyway with XLFD fonts
       
   358     QVarLengthArray<ushort> _s(len);
       
   359     QChar *str = (QChar *)_s.data();
       
   360     for (int i = 0; i < len; ++i) {
       
   361         if (i < len - 1
       
   362             && s[i].unicode() >= 0xd800 && s[i].unicode() < 0xdc00
       
   363             && s[i+1].unicode() >= 0xdc00 && s[i].unicode() < 0xe000) {
       
   364             *str = QChar();
       
   365             ++i;
       
   366         } else {
       
   367             *str = s[i];
       
   368         }
       
   369         ++str;
       
   370     }
       
   371 
       
   372     len = str - (QChar *)_s.data();
       
   373     str = (QChar *)_s.data();
       
   374 
       
   375     bool mirrored = flags & QTextEngine::RightToLeft;
       
   376     if (_codec) {
       
   377         bool haveNbsp = false;
       
   378         for (int i = 0; i < len; i++)
       
   379             if (str[i].unicode() == 0xa0) {
       
   380                 haveNbsp = true;
       
   381                 break;
       
   382             }
       
   383 
       
   384         QVarLengthArray<unsigned short> ch(len);
       
   385         QChar *chars = (QChar *)ch.data();
       
   386         if (haveNbsp || mirrored) {
       
   387             for (int i = 0; i < len; i++)
       
   388                 chars[i] = (str[i].unicode() == 0xa0 ? 0x20 :
       
   389                             (mirrored ? QChar::mirroredChar(str[i].unicode()) : str[i].unicode()));
       
   390         } else {
       
   391             for (int i = 0; i < len; i++)
       
   392                 chars[i] = str[i].unicode();
       
   393         }
       
   394         QTextCodec::ConverterState state;
       
   395         state.flags = QTextCodec::ConvertInvalidToNull;
       
   396         QByteArray ba = _codec->fromUnicode(chars, len, &state);
       
   397         if (ba.length() == 2*len) {
       
   398             // double byte encoding
       
   399             const uchar *data = (const uchar *)ba.constData();
       
   400             for (int i = 0; i < len; i++) {
       
   401                 glyphs->glyphs[i] = ((ushort)data[0] << 8) + data[1];
       
   402                 data += 2;
       
   403             }
       
   404         } else {
       
   405             const uchar *data = (const uchar *)ba.constData();
       
   406             for (int i = 0; i < len; i++)
       
   407                 glyphs->glyphs[i] = (ushort)data[i];
       
   408         }
       
   409     } else {
       
   410         int i = len;
       
   411         const QChar *c = str + len;
       
   412         if (mirrored) {
       
   413             while (c != str)
       
   414                 glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : QChar::mirroredChar(c->unicode());
       
   415         } else {
       
   416             while (c != str)
       
   417                 glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : c->unicode();
       
   418         }
       
   419     }
       
   420     *nglyphs = len;
       
   421     glyphs->numGlyphs = len;
       
   422 
       
   423     if (!(flags & QTextEngine::GlyphIndicesOnly))
       
   424         recalcAdvances(glyphs, flags);
       
   425     return true;
       
   426 }
       
   427 
       
   428 void QFontEngineXLFD::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags /*flags*/) const
       
   429 {
       
   430     int i = glyphs->numGlyphs;
       
   431     XCharStruct *xcs;
       
   432     // inlined for better perfomance
       
   433     if (!_fs->per_char) {
       
   434         xcs = &_fs->min_bounds;
       
   435         while (i != 0) {
       
   436             --i;
       
   437             const unsigned char r = glyphs->glyphs[i] >> 8;
       
   438             const unsigned char c = glyphs->glyphs[i] & 0xff;
       
   439             if (r >= _fs->min_byte1 &&
       
   440                 r <= _fs->max_byte1 &&
       
   441                 c >= _fs->min_char_or_byte2 &&
       
   442                 c <= _fs->max_char_or_byte2) {
       
   443                 glyphs->advances_x[i] = xcs->width;
       
   444             } else {
       
   445                 glyphs->glyphs[i] = 0;
       
   446             }
       
   447         }
       
   448     }
       
   449     else if (!_fs->max_byte1) {
       
   450         XCharStruct *base = _fs->per_char - _fs->min_char_or_byte2;
       
   451         while (i != 0) {
       
   452             unsigned int gl = glyphs->glyphs[--i];
       
   453             xcs = (gl >= _fs->min_char_or_byte2 && gl <= _fs->max_char_or_byte2) ?
       
   454                   base + gl : 0;
       
   455             if (!xcs || (!xcs->width && !xcs->ascent && !xcs->descent)) {
       
   456                 glyphs->glyphs[i] = 0;
       
   457             } else {
       
   458                 glyphs->advances_x[i] = xcs->width;
       
   459             }
       
   460         }
       
   461     }
       
   462     else {
       
   463         while (i != 0) {
       
   464             xcs = charStruct(_fs, glyphs->glyphs[--i]);
       
   465             if (!xcs) {
       
   466                 glyphs->glyphs[i] = 0;
       
   467             } else {
       
   468                 glyphs->advances_x[i] = xcs->width;
       
   469             }
       
   470         }
       
   471     }
       
   472 }
       
   473 
       
   474 glyph_metrics_t QFontEngineXLFD::boundingBox(const QGlyphLayout &glyphs)
       
   475 {
       
   476     int i;
       
   477 
       
   478     glyph_metrics_t overall;
       
   479     // initialize with line height, we get the same behaviour on all platforms
       
   480     overall.y = -ascent();
       
   481     overall.height = ascent() + descent() + 1;
       
   482     QFixed ymax;
       
   483     QFixed xmax;
       
   484     for (i = 0; i < glyphs.numGlyphs; i++) {
       
   485         XCharStruct *xcs = charStruct(_fs, glyphs.glyphs[i]);
       
   486         if (xcs) {
       
   487             QFixed x = overall.xoff + glyphs.offsets[i].x + xcs->lbearing;
       
   488             QFixed y = overall.yoff + glyphs.offsets[i].y - xcs->ascent;
       
   489             overall.x = qMin(overall.x, x);
       
   490             overall.y = qMin(overall.y, y);
       
   491             // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel
       
   492             xmax = qMax(xmax, overall.xoff + glyphs.offsets[i].x + xcs->rbearing);
       
   493             ymax = qMax(ymax, y + xcs->ascent + xcs->descent);
       
   494             overall.xoff += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);
       
   495         } else {
       
   496             QFixed size = _fs->ascent;
       
   497             overall.x = qMin(overall.x, overall.xoff);
       
   498             overall.y = qMin(overall.y, overall.yoff - size);
       
   499             ymax = qMax(ymax, overall.yoff);
       
   500             overall.xoff += size;
       
   501             xmax = qMax(xmax, overall.xoff);
       
   502         }
       
   503     }
       
   504     overall.height = qMax(overall.height, ymax - overall.y);
       
   505     overall.width = xmax - overall.x;
       
   506 
       
   507     return overall;
       
   508 }
       
   509 
       
   510 glyph_metrics_t QFontEngineXLFD::boundingBox(glyph_t glyph)
       
   511 {
       
   512     glyph_metrics_t gm;
       
   513     XCharStruct *xcs = charStruct(_fs, glyph);
       
   514     if (xcs) {
       
   515         // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel
       
   516         // XCharStruct::width is defined as the advance
       
   517         gm = glyph_metrics_t(xcs->lbearing, -xcs->ascent, xcs->rbearing- xcs->lbearing, xcs->ascent + xcs->descent,
       
   518                               xcs->width, 0);
       
   519     } else {
       
   520         QFixed size = ascent();
       
   521         gm = glyph_metrics_t(0, size, size, size, size, 0);
       
   522     }
       
   523     return gm;
       
   524 }
       
   525 
       
   526 QFixed QFontEngineXLFD::ascent() const
       
   527 {
       
   528     return _fs->ascent;
       
   529 }
       
   530 
       
   531 QFixed QFontEngineXLFD::descent() const
       
   532 {
       
   533     return (_fs->descent-1);
       
   534 }
       
   535 
       
   536 QFixed QFontEngineXLFD::leading() const
       
   537 {
       
   538     QFixed l = QFixed(qMin<int>(_fs->ascent, _fs->max_bounds.ascent)
       
   539                       + qMin<int>(_fs->descent, _fs->max_bounds.descent)) * QFixed::fromReal(0.15);
       
   540     return l.ceil();
       
   541 }
       
   542 
       
   543 qreal QFontEngineXLFD::maxCharWidth() const
       
   544 {
       
   545     return _fs->max_bounds.width;
       
   546 }
       
   547 
       
   548 
       
   549 // Loads the font for the specified script
       
   550 static inline int maxIndex(XFontStruct *f) {
       
   551     return (((f->max_byte1 - f->min_byte1) *
       
   552              (f->max_char_or_byte2 - f->min_char_or_byte2 + 1)) +
       
   553             f->max_char_or_byte2 - f->min_char_or_byte2);
       
   554 }
       
   555 
       
   556 qreal QFontEngineXLFD::minLeftBearing() const
       
   557 {
       
   558     if (lbearing == SHRT_MIN) {
       
   559         if (_fs->per_char) {
       
   560             XCharStruct *cs = _fs->per_char;
       
   561             int nc = maxIndex(_fs) + 1;
       
   562             int mx = cs->lbearing;
       
   563 
       
   564             for (int c = 1; c < nc; c++) {
       
   565                 // ignore the bearings for characters whose ink is
       
   566                 // completely outside the normal bounding box
       
   567                 if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) ||
       
   568                     (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width))
       
   569                     continue;
       
   570 
       
   571                 int nmx = cs[c].lbearing;
       
   572 
       
   573                 if (nmx < mx)
       
   574                     mx = nmx;
       
   575             }
       
   576 
       
   577             ((QFontEngineXLFD *)this)->lbearing = mx;
       
   578         } else
       
   579             ((QFontEngineXLFD *)this)->lbearing = _fs->min_bounds.lbearing;
       
   580     }
       
   581     return lbearing;
       
   582 }
       
   583 
       
   584 qreal QFontEngineXLFD::minRightBearing() const
       
   585 {
       
   586     if (rbearing == SHRT_MIN) {
       
   587         if (_fs->per_char) {
       
   588             XCharStruct *cs = _fs->per_char;
       
   589             int nc = maxIndex(_fs) + 1;
       
   590             int mx = cs->rbearing;
       
   591 
       
   592             for (int c = 1; c < nc; c++) {
       
   593                 // ignore the bearings for characters whose ink is
       
   594                 // completely outside the normal bounding box
       
   595                 if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) ||
       
   596                     (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width))
       
   597                     continue;
       
   598 
       
   599                 int nmx = cs[c].rbearing;
       
   600 
       
   601                 if (nmx < mx)
       
   602                     mx = nmx;
       
   603             }
       
   604 
       
   605             ((QFontEngineXLFD *)this)->rbearing = mx;
       
   606         } else
       
   607             ((QFontEngineXLFD *)this)->rbearing = _fs->min_bounds.rbearing;
       
   608     }
       
   609     return rbearing;
       
   610 }
       
   611 
       
   612 const char *QFontEngineXLFD::name() const
       
   613 {
       
   614     return _name;
       
   615 }
       
   616 
       
   617 bool QFontEngineXLFD::canRender(const QChar *string, int len)
       
   618 {
       
   619     QVarLengthGlyphLayoutArray glyphs(len);
       
   620     int nglyphs = len;
       
   621     if (stringToCMap(string, len, &glyphs, &nglyphs, 0) == false) {
       
   622         glyphs.resize(nglyphs);
       
   623         stringToCMap(string, len, &glyphs, &nglyphs, 0);
       
   624     }
       
   625 
       
   626     bool allExist = true;
       
   627     for (int i = 0; i < nglyphs; i++) {
       
   628         if (!glyphs.glyphs[i] || !charStruct(_fs, glyphs.glyphs[i])) {
       
   629             allExist = false;
       
   630             break;
       
   631         }
       
   632     }
       
   633 
       
   634     return allExist;
       
   635 }
       
   636 
       
   637 QBitmap QFontEngineXLFD::bitmapForGlyphs(const QGlyphLayout &glyphs, const glyph_metrics_t &metrics, QTextItem::RenderFlags flags)
       
   638 {
       
   639     int w = metrics.width.toInt();
       
   640     int h = metrics.height.toInt();
       
   641     if (w <= 0 || h <= 0)
       
   642         return QBitmap();
       
   643 
       
   644     QPixmapData *data = new QX11PixmapData(QPixmapData::BitmapType);
       
   645     data->resize(w, h);
       
   646     QPixmap bm(data);
       
   647     QPainter p(&bm);
       
   648     p.fillRect(0, 0, w, h, Qt::color0);
       
   649     p.setPen(Qt::color1);
       
   650 
       
   651     QTextItemInt item;
       
   652     item.flags = flags;
       
   653     item.ascent = -metrics.y;
       
   654     item.descent = metrics.height - item.ascent;
       
   655     item.width = metrics.width;
       
   656     item.chars = 0;
       
   657     item.num_chars = 0;
       
   658     item.logClusters = 0;
       
   659     item.glyphs = glyphs;
       
   660     item.fontEngine = this;
       
   661     item.f = 0;
       
   662 
       
   663     p.drawTextItem(QPointF(-metrics.x.toReal(), item.ascent.toReal()), item);
       
   664     p.end();
       
   665 
       
   666     return QBitmap(bm);
       
   667 }
       
   668 
       
   669 void QFontEngineXLFD::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
       
   670 {
       
   671     // cannot use QFontEngine::addBitmapFontToPath(), since we don't
       
   672     // have direct access to the glyph bitmaps, so we have to draw
       
   673     // onto a QBitmap, then convert to QImage, then to path
       
   674     glyph_metrics_t metrics = boundingBox(glyphs);
       
   675 
       
   676     QImage image = bitmapForGlyphs(glyphs, metrics, flags).toImage();
       
   677     if (image.isNull())
       
   678         return;
       
   679 
       
   680     image = image.convertToFormat(QImage::Format_Mono);
       
   681     const uchar *image_data = image.bits();
       
   682     uint bpl = image.bytesPerLine();
       
   683     // from qfontengine.cpp
       
   684     extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data,
       
   685                                    int bpl, int w, int h, QPainterPath *path);
       
   686     qt_addBitmapToPath(x, y + metrics.y.toReal(), image_data, bpl, image.width(), image.height(), path);
       
   687 }
       
   688 
       
   689 QFontEngine::FaceId QFontEngineXLFD::faceId() const
       
   690 {
       
   691 #ifndef QT_NO_FREETYPE
       
   692     if (face_id.index == -1) {
       
   693         face_id = fontFile(_name, &freetype, &synth);
       
   694         if (_codec)
       
   695             face_id.encoding = _codec->mibEnum();
       
   696         if (freetype) {
       
   697             const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType();
       
   698         } else {
       
   699             face_id.index = 0;
       
   700             face_id.filename = '-' + QFontEngine::properties().postscriptName;
       
   701         }
       
   702     }
       
   703 #endif
       
   704 
       
   705     return face_id;
       
   706 }
       
   707 
       
   708 QFontEngine::Properties QFontEngineXLFD::properties() const
       
   709 {
       
   710     if (face_id.index == -1)
       
   711         (void)faceId();
       
   712 
       
   713 #ifndef QT_NO_FREETYPE
       
   714     if (freetype)
       
   715         return freetype->properties();
       
   716 #endif
       
   717     return QFontEngine::properties();
       
   718 }
       
   719 
       
   720 void QFontEngineXLFD::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
       
   721 {
       
   722     if (face_id.index == -1)
       
   723         (void)faceId();
       
   724 #ifndef QT_NO_FREETYPE
       
   725     if (!freetype)
       
   726 #endif
       
   727     {
       
   728         QFontEngine::getUnscaledGlyph(glyph, path, metrics);
       
   729         return;
       
   730     }
       
   731 
       
   732 #ifndef QT_NO_FREETYPE
       
   733     freetype->lock();
       
   734 
       
   735     FT_Face face = freetype->face;
       
   736     FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
       
   737     freetype->xsize = face->units_per_EM << 6;
       
   738     freetype->ysize = face->units_per_EM << 6;
       
   739     FT_Set_Transform(face, 0, 0);
       
   740     glyph = glyphIndexToFreetypeGlyphIndex(glyph);
       
   741     FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
       
   742 
       
   743     int left  = face->glyph->metrics.horiBearingX;
       
   744     int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width;
       
   745     int top    = face->glyph->metrics.horiBearingY;
       
   746     int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
       
   747 
       
   748     QFixedPoint p;
       
   749     p.x = 0;
       
   750     p.y = 0;
       
   751     metrics->width = QFixed::fromFixed(right-left);
       
   752     metrics->height = QFixed::fromFixed(top-bottom);
       
   753     metrics->x = QFixed::fromFixed(left);
       
   754     metrics->y = QFixed::fromFixed(-top);
       
   755     metrics->xoff = QFixed::fromFixed(face->glyph->advance.x);
       
   756 
       
   757     if (!FT_IS_SCALABLE(freetype->face))
       
   758         QFreetypeFace::addBitmapToPath(face->glyph, p, path);
       
   759     else
       
   760         QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6);
       
   761 
       
   762     FT_Set_Transform(face, &freetype->matrix, 0);
       
   763     freetype->unlock();
       
   764 #endif // QT_NO_FREETYPE
       
   765 }
       
   766 
       
   767 
       
   768 bool QFontEngineXLFD::getSfntTableData(uint tag, uchar *buffer, uint *length) const
       
   769 {
       
   770 #ifndef QT_NO_FREETYPE
       
   771     if (face_id.index == -1)
       
   772         (void)faceId();
       
   773     if (!freetype)
       
   774         return false;
       
   775     return freetype->getSfntTable(tag, buffer, length);
       
   776 #else
       
   777     Q_UNUSED(tag);
       
   778     Q_UNUSED(buffer);
       
   779     Q_UNUSED(length);
       
   780     return false;
       
   781 #endif
       
   782 }
       
   783 
       
   784 int QFontEngineXLFD::synthesized() const
       
   785 {
       
   786     return synth;
       
   787 }
       
   788 
       
   789 QImage QFontEngineXLFD::alphaMapForGlyph(glyph_t glyph)
       
   790 {
       
   791     glyph_metrics_t metrics = boundingBox(glyph);
       
   792 
       
   793 /*
       
   794     printf("a) w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
       
   795            metrics.width.toReal(),
       
   796            metrics.height.toReal(),
       
   797            metrics.xoff.toReal(),
       
   798            metrics.yoff.toReal(),
       
   799            metrics.x.toReal(),
       
   800            metrics.y.toReal());
       
   801 */
       
   802 
       
   803     QGlyphLayoutArray<1> glyphs;
       
   804     glyphs.glyphs[0] = glyph;
       
   805 
       
   806     QImage image = bitmapForGlyphs(glyphs, metrics).toImage();
       
   807 //image.save(QString::fromLatin1("x11cache-%1.png").arg((int)glyph));
       
   808 
       
   809     image = image.convertToFormat(QImage::Format_Indexed8);
       
   810     QVector<QRgb> colors(256);
       
   811     for (int i = 0; i < 256; ++i)
       
   812         colors[i] = qRgba(0, 0, 0, i);
       
   813     image.setColorTable(colors);
       
   814 
       
   815     int width = image.width();
       
   816     int height = image.height();
       
   817     for (int y = 0; y < height; ++y) {
       
   818         uchar *bits = image.scanLine(y);
       
   819         for (int x = 0; x < width; ++x)
       
   820             bits[x] = ~(bits[x]-1);
       
   821     }
       
   822 
       
   823     return image;
       
   824 }
       
   825 
       
   826 #ifndef QT_NO_FREETYPE
       
   827 
       
   828 FT_Face QFontEngineXLFD::non_locked_face() const
       
   829 {
       
   830     return freetype ? freetype->face : 0;
       
   831 }
       
   832 
       
   833 uint QFontEngineXLFD::toUnicode(glyph_t g) const
       
   834 {
       
   835     if (_codec) {
       
   836         QTextCodec::ConverterState state;
       
   837         state.flags = QTextCodec::ConvertInvalidToNull;
       
   838         uchar data[2];
       
   839         int l = 1;
       
   840         if (g > 255) {
       
   841             data[0] = (g >> 8);
       
   842             data[1] = (g & 255);
       
   843             l = 2;
       
   844         } else {
       
   845             data[0] = g;
       
   846         }
       
   847         QString s = _codec->toUnicode((char *)data, l, &state);
       
   848         Q_ASSERT(s.length() == 1);
       
   849         g = s.at(0).unicode();
       
   850     }
       
   851     return g;
       
   852 }
       
   853 
       
   854 glyph_t QFontEngineXLFD::glyphIndexToFreetypeGlyphIndex(glyph_t g) const
       
   855 {
       
   856     return FT_Get_Char_Index(freetype->face, toUnicode(g));
       
   857 }
       
   858 #endif
       
   859 
       
   860 #ifndef QT_NO_FONTCONFIG
       
   861 
       
   862 // ------------------------------------------------------------------
       
   863 // Multi FT engine
       
   864 // ------------------------------------------------------------------
       
   865 
       
   866 static QFontEngine *engineForPattern(FcPattern *pattern, const QFontDef &request,
       
   867                                      int screen)
       
   868 {
       
   869     FcResult res;
       
   870     FcPattern *match = FcFontMatch(0, pattern, &res);
       
   871     QFontEngineX11FT *engine = new QFontEngineX11FT(match, request, screen);
       
   872     if (!engine->invalid())
       
   873         return engine;
       
   874 
       
   875     delete engine;
       
   876     QFontEngine *fe = new QFontEngineBox(request.pixelSize);
       
   877     fe->fontDef = request;
       
   878     return fe;
       
   879 }
       
   880 
       
   881 QFontEngineMultiFT::QFontEngineMultiFT(QFontEngine *fe, FcPattern *matchedPattern, FcPattern *p, int s, const QFontDef &req)
       
   882     : QFontEngineMulti(2), request(req), pattern(p), firstEnginePattern(matchedPattern), fontSet(0), screen(s)
       
   883 {
       
   884 
       
   885     engines[0] = fe;
       
   886     engines.at(0)->ref.ref();
       
   887     fontDef = engines[0]->fontDef;
       
   888     cache_cost = 100;
       
   889     firstFontIndex = 1;
       
   890 }
       
   891 
       
   892 QFontEngineMultiFT::~QFontEngineMultiFT()
       
   893 {
       
   894     extern QMutex *qt_fontdatabase_mutex();
       
   895     QMutexLocker locker(qt_fontdatabase_mutex());
       
   896 
       
   897     FcPatternDestroy(pattern);
       
   898     if (firstEnginePattern)
       
   899         FcPatternDestroy(firstEnginePattern);
       
   900     if (fontSet)
       
   901         FcFontSetDestroy(fontSet);
       
   902 }
       
   903 
       
   904 
       
   905 void QFontEngineMultiFT::loadEngine(int at)
       
   906 {
       
   907     extern QMutex *qt_fontdatabase_mutex();
       
   908     QMutexLocker locker(qt_fontdatabase_mutex());
       
   909 
       
   910     extern void qt_addPatternProps(FcPattern *pattern, int screen, int script,
       
   911                                    const QFontDef &request);
       
   912     extern QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &);
       
   913     extern FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request);
       
   914 
       
   915     Q_ASSERT(at > 0);
       
   916     if (!fontSet) {
       
   917         fontSet = qt_fontSetForPattern(pattern, request);
       
   918 
       
   919         // it may happen that the fontset of fallbacks consists of only one font. In this case we
       
   920         // have to fall back to the box fontengine as we cannot render the glyph.
       
   921         if (fontSet->nfont == 1 && at == 1 && engines.size() == 2) {
       
   922             Q_ASSERT(engines.at(at) == 0);
       
   923             QFontEngine *fe = new QFontEngineBox(request.pixelSize);
       
   924             fe->fontDef = request;
       
   925             engines[at] = fe;
       
   926             return;
       
   927         }
       
   928 
       
   929         if (firstEnginePattern) {
       
   930 
       
   931             if (!FcPatternEqual(firstEnginePattern, fontSet->fonts[0]))
       
   932                 firstFontIndex = 0;
       
   933 
       
   934             FcPatternDestroy(firstEnginePattern);
       
   935             firstEnginePattern = 0;
       
   936         }
       
   937 
       
   938         engines.resize(fontSet->nfont + 1 - firstFontIndex);
       
   939     }
       
   940     Q_ASSERT(at < engines.size());
       
   941     Q_ASSERT(engines.at(at) == 0);
       
   942 
       
   943     FcPattern *pattern = FcPatternDuplicate(fontSet->fonts[at + firstFontIndex - 1]);
       
   944     qt_addPatternProps(pattern, screen, QUnicodeTables::Common, request);
       
   945 
       
   946     QFontDef fontDef = qt_FcPatternToQFontDef(pattern, this->request);
       
   947 
       
   948     // note: we use -1 for the script to make sure that we keep real
       
   949     // FT engines separate from Multi engines in the font cache
       
   950     QFontCache::Key key(fontDef, -1, screen);
       
   951     QFontEngine *fontEngine = QFontCache::instance()->findEngine(key);
       
   952     if (!fontEngine) {
       
   953         FcConfigSubstitute(0, pattern, FcMatchPattern);
       
   954         FcDefaultSubstitute(pattern);
       
   955         fontEngine = engineForPattern(pattern, request, screen);
       
   956         QFontCache::instance()->insertEngine(key, fontEngine);
       
   957     }
       
   958     FcPatternDestroy(pattern);
       
   959     fontEngine->ref.ref();
       
   960     engines[at] = fontEngine;
       
   961 }
       
   962 
       
   963 // ------------------------------------------------------------------
       
   964 // X11 FT engine
       
   965 // ------------------------------------------------------------------
       
   966 
       
   967 
       
   968 
       
   969 Q_GUI_EXPORT void qt_x11ft_convert_pattern(FcPattern *pattern, QByteArray *file_name, int *index, bool *antialias)
       
   970 {
       
   971     FcChar8 *fileName;
       
   972     FcPatternGetString(pattern, FC_FILE, 0, &fileName);
       
   973     *file_name = (const char *)fileName;
       
   974     if (!FcPatternGetInteger(pattern, FC_INDEX, 0, index))
       
   975         index = 0;
       
   976     FcBool b;
       
   977     if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &b) == FcResultMatch)
       
   978         *antialias = b;
       
   979 }
       
   980 
       
   981 
       
   982 QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen)
       
   983     : QFontEngineFT(fd)
       
   984 {
       
   985 //     FcPatternPrint(pattern);
       
   986 
       
   987     bool antialias = X11->fc_antialias;
       
   988     QByteArray file_name;
       
   989     int face_index;
       
   990     qt_x11ft_convert_pattern(pattern, &file_name, &face_index, &antialias);
       
   991     QFontEngine::FaceId face_id;
       
   992     face_id.filename = file_name;
       
   993     face_id.index = face_index;
       
   994 
       
   995     canUploadGlyphsToServer = qApp->thread() == QThread::currentThread();
       
   996 
       
   997     subpixelType = Subpixel_None;
       
   998     if (antialias) {
       
   999         int subpixel = X11->display ? X11->screens[screen].subpixel : FC_RGBA_UNKNOWN;
       
  1000         if (subpixel == FC_RGBA_UNKNOWN)
       
  1001             (void) FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel);
       
  1002         if (!antialias || subpixel == FC_RGBA_UNKNOWN)
       
  1003             subpixel = FC_RGBA_NONE;
       
  1004 
       
  1005         switch (subpixel) {
       
  1006             case FC_RGBA_NONE: subpixelType = Subpixel_None; break;
       
  1007             case FC_RGBA_RGB: subpixelType = Subpixel_RGB; break;
       
  1008             case FC_RGBA_BGR: subpixelType = Subpixel_BGR; break;
       
  1009             case FC_RGBA_VRGB: subpixelType = Subpixel_VRGB; break;
       
  1010             case FC_RGBA_VBGR: subpixelType = Subpixel_VBGR; break;
       
  1011             default: break;
       
  1012         }
       
  1013     }
       
  1014 
       
  1015 #ifdef FC_HINT_STYLE
       
  1016     {
       
  1017         int hint_style = 0;
       
  1018         if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch)
       
  1019             hint_style = X11->fc_hint_style;
       
  1020 
       
  1021         switch (hint_style) {
       
  1022         case FC_HINT_NONE:
       
  1023             default_hint_style = HintNone;
       
  1024             break;
       
  1025         case FC_HINT_SLIGHT:
       
  1026             default_hint_style = HintLight;
       
  1027             break;
       
  1028         case FC_HINT_MEDIUM:
       
  1029             default_hint_style = HintMedium;
       
  1030             break;
       
  1031         default:
       
  1032             default_hint_style = HintFull;
       
  1033             break;
       
  1034         }
       
  1035     }
       
  1036 #endif
       
  1037 
       
  1038 #if defined(FC_AUTOHINT) && defined(FT_LOAD_FORCE_AUTOHINT)
       
  1039     {
       
  1040         bool autohint = false;
       
  1041 
       
  1042         FcBool b;
       
  1043         if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &b) == FcResultMatch)
       
  1044             autohint = b;
       
  1045 
       
  1046         if (autohint)
       
  1047             default_load_flags |= FT_LOAD_FORCE_AUTOHINT;
       
  1048     }
       
  1049 #endif
       
  1050 
       
  1051 #if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H)
       
  1052     {
       
  1053         int filter = FC_LCD_FILTER_NONE;
       
  1054         if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) {
       
  1055             switch (filter) {
       
  1056             case FC_LCD_FILTER_NONE:
       
  1057                 lcdFilterType = FT_LCD_FILTER_NONE;
       
  1058                 break;
       
  1059             case FC_LCD_FILTER_DEFAULT:
       
  1060                 lcdFilterType = FT_LCD_FILTER_DEFAULT;
       
  1061                 break;
       
  1062             case FC_LCD_FILTER_LIGHT:
       
  1063                 lcdFilterType = FT_LCD_FILTER_LIGHT;
       
  1064                 break;
       
  1065             case FC_LCD_FILTER_LEGACY:
       
  1066                 lcdFilterType = FT_LCD_FILTER_LEGACY;
       
  1067                 break;
       
  1068             default:
       
  1069                 // new unknown lcd filter type?!
       
  1070                 break;
       
  1071             }
       
  1072         }
       
  1073     }
       
  1074 #endif
       
  1075 
       
  1076 #ifdef FC_EMBEDDED_BITMAP
       
  1077     {
       
  1078         FcBool b;
       
  1079         if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch)
       
  1080             embeddedbitmap = b;
       
  1081     }
       
  1082 #endif
       
  1083 
       
  1084     GlyphFormat defaultFormat = Format_None;
       
  1085 
       
  1086 #ifndef QT_NO_XRENDER
       
  1087     if (X11->use_xrender) {
       
  1088         int format = PictStandardA8;
       
  1089         if (!antialias)
       
  1090             format = PictStandardA1;
       
  1091         else if (subpixelType == Subpixel_RGB
       
  1092                  || subpixelType == Subpixel_BGR
       
  1093                  || subpixelType == Subpixel_VRGB
       
  1094                  || subpixelType == Subpixel_VBGR)
       
  1095             format = PictStandardARGB32;
       
  1096         xglyph_format = format;
       
  1097 
       
  1098         if (subpixelType != QFontEngineFT::Subpixel_None)
       
  1099             defaultFormat = Format_A32;
       
  1100         else if (antialias)
       
  1101             defaultFormat = Format_A8;
       
  1102         else
       
  1103             defaultFormat = Format_Mono;
       
  1104     }
       
  1105 #endif
       
  1106 
       
  1107     if (!init(face_id, antialias, defaultFormat)) {
       
  1108         FcPatternDestroy(pattern);
       
  1109         return;
       
  1110     }
       
  1111 
       
  1112     if (!freetype->charset) {
       
  1113         FcCharSet *cs;
       
  1114         FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs);
       
  1115         freetype->charset = FcCharSetCopy(cs);
       
  1116     }
       
  1117     FcPatternDestroy(pattern);
       
  1118 }
       
  1119 
       
  1120 QFontEngineX11FT::~QFontEngineX11FT()
       
  1121 {
       
  1122     freeGlyphSets();
       
  1123 }
       
  1124 
       
  1125 unsigned long QFontEngineX11FT::allocateServerGlyphSet()
       
  1126 {
       
  1127 #ifndef QT_NO_XRENDER
       
  1128     if (!canUploadGlyphsToServer || !X11->use_xrender)
       
  1129         return 0;
       
  1130     return XRenderCreateGlyphSet(X11->display, XRenderFindStandardFormat(X11->display, xglyph_format));
       
  1131 #else
       
  1132     return 0;
       
  1133 #endif
       
  1134 }
       
  1135 
       
  1136 void QFontEngineX11FT::freeServerGlyphSet(unsigned long id)
       
  1137 {
       
  1138 #ifndef QT_NO_XRENDER
       
  1139     if (!id)
       
  1140         return;
       
  1141     XRenderFreeGlyphSet(X11->display, id);
       
  1142 #endif
       
  1143 }
       
  1144 
       
  1145 bool QFontEngineX11FT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const
       
  1146 {
       
  1147 #ifndef QT_NO_XRENDER
       
  1148     if (!canUploadGlyphsToServer)
       
  1149         return false;
       
  1150     if (g->format == Format_Mono) {
       
  1151         /*
       
  1152          * swap bit order around; FreeType is always MSBFirst
       
  1153          */
       
  1154         if (BitmapBitOrder(X11->display) != MSBFirst) {
       
  1155             unsigned char *line = g->data;
       
  1156             int i = glyphDataSize;
       
  1157             while (i--) {
       
  1158                 unsigned char c;
       
  1159                 c = *line;
       
  1160                 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
       
  1161                 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
       
  1162                 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
       
  1163                 *line++ = c;
       
  1164             }
       
  1165         }
       
  1166     }
       
  1167 
       
  1168     ::Glyph xglyph = glyphid;
       
  1169     XRenderAddGlyphs (X11->display, set->id, &xglyph, info, 1, (const char *)g->data, glyphDataSize);
       
  1170     delete [] g->data;
       
  1171     g->data = 0;
       
  1172     g->format = Format_None;
       
  1173     g->uploadedToServer = true;
       
  1174     return true;
       
  1175 #else
       
  1176     return false;
       
  1177 #endif
       
  1178 }
       
  1179 
       
  1180 #endif // QT_NO_FONTCONFIG
       
  1181 
       
  1182 QT_END_NAMESPACE