[gs-commits] ghostpdl branch, master, updated. jbig2dec-0.14-1608-g1fe43c3

[email protected] (Robin Watts)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, master has been updated
       via  1fe43c3ba4423631129925d789c936b9e461d1d6 (commit)
       via  0ac36b1eb87a919d3df19b7fb555d277d959396b (commit)
       via  cda2b1e057951dc4687c4d2ad489100d1ea6ea4b (commit)
      from  4e220de447dc5cc79a00e8bb57b69c6ea242fe75 (commit)

----------------------------------------------------------------------
commit 1fe43c3ba4423631129925d789c936b9e461d1d6
Author: Robin Watts <[email protected]>
Date:   Mon Aug 26 11:28:40 2019 +0100

    Fix problems with pngalpha and deep color transparency filling.
    
    The pngalpha device is created with a depth of 32, with 3 color
    components; this was confusing pdf14 into thinking that more
    than 8 bits per color were being used, and so deep color buffers
    were required.
    
    To fix this we update the logic to be smarter; in cases where we
    don't have a clear determination based on bits alone, we look
    at the max_color and max_gray values. Because this code is now
    more complex than before, we pull it into a shared function.

diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index 630becf..f1d1bb8 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -532,10 +532,7 @@ void check_device_compatible_encoding(gx_device *dev)
     gx_color_index mul, color_index;
     int i, j;
     gx_color_value colorants[GX_DEVICE_COLOR_MAX_COMPONENTS];
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (pinfo->separable_and_linear == GX_CINFO_UNKNOWN_SEP_LIN)
         check_device_separable(dev);
