| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- // Copyright (C) 2004-2025 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- #include "mupdf/pdf.h"
- #include <string.h>
- static fz_colorspace *pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj, pdf_cycle_list *cycle_up);
- /* ICCBased */
- static fz_colorspace *
- load_icc_based(fz_context *ctx, pdf_obj *dict, int allow_alt, pdf_cycle_list *cycle_up)
- {
- int n = pdf_dict_get_int(ctx, dict, PDF_NAME(N));
- fz_colorspace *alt = NULL;
- fz_colorspace *cs = NULL;
- pdf_obj *obj;
- fz_var(alt);
- fz_var(cs);
- /* Look at Alternate to detect type (especially Lab). */
- if (allow_alt)
- {
- obj = pdf_dict_get(ctx, dict, PDF_NAME(Alternate));
- if (obj)
- {
- fz_try(ctx)
- alt = pdf_load_colorspace_imp(ctx, obj, cycle_up);
- fz_catch(ctx)
- {
- fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
- fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
- fz_report_error(ctx);
- fz_warn(ctx, "ignoring broken ICC Alternate colorspace");
- }
- }
- }
- #if FZ_ENABLE_ICC
- {
- fz_buffer *buf = NULL;
- fz_var(buf);
- fz_try(ctx)
- {
- buf = pdf_load_stream(ctx, dict);
- cs = fz_new_icc_colorspace(ctx, alt ? alt->type : FZ_COLORSPACE_NONE, 0, NULL, buf);
- if (cs->n > n)
- {
- fz_warn(ctx, "ICC colorspace N=%d does not match profile N=%d (ignoring profile)", n, cs->n);
- fz_drop_colorspace(ctx, cs);
- cs = NULL;
- }
- else if (cs->n < n)
- {
- fz_warn(ctx, "ICC colorspace N=%d does not match profile N=%d (using profile)", n, cs->n);
- }
- }
- fz_always(ctx)
- fz_drop_buffer(ctx, buf);
- fz_catch(ctx)
- {
- if (fz_caught(ctx) == FZ_ERROR_TRYLATER || fz_caught(ctx) == FZ_ERROR_SYSTEM)
- {
- fz_drop_colorspace(ctx, alt);
- fz_rethrow(ctx);
- }
- fz_report_error(ctx);
- fz_warn(ctx, "ignoring broken ICC profile");
- }
- }
- #endif
- if (!cs)
- cs = alt;
- else
- fz_drop_colorspace(ctx, alt);
- if (!cs)
- {
- if (n == 1) cs = fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (n == 3) cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- else if (n == 4) cs = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else fz_throw(ctx, FZ_ERROR_SYNTAX, "invalid ICC colorspace");
- }
- return cs;
- }
- static void
- devicen_eval(fz_context *ctx, void *tint, const float *sv, int sn, float *dv, int dn)
- {
- pdf_eval_function(ctx, tint, sv, sn, dv, dn);
- }
- static void
- devicen_drop(fz_context *ctx, void *tint)
- {
- pdf_drop_function(ctx, tint);
- }
- static fz_colorspace *
- load_devicen(fz_context *ctx, pdf_obj *array, int is_devn, pdf_cycle_list *cycle_up)
- {
- fz_colorspace *base = NULL;
- fz_colorspace *cs = 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);
- char name[100];
- int i, n;
- fz_var(cs);
- if (pdf_is_array(ctx, nameobj))
- {
- n = pdf_array_len(ctx, nameobj);
- if (n < 1)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "too few components in DeviceN colorspace");
- if (n > FZ_MAX_COLORS)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "too many components in DeviceN colorspace");
- }
- else
- {
- n = 1;
- }
- base = pdf_load_colorspace_imp(ctx, baseobj, cycle_up);
- fz_try(ctx)
- {
- if (is_devn)
- {
- fz_snprintf(name, sizeof name, "DeviceN(%d,%s", n, base->name);
- for (i = 0; i < n; i++) {
- fz_strlcat(name, ",", sizeof name);
- fz_strlcat(name, pdf_array_get_name(ctx, nameobj, i), sizeof name);
- }
- fz_strlcat(name, ")", sizeof name);
- }
- else
- {
- fz_snprintf(name, sizeof name, "Separation(%s,%s)", base->name, pdf_to_name(ctx, nameobj));
- }
- cs = fz_new_colorspace(ctx, FZ_COLORSPACE_SEPARATION, 0, n, name);
- cs->u.separation.eval = devicen_eval;
- cs->u.separation.drop = devicen_drop;
- cs->u.separation.base = fz_keep_colorspace(ctx, base);
- cs->u.separation.tint = pdf_load_function(ctx, tintobj, n, cs->u.separation.base->n);
- if (pdf_is_array(ctx, nameobj))
- for (i = 0; i < n; i++)
- fz_colorspace_name_colorant(ctx, cs, i, pdf_array_get_name(ctx, nameobj, i));
- else
- fz_colorspace_name_colorant(ctx, cs, 0, pdf_to_name(ctx, nameobj));
- }
- fz_always(ctx)
- {
- fz_drop_colorspace(ctx, base);
- }
- fz_catch(ctx)
- {
- fz_drop_colorspace(ctx, cs);
- fz_rethrow(ctx);
- }
- return cs;
- }
- int
- pdf_is_tint_colorspace(fz_context *ctx, fz_colorspace *cs)
- {
- return cs && cs->type == FZ_COLORSPACE_SEPARATION;
- }
- /* Indexed */
- static fz_colorspace *
- load_indexed(fz_context *ctx, pdf_obj *array, pdf_cycle_list *cycle_up)
- {
- pdf_obj *baseobj = pdf_array_get(ctx, array, 1);
- pdf_obj *highobj = pdf_array_get(ctx, array, 2);
- pdf_obj *lookupobj = pdf_array_get(ctx, array, 3);
- fz_colorspace *base = NULL;
- fz_colorspace *cs;
- size_t i, n;
- int high;
- unsigned char *lookup = NULL;
- fz_var(base);
- fz_var(lookup);
- fz_try(ctx)
- {
- base = pdf_load_colorspace_imp(ctx, baseobj, cycle_up);
- high = pdf_to_int(ctx, highobj);
- high = fz_clampi(high, 0, 255);
- n = (size_t)base->n * (high + 1);
- lookup = Memento_label(fz_malloc(ctx, n), "cs_lookup");
- if (pdf_is_string(ctx, lookupobj))
- {
- size_t sn = fz_minz(n, pdf_to_str_len(ctx, lookupobj));
- unsigned char *buf = (unsigned char *) pdf_to_str_buf(ctx, lookupobj);
- for (i = 0; i < sn; ++i)
- lookup[i] = buf[i];
- for (; i < n; ++i)
- lookup[i] = 0;
- }
- else if (pdf_is_indirect(ctx, lookupobj))
- {
- fz_stream *file = NULL;
- fz_var(file);
- fz_try(ctx)
- {
- file = pdf_open_stream(ctx, lookupobj);
- i = fz_read(ctx, file, lookup, n);
- if (i < n)
- memset(lookup+i, 0, n-i);
- }
- fz_always(ctx)
- {
- fz_drop_stream(ctx, file);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- else
- {
- fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot parse colorspace lookup table");
- }
- cs = fz_new_indexed_colorspace(ctx, base, high, lookup);
- }
- fz_always(ctx)
- fz_drop_colorspace(ctx, base);
- fz_catch(ctx)
- {
- fz_free(ctx, lookup);
- fz_rethrow(ctx);
- }
- return cs;
- }
- static void
- pdf_load_cal_common(fz_context *ctx, pdf_obj *dict, float *wp, float *bp, float *gamma)
- {
- pdf_obj *obj;
- int i;
- obj = pdf_dict_get(ctx, dict, PDF_NAME(WhitePoint));
- if (pdf_array_len(ctx, obj) != 3)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint must be a 3-element array");
- for (i = 0; i < 3; i++)
- {
- wp[i] = pdf_array_get_real(ctx, obj, i);
- if (wp[i] < 0)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint numbers must be positive");
- }
- if (wp[1] != 1)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint Yw must be 1.0");
- obj = pdf_dict_get(ctx, dict, PDF_NAME(BlackPoint));
- if (pdf_array_len(ctx, obj) == 3)
- {
- for (i = 0; i < 3; i++)
- {
- bp[i] = pdf_array_get_real(ctx, obj, i);
- if (bp[i] < 0)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "BlackPoint numbers must be positive");
- }
- }
- obj = pdf_dict_get(ctx, dict, PDF_NAME(Gamma));
- if (pdf_is_number(ctx, obj))
- {
- gamma[0] = pdf_to_real(ctx, obj);
- gamma[1] = gamma[2];
- if (gamma[0] <= 0)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "Gamma must be greater than zero");
- }
- else if (pdf_array_len(ctx, obj) == 3)
- {
- for (i = 0; i < 3; i++)
- {
- gamma[i] = pdf_array_get_real(ctx, obj, i);
- if (gamma[i] <= 0)
- fz_throw(ctx, FZ_ERROR_SYNTAX, "Gamma must be greater than zero");
- }
- }
- }
- static fz_colorspace *
- pdf_load_cal_gray(fz_context *ctx, pdf_obj *dict)
- {
- float wp[3];
- float bp[3] = { 0, 0, 0 };
- float gamma[3] = { 1, 1, 1 };
- if (dict == NULL)
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- fz_try(ctx)
- pdf_load_cal_common(ctx, dict, wp, bp, gamma);
- fz_catch(ctx)
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- return fz_new_cal_gray_colorspace(ctx, wp, bp, gamma[0]);
- }
- static fz_colorspace *
- pdf_load_cal_rgb(fz_context *ctx, pdf_obj *dict)
- {
- pdf_obj *obj;
- float matrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
- float wp[3];
- float bp[3] = { 0, 0, 0 };
- float gamma[3] = { 1, 1, 1 };
- int i;
- if (dict == NULL)
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- fz_try(ctx)
- {
- pdf_load_cal_common(ctx, dict, wp, bp, gamma);
- obj = pdf_dict_get(ctx, dict, PDF_NAME(Matrix));
- if (pdf_array_len(ctx, obj) == 9)
- {
- for (i = 0; i < 9; i++)
- matrix[i] = pdf_array_get_real(ctx, obj, i);
- }
- }
- fz_catch(ctx)
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- return fz_new_cal_rgb_colorspace(ctx, wp, bp, gamma, matrix);
- }
- /* Parse and create colorspace from PDF object */
- static fz_colorspace *
- pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj, pdf_cycle_list *cycle_up)
- {
- fz_colorspace *cs = NULL;
- pdf_cycle_list cycle;
- if (pdf_cycle(ctx, &cycle, cycle_up, obj))
- fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive colorspace");
- if (pdf_is_name(ctx, obj))
- {
- if (pdf_name_eq(ctx, obj, PDF_NAME(Pattern)))
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(G)))
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(RGB)))
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(CMYK)))
- return fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(DeviceGray)))
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(DeviceRGB)))
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- else if (pdf_name_eq(ctx, obj, PDF_NAME(DeviceCMYK)))
- return fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else
- fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown colorspace: %s", pdf_to_name(ctx, obj));
- }
- else if (pdf_is_array(ctx, obj))
- {
- pdf_obj *name = pdf_array_get(ctx, obj, 0);
- if (pdf_is_name(ctx, name))
- {
- /* load base colorspace instead */
- if (pdf_name_eq(ctx, name, PDF_NAME(G)))
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(RGB)))
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(CMYK)))
- return fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(DeviceGray)))
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(DeviceRGB)))
- return fz_keep_colorspace(ctx, fz_device_rgb(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(DeviceCMYK)))
- return fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(CalCMYK)))
- return fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
- else if (pdf_name_eq(ctx, name, PDF_NAME(Lab)))
- return fz_keep_colorspace(ctx, fz_device_lab(ctx));
- else
- {
- if ((cs = pdf_find_item(ctx, fz_drop_colorspace_imp, obj)) != NULL)
- return cs;
- if (pdf_name_eq(ctx, name, PDF_NAME(ICCBased)))
- cs = load_icc_based(ctx, pdf_array_get(ctx, obj, 1), 1, &cycle);
- else if (pdf_name_eq(ctx, name, PDF_NAME(CalGray)))
- cs = pdf_load_cal_gray(ctx, pdf_array_get(ctx, obj, 1));
- else if (pdf_name_eq(ctx, name, PDF_NAME(CalRGB)))
- cs = pdf_load_cal_rgb(ctx, pdf_array_get(ctx, obj, 1));
- else if (pdf_name_eq(ctx, name, PDF_NAME(Indexed)))
- cs = load_indexed(ctx, obj, &cycle);
- else if (pdf_name_eq(ctx, name, PDF_NAME(I)))
- cs = load_indexed(ctx, obj, &cycle);
- else if (pdf_name_eq(ctx, name, PDF_NAME(Separation)))
- cs = load_devicen(ctx, obj, 0, &cycle);
- else if (pdf_name_eq(ctx, name, PDF_NAME(DeviceN)))
- cs = load_devicen(ctx, obj, 1, &cycle);
- else if (pdf_name_eq(ctx, name, PDF_NAME(Pattern)))
- {
- pdf_obj *pobj = pdf_array_get(ctx, obj, 1);
- if (!pobj)
- return fz_keep_colorspace(ctx, fz_device_gray(ctx));
- cs = pdf_load_colorspace_imp(ctx, pobj, &cycle);
- }
- else
- fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown colorspace %s", pdf_to_name(ctx, name));
- pdf_store_item(ctx, obj, cs, 1000);
- return cs;
- }
- }
- }
- /* We have seen files where /DefaultRGB is specified as 1 0 R,
- * and 1 0 obj << /Length 3144 /Alternate /DeviceRGB /N 3 >>
- * stream ...iccprofile... endstream endobj.
- * This *should* be [ /ICCBased 1 0 R ], but Acrobat seems to
- * handle it, so do our best. */
- else if (pdf_is_dict(ctx, obj))
- {
- if ((cs = pdf_find_item(ctx, fz_drop_colorspace_imp, obj)) != NULL)
- return cs;
- cs = load_icc_based(ctx, obj, 1, &cycle);
- pdf_store_item(ctx, obj, cs, 1000);
- return cs;
- }
- fz_throw(ctx, FZ_ERROR_SYNTAX, "could not parse color space (%d 0 R)", pdf_to_num(ctx, obj));
- }
- fz_colorspace *
- pdf_load_colorspace(fz_context *ctx, pdf_obj *obj)
- {
- return pdf_load_colorspace_imp(ctx, obj, NULL);
- }
- #if FZ_ENABLE_ICC
- static fz_colorspace *
- pdf_load_output_intent(fz_context *ctx, pdf_document *doc)
- {
- pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root));
- pdf_obj *intents = pdf_dict_get(ctx, root, PDF_NAME(OutputIntents));
- pdf_obj *intent_dict;
- pdf_obj *dest_profile;
- fz_colorspace *cs = NULL;
- /* An array of intents */
- if (!intents)
- return NULL;
- /* For now, always just use the first intent. I have never even seen a file
- * with multiple intents but it could happen */
- intent_dict = pdf_array_get(ctx, intents, 0);
- if (!intent_dict)
- return NULL;
- dest_profile = pdf_dict_get(ctx, intent_dict, PDF_NAME(DestOutputProfile));
- if (!dest_profile)
- return NULL;
- fz_var(cs);
- fz_try(ctx)
- cs = load_icc_based(ctx, dest_profile, 0, NULL);
- fz_catch(ctx)
- {
- fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
- fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
- fz_report_error(ctx);
- fz_warn(ctx, "Attempt to read Output Intent failed");
- }
- return cs;
- }
- fz_colorspace *
- pdf_document_output_intent(fz_context *ctx, pdf_document *doc)
- {
- if (!doc->oi)
- doc->oi = pdf_load_output_intent(ctx, doc);
- return doc->oi;
- }
- #else
- fz_colorspace *
- pdf_document_output_intent(fz_context *ctx, pdf_document *doc)
- {
- return NULL;
- }
- #endif
- static pdf_obj *
- pdf_add_indexed_colorspace(fz_context *ctx, pdf_document *doc, fz_colorspace *cs)
- {
- fz_colorspace *basecs;
- unsigned char *lookup = NULL;
- int high = 0;
- int basen;
- pdf_obj *obj;
- basecs = cs->u.indexed.base;
- high = cs->u.indexed.high;
- lookup = cs->u.indexed.lookup;
- basen = basecs->n;
- if (fz_colorspace_is_indexed(ctx, basecs))
- fz_throw(ctx, FZ_ERROR_FORMAT, "indexed colorspaces must not have an indexed colorspace as base");
- obj = pdf_add_new_array(ctx, doc, 4);
- fz_try(ctx)
- {
- pdf_array_push(ctx, obj, PDF_NAME(Indexed));
- pdf_array_push(ctx, obj, pdf_add_colorspace(ctx, doc, basecs));
- pdf_array_push_int(ctx, obj, high);
- pdf_array_push_string(ctx, obj, (char *) lookup, (size_t)basen * (high + 1));
- }
- fz_catch(ctx)
- {
- pdf_drop_obj(ctx, obj);
- fz_rethrow(ctx);
- }
- return obj;
- }
- static pdf_obj *
- pdf_add_icc_colorspace(fz_context *ctx, pdf_document *doc, fz_colorspace *cs)
- {
- #if FZ_ENABLE_ICC
- pdf_obj *obj = NULL;
- pdf_obj *stm = NULL;
- pdf_obj *base;
- pdf_obj *ref;
- pdf_colorspace_resource_key key;
- fz_var(obj);
- fz_var(stm);
- obj = pdf_find_colorspace_resource(ctx, doc, cs, &key);
- if (obj)
- return obj;
- switch (fz_colorspace_type(ctx, cs))
- {
- default:
- fz_throw(ctx, FZ_ERROR_UNSUPPORTED, "only Gray, RGB, and CMYK ICC colorspaces supported");
- case FZ_COLORSPACE_GRAY:
- base = PDF_NAME(DeviceGray);
- break;
- case FZ_COLORSPACE_RGB:
- base = PDF_NAME(DeviceRGB);
- break;
- case FZ_COLORSPACE_CMYK:
- base = PDF_NAME(DeviceCMYK);
- break;
- case FZ_COLORSPACE_LAB:
- base = PDF_NAME(Lab);
- break;
- }
- fz_try(ctx)
- {
- stm = pdf_add_stream(ctx, doc, cs->u.icc.buffer, NULL, 0);
- pdf_dict_put_int(ctx, stm, PDF_NAME(N), cs->n);
- pdf_dict_put(ctx, stm, PDF_NAME(Alternate), base);
- obj = pdf_add_new_array(ctx, doc, 2);
- pdf_array_push(ctx, obj, PDF_NAME(ICCBased));
- pdf_array_push(ctx, obj, stm);
- ref = pdf_insert_colorspace_resource(ctx, doc, &key, obj);
- }
- fz_always(ctx)
- {
- pdf_drop_obj(ctx, obj);
- pdf_drop_obj(ctx, stm);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- return ref;
- #else
- fz_throw(ctx, FZ_ERROR_UNSUPPORTED, "ICC support disabled");
- #endif
- }
- pdf_obj *
- pdf_add_colorspace(fz_context *ctx, pdf_document *doc, fz_colorspace *cs)
- {
- if (fz_colorspace_is_indexed(ctx, cs))
- return pdf_add_indexed_colorspace(ctx, doc, cs);
- if (fz_colorspace_is_icc(ctx, cs))
- return pdf_add_icc_colorspace(ctx, doc, cs);
- switch (fz_colorspace_type(ctx, cs))
- {
- case FZ_COLORSPACE_NONE:
- case FZ_COLORSPACE_GRAY:
- return PDF_NAME(DeviceGray);
- case FZ_COLORSPACE_RGB:
- return PDF_NAME(DeviceRGB);
- case FZ_COLORSPACE_CMYK:
- return PDF_NAME(DeviceCMYK);
- case FZ_COLORSPACE_LAB:
- return PDF_NAME(Lab);
- default:
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "only Gray, RGB, and CMYK colorspaces supported");
- break;
- }
- }
|