summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/pixmap.h4
-rw-r--r--include/mupdf/fitz/separation.h14
-rw-r--r--resources/pdf/names.txt1
-rw-r--r--source/fitz/draw-device.c36
-rw-r--r--source/fitz/output-psd.c19
-rw-r--r--source/fitz/separation.c110
-rw-r--r--source/gprf/gprf-doc.c21
-rw-r--r--source/pdf/pdf-page.c188
8 files changed, 280 insertions, 113 deletions
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index 580ccdf9..5c6fa607 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -422,8 +422,8 @@ int fz_valgrind_pixmap(const fz_pixmap *pix);
fz_clone_pixmap_area_with_different_seps: Convert between
different separation results.
*/
-fz_pixmap *fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const fz_irect *bbox, fz_colorspace *dcs, fz_separations *seps, fz_colorspace *prf, fz_default_colorspaces *default_cs);
+fz_pixmap *fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const fz_irect *bbox, fz_colorspace *dcs, fz_separations *seps, const fz_color_params *color_params, fz_colorspace *prf, fz_default_colorspaces *default_cs);
-fz_pixmap *fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs);
+fz_pixmap *fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, const fz_color_params *color_params, fz_colorspace *prf, fz_default_colorspaces *default_cs);
#endif
diff --git a/include/mupdf/fitz/separation.h b/include/mupdf/fitz/separation.h
index 4b4be865..9bbb1845 100644
--- a/include/mupdf/fitz/separation.h
+++ b/include/mupdf/fitz/separation.h
@@ -40,8 +40,11 @@ fz_separations *fz_keep_separations(fz_context *ctx, fz_separations *sep);
/* Drop a reference */
void fz_drop_separations(fz_context *ctx, fz_separations *sep);
-/* Add a separation (RGBA and CYMK equivalents, null terminated name) */
-void fz_add_separation(fz_context *ctx, fz_separations *sep, uint32_t rgba, uint32_t cmyk, const char *name);
+/* Add a separation (null terminated name, colorspace) */
+void fz_add_separation(fz_context *ctx, fz_separations *sep, const char *name, fz_colorspace *cs, int cs_channel);
+
+/* Add a separation with equivalents (null terminated name, colorspace) (old, deprecated) */
+void fz_add_separation_equivalents(fz_context *ctx, fz_separations *sep, uint32_t rgba, uint32_t cmyk, const char *name);
/* Control the rendering of a given separation */
void fz_set_separation_behavior(fz_context *ctx, fz_separations *sep, int separation, fz_separation_behavior behavior);
@@ -52,8 +55,8 @@ fz_separation_behavior fz_separation_current_behavior(fz_context *ctx, const fz_
/* Quick test for all separations composite (the common case) */
int fz_separations_all_composite(fz_context *ctx, const fz_separations *sep);
-/* Read separation details */
-const char *fz_get_separation(fz_context *ctx, const fz_separations *sep, int separation, uint32_t *rgb, uint32_t *cmyk);
+/* Read separation name */
+const char *fz_separation_name(fz_context *ctx, const fz_separations *sep, int separation);
/* Count the number of separations */
int fz_count_separations(fz_context *ctx, const fz_separations *sep);
@@ -72,4 +75,7 @@ fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separatio
* to a color in terms of another colorspace/separations. */
void fz_convert_separation_colors(fz_context *ctx, const fz_color_params *color_params, const fz_colorspace *dst_cs, const fz_separations *dst_sep, float *dst_color, const fz_colorspace *src_cs, const float *src_color);
+/* Get the equivalent separation color in a given colorspace. */
+void fz_separation_equivalent(fz_context *ctx, const fz_separations *seps, int i, const fz_color_params *color_params, const fz_colorspace *dst_cs, const fz_colorspace *prf, float *convert);
+
#endif
diff --git a/resources/pdf/names.txt b/resources/pdf/names.txt
index 19293009..5ba1c026 100644
--- a/resources/pdf/names.txt
+++ b/resources/pdf/names.txt
@@ -77,6 +77,7 @@ ClosedArrow
Collection
ColorSpace
ColorTransform
+Colorants
Colors
Columns
Configs
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index cadd7d57..6a6a7067 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -363,7 +363,7 @@ resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, fl
}
static fz_draw_state *
-push_group_for_separations(fz_context *ctx, fz_draw_device *dev, fz_colorspace *prf, fz_default_colorspaces *default_cs)
+push_group_for_separations(fz_context *ctx, fz_draw_device *dev, const fz_color_params *color_params, fz_colorspace *prf, fz_default_colorspaces *default_cs)
{
fz_separations *clone = fz_clone_separations_for_overprint(ctx, dev->stack[0].dest->seps);
@@ -379,7 +379,7 @@ push_group_for_separations(fz_context *ctx, fz_draw_device *dev, fz_colorspace *
{
dev->stack[1] = dev->stack[0];
dev->stack[1].dest = NULL; /* So we are safe to destroy */
- dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, fz_device_cmyk(ctx), clone, prf, default_cs);
+ dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, fz_device_cmyk(ctx), clone, color_params, prf, default_cs);
dev->top++;
}
fz_always(ctx)
@@ -406,7 +406,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_draw_state *state = &dev->stack[dev->top];
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
if (flatness < 0.001f)
flatness = 0.001f;
@@ -453,7 +453,7 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
float mlw = fz_rasterizer_graphics_min_line_width(rast);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
if (mlw > aa_level)
aa_level = mlw;
@@ -515,7 +515,7 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_irect *scissor_ptr = &state->scissor;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
if (flatness < 0.001f)
flatness = 0.001f;
@@ -586,7 +586,7 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_irect *scissor_ptr = &state->scissor;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx) /* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
if (mlw > aa_level)
aa_level = mlw;
@@ -736,7 +736,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_rasterizer *rast = dev->rast;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -827,7 +827,7 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
int aa = fz_rasterizer_text_aa_level(dev->rast);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -902,7 +902,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_rasterizer *rast = dev->rast;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
state = push_stack(ctx, dev);
STACK_PUSHED("clip text");
@@ -1034,7 +1034,7 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
int aa = fz_rasterizer_text_aa_level(dev->rast);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
STACK_PUSHED("clip stroke text");
/* make the mask the exact size needed */
@@ -1161,7 +1161,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
fz_colorspace *prf = fz_proof_cs(ctx, dev);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
fz_bound_shade(ctx, shade, &ctm, &bounds);
scissor = state->scissor;
@@ -1331,7 +1331,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_colorspace *prf = fz_proof_cs(ctx, dev);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor);
@@ -1463,7 +1463,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_colorspace *prf = fz_proof_cs(ctx, dev);
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -1565,7 +1565,7 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_rect urect;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
STACK_PUSHED("clip image mask");
fz_pixmap_bbox(ctx, state->dest, &clip);
@@ -1729,7 +1729,7 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_colorspace *colorspace = NULL;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, color_params, fz_proof_cs(ctx, dev), dev->default_cs);
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -1868,7 +1868,7 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, fz_co
fz_rect trect = *rect;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
if (cs != NULL)
model = fz_default_colorspace(ctx, dev->default_cs, cs);
@@ -2114,7 +2114,7 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
fz_rect local_view = *view;
if (dev->top == 0 && dev->resolve_spots)
- state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs);
+ state = push_group_for_separations(ctx, dev, fz_default_color_params(ctx)/* FIXME */, fz_proof_cs(ctx, dev), dev->default_cs);
/* area, view, xstep, ystep are in pattern space */
/* ctm maps from pattern space to device space */
@@ -2402,7 +2402,7 @@ fz_draw_close_device(fz_context *ctx, fz_device *devp)
if (dev->resolve_spots && dev->top)
{
fz_draw_state *state = &dev->stack[--dev->top];
- fz_copy_pixmap_area_converting_seps(ctx, state[0].dest, state[1].dest, prf, dev->default_cs);
+ fz_copy_pixmap_area_converting_seps(ctx, state[0].dest, state[1].dest, fz_default_color_params(ctx)/* FIXME */, prf, dev->default_cs);
fz_drop_pixmap(ctx, state[1].dest);
assert(state[1].mask == NULL);
assert(state[1].shape == NULL);
diff --git a/source/fitz/output-psd.c b/source/fitz/output-psd.c
index 4d0f9574..d39051dd 100644
--- a/source/fitz/output-psd.c
+++ b/source/fitz/output-psd.c
@@ -74,6 +74,9 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *
fz_buffer *buffer = fz_icc_data_from_icc_colorspace(ctx, cs);
unsigned char *data;
size_t size = fz_buffer_storage(ctx, buffer, &data);
+ const fz_colorspace *cs_cmyk = cs;
+ if (fz_colorspace_n(ctx, cs) != 4)
+ cs_cmyk = fz_device_cmyk(ctx);
if (!fz_colorspace_is_subtractive(ctx, cs))
writer->num_additive = fz_colorspace_n(ctx, cs);
@@ -110,7 +113,7 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *
len = 0;
for (i = 0; i < s; i++)
{
- const char *name = fz_get_separation(ctx, seps, i, NULL, NULL);
+ const char *name = fz_separation_name(ctx, seps, i);
char text[32];
size_t len2;
if (name == NULL)
@@ -140,7 +143,7 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *
fz_write_int32_be(ctx, out, (len + 1)&~1);
for (i = 0; i < s; i++) {
size_t len2;
- const char *name = fz_get_separation(ctx, seps, i, NULL, NULL);
+ const char *name = fz_separation_name(ctx, seps, i);
char text[32];
if (name == NULL)
{
@@ -164,14 +167,14 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *
fz_write_int16_be(ctx, out, 0); /* PString */
fz_write_int32_be(ctx, out, 14 * s); /* Length */
for (i = 0; i < s; i++) {
- uint32_t cmyk;
- (void)fz_get_separation(ctx, seps, i, NULL, &cmyk);
+ float cmyk[4];
+ fz_separation_equivalent(ctx, seps, i, NULL, cs_cmyk, NULL, cmyk);
fz_write_int16_be(ctx, out, 02); /* CMYK */
/* PhotoShop stores all component values as if they were additive. */
- fz_write_int16_be(ctx, out, 257 * (cmyk & 0xFF));/* Cyan */
- fz_write_int16_be(ctx, out, 257 * ((cmyk>>8) & 0xFF));/* Magenta */
- fz_write_int16_be(ctx, out, 257 * ((cmyk>>16) & 0xFF));/* Yellow */
- fz_write_int16_be(ctx, out, 257 * ((cmyk>>24) & 0xFF));/* Black */
+ fz_write_int16_be(ctx, out, 65535 * (1-cmyk[0]));/* Cyan */
+ fz_write_int16_be(ctx, out, 65535 * (1-cmyk[1]));/* Magenta */
+ fz_write_int16_be(ctx, out, 65535 * (1-cmyk[2]));/* Yellow */
+ fz_write_int16_be(ctx, out, 65535 * (1-cmyk[3]));/* Black */
fz_write_int16_be(ctx, out, 0); /* Opacity 0 to 100 */
fz_write_byte(ctx, out, 2); /* Don't know */
fz_write_byte(ctx, out, 0); /* Padding - Always Zero */
diff --git a/source/fitz/separation.c b/source/fitz/separation.c
index 0baf30b4..f202d1aa 100644
--- a/source/fitz/separation.c
+++ b/source/fitz/separation.c
@@ -12,8 +12,10 @@ struct fz_separations_s
int num_separations;
int controllable;
uint32_t state[(2*FZ_MAX_SEPARATIONS + 31) / 32];
- uint32_t equiv_rgb[FZ_MAX_SEPARATIONS];
- uint32_t equiv_cmyk[FZ_MAX_SEPARATIONS];
+ fz_colorspace *cs[FZ_MAX_SEPARATIONS];
+ uint8_t cs_pos[FZ_MAX_SEPARATIONS];
+ uint32_t rgba[FZ_MAX_SEPARATIONS];
+ uint32_t cmyk[FZ_MAX_SEPARATIONS];
char *name[FZ_MAX_SEPARATIONS];
};
@@ -39,12 +41,33 @@ void fz_drop_separations(fz_context *ctx, fz_separations *sep)
{
int i;
for (i = 0; i < sep->num_separations; i++)
+ {
fz_free(ctx, sep->name[i]);
+ fz_drop_colorspace(ctx, sep->cs[i]);
+ }
fz_free(ctx, sep);
}
}
-void fz_add_separation(fz_context *ctx, fz_separations *sep, uint32_t rgb, uint32_t cmyk, const char *name)
+void fz_add_separation(fz_context *ctx, fz_separations *sep, const char *name, fz_colorspace *cs, int colorant)
+{
+ int n;
+
+ if (!sep)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "can't add to non-existent separations");
+
+ n = sep->num_separations;
+ if (n == FZ_MAX_SEPARATIONS)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "too many separations");
+
+ sep->name[n] = fz_strdup(ctx, name);
+ sep->cs[n] = fz_keep_colorspace(ctx, cs);
+ sep->cs_pos[n] = colorant;
+
+ sep->num_separations++;
+}
+
+void fz_add_separation_equivalents(fz_context *ctx, fz_separations *sep, uint32_t rgba, uint32_t cmyk, const char *name)
{
int n;
@@ -56,8 +79,8 @@ void fz_add_separation(fz_context *ctx, fz_separations *sep, uint32_t rgb, uint3
fz_throw(ctx, FZ_ERROR_GENERIC, "too many separations");
sep->name[n] = fz_strdup(ctx, name);
- sep->equiv_rgb[n] = rgb;
- sep->equiv_cmyk[n] = cmyk;
+ sep->rgba[n] = rgba;
+ sep->cmyk[n] = cmyk;
sep->num_separations++;
}
@@ -128,22 +151,17 @@ int fz_separations_all_composite(fz_context *ctx, const fz_separations *sep)
return 1;
for (i = 0; i < (FZ_MAX_SEPARATIONS + 31) / 32; i++)
- if (sep->state[i] != FZ_SEPARATION_COMPOSITE)
+ if (sep_state(sep, i) != FZ_SEPARATION_COMPOSITE)
return 0;
return 1;
}
-const char *fz_get_separation(fz_context *ctx, const fz_separations *sep, int separation, uint32_t *rgb, uint32_t *cmyk)
+const char *fz_separation_name(fz_context *ctx, const fz_separations *sep, int separation)
{
if (!sep || separation < 0 || separation >= sep->num_separations)
fz_throw(ctx, FZ_ERROR_GENERIC, "can't access non-existent separation");
- if (rgb)
- *rgb = sep->equiv_rgb[separation];
- if (cmyk)
- *cmyk = sep->equiv_cmyk[separation];
-
return sep->name[separation];
}
@@ -207,8 +225,7 @@ fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separatio
beh = FZ_SEPARATION_SPOT;
fz_set_separation_behavior(ctx, clone, j, beh);
clone->name[j] = sep->name[i] ? fz_strdup(ctx, sep->name[i]) : NULL;
- clone->equiv_rgb[j] = sep->equiv_rgb[i];
- clone->equiv_cmyk[j] = sep->equiv_cmyk[i];
+ clone->cs[j] = fz_keep_colorspace(ctx, sep->cs[i]);
}
}
fz_catch(ctx)
@@ -221,7 +238,7 @@ fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separatio
}
fz_pixmap *
-fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const fz_irect *bbox, fz_colorspace *dcs, fz_separations *dseps, fz_colorspace *prf, fz_default_colorspaces *default_cs)
+fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const fz_irect *bbox, fz_colorspace *dcs, fz_separations *dseps, const fz_color_params *color_params, fz_colorspace *prf, fz_default_colorspaces *default_cs)
{
fz_irect local_bbox;
fz_pixmap *dst;
@@ -245,11 +262,11 @@ fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const
else
dst->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
- return fz_copy_pixmap_area_converting_seps(ctx, dst, src, prf, default_cs);
+ return fz_copy_pixmap_area_converting_seps(ctx, dst, src, color_params, prf, default_cs);
}
fz_pixmap *
-fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs)
+fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, const fz_color_params *color_params, fz_colorspace *prf, fz_default_colorspaces *default_cs)
{
int dw = dst->w;
int dh = dst->h;
@@ -360,33 +377,12 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
/* Still need to handle mapping 'lost' spots down to process colors */
for (i = 0; i < sseps_n; i++)
{
- uint8_t convert[4];
- uint32_t c;
+ float convert[FZ_MAX_COLORS];
if (mapped[i])
continue;
/* Src spot i is not mapped. We need to convert that down. */
- switch (dc)
- {
- case 1: /* Grey */
- /* FIXME: Should we hold a grey equivalent in each spot? */
- c = sseps->equiv_rgb[i];
- convert[0] = ((c & 0xff) * 77 + ((c>>8) & 0xff) * 150 + ((c>>16) & 0xff) * 28 + 255)>>8;
- break;
- case 3: /* RGB */
- c = sseps->equiv_rgb[i];
- convert[0] = c;
- convert[1] = c>>8;
- convert[2] = c>>16;
- break;
- case 4: /* CMYK */
- c = sseps->equiv_cmyk[i];
- convert[0] = c;
- convert[1] = c>>8;
- convert[2] = c>>16;
- convert[3] = c>>24;
- break;
- }
+ fz_separation_equivalent(ctx, sseps, i, color_params, dst->colorspace, prf, convert);
{
unsigned char *dd = ddata;
@@ -395,11 +391,11 @@ fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *
{
for (x = dw; x > 0; x--)
{
- unsigned char v = sd[i];
+ unsigned char v = sd[i];
if (v == 0)
continue;
for (i = 0; i < dc; i++)
- dd[i] = fz_clampi(dd[i] + fz_mul255(v, convert[i]), 0, 255);
+ dd[i] = fz_clampi(dd[i] + v * convert[i], 0, 255);
dd += dn;
sd += sn;
}
@@ -501,3 +497,33 @@ found_process:
dst_color[i] += converted[i];
}
}
+
+void fz_separation_equivalent(fz_context *ctx, const fz_separations *seps, int i, const fz_color_params *color_params, const fz_colorspace *dst_cs, const fz_colorspace *prf, float *convert)
+{
+ float colors[FZ_MAX_COLORS];
+
+ if (!seps->cs[i])
+ {
+ switch (fz_colorspace_n(ctx, dst_cs))
+ {
+ case 3:
+ convert[0] = (seps->rgba[i] & 0xff)/ 255.0f;
+ convert[1] = ((seps->rgba[i]>>8) & 0xff)/ 255.0f;
+ convert[2] = ((seps->rgba[i]>>16) & 0xff)/ 255.0f;
+ convert[3] = ((seps->rgba[i]>>24) & 0xff)/ 255.0f;
+ return;
+ case 4:
+ convert[0] = (seps->cmyk[i] & 0xff)/ 255.0f;
+ convert[1] = ((seps->cmyk[i]>>8) & 0xff)/ 255.0f;
+ convert[2] = ((seps->cmyk[i]>>16) & 0xff)/ 255.0f;
+ convert[3] = ((seps->cmyk[i]>>24) & 0xff)/ 255.0f;
+ return;
+ default:
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot return equivalent in this colorspace");
+ }
+ }
+
+ memset(colors, 0, sizeof(float) * fz_colorspace_n(ctx, seps->cs[i]));
+ colors[seps->cs_pos[i]] = 1;
+ fz_convert_color(ctx, color_params, prf, dst_cs, convert, seps->cs[i], colors);
+}
diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c
index 74b50a9b..f66d78bb 100644
--- a/source/gprf/gprf-doc.c
+++ b/source/gprf/gprf-doc.c
@@ -368,13 +368,13 @@ gprf_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *area, int w, int h,
read_sep[i] = !FZ_SEPARATION_DISABLED(ctx, image->separations, i-3);
if (read_sep[i])
{
- uint32_t rgb, cmyk;
+ float cmyk[4];
- (void)fz_get_separation(ctx, image->separations, i - 3, &rgb, &cmyk);
- equiv[i][0] = (cmyk>> 0) & 0xFF;
- equiv[i][1] = (cmyk>> 8) & 0xFF;
- equiv[i][2] = (cmyk>>16) & 0xFF;
- equiv[i][3] = (cmyk>>24) & 0xFF;
+ (void)fz_separation_equivalent(ctx, image->separations, i - 3, NULL, fz_device_cmyk(ctx), NULL, cmyk);
+ equiv[i][0] = cmyk[0] * 0xFF;
+ equiv[i][1] = cmyk[1] * 0xFF;
+ equiv[i][2] = cmyk[2] * 0xFF;
+ equiv[i][3] = cmyk[3] * 0xFF;
}
}
}
@@ -744,7 +744,7 @@ read_tiles(fz_context *ctx, gprf_page *page)
int32_t rgba = fz_read_int32_le(ctx, file);
int32_t cmyk = fz_read_int32_le(ctx, file);
fz_read_string(ctx, file, blatter, sizeof(blatter));
- fz_add_separation(ctx, page->separations, rgba, cmyk, blatter);
+ fz_add_separation_equivalents(ctx, page->separations, rgba, cmyk, blatter);
}
/* Seek to the image data */
@@ -854,13 +854,6 @@ static int gprf_separation_disabled(fz_context *ctx, fz_page *page_, int sep)
return FZ_SEPARATION_DISABLED(ctx, page->separations, sep);
}
-static const char *gprf_get_separation(fz_context *ctx, fz_page *page_, int sep, uint32_t *rgba, uint32_t*cmyk)
-{
- gprf_page *page = (gprf_page *)page_;
-
- return fz_get_separation(ctx, page->separations, sep, rgba, cmyk);
-}
-
static fz_separations *
gprf_separations(fz_context *ctx, fz_page *page_)
{
diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c
index 5b319e3a..9c7c8922 100644
--- a/source/pdf/pdf-page.c
+++ b/source/pdf/pdf-page.c
@@ -638,42 +638,115 @@ pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *page_mediabox, fz_m
pdf_page_obj_transform(ctx, page->obj, page_mediabox, page_ctm);
}
-fz_separations *
-pdf_page_separations(fz_context *ctx, pdf_page *page)
+static void
+find_seps(fz_context *ctx, fz_separations **seps, pdf_obj *obj)
{
- pdf_obj *res = pdf_page_resources(ctx, page);
- fz_separations *seps = NULL;
- int i, len;
+ int i, n;
+ pdf_obj *nameobj = pdf_array_get(ctx, obj, 0);
- res = pdf_dict_get(ctx, res, PDF_NAME_ColorSpace);
- if (!res)
- return NULL;
+ if (pdf_name_eq(ctx, nameobj, PDF_NAME_Separation))
+ {
+ fz_colorspace *cs;
+ const char *name = pdf_to_name(ctx, pdf_array_get(ctx, obj, 1));
+
+ /* Skip 'special' colorants. */
+ if (!strcmp(name, "Black") ||
+ !strcmp(name, "Cyan") ||
+ !strcmp(name, "Magenta") ||
+ !strcmp(name, "Yellow") ||
+ !strcmp(name, "All") ||
+ !strcmp(name, "None"))
+ return;
+
+ n = fz_count_separations(ctx, *seps);
+ for (i = 0; i < n; i++)
+ {
+ if (!strcmp(name, fz_separation_name(ctx, *seps, i)))
+ return; /* Got that one already */
+ }
- fz_var(seps);
- fz_var(i);
+ cs = pdf_load_colorspace(ctx, obj);
+ if (!*seps)
+ *seps = fz_new_separations(ctx, 0);
+ fz_add_separation(ctx, *seps, name, cs, 0);
+ fz_drop_colorspace(ctx, cs);
+ }
+ else if (pdf_name_eq(ctx, nameobj, PDF_NAME_Indexed))
+ {
+ find_seps(ctx, seps, pdf_array_get(ctx, obj, 1));
+ }
+ else if (pdf_name_eq(ctx, nameobj, PDF_NAME_DeviceN))
+ {
+ /* If the separation colorants exists for this DeviceN color space
+ * add those prior to our search for DeviceN color */
+ pdf_obj *cols = pdf_dict_get(ctx, pdf_array_get(ctx, obj, 4), PDF_NAME_Colorants);
+ int i, n = pdf_dict_len(ctx, cols);
+ for (i = 0; i < n; i++)
+ find_seps(ctx, seps, pdf_dict_get_val(ctx, cols, i));
+ }
+}
- len = pdf_dict_len(ctx, res);
+static void
+find_devn(fz_context *ctx, fz_separations **seps, pdf_obj *obj)
+{
+ int i, j, n, m;
+ pdf_obj *arr;
+ pdf_obj *nameobj = pdf_array_get(ctx, obj, 0);
+
+ if (!pdf_name_eq(ctx, nameobj, PDF_NAME_DeviceN))
+ return;
+
+ arr = pdf_array_get(ctx, obj, 1);
+ m = pdf_array_len(ctx, arr);
+ for (j = 0; j < m; j++)
+ {
+ fz_colorspace *cs;
+ const char *name = pdf_to_name(ctx, pdf_array_get(ctx, arr, j));
+
+ /* Skip 'special' colorants. */
+ if (!strcmp(name, "Black") ||
+ !strcmp(name, "Cyan") ||
+ !strcmp(name, "Magenta") ||
+ !strcmp(name, "Yellow") ||
+ !strcmp(name, "All") ||
+ !strcmp(name, "None"))
+ continue;
+
+ n = fz_count_separations(ctx, *seps);
+ for (i = 0; i < n; i++)
+ {
+ if (!strcmp(name, fz_separation_name(ctx, *seps, i)))
+ break; /* Got that one already */
+ }
+
+ if (i == n)
+ {
+ cs = pdf_load_colorspace(ctx, obj);
+ if (!*seps)
+ *seps = fz_new_separations(ctx, 0);
+ fz_add_separation(ctx, *seps, name, cs, j);
+ fz_drop_colorspace(ctx, cs);
+ }
+ }
+}
+
+typedef void (res_finder_fn)(fz_context *ctx, fz_separations **seps, pdf_obj *obj);
+
+static void
+search_res(fz_context *ctx, fz_separations **seps, pdf_obj *res, res_finder_fn *fn)
+{
+ int i = 0;
+ int len = pdf_dict_len(ctx, res);
+
+ fz_var(i);
- i = 0;
while (i < len)
{
fz_try(ctx)
{
do
{
- pdf_obj *obj;
- i++;
- obj = pdf_dict_get_val(ctx, res, i-1);
-
- if (pdf_name_eq(ctx, pdf_array_get(ctx, obj, 0), PDF_NAME_Separation))
- {
- uint32_t rgba = 0; /* FIXME */
- uint32_t cmyk = 0; /* FIXME */
- const char *name = pdf_to_name(ctx, pdf_array_get(ctx, obj, 1));
- if (!seps)
- seps = fz_new_separations(ctx, 0);
- fz_add_separation(ctx, seps, rgba, cmyk, name);
- }
+ fn(ctx, seps, pdf_dict_get_val(ctx, res, i++));
}
while (i < len);
}
@@ -682,6 +755,71 @@ pdf_page_separations(fz_context *ctx, pdf_page *page)
/* Don't die because a single separation failed to load */
}
}
+}
+
+static void
+scan_page_seps(fz_context *ctx, pdf_obj *res, fz_separations **seps, res_finder_fn *fn)
+{
+ pdf_obj *forms;
+ pdf_obj *sh;
+ pdf_obj *xo = NULL;
+ int i, len;
+
+ fz_var(xo);
+
+ if (pdf_mark_obj(ctx, res))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in resources");
+
+ fz_try(ctx)
+ {
+ search_res(ctx, seps, pdf_dict_get(ctx, res, PDF_NAME_ColorSpace), fn);
+
+ sh = pdf_dict_get(ctx, res, PDF_NAME_Shading);
+ len = pdf_dict_len(ctx, sh);
+ for (i = 0; i < len; i++)
+ fn(ctx, seps, pdf_dict_get(ctx, pdf_dict_get_val(ctx, sh, i), PDF_NAME_ColorSpace));
+
+ forms = pdf_dict_get(ctx, res, PDF_NAME_XObject);
+ len = pdf_dict_len(ctx, forms);
+
+ /* Recurse on the forms. Throw if we cycle */
+ for (i = 0; i < len; i++)
+ {
+ xo = pdf_dict_get_val(ctx, forms, i++);
+
+ if (pdf_mark_obj(ctx, xo))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in forms");
+
+ scan_page_seps(ctx, pdf_dict_get(ctx, xo, PDF_NAME_Resources), seps, fn);
+ pdf_unmark_obj(ctx, xo);
+ xo = NULL;
+ }
+ }
+ fz_always(ctx)
+ {
+ pdf_unmark_obj(ctx, xo);
+ pdf_unmark_obj(ctx, res);
+ }
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
+fz_separations *
+pdf_page_separations(fz_context *ctx, pdf_page *page)
+{
+ pdf_obj *res = pdf_page_resources(ctx, page);
+ fz_separations *seps = NULL;
+
+ /* Run through and look for separations first. This is
+ * because separations are simplest to deal with, and
+ * because DeviceN may be implemented on top of separations.
+ */
+ scan_page_seps(ctx, res, &seps, find_seps);
+
+ /* Now run through again, and look for DeviceNs. These may
+ * have spot colors in that aren't defined in terms of
+ * separations. */
+ scan_page_seps(ctx, res, &seps, find_devn);
return seps;
}