diff --git a/base/gdevmem.c b/base/gdevmem.c
index 4f1ab99..9a3fe5e 100644
--- a/base/gdevmem.c
+++ b/base/gdevmem.c
@@ -387,10 +387,7 @@ gdev_mem_max_height(const gx_device_memory * dev, int width, ulong size,
     int height;
     ulong max_height;
     ulong data_size;
-    bool has_tags = device_encodes_tags((gx_device *)dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                          dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (page_uses_transparency) {
         /*
diff --git a/base/gdevp14.c b/base/gdevp14.c
index 18211aa..d38951a 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -3371,10 +3371,7 @@ pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
                       gx_color_index color, const gx_device_color *pdc,
                       int depth, bool devn)
 {
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (deep)
         return do_pdf14_copy_alpha_color_16(dev, data, data_x, aa_raster,
@@ -4130,10 +4127,7 @@ get_pdf14_device_proto(gx_device * dev, pdf14_device ** pdevproto,
     pdf14_default_colorspace_t dev_cs =
                 pdf14_determine_default_blend_cs(dev, use_pdf14_accum,
                                                  &using_blend_cs);
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     switch (dev_cs) {
         case PDF14_DeviceGray:
@@ -4232,10 +4226,7 @@ pdf14_ok_to_optimize(gx_device *dev)
     int tag_depth = device_encodes_tags(dev) ? 8 : 0;
     cmm_dev_profile_t *dev_profile;
     int code = dev_proc(dev, get_profile)(dev,  &dev_profile);
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (code < 0)
         return false;
@@ -4295,9 +4286,7 @@ pdf14_recreate_device(gs_memory_t *mem,	gs_gstate	* pgs,
     pdf14_device temp_dev_proto;
     bool has_tags = device_encodes_tags(dev);
     int code;
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if_debug0m('v', dev->memory, "[v]pdf14_recreate_device\n");
 
@@ -5215,9 +5204,7 @@ pdf14_update_device_color_procs_push_c(gx_device               *dev,
     cmm_profile_t *icc_profile_dev = NULL;
     gsicc_rendering_param_t render_cond;
     cmm_dev_profile_t *dev_profile;
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    int deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     memset(comp_bits, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
     memset(comp_shift, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
@@ -5572,10 +5559,7 @@ pdf14_begin_transparency_mask(gx_device	*dev,
     int code;
     int group_color_numcomps;
     gs_transparency_color_t group_color;
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    int deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (ptmp->subtype == TRANSPARENCY_MASK_None) {
         pdf14_ctx *ctx = pdev->ctx;
@@ -6533,7 +6517,6 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
     uchar k;
     int max_bitmap;
     bool use_pdf14_accum = false;
-    int bits_per_comp;
     bool deep;
 
     /* Guard against later seg faults, this should not be possible */
@@ -6541,9 +6524,7 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
         return gs_throw_code(gs_error_Fatal);
 
     has_tags = device_encodes_tags(target);
-    bits_per_comp = ((target->color_info.depth - has_tags*8) /
-                      target->color_info.num_components);
-    deep = bits_per_comp > 8;
+    deep = device_is_deep(target);
     max_bitmap = target->space_params.MaxBitmap == 0 ? MAX_BITMAP :
                                  target->space_params.MaxBitmap;
     /* If the device is not a printer class device, it won't support saved-pages */
@@ -6817,10 +6798,7 @@ c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize,
     int pdf14_needed = cdev->pdf14_needed;
     int trans_group_level = cdev->pdf14_trans_group_level;
     int smask_level = cdev->pdf14_smask_level;
-    bool has_tags = device_encodes_tags((gx_device *)cdev);
-    int bits_per_comp = ((cdev->color_info.depth - has_tags*8) /
-                         cdev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(cdev);
 
     code = dev_proc((gx_device *) cdev, get_profile)((gx_device *) cdev,
                                                      &dev_profile);
@@ -7746,9 +7724,7 @@ get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto,
                 pdf14_determine_default_blend_cs(dev, use_pdf14_accum,
                                                  &using_blend_cs);
     bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     switch (dev_cs) {
         case PDF14_DeviceGray:
@@ -7866,9 +7842,7 @@ pdf14_create_clist_device(gs_memory_t *mem, gs_gstate * pgs,
     gsicc_rendering_param_t render_cond;
     cmm_dev_profile_t *dev_profile;
     uchar k;
-    int bits_per_comp = ((target->color_info.depth - has_tags*8) /
-                         target->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(target);
 
     code = dev_proc(target, get_profile)(target,  &dev_profile);
     if (code < 0)
@@ -8099,10 +8073,7 @@ pdf14_clist_create_compositor(gx_device	* dev, gx_device ** pcdev,
     pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
     int code, is_pdf14_compositor;
     const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((pdev->color_info.depth - has_tags*8) /
-                         pdev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     /* We only handle a few PDF 1.4 transparency operations */
     if ((is_pdf14_compositor = gs_is_pdf14trans_compositor(pct)) != 0) {
diff --git a/base/gdevprn.c b/base/gdevprn.c
index cc71e5c..b945428 100644
--- a/base/gdevprn.c
+++ b/base/gdevprn.c
@@ -384,10 +384,7 @@ gdev_prn_allocate(gx_device *pdev, gdev_prn_space_params *new_space_params,
     gs_memory_t *buffer_memory =
         (ppdev->buffer_memory == 0 ? pdev->memory->non_gc_memory :
          ppdev->buffer_memory);
-    bool has_tags = device_encodes_tags(pdev);
-    int bits_per_comp = ((pdev->color_info.depth - has_tags*8) /
-                         pdev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(pdev);
 
     /* If reallocate, find allocated memory & tear down buffer device */
     if (reallocate)
diff --git a/base/gsptype1.c b/base/gsptype1.c
index da96e8b..f81a63c 100644
--- a/base/gsptype1.c
+++ b/base/gsptype1.c
@@ -2047,10 +2047,7 @@ gx_dc_pattern_read(
     int code, l;
     tile_trans_clist_info_t trans_info = { { { 0 } } };
     int cache_space_needed;
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     if (offset == 0) {
         pdevc->mask.id = gx_no_bitmap_id;
diff --git a/base/gstrans.c b/base/gstrans.c
index fd4d299..44ed3a7 100644
--- a/base/gstrans.c
+++ b/base/gstrans.c
@@ -558,10 +558,7 @@ gs_begin_transparency_mask(gs_gstate * pgs,
     int i, code;
     gs_color_space *blend_color_space;
     gsicc_manager_t *icc_manager = pgs->icc_manager;
-    bool has_tags = device_encodes_tags(pgs->device);
-    int bits_per_comp = ((pgs->device->color_info.depth - has_tags*8) /
-                         pgs->device->color_info.num_components);
-    int deep = bits_per_comp > 8;
+    bool deep = device_is_deep(pgs->device);
 
     if (check_for_nontrans_pattern(pgs,
                   (unsigned char *)"gs_pop_transparency_state")) {
diff --git a/base/gxclthrd.c b/base/gxclthrd.c
index 0cfd30b..833f9a5 100644
--- a/base/gxclthrd.c
+++ b/base/gxclthrd.c
@@ -302,10 +302,7 @@ clist_setup_render_threads(gx_device *dev, int y, gx_process_page_options_t *opt
     /* this will be increased by the measured profile storage and icclinks (estimated).		  */
     int reserve_size = 2 * 1024 * 1024 + (gx_ht_cache_default_bits_size() * dev->color_info.num_components);
     clist_icctable_entry_t *curr_entry;
-    bool has_tags = device_encodes_tags(dev);
-    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
-                         dev->color_info.num_components);
-    bool deep = bits_per_comp > 8;
+    bool deep = device_is_deep(dev);
 
     crdev->num_render_threads = pdev->num_render_threads_requested;
 
diff --git a/base/gxdevcli.h b/base/gxdevcli.h
index 33f7c37..5524ff8 100644
--- a/base/gxdevcli.h
+++ b/base/gxdevcli.h
@@ -1835,6 +1835,21 @@ static inline bool device_encodes_tags(const gx_device *dev)
     return (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) != 0;
 }
 
+static inline bool device_is_deep(const gx_device *dev)
+{
+    bool has_tags = device_encodes_tags(dev);
+    int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
+                         dev->color_info.num_components);
+    if (bits_per_comp > 16)
+        return 1;
+    if (bits_per_comp == 16 && dev->color_info.num_components > 1)
+        return 1;
+    if (bits_per_comp == 8)
+        return 0;
+    return (dev->color_info.max_color > 255 ||
+            dev->color_info.max_gray > 255);
+}
+
 /* A null device.  This is used to temporarily disable output. */
 struct gx_device_null_s {
     gx_device_forward_common;

----------------------------------------------------------------------
commit 0ac36b1eb87a919d3df19b7fb555d277d959396b
Author: Robin Watts <[email protected]>
Date:   Fri Aug 23 15:06:17 2019 +0100

    Fix deep color transparency issue.
    
    Fix overflow in art_pdf_composite_knockout_16, seen in:
    
       tests_private/comparefiles/Bug690546.pdf.psdcmyk16.72.0

diff --git a/base/gdevp14.c b/base/gdevp14.c
index 5e32683..18211aa 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -4878,7 +4878,6 @@ pdf14_begin_transparency_group(gx_device *dev,
     if_debug0m('v', dev->memory, "[v]Transparency group color space update\n");
     if (code < 0)
         return code;
-    /* FIXME: deep */
     code = pdf14_push_transparency_group(pdev->ctx, &rect, isolated, ptgp->Knockout,
                                          (uint16_t)floor (65535 * alpha + 0.5),
                                          (uint16_t)floor (65535 * pgs->shape.alpha + 0.5),
diff --git a/base/gxblend.c b/base/gxblend.c
index f3bf38d..6756613 100644
--- a/base/gxblend.c
+++ b/base/gxblend.c
@@ -2524,7 +2524,8 @@ art_pdf_composite_knockout_16(uint16_t *gs_restrict dst,
                               pdf14_device *p14dev)
 {
     uint16_t src_shape = src[n_chan];
-    int i, tmp;
+    int i;
+    unsigned int tmp;
 
     if (blend_mode == BLEND_MODE_Normal) {
         /* Do simple compositing of source over backdrop */
@@ -2542,14 +2543,17 @@ art_pdf_composite_knockout_16(uint16_t *gs_restrict dst,
             tmp = (65535 - dst_alpha) * src_shape + 0x8000;
             result_alpha = dst_alpha + ((tmp + (tmp >> 16)) >> 16);
 
-            if (result_alpha != 0)
+            if (result_alpha != 0) {
+                dst_alpha += dst_alpha>>15;
                 for (i = 0; i < n_chan; i++) {
                     /* todo: optimize this - can strength-reduce so that
                        inner loop is a single interpolation */
-                    tmp = dst[i] * dst_alpha * (65535 - src_shape) +
-                        ((int)src[i]) * 65535 * src_shape + (result_alpha << 15);
-                    dst[i] = tmp / (result_alpha * 65535);
+                    tmp = dst[i] * dst_alpha;
+                    tmp = (tmp>>16) * (65535 - src_shape) +
+                           src[i] * src_shape + (result_alpha>>1);
+                    dst[i] = tmp / result_alpha;
                 }
+            }
             dst[n_chan] = result_alpha;
         }
     } else {

----------------------------------------------------------------------
commit cda2b1e057951dc4687c4d2ad489100d1ea6ea4b
Author: Robin Watts <[email protected]>
Date:   Thu Aug 22 18:24:49 2019 +0100

    Fix deep color transparent pattern problems.
    
    Transparency buffers are held as native endian. Pattern cache
    tiles are held as big endian. When we make pattern cache tiles
    from transparency buffers we therefore need a conversion.

diff --git a/base/gdevp14.c b/base/gdevp14.c
index 6a7a8a7..5e32683 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -1973,6 +1973,17 @@ pdf14_grayspot_get_color_mapping_procs(const gx_device * dev)
     return &pdf14_DeviceGrayspot_procs;
 }
 
+static void
+be_rev_cpy(uint16_t *dst,const uint16_t *src,int n)
+{
+    for (; n != 0; n--) {
+        uint16_t in = *src++;
+        ((byte *)dst)[0] = in>>8;
+        ((byte *)dst)[1] = in;
+        dst++;
+    }
+}
+
 /* Used to pass along information about the buffer created by the
    pdf14 device.  This is used by the pattern accumulator when the
    pattern contains transparency.  Note that if free_device is true then
@@ -2035,14 +2046,28 @@ pdf14_get_buffer_information(const gx_device * dev,
                 return gs_error_VMerror;
 
             transbuff->mem = mem;
-            for (j = 0; j < transbuff->n_chan; j++) {
-                buff_ptr_src = buf->data + j * buf->planestride +
-                           buf->rowstride * rect.p.y + (rect.p.x<<buf->deep);
-                buff_ptr_des = transbuff->transbytes + j * planestride;
-                for (k = 0; k < height; k++) {
-                    memcpy(buff_ptr_des, buff_ptr_src, rowstride);
-                    buff_ptr_des += rowstride;
-                    buff_ptr_src += buf->rowstride;
+            if (transbuff->deep) {
+                /* FIXME: */
+                for (j = 0; j < transbuff->n_chan; j++) {
+                    buff_ptr_src = buf->data + j * buf->planestride +
+                               buf->rowstride * rect.p.y + (rect.p.x<<buf->deep);
+                    buff_ptr_des = transbuff->transbytes + j * planestride;
+                    for (k = 0; k < height; k++) {
+                        be_rev_cpy((uint16_t *)buff_ptr_des, (const uint16_t *)buff_ptr_src, rowstride>>1);
+                        buff_ptr_des += rowstride;
+                        buff_ptr_src += buf->rowstride;
+                    }
+                }
+            } else {
+                for (j = 0; j < transbuff->n_chan; j++) {
+                    buff_ptr_src = buf->data + j * buf->planestride +
+                               buf->rowstride * rect.p.y + (rect.p.x<<buf->deep);
+                    buff_ptr_des = transbuff->transbytes + j * planestride;
+                    for (k = 0; k < height; k++) {
+                        memcpy(buff_ptr_des, buff_ptr_src, rowstride);
+                        buff_ptr_des += rowstride;
+                        buff_ptr_src += buf->rowstride;
+                    }
                 }
             }
 
@@ -2055,14 +2080,33 @@ pdf14_get_buffer_information(const gx_device * dev,
             transbuff->transbytes = buf->data;
             transbuff->mem = buf->memory;
             buf->data = NULL;  /* So that the buffer is not freed */
+            if (transbuff->deep) {
+                /* We have the data in native endian. We need it in big endian. Do an in-place conversion. */
+                /* FIXME: This is a nop on big endian machines. Is the compiler smart enough to spot that? */
+                uint16_t *buff_ptr;
+                int j, k, z;
+                int rowstride = transbuff->rowstride>>1;
+                int planestride = transbuff->planestride;
+                for (j = 0; j < transbuff->n_chan; j++) {
+                    buff_ptr = (uint16_t *)(transbuff->transbytes + j * planestride);
+                    for (k = 0; k < height; k++) {
+                        for (z = 0; z < width; z++) {
+                            uint16_t in = buff_ptr[z];
+                            ((byte *)(&buff_ptr[z]))[0] = in>>8;
+                            ((byte *)(&buff_ptr[z]))[1] = in;
+                        }
+                        buff_ptr += rowstride;
+                    }
+                }
+            }
         }
 #if RAW_DUMP
         /* Dump the buffer that should be going into the pattern */;
-        dump_raw_buffer(buf->memory,
-                        height, width, transbuff->n_chan,
-                        transbuff->planestride, transbuff->rowstride,
-                        "pdf14_pattern_buff", transbuff->transbytes,
-                        transbuff->deep);
+        dump_raw_buffer_be(buf->memory,
+                           height, width, transbuff->n_chan,
+                           transbuff->planestride, transbuff->rowstride,
+                           "pdf14_pattern_buff", transbuff->transbytes,
+                           transbuff->deep);
         global_index++;
 #endif
         /* Go ahead and free up the pdf14 device */
@@ -3592,7 +3636,7 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
                                curr_clip_rect->ymax-curr_clip_rect->ymin, (int)ptile->id);
                     code = gx_trans_pattern_fill_rect(curr_clip_rect->xmin, curr_clip_rect->ymin,
                                                       curr_clip_rect->xmax, curr_clip_rect->ymax, ptile,
-                                                      fill_trans_buffer, phase, pdev, pdevc);
+                                                      fill_trans_buffer, phase, pdev, pdevc, 1);
                     curr_clip_rect = curr_clip_rect->next;
                 }
             } else if (cpath_intersection.rect_list->list.count == 1) {
@@ -3610,7 +3654,7 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
                                                   cpath_intersection.rect_list->list.single.ymin,
                                                   cpath_intersection.rect_list->list.single.xmax,
                                                   cpath_intersection.rect_list->list.single.ymax,
-                                                  ptile, fill_trans_buffer, phase, pdev, pdevc);
+                                                  ptile, fill_trans_buffer, phase, pdev, pdevc, 1);
             }
         } else {
             /* Clist pattern with transparency.  Create a clip device from our
@@ -3626,7 +3670,7 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
             phase.y = pdevc->phase.y;
             code = gx_trans_pattern_fill_rect(rect.p.x, rect.p.y, rect.q.x, rect.q.y,
                                               ptile, fill_trans_buffer, phase,
-                                              dev, pdevc);
+                                              dev, pdevc, 1);
 
         }
         /* We're done drawing with the pattern, remove the reference to the
diff --git a/base/gxblend.c b/base/gxblend.c
index 15b8e9b..f3bf38d 100644
--- a/base/gxblend.c
+++ b/base/gxblend.c
@@ -1743,7 +1743,7 @@ art_pdf_composite_pixel_alpha_16(uint16_t *gs_restrict dst, const uint16_t *gs_r
 {
     int a_b, a_s;
     unsigned int a_r;
-    int tmp;
+    unsigned int tmp;
     int src_scale;
     int c_b, c_s;
     int i;
@@ -1771,7 +1771,7 @@ art_pdf_composite_pixel_alpha_16(uint16_t *gs_restrict dst, const uint16_t *gs_r
     /* todo: verify that a_r is nonzero in all cases */
 
     /* Compute a_s / a_r in 16.16 format */
-    src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
+    src_scale = ((unsigned int)((a_s << 16) + (a_r >> 1))) / a_r;
 
     if (first_spot != 0) {
         /* Do compositing with blending */
diff --git a/base/gxp1fill.c b/base/gxp1fill.c
index bb4efc8..61eae3f 100644
--- a/base/gxp1fill.c
+++ b/base/gxp1fill.c
@@ -612,7 +612,8 @@ gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc,
  */
 static int
 tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int h0,
-              gx_pattern_trans_t *fill_trans_buffer, const gx_color_tile * ptile)
+              gx_pattern_trans_t *fill_trans_buffer, const gx_color_tile * ptile,
+              int native16)
 {
     int x1 = x0 + w0, y1 = y0 + h0;
     int i0, i1, j0, j1, i, j;
@@ -705,12 +706,23 @@ tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int
                     y > fill_trans_buffer->rect.q.y || y+h < 0)
                     continue;	/* skip the fill (can breakpoint here) */
                 ptile->ttrans->pat_trans_fill(x, y, x+w, y+h, px, py, ptile,
-                    fill_trans_buffer);
+                    fill_trans_buffer, native16);
             }
         }
     return 0;
 }
 
+static void
+be_rev_cpy(uint16_t *dst,const uint16_t *src,int n)
+{
+    for (; n != 0; n--) {
+        uint16_t in = *src++;
+        ((byte *)dst)[0] = in>>8;
+        ((byte *)dst)[1] = in;
+        dst++;
+    }
+}
+
 /* This does the case of tiling with simple tiles.  Since it is not commented
  * anywhere note that simple means that the tile size is the same as the step
  * matrix size and the cross terms in the step matrix are 0.  Hence a simple
@@ -721,7 +733,8 @@ tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int
 void
 tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax,
                        int px, int py, const gx_color_tile *ptile,
-                       gx_pattern_trans_t *fill_trans_buffer)
+                       gx_pattern_trans_t *fill_trans_buffer,
+                       int native16)
 {
     int kk, jj, ii, h, w;
     int buff_out_y_offset, buff_out_x_offset;
@@ -795,39 +808,79 @@ tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax,
     if (right_copy_width < 0)
         right_copy_width = 0;
 
-    for (kk = 0; kk < src_planes; kk++) {
+    if (deep && native16) {
+        /* fill_trans_buffer is in native endian. ptile is in big endian. */
+        /* Convert as we copy. */
+        for (kk = 0; kk < src_planes; kk++) {
 
-        ptr_out = buff_out + kk * fill_trans_buffer->planestride;
-        ptr_in  = buff_in  + kk * ptile->ttrans->planestride;
-        if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan)
-            ptr_out += fill_trans_buffer->planestride;	/* tag plane follows shape plane */
+            ptr_out = buff_out + kk * fill_trans_buffer->planestride;
+            ptr_in  = buff_in  + kk * ptile->ttrans->planestride;
+            if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan)
+                ptr_out += fill_trans_buffer->planestride;	/* tag plane follows shape plane */
 
-        for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
+            for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
 
-            in_row_offset = ((jj + dy) % ptile->ttrans->height);
-            if (in_row_offset >= ptile->ttrans->rect.q.y)
-                continue;
-            in_row_offset -= ptile->ttrans->rect.p.y;
-            if (in_row_offset < 0)
-                continue;
-            row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
+                in_row_offset = ((jj + dy) % ptile->ttrans->height);
+                if (in_row_offset >= ptile->ttrans->rect.q.y)
+                    continue;
+                in_row_offset -= ptile->ttrans->rect.p.y;
+                if (in_row_offset < 0)
+                    continue;
+                row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
 
-             /* This is the case when we have no blending. */
-            ptr_out_temp = ptr_out;
+                 /* This is the case when we have no blending. */
+                ptr_out_temp = ptr_out;
 
-            /* Left part */
-            memcpy( ptr_out_temp, row_ptr + left_copy_offset, left_copy_width<<deep);
-            ptr_out_temp += left_width<<deep;
+                /* Left part */
+                be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)(row_ptr + left_copy_offset), left_copy_width);
+                ptr_out_temp += left_width<<deep;
 
-            /* Now the full tiles */
+                /* Now the full tiles */
 
-            for ( ii = 0; ii < num_full_tiles; ii++){
-                memcpy( ptr_out_temp, row_ptr, mid_copy_width<<deep);
-                ptr_out_temp += tile_width<<deep;
+                for ( ii = 0; ii < num_full_tiles; ii++){
+                    be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, mid_copy_width);
+                    ptr_out_temp += tile_width<<deep;
+                }
+
+                /* Now the remainder */
+                be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, right_copy_width);
             }
+        }
+    } else {
+        for (kk = 0; kk < src_planes; kk++) {
+
+            ptr_out = buff_out + kk * fill_trans_buffer->planestride;
+            ptr_in  = buff_in  + kk * ptile->ttrans->planestride;
+            if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan)
+                ptr_out += fill_trans_buffer->planestride;	/* tag plane follows shape plane */
+
+            for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
+
+                in_row_offset = ((jj + dy) % ptile->ttrans->height);
+                if (in_row_offset >= ptile->ttrans->rect.q.y)
+                    continue;
+                in_row_offset -= ptile->ttrans->rect.p.y;
+                if (in_row_offset < 0)
+                    continue;
+                row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
+
+                 /* This is the case when we have no blending. */
+                ptr_out_temp = ptr_out;
 
-            /* Now the remainder */
-            memcpy( ptr_out_temp, row_ptr, right_copy_width<<deep);
+                /* Left part */
+                memcpy( ptr_out_temp, row_ptr + left_copy_offset, left_copy_width<<deep);
+                ptr_out_temp += left_width<<deep;
+
+                /* Now the full tiles */
+
+                for ( ii = 0; ii < num_full_tiles; ii++){
+                    memcpy( ptr_out_temp, row_ptr, mid_copy_width<<deep);
+                    ptr_out_temp += tile_width<<deep;
+                }
+
+                /* Now the remainder */
+                memcpy( ptr_out_temp, row_ptr, right_copy_width<<deep);
+            }
         }
     }
 
