painting/qtextureglyphcache.cpp

Switch to Source codePreprocessed file
LineSource CodeCoverage
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
9static inline int qt_next_power_of_two(int v) -
10{ -
11 v--; -
12 v |= v >> 1; -
13 v |= v >> 2; -
14 v |= v >> 4; -
15 v |= v >> 8; -
16 v |= v >> 16; -
17 ++v; -
18 return v;
-
19} -
20 -
21int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const -
22{ -
23 -
24 -
25 -
26 QList<QImage> images; -
27 for (int i=0; i<12; ++i) {
-
28 QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0)); -
29 -
30 if (images.isEmpty()) {
-
31 QPainterPath path; -
32 QFixedPoint point; -
33 m_current_fontengine->addGlyphsToPath(&glyph, &point, 1, &path, QTextItem::RenderFlags()); -
34 -
35 -
36 if (path.isEmpty())
-
37 break;
-
38 -
39 images.append(img); -
40 } else {
-
41 bool found = false; -
42 for (int j=0; j<images.size(); ++j) {
-
43 if (images.at(j) == img) {
-
44 found = true; -
45 break;
-
46 } -
47 }
-
48 if (!found)
-
49 images.append(img);
-
50 }
-
51 } -
52 -
53 return images.size();
-
54} -
55 -
56bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, -
57 const QFixedPoint *positions) -
58{ -
59 -
60 -
61 -
62 -
63 -
64 m_current_fontengine = fontEngine; -
65 const int margin = m_current_fontengine->glyphMargin(m_type); -
66 const int paddingDoubled = glyphPadding() * 2; -
67 -
68 bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); -
69 if (fontEngine->m_subPixelPositionCount == 0) {
-
70 if (!supportsSubPixelPositions) {
-
71 fontEngine->m_subPixelPositionCount = 1; -
72 } else {
-
73 int i = 0; -
74 while (fontEngine->m_subPixelPositionCount == 0 && i < numGlyphs)
-
75 fontEngine->m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
-
76 }
-
77 } -
78 -
79 QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates; -
80 int rowHeight = 0; -
81 -
82 QFontEngine::GlyphFormat format; -
83 switch (m_type) { -
84 case Raster_A8: format = QFontEngine::Format_A8; break;
-
85 case Raster_RGBMask: format = QFontEngine::Format_A32; break;
-
86 default: format = QFontEngine::Format_Mono; break;
-
87 } -
88 -
89 -
90 for (int i=0; i < numGlyphs; ++i) {
-
91 const glyph_t glyph = glyphs[i]; -
92 -
93 QFixed subPixelPosition; -
94 if (supportsSubPixelPositions) {
-
95 QFixed x = positions != 0 ? positions[i].x : QFixed();
-
96 subPixelPosition = fontEngine->subPixelPositionForX(x); -
97 }
-
98 -
99 if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
-
100 continue;
-
101 if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
-
102 continue;
-
103 glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, format); -
104 GlyphAndSubPixelPosition key(glyph, subPixelPosition); -
105 int glyph_width = metrics.width.ceil().toInt(); -
106 int glyph_height = metrics.height.ceil().toInt(); -
107 if (glyph_height == 0 || glyph_width == 0) {
-
108 -
109 Coord c = { 0, 0, 0, 0, 0, 0 }; -
110 coords.insert(key, c); -
111 continue;
-
112 } -
113 glyph_width += margin * 2 + 4; -
114 glyph_height += margin * 2 + 4; -
115 -
116 if (m_type == QFontEngineGlyphCache::Raster_Mono)
-
117 glyph_width = (glyph_width+7)&~7;
-
118 -
119 Coord c = { 0, 0, -
120 glyph_width, -
121 glyph_height, -
122 metrics.x.truncate(), -
123 -metrics.y.truncate() }; -
124 -
125 listItemCoordinates.insert(key, c); -
126 rowHeight = qMax(rowHeight, glyph_height); -
127 }
-
128 if (listItemCoordinates.isEmpty())
-
129 return true;
-
130 -
131 rowHeight += margin * 2 + paddingDoubled; -
132 -
133 if (m_w == 0) {
-
134 if (fontEngine->maxCharWidth() <= 256)
-
135 m_w = 256;
-
136 else -
137 m_w = qt_next_power_of_two(fontEngine->maxCharWidth());
-
138 } -
139 -
140 -
141 QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = listItemCoordinates.begin(); -
142 int requiredWidth = m_w; -
143 while (iter != listItemCoordinates.end()) {
-
144 Coord c = iter.value(); -
145 -
146 m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2); -
147 -
148 if (m_cx + c.w > requiredWidth) {
-
149 int new_width = requiredWidth*2; -
150 while (new_width < m_cx + c.w)
-
151 new_width *= 2;
-
152 if (new_width <= maxTextureWidth()) {
-
153 requiredWidth = new_width; -
154 } else {
-
155 -
156 m_cx = 0; -
157 m_cy += m_currentRowHeight + paddingDoubled; -
158 m_currentRowHeight = c.h + margin * 2; -
159 }
-
160 } -
161 -
162 if (maxTextureHeight() > 0 && m_cy + c.h > maxTextureHeight()) {
-
163 -
164 return false;
-
165 } -
166 -
167 c.x = m_cx; -
168 c.y = m_cy; -
169 -
170 coords.insert(iter.key(), c); -
171 m_pendingGlyphs.insert(iter.key(), c); -
172 -
173 m_cx += c.w + paddingDoubled; -
174 ++iter; -
175 }
-
176 return true;
-
177 -
178} -
179 -
180void QTextureGlyphCache::fillInPendingGlyphs() -
181{ -
182 if (m_pendingGlyphs.isEmpty())
-
183 return;
-
184 -
185 int requiredHeight = m_h; -
186 int requiredWidth = m_w; -
187 { -
188 QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); -
189 while (iter != m_pendingGlyphs.end()) {
-
190 Coord c = iter.value(); -
191 requiredHeight = qMax(requiredHeight, c.y + c.h); -
192 requiredWidth = qMax(requiredWidth, c.x + c.w); -
193 ++iter; -
194 }
-
195 } -
196 -
197 if (isNull() || requiredHeight > m_h || requiredWidth > m_w) {
-
198 if (isNull())
-
199 createCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
-
200 else -
201 resizeCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
-
202 } -
203 -
204 { -
205 QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); -
206 while (iter != m_pendingGlyphs.end()) {
-
207 GlyphAndSubPixelPosition key = iter.key(); -
208 fillTexture(iter.value(), key.glyph, key.subPixelPosition); -
209 -
210 ++iter; -
211 }
-
212 } -
213 -
214 m_pendingGlyphs.clear(); -
215}
-
216 -
217QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const -
218{ -
219 if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
-
220 return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, m_transform);
-
221 return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform);
-
222} -
223 -
224 -
225 -
226 -
227 -
228void QImageTextureGlyphCache::resizeTextureData(int width, int height) -
229{ -
230 m_image = m_image.copy(0, 0, width, height); -
231}
-
232 -
233void QImageTextureGlyphCache::createTextureData(int width, int height) -
234{ -
235 switch (m_type) { -
236 case QFontEngineGlyphCache::Raster_Mono: -
237 m_image = QImage(width, height, QImage::Format_Mono); -
238 break;
never executed: break;
0
239 case QFontEngineGlyphCache::Raster_A8: { -
240 m_image = QImage(width, height, QImage::Format_Indexed8); -
241 m_image.fill(0); -
242 QVector<QRgb> colors(256); -
243 QRgb *it = colors.data(); -
244 for (int i=0; i<256; ++i, ++it)
evaluated: i<256
TRUEFALSE
yes
Evaluation Count:256
yes
Evaluation Count:1
1-256
245 *it = 0xff000000 | i | (i<<8) | (i<<16);
executed: *it = 0xff000000 | i | (i<<8) | (i<<16);
Execution Count:256
256
246 m_image.setColorTable(colors); -
247 break; }
executed: break;
Execution Count:1
1
248 case QFontEngineGlyphCache::Raster_RGBMask: -
249 m_image = QImage(width, height, QImage::Format_RGB32); -
250 break;
never executed: break;
0
251 case QFontEngineGlyphCache::Raster_ARGB: -
252 break;
never executed: break;
0
253 } -
254}
executed: }
Execution Count:1
1
255 -
256void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition) -
257{ -
258 QImage mask = textureMapForGlyph(g, subPixelPosition); -
259 if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
-
260 QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()), -
261 qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(), -
262 m_image.format()); -
263 QPainter p(&ref); -
264 p.setCompositionMode(QPainter::CompositionMode_Source); -
265 p.fillRect(0, 0, c.w, c.h, QColor(0,0,0,0)); -
266 p.drawImage(0, 0, mask); -
267 p.end(); -
268 } else if (m_type == QFontEngineGlyphCache::Raster_Mono) {
-
269 if (mask.depth() > 1) {
-
270 -
271 mask = mask.alphaChannel(); -
272 mask.invertPixels(); -
273 mask = mask.convertToFormat(QImage::Format_Mono); -
274 }
-
275 -
276 int mw = qMin(mask.width(), c.w); -
277 int mh = qMin(mask.height(), c.h); -
278 uchar *d = m_image.bits(); -
279 int dbpl = m_image.bytesPerLine(); -
280 -
281 for (int y = 0; y < c.h; ++y) {
-
282 uchar *dest = d + (c.y + y) *dbpl + c.x/8; -
283 -
284 if (y < mh) {
-
285 uchar *src = mask.scanLine(y); -
286 for (int x = 0; x < c.w/8; ++x) {
-
287 if (x < (mw+7)/8)
-
288 dest[x] = src[x];
-
289 else -
290 dest[x] = 0;
-
291 } -
292 } else {
-
293 for (int x = 0; x < c.w/8; ++x)
-
294 dest[x] = 0;
-
295 }
-
296 } -
297 } else {
-
298 int mw = qMin(mask.width(), c.w); -
299 int mh = qMin(mask.height(), c.h); -
300 uchar *d = m_image.bits(); -
301 int dbpl = m_image.bytesPerLine(); -
302 -
303 if (mask.depth() == 1) {
-
304 for (int y = 0; y < c.h; ++y) {
-
305 uchar *dest = d + (c.y + y) *dbpl + c.x; -
306 if (y < mh) {
-
307 uchar *src = (uchar *) mask.scanLine(y); -
308 for (int x = 0; x < c.w; ++x) {
-
309 if (x < mw)
-
310 dest[x] = (src[x >> 3] & (1 << (7 - (x & 7)))) > 0 ? 255 : 0;
-
311 }
-
312 }
-
313 }
-
314 } else if (mask.depth() == 8) {
-
315 for (int y = 0; y < c.h; ++y) {
-
316 uchar *dest = d + (c.y + y) *dbpl + c.x; -
317 if (y < mh) {
-
318 uchar *src = (uchar *) mask.scanLine(y); -
319 for (int x = 0; x < c.w; ++x) {
-
320 if (x < mw)
-
321 dest[x] = src[x];
-
322 }
-
323 }
-
324 }
-
325 }
-
326 } -
327} -
328 -
329 -
330 -
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial