9#include "private/qimage_p.h"
10#include <private/qstringiterator_p.h>
13#include <qpa/qplatformscreen.h>
14#include <QtCore/QUuid>
15#include <QtGui/QPainterPath>
31#include FT_SYNTHESIS_H
32#include FT_TRUETYPE_TABLES_H
33#include FT_TYPE1_TABLES_H
36#include FT_LCD_FILTER_H
38#if defined(FT_CONFIG_OPTIONS_H)
39#include FT_CONFIG_OPTIONS_H
42#if defined(FT_FONT_FORMATS_H)
43#include FT_FONT_FORMATS_H
50#if !defined(QT_MAX_CACHED_GLYPH_SIZE)
51# define QT_MAX_CACHED_GLYPH_SIZE 64
58#define FLOOR(x) ((x) & -64)
59#define CEIL(x) (((x)+63) & -64)
60#define TRUNC(x) ((x) >> 6)
61#define ROUND(x) (((x)+32) & -64)
68 if (FT_IS_SFNT(
face)) {
115 iter.value()->cleanup();
139 FT_Init_FreeType(&freetypeData->
library);
140#if defined(FT_FONT_FORMATS_H)
142 FT_Bool no_darkening =
false;
143 FT_Property_Set(freetypeData->
library,
"cff",
"no-stem-darkening", &no_darkening);
159 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(
face, ft_sfnt_os2);
170 if (
face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
173 *nPoints =
face->glyph->outline.n_points;
177 if (point > *nPoints)
189 return !FT_IS_SCALABLE(
face) && FT_HAS_COLOR(
face);
224 idx.
remove(0, strlen(prefix));
239 if (!newFreetype->fontData.isEmpty()) {
240 if (FT_New_Memory_Face(freetypeData->
library, (
const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.
index, &
face)) {
246 newFreetype->face =
face;
248 newFreetype->ref.storeRelaxed(1);
249 newFreetype->xsize = 0;
250 newFreetype->ysize = 0;
251 newFreetype->matrix.xx = 0x10000;
252 newFreetype->matrix.yy = 0x10000;
253 newFreetype->matrix.xy = 0;
254 newFreetype->matrix.yx = 0;
255 newFreetype->unicode_map =
nullptr;
256 newFreetype->symbol_map =
nullptr;
258 memset(newFreetype->cmapCache, 0,
sizeof(newFreetype->cmapCache));
260 for (
int i = 0;
i < newFreetype->face->num_charmaps; ++
i) {
261 FT_CharMap cm = newFreetype->face->charmaps[
i];
262 switch(cm->encoding) {
263 case FT_ENCODING_UNICODE:
264 newFreetype->unicode_map = cm;
266 case FT_ENCODING_APPLE_ROMAN:
267 case FT_ENCODING_ADOBE_LATIN_1:
268 if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE)
269 newFreetype->unicode_map = cm;
271 case FT_ENCODING_ADOBE_CUSTOM:
272 case FT_ENCODING_MS_SYMBOL:
273 if (!newFreetype->symbol_map)
274 newFreetype->symbol_map = cm;
281 if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
282 FT_Set_Char_Size(
face, newFreetype->face->available_sizes[0].x_ppem, newFreetype->face->available_sizes[0].y_ppem, 0, 0);
284 FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
286 freetypeData->
faces.
insert(face_id, newFreetype.get());
288 newFreetype.release()->release(face_id);
292 freetype = newFreetype.
release();
297void QFreetypeFace::cleanup()
317 FT_Done_FreeType(freetypeData->
library);
318 freetypeData->
library =
nullptr;
337 if (
error != FT_Err_Ok) {
343 numFaces =
face->num_faces;
347 if (faceStyleName == styleName)
377 *scalableBitmapScaleFactor = 1;
378 *outline_drawing =
false;
380 if (!(
face->face_flags & FT_FACE_FLAG_SCALABLE)) {
387 for (
int i = 1;
i <
face->num_fixed_sizes;
i++) {
399 for (
int i = 1;
i <
face->num_fixed_sizes;
i++) {
400 if (
face->available_sizes[
i].y_ppem < *
ysize) {
401 if (
face->available_sizes[
i].y_ppem >
face->available_sizes[best].y_ppem)
403 }
else if (
face->available_sizes[best].y_ppem < *
ysize) {
405 }
else if (
face->available_sizes[
i].y_ppem <
face->available_sizes[best].y_ppem) {
413 if (FT_Select_Size(
face, best) == 0) {
416 *
xsize =
face->available_sizes[best].x_ppem;
417 *
ysize =
face->available_sizes[best].y_ppem;
429 p.postscriptName = FT_Get_Postscript_Name(
face);
430 PS_FontInfoRec font_info;
431 if (FT_Get_PS_Font_Info(
face, &font_info) == 0)
432 p.copyright = font_info.notice;
433 if (FT_IS_SCALABLE(
face)) {
434 p.ascent =
face->ascender;
435 p.descent = -
face->descender;
437 p.emSquare =
face->units_per_EM;
445 p.emSquare =
face->size->metrics.y_ppem;
447 p.boundingBox =
QRectF(0, -
p.ascent.toReal(),
448 face->size->metrics.max_advance/64, (
p.ascent +
p.descent).toReal() );
451 p.capHeight =
p.ascent;
452 p.lineWidth =
face->underline_thickness;
473 x_scale = FT_MulDiv(x_scale, 1 << 10,
face->units_per_EM);
474 y_scale = FT_MulDiv(y_scale, 1 << 10,
face->units_per_EM);
475 FT_Vector *
p =
g->outline.points;
476 const FT_Vector *
e =
p +
g->outline.n_points;
478 p->x = FT_MulFix(
p->x, x_scale);
479 p->y = FT_MulFix(
p->y, y_scale);
484#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO
487 const qreal factor = 1/64.;
494 for (
int j = 0;
j <
g->outline.n_contours; ++
j) {
495 int last_point =
g->outline.contours[
j];
498 if (!(
g->outline.tags[
i] & 1)) {
499 if (!(
g->outline.tags[last_point] & 1)) {
502 -
g->outline.points[last_point].y*factor) +
start) / 2.0;
506 -
g->outline.points[last_point].y*factor);
517 while (
i < last_point) {
519 c[
n] = cp +
QPointF(
g->outline.points[
i].x*factor, -
g->outline.points[
i].y*factor);
521 <<
": on curve =" << (
bool)(
g->outline.tags[
i] & 1);
523 switch (
g->outline.tags[
i] & 3) {
528 c[3] = (
c[3] +
c[2])/2;
535 c[3] = (
c[1] +
c[2])/2;
536 c[2] = (2*
c[1] +
c[3])/3;
537 c[1] = (2*
c[1] +
c[0])/3;
550 c[2] = (2*
c[1] +
c[3])/3;
551 c[1] = (2*
c[1] +
c[0])/3;
556 path->cubicTo(
c[1],
c[2],
c[3]);
563 path->closeSubpath();
567 c[2] = (2*
c[1] +
c[3])/3;
568 c[1] = (2*
c[1] +
c[0])/3;
571 path->cubicTo(
c[1],
c[2],
c[3]);
581 if (slot->format != FT_GLYPH_FORMAT_BITMAP
582 || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
587 slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows,
path);
592 const int offs = bgr ? -1 : 1;
596 for (
int x = 0;
x <
w;
x += 3) {
600 *dd++ = (0xFFU << 24) | (
red << 16) | (
green << 8) |
blue;
609 const int offs = bgr ? -src_pitch : src_pitch;
623 static int type = -1;
650 qWarning(
"QFontEngineFT: Failed to create FreeType font engine");
666 void updateFamilyNameAndStyle()
670 if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)
673 if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD)
696 QFontEngineFTRawData *fe =
new QFontEngineFTRawData(
fontDef);
702 fe->updateFamilyNameAndStyle();
717 kerning_pairs_loaded =
false;
770 PS_FontInfoRec psrec;
772 if (FT_Get_PS_Font_Info(
freetype->
face, &psrec) == FT_Err_Ok) {
780 if (FT_IS_SCALABLE(
face)) {
788 if (
const TT_OS2 *os2 =
reinterpret_cast<const TT_OS2 *
>(FT_Get_Sfnt_Table(
face, ft_sfnt_os2))) {
789 if (os2->usWeightClass < 700 &&
798 underline_position = center_position - line_thickness / 2;
802 line_thickness = score / 7000;
804 if (line_thickness < 2 && score >= 1050)
806 underline_position = ((line_thickness * 2) + 3) / 6;
812 if (line_thickness < 1)
824 if (FT_IS_SCALABLE(
face)) {
825 for (
int i = 0;
i <
face->num_fixed_sizes; ++
i) {
826 if (xsize ==
face->available_sizes[
i].x_ppem && ysize ==
face->available_sizes[
i].y_ppem) {
827 face->face_flags &= ~FT_FACE_FLAG_SCALABLE;
829 FT_Select_Size(
face,
i);
830 if (
face->size->metrics.ascender +
face->size->metrics.descender > 0) {
840 FT_Set_Char_Size(
face, xsize, ysize, 0, 0);
842 face->face_flags |= FT_FACE_FLAG_SCALABLE;
847#if defined(FT_FONT_FORMATS_H)
848 const char *
fmt = FT_Get_Font_Format(
face);
850 FT_Bool no_stem_darkening =
true;
851 FT_Error err = FT_Property_Get(
qt_getFreetype(),
"cff",
"no-stem-darkening", &no_stem_darkening);
852 if (err == FT_Err_Ok)
880 switch (hintingPreference) {
906int QFontEngineFT::loadFlags(QGlyphSet *
set, GlyphFormat
format,
int flags,
907 bool &hsubpixel,
int &vfactor)
const
911 ? FT_LOAD_TARGET_LIGHT
912 : FT_LOAD_TARGET_NORMAL;
915 load_target = FT_LOAD_TARGET_MONO;
923 load_flags |= FT_LOAD_COLOR;
927 if (
set &&
set->outline_drawing)
928 load_flags |= FT_LOAD_NO_BITMAP;
931 load_flags |= FT_LOAD_NO_HINTING;
933 load_flags |= load_target;
936 load_flags |= FT_LOAD_FORCE_AUTOHINT;
944 return info.width > 0xFF ||
info.height > 0xFF ||
info.linearAdvance > 0x7FFF;
986 bool fetchMetricsOnly,
987 bool disableOutlineDrawing)
const
995 Glyph *
g =
set ?
set->getGlyph(glyph, subPixelPosition) :
nullptr;
996 if (
g &&
g->format ==
format && (fetchMetricsOnly ||
g->data))
999 if (!
g &&
set &&
set->isGlyphMissing(glyph))
1012 bool hsubpixel =
false;
1014 int load_flags = loadFlags(
set,
format, 0, hsubpixel, vfactor);
1022 load_flags |= FT_LOAD_NO_BITMAP;
1024 FT_Error err = FT_Load_Glyph(
face, glyph, load_flags);
1025 if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
1026 load_flags &= ~FT_LOAD_NO_BITMAP;
1027 err = FT_Load_Glyph(
face, glyph, load_flags);
1029 if (err == FT_Err_Too_Few_Arguments) {
1031 load_flags |= FT_LOAD_FORCE_AUTOHINT;
1032 err = FT_Load_Glyph(
face, glyph, load_flags);
1033 }
else if (err == FT_Err_Execution_Too_Long) {
1036 qWarning(
"load glyph failed due to broken hinting bytecode in font, switching to auto hinting");
1038 load_flags |= FT_LOAD_FORCE_AUTOHINT;
1039 err = FT_Load_Glyph(
face, glyph, load_flags);
1041 if (err != FT_Err_Ok) {
1042 qWarning(
"load glyph failed err=%x face=%p, glyph=%d", err,
face, glyph);
1044 set->setGlyphMissing(glyph);
1048 FT_GlyphSlot slot =
face->glyph;
1051 FT_GlyphSlot_Embolden(slot);
1053 FT_GlyphSlot_Oblique(slot);
1064 FT_Matrix_Multiply(&
m, &
matrix);
1068 info.linearAdvance = slot->linearHoriAdvance >> 10;
1072 if ((
set &&
set->outline_drawing && !disableOutlineDrawing) || fetchMetricsOnly) {
1073 int left = slot->metrics.horiBearingX;
1074 int right = slot->metrics.horiBearingX + slot->metrics.width;
1075 int top = slot->metrics.horiBearingY;
1076 int bottom = slot->metrics.horiBearingY - slot->metrics.height;
1078 if (
transform && slot->format != FT_GLYPH_FORMAT_BITMAP)
1098 g->linearAdvance =
info.linearAdvance;
1099 g->width =
info.width;
1100 g->height =
info.height;
1103 g->advance =
info.xOff;
1107 set->setGlyph(glyph, subPixelPosition,
g);
1112 int glyph_buffer_size = 0;
1113 std::unique_ptr<uchar[]> glyph_buffer;
1117 renderMode = FT_RENDER_MODE_MONO;
1120 if (!hsubpixel && vfactor == 1) {
1121 qWarning(
"Format_A32 requested, but subpixel layout is unknown.");
1125 renderMode = hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V;
1133 FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)
lcdFilterType);
1135 err = FT_Render_Glyph(slot, renderMode);
1136 if (err != FT_Err_Ok)
1137 qWarning(
"render glyph failed err=%x face=%p, glyph=%d", err,
face, glyph);
1139 FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE);
1141 info.height = slot->bitmap.rows;
1142 info.width = slot->bitmap.width;
1143 info.x = slot->bitmap_left;
1144 info.y = slot->bitmap_top;
1145 if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
1147 if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V)
1148 info.height =
info.height / vfactor;
1153 glyph_buffer_size =
info.height * pitch;
1154 glyph_buffer.reset(
new uchar[glyph_buffer_size]);
1156 if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
1159 int h = slot->bitmap.rows;
1162 int bytes = ((
info.width + 7) & ~7) >> 3;
1164 memcpy (
dst,
src, bytes);
1166 src += slot->bitmap.pitch;
1170 for (
int x = 0;
x <
int{
info.width};
x++)
1171 dst[
x] = ((
src[
x >> 3] & (0x80 >> (
x & 7))) ? 0xff : 0x00);
1173 src += slot->bitmap.pitch;
1178 for (
int x = 0;
x <
int{
info.width};
x++)
1179 dd[
x] = ((
src[
x >> 3] & (0x80 >> (
x & 7))) ? 0xffffffff : 0x00000000);
1181 src += slot->bitmap.pitch;
1184 }
else if (slot->bitmap.pixel_mode == 7 ) {
1188 int h = slot->bitmap.rows;
1190#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1193 for (
int x = 0; x < static_cast<int>(slot->bitmap.width);
x++, srcPixel++, dstPixel++) {
1194 const quint32 pixel = *srcPixel;
1195 *dstPixel =
qbswap(pixel);
1198 memcpy(
dst,
src, slot->bitmap.width * 4);
1200 dst += slot->bitmap.pitch;
1201 src += slot->bitmap.pitch;
1203 info.linearAdvance =
info.xOff = slot->bitmap.width;
1204 }
else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
1208 int h = slot->bitmap.rows;
1209 int bytes =
info.width;
1211 memcpy (
dst,
src, bytes);
1213 src += slot->bitmap.pitch;
1215 }
else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
1218 }
else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
1222 qWarning(
"QFontEngine: Glyph rendered in unknown pixel_mode=%d", slot->bitmap.pixel_mode);
1231 g->linearAdvance =
info.linearAdvance;
1232 g->width =
info.width;
1233 g->height =
info.height;
1236 g->advance =
info.xOff;
1239 g->data = glyph_buffer.release();
1242 set->setGlyph(glyph, subPixelPosition,
g);
1255 if (
p.postscriptName.isEmpty()) {
1295 if (scalableBitmapScaleFactor != 1) {
1296 m_ascent *= scalableBitmapScaleFactor;
1304 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(
freetype->
face, ft_sfnt_os2);
1305 if (os2 && os2->version >= 2) {
1316 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(
freetype->
face, ft_sfnt_os2);
1317 if (os2 && os2->sxHeight) {
1329 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(
freetype->
face, ft_sfnt_os2);
1330 if (os2 && os2->xAvgCharWidth) {
1343 if (scalableBitmapScaleFactor != 1)
1344 max_advance *= scalableBitmapScaleFactor;
1345 return max_advance.
toReal();
1350 return line_thickness;
1355 return underline_position;
1360 if (!kerning_pairs_loaded) {
1361 kerning_pairs_loaded =
true;
1372 if (shouldUseDesignMetrics(
flags))
1375 flags &= ~DesignMetrics;
1384 m.xx = FT_Fixed(
matrix.m11() * 65536);
1385 m.xy = FT_Fixed(-
matrix.m21() * 65536);
1386 m.yx = FT_Fixed(-
matrix.m12() * 65536);
1387 m.yy = FT_Fixed(
matrix.m22() * 65536);
1397 for (;
i < nSets; ++
i) {
1398 QGlyphSet *
g = sets[
i];
1401 if (
g->transformationMatrix.xx ==
m.xx
1402 &&
g->transformationMatrix.xy ==
m.xy
1403 &&
g->transformationMatrix.yx ==
m.yx
1404 &&
g->transformationMatrix.yy ==
m.yy) {
1416 moveToFront(nSets - 1);
1418 sets[0] =
new QGlyphSet;
1419 QGlyphSet *gs = sets[0];
1421 gs->transformationMatrix =
m;
1428void QFontEngineFT::TransformedGlyphSets::moveToFront(
int i)
1430 QGlyphSet *
g = sets[
i];
1432 sets[
i] = sets[
i - 1];
1454 FT_Set_Transform(
face,
nullptr,
nullptr);
1455 FT_Load_Glyph(
face, glyph, FT_LOAD_NO_BITMAP);
1457 int left =
face->glyph->metrics.horiBearingX;
1458 int right =
face->glyph->metrics.horiBearingX +
face->glyph->metrics.width;
1459 int top =
face->glyph->metrics.horiBearingY;
1460 int bottom =
face->glyph->metrics.horiBearingY -
face->glyph->metrics.height;
1501 for (
int gl = 0; gl < glyphs.
numGlyphs; gl++) {
1502 FT_UInt glyph = positioned_glyphs[gl];
1503 FT_Load_Glyph(
face, glyph, FT_LOAD_TARGET_MONO);
1515 for (
int gl = 0; gl <
numGlyphs; gl++) {
1516 FT_UInt glyph = glyphs[gl];
1518 FT_Load_Glyph(
face, glyph, FT_LOAD_NO_BITMAP);
1520 FT_GlyphSlot
g =
face->glyph;
1521 if (
g->format != FT_GLYPH_FORMAT_OUTLINE)
1524 FT_GlyphSlot_Embolden(
g);
1526 FT_GlyphSlot_Oblique(
g);
1537 glyph = FT_Get_Char_Index(
face, ucs4);
1551 glyph = FT_Get_Char_Index(
face, ucs4);
1553 if (!glyph &&
symbol && ucs4 < 0x100)
1554 glyph = FT_Get_Char_Index(
face, ucs4 + 0xf000);
1565 QFontEngine::ShaperFlags
flags)
const
1568 if (*nglyphs <
len) {
1577 while (
it.hasNext()) {
1580 if ( !glyphs->
glyphs[glyph_pos] ) {
1590 if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1592 glyph = FT_Get_Char_Index(
face, uc);
1596 glyph = FT_Get_Char_Index(
face, uc);
1598 if (!glyph &&
symbol && uc < 0x100)
1599 glyph = FT_Get_Char_Index(
face, uc + 0xf000);
1601 glyphs->
glyphs[glyph_pos] = glyph;
1610 while (
it.hasNext()) {
1613 if (!glyphs->
glyphs[glyph_pos]) {
1617 if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1621 glyphs->
glyphs[glyph_pos] = glyph;
1630 *nglyphs = glyph_pos;
1639bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags
flags)
const
1649 return m * scalableBitmapScaleFactor;
1656 t.m21(),
t.m22(),
t.m23(),
1658 const qreal scaleFactor = scalableBitmapScaleFactor.
toReal();
1659 trans.
scale(scaleFactor, scaleFactor);
1661 QRectF rect(
m.x.toReal(),
m.y.toReal(),
m.width.toReal(),
m.height.toReal());
1679 FT_Face
face =
nullptr;
1680 bool design = shouldUseDesignMetrics(
flags);
1685 if (
g &&
g->format == acceptableFormat) {
1704 if (scalableBitmapScaleFactor != 1)
1705 glyphs->
advances[
i] *= scalableBitmapScaleFactor;
1713 FT_Face
face =
nullptr;
1744 overall.
x =
qMin(overall.
x,
x);
1745 overall.
y =
qMin(overall.
y,
y);
1752 int right =
CEIL(
face->glyph->metrics.horiBearingX +
face->glyph->metrics.width);
1753 int top =
CEIL(
face->glyph->metrics.horiBearingY);
1758 overall.
x =
qMin(overall.
x,
x);
1759 overall.
y =
qMin(overall.
y,
y);
1766 overall.
width = xmax - overall.
x;
1772 overall = scaledBitmapMetrics(overall,
QTransform());
1778 FT_Face
face =
nullptr;
1792 overall.
width =
g->width;
1794 overall.
xoff =
g->advance;
1799 int right =
CEIL(
face->glyph->metrics.horiBearingX +
face->glyph->metrics.width);
1800 int top =
CEIL(
face->glyph->metrics.horiBearingY);
1813 overall = scaledBitmapMetrics(overall,
QTransform());
1831 const bool needsImageTransform = !FT_IS_SCALABLE(
freetype->
face)
1841 overall.
width =
g->width;
1843 overall.
xoff =
g->advance;
1849 int right =
CEIL(
face->glyph->metrics.horiBearingX +
face->glyph->metrics.width);
1850 int top =
CEIL(
face->glyph->metrics.horiBearingY);
1862 overall = scaledBitmapMetrics(overall,
matrix);
1868 if (glyph ==
nullptr || glyph->
height == 0 || glyph->
width == 0)
1872 int bytesPerLine = -1;
1873 switch (glyphFormat) {
1876 bytesPerLine = ((glyph->
width + 31) & ~31) >> 3;
1880 bytesPerLine = (glyph->
width + 3) & ~3;
1884 bytesPerLine = glyph->
width * 4;
1906 neededFormat = defaultFormat;
1927 bool fetchBoundingBox,
1928 bool disableOutlineDrawing)
1931 if (glyphSet !=
nullptr && glyphSet->
outline_drawing && !disableOutlineDrawing && !fetchBoundingBox)
1934 Glyph *glyph = glyphSet !=
nullptr ? glyphSet->
getGlyph(
g, subPixelPosition) :
nullptr;
1935 if (!glyph || glyph->
format !=
format || (!fetchBoundingBox && !glyph->
data)) {
1941 FT_Matrix
m = this->matrix;
1943 FT_Matrix_Multiply(&ftMatrix, &
m);
1945 glyph =
loadGlyph(glyphSet,
g, subPixelPosition,
format,
false, disableOutlineDrawing);
1961 const bool needsImageTransform = !FT_IS_SCALABLE(
freetype->
face)
1968 if (needsImageTransform)
2010 if (glyph ==
nullptr)
2019 if (!
img.isNull() && (!
t.isIdentity() || scalableBitmapScaleFactor != 1)) {
2021 const qreal scaleFactor = scalableBitmapScaleFactor.
toReal();
2022 trans.
scale(scaleFactor, scaleFactor);
2053 if (FT_Set_Char_Size(
face,
face->units_per_EM << 6,
face->units_per_EM << 6, 0, 0) == 0) {
2058 FT_Set_Char_Size(
face, xsize, ysize, 0, 0);
2085 : outline_drawing(
false)
2091 memset(fast_glyph_data, 0,
sizeof(fast_glyph_data));
2092 fast_glyph_count = 0;
2102 if (fast_glyph_count > 0) {
2103 for (
int i = 0;
i < 256; ++
i) {
2104 if (fast_glyph_data[
i]) {
2105 delete fast_glyph_data[
i];
2106 fast_glyph_data[
i] =
nullptr;
2109 fast_glyph_count = 0;
2118 if (useFastGlyphData(
index, subPixelPosition)) {
2119 if (fast_glyph_data[
index]) {
2120 delete fast_glyph_data[
index];
2121 fast_glyph_data[
index] =
nullptr;
2122 if (fast_glyph_count > 0)
2134 if (useFastGlyphData(
index, subPixelPosition)) {
2135 if (!fast_glyph_data[
index])
2137 fast_glyph_data[
index] = glyph;
2146 bool hsubpixel =
true;
2148 int load_flags = loadFlags(
nullptr,
Format_A8,
flags, hsubpixel, vfactor);
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
bool startsWith(QByteArrayView bv) const
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
QByteArray & remove(qsizetype index, qsizetype len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
The QColor class provides colors based on RGB, HSV or CMYK values.
\inmodule QtCore \reentrant
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
bool expectsGammaCorrectedBlending() const override
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override
void setDefaultHintStyle(HintStyle style) override
HintStyle default_hint_style
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format) override
int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) override
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override
void initializeHeightMetrics() const override
QGlyphSet * loadGlyphSet(const QTransform &matrix)
QFixed underlinePosition() const override
QFixed lineThickness() const override
QFixed emSquareSize() const override
bool initFromFontEngine(const QFontEngineFT *fontEngine)
QFontEngine * cloneWithSize(qreal pixelSize) const override
void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override
QImage alphaMapForGlyph(glyph_t g) override
QFontEngineFT(const QFontDef &fd)
bool isScalableBitmap() const
QFixed xHeight() const override
FT_Face non_locked_face() const
bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat=Format_None, const QByteArray &fontData=QByteArray())
void removeGlyphFromCache(glyph_t glyph) override
qreal maxCharWidth() const override
void doKerning(QGlyphLayout *, ShaperFlags) const override
void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference)
Qt::HANDLE handle() const override
QFontEngine::Properties properties() const override
QFontEngine::FaceId faceId() const override
Glyph * loadGlyphFor(glyph_t g, const QFixedPoint &subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox=false, bool disableOutlineDrawing=false)
Glyph * loadGlyph(uint glyph, const QFixedPoint &subPixelPosition, GlyphFormat format=Format_None, bool fetchMetricsOnly=false, bool disableOutlineDrawing=false) const
int glyphCount() const override
static QFontEngineFT * create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData=QByteArray())
bool isBitmapFont() const
Glyph * glyphData(glyph_t glyph, const QFixedPoint &subPixelPosition, GlyphFormat neededFormat, const QTransform &t) override
glyph_t glyphIndex(uint ucs4) const override
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags) override
int synthesized() const override
QFixed capHeight() const override
QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override
QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override
SubpixelAntialiasingType subpixelType
QFixed averageCharWidth() const override
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override
Returns true if the font table idetified by tag exists in the font; returns false otherwise.
bool supportsTransformation(const QTransform &transform) const override
FT_Face lockFace(Scaling scale=Scaled) const
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const override
void * get() const noexcept
virtual QFixed descent() const
void loadKerningPairs(QFixed scalingFactor)
QFixed calculatedCapHeight() const
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily)
int m_subPixelPositionCount
virtual QFixed ascent() const
struct QFontEngine::FaceData faceData
virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t)
virtual QFixed averageCharWidth() const
virtual void initializeHeightMetrics() const
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags)
virtual void doKerning(QGlyphLayout *, ShaperFlags) const
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
virtual QFixed leading() const
void * harfbuzzFace() const
virtual QFixed xHeight() const
int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints)
static int getFaceIndexByStyleName(const QString &faceFileName, const QString &styleName)
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path)
static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale)
bool isScalableBitmap() const
glyph_t cmapCache[cmapCacheSize]
static QFreetypeFace * getFace(const QFontEngine::FaceId &face_id, const QByteArray &fontData=QByteArray())
void release(const QFontEngine::FaceId &face_id)
QFontEngine::Properties properties() const
void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor)
bool getSfntTable(uint tag, uchar *buffer, uint *length) const
QScreen * primaryScreen
the primary (or default) screen of the application.
const_iterator cbegin() const noexcept
const_iterator constFind(const Key &key) const noexcept
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
iterator erase(const_iterator it)
T value(const Key &key) const noexcept
const_iterator cend() const noexcept
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Format
The following image formats are available in Qt.
@ Format_ARGB32_Premultiplied
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
The QScreen class is used to query screen properties. \inmodule QtGui.
QPlatformScreen * handle() const
Get the platform screen handle.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
QByteArray toByteArray(StringFormat mode=WithBraces) const
QHash< QFontEngine::FaceId, QFreetypeFace * > faces
QHash< FaceStyle, int > faceIndices
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
int qstrncmp(const char *str1, const char *str2, size_t len)
AudioChannelLayoutTag tag
static const QCssKnownValue positions[NumKnownPositionModes - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void * user_data
DBusConnection const char DBusError * error
constexpr T qbswap(T source)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
int qRound(qfloat16 d) noexcept
static QFontEngineFT::Glyph emptyGlyph
void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint()
static FT_Matrix QTransformToFTMatrix(const QTransform &matrix)
static void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix)
static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
QtFreetypeData * qt_getFreetypeData()
static bool is2dRotation(const QTransform &t)
static QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat)
size_t qHash(const QtFreetypeData::FaceStyle &style, size_t seed)
static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
static const QFontEngine::HintStyle ftInitialDefaultHintStyle
static int computeFaceIndex(const QString &faceFileName, const QString &styleName)
bool operator==(const QtFreetypeData::FaceStyle &style1, const QtFreetypeData::FaceStyle &style2)
FT_Library qt_getFreetype()
QByteArray qt_fontdata_from_index(int)
static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
#define QT_MAX_CACHED_GLYPH_SIZE
static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale)
static void dont_delete(void *)
static bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info)
Q_GUI_EXPORT FT_Library qt_getFreetype()
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
constexpr QtPrivate::QHashMultiReturnType< T... > qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v< QtPrivate::QNothrowHashable< T >... >)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
constexpr T qAbs(const T &t)
GLboolean GLboolean GLboolean b
GLenum GLsizeiptr const void GLsizei faceIndex
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLenum const void GLbitfield GLsizei numGlyphs
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLenum GLsizeiptr const void * fontData
GLuint GLfloat GLfloat y0
GLfloat GLfloat GLfloat GLfloat h
GLuint GLenum GLenum transform
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
#define QT_MAX_CACHED_GLYPH_SIZE
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QVideoFrameFormat::PixelFormat fmt
QFuture< QSet< QChar > > set
[10]
QFileInfo info(fileName)
[8]
constexpr QPointF toPointF() const
static constexpr QFixed fromReal(qreal r)
static constexpr QFixed fromFixed(int fixed)
constexpr int value() const
constexpr QFixed round() const
constexpr QFixed ceil() const
constexpr qreal toReal() const
void setGlyph(glyph_t index, const QFixedPoint &spp, Glyph *glyph)
FT_Matrix transformationMatrix
void removeGlyphFromCache(glyph_t index, const QFixedPoint &subPixelPosition)
Glyph * getGlyph(glyph_t index, const QFixedPoint &subPixelPositionX=QFixedPoint()) const
qt_get_font_table_func_t get_font_table
QByteArray postscriptName
QFixed effectiveAdvance(int item) const
QGlyphAttributes * attributes
FaceStyle(QString faceFileName, QString styleName)