@@ -952,6 +1005,7 @@ do_tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
     }
 }
 
+/* In this version, source data is big endian, dest is native endian */
 static void
 do_tile_rect_trans_blend_16(int xmin, int ymin, int xmax, int ymax,
                             int px, int py, const gx_color_tile *ptile,
@@ -1023,6 +1077,119 @@ do_tile_rect_trans_blend_16(int xmin, int ymin, int xmax, int ymax,
             /* Data is stored in big endian, but must be processed in native */
 #define GET16_BE2NATIVE(v) \
     ((((byte *)(v))[0]<<8) | (((byte *)(v))[1]))
+
+            /* The color values. This needs to be optimized */
+            for (kk = 0; kk < num_chan; kk++) {
+                dst[kk] = *(buff_ptr + kk * (fill_trans_buffer->planestride>>1));
+                src[kk] = GET16_BE2NATIVE(tile_ptr + kk * (ptile->ttrans->planestride>>1));
+            }
+
+            /* Blend */
+            art_pdf_composite_pixel_alpha_16(dst, src, ptile->ttrans->n_chan-1,
+                                             ptile->blending_mode, ptile->ttrans->n_chan-1,
+                                             ptile->ttrans->blending_procs, p14dev);
+
+            /* Store the color values */
+            for (kk = 0; kk < num_chan; kk++) {
+                *(buff_ptr + kk * (fill_trans_buffer->planestride>>1)) = dst[kk];
+            }
+            /* Now handle the blending of the tag. NB: dst tag_offset follows shape */
+            if (tag_offset > 0) {
+                int src_tag = GET16_BE2NATIVE(tile_ptr + (num_chan * ptile->ttrans->planestride>>1));
+                int dst_tag = *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1));
+
+                dst_tag |= src_tag;	/* simple blend combines tags */
+                *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1)) = dst_tag;
+            }
+        }
+    }
+#undef GET16_BE2NATIVE
+
+    /* If the group we are filling has a shape plane fill that now */
+    /* Note:  Since this was a virgin group push we can just blast it with
+     * 255 */
+    if (fill_trans_buffer->has_shape) {
+        buff_ptr = buff_out + fill_trans_buffer->n_chan * (fill_trans_buffer->planestride>>1);
+
+        for (jj = 0; jj < h; jj++) {
+            memset(buff_ptr, 255, w*2);
+            buff_ptr += fill_trans_buffer->rowstride>>1;
+        }
+    }
+}
+
+/* In this version, both source and dest data is big endian */
+static void
+do_tile_rect_trans_blend_16be(int xmin, int ymin, int xmax, int ymax,
+                              int px, int py, const gx_color_tile *ptile,
+                              gx_pattern_trans_t *fill_trans_buffer)
+{
+    int kk, jj, ii, h, w;
+    int buff_out_y_offset, buff_out_x_offset;
+    uint16_t *buff_out, *buff_in;
+    uint16_t *buff_ptr, *row_ptr_in, *row_ptr_out;
+    uint16_t *tile_ptr;
+    int in_row_offset;
+    int dx, dy;
+    uint16_t src[PDF14_MAX_PLANES];
+    uint16_t dst[PDF14_MAX_PLANES];
+    int tile_width  = ptile->ttrans->width;
+    int tile_height = ptile->ttrans->height;
+    int num_chan    = ptile->ttrans->n_chan;  /* Includes alpha */
+    int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0);
+    pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14;
+
+    if (fill_trans_buffer->has_tags == 0)
+        tag_offset = 0;
+
+    buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
+    buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
+
+    h = ymax - ymin;
+    w = xmax - xmin;
+
+    if (h <= 0 || w <= 0) return;
+
+    /* Calc dx, dy within the entire (conceptual) input tile. */
+    dx = (xmin + px) % tile_width;
+    dy = (ymin + py) % tile_height;
+
+    buff_out = (uint16_t *)(void *)(fill_trans_buffer->transbytes +
+                                    buff_out_y_offset * fill_trans_buffer->rowstride +
+                                    buff_out_x_offset*2);
+
+    buff_in = (uint16_t *)(void *)ptile->ttrans->transbytes;
+
+    for (jj = 0; jj < h; jj++){
+
+        in_row_offset = (jj + dy) % ptile->ttrans->height;
+        if (in_row_offset >= ptile->ttrans->rect.q.y)
+            continue;
+        in_row_offset -= ptile->ttrans->rect.p.y;
+        if (in_row_offset < 0)
+            continue;
+        row_ptr_in = buff_in + in_row_offset * (ptile->ttrans->rowstride>>1);
+
+        row_ptr_out = buff_out + jj * (fill_trans_buffer->rowstride>>1);
+
+        for (ii = 0; ii < w; ii++) {
+            int x_in_offset = (dx + ii) % ptile->ttrans->width;
+
+            if (x_in_offset >= ptile->ttrans->rect.q.x)
+                continue;
+            x_in_offset -= ptile->ttrans->rect.p.x;
+            if (x_in_offset < 0)
+                continue;
+            tile_ptr = row_ptr_in + x_in_offset;
+            buff_ptr = row_ptr_out + ii;
+
+            /* We need to blend here.  The blending mode from the current
+               imager state is used.
+            */
+
+            /* Data is stored in big endian, but must be processed in native */
+#define GET16_BE2NATIVE(v) \
+    ((((byte *)(v))[0]<<8) | (((byte *)(v))[1]))
 #define PUT16_NATIVE2BE(p,v) \
     ((((byte *)(p))[0] = v>>8), (((byte *)(p))[1] = v))
 
@@ -1068,7 +1235,8 @@ do_tile_rect_trans_blend_16(int xmin, int ymin, int xmax, int ymax,
 void
 tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
                       int px, int py, const gx_color_tile *ptile,
-                      gx_pattern_trans_t *fill_trans_buffer)
+                      gx_pattern_trans_t *fill_trans_buffer,
+                      int native16)
 {
     pdf14_buf *buf = fill_trans_buffer->buf;
 
@@ -1083,12 +1251,15 @@ tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
     if (buf->dirty.q.y < ymax)
         buf->dirty.q.y = ymax;
 
-    if (ptile->ttrans->deep)
+    if (!ptile->ttrans->deep)
+        do_tile_rect_trans_blend(xmin, ymin, xmax, ymax,
+                                 px, py, ptile, fill_trans_buffer);
+    else if (native16)
         do_tile_rect_trans_blend_16(xmin, ymin, xmax, ymax,
                                     px, py, ptile, fill_trans_buffer);
     else
-        do_tile_rect_trans_blend(xmin, ymin, xmax, ymax,
-                                 px, py, ptile, fill_trans_buffer);
+        do_tile_rect_trans_blend_16be(xmin, ymin, xmax, ymax,
+                                      px, py, ptile, fill_trans_buffer);
 }
 
 /* This version does a rect fill with the transparency object */
@@ -1124,7 +1295,7 @@ gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y,
 #endif
     code = gx_trans_pattern_fill_rect(x, y, x+w, y+h, ptile,
                                       ptile->ttrans->fill_trans_buffer, phase,
-                                      dev, pdevc);
+                                      dev, pdevc, 0);
     return code;
 }
 
