summaryrefslogtreecommitdiff
path: root/source/fitz/separation.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/fitz/separation.c')
-rw-r--r--source/fitz/separation.c334
1 files changed, 334 insertions, 0 deletions
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];
+ }
+}