diff options
-rw-r--r-- | gs/base/gdevpdfb.h | 11 | ||||
-rw-r--r-- | gs/base/gdevpdfg.c | 500 | ||||
-rw-r--r-- | gs/base/gdevpdfi.c | 982 | ||||
-rw-r--r-- | gs/base/gdevpdfk.c | 5 | ||||
-rw-r--r-- | gs/base/gdevpdfp.c | 125 | ||||
-rw-r--r-- | gs/base/gdevpdfx.h | 5 | ||||
-rw-r--r-- | gs/base/gdevpsdf.h | 18 | ||||
-rw-r--r-- | gs/base/gdevpsdi.c | 154 | ||||
-rw-r--r-- | gs/base/gdevpsds.c | 43 | ||||
-rw-r--r-- | gs/base/gdevpsds.h | 11 |
10 files changed, 1801 insertions, 53 deletions
diff --git a/gs/base/gdevpdfb.h b/gs/base/gdevpdfb.h index 48b85ab28..13babb957 100644 --- a/gs/base/gdevpdfb.h +++ b/gs/base/gdevpdfb.h | |||
@@ -272,8 +272,11 @@ const gx_device_pdf PDF_DEVICE_IDENT = | |||
272 | true, /* IsDistiller (true even for ps2write!) */ | 272 | true, /* IsDistiller (true even for ps2write!) */ |
273 | !PDF_FOR_OPDFREAD, /* PreserveSMask */ | 273 | !PDF_FOR_OPDFREAD, /* PreserveSMask */ |
274 | !PDF_FOR_OPDFREAD, /* PreserveTrMode */ | 274 | !PDF_FOR_OPDFREAD, /* PreserveTrMode */ |
275 | false, /* NoT3CCITT */ | 275 | false, /* NoT3CCITT */ |
276 | false, /* Linearise */ | 276 | true, /* UseOldColor */ |
277 | 0, /* FirstPage */ | 277 | false, /* Linearise */ |
278 | 0 /* LastPage */ | 278 | 0, /* FirstPage (from the command line) */ |
279 | 0, /* LastPage (from the command line) */ | ||
280 | 0, /* pointer to resourceusage */ | ||
281 | 0 /* Size of resourceusage */ | ||
279 | }; | 282 | }; |
diff --git a/gs/base/gdevpdfg.c b/gs/base/gdevpdfg.c index f71f94554..d5f84cb1e 100644 --- a/gs/base/gdevpdfg.c +++ b/gs/base/gdevpdfg.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "gdevpdfg.h" | 36 | #include "gdevpdfg.h" |
37 | #include "gdevpdfo.h" | 37 | #include "gdevpdfo.h" |
38 | #include "gsicc_manage.h" | 38 | #include "gsicc_manage.h" |
39 | #include "gsicc_cache.h" | ||
39 | 40 | ||
40 | /* ---------------- Miscellaneous ---------------- */ | 41 | /* ---------------- Miscellaneous ---------------- */ |
41 | 42 | ||
@@ -292,6 +293,502 @@ is_pattern2_allowed_in_strategy(gx_device_pdf * pdev, const gx_drawing_color *pd | |||
292 | return is_cspace_allowed_in_strategy(pdev, csi); | 293 | return is_cspace_allowed_in_strategy(pdev, csi); |
293 | } | 294 | } |
294 | 295 | ||
296 | |||
297 | static int write_color_as_process(gx_device_pdf * pdev, const gs_imager_state * pis, const gs_color_space *pcs, | ||
298 | const gx_drawing_color *pdc, bool *used_process_color, | ||
299 | const psdf_set_color_commands_t *ppscc, gs_client_color *pcc) | ||
300 | { | ||
301 | int code, i; | ||
302 | gsicc_link_t *icc_link; | ||
303 | gsicc_rendering_param_t rendering_params; | ||
304 | frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS]; | ||
305 | unsigned short Converted[GS_CLIENT_COLOR_MAX_COMPONENTS]; | ||
306 | unsigned short Source[GS_CLIENT_COLOR_MAX_COMPONENTS]; | ||
307 | gs_color_space_index csi, csi2; | ||
308 | |||
309 | csi = csi2 = gs_color_space_get_index(pcs); | ||
310 | |||
311 | if (csi == gs_color_space_index_Indexed) { | ||
312 | gs_color_space *pcs2 = pcs->base_space; | ||
313 | csi2 = gs_color_space_get_index(pcs2); | ||
314 | } | ||
315 | if (csi2 == gs_color_space_index_DeviceN || | ||
316 | csi2 == gs_color_space_index_Separation) { | ||
317 | |||
318 | const char *command = NULL; | ||
319 | |||
320 | memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS); | ||
321 | pcs->type->concretize_color(pcc, pcs, conc, pis, (gx_device *)pdev); | ||
322 | csi = gs_color_space_get_index(pcs->base_space); | ||
323 | if (csi != gs_color_space_index_ICC) { | ||
324 | *used_process_color = true; | ||
325 | switch (pdev->color_info.num_components) { | ||
326 | case 1: | ||
327 | command = ppscc->setgray; | ||
328 | break; | ||
329 | case 3: | ||
330 | command = ppscc->setrgbcolor; | ||
331 | break; | ||
332 | case 4: | ||
333 | command = ppscc->setcmykcolor; | ||
334 | break; | ||
335 | } | ||
336 | pprintg1(pdev->strm, "%g", psdf_round((conc[0] / (double)65535), 255, 8)); | ||
337 | for (i = 1; i < pdev->color_info.num_components; i++) { | ||
338 | pprintg1(pdev->strm, " %g", psdf_round((conc[i] / (double)65535), 255, 8)); | ||
339 | } | ||
340 | pprints1(pdev->strm, " %s\n", command); | ||
341 | return 0; | ||
342 | } else { | ||
343 | pcs = pcs->base_space; | ||
344 | for (i=0;i<pdev->color_info.num_components;i++) | ||
345 | Source[i] = (unsigned short)(conc[i]); | ||
346 | } | ||
347 | } | ||
348 | if (csi == gs_color_space_index_Indexed) { | ||
349 | memset (&conc, 0x00, sizeof(frac) * GS_CLIENT_COLOR_MAX_COMPONENTS); | ||
350 | pcs->type->concretize_color(pcc, pcs, conc, pis, (gx_device *)pdev); | ||
351 | pcs = pcs->base_space; | ||
352 | for (i=0;i<pcs->cmm_icc_profile_data->num_comps;i++) | ||
353 | Source[i] = (unsigned short)(conc[i]); | ||
354 | } else { | ||
355 | if (csi2 >= gs_color_space_index_CIEDEFG && | ||
356 | csi2 <= gs_color_space_index_CIEA) { | ||
357 | int j = 0; | ||
358 | |||
359 | switch (csi2) { | ||
360 | case gs_color_space_index_CIEDEFG: | ||
361 | j += 1; | ||
362 | case gs_color_space_index_CIEDEF: | ||
363 | case gs_color_space_index_CIEABC: | ||
364 | j += 2; | ||
365 | case gs_color_space_index_CIEA: | ||
366 | j += 1; | ||
367 | break; | ||
368 | default: /* can't happen, simply silences compiler warnings */ | ||
369 | break; | ||
370 | } | ||
371 | for (i=0;i<j;i++) | ||
372 | Source[i] = (unsigned short)(pcc->paint.values[i] * 65535); | ||
373 | } else { | ||
374 | if (csi2 != gs_color_space_index_DeviceN && | ||
375 | csi2 != gs_color_space_index_Separation) { | ||
376 | for (i=0;i<pcs->cmm_icc_profile_data->num_comps;i++) | ||
377 | Source[i] = (unsigned short)(pcc->paint.values[i] * 65535); | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | rendering_params.black_point_comp = pis->blackptcomp; | ||
382 | rendering_params.graphics_type_tag = pdev->graphics_type_tag; | ||
383 | rendering_params.override_icc = false; | ||
384 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; | ||
385 | rendering_params.rendering_intent = pis->renderingintent; | ||
386 | rendering_params.cmm = gsCMM_DEFAULT; | ||
387 | icc_link = gsicc_get_link(pis, (gx_device *)pdev, pcs, | ||
388 | NULL, &rendering_params, | ||
389 | pis->memory); | ||
390 | (icc_link->procs.map_color)((gx_device *)pdev, icc_link, Source, Converted, 2); | ||
391 | gsicc_release_link(icc_link); | ||
392 | for (i = 0;i < pdev->color_info.num_components;i++) | ||
393 | pcc->paint.values[i] = Source[i] / 65535.0f; | ||
394 | code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc); | ||
395 | if (code < 0) | ||
396 | return code; | ||
397 | *used_process_color = true; | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int write_color_unchanged(gx_device_pdf * pdev, const gs_imager_state * pis, | ||
402 | gs_client_color *pcc, gx_hl_saved_color *current, | ||
403 | gx_hl_saved_color * psc, const psdf_set_color_commands_t *ppscc, | ||
404 | bool *used_process_color, const gs_color_space *pcs, | ||
405 | const gx_drawing_color *pdc) | ||
406 | { | ||
407 | gs_color_space_index csi, csi2; | ||
408 | int code; | ||
409 | const char *command = NULL; | ||
410 | |||
411 | csi = csi2 = gs_color_space_get_index(pcs); | ||
412 | if (csi == gs_color_space_index_ICC) { | ||
413 | csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data); | ||
414 | } | ||
415 | |||
416 | switch (csi2) { | ||
417 | case gs_color_space_index_DeviceGray: | ||
418 | command = ppscc->setgray; | ||
419 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
420 | if (code < 0) | ||
421 | return code; | ||
422 | pprints1(pdev->strm, " %s\n", command); | ||
423 | break; | ||
424 | case gs_color_space_index_DeviceRGB: | ||
425 | command = ppscc->setrgbcolor; | ||
426 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
427 | if (code < 0) | ||
428 | return code; | ||
429 | pprints1(pdev->strm, " %s\n", command); | ||
430 | break; | ||
431 | case gs_color_space_index_DeviceCMYK: | ||
432 | command = ppscc->setcmykcolor; | ||
433 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
434 | if (code < 0) | ||
435 | return code; | ||
436 | pprints1(pdev->strm, " %s\n", command); | ||
437 | break; | ||
438 | default: | ||
439 | if (!gx_hld_saved_color_same_cspace(current, psc)) { | ||
440 | cos_value_t cs_value; | ||
441 | |||
442 | code = pdf_color_space_named(pdev, &cs_value, NULL, pcs, | ||
443 | &pdf_color_space_names, true, NULL, 0); | ||
444 | /* fixme : creates redundant PDF objects. */ | ||
445 | if (code == gs_error_rangecheck) { | ||
446 | /* The color space can't write to PDF. This should never happen */ | ||
447 | return write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
448 | } | ||
449 | if (code < 0) | ||
450 | return code; | ||
451 | code = cos_value_write(&cs_value, pdev); | ||
452 | if (code < 0) | ||
453 | return code; | ||
454 | pprints1(pdev->strm, " %s\n", ppscc->setcolorspace); | ||
455 | *used_process_color = false; | ||
456 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
457 | if (code < 0) | ||
458 | return code; | ||
459 | pprints1(pdev->strm, " %s\n", ppscc->setcolorn); | ||
460 | } else if (*used_process_color) | ||
461 | return write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
462 | else { | ||
463 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
464 | if (code < 0) | ||
465 | return code; | ||
466 | pprints1(pdev->strm, " %s\n", ppscc->setcolorn); | ||
467 | } | ||
468 | break; | ||
469 | } | ||
470 | *used_process_color = false; | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int write_color_as_process_ICC(gx_device_pdf * pdev, const gs_imager_state * pis, const gs_color_space *pcs, | ||
476 | const gx_drawing_color *pdc, gx_hl_saved_color * psc, bool *used_process_color, | ||
477 | const psdf_set_color_commands_t *ppscc, gs_client_color *pcc, | ||
478 | gx_hl_saved_color *current) | ||
479 | { | ||
480 | int i, code; | ||
481 | cos_value_t cs_value; | ||
482 | |||
483 | if (!gx_hld_saved_color_same_cspace(current, psc)) { | ||
484 | code = pdf_color_space_named(pdev, &cs_value, NULL, pcs, | ||
485 | &pdf_color_space_names, true, NULL, 0); | ||
486 | /* fixme : creates redundant PDF objects. */ | ||
487 | if (code == gs_error_rangecheck) { | ||
488 | /* The color space can't write to PDF. This should never happen */ | ||
489 | return write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
490 | } | ||
491 | if (code < 0) | ||
492 | return code; | ||
493 | code = cos_value_write(&cs_value, pdev); | ||
494 | if (code < 0) | ||
495 | return code; | ||
496 | pprints1(pdev->strm, " %s\n", ppscc->setcolorspace); | ||
497 | *used_process_color = false; | ||
498 | pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8)); | ||
499 | for (i = 1; i < pcs->type->num_components(pcs); i++) { | ||
500 | pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8)); | ||
501 | } | ||
502 | if (code < 0) | ||
503 | return code; | ||
504 | pprints1(pdev->strm, " %s\n", ppscc->setcolorn); | ||
505 | } else if (*used_process_color) | ||
506 | return write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static int new_pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis, | ||
511 | const gx_drawing_color *pdc, gx_hl_saved_color * psc, | ||
512 | bool *used_process_color, | ||
513 | const psdf_set_color_commands_t *ppscc) | ||
514 | { | ||
515 | int code=0, code1=0; | ||
516 | gx_hl_saved_color temp; | ||
517 | gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */ | ||
518 | cos_value_t cs_value; | ||
519 | gs_color_space_index csi; | ||
520 | gs_color_space_index csi2; | ||
521 | const gs_color_space *pcs, *pcs2; | ||
522 | |||
523 | if (pdev->skip_colors) | ||
524 | return 0; | ||
525 | |||
526 | /* Get a copy of the current colour so we can examine it. */ | ||
527 | gx_hld_save_color(pis, pdc, &temp); | ||
528 | |||
529 | /* Since pdfwrite never applies halftones and patterns, but monitors | ||
530 | * halftone/pattern IDs separately, we don't need to compare | ||
531 | * halftone/pattern bodies here. | ||
532 | */ | ||
533 | if (gx_hld_saved_color_equal(&temp, psc)) | ||
534 | /* New colour (and space) same as old colour, no need to do anything */ | ||
535 | return 0; | ||
536 | |||
537 | /* Do we have a Pattern colour space ? */ | ||
538 | switch (gx_hld_get_color_space_and_ccolor(pis, pdc, &pcs, (const gs_client_color **)&pcc)) { | ||
539 | case pattern_color_space: | ||
540 | { | ||
541 | pdf_resource_t *pres; | ||
542 | |||
543 | if (pdc->type == gx_dc_type_pattern) { | ||
544 | /* Can't handle tiling patterns in levels 1.0 and 1.1, and | ||
545 | * unlike shading patterns we have no fallback. | ||
546 | */ | ||
547 | if (pdev->CompatibilityLevel < 1.2) { | ||
548 | return gs_error_undefined; | ||
549 | } | ||
550 | code = pdf_put_colored_pattern(pdev, pdc, pcs, | ||
551 | ppscc, pis->have_pattern_streams, &pres); | ||
552 | } | ||
553 | else if (pdc->type == &gx_dc_pure_masked) { | ||
554 | code = pdf_put_uncolored_pattern(pdev, pdc, pcs, | ||
555 | ppscc, pis->have_pattern_streams, &pres); | ||
556 | if (code < 0 || pres == 0) { | ||
557 | /* replaced a pattern with a flat fill, but we still | ||
558 | * need to change the 'saved' colour or we will | ||
559 | * get out of step with the PDF content. | ||
560 | */ | ||
561 | *psc = temp; | ||
562 | return code; | ||
563 | } | ||
564 | if (pis->have_pattern_streams) | ||
565 | code = pdf_write_ccolor(pdev, pis, pcc); | ||
566 | } else if (pdc->type == &gx_dc_pattern2) { | ||
567 | if (pdev->CompatibilityLevel <= 1.2) | ||
568 | return_error(gs_error_rangecheck); | ||
569 | if (!is_pattern2_allowed_in_strategy(pdev, pdc)) | ||
570 | return_error(gs_error_rangecheck); | ||
571 | code1 = pdf_put_pattern2(pdev, pdc, ppscc, &pres); | ||
572 | if (code1 < 0) | ||
573 | return code1; | ||
574 | } else | ||
575 | return_error(gs_error_rangecheck); | ||
576 | if (code < 0) | ||
577 | return code; | ||
578 | code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres); | ||
579 | if (code1 != gs_error_rangecheck) { | ||
580 | cos_value_write(cos_resource_value(&cs_value, pres->object), pdev); | ||
581 | pprints1(pdev->strm, " %s\n", ppscc->setcolorn); | ||
582 | } | ||
583 | else | ||
584 | pres->where_used = 0; | ||
585 | if (code < 0) | ||
586 | return code; | ||
587 | *used_process_color = false; | ||
588 | } | ||
589 | break; | ||
590 | case non_pattern_color_space: | ||
591 | csi = csi2 = gs_color_space_get_index(pcs); | ||
592 | if (csi == gs_color_space_index_ICC) { | ||
593 | csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data); | ||
594 | } | ||
595 | /* Figure out what to do if we are outputting to really ancient versions of PDF */ | ||
596 | /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */ | ||
597 | if (pdev->CompatibilityLevel <= 1.2) { | ||
598 | |||
599 | /* If we have an /Indexed space, we need to look at the base space */ | ||
600 | if (csi2 == gs_color_space_index_Indexed) { | ||
601 | pcs2 = pcs->base_space; | ||
602 | csi2 = gs_color_space_get_index(pcs2); | ||
603 | } | ||
604 | |||
605 | switch (csi2) { | ||
606 | case gs_color_space_index_DeviceGray: | ||
607 | if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
608 | pdev->params.ColorConversionStrategy == ccs_Gray) | ||
609 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
610 | else | ||
611 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
612 | break; | ||
613 | case gs_color_space_index_DeviceRGB: | ||
614 | if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
615 | pdev->params.ColorConversionStrategy == ccs_RGB) | ||
616 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
617 | else | ||
618 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
619 | break; | ||
620 | case gs_color_space_index_DeviceCMYK: | ||
621 | if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
622 | pdev->params.ColorConversionStrategy == ccs_CMYK) | ||
623 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
624 | else | ||
625 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
626 | break; | ||
627 | case gs_color_space_index_CIEA: | ||
628 | case gs_color_space_index_CIEABC: | ||
629 | case gs_color_space_index_CIEDEF: | ||
630 | case gs_color_space_index_CIEDEFG: | ||
631 | case gs_color_space_index_Separation: | ||
632 | if (pdev->ForOPDFRead) { | ||
633 | switch (pdev->params.ColorConversionStrategy) { | ||
634 | case ccs_ByObjectType: | ||
635 | /* Object type not implemented yet */ | ||
636 | case ccs_UseDeviceDependentColor: | ||
637 | /* DeviceDependentColor deprecated */ | ||
638 | case ccs_UseDeviceIndependentColorForImages: | ||
639 | /* If only correcting images, then leave unchanged */ | ||
640 | case ccs_LeaveColorUnchanged: | ||
641 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
642 | break; | ||
643 | default: | ||
644 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
645 | break; | ||
646 | } | ||
647 | } | ||
648 | else | ||
649 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
650 | break; | ||
651 | case gs_color_space_index_DeviceN: | ||
652 | case gs_color_space_index_DevicePixel: | ||
653 | case gs_color_space_index_Indexed: | ||
654 | case gs_color_space_index_ICC: | ||
655 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
656 | break; | ||
657 | default: | ||
658 | return (gs_note_error(gs_error_rangecheck)); | ||
659 | break; | ||
660 | } | ||
661 | } else { | ||
662 | switch(pdev->params.ColorConversionStrategy) { | ||
663 | case ccs_ByObjectType: | ||
664 | /* Object type not implemented yet */ | ||
665 | case ccs_UseDeviceDependentColor: | ||
666 | /* DeviceDependentCOlor deprecated */ | ||
667 | case ccs_UseDeviceIndependentColorForImages: | ||
668 | /* If only correcting images, then leave unchanged */ | ||
669 | case ccs_LeaveColorUnchanged: | ||
670 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
671 | break; | ||
672 | case ccs_sRGB: | ||
673 | case ccs_UseDeviceIndependentColor: | ||
674 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
675 | break; | ||
676 | case ccs_CMYK: | ||
677 | switch(csi2) { | ||
678 | case gs_color_space_index_DeviceGray: | ||
679 | case gs_color_space_index_DeviceCMYK: | ||
680 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
681 | break; | ||
682 | case gs_color_space_index_Separation: | ||
683 | case gs_color_space_index_DeviceN: | ||
684 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
685 | break; | ||
686 | case gs_color_space_index_Indexed: | ||
687 | pcs2 = pcs->base_space; | ||
688 | csi = gs_color_space_get_index(pcs2); | ||
689 | if (csi == gs_color_space_index_ICC) | ||
690 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
691 | switch(csi) { | ||
692 | case gs_color_space_index_DeviceGray: | ||
693 | case gs_color_space_index_DeviceCMYK: | ||
694 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
695 | break; | ||
696 | case gs_color_space_index_Separation: | ||
697 | case gs_color_space_index_DeviceN: | ||
698 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
699 | break; | ||
700 | default: | ||
701 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
702 | break; | ||
703 | } | ||
704 | break; | ||
705 | default: | ||
706 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
707 | break; | ||
708 | } | ||
709 | break; | ||
710 | case ccs_Gray: | ||
711 | switch(csi2) { | ||
712 | case gs_color_space_index_DeviceGray: | ||
713 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
714 | break; | ||
715 | case gs_color_space_index_Separation: | ||
716 | case gs_color_space_index_DeviceN: | ||
717 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
718 | break; | ||
719 | case gs_color_space_index_Indexed: | ||
720 | pcs2 = pcs->base_space; | ||
721 | csi = gs_color_space_get_index(pcs2); | ||
722 | if (csi == gs_color_space_index_ICC) | ||
723 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
724 | switch(csi) { | ||
725 | case gs_color_space_index_DeviceGray: | ||
726 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
727 | break; | ||
728 | case gs_color_space_index_Separation: | ||
729 | case gs_color_space_index_DeviceN: | ||
730 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
731 | break; | ||
732 | default: | ||
733 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
734 | break; | ||
735 | } | ||
736 | break; | ||
737 | default: | ||
738 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
739 | break; | ||
740 | } | ||
741 | break; | ||
742 | case ccs_RGB: | ||
743 | switch(csi2) { | ||
744 | case gs_color_space_index_DeviceGray: | ||
745 | case gs_color_space_index_DeviceRGB: | ||
746 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
747 | break; | ||
748 | case gs_color_space_index_Separation: | ||
749 | case gs_color_space_index_DeviceN: | ||
750 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
751 | break; | ||
752 | case gs_color_space_index_Indexed: | ||
753 | pcs2 = pcs->base_space; | ||
754 | csi = gs_color_space_get_index(pcs2); | ||
755 | if (csi == gs_color_space_index_ICC) | ||
756 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
757 | switch(csi) { | ||
758 | case gs_color_space_index_DeviceGray: | ||
759 | case gs_color_space_index_DeviceRGB: | ||
760 | code = write_color_unchanged(pdev, pis, pcc, &temp, psc, ppscc, used_process_color, pcs, pdc); | ||
761 | break; | ||
762 | case gs_color_space_index_Separation: | ||
763 | case gs_color_space_index_DeviceN: | ||
764 | code = write_color_as_process_ICC(pdev, pis, pcs, pdc, psc, used_process_color, ppscc, pcc, &temp); | ||
765 | break; | ||
766 | default: | ||
767 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
768 | break; | ||
769 | } | ||
770 | break; | ||
771 | default: | ||
772 | code = write_color_as_process(pdev, pis, pcs, pdc, used_process_color, ppscc, pcc); | ||
773 | break; | ||
774 | } | ||
775 | break; | ||
776 | default: | ||
777 | break; | ||
778 | } | ||
779 | } | ||
780 | break; | ||
781 | default: /* must not happen. */ | ||
782 | case use_process_color: | ||
783 | code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc); | ||
784 | if (code < 0) | ||
785 | return code; | ||
786 | *used_process_color = true; | ||
787 | break; | ||
788 | } | ||
789 | *psc = temp; | ||
790 | return code; | ||
791 | } | ||
295 | /* Set the fill or stroke color. */ | 792 | /* Set the fill or stroke color. */ |
296 | int | 793 | int |
297 | pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis, | 794 | pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis, |
@@ -309,6 +806,9 @@ pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis, | |||
309 | gs_color_space_index csi; | 806 | gs_color_space_index csi; |
310 | gs_color_space_index csi2; | 807 | gs_color_space_index csi2; |
311 | 808 | ||
809 | if (!pdev->UseOldColor) | ||
810 | return new_pdf_reset_color(pdev, pis, pdc, psc, used_process_color, ppscc); | ||
811 | |||
312 | if (pdev->skip_colors) | 812 | if (pdev->skip_colors) |
313 | return 0; | 813 | return 0; |
314 | gx_hld_save_color(pis, pdc, &temp); | 814 | gx_hld_save_color(pis, pdc, &temp); |
diff --git a/gs/base/gdevpdfi.c b/gs/base/gdevpdfi.c index b20109e0f..0d467c636 100644 --- a/gs/base/gdevpdfi.c +++ b/gs/base/gdevpdfi.c | |||
@@ -900,11 +900,11 @@ pdf_begin_typed_image_impl(gx_device_pdf *pdev, const gs_imager_state * pis, | |||
900 | nyi: | 900 | nyi: |
901 | return gx_default_begin_typed_image | 901 | return gx_default_begin_typed_image |
902 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, | 902 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, |
903 | pinfo); | 903 | pinfo); |
904 | } | 904 | } |
905 | 905 | ||
906 | static int | 906 | static int |
907 | pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis, | 907 | old_pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis, |
908 | const gs_matrix *pmat, const gs_image_common_t *pic, | 908 | const gs_matrix *pmat, const gs_image_common_t *pic, |
909 | const gs_int_rect * prect, | 909 | const gs_int_rect * prect, |
910 | const gx_drawing_color * pdcolor, | 910 | const gx_drawing_color * pdcolor, |
@@ -924,6 +924,984 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis, | |||
924 | return code; | 924 | return code; |
925 | } | 925 | } |
926 | 926 | ||
927 | static int setup_type1_image(gx_device_pdf *pdev, const gs_image_common_t *pic, | ||
928 | const gx_drawing_color * pdcolor, image_union_t *image, | ||
929 | pdf_typed_image_context_t context) | ||
930 | { | ||
931 | const gs_image_t *pim1 = (const gs_image_t *)pic; | ||
932 | |||
933 | if (pim1->Alpha != gs_image_alpha_none) | ||
934 | return -1; | ||
935 | if (pim1->ImageMask) { | ||
936 | /* If parameters are invalid, use the fallback implementation. */ | ||
937 | if (!(gx_dc_is_pattern1_color(pdcolor))) | ||
938 | if (pim1->BitsPerComponent != 1 || | ||
939 | !((pim1->Decode[0] == 0.0 && pim1->Decode[1] == 1.0) || | ||
940 | (pim1->Decode[0] == 1.0 && pim1->Decode[1] == 0.0)) | ||
941 | ) | ||
942 | return -1; | ||
943 | } | ||
944 | image[0].type1 = *pim1; | ||
945 | /* If we can write in-line then make it so */ | ||
946 | return (context == PDF_IMAGE_DEFAULT && | ||
947 | can_write_image_in_line(pdev, pim1)); | ||
948 | } | ||
949 | |||
950 | static int setup_type3_image(gx_device_pdf *pdev, const gs_imager_state * pis, | ||
951 | const gs_matrix *pmat, const gs_image_common_t *pic, | ||
952 | const gs_int_rect * prect, | ||
953 | const gx_drawing_color * pdcolor, | ||
954 | const gx_clip_path * pcpath, gs_memory_t * mem, | ||
955 | gx_image_enum_common_t ** pinfo, | ||
956 | image_union_t *image) | ||
957 | { | ||
958 | const gs_image3_t *pim3 = (const gs_image3_t *)pic; | ||
959 | gs_image3_t pim3a; | ||
960 | const gs_image_common_t *pic1 = pic; | ||
961 | gs_matrix m, mi; | ||
962 | const gs_matrix *pmat1 = pmat; | ||
963 | int code; | ||
964 | |||
965 | if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) { | ||
966 | if (pdf_must_put_clip_path(pdev, pcpath)) | ||
967 | code = pdf_unclip(pdev); | ||
968 | else | ||
969 | code = pdf_open_page(pdev, PDF_IN_STREAM); | ||
970 | if (code < 0) | ||
971 | return code; | ||
972 | code = pdf_put_clip_path(pdev, pcpath); | ||
973 | if (code < 0) | ||
974 | return code; | ||
975 | gs_make_identity(&m); | ||
976 | pmat1 = &m; | ||
977 | m.tx = floor(pis->ctm.tx + 0.5); /* Round the origin against the image size distorsions */ | ||
978 | m.ty = floor(pis->ctm.ty + 0.5); | ||
979 | pim3a = *pim3; | ||
980 | gs_matrix_invert(&pim3a.ImageMatrix, &mi); | ||
981 | gs_make_identity(&pim3a.ImageMatrix); | ||
982 | if (pim3a.Width < pim3a.MaskDict.Width && pim3a.Width > 0) { | ||
983 | int sx = (pim3a.MaskDict.Width + pim3a.Width - 1) / pim3a.Width; | ||
984 | |||
985 | gs_matrix_scale(&mi, 1.0 / sx, 1, &mi); | ||
986 | gs_matrix_scale(&pim3a.ImageMatrix, 1.0 / sx, 1, &pim3a.ImageMatrix); | ||
987 | } | ||
988 | if (pim3a.Height < pim3a.MaskDict.Height && pim3a.Height > 0) { | ||
989 | int sy = (pim3a.MaskDict.Height + pim3a.Height - 1) / pim3a.Height; | ||
990 | |||
991 | gs_matrix_scale(&mi, 1, 1.0 / sy, &mi); | ||
992 | gs_matrix_scale(&pim3a.ImageMatrix, 1, 1.0 / sy, &pim3a.ImageMatrix); | ||
993 | } | ||
994 | gs_matrix_multiply(&mi, &pim3a.MaskDict.ImageMatrix, &pim3a.MaskDict.ImageMatrix); | ||
995 | pic1 = (gs_image_common_t *)&pim3a; | ||
996 | /* Setting pdev->converting_image_matrix to communicate with pdf_image3_make_mcde. */ | ||
997 | gs_matrix_multiply(&mi, &ctm_only(pis), &pdev->converting_image_matrix); | ||
998 | } | ||
999 | /* | ||
1000 | * We handle ImageType 3 images in a completely different way: | ||
1001 | * the default implementation sets up the enumerator. | ||
1002 | */ | ||
1003 | return gx_begin_image3_generic((gx_device *)pdev, pis, pmat1, pic1, | ||
1004 | prect, pdcolor, pcpath, mem, | ||
1005 | pdf_image3_make_mid, | ||
1006 | pdf_image3_make_mcde, pinfo); | ||
1007 | } | ||
1008 | |||
1009 | static int convert_type4_image(gx_device_pdf *pdev, const gs_imager_state * pis, | ||
1010 | const gs_matrix *pmat, const gs_image_common_t *pic, | ||
1011 | const gs_int_rect * prect, | ||
1012 | const gx_drawing_color * pdcolor, | ||
1013 | const gx_clip_path * pcpath, gs_memory_t * mem, | ||
1014 | gx_image_enum_common_t ** pinfo, | ||
1015 | pdf_typed_image_context_t context, image_union_t *image, | ||
1016 | cos_dict_t *pnamed) | ||
1017 | { | ||
1018 | /* Try to convert the image to a plain masked image. */ | ||
1019 | gx_drawing_color icolor; | ||
1020 | int code; | ||
1021 | |||
1022 | pdev->image_mask_is_SMask = false; | ||
1023 | if (pdf_convert_image4_to_image1(pdev, pis, pdcolor, | ||
1024 | (const gs_image4_t *)pic, | ||
1025 | &image[0].type1, &icolor) >= 0) { | ||
1026 | gs_state *pgs = (gs_state *)gx_hld_get_gstate_ptr(pis); | ||
1027 | |||
1028 | if (pgs == NULL) | ||
1029 | return_error(gs_error_unregistered); /* Must not happen. */ | ||
1030 | |||
1031 | /* Undo the pop of the NI stack if necessary. */ | ||
1032 | if (pnamed) | ||
1033 | cos_array_add_object(pdev->NI_stack, COS_OBJECT(pnamed)); | ||
1034 | /* HACK: temporary patch the color space, to allow | ||
1035 | pdf_prepare_imagemask to write the right color for the imagemask. */ | ||
1036 | code = gs_gsave(pgs); | ||
1037 | if (code < 0) | ||
1038 | return code; | ||
1039 | /* {csrc}: const cast warning */ | ||
1040 | code = gs_setcolorspace(pgs, ((const gs_image4_t *)pic)->ColorSpace); | ||
1041 | if (code < 0) | ||
1042 | return code; | ||
1043 | code = pdf_begin_typed_image(pdev, pis, pmat, | ||
1044 | (gs_image_common_t *)&image[0].type1, | ||
1045 | prect, &icolor, pcpath, mem, | ||
1046 | pinfo, context); | ||
1047 | if (code < 0) | ||
1048 | return code; | ||
1049 | return gs_grestore(pgs); | ||
1050 | } | ||
1051 | return 1; | ||
1052 | } | ||
1053 | |||
1054 | static int convert_type4_to_masked_image(gx_device_pdf *pdev, const gs_imager_state * pis, | ||
1055 | const gs_image_common_t *pic, | ||
1056 | const gs_int_rect * prect, | ||
1057 | const gx_drawing_color * pdcolor, | ||
1058 | const gx_clip_path * pcpath, gs_memory_t * mem, | ||
1059 | gx_image_enum_common_t ** pinfo) | ||
1060 | { | ||
1061 | gs_matrix m, m1, mi; | ||
1062 | gs_image4_t pi4 = *(const gs_image4_t *)pic; | ||
1063 | int code; | ||
1064 | pdf_lcvd_t *cvd = NULL; | ||
1065 | |||
1066 | if (pdf_must_put_clip_path(pdev, pcpath)) | ||
1067 | code = pdf_unclip(pdev); | ||
1068 | else | ||
1069 | code = pdf_open_page(pdev, PDF_IN_STREAM); | ||
1070 | if (code < 0) | ||
1071 | return code; | ||
1072 | code = pdf_put_clip_path(pdev, pcpath); | ||
1073 | if (code < 0) | ||
1074 | return code; | ||
1075 | gs_make_identity(&m1); | ||
1076 | gs_matrix_invert(&pic->ImageMatrix, &mi); | ||
1077 | gs_matrix_multiply(&mi, &ctm_only(pis), &m); | ||
1078 | code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd, | ||
1079 | true, 0, 0, pi4.Width, pi4.Height, false); | ||
1080 | if (code < 0) | ||
1081 | return code; | ||
1082 | cvd->mdev.is_open = true; /* fixme: same as above. */ | ||
1083 | cvd->mask->is_open = true; /* fixme: same as above. */ | ||
1084 | cvd->mask_is_empty = false; | ||
1085 | code = (*dev_proc(cvd->mask, fill_rectangle))((gx_device *)cvd->mask, | ||
1086 | 0, 0, cvd->mask->width, cvd->mask->height, (gx_color_index)0); | ||
1087 | if (code < 0) | ||
1088 | return code; | ||
1089 | gx_device_retain((gx_device *)cvd, true); | ||
1090 | gx_device_retain((gx_device *)cvd->mask, true); | ||
1091 | gs_make_identity(&pi4.ImageMatrix); | ||
1092 | code = gx_default_begin_typed_image((gx_device *)cvd, | ||
1093 | pis, &m1, (gs_image_common_t *)&pi4, prect, pdcolor, NULL, mem, pinfo); | ||
1094 | if (code < 0) | ||
1095 | return code; | ||
1096 | (*pinfo)->procs = &pdf_image_cvd_enum_procs; | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | static int setup_image_process_colorspace(gx_device_pdf *pdev, image_union_t *image, gs_color_space **pcs_orig, | ||
1101 | const char *sname, cos_value_t *cs_value) | ||
1102 | { | ||
1103 | int code; | ||
1104 | gs_color_space *pcs_device = NULL; | ||
1105 | |||
1106 | cos_c_string_value(cs_value, sname); | ||
1107 | *pcs_orig = image->pixel.ColorSpace; | ||
1108 | code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device); | ||
1109 | if (code < 0) | ||
1110 | return code; | ||
1111 | image->pixel.ColorSpace = pcs_device; | ||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | /* 0 = write unchanged | ||
1116 | 1 = convert to process | ||
1117 | 2 = write as ICC | ||
1118 | */ | ||
1119 | static int setup_image_colorspace(gx_device_pdf *pdev, image_union_t *image, const gs_color_space *pcs, gs_color_space **pcs_orig, | ||
1120 | const pdf_color_space_names_t *names, cos_value_t *cs_value) | ||
1121 | { | ||
1122 | int code=0; | ||
1123 | gs_color_space_index csi; | ||
1124 | gs_color_space_index csi2; | ||
1125 | const gs_color_space *pcs2 = pcs; | ||
1126 | |||
1127 | csi = csi2 = gs_color_space_get_index(pcs); | ||
1128 | if (csi == gs_color_space_index_ICC) { | ||
1129 | csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data); | ||
1130 | } | ||
1131 | /* Figure out what to do if we are outputting to really ancient versions of PDF */ | ||
1132 | /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */ | ||
1133 | if (pdev->CompatibilityLevel <= 1.2) { | ||
1134 | |||
1135 | /* If we have an /Indexed space, we need to look at the base space */ | ||
1136 | if (csi2 == gs_color_space_index_Indexed) { | ||
1137 | pcs2 = pcs->base_space; | ||
1138 | csi2 = gs_color_space_get_index(pcs2); | ||
1139 | } | ||
1140 | |||
1141 | switch (csi2) { | ||
1142 | case gs_color_space_index_DeviceGray: | ||
1143 | if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
1144 | pdev->params.ColorConversionStrategy == ccs_Gray) { | ||
1145 | return 0; | ||
1146 | } | ||
1147 | else { | ||
1148 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value); | ||
1149 | if (code < 0) | ||
1150 | return code; | ||
1151 | return 1; | ||
1152 | } | ||
1153 | break; | ||
1154 | case gs_color_space_index_DeviceRGB: | ||
1155 | if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
1156 | pdev->params.ColorConversionStrategy == ccs_RGB) | ||
1157 | return 0; | ||
1158 | else { | ||
1159 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value); | ||
1160 | if (code < 0) | ||
1161 | return code; | ||
1162 | return 1; | ||
1163 | } | ||
1164 | break; | ||
1165 | case gs_color_space_index_DeviceCMYK: | ||
1166 | if ((pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged || | ||
1167 | pdev->params.ColorConversionStrategy == ccs_CMYK) && !pdev->params.ConvertCMYKImagesToRGB) | ||
1168 | return 0; | ||
1169 | else { | ||
1170 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value); | ||
1171 | if (code < 0) | ||
1172 | return code; | ||
1173 | return 1; | ||
1174 | } | ||
1175 | break; | ||
1176 | case gs_color_space_index_CIEA: | ||
1177 | case gs_color_space_index_CIEABC: | ||
1178 | case gs_color_space_index_CIEDEF: | ||
1179 | case gs_color_space_index_CIEDEFG: | ||
1180 | case gs_color_space_index_Separation: | ||
1181 | if (pdev->ForOPDFRead) { | ||
1182 | switch (pdev->params.ColorConversionStrategy) { | ||
1183 | case ccs_ByObjectType: | ||
1184 | /* Object type not implemented yet */ | ||
1185 | case ccs_UseDeviceDependentColor: | ||
1186 | /* DeviceDependentColor deprecated */ | ||
1187 | case ccs_UseDeviceIndependentColorForImages: | ||
1188 | /* If only correcting images, then leave unchanged */ | ||
1189 | case ccs_LeaveColorUnchanged: | ||
1190 | if (csi2 == gs_color_space_index_Separation) | ||
1191 | return 0; | ||
1192 | /* Fall through and convert CIE to the device space */ | ||
1193 | default: | ||
1194 | switch (pdev->pcm_color_info_index) { | ||
1195 | case gs_color_space_index_DeviceGray: | ||
1196 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value); | ||
1197 | break; | ||
1198 | case gs_color_space_index_DeviceRGB: | ||
1199 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value); | ||
1200 | break; | ||
1201 | case gs_color_space_index_DeviceCMYK: | ||
1202 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value); | ||
1203 | break; | ||
1204 | default: | ||
1205 | emprintf(pdev->memory, "Unsupported ProcessColorModel."); | ||
1206 | return_error(gs_error_undefined); | ||
1207 | } | ||
1208 | if (code < 0) | ||
1209 | return code; | ||
1210 | return 1; | ||
1211 | break; | ||
1212 | } | ||
1213 | } | ||
1214 | else | ||
1215 | return 1; | ||
1216 | break; | ||
1217 | |||
1218 | case gs_color_space_index_ICC: | ||
1219 | /* Note that if csi is ICC, check to see if this was one of | ||
1220 | the default substitutes that we introduced for DeviceGray, | ||
1221 | DeviceRGB or DeviceCMYK. If it is, then just write | ||
1222 | the default color. Depending upon the flavor of PDF, | ||
1223 | or other options, we may want to actually have all | ||
1224 | the colors defined by ICC profiles and not do the following | ||
1225 | substituion of the Device space. */ | ||
1226 | csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
1227 | |||
1228 | switch (csi2) { | ||
1229 | case gs_color_space_index_DeviceGray: | ||
1230 | if (pdev->params.ColorConversionStrategy == ccs_Gray || | ||
1231 | pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) | ||
1232 | return 0; | ||
1233 | break; | ||
1234 | case gs_color_space_index_DeviceRGB: | ||
1235 | if (pdev->params.ColorConversionStrategy == ccs_RGB || | ||
1236 | pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) | ||
1237 | return 0; | ||
1238 | break; | ||
1239 | case gs_color_space_index_DeviceCMYK: | ||
1240 | if (pdev->params.ColorConversionStrategy == ccs_CMYK || | ||
1241 | pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged) | ||
1242 | return 0; | ||
1243 | break; | ||
1244 | default: | ||
1245 | break; | ||
1246 | } | ||
1247 | /* Fall through for non-handled cases */ | ||
1248 | case gs_color_space_index_DeviceN: | ||
1249 | case gs_color_space_index_DevicePixel: | ||
1250 | case gs_color_space_index_Indexed: | ||
1251 | switch (pdev->pcm_color_info_index) { | ||
1252 | case gs_color_space_index_DeviceGray: | ||
1253 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value); | ||
1254 | break; | ||
1255 | case gs_color_space_index_DeviceRGB: | ||
1256 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value); | ||
1257 | break; | ||
1258 | case gs_color_space_index_DeviceCMYK: | ||
1259 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value); | ||
1260 | break; | ||
1261 | default: | ||
1262 | emprintf(pdev->memory, "Unsupported ProcessColorModel."); | ||
1263 | return_error(gs_error_undefined); | ||
1264 | } | ||
1265 | if (code < 0) | ||
1266 | return code; | ||
1267 | return 1; | ||
1268 | break; | ||
1269 | default: | ||
1270 | return (gs_note_error(gs_error_rangecheck)); | ||
1271 | break; | ||
1272 | } | ||
1273 | } else { | ||
1274 | switch(pdev->params.ColorConversionStrategy) { | ||
1275 | case ccs_ByObjectType: | ||
1276 | /* Object type not implemented yet */ | ||
1277 | case ccs_UseDeviceDependentColor: | ||
1278 | /* DeviceDependentCOlor deprecated */ | ||
1279 | case ccs_UseDeviceIndependentColorForImages: | ||
1280 | /* If only correcting images, then leave unchanged */ | ||
1281 | case ccs_LeaveColorUnchanged: | ||
1282 | return 0; | ||
1283 | break; | ||
1284 | case ccs_sRGB: | ||
1285 | case ccs_UseDeviceIndependentColor: | ||
1286 | return 2; | ||
1287 | break; | ||
1288 | case ccs_CMYK: | ||
1289 | switch(csi2) { | ||
1290 | case gs_color_space_index_DeviceGray: | ||
1291 | case gs_color_space_index_DeviceCMYK: | ||
1292 | return 0; | ||
1293 | break; | ||
1294 | case gs_color_space_index_Separation: | ||
1295 | case gs_color_space_index_DeviceN: | ||
1296 | return 0; | ||
1297 | break; | ||
1298 | case gs_color_space_index_Indexed: | ||
1299 | pcs2 = pcs->base_space; | ||
1300 | csi = gs_color_space_get_index(pcs2); | ||
1301 | if (csi == gs_color_space_index_ICC) | ||
1302 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
1303 | switch(csi) { | ||
1304 | case gs_color_space_index_DeviceGray: | ||
1305 | case gs_color_space_index_DeviceCMYK: | ||
1306 | return 0; | ||
1307 | break; | ||
1308 | case gs_color_space_index_Separation: | ||
1309 | case gs_color_space_index_DeviceN: | ||
1310 | return 2; | ||
1311 | break; | ||
1312 | default: | ||
1313 | switch (pdev->pcm_color_info_index) { | ||
1314 | case gs_color_space_index_DeviceGray: | ||
1315 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value); | ||
1316 | break; | ||
1317 | case gs_color_space_index_DeviceRGB: | ||
1318 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value); | ||
1319 | break; | ||
1320 | case gs_color_space_index_DeviceCMYK: | ||
1321 | code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value); | ||
1322 | break; | ||
1323 | default: | ||
1324 | emprintf(pdev->memory, "Unsupported ProcessColorModel."); | ||
1325 | return_error(gs_error_undefined); | ||
1326 | } | ||
1327 | if (code < 0) | ||
1328 | return code; | ||
1329 | return 1; | ||
1330 | break; | ||
1331 | } | ||
1332 | break; | ||
1333 | default: | ||
1334 | return 0; | ||
1335 | break; | ||
1336 | } | ||
1337 | break; | ||
1338 | case ccs_Gray: | ||
1339 | switch(csi2) { | ||
1340 | case gs_color_space_index_DeviceGray: | ||
1341 | return 0; | ||
1342 | break; | ||
1343 | case gs_color_space_index_Separation: | ||
1344 | case gs_color_space_index_DeviceN: | ||
1345 | return 2; | ||
1346 | break; | ||
1347 | case gs_color_space_index_Indexed: | ||
1348 | pcs2 = pcs->base_space; | ||
1349 | csi = gs_color_space_get_index(pcs2); | ||
1350 | if (csi == gs_color_space_index_ICC) | ||
1351 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
1352 | switch(csi) { | ||
1353 | case gs_color_space_index_DeviceGray: | ||
1354 | return 0; | ||
1355 | break; | ||
1356 | case gs_color_space_index_Separation: | ||
1357 | case gs_color_space_index_DeviceN: | ||
1358 | return 2; | ||
1359 | break; | ||
1360 | default: | ||
1361 | return 0; | ||
1362 | break; | ||
1363 | } | ||
1364 | break; | ||
1365 | default: | ||
1366 | return 0; | ||
1367 | break; | ||
1368 | } | ||
1369 | break; | ||
1370 | case ccs_RGB: | ||
1371 | switch(csi2) { | ||
1372 | case gs_color_space_index_DeviceGray: | ||
1373 | case gs_color_space_index_DeviceRGB: | ||
1374 | return 0; | ||
1375 | break; | ||
1376 | case gs_color_space_index_Separation: | ||
1377 | case gs_color_space_index_DeviceN: | ||
1378 | return 2; | ||
1379 | break; | ||
1380 | case gs_color_space_index_Indexed: | ||
1381 | pcs2 = pcs->base_space; | ||
1382 | csi = gs_color_space_get_index(pcs2); | ||
1383 | if (csi == gs_color_space_index_ICC) | ||
1384 | csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data); | ||
1385 | switch(csi) { | ||
1386 | case gs_color_space_index_DeviceGray: | ||
1387 | case gs_color_space_index_DeviceRGB: | ||
1388 | return 0; | ||
1389 | break; | ||
1390 | case gs_color_space_index_Separation: | ||
1391 | case gs_color_space_index_DeviceN: | ||
1392 | return 2; | ||
1393 | break; | ||
1394 | default: | ||
1395 | return 0; | ||
1396 | break; | ||
1397 | } | ||
1398 | break; | ||
1399 | default: | ||
1400 | return 0; | ||
1401 | break; | ||
1402 | } | ||
1403 | break; | ||
1404 | default: | ||
1405 | break; | ||
1406 | } | ||
1407 | } | ||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1411 | static int | ||
1412 | new_pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis, | ||
1413 | const gs_matrix *pmat, const gs_image_common_t *pic, | ||
1414 | const gs_int_rect * prect, | ||
1415 | const gx_drawing_color * pdcolor, | ||
1416 | const gx_clip_path * pcpath, gs_memory_t * mem, | ||
1417 | gx_image_enum_common_t ** pinfo, | ||
1418 | pdf_typed_image_context_t context) | ||
1419 | { | ||
1420 | int code, i; | ||
1421 | unsigned int use_fallback = 0, in_line = 0, is_mask = 0, | ||
1422 | force_lossless = 0, convert_to_process_colors = 0, reduce_bits = 0; | ||
1423 | int width, height; | ||
1424 | cos_dict_t *pnamed = 0; | ||
1425 | image_union_t *image; | ||
1426 | const gs_pixel_image_t *pim; | ||
1427 | gs_int_rect rect; | ||
1428 | gs_image_format_t format; | ||
1429 | const gs_color_space *pcs; | ||
1430 | int num_components; | ||
1431 | pdf_image_enum *pie; | ||
1432 | const pdf_color_space_names_t *names; | ||
1433 | gs_color_space *pcs_orig = NULL; | ||
1434 | gs_color_space *pcs_device = NULL; | ||
1435 | cos_value_t cs_value; | ||
1436 | const gs_range_t *pranges = 0; | ||
1437 | |||
1438 | image = (image_union_t *)gs_malloc(mem->non_gc_memory, 4, | ||
1439 | sizeof(image_union_t), "pdf_begin_typed_image(image)"); | ||
1440 | if (image == 0) | ||
1441 | return_error(gs_error_VMerror); | ||
1442 | |||
1443 | /* | ||
1444 | * Pop the image name from the NI stack. We must do this, to keep the | ||
1445 | * stack in sync, even if it turns out we can't handle the image. | ||
1446 | */ | ||
1447 | { | ||
1448 | cos_value_t ni_value; | ||
1449 | |||
1450 | if (cos_array_unadd(pdev->NI_stack, &ni_value) >= 0) | ||
1451 | pnamed = (cos_dict_t *)ni_value.contents.object; | ||
1452 | } | ||
1453 | |||
1454 | /* An initialization for pdf_end_and_do_image : | ||
1455 | We need to delay adding the "Mask" entry into a type 3 image dictionary | ||
1456 | until the mask is completed due to equal image merging. */ | ||
1457 | pdev->image_mask_id = gs_no_id; | ||
1458 | |||
1459 | /* Check for the image types we can handle. */ | ||
1460 | switch (pic->type->index) { | ||
1461 | case 1: | ||
1462 | is_mask = ((const gs_image_t *)pic)->ImageMask; | ||
1463 | code = setup_type1_image(pdev, pic, pdcolor, image, context); | ||
1464 | if (code < 0) { | ||
1465 | use_fallback = 1; | ||
1466 | } | ||
1467 | else | ||
1468 | in_line = code; | ||
1469 | break; | ||
1470 | |||
1471 | case 3: | ||
1472 | pdev->image_mask_is_SMask = false; | ||
1473 | if (pdev->CompatibilityLevel < 1.2 || | ||
1474 | (prect && !(prect->p.x == 0 && prect->p.y == 0 && | ||
1475 | prect->q.x == ((const gs_image3_t *)pic)->Width && | ||
1476 | prect->q.y == ((const gs_image3_t *)pic)->Height))) { | ||
1477 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1478 | "pdf_begin_typed_image(image)"); | ||
1479 | return (gx_default_begin_typed_image((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, | ||
1480 | pcpath, mem, pinfo)); | ||
1481 | } | ||
1482 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1483 | "pdf_begin_typed_image(image)"); | ||
1484 | return (setup_type3_image(pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image)); | ||
1485 | break; | ||
1486 | |||
1487 | case IMAGE3X_IMAGETYPE: | ||
1488 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1489 | "pdf_begin_typed_image(image)"); | ||
1490 | if (pdev->CompatibilityLevel < 1.4 || | ||
1491 | (prect && !(prect->p.x == 0 && prect->p.y == 0 && | ||
1492 | prect->q.x == ((const gs_image3x_t *)pic)->Width && | ||
1493 | prect->q.y == ((const gs_image3x_t *)pic)->Height))) { | ||
1494 | return (gx_default_begin_typed_image((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, | ||
1495 | pcpath, mem, pinfo)); | ||
1496 | } | ||
1497 | pdev->image_mask_is_SMask = true; | ||
1498 | return gx_begin_image3x_generic((gx_device *)pdev, pis, pmat, pic, | ||
1499 | prect, pdcolor, pcpath, mem, | ||
1500 | pdf_image3x_make_mid, | ||
1501 | pdf_image3x_make_mcde, pinfo); | ||
1502 | break; | ||
1503 | |||
1504 | case 4: | ||
1505 | code = convert_type4_image(pdev, pis, pmat, pic, prect, pdcolor, | ||
1506 | pcpath, mem, pinfo, context, image, pnamed); | ||
1507 | if (code < 0) { | ||
1508 | use_fallback = 1; | ||
1509 | } | ||
1510 | if (code == 0) { | ||
1511 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1512 | "pdf_begin_typed_image(image)"); | ||
1513 | return code; | ||
1514 | } | ||
1515 | /* No luck. Masked images require PDF 1.3 or higher. */ | ||
1516 | if (pdev->CompatibilityLevel < 1.2) { | ||
1517 | use_fallback = 1; | ||
1518 | } | ||
1519 | if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) { | ||
1520 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1521 | "pdf_begin_typed_image(image)"); | ||
1522 | return (convert_type4_to_masked_image(pdev, pis, pic, prect, pdcolor, | ||
1523 | pcpath, mem,pinfo)); | ||
1524 | } | ||
1525 | image[0].type4 = *(const gs_image4_t *)pic; | ||
1526 | break; | ||
1527 | |||
1528 | default: | ||
1529 | use_fallback = 1; | ||
1530 | break; | ||
1531 | } | ||
1532 | |||
1533 | pim = (const gs_pixel_image_t *)pic; | ||
1534 | format = pim->format; | ||
1535 | switch (format) { | ||
1536 | case gs_image_format_chunky: | ||
1537 | case gs_image_format_component_planar: | ||
1538 | break; | ||
1539 | default: | ||
1540 | use_fallback = 1; | ||
1541 | } | ||
1542 | /* AR5 on Windows doesn't support 0-size images. Skipping. */ | ||
1543 | if (pim->Width == 0 || pim->Height == 0) | ||
1544 | use_fallback = 1; | ||
1545 | /* PDF doesn't support images with more than 8 bits per component. */ | ||
1546 | switch (pim->BitsPerComponent) { | ||
1547 | case 1: | ||
1548 | case 2: | ||
1549 | case 4: | ||
1550 | case 8: | ||
1551 | break; | ||
1552 | case 12: | ||
1553 | case 16: | ||
1554 | use_fallback = 1; | ||
1555 | // reduce_bits = pim->BitsPerComponent; | ||
1556 | break; | ||
1557 | default: | ||
1558 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1559 | "pdf_begin_typed_image(image)"); | ||
1560 | return_error(gs_error_rangecheck); | ||
1561 | } | ||
1562 | if (prect) | ||
1563 | rect = *prect; | ||
1564 | else { | ||
1565 | rect.p.x = rect.p.y = 0; | ||
1566 | rect.q.x = pim->Width, rect.q.y = pim->Height; | ||
1567 | } | ||
1568 | if (rect.p.x != 0 || rect.p.y != 0 || | ||
1569 | rect.q.x != pim->Width || rect.q.y != pim->Height || | ||
1570 | (is_mask && pim->CombineWithColor)) | ||
1571 | use_fallback = 1; | ||
1572 | |||
1573 | if (use_fallback) { | ||
1574 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1575 | "pdf_begin_typed_image(image)"); | ||
1576 | return gx_default_begin_typed_image | ||
1577 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, | ||
1578 | pinfo); | ||
1579 | } | ||
1580 | |||
1581 | pcs = pim->ColorSpace; | ||
1582 | num_components = (is_mask ? 1 : gs_color_space_num_components(pcs)); | ||
1583 | |||
1584 | if (pdf_must_put_clip_path(pdev, pcpath)) | ||
1585 | code = pdf_unclip(pdev); | ||
1586 | else | ||
1587 | code = pdf_open_page(pdev, PDF_IN_STREAM); | ||
1588 | if (code < 0) { | ||
1589 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1590 | "pdf_begin_typed_image(image)"); | ||
1591 | return gx_default_begin_typed_image | ||
1592 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, | ||
1593 | pinfo); | ||
1594 | } | ||
1595 | |||
1596 | if (context == PDF_IMAGE_TYPE3_MASK) { | ||
1597 | /* | ||
1598 | * The soft mask for an ImageType 3x image uses a DevicePixel | ||
1599 | * color space, which pdf_color_space() can't handle. Patch it | ||
1600 | * to DeviceGray here. | ||
1601 | */ | ||
1602 | /* {csrc} make sure this gets freed */ | ||
1603 | pcs = gs_cspace_new_DeviceGray(pdev->memory); | ||
1604 | } else if (is_mask) | ||
1605 | code = pdf_prepare_imagemask(pdev, pis, pdcolor); | ||
1606 | else | ||
1607 | code = pdf_prepare_image(pdev, pis); | ||
1608 | if (code < 0) { | ||
1609 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1610 | "pdf_begin_typed_image(image)"); | ||
1611 | return gx_default_begin_typed_image | ||
1612 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, | ||
1613 | pinfo); | ||
1614 | } | ||
1615 | |||
1616 | pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum, | ||
1617 | "pdf_begin_image"); | ||
1618 | if (pie == 0) { | ||
1619 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1620 | "pdf_begin_typed_image(image)"); | ||
1621 | return_error(gs_error_VMerror); | ||
1622 | } | ||
1623 | memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */ | ||
1624 | *pinfo = (gx_image_enum_common_t *) pie; | ||
1625 | gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim, | ||
1626 | ((pdev->CompatibilityLevel >= 1.3) ? | ||
1627 | (context == PDF_IMAGE_TYPE3_MASK ? | ||
1628 | &pdf_image_object_enum_procs : | ||
1629 | &pdf_image_enum_procs) : | ||
1630 | context == PDF_IMAGE_TYPE3_MASK ? | ||
1631 | &pdf_image_object_enum_procs : | ||
1632 | context == PDF_IMAGE_TYPE3_DATA ? | ||
1633 | &pdf_image_object_enum_procs2 : | ||
1634 | &pdf_image_enum_procs), | ||
1635 | (gx_device *)pdev, num_components, format); | ||
1636 | pie->memory = mem; | ||
1637 | width = rect.q.x - rect.p.x; | ||
1638 | pie->width = width; | ||
1639 | height = rect.q.y - rect.p.y; | ||
1640 | pie->bits_per_pixel = | ||
1641 | (reduce_bits ? reduce_bits : pim->BitsPerComponent) * num_components / pie->num_planes; | ||
1642 | pie->rows_left = height; | ||
1643 | if (pnamed != 0) /* Don't in-line the image if it is named. */ | ||
1644 | in_line = false; | ||
1645 | else { | ||
1646 | double nbytes = (double)(((ulong) pie->width * pie->bits_per_pixel + 7) >> 3) * | ||
1647 | pie->num_planes * pie->rows_left; | ||
1648 | |||
1649 | in_line &= (nbytes < pdev->MaxInlineImageSize); | ||
1650 | } | ||
1651 | |||
1652 | if (pmat == 0) | ||
1653 | pmat = &ctm_only(pis); | ||
1654 | { | ||
1655 | gs_matrix mat; | ||
1656 | gs_matrix bmat; | ||
1657 | int code; | ||
1658 | |||
1659 | pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y, | ||
1660 | pim->Width, pim->Height, height); | ||
1661 | if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 || | ||
1662 | (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 || | ||
1663 | (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0 | ||
1664 | ) { | ||
1665 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1666 | "pdf_begin_typed_image(image)"); | ||
1667 | gs_free_object(mem, pie, "pdf_begin_image"); | ||
1668 | return code; | ||
1669 | } | ||
1670 | /* AR3,AR4 show no image when CTM is singular; AR5 reports an error */ | ||
1671 | if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx) | ||
1672 | goto fail_and_fallback; | ||
1673 | } | ||
1674 | |||
1675 | code = pdf_put_clip_path(pdev, pcpath); | ||
1676 | if (code < 0) { | ||
1677 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1678 | "pdf_begin_typed_image(image)"); | ||
1679 | gs_free_object(mem, pie, "pdf_begin_image"); | ||
1680 | return code; | ||
1681 | } | ||
1682 | pdf_image_writer_init(&pie->writer); | ||
1683 | /* Note : Possible values for alt_writer_count are 1,2,3,4. | ||
1684 | 1 means no alternative streams. | ||
1685 | 2 means the main image stream and a mask stream while converting | ||
1686 | an Image Type 4. | ||
1687 | 3 means the main image stream, alternative image compression stream, | ||
1688 | and the compression chooser. | ||
1689 | 4 meams 3 and a mask stream while convertingh an Image Type 4. | ||
1690 | */ | ||
1691 | pie->writer.alt_writer_count = (in_line || | ||
1692 | (pim->Width <= 64 && pim->Height <= 64) | ||
1693 | ? 1 : 2); | ||
1694 | if ((image[0].pixel.ColorSpace != NULL && | ||
1695 | image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed | ||
1696 | && pdev->params.ColorImage.DownsampleType != ds_Subsample) || | ||
1697 | pdev->transfer_not_identity) | ||
1698 | force_lossless = true; | ||
1699 | |||
1700 | names = (in_line ? &pdf_color_space_names_short : &pdf_color_space_names); | ||
1701 | |||
1702 | /* We don't want to change the colour space of a mask, or an SMask (both of which are Gray) */ | ||
1703 | if (!is_mask) { | ||
1704 | if (image[0].pixel.ColorSpace != NULL && !(context == PDF_IMAGE_TYPE3_MASK)) | ||
1705 | convert_to_process_colors = setup_image_colorspace(pdev, &image[0], pcs, &pcs_orig, names, &cs_value); | ||
1706 | if (convert_to_process_colors == 1) { | ||
1707 | code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device); | ||
1708 | if (code < 0) | ||
1709 | goto fail_and_fallback; | ||
1710 | image[0].pixel.ColorSpace = pcs_device; | ||
1711 | code = pdf_color_space_named(pdev, &cs_value, &pranges, pcs_device, names, | ||
1712 | in_line, NULL, 0); | ||
1713 | if (code < 0) | ||
1714 | goto fail_and_fallback; | ||
1715 | } else { | ||
1716 | if (pcs->cmm_icc_profile_data != NULL && | ||
1717 | pcs->cmm_icc_profile_data->islab) { | ||
1718 | gscms_set_icc_range((cmm_profile_t **)&(pcs->cmm_icc_profile_data)); | ||
1719 | } | ||
1720 | code = pdf_color_space_named(pdev, &cs_value, &pranges, pcs, names, | ||
1721 | in_line, NULL, 0); | ||
1722 | if (code < 0) | ||
1723 | goto fail_and_fallback; | ||
1724 | } | ||
1725 | } | ||
1726 | |||
1727 | image[1] = image[0]; | ||
1728 | |||
1729 | pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel; | ||
1730 | |||
1731 | code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width, | ||
1732 | height, pnamed, in_line); | ||
1733 | if (code < 0) | ||
1734 | goto fail_and_fallback; | ||
1735 | |||
1736 | /* Code below here deals with setting up the multiple data stream writing. | ||
1737 | * We can have up to 4 stream writers, which we keep in an array. We must | ||
1738 | * always have at least one which writes the uncompressed stream. If we | ||
1739 | * are writing compressed streams, we have one for the compressed stream | ||
1740 | * and one for the compression chooser. | ||
1741 | * For type 4 images being converted (for old versions of PDF or for ps2write) | ||
1742 | * we need an additional stream to write a mask, which masks the real | ||
1743 | * image. | ||
1744 | * For colour conversion we will place an additional filter in front of all | ||
1745 | * the streams which does the conversion. | ||
1746 | */ | ||
1747 | if (in_line) { | ||
1748 | code = new_setup_lossless_filters((gx_device_psdf *) pdev, | ||
1749 | &pie->writer.binary[0], | ||
1750 | &image[0].pixel, in_line, convert_to_process_colors); | ||
1751 | } else { | ||
1752 | if (force_lossless) { | ||
1753 | /* | ||
1754 | * Some regrettable PostScript code (such as LanguageLevel 1 output | ||
1755 | * from Microsoft's PSCRIPT.DLL driver) misuses the transfer | ||
1756 | * function to accomplish the equivalent of indexed color. | ||
1757 | * Downsampling (well, only averaging) or JPEG compression are not | ||
1758 | * compatible with this. Play it safe by using only lossless | ||
1759 | * filters if the transfer function(s) is/are other than the | ||
1760 | * identity and by setting the downsample type to Subsample.. | ||
1761 | */ | ||
1762 | int saved_downsample = pdev->params.ColorImage.DownsampleType; | ||
1763 | |||
1764 | pdev->params.ColorImage.DownsampleType = ds_Subsample; | ||
1765 | code = new_setup_image_filters((gx_device_psdf *) pdev, | ||
1766 | &pie->writer.binary[0], &image[0].pixel, | ||
1767 | pmat, pis, true, in_line, convert_to_process_colors); | ||
1768 | pdev->params.ColorImage.DownsampleType = saved_downsample; | ||
1769 | } else { | ||
1770 | code = new_setup_image_filters((gx_device_psdf *) pdev, | ||
1771 | &pie->writer.binary[0], &image[0].pixel, | ||
1772 | pmat, pis, true, in_line, convert_to_process_colors); | ||
1773 | } | ||
1774 | } | ||
1775 | |||
1776 | if (code < 0) | ||
1777 | goto fail_and_fallback; | ||
1778 | |||
1779 | if (convert_to_process_colors) { | ||
1780 | image[0].pixel.ColorSpace = pcs_orig; | ||
1781 | code = psdf_setup_image_colors_filter(&pie->writer.binary[0], | ||
1782 | (gx_device_psdf *)pdev, &image[0].pixel, pis); | ||
1783 | if (code < 0) | ||
1784 | goto fail_and_fallback; | ||
1785 | image[0].pixel.ColorSpace = pcs_device; | ||
1786 | } | ||
1787 | |||
1788 | if (reduce_bits) { | ||
1789 | code = new_resize_input(&pie->writer.binary[0], pim->Width, gs_color_space_num_components(pim->ColorSpace), reduce_bits, 8); | ||
1790 | if (code < 0) | ||
1791 | goto fail_and_fallback; | ||
1792 | } | ||
1793 | |||
1794 | if (pie->writer.alt_writer_count > 1) { | ||
1795 | code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]); | ||
1796 | if (code) { | ||
1797 | goto fail_and_fallback; | ||
1798 | } | ||
1799 | code = new_setup_image_filters((gx_device_psdf *) pdev, | ||
1800 | &pie->writer.binary[1], &image[1].pixel, | ||
1801 | pmat, pis, force_lossless, in_line, convert_to_process_colors); | ||
1802 | if (code == gs_error_rangecheck) { | ||
1803 | |||
1804 | for (i=1;i < pie->writer.alt_writer_count; i++) { | ||
1805 | stream *s = pie->writer.binary[i].strm; | ||
1806 | cos_stream_t *pcos = cos_stream_from_pipeline(pie->writer.binary[i].strm); | ||
1807 | s_close_filters(&s, NULL); | ||
1808 | gs_free_object(pdev->pdf_memory, s, "compressed image stream"); | ||
1809 | pcos->cos_procs->release((cos_object_t *)pcos, "pdf_begin_typed_image_impl"); | ||
1810 | gs_free_object(pdev->pdf_memory, pcos, "compressed image cos_stream"); | ||
1811 | } | ||
1812 | /* setup_image_compression rejected the alternative compression. */ | ||
1813 | pie->writer.alt_writer_count = 1; | ||
1814 | memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1])); | ||
1815 | memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1])); | ||
1816 | } else if (code) { | ||
1817 | goto fail_and_fallback; | ||
1818 | } else if (convert_to_process_colors) { | ||
1819 | image[1].pixel.ColorSpace = pcs_orig; | ||
1820 | code = psdf_setup_image_colors_filter(&pie->writer.binary[1], | ||
1821 | (gx_device_psdf *)pdev, &image[1].pixel, pis); | ||
1822 | if (code < 0) { | ||
1823 | goto fail_and_fallback; | ||
1824 | } | ||
1825 | image[1].pixel.ColorSpace = pcs_device; | ||
1826 | } | ||
1827 | if (reduce_bits) { | ||
1828 | code = new_resize_input(&pie->writer.binary[0], pim->Width, gs_color_space_num_components(pim->ColorSpace), reduce_bits, 8); | ||
1829 | if (code < 0) | ||
1830 | goto fail_and_fallback; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | for (i = 0; i < pie->writer.alt_writer_count; i++) { | ||
1835 | code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i, | ||
1836 | &image[i].pixel, &cs_value, pie); | ||
1837 | if (code < 0) | ||
1838 | goto fail_and_fallback; | ||
1839 | } | ||
1840 | if (pie->writer.alt_writer_count == 2) { | ||
1841 | psdf_setup_compression_chooser(&pie->writer.binary[2], | ||
1842 | (gx_device_psdf *)pdev, pim->Width, pim->Height, | ||
1843 | num_components, pim->BitsPerComponent); | ||
1844 | pie->writer.alt_writer_count = 3; | ||
1845 | } | ||
1846 | if (pic->type->index == 4 && pdev->CompatibilityLevel < 1.3) { | ||
1847 | int i; | ||
1848 | |||
1849 | /* Create a stream for writing the mask. */ | ||
1850 | i = pie->writer.alt_writer_count; | ||
1851 | gs_image_t_init_mask_adjust((gs_image_t *)&image[i].type1, true, false); | ||
1852 | image[i].type1.Width = image[0].pixel.Width; | ||
1853 | image[i].type1.Height = image[0].pixel.Height; | ||
1854 | /* Won't use image[2]. */ | ||
1855 | code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width, | ||
1856 | height, NULL, false); | ||
1857 | if (code) | ||
1858 | goto fail_and_fallback; | ||
1859 | code = psdf_setup_image_filters((gx_device_psdf *) pdev, | ||
1860 | &pie->writer.binary[i], &image[i].pixel, | ||
1861 | pmat, pis, force_lossless, in_line); | ||
1862 | if (code < 0) | ||
1863 | goto fail_and_fallback; | ||
1864 | psdf_setup_image_to_mask_filter(&pie->writer.binary[i], | ||
1865 | (gx_device_psdf *)pdev, pim->Width, pim->Height, | ||
1866 | num_components, pim->BitsPerComponent, image[i].type4.MaskColor); | ||
1867 | code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i, | ||
1868 | &image[i].pixel, &cs_value, pie); | ||
1869 | if (code < 0) | ||
1870 | goto fail_and_fallback; | ||
1871 | ++pie->writer.alt_writer_count; | ||
1872 | } | ||
1873 | |||
1874 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1875 | "pdf_begin_typed_image(image)"); | ||
1876 | return 0; | ||
1877 | |||
1878 | fail_and_fallback: | ||
1879 | gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), | ||
1880 | "pdf_begin_typed_image(image)"); | ||
1881 | gs_free_object(mem, pie, "pdf_begin_image"); | ||
1882 | return gx_default_begin_typed_image | ||
1883 | ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, | ||
1884 | pinfo); | ||
1885 | } | ||
1886 | |||
1887 | static int pdf_begin_typed_image(gx_device_pdf *pdev, | ||
1888 | const gs_imager_state * pis, const gs_matrix *pmat, | ||
1889 | const gs_image_common_t *pic, const gs_int_rect * prect, | ||
1890 | const gx_drawing_color * pdcolor, const gx_clip_path * pcpath, | ||
1891 | gs_memory_t * mem, gx_image_enum_common_t ** pinfo, | ||
1892 | pdf_typed_image_context_t context) | ||
1893 | { | ||
1894 | if (!pdev->UseOldColor) { | ||
1895 | return new_pdf_begin_typed_image(pdev, pis, pmat, pic, prect, | ||
1896 | pdcolor, pcpath, mem, pinfo, | ||
1897 | context); | ||
1898 | } else { | ||
1899 | return old_pdf_begin_typed_image(pdev, pis, pmat, pic, prect, | ||
1900 | pdcolor, pcpath, mem, pinfo, | ||
1901 | context); | ||
1902 | } | ||
1903 | } | ||
1904 | |||
927 | int | 1905 | int |
928 | gdev_pdf_begin_typed_image(gx_device * dev, const gs_imager_state * pis, | 1906 | gdev_pdf_begin_typed_image(gx_device * dev, const gs_imager_state * pis, |
929 | const gs_matrix *pmat, const gs_image_common_t *pic, | 1907 | const gs_matrix *pmat, const gs_image_common_t *pic, |
diff --git a/gs/base/gdevpdfk.c b/gs/base/gdevpdfk.c index 3e5092d5d..b54a0d7a3 100644 --- a/gs/base/gdevpdfk.c +++ b/gs/base/gdevpdfk.c | |||
@@ -271,6 +271,10 @@ pdf_make_iccbased(gx_device_pdf *pdev, cos_array_t *pca, int ncomps, | |||
271 | bool scale_inputs = false; | 271 | bool scale_inputs = false; |
272 | int i; | 272 | int i; |
273 | 273 | ||
274 | /* This code makes no sense to me, and if I remove it we get better | ||
275 | * results. So we'll chop it out for the new colour work. | ||
276 | */ | ||
277 | if (pdev->UseOldColor) { | ||
274 | /* Check the ranges. */ | 278 | /* Check the ranges. */ |
275 | if (pprange) | 279 | if (pprange) |
276 | *pprange = 0; | 280 | *pprange = 0; |
@@ -287,6 +291,7 @@ pdf_make_iccbased(gx_device_pdf *pdev, cos_array_t *pca, int ncomps, | |||
287 | else if (rmin > 0.0 || rmax < 1.0) | 291 | else if (rmin > 0.0 || rmax < 1.0) |
288 | std_ranges = false; | 292 | std_ranges = false; |
289 | } | 293 | } |
294 | } | ||
290 | 295 | ||
291 | /* Range values are a bit tricky to check. | 296 | /* Range values are a bit tricky to check. |
292 | For example, CIELAB ICC profiles have | 297 | For example, CIELAB ICC profiles have |
diff --git a/gs/base/gdevpdfp.c b/gs/base/gdevpdfp.c index 7e12fe111..e86424c40 100644 --- a/gs/base/gdevpdfp.c +++ b/gs/base/gdevpdfp.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "gdevpdfo.h" | 22 | #include "gdevpdfo.h" |
23 | #include "gdevpdfg.h" | 23 | #include "gdevpdfg.h" |
24 | #include "gsparamx.h" | 24 | #include "gsparamx.h" |
25 | #include "gsicc_manage.h" | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * The pdfwrite device supports the following "real" parameters: | 28 | * The pdfwrite device supports the following "real" parameters: |
@@ -125,6 +126,7 @@ static const gs_param_item_t pdf_param_items[] = { | |||
125 | pi("PreserveSMask", gs_param_type_bool, PreserveSMask), | 126 | pi("PreserveSMask", gs_param_type_bool, PreserveSMask), |
126 | pi("PreserveTrMode", gs_param_type_bool, PreserveTrMode), | 127 | pi("PreserveTrMode", gs_param_type_bool, PreserveTrMode), |
127 | pi("NoT3CCITT", gs_param_type_bool, NoT3CCITT), | 128 | pi("NoT3CCITT", gs_param_type_bool, NoT3CCITT), |
129 | pi("PDFUseOldCMS", gs_param_type_bool, UseOldColor), | ||
128 | pi("FastWebView", gs_param_type_bool, Linearise), | 130 | pi("FastWebView", gs_param_type_bool, Linearise), |
129 | pi("FirstPage", gs_param_type_int, FirstPage), | 131 | pi("FirstPage", gs_param_type_int, FirstPage), |
130 | pi("LastPage", gs_param_type_int, LastPage), | 132 | pi("LastPage", gs_param_type_int, LastPage), |
@@ -508,30 +510,70 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par | |||
508 | ecode = gdev_psdf_put_params(dev, plist); | 510 | ecode = gdev_psdf_put_params(dev, plist); |
509 | if (ecode < 0) | 511 | if (ecode < 0) |
510 | goto fail; | 512 | goto fail; |
511 | if ((pdev->params.ColorConversionStrategy == ccs_CMYK && | 513 | if (!pdev->UseOldColor) { |
512 | strcmp(pdev->color_info.cm_name, "DeviceCMYK")) || | 514 | if (pdev->params.ConvertCMYKImagesToRGB) { |
513 | (pdev->params.ColorConversionStrategy == ccs_sRGB && | 515 | if (pdev->params.ColorConversionStrategy == ccs_CMYK) { |
514 | strcmp(pdev->color_info.cm_name, "DeviceRGB")) || | 516 | emprintf(pdev->memory, "ConvertCMYKImagesToRGB is not compatible with ColorConversionStrategy of CMYK\n"); |
515 | (pdev->params.ColorConversionStrategy == ccs_Gray && | 517 | } else { |
516 | strcmp(pdev->color_info.cm_name, "DeviceGray"))) { | 518 | if (pdev->params.ColorConversionStrategy == ccs_Gray) { |
517 | emprintf(pdev->memory, | 519 | emprintf(pdev->memory, "ConvertCMYKImagesToRGB is not compatible with ColorConversionStrategy of Gray\n"); |
518 | "ColorConversionStrategy is incompatible to ProcessColorModel.\n"); | 520 | } else { |
519 | ecode = gs_note_error(gs_error_rangecheck); | 521 | if (pdev->icc_struct) |
520 | pdev->params.ColorConversionStrategy = save_ccs; | 522 | rc_decrement(pdev->icc_struct, |
521 | } | 523 | "reset default profile\n"); |
522 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceIndependentColor) { | 524 | pdf_set_process_color_model(pdev,1); |
523 | if (!pdev->UseCIEColor) { | 525 | code = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0); |
526 | } | ||
527 | } | ||
528 | } | ||
529 | switch (pdev->params.ColorConversionStrategy) { | ||
530 | case ccs_LeaveColorUnchanged: | ||
531 | case ccs_UseDeviceDependentColor: | ||
532 | case ccs_UseDeviceIndependentColor: | ||
533 | case ccs_UseDeviceIndependentColorForImages: | ||
534 | case ccs_ByObjectType: | ||
535 | case ccs_sRGB: | ||
536 | break; | ||
537 | case ccs_CMYK: | ||
538 | if (pdev->icc_struct) | ||
539 | rc_decrement(pdev->icc_struct, | ||
540 | "reset default profile\n"); | ||
541 | pdf_set_process_color_model(pdev, 2); | ||
542 | code = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0); | ||
543 | break; | ||
544 | case ccs_Gray: | ||
545 | if (pdev->icc_struct) | ||
546 | rc_decrement(pdev->icc_struct, | ||
547 | "reset default profile\n"); | ||
548 | pdf_set_process_color_model(pdev,0); | ||
549 | code = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0); | ||
550 | break; | ||
551 | case ccs_RGB: | ||
552 | /* Only bother to do this if we didn't handle it above */ | ||
553 | if (!pdev->params.ConvertCMYKImagesToRGB) { | ||
554 | if (pdev->icc_struct) | ||
555 | rc_decrement(pdev->icc_struct, | ||
556 | "reset default profile\n"); | ||
557 | pdf_set_process_color_model(pdev,1); | ||
558 | code = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0); | ||
559 | } | ||
560 | break; | ||
561 | default: | ||
562 | break; | ||
563 | } | ||
564 | } else { | ||
565 | if ((pdev->params.ColorConversionStrategy == ccs_CMYK && | ||
566 | strcmp(pdev->color_info.cm_name, "DeviceCMYK")) || | ||
567 | (pdev->params.ColorConversionStrategy == ccs_sRGB && | ||
568 | strcmp(pdev->color_info.cm_name, "DeviceRGB")) || | ||
569 | (pdev->params.ColorConversionStrategy == ccs_Gray && | ||
570 | strcmp(pdev->color_info.cm_name, "DeviceGray"))) { | ||
524 | emprintf(pdev->memory, | 571 | emprintf(pdev->memory, |
525 | "Set UseCIEColor for UseDeviceIndependentColor to work properly.\n"); | 572 | "ColorConversionStrategy is incompatible to ProcessColorModel.\n"); |
526 | ecode = gs_note_error(gs_error_rangecheck); | 573 | ecode = gs_note_error(gs_error_rangecheck); |
527 | pdev->UseCIEColor = true; | 574 | pdev->params.ColorConversionStrategy = save_ccs; |
528 | } | 575 | } |
529 | } | 576 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceIndependentColor) { |
530 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceIndependentColorForImages) { | ||
531 | if (!pdev->UseCIEColor) { | ||
532 | emprintf(pdev->memory, | ||
533 | "UseDeviceDependentColorForImages is not supported. Use UseDeviceIndependentColor.\n"); | ||
534 | pdev->params.ColorConversionStrategy = ccs_UseDeviceIndependentColor; | ||
535 | if (!pdev->UseCIEColor) { | 577 | if (!pdev->UseCIEColor) { |
536 | emprintf(pdev->memory, | 578 | emprintf(pdev->memory, |
537 | "Set UseCIEColor for UseDeviceIndependentColor to work properly.\n"); | 579 | "Set UseCIEColor for UseDeviceIndependentColor to work properly.\n"); |
@@ -539,20 +581,33 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par | |||
539 | pdev->UseCIEColor = true; | 581 | pdev->UseCIEColor = true; |
540 | } | 582 | } |
541 | } | 583 | } |
542 | } | 584 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceIndependentColorForImages) { |
543 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceDependentColor) { | 585 | if (!pdev->UseCIEColor) { |
544 | if (!strcmp(pdev->color_info.cm_name, "DeviceCMYK")) { | 586 | emprintf(pdev->memory, |
545 | emprintf(pdev->memory, | 587 | "UseDeviceDependentColorForImages is not supported. Use UseDeviceIndependentColor.\n"); |
546 | "Replacing the deprecated device parameter value UseDeviceDependentColor with CMYK.\n"); | 588 | pdev->params.ColorConversionStrategy = ccs_UseDeviceIndependentColor; |
547 | pdev->params.ColorConversionStrategy = ccs_CMYK; | 589 | if (!pdev->UseCIEColor) { |
548 | } else if (!strcmp(pdev->color_info.cm_name, "DeviceRGB")) { | 590 | emprintf(pdev->memory, |
549 | emprintf(pdev->memory, | 591 | "Set UseCIEColor for UseDeviceIndependentColor to work properly.\n"); |
550 | "Replacing the deprecated device parameter value UseDeviceDependentColor with sRGB.\n"); | 592 | ecode = gs_note_error(gs_error_rangecheck); |
551 | pdev->params.ColorConversionStrategy = ccs_sRGB; | 593 | pdev->UseCIEColor = true; |
552 | } else { | 594 | } |
553 | emprintf(pdev->memory, | 595 | } |
554 | "Replacing the deprecated device parameter value UseDeviceDependentColor with Gray.\n"); | 596 | } |
555 | pdev->params.ColorConversionStrategy = ccs_Gray; | 597 | if (pdev->params.ColorConversionStrategy == ccs_UseDeviceDependentColor) { |
598 | if (!strcmp(pdev->color_info.cm_name, "DeviceCMYK")) { | ||
599 | emprintf(pdev->memory, | ||
600 | "Replacing the deprecated device parameter value UseDeviceDependentColor with CMYK.\n"); | ||
601 | pdev->params.ColorConversionStrategy = ccs_CMYK; | ||
602 | } else if (!strcmp(pdev->color_info.cm_name, "DeviceRGB")) { | ||
603 | emprintf(pdev->memory, | ||
604 | "Replacing the deprecated device parameter value UseDeviceDependentColor with sRGB.\n"); | ||
605 | pdev->params.ColorConversionStrategy = ccs_sRGB; | ||
606 | } else { | ||
607 | emprintf(pdev->memory, | ||
608 | "Replacing the deprecated device parameter value UseDeviceDependentColor with Gray.\n"); | ||
609 | pdev->params.ColorConversionStrategy = ccs_Gray; | ||
610 | } | ||
556 | } | 611 | } |
557 | } | 612 | } |
558 | if (cl < 1.5 && pdev->params.ColorImage.Filter != NULL && | 613 | if (cl < 1.5 && pdev->params.ColorImage.Filter != NULL && |
diff --git a/gs/base/gdevpdfx.h b/gs/base/gdevpdfx.h index bc0545d9e..7a444433a 100644 --- a/gs/base/gdevpdfx.h +++ b/gs/base/gdevpdfx.h | |||
@@ -842,6 +842,9 @@ struct gx_device_pdf_s { | |||
842 | * This parameter is present only to allow | 842 | * This parameter is present only to allow |
843 | * ps2write output to work on those pritners. | 843 | * ps2write output to work on those pritners. |
844 | */ | 844 | */ |
845 | bool UseOldColor; /* Use the old pdfwrite colour conversions instead of the CMS | ||
846 | * temporary variable | ||
847 | */ | ||
845 | bool Linearise; /* Whether to Linearizse the file, the next 2 parameter | 848 | bool Linearise; /* Whether to Linearizse the file, the next 2 parameter |
846 | * are only used if this is true. | 849 | * are only used if this is true. |
847 | */ | 850 | */ |
@@ -859,8 +862,6 @@ struct gx_device_pdf_s { | |||
859 | 862 | ||
860 | #define is_in_page(pdev)\ | 863 | #define is_in_page(pdev)\ |
861 | ((pdev)->contents_id != 0) | 864 | ((pdev)->contents_id != 0) |
862 | #define is_in_document(pdev)\ | ||
863 | (is_in_page(pdev) || (pdev)->last_resource != 0) | ||
864 | 865 | ||
865 | /* Enumerate the individual pointers in a gx_device_pdf. */ | 866 | /* Enumerate the individual pointers in a gx_device_pdf. */ |
866 | #define gx_device_pdf_do_ptrs(m)\ | 867 | #define gx_device_pdf_do_ptrs(m)\ |
diff --git a/gs/base/gdevpsdf.h b/gs/base/gdevpsdf.h index 8fefe6237..a71ff70ea 100644 --- a/gs/base/gdevpsdf.h +++ b/gs/base/gdevpsdf.h | |||
@@ -116,12 +116,15 @@ typedef struct psdf_distiller_params_s { | |||
116 | ccs_UseDeviceIndependentColorForImages, | 116 | ccs_UseDeviceIndependentColorForImages, |
117 | ccs_sRGB, | 117 | ccs_sRGB, |
118 | ccs_CMYK, | 118 | ccs_CMYK, |
119 | ccs_Gray | 119 | ccs_Gray, |
120 | ccs_RGB, | ||
121 | ccs_ByObjectType | ||
120 | } ColorConversionStrategy; | 122 | } ColorConversionStrategy; |
121 | #define psdf_ccs_names\ | 123 | #define psdf_ccs_names\ |
122 | "LeaveColorUnchanged", "UseDeviceDependentColor",\ | 124 | "LeaveColorUnchanged", "UseDeviceDependentColor",\ |
123 | "UseDeviceIndependentColor", "UseDeviceIndependentColorForImages",\ | 125 | "UseDeviceIndependentColor", "UseDeviceIndependentColorForImages",\ |
124 | "sRGB", "CMYK", "Gray" | 126 | "sRGB", "CMYK", "Gray", "RGB", "ByObjectType" |
127 | |||
125 | bool PreserveHalftoneInfo; | 128 | bool PreserveHalftoneInfo; |
126 | bool PreserveOverprintSettings; | 129 | bool PreserveOverprintSettings; |
127 | enum psdf_transfer_function_info { | 130 | enum psdf_transfer_function_info { |
@@ -407,12 +410,23 @@ int psdf_setup_image_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, | |||
407 | const gs_imager_state * pis, bool lossless, | 410 | const gs_imager_state * pis, bool lossless, |
408 | bool in_line); | 411 | bool in_line); |
409 | 412 | ||
413 | int new_setup_image_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, | ||
414 | gs_pixel_image_t *pim, const gs_matrix *pctm, | ||
415 | const gs_imager_state * pis, bool lossless, | ||
416 | bool in_line, bool colour_conversion); | ||
417 | |||
410 | /* Set up compression filters for a lossless image, with no downsampling, */ | 418 | /* Set up compression filters for a lossless image, with no downsampling, */ |
411 | /* no color space conversion, and only lossless filters. */ | 419 | /* no color space conversion, and only lossless filters. */ |
412 | /* Note that this may modify the image parameters. */ | 420 | /* Note that this may modify the image parameters. */ |
413 | int psdf_setup_lossless_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, | 421 | int psdf_setup_lossless_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, |
414 | gs_pixel_image_t *pim, bool in_line); | 422 | gs_pixel_image_t *pim, bool in_line); |
415 | 423 | ||
424 | int new_setup_lossless_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, | ||
425 | gs_pixel_image_t *pim, bool in_line, bool colour_conversion); | ||
426 | |||
427 | |||
428 | int new_resize_input(psdf_binary_writer *pbw, int width, int num_comps, int bpc_in, int bpc_out); | ||
429 | |||
416 | /* Finish writing binary data. */ | 430 | /* Finish writing binary data. */ |
417 | int psdf_end_binary(psdf_binary_writer * pbw); | 431 | int psdf_end_binary(psdf_binary_writer * pbw); |
418 | 432 | ||
diff --git a/gs/base/gdevpsdi.c b/gs/base/gdevpsdi.c index 31304e423..ca33cc0b4 100644 --- a/gs/base/gdevpsdi.c +++ b/gs/base/gdevpsdi.c | |||
@@ -48,7 +48,7 @@ extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state); | |||
48 | /* | 48 | /* |
49 | * Add a filter to expand or reduce the pixel width if needed. | 49 | * Add a filter to expand or reduce the pixel width if needed. |
50 | * At least one of bpc_in and bpc_out is 8; the other is 1, 2, 4, or 8, | 50 | * At least one of bpc_in and bpc_out is 8; the other is 1, 2, 4, or 8, |
51 | * except if bpc_out is 8, bpc_in may be 12. | 51 | * except if bpc_out is 8, bpc_in may be 12 (or 16). |
52 | */ | 52 | */ |
53 | static int | 53 | static int |
54 | pixel_resize(psdf_binary_writer * pbw, int width, int num_components, | 54 | pixel_resize(psdf_binary_writer * pbw, int width, int num_components, |
@@ -62,9 +62,9 @@ pixel_resize(psdf_binary_writer * pbw, int width, int num_components, | |||
62 | if (bpc_out == bpc_in) | 62 | if (bpc_out == bpc_in) |
63 | return 0; | 63 | return 0; |
64 | if (bpc_in != 8) { | 64 | if (bpc_in != 8) { |
65 | static const stream_template *const exts[13] = { | 65 | static const stream_template *const exts[17] = { |
66 | 0, &s_1_8_template, &s_2_8_template, 0, &s_4_8_template, | 66 | 0, &s_1_8_template, &s_2_8_template, 0, &s_4_8_template, |
67 | 0, 0, 0, 0, 0, 0, 0, &s_12_8_template | 67 | 0, 0, 0, 0, 0, 0, 0, &s_12_8_template, 0, 0, 0, &s_16_8_template |
68 | }; | 68 | }; |
69 | 69 | ||
70 | templat = exts[bpc_in]; | 70 | templat = exts[bpc_in]; |
@@ -105,7 +105,7 @@ convert_color(gx_device *pdev, const gs_color_space *pcs, const gs_imager_state | |||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | /* A hewristic choice of DCT compression parameters - see bug 687174. */ | 108 | /* A heuristic choice of DCT compression parameters - see bug 687174. */ |
109 | static int | 109 | static int |
110 | choose_DCT_params(gx_device *pdev, const gs_color_space *pcs, | 110 | choose_DCT_params(gx_device *pdev, const gs_color_space *pcs, |
111 | const gs_imager_state * pis, | 111 | const gs_imager_state * pis, |
@@ -743,3 +743,149 @@ psdf_setup_image_colors_filter(psdf_binary_writer *pbw, | |||
743 | } | 743 | } |
744 | return 0; | 744 | return 0; |
745 | } | 745 | } |
746 | |||
747 | /* Set up compression and downsampling filters for an image. */ | ||
748 | /* Note that this may modify the image parameters. */ | ||
749 | int | ||
750 | new_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw, | ||
751 | gs_pixel_image_t * pim, const gs_matrix * pctm, | ||
752 | const gs_imager_state * pis, bool lossless, bool in_line, | ||
753 | bool colour_conversion) | ||
754 | { | ||
755 | /* | ||
756 | * The following algorithms are per Adobe Tech Note # 5151, | ||
757 | * "Acrobat Distiller Parameters", revised 16 September 1996 | ||
758 | * for Acrobat(TM) Distiller(TM) 3.0. | ||
759 | * | ||
760 | * The control structure is a little tricky, because filter | ||
761 | * pipelines must be constructed back-to-front. | ||
762 | */ | ||
763 | int code = 0; | ||
764 | psdf_image_params params; | ||
765 | int bpc = pim->BitsPerComponent; | ||
766 | int bpc_out = pim->BitsPerComponent = min(bpc, 8); | ||
767 | int ncomp; | ||
768 | double resolution; | ||
769 | |||
770 | /* | ||
771 | * The Adobe documentation doesn't say this, but mask images are | ||
772 | * compressed on the same basis as 1-bit-deep monochrome images, | ||
773 | * except that anti-aliasing (resolution/depth tradeoff) is not | ||
774 | * allowed. | ||
775 | */ | ||
776 | if (pim->ColorSpace == NULL) { /* mask image */ | ||
777 | params = pdev->params.MonoImage; | ||
778 | params.Depth = 1; | ||
779 | ncomp = 1; | ||
780 | } else { | ||
781 | ncomp = gs_color_space_num_components(pim->ColorSpace); | ||
782 | if (pim->ColorSpace->type->index == gs_color_space_index_Indexed) { | ||
783 | params = pdev->params.ColorImage; | ||
784 | /* Ensure we don't use JPEG on a /Indexed colour space */ | ||
785 | params.AutoFilter = false; | ||
786 | params.Filter = "FlateEncode"; | ||
787 | } else { | ||
788 | if (ncomp == 1) { | ||
789 | if (bpc == 1) | ||
790 | params = pdev->params.MonoImage; | ||
791 | else | ||
792 | params = pdev->params.GrayImage; | ||
793 | if (params.Depth == -1) | ||
794 | params.Depth = bpc; | ||
795 | } else { | ||
796 | params = pdev->params.ColorImage; | ||
797 | /* params.Depth is reset below */ | ||
798 | } | ||
799 | } | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * We can compute the image resolution by: | ||
804 | * W / (W * ImageMatrix^-1 * CTM / HWResolution). | ||
805 | * We can replace W by 1 to simplify the computation. | ||
806 | */ | ||
807 | if (pctm == 0) | ||
808 | resolution = -1; | ||
809 | else { | ||
810 | gs_point pt; | ||
811 | |||
812 | /* We could do both X and Y, but why bother? */ | ||
813 | code = gs_distance_transform_inverse(1.0, 0.0, &pim->ImageMatrix, &pt); | ||
814 | if (code < 0) | ||
815 | return code; | ||
816 | gs_distance_transform(pt.x, pt.y, pctm, &pt); | ||
817 | resolution = 1.0 / hypot(pt.x / pdev->HWResolution[0], | ||
818 | pt.y / pdev->HWResolution[1]); | ||
819 | } | ||
820 | if (ncomp == 1 && pim->ColorSpace && pim->ColorSpace->type->index != gs_color_space_index_Indexed) { | ||
821 | /* Monochrome, gray, or mask */ | ||
822 | /* Check for downsampling. */ | ||
823 | if (do_downsample(¶ms, pim, resolution)) { | ||
824 | /* Use the downsampled depth, not the original data depth. */ | ||
825 | if (params.Depth == 1) { | ||
826 | params.Filter = pdev->params.MonoImage.Filter; | ||
827 | params.filter_template = pdev->params.MonoImage.filter_template; | ||
828 | params.Dict = pdev->params.MonoImage.Dict; | ||
829 | adjust_auto_filter_strategy_mono(pdev, ¶ms, pdev->params.MonoImage.Dict, pim, in_line); | ||
830 | } else { | ||
831 | params.Filter = pdev->params.GrayImage.Filter; | ||
832 | params.filter_template = pdev->params.GrayImage.filter_template; | ||
833 | params.Dict = pdev->params.GrayImage.Dict; | ||
834 | adjust_auto_filter_strategy(pdev, ¶ms, pdev->params.GrayImage.Dict, pim, in_line); | ||
835 | } | ||
836 | code = setup_downsampling(pbw, ¶ms, pim, pis, resolution, lossless); | ||
837 | } else { | ||
838 | adjust_auto_filter_strategy(pdev, ¶ms, pdev->params.GrayImage.Dict, pim, in_line); | ||
839 | code = setup_image_compression(pbw, ¶ms, pim, pis, lossless); | ||
840 | } | ||
841 | if (code < 0) | ||
842 | return code; | ||
843 | code = pixel_resize(pbw, pim->Width, ncomp, bpc, bpc_out); | ||
844 | } else { | ||
845 | /* Color */ | ||
846 | if (params.Depth == -1) | ||
847 | params.Depth = (colour_conversion ? 8 : bpc_out); | ||
848 | if (do_downsample(¶ms, pim, resolution)) { | ||
849 | adjust_auto_filter_strategy(pdev, ¶ms, pdev->params.ColorImage.Dict, pim, in_line); | ||
850 | code = setup_downsampling(pbw, ¶ms, pim, pis, resolution, lossless); | ||
851 | } else { | ||
852 | adjust_auto_filter_strategy(pdev, ¶ms, pdev->params.ColorImage.Dict, pim, in_line); | ||
853 | code = setup_image_compression(pbw, ¶ms, pim, pis, lossless); | ||
854 | } | ||
855 | if (code < 0) | ||
856 | return code; | ||
857 | code = pixel_resize(pbw, pim->Width, ncomp, bpc, bpc_out); | ||
858 | if (code < 0) | ||
859 | return code; | ||
860 | } | ||
861 | return code; | ||
862 | } | ||
863 | |||
864 | int | ||
865 | new_setup_lossless_filters(gx_device_psdf *pdev, psdf_binary_writer *pbw, | ||
866 | gs_pixel_image_t *pim, bool in_line, | ||
867 | bool colour_conversion) | ||
868 | { | ||
869 | /* | ||
870 | * Set up a device with modified parameters for computing the image | ||
871 | * compression filters. Don't allow downsampling or lossy compression. | ||
872 | */ | ||
873 | gx_device_psdf ipdev; | ||
874 | |||
875 | ipdev = *pdev; | ||
876 | ipdev.params.ColorImage.AutoFilter = false; | ||
877 | ipdev.params.ColorImage.Downsample = false; | ||
878 | ipdev.params.ColorImage.Filter = "FlateEncode"; | ||
879 | ipdev.params.ColorImage.filter_template = &s_zlibE_template; | ||
880 | ipdev.params.ConvertCMYKImagesToRGB = false; | ||
881 | ipdev.params.GrayImage.AutoFilter = false; | ||
882 | ipdev.params.GrayImage.Downsample = false; | ||
883 | ipdev.params.GrayImage.Filter = "FlateEncode"; | ||
884 | ipdev.params.GrayImage.filter_template = &s_zlibE_template; | ||
885 | return new_setup_image_filters(&ipdev, pbw, pim, NULL, NULL, true, in_line, colour_conversion); | ||
886 | } | ||
887 | |||
888 | int new_resize_input(psdf_binary_writer *pbw, int width, int num_comps, int bpc_in, int bpc_out) | ||
889 | { | ||
890 | return pixel_resize(pbw, width, num_comps, bpc_in, bpc_out); | ||
891 | } | ||
diff --git a/gs/base/gdevpsds.c b/gs/base/gdevpsds.c index 94065bf3a..8c662b5ab 100644 --- a/gs/base/gdevpsds.c +++ b/gs/base/gdevpsds.c | |||
@@ -76,6 +76,15 @@ s_12_init(stream_state * st) | |||
76 | ss->bits_per_sample = 12; /* not needed */ | 76 | ss->bits_per_sample = 12; /* not needed */ |
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | static int | ||
80 | s_16_init(stream_state * st) | ||
81 | { | ||
82 | stream_1248_state *const ss = (stream_1248_state *) st; | ||
83 | |||
84 | ss->left = ss->samples_per_row; | ||
85 | ss->bits_per_sample = 16; /* not needed */ | ||
86 | return 0; | ||
87 | } | ||
79 | 88 | ||
80 | /* Process one buffer. */ | 89 | /* Process one buffer. */ |
81 | #define BEGIN_1248\ | 90 | #define BEGIN_1248\ |
@@ -207,6 +216,22 @@ s_12_8_process(stream_state * st, stream_cursor_read * pr, | |||
207 | END_1248; | 216 | END_1248; |
208 | } | 217 | } |
209 | 218 | ||
219 | /* 16-to-8 "expansion" */ | ||
220 | static int | ||
221 | s_16_8_process(stream_state * st, stream_cursor_read * pr, | ||
222 | stream_cursor_write * pw, bool last) | ||
223 | { | ||
224 | BEGIN_1248; | ||
225 | |||
226 | n = ss->samples_per_row; /* misuse n to avoid a compiler warning */ | ||
227 | status = 0; | ||
228 | for (; rlimit - p >= 2; ++q) { | ||
229 | q[1] = (byte)p[1]; /* Set output to the high byte of the input */ | ||
230 | p+=2; /* Discard the low byte */ | ||
231 | } | ||
232 | END_1248; | ||
233 | } | ||
234 | |||
210 | /* 8-to-N reduction */ | 235 | /* 8-to-N reduction */ |
211 | #define FOREACH_8_N(out, nin)\ | 236 | #define FOREACH_8_N(out, nin)\ |
212 | byte out;\ | 237 | byte out;\ |
@@ -297,6 +322,9 @@ const stream_template s_4_8_template = { | |||
297 | const stream_template s_12_8_template = { | 322 | const stream_template s_12_8_template = { |
298 | &st_1248_state, s_12_init, s_12_8_process, 1, 2 | 323 | &st_1248_state, s_12_init, s_12_8_process, 1, 2 |
299 | }; | 324 | }; |
325 | const stream_template s_16_8_template = { | ||
326 | &st_1248_state, s_16_init, s_16_8_process, 1, 2 | ||
327 | }; | ||
300 | 328 | ||
301 | const stream_template s_8_1_template = { | 329 | const stream_template s_8_1_template = { |
302 | &st_1248_state, s_1_init, s_8_N_process, 8, 1 | 330 | &st_1248_state, s_1_init, s_8_N_process, 8, 1 |
@@ -1108,6 +1136,21 @@ s_image_colors_set_color_space(stream_image_colors_state * ss, gx_device *pdev, | |||
1108 | memcpy(ss->Decode, Decode, ss->depth * sizeof(Decode[0]) * 2); | 1136 | memcpy(ss->Decode, Decode, ss->depth * sizeof(Decode[0]) * 2); |
1109 | } | 1137 | } |
1110 | 1138 | ||
1139 | void | ||
1140 | s_new_image_colors_set_color_space(stream_image_colors_state * ss, gx_device *pdev, | ||
1141 | const gs_color_space *pcs, const gs_imager_state *pis, | ||
1142 | float *Decode) | ||
1143 | { | ||
1144 | ss->output_depth = pdev->color_info.num_components; | ||
1145 | ss->output_component_index = ss->output_depth; | ||
1146 | ss->output_bits_per_sample = pdev->color_info.comp_bits[0]; /* Same precision for all components. */ | ||
1147 | ss->convert_color = s_image_colors_convert_to_device_color; | ||
1148 | ss->pdev = pdev; | ||
1149 | ss->pcs = pcs; | ||
1150 | ss->pis = pis; | ||
1151 | memcpy(ss->Decode, Decode, ss->depth * sizeof(Decode[0]) * 2); | ||
1152 | } | ||
1153 | |||
1111 | /* Process a buffer. */ | 1154 | /* Process a buffer. */ |
1112 | static int | 1155 | static int |
1113 | s_image_colors_process(stream_state * st, stream_cursor_read * pr, | 1156 | s_image_colors_process(stream_state * st, stream_cursor_read * pr, |
diff --git a/gs/base/gdevpsds.h b/gs/base/gdevpsds.h index 6d54c4e57..5917863b4 100644 --- a/gs/base/gdevpsds.h +++ b/gs/base/gdevpsds.h | |||
@@ -34,14 +34,15 @@ typedef struct stream_1248_state_s { | |||
34 | uint left; /* # of samples left in current row */ | 34 | uint left; /* # of samples left in current row */ |
35 | } stream_1248_state; | 35 | } stream_1248_state; |
36 | 36 | ||
37 | /* Convert N (1, 2, 4, 12) bits to 8. */ | 37 | /* Convert N (1, 2, 4, 12, 16) bits to 8. */ |
38 | extern const stream_template s_1_8_template; | 38 | extern const stream_template s_1_8_template; |
39 | extern const stream_template s_2_8_template; | 39 | extern const stream_template s_2_8_template; |
40 | extern const stream_template s_4_8_template; | 40 | extern const stream_template s_4_8_template; |
41 | extern const stream_template s_12_8_template; | 41 | extern const stream_template s_12_8_template; |
42 | extern const stream_template s_16_8_template; | ||
42 | 43 | ||
43 | /* Reduce 8 bits to N (1, 2, 4). */ | 44 | /* Reduce 8 bits to N (1, 2, 4). */ |
44 | /* We do not currently support converting 8 bits to 12. */ | 45 | /* We do not currently support converting 8 bits to 12 or 16. */ |
45 | extern const stream_template s_8_1_template; | 46 | extern const stream_template s_8_1_template; |
46 | extern const stream_template s_8_2_template; | 47 | extern const stream_template s_8_2_template; |
47 | extern const stream_template s_8_4_template; | 48 | extern const stream_template s_8_4_template; |
@@ -215,8 +216,6 @@ struct stream_image_colors_state_s { | |||
215 | "stream_image_colors_state", stream_image_colors_enum_ptrs,\ | 216 | "stream_image_colors_state", stream_image_colors_enum_ptrs,\ |
216 | stream_image_colors_reloc_ptrs, pcs, pdev, pis) | 217 | stream_image_colors_reloc_ptrs, pcs, pdev, pis) |
217 | 218 | ||
218 | extern const stream_template s_image_colors_template; | ||
219 | |||
220 | void s_image_colors_set_dimensions(stream_image_colors_state * st, | 219 | void s_image_colors_set_dimensions(stream_image_colors_state * st, |
221 | int width, int height, int depth, int bits_per_sample); | 220 | int width, int height, int depth, int bits_per_sample); |
222 | 221 | ||
@@ -226,6 +225,10 @@ void s_image_colors_set_color_space(stream_image_colors_state * ss, gx_device *p | |||
226 | const gs_color_space *pcs, const gs_imager_state *pis, | 225 | const gs_color_space *pcs, const gs_imager_state *pis, |
227 | float *Decode); | 226 | float *Decode); |
228 | 227 | ||
228 | void s_new_image_colors_set_color_space(stream_image_colors_state * ss, gx_device *pdev, | ||
229 | const gs_color_space *pcs, const gs_imager_state *pis, | ||
230 | float *Decode); | ||
231 | |||
229 | extern const stream_template s__image_colors_template; | 232 | extern const stream_template s__image_colors_template; |
230 | 233 | ||
231 | #endif /* gdevpsds_INCLUDED */ | 234 | #endif /* gdevpsds_INCLUDED */ |