48 #ifndef QT_NO_FREETYPE 54 #include <private/qharfbuzz_p.h> 58 #include FT_FREETYPE_H 60 #include FT_SYNTHESIS_H 61 #include FT_TRUETYPE_TABLES_H 62 #include FT_TYPE1_TABLES_H 65 #if defined(FT_LCD_FILTER_H) 66 #include FT_LCD_FILTER_H 69 #if defined(FT_CONFIG_OPTIONS_H) 70 #include FT_CONFIG_OPTIONS_H 73 #if defined(FT_LCD_FILTER_H) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING) 74 #define QT_USE_FREETYPE_LCDFILTER 81 #if !defined(QT_MAX_CACHED_GLYPH_SIZE) 82 # define QT_MAX_CACHED_GLYPH_SIZE 64 92 #if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20105 93 #define X_SIZE(face,i) ((face)->available_sizes[i].x_ppem) 94 #define Y_SIZE(face,i) ((face)->available_sizes[i].y_ppem) 96 #define X_SIZE(face,i) ((face)->available_sizes[i].width << 6) 97 #define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6) 101 #if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20110 102 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot) FT_GlyphSlot_Embolden(slot) 104 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot) 107 #define FLOOR(x) ((x) & -64) 108 #define CEIL(x) (((x)+63) & -64) 109 #define TRUNC(x) ((x) >> 6) 110 #define ROUND(x) (((x)+32) & -64) 112 static HB_Error
hb_getSFntTable(
void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
114 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103 116 FT_ULong ftlen = *length;
119 if ( !FT_IS_SFNT(face) )
120 return HB_Err_Invalid_Argument;
122 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
124 return (HB_Error)
error;
126 return HB_Err_Invalid_Argument;
148 return theFreetypeData();
166 FT_Init_FreeType(&freetypeData->
library);
173 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
175 fsType = os2->fsType;
181 if (HB_Error
error = (HB_Error)FT_Load_Glyph(face, glyph, flags))
184 if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
185 return HB_Err_Invalid_SubTable;
187 *nPoints = face->glyph->outline.n_points;
191 if (point > *nPoints)
192 return HB_Err_Invalid_SubTable;
194 *xpos = face->glyph->outline.points[point].x;
195 *ypos = face->glyph->outline.points[point].y;
215 FT_Init_FreeType(&freetypeData->
library);
250 newFreetype->
face = face;
254 newFreetype->
ref = 1;
255 newFreetype->
xsize = 0;
256 newFreetype->
ysize = 0;
257 newFreetype->
matrix.xx = 0x10000;
258 newFreetype->
matrix.yy = 0x10000;
259 newFreetype->
matrix.xy = 0;
260 newFreetype->
matrix.yx = 0;
263 #ifndef QT_NO_FONTCONFIG 269 for (
int i = 0; i < newFreetype->
face->num_charmaps; ++i) {
270 FT_CharMap cm = newFreetype->
face->charmaps[i];
271 switch(cm->encoding) {
272 case FT_ENCODING_UNICODE:
275 case FT_ENCODING_APPLE_ROMAN:
276 case FT_ENCODING_ADOBE_LATIN_1:
280 case FT_ENCODING_ADOBE_CUSTOM:
281 case FT_ENCODING_MS_SYMBOL:
290 if (!FT_IS_SCALABLE(newFreetype->
face) && newFreetype->
face->num_fixed_sizes == 1)
294 FcPatternGetString(pattern, FC_FAMILY, 0, &name);
295 qDebug(
"%s: using maps: default: %x unicode: %x, symbol: %x", name,
296 newFreetype->
face->charmap ? newFreetype->
face->charmap->encoding : 0,
300 for (
int i = 0; i < 256; i += 8)
301 qDebug(
" %x: %d %d %d %d %d %d %d %d", i,
302 FcCharSetHasChar(newFreetype->
charset, i), FcCharSetHasChar(newFreetype->
charset, i),
303 FcCharSetHasChar(newFreetype->
charset, i), FcCharSetHasChar(newFreetype->
charset, i),
304 FcCharSetHasChar(newFreetype->
charset, i), FcCharSetHasChar(newFreetype->
charset, i),
305 FcCharSetHasChar(newFreetype->
charset, i), FcCharSetHasChar(newFreetype->
charset, i));
316 freetype = newFreetype.
take();
327 #ifndef QT_NO_FONTCONFIG 329 FcCharSetDestroy(charset);
336 FT_Done_FreeType(freetypeData->
library);
345 *xsize = *ysize * fontDef.
stretch / 100;
346 *outline_drawing =
false;
352 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
354 for (
int i = 1; i < face->num_fixed_sizes; i++) {
364 if (FT_Set_Char_Size (face,
X_SIZE(face, best),
Y_SIZE(face, best), 0, 0) == 0) {
365 *xsize =
X_SIZE(face, best);
366 *ysize =
Y_SIZE(face, best);
369 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) && ysize == 0 && face->num_fixed_sizes >= 1) {
371 err = FT_Set_Pixel_Sizes(face, face->available_sizes[0].width, face->available_sizes[0].height);
372 if (err && face->num_fixed_sizes == 1)
388 PS_FontInfoRec font_info;
389 if (FT_Get_PS_Font_Info(face, &font_info) == 0)
391 if (FT_IS_SCALABLE(face)) {
392 p.
ascent = face->ascender;
394 p.
leading = face->height - face->ascender + face->descender;
397 face->bbox.xMax - face->bbox.xMin,
398 face->bbox.yMax - face->bbox.yMin);
402 p.
leading =
QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender);
403 p.
emSquare = face->size->metrics.y_ppem;
417 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103 418 if (FT_IS_SFNT(face)) {
419 FT_ULong len = *length;
420 result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok;
438 x_scale = FT_MulDiv(x_scale, 1 << 10, face->units_per_EM);
439 y_scale = FT_MulDiv(y_scale, 1 << 10, face->units_per_EM);
440 FT_Vector *p = g->outline.points;
441 const FT_Vector *e = p + g->outline.n_points;
443 p->x = FT_MulFix(p->x, x_scale);
444 p->y = FT_MulFix(p->y, y_scale);
451 const qreal factor = 1/64.;
458 for (
int j = 0; j < g->outline.n_contours; ++j) {
459 int last_point = g->outline.contours[j];
460 QPointF start = cp +
QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
461 if(!(g->outline.tags[i] & 1)) {
462 start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor);
472 while (i < last_point) {
474 c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
477 switch (g->outline.tags[i] & 3) {
482 c[3] = (c[3] + c[2])/2;
489 c[3] = (c[1] + c[2])/2;
490 c[2] = (2*c[1] + c[3])/3;
491 c[1] = (2*c[1] + c[0])/3;
504 c[2] = (2*c[1] + c[3])/3;
505 c[1] = (2*c[1] + c[0])/3;
510 path->
cubicTo(c[1], c[2], c[3]);
520 c[2] = (2*c[1] + c[3])/3;
521 c[1] = (2*c[1] + c[0])/3;
524 path->
cubicTo(c[1], c[2], c[3]);
534 if (slot->format != FT_GLYPH_FORMAT_BITMAP
535 || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
540 slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path);
561 res = (mid << 24) + (high << 16) + (mid << 8) + low;
564 res = (alpha << 24) + (red << 16) + (green << 8) + blue;
572 const int offs = bgr ? -1 : 1;
573 const int w = width * 3;
576 for (
int x = 0; x < w; x += 3) {
591 const int offs = bgr ? -src_pitch : src_pitch;
593 for (
int x = 0; x < width; x++) {
594 uint red = src[x+src_pitch-offs];
597 dst[x] =
filterPixel(red, green, blue, legacyFilter);
614 for (
int x = 2; x < width - 2; ++x) {
615 uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2];
616 dst[x] = (
uchar) (sum >> 4);
618 dst[width - 2] = dst[width - 1] = 0;
632 kerning_pairs_loaded =
false;
637 default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
638 default_hint_style = HintNone;
639 subpixelType = Subpixel_None;
641 #if defined(FT_LCD_FILTER_H) 642 lcdFilterType = (int)((
quintptr) FT_LCD_FILTER_DEFAULT);
644 defaultFormat = Format_None;
645 canUploadGlyphsToServer =
false;
646 embeddedbitmap =
false;
652 freetype->release(face_id);
658 freeServerGlyphSet(defaultGlyphSet.id);
659 for (
int i = 0; i < transformedGlyphSets.count(); ++i)
660 freeServerGlyphSet(transformedGlyphSets.at(i).id);
672 freetype = freetypeFace;
679 this->antialias = antialias;
683 else if (format == Format_A8)
685 else if (format == Format_A32)
690 symbol = freetype->symbol_map != 0;
691 PS_FontInfoRec psrec;
693 if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) {
697 freetype->hbFace->isSymbolFont = symbol;
699 lbearing = rbearing = SHRT_MIN;
700 freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
704 if (FT_IS_SCALABLE(face)) {
705 bool fake_oblique = (fontDef.style !=
QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC);
707 matrix.xy = 0x10000*3/10;
708 FT_Set_Transform(face, &matrix, 0);
709 freetype->matrix = matrix;
713 if ((fontDef.weight ==
QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face))
716 line_thickness =
QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale));
717 underline_position =
QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));
721 int score = fontDef.weight * fontDef.pixelSize;
722 line_thickness = score / 700;
724 if (line_thickness < 2 && score >= 1050)
726 underline_position = ((line_thickness * 2) + 3) / 6;
728 if (line_thickness < 1)
731 hbFont.x_ppem = face->size->metrics.x_ppem;
732 hbFont.y_ppem = face->size->metrics.y_ppem;
733 hbFont.x_scale = face->size->metrics.x_scale;
734 hbFont.y_scale = face->size->metrics.y_scale;
736 hbFace = freetype->hbFace;
738 metrics = face->size->metrics;
740 #if defined(Q_WS_QWS) || defined(Q_WS_QPA) 748 if (FT_IS_SCALABLE(face)) {
749 for (
int i = 0; i < face->num_fixed_sizes; ++i) {
750 if (xsize ==
X_SIZE(face, i) && ysize ==
Y_SIZE(face, i)) {
751 face->face_flags &= ~FT_FACE_FLAG_SCALABLE;
753 FT_Select_Size(face, i);
754 metrics.ascender = face->size->metrics.ascender;
755 metrics.descender = face->size->metrics.descender;
756 FT_Set_Char_Size(face, xsize, ysize, 0, 0);
758 face->face_flags |= FT_FACE_FLAG_SCALABLE;
769 fsType = freetype->fsType();
770 defaultGlyphSet.id = allocateServerGlyphSet();
776 default_hint_style = style;
780 bool &hsubpixel,
int &vfactor)
const 782 int load_flags = FT_LOAD_DEFAULT | default_load_flags;
783 int load_target = default_hint_style == HintLight
784 ? FT_LOAD_TARGET_LIGHT
785 : FT_LOAD_TARGET_NORMAL;
787 if (format == Format_Mono) {
788 load_target = FT_LOAD_TARGET_MONO;
789 }
else if (format == Format_A32) {
791 if (default_hint_style == HintFull)
792 load_target = FT_LOAD_TARGET_LCD;
795 if (default_hint_style == HintFull)
796 load_target = FT_LOAD_TARGET_LCD_V;
801 if (
set &&
set->outline_drawing)
802 load_flags = FT_LOAD_NO_BITMAP;
804 if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics) || (
set &&
set->outline_drawing))
805 load_flags |= FT_LOAD_NO_HINTING;
807 load_flags |= load_target;
815 bool fetchMetricsOnly)
const 819 bool uploadToServer =
false;
820 if (format == Format_None) {
821 if (defaultFormat != Format_None) {
822 format = defaultFormat;
823 if (canUploadGlyphsToServer)
824 uploadToServer =
true;
826 format = Format_Mono;
830 Glyph *g =
set->getGlyph(glyph, subPixelPosition);
831 if (g && g->
format == format) {
833 set->setGlyph(glyph, subPixelPosition, 0);
844 bool hsubpixel =
false;
846 int load_flags = loadFlags(
set, format, 0, hsubpixel, vfactor);
849 if (format != Format_Mono && !embeddedbitmap)
850 load_flags |= FT_LOAD_NO_BITMAP;
853 FT_Matrix matrix = freetype->matrix;
854 bool transform = matrix.xx != 0x10000
855 || matrix.yy != 0x10000
860 load_flags |= FT_LOAD_NO_BITMAP;
865 v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.
toReal() * 64);
867 FT_Set_Transform(face, &freetype->matrix, &v);
869 FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
870 if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
871 load_flags &= ~FT_LOAD_NO_BITMAP;
872 err = FT_Load_Glyph(face, glyph, load_flags);
874 if (err == FT_Err_Too_Few_Arguments) {
876 load_flags |= FT_LOAD_FORCE_AUTOHINT;
877 err = FT_Load_Glyph(face, glyph, load_flags);
879 if (err != FT_Err_Ok)
880 qWarning(
"load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
882 if (
set->outline_drawing && fetchMetricsOnly)
885 FT_GlyphSlot slot = face->glyph;
892 uchar *glyph_buffer = 0;
893 int glyph_buffer_size = 0;
894 #if defined(QT_USE_FREETYPE_LCDFILTER) 895 bool useFreetypeRenderGlyph =
false;
896 if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
897 err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType);
898 if (err == FT_Err_Ok)
899 useFreetypeRenderGlyph =
true;
902 if (useFreetypeRenderGlyph) {
903 err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V);
905 if (err != FT_Err_Ok)
906 qWarning(
"render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
908 FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE);
910 info.height = slot->bitmap.rows / vfactor;
911 info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
912 info.x = -slot->bitmap_left;
913 info.y = slot->bitmap_top;
915 glyph_buffer_size = info.width * info.height * 4;
916 glyph_buffer =
new uchar[glyph_buffer_size];
920 else if (vfactor != 1)
925 int left = slot->metrics.horiBearingX;
926 int right = slot->metrics.horiBearingX + slot->metrics.width;
927 int top = slot->metrics.horiBearingY;
928 int bottom = slot->metrics.horiBearingY - slot->metrics.height;
929 if(transform && slot->format != FT_GLYPH_FORMAT_BITMAP) {
934 FT_Vector_Transform(&vector, &matrix);
939 FT_Vector_Transform(&vector, &matrix);
940 if (l > vector.x) l = vector.x;
941 if (r < vector.x) r = vector.x;
942 if (t < vector.y) t = vector.y;
943 if (b > vector.y) b = vector.y;
946 FT_Vector_Transform(&vector, &matrix);
947 if (l > vector.x) l = vector.x;
948 if (r < vector.x) r = vector.x;
949 if (t < vector.y) t = vector.y;
950 if (b > vector.y) b = vector.y;
953 FT_Vector_Transform(&vector, &matrix);
954 if (l > vector.x) l = vector.x;
955 if (r < vector.x) r = vector.x;
956 if (t < vector.y) t = vector.y;
957 if (b > vector.y) b = vector.y;
965 bottom =
FLOOR(bottom);
968 int hpixels =
TRUNC(right - left);
970 if (subPixelPosition > 0 && format != Format_Mono)
974 hpixels = hpixels*3 + 8;
975 info.width = hpixels;
976 info.height =
TRUNC(top - bottom);
977 info.x = -
TRUNC(left);
984 bool large_glyph = (((short)(slot->linearHoriAdvance>>10) != slot->linearHoriAdvance>>10)
985 || ((
uchar)(info.width) != info.width)
986 || ((
uchar)(info.height) != info.height)
987 || ((
signed char)(info.x) != info.x)
988 || ((
signed char)(info.y) != info.y)
989 || ((
signed char)(info.xOff) != info.xOff));
992 delete [] glyph_buffer;
996 int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
997 (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
998 glyph_buffer_size = pitch * info.height;
999 glyph_buffer =
new uchar[glyph_buffer_size];
1001 if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
1003 bitmap.rows = info.height*vfactor;
1004 bitmap.width = hpixels;
1005 bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3);
1006 if (!hsubpixel && vfactor == 1)
1007 bitmap.buffer = glyph_buffer;
1009 bitmap.buffer =
new uchar[bitmap.rows*bitmap.pitch];
1010 memset(bitmap.buffer, 0, bitmap.rows*bitmap.pitch);
1011 bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY;
1013 matrix.xx = (hsubpixel ? 3 : 1) << 16;
1014 matrix.yy = vfactor << 16;
1015 matrix.yx = matrix.xy = 0;
1017 FT_Outline_Transform(&slot->outline, &matrix);
1018 FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor);
1019 FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap);
1021 Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
1023 uchar *convoluted =
new uchar[bitmap.rows*bitmap.pitch];
1024 bool useLegacyLcdFilter =
false;
1025 #if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) 1026 useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
1028 uchar *buffer = bitmap.buffer;
1029 if (!useLegacyLcdFilter) {
1030 convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
1031 buffer = convoluted;
1034 delete [] convoluted;
1035 }
else if (vfactor != 1) {
1039 if (bitmap.buffer != glyph_buffer)
1040 delete [] bitmap.buffer;
1041 }
else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
1042 Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
1043 uchar *src = slot->bitmap.buffer;
1044 uchar *dst = glyph_buffer;
1045 int h = slot->bitmap.rows;
1046 if (format == Format_Mono) {
1047 int bytes = ((info.width + 7) & ~7) >> 3;
1049 memcpy (dst, src, bytes);
1051 src += slot->bitmap.pitch;
1058 for (
int x = 0; x < slot->bitmap.width; x++) {
1059 uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1064 src += slot->bitmap.pitch;
1066 }
else if (vfactor != 1) {
1069 for (
int x = 0; x < slot->bitmap.width; x++) {
1070 uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1074 src += slot->bitmap.pitch;
1078 for (
int x = 0; x < slot->bitmap.width; x++) {
1079 unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
1083 src += slot->bitmap.pitch;
1088 qWarning(
"QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
1089 delete [] glyph_buffer;
1102 g->
width = info.width;
1109 g->
data = glyph_buffer;
1111 if (uploadToServer) {
1112 uploadGlyphToServer(
set, glyph, g, &info, glyph_buffer_size);
1115 set->setGlyph(glyph, subPixelPosition, g);
1142 return freetype->properties();
1147 if (FT_IS_SCALABLE(freetype->face))
1148 return freetype->face->units_per_EM;
1150 return freetype->face->size->metrics.y_ppem;
1155 return freetype->getSfntTable(tag, buffer, length);
1161 if ((fontDef.style !=
QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC))
1162 s = SynthesizedItalic;
1163 if ((fontDef.weight ==
QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD))
1164 s |= SynthesizedBold;
1165 if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face))
1166 s |= SynthesizedStretch;
1183 return QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
1188 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1189 if (os2 && os2->sxHeight) {
1191 QFixed answer =
QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM;
1200 TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1201 if (os2 && os2->xAvgCharWidth) {
1203 QFixed answer =
QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM;
1212 return metrics.max_advance >> 6;
1241 if (lbearing == SHRT_MIN)
1242 (void) minRightBearing();
1243 return lbearing.toReal();
1248 if (rbearing == SHRT_MIN) {
1249 lbearing = rbearing = 0;
1257 lbearing =
qMin(lbearing, gi.
x);
1262 return rbearing.toReal();
1267 return line_thickness;
1272 return underline_position;
1277 if (!kerning_pairs_loaded) {
1278 kerning_pairs_loaded =
true;
1280 if (freetype->face->size->metrics.x_ppem != 0) {
1281 QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem);
1283 const_cast<QFontEngineFT *
>(
this)->loadKerningPairs(scalingFactor);
1297 if (!FT_IS_SCALABLE(freetype->face))
1301 m.xx = FT_Fixed(matrix.
m11() * 65536);
1302 m.xy = FT_Fixed(-matrix.
m21() * 65536);
1303 m.yx = FT_Fixed(-matrix.
m12() * 65536);
1304 m.yy = FT_Fixed(matrix.
m22() * 65536);
1308 for (
int i = 0; i < transformedGlyphSets.count(); ++i) {
1309 const QGlyphSet &g = transformedGlyphSets.at(i);
1316 transformedGlyphSets.move(i, 0);
1317 gs = &transformedGlyphSets[0];
1325 if (draw_as_outline)
1329 if (transformedGlyphSets.count() >= 10) {
1330 transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1331 freeServerGlyphSet(transformedGlyphSets.at(0).id);
1333 transformedGlyphSets.prepend(
QGlyphSet());
1335 gs = &transformedGlyphSets[0];
1339 gs->id = allocateServerGlyphSet();
1341 gs->transformationMatrix = m;
1342 gs->outline_drawing = draw_as_outline;
1350 int m_subPixelPositionCount = 4;
1351 if (!supportsSubPixelPositions())
1356 subPixelPosition = x - x.
floor();
1358 subPixelPosition = fraction /
QFixed(m_subPixelPositionCount);
1360 return subPixelPosition;
1369 for (
int i = 0; i < num_glyphs; ++i) {
1370 QFixed spp = subPixelPositionForX(positions[i].x);
1372 if (glyph == 0 || glyph->
format != format) {
1375 FT_Matrix m = matrix;
1377 FT_Set_Transform(face, &m, 0);
1378 freetype->matrix = m;
1380 if (!loadGlyph(gs, glyphs[i], spp, format)) {
1395 FT_Face face = lockFace(Unscaled);
1396 FT_Set_Transform(face, 0, 0);
1397 FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1399 int left = face->glyph->metrics.horiBearingX;
1400 int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width;
1401 int top = face->glyph->metrics.horiBearingY;
1402 int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
1414 if (!FT_IS_SCALABLE(freetype->face))
1419 FT_Set_Transform(face, &freetype->matrix, 0);
1423 static inline unsigned int getChar(
const QChar *str,
int &i,
const int len)
1426 if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()) {
1435 FT_Face face = freetype->face;
1439 for (
int i = 0; i < len; i++ ) {
1440 unsigned int uc =
getChar(
string, i, len);
1441 if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) {
1450 for (
int i = 0; i < len; i++ ) {
1451 unsigned int uc =
getChar(
string, i, len);
1452 if (!FT_Get_Char_Index(face, uc))
1464 if (FT_IS_SCALABLE(freetype->face)) {
1471 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
1473 FT_Face face = lockFace(Unscaled);
1474 for (
int gl = 0; gl < glyphs.
numGlyphs; gl++) {
1475 FT_UInt glyph = positioned_glyphs[gl];
1476 FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO);
1477 freetype->addBitmapToPath(face->glyph, positions[gl], path);
1486 FT_Face face = lockFace(Unscaled);
1488 for (
int gl = 0; gl < numGlyphs; gl++) {
1489 FT_UInt glyph = glyphs[gl];
1491 FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1493 FT_GlyphSlot g = face->glyph;
1494 if (g->format != FT_GLYPH_FORMAT_OUTLINE)
1502 QTextEngine::ShaperFlags flags)
const 1504 if (*nglyphs < len) {
1509 #if !defined(QT_NO_FONTCONFIG) 1516 if (freetype->symbol_map) {
1517 FT_Face face = freetype->face;
1518 for (
int i = 0; i < len; ++i ) {
1519 unsigned int uc =
getChar(str, i, len);
1521 if ( !glyphs->
glyphs[glyph_pos] ) {
1523 #if !defined(QT_NO_FONTCONFIG) 1529 if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
1534 glyph = FT_Get_Char_Index(face, uc);
1535 if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1540 FT_Set_Charmap(face, freetype->symbol_map);
1541 glyph = FT_Get_Char_Index(face, uc);
1542 FT_Set_Charmap(face, freetype->unicode_map);
1544 glyphs->
glyphs[glyph_pos] = glyph;
1546 freetype->cmapCache[uc] = glyph;
1551 FT_Face face = freetype->face;
1552 for (
int i = 0; i < len; ++i) {
1553 unsigned int uc =
getChar(str, i, len);
1557 if (!glyphs->
glyphs[glyph_pos]) {
1558 #if !defined(QT_NO_FONTCONFIG) 1564 if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
1568 glyph_t glyph = FT_Get_Char_Index(face, uc);
1569 if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1573 glyphs->
glyphs[glyph_pos] = glyph;
1575 freetype->cmapCache[uc] = glyph;
1582 *nglyphs = glyph_pos;
1585 #if !defined(QT_NO_FONTCONFIG) 1593 recalcAdvances(glyphs, flags);
1601 bool design = (default_hint_style == HintNone ||
1602 default_hint_style == HintLight ||
1603 (flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face);
1604 for (
int i = 0; i < glyphs->
numGlyphs; i++) {
1605 Glyph *g = defaultGlyphSet.getGlyph(glyphs->
glyphs[i]);
1611 g = loadGlyph(glyphs->
glyphs[i], 0, Format_None,
true);
1630 overall.
y = -ascent();
1631 overall.
height = ascent() + descent() + 1;
1635 for (
int i = 0; i < glyphs.
numGlyphs; i++) {
1636 Glyph *g = defaultGlyphSet.getGlyph(glyphs.
glyphs[i]);
1640 g = loadGlyph(glyphs.
glyphs[i], 0, Format_None,
true);
1645 overall.
x =
qMin(overall.
x, x);
1646 overall.
y =
qMin(overall.
y, y);
1651 int left =
FLOOR(face->glyph->metrics.horiBearingX);
1652 int right =
CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1653 int top =
CEIL(face->glyph->metrics.horiBearingY);
1654 int bottom =
FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1658 overall.
x =
qMin(overall.
x, x);
1659 overall.
y =
qMin(overall.
y, y);
1660 xmax =
qMax(xmax, x +
TRUNC(right - left));
1661 ymax =
qMax(ymax, y +
TRUNC(top - bottom));
1666 overall.
width = xmax - overall.
x;
1678 Glyph *g = defaultGlyphSet.getGlyph(glyph);
1681 g = loadGlyph(glyph, 0, Format_None,
true);
1692 int left =
FLOOR(face->glyph->metrics.horiBearingX);
1693 int right =
CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1694 int top =
CEIL(face->glyph->metrics.horiBearingY);
1695 int bottom =
FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1722 m.xx = FT_Fixed(matrix.
m11() * 65536);
1723 m.xy = FT_Fixed(-matrix.
m21() * 65536);
1724 m.yx = FT_Fixed(-matrix.
m12() * 65536);
1725 m.yy = FT_Fixed(matrix.
m22() * 65536);
1726 for (
int i = 0; i < transformedGlyphSets.count(); ++i) {
1727 const QGlyphSet &g = transformedGlyphSets.at(i);
1734 transformedGlyphSets.move(i, 0);
1735 glyphSet = &transformedGlyphSets[0];
1742 if (transformedGlyphSets.count() >= 10) {
1743 transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1744 freeServerGlyphSet(transformedGlyphSets.at(0).id);
1746 transformedGlyphSets.prepend(
QGlyphSet());
1748 glyphSet = &transformedGlyphSets[0];
1750 glyphSet->
id = allocateServerGlyphSet();
1755 glyphSet = &defaultGlyphSet;
1758 if (!g || g->
format != format) {
1760 FT_Matrix m = this->matrix;
1762 freetype->matrix = m;
1763 g = loadGlyph(glyphSet, glyph, subPixelPosition, format);
1773 int left =
FLOOR(face->glyph->metrics.horiBearingX);
1774 int right =
CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1775 int top =
CEIL(face->glyph->metrics.horiBearingY);
1776 int bottom =
FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1793 GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono;
1795 Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1801 const int pitch = antialias ? (glyph->
width + 3) & ~3 : ((glyph->
width + 31)/32) * 4;
1806 for (
int i=0; i<256; ++i)
1807 colors[i] =
qRgba(0, 0, 0, i);
1808 img.setColorTable(colors);
1811 colors[0] =
qRgba(0, 0, 0, 0);
1812 colors[1] =
qRgba(0, 0, 0, 255);
1813 img.setColorTable(colors);
1815 Q_ASSERT(img.bytesPerLine() == pitch);
1817 for (
int y = 0; y < glyph->
height; ++y)
1818 memcpy(img.scanLine(y), &glyph->
data[y * pitch], pitch);
1834 Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1849 defaultGlyphSet.removeGlyphFromCache(glyph, 0);
1857 count = face->num_glyphs;
1866 FT_Face face = freetype->face;
1867 if (scale == Unscaled) {
1868 FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
1869 freetype->xsize = face->units_per_EM << 6;
1870 freetype->ysize = face->units_per_EM << 6;
1871 }
else if (freetype->xsize != xsize || freetype->ysize != ysize) {
1872 FT_Set_Char_Size(face, xsize, ysize, 0, 0);
1873 freetype->xsize = xsize;
1874 freetype->ysize = ysize;
1876 if (freetype->matrix.xx != matrix.xx ||
1877 freetype->matrix.yy != matrix.yy ||
1878 freetype->matrix.xy != matrix.xy ||
1879 freetype->matrix.yx != matrix.yx) {
1880 freetype->matrix = matrix;
1881 FT_Set_Transform(face, &freetype->matrix, 0);
1894 return freetype->face;
1899 : id(0), outline_drawing(false)
1917 for (
int i = 0; i < 256; ++i) {
1967 bool hsubpixel =
true;
2012 #endif // QT_NO_FREETYPE
static QFreetypeFace * getFace(const QFontEngine::FaceId &face_id, const QByteArray &fontData=QByteArray())
HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const
This function should return the set of OR'd flags that are true for the file engine's file...
SubpixelAntialiasingType subpixelType
static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
virtual QFixed averageCharWidth() const
unsigned int uploadedToServer
static QFixed fromFixed(int fixed)
void qHBFreeFace(HB_Face face)
Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
QIntegerForSizeof< void * >::Unsigned quintptr
QFontEngineFT(const QFontDef &fd)
virtual QImage alphaMapForGlyph(glyph_t)
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
static const ushort char_table[]
#define QT_END_NAMESPACE
This macro expands to.
void lock()
Locks the mutex.
void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
void setGlyph(glyph_t index, QFixed spp, Glyph *glyph)
The QMutex class provides access serialization between threads.
T * data() const
Returns the value of the pointer referenced by this object.
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
The QByteArray class provides an array of bytes.
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags)
T * take()
Returns the value of the pointer referenced by this object.
The QPointF class defines a point in the plane using floating point precision.
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
virtual QAbstractFileEngine * fileEngine() const
Returns the QIOEngine for this QFile object.
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
virtual QImage alphaMapForGlyph(glyph_t g)
long ASN1_INTEGER_get ASN1_INTEGER * a
GlyphFormat defaultFormat
virtual void freeServerGlyphSet(unsigned long id)
static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale)
bool ref()
Atomically increments the value of this QAtomicInt.
virtual QFontEngine::Properties properties() const
bool getSfntTable(uint tag, uchar *buffer, uint *length) const
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it...
The QHash class is a template class that provides a hash-table-based dictionary.
static QFixed fromReal(qreal r)
Q_DECL_CONSTEXPR T qAbs(const T &t)
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
The QChar class provides a 16-bit Unicode character.
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)
const T value(const Key &key) const
Returns the value associated with the key.
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t)
Glyph * getGlyph(glyph_t index, QFixed subPixelPosition=0) const
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
qreal x() const
Returns the x-coordinate of this point.
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
virtual bool canRender(const QChar *string, int len)
bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat=Format_None, const QByteArray &fontData=QByteArray())
HintStyle default_hint_style
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
Q_CORE_EXPORT void qDebug(const char *,...)
static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale)
bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
#define QT_BEGIN_NAMESPACE
This macro expands to.
#define Q_FT_GLYPHSLOT_EMBOLDEN(slot)
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
FT_Matrix transformationMatrix
The QRectF class defines a rectangle in the plane using floating point precision. ...
virtual unsigned long allocateServerGlyphSet()
struct FT_FaceRec_ * FT_Face
static float pixelSize(const QFontDef &request, int dpi)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
#define QT_MAX_CACHED_GLYPH_SIZE
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
static unsigned int getChar(const QChar *str, int &i, const int len)
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags)
QChar mirroredChar() const
Returns the mirrored character if this character is a mirrored character; otherwise returns the chara...
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool=false)
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const
Q_CORE_EXPORT void qWarning(const char *,...)
virtual QFixed lineThickness() const
static const uint subpixel_filter[3][3]
The QImage class provides a hardware-independent image representation that allows direct access to th...
virtual QFixed ascent() const
static const char * data(const QByteArray &arr)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
virtual QFontEngine::FaceId faceId() const
void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t)
QtFreetypeData * qt_getFreetypeData()
virtual qreal maxCharWidth() const
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs, const QFixedPoint *positions, GlyphFormat format=Format_Render)
void unlock()
Unlocks the mutex.
virtual QFixed xHeight() const
virtual QFixed xHeight() const
virtual qreal minRightBearing() const
QByteArray postscriptName
const char * constData() const
Returns a pointer to the data stored in the byte array.
uchar * bits()
Returns a pointer to the first pixel data.
bool initFromFontEngine(const QFontEngineFT *fontEngine)
HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc)
QFontEngine::Properties properties() const
virtual QFixed underlinePosition() const
static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph, QFontEngine *fe)
The QFile class provides an interface for reading from and writing to files.
glyph_t cmapCache[cmapCacheSize]
QHash< GlyphAndSubPixelPosition, Glyph * > glyph_data
void setDefaultHintStyle(HintStyle style)
void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
QFixed subPixelPositionForX(QFixed x)
void release(const QFontEngine::FaceId &face_id)
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format)
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
virtual QFixed leading() const
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily)
virtual bool uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const
virtual QFixed emSquareSize() const
FT_Face lockFace(Scaling scale=Scaled) const
bool canUploadGlyphsToServer
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
static uint surrogateToUcs4(ushort high, ushort low)
Converts a UTF16 surrogate pair with the given high and low values to its UCS-4 code point...
virtual int glyphCount() const
int size() const
Returns the number of bytes in this byte array.
QMutex * qt_fontdatabase_mutex()
qreal y() const
Returns the y-coordinate of this point.
void cubicTo(const QPointF &ctrlPt1, const QPointF &ctrlPt2, const QPointF &endPt)
Adds a cubic Bezier curve between the current position and the given endPoint using the control point...
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const
static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
QGlyphSet * loadTransformedGlyphSet(const QTransform &matrix)
static const int char_table_entries
virtual QFontEngine * cloneWithSize(qreal pixelSize) const
virtual QFixed descent() const
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
FT_Face non_locked_face() const
static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch)
FT_Library qt_getFreetype()
virtual qreal minLeftBearing() const
void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
The QThreadStorage class provides per-thread data storage.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Glyph * loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format=Format_None, bool fetchMetricsOnly=false) const
Glyph * fast_glyph_data[256]
virtual QFixed averageCharWidth() const
QByteArray & remove(int index, int len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
Q_DECL_CONSTEXPR int qRound(qreal d)
virtual void removeGlyphFromCache(glyph_t glyph)
static uint filterPixel(uint red, uint green, uint blue, bool legacyFilter)
QHash< QFontEngine::FaceId, QFreetypeFace * > faces
static qreal toReal(Register *reg, int type, bool *ok=0)
virtual int synthesized() const