📄 ftfont.cc
字号:
} // compute: (x0,y0) = position in destination drawable // (x1,y1) = position in glyph image // (w0,h0) = size of image transfer x0 = x - xOffset; y0 = y - yOffset; x1 = 0; y1 = 0; w0 = gw; h0 = gh; if (x0 < 0) { x1 = -x0; w0 += x0; x0 = 0; } if (x0 + w0 > w) { w0 = w - x0; } if (w0 < 0) { return gTrue; } if (y0 < 0) { y1 = -y0; h0 += y0; y0 = 0; } if (y0 + h0 > h) { h0 = h - y0; } if (h0 < 0) { return gTrue; } // read the X image XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1, ZPixmap, image, x1, y1); if (engine->aa) { // compute the colors xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2); XQueryColor(engine->display, engine->colormap, &xcolor); bgR = xcolor.red; bgG = xcolor.green; bgB = xcolor.blue; colors[1] = engine->findColor((r + 3*bgR) / 4, (g + 3*bgG) / 4, (b + 3*bgB) / 4); colors[2] = engine->findColor((r + bgR) / 2, (g + bgG) / 2, (b + bgB) / 2); colors[3] = engine->findColor((3*r + bgR) / 4, (3*g + bgG) / 4, (3*b + bgB) / 4); colors[4] = engine->findColor(r, g, b); // stuff the glyph pixmap into the X image for (yy = 0; yy < gh; ++yy) { for (xx = 0; xx < gw; ++xx) { pix = *p++ & 0xff; // this is a heuristic which seems to produce decent // results -- the linear mapping would be: // pix = (pix * 5) / 256; pix = ((pix + 10) * 5) / 256; if (pix > 4) { pix = 4; } if (pix > 0) { XPutPixel(image, xx, yy, colors[pix]); } } } } else { // one color colors[1] = engine->findColor(r, g, b); // stuff the glyph bitmap into the X image for (yy = 0; yy < gh; ++yy) { for (xx = 0; xx < gw; xx += 8) { pix = *p++; for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) { if (pix & 0x80) { XPutPixel(image, xx1, yy, colors[1]); } pix <<= 1; } } } } // draw the X image XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0); return gTrue;}Guchar *FTFont::getGlyphPixmap(CharCode c, Unicode u, int *x, int *y, int *w, int *h) { FT_GlyphSlot slot; FT_UInt idx; int rowSize; int i, j, k; Guchar *ret, *p, *q; // check the cache i = (c & (cacheSets - 1)) * cacheAssoc; for (j = 0; j < cacheAssoc; ++j) { if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) { *x = cacheTags[i+j].x; *y = cacheTags[i+j].y; *w = cacheTags[i+j].w; *h = cacheTags[i+j].h; for (k = 0; k < cacheAssoc; ++k) { if (k != j && (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) { ++cacheTags[i+k].mru; } } cacheTags[i+j].mru = 0x8000; return cache + (i+j) * glyphSize; } } // generate the glyph pixmap or bitmap fontFile->face->size = sizeObj; FT_Set_Transform(fontFile->face, &matrix, NULL); slot = fontFile->face->glyph; idx = getGlyphIndex(c, u); // if we have the FT2 bytecode interpreter, autohinting won't be used#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) { return gFalse; }#else // FT2's autohinting doesn't always work very well (especially with // font subsets), so turn it off if anti-aliasing is enabled; if // anti-aliasing is disabled, this seems to be a tossup - some fonts // look better with hinting, some without, so leave hinting on if (FT_Load_Glyph(fontFile->face, idx, fontFile->engine->aa ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT)) { return gFalse; }#endif if (FT_Render_Glyph(slot, fontFile->engine->aa ? ft_render_mode_normal : ft_render_mode_mono)) { return gFalse; } *x = -slot->bitmap_left; *y = slot->bitmap_top; *w = slot->bitmap.width; *h = slot->bitmap.rows; if (*w > glyphW || *h > glyphH) {#if 1 //~ debug fprintf(stderr, "Weird FreeType glyph size: %d > %d or %d > %d\n", *w, glyphW, *h, glyphH);#endif return NULL; } // store glyph pixmap in cache ret = NULL; for (j = 0; j < cacheAssoc; ++j) { if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) { cacheTags[i+j].mru = 0x8000; cacheTags[i+j].code = c; cacheTags[i+j].x = *x; cacheTags[i+j].y = *y; cacheTags[i+j].w = *w; cacheTags[i+j].h = *h; if (fontFile->engine->aa) { rowSize = *w; } else { rowSize = (*w + 7) >> 3; } ret = cache + (i+j) * glyphSize; for (k = 0, p = ret, q = slot->bitmap.buffer; k < slot->bitmap.rows; ++k, p += rowSize, q += slot->bitmap.pitch) { memcpy(p, q, rowSize); } } else { ++cacheTags[i+j].mru; } } return ret;}GBool FTFont::getCharPath(CharCode c, Unicode u, GfxState *state) { static FT_Outline_Funcs outlineFuncs = { &charPathMoveTo, &charPathLineTo, &charPathConicTo, &charPathCubicTo, 0, 0 }; FT_GlyphSlot slot; FT_UInt idx; FT_Glyph glyph; fontFile->face->size = sizeObj; FT_Set_Transform(fontFile->face, &matrix, NULL); slot = fontFile->face->glyph; idx = getGlyphIndex(c, u);#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) { return gFalse; }#else // FT2's autohinting doesn't always work very well (especially with // font subsets), so turn it off if anti-aliasing is enabled; if // anti-aliasing is disabled, this seems to be a tossup - some fonts // look better with hinting, some without, so leave hinting on if (FT_Load_Glyph(fontFile->face, idx, fontFile->engine->aa ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT)) { return gFalse; }#endif if (FT_Get_Glyph(slot, &glyph)) { return gFalse; } FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline, &outlineFuncs, state); return gTrue;}int FTFont::charPathMoveTo(FT_Vector *pt, void *state) { ((GfxState *)state)->moveTo(pt->x / 64.0, -pt->y / 64.0); return 0;}int FTFont::charPathLineTo(FT_Vector *pt, void *state) { ((GfxState *)state)->lineTo(pt->x / 64.0, -pt->y / 64.0); return 0;}int FTFont::charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state) { double x0, y0, x1, y1, x2, y2, x3, y3, xc, yc; x0 = ((GfxState *)state)->getCurX(); y0 = ((GfxState *)state)->getCurY(); xc = ctrl->x / 64.0; yc = -ctrl->y / 64.0; x3 = pt->x / 64.0; y3 = -pt->y / 64.0; // A second-order Bezier curve is defined by two endpoints, p0 and // p3, and one control point, pc: // // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3 // // A third-order Bezier curve is defined by the same two endpoints, // p0 and p3, and two control points, p1 and p2: // // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3 // // Applying some algebra, we can convert a second-order curve to a // third-order curve: // // p1 = (1/3) * (p0 + 2pc) // p2 = (1/3) * (2pc + p3) x1 = (1.0 / 3.0) * (x0 + 2 * xc); y1 = (1.0 / 3.0) * (y0 + 2 * yc); x2 = (1.0 / 3.0) * (2 * xc + x3); y2 = (1.0 / 3.0) * (2 * yc + y3); ((GfxState *)state)->curveTo(x1, y1, x2, y2, x3, y3); return 0;}int FTFont::charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2, FT_Vector *pt, void *state) { ((GfxState *)state)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0, ctrl2->x / 64.0, -ctrl2->y / 64.0, pt->x / 64.0, -pt->y / 64.0); return 0;}FT_UInt FTFont::getGlyphIndex(CharCode c, Unicode u) { FT_UInt idx; int j; idx = 0; // make gcc happy switch (fontFile->mode) { case ftFontModeUnicode: idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)u); break; case ftFontModeCharCode: idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)c); break; case ftFontModeCharCodeOffset: idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)(c + fontFile->charMapOffset)); break; case ftFontModeCodeMap: if (c <= 0xff) { idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)fontFile->codeMap[c]); } else { idx = 0; } break; case ftFontModeCodeMapDirect: if (c <= 0xff) { idx = (FT_UInt)fontFile->codeMap[c]; } else { idx = 0; } break; case ftFontModeCIDToGIDMap: if (fontFile->cidToGIDLen) { if ((int)c < fontFile->cidToGIDLen) { idx = (FT_UInt)fontFile->cidToGID[c]; } else { idx = (FT_UInt)0; } } else { idx = (FT_UInt)c; } break; case ftFontModeCFFCharset:#if 1 //~ cff cid->gid map {#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0 CFF_Font *cff = (CFF_Font *)((TT_Face)fontFile->face)->extra.data;#else CFF_Font cff = (CFF_Font)((TT_Face)fontFile->face)->extra.data;#endif idx = 0; for (j = 0; j < (int)cff->num_glyphs; ++j) { if (cff->charset.sids[j] == c) { idx = j; break; } } }#endif break; case ftFontModeCID: idx = c; break; } return idx;}#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -