Skip to content

Commit

Permalink
Transfer function support.
Browse files Browse the repository at this point in the history
Just for SMask transfer functions for now.
  • Loading branch information
robinwatts committed Jan 16, 2024
1 parent e05c18f commit c7581a1
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 44 deletions.
3 changes: 2 additions & 1 deletion include/mupdf/fitz/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ struct fz_device
void (*pop_clip)(fz_context *, fz_device *);

void (*begin_mask)(fz_context *, fz_device *, fz_rect area, int luminosity, fz_colorspace *, const float *bc, fz_color_params );
void (*end_mask)(fz_context *, fz_device *);
void (*end_mask)(fz_context *, fz_device *, fz_function *fn);
void (*begin_group)(fz_context *, fz_device *, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha);
void (*end_group)(fz_context *, fz_device *);

Expand Down Expand Up @@ -361,6 +361,7 @@ void fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_mat
void fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor);
void fz_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, const float *bc, fz_color_params color_params);
void fz_end_mask(fz_context *ctx, fz_device *dev);
void fz_end_mask_tr(fz_context *ctx, fz_device *dev, fz_function *fn);
void fz_begin_group(fz_context *ctx, fz_device *dev, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha);
void fz_end_group(fz_context *ctx, fz_device *dev);
void fz_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm);
Expand Down
2 changes: 1 addition & 1 deletion include/mupdf/pdf/interpret.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct pdf_processor
void (*op_gs_BM)(fz_context *ctx, pdf_processor *proc, const char *blendmode);
void (*op_gs_ca)(fz_context *ctx, pdf_processor *proc, float alpha);
void (*op_gs_CA)(fz_context *ctx, pdf_processor *proc, float alpha);
void (*op_gs_SMask)(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity);
void (*op_gs_SMask)(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity, pdf_obj *tr);
void (*op_gs_end)(fz_context *ctx, pdf_processor *proc);

/* special graphics state */
Expand Down
2 changes: 1 addition & 1 deletion source/fitz/bbox-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ fz_bbox_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity
}

static void
fz_bbox_end_mask(fz_context *ctx, fz_device *dev)
fz_bbox_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
fz_bbox_device *bdev = (fz_bbox_device*)dev;
assert(bdev->ignore > 0);
Expand Down
10 changes: 8 additions & 2 deletions source/fitz/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,14 @@ fz_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity, fz_
}

void
fz_end_mask(fz_context *ctx, fz_device *dev)
fz_end_mask_tr(fz_context *ctx, fz_device *dev, fz_function *fn)
{
pop_push_clip_stack(ctx, dev, fz_device_container_stack_is_mask, fz_device_container_stack_is_clip);

if (dev->end_mask)
{
fz_try(ctx)
dev->end_mask(ctx, dev);
dev->end_mask(ctx, dev, fn);
fz_catch(ctx)
{
fz_disable_device(ctx, dev);
Expand All @@ -432,6 +432,12 @@ fz_end_mask(fz_context *ctx, fz_device *dev)
}
}

void
fz_end_mask(fz_context *ctx, fz_device *dev)
{
fz_end_mask_tr(ctx, dev, NULL);
}

void
fz_begin_group(fz_context *ctx, fz_device *dev, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
{
Expand Down
31 changes: 30 additions & 1 deletion source/fitz/draw-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -2275,7 +2275,31 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, fz_rect area, int luminosit
}

static void
fz_draw_end_mask(fz_context *ctx, fz_device *devp)
apply_transform_function_to_pixmap(fz_context *ctx, fz_pixmap *pix, fz_function *tr)
{
int w, h;
ptrdiff_t stride;
uint8_t *s;

assert(pix && pix->n == 1);

s = pix->samples;
stride = pix->stride - pix->w;
for (h = pix->h; h > 0; h--)
{
for (w = pix->w; w > 0; w--)
{
float f = *s / 255.0f;
float d;
fz_eval_function(ctx, tr, &f, 1, &d, 1);
*s++ = (uint8_t)fz_clampi(d*255.0f, 0, 255);
}
s += stride;
}
}

static void
fz_draw_end_mask(fz_context *ctx, fz_device *devp, fz_function *tr)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_pixmap *temp, *dest;
Expand Down Expand Up @@ -2315,6 +2339,11 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
fz_dump_blend(ctx, "-> Clip ", temp);
printf("\n");
#endif
if (tr)
{
/* Apply transfer function to state[1].mask */
apply_transform_function_to_pixmap(ctx, state[1].mask, tr);
}

/* create new dest scratch buffer */
bbox = fz_pixmap_bbox(ctx, temp);
Expand Down
46 changes: 30 additions & 16 deletions source/fitz/list-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ cmd_needs_alignment(fz_display_command cmd)
cmd == FZ_CMD_FILL_IMAGE ||
cmd == FZ_CMD_FILL_IMAGE_MASK ||
cmd == FZ_CMD_CLIP_IMAGE_MASK ||
cmd == FZ_CMD_END_MASK ||
cmd == FZ_CMD_DEFAULT_COLORSPACES);
}

