summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/colorspace.h14
-rw-r--r--source/fitz/colorspace-imp.h6
-rw-r--r--source/fitz/colorspace.c52
-rw-r--r--source/pdf/pdf-colorspace.c74
4 files changed, 102 insertions, 44 deletions
diff --git a/include/mupdf/fitz/colorspace.h b/include/mupdf/fitz/colorspace.h
index 6bd24faa..57404fa9 100644
--- a/include/mupdf/fitz/colorspace.h
+++ b/include/mupdf/fitz/colorspace.h
@@ -61,7 +61,14 @@ typedef struct fz_default_colorspaces_s fz_default_colorspaces;
True for CMYK, Separation and DeviceN colorspaces.
*/
-int fz_colorspace_is_subtractive(fz_context *ctx, fz_colorspace *pix);
+int fz_colorspace_is_subtractive(fz_context *ctx, const fz_colorspace *cs);
+
+/*
+ fz_colorspace_is_device_n: Return true if a colorspace is separation or devicen.
+
+ True for Separation and DeviceN colorspaces.
+*/
+int fz_colorspace_is_device_n(fz_context *ctx, const fz_colorspace *cs);
/*
fz_device_gray: Get colorspace representing device specific gray.
@@ -101,7 +108,9 @@ typedef fz_colorspace *(fz_colorspace_base_fn)(const fz_colorspace *cs);
typedef void (fz_colorspace_clamp_fn)(const fz_colorspace *cs, const float *src, float *dst);
-fz_colorspace *fz_new_colorspace(fz_context *ctx, const char *name, int n, int is_subtractive, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size);
+fz_colorspace *fz_new_colorspace(fz_context *ctx, const char *name, int n, int is_subtractive, int is_device_n, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size);
+void fz_colorspace_name_colorant(fz_context *ctx, fz_colorspace *cs, int n, const char *name);
+const char *fz_colorspace_colorant(fz_context *ctx, const fz_colorspace *cs, int n);
fz_colorspace *fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup);
fz_colorspace *fz_keep_colorspace(fz_context *ctx, fz_colorspace *colorspace);
void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace);
@@ -113,6 +122,7 @@ int fz_colorspace_is_lab_icc(fz_context *ctx, const fz_colorspace *cs);
int fz_colorspace_is_cal(fz_context *ctx, const fz_colorspace *cs);
int fz_colorspace_is_indexed(fz_context *ctx, const fz_colorspace *cs);
int fz_colorspace_n(fz_context *ctx, const fz_colorspace *cs);
+int fz_colorspace_devicen_n(fz_context *ctx, const fz_colorspace *cs);
const char *fz_colorspace_name(fz_context *ctx, const fz_colorspace *cs);
void fz_clamp_color(fz_context *ctx, const fz_colorspace *cs, const float *in, float *out);
void fz_convert_color(fz_context *ctx, const fz_color_params *params, fz_colorspace *intcs, fz_colorspace *dscs, float *dstv, fz_colorspace *srcs, const float *srcv);
diff --git a/source/fitz/colorspace-imp.h b/source/fitz/colorspace-imp.h
index fb10bf80..b2d266da 100644
--- a/source/fitz/colorspace-imp.h
+++ b/source/fitz/colorspace-imp.h
@@ -27,14 +27,16 @@ struct fz_colorspace_s
fz_storable storable;
size_t size;
char name[24];
- int n;
- int is_subtractive;
+ unsigned char n;
+ unsigned char is_subtractive;
+ unsigned char is_device_n;
fz_colorspace_convert_fn *to_ccs;
fz_colorspace_convert_fn *from_ccs;
fz_colorspace_clamp_fn *clamp;
fz_colorspace_base_fn *get_base;
fz_colorspace_destruct_fn *free_data;
void *data;
+ char *colorant[FZ_MAX_COLORS];
};
struct fz_iccprofile_s
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 2d66e8a2..d3a63fb6 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -138,9 +138,12 @@ void
fz_drop_colorspace_imp(fz_context *ctx, fz_storable *cs_)
{
fz_colorspace *cs = (fz_colorspace *)cs_;
+ int i;
if (cs->free_data && cs->data)
cs->free_data(ctx, cs);
+ for (i = 0; i < FZ_MAX_COLORS; i++)
+ fz_free(ctx, cs->colorant[i]);
fz_free(ctx, cs);
}
@@ -154,7 +157,7 @@ clamp_default(const fz_colorspace *cs, const float *src, float *dst)
}
fz_colorspace *
-fz_new_colorspace(fz_context *ctx, const char *name, int n, int is_subtractive, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size)
+fz_new_colorspace(fz_context *ctx, const char *name, int n, int is_subtractive, int is_device_n, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size)
{
fz_colorspace *cs = fz_malloc_struct(ctx, fz_colorspace);
FZ_INIT_STORABLE(cs, 1, fz_drop_colorspace_imp);
@@ -162,6 +165,7 @@ fz_new_colorspace(fz_context *ctx, const char *name, int n, int is_subtractive,
fz_strlcpy(cs->name, name ? name : "UNKNOWN", sizeof cs->name);
cs->n = n;
cs->is_subtractive = is_subtractive;
+ cs->is_device_n = is_device_n;
cs->to_ccs = to_ccs;
cs->from_ccs = from_ccs;
cs->get_base = base;
@@ -659,16 +663,16 @@ static int fz_colorspace_is_lab(fz_context *ctx, const fz_colorspace *cs)
}
int
-fz_colorspace_is_subtractive(fz_context *ctx, fz_colorspace *cs)
+fz_colorspace_is_subtractive(fz_context *ctx, const fz_colorspace *cs)
{
return (cs && cs->is_subtractive);
}
-static fz_colorspace k_default_gray = { {-1, fz_drop_colorspace_imp}, 0, "DeviceGray", 1, 0, gray_to_rgb, rgb_to_gray, clamp_default, NULL, NULL, NULL };
-static fz_colorspace k_default_rgb = { {-1, fz_drop_colorspace_imp}, 0, "DeviceRGB", 3, 0, rgb_to_rgb, rgb_to_rgb, clamp_default, NULL, NULL, NULL };
-static fz_colorspace k_default_bgr = { {-1, fz_drop_colorspace_imp}, 0, "DeviceBGR", 3, 0, bgr_to_rgb, rgb_to_bgr, clamp_default, NULL, NULL, NULL };
-static fz_colorspace k_default_cmyk = { {-1, fz_drop_colorspace_imp}, 0, "DeviceCMYK", 4, 1, cmyk_to_rgb, rgb_to_cmyk, clamp_default, NULL, NULL, NULL };
-static fz_colorspace k_default_lab = { {-1, fz_drop_colorspace_imp}, 0, "Lab", 3, 0, lab_to_rgb, rgb_to_lab, clamp_lab, NULL, NULL, NULL};
+static fz_colorspace k_default_gray = { {-1, fz_drop_colorspace_imp}, 0, "DeviceGray", 1, 0, 0, gray_to_rgb, rgb_to_gray, clamp_default, NULL, NULL, NULL, { "Gray" } };
+static fz_colorspace k_default_rgb = { {-1, fz_drop_colorspace_imp}, 0, "DeviceRGB", 3, 0, 0, rgb_to_rgb, rgb_to_rgb, clamp_default, NULL, NULL, NULL, { "Red", "Green", "Blue" } };
+static fz_colorspace k_default_bgr = { {-1, fz_drop_colorspace_imp}, 0, "DeviceBGR", 3, 0, 0, bgr_to_rgb, rgb_to_bgr, clamp_default, NULL, NULL, NULL, { "Blue", "Green", "Red" } };
+static fz_colorspace k_default_cmyk = { {-1, fz_drop_colorspace_imp}, 0, "DeviceCMYK", 4, 1, 0, cmyk_to_rgb, rgb_to_cmyk, clamp_default, NULL, NULL, NULL, { "Cyan", "Magenta", "Yellow", "Black" } };
+static fz_colorspace k_default_lab = { {-1, fz_drop_colorspace_imp}, 0, "Lab", 3, 0, 0, lab_to_rgb, rgb_to_lab, clamp_lab, NULL, NULL, NULL, { "L*", "a*", "b*" } };
static fz_color_params k_default_color_params = { FZ_RI_RELATIVE_COLORIMETRIC, 1, 0, 0 };
static fz_colorspace *default_gray = &k_default_gray;
@@ -3156,7 +3160,7 @@ fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsign
idx->high = high;
fz_try(ctx)
- cs = fz_new_colorspace(ctx, "Indexed", 1, 0, fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? indexed_to_alt : indexed_to_rgb, NULL, base_indexed, clamp_indexed, free_indexed, idx, sizeof(*idx) + (base->n * (idx->high + 1)) + base->size);
+ cs = fz_new_colorspace(ctx, "Indexed", 1, 0, 0, fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? indexed_to_alt : indexed_to_rgb, NULL, base_indexed, clamp_indexed, free_indexed, idx, sizeof(*idx) + (base->n * (idx->high + 1)) + base->size);
fz_catch(ctx)
{
fz_free(ctx, idx);
@@ -3394,7 +3398,7 @@ fz_new_icc_colorspace(fz_context *ctx, const char *name, int num, fz_buffer *buf
else
{
fz_md5_icc(ctx, profile);
- cs = fz_new_colorspace(ctx, name, num, 0, NULL, NULL, NULL, is_lab ? clamp_lab_icc : clamp_default_icc, free_icc, profile, sizeof(profile));
+ cs = fz_new_colorspace(ctx, name, num, 0, 0, NULL, NULL, NULL, is_lab ? clamp_lab_icc : clamp_default_icc, free_icc, profile, sizeof(profile));
/* This is a bit of a handwave, but should be safe for our cases */
if (profile->num_devcomp == 4)
@@ -3460,7 +3464,7 @@ fz_new_cal_colorspace(fz_context *ctx, const char *name, float *wp, float *bp, f
cal_data->n = num;
fz_try(ctx)
- cs = fz_new_colorspace(ctx, "pdf-cal", num, 0, NULL, NULL, NULL, NULL, free_cal, cal_data, sizeof(cal_data));
+ cs = fz_new_colorspace(ctx, "pdf-cal", num, 0, 0, NULL, NULL, NULL, NULL, free_cal, cal_data, sizeof(cal_data));
fz_catch(ctx)
{
fz_free(ctx, cal_data);
@@ -3598,3 +3602,31 @@ fz_drop_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs)
fz_free(ctx, default_cs);
}
}
+
+void fz_colorspace_name_colorant(fz_context *ctx, fz_colorspace *cs, int i, const char *name)
+{
+ if (!cs)
+ return;
+
+ if (i < 0 || i >= cs->n)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Attempt to name out of range colorant");
+
+ fz_free(ctx, cs->colorant[i]);
+ cs->colorant[i] = NULL;
+ if (name)
+ cs->colorant[i] = fz_strdup(ctx, name);
+
+}
+
+const char *fz_colorspace_colorant(fz_context *ctx, const fz_colorspace *cs, int i)
+{
+ if (!cs || i < 0 || i >= cs->n)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Colorant out of range");
+
+ return cs->colorant[i];
+}
+
+int fz_colorspace_is_device_n(fz_context *ctx, const fz_colorspace *cs)
+{
+ return (cs && cs->is_device_n);
+}
diff --git a/source/pdf/pdf-colorspace.c b/source/pdf/pdf-colorspace.c
index 905d2a85..31728a69 100644
--- a/source/pdf/pdf-colorspace.c
+++ b/source/pdf/pdf-colorspace.c
@@ -124,65 +124,71 @@ load_icc_based(fz_context *ctx, pdf_obj *dict, int alt)
return cs;
}
-struct separation
+struct devicen
{
fz_colorspace *base;
pdf_function *tint;
};
static void
-separation_to_alt(fz_context *ctx, fz_colorspace *cs, const float *color, float *alt)
+devicen_to_alt(fz_context *ctx, fz_colorspace *cs, const float *color, float *alt)
{
- struct separation *sep = cs->data;
- pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
+ struct devicen *devn = cs->data;
+ pdf_eval_function(ctx, devn->tint, color, cs->n, alt, devn->base->n);
}
static void
-separation_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
+devicen_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
{
- struct separation *sep = cs->data;
+ struct devicen *devn = cs->data;
float alt[FZ_MAX_COLORS];
- pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
- fz_convert_color(ctx, fz_default_color_params(ctx), NULL, fz_device_rgb(ctx), rgb, sep->base, alt);
+ pdf_eval_function(ctx, devn->tint, color, cs->n, alt, devn->base->n);
+ fz_convert_color(ctx, fz_default_color_params(ctx), NULL, fz_device_rgb(ctx), rgb, devn->base, alt);
}
static void
-free_separation(fz_context *ctx, fz_colorspace *cs)
+free_devicen(fz_context *ctx, fz_colorspace *cs)
{
- struct separation *sep = cs->data;
- fz_drop_colorspace(ctx, sep->base);
- pdf_drop_function(ctx, sep->tint);
- fz_free(ctx, sep);
+ struct devicen *devn = cs->data;
+ fz_drop_colorspace(ctx, devn->base);
+ pdf_drop_function(ctx, devn->tint);
+ fz_free(ctx, devn);
}
static fz_colorspace *
-base_separation(const fz_colorspace *cs)
+base_devicen(const fz_colorspace *cs)
{
- struct separation *sep = cs->data;
+ struct devicen *devn = cs->data;
- return sep->base;
+ return devn->base;
}
static fz_colorspace *
-load_separation(fz_context *ctx, pdf_obj *array)
+load_devicen(fz_context *ctx, pdf_obj *array)
{
fz_colorspace *cs;
- struct separation *sep = NULL;
+ struct devicen *devn = NULL;
pdf_obj *nameobj = pdf_array_get(ctx, array, 1);
pdf_obj *baseobj = pdf_array_get(ctx, array, 2);
pdf_obj *tintobj = pdf_array_get(ctx, array, 3);
fz_colorspace *base;
pdf_function *tint = NULL;
- int n;
+ int i, n;
+ char *colorspace_name = "DeviceN";
fz_var(tint);
- fz_var(sep);
+ fz_var(devn);
if (pdf_is_array(ctx, nameobj))
n = pdf_array_len(ctx, nameobj);
else
+ {
n = 1;
+ colorspace_name = "Separation";
+ }
+ if (n < 1)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "insufficient components in colorspace");
if (n > FZ_MAX_COLORS)
fz_throw(ctx, FZ_ERROR_SYNTAX, "too many components in colorspace");
@@ -194,20 +200,28 @@ load_separation(fz_context *ctx, pdf_obj *array)
/* RJW: fz_drop_colorspace(ctx, base);
* "cannot load tint function (%d 0 R)", pdf_to_num(ctx, tintobj) */
- sep = fz_malloc_struct(ctx, struct separation);
- sep->base = fz_keep_colorspace(ctx, base); /* We drop it during the sep free... */
- sep->tint = tint;
+ devn = fz_malloc_struct(ctx, struct devicen);
+ devn->base = fz_keep_colorspace(ctx, base); /* We drop it during the devn free... */
+ devn->tint = tint;
+
+ cs = fz_new_colorspace(ctx, colorspace_name, n, 1, 1,
+ fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? devicen_to_alt : devicen_to_rgb, NULL, base_devicen, NULL, free_devicen, devn,
+ sizeof(struct devicen) + (base ? base->size : 0) + pdf_function_size(ctx, tint));
+
+ devn = NULL;
+ if (pdf_is_array(ctx, nameobj))
+ for (i = 0; i < n; i++)
+ fz_colorspace_name_colorant(ctx, cs, i, pdf_to_name(ctx, pdf_array_get(ctx, nameobj, i)));
+ else
+ fz_colorspace_name_colorant(ctx, cs, 0, pdf_to_name(ctx, nameobj));
- cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", n, 1,
- fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? separation_to_alt : separation_to_rgb, NULL, base_separation, NULL, free_separation, sep,
- sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(ctx, tint));
}
fz_always(ctx)
fz_drop_colorspace(ctx, base);
fz_catch(ctx)
{
pdf_drop_function(ctx, tint);
- fz_free(ctx, sep);
+ fz_free(ctx, devn);
fz_rethrow(ctx);
}
@@ -217,7 +231,7 @@ load_separation(fz_context *ctx, pdf_obj *array)
int
pdf_is_tint_colorspace(fz_context *ctx, fz_colorspace *cs)
{
- return cs && cs->free_data == free_separation;
+ return cs && cs->free_data == free_devicen;
}
/* Indexed */
@@ -470,10 +484,10 @@ pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj)
cs = load_indexed(ctx, obj);
else if (pdf_name_eq(ctx, name, PDF_NAME_Separation))
- cs = load_separation(ctx, obj);
+ cs = load_devicen(ctx, obj);
else if (pdf_name_eq(ctx, name, PDF_NAME_DeviceN))
- cs = load_separation(ctx, obj);
+ cs = load_devicen(ctx, obj);
else if (pdf_name_eq(ctx, name, PDF_NAME_Pattern))
{
pdf_obj *pobj;