Fix for 688018 (PreserveHalftones in pdfwrite) |

Ray Johnston <[email protected]> Tue, 12 Apr 2005 14:20:12 -0700
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Artifex Software Inc.
Message-ID <[email protected]>
All,

I know this is usually Igor's area, but he's busy right now and
rather than divert his attention, I decided to look into this
SEGV in pdfwrite. Good learning oppurtunity for me :-)

The patch is attached.

Log message:

Fix for SEGV when PreserveHalftoneInfo=true is given as a
pdfwrite option. Bug 688018.

DETAILS:

The initial problem was that the num_comp was not being looked at
when HalftoneType 5 was written and if num_comp was 3, the 4th
element of ht_ids[] was being used (UMR-wise). The solution to
this was to only write the three halftones and to use the 'Green'
halftone (arbitrarily) for Default.

After fixing the SEGV, another problem surfaced because the object
dictionary was not being terminated with the ">>".

Since I suspected that the threshold_halftone writers were also
broken I tested with 258-01.ps and found more problems. This
code was also quite broken. Since the Threshold array is the
stream data for HalftoneType 6 and 16, I changed this a lot to
emit valid PDF.

EXPECTED DIFFERENCES:

None, since we don't set PreserveHalftoneInfo.
-- 
Ray Johnston
Director of Engineering                          Tel: (714) 484-0376
Artifex Software Inc.                            Fax: (714) 220-1022
______________________________________________________________________

_______________________________________________
gs-code-review mailing list
[email protected]
http://www.ghostscript.com/mailman/listinfo/gs-code-review
688018.patch (text/plain, 6 KB)
Index: src/gdevpdfg.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfg.c,v
retrieving revision 1.60
diff -c -r1.60 gdevpdfg.c
*** src/gdevpdfg.c	1 Apr 2005 17:42:38 -0000	1.60
--- src/gdevpdfg.c	12 Apr 2005 21:14:12 -0000
***************
*** 865,871 ****
      stream *s;
      long ht_ids[4];
  
!     for (i = 0; i < 4; ++i) {
  	int code = pdf_write_screen_halftone(pdev, &pcsht->screens.indexed[i],
  					     &pdht->components[i].corder,
  					     &ht_ids[i]);
--- 865,871 ----
      stream *s;
      long ht_ids[4];
  
!     for (i = 0; i < pdht->num_comp ; ++i) {
  	int code = pdf_write_screen_halftone(pdev, &pcsht->screens.indexed[i],
  					     &pdht->components[i].corder,
  					     &ht_ids[i]);
***************
*** 874,908 ****
      }
      *pid = pdf_begin_separate(pdev);
      s = pdev->strm;
      pprintld1(s, "<</Type/Halftone/HalftoneType 5/Default %ld 0 R\n",
! 	      ht_ids[3]);
      pprintld2(s, "/Red %ld 0 R/Cyan %ld 0 R", ht_ids[0], ht_ids[0]);
      pprintld2(s, "/Green %ld 0 R/Magenta %ld 0 R", ht_ids[1], ht_ids[1]);
      pprintld2(s, "/Blue %ld 0 R/Yellow %ld 0 R", ht_ids[2], ht_ids[2]);
      pprintld2(s, "/Gray %ld 0 R/Black %ld 0 R", ht_ids[3], ht_ids[3]);
      return pdf_end_separate(pdev);
  }
  private int
  pdf_write_threshold_halftone(gx_device_pdf *pdev,
  			     const gs_threshold_halftone *ptht,
  			     const gx_ht_order *porder, long *pid)
  {
      char trs[17 + MAX_FN_CHARS + 1];
!     int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
! 				  trs);
!     long id = pdf_begin_separate(pdev);
!     stream *s = pdev->strm;
      pdf_data_writer_t writer;
  
      if (code < 0)
  	return code;
!     *pid = id;
!     pprintd2(s, "<</Type/Halftone/HalftoneType 6/Width %d/Height %d",
! 	     ptht->width, ptht->height);
!     stream_puts(s, trs);
!     code = pdf_begin_data(pdev, &writer);
!     if (code < 0)
! 	return code;
      stream_write(writer.binary.strm, ptht->thresholds.data, ptht->thresholds.size);
      return pdf_end_data(&writer);
  }