Expand Down Expand Up @@ -1153,22 +1154,30 @@ fz_list_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity
}

static void
fz_list_end_mask(fz_context *ctx, fz_device *dev)
fz_list_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
fz_append_display_node(
ctx,
dev,
FZ_CMD_END_MASK,
0, /* flags */
NULL, /* rect */
NULL, /* path */
NULL, /* color */
NULL, /* colorspace */
NULL, /* alpha */
NULL, /* ctm */
NULL, /* stroke */
NULL, /* private_data */
0); /* private_data_len */
fz_function *tr2 = fz_keep_function(ctx, tr);

fz_try(ctx)
fz_append_display_node(
ctx,
dev,
FZ_CMD_END_MASK,
0, /* flags */
NULL, /* rect */
NULL, /* path */
NULL, /* color */
NULL, /* colorspace */
NULL, /* alpha */
NULL, /* ctm */
NULL, /* stroke */
&tr2, /* private_data */
sizeof(tr2)); /* private_data_len */
fz_catch(ctx)
{
fz_drop_function(ctx, tr);
fz_rethrow(ctx);
}
}

static void
Expand Down Expand Up @@ -1636,6 +1645,10 @@ fz_drop_display_list_imp(fz_context *ctx, fz_storable *list_)
align_node_for_pointer(&node);
fz_drop_image(ctx, *(fz_image **)node);
break;
case FZ_CMD_END_MASK:
align_node_for_pointer(&node);
fz_drop_function(ctx, *(fz_function **)node);
break;
case FZ_CMD_DEFAULT_COLORSPACES:
align_node_for_pointer(&node);
fz_drop_default_colorspaces(ctx, *(fz_default_colorspaces **)node);
Expand Down Expand Up @@ -2001,7 +2014,8 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, fz_m
fz_begin_mask(ctx, dev, trans_rect, n.flags & 1, colorspace, color, color_params);
break;
case FZ_CMD_END_MASK:
fz_end_mask(ctx, dev);
align_node_for_pointer(&node);
fz_end_mask_tr(ctx, dev, *(fz_function **)node);
break;
case FZ_CMD_BEGIN_GROUP:
fz_begin_group(ctx, dev, trans_rect, colorspace, (n.flags & ISOLATED) != 0, (n.flags & KNOCKOUT) != 0, (n.flags>>2), alpha);
Expand Down
10 changes: 5 additions & 5 deletions source/fitz/ocr-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ fz_ocr_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity,
}

static void
fz_ocr_end_mask(fz_context *ctx, fz_device *dev)
fz_ocr_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
fz_ocr_device *ocr = (fz_ocr_device *)dev;

fz_end_mask(ctx, ocr->list_dev);
fz_end_mask(ctx, ocr->draw_dev);
fz_end_mask_tr(ctx, ocr->list_dev, tr);
fz_end_mask_tr(ctx, ocr->draw_dev, tr);
}

static void
Expand Down Expand Up @@ -852,11 +852,11 @@ rewrite_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity
}

static void
rewrite_end_mask(fz_context *ctx, fz_device *dev)
rewrite_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
fz_rewrite_device *rewrite = (fz_rewrite_device *)dev;

fz_end_mask(ctx, rewrite->target);
fz_end_mask_tr(ctx, rewrite->target, tr);
}

static void
Expand Down
5 changes: 4 additions & 1 deletion source/fitz/svg-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ svg_dev_begin_mask(fz_context *ctx, fz_device *dev, fz_rect bbox, int luminosity
}

static void
svg_dev_end_mask(fz_context *ctx, fz_device *dev)
svg_dev_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
svg_device *sdev = (svg_device*)dev;
fz_buffer *out = sdev->out;
Expand All @@ -1096,6 +1096,9 @@ svg_dev_end_mask(fz_context *ctx, fz_device *dev)
if (dev->container_len > 0)
mask = dev->container[dev->container_len-1].user;

if (tr)
fz_warn(ctx, "Ignoring Transfer Function");

