summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/color-management.h2
-rw-r--r--include/mupdf/fitz/pixmap.h10
-rw-r--r--include/mupdf/fitz/separation.h8
-rw-r--r--include/mupdf/fitz/store.h11
-rw-r--r--source/fitz/color-lcms.c12
-rw-r--r--source/fitz/colorspace-imp.h8
-rw-r--r--source/fitz/colorspace.c394
-rw-r--r--source/fitz/draw-affine.c6
-rw-r--r--source/fitz/draw-device.c316
-rw-r--r--source/fitz/draw-paint.c5
-rw-r--r--source/fitz/pixmap.c4
-rw-r--r--source/fitz/separation.c334
12 files changed, 891 insertions, 219 deletions
diff --git a/include/mupdf/fitz/color-management.h b/include/mupdf/fitz/color-management.h
index 9ab1d133..a2f20e9d 100644
--- a/include/mupdf/fitz/color-management.h
+++ b/include/mupdf/fitz/color-management.h
@@ -45,7 +45,7 @@ typedef void (fz_cmm_transform_color_fn)(fz_cmm_instance *ctx, fz_icclink *link,
/*
fz_cmm_init_link_fn: Create a new link between icc profiles.
*/
-typedef void (fz_cmm_init_link_fn)(fz_cmm_instance *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int extras, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des);
+typedef void (fz_cmm_init_link_fn)(fz_cmm_instance *ctx, fz_icclink *link, const fz_iccprofile *dst, int dst_extras, const fz_iccprofile *src, int src_extras, const fz_iccprofile *prf, const fz_color_params *rend, int cmm_flags, int num_bytes, int copy_spots);
/*
fz_cmm_fin_link_fn: Drop a link.
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index 533ff735..580ccdf9 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -401,7 +401,7 @@ void fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict sr
fz_pixmap_converter: Color convert a pixmap. The passing of default_cs is needed due to the base cs of the image possibly
needing to be treated as being in one of the page default color spaces.
*/
-typedef void (fz_pixmap_converter)(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params);
+typedef void (fz_pixmap_converter)(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots);
fz_pixmap_converter *fz_lookup_pixmap_converter(fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss);
/*
@@ -418,4 +418,12 @@ int fz_valgrind_pixmap(const fz_pixmap *pix);
#define fz_valgrind_pixmap(pix) do {} while (0)
#endif
+/*
+ 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_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs);
+
#endif
diff --git a/include/mupdf/fitz/separation.h b/include/mupdf/fitz/separation.h
index 4d17fc53..4b4be865 100644
--- a/include/mupdf/fitz/separation.h
+++ b/include/mupdf/fitz/separation.h
@@ -64,4 +64,12 @@ int fz_separations_controllable(fz_context *ctx, const fz_separations *seps);
/* Return the number of active separations. */
int fz_count_active_separations(fz_context *ctx, const fz_separations *seps);
+/* If the separations selection is unsuitable for overprint,
+ * clone it to produce one that is, otherwise return NULL. */
+fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separations *seps);
+
+/* Convert a color given in terms of one colorspace,
+ * 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);
+
#endif
diff --git a/include/mupdf/fitz/store.h b/include/mupdf/fitz/store.h
index 1a0ae87b..9d363c6b 100644
--- a/include/mupdf/fitz/store.h
+++ b/include/mupdf/fitz/store.h
@@ -139,10 +139,13 @@ typedef struct fz_store_hash_s
{
unsigned char src_md5[16];
unsigned char dst_md5[16];
- uint8_t ri_bp;
- uint8_t depth;
- uint8_t extras;
- uint8_t proof;
+ unsigned int ri:2;
+ unsigned int bp:1;
+ unsigned int bpp16:1;
+ unsigned int proof:1;
+ unsigned int src_extras:5;
+ unsigned int dst_extras:5;
+ unsigned int copy_spots:1;
} link; /* 36 bytes */
} u;
} fz_store_hash; /* 40 or 44 bytes */
diff --git a/source/fitz/color-lcms.c b/source/fitz/color-lcms.c
index 1bc344f4..3714ea45 100644
--- a/source/fitz/color-lcms.c
+++ b/source/fitz/color-lcms.c
@@ -180,7 +180,7 @@ fz_lcms_transform_color(fz_cmm_instance *instance, fz_icclink *link, unsigned sh
}
void
-fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int extras, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *dst)
+fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_iccprofile *dst, int dst_extras, const fz_iccprofile *src, int src_extras, const fz_iccprofile *prf, const fz_color_params *rend, int cmm_flags, int num_bytes, int copy_spots)
{
cmsContext cmm_ctx = (cmsContext)instance;
fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx);
@@ -199,7 +199,7 @@ fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_pa
if (lcms_src_cs < 0)
lcms_src_cs = 0;
src_num_chan = cmsChannelsOf(cmm_ctx, src_cs);
- src_data_type = (COLORSPACE_SH(lcms_src_cs) | CHANNELS_SH(src_num_chan) | DOSWAP_SH(src->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(extras));
+ src_data_type = (COLORSPACE_SH(lcms_src_cs) | CHANNELS_SH(src_num_chan) | DOSWAP_SH(src->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(src_extras));
/* dst */
des_cs = cmsGetColorSpace(cmm_ctx, dst->cmm_handle);
@@ -207,17 +207,19 @@ fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_pa
if (lcms_des_cs < 0)
lcms_des_cs = 0;
des_num_chan = cmsChannelsOf(cmm_ctx, des_cs);
- des_data_type = (COLORSPACE_SH(lcms_des_cs) | CHANNELS_SH(des_num_chan) | DOSWAP_SH(dst->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(extras));
+ des_data_type = (COLORSPACE_SH(lcms_des_cs) | CHANNELS_SH(des_num_chan) | DOSWAP_SH(dst->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(dst_extras));
/* flags */
if (rend->bp)
flag |= cmsFLAGS_BLACKPOINTCOMPENSATION;
- if (extras)
+ if (copy_spots)
flag |= cmsFLAGS_COPY_ALPHA;
link->depth = num_bytes;
- link->extras = extras;
+ link->src_extras = src_extras;
+ link->dst_extras = dst_extras;
+ link->copy_spots = copy_spots;
if (prf == NULL)
{
diff --git a/source/fitz/colorspace-imp.h b/source/fitz/colorspace-imp.h
index c4e94f03..0ca960a0 100644
--- a/source/fitz/colorspace-imp.h
+++ b/source/fitz/colorspace-imp.h
@@ -15,7 +15,7 @@
int fz_cmm_avoid_white_fix_flag(fz_context *ctx);
void fz_cmm_transform_pixmap(fz_context *ctx, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src);
void fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, const unsigned short *src);
-void fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int extras, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des);
+void fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_iccprofile *dst, int dst_extras, const fz_iccprofile *src, int src_extras, const fz_iccprofile *prf, const fz_color_params *rend, int cmm_flags, int num_bytes, int copy_spots);
void fz_cmm_fin_link(fz_context *ctx, fz_icclink *link);
fz_cmm_instance *fz_cmm_new_instance(fz_context *ctx);
void fz_cmm_drop_instance(fz_context *ctx);
@@ -51,10 +51,10 @@ struct fz_iccprofile_s
struct fz_icclink_s
{
fz_storable storable;
- int num_in;
- int num_out;
int depth;
- int extras;
+ int src_extras;
+ int dst_extras;
+ int copy_spots;
int is_identity;
void *cmm_handle;
};
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 29ad18d3..3e322bd9 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -32,10 +32,10 @@ fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, c
}
void
-fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int extras, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des)
+fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_iccprofile *dst, int dst_extras, const fz_iccprofile *src, int src_extras, const fz_iccprofile *prf, const fz_color_params *rend, int cmm_flags, int num_bytes, int copy_spots)
{
if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
- ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, rend, cmm_flags, num_bytes, extras, src, prf, des);
+ ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, dst, dst_extras, src, src_extras, prf, rend, cmm_flags, num_bytes, copy_spots);
}
void
@@ -201,7 +201,9 @@ struct fz_link_key_s {
unsigned char src_md5[16];
unsigned char dst_md5[16];
fz_color_params rend;
- int extras;
+ int src_extras;
+ int dst_extras;
+ int copy_spots;
int depth;
int proof;
};
@@ -227,7 +229,9 @@ fz_cmp_link_key(fz_context *ctx, void *k0_, void *k1_)
fz_link_key *k0 = (fz_link_key *)k0_;
fz_link_key *k1 = (fz_link_key *)k1_;
return k0->proof == k1->proof &&
- k0->extras == k1->extras &&
+ k0->src_extras == k1->src_extras &&
+ k0->dst_extras == k1->dst_extras &&
+ k0->copy_spots == k1->copy_spots &&
k0->depth == k1->depth &&
k0->rend.bp == k1->rend.bp &&
k0->rend.ri == k1->rend.ri &&
@@ -260,10 +264,13 @@ fz_make_hash_link_key(fz_context *ctx, fz_store_hash *hash, void *key_)
fz_link_key *key = (fz_link_key *)key_;
memcpy(hash->u.link.dst_md5, key->dst_md5, 16);
memcpy(hash->u.link.src_md5, key->src_md5, 16);
- hash->u.link.ri_bp = (key->rend.ri<<1) | key->rend.bp;
- hash->u.link.extras = key->extras;
- hash->u.link.depth = key->depth;
+ hash->u.link.ri = key->rend.ri;
+ hash->u.link.bp = key->rend.bp;
+ hash->u.link.src_extras = key->src_extras;
+ hash->u.link.dst_extras = key->dst_extras;
+ hash->u.link.bpp16 = key->depth == 2;
hash->u.link.proof = key->proof;
+ hash->u.link.copy_spots = key->copy_spots;
return 1;
}
@@ -319,14 +326,11 @@ get_base_icc_profile(fz_context *ctx, const fz_colorspace *cs)
}
static fz_icclink *
-fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccprofile *dst, const fz_color_params *rend, int num_bytes, int extras)
+fz_new_icc_link(fz_context *ctx, fz_iccprofile *dst, int dst_extras, fz_iccprofile *src, int src_extras, fz_iccprofile *prf, const fz_color_params *rend, int num_bytes, int copy_extras)
{
fz_icclink *link = fz_malloc_struct(ctx, fz_icclink);
FZ_INIT_STORABLE(link, 1, fz_drop_link_imp);
- link->num_in = src->num_devcomp;
- link->num_out = dst->num_devcomp;
-
if (memcmp(src->md5, dst->md5, 16) == 0 && prf == NULL)
{
link->is_identity = 1;
@@ -334,7 +338,7 @@ fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccp
}
fz_try(ctx)
- fz_cmm_init_link(ctx, link, rend, 0, num_bytes, extras, src, prf, dst);
+ fz_cmm_init_link(ctx, link, dst, dst_extras, src, src_extras, prf, rend, 0, num_bytes, copy_extras);
fz_catch(ctx)
{
fz_free(ctx, link);
@@ -378,7 +382,7 @@ fz_icc_from_cal(fz_context *ctx, const fz_colorspace *cs)
}
static fz_icclink *
-fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *prf, const fz_colorspace *dst, const fz_color_params *rend, int num_bytes, int extras, int *src_n)
+fz_get_icc_link(fz_context *ctx, const fz_colorspace *dst, int dst_extras, const fz_colorspace *src, int src_extras, const fz_colorspace *prf, const fz_color_params *rend, int num_bytes, int copy_spots, int *src_n)
{
fz_icclink *link = NULL;
fz_iccprofile *src_icc = NULL;
@@ -387,6 +391,8 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
fz_link_key *key = NULL;
fz_icclink *new_link;
+ assert(!copy_spots || src_extras == dst_extras);
+
if (prf != NULL)
prf_icc = prf->data;
@@ -440,6 +446,9 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
fz_var(link);
fz_var(key);
+ if (rend == NULL)
+ rend = fz_default_color_params(ctx);
+
fz_try(ctx)
{
/* Check the storable to see if we have a copy. */
@@ -449,15 +458,17 @@ fz_get_icc_link(fz_context *ctx, const fz_colorspace *src, const fz_colorspace *
memcpy(&key->src_md5, src_icc->md5, 16);
key->rend.ri = rend->ri;
key->rend.bp = rend->bp;
- key->extras = extras;
+ key->src_extras = src_extras;
+ key->dst_extras = dst_extras;
key->depth = num_bytes;
key->proof = (prf_icc != NULL);
+ key->copy_spots = copy_spots;
link = fz_find_item(ctx, fz_drop_link_imp, key, &fz_link_store_type);
/* Not found. Make new one add to store. */
if (link == NULL)
{
- link = fz_new_icc_link(ctx, src_icc, prf_icc, dst_icc, rend, num_bytes, extras);
+ link = fz_new_icc_link(ctx, dst_icc, dst_extras, src_icc, src_extras, prf_icc, rend, num_bytes, copy_spots);
new_link = fz_store_item(ctx, key, link, sizeof(fz_icclink), &fz_link_store_type);
if (new_link != NULL)
{
@@ -828,21 +839,23 @@ fz_default_color_params(fz_context *ctx)
/* Fast pixmap color conversions */
-static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 1);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 1 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -917,7 +930,7 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -940,23 +953,44 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 1);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 1 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1034,7 +1068,7 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -1058,23 +1092,45 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1143,7 +1199,7 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
int i;
@@ -1164,23 +1220,42 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1251,7 +1326,7 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1272,23 +1347,43 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots || ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1378,7 +1473,7 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1406,23 +1501,49 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = s[0];
+ unsigned char m = s[1];
+ unsigned char y = s[2];
+ unsigned char k = (unsigned char)(255 - fz_maxi(c, fz_maxi(m, y)));
+ d[0] = c + k;
+ d[1] = m + k;
+ d[2] = y + k;
+ d[3] = 255 - k;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 4);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 4 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1512,7 +1633,7 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1540,23 +1661,49 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = s[2];
+ unsigned char m = s[1];
+ unsigned char y = s[0];
+ unsigned char k = (unsigned char)(255 - fz_maxi(c, fz_maxi(m, y)));
+ d[0] = c + k;
+ d[1] = m + k;
+ d[2] = y + k;
+ d[3] = 255 - k;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 1);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 1 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -1634,7 +1781,7 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -1658,6 +1805,26 @@ static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, f
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(255 - s[0], 77);
+ unsigned char m = fz_mul255(255 - s[1], 150);
+ unsigned char y = fz_mul255(255 - s[2], 28);
+ d[0] = (unsigned char)fz_maxi(s[3] - c - m - y, 0);
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
#ifdef ARCH_ARM
@@ -1987,23 +2154,25 @@ static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned c
#endif
}
-static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
unsigned int C,M,Y,K;
unsigned char r,g,b;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2033,13 +2202,13 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
{
if (sa)
{
- #ifdef ARCH_ARM
+#ifdef ARCH_ARM
if (h == 1)
{
fast_cmyk_to_rgb_ARM(d, s, w);
return;
}
- #endif
+#endif
while (h--)
{
size_t ww = w;
@@ -2096,7 +2265,7 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2120,25 +2289,48 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 4);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
unsigned int C,M,Y,K;
unsigned char r,g,b;
/* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 4 + ss + sa || ss != ds || (!da && sa))
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2227,7 +2419,7 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2251,23 +2443,46 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz
s += s_line_inc;
}
}
+ else
+ {
+ /* Slower, spots capable version */
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
-static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
size_t w = src->w;
int h = src->h;
+ int sn = src->n;
int ss = src->s;
int sa = src->alpha;
+ int dn = dst->n;
int ds = dst->s;
int da = dst->alpha;
- ptrdiff_t d_line_inc = dst->stride - w * (da + ds + 3);
- ptrdiff_t s_line_inc = src->stride - w * (sa + ss + 3);
+ ptrdiff_t d_line_inc = dst->stride - w * dn;
+ ptrdiff_t s_line_inc = src->stride - w * sn;
- /* Spots must match, and we can never drop alpha (but we can invent it) */
- if (dst->n != 3 + ds + da || src->n != 3 + ss + sa || ss != ds || (!da && sa))
+ /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
+ if ((copy_spots && ss != ds) || (!da && sa))
{
assert("This should never happen" == NULL);
fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot convert between incompatible pixmaps");
@@ -2336,7 +2551,7 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_
}
}
}
- else
+ else if (copy_spots)
{
/* Slower, spots capable version */
while (h--)
@@ -2359,10 +2574,29 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_
s += s_line_inc;
}
}
+ else
+ {
+ while (h--)
+ {
+ size_t ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ s += sn;
+ d += dn;
+ if (da)
+ d[-1] = sa ? s[-1] : 255;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
}
static void
-icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
fz_colorspace *srcs = src->colorspace;
fz_colorspace *dsts = dst->colorspace;
@@ -2394,7 +2628,7 @@ icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *
inputpos = src->samples;
outputpos = dst->samples;
- link = fz_get_icc_link(ctx, srcs, prf, dsts, color_params, 1, dst->alpha, &src_n);
+ link = fz_get_icc_link(ctx, dsts, dst->s + dst->alpha, srcs, src->s + src->alpha, prf, color_params, 1, copy_spots, &src_n);
if (link->is_identity)
{
@@ -2450,7 +2684,7 @@ convert_to_icc_base(fz_context *ctx, fz_colorspace *srcs, float *src_f, float *d
* be handled. Realize those can map from index->devn->pdf-cal->icc for
* example. */
static void
-icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
fz_colorspace *srcs = src->colorspace;
fz_colorspace *base_cs = get_base_icc_space(ctx, srcs);
@@ -2501,7 +2735,7 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp
}
fz_try(ctx)
- icc_conv_pixmap(ctx, dst, base, prf, default_cs, color_params);
+ icc_conv_pixmap(ctx, dst, base, prf, default_cs, color_params, copy_spots);
fz_always(ctx)
fz_drop_pixmap(ctx, base);
fz_catch(ctx)
@@ -2509,7 +2743,7 @@ icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorsp
}
static void
-std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
float srcv[FZ_MAX_COLORS];
float dstv[FZ_MAX_COLORS];
@@ -2710,8 +2944,10 @@ std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *
}
}
-static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, const fz_default_colorspaces *default_cs, const fz_color_params *color_params, int copy_spots)
{
+ assert(copy_spots && dst->s == 0 && src->s == 0);
+
if (!src->alpha)
fz_clear_pixmap_with_value(ctx, dst, 255);
else
@@ -3060,7 +3296,7 @@ void fz_find_color_converter(fz_context *ctx, fz_color_converter *cc, const fz_c
cc->convert = icc_conv_color;
else
cc->convert = icc_base_conv_color;
- cc->link = fz_get_icc_link(ctx, ss_base, is, ds, params, 2, 0, &cc->n);
+ cc->link = fz_get_icc_link(ctx, ds, 0, ss_base, 0, is, params, 2, 0, &cc->n);
}
else
cc->convert = std_conv_color;
diff --git a/source/fitz/draw-affine.c b/source/fitz/draw-affine.c
index b67e3e0d..6ece799f 100644
--- a/source/fitz/draw-affine.c
+++ b/source/fitz/draw-affine.c
@@ -3356,6 +3356,12 @@ fz_paint_image_with_color(fz_pixmap * restrict dst, const fz_irect * restrict sc
void
fz_paint_image(fz_pixmap * restrict dst, const fz_irect * restrict scissor, fz_pixmap * restrict shape, const fz_pixmap * restrict img, const fz_matrix * restrict ctm, int alpha, int lerp_allowed, int as_tiled)
{
+ // FIXME
+ if (dst->n - dst->alpha != img->n - img->alpha && (dst->n != 3 + dst->alpha || img->n != 1 + img->alpha))
+ {
+ fprintf(stderr, "Skipping image plot - FIXME\n");
+ return;
+ }
assert(dst->n - dst->alpha == img->n - img->alpha|| (dst->n == 3 + dst->alpha && img->n == 1 + img->alpha));
fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha, lerp_allowed, as_tiled);
}
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 3a5ae1db..cadd7d57 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -46,6 +46,7 @@ struct fz_draw_device_s
fz_rasterizer *rast;
fz_default_colorspaces *default_cs;
int flags;
+ int resolve_spots;
int top;
fz_scale_cache *cache_x;
fz_scale_cache *cache_y;
@@ -116,9 +117,8 @@ static void stack_change(fz_context *ctx, fz_draw_device *dev, char *s)
* in a color space that is our target color space or a transparency group
* color space decide if we should be using the proof color space at this time */
static fz_colorspace *
-fz_proof_cs(fz_context *ctx, fz_device *devp)
+fz_proof_cs(fz_context *ctx, fz_draw_device *dev)
{
- fz_draw_device *dev = (fz_draw_device*)devp;
fz_colorspace *prf = fz_default_output_intent(ctx, dev->default_cs);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
@@ -329,6 +329,68 @@ static inline fz_matrix concat(const fz_matrix *one, const fz_matrix *two)
}
static void
+resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, float alpha, const fz_color_params *color_params, unsigned char *colorbv, fz_pixmap *dest, fz_colorspace *prf)
+{
+ float colorfv[FZ_MAX_COLORS];
+ int i;
+ int n = dest->n - dest->alpha;
+ fz_colorspace *model = dest->colorspace;
+
+ if (colorspace == NULL && model != NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
+ if (n == 0)
+ i = 0;
+ else if (fz_colorspace_is_device_n(ctx, colorspace) && dest->seps)
+ {
+ fz_convert_separation_colors(ctx, color_params, dest->colorspace, dest->seps, colorfv, colorspace, color);
+ for (i = 0; i < n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ }
+ else
+ {
+ int c = n - dest->s;
+ fz_convert_color(ctx, color_params, prf, dest->colorspace, colorfv, colorspace, color);
+ for (i = 0; i < c; i++)
+ colorbv[i] = colorfv[i] * 255;
+ for (; i < n; i++)
+ colorbv[i] = 0;
+ }
+ colorbv[i] = alpha * 255;
+}
+
+static fz_draw_state *
+push_group_for_separations(fz_context *ctx, fz_draw_device *dev, fz_colorspace *prf, fz_default_colorspaces *default_cs)
+{
+ fz_separations *clone = fz_clone_separations_for_overprint(ctx, dev->stack[0].dest->seps);
+
+ /* Not needed */
+ if (clone == NULL)
+ {
+ dev->resolve_spots = 0;
+ return &dev->stack[0];
+ }
+
+ /* Make a new pixmap to render to. */
+ fz_try(ctx)
+ {
+ 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->top++;
+ }
+ fz_always(ctx)
+ fz_drop_separations(ctx, clone);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+
+ return &dev->stack[1];
+}
+
+static void
fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm,
fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
@@ -336,21 +398,15 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ fz_colorspace *prf = fz_proof_cs(ctx, dev);
float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i, n;
fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
-
- if (colorspace == NULL && model != NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
- if (color_params == NULL)
- color_params = fz_default_color_params(ctx);
+ if (dev->top == 0 && dev->resolve_spots)
+ state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
if (flatness < 0.001f)
flatness = 0.001f;
@@ -362,16 +418,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = alpha * 255;
+ resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
fz_convert_rasterizer(ctx, rast, even_odd, state->dest, colorbv);
if (state->shape)
@@ -395,25 +442,18 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ fz_colorspace *prf = fz_proof_cs(ctx, dev);
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_irect bbox;
- int i, n;
float aa_level = 2.0f/(fz_rasterizer_graphics_aa_level(rast)+2);
fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
float mlw = fz_rasterizer_graphics_min_line_width(rast);
-
- if (colorspace == NULL && model != NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
-
- if (color_params == NULL)
- color_params = fz_default_color_params(ctx);
+ if (dev->top == 0 && dev->resolve_spots)
+ state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
if (mlw > aa_level)
aa_level = mlw;
@@ -429,16 +469,7 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = alpha * 255;
+ resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
#ifdef DUMP_GROUP_BLENDS
dump_spaces(dev->top, "");
@@ -483,6 +514,9 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_irect local_scissor;
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);
+
if (flatness < 0.001f)
flatness = 0.001f;
@@ -551,6 +585,9 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_irect local_scissor;
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);
+
if (mlw > aa_level)
aa_level = mlw;
if (linewidth * expansion < aa_level)
@@ -692,13 +729,15 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_colorspace *model = state->dest->colorspace;
unsigned char colorbv[FZ_MAX_COLORS + 1];
unsigned char shapebv;
- float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i, n;
+ int i;
fz_colorspace *colorspace = NULL;
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ fz_colorspace *prf = fz_proof_cs(ctx, dev);
fz_rasterizer *rast = dev->rast;
+ if (dev->top == 0 && dev->resolve_spots)
+ state = push_group_for_separations(ctx, dev, prf, dev->default_cs);
+
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -711,16 +750,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = alpha * 255;
+ resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
shapebv = 255;
for (span = text->head; span; span = span->next)
@@ -789,37 +819,23 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i, n;
+ int i;
fz_colorspace *colorspace = NULL;
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ fz_colorspace *prf = fz_proof_cs(ctx, dev);
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);
+
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
- if (colorspace == NULL && model != NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
-
- if (color_params == NULL)
- color_params = fz_default_color_params(ctx);
-
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = alpha * 255;
+ resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
for (span = text->head; span; span = span->next)
{
@@ -885,6 +901,9 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_rect rect;
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_stack(ctx, dev);
STACK_PUSHED("clip text");
model = state->dest->colorspace;
@@ -1014,6 +1033,9 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
fz_rect rect;
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);
+
STACK_PUSHED("clip stroke text");
/* make the mask the exact size needed */
fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, stroke, &ctm, &rect));
@@ -1134,11 +1156,12 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
fz_rect bounds;
fz_irect bbox, scissor;
fz_pixmap *dest, *shape;
- float colorfv[FZ_MAX_COLORS];
unsigned char colorbv[FZ_MAX_COLORS + 1];
fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ 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);
fz_bound_shade(ctx, shade, &ctm, &bounds);
scissor = state->scissor;
@@ -1174,16 +1197,8 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
unsigned char *s;
int x, y, n, i;
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), shade->background);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = 255;
+
+ resolve_color(ctx, shade->background, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), alpha, color_params, colorbv, state->dest, prf);
n = dest->n;
for (y = scissor.y0; y < scissor.y1; y++)
@@ -1313,7 +1328,10 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_matrix inverse;
fz_irect src_area;
fz_colorspace *src_cs;
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ 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);
fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor);
@@ -1434,28 +1452,22 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix local_ctm = concat(in_ctm, &dev->transform);
unsigned char colorbv[FZ_MAX_COLORS + 1];
- float colorfv[FZ_MAX_COLORS];
fz_pixmap *scaled = NULL;
fz_pixmap *pixmap;
int dx, dy;
- int i, n;
fz_draw_state *state = &dev->stack[dev->top];
- fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
fz_matrix inverse;
fz_irect src_area;
fz_colorspace *colorspace = NULL;
- fz_colorspace *prf = fz_proof_cs(ctx, devp);
+ 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);
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
- if (color_params == NULL)
- color_params = fz_default_color_params(ctx);
-
- if (colorspace == NULL && model != NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
-
fz_pixmap_bbox(ctx, state->dest, &clip);
fz_intersect_irect(&clip, &state->scissor);
@@ -1525,16 +1537,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
}
}
- n = fz_colorspace_n(ctx, model);
- if (n > 0)
- {
- fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
- for (i = 0; i < n; i++)
- colorbv[i] = colorfv[i] * 255;
- }
- else
- i = 0;
- colorbv[i] = alpha * 255;
+ resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
@@ -1561,6 +1564,9 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_irect clip;
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);
+
STACK_PUSHED("clip image mask");
fz_pixmap_bbox(ctx, state->dest, &clip);
fz_intersect_irect(&clip, &state->scissor);
@@ -1722,6 +1728,9 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_rect trect = *rect;
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);
+
if (colorspace_in)
colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
@@ -1858,6 +1867,9 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, fz_co
fz_colorspace *model = state->dest->colorspace;
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);
+
if (cs != NULL)
model = fz_default_colorspace(ctx, dev->default_cs, cs);
@@ -2101,6 +2113,9 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
fz_colorspace *model = state->dest->colorspace;
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);
+
/* area, view, xstep, ystep are in pattern space */
/* ctm maps from pattern space to device space */
@@ -2364,6 +2379,37 @@ fz_draw_set_default_colorspaces(fz_context *ctx, fz_device *devp, fz_default_col
}
static void
+fz_draw_close_device(fz_context *ctx, fz_device *devp)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_colorspace *prf = fz_proof_cs(ctx, dev);
+
+ /* pop and free the stacks */
+ if (dev->top > dev->resolve_spots)
+ fz_warn(ctx, "items left on stack in draw device: %d", dev->top);
+
+ while(dev->top > dev->resolve_spots)
+ {
+ fz_draw_state *state = &dev->stack[--dev->top];
+ if (state[1].mask != state[0].mask)
+ fz_drop_pixmap(ctx, state[1].mask);
+ if (state[1].dest != state[0].dest)
+ fz_drop_pixmap(ctx, state[1].dest);
+ if (state[1].shape != state[0].shape)
+ fz_drop_pixmap(ctx, state[1].shape);
+ }
+
+ 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_drop_pixmap(ctx, state[1].dest);
+ assert(state[1].mask == NULL);
+ assert(state[1].shape == NULL);
+ }
+}
+
+static void
fz_draw_drop_device(fz_context *ctx, fz_device *devp)
{
fz_draw_device *dev = (fz_draw_device*)devp;
@@ -2373,7 +2419,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
/* pop and free the stacks */
if (dev->top > 0)
- fz_warn(ctx, "items left on stack in draw device: %d", dev->top+1);
+ fz_warn(ctx, "items left on stack in draw device: %d", dev->top);
while(dev->top-- > 0)
{
@@ -2385,6 +2431,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
if (state[1].shape != state[0].shape)
fz_drop_pixmap(ctx, state[1].shape);
}
+
/* We never free the dest/mask/shape at level 0, as:
* 1) dest is passed in and ownership remains with the caller.
* 2) shape and mask are NULL at level 0.
@@ -2397,11 +2444,12 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
}
fz_device *
-new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa)
+new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa, const fz_irect *clip)
{
fz_draw_device *dev = fz_new_derived_device(ctx, fz_draw_device);
dev->super.drop_device = fz_draw_drop_device;
+ dev->super.close_device = fz_draw_close_device;
dev->super.fill_path = fz_draw_fill_path;
dev->super.stroke_path = fz_draw_stroke_path;
@@ -2434,6 +2482,7 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
dev->transform = transform ? *transform : fz_identity;
dev->flags = 0;
+ dev->resolve_spots = 0;
dev->top = 0;
dev->stack = &dev->init_stack[0];
dev->stack_cap = STACK_SIZE;
@@ -2446,6 +2495,38 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
dev->stack[0].scissor.x1 = dest->x + dest->w;
dev->stack[0].scissor.y1 = dest->y + dest->h;
+ if (clip)
+ {
+ if (clip->x0 > dev->stack[0].scissor.x0)
+ dev->stack[0].scissor.x0 = clip->x0;
+ if (clip->x1 < dev->stack[0].scissor.x1)
+ dev->stack[0].scissor.x1 = clip->x1;
+ if (clip->y0 > dev->stack[0].scissor.y0)
+ dev->stack[0].scissor.y0 = clip->y0;
+ if (clip->y1 < dev->stack[0].scissor.y1)
+ dev->stack[0].scissor.y1 = clip->y1;
+ }
+
+ /* If we have no separations structure at all, then we want a
+ * simple composite rendering (with no overprint simulation).
+ * If we do have a separations structure, so: 1) Any
+ * 'disabled' separations are ignored. 2) Any 'composite'
+ * separations means we will need to do an overprint
+ * simulation.
+ *
+ * The supplied pixmaps 's' will match the number of
+ * 'spots' separations. If we have any 'composite'
+ * separations therefore, we'll need to make a new pixmap
+ * with a new (completely 'spots') separations structure,
+ * render to that, and then map down at the end.
+ *
+ * Unfortunately we can't produce this until we know what
+ * the default_colorspaces etc are, so set a flag for us
+ * to trigger on later.
+ */
+ if (dest->seps)
+ dev->resolve_spots = 1;
+
fz_try(ctx)
{
dev->rast = fz_new_rasterizer(ctx, aa);
@@ -2464,24 +2545,13 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co
fz_device *
fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
- return new_draw_device(ctx, transform, dest, NULL);
+ return new_draw_device(ctx, transform, dest, NULL, NULL);
}
fz_device *
fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip)
{
- fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, transform, dest);
-
- if (clip->x0 > dev->stack[0].scissor.x0)
- dev->stack[0].scissor.x0 = clip->x0;
- if (clip->x1 < dev->stack[0].scissor.x1)
- dev->stack[0].scissor.x1 = clip->x1;
- if (clip->y0 > dev->stack[0].scissor.y0)
- dev->stack[0].scissor.y0 = clip->y0;
- if (clip->y1 < dev->stack[0].scissor.y1)
- dev->stack[0].scissor.y1 = clip->y1;
-
- return (fz_device*)dev;
+ return new_draw_device(ctx, transform, dest, NULL, clip);
}
fz_device *
diff --git a/source/fitz/draw-paint.c b/source/fitz/draw-paint.c
index 8357d5a1..76f9638a 100644
--- a/source/fitz/draw-paint.c
+++ b/source/fitz/draw-paint.c
@@ -1906,6 +1906,11 @@ fz_paint_pixmap(fz_pixmap * restrict dst, const fz_pixmap * restrict src, int al
if (alpha == 0)
return;
+ if (dst->n - dst->alpha != src->n - src->alpha)
+ {
+ fprintf(stderr, "fz_paint_pixmap - FIXME\n");
+ return;
+ }
assert(dst->n - dst->alpha == src->n - src->alpha);
fz_pixmap_bbox_no_ctx(dst, &bbox);
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index bef5b6a5..c5112985 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -599,7 +599,7 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
fake_src.h = y;
fake_src.samples = srcp;
- pc(ctx, dest, &fake_src, NULL, default_cs, fz_default_color_params(ctx));
+ pc(ctx, dest, &fake_src, NULL, default_cs, fz_default_color_params(ctx), 0);
}
}
@@ -892,7 +892,7 @@ fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *ds, fz_colorsp
fz_try(ctx)
{
fz_pixmap_converter *pc = fz_lookup_pixmap_converter(ctx, ds, pix->colorspace);
- pc(ctx, cvt, pix, prf, default_cs, color_params);
+ pc(ctx, cvt, pix, prf, default_cs, color_params, 1);
}
fz_catch(ctx)
{
diff --git a/source/fitz/separation.c b/source/fitz/separation.c
index 45b60b92..0baf30b4 100644
--- a/source/fitz/separation.c
+++ b/source/fitz/separation.c
@@ -167,3 +167,337 @@ int fz_count_active_separations(fz_context *ctx, const fz_separations *sep)
c++;
return c;
}
+
+fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separations *sep)
+{
+ int i, j, n, c;
+ fz_separations *clone;
+
+ if (!sep)
+ return NULL;
+
+ n = sep->num_separations;
+ c = 0;
+ for (i = 0; i < n; i++)
+ {
+ fz_separation_behavior state = sep_state(sep, i);
+ if (state == FZ_SEPARATION_COMPOSITE)
+ c++;
+ }
+
+ /* If no composites, then we are fine to render direct. */
+ if (c == 0)
+ return NULL;
+
+ /* We need to clone us a separation structure, with all
+ * the composite separations marked as enabled. */
+ clone = fz_malloc_struct(ctx, fz_separations);
+
+ fz_try(ctx)
+ {
+ clone->refs = 1;
+ clone->controllable = 0;
+ for (i = 0; i < n; i++)
+ {
+ fz_separation_behavior beh = sep_state(sep, i);
+ if (beh == FZ_SEPARATION_DISABLED)
+ continue;
+ j = clone->num_separations++;
+ if (beh == FZ_SEPARATION_COMPOSITE)
+ 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];
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_separations(ctx, clone);
+ fz_rethrow(ctx);
+ }
+
+ return clone;
+}
+
+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_irect local_bbox;
+ fz_pixmap *dst;
+ fz_colorspace *oi = fz_default_output_intent(ctx, default_cs);
+
+ if (fz_colorspace_n(ctx, dcs) == fz_colorspace_n(ctx, oi))
+ dcs = oi;
+
+ if (bbox == NULL)
+ {
+ local_bbox.x0 = src->x;
+ local_bbox.y0 = src->y;
+ local_bbox.x1 = src->x + src->w;
+ local_bbox.y1 = src->y + src->h;
+ bbox = &local_bbox;
+ }
+
+ dst = fz_new_pixmap_with_bbox(ctx, dcs, bbox, dseps, src->alpha);
+ if (src->flags & FZ_PIXMAP_FLAG_INTERPOLATE)
+ dst->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
+ else
+ dst->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
+
+ return fz_copy_pixmap_area_converting_seps(ctx, dst, src, 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)
+{
+ int dw = dst->w;
+ int dh = dst->h;
+ fz_separations *sseps = src->seps;
+ fz_separations *dseps = dst->seps;
+ int sseps_n = sseps ? sseps->num_separations : 0;
+ int dseps_n = dseps ? dseps->num_separations : 0;
+ int sstride = src->stride;
+ int dstride = dst->stride;
+ int sn = src->n;
+ int dn = dst->n;
+ int sa = src->alpha;
+ int da = dst->alpha;
+ int ss = src->s;
+ int ds = dst->s;
+ int sc = sn - ss - sa;
+ int dc = dn - ds - da;
+ const unsigned char *sdata = src->samples + sstride * (dst->y - src->y) + (dst->x - src->x) * sn;
+ unsigned char *ddata = dst->samples;
+ signed char map[FZ_MAX_COLORS];
+ int x, y, i, j, k;
+ unsigned char mapped[FZ_MAX_COLORS];
+ int unmapped = sseps_n;
+
+ assert(da == sa);
+ assert(ss == fz_count_active_separations(ctx, sseps));
+ assert(ds == fz_count_active_separations(ctx, dseps));
+
+ dstride -= dn * dw;
+ sstride -= sn * dw;
+
+ /* Process colorants first */
+ if (dst->colorspace == src->colorspace)
+ {
+ /* Simple copy */
+ unsigned char *dd = ddata;
+ const unsigned char *sd = sdata;
+ for (y = dh; y > 0; y--)
+ {
+ for (x = dw; x > 0; x--)
+ {
+ for (i = 0; i < dn; i++)
+ dd[i] = sd[i];
+ dd += dn;
+ sd += sn;
+ }
+ dd += dstride;
+ sd += sstride;
+ }
+ }
+ else
+ {
+ fz_pixmap_converter *pc = fz_lookup_pixmap_converter(ctx, dst->colorspace, src->colorspace);
+
+ pc(ctx, dst, src, prf, default_cs, NULL, 0);
+ }
+
+ /* Make a map of what spots go where */
+ for (i = 0, k = 0; i < dseps_n; i++)
+ {
+ const char *name;
+
+ if (sep_state(dseps, i) >= FZ_SEPARATION_DISABLED)
+ continue;
+ name = dseps->name[i];
+ map[k] = -1;
+ mapped[k] = 0;
+ for (j = 0; j < sseps_n; j++)
+ {
+ if (sep_state(sseps, j) >= FZ_SEPARATION_DISABLED)
+ continue;
+ if (!strcmp(name, sseps->name[j]))
+ {
+ map[k] = j;
+ unmapped--;
+ mapped[k] = 1;
+ break;
+ }
+ }
+ k++;
+ }
+ if (sa)
+ map[k] = sseps_n;
+
+ /* Now we need to make d[i] = map[i] < 0 : 255 ? s[map[i]] */
+
+ {
+ unsigned char *dd = ddata + dc;
+ const unsigned char *sd = sdata + sc;
+ for (y = dh; y > 0; y--)
+ {
+ for (x = dw; x > 0; x--)
+ {
+ for (i = 0; i < ds; i++)
+ dd[i] = map[i] < 0 ? 255 : sd[map[i]];
+ dd += dn;
+ sd += sn;
+ }
+ dd += dstride;
+ sd += sstride;
+ }
+ }
+
+ /* If we've handled all the spots, we're done. */
+ if (unmapped == 0)
+ return dst;
+
+ /* 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;
+
+ 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;
+ }
+
+ {
+ unsigned char *dd = ddata;
+ const unsigned char *sd = sdata + sc;
+ for (y = dh; y > 0; y--)
+ {
+ for (x = dw; x > 0; x--)
+ {
+ 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 += dn;
+ sd += sn;
+ }
+ dd += dstride;
+ sd += sstride;
+ }
+ }
+ }
+
+ return dst;
+}
+
+void fz_convert_separation_colors(fz_context *ctx, const fz_color_params *color_params, const fz_colorspace *dst_cs, const fz_separations *dst_seps, float *dst_color, const fz_colorspace *src_cs, const float *src_color)
+{
+ int i, j, n, dc, ds, dn, pred;
+ float remainders[FZ_MAX_COLORS];
+ int remaining = 0;
+
+ assert(dst_cs && dst_seps && src_cs && dst_color && src_color);
+ assert(fz_colorspace_is_device_n(ctx, src_cs));
+
+ dc = fz_colorspace_n(ctx, dst_cs);
+ ds = dst_seps->num_separations;
+ dn = dc + ds;
+
+ i = 0;
+ if (!fz_colorspace_is_subtractive(ctx, dst_cs))
+ for (; i < dc; i++)
+ dst_color[i] = 1;
+ for (; i < dn; i++)
+ dst_color[i] = 0;
+
+ n = fz_colorspace_n(ctx, src_cs);
+ pred = 0;
+ for (i = 0; i < n; i++)
+ {
+ const char *name = fz_colorspace_colorant(ctx, src_cs, i);
+
+ if (i == 0 && !strcmp(name, "All"))
+ {
+ /* This is only supposed to happen in separation spaces, not DeviceN */
+ if (n != 1)
+ fz_warn(ctx, "All found in DeviceN space");
+ for (i = 0; i < dn; i++)
+ dst_color[i] = src_color[0];
+ break;
+ }
+ if (!strcmp(name, "None"))
+ continue;
+
+ /* The most common case is that the colorant we match is the
+ * one after the one we matched before, so optimise for that. */
+ for (j = pred; j < ds; j++)
+ {
+ const char *dname = dst_seps->name[j];
+ if (!strcmp(name, dname))
+ goto found_sep;
+ }
+ for (j = 0; j < pred; j++)
+ {
+ const char *dname = dst_seps->name[j];
+ if (!strcmp(name, dname))
+ goto found_sep;
+ }
+ for (j = 0; j < dc; j++)
+ {
+ const char *dname = fz_colorspace_colorant(ctx, dst_cs, j);
+ if (!strcmp(name, dname))
+ goto found_process;
+ }
+ if (0) {
+found_sep:
+ dst_color[j+dc] = src_color[i];
+ pred = j+1;
+ }
+ else if (0)
+ {
+found_process:
+ dst_color[j] += src_color[i];
+ }
+ else
+ {
+ if (remaining == 0)
+ {
+ memset(remainders, 0, sizeof(float) * n);
+ remaining = 1;
+ }
+ remainders[i] = src_color[i];
+ }
+ }
+
+ if (remaining)
+ {
+ /* There were some spots that didn't copy over */
+ float converted[FZ_MAX_COLORS];
+ fz_convert_color(ctx, color_params, NULL, dst_cs, converted, src_cs, remainders);
+
+ for (i = 0; i < dc; i++)
+ dst_color[i] += converted[i];
+ }
+}