Qt 4.8
qfontengine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <qdebug.h>
43 #include <private/qfontengine_p.h>
44 
45 #include "qbitmap.h"
46 #include "qpainter.h"
47 #include "qpainterpath.h"
48 #include "qvarlengtharray.h"
49 #include <qmath.h>
50 #include <qendian.h>
51 #include <private/qharfbuzz_p.h>
52 
54 
55 static inline bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b)
56 {
58  return true;
59  } else {
60  // We always use paths for perspective text anyway, so no
61  // point in checking the full matrix...
64 
65  return a.m11() == b.m11()
66  && a.m12() == b.m12()
67  && a.m21() == b.m21()
68  && a.m22() == b.m22();
69  }
70 }
71 
72 // Harfbuzz helper functions
73 
74 static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
75 {
76  QFontEngine *fe = (QFontEngine *)font->userData;
77 
78  QVarLengthGlyphLayoutArray qglyphs(*numGlyphs);
79 
80  QTextEngine::ShaperFlags shaperFlags(QTextEngine::GlyphIndicesOnly);
81  if (rightToLeft)
82  shaperFlags |= QTextEngine::RightToLeft;
83 
84  int nGlyphs = *numGlyphs;
85  bool result = fe->stringToCMap(reinterpret_cast<const QChar *>(string), length, &qglyphs, &nGlyphs, shaperFlags);
86  *numGlyphs = nGlyphs;
87  if (!result)
88  return false;
89 
90  for (hb_uint32 i = 0; i < *numGlyphs; ++i)
91  glyphs[i] = qglyphs.glyphs[i];
92 
93  return true;
94 }
95 
96 static void hb_getAdvances(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags)
97 {
98  QFontEngine *fe = (QFontEngine *)font->userData;
99 
100  QVarLengthGlyphLayoutArray qglyphs(numGlyphs);
101 
102  for (hb_uint32 i = 0; i < numGlyphs; ++i)
103  qglyphs.glyphs[i] = glyphs[i];
104 
105  fe->recalcAdvances(&qglyphs, flags & HB_ShaperFlag_UseDesignMetrics ? QFlags<QTextEngine::ShaperFlag>(QTextEngine::DesignMetrics) : QFlags<QTextEngine::ShaperFlag>(0));
106 
107  for (hb_uint32 i = 0; i < numGlyphs; ++i)
108  advances[i] = qglyphs.advances_x[i].value();
109 }
110 
111 static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 length)
112 {
113  QFontEngine *fe = (QFontEngine *)font->userData;
114  return fe->canRender(reinterpret_cast<const QChar *>(string), length);
115 }
116 
117 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
118 {
119  QFontEngine *fe = (QFontEngine *)font->userData;
120  glyph_metrics_t m = fe->boundingBox(glyph);
121  metrics->x = m.x.value();
122  metrics->y = m.y.value();
123  metrics->width = m.width.value();
124  metrics->height = m.height.value();
125  metrics->xOffset = m.xoff.value();
126  metrics->yOffset = m.yoff.value();
127 }
128 
129 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
130 {
131  QFontEngine *fe = (QFontEngine *)font->userData;
132  switch (metric) {
133  case HB_FontAscent:
134  return fe->ascent().value();
135  break;
136  case HB_FontDescent:
137  return fe->descent().value();
138  break;
139  default:
140  return 0;
141  }
142 }
143 
144 HB_Error QFontEngine::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
145 {
146  Q_UNUSED(glyph)
147  Q_UNUSED(flags)
148  Q_UNUSED(point)
149  Q_UNUSED(xpos)
150  Q_UNUSED(ypos)
151  Q_UNUSED(nPoints)
152  return HB_Err_Not_Covered;
153 }
154 
155 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
156 {
157  QFontEngine *fe = (QFontEngine *)font->userData;
158  return fe->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints);
159 }
160 
161 static const HB_FontClass hb_fontClass = {
164 };
165 
166 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
167 {
168  QFontEngine *fe = (QFontEngine *)font;
169  if (!fe->getSfntTableData(tableTag, buffer, length))
170  return HB_Err_Invalid_Argument;
171  return HB_Err_Ok;
172 }
173 
174 // QFontEngine
175 
177  : QObject()
178 {
179  ref = 0;
180  cache_count = 0;
181  fsType = 0;
182  symbol = false;
183  memset(&hbFont, 0, sizeof(hbFont));
184  hbFont.klass = &hb_fontClass;
185  hbFont.userData = this;
186 
187  hbFace = 0;
188  glyphFormat = -1;
189 }
190 
192 {
193  m_glyphCaches.clear();
195 }
196 
198 {
199  // ad hoc algorithm
200  int score = fontDef.weight * fontDef.pixelSize;
201  int lw = score / 700;
202 
203  // looks better with thicker line for small pointsizes
204  if (lw < 2 && score >= 1050) lw = 2;
205  if (lw == 0) lw = 1;
206 
207  return lw;
208 }
209 
211 {
212  return ((lineThickness() * 2) + 3) / 6;
213 }
214 
216 {
217  if (!hbFont.x_ppem) {
218  QFixed emSquare = emSquareSize();
219  hbFont.x_ppem = fontDef.pixelSize;
220  hbFont.y_ppem = fontDef.pixelSize * fontDef.stretch / 100;
221  hbFont.x_scale = (QFixed(hbFont.x_ppem * (1 << 16)) / emSquare).value();
222  hbFont.y_scale = (QFixed(hbFont.y_ppem * (1 << 16)) / emSquare).value();
223  }
224  return &hbFont;
225 }
226 
228 {
229  if (!hbFace) {
230  hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
232  }
233  return hbFace;
234 }
235 
237 {
238  glyph_metrics_t metrics = boundingBox(glyph);
239 
240  if (matrix.type() > QTransform::TxTranslate) {
241  return metrics.transformed(matrix);
242  }
243  return metrics;
244 }
245 
247 {
248  QGlyphLayoutArray<8> glyphs;
249  int nglyphs = 7;
250  QChar x((ushort)'x');
251  stringToCMap(&x, 1, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);
252 
253  glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
254  return bb.height;
255 }
256 
258 {
259  QGlyphLayoutArray<8> glyphs;
260  int nglyphs = 7;
261  QChar x((ushort)'x');
262  stringToCMap(&x, 1, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);
263 
264  glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
265  return bb.xoff;
266 }
267 
268 
269 void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
271 {
272  QFixed xpos;
273  QFixed ypos;
274 
275  const bool transform = matrix.m11() != 1.
276  || matrix.m12() != 0.
277  || matrix.m21() != 0.
278  || matrix.m22() != 1.;
279  if (!transform) {
280  xpos = QFixed::fromReal(matrix.dx());
281  ypos = QFixed::fromReal(matrix.dy());
282  }
283 
284  int current = 0;
285  if (flags & QTextItem::RightToLeft) {
286  int i = glyphs.numGlyphs;
287  int totalKashidas = 0;
288  while(i--) {
289  if (glyphs.attributes[i].dontPrint)
290  continue;
291  xpos += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);
292  ypos += glyphs.advances_y[i];
293  totalKashidas += glyphs.justifications[i].nKashidas;
294  }
295  positions.resize(glyphs.numGlyphs+totalKashidas);
296  glyphs_out.resize(glyphs.numGlyphs+totalKashidas);
297 
298  i = 0;
299  while(i < glyphs.numGlyphs) {
300  if (glyphs.attributes[i].dontPrint) {
301  ++i;
302  continue;
303  }
304  xpos -= glyphs.advances_x[i];
305  ypos -= glyphs.advances_y[i];
306 
307  QFixed gpos_x = xpos + glyphs.offsets[i].x;
308  QFixed gpos_y = ypos + glyphs.offsets[i].y;
309  if (transform) {
310  QPointF gpos(gpos_x.toReal(), gpos_y.toReal());
311  gpos = gpos * matrix;
312  gpos_x = QFixed::fromReal(gpos.x());
313  gpos_y = QFixed::fromReal(gpos.y());
314  }
315  positions[current].x = gpos_x;
316  positions[current].y = gpos_y;
317  glyphs_out[current] = glyphs.glyphs[i];
318  ++current;
319  if (glyphs.justifications[i].nKashidas) {
320  QChar ch(0x640); // Kashida character
322  int nglyphs = 7;
323  stringToCMap(&ch, 1, &g, &nglyphs, 0);
324  for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
325  xpos -= g.advances_x[0];
326  ypos -= g.advances_y[0];
327 
328  QFixed gpos_x = xpos + glyphs.offsets[i].x;
329  QFixed gpos_y = ypos + glyphs.offsets[i].y;
330  if (transform) {
331  QPointF gpos(gpos_x.toReal(), gpos_y.toReal());
332  gpos = gpos * matrix;
333  gpos_x = QFixed::fromReal(gpos.x());
334  gpos_y = QFixed::fromReal(gpos.y());
335  }
336  positions[current].x = gpos_x;
337  positions[current].y = gpos_y;
338  glyphs_out[current] = g.glyphs[0];
339  ++current;
340  }
341  } else {
342  xpos -= QFixed::fromFixed(glyphs.justifications[i].space_18d6);
343  }
344  ++i;
345  }
346  } else {
347  positions.resize(glyphs.numGlyphs);
348  glyphs_out.resize(glyphs.numGlyphs);
349  int i = 0;
350  if (!transform) {
351  while (i < glyphs.numGlyphs) {
352  if (!glyphs.attributes[i].dontPrint) {
353  positions[current].x = xpos + glyphs.offsets[i].x;
354  positions[current].y = ypos + glyphs.offsets[i].y;
355  glyphs_out[current] = glyphs.glyphs[i];
356  xpos += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);
357  ypos += glyphs.advances_y[i];
358  ++current;
359  }
360  ++i;
361  }
362  } else {
363  while (i < glyphs.numGlyphs) {
364  if (!glyphs.attributes[i].dontPrint) {
365  QFixed gpos_x = xpos + glyphs.offsets[i].x;
366  QFixed gpos_y = ypos + glyphs.offsets[i].y;
367  QPointF gpos(gpos_x.toReal(), gpos_y.toReal());
368  gpos = gpos * matrix;
369  positions[current].x = QFixed::fromReal(gpos.x());
370  positions[current].y = QFixed::fromReal(gpos.y());
371  glyphs_out[current] = glyphs.glyphs[i];
372  xpos += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);
373  ypos += glyphs.advances_y[i];
374  ++current;
375  }
376  ++i;
377  }
378  }
379  }
380  positions.resize(current);
381  glyphs_out.resize(current);
382  Q_ASSERT(positions.size() == glyphs_out.size());
383 }
384 
385 void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
386 {
387  glyph_metrics_t gi = boundingBox(glyph);
388  bool isValid = gi.isValid();
389  if (leftBearing != 0)
390  *leftBearing = isValid ? gi.x.toReal() : qreal(0.0);
391  if (rightBearing != 0)
392  *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : qreal(0.0);
393 }
394 
396 {
397  glyph_metrics_t overall;
398 
399  QFixed ymax = 0;
400  QFixed xmax = 0;
401  for (int i = 0; i < glyphs.numGlyphs; i++) {
402  glyph_metrics_t bb = boundingBox(glyphs.glyphs[i]);
403  QFixed x = overall.xoff + glyphs.offsets[i].x + bb.x;
404  QFixed y = overall.yoff + glyphs.offsets[i].y + bb.y;
405  overall.x = qMin(overall.x, x);
406  overall.y = qMin(overall.y, y);
407  xmax = qMax(xmax, x + bb.width);
408  ymax = qMax(ymax, y + bb.height);
409  overall.xoff += bb.xoff;
410  overall.yoff += bb.yoff;
411  }
412  overall.height = qMax(overall.height, ymax - overall.y);
413  overall.width = xmax - overall.x;
414 
415  return overall;
416 }
417 
418 
420  QTextItem::RenderFlags flags)
421 {
422  if (!glyphs.numGlyphs)
423  return;
424 
426  QVarLengthArray<glyph_t> positioned_glyphs;
427  QTransform matrix = QTransform::fromTranslate(x, y);
428  getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
429  addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);
430 }
431 
432 #define GRID(x, y) grid[(y)*(w+1) + (x)]
433 #define SET(x, y) (*(image_data + (y)*bpl + ((x) >> 3)) & (0x80 >> ((x) & 7)))
434 
435 enum { EdgeRight = 0x1,
436  EdgeDown = 0x2,
437  EdgeLeft = 0x4,
438  EdgeUp = 0x8
439 };
440 
441 static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, int w, int h, QPainterPath *path)
442 {
443  Q_UNUSED(h);
444 
445  path->moveTo(x + x0, y + y0);
446  while (GRID(x, y)) {
447  if (GRID(x, y) & EdgeRight) {
448  while (GRID(x, y) & EdgeRight) {
449  GRID(x, y) &= ~EdgeRight;
450  ++x;
451  }
452  Q_ASSERT(x <= w);
453  path->lineTo(x + x0, y + y0);
454  continue;
455  }
456  if (GRID(x, y) & EdgeDown) {
457  while (GRID(x, y) & EdgeDown) {
458  GRID(x, y) &= ~EdgeDown;
459  ++y;
460  }
461  Q_ASSERT(y <= h);
462  path->lineTo(x + x0, y + y0);
463  continue;
464  }
465  if (GRID(x, y) & EdgeLeft) {
466  while (GRID(x, y) & EdgeLeft) {
467  GRID(x, y) &= ~EdgeLeft;
468  --x;
469  }
470  Q_ASSERT(x >= 0);
471  path->lineTo(x + x0, y + y0);
472  continue;
473  }
474  if (GRID(x, y) & EdgeUp) {
475  while (GRID(x, y) & EdgeUp) {
476  GRID(x, y) &= ~EdgeUp;
477  --y;
478  }
479  Q_ASSERT(y >= 0);
480  path->lineTo(x + x0, y + y0);
481  continue;
482  }
483  }
484  path->closeSubpath();
485 }
486 
487 Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
488 {
489  uint *grid = new uint[(w+1)*(h+1)];
490  // set up edges
491  for (int y = 0; y <= h; ++y) {
492  for (int x = 0; x <= w; ++x) {
493  bool topLeft = (x == 0)|(y == 0) ? false : SET(x - 1, y - 1);
494  bool topRight = (x == w)|(y == 0) ? false : SET(x, y - 1);
495  bool bottomLeft = (x == 0)|(y == h) ? false : SET(x - 1, y);
496  bool bottomRight = (x == w)|(y == h) ? false : SET(x, y);
497 
498  GRID(x, y) = 0;
499  if ((!topRight) & bottomRight)
500  GRID(x, y) |= EdgeRight;
501  if ((!bottomRight) & bottomLeft)
502  GRID(x, y) |= EdgeDown;
503  if ((!bottomLeft) & topLeft)
504  GRID(x, y) |= EdgeLeft;
505  if ((!topLeft) & topRight)
506  GRID(x, y) |= EdgeUp;
507  }
508  }
509 
510  // collect edges
511  for (int y = 0; y < h; ++y) {
512  for (int x = 0; x < w; ++x) {
513  if (!GRID(x, y))
514  continue;
515  // found start of a contour, follow it
516  collectSingleContour(x0, y0, grid, x, y, w, h, path);
517  }
518  }
519  delete [] grid;
520 }
521 
522 #undef GRID
523 #undef SET
524 
525 
527  QPainterPath *path, QTextItem::RenderFlags flags)
528 {
529 // TODO what to do with 'flags' ??
530  Q_UNUSED(flags);
531  QFixed advanceX = QFixed::fromReal(x);
532  QFixed advanceY = QFixed::fromReal(y);
533  for (int i=0; i < glyphs.numGlyphs; ++i) {
534  glyph_metrics_t metrics = boundingBox(glyphs.glyphs[i]);
535  if (metrics.width.value() == 0 || metrics.height.value() == 0) {
536  advanceX += glyphs.advances_x[i];
537  advanceY += glyphs.advances_y[i];
538  continue;
539  }
540  const QImage alphaMask = alphaMapForGlyph(glyphs.glyphs[i]);
541 
542  const int w = alphaMask.width();
543  const int h = alphaMask.height();
544  const int srcBpl = alphaMask.bytesPerLine();
545  QImage bitmap;
546  if (alphaMask.depth() == 1) {
547  bitmap = alphaMask;
548  } else {
549  bitmap = QImage(w, h, QImage::Format_Mono);
550  const uchar *imageData = alphaMask.bits();
551  const int destBpl = bitmap.bytesPerLine();
552  uchar *bitmapData = bitmap.bits();
553 
554  for (int yi = 0; yi < h; ++yi) {
555  const uchar *src = imageData + yi*srcBpl;
556  uchar *dst = bitmapData + yi*destBpl;
557  for (int xi = 0; xi < w; ++xi) {
558  const int byte = xi / 8;
559  const int bit = xi % 8;
560  if (bit == 0)
561  dst[byte] = 0;
562  if (src[xi])
563  dst[byte] |= 128 >> bit;
564  }
565  }
566  }
567  const uchar *bitmap_data = bitmap.bits();
568  QFixedPoint offset = glyphs.offsets[i];
569  advanceX += offset.x;
570  advanceY += offset.y;
571  qt_addBitmapToPath((advanceX + metrics.x).toReal(), (advanceY + metrics.y).toReal(), bitmap_data, bitmap.bytesPerLine(), w, h, path);
572  advanceX += glyphs.advances_x[i];
573  advanceY += glyphs.advances_y[i];
574  }
575 }
576 
578  QPainterPath *path, QTextItem::RenderFlags flags)
579 {
580  qreal x = positions[0].x.toReal();
581  qreal y = positions[0].y.toReal();
582  QVarLengthGlyphLayoutArray g(nGlyphs);
583 
584  for (int i = 0; i < nGlyphs; ++i) {
585  g.glyphs[i] = glyphs[i];
586  if (i < nGlyphs - 1) {
587  g.advances_x[i] = positions[i+1].x - positions[i].x;
588  g.advances_y[i] = positions[i+1].y - positions[i].y;
589  } else {
591  g.advances_y[i] = 0;
592  }
593  }
594 
595  addBitmapFontToPath(x, y, g, path, flags);
596 }
597 
599 {
600  // For font engines don't support subpixel positioning
601  return alphaMapForGlyph(glyph);
602 }
603 
605 {
606  QImage i = alphaMapForGlyph(glyph);
607  if (t.type() > QTransform::TxTranslate)
609  Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...
610 
611  return i;
612 }
613 
615 {
617  return alphaMapForGlyph(glyph, t);
618 
619  QImage i = alphaMapForGlyph(glyph, subPixelPosition);
620  if (t.type() > QTransform::TxTranslate)
622  Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...
623 
624  return i;
625 }
626 
627 QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, int /* margin */, const QTransform &t)
628 {
629  QImage alphaMask = alphaMapForGlyph(glyph, t);
630  QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);
631 
632  QVector<QRgb> colorTable = alphaMask.colorTable();
633  for (int y=0; y<alphaMask.height(); ++y) {
634  uint *dst = (uint *) rgbMask.scanLine(y);
635  uchar *src = (uchar *) alphaMask.scanLine(y);
636  for (int x=0; x<alphaMask.width(); ++x) {
637  int val = qAlpha(colorTable.at(src[x]));
638  dst[x] = qRgb(val, val, val);
639  }
640  }
641 
642  return rgbMask;
643 }
644 
646 {
647  glyph_metrics_t gm = boundingBox(glyph);
648  int glyph_x = qFloor(gm.x.toReal());
649  int glyph_y = qFloor(gm.y.toReal());
650  int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x;
651  int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y;
652 
653  if (glyph_width <= 0 || glyph_height <= 0)
654  return QImage();
655  QFixedPoint pt;
656  pt.x = -glyph_x;
657  pt.y = -glyph_y; // the baseline
658  QPainterPath path;
659  QImage im(glyph_width + 4, glyph_height, QImage::Format_ARGB32_Premultiplied);
660  im.fill(Qt::transparent);
661  QPainter p(&im);
663  addGlyphsToPath(&glyph, &pt, 1, &path, 0);
664  p.setPen(Qt::NoPen);
665  p.setBrush(Qt::black);
666  p.drawPath(path);
667  p.end();
668 
669  QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
670  QVector<QRgb> colors(256);
671  for (int i=0; i<256; ++i)
672  colors[i] = qRgba(0, 0, 0, i);
673  indexed.setColorTable(colors);
674 
675  for (int y=0; y<im.height(); ++y) {
676  uchar *dst = (uchar *) indexed.scanLine(y);
677  uint *src = (uint *) im.scanLine(y);
678  for (int x=0; x<im.width(); ++x)
679  dst[x] = qAlpha(src[x]);
680  }
681 
682  return indexed;
683 }
684 
686 {
687 }
688 
690 {
691  Properties p;
693  psname += '-';
694  psname += QByteArray::number(fontDef.style);
695  psname += '-';
696  psname += QByteArray::number(fontDef.weight);
697 
698  p.postscriptName = psname;
699  p.ascent = ascent();
700  p.descent = descent();
701  p.leading = leading();
702  p.emSquare = p.ascent;
703  p.boundingBox = QRectF(0, -p.ascent.toReal(), maxCharWidth(), (p.ascent + p.descent).toReal());
704  p.italicAngle = 0;
705  p.capHeight = p.ascent;
706  p.lineWidth = lineThickness();
707  return p;
708 }
709 
711 {
712  *metrics = boundingBox(glyph);
713  QFixedPoint p;
714  p.x = 0;
715  p.y = 0;
716  addGlyphsToPath(&glyph, &p, 1, path, QFlag(0));
717 }
718 
720 {
721  QByteArray table;
722  uint len = 0;
723  if (!getSfntTableData(tag, 0, &len))
724  return table;
725  if (!len)
726  return table;
727  table.resize(len);
728  if (!getSfntTableData(tag, reinterpret_cast<uchar *>(table.data()), &len))
729  return QByteArray();
730  return table;
731 }
732 
734 {
735  Q_ASSERT(data);
736 
737  GlyphCacheEntry entry;
738  entry.context = key;
739  entry.cache = data;
740  if (m_glyphCaches.contains(entry))
741  return;
742 
743  // Limit the glyph caches to 4. This covers all 90 degree rotations and limits
744  // memory use when there is continuous or random rotation
745  if (m_glyphCaches.size() == 4)
746  m_glyphCaches.removeLast();
747 
748  m_glyphCaches.push_front(entry);
749 
750 }
751 
753 {
754  for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) {
755  QFontEngineGlyphCache *c = it->cache.data();
756  if (key == it->context
757  && type == c->cacheType()
758  && qtransform_equals_no_translate(c->m_transform, transform)) {
759  return c;
760  }
761  }
762  return 0;
763 }
764 
765 #if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
766 static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
767 {
768  uint left_right = (left << 16) + right;
769 
770  left = 0, right = numPairs - 1;
771  while (left <= right) {
772  int middle = left + ( ( right - left ) >> 1 );
773 
774  if(pairs[middle].left_right == left_right)
775  return pairs[middle].adjust;
776 
777  if (pairs[middle].left_right < left_right)
778  left = middle + 1;
779  else
780  right = middle - 1;
781  }
782  return 0;
783 }
784 
785 void QFontEngine::doKerning(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
786 {
787  int numPairs = kerning_pairs.size();
788  if(!numPairs)
789  return;
790 
791  const KernPair *pairs = kerning_pairs.constData();
792 
793  if(flags & QTextEngine::DesignMetrics) {
794  for(int i = 0; i < glyphs->numGlyphs - 1; ++i)
795  glyphs->advances_x[i] += kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs);
796  } else {
797  for(int i = 0; i < glyphs->numGlyphs - 1; ++i)
798  glyphs->advances_x[i] += qRound(kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs));
799  }
800 }
801 
803 {
804  kerning_pairs.clear();
805 
806  QByteArray tab = getSfntTable(MAKE_TAG('k', 'e', 'r', 'n'));
807  if (tab.isEmpty())
808  return;
809 
810  const uchar *table = reinterpret_cast<const uchar *>(tab.constData());
811 
812  unsigned short version = qFromBigEndian<quint16>(table);
813  if (version != 0) {
814 // qDebug("wrong version");
815  return;
816  }
817 
818  unsigned short numTables = qFromBigEndian<quint16>(table + 2);
819  {
820  int offset = 4;
821  for(int i = 0; i < numTables; ++i) {
822  if (offset + 6 > tab.size()) {
823 // qDebug("offset out of bounds");
824  goto end;
825  }
826  const uchar *header = table + offset;
827 
828  ushort version = qFromBigEndian<quint16>(header);
829  ushort length = qFromBigEndian<quint16>(header+2);
830  ushort coverage = qFromBigEndian<quint16>(header+4);
831 // qDebug("subtable: version=%d, coverage=%x",version, coverage);
832  if(version == 0 && coverage == 0x0001) {
833  if (offset + length > tab.size()) {
834 // qDebug("length ouf ot bounds");
835  goto end;
836  }
837  const uchar *data = table + offset + 6;
838 
840  if(nPairs * 6 + 8 > length - 6) {
841 // qDebug("corrupt table!");
842  // corrupt table
843  goto end;
844  }
845 
846  int off = 8;
847  for(int i = 0; i < nPairs; ++i) {
849  p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2);
850  p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor;
851  kerning_pairs.append(p);
852  off += 6;
853  }
854  }
855  offset += length;
856  }
857  }
858 end:
860 // for (int i = 0; i < kerning_pairs.count(); ++i)
861 // qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;
862 }
863 
864 #else
865 void QFontEngine::doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
866 {
867 }
868 #endif
869 
871 {
872  QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
873  if (maxpTable.size() < 6)
874  return 0;
875  return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));
876 }
877 
878 const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
879 {
880  const uchar *header = table;
881  if (tableSize < 4)
882  return 0;
883 
884  const uchar *endPtr = table + tableSize;
885 
886  // version check
887  if (qFromBigEndian<quint16>(header) != 0)
888  return 0;
889 
890  unsigned short numTables = qFromBigEndian<quint16>(header + 2);
891  const uchar *maps = table + 4;
892  if (maps + 8 * numTables > endPtr)
893  return 0;
894 
895  enum {
896  Invalid,
897  AppleRoman,
898  Symbol,
899  Unicode11,
900  Unicode,
901  MicrosoftUnicode,
902  MicrosoftUnicodeExtended
903  };
904 
905  int symbolTable = -1;
906  int tableToUse = -1;
907  int score = Invalid;
908  for (int n = 0; n < numTables; ++n) {
909  const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
910  const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2);
911  switch (platformId) {
912  case 0: // Unicode
913  if (score < Unicode &&
914  (platformSpecificId == 0 ||
915  platformSpecificId == 2 ||
916  platformSpecificId == 3)) {
917  tableToUse = n;
918  score = Unicode;
919  } else if (score < Unicode11 && platformSpecificId == 1) {
920  tableToUse = n;
921  score = Unicode11;
922  }
923  break;
924  case 1: // Apple
925  if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman
926  tableToUse = n;
927  score = AppleRoman;
928  }
929  break;
930  case 3: // Microsoft
931  switch (platformSpecificId) {
932  case 0:
933  symbolTable = n;
934  if (score < Symbol) {
935  tableToUse = n;
936  score = Symbol;
937  }
938  break;
939  case 1:
940  if (score < MicrosoftUnicode) {
941  tableToUse = n;
942  score = MicrosoftUnicode;
943  }
944  break;
945  case 0xa:
946  if (score < MicrosoftUnicodeExtended) {
947  tableToUse = n;
948  score = MicrosoftUnicodeExtended;
949  }
950  break;
951  default:
952  break;
953  }
954  default:
955  break;
956  }
957  }
958  if(tableToUse < 0)
959  return 0;
960 
961 resolveTable:
962  *isSymbolFont = (symbolTable > -1);
963 
964  unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
965 
966  if (!unicode_table || unicode_table + 8 > tableSize)
967  return 0;
968 
969  // get the header of the unicode table
970  header = table + unicode_table;
971 
972  unsigned short format = qFromBigEndian<quint16>(header);
973  unsigned int length;
974  if(format < 8)
975  length = qFromBigEndian<quint16>(header + 2);
976  else
977  length = qFromBigEndian<quint32>(header + 4);
978 
979  if (table + unicode_table + length > endPtr)
980  return 0;
981  *cmapSize = length;
982 
983  // To support symbol fonts that contain a unicode table for the symbol area
984  // we check the cmap tables and fall back to symbol font unless that would
985  // involve losing information from the unicode table
986  if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) {
987  const uchar *selectedTable = table + unicode_table;
988 
989  // Check that none of the latin1 range are in the unicode table
990  bool unicodeTableHasLatin1 = false;
991  for (int uc=0x00; uc<0x100; ++uc) {
992  if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
993  unicodeTableHasLatin1 = true;
994  break;
995  }
996  }
997 
998  // Check that at least one symbol char is in the unicode table
999  bool unicodeTableHasSymbols = false;
1000  if (!unicodeTableHasLatin1) {
1001  for (int uc=0xf000; uc<0xf100; ++uc) {
1002  if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
1003  unicodeTableHasSymbols = true;
1004  break;
1005  }
1006  }
1007  }
1008 
1009  // Fall back to symbol table
1010  if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) {
1011  tableToUse = symbolTable;
1012  score = Symbol;
1013  goto resolveTable;
1014  }
1015  }
1016 
1017  return table + unicode_table;
1018 }
1019 
1021 {
1022  unsigned short format = qFromBigEndian<quint16>(cmap);
1023  if (format == 0) {
1024  if (unicode < 256)
1025  return (int) *(cmap+6+unicode);
1026  } else if (format == 4) {
1027  /* some fonts come with invalid cmap tables, where the last segment
1028  specified end = start = rangeoffset = 0xffff, delta = 0x0001
1029  Since 0xffff is never a valid Unicode char anyway, we just get rid of the issue
1030  by returning 0 for 0xffff
1031  */
1032  if(unicode >= 0xffff)
1033  return 0;
1034  quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
1035  const unsigned char *ends = cmap + 14;
1036  int i = 0;
1037  for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
1038 
1039  const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
1040  quint16 startIndex = qFromBigEndian<quint16>(idx);
1041 
1042  if (startIndex > unicode)
1043  return 0;
1044 
1045  idx += segCountX2;
1046  qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
1047  idx += segCountX2;
1048  quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
1049 
1050  quint16 glyphIndex;
1051  if (idRangeoffset_t) {
1052  quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx);
1053  if (id)
1054  glyphIndex = (idDelta + id) % 0x10000;
1055  else
1056  glyphIndex = 0;
1057  } else {
1058  glyphIndex = (idDelta + unicode) % 0x10000;
1059  }
1060  return glyphIndex;
1061  } else if (format == 6) {
1062  quint16 tableSize = qFromBigEndian<quint16>(cmap + 2);
1063 
1064  quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6);
1065  if (unicode < firstCode6)
1066  return 0;
1067 
1068  quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8);
1069  if (entryCount6 * 2 + 10 > tableSize)
1070  return 0;
1071 
1072  quint16 sentinel6 = firstCode6 + entryCount6;
1073  if (unicode >= sentinel6)
1074  return 0;
1075 
1076  quint16 entryIndex6 = unicode - firstCode6;
1077  return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2));
1078  } else if (format == 12) {
1079  quint32 nGroups = qFromBigEndian<quint32>(cmap + 12);
1080 
1081  cmap += 16; // move to start of groups
1082 
1083  int left = 0, right = nGroups - 1;
1084  while (left <= right) {
1085  int middle = left + ( ( right - left ) >> 1 );
1086 
1087  quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle);
1088  if(unicode < startCharCode)
1089  right = middle - 1;
1090  else {
1091  quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4);
1092  if(unicode <= endCharCode)
1093  return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode;
1094  left = middle + 1;
1095  }
1096  }
1097  } else {
1098  qDebug("cmap table of format %d not implemented", format);
1099  }
1100 
1101  return 0;
1102 }
1103 
1105 {
1106  QByteArray f = family;
1107  f.replace(' ', "");
1108  f.replace('(', "");
1109  f.replace(')', "");
1110  f.replace('<', "");
1111  f.replace('>', "");
1112  f.replace('[', "");
1113  f.replace(']', "");
1114  f.replace('{', "");
1115  f.replace('}', "");
1116  f.replace('/', "");
1117  f.replace('%', "");
1118  return f;
1119 }
1120 
1122  x->resize(256);
1123  QRgb *it = x->data();
1124  for (int i = 0; i < x->size(); ++i, ++it)
1125  *it = 0xff000000 | i | (i<<8) | (i<<16);
1126 })
1127 
1129 {
1130  return *qt_grayPalette();
1131 }
1132 
1134 {
1135  if (glyphs.numGlyphs >= 1) {
1136  glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1];
1137  glyph_metrics_t gi = boundingBox(glyph);
1138  if (gi.isValid())
1139  return round ? QFixed(qRound(gi.xoff - gi.x - gi.width))
1140  : QFixed(gi.xoff - gi.x - gi.width);
1141  }
1142  return 0;
1143 }
1144 
1145 // ------------------------------------------------------------------
1146 // The box font engine
1147 // ------------------------------------------------------------------
1148 
1150  : _size(size)
1151 {
1152  cache_cost = sizeof(QFontEngineBox);
1153 }
1154 
1156 {
1157 }
1158 
1159 bool QFontEngineBox::stringToCMap(const QChar *, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags) const
1160 {
1161  if (*nglyphs < len) {
1162  *nglyphs = len;
1163  return false;
1164  }
1165 
1166  for (int i = 0; i < len; i++) {
1167  glyphs->glyphs[i] = 0;
1168  glyphs->advances_x[i] = _size;
1169  glyphs->advances_y[i] = 0;
1170  }
1171 
1172  *nglyphs = len;
1173  glyphs->numGlyphs = len;
1174  return true;
1175 }
1176 
1177 void QFontEngineBox::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const
1178 {
1179  for (int i = 0; i < glyphs->numGlyphs; i++) {
1180  glyphs->advances_x[i] = _size;
1181  glyphs->advances_y[i] = 0;
1182  }
1183 }
1184 
1185 void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
1186 {
1187  if (!glyphs.numGlyphs)
1188  return;
1189 
1191  QVarLengthArray<glyph_t> positioned_glyphs;
1192  QTransform matrix = QTransform::fromTranslate(x, y - _size);
1193  getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
1194 
1195  QSize s(_size - 3, _size - 3);
1196  for (int k = 0; k < positions.size(); k++)
1197  path->addRect(QRectF(positions[k].toPointF(), s));
1198 }
1199 
1201 {
1202  glyph_metrics_t overall;
1203  overall.width = _size*glyphs.numGlyphs;
1204  overall.height = _size;
1205  overall.xoff = overall.width;
1206  return overall;
1207 }
1208 
1209 #if defined(Q_WS_QWS) || defined(Q_WS_QPA)
1210 void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti)
1211 {
1212  if (!ti.glyphs.numGlyphs)
1213  return;
1214 
1215  // any fixes here should probably also be done in QPaintEnginePrivate::drawBoxTextItem
1216  QSize s(_size - 3, _size - 3);
1217 
1219  QVarLengthArray<glyph_t> glyphs;
1220  QTransform matrix = QTransform::fromTranslate(x, y - _size);
1221  ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
1222  if (glyphs.size() == 0)
1223  return;
1224 
1225 
1226  QPainter *painter = p->painter();
1227  painter->save();
1228  painter->setBrush(Qt::NoBrush);
1229  QPen pen = painter->pen();
1230  pen.setWidthF(lineThickness().toReal());
1231  painter->setPen(pen);
1232  for (int k = 0; k < positions.size(); k++)
1233  painter->drawRect(QRectF(positions[k].toPointF(), s));
1234  painter->restore();
1235 }
1236 #endif
1237 
1239 {
1240  return glyph_metrics_t(0, -_size, _size, _size, _size, 0);
1241 }
1242 
1243 
1244 
1246 {
1247  return _size;
1248 }
1249 
1251 {
1252  return 0;
1253 }
1254 
1256 {
1257  QFixed l = _size * QFixed::fromReal(qreal(0.15));
1258  return l.ceil();
1259 }
1260 
1262 {
1263  return _size;
1264 }
1265 
1266 #ifdef Q_WS_X11
1268 {
1269  return -1;
1270 }
1271 #endif
1272 
1273 const char *QFontEngineBox::name() const
1274 {
1275  return "null";
1276 }
1277 
1279 {
1280  return true;
1281 }
1282 
1284 {
1285  return Box;
1286 }
1287 
1289 {
1291  QVector<QRgb> colors(256);
1292  for (int i=0; i<256; ++i)
1293  colors[i] = qRgba(0, 0, 0, i);
1294  image.setColorTable(colors);
1295  image.fill(0);
1296 
1297  // can't use qpainter for index8; so use setPixel to draw our rectangle.
1298  for (int i=2; i <= _size-3; ++i) {
1299  image.setPixel(i, 2, 255);
1300  image.setPixel(i, _size-3, 255);
1301  image.setPixel(2, i, 255);
1302  image.setPixel(_size-3, i, 255);
1303  }
1304  return image;
1305 }
1306 
1307 // ------------------------------------------------------------------
1308 // Multi engine
1309 // ------------------------------------------------------------------
1310 
1311 static inline uchar highByte(glyph_t glyph)
1312 { return glyph >> 24; }
1313 
1314 // strip high byte from glyph
1315 static inline glyph_t stripped(glyph_t glyph)
1316 { return glyph & 0x00ffffff; }
1317 
1319 {
1320  engines.fill(0, engineCount);
1321  cache_cost = 0;
1322 }
1323 
1325 {
1326  for (int i = 0; i < engines.size(); ++i) {
1327  QFontEngine *fontEngine = engines.at(i);
1328  if (fontEngine) {
1329  fontEngine->ref.deref();
1330  if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
1331  delete fontEngine;
1332  }
1333  }
1334 }
1335 
1336 bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
1337  QGlyphLayout *glyphs, int *nglyphs,
1338  QTextEngine::ShaperFlags flags) const
1339 {
1340  int ng = *nglyphs;
1341  if (!engine(0)->stringToCMap(str, len, glyphs, &ng, flags))
1342  return false;
1343 
1344  int glyph_pos = 0;
1345  for (int i = 0; i < len; ++i) {
1346  bool surrogate = (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate());
1347 
1348  if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) {
1349  QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos);
1350  for (int x = 1; x < engines.size(); ++x) {
1351  QFontEngine *engine = engines.at(x);
1352  if (!engine) {
1353  const_cast<QFontEngineMulti *>(this)->loadEngine(x);
1354  engine = engines.at(x);
1355  }
1356  Q_ASSERT(engine != 0);
1357  if (engine->type() == Box)
1358  continue;
1359  glyphs->advances_x[glyph_pos] = glyphs->advances_y[glyph_pos] = 0;
1360  glyphs->offsets[glyph_pos] = QFixedPoint();
1361  int num = 2;
1362  QGlyphLayout offs = glyphs->mid(glyph_pos, num);
1363  engine->stringToCMap(str + i, surrogate ? 2 : 1, &offs, &num, flags);
1364  Q_ASSERT(num == 1); // surrogates only give 1 glyph
1365  if (glyphs->glyphs[glyph_pos]) {
1366  // set the high byte to indicate which engine the glyph came from
1367  glyphs->glyphs[glyph_pos] |= (x << 24);
1368  break;
1369  }
1370  }
1371  // ensure we use metrics from the 1st font when we use the fallback image.
1372  if (!glyphs->glyphs[glyph_pos]) {
1373  glyphs->setInstance(glyph_pos, tmp);
1374  }
1375  }
1376  if (surrogate)
1377  ++i;
1378  ++glyph_pos;
1379  }
1380 
1381  *nglyphs = ng;
1382  glyphs->numGlyphs = ng;
1383  return true;
1384 }
1385 
1387 {
1388  if (glyphs.numGlyphs <= 0)
1389  return glyph_metrics_t();
1390 
1391  glyph_metrics_t overall;
1392 
1393  int which = highByte(glyphs.glyphs[0]);
1394  int start = 0;
1395  int end, i;
1396  for (end = 0; end < glyphs.numGlyphs; ++end) {
1397  const int e = highByte(glyphs.glyphs[end]);
1398  if (e == which)
1399  continue;
1400 
1401  // set the high byte to zero
1402  for (i = start; i < end; ++i)
1403  glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
1404 
1405  // merge the bounding box for this run
1406  const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));
1407 
1408  overall.x = qMin(overall.x, gm.x);
1409  overall.y = qMin(overall.y, gm.y);
1410  overall.width = overall.xoff + gm.width;
1411  overall.height = qMax(overall.height + overall.y, gm.height + gm.y) -
1412  qMin(overall.y, gm.y);
1413  overall.xoff += gm.xoff;
1414  overall.yoff += gm.yoff;
1415 
1416  // reset the high byte for all glyphs
1417  const int hi = which << 24;
1418  for (i = start; i < end; ++i)
1419  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
1420 
1421  // change engine
1422  start = end;
1423  which = e;
1424  }
1425 
1426  // set the high byte to zero
1427  for (i = start; i < end; ++i)
1428  glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
1429 
1430  // merge the bounding box for this run
1431  const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));
1432 
1433  overall.x = qMin(overall.x, gm.x);
1434  overall.y = qMin(overall.y, gm.y);
1435  overall.width = overall.xoff + gm.width;
1436  overall.height = qMax(overall.height + overall.y, gm.height + gm.y) -
1437  qMin(overall.y, gm.y);
1438  overall.xoff += gm.xoff;
1439  overall.yoff += gm.yoff;
1440 
1441  // reset the high byte for all glyphs
1442  const int hi = which << 24;
1443  for (i = start; i < end; ++i)
1444  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
1445 
1446  return overall;
1447 }
1448 
1449 void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
1450 {
1451  int which = highByte(glyph);
1452  engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);
1453 }
1454 
1456  QPainterPath *path, QTextItem::RenderFlags flags)
1457 {
1458  if (glyphs.numGlyphs <= 0)
1459  return;
1460 
1461  int which = highByte(glyphs.glyphs[0]);
1462  int start = 0;
1463  int end, i;
1464  if (flags & QTextItem::RightToLeft) {
1465  for (int gl = 0; gl < glyphs.numGlyphs; gl++) {
1466  x += glyphs.advances_x[gl].toReal();
1467  y += glyphs.advances_y[gl].toReal();
1468  }
1469  }
1470  for (end = 0; end < glyphs.numGlyphs; ++end) {
1471  const int e = highByte(glyphs.glyphs[end]);
1472  if (e == which)
1473  continue;
1474 
1475  if (flags & QTextItem::RightToLeft) {
1476  for (i = start; i < end; ++i) {
1477  x -= glyphs.advances_x[i].toReal();
1478  y -= glyphs.advances_y[i].toReal();
1479  }
1480  }
1481 
1482  // set the high byte to zero
1483  for (i = start; i < end; ++i)
1484  glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
1485  engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);
1486  // reset the high byte for all glyphs and update x and y
1487  const int hi = which << 24;
1488  for (i = start; i < end; ++i)
1489  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
1490 
1491  if (!(flags & QTextItem::RightToLeft)) {
1492  for (i = start; i < end; ++i) {
1493  x += glyphs.advances_x[i].toReal();
1494  y += glyphs.advances_y[i].toReal();
1495  }
1496  }
1497 
1498  // change engine
1499  start = end;
1500  which = e;
1501  }
1502 
1503  if (flags & QTextItem::RightToLeft) {
1504  for (i = start; i < end; ++i) {
1505  x -= glyphs.advances_x[i].toReal();
1506  y -= glyphs.advances_y[i].toReal();
1507  }
1508  }
1509 
1510  // set the high byte to zero
1511  for (i = start; i < end; ++i)
1512  glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
1513 
1514  engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);
1515 
1516  // reset the high byte for all glyphs
1517  const int hi = which << 24;
1518  for (i = start; i < end; ++i)
1519  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
1520 }
1521 
1522 void QFontEngineMulti::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
1523 {
1524  if (glyphs->numGlyphs <= 0)
1525  return;
1526 
1527  int which = highByte(glyphs->glyphs[0]);
1528  int start = 0;
1529  int end, i;
1530  for (end = 0; end < glyphs->numGlyphs; ++end) {
1531  const int e = highByte(glyphs->glyphs[end]);
1532  if (e == which)
1533  continue;
1534 
1535  // set the high byte to zero
1536  for (i = start; i < end; ++i)
1537  glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
1538 
1539  QGlyphLayout offs = glyphs->mid(start, end - start);
1540  engine(which)->recalcAdvances(&offs, flags);
1541 
1542  // reset the high byte for all glyphs and update x and y
1543  const int hi = which << 24;
1544  for (i = start; i < end; ++i)
1545  glyphs->glyphs[i] = hi | glyphs->glyphs[i];
1546 
1547  // change engine
1548  start = end;
1549  which = e;
1550  }
1551 
1552  // set the high byte to zero
1553  for (i = start; i < end; ++i)
1554  glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
1555 
1556  QGlyphLayout offs = glyphs->mid(start, end - start);
1557  engine(which)->recalcAdvances(&offs, flags);
1558 
1559  // reset the high byte for all glyphs
1560  const int hi = which << 24;
1561  for (i = start; i < end; ++i)
1562  glyphs->glyphs[i] = hi | glyphs->glyphs[i];
1563 }
1564 
1565 void QFontEngineMulti::doKerning(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
1566 {
1567  if (glyphs->numGlyphs <= 0)
1568  return;
1569 
1570  int which = highByte(glyphs->glyphs[0]);
1571  int start = 0;
1572  int end, i;
1573  for (end = 0; end < glyphs->numGlyphs; ++end) {
1574  const int e = highByte(glyphs->glyphs[end]);
1575  if (e == which)
1576  continue;
1577 
1578  // set the high byte to zero
1579  for (i = start; i < end; ++i)
1580  glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
1581 
1582  QGlyphLayout offs = glyphs->mid(start, end - start);
1583  engine(which)->doKerning(&offs, flags);
1584 
1585  // reset the high byte for all glyphs and update x and y
1586  const int hi = which << 24;
1587  for (i = start; i < end; ++i)
1588  glyphs->glyphs[i] = hi | glyphs->glyphs[i];
1589 
1590  // change engine
1591  start = end;
1592  which = e;
1593  }
1594 
1595  // set the high byte to zero
1596  for (i = start; i < end; ++i)
1597  glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
1598 
1599  QGlyphLayout offs = glyphs->mid(start, end - start);
1600  engine(which)->doKerning(&offs, flags);
1601 
1602  // reset the high byte for all glyphs
1603  const int hi = which << 24;
1604  for (i = start; i < end; ++i)
1605  glyphs->glyphs[i] = hi | glyphs->glyphs[i];
1606 }
1607 
1609 {
1610  const int which = highByte(glyph);
1611  Q_ASSERT(which < engines.size());
1612  return engine(which)->boundingBox(stripped(glyph));
1613 }
1614 
1616 { return engine(0)->ascent(); }
1617 
1619 { return engine(0)->descent(); }
1620 
1622 {
1623  return engine(0)->leading();
1624 }
1625 
1627 {
1628  return engine(0)->xHeight();
1629 }
1630 
1632 {
1633  return engine(0)->averageCharWidth();
1634 }
1635 
1637 {
1638  return engine(0)->lineThickness();
1639 }
1640 
1642 {
1643  return engine(0)->underlinePosition();
1644 }
1645 
1647 {
1648  return engine(0)->maxCharWidth();
1649 }
1650 
1652 {
1653  return engine(0)->minLeftBearing();
1654 }
1655 
1657 {
1658  return engine(0)->minRightBearing();
1659 }
1660 
1661 bool QFontEngineMulti::canRender(const QChar *string, int len)
1662 {
1663  if (engine(0)->canRender(string, len))
1664  return true;
1665 
1666  QVarLengthGlyphLayoutArray glyphs(len);
1667  int nglyphs = len;
1668  if (stringToCMap(string, len, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly) == false) {
1669  glyphs.resize(nglyphs);
1670  stringToCMap(string, len, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);
1671  }
1672 
1673  bool allExist = true;
1674  for (int i = 0; i < nglyphs; i++) {
1675  if (!glyphs.glyphs[i]) {
1676  allExist = false;
1677  break;
1678  }
1679  }
1680 
1681  return allExist;
1682 }
1683 
1685 {
1686  Q_ASSERT(false);
1687  return QImage();
1688 }
1689 
1690 
QAtomicInt ref
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
void resize(int size)
virtual QFixed lineThickness() const
glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs)
QFontEngine * fontEngine
virtual QFixed averageCharWidth() const
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
QGlyphJustification * justifications
void drawPath(const QPainterPath &path)
Draws the given painter path using the current pen for outline and the current brush for filling...
Definition: qpainter.cpp:3502
unsigned int QRgb
Definition: qrgb.h:53
virtual qreal minRightBearing() const
QFixed * advances_y
static QFixed fromFixed(int fixed)
Definition: qfixed_p.h:71
void qHBFreeFace(HB_Face face)
Definition: qharfbuzz.cpp:128
double qreal
Definition: qglobal.h:1193
virtual QFixed lineThickness() const
virtual int glyphCount() const
virtual QImage alphaMapForGlyph(glyph_t)
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int value() const
Definition: qfixed_p.h:73
virtual Type type() const
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QFixed * advances_x
int qCeil(qreal v)
Definition: qmath.h:63
void setColorTable(const QVector< QRgb > colors)
Sets the color table used to translate color indexes to QRgb values, to the specified colors...
Definition: qimage.cpp:1744
#define it(className, varName)
The QFlag class is a helper data type for QFlags.
Definition: qglobal.h:2289
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
HB_Glyph * glyphs
static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
static void hb_getAdvances(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags)
Definition: qfontengine.cpp:96
int qFloor(qreal v)
Definition: qmath.h:73
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
static glyph_t stripped(glyph_t glyph)
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
virtual QFixed averageCharWidth() const
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
HB_FontRec hbFont
RenderFlags flags
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags)
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
QObjectUserData * userData(uint id) const
Definition: qobject.cpp:4016
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
static const uchar * getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
static QColor cmap[256]
Definition: qgl_mac.mm:760
bool isLowSurrogate() const
Returns true if the QChar is the low part of a utf16 surrogate (ie.
Definition: qchar.h:279
virtual QImage alphaMapForGlyph(glyph_t)
QLinkedList< GlyphCacheEntry > m_glyphCaches
virtual QFixed ascent() const
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
long ASN1_INTEGER_get ASN1_INTEGER * a
Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
QGlyphLayout mid(int position, int n=-1) const
static QFixed fromReal(qreal r)
Definition: qfixed_p.h:70
virtual const char * name() const
bool isHighSurrogate() const
Returns true if the QChar is the high part of a utf16 surrogate (ie.
Definition: qchar.h:276
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const =0
TransformationType type() const
Returns the transformation type of this matrix.
virtual bool canRender(const QChar *string, int len)
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
virtual Type type() const =0
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
int cmap() const
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t)
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
Category category() const
Returns the character&#39;s category.
Definition: qchar.cpp:853
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
virtual ~QFontEngine()
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing=0, qreal *rightBearing=0)
#define MAKE_TAG(ch1, ch2, ch3, ch4)
virtual qreal maxCharWidth() const =0
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
Q_CORE_EXPORT void qDebug(const char *,...)
QGlyphLayout glyphs
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
unsigned char uchar
Definition: qglobal.h:994
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint...
Definition: qpainter.cpp:7620
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round=false)
QPainter * painter() const
Returns the paint engine&#39;s painter.
const QPen & pen() const
Returns the painter&#39;s current pen.
Definition: qpainter.cpp:4152
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
glyph_metrics_t transformed(const QTransform &xform) const
static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 length)
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
Definition: qrgb.h:72
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
QFixed y
Definition: qfixed_p.h:191
The QLinkedList::const_iterator class provides an STL-style const iterator for QLinkedList.
Definition: qlinkedlist.h:151
static QList< QAxEngineDescriptor > engines
Definition: qaxscript.cpp:69
static bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b)
Definition: qfontengine.cpp:55
static const QCssKnownValue positions[NumKnownPositionModes - 1]
Definition: qcssparser.cpp:329
static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
virtual bool canRender(const QChar *string, int len)=0
QExplicitlySharedDataPointer< QFontEngineGlyphCache > cache
virtual qreal maxCharWidth() const
bool deref()
Atomically decrements the value of this QAtomicInt.
static QFontEngine * loadEngine(int script, const QFontDef &request, QtFontFamily *family, QtFontFoundry *foundry, QtFontStyle *style, QtFontSize *size)
virtual QFixed ascent() const =0
short qint16
Definition: qglobal.h:935
virtual QFixed descent() const =0
virtual qreal maxCharWidth() const
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
unsigned short quint16
Definition: qglobal.h:936
Internal QTextItem.
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
uint weight
Definition: qfont_p.h:95
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const
static const HB_FontClass hb_fontClass
HB_Face hbFace
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)=0
QGlyphLayoutInstance instance(int position) const
virtual bool getSfntTableData(uint, uchar *, uint *) const
QImage transformed(const QMatrix &matrix, Qt::TransformationMode mode=Qt::FastTransformation) const
Returns a copy of the image that is transformed using the given transformation matrix and transformat...
Definition: qimage.cpp:4698
virtual void removeGlyphFromCache(glyph_t)
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
virtual bool canRender(const QChar *string, int len)
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
bool isValid() const
qreal pixelSize
Definition: qfont_p.h:90
virtual QFixed xHeight() const
static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, int w, int h, QPainterPath *path)
HB_Font harfbuzzFont() const
quint16 qFromBigEndian< quint16 >(const uchar *src)
Definition: qendian.h:249
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags)
virtual QFixed leading() const
void resize(int totalGlyphs)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QFixed x
Definition: qfixed_p.h:190
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
void setPixel(int x, int y, uint index_or_rgb)
Sets the pixel index or color at (x, y) to index_or_rgb.
Definition: qimage.cpp:4311
virtual qreal minLeftBearing() const
HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc)
Definition: qharfbuzz.cpp:123
QFontEngineBox(int size)
#define Q_CHECK_PTR(p)
Definition: qglobal.h:1853
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
virtual QFixed ascent() const
virtual Properties properties() const
void setGlyphCache(void *key, QFontEngineGlyphCache *data)
unsigned short ushort
Definition: qglobal.h:995
void setWidthF(qreal width)
Sets the pen width to the given width in pixels with floating point precision.
Definition: qpen.cpp:690
uint style
Definition: qfont_p.h:97
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily)
virtual QFixed descent() const
int key
void setBrush(const QBrush &brush)
Sets the painter&#39;s brush to the given brush.
Definition: qpainter.cpp:4171
void resize(int size)
Sets the size of the byte array to size bytes.
unsigned int quint32
Definition: qglobal.h:938
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
if(void) toggleToolbarShown
#define GRID(x, y)
QFactoryLoader * l
virtual QFixed emSquareSize() const
qreal toReal() const
Definition: qfixed_p.h:77
uint stretch
Definition: qfont_p.h:98
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
virtual QFixed descent() const
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition: qpainter.h:650
QVector< KernPair > kerning_pairs
static const QVector< QRgb > & grayPalette()
HB_GlyphAttributes * attributes
QByteArray & replace(int index, int len, const char *s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
static QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis...
Definition: qtransform.cpp:462
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
Definition: qfontengine.cpp:74
void loadKerningPairs(QFixed scalingFactor)
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qglobal.h:2313
QFontEngineGlyphCache * glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const
static uchar highByte(glyph_t glyph)
QFontDef fontDef
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing=0, qreal *rightBearing=0)
QFontEngineMulti(int engineCount)
QString family
Definition: qfont_p.h:82
virtual QFixed underlinePosition() const
virtual QImage alphaMapForGlyph(glyph_t)
QFixedPoint * offsets
static const KeyPair *const end
void setInstance(int position, const QGlyphLayoutInstance &g)
virtual QFixed xHeight() const
virtual QFixed leading() const
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
QFixed ceil() const
Definition: qfixed_p.h:82
void addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags)
QVector< QRgb > colorTable() const
Returns a list of the colors contained in the image&#39;s color table, or an empty list if the image does...
Definition: qimage.cpp:1770
Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector< QRgb >, qt_grayPalette, { x->resize(256);QRgb *it=x->data();for(int i=0;i< x->size();++i,++it) *it=0xff000000|i|(i<< 8)|(i<< 16);}) const QVector< QRgb > &QFontEngine
unsigned int glyph_t
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
virtual QFixed underlinePosition() const
bool end()
Ends painting.
Definition: qpainter.cpp:1929
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
virtual QFixed leading() const =0
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags)
int size() const
static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
static qreal toReal(Register *reg, int type, bool *ok=0)
virtual bool supportsSubPixelPositions() const
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
HB_Face harfbuzzFace() const
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
QByteArray getSfntTable(uint) const
#define SET(x, y)