diff options
Diffstat (limited to 'devices/vector')
-rw-r--r-- | devices/vector/gdevagl.c | 2 | ||||
-rw-r--r-- | devices/vector/gdevagl.h | 2 | ||||
-rw-r--r-- | devices/vector/gdevpdf.c | 4 | ||||
-rw-r--r-- | devices/vector/gdevpdfb.h | 16 | ||||
-rw-r--r-- | devices/vector/gdevpdfd.c | 203 | ||||
-rw-r--r-- | devices/vector/gdevpdfe.c | 20 | ||||
-rw-r--r-- | devices/vector/gdevpdfg.c | 256 | ||||
-rw-r--r-- | devices/vector/gdevpdfg.h | 9 | ||||
-rw-r--r-- | devices/vector/gdevpdfi.c | 21 | ||||
-rw-r--r-- | devices/vector/gdevpdfp.c | 19 | ||||
-rw-r--r-- | devices/vector/gdevpdft.c | 4 | ||||
-rw-r--r-- | devices/vector/gdevpdfu.c | 4 | ||||
-rw-r--r-- | devices/vector/gdevpdfx.h | 10 | ||||
-rw-r--r-- | devices/vector/gdevpdtb.c | 2 | ||||
-rw-r--r-- | devices/vector/gdevpdts.c | 2 | ||||
-rw-r--r-- | devices/vector/gdevpdtt.c | 4 | ||||
-rw-r--r-- | devices/vector/gdevpsdf.h | 7 | ||||
-rw-r--r-- | devices/vector/gdevpsdi.c | 15 | ||||
-rw-r--r-- | devices/vector/gdevpsds.c | 5 | ||||
-rw-r--r-- | devices/vector/gdevpsds.h | 3 | ||||
-rw-r--r-- | devices/vector/gdevpsdu.c | 2 | ||||
-rw-r--r-- | devices/vector/gdevpsu.c | 5 | ||||
-rw-r--r-- | devices/vector/gdevpx.c | 1 | ||||
-rw-r--r-- | devices/vector/gdevtxtw.c | 201 | ||||
-rw-r--r-- | devices/vector/gdevxps.c | 43 |
25 files changed, 628 insertions, 232 deletions
diff --git a/devices/vector/gdevagl.c b/devices/vector/gdevagl.c index b2813e04..f9428a6e 100644 --- a/devices/vector/gdevagl.c +++ b/devices/vector/gdevagl.c @@ -4308,5 +4308,5 @@ treble_glyph_list_t TrebleGlyphList[] = { quad_glyph_list_t QuadGlyphList[] = { {"rehyehaleflamarabic", {0x0631, 0xFEF3, 0xFE8E, 0x0644}}, - {0x00, {0,0,0}} + {0x00, {0,0,0,0}} }; diff --git a/devices/vector/gdevagl.h b/devices/vector/gdevagl.h index e509f897..e3569226 100644 --- a/devices/vector/gdevagl.h +++ b/devices/vector/gdevagl.h @@ -33,5 +33,5 @@ typedef struct treble_glyph_list_s { typedef struct quad_glyph_list_s { const char *Glyph; - short Unicode[4]; + unsigned short Unicode[4]; } quad_glyph_list_t; diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c index d918d603..b25a4a6a 100644 --- a/devices/vector/gdevpdf.c +++ b/devices/vector/gdevpdf.c @@ -1020,6 +1020,7 @@ pdf_close_page(gx_device_pdf * pdev, int num_copies) page->contents_id = pdev->contents_id; page->NumCopies_set = pdev->NumCopies_set; page->NumCopies = pdev->NumCopies; + page->UserUnit = pdev->UserUnit; pdf_record_usage(pdev, pdev->contents_id, pdev->next_page); pdf_record_usage(pdev, pdev->contents_length_id, pdev->next_page); pdf_record_usage(pdev, page->Page->id, pdev->next_page); @@ -1337,6 +1338,9 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) bleedbox[0], bleedbox[1], bleedbox[2], bleedbox[3]); } pdf_print_orientation(pdev, page); + if (page->UserUnit != 1) + pprintg1(s, "/UserUnit %g\n", page->UserUnit); + pprintld1(s, "/Parent %ld 0 R\n", pdev->Pages->id); if (pdev->ForOPDFRead && pdev->DoNumCopies && !pdev->ProduceDSC) { if (page->NumCopies_set) diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h index d000ee96..5ea7a355 100644 --- a/devices/vector/gdevpdfb.h +++ b/devices/vector/gdevpdfb.h @@ -98,7 +98,16 @@ const gx_device_pdf PDF_DEVICE_IDENT = NULL, /* push_transparency_state */ NULL, /* pop_transparency_state */ NULL, /* put_image */ - gdev_pdf_dev_spec_op /* dev_spec_op */ + gdev_pdf_dev_spec_op, /* dev_spec_op */ + NULL, /* copy_planes */ + NULL, /* get_profile */ + NULL, /* set_graphics_type_tag */ + NULL, /* strip_copy_rop2 */ + NULL, /* strip_tile_rect_devn */ + NULL, /* copy_alpha_hl_color */ + NULL, /* process_page */ + NULL, /* transform_pixel_region */ + gdev_pdf_fill_stroke_path /* fill_stroke_path */ }, psdf_initial_values(PSDF_VERSION_INITIAL, 0 /*false */ ), /* (!ASCII85EncodePages) */ 0, /* pdf_font_dir */ @@ -162,9 +171,9 @@ const gx_device_pdf PDF_DEVICE_IDENT = {-1, -1}, /* page_dsc_info */ 0 /*false*/, /* fill_overprint */ 0 /*false*/, /* stroke_overprint */ + 1 /* Absolute Colorimetric */, /* rendering intent */ 0 /*false*/, /* remap_fill_coilor */ 0 /*false*/, /* remap_stroke_coilor */ - 0, /* overprint_mode */ gs_no_id, /* halftone_id */ {gs_no_id, gs_no_id, gs_no_id, gs_no_id}, /* transfer_ids */ 0, /* transfer_not_identity */ @@ -288,7 +297,8 @@ const gx_device_pdf PDF_DEVICE_IDENT = -1, /* Last Form ID, start with -1 which means 'none' */ 0, /* ExtensionMetadata */ 0, /* PDFFormName */ - 0 /* PassThroughWriter */ + 0, /* PassThroughWriter */ + 1.0 /* UserUnit */ }; #else diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c index 28c6b01d..1e62bad1 100644 --- a/devices/vector/gdevpdfd.c +++ b/devices/vector/gdevpdfd.c @@ -846,7 +846,7 @@ prepare_fill_with_clip(gx_device_pdf *pdev, const gs_gstate * pgs, if (code < 0) return code; } - code = pdf_prepare_fill(pdev, pgs); + code = pdf_prepare_fill(pdev, pgs, false); if (code < 0) return code; return pdf_put_clip_path(pdev, pcpath); @@ -1743,7 +1743,7 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs, code = pdf_open_page(pdev, PDF_IN_STREAM); if (code < 0) return code; - code = pdf_prepare_stroke(pdev, pgs); + code = pdf_prepare_stroke(pdev, pgs, false); if (code == gs_error_rangecheck) { /* Fallback to the default implermentation for handling a transparency with CompatibilityLevel<=1.3 . */ @@ -1866,6 +1866,205 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs, return 0; } +int +gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, + const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill, + const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke, + const gx_clip_path *pcpath) +{ + gx_device_pdf *pdev = (gx_device_pdf *) dev; + int code; + bool new_clip; + bool have_path; + + have_path = !gx_path_is_void(ppath); + if (!have_path) { + if (!pdev->vg_initial_set) { + /* See lib/gs_pdfwr.ps about "initial graphic state". */ + pdf_prepare_initial_viewer_state(pdev, pgs); + pdf_reset_graphics(pdev); + return 0; + } + } + + /* PostScript doesn't have a fill+stroke primitive, so break it into two operations + * PDF 1.2 only has a single overprint setting, we can't be certainto match that + * Because our inpu tcould be from a higher level. So be sure and break it into + * 2 operations. + */ + if (pdev->ForOPDFRead || pdev->CompatibilityLevel < 1.3) { + code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath); + if (code < 0) + return code; + gs_swapcolors_quick(pgs); + code = gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath); + gs_swapcolors_quick(pgs); + return code; + } else { + bool set_ctm; + gs_matrix mat; + double scale, path_scale; + double prescale = 1; + gs_fixed_rect bbox; + gs_path_enum cenum; + gdev_vector_dopath_state_t state; + stream *s = pdev->strm; + /* + * Check for an empty clipping path. + */ + if (pcpath) { + gs_fixed_rect cbox; + + gx_cpath_outer_box(pcpath, &cbox); + if (cbox.p.x >= cbox.q.x || cbox.p.y >= cbox.q.y) + return 1; /* empty clipping path */ +// *box = cbox; + } + code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs); + if (code < 0) + return code; + + new_clip = pdf_must_put_clip_path(pdev, pcpath); + if (have_path || pdev->context == PDF_IN_NONE || new_clip) { + if (new_clip) + code = pdf_unclip(pdev); + else + code = pdf_open_page(pdev, PDF_IN_STREAM); + if (code < 0) + return code; + } + code = pdf_prepare_fill_stroke(pdev, pgs, false); + if (code < 0) + return code; + + code = pdf_put_clip_path(pdev, pcpath); + if (code < 0) + return code; + /* + * If the CTM is not uniform, stroke width depends on angle. + * We'd like to avoid resetting the CTM, so we check for uniform + * CTMs explicitly. Note that in PDF, unlike PostScript, it is + * the CTM at the time of the stroke operation, not the CTM at + * the time the path was constructed, that is used for transforming + * the points of the path; so if we have to reset the CTM, we must + * do it before constructing the path, and inverse-transform all + * the coordinates. + */ + set_ctm = (bool)gdev_vector_stroke_scaling((gx_device_vector *)pdev, + pgs, &scale, &mat); + if (set_ctm && ((pgs->ctm.xx == 0 && pgs->ctm.xy == 0) || + (pgs->ctm.yx == 0 && pgs->ctm.yy == 0))) { + /* Acrobat Reader 5 and Adobe Reader 6 issues + the "Wrong operand type" error with matrices, which have 3 zero coefs. + Besides that, we found that Acrobat Reader 4, Acrobat Reader 5 + and Adobe Reader 6 all store the current path in user space + and apply CTM in the time of stroking - See the bug 687901. + Therefore a precise conversion of Postscript to PDF isn't possible in this case. + Adobe viewers render a line with a constant width instead. + At last, with set_ctm == true we need the inverse matrix in + gdev_vector_dopath. Therefore we exclude projection matrices + (see bug 688363). */ + set_ctm = false; + scale = fabs(pgs->ctm.xx + pgs->ctm.xy + pgs->ctm.yx + pgs->ctm.yy) /* Using the non-zero coeff. */ + / sqrt(2); /* Empirically from Adobe. */ + } + if (set_ctm) { + /* + * We want a scaling factor that will bring the largest reasonable + * user coordinate within bounds. We choose a factor based on the + * minor axis of the transformation. Thanks to Raph Levien for + * the following formula. + */ + double a = mat.xx, b = mat.xy, c = mat.yx, d = mat.yy; + double u = fabs(a * d - b * c); + double v = a * a + b * b + c * c + d * d; + double minor = (sqrt(v + 2 * u) - sqrt(v - 2 * u)) * 0.5; + + prescale = (minor == 0 || minor > 1 ? 1 : 1 / minor); + } + gx_path_bbox(ppath, &bbox); + { + /* Check whether a painting appears inside the clipping box. + Doing so after writing the clipping path due to /SP pdfmark + uses a special hack with painting outside the clipping box + for synchronizing the clipping path (see lib/gs_pdfwr.ps). + That hack appeared because there is no way to pass + the gs_gstate through gdev_pdf_put_params, + which pdfmark is implemented with. + */ + gs_fixed_rect clip_box, stroke_bbox = bbox; + gs_point d0, d1; + gs_fixed_point p0, p1; + fixed bbox_expansion_x, bbox_expansion_y; + + gs_distance_transform(pgs->line_params.half_width, 0, &ctm_only(pgs), &d0); + gs_distance_transform(0, pgs->line_params.half_width, &ctm_only(pgs), &d1); + p0.x = float2fixed(any_abs(d0.x)); + p0.y = float2fixed(any_abs(d0.y)); + p1.x = float2fixed(any_abs(d1.x)); + p1.y = float2fixed(any_abs(d1.y)); + bbox_expansion_x = max(p0.x, p1.x) + fixed_1 * 2; + bbox_expansion_y = max(p0.y, p1.y) + fixed_1 * 2; + stroke_bbox.p.x -= bbox_expansion_x; + stroke_bbox.p.y -= bbox_expansion_y; + stroke_bbox.q.x += bbox_expansion_x; + stroke_bbox.q.y += bbox_expansion_y; + gx_cpath_outer_box(pcpath, &clip_box); + rect_intersect(stroke_bbox, clip_box); + if (stroke_bbox.q.x < stroke_bbox.p.x || stroke_bbox.q.y < stroke_bbox.p.y) + return 0; + } + if (make_rect_scaling(pdev, &bbox, prescale, &path_scale)) { + scale /= path_scale; + if (set_ctm) + gs_matrix_scale(&mat, path_scale, path_scale, &mat); + else { + gs_make_scaling(path_scale, path_scale, &mat); + set_ctm = true; + } + } + + code = pdf_setfillcolor((gx_device_vector *)pdev, pgs, pdcolor_fill); + if (code == gs_error_rangecheck) { + /* rangecheck means we revert to the equivalent to the default implementation */ + code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath); + if (code < 0) + return code; + /* Swap colors to make sure the pgs colorspace is correct for stroke */ + gs_swapcolors_quick(pgs); + code = gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath); + gs_swapcolors_quick(pgs); + return code; + } + + /* Swap colors to make sure the pgs colorspace is correct for stroke */ + gs_swapcolors_quick(pgs); + code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, pgs, stroke_params, + pdcolor_stroke, scale); + gs_swapcolors_quick(pgs); + if (code < 0) { + code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath); + if (code < 0) + return code; + return gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath); + } + if (!pdev->HaveStrokeColor) + pdev->saved_fill_color = pdev->saved_stroke_color; + if (set_ctm) + pdf_put_matrix(pdev, "q ", &mat, "cm\n"); + if (pgs->line_params.dash.offset != 0 || pgs->line_params.dash.pattern_size != 0) + code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_stroke | gx_path_type_optimize | gx_path_type_dashed_stroke, (set_ctm ? &mat : (const gs_matrix *)0)); + else + code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_stroke | gx_path_type_optimize, (set_ctm ? &mat : (const gs_matrix *)0)); + if (code < 0) + return code; + s = pdev->strm; + stream_puts(s, (fill_params->rule < 0 ? "B\n" : "B*\n")); + stream_puts(s, (set_ctm ? " Q\n" : "\n")); + } + return 0; +} + /* The fill_rectangle_hl_color device method. See gxdevcli.h about return codes. diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c index 88ca7ac5..1c540709 100644 --- a/devices/vector/gdevpdfe.c +++ b/devices/vector/gdevpdfe.c @@ -202,8 +202,13 @@ pdf_xmp_time(char *buf, int buf_length) time_t t; char buf1[4+1+2+1+2+1]; /* yyyy-mm-dd\0 */ +#ifdef CLUSTER + memset(&t, 0, sizeof(t)); + memset(&tms, 0, sizeof(tms)); +#else time(&t); tms = *localtime(&t); +#endif gs_sprintf(buf1, "%04d-%02d-%02d", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday); @@ -646,8 +651,7 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) { pdf_xml_tag_open_beg(s, "rdf:Description"); - pdf_xml_attribute_name(s, "rdf:about"); - pdf_xml_attribute_value(s, instance_uuid); + pdf_xml_copy(s, " rdf:about=\"\""); pdf_xml_attribute_name(s, "xmlns:pdf"); pdf_xml_attribute_value(s, "http://ns.adobe.com/pdf/1.3/"); @@ -684,8 +688,7 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) } pdf_xml_tag_open_beg(s, "rdf:Description"); - pdf_xml_attribute_name(s, "rdf:about"); - pdf_xml_attribute_value(s, instance_uuid); + pdf_xml_copy(s, " rdf:about=\"\""); pdf_xml_attribute_name(s, "xmlns:xmp"); pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/"); pdf_xml_tag_end(s); @@ -718,8 +721,7 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) pdf_xml_newline(s); pdf_xml_tag_open_beg(s, "rdf:Description"); - pdf_xml_attribute_name(s, "rdf:about"); - pdf_xml_attribute_value(s, instance_uuid); + pdf_xml_copy(s, " rdf:about=\"\""); pdf_xml_attribute_name(s, "xmlns:xapMM"); pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/mm/"); pdf_xml_attribute_name(s, "xapMM:DocumentID"); @@ -728,8 +730,7 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) pdf_xml_newline(s); pdf_xml_tag_open_beg(s, "rdf:Description"); - pdf_xml_attribute_name(s, "rdf:about"); - pdf_xml_attribute_value(s, instance_uuid); + pdf_xml_copy(s, " rdf:about=\"\""); pdf_xml_attribute_name(s, "xmlns:dc"); pdf_xml_attribute_value(s, "http://purl.org/dc/elements/1.1/"); pdf_xml_attribute_name(s, "dc:format"); @@ -803,8 +804,7 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) pdf_xml_newline(s); if (pdev->PDFA != 0) { pdf_xml_tag_open_beg(s, "rdf:Description"); - pdf_xml_attribute_name(s, "rdf:about"); - pdf_xml_attribute_value(s, instance_uuid); + pdf_xml_copy(s, " rdf:about=\"\""); pdf_xml_attribute_name(s, "xmlns:pdfaid"); pdf_xml_attribute_value(s, "http://www.aiim.org/pdfa/ns/id/"); pdf_xml_attribute_name(s, "pdfaid:part"); diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c index bd06b9f1..0aa93e53 100644 --- a/devices/vector/gdevpdfg.c +++ b/devices/vector/gdevpdfg.c @@ -75,13 +75,14 @@ pdf_save_viewer_state(gx_device_pdf *pdev, stream *s) pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2]; pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3]; pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity; - pdev->vgstack[i].opacity_alpha = pdev->state.opacity.alpha; - pdev->vgstack[i].shape_alpha = pdev->state.shape.alpha; + pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha; + pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha; + pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape; pdev->vgstack[i].blend_mode = pdev->state.blend_mode; pdev->vgstack[i].halftone_id = pdev->halftone_id; pdev->vgstack[i].black_generation_id = pdev->black_generation_id; pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id; - pdev->vgstack[i].overprint_mode = pdev->overprint_mode; + pdev->vgstack[i].overprint_mode = pdev->state.overprint_mode; pdev->vgstack[i].smoothness = pdev->state.smoothness; pdev->vgstack[i].flatness = pdev->state.flatness; pdev->vgstack[i].text_knockout = pdev->state.text_knockout; @@ -125,13 +126,14 @@ pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s) pdev->transfer_ids[2] = s->transfer_ids[2]; pdev->transfer_ids[3] = s->transfer_ids[3]; pdev->transfer_not_identity = s->transfer_not_identity; - pdev->state.opacity.alpha = s->opacity_alpha; - pdev->state.shape.alpha = s->shape_alpha; + pdev->state.strokeconstantalpha = s->strokeconstantalpha; + pdev->state.fillconstantalpha = s->fillconstantalpha; + pdev->state.alphaisshape = s->alphaisshape; pdev->state.blend_mode = s->blend_mode; pdev->halftone_id = s->halftone_id; pdev->black_generation_id = s->black_generation_id; pdev->undercolor_removal_id = s->undercolor_removal_id; - pdev->overprint_mode = s->overprint_mode; + pdev->state.overprint_mode = s->overprint_mode; pdev->state.smoothness = s->smoothness; pdev->state.flatness = s->flatness; pdev->state.text_knockout = s->text_knockout; @@ -209,8 +211,9 @@ pdf_viewer_state_from_gs_gstate_aux(pdf_viewer_state *pvs, const gs_gstate *pgs) pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0); pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0); pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0); - pvs->opacity_alpha = pgs->opacity.alpha; - pvs->shape_alpha = pgs->shape.alpha; + pvs->fillconstantalpha = pgs->fillconstantalpha; + pvs->strokeconstantalpha = pgs->strokeconstantalpha; + pvs->alphaisshape = pgs->alphaisshape; pvs->blend_mode = pgs->blend_mode; pvs->halftone_id = (pgs->dev_ht != 0 ? pgs->dev_ht->id : 0); pvs->black_generation_id = (pgs->black_generation != 0 ? pgs->black_generation->id : 0); @@ -776,7 +779,7 @@ int convert_DeviceN_alternate(gx_device_pdf * pdev, const gs_gstate * pgs, const return_error(gs_error_VMerror); samples = (unsigned int)pow(2, pcs->params.device_n.num_components); - data_buff = gs_alloc_bytes(pdev->memory, pdev->color_info.num_components * samples, "Convert DeviceN"); + data_buff = gs_alloc_bytes(pdev->memory, (unsigned long)pdev->color_info.num_components * samples, "Convert DeviceN"); if (data_buff == 0) { COS_FREE(pca, "convert DeviceN"); return_error(gs_error_VMerror); @@ -2869,10 +2872,8 @@ pdf_update_transfer(gx_device_pdf *pdev, const gs_gstate *pgs, */ static int pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs, - pdf_resource_t **ppres) + pdf_resource_t **ppres, bool for_text) { - bool ais; - double alpha; int code; if (pdev->state.soft_mask_id != pgs->soft_mask_id) { @@ -2882,9 +2883,11 @@ pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs, code = pdf_open_contents(pdev, PDF_IN_STREAM); if (code < 0) return code; - code = pdf_restore_viewer_state(pdev, pdev->strm); - if (code < 0) - return code; + if (pdev->vgstack_depth > pdev->vgstack_bottom) { + code = pdf_restore_viewer_state(pdev, pdev->strm); + if (code < 0) + return code; + } } else{ gs_sprintf(buf, "%ld 0 R", pgs->soft_mask_id); @@ -2901,44 +2904,27 @@ pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs, } pdev->state.soft_mask_id = pgs->soft_mask_id; } - if (pdev->state.opacity.alpha != pgs->opacity.alpha) { - if (pdev->state.shape.alpha != pgs->shape.alpha) { - /* We had previously set one of opacity or shape, but we didn't - * ever need to write the graphcis state out, leaving us with a - * dangling alpha. We should honour the current state. One of - * opacity or alpha will be the default (1.0), so use the other. - */ - pdev->state.opacity.alpha = pgs->opacity.alpha; - pdev->state.shape.alpha = pgs->shape.alpha; - if (pgs->opacity.alpha != 1.0) { - ais = false; - alpha = pdev->state.opacity.alpha; - } - else { - ais = true; - alpha = pdev->state.shape.alpha; - } - } else { - ais = false; - alpha = pdev->state.opacity.alpha = pgs->opacity.alpha; - } - } else if (pdev->state.shape.alpha != pgs->shape.alpha) { - ais = true; - alpha = pdev->state.shape.alpha = pgs->shape.alpha; + + if (pdev->state.alphaisshape != pgs->alphaisshape || + pdev->state.strokeconstantalpha != pgs->strokeconstantalpha || + pdev->state.fillconstantalpha != pgs->fillconstantalpha) { + + pdev->state.strokeconstantalpha = pgs->strokeconstantalpha; + pdev->state.fillconstantalpha = pgs->fillconstantalpha; + pdev->state.alphaisshape = pgs->alphaisshape; + + code = pdf_open_gstate(pdev, ppres); + if (code < 0) + return code; + code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape); + if (code < 0) + return code; + code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha); + if (code < 0) + return code; + return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha); } else return 0; - code = pdf_open_gstate(pdev, ppres); - if (code < 0) - return code; - code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", ais); - if (code < 0) - return code; - /* we never do the 'both' operations (b, B, b*, B*) so we set both */ - /* CA and ca the same so that we stay in sync with state.*.alpha */ - code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", alpha); - if (code < 0) - return code; - return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", alpha); } /* @@ -2946,7 +2932,7 @@ pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs, */ int pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, - pdf_resource_t **ppres) + pdf_resource_t **ppres, bool for_text) { int code = 0; int bottom; @@ -2966,7 +2952,7 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, return code; pdev->state.blend_mode = pgs->blend_mode; } - code = pdf_update_alpha(pdev, pgs, ppres); + code = pdf_update_alpha(pdev, pgs, ppres, for_text); if (code < 0) return code; } else { @@ -2974,8 +2960,8 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, * If the graphics state calls for any transparency functions, * we can't represent them, so return a rangecheck. */ - if (pgs->opacity.alpha != 1 || - pgs->shape.alpha != 1) + if (pgs->strokeconstantalpha != 1 || + pgs->fillconstantalpha != 1) return_error(gs_error_rangecheck); } /* @@ -3072,9 +3058,13 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, } } } - if (pdev->CompatibilityLevel >= 1.3 && pdev->sbstack_depth == bottom) { - if (pdev->overprint_mode != pdev->params.OPM) { - if (pdev->params.OPM == 1 && pdev->PDFA == 2) { + if (pdev->state.overprint_mode != pdev->params.OPM) { + if (pdev->params.OPM != pgs->overprint_mode) + ((gs_gstate *)pgs)->overprint_mode = pdev->params.OPM; + } + if (pdev->CompatibilityLevel >= 1.3 /*&& pdev->sbstack_depth == bottom */) { + if (pdev->state.overprint_mode != pgs->overprint_mode) { + if (pgs->overprint_mode == 1 && pdev->PDFA == 2) { switch (pdev->PDFACompatibilityPolicy) { case 0: emprintf(pdev->memory, @@ -3085,7 +3075,8 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, case 1: emprintf(pdev->memory, "Setting Overprint Mode to 1\n not permitted in PDF/A-2, overprint mode not set\n\n"); - pdev->params.OPM = 0; + /* Deliberately breaking const here in order to force the graphics state overprint mode to be unchanged */ + ((gs_gstate *)pgs)->overprint_mode = pdev->state.overprint_mode; break; case 2: emprintf(pdev->memory, @@ -3100,14 +3091,14 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, break; } } - if (pdev->overprint_mode != pdev->params.OPM) { + if (pdev->state.overprint_mode != pgs->overprint_mode) { code = pdf_open_gstate(pdev, ppres); if (code < 0) return code; - code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pdev->params.OPM); + code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pgs->overprint_mode); if (code < 0) return code; - pdev->overprint_mode = pdev->params.OPM; + pdev->params.OPM = pdev->state.overprint_mode = pgs->overprint_mode; } } if (pdev->state.smoothness != pgs->smoothness) { @@ -3136,19 +3127,36 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, /* Update the graphics state for filling. */ int -pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs) +pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) { pdf_resource_t *pres = 0; - int code = pdf_prepare_drawing(pdev, pgs, &pres); + int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text); if (code < 0) return code; + if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) { + static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" }; + char buf[32]; + + code = pdf_open_gstate(pdev, &pres); + if (code < 0) + return code; + + buf[0] = '/'; + strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2); + code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf); + if (code < 0) + return code; + pdev->rendering_intent = pgs->renderingintent; + } + /* Update overprint. */ if (pdev->params.PreserveOverprintSettings && (pdev->fill_overprint != pgs->overprint || pdev->font3) && !pdev->skip_colors ) { - code = pdf_open_gstate(pdev, &pres); + if (pres == 0) + code = pdf_open_gstate(pdev, &pres); if (code < 0) return code; /* PDF 1.2 only has a single overprint setting. */ @@ -3167,45 +3175,136 @@ pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs) return pdf_end_gstate(pdev, pres); } int -pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs) +pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) { int code; if (pdev->context != PDF_IN_STREAM) { - code = pdf_try_prepare_fill(pdev, pgs); + code = pdf_try_prepare_fill(pdev, pgs, for_text); if (code != gs_error_interrupt) /* See pdf_open_gstate */ return code; code = pdf_open_contents(pdev, PDF_IN_STREAM); if (code < 0) return code; } - return pdf_try_prepare_fill(pdev, pgs); + return pdf_try_prepare_fill(pdev, pgs, for_text); } /* Update the graphics state for stroking. */ static int -pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs) +pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) +{ + pdf_resource_t *pres = 0; + int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text); + + if (code < 0) + return code; + if (pdev->rendering_intent != pgs->renderingintent && !pdev->ForOPDFRead) { + static const char *const ri_names[] = { "Perceptual", "RelativeColorimetric", "Saturation", "AbsoluteColorimetric" }; + char buf[32]; + + code = pdf_open_gstate(pdev, &pres); + if (code < 0) + return code; + + buf[0] = '/'; + strncpy(buf + 1, ri_names[pgs->renderingintent], sizeof(buf) - 2); + code = cos_dict_put_string_copy(resource_dict(pres), "/RI", buf); + if (code < 0) + return code; + pdev->rendering_intent = pgs->renderingintent; + } + /* Update overprint, stroke adjustment. */ + if (pdev->params.PreserveOverprintSettings && + pdev->stroke_overprint != pgs->stroke_overprint && + !pdev->skip_colors + ) { + if (pres == 0) + code = pdf_open_gstate(pdev, &pres); + if (code < 0) + return code; + code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint); + if (code < 0) + return code; + pdev->stroke_overprint = pgs->stroke_overprint; + + /* According to PDF>=1.3 spec, OP also sets op, + if there is no /op in same graphic state object. + We don't write /op, so monitor the viewer's state here : */ + pdev->fill_overprint = pgs->stroke_overprint; + } + if (pdev->state.stroke_adjust != pgs->stroke_adjust) { + code = pdf_open_gstate(pdev, &pres); + if (code < 0) + return code; + code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust); + if (code < 0) + return code; + pdev->state.stroke_adjust = pgs->stroke_adjust; + } + return pdf_end_gstate(pdev, pres); +} +int +pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) +{ + int code; + + if (pdev->context != PDF_IN_STREAM) { + code = pdf_try_prepare_stroke(pdev, pgs, for_text); + if (code != gs_error_interrupt) /* See pdf_open_gstate */ + return code; + code = pdf_open_contents(pdev, PDF_IN_STREAM); + if (code < 0) + return code; + } + return pdf_try_prepare_stroke(pdev, pgs, for_text); +} + +static int +pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) { pdf_resource_t *pres = 0; - int code = pdf_prepare_drawing(pdev, pgs, &pres); + int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text); if (code < 0) return code; + /* Update overprint. */ + if (pdev->params.PreserveOverprintSettings && + (pdev->fill_overprint != pgs->overprint || + pdev->stroke_overprint != pgs->stroke_overprint || + pdev->font3) && !pdev->skip_colors + ) { + code = pdf_open_gstate(pdev, &pres); + if (code < 0) + return code; + /* PDF 1.2 only has a single overprint setting. */ + if (pdev->CompatibilityLevel < 1.3) { + code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint); + if (code < 0) + return code; + pdev->stroke_overprint = pgs->overprint; + } else { + code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint); + if (code < 0) + return code; + } + pdev->fill_overprint = pgs->overprint; + } /* Update overprint, stroke adjustment. */ if (pdev->params.PreserveOverprintSettings && - pdev->stroke_overprint != pgs->overprint && + pdev->stroke_overprint != pgs->stroke_overprint && !pdev->skip_colors ) { code = pdf_open_gstate(pdev, &pres); if (code < 0) return code; - code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint); + code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint); if (code < 0) return code; - pdev->stroke_overprint = pgs->overprint; + pdev->stroke_overprint = pgs->stroke_overprint; if (pdev->CompatibilityLevel < 1.3) { /* PDF 1.2 only has a single overprint setting. */ - pdev->fill_overprint = pgs->overprint; + pdev->fill_overprint = pgs->stroke_overprint; } else { /* According to PDF>=1.3 spec, OP also sets op, if there is no /op in same garphic state object. @@ -3224,20 +3323,21 @@ pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs) } return pdf_end_gstate(pdev, pres); } + int -pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs) +pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text) { int code; if (pdev->context != PDF_IN_STREAM) { - code = pdf_try_prepare_stroke(pdev, pgs); + code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text); if (code != gs_error_interrupt) /* See pdf_open_gstate */ return code; code = pdf_open_contents(pdev, PDF_IN_STREAM); if (code < 0) return code; } - return pdf_try_prepare_stroke(pdev, pgs); + return pdf_try_prepare_fill_stroke(pdev, pgs, for_text); } /* Update the graphics state for an image other than an ImageType 1 mask. */ @@ -3248,7 +3348,7 @@ pdf_prepare_image(gx_device_pdf *pdev, const gs_gstate *pgs) * As it turns out, this requires updating the same parameters as for * filling. */ - return pdf_prepare_fill(pdev, pgs); + return pdf_prepare_fill(pdev, pgs, false); } /* Update the graphics state for an ImageType 1 mask. */ diff --git a/devices/vector/gdevpdfg.h b/devices/vector/gdevpdfg.h index ffa7296d..e846b1a8 100644 --- a/devices/vector/gdevpdfg.h +++ b/devices/vector/gdevpdfg.h @@ -150,10 +150,11 @@ int pdf_set_drawing_color(gx_device_pdf * pdev, const gs_gstate * pgs, * Bring the graphics state up to date for a drawing operation. * (Text uses either fill or stroke.) */ -int pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs); -int pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, pdf_resource_t **ppres); -int pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs); -int pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs); +int pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text); +int pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, pdf_resource_t **ppres, bool for_text); +int pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text); +int pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text); +int pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text); int pdf_prepare_image(gx_device_pdf *pdev, const gs_gstate *pgs); int pdf_prepare_imagemask(gx_device_pdf *pdev, const gs_gstate *pgs, const gx_drawing_color *pdcolor); diff --git a/devices/vector/gdevpdfi.c b/devices/vector/gdevpdfi.c index fed96e46..b73ed3d6 100644 --- a/devices/vector/gdevpdfi.c +++ b/devices/vector/gdevpdfi.c @@ -1511,7 +1511,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, image[0].pixel.ColorSpace = pcs_orig; image[0].pixel.BitsPerComponent = pim->BitsPerComponent; code = psdf_setup_image_colors_filter(&pie->writer.binary[0], - (gx_device_psdf *)pdev, &image[0].pixel, pgs); + (gx_device_psdf *)pdev, pim, &image[0].pixel, pgs); if (code < 0) goto fail_and_fallback; image[0].pixel.ColorSpace = pcs_device; @@ -1556,8 +1556,9 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, goto fail_and_fallback; } else if (convert_to_process_colors) { image[1].pixel.ColorSpace = pcs_orig; + image[1].pixel.BitsPerComponent = pim->BitsPerComponent; code = psdf_setup_image_colors_filter(&pie->writer.binary[1], - (gx_device_psdf *)pdev, &image[1].pixel, pgs); + (gx_device_psdf *)pdev, pim, &image[1].pixel, pgs); if (code < 0) { goto fail_and_fallback; } @@ -1595,9 +1596,13 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, pmat, pgs, force_lossless, in_line); if (code < 0) goto fail_and_fallback; + /* Bug701972 -- added input_width arg here. For this case, just passing in the same + * width as before, so nothing changes. This is an obscure case that isn't tested + * on the cluster (note that it requires CompatibilityLevel < 1.3). + */ psdf_setup_image_to_mask_filter(&pie->writer.binary[i], - (gx_device_psdf *)pdev, pim->Width, pim->Height, - num_components, pim->BitsPerComponent, image[i].type4.MaskColor); + (gx_device_psdf *)pdev, pim->Width, pim->Height, pim->Width, + num_components, pim->BitsPerComponent, image[i].type4.MaskColor); code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i, &image[i].pixel, &cs_value, pie); if (code < 0) @@ -1878,7 +1883,7 @@ pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last, pdf_image_enum *pie = (pdf_image_enum *)info; int height = pie->writer.height; int data_height = height - pie->rows_left; - int code = 0; + int code = 0, ecode; if (pie->writer.pres) ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height; @@ -1920,6 +1925,12 @@ pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last, if (pie->initial_colorspace != pdev->pcm_color_info_index) pdf_set_process_color_model(pdev, pie->initial_colorspace); + /* Clean up any outstanding streams before freeing the enumerator */ + while (pie->writer.alt_writer_count-- > 0) { + ecode = psdf_end_binary(&(pie->writer.binary[pie->writer.alt_writer_count])); + if (ecode < 0 && code >= 0) code = ecode; + } + gx_image_free_enum(&info); return code; } diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c index df2ff377..2f29dba5 100644 --- a/devices/vector/gdevpdfp.c +++ b/devices/vector/gdevpdfp.c @@ -127,6 +127,7 @@ static const gs_param_item_t pdf_param_items[] = { pi("FastWebView", gs_param_type_bool, Linearise), pi("NoOutputFonts", gs_param_type_bool, FlattenFonts), pi("WantsPageLabels", gs_param_type_bool, WantsPageLabels), + pi("UserUnit", gs_param_type_float, UserUnit), #undef pi gs_param_item_end }; @@ -237,6 +238,14 @@ gdev_pdf_get_param(gx_device *dev, char *Param, void *list) if (strcmp(Param, "ForOPDFRead") == 0) { return(param_write_bool(plist, "ForOPDFRead", &pdev->ForOPDFRead)); } + if (strcmp(Param, "PassUserUnit") == 0) { + bool dummy; + if (pdev->CompatibilityLevel > 1.5) + dummy = true; + else + dummy = false; + return(param_write_bool(plist, "PassUserUnit", &dummy)); + } if (!pdev->is_ps2write) { if (strcmp(Param, "pdfmark") == 0){ return(param_write_null(plist, "pdfmark")); @@ -559,6 +568,16 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par if (cl < 1.2) { pdev->HaveCFF = false; } + + ecode = param_read_float(plist, "UserUnit", &pdev->UserUnit); + if (ecode < 0) + goto fail; + if (pdev->UserUnit == 0 || (pdev->UserUnit != 1 && pdev->CompatibilityLevel < 1.6)) { + ecode = gs_note_error(gs_error_rangecheck); + param_signal_error(plist, "UserUnit", ecode); + goto fail; + } + ecode = gdev_psdf_put_params(dev, plist); if (ecode < 0) goto fail; diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c index e8fb227a..46f4d312 100644 --- a/devices/vector/gdevpdft.c +++ b/devices/vector/gdevpdft.c @@ -200,7 +200,7 @@ pdf_begin_transparency_group(gs_gstate * pgs, gx_device_pdf * pdev, pdf_resource_t *pres, *pres_gstate = NULL; cos_dict_t *pcd = NULL, *pcd_Resources = NULL; - code = pdf_prepare_drawing(pdev, pgs, &pres_gstate); + code = pdf_prepare_drawing(pdev, pgs, &pres_gstate, false); if (code < 0) return code; code = pdf_end_gstate(pdev, pres_gstate); @@ -282,7 +282,7 @@ pdf_begin_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, * changed, and so doesn't write out the GState */ pgs->soft_mask_id = 0; - code = pdf_prepare_drawing(pdev, pgs, &pres); + code = pdf_prepare_drawing(pdev, pgs, &pres, false); if (code == gs_error_interrupt) { /* Not in an appropriate context, ignore it but restore * the old soft_mask_id. Not sure this is correct, but it works for now. diff --git a/devices/vector/gdevpdfu.c b/devices/vector/gdevpdfu.c index 0b2b6400..05ea7881 100644 --- a/devices/vector/gdevpdfu.c +++ b/devices/vector/gdevpdfu.c @@ -51,7 +51,7 @@ #include "gs_mgl_e.h" #include "gs_mro_e.h" -extern single_glyph_list_t *SingleGlyphList; +extern single_glyph_list_t SingleGlyphList[]; /* Define the size of internal stream buffers. */ /* (This is not a limitation, it only affects performance.) */ @@ -339,7 +339,7 @@ static int write_tt_encodings(stream *s, bool HaveTrueTypes) if (HaveTrueTypes) { char Buffer[256]; - single_glyph_list_t *entry = (single_glyph_list_t *)&SingleGlyphList; + single_glyph_list_t *entry = SingleGlyphList; gs_sprintf(Buffer, "/AdobeGlyphList mark\n"); stream_write(s, Buffer, strlen(Buffer)); diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h index b7e00481..0e43a028 100644 --- a/devices/vector/gdevpdfx.h +++ b/devices/vector/gdevpdfx.h @@ -326,6 +326,7 @@ typedef struct pdf_page_s { pdf_page_dsc_info_t dsc_info; bool NumCopies_set; /* ps2write only. */ int NumCopies; /* ps2write only. */ + float UserUnit; /* pdfwrite only */ } pdf_page_t; #define private_st_pdf_page() /* in gdevpdf.c */\ gs_private_st_ptrs2(st_pdf_page, pdf_page_t, "pdf_page_t",\ @@ -479,8 +480,9 @@ struct pdf_font_cache_elem_s { typedef struct pdf_viewer_state_s { int transfer_not_identity; /* bitmask */ gs_id transfer_ids[4]; - float opacity_alpha; /* state.opacity.alpha */ - float shape_alpha; /* state.shape.alpha */ + float strokeconstantalpha; + float fillconstantalpha; + bool alphaisshape; gs_blend_mode_t blend_mode; /* state.blend_mode */ gs_id halftone_id; gs_id black_generation_id; @@ -618,8 +620,8 @@ struct gx_device_pdf_s { pdf_page_dsc_info_t page_dsc_info; /* current page */ /* Additional graphics state */ bool fill_overprint, stroke_overprint; + int rendering_intent; bool remap_fill_color, remap_stroke_color; - int overprint_mode; gs_id halftone_id; gs_id transfer_ids[4]; int transfer_not_identity; /* bitmask */ @@ -900,6 +902,7 @@ struct gx_device_pdf_s { * doing JPEG pass through we write the JPEG data here, and don't write * anything in the image processing routines. */ + float UserUnit; }; #define is_in_page(pdev)\ @@ -960,6 +963,7 @@ extern const gx_device_vector_procs pdf_vector_procs; dev_proc_fill_rectangle(gdev_pdf_fill_rectangle); dev_proc_fill_path(gdev_pdf_fill_path); dev_proc_stroke_path(gdev_pdf_stroke_path); +dev_proc_fill_stroke_path(gdev_pdf_fill_stroke_path); dev_proc_fillpage(gdev_pdf_fillpage); /* In gdevpdfi.c */ dev_proc_begin_typed_image(gdev_pdf_begin_typed_image); diff --git a/devices/vector/gdevpdtb.c b/devices/vector/gdevpdtb.c index 8c98f4ae..9caa640e 100644 --- a/devices/vector/gdevpdtb.c +++ b/devices/vector/gdevpdtb.c @@ -509,7 +509,7 @@ pdf_write_FontFile_entry(gx_device_pdf *pdev, pdf_base_font_t *pbfont) FontFile_key = "/FontFile2"; break; default: /* Type 1/2, CIDFontType 0 */ - if (pdev->ResourcesBeforeUsage) + if (!pdev->HaveCFF) FontFile_key = "/FontFile"; else FontFile_key = "/FontFile3"; diff --git a/devices/vector/gdevpdts.c b/devices/vector/gdevpdts.c index 8fba9080..055aeb44 100644 --- a/devices/vector/gdevpdts.c +++ b/devices/vector/gdevpdts.c @@ -815,7 +815,7 @@ int pdf_set_PaintType0_params (gx_device_pdf *pdev, gs_gstate *pgs, float size, if (code < 0) return code; if (pdev->text->text_state->in.render_mode == ptsv->render_mode){ - code = pdf_prepare_stroke(pdev, pgs); + code = pdf_prepare_stroke(pdev, pgs, false); if (code >= 0) code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, pgs, NULL, NULL, 1); diff --git a/devices/vector/gdevpdtt.c b/devices/vector/gdevpdtt.c index 2c571de3..f248e998 100644 --- a/devices/vector/gdevpdtt.c +++ b/devices/vector/gdevpdtt.c @@ -416,7 +416,7 @@ pdf_prepare_text_drawing(gx_device_pdf *const pdev, gs_text_enum_t *pte) code = 0; if (code < 0) return code; - code = pdf_prepare_fill(pdev, pgs); + code = pdf_prepare_fill(pdev, pgs, true); if (code < 0) return code; } @@ -2535,7 +2535,7 @@ pdf_set_text_process_state(gx_device_pdf *pdev, if (code < 0) return code; - code = pdf_prepare_stroke(pdev, pgs); + code = pdf_prepare_stroke(pdev, pgs, true); if (code >= 0) { code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, pgs, NULL, NULL, 1); diff --git a/devices/vector/gdevpsdf.h b/devices/vector/gdevpsdf.h index 959a4143..5047f43a 100644 --- a/devices/vector/gdevpsdf.h +++ b/devices/vector/gdevpsdf.h @@ -459,11 +459,14 @@ int psdf_setup_compression_chooser(psdf_binary_writer *pbw, /* Set up an "image to mask" filter. */ int psdf_setup_image_to_mask_filter(psdf_binary_writer *pbw, gx_device_psdf *pdev, - int width, int height, int depth, int bits_per_sample, uint *MaskColor); + int width, int height, int input_width, + int depth, int bits_per_sample, uint *MaskColor); /* Set up an image colors filter. */ int psdf_setup_image_colors_filter(psdf_binary_writer *pbw, - gx_device_psdf *pdev, gs_pixel_image_t * pim, + gx_device_psdf *pdev, + const gs_pixel_image_t *input_pim, + gs_pixel_image_t * pim, const gs_gstate *pgs); /* ---------------- Symbolic data printing ---------------- */ diff --git a/devices/vector/gdevpsdi.c b/devices/vector/gdevpsdi.c index 485d685a..9c2adb72 100644 --- a/devices/vector/gdevpsdi.c +++ b/devices/vector/gdevpsdi.c @@ -828,7 +828,8 @@ psdf_setup_compression_chooser(psdf_binary_writer *pbw, gx_device_psdf *pdev, /* Set up an "image to mask" filter. */ int psdf_setup_image_to_mask_filter(psdf_binary_writer *pbw, gx_device_psdf *pdev, - int width, int height, int depth, int bits_per_sample, uint *MaskColor) + int width, int height, int input_width, + int depth, int bits_per_sample, uint *MaskColor) { int code; stream_state *ss = s_alloc_state(pdev->memory, s__image_colors_template.stype, @@ -842,7 +843,7 @@ psdf_setup_image_to_mask_filter(psdf_binary_writer *pbw, gx_device_psdf *pdev, if (code < 0) return code; s_image_colors_set_dimensions((stream_image_colors_state *)ss, - width, height, depth, bits_per_sample); + width, height, input_width, depth, bits_per_sample); s_image_colors_set_mask_colors((stream_image_colors_state *)ss, MaskColor); return 0; } @@ -850,7 +851,9 @@ psdf_setup_image_to_mask_filter(psdf_binary_writer *pbw, gx_device_psdf *pdev, /* Set up an image colors filter. */ int psdf_setup_image_colors_filter(psdf_binary_writer *pbw, - gx_device_psdf *pdev, gs_pixel_image_t * pim, + gx_device_psdf *pdev, + const gs_pixel_image_t *input_pim, + gs_pixel_image_t * pim, const gs_gstate *pgs) { /* fixme: currently it's a stub convertion to mask. */ int code; @@ -866,9 +869,9 @@ psdf_setup_image_colors_filter(psdf_binary_writer *pbw, if (code < 0) return code; s_image_colors_set_dimensions((stream_image_colors_state *)ss, - pim->Width, pim->Height, - gs_color_space_num_components(pim->ColorSpace), - pim->BitsPerComponent); + pim->Width, pim->Height, input_pim->Width, + gs_color_space_num_components(pim->ColorSpace), + pim->BitsPerComponent); s_image_colors_set_color_space((stream_image_colors_state *)ss, (gx_device *)pdev, pim->ColorSpace, pgs, pim->Decode); pim->BitsPerComponent = pdev->color_info.comp_bits[0]; /* Same precision for all components. */ diff --git a/devices/vector/gdevpsds.c b/devices/vector/gdevpsds.c index 44ba2b4c..65bbf544 100644 --- a/devices/vector/gdevpsds.c +++ b/devices/vector/gdevpsds.c @@ -1248,13 +1248,14 @@ s_image_colors_set_mask_colors(stream_image_colors_state * ss, uint *MaskColor) /* Set image dimensions. */ void s_image_colors_set_dimensions(stream_image_colors_state * ss, - int width, int height, int depth, int bits_per_sample) + int width, int height, int input_width, + int depth, int bits_per_sample) { ss->width = width; ss->height = height; ss->depth = depth; ss->bits_per_sample = bits_per_sample; - ss->row_bits = bits_per_sample * depth * width; + ss->row_bits = bits_per_sample * depth * input_width; ss->raster = bitmap_raster(ss->row_bits); ss->row_alignment_bytes = 0; /* (ss->raster * 8 - ss->row_bits) / 8) doesn't work. */ } diff --git a/devices/vector/gdevpsds.h b/devices/vector/gdevpsds.h index 310072ce..35a756f0 100644 --- a/devices/vector/gdevpsds.h +++ b/devices/vector/gdevpsds.h @@ -253,7 +253,8 @@ struct stream_image_transfer_state_s { stream_image_colors_reloc_ptrs, pcs, pdev, pgs) void s_image_colors_set_dimensions(stream_image_colors_state * st, - int width, int height, int depth, int bits_per_sample); + int width, int height, int input_width, + int depth, int bits_per_sample); void s_image_colors_set_mask_colors(stream_image_colors_state * ss, uint *MaskColor); diff --git a/devices/vector/gdevpsdu.c b/devices/vector/gdevpsdu.c index c86405ec..d626358a 100644 --- a/devices/vector/gdevpsdu.c +++ b/devices/vector/gdevpsdu.c @@ -393,6 +393,8 @@ psdf_DCT_filter(gs_param_list *plist /* may be NULL */, &st_jpeg_compress_data, "zDCTE"); if (jcdp == 0) return_error(gs_error_VMerror); + jcdp->cinfo.mem = NULL; + jcdp->cinfo.client_data = NULL; ss->data.compress = jcdp; jcdp->memory = ss->jpeg_memory = mem; /* set now for allocation */ if ((code = gs_jpeg_create_compress(ss)) < 0) diff --git a/devices/vector/gdevpsu.c b/devices/vector/gdevpsu.c index 10a13d95..094ff945 100644 --- a/devices/vector/gdevpsu.c +++ b/devices/vector/gdevpsu.c @@ -186,8 +186,13 @@ psw_begin_file_header(gp_file *f, const gx_device *dev, const gs_rect *pbbox, time_t t; struct tm tms; +#ifdef CLUSTER + memset(&t, 0, sizeof(t)); + memset(&tms, 0, sizeof(tms)); +#else time(&t); tms = *localtime(&t); +#endif fprintf(f, "%%%%CreationDate: %d/%02d/%02d %02d:%02d:%02d\n", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, tms.tm_hour, tms.tm_min, tms.tm_sec); diff --git a/devices/vector/gdevpx.c b/devices/vector/gdevpx.c index 5d2d0edf..a1fce1b7 100644 --- a/devices/vector/gdevpx.c +++ b/devices/vector/gdevpx.c @@ -741,6 +741,7 @@ pclxl_write_image_data_RLE(gx_device_pclxl * xdev, const byte * base, goto nc; s_RLE_set_defaults_inline(&rlstate); rlstate.EndOfData = false; + rlstate.omitEOD = true; s_RLE_init_inline(&rlstate); w.ptr = buf - 1; w.limit = w.ptr + num_bytes; diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c index aed535bc..87f9355d 100644 --- a/devices/vector/gdevtxtw.c +++ b/devices/vector/gdevtxtw.c @@ -37,10 +37,10 @@ /* #define TRACE_TXTWRITE 1 */ -extern single_glyph_list_t *SingleGlyphList; -extern double_glyph_list_t *DoubleGlyphList; -extern treble_glyph_list_t *TrebleGlyphList; -extern quad_glyph_list_t *QuadGlyphList; +extern single_glyph_list_t SingleGlyphList[]; +extern double_glyph_list_t DoubleGlyphList[]; +extern treble_glyph_list_t TrebleGlyphList[]; +extern quad_glyph_list_t QuadGlyphList[]; /* * Define the structure used to return glyph width information. Note that * there are two different sets of width information: real-number (x,y) @@ -1046,10 +1046,10 @@ txtwrite_put_params(gx_device * dev, gs_param_list * plist) { gx_device_txtwrite_t *tdev = (gx_device_txtwrite_t *) dev; int ecode = 0; - int code; + int code, old_TextFormat = tdev->TextFormat; const char *param_name; gs_param_string ofs; - bool dummy; + bool dummy, open = dev->is_open; switch (code = param_read_string(plist, (param_name = "OutputFile"), &ofs)) { case 0: @@ -1092,12 +1092,6 @@ txtwrite_put_params(gx_device * dev, gs_param_list * plist) if (code < 0) return code; - code = gx_default_put_params(dev, plist); - if (code < 0) - return code; - - dev->interpolate_control = 0; - if (ofs.data != 0) { /* Close the file if it's open. */ if (tdev->file != 0) { gp_fclose(tdev->file); @@ -1106,6 +1100,23 @@ txtwrite_put_params(gx_device * dev, gs_param_list * plist) memcpy(tdev->fname, ofs.data, ofs.size); tdev->fname[ofs.size] = 0; } + + /* If we change media size then gs_default_put_params will close + * the device if it is open. We don't want it to do that, so set + * the device's 'is_open' flag to false, and reset it after we've + * processed the params. + */ + if (old_TextFormat == tdev->TextFormat && open) + dev->is_open = false; + + code = gx_default_put_params(dev, plist); + if (code < 0) + return code; + + dev->is_open = open; + + dev->interpolate_control = 0; + return 0; } @@ -1693,97 +1704,99 @@ static int get_unicode(textw_text_enum_t *penum, gs_font *font, gs_glyph glyph, length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0); if (length == 0) { - code = font->procs.glyph_name(font, glyph, &gnstr); - if (code >= 0 && gnstr.size == 7) { - if (!memcmp(gnstr.data, "uni", 3)) { - static const char *hexdigits = "0123456789ABCDEF"; - char *d0 = strchr(hexdigits, gnstr.data[3]); - char *d1 = strchr(hexdigits, gnstr.data[4]); - char *d2 = strchr(hexdigits, gnstr.data[5]); - char *d3 = strchr(hexdigits, gnstr.data[6]); - - if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) { - *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits); - return 1; - } - } - } - if (length == 0) { - single_glyph_list_t *sentry = (single_glyph_list_t *)&SingleGlyphList; - double_glyph_list_t *dentry = (double_glyph_list_t *)&DoubleGlyphList; - treble_glyph_list_t *tentry = (treble_glyph_list_t *)&TrebleGlyphList; - quad_glyph_list_t *qentry = (quad_glyph_list_t *)&QuadGlyphList; - - /* Search glyph to single Unicode value table */ - while (sentry->Glyph != 0) { - if (sentry->Glyph[0] < gnstr.data[0]) { - sentry++; - continue; - } - if (sentry->Glyph[0] > gnstr.data[0]){ - break; - } - if (strlen(sentry->Glyph) == gnstr.size) { - if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) { - *Buffer = sentry->Unicode; + if (glyph != GS_NO_GLYPH) { + code = font->procs.glyph_name(font, glyph, &gnstr); + if (code >= 0 && gnstr.size == 7) { + if (!memcmp(gnstr.data, "uni", 3)) { + static const char *hexdigits = "0123456789ABCDEF"; + char *d0 = strchr(hexdigits, gnstr.data[3]); + char *d1 = strchr(hexdigits, gnstr.data[4]); + char *d2 = strchr(hexdigits, gnstr.data[5]); + char *d3 = strchr(hexdigits, gnstr.data[6]); + + if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) { + *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits); return 1; } } - sentry++; } - - /* Search glyph to double Unicode value table */ - while (dentry->Glyph != 0) { - if (dentry->Glyph[0] < gnstr.data[0]) { - dentry++; - continue; - } - if (dentry->Glyph[0] > gnstr.data[0]){ - break; - } - if (strlen(dentry->Glyph) == gnstr.size) { - if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) { - memcpy(Buffer, dentry->Unicode, 2); - return 2; + if (length == 0) { + single_glyph_list_t *sentry = SingleGlyphList; + double_glyph_list_t *dentry = DoubleGlyphList; + treble_glyph_list_t *tentry = TrebleGlyphList; + quad_glyph_list_t *qentry = QuadGlyphList; + + /* Search glyph to single Unicode value table */ + while (sentry->Glyph != 0) { + if (sentry->Glyph[0] < gnstr.data[0]) { + sentry++; + continue; + } + if (sentry->Glyph[0] > gnstr.data[0]){ + break; } + if (strlen(sentry->Glyph) == gnstr.size) { + if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) { + *Buffer = sentry->Unicode; + return 1; + } + } + sentry++; } - dentry++; - } - /* Search glyph to triple Unicode value table */ - while (tentry->Glyph != 0) { - if (tentry->Glyph[0] < gnstr.data[0]) { - tentry++; - continue; - } - if (tentry->Glyph[0] > gnstr.data[0]){ - break; - } - if (strlen(tentry->Glyph) == gnstr.size) { - if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) { - memcpy(Buffer, tentry->Unicode, 3); - return 3; + /* Search glyph to double Unicode value table */ + while (dentry->Glyph != 0) { + if (dentry->Glyph[0] < gnstr.data[0]) { + dentry++; + continue; + } + if (dentry->Glyph[0] > gnstr.data[0]){ + break; + } + if (strlen(dentry->Glyph) == gnstr.size) { + if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) { + memcpy(Buffer, dentry->Unicode, 2); + return 2; + } } + dentry++; } - tentry++; - } - /* Search glyph to quadruple Unicode value table */ - while (qentry->Glyph != 0) { - if (qentry->Glyph[0] < gnstr.data[0]) { - qentry++; - continue; - } - if (qentry->Glyph[0] > gnstr.data[0]){ - break; + /* Search glyph to triple Unicode value table */ + while (tentry->Glyph != 0) { + if (tentry->Glyph[0] < gnstr.data[0]) { + tentry++; + continue; + } + if (tentry->Glyph[0] > gnstr.data[0]){ + break; + } + if (strlen(tentry->Glyph) == gnstr.size) { + if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) { + memcpy(Buffer, tentry->Unicode, 3); + return 3; + } + } + tentry++; } - if (strlen(qentry->Glyph) == gnstr.size) { - if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) { - memcpy(Buffer, qentry->Unicode, 4); - return 4; + + /* Search glyph to quadruple Unicode value table */ + while (qentry->Glyph != 0) { + if (qentry->Glyph[0] < gnstr.data[0]) { + qentry++; + continue; + } + if (qentry->Glyph[0] > gnstr.data[0]){ + break; + } + if (strlen(qentry->Glyph) == gnstr.size) { + if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) { + memcpy(Buffer, qentry->Unicode, 4); + return 4; + } } + qentry++; } - qentry++; } } *Buffer = fallback; @@ -1890,8 +1903,8 @@ txtwrite_process_cmap_text(gs_text_enum_t *pte) pte->returned.total_width.x += dpt.x; pte->returned.total_width.y += dpt.y; - penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]); penum->Widths[penum->TextBufferIndex] += dpt.x; + penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]); break; case 2: /* end of string */ return 0; @@ -2109,7 +2122,8 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); if (!penum->text_state->Widths) return gs_note_error(gs_error_VMerror); - memcpy(penum->text_state->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float)); + memset(penum->text_state->Widths, 0x00, penum->TextBufferIndex * sizeof(float)); + memcpy(penum->text_state->Widths, penum->Widths, penum->text.size * sizeof(float)); unsorted_entry->Unicode_Text = (unsigned short *)gs_malloc(tdev->memory->stable_memory, penum->TextBufferIndex, sizeof(unsigned short), "txtwrite alloc sorted text buffer"); @@ -2121,7 +2135,8 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); if (!unsorted_entry->Widths) return gs_note_error(gs_error_VMerror); - memcpy(unsorted_entry->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float)); + memset(unsorted_entry->Widths, 0x00, penum->TextBufferIndex * sizeof(float)); + memcpy(unsorted_entry->Widths, penum->Widths, penum->text.size * sizeof(float)); unsorted_entry->FontName = (char *)gs_malloc(tdev->memory->stable_memory, (strlen(penum->text_state->FontName) + 1), sizeof(unsigned char), "txtwrite alloc sorted text buffer"); diff --git a/devices/vector/gdevxps.c b/devices/vector/gdevxps.c index 71ca1f74..5d98c283 100644 --- a/devices/vector/gdevxps.c +++ b/devices/vector/gdevxps.c @@ -152,9 +152,12 @@ typedef struct xps_image_enum_s { gp_file *fid; } xps_image_enum_t; -gs_private_st_suffix_add4(st_xps_image_enum, xps_image_enum_t, +static void +xps_image_enum_finalize(const gs_memory_t *cmem, void *vptr); + +gs_private_st_suffix_add4_final(st_xps_image_enum, xps_image_enum_t, "xps_image_enum_t", xps_image_enum_enum_ptrs, - xps_image_enum_reloc_ptrs, st_vector_image_enum, + xps_image_enum_reloc_ptrs, xps_image_enum_finalize, st_vector_image_enum, buffer, devc_buffer, pcs, pgs); typedef struct gx_device_xps_s { @@ -1424,6 +1427,11 @@ xps_finish_image_path(gx_device_vector *vdev) const char *fmt; gs_matrix matrix; + /* If an error occurs during an image, we can get here after the enumerator + * has been freed - if that's the case, just bail out immediately + */ + if (xps->xps_pie == NULL) + return; /* Path is started. Do the image brush image brush and close the path */ write_str_to_current_page(xps, "\t<Path.Fill>\n"); write_str_to_current_page(xps, "\t\t<ImageBrush "); @@ -2214,17 +2222,6 @@ xps_image_end_image(gx_image_enum_common_t * info, bool draw_last) code = xps_add_image_relationship(pie); exit: - if (pie->pcs != NULL) - rc_decrement(pie->pcs, "xps_image_end_image (pcs)"); - if (pie->buffer != NULL) - gs_free_object(pie->memory, pie->buffer, "xps_image_end_image"); - if (pie->devc_buffer != NULL) - gs_free_object(pie->memory, pie->devc_buffer, "xps_image_end_image"); - - /* ICC clean up */ - if (pie->icc_link != NULL) - gsicc_release_link(pie->icc_link); - return code; } @@ -2485,3 +2482,23 @@ tiff_from_name(gx_device_xps *dev, const char *name, int big_endian, bool usebig xps_tifsDummyUnmapProc); return t; } + +static void +xps_image_enum_finalize(const gs_memory_t *cmem, void *vptr) +{ + xps_image_enum_t *xpie = (xps_image_enum_t *)vptr; + gx_device_xps *xdev = (gx_device_xps *)xpie->dev; + + xpie->dev = NULL; + if (xpie->pcs != NULL) + rc_decrement(xpie->pcs, "xps_image_end_image (pcs)"); + if (xpie->buffer != NULL) + gs_free_object(xpie->memory, xpie->buffer, "xps_image_end_image"); + if (xpie->devc_buffer != NULL) + gs_free_object(xpie->memory, xpie->devc_buffer, "xps_image_end_image"); + + /* ICC clean up */ + if (xpie->icc_link != NULL) + gsicc_release_link(xpie->icc_link); + xdev->xps_pie = NULL; +} |