diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2012-07-17 18:05:05 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2012-07-17 18:05:05 +0200 |
commit | 4091b7a357728aed033216baafed540b795bcf9e (patch) | |
tree | ad0cd73cc428bc8922d1eaa94663479c04192edb /draw | |
parent | 2b857ab9878d5ca8acd862ae58dafa8d269bc502 (diff) | |
download | mupdf-4091b7a357728aed033216baafed540b795bcf9e.tar.xz |
Handle glyphs that are too large to render as pixmaps.
Diffstat (limited to 'draw')
-rw-r--r-- | draw/draw_device.c | 36 | ||||
-rw-r--r-- | draw/draw_glyph.c | 44 |
2 files changed, 58 insertions, 22 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c index 6f74eabf..2eaf1d49 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -463,11 +463,12 @@ fz_draw_fill_text(fz_device *devp, fz_text *text, fz_matrix ctm, unsigned char colorbv[FZ_MAX_COLORS + 1]; unsigned char shapebv; float colorfv[FZ_MAX_COLORS]; - fz_matrix tm, trm; + fz_matrix tm, trm, trunc_trm; fz_pixmap *glyph; int i, x, y, gid; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; + fz_bbox scissor = state->scissor; if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(dev); @@ -491,10 +492,15 @@ fz_draw_fill_text(fz_device *devp, fz_text *text, fz_matrix ctm, trm = fz_concat(tm, ctm); x = floorf(trm.e); y = floorf(trm.f); - trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); - trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_glyph(dev->ctx, text->font, gid, trm, model); + trunc_trm = trm; + trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); + trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); + + scissor.x0 -= x; scissor.x1 -= x; + scissor.y0 -= y; scissor.y1 -= y; + + glyph = fz_render_glyph(dev->ctx, text->font, gid, trunc_trm, model, scissor); if (glyph) { if (glyph->n == 1) @@ -510,6 +516,20 @@ fz_draw_fill_text(fz_device *devp, fz_text *text, fz_matrix ctm, } fz_drop_pixmap(dev->ctx, glyph); } + else + { + fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm); + if (path) + { + fz_draw_fill_path(devp, path, 0, fz_identity, colorspace, color, alpha); + fz_free_path(dev->ctx, path); + } + + else + { + fz_warn(dev->ctx, "cannot render glyph"); + } + } } if (state->blendmode & FZ_BLEND_KNOCKOUT) @@ -553,7 +573,9 @@ fz_draw_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke, fz_ trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trm, ctm, stroke); + // TODO: dash state + + glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trm, ctm, stroke, state->scissor); if (glyph) { draw_glyph(colorbv, state->dest, glyph, x, y, state->scissor); @@ -645,7 +667,7 @@ fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_glyph(dev->ctx, text->font, gid, trm, model); + glyph = fz_render_glyph(dev->ctx, text->font, gid, trm, model, bbox); if (glyph) { draw_glyph(NULL, mask, glyph, x, y, bbox); @@ -712,7 +734,7 @@ fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trm, ctm, stroke); + glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trm, ctm, stroke, bbox); if (glyph) { draw_glyph(NULL, mask, glyph, x, y, bbox); diff --git a/draw/draw_glyph.c b/draw/draw_glyph.c index cef9d7fa..e7e7f03a 100644 --- a/draw/draw_glyph.c +++ b/draw/draw_glyph.c @@ -1,6 +1,5 @@ #include "fitz-internal.h" -#define MAX_FONT_SIZE 1000 #define MAX_GLYPH_SIZE 256 #define MAX_CACHE_SIZE (1024*1024) @@ -96,29 +95,44 @@ fz_keep_glyph_cache(fz_context *ctx) } fz_pixmap * -fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke) +fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke, fz_bbox scissor) { if (font->ft_face) return fz_render_ft_stroked_glyph(ctx, font, gid, trm, ctm, stroke); - return fz_render_glyph(ctx, font, gid, trm, NULL); + return fz_render_glyph(ctx, font, gid, trm, NULL, scissor); } +/* + Render a glyph and return a bitmap. + If the glyph is too large to fit the cache we have two choices: + 1) Return NULL so the caller can draw the glyph using an outline. + Only supported for freetype fonts. + 2) Render a clipped glyph by using the scissor rectangle. + Only supported for type 3 fonts. + This must not be inserted into the cache. + */ fz_pixmap * -fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model) +fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model, fz_bbox scissor) { fz_glyph_cache *cache; fz_glyph_key key; fz_pixmap *val; float size = fz_matrix_expansion(ctm); + int do_cache; - cache = ctx->glyph_cache; - - if (size > MAX_FONT_SIZE) + if (size <= MAX_GLYPH_SIZE) { - /* TODO: this case should be handled by rendering glyph as a path fill */ - fz_warn(ctx, "font size too large (%g), not rendering glyph", size); - return NULL; + scissor = fz_infinite_bbox; + do_cache = 1; } + else + { + if (font->ft_face) + return NULL; + do_cache = 0; + } + + cache = ctx->glyph_cache; memset(&key, 0, sizeof key); key.font = font; @@ -131,6 +145,9 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color key.f = (ctm.f - floorf(ctm.f)) * 256; key.aa = fz_aa_level(ctx); + ctm.e = floorf(ctm.e) + key.e / 256.0f; + ctm.f = floorf(ctm.f) + key.f / 256.0f; + fz_lock(ctx, FZ_LOCK_GLYPHCACHE); val = fz_hash_find(ctx, cache->hash, &key); if (val) @@ -140,9 +157,6 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color return val; } - ctm.e = floorf(ctm.e) + key.e / 256.0f; - ctm.f = floorf(ctm.f) + key.f / 256.0f; - fz_try(ctx) { if (font->ft_face) @@ -161,7 +175,7 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color * abandon ours, and use the one there already. */ fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); - val = fz_render_t3_glyph(ctx, font, gid, ctm, model); + val = fz_render_t3_glyph(ctx, font, gid, ctm, model, scissor); fz_lock(ctx, FZ_LOCK_GLYPHCACHE); } else @@ -176,7 +190,7 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color fz_rethrow(ctx); } - if (val) + if (val && do_cache) { if (val->w < MAX_GLYPH_SIZE && val->h < MAX_GLYPH_SIZE) { |