summaryrefslogtreecommitdiff
path: root/fitz/dev_draw.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2011-04-05 12:04:13 +0200
committerTor Andersson <tor.andersson@artifex.com>2011-04-05 12:04:13 +0200
commitc61a13b445c2d4d7b6468a0f2fe7ab998e210e90 (patch)
tree358cc5fc883fdf34f8fecad0965d5fc5426e75c3 /fitz/dev_draw.c
parent68f9077504d387a396efd0af6b8ee4147c3451f3 (diff)
downloadmupdf-c61a13b445c2d4d7b6468a0f2fe7ab998e210e90.tar.xz
Makefile tweaks.
Diffstat (limited to 'fitz/dev_draw.c')
-rw-r--r--fitz/dev_draw.c1029
1 files changed, 0 insertions, 1029 deletions
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c
deleted file mode 100644
index 05f96f28..00000000
--- a/fitz/dev_draw.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#include "fitz.h"
-
-#define QUANT(x,a) (((int)((x) * (a))) / (a))
-#define HSUBPIX 5.0
-#define VSUBPIX 5.0
-
-#define STACK_SIZE 96
-
-typedef struct fz_draw_device_s fz_draw_device;
-
-struct fz_draw_device_s
-{
- fz_glyph_cache *cache;
- fz_gel *gel;
- fz_ael *ael;
-
- fz_pixmap *dest;
- fz_bbox scissor;
-
- int top;
- struct {
- fz_bbox scissor;
- fz_pixmap *dest;
- fz_pixmap *mask;
- fz_blendmode blendmode;
- int luminosity;
- float alpha;
- fz_matrix ctm;
- float xstep, ystep;
- fz_rect area;
- } stack[STACK_SIZE];
-};
-
-static void
-fz_draw_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- float expansion = fz_matrix_expansion(ctm);
- float flatness = 0.3f / expansion;
- unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
- fz_bbox bbox;
- int i;
-
- fz_reset_gel(dev->gel, dev->scissor);
- fz_flatten_fill_path(dev->gel, path, ctm, flatness);
- fz_sort_gel(dev->gel);
-
- bbox = fz_bound_gel(dev->gel);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- if (fz_is_empty_rect(bbox))
- return;
-
- fz_convert_color(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
-
- fz_scan_convert(dev->gel, dev->ael, even_odd, bbox, dev->dest, colorbv);
-}
-
-static void
-fz_draw_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- float expansion = fz_matrix_expansion(ctm);
- float flatness = 0.3f / expansion;
- float linewidth = stroke->linewidth;
- unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
- fz_bbox bbox;
- int i;
-
- if (linewidth * expansion < 0.1f)
- linewidth = 1 / expansion;
-
- fz_reset_gel(dev->gel, dev->scissor);
- if (stroke->dash_len > 0)
- fz_flatten_dash_path(dev->gel, path, stroke, ctm, flatness, linewidth);
- else
- fz_flatten_stroke_path(dev->gel, path, stroke, ctm, flatness, linewidth);
- fz_sort_gel(dev->gel);
-
- bbox = fz_bound_gel(dev->gel);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- if (fz_is_empty_rect(bbox))
- return;
-
- fz_convert_color(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
-
- fz_scan_convert(dev->gel, dev->ael, 0, bbox, dev->dest, colorbv);
-}
-
-static void
-fz_draw_clip_path(void *user, fz_path *path, int even_odd, fz_matrix ctm)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- float expansion = fz_matrix_expansion(ctm);
- float flatness = 0.3f / expansion;
- fz_pixmap *mask, *dest;
- fz_bbox bbox;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- fz_reset_gel(dev->gel, dev->scissor);
- fz_flatten_fill_path(dev->gel, path, ctm, flatness);
- fz_sort_gel(dev->gel);
-
- bbox = fz_bound_gel(dev->gel);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- if (fz_is_empty_rect(bbox) || fz_is_rect_gel(dev->gel))
- {
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = NULL;
- dev->stack[dev->top].dest = NULL;
- dev->scissor = bbox;
- dev->top++;
- return;
- }
-
- mask = fz_new_pixmap_with_rect(NULL, bbox);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(mask);
- fz_clear_pixmap(dest);
-
- fz_scan_convert(dev->gel, dev->ael, even_odd, bbox, mask, NULL);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = mask;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
-}
-
-static void
-fz_draw_clip_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- float expansion = fz_matrix_expansion(ctm);
- float flatness = 0.3f / expansion;
- float linewidth = stroke->linewidth;
- fz_pixmap *mask, *dest;
- fz_bbox bbox;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- if (linewidth * expansion < 0.1f)
- linewidth = 1 / expansion;
-
- fz_reset_gel(dev->gel, dev->scissor);
- if (stroke->dash_len > 0)
- fz_flatten_dash_path(dev->gel, path, stroke, ctm, flatness, linewidth);
- else
- fz_flatten_stroke_path(dev->gel, path, stroke, ctm, flatness, linewidth);
- fz_sort_gel(dev->gel);
-
- bbox = fz_bound_gel(dev->gel);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- mask = fz_new_pixmap_with_rect(NULL, bbox);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(mask);
- fz_clear_pixmap(dest);
-
- if (!fz_is_empty_rect(bbox))
- fz_scan_convert(dev->gel, dev->ael, 0, bbox, mask, NULL);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = mask;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
-}
-
-static void
-draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_pixmap *msk,
- int xorig, int yorig, fz_bbox scissor)
-{
- unsigned char *dp, *mp;
- fz_bbox bbox;
- int x, y, w, h;
-
- bbox = fz_bound_pixmap(msk);
- bbox.x0 += xorig;
- bbox.y0 += yorig;
- bbox.x1 += xorig;
- bbox.y1 += yorig;
-
- bbox = fz_intersect_bbox(bbox, scissor); /* scissor < dst */
- x = bbox.x0;
- y = bbox.y0;
- w = bbox.x1 - bbox.x0;
- h = bbox.y1 - bbox.y0;
-
- mp = msk->samples + ((y - msk->y - yorig) * msk->w + (x - msk->x - xorig));
- dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
-
- assert(msk->n == 1);
-
- while (h--)
- {
- if (dst->colorspace)
- fz_paint_span_with_color(dp, mp, dst->n, w, colorbv);
- else
- fz_paint_span(dp, mp, 1, w, 255);
- dp += dst->w * dst->n;
- mp += msk->w;
- }
-}
-
-static void
-fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
- fz_matrix tm, trm;
- fz_pixmap *glyph;
- int i, x, y, gid;
-
- fz_convert_color(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
-
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- gid = text->items[i].gid;
- if (gid < 0)
- continue;
-
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- 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->cache, text->font, gid, trm);
- if (glyph)
- {
- draw_glyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
- fz_drop_pixmap(glyph);
- }
- }
-}
-
-static void
-fz_draw_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
- fz_matrix tm, trm;
- fz_pixmap *glyph;
- int i, x, y, gid;
-
- fz_convert_color(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
-
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- gid = text->items[i].gid;
- if (gid < 0)
- continue;
-
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- 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_stroked_glyph(dev->cache, text->font, gid, trm, ctm, stroke);
- if (glyph)
- {
- draw_glyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
- fz_drop_pixmap(glyph);
- }
- }
-}
-
-static void
-fz_draw_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_bbox bbox;
- fz_pixmap *mask, *dest;
- fz_matrix tm, trm;
- fz_pixmap *glyph;
- int i, x, y, gid;
-
- /* If accumulate == 0 then this text object is guaranteed complete */
- /* If accumulate == 1 then this text object is the first (or only) in a sequence */
- /* If accumulate == 2 then this text object is a continuation */
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- if (accumulate == 0)
- {
- /* make the mask the exact size needed */
- bbox = fz_round_rect(fz_bound_text(text, ctm));
- bbox = fz_intersect_bbox(bbox, dev->scissor);
- }
- else
- {
- /* be conservative about the size of the mask needed */
- bbox = dev->scissor;
- }
-
- if (accumulate == 0 || accumulate == 1)
- {
- mask = fz_new_pixmap_with_rect(NULL, bbox);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(mask);
- fz_clear_pixmap(dest);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = mask;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
- }
- else
- {
- mask = dev->stack[dev->top-1].mask;
- }
-
- if (!fz_is_empty_rect(bbox))
- {
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- gid = text->items[i].gid;
- if (gid < 0)
- continue;
-
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- 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->cache, text->font, gid, trm);
- if (glyph)
- {
- draw_glyph(NULL, mask, glyph, x, y, bbox);
- fz_drop_pixmap(glyph);
- }
- }
- }
-}
-
-static void
-fz_draw_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_bbox bbox;
- fz_pixmap *mask, *dest;
- fz_matrix tm, trm;
- fz_pixmap *glyph;
- int i, x, y, gid;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- /* make the mask the exact size needed */
- bbox = fz_round_rect(fz_bound_text(text, ctm));
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- mask = fz_new_pixmap_with_rect(NULL, bbox);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(mask);
- fz_clear_pixmap(dest);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = mask;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
-
- if (!fz_is_empty_rect(bbox))
- {
- tm = text->trm;
-
- for (i = 0; i < text->len; i++)
- {
- gid = text->items[i].gid;
- if (gid < 0)
- continue;
-
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- 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_stroked_glyph(dev->cache, text->font, gid, trm, ctm, stroke);
- if (glyph)
- {
- draw_glyph(NULL, mask, glyph, x, y, bbox);
- fz_drop_pixmap(glyph);
- }
- }
- }
-}
-
-static void
-fz_draw_ignore_text(void *user, fz_text *text, fz_matrix ctm)
-{
-}
-
-static void
-fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_pixmap *dest = dev->dest;
- fz_rect bounds;
- fz_bbox bbox, scissor;
- float colorfv[FZ_MAX_COLORS];
- unsigned char colorbv[FZ_MAX_COLORS + 1];
-
- bounds = fz_bound_shade(shade, ctm);
- bbox = fz_intersect_bbox(fz_round_rect(bounds), dev->scissor);
- scissor = dev->scissor;
-
- // TODO: proper clip by shade->bbox
-
- if (fz_is_empty_rect(bbox))
- return;
-
- if (!model)
- {
- fz_warn("cannot render shading directly to an alpha mask");
- return;
- }
-
- if (alpha < 1)
- {
- dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox);
- fz_clear_pixmap(dest);
- }
-
- if (shade->use_background)
- {
- unsigned char *s;
- int x, y, n, i;
- fz_convert_color(shade->colorspace, shade->background, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = 255;
-
- n = dest->n;
- for (y = scissor.y0; y < scissor.y1; y++)
- {
- s = dest->samples + ((scissor.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n;
- for (x = scissor.x0; x < scissor.x1; x++)
- {
- for (i = 0; i < n; i++)
- *s++ = colorbv[i];
- }
- }
- }
-
- fz_paint_shade(shade, ctm, dest, bbox);
-
- if (alpha < 1)
- {
- fz_paint_pixmap(dev->dest, dest, alpha * 255);
- fz_drop_pixmap(dest);
- }
-}
-
-static fz_pixmap *
-fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy)
-{
- fz_pixmap *scaled;
-
- if ((ctm->a != 0) && (ctm->b == 0) && (ctm->c == 0) && (ctm->d != 0))
- {
- /* Unrotated or X flip or Yflip or XYflip */
- scaled = fz_scale_pixmap(image, ctm->e, ctm->f, ctm->a, ctm->d);
- if (scaled == NULL)
- return NULL;
- ctm->a = scaled->w;
- ctm->d = scaled->h;
- ctm->e = scaled->x;
- ctm->f = scaled->y;
- return scaled;
- }
- if ((ctm->a == 0) && (ctm->b != 0) && (ctm->c != 0) && (ctm->d == 0))
- {
- /* Other orthogonal flip/rotation cases */
- scaled = fz_scale_pixmap(image, ctm->f, ctm->e, ctm->b, ctm->c);
- if (scaled == NULL)
- return NULL;
- ctm->b = scaled->w;
- ctm->c = scaled->h;
- ctm->f = scaled->x;
- ctm->e = scaled->y;
- return scaled;
- }
- /* Downscale, non rectilinear case */
- if ((dx > 0) && (dy > 0))
- {
- scaled = fz_scale_pixmap(image, 0, 0, (float)dx, (float)dy);
- return scaled;
- }
- return NULL;
-}
-
-static void
-fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_pixmap *converted = NULL;
- fz_pixmap *scaled = NULL;
- int after;
- int dx, dy;
-
- if (!model)
- {
- fz_warn("cannot render image directly to an alpha mask");
- return;
- }
-
- if (image->w == 0 || image->h == 0)
- return;
-
- /* convert images with more components (cmyk->rgb) before scaling */
- /* convert images with fewer components (gray->rgb after scaling */
- /* convert images with expensive colorspace transforms after scaling */
-
- after = 0;
- if (image->colorspace == fz_device_gray)
- after = 1;
-
- if (image->colorspace != model && !after)
- {
- converted = fz_new_pixmap(model, image->x, image->y, image->w, image->h);
- fz_convert_pixmap(image, converted);
- image = converted;
- }
-
- dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
- dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
- if (dx < image->w && dy < image->h)
- {
- scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
- if (scaled == NULL)
- {
- if (dx < 1)
- dx = 1;
- if (dy < 1)
- dy = 1;
- scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy);
- }
- if (scaled != NULL)
- image = scaled;
- }
-
- if (image->colorspace != model && after)
- {
- converted = fz_new_pixmap(model, image->x, image->y, image->w, image->h);
- fz_convert_pixmap(image, converted);
- image = converted;
- }
-
- fz_paint_image(dev->dest, dev->scissor, image, ctm, alpha * 255);
-
- if (scaled)
- fz_drop_pixmap(scaled);
- if (converted)
- fz_drop_pixmap(converted);
-}
-
-static void
-fz_draw_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
- fz_pixmap *scaled = NULL;
- int dx, dy;
- int i;
-
- if (image->w == 0 || image->h == 0)
- return;
-
- dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
- dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
- if (dx < image->w && dy < image->h)
- {
- scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
- if (scaled == NULL)
- {
- if (dx < 1)
- dx = 1;
- if (dy < 1)
- dy = 1;
- scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy);
- }
- if (scaled != NULL)
- image = scaled;
- }
-
- fz_convert_color(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
-
- fz_paint_image_with_color(dev->dest, dev->scissor, image, ctm, colorbv);
-
- if (scaled)
- fz_drop_pixmap(scaled);
-}
-
-static void
-fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_matrix ctm)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_bbox bbox;
- fz_pixmap *mask, *dest;
- fz_pixmap *scaled = NULL;
- int dx, dy;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- if (image->w == 0 || image->h == 0)
- {
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = NULL;
- dev->stack[dev->top].dest = NULL;
- dev->scissor = fz_empty_bbox;
- dev->top++;
- return;
- }
-
- bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect));
- bbox = fz_intersect_bbox(bbox, dev->scissor);
-
- mask = fz_new_pixmap_with_rect(NULL, bbox);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(mask);
- fz_clear_pixmap(dest);
-
- dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
- dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
- if (dx < image->w && dy < image->h)
- {
- scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
- if (scaled == NULL)
- {
- if (dx < 1)
- dx = 1;
- if (dy < 1)
- dy = 1;
- scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy);
- }
- if (scaled != NULL)
- image = scaled;
- }
-
- fz_paint_image(mask, bbox, image, ctm, 255);
-
- if (scaled)
- fz_drop_pixmap(scaled);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = mask;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
-}
-
-static void
-fz_draw_pop_clip(void *user)
-{
- fz_draw_device *dev = user;
- fz_pixmap *mask, *dest;
- if (dev->top > 0)
- {
- dev->top--;
- dev->scissor = dev->stack[dev->top].scissor;
- mask = dev->stack[dev->top].mask;
- dest = dev->stack[dev->top].dest;
- if (mask && dest)
- {
- fz_pixmap *scratch = dev->dest;
- fz_paint_pixmap_with_mask(dest, scratch, mask);
- fz_drop_pixmap(mask);
- fz_drop_pixmap(scratch);
- dev->dest = dest;
- }
- }
-}
-
-static void
-fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *colorfv)
-{
- fz_draw_device *dev = user;
- fz_pixmap *dest;
- fz_bbox bbox;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- bbox = fz_round_rect(rect);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
- dest = fz_new_pixmap_with_rect(fz_device_gray, bbox);
-
- if (luminosity)
- {
- float bc;
- if (!colorspace)
- colorspace = fz_device_gray;
- fz_convert_color(colorspace, colorfv, fz_device_gray, &bc);
- fz_clear_pixmap_with_color(dest, bc * 255);
- }
- else
- fz_clear_pixmap(dest);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].dest = dev->dest;
- dev->stack[dev->top].luminosity = luminosity;
- dev->top++;
-
- dev->scissor = bbox;
- dev->dest = dest;
-}
-
-static void
-fz_draw_end_mask(void *user)
-{
- fz_draw_device *dev = user;
- fz_pixmap *mask = dev->dest;
- fz_pixmap *temp, *dest;
- fz_bbox bbox;
- int luminosity;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- if (dev->top > 0)
- {
- /* pop soft mask buffer */
- dev->top--;
- luminosity = dev->stack[dev->top].luminosity;
- dev->scissor = dev->stack[dev->top].scissor;
- dev->dest = dev->stack[dev->top].dest;
-
- /* convert to alpha mask */
- temp = fz_alpha_from_gray(mask, luminosity);
- fz_drop_pixmap(mask);
-
- /* create new dest scratch buffer */
- bbox = fz_bound_pixmap(temp);
- dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox);
- fz_clear_pixmap(dest);
-
- /* push soft mask as clip mask */
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].mask = temp;
- dev->stack[dev->top].dest = dev->dest;
- dev->scissor = bbox;
- dev->dest = dest;
- dev->top++;
- }
-}
-
-static void
-fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, fz_blendmode blendmode, float alpha)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_bbox bbox;
- fz_pixmap *dest;
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- bbox = fz_round_rect(rect);
- bbox = fz_intersect_bbox(bbox, dev->scissor);
- dest = fz_new_pixmap_with_rect(model, bbox);
-
- fz_clear_pixmap(dest);
-
- dev->stack[dev->top].alpha = alpha;
- dev->stack[dev->top].blendmode = blendmode;
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].dest = dev->dest;
- dev->top++;
-
- dev->scissor = bbox;
- dev->dest = dest;
-}
-
-static void
-fz_draw_end_group(void *user)
-{
- fz_draw_device *dev = user;
- fz_pixmap *group = dev->dest;
- fz_blendmode blendmode;
- float alpha;
-
- if (dev->top > 0)
- {
- dev->top--;
- alpha = dev->stack[dev->top].alpha;
- blendmode = dev->stack[dev->top].blendmode;
- dev->dest = dev->stack[dev->top].dest;
- dev->scissor = dev->stack[dev->top].scissor;
-
- if (blendmode == FZ_BLEND_NORMAL)
- fz_paint_pixmap(dev->dest, group, alpha * 255);
- else
- fz_blend_pixmap(dev->dest, group, alpha * 255, blendmode);
-
- fz_drop_pixmap(group);
- }
-}
-
-static void
-fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
-{
- fz_draw_device *dev = user;
- fz_colorspace *model = dev->dest->colorspace;
- fz_pixmap *dest;
- fz_bbox bbox;
-
- /* area, view, xstep, ystep are in pattern space */
- /* ctm maps from pattern space to device space */
-
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
-
- bbox = fz_round_rect(fz_transform_rect(ctm, view));
- dest = fz_new_pixmap_with_rect(model, bbox);
- fz_clear_pixmap(dest);
-
- dev->stack[dev->top].scissor = dev->scissor;
- dev->stack[dev->top].dest = dev->dest;
- dev->stack[dev->top].xstep = xstep;
- dev->stack[dev->top].ystep = ystep;
- dev->stack[dev->top].area = area;
- dev->stack[dev->top].ctm = ctm;
- dev->top++;
-
- dev->scissor = bbox;
- dev->dest = dest;
-}
-
-static void
-fz_draw_end_tile(void *user)
-{
- fz_draw_device *dev = user;
- fz_pixmap *tile = dev->dest;
- float xstep, ystep;
- fz_matrix ctm, ttm;
- fz_rect area;
- int x0, y0, x1, y1, x, y;
-
- if (dev->top > 0)
- {
- dev->top--;
- xstep = dev->stack[dev->top].xstep;
- ystep = dev->stack[dev->top].ystep;
- area = dev->stack[dev->top].area;
- ctm = dev->stack[dev->top].ctm;
- dev->scissor = dev->stack[dev->top].scissor;
- dev->dest = dev->stack[dev->top].dest;
-
- x0 = floorf(area.x0 / xstep);
- y0 = floorf(area.y0 / ystep);
- x1 = ceilf(area.x1 / xstep);
- y1 = ceilf(area.y1 / ystep);
-
- ctm.e = tile->x;
- ctm.f = tile->y;
-
- for (y = y0; y < y1; y++)
- {
- for (x = x0; x < x1; x++)
- {
- ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm);
- tile->x = ttm.e;
- tile->y = ttm.f;
- fz_paint_pixmap_with_rect(dev->dest, tile, 255, dev->scissor);
- }
- }
-
- fz_drop_pixmap(tile);
- }
-}
-
-static void
-fz_draw_free_user(void *user)
-{
- fz_draw_device *dev = user;
- /* TODO: pop and free the stacks */
- fz_free_gel(dev->gel);
- fz_free_ael(dev->ael);
- fz_free(dev);
-}
-
-fz_device *
-fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest)
-{
- fz_device *dev;
- fz_draw_device *ddev = fz_malloc(sizeof(fz_draw_device));
- ddev->cache = cache;
- ddev->gel = fz_new_gel();
- ddev->ael = fz_new_ael();
- ddev->dest = dest;
- ddev->top = 0;
-
- ddev->scissor.x0 = dest->x;
- ddev->scissor.y0 = dest->y;
- ddev->scissor.x1 = dest->x + dest->w;
- ddev->scissor.y1 = dest->y + dest->h;
-
- dev = fz_new_device(ddev);
- dev->free_user = fz_draw_free_user;
-
- dev->fill_path = fz_draw_fill_path;
- dev->stroke_path = fz_draw_stroke_path;
- dev->clip_path = fz_draw_clip_path;
- dev->clip_stroke_path = fz_draw_clip_stroke_path;
-
- dev->fill_text = fz_draw_fill_text;
- dev->stroke_text = fz_draw_stroke_text;
- dev->clip_text = fz_draw_clip_text;
- dev->clip_stroke_text = fz_draw_clip_stroke_text;
- dev->ignore_text = fz_draw_ignore_text;
-
- dev->fill_image_mask = fz_draw_fill_image_mask;
- dev->clip_image_mask = fz_draw_clip_image_mask;
- dev->fill_image = fz_draw_fill_image;
- dev->fill_shade = fz_draw_fill_shade;
-
- dev->pop_clip = fz_draw_pop_clip;
-
- dev->begin_mask = fz_draw_begin_mask;
- dev->end_mask = fz_draw_end_mask;
- dev->begin_group = fz_draw_begin_group;
- dev->end_group = fz_draw_end_group;
-
- dev->begin_tile = fz_draw_begin_tile;
- dev->end_tile = fz_draw_end_tile;
-
- return dev;
-}