--- 874,922 ----
      }
      *pid = pdf_begin_separate(pdev);
      s = pdev->strm;
+     /* Use Black, Gray as the Default unless we are in RGB colormodel */
+     /* (num_comp < 4) in which case we use Green (arbitrarily) */
      pprintld1(s, "<</Type/Halftone/HalftoneType 5/Default %ld 0 R\n",
! 	      pdht->num_comp > 3 ? ht_ids[3] : ht_ids[1]);
      pprintld2(s, "/Red %ld 0 R/Cyan %ld 0 R", ht_ids[0], ht_ids[0]);
      pprintld2(s, "/Green %ld 0 R/Magenta %ld 0 R", ht_ids[1], ht_ids[1]);
      pprintld2(s, "/Blue %ld 0 R/Yellow %ld 0 R", ht_ids[2], ht_ids[2]);
+     if (pdht->num_comp > 3)
      pprintld2(s, "/Gray %ld 0 R/Black %ld 0 R", ht_ids[3], ht_ids[3]);
+     stream_puts(s, ">>\n");
      return pdf_end_separate(pdev);
  }
+ 
+ #define CHECK(expr)\
+   BEGIN if ((code = (expr)) < 0) return code; END
+ 
  private int
  pdf_write_threshold_halftone(gx_device_pdf *pdev,
  			     const gs_threshold_halftone *ptht,
  			     const gx_ht_order *porder, long *pid)
  {
      char trs[17 + MAX_FN_CHARS + 1];
!     stream *s;
      pdf_data_writer_t writer;
+     int code = pdf_write_transfer(pdev, porder->transfer, "",
+ 				  trs);
  
      if (code < 0)
  	return code;
!     CHECK(pdf_begin_data(pdev, &writer)); 
!     s = pdev->strm;
!     *pid = writer.pres->object->id;
!     CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	"/Type", "/Halftone"));
!     CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	"/HalftoneType", "6"));
!     CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	"/Width", ptht->width));
!     CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	"/Height", ptht->height));
!     if (*trs != 0)
! 	CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	    "/TransferFunction", trs));
      stream_write(writer.binary.strm, ptht->thresholds.data, ptht->thresholds.size);
      return pdf_end_data(&writer);
  }
***************
*** 912,934 ****
  			      const gx_ht_order *porder, long *pid)
  {
      char trs[17 + MAX_FN_CHARS + 1];
      int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
  				  trs);
-     long id = pdf_begin_separate(pdev);
-     stream *s = pdev->strm;
-     pdf_data_writer_t writer;
  
      if (code < 0)
  	return code;
!     *pid = id;
!     pprintd2(s, "<</Type/Halftone/HalftoneType 16/Width %d/Height %d",
! 	     ptht->width, ptht->height);
!     if (ptht->width2 && ptht->height2)
! 	pprintd2(s, "/Width2 %d/Height2 %d", ptht->width2, ptht->height2);
!     stream_puts(s, trs);
!     code = pdf_begin_data(pdev, &writer);
!     if (code < 0)
! 	return code;
      s = writer.binary.strm;
      if (ptht->bytes_per_sample == 2)
  	stream_write(s, ptht->thresholds.data, ptht->thresholds.size);
--- 926,958 ----
  			      const gx_ht_order *porder, long *pid)
  {
      char trs[17 + MAX_FN_CHARS + 1];
+     stream *s;
+     pdf_data_writer_t writer;
      int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
  				  trs);
  
      if (code < 0)
  	return code;
!     CHECK(pdf_begin_data(pdev, &writer)); 
!     s = pdev->strm;
!     *pid = writer.pres->object->id;
!     CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	"/Type", "/Halftone"));
!     CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	"/HalftoneType", "16"));
!     CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	"/Width", ptht->width));
!     CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	"/Height", ptht->height));
!     if (ptht->width2 && ptht->height2) {
! 	CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	    "/Width2", ptht->width2));
! 	CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
! 	    "/Height2", ptht->height2));
!     }
!     if (*trs != 0)
! 	CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
! 	    "/TransferFunction", trs));
      s = writer.binary.strm;
      if (ptht->bytes_per_sample == 2)
  	stream_write(s, ptht->thresholds.data, ptht->thresholds.size);