diff options
Diffstat (limited to 'fitz/res_font.c')
-rw-r--r-- | fitz/res_font.c | 179 |
1 files changed, 168 insertions, 11 deletions
diff --git a/fitz/res_font.c b/fitz/res_font.c index 25939d02..a68a1ff1 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -6,6 +6,9 @@ #define MAX_BBOX_TABLE_SIZE 4096 +/* 20 degrees */ +#define SHEAR 0.36397f + static void fz_drop_freetype(fz_context *ctx); static fz_font * @@ -251,7 +254,7 @@ fz_drop_freetype(fz_context *ctx) } fz_font * -fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_glyph_bbox) +fz_new_font_from_file(fz_context *ctx, char *name, char *path, int index, int use_glyph_bbox) { FT_Face face; fz_font *font; @@ -268,7 +271,10 @@ fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_glyph_bbox fz_throw(ctx, "freetype: cannot load font: %s", ft_error_string(fterr)); } - font = fz_new_font(ctx, face->family_name, use_glyph_bbox, face->num_glyphs); + if (!name) + name = face->family_name; + + font = fz_new_font(ctx, name, use_glyph_bbox, face->num_glyphs); font->ft_face = face; font->bbox.x0 = (float) face->bbox.xMin / face->units_per_EM; font->bbox.y0 = (float) face->bbox.yMin / face->units_per_EM; @@ -279,7 +285,7 @@ fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_glyph_bbox } fz_font * -fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index, int use_glyph_bbox) +fz_new_font_from_memory(fz_context *ctx, char *name, unsigned char *data, int len, int index, int use_glyph_bbox) { FT_Face face; fz_font *font; @@ -296,7 +302,10 @@ fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index fz_throw(ctx, "freetype: cannot load font: %s", ft_error_string(fterr)); } - font = fz_new_font(ctx, face->family_name, use_glyph_bbox, face->num_glyphs); + if (!name) + name = face->family_name; + + font = fz_new_font(ctx, name, use_glyph_bbox, face->num_glyphs); font->ft_face = face; font->bbox.x0 = (float) face->bbox.xMin / face->units_per_EM; font->bbox.y0 = (float) face->bbox.yMin / face->units_per_EM; @@ -377,7 +386,7 @@ fz_copy_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap) for (y = 0; y < pixmap->h; y++) { memcpy(pixmap->samples + (unsigned int)(y * pixmap->w), - bitmap->buffer + (unsigned int)((pixmap->h - y - 1) * bitmap->pitch), + bitmap->buffer + (unsigned int)((pixmap->h - y - 1) * bitmap->pitch), pixmap->w); } } @@ -395,10 +404,12 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int a FT_Error fterr; fz_pixmap *result; + float strength = fz_matrix_expansion(trm) * 0.02f; + trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); if (font->ft_italic) - trm = fz_concat(fz_shear(0.3f, 0), trm); + trm = fz_concat(fz_shear(SHEAR, 0), trm); /* Freetype mutilates complex glyphs if they are loaded @@ -471,7 +482,6 @@ retry_unhinted: if (font->ft_bold) { - float strength = fz_matrix_expansion(trm) * 0.04f; FT_Outline_Embolden(&face->glyph->outline, strength * 64); FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); } @@ -507,7 +517,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); if (font->ft_italic) - trm = fz_concat(fz_shear(0.3f, 0), trm); + trm = fz_concat(fz_shear(SHEAR, 0), trm); m.xx = trm.a * 64; /* should be 65536 */ m.yx = trm.b * 64; @@ -611,10 +621,12 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) // TODO: refactor loading into fz_load_ft_glyph // TODO: cache results + float strength = fz_matrix_expansion(trm) * 0.02f; + trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); if (font->ft_italic) - trm = fz_concat(fz_shear(0.3f, 0), trm); + trm = fz_concat(fz_shear(SHEAR, 0), trm); m.xx = trm.a * 64; /* should be 65536 */ m.yx = trm.b * 64; @@ -641,7 +653,6 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) if (font->ft_bold) { - float strength = fz_matrix_expansion(trm) * 0.04f; FT_Outline_Embolden(&face->glyph->outline, strength * 64); FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); } @@ -662,6 +673,136 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) return bounds; } +/* Turn FT_Outline into a fz_path */ + +struct closure { + fz_context *ctx; + fz_path *path; + float x, y; +}; + +static int move_to(const FT_Vector *p, void *cc) +{ + fz_context *ctx = ((struct closure *)cc)->ctx; + fz_path *path = ((struct closure *)cc)->path; + float tx = ((struct closure *)cc)->x; + float ty = ((struct closure *)cc)->y; + fz_moveto(ctx, path, tx + p->x / 64.0f, ty + p->y / 64.0f); + return 0; +} + +static int line_to(const FT_Vector *p, void *cc) +{ + fz_context *ctx = ((struct closure *)cc)->ctx; + fz_path *path = ((struct closure *)cc)->path; + float tx = ((struct closure *)cc)->x; + float ty = ((struct closure *)cc)->y; + fz_lineto(ctx, path, tx + p->x / 64.0f, ty + p->y / 64.0f); + return 0; +} + +static int conic_to(const FT_Vector *c, const FT_Vector *p, void *cc) +{ + fz_context *ctx = ((struct closure *)cc)->ctx; + fz_path *path = ((struct closure *)cc)->path; + float tx = ((struct closure *)cc)->x; + float ty = ((struct closure *)cc)->y; + fz_point s, c1, c2; + float cx = tx + c->x / 64.0f, cy = ty + c->y / 64.0f; + float px = tx + p->x / 64.0f, py = ty + p->y / 64.0f; + s = fz_currentpoint(ctx, path); + c1.x = (s.x + cx * 2) / 3; + c1.y = (s.y + cy * 2) / 3; + c2.x = (px + cx * 2) / 3; + c2.y = (py + cy * 2) / 3; + fz_curveto(ctx, path, c1.x, c1.y, c2.x, c2.y, px, py); + return 0; +} + +static int cubic_to(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p, void *cc) +{ + fz_context *ctx = ((struct closure *)cc)->ctx; + fz_path *path = ((struct closure *)cc)->path; + float tx = ((struct closure *)cc)->x; + float ty = ((struct closure *)cc)->y; + fz_curveto(ctx, path, + tx + c1->x/64.0f, ty + c1->y/64.0f, + tx + c2->x/64.0f, ty + c2->y/64.0f, + tx + p->x/64.0f, ty + p->y/64.0f); + return 0; +} + +static const FT_Outline_Funcs outline_funcs = { + move_to, line_to, conic_to, cubic_to, 0, 0 +}; + +fz_path * +fz_outline_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) +{ + struct closure cc; + FT_Face face = font->ft_face; + FT_Matrix m; + FT_Vector v; + int fterr; + + float strength = fz_matrix_expansion(trm) * 0.02f; + + trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); + + if (font->ft_italic) + trm = fz_concat(fz_shear(SHEAR, 0), trm); + + 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 = 0; + v.y = 0; + + fz_lock(ctx, FZ_LOCK_FREETYPE); + + fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ + if (fterr) + fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); + FT_Set_Transform(face, &m, &v); + + fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + if (fterr) + { + fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); + return NULL; + } + + if (font->ft_bold) + { + FT_Outline_Embolden(&face->glyph->outline, strength * 64); + FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); + } + + fz_try(ctx) + { + cc.ctx = ctx; + cc.path = fz_new_path(ctx); + cc.x = trm.e; + cc.y = trm.f; + fz_moveto(ctx, cc.path, cc.x, cc.y); + FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, &cc); + fz_closepath(ctx, cc.path); + } + fz_catch(ctx) + { + fz_warn(ctx, "freetype cannot decompose outline"); + fz_free(ctx, cc.path); + fz_unlock(ctx, FZ_LOCK_FREETYPE); + return NULL; + } + + fz_unlock(ctx, FZ_LOCK_FREETYPE); + + return cc.path; +} + /* * Type 3 fonts... */ @@ -723,7 +864,7 @@ fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) } fz_pixmap * -fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) +fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model, fz_bbox scissor) { fz_matrix ctm; void *contents; @@ -762,6 +903,8 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co bbox.x1++; bbox.y1++; + bbox = fz_intersect_bbox(bbox, scissor); + glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray, bbox); fz_clear_pixmap(ctx, glyph); @@ -813,6 +956,7 @@ fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gi /* RJW: "cannot draw type3 glyph" */ } +#ifndef NDEBUG void fz_print_font(fz_context *ctx, FILE *out, fz_font *font) { @@ -838,6 +982,7 @@ fz_print_font(fz_context *ctx, FILE *out, fz_font *font) fprintf(out, "}\n"); } +#endif fz_rect fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) @@ -860,6 +1005,18 @@ fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) return fz_transform_rect(trm, font->bbox); } +fz_path * +fz_outline_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm) +{ + if (!font->ft_face) + { + fz_warn(ctx, "cannot convert type3 glyph to path"); + return NULL; + } + + return fz_outline_ft_glyph(ctx, font, gid, ctm); +} + int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid) { if (!font->t3procs || !font->t3flags || gid < 0 || gid >= font->bbox_count) |