diff options
-rw-r--r-- | gs/Resource/Init/pdf_draw.ps | 2 | ||||
-rw-r--r-- | gs/base/gdevp14.c | 388 | ||||
-rw-r--r-- | gs/base/gdevp14.h | 3 | ||||
-rw-r--r-- | gs/base/gsccolor.h | 1 | ||||
-rw-r--r-- | gs/base/gscms.h | 40 | ||||
-rw-r--r-- | gs/base/gsicc_profilecache.c | 228 | ||||
-rw-r--r-- | gs/base/gsicc_profilecache.h | 36 | ||||
-rw-r--r-- | gs/base/gsicccache.c | 46 | ||||
-rw-r--r-- | gs/base/gsicccache.h | 5 | ||||
-rw-r--r-- | gs/base/gsistate.c | 20 | ||||
-rw-r--r-- | gs/base/gstparam.h | 4 | ||||
-rw-r--r-- | gs/base/gstrans.c | 206 | ||||
-rw-r--r-- | gs/base/gstrans.h | 2 | ||||
-rw-r--r-- | gs/base/gxistate.h | 5 | ||||
-rw-r--r-- | gs/base/lib.mak | 13 |
15 files changed, 818 insertions, 181 deletions
diff --git a/gs/Resource/Init/pdf_draw.ps b/gs/Resource/Init/pdf_draw.ps index 2a29a2947..a8802a236 100644 --- a/gs/Resource/Init/pdf_draw.ps +++ b/gs/Resource/Init/pdf_draw.ps @@ -478,7 +478,7 @@ def /.beginformgroup { % groupdict bbox .beginformgroup - exch mark exch % bbox mark groupdict - dup /CS knownoget { resolvecolorspace setgcolorspace } if + dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} if dup /I knownoget { /Isolated exch 3 2 roll } if dup /K knownoget { /Knockout exch 3 2 roll } if pop .dicttomark diff --git a/gs/base/gdevp14.c b/gs/base/gdevp14.c index acfb6021c..dec524f42 100644 --- a/gs/base/gdevp14.c +++ b/gs/base/gdevp14.c @@ -50,6 +50,7 @@ #include "gzcpath.h" #include "gxpaint.h" #include "gsiccmanage.h" +#include "gsicccache.h" /* Visual trace options : set one to 1. */ #define VD_PAINT_MASK 0 @@ -90,9 +91,9 @@ gs_private_st_ptrs2(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx", pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs, stack, maskbuf); -gs_private_st_ptrs1(st_pdf14_clr, pdf14_parent_color_t, "pdf14_clr", +gs_private_st_ptrs2(st_pdf14_clr, pdf14_parent_color_t, "pdf14_clr", pdf14_clr_enum_ptrs, pdf14_clr_reloc_ptrs, - previous); + previous, icc_profile); /* ------ The device descriptors ------ */ @@ -244,7 +245,7 @@ static int pdf14_custom_put_image(gx_device * dev, gs_imager_state * pis, /* Used to alter device color mapping procs based upon group or softmask color space */ static int pdf14_update_device_color_procs(gx_device *dev, gs_transparency_color_t group_color, - gs_imager_state *pis); + gs_imager_state *pis, cmm_profile_t *iccprofile); /* Used to alter device color mapping procs based upon group or softmask color space */ @@ -452,6 +453,7 @@ pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle, /* yet another plane */ pdf14_buf *result; + pdf14_parent_color_t *new_parent_color; int rowstride = (rect->q.x - rect->p.x + 3) & -4; int height = (rect->q.y - rect->p.y); int n_planes = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0); @@ -479,9 +481,17 @@ pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle, result->maskbuf = NULL; result->idle = idle; result->mask_id = 0; - result->parent_color_info_procs.get_cmap_procs = NULL; - result->parent_color_info_procs.parent_color_mapping_procs = NULL; - result->parent_color_info_procs.parent_color_comp_index = NULL; + + new_parent_color = gs_alloc_struct(memory, pdf14_parent_color_t, &st_pdf14_clr, + "pdf14_buf_new"); + + result->parent_color_info_procs = new_parent_color; + + result->parent_color_info_procs->get_cmap_procs = NULL; + result->parent_color_info_procs->parent_color_mapping_procs = NULL; + result->parent_color_info_procs->parent_color_comp_index = NULL; + result->parent_color_info_procs->icc_profile = NULL; + result->parent_color_info_procs->previous = NULL; if (height <= 0 || idle) { /* Empty clipping - will skip all drawings. */ @@ -514,6 +524,7 @@ pdf14_buf_free(pdf14_buf *buf, gs_memory_t *memory) { gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free"); gs_free_object(memory, buf->data, "pdf14_buf_free"); + gs_free_object(memory, buf->parent_color_info_procs, "pdf14_buf_free"); gs_free_object(memory, buf, "pdf14_buf_free"); } @@ -670,8 +681,9 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, } static int -pdf14_pop_transparency_group(pdf14_ctx *ctx, - const pdf14_nonseparable_blending_procs_t * pblend_procs, int curr_num_color_comp) +pdf14_pop_transparency_group(gs_imager_state *pis, pdf14_ctx *ctx, + const pdf14_nonseparable_blending_procs_t * pblend_procs, int curr_num_color_comp, + cmm_profile_t *curr_icc_profile) { pdf14_buf *tos = ctx->stack; pdf14_buf *nos = tos->saved; @@ -679,6 +691,13 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx, int x0, x1, y0, y1; byte *new_data_buf; int num_noncolor_planes, new_num_planes; + int num_cols, num_rows; + + gsicc_rendering_param_t rendering_params; + gsicc_link_t *icc_link; + gsicc_bufferdesc_t input_buff_desc; + gsicc_bufferdesc_t output_buff_desc; + if (nos == NULL) return_error(gs_error_rangecheck); @@ -732,7 +751,9 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx, /* If the color spaces are different and we actually did do a swap of the procs for color */ - if(nos->parent_color_info_procs.num_components != curr_num_color_comp && nos->parent_color_info_procs.parent_color_mapping_procs != NULL){ + if ( (nos->parent_color_info_procs->num_components != curr_num_color_comp && + nos->parent_color_info_procs->parent_color_mapping_procs != NULL) || + nos->parent_color_info_procs->icc_profile->hashcode != curr_icc_profile->hashcode) { if (x0 < x1 && y0 < y1) { @@ -747,7 +768,7 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx, reuse. Save that for a later optimization. */ num_noncolor_planes = tos->n_planes - curr_num_color_comp; - new_num_planes = num_noncolor_planes + nos->parent_color_info_procs.num_components; + new_num_planes = num_noncolor_planes + nos->parent_color_info_procs->num_components; new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride*new_num_planes, "pdf14_buf_new"); if (new_data_buf == NULL) @@ -765,8 +786,63 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx, /* later this will be replaced by gscms_transform_color_buffer */ /* This simple function is for planar data only. */ - gs_transform_color_buffer_generic(tos->data,tos->rowstride,tos->planestride, - curr_num_color_comp,tos->rect,new_data_buf,nos->parent_color_info_procs.num_components,num_noncolor_planes); + if (nos->parent_color_info_procs->icc_profile != NULL && curr_icc_profile != NULL){ + + /* Use the ICC color management for buffer color conversion */ + + /* Define the rendering intents */ + + rendering_params.black_point_comp = BP_ON; + rendering_params.object_type = GS_IMAGE_TAG; + rendering_params.rendering_intent = gsPERCEPTUAL; + + /* Request the ICC link for the transform that we will need to use */ + + icc_link = gsicc_get_link_profile(pis, curr_icc_profile, + nos->parent_color_info_procs->icc_profile, + &rendering_params, pis->memory, false); + + /* If the link is the identity, then we don't need to do any color conversions */ + + if (icc_link->is_identity ) { + + memset(new_data_buf, 0, tos->planestride*new_num_planes); + + } else { + + /* Set up the buffer descriptors. Note that pdf14 always has + the alpha channels at the back end (last planes). We will just handle that + here and let the CMM know nothing about it */ + + num_rows = tos->rect.q.y - tos->rect.p.y; + num_cols = tos->rect.q.x - tos->rect.p.x; + + gsicc_init_buffer(&input_buff_desc, curr_num_color_comp, 1, + false, false, true, tos->planestride, tos->rowstride, + num_rows, num_cols); + + gsicc_init_buffer(&output_buff_desc, + nos->parent_color_info_procs->num_components, 1, + false, false, true, tos->planestride, tos->rowstride, + num_rows, num_cols); + + /* Transform the data */ + + gscms_transform_color_buffer(icc_link, &input_buff_desc, &output_buff_desc, + tos->data, new_data_buf); + + } + + /* Release the link */ + + gsicc_release_link(icc_link); + + } else { + + gs_transform_color_buffer_generic(tos->data,tos->rowstride,tos->planestride, + curr_num_color_comp,tos->rect,new_data_buf,nos->parent_color_info_procs->num_components,num_noncolor_planes); + + } /* Free the old object */ @@ -792,8 +868,8 @@ pdf14_pop_transparency_group(pdf14_ctx *ctx, /* compose */ pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan, - nos->parent_color_info_procs.isadditive, - nos->parent_color_info_procs.parent_blending_procs); + nos->parent_color_info_procs->isadditive, + nos->parent_color_info_procs->parent_blending_procs); } @@ -1699,7 +1775,8 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_imager_state * pis, /* pop our transparency group which will force the blending */ - code = pdf14_pop_transparency_group(p14dev->ctx, p14dev->blend_procs, p14dev->color_info.num_components); + code = pdf14_pop_transparency_group(pis, p14dev->ctx, p14dev->blend_procs, p14dev->color_info.num_components, + pis->icc_manager->device_profile); } @@ -2388,7 +2465,7 @@ pdf14_begin_transparency_group(gx_device *dev, The exception would be if we are in doing the group for a soft mask */ if (!sep_target) { - code = pdf14_update_device_color_procs(dev,group_color,pis); + code = pdf14_update_device_color_procs(dev,group_color,pis,ptgp->iccprofile); } else { code = 0; group_color_numcomps = pdev->color_info.num_components; @@ -2430,6 +2507,7 @@ pdf14_end_transparency_group(gx_device *dev, pdf14_device *pdev = (pdf14_device *)dev; int code; pdf14_parent_color_t *parent_color; + cmm_profile_t *curr_device_profile = pis->icc_manager->device_profile; if_debug0('v', "[v]pdf14_end_transparency_group\n"); vd_get_dc('c'); @@ -2437,42 +2515,41 @@ pdf14_end_transparency_group(gx_device *dev, vd_set_scale(0.01); vd_set_origin(0, 0); vd_erase(RGB(192, 192, 192)); - code = pdf14_pop_transparency_group(pdev->ctx, pdev->blend_procs,pdev->color_info.num_components); + code = pdf14_pop_transparency_group(pis, pdev->ctx, pdev->blend_procs,pdev->color_info.num_components, curr_device_profile); /* May need to reset some color stuff related * to a mismatch between the parents color space * and the group blending space */ - parent_color = &(pdev->ctx->stack->parent_color_info_procs); + parent_color = pdev->ctx->stack->parent_color_info_procs; if (!(parent_color->parent_color_mapping_procs == NULL && parent_color->parent_color_comp_index == NULL)) { - pis->get_cmap_procs = parent_color->get_cmap_procs; - gx_set_cmap_procs(pis, dev); - - pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs; - pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index; - pdev->color_info.polarity = parent_color->polarity; - pdev->color_info.num_components = parent_color->num_components; - pdev->blend_procs = parent_color->parent_blending_procs; - pdev->ctx->additive = parent_color->isadditive; - pdev->pdf14_procs = parent_color->unpack_procs; - pdev->color_info.depth = parent_color->depth; - - parent_color->get_cmap_procs = NULL; - parent_color->parent_color_comp_index = NULL; - parent_color->parent_color_mapping_procs = NULL; - } - - - - - - + pis->get_cmap_procs = parent_color->get_cmap_procs; + gx_set_cmap_procs(pis, dev); + pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs; + pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index; + pdev->color_info.polarity = parent_color->polarity; + pdev->color_info.num_components = parent_color->num_components; + pdev->blend_procs = parent_color->parent_blending_procs; + pdev->ctx->additive = parent_color->isadditive; + pdev->pdf14_procs = parent_color->unpack_procs; + pdev->color_info.depth = parent_color->depth; + + if (parent_color->icc_profile != NULL){ + rc_decrement(pis->icc_manager->device_profile,"pdf14_end_transparency_group"); + pis->icc_manager->device_profile = parent_color->icc_profile; + } + + parent_color->get_cmap_procs = NULL; + parent_color->parent_color_comp_index = NULL; + parent_color->parent_color_mapping_procs = NULL; + parent_color->icc_profile = NULL; + } vd_release_dc; return code; @@ -2482,13 +2559,13 @@ pdf14_end_transparency_group(gx_device *dev, static int pdf14_update_device_color_procs(gx_device *dev, gs_transparency_color_t group_color, - gs_imager_state *pis) + gs_imager_state *pis, cmm_profile_t *iccprofile) { pdf14_device *pdevproto; pdf14_device *pdev = (pdf14_device *)dev; const pdf14_procs_t *new_14procs; - pdf14_parent_color_t *parent_color_info = &(pdev->ctx->stack->parent_color_info_procs); + pdf14_parent_color_t *parent_color_info = pdev->ctx->stack->parent_color_info_procs; gx_color_polarity_t new_polarity; int new_num_comps; bool new_additive; @@ -2527,7 +2604,6 @@ pdf14_update_device_color_procs(gx_device *dev, new_14procs = &gray_pdf14_procs; new_depth = 8; - break; case DEVICE_RGB: @@ -2553,6 +2629,53 @@ pdf14_update_device_color_procs(gx_device *dev, break; + case ICC: + + /* We need to store the ICC profile */ + + new_num_comps = iccprofile->num_comps; + new_depth = new_num_comps * 8; + + if (new_num_comps == 4) { + + new_additive = false; + new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; + + } else { + + new_additive = true; + new_polarity = GX_CINFO_POLARITY_ADDITIVE; + + } + + switch (new_num_comps) { + + case 1: + + pdevproto = (pdf14_device *)&gs_pdf14_Gray_device; + new_14procs = &gray_pdf14_procs; + + break; + + case 3: + + pdevproto = (pdf14_device *)&gs_pdf14_RGB_device; + new_14procs = &rgb_pdf14_procs; + + break; + + case 4: + + pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device; + new_14procs = &cmyk_pdf14_procs; + + break; + + } + + + break; + default: return_error(gs_error_rangecheck); break; @@ -2576,6 +2699,12 @@ pdf14_update_device_color_procs(gx_device *dev, parent_color_info->unpack_procs = pdev->pdf14_procs; parent_color_info->depth = pdev->color_info.depth; + /* Don't increment the space since we are going to remove it from the + ICC manager anyway */ + if (group_color == ICC && iccprofile != NULL){ + parent_color_info->icc_profile = pis->icc_manager->device_profile; + } + /* Set new information */ pis->get_cmap_procs = pdf14_get_cmap_procs_group; @@ -2591,6 +2720,15 @@ pdf14_update_device_color_procs(gx_device *dev, pdev->pdf14_procs = new_14procs; pdev->color_info.depth = new_depth; + /* If the CS was ICC based, we need to update the device ICC profile + in the ICC manager, since that is the profile that is used for the + PDF14 device */ + + if (group_color == ICC && iccprofile != NULL){ + pis->icc_manager->device_profile = iccprofile; + rc_increment(parent_color_info->icc_profile); + } + return(1); /* Lets us detect that we did do an update */ } @@ -2614,6 +2752,25 @@ pdf14_update_device_color_procs_push_c(gx_device *dev, int new_num_comps; bool new_additive; byte new_depth; + gs_state *pgs; + cmm_profile_t *cmm_icc_profile_data; + + if (pis->is_gstate) { + + pgs = (gs_state *)pis; + cmm_icc_profile_data = pgs->color_space->cmm_icc_profile_data; + + } else { + + pgs = NULL; + cmm_icc_profile_data = NULL; + + if (group_color == ICC ) { + return gs_rethrow(gs_error_undefinedresult, + "Missing ICC data"); + } + + } if_debug0('v', "[v]pdf14_update_device_color_procs_push_c\n"); @@ -2632,6 +2789,8 @@ pdf14_update_device_color_procs_push_c(gx_device *dev, Remember that only isolated groups can have color spaces that are different than their parent. */ + + update_color_info = false; switch (group_color) { @@ -2684,6 +2843,55 @@ pdf14_update_device_color_procs_push_c(gx_device *dev, break; + case ICC: + + /* Check if the profile is different. */ + + if (pis->icc_manager->device_profile->hashcode != cmm_icc_profile_data->hashcode) + { + + update_color_info = true; + new_num_comps = cmm_icc_profile_data->num_comps; + new_depth = cmm_icc_profile_data->num_comps*8; + + switch (new_num_comps) { + + case 1: + + new_polarity = GX_CINFO_POLARITY_ADDITIVE; + new_additive = true; + pdevproto = (pdf14_device *)&gs_pdf14_Gray_device; + new_14procs = &gray_pdf14_procs; + break; + + case 3: + + new_polarity = GX_CINFO_POLARITY_ADDITIVE; + new_additive = true; + pdevproto = (pdf14_device *)&gs_pdf14_RGB_device; + new_14procs = &rgb_pdf14_procs; + break; + + case 4: + + new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; + new_additive = false; + pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device; + new_14procs = &cmyk_pdf14_procs; + break; + + default: + + return gs_rethrow(gs_error_undefinedresult, + "ICC Number of colorants illegal"); + + } + + } + + + break; + default: return_error(gs_error_rangecheck); break; @@ -2713,7 +2921,17 @@ pdf14_update_device_color_procs_push_c(gx_device *dev, cldev->clist_color_info.polarity = pdev->color_info.polarity; cldev->clist_color_info.num_components = pdev->color_info.num_components; + /* For the ICC profiles, we want to update the ICC profile for the + device in the ICC manager. We already stored in in pdf14_parent_color_t. + That will be stored in the clist and restored during the reading phase */ + if (group_color == ICC) { + + rc_decrement_only(pis->icc_manager->device_profile, "pdf14_update_device_color_procs_push_c"); + pis->icc_manager->device_profile = cmm_icc_profile_data; + rc_increment(cmm_icc_profile_data); + + } if (pdev->ctx) { @@ -2808,9 +3026,8 @@ pdf14_push_parent_color(gx_device *dev, const gs_imager_state *pis) /* Allocate a new one */ - new_parent_color = gs_alloc_struct(dev->memory, pdf14_parent_color_t,&st_pdf14_clr, + new_parent_color = gs_alloc_struct(dev->memory, pdf14_parent_color_t, &st_pdf14_clr, "pdf14_clr_new"); - /* Link to old one */ new_parent_color->previous = pdev->trans_group_parent_cmap_procs; @@ -2831,6 +3048,11 @@ pdf14_push_parent_color(gx_device *dev, const gs_imager_state *pis) new_parent_color->num_components = pdev->color_info.num_components; new_parent_color->unpack_procs = pdev->pdf14_procs; new_parent_color->depth = pdev->color_info.depth; + + /* The ICC manager has the ICC profile for the device */ + + new_parent_color->icc_profile = pis->icc_manager->device_profile; + rc_increment(pis->icc_manager->device_profile); /* isadditive is only used in ctx */ if (pdev->ctx) @@ -2937,10 +3159,9 @@ pdf14_begin_transparency_mask(gx_device *dev, } - /* Always update the color mapping procs. Otherwise we end up fowarding to the target device. */ - code = pdf14_update_device_color_procs(dev,group_color,pis); + code = pdf14_update_device_color_procs(dev,group_color,pis,ptmp->iccprofile); if (code < 0) return code; @@ -2971,7 +3192,7 @@ pdf14_end_transparency_mask(gx_device *dev, gs_imager_state *pis, if (pdev->ctx->stack != NULL ) { - parent_color = &(pdev->ctx->stack->parent_color_info_procs); + parent_color = pdev->ctx->stack->parent_color_info_procs; if (!(parent_color->parent_color_mapping_procs == NULL && parent_color->parent_color_comp_index == NULL)) { @@ -3779,12 +4000,16 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_imager_state * pis, * entire gs_pdf14trans_s structure. */ #define private_st_gs_pdf14trans_t()\ - gs_private_st_ptrs1(st_pdf14trans, gs_pdf14trans_t, "gs_pdf14trans_t",\ - st_pdf14trans_enum_ptrs, st_pdf14trans_reloc_ptrs, params.transfer_function) + gs_private_st_ptrs2(st_pdf14trans, gs_pdf14trans_t, "gs_pdf14trans_t",\ + st_pdf14trans_enum_ptrs, st_pdf14trans_reloc_ptrs, params.transfer_function, params.iccprofile) + + /* GC descriptor for gs_pdf14trans_t */ private_st_gs_pdf14trans_t(); + + /* * Check for equality of two PDF 1.4 transparency compositor objects. * @@ -4599,25 +4824,59 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto, *ptempdevproto = **pdevproto; ptempdevproto->color_info.max_components = 1; ptempdevproto->color_info.num_components = ptempdevproto->color_info.max_components; + + if (dev->color_info.icc_profile == '\0'){ + strcpy(&(ptempdevproto->color_info.icc_profile[0]), DEFAULT_GRAY_ICC); + } else { + strcpy(&(ptempdevproto->color_info.icc_profile[0]), dev->color_info.icc_profile); + } + *pdevproto = ptempdevproto; break; + case PDF14_DeviceRGB: + *pdevproto = (pdf14_clist_device *)&pdf14_clist_RGB_device; + *ptempdevproto = **pdevproto; + + if (dev->color_info.icc_profile == '\0'){ + strcpy(&(ptempdevproto->color_info.icc_profile[0]), DEFAULT_RGB_ICC); + } else { + strcpy(&(ptempdevproto->color_info.icc_profile[0]), dev->color_info.icc_profile); + } + + *pdevproto = ptempdevproto; + break; + case PDF14_DeviceCMYK: + *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYK_device; - break; + *ptempdevproto = **pdevproto; + + if (dev->color_info.icc_profile == '\0'){ + strcpy(&(ptempdevproto->color_info.icc_profile[0]), DEFAULT_CMYK_ICC); + } else { + strcpy(&(ptempdevproto->color_info.icc_profile[0]), dev->color_info.icc_profile); + } + + *pdevproto = ptempdevproto; + + break; + case PDF14_DeviceCMYKspot: + *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYKspot_device; - *pdevproto = (pdf14_clist_device *)&pdf14_clist_custom_device; + *ptempdevproto = **pdevproto; + /* * The number of components for the PDF14 device is the sum * of the process components and the number of spot colors * for the page. */ + if (pdf14pct->params.num_spot_colors >= 0) { - *ptempdevproto = **pdevproto; ptempdevproto->devn_params.page_spot_colors = pdf14pct->params.num_spot_colors; ptempdevproto->color_info.num_components = @@ -4627,9 +4886,18 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto, ptempdevproto->color_info.max_components) ptempdevproto->color_info.num_components = ptempdevproto->color_info.max_components; - *pdevproto = ptempdevproto; - } + } + + if (dev->color_info.icc_profile == '\0'){ + strcpy(&(ptempdevproto->color_info.icc_profile[0]), DEFAULT_CMYK_ICC); + } else { + strcpy(&(ptempdevproto->color_info.icc_profile[0]), dev->color_info.icc_profile); + } + + *pdevproto = ptempdevproto; + break; + case PDF14_DeviceCustom: /* * We are using the output device's process color model. The @@ -4638,7 +4906,15 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto, */ *ptempdevproto = pdf14_clist_custom_device; ptempdevproto->color_info = dev->color_info; - *pdevproto = ptempdevproto; + + if (dev->color_info.icc_profile == '\0'){ + strcpy(&(ptempdevproto->color_info.icc_profile[0]), DEFAULT_CMYK_ICC); + } else { + strcpy(&(ptempdevproto->color_info.icc_profile[0]), dev->color_info.icc_profile); + } + + *pdevproto = ptempdevproto; + break; default: /* Should not occur */ return_error(gs_error_rangecheck); diff --git a/gs/base/gdevp14.h b/gs/base/gdevp14.h index 374b0c7e5..9886635bb 100644 --- a/gs/base/gdevp14.h +++ b/gs/base/gdevp14.h @@ -81,6 +81,7 @@ struct pdf14_parent_color_s { int (*parent_color_comp_index)(gx_device *, const char *, int, int); const pdf14_procs_t * unpack_procs; const pdf14_nonseparable_blending_procs_t * parent_blending_procs; + cmm_profile_t *icc_profile; pdf14_parent_color_t *previous; }; @@ -119,7 +120,7 @@ struct pdf14_buf_s { gs_transparency_mask_subtype_t SMask_SubType; uint mask_id; - pdf14_parent_color_t parent_color_info_procs; + pdf14_parent_color_t *parent_color_info_procs; gs_transparency_color_t color_space; /* Different groups can have different spaces for blending */ }; diff --git a/gs/base/gsccolor.h b/gs/base/gsccolor.h index 74fa46281..6d5d66ff2 100644 --- a/gs/base/gsccolor.h +++ b/gs/base/gsccolor.h @@ -74,6 +74,7 @@ typedef enum { DEVICE_CMYK, CIE_XYZ, DEVICEN, + ICC, UNKNOWN, OTHER } gs_transparency_color_t; diff --git a/gs/base/gscms.h b/gs/base/gscms.h index 918fc7b68..e269bd755 100644 --- a/gs/base/gscms.h +++ b/gs/base/gscms.h @@ -117,7 +117,7 @@ typedef enum { of the ghostscript color structure. The item is reference counted. */
struct cmm_profile_s {
- void *profile_handle; /* The profile handle to be used in linking */
+ void *profile_handle; /* The profile handle */
unsigned char num_comps; /* number of device dependent values */
bool islab; /* Needed since we want to detect this to avoid
expensive decode on LAB images. Is true
@@ -138,12 +138,50 @@ struct cmm_profile_s { are reloaded. */
};
+
+
#ifndef cmm_profile_DEFINED
typedef struct cmm_profile_s cmm_profile_t;
#define cmm_profile_DEFINED
#endif
+
+/* A linked list structure for storing profiles in a table in which we
+ can store and refer to from the clist and also when creating icc profiles
+ from ps object. Right now it is not clear to me if we really need a
+ cache in the traditional sense or a list since I believe the number of entries will
+ in general be very small (i.e. there will not be at MOST more than 2 to 3 internal
+ ICC profiles in a file). The default GRAY, RGB, and CMYK profiles are not
+ stored here but are maintained in the ICC manager. This is for profiles
+ that are in the content and for profiles we generate from PS and PDF CIE (NonICC)
+ color spaces. */
+
+typedef struct gsicc_profile_entry_s gsicc_profile_entry_t;
+
+struct gsicc_profile_entry_s {
+
+ cmm_profile_t *profile; /* The profile */
+ gsicc_profile_entry_t *next; /* next profile */
+ gsicc_profile_entry_t *prev; /* previous profile */
+
+};
+
+
+/* ProfileList. The size of the list is limited
+ by max_memory_size. Profiles are added if there
+ is sufficient memory. */
+
+typedef struct gsicc_profile_list_s {
+
+ gsicc_profile_entry_t *icc_profile_entry;
+ int num_entries;
+ rc_header rc;
+ gs_memory_t *memory;
+
+} gsicc_profile_list_t;
+
+
/* These are the types that we can
potentially have linked together
by the CMS. If the CMS does
diff --git a/gs/base/gsicc_profilecache.c b/gs/base/gsicc_profilecache.c new file mode 100644 index 000000000..66cf599da --- /dev/null +++ b/gs/base/gsicc_profilecache.c @@ -0,0 +1,228 @@ +/* Copyright (C) 2001-2009 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+/* icc profile cache. at this point not really a cache but
+ a double linked list. it is not clear to me yet that we
+ really need to have a real cache. */
+
+#include "std.h"
+#include "stdpre.h"
+#include "gstypes.h"
+#include "gsmemory.h"
+#include "gsstruct.h"
+#include "scommon.h"
+#include "gscms.h"
+#include "gsicc_profilecache.h"
+#include "gserrors.h"
+
+#define ICC_CACHE_MAXPROFILE 50
+
+gs_private_st_ptrs3(st_profile_entry, gsicc_profile_entry_t, "gsicc_profile_entry",
+ profile_entry_enum_ptrs, profile_entry_reloc_ptrs,
+ profile, next, prev);
+
+gs_private_st_ptrs1(st_profile_list, gsicc_profile_list_t, "gsicc_profile_list",
+ profile_list_enum_ptrs, profile_list_reloc_ptrs,
+ icc_profile_entry);
+
+/**
+ * gsicc_cache_new: Allocate a new ICC cache manager
+ * Return value: Pointer to allocated manager, or NULL on failure.
+ **/
+
+gsicc_profile_list_t *
+gsicc_profilelist_new(gs_memory_t *memory)
+{
+
+ gsicc_profile_list_t *result;
+
+ /* We want this to be maintained in stable_memory. It should not be effected by the
+ save and restores */
+
+ result = gs_alloc_struct(memory->stable_memory, gsicc_profile_list_t, &st_profile_list,
+ "gsicc_profilelist_new");
+
+ if ( result == NULL )
+ return(NULL);
+
+ /* rc_init_free(result, memory->stable_memory, 1, rc_gsicc_profile_list_free); */
+
+ result->icc_profile_entry = NULL;
+ result->num_entries = 0;
+ result->memory = memory;
+
+ return(result);
+
+}
+
+static void
+rc_gsicc_profile_list_free(gs_memory_t * mem, void *ptr_in, client_name_t cname)
+{
+ /* Ending the list. */
+
+ /* gsicc_profile_list_t *profile_list = (gsicc_profile_list_t * ) ptr_in;
+ int k;
+ gsicc_profile_entry_t *profile_entry;
+
+ profile_entry = gsicc_find_zeroref_list(profile_list);
+
+ for( k = 0; k < profile_list->num_entries; k++){
+
+ if ( profile_entry->next != NULL){
+
+ gsicc_remove_profile(profile_entry,profile_list, mem);
+
+ }
+
+ }
+
+ gs_free_object(mem->stable_memory, profile_list, "rc_gsicc_profile_list_free"); */
+
+}
+
+static void
+gsicc_add_profile(gsicc_profile_list_t *profile_list, cmm_profile_t *profile, gs_memory_t *memory)
+{
+
+ gsicc_profile_entry_t *result, *nextentry;
+
+ /* The profile has to be added in stable memory. We want them
+ to be maintained across the gsave and grestore process */
+
+ result = gs_alloc_struct(memory->stable_memory, gsicc_profile_entry_t, &st_profile_entry,
+ "gsicc_add_profile");
+
+ if (profile_list->icc_profile_entry != NULL){
+
+ /* Add where ever we are right
+ now. Later we may want to
+ do this differently. */
+
+ nextentry = profile_list->icc_profile_entry->next;
+ profile_list->icc_profile_entry->next = result;
+ result->prev = profile_list->icc_profile_entry;
+ result->next = nextentry;
+
+ if (nextentry != NULL){
+
+ nextentry->prev = result;
+
+ }
+
+ } else {
+
+ result->next = NULL;
+ result->prev = NULL;
+ profile_list->icc_profile_entry = result;
+
+ }
+
+ profile_list->num_entries++;
+
+}
+
+
+static cmm_profile_t*
+gsicc_findprofile(int64_t hash, gsicc_profile_list_t *profile_list)
+{
+
+ gsicc_profile_entry_t *curr_pos1,*curr_pos2;
+ bool foundit = 0;
+
+ /* Look through the cache for the hashcode */
+
+ curr_pos1 = profile_list->icc_profile_entry;
+ curr_pos2 = curr_pos1;
+
+ while (curr_pos1 != NULL ){
+
+ if (curr_pos1->profile->hashcode == hash){
+
+ return(curr_pos1->profile);
+
+ }
+
+ curr_pos1 = curr_pos1->prev;
+
+ }
+
+ while (curr_pos2 != NULL ){
+
+ if (curr_pos2->profile->hashcode == hash){
+
+ return(curr_pos2->profile);
+
+ }
+
+ curr_pos2 = curr_pos2->next;
+
+ }
+
+ return(NULL);
+
+
+}
+
+
+/* Find entry with zero ref count and remove it */
+/* may need to lock cache during this time to avoid */
+/* issue in multi-threaded case */
+
+static gsicc_profile_entry_t*
+gsicc_find_zeroref_list(gsicc_profile_list_t *profile_list){
+
+ gsicc_profile_entry_t *curr_pos1,*curr_pos2;
+ bool foundit = 0;
+
+ /* Look through the cache for zero ref count */
+
+ curr_pos1 = profile_list->icc_profile_entry;
+ curr_pos2 = curr_pos1;
+
+ while (curr_pos1 != NULL ){
+
+ curr_pos2 = curr_pos1;
+ curr_pos1 = curr_pos1->prev;
+
+ }
+
+ return(curr_pos2);
+
+}
+
+/* Remove link from cache. Notify CMS and free */
+
+/*
+static void
+gsicc_remove_link(gsicc_link_t *link, gsicc_link_cache_t *icc_cache, gs_memory_t *memory){
+
+
+ gsicc_link_t *prevlink,*nextlink;
+
+ prevlink = link->prevlink;
+ nextlink = link->nextlink;
+
+ if (prevlink != NULL){
+ prevlink->nextlink = nextlink;
+ }
+
+ if (nextlink != NULL){
+ nextlink->prevlink = prevlink;
+ }
+
+ gsicc_link_free(link, memory);
+
+}
+*/
+
+
+
diff --git a/gs/base/gsicc_profilecache.h b/gs/base/gsicc_profilecache.h new file mode 100644 index 000000000..43adae3c9 --- /dev/null +++ b/gs/base/gsicc_profilecache.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2001-2009 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+
+/* Header for the profile cache. Not really a cache in but a double linked
+ list for now. We need to see what is going to work best for this. */
+
+
+#ifndef gsicc_profilecache_INCLUDED
+# define gsicc_profilecache_INCLUDED
+
+
+gsicc_profile_list_t * gsicc_profilelist_new(gs_memory_t *memory);
+
+static void rc_gsicc_profile_list_free(gs_memory_t * mem, void *ptr_in, client_name_t cname);
+
+static void gsicc_add_profile(gsicc_profile_list_t *profile_list,
+ cmm_profile_t *profile, gs_memory_t *memory);
+
+static cmm_profile_t* gsicc_findprofile(int64_t hash, gsicc_profile_list_t *profile_list);
+
+static gsicc_profile_entry_t* gsicc_find_zeroref_list(gsicc_profile_list_t *profile_list);
+
+
+#endif
+
diff --git a/gs/base/gsicccache.c b/gs/base/gsicccache.c index 4bef3b313..87cbdfa6e 100644 --- a/gs/base/gsicccache.c +++ b/gs/base/gsicccache.c @@ -440,26 +440,12 @@ gsicc_remove_link(gsicc_link_t *link, gsicc_link_cache_t *icc_cache, gs_memory_t } -/* This is the main function called to obtain a linked transform from the ICC cache - If the cache has the link ready, it will return it. If not, it will request - one from the CMS and then return it. We may need to do some cache locking during - this process to avoid multi-threaded issues (e.g. someone deleting while someone - is updating a reference count) */ - gsicc_link_t* gsicc_get_link(gs_imager_state *pis, gs_color_space *input_colorspace, gs_color_space *output_colorspace, gsicc_rendering_param_t *rendering_params, gs_memory_t *memory, bool include_softproof) { - gsicc_hashlink_t hash; - gsicc_link_t *link; - gcmmhprofile_t link_handle = NULL; - void **contextptr = NULL; - gsicc_manager_t *icc_manager = pis->icc_manager; - gsicc_link_cache_t *icc_cache = pis->icc_cache; - gcmmhprofile_t *cms_input_profile; - gcmmhprofile_t *cms_output_profile; cmm_profile_t *gs_input_profile; cmm_profile_t *gs_output_profile; @@ -475,7 +461,6 @@ gsicc_get_link(gs_imager_state *pis, gs_color_space *input_colorspace, } - if ( output_colorspace != NULL ) { gs_output_profile = output_colorspace->cmm_icc_profile_data; @@ -487,6 +472,37 @@ gsicc_get_link(gs_imager_state *pis, gs_color_space *input_colorspace, } + return(gsicc_get_link_profile(pis, gs_input_profile, gs_output_profile, + rendering_params, memory, include_softproof)); + + + +} + + + + +/* This is the main function called to obtain a linked transform from the ICC cache + If the cache has the link ready, it will return it. If not, it will request + one from the CMS and then return it. We may need to do some cache locking during + this process to avoid multi-threaded issues (e.g. someone deleting while someone + is updating a reference count) */ + +gsicc_link_t* +gsicc_get_link_profile(gs_imager_state *pis, cmm_profile_t *gs_input_profile, + cmm_profile_t *gs_output_profile, + gsicc_rendering_param_t *rendering_params, gs_memory_t *memory, bool include_softproof) +{ + + gsicc_hashlink_t hash; + gsicc_link_t *link; + gcmmhprofile_t link_handle = NULL; + void **contextptr = NULL; + gsicc_manager_t *icc_manager = pis->icc_manager; + gsicc_link_cache_t *icc_cache = pis->icc_link_cache; + gcmmhprofile_t *cms_input_profile; + gcmmhprofile_t *cms_output_profile; + /* First compute the hash code for the incoming case */ /* If the output color space is NULL we will use the device profile for the output color space */ diff --git a/gs/base/gsicccache.h b/gs/base/gsicccache.h index 8db8bb1ce..1131d1bfb 100644 --- a/gs/base/gsicccache.h +++ b/gs/base/gsicccache.h @@ -51,6 +51,11 @@ gsicc_link_t* gsicc_get_link(gs_imager_state * pis, gs_color_space *input_color gs_color_space *output_colorspace, gsicc_rendering_param_t *rendering_params, gs_memory_t *memory, bool include_softproof); +gsicc_link_t* gsicc_get_link_profile(gs_imager_state *pis, cmm_profile_t *gs_input_profile, + cmm_profile_t *gs_output_profile, + gsicc_rendering_param_t *rendering_params, gs_memory_t *memory, bool include_softproof); + + void gsicc_release_link(gsicc_link_t *icclink); diff --git a/gs/base/gsistate.c b/gs/base/gsistate.c index dc54a8c40..d6a4c38bf 100644 --- a/gs/base/gsistate.c +++ b/gs/base/gsistate.c @@ -65,8 +65,9 @@ ENUM_PTRS_BEGIN(imager_state_enum_ptrs) ENUM_PTR(1, gs_imager_state, transparency_stack); ENUM_PTR(2, gs_imager_state, trans_device); ENUM_PTR(3, gs_imager_state, icc_manager); - ENUM_PTR(4, gs_imager_state, icc_cache); -#define E1(i,elt) ENUM_PTR(i+5,gs_imager_state,elt); + ENUM_PTR(4, gs_imager_state, icc_link_cache); + ENUM_PTR(5, gs_imager_state, icc_profile_cache); +#define E1(i,elt) ENUM_PTR(i+6,gs_imager_state,elt); gs_cr_state_do_ptrs(E1) #undef E1 ENUM_PTRS_END @@ -77,7 +78,8 @@ static RELOC_PTRS_BEGIN(imager_state_reloc_ptrs) RELOC_PTR(gs_imager_state, transparency_stack); RELOC_PTR(gs_imager_state, trans_device); RELOC_PTR(gs_imager_state, icc_manager); - RELOC_PTR(gs_imager_state, icc_cache); + RELOC_PTR(gs_imager_state, icc_link_cache); + RELOC_PTR(gs_imager_state, icc_profile_cache); #define R1(i,elt) RELOC_PTR(gs_imager_state,elt); gs_cr_state_do_ptrs(R1) #undef R1 @@ -132,8 +134,9 @@ gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem) pis->have_pattern_streams = false; pis->devicergb_cs = gs_cspace_new_DeviceRGB(mem); pis->devicecmyk_cs = gs_cspace_new_DeviceCMYK(mem); - pis->icc_cache = gsicc_cache_new(pis->memory); + pis->icc_link_cache = gsicc_cache_new(pis->memory); pis->icc_manager = gsicc_manager_new(pis->memory); + pis->icc_profile_cache = gsicc_profilelist_new(pis->memory); return 0; } @@ -172,7 +175,8 @@ gs_imager_state_copied(gs_imager_state * pis) rc_increment(pis->cie_joint_caches); rc_increment(pis->devicergb_cs); rc_increment(pis->devicecmyk_cs); - rc_increment(pis->icc_cache); + rc_increment(pis->icc_link_cache); + rc_increment(pis->icc_profile_cache); rc_increment(pis->icc_manager); } @@ -197,7 +201,8 @@ gs_imager_state_pre_assign(gs_imager_state *pto, const gs_imager_state *pfrom) RCCOPY(halftone); RCCOPY(devicergb_cs); RCCOPY(devicecmyk_cs); - RCCOPY(icc_cache); + RCCOPY(icc_link_cache); + RCCOPY(icc_profile_cache); RCCOPY(icc_manager); #undef RCCOPY } @@ -231,7 +236,8 @@ gs_imager_state_release(gs_imager_state * pis) RCDECR(halftone); RCDECR(devicergb_cs); RCDECR(devicecmyk_cs); - RCDECR(icc_cache); + RCDECR(icc_link_cache); + RCDECR(icc_profile_cache); RCDECR(icc_manager); #undef RCDECR } diff --git a/gs/base/gstparam.h b/gs/base/gstparam.h index c0bc24f27..409f42827 100644 --- a/gs/base/gstparam.h +++ b/gs/base/gstparam.h @@ -19,6 +19,7 @@ #include "gsccolor.h" #include "gsrefct.h" +#include "gscspace.h" /* Define the names of the known blend modes. */ typedef enum { @@ -87,6 +88,7 @@ typedef struct gs_transparency_group_params_s { uint mask_id; int group_color_numcomps; gs_transparency_color_t group_color; + cmm_profile_t *iccprofile; /* The profile */ } gs_transparency_group_params_t; /* Define the parameter structure for a transparency mask. */ @@ -109,6 +111,7 @@ typedef struct gs_transparency_mask_params_s { int (*TransferFunction)(floatp in, float *out, void *proc_data); gs_function_t *TransferFunction_data; bool replacing; + cmm_profile_t *iccprofile; /* The profile */ } gs_transparency_mask_params_t; #define MASK_TRANSFER_FUNCTION_SIZE 256 @@ -127,6 +130,7 @@ typedef struct gx_transparency_mask_params_s { bool replacing; uint mask_id; byte transfer_fn[MASK_TRANSFER_FUNCTION_SIZE]; + cmm_profile_t *iccprofile; /* The profile */ } gx_transparency_mask_params_t; /* diff --git a/gs/base/gstrans.c b/gs/base/gstrans.c index 432e2ee7a..fd02f88cd 100644 --- a/gs/base/gstrans.c +++ b/gs/base/gstrans.c @@ -28,6 +28,11 @@ #define PUSH_TS 0 + +gs_private_st_ptrs2(st_gstransparams, gs_transparency_group_params_t, "gs_gstransparams", + st_gstransparams_enum_ptrs, st_gstransparams_reloc_ptrs, ColorSpace, iccprofile); + + /* ------ Transparency-related graphics state elements ------ */ int @@ -171,11 +176,13 @@ gs_state_update_pdf14trans(gs_state * pgs, gs_pdf14trans_params_t * pparams) void gs_trans_group_params_init(gs_transparency_group_params_t *ptgp) { - ptgp->ColorSpace = 0; /* bogus, but can't do better */ + + ptgp->ColorSpace = NULL; /* bogus, but can't do better */ ptgp->Isolated = false; ptgp->Knockout = false; ptgp->image_with_SMask = false; ptgp->mask_id = 0; + ptgp->iccprofile = NULL; } int @@ -188,6 +195,7 @@ gs_begin_transparency_group(gs_state *pgs, gs_imager_state * pis = (gs_imager_state *)pgs; + /* * Put parameters into a compositor parameter and then call the * create_compositor. This will pass the data to the PDF 1.4 @@ -216,16 +224,10 @@ gs_begin_transparency_group(gs_state *pgs, } else { - /* ICC and CIE based color space. Problem right now is that the - current code does a concretization to the color space - defined by the CRD. This is not the space that we want - to blend in. Instead we want all colors to be mapped TO - the ICC color space. Then when the group is popped they - should be converted to the parent space. - That I will need to fix another day with the color changes. - For now we will punt and set our blending space as the - concrete space for the ICC space, which is defined by - the output (or default) CRD. */ + /* ICC and CIE based color space. With upcoming code changes + all CIE based spaces will actually be ICC based spaces and + ICC spaces are already concrete. So this will return the + ICC color space. */ blend_color_space = cs_concrete_space(pgs->color_space, pis); @@ -246,31 +248,53 @@ gs_begin_transparency_group(gs_state *pgs, } else { - switch (cs_num_components(blend_color_space)) { - case 1: - params.group_color = GRAY_SCALE; - params.group_color_numcomps = 1; /* Need to check */ - break; - case 3: - params.group_color = DEVICE_RGB; - params.group_color_numcomps = 3; + if ( gs_color_space_is_ICC(blend_color_space) ) { + + /* Blending space is ICC based. If we + are doing c-list rendering we will need + to write this color space into the clist. + MJV ToDo. + */ + + params.group_color = ICC; + params.group_color_numcomps = + blend_color_space->cmm_icc_profile_data->num_comps; + + /* Get the ICC profile */ + + params.iccprofile = blend_color_space->cmm_icc_profile_data; + rc_increment(params.iccprofile); + + + } else { + + switch (cs_num_components(blend_color_space)) { + case 1: + params.group_color = GRAY_SCALE; + params.group_color_numcomps = 1; /* Need to check */ + break; + case 3: + params.group_color = DEVICE_RGB; + params.group_color_numcomps = 3; + break; + case 4: + params.group_color = DEVICE_CMYK; + params.group_color_numcomps = 4; break; - case 4: - params.group_color = DEVICE_CMYK; - params.group_color_numcomps = 4; - break; - default: - - /* We can end up here if we are in - a deviceN color space and - we have a sep output device */ + default: + + /* We can end up here if we are in + a deviceN color space and + we have a sep output device */ - params.group_color = DEVICEN; - params.group_color_numcomps = cs_num_components(blend_color_space); + params.group_color = DEVICEN; + params.group_color_numcomps = cs_num_components(blend_color_space); - break; + break; - } + } + + } } @@ -287,6 +311,7 @@ gs_begin_transparency_group(gs_state *pgs, cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]); else dputs(" (no CS)"); + dprintf2(" Isolated = %d Knockout = %d\n", ptgp->Isolated, ptgp->Knockout); } @@ -314,6 +339,7 @@ gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev, /* Needed so that we do proper blending */ tgp.group_color = pparams->group_color; tgp.group_color_numcomps = pparams->group_color_numcomps; + tgp.iccprofile = pparams->iccprofile; pis->opacity.alpha = pparams->opacity.alpha; pis->shape.alpha = pparams->shape.alpha; @@ -327,13 +353,15 @@ gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev, dlprintf6("[v](0x%lx)gx_begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n", (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y,pparams->group_color_numcomps); - if (tgp.ColorSpace) + if (tgp.ColorSpace) dprintf1(" CS = %s", cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]); else dputs(" (no CS)"); dprintf2(" Isolated = %d Knockout = %d\n", tgp.Isolated, tgp.Knockout); + if (tgp.iccprofile) + dprintf(" Have ICC Profile for blending\n"); } #endif if (dev_proc(pdev, begin_transparency_group) != 0) @@ -383,6 +411,8 @@ gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp, ptmp->TransferFunction = mask_transfer_identity; ptmp->TransferFunction_data = 0; ptmp->replacing = false; + ptmp->iccprofile = NULL; + } int @@ -444,80 +474,54 @@ gs_begin_transparency_mask(gs_state * pgs, /* Note: This function is called during the c-list writer side. */ + blend_color_space = pgs->color_space; - if ( params.SMask_is_CIE && params.subtype == TRANSPARENCY_MASK_Luminosity ){ - - /* Install Color Space to go to CIEXYZ */ - - /* int ok; - ok = gx_cie_to_xyz_alloc2(pgs->color_space,pgs); */ /* quite compiler */ - params.group_color_numcomps = 3; /* CIEXYZ */ - - /* Mark the proper spaces so that we make - * the appropriate changes in the device */ + if ( gs_color_space_is_ICC(blend_color_space) ) { - params.group_color = CIE_XYZ; - - } else { - - /* Set the group color type, which may be - * different than the device type. Note - we want to check the concrete space due - to the fact that things are done - in device space always. */ - - - if(!gs_color_space_is_CIE(pgs->color_space)){ + /* Blending space is ICC based. If we + are doing c-list rendering we will need + to write this color space into the clist. + MJV ToDo. + */ - blend_color_space = pgs->color_space; + params.group_color = ICC; + params.group_color_numcomps = + blend_color_space->cmm_icc_profile_data->num_comps; - } else { + /* Get the ICC profile */ - /* ICC or CIE based color space. Problem right now is that the - current code does a concretization to the color space - defined by the CRD. This is not the space that we want - to blend in. Instead we want all colors to be mapped TO - the ICC color space. Then when the group is popped they - should be converted to the parent space. - That I will need to fix another day with the color changes. - For now we will punt and set our blending space as the - concrete space for the ICC space, which is defined by - the output (or default) CRD. */ + params.iccprofile = blend_color_space->cmm_icc_profile_data; + rc_increment(params.iccprofile); - blend_color_space = cs_concrete_space(pgs->color_space, pis); - } + } else { - /* For the softmask blend color space, we will always use the above blend_color_space. - Problems can occur if we go all the way back to the device color space, - which could be DeviceN for a sep device. Blending to the luminosity - channel for this case would not be defined. */ - switch (cs_num_components(blend_color_space)) { + switch (cs_num_components(blend_color_space)) { - case 1: - params.group_color = GRAY_SCALE; - params.group_color_numcomps = 1; /* Need to check */ - break; - case 3: - params.group_color = DEVICE_RGB; - params.group_color_numcomps = 3; - break; - case 4: - params.group_color = DEVICE_CMYK; - params.group_color_numcomps = 4; - break; - default: - /* Transparency soft mask spot - colors are NEVER available. - We must use the alternate tint - transform */ - return_error(gs_error_rangecheck); - break; + case 1: + params.group_color = GRAY_SCALE; + params.group_color_numcomps = 1; /* Need to check */ + break; + case 3: + params.group_color = DEVICE_RGB; + params.group_color_numcomps = 3; + break; + case 4: + params.group_color = DEVICE_CMYK; + params.group_color_numcomps = 4; + break; + default: + /* Transparency soft mask spot + colors are NEVER available. + We must use the alternate tint + transform */ + return_error(gs_error_rangecheck); + break; - } + } - } + } return gs_state_update_pdf14trans(pgs, ¶ms); } @@ -542,6 +546,18 @@ gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev, tmp.idle = pparams->idle; tmp.replacing = pparams->replacing; tmp.mask_id = pparams->mask_id; + + if (tmp.group_color == ICC ) { + + tmp.iccprofile = pparams->iccprofile; + /* Do I need to ref count here */ + + } else { + + tmp.iccprofile = NULL; + + } + memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn)); if_debug9('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\ subtype = %d Background_components = %d Num_grp_clr_comp = %d %s\n", diff --git a/gs/base/gstrans.h b/gs/base/gstrans.h index d618a27f3..27342fb4d 100644 --- a/gs/base/gstrans.h +++ b/gs/base/gstrans.h @@ -99,6 +99,8 @@ struct gs_pdf14trans_params_s { bool SMask_is_CIE; int group_color_numcomps; gs_transparency_color_t group_color; + cmm_profile_t *iccprofile; /* The profile */ + }; #ifndef gs_pdf14trans_params_DEFINED diff --git a/gs/base/gxistate.h b/gs/base/gxistate.h index adae58f97..e9be5880f 100644 --- a/gs/base/gxistate.h +++ b/gs/base/gxistate.h @@ -246,7 +246,8 @@ typedef struct gs_devicen_color_map_s { float smoothness;\ int renderingintent; /* See gsstate.c */\ gsicc_manager_t *icc_manager; /* ICC color manager, profile */\ - gsicc_link_cache_t *icc_cache; /* ICC linked transforms */\ + gsicc_link_cache_t *icc_link_cache; /* ICC linked transforms */\ + gsicc_profile_list_t *icc_profile_cache; /* ICC profiles. */\ CUSTOM_COLOR_PTR /* Pointer to custom color callback struct */\ const gx_color_map_procs *\ (*get_cmap_procs)(const gs_imager_state *, const gx_device *);\ @@ -280,7 +281,7 @@ struct gs_imager_state_s { lop_default, gx_max_color_value, BLEND_MODE_Compatible,\ { 1.0 }, { 1.0 }, 0, 0/*false*/, 0, 0, 0, 0, 0/*false*/, 0, 0, 1.0, \ { fixed_half, fixed_half }, 0/*false*/, 0/*false*/, 0/*false*/, 1.0,\ - 1, 0, 0, INIT_CUSTOM_COLOR_PTR /* 'Custom color' callback pointer */ \ + 1, 0, 0, 0, INIT_CUSTOM_COLOR_PTR /* 'Custom color' callback pointer */ \ gx_default_get_cmap_procs /* The imager state structure is public only for subclassing. */ diff --git a/gs/base/lib.mak b/gs/base/lib.mak index e513f0702..62f00915d 100644 --- a/gs/base/lib.mak +++ b/gs/base/lib.mak @@ -348,7 +348,7 @@ gsimage_h=$(GLSRC)gsimage.h $(gsiparam_h) gsline_h=$(GLSRC)gsline.h $(gslparam_h) gspath_h=$(GLSRC)gspath.h $(gspenum_h) gsrop_h=$(GLSRC)gsrop.h $(gsropt_h) -gstparam_h=$(GLSRC)gstparam.h $(gsccolor_h) $(gsrefct_h) +gstparam_h=$(GLSRC)gstparam.h $(gsccolor_h) $(gsrefct_h) $(gscspace_h) gxalpha_h=$(GLSRC)gxalpha.h gxbcache_h=$(GLSRC)gxbcache.h $(gxbitmap_h) @@ -2450,7 +2450,7 @@ $(GLOBJ)gxctable.$(OBJ) : $(GLSRC)gxctable.c $(GX)\ # ---------------- ICCBased color ---------------- # gsicc_=$(GLOBJ)gsiccmanage.$(OBJ) $(GLOBJ)gsicccache.$(OBJ)\ - $(GLOBJ)gsicc_littlecms.$(OBJ) + $(GLOBJ)gsicc_littlecms.$(OBJ) $(GLOBJ)gsicc_profilecache.$(OBJ) sicclib_=$(GLOBJ)gsicc.$(OBJ) $(GLD)sicclib.dev : $(LIB_MAK) $(ECHOGS_XE) $(sicclib_) $(gsicc_)\ @@ -2468,6 +2468,7 @@ gscms_h=$(std_h) $(stdpre_h) $(gstypes_h) $(gsutil_h) $(stdint_h) gsicc_littlecms_h=$(GLSRC)gsicc_littlecms.h $(gxcvalue_h) $(gscms_h) gsiccmanage_h=$(GLSRC)gsiccmanage.h $(gsicc_littlecms_h) gsicccache_h=$(GLSRC)gsicccache.h $(GX) +gsicc_profilecache_h=$(GLSRC)gsicc_profilecache.h $(GLOBJ)gsiccmanage.$(OBJ) : $(GLSRC)gsiccmanage.c $(GX) $(stdpre_h)\ $(gstypes_h) $(gsmemory_h) $(gsstruct_h) $(scommon_h) $(strmio_h)\ @@ -2480,7 +2481,13 @@ $(GLOBJ)gsicccache.$(OBJ) : $(GLSRC)gsicccache.c $(GX) $(stdpre_h)\ $(gxistate_h) $(gscms_h) $(gsiccmanage_h) $(gsicccache_h)\ $(gserrors_h) $(GLCC) $(GLO_)gsicccache.$(OBJ) $(C_) $(GLSRC)gsicccache.c - + +$(GLOBJ)gsicc_profilecache.$(OBJ) : $(GLSRC)gsicc_profilecache.c $(GX) $(std_h)\ + $(stdpre_h) $(gstypes_h) $(gsmemory_h) $(gsstruct_h) $(scommon_h)\ + $(gscms_h) $(gsicc_profilecache_h)\ + $(gserrors_h) + $(GLCC) $(GLO_)gsicc_profilecache.$(OBJ) $(C_) $(GLSRC)gsicc_profilecache.c + $(GLOBJ)gsicc_littlecms.$(OBJ) : $(GLSRC)gsicc_littlecms.c\ $(gsicc_littlecms_h) $(GLLCMSCC) $(GLO_)gsicc_littlecms.$(OBJ) $(C_) $(GLSRC)gsicc_littlecms.c |