static fz_error * ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) { pdf_font *font = (pdf_font*)fzfont; FT_Face face = font->ftface; FT_Matrix m; FT_Vector v; FT_Error fterr; float scale; int gid; int x, y; int hint = font->hint; gid = ftcidtogid(font, cid); if (font->substitute && fzfont->wmode == 0) { fz_hmtx subw; int realw; FT_Set_Char_Size(face, 1000, 1000, 72, 72); fterr = FT_Load_Glyph(font->ftface, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (fterr) return fz_throw("freetype failed to load glyph: %s", ft_errstr(fterr)); realw = ((FT_Face)font->ftface)->glyph->advance.x; subw = fz_gethmtx(fzfont, cid); if (realw) scale = (float) subw.w / realw; else scale = 1.0; trm = fz_concat(fz_scale(scale, 1.0), trm); } glyph->w = 0; glyph->h = 0; glyph->x = 0; glyph->y = 0; glyph->samples = nil; /* freetype mutilates complex glyphs if they are loaded * with FT_Set_Char_Size 1.0. it rounds the coordinates * before applying transformation. to get more precision in * freetype, we shift part of the scale in the matrix * into FT_Set_Char_Size instead */ #ifdef HINT hint = 1; #endif if (hint) { scale = fz_matrixexpansion(trm); m.xx = trm.a * 65536 / scale; m.yx = trm.b * 65536 / scale; m.xy = trm.c * 65536 / scale; m.yy = trm.d * 65536 / scale; v.x = 0; v.y = 0; FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72); FT_Set_Transform(face, &m, &v); fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); if (fterr) fz_warn("freetype load glyph: %s", ft_errstr(fterr)); } else { m.xx = trm.a * 64; /* should be 65536 */ m.yx = trm.b * 64; m.xy = trm.c * 64; m.yy = trm.d * 64; v.x = trm.e * 64; v.y = trm.f * 64; FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ FT_Set_Transform(face, &m, &v); fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if (fterr) fz_warn("freetype load glyph: %s", ft_errstr(fterr)); } fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal); if (fterr) fz_warn("freetype render glyph: %s", ft_errstr(fterr)); glyph->w = face->glyph->bitmap.width; glyph->h = face->glyph->bitmap.rows; glyph->x = face->glyph->bitmap_left; glyph->y = face->glyph->bitmap_top - glyph->h; glyph->samples = face->glyph->bitmap.buffer; for (y = 0; y < glyph->h / 2; y++) { for (x = 0; x < glyph->w; x++) { unsigned char a = glyph->samples[y * glyph->w + x ]; unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x]; glyph->samples[y * glyph->w + x ] = b; glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a; } } return fz_okay; }
fz_error fz_renderftglyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm) { FT_Face face = font->ftface; FT_Matrix m; FT_Vector v; FT_Error fterr; int x, y; #if 0 /* We lost this feature in refactoring. * We can't access pdf_fontdesc metrics from fz_font. * The pdf_fontdesc metrics are character based (cid), * where the glyph being rendered is given by glyph (gid). */ if (font->ftsubstitute && font->wmode == 0) { fz_hmtx subw; int realw; float scale; fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) return fz_warn("freetype setting character size: %s", ft_errorstring(fterr)); fterr = FT_Load_Glyph(font->ftface, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (fterr) return fz_throw("freetype failed to load glyph: %s", ft_errorstring(fterr)); realw = ((FT_Face)font->ftface)->glyph->advance.x; subw = fz_gethmtx(font, cid); // <-- this is the offender if (realw) scale = (float) subw.w / realw; else scale = 1.0; trm = fz_concat(fz_scale(scale, 1.0), trm); } #endif glyph->w = 0; glyph->h = 0; glyph->x = 0; glyph->y = 0; glyph->samples = nil; /* freetype mutilates complex glyphs if they are loaded * with FT_Set_Char_Size 1.0. it rounds the coordinates * before applying transformation. to get more precision in * freetype, we shift part of the scale in the matrix * into FT_Set_Char_Size instead */ m.xx = trm.a * 64; /* should be 65536 */ m.yx = trm.b * 64; m.xy = trm.c * 64; m.yy = trm.d * 64; v.x = trm.e * 64; v.y = trm.f * 64; fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) fz_warn("freetype setting character size: %s", ft_errorstring(fterr)); FT_Set_Transform(face, &m, &v); if (font->fthint) { /* Enable hinting, but keep the huge char size so that * it is hinted for a character. This will in effect nullify * the effect of grid fitting. This form of hinting should * only be used for DynaLab and similar tricky TrueType fonts, * so that we get the correct outline shape. */ #ifdef USE_HINTING /* If you really want grid fitting, enable this code. */ float scale = fz_matrixexpansion(trm); m.xx = trm.a * 65536 / scale; m.xy = trm.b * 65536 / scale; m.yx = trm.c * 65536 / scale; m.yy = trm.d * 65536 / scale; v.x = 0; v.y = 0; fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72); if (fterr) fz_warn("freetype setting character size: %s", ft_errorstring(fterr)); FT_Set_Transform(face, &m, &v); #endif fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); if (fterr) fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr)); } else { fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if (fterr) fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr)); } fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal); if (fterr) fz_warn("freetype render glyph (gid %d): %s", gid, ft_errorstring(fterr)); glyph->w = face->glyph->bitmap.width; glyph->h = face->glyph->bitmap.rows; glyph->x = face->glyph->bitmap_left; glyph->y = face->glyph->bitmap_top - glyph->h; glyph->samples = face->glyph->bitmap.buffer; for (y = 0; y < glyph->h / 2; y++) { for (x = 0; x < glyph->w; x++) { unsigned char a = glyph->samples[y * glyph->w + x ]; unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x]; glyph->samples[y * glyph->w + x ] = b; glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a; } } return fz_okay; }
fz_error * showglyph(pdf_csi *csi, int cid) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font *font = gstate->font; fz_error *error; fz_matrix tsm, trm; float w0, w1, tx, ty; fz_hmtx h; fz_vmtx v; tsm.a = gstate->size * gstate->scale; tsm.b = 0; tsm.c = 0; tsm.d = gstate->size; tsm.e = 0; tsm.f = gstate->rise; if (font->super.wmode == 1) { v = fz_getvmtx((fz_font*)font, cid); tsm.e -= v.x * gstate->size / 1000.0; tsm.f -= v.y * gstate->size / 1000.0; } trm = fz_concat(tsm, csi->tm); /* flush buffered text if face or matrix or rendermode has changed */ if (!csi->text || ((fz_font*)font) != csi->text->font || fabs(trm.a - csi->text->trm.a) > FLT_EPSILON || fabs(trm.b - csi->text->trm.b) > FLT_EPSILON || fabs(trm.c - csi->text->trm.c) > FLT_EPSILON || fabs(trm.d - csi->text->trm.d) > FLT_EPSILON || gstate->render != csi->textmode) { error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (face/matrix change)"); error = fz_newtextnode(&csi->text, (fz_font*)font); if (error) return fz_rethrow(error, "cannot create text node"); csi->text->trm = trm; csi->text->trm.e = 0; csi->text->trm.f = 0; csi->textmode = gstate->render; } /* add glyph to textobject */ error = fz_addtext(csi->text, cid, trm.e, trm.f); if (error) return fz_rethrow(error, "cannot add glyph to text node"); if (font->super.wmode == 0) { h = fz_gethmtx((fz_font*)font, cid); w0 = h.w / 1000.0; tx = (w0 * gstate->size + gstate->charspace) * gstate->scale; csi->tm = fz_concat(fz_translate(tx, 0), csi->tm); } else { w1 = v.w / 1000.0; ty = w1 * gstate->size + gstate->charspace; csi->tm = fz_concat(fz_translate(0, ty), csi->tm); } return fz_okay; }