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 |