source: trunk/src/gui/text/qfontengine_s60.cpp@ 563

Last change on this file since 563 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qfontengine_s60_p.h"
43#include "qtextengine_p.h"
44#include "qglobal.h"
45#include <private/qapplication_p.h>
46#include "qimage.h"
47#include "qt_s60_p.h"
48
49#include <e32base.h>
50#include <e32std.h>
51#include <eikenv.h>
52#include <gdi.h>
53
54QT_BEGIN_NAMESPACE
55
56QFontEngineS60Extensions::QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font)
57 : m_font(font)
58 , m_cmap(0)
59 , m_symbolCMap(false)
60 , m_fontOwner(fontOwner)
61{
62 TAny *shapingExtension = NULL;
63 m_font->ExtendedInterface(KUidOpenFontShapingExtension, shapingExtension);
64 m_shapingExtension = static_cast<MOpenFontShapingExtension*>(shapingExtension);
65 TAny *trueTypeExtension = NULL;
66 m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension);
67 m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension);
68 Q_ASSERT(m_shapingExtension && m_trueTypeExtension);
69}
70
71QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const
72{
73 Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
74 TInt error = KErrNone;
75 TInt tableByteLength = 0;
76 TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength));
77 QByteArray result(static_cast<const char*>(table), tableByteLength);
78 m_trueTypeExtension->ReleaseTrueTypeTable(table);
79 return result;
80}
81
82const unsigned char *QFontEngineS60Extensions::cmap() const
83{
84 if (!m_cmap) {
85 m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
86 int size = 0;
87 m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size);
88 }
89 return m_cmap;
90}
91
92QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const
93{
94 QPainterPath result;
95 QPolygonF polygon;
96 TInt glyphIndex = glyph;
97 TInt pointNumber = 0;
98 TInt x, y;
99 while (m_shapingExtension->GlyphPointInFontUnits(glyphIndex, pointNumber++, x, y)) {
100 const QPointF point(qreal(x) / 0xffff, qreal(y) / 0xffff);
101 if (polygon.contains(point)) {
102 result.addPolygon(polygon);
103 result.closeSubpath();
104 polygon.clear();
105 } else {
106 polygon.append(point);
107 }
108 }
109 return result;
110}
111
112CFont *QFontEngineS60Extensions::fontOwner() const
113{
114 return m_fontOwner;
115}
116
117
118// duplicated from qfontengine_xyz.cpp
119static inline unsigned int getChar(const QChar *str, int &i, const int len)
120{
121 unsigned int uc = str[i].unicode();
122 if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
123 uint low = str[i+1].unicode();
124 if (low >= 0xdc00 && low < 0xe000) {
125 uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
126 ++i;
127 }
128 }
129 return uc;
130}
131
132QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Extensions *extensions)
133 : m_extensions(extensions)
134{
135 QFontEngine::fontDef = request;
136 m_fontSizeInPixels = (request.pixelSize >= 0)?
137 request.pixelSize:pointsToPixels(request.pointSize);
138
139 TFontSpec fontSpec(qt_QString2TPtrC(request.family), m_fontSizeInPixels);
140 fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
141 fontSpec.iFontStyle.SetPosture(request.style == QFont::StyleNormal?EPostureUpright:EPostureItalic);
142 fontSpec.iFontStyle.SetStrokeWeight(request.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal);
143 const TInt errorCode = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(m_font, fontSpec);
144 Q_ASSERT(errorCode == 0);
145
146 cache_cost = sizeof(QFontEngineS60);
147}
148
149QFontEngineS60::~QFontEngineS60()
150{
151 S60->screenDevice()->ReleaseFont(m_font);
152}
153
154bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
155{
156 if (*nglyphs < len) {
157 *nglyphs = len;
158 return false;
159 }
160
161 HB_Glyph *g = glyphs->glyphs;
162 const unsigned char* cmap = m_extensions->cmap();
163 for (int i = 0; i < len; ++i) {
164 const unsigned int uc = getChar(characters, i, len);
165 *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, uc);
166 }
167
168 glyphs->numGlyphs = g - glyphs->glyphs;
169 *nglyphs = glyphs->numGlyphs;
170
171 if (flags & QTextEngine::GlyphIndicesOnly)
172 return true;
173
174 recalcAdvances(glyphs, flags);
175 return true;
176}
177
178void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
179{
180 Q_UNUSED(flags);
181 for (int i = 0; i < glyphs->numGlyphs; i++) {
182 const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]);
183 glyphs->advances_x[i] = glyphs->offsets[i].x = bbox.xoff;
184 glyphs->advances_y[i] = glyphs->offsets[i].y = bbox.yoff;
185 }
186}
187
188QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph)
189{
190 TOpenFontCharMetrics metrics;
191 const TUint8 *glyphBitmapBytes;
192 TSize glyphBitmapSize;
193 getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
194 QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8);
195 result.setColorTable(grayPalette());
196
197 // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can.
198 // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly.
199 // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished
200 // for every time we want to blit this glyph in the raster paint engine.
201 // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values.
202 // Blitting is however, evidentially faster now.
203 const int bpl = result.bytesPerLine();
204 for (int row = 0; row < result.height(); ++row) {
205 uchar *scanLine = result.scanLine(row);
206 for (int column = 0; column < bpl; ++column) {
207 if (*scanLine == 0xf0)
208 *scanLine = 0xff;
209 scanLine++;
210 }
211 }
212
213 return result;
214}
215
216glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs)
217{
218 if (glyphs.numGlyphs == 0)
219 return glyph_metrics_t();
220
221 QFixed w = 0;
222 for (int i = 0; i < glyphs.numGlyphs; ++i)
223 w += glyphs.effectiveAdvance(i);
224
225 return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0);
226}
227
228glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const
229{
230 TOpenFontCharMetrics metrics;
231 const TUint8 *glyphBitmapBytes;
232 TSize glyphBitmapSize;
233 getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
234 TRect glyphBounds;
235 metrics.GetHorizBounds(glyphBounds);
236 const glyph_metrics_t result(
237 glyphBounds.iTl.iX,
238 glyphBounds.iTl.iY,
239 glyphBounds.Width(),
240 glyphBounds.Height(),
241 metrics.HorizAdvance(),
242 0
243 );
244 return result;
245}
246
247glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph)
248{
249 return boundingBox_const(glyph);
250}
251
252QFixed QFontEngineS60::ascent() const
253{
254 return m_font->FontMaxAscent();
255}
256
257QFixed QFontEngineS60::descent() const
258{
259 return m_font->FontMaxDescent();
260}
261
262QFixed QFontEngineS60::leading() const
263{
264 return 0;
265}
266
267qreal QFontEngineS60::maxCharWidth() const
268{
269 return m_font->MaxCharWidthInPixels();
270}
271
272const char *QFontEngineS60::name() const
273{
274 return "QFontEngineS60";
275}
276
277bool QFontEngineS60::canRender(const QChar *string, int len)
278{
279 const unsigned char *cmap = m_extensions->cmap();
280 for (int i = 0; i < len; ++i) {
281 const unsigned int uc = getChar(string, i, len);
282 if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0)
283 return false;
284 }
285 return true;
286}
287
288QByteArray QFontEngineS60::getSfntTable(uint tag) const
289{
290 return m_extensions->getSfntTable(tag);
291}
292
293QFontEngine::Type QFontEngineS60::type() const
294{
295 return QFontEngine::S60FontEngine;
296}
297
298void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const
299{
300 // Setting the most significant bit tells GetCharacterData
301 // that 'code' is a Glyph ID, rather than a UTF-16 value
302 const TUint specialCode = (TUint)glyph | 0x80000000;
303
304 const CFont::TCharacterDataAvailability availability =
305 m_font->GetCharacterData(specialCode, metrics, bitmap, bitmapSize);
306 const glyph_t fallbackGlyph = '?';
307 if (availability != CFont::EAllCharacterData) {
308 const CFont::TCharacterDataAvailability fallbackAvailability =
309 m_font->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize);
310 Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData);
311 }
312}
313
314QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.