fz_append_printf(ctx, out, "\"/>\n</mask>\n");
out = end_def(ctx, sdev, 0);
fz_append_printf(ctx, out, "<g mask=\"url(#mask_%d)\">\n", mask);
Expand Down
4 changes: 2 additions & 2 deletions source/fitz/test-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,12 @@ fz_test_begin_mask(fz_context *ctx, fz_device *dev_, fz_rect rect, int luminosit
}

static void
fz_test_end_mask(fz_context *ctx, fz_device *dev_)
fz_test_end_mask(fz_context *ctx, fz_device *dev_, fz_function *tr)
{
fz_test_device *dev = (fz_test_device*)dev_;

if (dev->passthrough)
fz_end_mask(ctx, dev->passthrough);
fz_end_mask_tr(ctx, dev->passthrough, tr);
}

static void
Expand Down
4 changes: 2 additions & 2 deletions source/fitz/trace-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,13 +488,13 @@ fz_trace_begin_mask(fz_context *ctx, fz_device *dev_, fz_rect bbox, int luminosi
}

static void
fz_trace_end_mask(fz_context *ctx, fz_device *dev_)
fz_trace_end_mask(fz_context *ctx, fz_device *dev_, fz_function *tr)
{
fz_trace_device *dev = (fz_trace_device*)dev_;
fz_output *out = dev->out;
dev->depth--;
fz_trace_indent(ctx, out, dev->depth);
fz_write_printf(ctx, out, "</clip_mask>\n");
fz_write_printf(ctx, out, "</clip_mask%s>\n", tr ? " (with TR)" : "");
dev->depth++;
}

Expand Down
5 changes: 4 additions & 1 deletion source/pdf/pdf-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1069,13 +1069,16 @@ pdf_dev_begin_mask(fz_context *ctx, fz_device *dev, fz_rect bbox, int luminosity
}

static void
pdf_dev_end_mask(fz_context *ctx, fz_device *dev)
pdf_dev_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
{
pdf_device *pdev = (pdf_device*)dev;
pdf_document *doc = pdev->doc;
gstate *gs = CURRENT_GSTATE(pdev);
pdf_obj *form_ref = (pdf_obj *)gs->on_pop_arg;

if (tr)
fz_warn(ctx, "Ignoring Transfer function");

/* Here we do part of the pop, but not all of it. */
pdf_dev_end_text(ctx, pdev);
fz_append_string(ctx, gs->buf, "Q\n");
Expand Down
8 changes: 4 additions & 4 deletions source/pdf/pdf-interpret.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,14 @@ pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_ob
luminosity = 0;

tr = pdf_dict_get(ctx, obj, PDF_NAME(TR));
if (tr && !pdf_name_eq(ctx, tr, PDF_NAME(Identity)))
fz_warn(ctx, "ignoring transfer function");
if (tr && pdf_name_eq(ctx, tr, PDF_NAME(Identity)))
tr = NULL;

proc->op_gs_SMask(ctx, proc, xobj, softmask_bc, luminosity);
proc->op_gs_SMask(ctx, proc, xobj, softmask_bc, luminosity, tr);
}
else if (pdf_is_name(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME(None)))
{
proc->op_gs_SMask(ctx, proc, NULL, NULL, 0);
proc->op_gs_SMask(ctx, proc, NULL, NULL, 0, NULL);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions source/pdf/pdf-op-color.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,12 +584,12 @@ pdf_color_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha)
}

static void
pdf_color_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity)
pdf_color_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity, pdf_obj *tr)
{
pdf_color_processor *p = (pdf_color_processor*)proc;

if (p->chain->op_gs_SMask)
p->chain->op_gs_SMask(ctx, p->chain, smask, bc, luminosity);
p->chain->op_gs_SMask(ctx, p->chain, smask, bc, luminosity, tr);
}

static void
Expand Down
4 changes: 2 additions & 2 deletions source/pdf/pdf-op-filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,15 +1186,15 @@ pdf_filter_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha)
}

static void
pdf_filter_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity)
pdf_filter_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, float *bc, int luminosity, pdf_obj *tr)
{
pdf_sanitize_processor *p = (pdf_sanitize_processor*)proc;

if (p->gstate->empty_clip_region)
return;

if (p->chain->op_gs_SMask)
p->chain->op_gs_SMask(ctx, p->chain, smask, bc, luminosity);
p->chain->op_gs_SMask(ctx, p->chain, smask, bc, luminosity, tr);
}

static void
Expand Down
Loading

0 comments on commit c7581a1

Please sign in to comment.