summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2012-07-17 18:05:05 +0200
committerTor Andersson <tor.andersson@artifex.com>2012-07-17 18:05:05 +0200
commit4091b7a357728aed033216baafed540b795bcf9e (patch)
treead0cd73cc428bc8922d1eaa94663479c04192edb /draw
parent2b857ab9878d5ca8acd862ae58dafa8d269bc502 (diff)
downloadmupdf-4091b7a357728aed033216baafed540b795bcf9e.tar.xz
Handle glyphs that are too large to render as pixmaps.
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_device.c36
-rw-r--r--draw/draw_glyph.c44
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)
{