@@ -1135,7 +1306,8 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
                            gx_color_tile *ptile,
                            gx_pattern_trans_t *fill_trans_buffer,
                            gs_int_point phase, gx_device *dev,
-                           const gx_device_color * pdevc)
+                           const gx_device_color * pdevc,
+                           int native16)
 {
     tile_fill_trans_state_t state_trans;
     tile_fill_state_t state_clist_trans;
@@ -1166,7 +1338,7 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
                  ptile->ttrans->height);
 
         tile_rect_trans_simple(xmin, ymin, xmax, ymax, px, py, ptile,
-            fill_trans_buffer);
+            fill_trans_buffer, native16);
     } else {
         if (ptile->cdev == NULL) {
             /* No clist for the pattern, but a complex case
@@ -1174,7 +1346,8 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
                and does partial rect fills with tiles that fall into this
                transformed bbox */
             code = tile_by_steps_trans(&state_trans, xmin, ymin, xmax-xmin,
-                                        ymax-ymin, fill_trans_buffer, ptile);
+                                        ymax-ymin, fill_trans_buffer, ptile,
+                                        native16);
 
         } else {
             /* clist for the trans tile.  This uses the pdf14 device as a target
diff --git a/base/gxpcolor.h b/base/gxpcolor.h
index 989a163..c12fa31 100644
--- a/base/gxpcolor.h
+++ b/base/gxpcolor.h
@@ -167,7 +167,8 @@ struct gx_pattern_trans_s {
     void *buf;
     void (* pat_trans_fill)(int xmin, int ymin, int xmax, int ymax, int px,
                             int py, const gx_color_tile *ptile,
-                            gx_pattern_trans_t *fill_trans_buffer);
+                            gx_pattern_trans_t *fill_trans_buffer,
+                            int native16);
     int (* image_render)(gx_image_enum * penum, const byte * buffer,
                             int data_x, uint w, int h, gx_device * dev);
 };
@@ -336,20 +337,23 @@ int gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
                                gx_color_tile *ptile,
                                gx_pattern_trans_t *fill_trans_buffer,
                                gs_int_point phase, gx_device *dev,
-                               const gx_device_color * pdevc);
+                               const gx_device_color * pdevc,
+                               int native16);
 
 gx_pattern_trans_t* new_pattern_trans_buff(gs_memory_t *mem);
 
 void tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax, int px,
                             int py, const gx_color_tile *ptile,
-                            gx_pattern_trans_t *fill_trans_buffer);
+                            gx_pattern_trans_t *fill_trans_buffer,
+                            int native16);
 
 /* This is used for the case when we may have overlapping tiles.
    We need to get better detection for this as
    it would be best to avoid doing it if not needed. */
 void tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax, int px,
                            int py, const gx_color_tile *ptile,
-                           gx_pattern_trans_t *fill_trans_buffer);
+                           gx_pattern_trans_t *fill_trans_buffer,
+                           int native16);
 
 /* File a colored pattern with white */
 int gx_erase_colored_pattern(gs_gstate *pgs);


Summary of changes:
 base/gdevdflt.c |   5 +-
 base/gdevmem.c  |   5 +-
 base/gdevp14.c  | 128 ++++++++++++++++-------------
 base/gdevprn.c  |   5 +-
 base/gsptype1.c |   5 +-
 base/gstrans.c  |   5 +-
 base/gxblend.c  |  18 +++--
 base/gxclthrd.c |   5 +-
 base/gxdevcli.h |  15 ++++
 base/gxp1fill.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 base/gxpcolor.h |  12 ++-
 11 files changed, 319 insertions(+), 127 deletions(-)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.