14 #include <fontconfig/fontconfig.h>
19 #include FT_FREETYPE_H
30 #define KERNING_UNKNOWN (-10000)
69 advanceX = GlyphData->advance.x >> 6;
70 advanceY = GlyphData->advance.y >> 6;
71 left = GlyphData->bitmap_left;
72 top = GlyphData->bitmap_top;
73 width = GlyphData->bitmap.width;
74 rows = GlyphData->bitmap.rows;
75 pitch = GlyphData->bitmap.pitch;
112 cGlyph*
Glyph(uint CharCode,
bool AntiAliased =
false)
const;
114 cFreetypeFont(
const char *Name,
int CharHeight,
int CharWidth = 0);
119 virtual int Width(uint c)
const;
120 virtual int Width(
const char *s)
const;
133 int error = FT_Init_FreeType(&
library);
137 if (
face->num_fixed_sizes &&
face->available_sizes) {
140 for (uint sym =
'A'; sym <
'z'; sym++) {
141 FT_UInt glyph_index = FT_Get_Char_Index(
face, sym);
142 error = FT_Load_Glyph(
face, glyph_index, FT_LOAD_DEFAULT);
144 error = FT_Render_Glyph(
face->glyph, FT_RENDER_MODE_NORMAL);
146 if (
int(
face->glyph->bitmap.rows-
face->glyph->bitmap_top) >
bottom)
150 esyslog(
"ERROR: FreeType: error %d in FT_Render_Glyph", error);
153 esyslog(
"ERROR: FreeType: error %d in FT_Load_Glyph", error);
157 error = FT_Set_Char_Size(
face,
163 height = (
face->size->metrics.ascender -
face->size->metrics.descender + 63) / 64;
164 bottom = abs((
face->size->metrics.descender - 63) / 64);
167 esyslog(
"ERROR: FreeType: error %d during FT_Set_Char_Size (font = %s)\n", error, Name);
171 esyslog(
"ERROR: FreeType: load error %d (font = %s)", error, Name);
174 esyslog(
"ERROR: FreeType: initialization error %d (font = %s)", error, Name);
186 if (
Glyph && PrevSym) {
191 FT_UInt glyph_index_prev = FT_Get_Char_Index(
face, PrevSym);
192 FT_Get_Kerning(
face, glyph_index_prev, glyph_index, FT_KERNING_DEFAULT, &delta);
193 kerning = delta.x / 64;
203 if (CharCode == 0xA0)
208 for (
cGlyph *g = glyphCache->First(); g; g = glyphCache->
Next(g)) {
209 if (g->CharCode() == CharCode)
213 FT_UInt glyph_index = FT_Get_Char_Index(
face, CharCode);
216 int error = FT_Load_Glyph(
face, glyph_index, FT_LOAD_DEFAULT);
218 esyslog(
"ERROR: FreeType: error during FT_Load_Glyph");
220 #if ((FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 7) || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 2 && FREETYPE_PATCH <= 1))// TODO workaround for bug? which one?
221 if (AntiAliased || CharCode == 32)
225 error = FT_Render_Glyph(
face->glyph, FT_RENDER_MODE_NORMAL);
227 error = FT_Render_Glyph(
face->glyph, FT_RENDER_MODE_MONO);
229 esyslog(
"ERROR: FreeType: error during FT_Render_Glyph %d, %d\n", CharCode, glyph_index);
236 #define UNKNOWN_GLYPH_INDICATOR '?'
270 #define MAX_BLEND_LEVELS 256
282 if (AntiAliased && !TransparentBackground)
283 memset(BlendLevelIndex, 0xFF,
sizeof(BlendLevelIndex));
293 int kerning =
Kerning(g, prevSym);
296 int symWidth = g->
Width();
299 if (x + symWidth + g->
Left() + kerning > 0) {
300 for (
int row = 0; row < g->
Rows(); row++) {
301 for (
int pitch = 0; pitch < g->
Pitch(); pitch++) {
302 uchar bt = *(buffer + (row * g->
Pitch() + pitch));
305 int px = x + pitch + g->
Left() + kerning;
310 else if (TransparentBackground)
311 bg = Bitmap->
Index(Bitmap->
Blend(ColorFg, Bitmap->GetColor(px, py), bt));
312 else if (BlendLevelIndex[bt] >= 0)
313 bg = BlendLevelIndex[bt];
315 bg = BlendLevelIndex[bt] = Bitmap->
Index(Bitmap->
Blend(ColorFg, ColorBg, bt));
320 for (
int col = 0; col < 8 && col + pitch * 8 <= symWidth; col++) {
330 if (x > Bitmap->
Width() - 1)
352 int kerning =
Kerning(g, prevSym);
355 int symWidth = g->
Width();
358 if (x + symWidth + g->
Left() + kerning > 0) {
359 for (
int row = 0; row < g->
Rows(); row++) {
360 for (
int pitch = 0; pitch < g->
Pitch(); pitch++) {
361 uchar bt = *(buffer + (row * g->
Pitch() + pitch));
367 for (
int col = 0; col < 8 && col + pitch * 8 <= symWidth; col++) {
377 if (x > Pixmap->DrawPort().Width() - 1)
422 default:
esyslog(
"ERROR: unknown Font %d (%s %d)",
Font, __FUNCTION__, __LINE__);
439 if (!FontNames->
Size()) {
441 FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
442 FcPattern *pat = FcPatternCreate();
443 FcPatternAddBool(pat, FC_SCALABLE, FcTrue);
445 FcPatternAddInteger(pat, FC_SPACING, FC_MONO);
446 FcFontSet* fontset = FcFontList(NULL, pat, os);
447 for (
int i = 0; i < fontset->nfont; i++) {
448 char *s = (
char *)FcNameUnparse(fontset->fonts[i]);
451 char *c = strchr(s,
':');
453 char *p = strchr(c + 1,
',');
457 char *p = strchr(s,
',');
460 memmove(p, c, strlen(c) + 1);
470 FcFontSetDestroy(fontset);
471 FcPatternDestroy(pat);
472 FcObjectSetDestroy(os);
476 return FontNames->
Size() > 0;
483 char *fn = strdup(FontName);
487 FcPattern *pat = FcNameParse((FcChar8 *)fn);
488 FcPatternAddBool(pat, FC_SCALABLE, FcTrue);
489 FcConfigSubstitute(NULL, pat, FcMatchPattern);
490 FcDefaultSubstitute(pat);
492 FcFontSet *fontset = FcFontSort(NULL, pat, FcFalse, NULL, &fresult);
494 for (
int i = 0; i < fontset->nfont; i++) {
496 FcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable);
499 FcPatternGetString(fontset->fonts[i], FC_FILE, 0, &s);
500 FontFileName = (
char *)s;
504 FcFontSetDestroy(fontset);
507 esyslog(
"ERROR: no usable font found for '%s'", FontName);
508 FcPatternDestroy(pat);
516 cString cFont::Bidi(
const char *Ltr)
519 fribidi_set_mirroring(
true);
520 fribidi_set_reorder_nsm(
false);
521 FriBidiCharSet fribidiCharset = FRIBIDI_CHAR_SET_UTF8;
522 int LtrLen = strlen(Ltr);
523 FriBidiCharType Base = FRIBIDI_TYPE_L;
524 FriBidiChar *Logical =
MALLOC(FriBidiChar, LtrLen + 1) ;
525 int RtlLen = fribidi_charset_to_unicode(fribidiCharset,
const_cast<char *
>(Ltr), LtrLen, Logical);
526 FriBidiChar *Visual =
MALLOC(FriBidiChar, LtrLen + 1) ;
528 bool ok = fribidi_log2vis(Logical, RtlLen, &Base, Visual, NULL, NULL, NULL);
530 fribidi_remove_bidi_marks(Visual, RtlLen, NULL, NULL, NULL);
531 Rtl =
MALLOC(
char, RtlLen * 4 + 1);
532 fribidi_unicode_to_charset(fribidiCharset, Visual, RtlLen, Rtl);
582 for (
char *p =
text; *p; ) {
588 Blank = Delim = NULL;
592 else if (sl == 1 && isspace(sym))
595 if (w + cw > Width) {
610 strcpy(s + l + 1, p);
618 if (strchr(
"-.,:;!?_", *p)) {
647 for (
int i = 0; i < Line; i++) {
656 if ((
eol = strchr(s,
'\n')) != NULL)