src/gui/text/qfontengine_s60.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    48 
    48 
    49 #include <e32base.h>
    49 #include <e32base.h>
    50 #include <e32std.h>
    50 #include <e32std.h>
    51 #include <eikenv.h>
    51 #include <eikenv.h>
    52 #include <gdi.h>
    52 #include <gdi.h>
       
    53 #if defined(Q_SYMBIAN_HAS_FONTTABLE_API) || defined(Q_SYMBIAN_HAS_GLYPHOUTLINE_API)
       
    54 #include <graphics/gdi/gdiplatapi.h>
       
    55 #endif // Q_SYMBIAN_HAS_FONTTABLE_API || Q_SYMBIAN_HAS_GLYPHOUTLINE_API
    53 
    56 
    54 QT_BEGIN_NAMESPACE
    57 QT_BEGIN_NAMESPACE
    55 
    58 
    56 QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* fontOwner, COpenFont *font)
    59 #ifdef Q_SYMBIAN_HAS_FONTTABLE_API
    57     : m_font(font)
    60 QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont)
    58     , m_cmap(0)
    61     : m_cFont(cFont)
    59     , m_symbolCMap(false)
    62     , m_symbolCMap(false)
    60     , m_fontOwner(fontOwner)
    63 {
       
    64     Q_UNUSED(openFont)
       
    65 }
       
    66 
       
    67 QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras()
       
    68 {
       
    69     S60->screenDevice()->ReleaseFont(m_cFont);
       
    70 }
       
    71 
       
    72 QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const
       
    73 {
       
    74     RFontTable fontTable;
       
    75     if (fontTable.Open(*m_cFont, tag) != KErrNone)
       
    76         return QByteArray();
       
    77     const QByteArray byteArray(reinterpret_cast<const char *>
       
    78             (fontTable.TableContent()),fontTable.TableLength());
       
    79     fontTable.Close();
       
    80     return byteArray;
       
    81 }
       
    82 
       
    83 bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const
       
    84 {
       
    85     RFontTable fontTable;
       
    86     if (fontTable.Open(*m_cFont, tag) != KErrNone)
       
    87         return false;
       
    88 
       
    89     bool result = true;
       
    90     const TInt tableByteLength = fontTable.TableLength();
       
    91 
       
    92     if (*length > 0 && *length < tableByteLength) {
       
    93         result = false; // Caller did not allocate enough memory
       
    94     } else {
       
    95         *length = tableByteLength;
       
    96         if (buffer)
       
    97             memcpy(buffer, fontTable.TableContent(), tableByteLength);
       
    98     }
       
    99 
       
   100     fontTable.Close();
       
   101     return result;
       
   102 }
       
   103 
       
   104 #else // Q_SYMBIAN_HAS_FONTTABLE_API
       
   105 QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont)
       
   106     : m_cFont(cFont)
       
   107     , m_symbolCMap(false)
       
   108     , m_openFont(openFont)
    61 {
   109 {
    62     TAny *trueTypeExtension = NULL;
   110     TAny *trueTypeExtension = NULL;
    63     m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension);
   111     m_openFont->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension);
    64     m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension);
   112     m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension);
    65     Q_ASSERT(m_trueTypeExtension);
   113     Q_ASSERT(m_trueTypeExtension);
       
   114 }
       
   115 
       
   116 QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras()
       
   117 {
    66 }
   118 }
    67 
   119 
    68 QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const
   120 QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const
    69 {
   121 {
    70     Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
   122     Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
    92     } else if (*length > 0 && *length < tableByteLength) {
   144     } else if (*length > 0 && *length < tableByteLength) {
    93         result = false; // Caller did not allocate enough memory
   145         result = false; // Caller did not allocate enough memory
    94     } else {
   146     } else {
    95         *length = tableByteLength;
   147         *length = tableByteLength;
    96         if (buffer)
   148         if (buffer)
    97             qMemCopy(buffer, table, tableByteLength);
   149             memcpy(buffer, table, tableByteLength);
    98     }
   150     }
    99 
   151 
   100     m_trueTypeExtension->ReleaseTrueTypeTable(table);
   152     m_trueTypeExtension->ReleaseTrueTypeTable(table);
   101     return result;
   153     return result;
   102 }
   154 }
   103 
   155 #endif // Q_SYMBIAN_HAS_FONTTABLE_API
   104 const unsigned char *QSymbianTypeFaceExtras::cmap() const
   156 
   105 {
   157 const uchar *QSymbianTypeFaceExtras::cmap() const
   106     if (!m_cmap) {
   158 {
   107         m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
   159     if (m_cmapTable.isNull()) {
       
   160         const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
   108         int size = 0;
   161         int size = 0;
   109         m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size);
   162         const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>
   110     }
   163                 (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size);
   111     return m_cmap;
   164         m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size);
       
   165     }
       
   166     return reinterpret_cast<const uchar *>(m_cmapTable.constData());
   112 }
   167 }
   113 
   168 
   114 CFont *QSymbianTypeFaceExtras::fontOwner() const
   169 CFont *QSymbianTypeFaceExtras::fontOwner() const
   115 {
   170 {
   116     return m_fontOwner;
   171     return m_cFont;
   117 }
   172 }
   118 
       
   119 
   173 
   120 // duplicated from qfontengine_xyz.cpp
   174 // duplicated from qfontengine_xyz.cpp
   121 static inline unsigned int getChar(const QChar *str, int &i, const int len)
   175 static inline unsigned int getChar(const QChar *str, int &i, const int len)
   122 {
   176 {
   123     unsigned int uc = str[i].unicode();
   177     unsigned int uc = str[i].unicode();
   221     for (int i = 0; i < glyphs->numGlyphs; i++) {
   275     for (int i = 0; i < glyphs->numGlyphs; i++) {
   222         const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]);
   276         const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]);
   223         glyphs->advances_x[i] = bbox.xoff;
   277         glyphs->advances_x[i] = bbox.xoff;
   224         glyphs->advances_y[i] = bbox.yoff;
   278         glyphs->advances_y[i] = bbox.yoff;
   225     }
   279     }
       
   280 }
       
   281 
       
   282 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   283 static bool parseGlyphPathData(const char *dataStr, const char *dataEnd, QPainterPath &path,
       
   284                                qreal fontPixelSize, const QPointF &offset, bool hinted);
       
   285 #endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   286 
       
   287 void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions,
       
   288                                      int nglyphs, QPainterPath *path,
       
   289                                      QTextItem::RenderFlags flags)
       
   290 {
       
   291 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   292     Q_UNUSED(flags)
       
   293     RGlyphOutlineIterator iterator;
       
   294     const TInt error = iterator.Open(*m_activeFont, glyphs, nglyphs);
       
   295     if (KErrNone != error)
       
   296         return;
       
   297     const qreal fontSizeInPixels = qreal(m_activeFont->HeightInPixels());
       
   298     int count = 0;
       
   299     do {
       
   300         const TUint8* outlineUint8 = iterator.Outline();
       
   301         const char* const outlineChar = reinterpret_cast<const char*>(outlineUint8);
       
   302         const char* const outlineEnd = outlineChar + iterator.OutlineLength();
       
   303         parseGlyphPathData(outlineChar, outlineEnd, *path, fontSizeInPixels,
       
   304                 positions[count++].toPointF(), false);
       
   305     } while(KErrNone == iterator.Next() && count <= nglyphs);
       
   306 #else // Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   307     QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags);
       
   308 #endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API
   226 }
   309 }
   227 
   310 
   228 QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph)
   311 QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph)
   229 {
   312 {
   230     TOpenFontCharMetrics metrics;
   313     TOpenFontCharMetrics metrics;
   354                 m_activeFont->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize);
   437                 m_activeFont->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize);
   355         Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData);
   438         Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData);
   356     }
   439     }
   357 }
   440 }
   358 
   441 
       
   442 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   443 static inline void skipSpacesAndComma(const char* &str, const char* const strEnd)
       
   444 {
       
   445     while (str <= strEnd && (*str == ' ' || *str == ','))
       
   446         ++str;
       
   447 }
       
   448 
       
   449 static bool parseGlyphPathData(const char *svgPath, const char *svgPathEnd, QPainterPath &path,
       
   450                                qreal fontPixelSize, const QPointF &offset, bool hinted)
       
   451 {
       
   452     Q_UNUSED(hinted)
       
   453     QPointF p1, p2, firstSubPathPoint;
       
   454     qreal *elementValues[] =
       
   455         {&p1.rx(), &p1.ry(), &p2.rx(), &p2.ry()};
       
   456     const int unitsPerEm = 2048; // See: http://en.wikipedia.org/wiki/Em_%28typography%29
       
   457     const qreal resizeFactor = fontPixelSize / unitsPerEm;
       
   458 
       
   459     while (svgPath < svgPathEnd) {
       
   460         skipSpacesAndComma(svgPath, svgPathEnd);
       
   461         const char pathElem = *svgPath++;
       
   462         skipSpacesAndComma(svgPath, svgPathEnd);
       
   463 
       
   464         if (pathElem != 'Z') {
       
   465             char *endStr = 0;
       
   466             int elementValuesCount = 0;
       
   467             for (int i = 0; i < 4; ++i) { // 4 = size of elementValues[]
       
   468                 qreal coordinateValue = strtod(svgPath, &endStr);
       
   469                 if (svgPath == endStr)
       
   470                     break;
       
   471                 if (i % 2) // Flip vertically
       
   472                     coordinateValue = -coordinateValue;
       
   473                 *elementValues[i] = coordinateValue * resizeFactor;
       
   474                 elementValuesCount++;
       
   475                 svgPath = endStr;
       
   476                 skipSpacesAndComma(svgPath, svgPathEnd);
       
   477             }
       
   478             p1 += offset;
       
   479             if (elementValuesCount == 2)
       
   480                 p2 = firstSubPathPoint;
       
   481             else
       
   482                 p2 += offset;
       
   483         }
       
   484 
       
   485         switch (pathElem) {
       
   486         case 'M':
       
   487             firstSubPathPoint = p1;
       
   488             path.moveTo(p1);
       
   489             break;
       
   490         case 'Z':
       
   491             path.closeSubpath();
       
   492             break;
       
   493         case 'L':
       
   494             path.lineTo(p1);
       
   495             break;
       
   496         case 'Q':
       
   497             path.quadTo(p1, p2);
       
   498             break;
       
   499         default:
       
   500             return false;
       
   501         }
       
   502     }
       
   503     return true;
       
   504 }
       
   505 #endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API
       
   506 
   359 QT_END_NAMESPACE
   507 QT_END_NAMESPACE