[gs-commits] ghostpdl branch, master, updated. jbig2dec-0.14-1557-g009d44b

[email protected] (Michael Vrhel)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, master has been updated
       via  009d44b855dcda9d0d9ecf5ca20944504648eebe (commit)
      from  d8f05309d5e54b6e75c2b78af9c0bcf5f62b493c (commit)

----------------------------------------------------------------------
commit 009d44b855dcda9d0d9ecf5ca20944504648eebe
Author: Michael Vrhel <[email protected]>
Date:   Fri Jun 14 16:52:28 2019 -0700

    CompatibleOverprint Mode
    
    Ray did the interpreter work on this and Michael did the graphics
    library portion.
    
    For the interpreter:
    When OP is set, change to CompatibleOverprint mode, but don't push a
    transparency group or change opacityalpha when the current blendmode
    is Normal or Compatible. This was determined based on the note on page
    568 of the PDF 1.7 spec (section 7.6.3 in the area titled "Compatibility
    with Opaque Printing"). It states:
    
      Note: It is not necessary to create such an implicit transparency
      group if the current blend mode is Normal; simply substituting
      the CompatibleOverprint blend mode while painting the object
      produces equivalent results. There are some additional cases in
      which the implicit transparency group can be optimized out.
    
    After painting, if the group was pushed, pop the group, and restore the
    opacityalpha and shapealpha,then restore the blendmode (if it was
    CompatibleOverprint).
    
    NB, we don't attempt to optimize any other groups hinted at in
    Adobe's comment.
    
    In addition, if we are going to an output device that handles transparency
    compositor actions do not do any of the above stuff.
    
    For the graphics library:
    When doing blending in non-isolated groups with compatible overprint
    the non-drawn colors must be corrected during the fill rectangles to
    ensure that the proper amount is maintained with the changing group
    alpha values.  This is poorly documented in the specification.
    In addition, the spec is poorly written in terms of how the blend
    computation is performed for overprint compatible.
    
    The spec claims the following:
    
     If the overprint mode is 1 (nonzero overprint mode) and the
     current color space and group color space are both DeviceCMYK,
     then only process color components with nonzero values replace
     the corresponding component values of the backdrop. All other
     component values leave the existing backdrop value unchanged.
     That is, the value of the blend function B(Cb,Cs) is the source
     component cs for any process (DeviceCMYK) color component whose
     (subtractive) color value is nonzero; otherwise it is the
     backdrop component cb. For spot color components, the value is
     always cb.
    
     The equation for compositing is
    
            ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*B(Cb,Cs)]
    
     Now if I simply set B(cb,cs) to cb for the case when the
     DevieCMYK value (with opm true) is zero I get
    
     ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*Cb]
    
     But what I am seeing with AR is
            ar*Cr = (1-as)*Cb + as*[(1-ab)*Cb+ab*Cb] = (1-as)*Cb + as*Cb = Cb
     which is what I think we want.
    
     The description in the spec is confusing as it says
    "then only process color components with nonzero values replace
     the corresponding component values of the backdrop. All other
     component values leave the existing backdrop value unchanged"
    
     which makes sense for overprinting,
    
     vs.
    
     "That is, the value of the blend function B(Cb,Cs) is the source
     component cs for any process (DeviceCMYK) color component whose
     (subtractive) color value is nonzero; otherwise it is the
     backdrop component cb."
    
     Which is NOT the same thing as leaving the backdrop unchanged
     with the compositing equation
     ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*B(Cb,Cs)]
    
     For this to work, we need to carry out the operation during
     the mixing of the source with the blend result.  Essentially
     replacing that mixing with the color we have here.

diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
index dc499e8..49bb4eb 100644
--- a/Resource/Init/pdf_draw.ps
+++ b/Resource/Init/pdf_draw.ps
@@ -1396,7 +1396,6 @@ drawopdict begin
   /W* { W* } executeonly def
 
   /sh_save 1 array def
-  /sh_group  << /Subtype /Group /Isolated //true >> readonly def
 
   /do_shade {
     0 .setoverprintmode
@@ -1417,38 +1416,19 @@ drawopdict begin
         setfillstate resolvesh
         //sh_save 0 save put
         PDFusingtransparency {
-           .currentSMask //null ne {
-             //sh_group
-             1 index /BBox knownoget {
-               { oforce } forall
-             } {
-               gsave clippath pathbbox grestore
-             } ifelse
-             .begintransparencygroup
-           } if
-           dup checkOPtrans exch 1 index {
-              % We need to push a non-isolated, non-knockout transparency group and
-              % perform the operation in CompatibleOverprint mode, then end the
-              % transparency group. Do the begintransparencygroup step here.
-              mark /Subtype /Group /Isolated //false .dicttomark
-              1 index /BBox knownoget {
-                { oforce } forall
-              } {
-                gsave clippath pathbbox grestore
-              } ifelse
-              .begintransparencygroup
-               exch .currentblendmode exch .currentopacityalpha exch 4 -1 roll % save current values
-               /CompatibleOverprint .setblendmode 1 .setopacityalpha
-           } if
-           //do_shade exec
-           {
-               .endtransparencygroup .setopacityalpha .setblendmode	% end the CompatibleOverprint group
-           } if
-           .currentSMask //null ne {
-             .endtransparencygroup
-           } if
+          gsave
+          dup /BBox knownoget {
+            { oforce } forall
+            4 2 roll moveto exch 0 lineto 0 exch lineto closepath
+          } {
+            clippath
+          } ifelse
+          //null setup_trans
+          grestore
+          //do_shade exec
+          teardown_trans
         } {
-           //do_shade exec
+          //do_shade exec
         } ifelse
         //sh_save 0 get restore
       } {
@@ -2255,7 +2235,7 @@ currentdict /last-ditch-bpc-csp undef
       PDFfile exch setfileposition
       0 .endtransparencymask
     } ifelse
-       << /Subtype /Group /Isolated //true
+    << /Subtype /Group /Isolated //true
        /.image_with_SMask //true
        % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c
        % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask
@@ -2265,7 +2245,7 @@ currentdict /last-ditch-bpc-csp undef
        % We also need to actually set the current colour space to be the same as the group
        % code only picks up the current colour space, not the space from the dictionary.
        currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if
-     >> 0 0 1 1 .begintransparencygroup
+    >> 0 0 1 1 .begintransparencygroup
      doimage
     .endtransparencygroup
     % tell the compositor we're done with the SMask.
@@ -2333,15 +2313,6 @@ currentdict /last-ditch-bpc-csp undef
 
 /doimage {	% <imagemask> doimage -
                 % imagedict is currentdict, gets popped from dstack
-  //null checkOPtrans {
-     % We need to push a non-isolated, non-knockout transparency group and
-     % perform the operation in CompatibleOverprint mode, then end the
-     % transparency group. Do the begintransparencygroup step here.
-     mark /Subtype /Group /Isolated //false .dicttomark 0 0 1 1 .begintransparencygroup
-     OPsavedict dup /saveBM .currentblendmode put /saveOA .currentopacityalpha put % save current values
-     /CompatibleOverprint .setblendmode 1 .setopacityalpha
-  } if
-
   %% save the current rendering intent
   .currentrenderintent exch
 
@@ -2363,6 +2334,7 @@ currentdict /last-ditch-bpc-csp undef
       makemaskimage
   } if
                 % Stack: datasource imagemask
+  gsave 1 1 moveto 0 0 lineto /image setup_trans grestore
   { currentdict end setfillstate //true ValidateDecode { imagemask } }
   { ColorSpace setgcolorspace currentdict end setfillblend //false ValidateDecode { image } }
   ifelse
@@ -2387,10 +2359,7 @@ currentdict /last-ditch-bpc-csp undef
   %% restore the rendering intent
   .setrenderingintent
 
-  .currentblendmode /CompatibleOverprint eq {
-     .endtransparencygroup
-     OPsavedict dup /saveOA get .setopacityalpha /saveBM get .setblendmode
-  } if
+  teardown_trans
 } bind executeonly def
 
 /.paintform {	% <formdict> <resdict> <stream> .paintform -
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 9d70f0d..00d7e36 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -2705,11 +2705,14 @@ currentdict /PDF2PS_matrix_key undef
         % (eg GSView 5) then it will not be present, so we must rescan.
   currentpagedevice /PageUsesTransparency .knownget not {dup pageusestransparency} if
   dup /PDFusingtransparency exch def {
-    % If the current device isn't CMYK, or if it is a HighLevelDevice (pdfwrite) we
-    % don't need the special handling of Overprint transparency, so disable the checking.
-    currentpagedevice dup /Colors get 4 lt exch /HighLevelDevice known or {
-      /checkOPtrans { pop //false } def	% NB: original will be restored from PDFsave
-    } if
+    % If the current device isn't CMYK, or if it is a device that (currently) supports transparency
+    % we don't need the special handling of Overprint transparency, so disable the checking.
+    currentpagedevice dup /Colors get 4 lt
+    exch /HaveTransparency .knownget not { //false } if or
+    % device needs special Oveprint handling
+    /setup_trans exch
+    { /setupSMtrans } { /setupOPtrans } ifelse
+    load def
     % Show the page within a PDF 1.4 device filter.
     0 .pushpdf14devicefilter {
       /DefaultQstate qstate store		% device has changed -- reset DefaultQstate
@@ -2737,7 +2740,7 @@ currentdict /PDF2PS_matrix_key undef
     .poppdf14devicefilter	% NB: reset to DefaultQstate will also restore transfer function
     /DefaultQstate qstate store	% device has changed -- reset DefaultQstate
   } {
-    /checkOPtrans { pop //false } def	% no-op the check if the page doesn't use transparency
+    /setup_trans { pop } def    % no-op this if the page doesn't use transparency
                                 % NB: original will be restored from PDFsave
     showpagecontents
   } ifelse
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index 014d7d4..a15c8c6 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -672,59 +672,127 @@ end def
   } ifelse
 } bind executeonly def
 
-/OPsavedict 2 dict def		% for saveOP, saveBM
+/OPsaveDstack 6 dict def		% for GroupPushed, saveOP, saveSA, saveBM
+//OPsaveDstack begin
+  /GroupPushed //false def
+  /ChangeBM //false def
+  /saveOA 1 def
+  /saveSA 1 def
+  /saveBM /Normal def
+  /previous 1 dict def		% for nested setup_trans levels
+end
+
+/Dpush {
+  .currentglobal //true .setglobal	% 'previous' dict must be in global VM
+  //OPsaveDstack 6 dict 1 index { 2 index 3 1 roll put } forall /previous exch put
+  .setglobal
+} def
+/Dpop { //OPsaveDstack begin previous { def } forall end } def
 
 % colorspaces that don't require special overprint transparency handling
 /okOPcs mark /DeviceGray 0 /DeviceCMYK 1 /DeviceN 2 /Separation 3 .dicttomark def
 
-/checkOPtrans	% <fillop|strokeop> checkOPtrans <bool>
-% return true if OP needs special transparency treatment
-% If the colorspace is not one where overprint makes sense, no special handling (return false)
-% NB: This will get replaced with a quick "no-op" if the device doesn't support Overprint
+% Take care of pushing a transparency group if we need it for SMask or for Overprint..
+% After pushing the group, we save the opacityalpha and shapealpha and change them
+% both to 1. For overprint if the colorspace is acceptable, also change to
+% CompatibleOverprint if the device needs it.
+
+% NB: setup_trans is defined as either setupOPtrans (for devices that can support
+%     overprint, or as setupSMtrans which pushes a group for SMask.
+% Also see 'teardown_trans' that pops the group and resets the changed values.
+/setupOPtrans	% <fillop|strokeop> setup_trans
 {  % Check OP and BM in case we need to push a group
-    okOPcs currentcolorspace 0 get dup /Indexed eq {
-       pop currentcolorspace 1 get	% use the base space
-    } if
-    known {
-       /stroke ne { .currentfilloverprint
-       } { .currentstrokeoverprint
-       } ifelse
-       .currentblendmode dup /Normal eq exch /Compatible eq or not and
-   } {
-      pop //false
-   } ifelse
+  //OPsaveDstack begin
+  //Dpush exec			% push the current OPsaveDstack values into 'previous'
+  okOPcs currentcolorspace 0 get dup /Indexed eq {
+    pop currentcolorspace 1 get	% use the base space
+  } if
+  known {
+    1 index /stroke ne { .currentfilloverprint } { .currentstrokeoverprint } ifelse
+    % Change BM to CompatibleOverprint if this has overprint true
+    dup /ChangeBM exch def
+    .currentblendmode dup /Normal eq exch /Compatible eq or
+    not and
+  } {
+    //false
+  } ifelse
+  .currentSMask //null ne or {		% push a group for OP or SMask
+    mark /Subtype /Group /Isolated .currentSMask //null ne .dicttomark
+    1 index /stroke eq {
+      % BBox needs to include line width / line join expansion.
+      gsave strokepath pathbbox grestore
+    } {
+      pathbbox     % fill/eofill cases
+    } ifelse
+    .begintransparencygroup
+    % After group pushed, set opacityalpha, shapealpha and blendmode
+    /saveOA .currentopacityalpha def
+    /saveSA .currentshapealpha def
+    1 .setopacityalpha 1 .setshapealpha
+    /GroupPushed //true def
+  } if
+  % we may change to CompatibleOverprint even if we didn't push a group.
+  ChangeBM {
+    /saveBM .currentblendmode def /CompatibleOverprint .setblendmode
+  } if
+  pop		% fillop/strokeop
+  end	% OPsaveDstack
 } bind executeonly def
 
+% Also see 'teardown_trans' that pops the group and resets the changed values.
+/setupSMtrans	% <fillop|strokeop> setup_trans
+{
+  //OPsaveDstack begin
+  //Dpush exec			% push the current OPsaveDstack values into 'previous'
+  .currentSMask //null ne 1 index /image ne and		% only push for SMask if not from image
+  {
+    mark /Subtype /Group /Isolated //true .dicttomark
+    exch /stroke eq {
+    % BBox needs to include line width / line join expansion.
+      gsave strokepath pathbbox grestore
+    } {
+      pathbbox     % fill/eofill cases
+    } ifelse
+    .begintransparencygroup
+    % After group pushed, set opacityalpha, shapealpha and blendmode
+    /saveOA .currentopacityalpha def
+    /saveSA .currentshapealpha def
+    1 .setopacityalpha 1 .setshapealpha
+    /GroupPushed //true def
+  } {
+    /GroupPushed //false def
+    pop		% fillop/strokeop
+  } ifelse
+  end	% OPsaveDstack
+} bind executeonly def
+
+% If a transparency group was pushed, pop it, and reset the settings.
+% Used after setup_trans
+/teardown_trans {
+  //OPsaveDstack begin
+  GroupPushed {
+    % pop the group, then restore the opacityalpha and shapealpha
+    .endtransparencygroup	% end the group
+    saveOA .setopacityalpha saveSA .setshapealpha
+  } if
+  % Also, if we changed the BM, restore it (AFTER the group was popped)
+  .currentblendmode /CompatibleOverprint eq {
+    % restore the blendmode
+    saveBM .setblendmode
+  } if
+  end	% OPsaveDstack
+  //Dpop exec			% load previous OPsaveDstack contents
+} bind executeonly def
+
+currentdict dup /Dpush .undef /Dpop .undef
+
+% ------------------------------------------------------------ %
 /fsexec		% <fillop|strokeop> fsexec -
 {
    PDFusingtransparency {
-      .currentSMask //null ne {
-        mark /Subtype /Group /Isolated //true .dicttomark
-        1 index /stroke eq {
-          % BBox needs to include line width / line join expansion.
-          gsave strokepath pathbbox grestore
-        } {
-          pathbbox	% fill/eofill cases
-        } ifelse
-        .begintransparencygroup
-        .currentshapealpha .currentopacityalpha 3 -1 roll % avoid double application
-        1 .setopacityalpha 1 .setshapealpha
-      } if
-      dup checkOPtrans exch 1 index {
-         % We need to push a non-isolated, non-knockout transparency group and
-         % perform the operation in CompatibleOverprint mode, then end the
-         % transparency group. Do the begintransparencygroup step here.
-         mark /Subtype /Group /Isolated //false .dicttomark pathbbox .begintransparencygroup
-         .currentblendmode .currentopacityalpha 4 -2 roll % save current values
-         /CompatibleOverprint .setblendmode 1 .setopacityalpha
-      } if
+      dup setup_trans
       cvx exec
-      {
-         .endtransparencygroup .setopacityalpha .setblendmode	% end the CompatibleOverprint group
-      } if
-      .currentSMask //null ne {
-       .endtransparencygroup .setopacityalpha .setshapealpha
-      } if
+      teardown_trans
    } {
       cvx exec
    } ifelse
@@ -1104,11 +1172,13 @@ end readonly def
 } bind executeonly odef
 
 /BT {
+  //false /illegal_BT gput
   currentdict /TextSaveMatrix known {
     (   **** Error: illegal nested BT operator detected.\n)
     pdfformaterror
     (               Output may be incorrect.\n) pdfformaterror
     ET_NO_TXT_KO  %% Does not push any compositor actions
+    //true /illegal_BT gput
   } if
 
   %% Bug #695897 see the explanation in /q defined above.
@@ -1118,6 +1188,7 @@ end readonly def
     pdfformaterror
     (               Output may be incorrect.\n) pdfformaterror
     ET_NO_TXT_KO  %% Does not push any compositor actions
+    //true /illegal_BT gput
   } if
   currentdict /n known {
     currentdict end
@@ -1139,7 +1210,9 @@ end readonly def
   %% If needed, let the pdf14 device know we are in a BT condition.  This
   %% distinguishes BT from an Annotation /FreeText show command which also
   %% can come into pdf_text_begin with an opacity not equal to 1.
-  PDFusingtransparency .currenttextknockout and {
+  PDFusingtransparency .currenttextknockout and
+  currentdict /illegal_BT get not and
+{
     .begintransparencytextgroup
   } if
 
@@ -1566,37 +1639,14 @@ end readonly def
 } bind executeonly def
 
 % If current path is not known to be valid, use the clip path
-/TextTransSetup {	% showarg path_valid TextTransSetup false showarg
-                        % showarg path_valid false TextTransSetup prev_BM prev_opacity true showarg
+/TextTransSetup {	% showarg path_valid TextTransSetup showarg
+                        % showarg path_valid false TextTransSetup showarg
    % NB: if 'show' is used, then we use the clippath, but a smaller bbox is preferred
-   .currentSMask //null ne {
-     dup mark /Subtype /Group /Isolated //true .dicttomark exch
-     { pathbbox } { gsave clippath pathbbox grestore } ifelse
-     .begintransparencygroup
-   } if
-   //null checkOPtrans {
-     % We need to push a non-isolated, non-knockout transparency group and
-     % perform the operation in CompatibleOverprint mode, then end the
-     % transparency group. Do the begintransparencygroup step here.
-     mark /Subtype /Group /Isolated //false .dicttomark exch
-     { pathbbox } { gsave clippath pathbbox grestore } ifelse
-     .begintransparencygroup
-     OPsavedict dup /saveBM .currentblendmode put /saveOA .currentopacityalpha put % save current values
-     /CompatibleOverprint .setblendmode 1 .setopacityalpha
-   } {
-     pop	% discard path_valid boolean
-   } ifelse
+   not dup { gsave clippath } if //null setup_trans { grestore } if
 } bind executeonly def
 
-/TextTransTeardown {	% stack: path_valid
-   .currentblendmode /CompatibleOverprint eq {
-     % end the CompatibleOverprint group and restore the opacity and BM
-     .endtransparencygroup
-     OPsavedict dup /saveOA get .setopacityalpha /saveBM get .setblendmode
-   } if
-   .currentSMask //null ne {
-     .endtransparencygroup
-   } if
+/TextTransTeardown {
+  teardown_trans
 } bind executeonly def
 
 /setshowstate
diff --git a/base/gdevp14.c b/base/gdevp14.c
index 9ddd9fb..18128ee 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -2782,11 +2782,11 @@ pdf14_set_marking_params(gx_device *dev, const gs_gstate *pgs)
     pdev->alpha = pgs->opacity.alpha * pgs->shape.alpha;
     pdev->blend_mode = pgs->blend_mode;
     pdev->overprint = pgs->overprint;
-    pdev->overprint_mode = pgs->overprint_mode;
+    pdev->effective_overprint_mode = pgs->effective_overprint_mode;
 
-    if_debug3m('v', dev->memory,
-               "[v]set_marking_params, opacity = %g, shape = %g, bm = %d\n",
-               pdev->opacity, pdev->shape, pgs->blend_mode);
+    if_debug5m('v', dev->memory,
+               "[v]set_marking_params, opacity = %g, shape = %g, bm = %d, op = %d, eop = %d\n",
+               pdev->opacity, pdev->shape, pgs->blend_mode, pgs->overprint, pgs->effective_overprint_mode);
 }
 
 static  void
@@ -2965,6 +2965,9 @@ do_pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
     bool has_shape = buf->has_shape;
     bool has_tags = buf->has_tags;
     bool knockout = buf->knockout;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
     int num_chan = buf->n_chan;
     int num_comp = num_chan - 1;
     int shape_off = num_chan * planestride;
@@ -3113,7 +3116,7 @@ do_pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
                 if (has_tags) {
                     /* If alpha is 100% then set to curr_tag, else or */
                     /* other than Normal BM, we always OR */
-                    if (src[num_comp] == 255 && blend_mode == BLEND_MODE_Normal) {
+                    if (src[num_comp] == 255 && tag_blend) {
                         dst_ptr[tag_off] = curr_tag;
                     } else {
                         dst_ptr[tag_off] |= curr_tag;
@@ -3142,6 +3145,9 @@ do_pdf14_copy_alpha_color_16(gx_device * dev, const byte * data, int data_x,
     uint16_t src[PDF14_MAX_PLANES];
     uint16_t dst[PDF14_MAX_PLANES] = { 0 };
     gs_blend_mode_t blend_mode = pdev->blend_mode;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
     bool additive = pdev->ctx->additive;
     int rowstride = buf->rowstride;
     int planestride = buf->planestride;
@@ -3301,7 +3307,7 @@ do_pdf14_copy_alpha_color_16(gx_device * dev, const byte * data, int data_x,
                 if (has_tags) {
                     /* If alpha is 100% then set to curr_tag, else or */
                     /* other than Normal BM, we always OR */
-                    if (src[num_comp] == 65535 && blend_mode == BLEND_MODE_Normal) {
+                    if (src[num_comp] == 65535 && tag_blend) {
                         dst_ptr[tag_off] = curr_tag;
                     } else {
                         dst_ptr[tag_off] |= curr_tag;
@@ -3863,7 +3869,7 @@ pdf14_set_params(gs_gstate * pgs,
     if (pparams->changed & PDF14_SET_OVERPRINT)
         pgs->overprint = pparams->overprint;
     if (pparams->changed & PDF14_SET_OVERPRINT_MODE)
-        pgs->overprint_mode = pparams->overprint_mode;
+        pgs->effective_overprint_mode = pparams->effective_overprint_mode;
     pdf14_set_marking_params(dev, pgs);
 }
 
@@ -4498,7 +4504,7 @@ pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
     gs_text_enum_t *penum;
     gs_blend_mode_t blend_mode = gs_currentblendmode(pgs);
     float opacity = gs_currentopacityalpha(pgs);
-    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible);
+    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint);
     pdf14_device *pdev = (pdf14_device*)dev;
     bool draw = !(text->operation & TEXT_DO_NONE);
 
@@ -5662,6 +5668,9 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
     pdf14_device *pdev = (pdf14_device *)dev;
     pdf14_buf *buf = pdev->ctx->stack;
     gs_blend_mode_t blend_mode = pdev->blend_mode;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
     int i, j, k;
     byte *bline, *bg_ptr, *line, *dst_ptr;
     byte src[PDF14_MAX_PLANES];
@@ -5794,7 +5803,7 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (src[num_comp] == 255 && blend_mode == BLEND_MODE_Normal) {
+                if (src[num_comp] == 255 && tag_blend) {
                     dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
@@ -5837,6 +5846,9 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
     pdf14_device *pdev = (pdf14_device *)dev;
     pdf14_buf *buf = pdev->ctx->stack;
     gs_blend_mode_t blend_mode = pdev->blend_mode;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
     int i, j, k;
     uint16_t *bline, *bg_ptr, *line, *dst_ptr;
     uint16_t src[PDF14_MAX_PLANES];
@@ -5972,7 +5984,7 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (src[num_comp] == 65535 && blend_mode == BLEND_MODE_Normal) {
+                if (src[num_comp] == 65535 && tag_blend) {
                     dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
@@ -6914,7 +6926,7 @@ c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize,
             if (pparams->changed & PDF14_SET_OVERPRINT)
                 put_value(pbuf, pparams->overprint);
             if (pparams->changed & PDF14_SET_OVERPRINT_MODE)
-                put_value(pbuf, pparams->overprint_mode);
+                put_value(pbuf, pparams->effective_overprint_mode);
             break;
         case PDF14_PUSH_TRANS_STATE:
             break;
@@ -7111,7 +7123,7 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte *	data,
             if (params.changed & PDF14_SET_OVERPRINT)
                 read_value(data, params.overprint);
             if (params.changed & PDF14_SET_OVERPRINT_MODE)
-                read_value(data, params.overprint_mode);
+                read_value(data, params.effective_overprint_mode);
             break;
     }
     code = gs_create_pdf14trans(ppct, &params, mem);
@@ -8384,9 +8396,9 @@ pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_gstate * pgs,
         changed |= PDF14_SET_OVERPRINT;
         params.overprint = pdev->overprint = pgs->overprint;
     }
-    if (pgs->overprint_mode != pdev->overprint_mode) {
+    if (pgs->effective_overprint_mode != pdev->effective_overprint_mode) {
         changed |= PDF14_SET_OVERPRINT_MODE;
-        params.overprint_mode = pdev->overprint_mode = pgs->overprint_mode;
+        params.effective_overprint_mode = pdev->effective_overprint_mode = pgs->effective_overprint_mode;
     }
     if (crop_blend_params) {
         params.ctm = group_params->ctm;
@@ -8542,7 +8554,7 @@ pdf14_clist_text_begin(gx_device * dev,	gs_gstate	* pgs,
     int code;
     gs_blend_mode_t blend_mode = gs_currentblendmode(pgs);
     float opacity = gs_currentopacityalpha(pgs);
-    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible);
+    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint);
     bool draw = !(text->operation & TEXT_DO_NONE);
 
     if_debug0m('v', memory, "[v]pdf14_clist_text_begin\n");
diff --git a/base/gdevp14.h b/base/gdevp14.h
index 546ad2e..3499193 100644
--- a/base/gdevp14.h
+++ b/base/gdevp14.h
@@ -208,7 +208,7 @@ typedef struct pdf14_device_s {
     gs_blend_mode_t blend_mode;
     bool text_knockout;
     bool overprint;
-    bool overprint_mode;
+    bool effective_overprint_mode;
     int text_group;
     gx_color_index drawn_comps;		/* Used for overprinting.  Passed from overprint compositor */
     gx_device * pclist_device;
diff --git a/base/gstrans.h b/base/gstrans.h
index 50425ca..0c9a3cd 100644
--- a/base/gstrans.h
+++ b/base/gstrans.h
@@ -126,7 +126,7 @@ struct gs_pdf14trans_params_s {
     gs_matrix ctm;
     bool replacing;
     bool overprint;
-    bool overprint_mode;
+    bool effective_overprint_mode;
     bool idle; /* For clist reader.*/
     uint mask_id; /* For clist reader.*/
     int group_color_numcomps;
diff --git a/base/gxblend.c b/base/gxblend.c
index 9fb287a..8d7b9aa 100644
--- a/base/gxblend.c
+++ b/base/gxblend.c
@@ -1217,8 +1217,57 @@ art_blend_pixel_8_inline(byte *gs_restrict dst, const byte *gs_restrict backdrop
                  * compositor is that it always has CMYK + spots with spots after
                  * the CMYK colorants (see gx_put_blended_image_cmykspot).
                  * that way we don't have to worry about where the process colors
-                 * are. */
-                if (p14dev->overprint_mode && p14dev->color_info.num_components > 3
+                 * are.
+
+                 * Note:  The spec claims the following:
+
+                 If the overprint mode is 1 (nonzero overprint mode) and the
+                 current color space and group color space are both DeviceCMYK,
+                 then only process color components with nonzero values replace
+                 the corresponding component values of the backdrop. All other
+                 component values leave the existing backdrop value unchanged.
+                 That is, the value of the blend function B(Cb,Cs) is the source
+                 component cs for any process (DeviceCMYK) color component whose
+                 (subtractive) color value is nonzero; otherwise it is the
+                 backdrop component cb. For spot color components, the value is
+                 always cb.
+
+                 The equation for compositing is
+
+                    ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*B(Cb,Cs)]
+
+                 Now if I simply set B(cb,cs) to cb for the case when the
+                 DevieCMYK value (with opm true) is zero I get
+
+                 ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*Cb]
+
+                 But what I am seeing with AR is
+                    ar*Cr = (1-as)*Cb + as*[(1-ab)*Cb+ab*Cb] = (1-as)*Cb + as*Cb = Cb
+                 which is what I think we want.
+
+                 The description in the spec is confusing as it says
+                "then only process color components with nonzero values replace
+                 the corresponding component values of the backdrop. All other
+                 component values leave the existing backdrop value unchanged"
+
+                 which makes sense for overprinting,
+
+                 vs.
+
+                 "That is, the value of the blend function B(Cb,Cs) is the source
+                 component cs for any process (DeviceCMYK) color component whose
+                 (subtractive) color value is nonzero; otherwise it is the
+                 backdrop component cb."
+
+                 Which is NOT the same thing as leaving the backdrop unchanged
+                 with the compositing equation
+                 ar*Cr = (1-as)*Cb + as*[(1-ab)*Cs+ab*B(Cb,Cs)]
+
+                 For this to work, we need to carry out the operation during
+                 the mixing of the source with the blend result.  Essentially
+                 replacing that mixing with the color we have here.
+                 */
+                if (p14dev->effective_overprint_mode && p14dev->color_info.num_components > 3
                     && !(p14dev->ctx->additive)) {
                     for (i = 0; i < 4; i++) {
                         b = backdrop[i];
@@ -1232,7 +1281,7 @@ art_blend_pixel_8_inline(byte *gs_restrict dst, const byte *gs_restrict backdrop
                     /* Otherwise we have B(cb, cs)= cs if cs is specified in
                      * the current color space all other color should get cb.
                      * Essentially the standard overprint case. */
-                    for (i = 0, comps = drawn_comps; comps != 0; ++i, comps >>= 1) {
+                    for (i = 0, comps = drawn_comps; i < n_chan; ++i, comps >>= 1) {
                         if ((comps & 0x1) != 0) {
                             dst[i] = src[i];
                         } else {
@@ -1421,7 +1470,7 @@ art_blend_pixel_16_inline(uint16_t *gs_restrict dst, const uint16_t *gs_restrict
                  * the CMYK colorants (see gx_put_blended_image_cmykspot).
                  * that way we don't have to worry about where the process colors
                  * are. */
-                if (p14dev->overprint_mode && p14dev->color_info.num_components > 3
+                if (p14dev->effective_overprint_mode && p14dev->color_info.num_components > 3
                     && !(p14dev->ctx->additive)) {
                     for (i = 0; i < 4; i++) {
                         b = backdrop[i];
@@ -1798,17 +1847,26 @@ art_pdf_composite_pixel_alpha_8_inline(byte *gs_restrict dst, byte *gs_restrict
         byte blend[ART_MAX_CHAN];
 
         art_blend_pixel_8_inline(blend, dst, src, first_spot, blend_mode, pblend_procs, p14dev);
-        for (i = 0; i < first_spot; i++) {
-            int c_bl;		/* Result of blend function */
-            int c_mix;		/* Blend result mixed with source color */
 
-            c_s = src[i];
-            c_b = dst[i];
-            c_bl = blend[i];
-            tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
-            c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
-            tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
-            dst[i] = tmp >> 16;
+        if (blend_mode == BLEND_MODE_CompatibleOverprint) {
+            for (i = 0; i < first_spot; i++) {
+                /* No mixing.  Blend[i] is backdrop or src */
+                tmp = (dst[i] << 16) + src_scale * (blend[i] - dst[i]) + 0x8000;
+                dst[i] = tmp >> 16;
+            }
+        } else {
+            for (i = 0; i < first_spot; i++) {
+                int c_bl;		/* Result of blend function */
+                int c_mix;		/* Blend result mixed with source color */
+
+                c_s = src[i];
+                c_b = dst[i];
+                c_bl = blend[i];
+                tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
+                c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
+                tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
+                dst[i] = tmp >> 16;
+            }
         }
     }
     dst[n_chan] = a_r;
@@ -1869,15 +1927,24 @@ art_pdf_composite_pixel_alpha_16_inline(uint16_t *gs_restrict dst, uint16_t *gs_
         uint16_t blend[ART_MAX_CHAN];
 
         art_blend_pixel_16_inline(blend, dst, src, first_spot, blend_mode, pblend_procs, p14dev);
-        for (i = 0; i < first_spot; i++) {
-            int c_bl;		/* Result of blend function */
 
-            c_s = src[i];
-            c_b = dst[i];
-            c_bl = blend[i];
-            c_s += (a_b * (c_bl - c_s) + 0x8000)>>16;
-            c_b += (src_scale * (c_s - c_b) + 0x8000)>>16;
-            dst[i] = c_b;
+        if (blend_mode == BLEND_MODE_CompatibleOverprint) {
+            for (i = 0; i < first_spot; i++) {
+                /* No mixing.  Blend[i] is backdrop or src */
+                dst[i] += (src_scale * (blend[i] - dst[i]) + 0x8000) >> 16;
+            }
+        } else {
+            for (i = 0; i < first_spot; i++) {
+                int c_bl;		/* Result of blend function */
+
+                c_s = src[i];
+                c_b = dst[i];
+                c_bl = blend[i];
+
+                c_s += (a_b * (c_bl - c_s) + 0x8000) >> 16;
+                c_b += (src_scale * (c_s - c_b) + 0x8000) >> 16;
+                dst[i] = c_b;
+            }
         }
     }
     dst[n_chan] = a_r;
@@ -3260,6 +3327,8 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
     bool has_mask = false;
     byte *backdrop_ptr = NULL;
     pdf14_device *pdev = (pdf14_device *)dev;
+
+
 #if RAW_DUMP
     byte *composed_ptr = NULL;
     int width = x1 - x0;
@@ -4473,17 +4542,21 @@ pdf14_compose_alphaless_group(pdf14_buf *tos, pdf14_buf *nos,
 typedef void (*pdf14_mark_fill_rect_fn)(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape);
+               int alpha_g_off, int shape_off, byte shape, bool isolated);
 
 static forceinline void
 template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i, j, k;
     gx_color_index comps;
     byte dst[PDF14_MAX_PLANES] = { 0 };
+    byte dest_alpha;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
 
     for (j = h; j > 0; --j) {
         for (i = w; i > 0; --i) {
@@ -4524,15 +4597,29 @@ template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restri
                     }
                 }
                 dst[num_comp] = dst_ptr[num_comp * planestride];
+                dest_alpha = dst[num_comp];
                 pdst = art_pdf_composite_pixel_alpha_8_inline(dst, src, num_comp, blend_mode, first_blend_spot,
                             pdev->blend_procs, pdev);
                 /* Until I see otherwise in AR or the spec, do not fool
                    with spot overprinting while we are in an RGB or Gray
                    blend color space. */
                 if (!additive && overprint) {
+                    /* If this is an overprint case, and alpha_r is different
+                       than alpha_d then we will need to adjust
+                       the colors of the non-drawn components here too */
                     for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
                         if ((comps & 0x1) != 0) {
                             dst_ptr[k * planestride] = 255 - pdst[k];
+                        } else if (dest_alpha != pdst[num_comp]) {
+                            /* We need val_new = (val_old * old_alpha) / new_alpha */
+                            if (pdst[num_comp] != 0) {
+                                int val = floor(((float)dest_alpha / (float)pdst[num_comp]) * (255 - pdst[k]) + 0.5);
+                                if (val < 0)
+                                    val = 0;
+                                else if (val > 255)
+                                    val = 255;
+                                dst_ptr[k * planestride] = val;
+                            }
                         }
                     }
                 } else {
@@ -4559,7 +4646,7 @@ template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restri
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (src[num_comp] == 255 && blend_mode == BLEND_MODE_Normal) {
+                if (src[num_comp] == 255 && tag_blend) {
                     dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
@@ -4583,7 +4670,7 @@ static void
 mark_fill_rect_alpha0(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i, j;
 
@@ -4607,19 +4694,19 @@ static void
 mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     template_mark_fill_rect(w, h, dst_ptr, src, num_comp, num_spots, first_blend_spot,
                src_alpha, rowstride, planestride, additive, pdev, blend_mode,
                overprint, drawn_comps, tag_off, curr_tag,
-               alpha_g_off, shape_off, shape);
+               alpha_g_off, shape_off, shape, isolated);
 }
 
 static void
 mark_fill_rect_sub4_fast(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i, j, k;
 
@@ -4663,43 +4750,43 @@ static void
 mark_fill_rect_add_nospots(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     template_mark_fill_rect(w, h, dst_ptr, src, num_comp, /*num_spots*/0, first_blend_spot,
                src_alpha, rowstride, planestride, /*additive*/1, pdev, blend_mode,
                /*overprint*/0, /*drawn_comps*/0, tag_off, curr_tag,
-               alpha_g_off, shape_off, shape);
+               alpha_g_off, shape_off, shape, /*isolated*/ 0);
 }
 
 static void
 mark_fill_rect_add_nospots_common(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     template_mark_fill_rect(w, h, dst_ptr, src, num_comp, /*num_spots*/0, /*first_blend_spot*/0,
                src_alpha, rowstride, planestride, /*additive*/1, pdev, /*blend_mode*/BLEND_MODE_Normal,
                /*overprint*/0, /*drawn_comps*/0, /*tag_off*/0, curr_tag,
-               alpha_g_off, /*shape_off*/0, shape);
+               alpha_g_off, /*shape_off*/0, shape, /*isolated*/ 0);
 }
 
 static void
 mark_fill_rect_add_nospots_common_no_alpha_g(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     template_mark_fill_rect(w, h, dst_ptr, src, num_comp, /*num_spots*/0, /*first_blend_spot*/0,
                src_alpha, rowstride, planestride, /*additive*/1, pdev, /*blend_mode*/BLEND_MODE_Normal,
                /*overprint*/0, /*drawn_comps*/0, /*tag_off*/0, curr_tag,
-               /*alpha_g_off*/0, /*shape_off*/0, shape);
+               /*alpha_g_off*/0, /*shape_off*/0, shape, /*isolated*/ 0);
 }
 
 static void
 mark_fill_rect_add3_common(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i, j, k;
 
@@ -4743,9 +4830,12 @@ static void
 mark_fill_rect_add1_no_spots(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
 
     for (; h > 0; --h) {
         for (i = w; i > 0; --i) {
@@ -4762,7 +4852,7 @@ mark_fill_rect_add1_no_spots(int w, int h, byte *gs_restrict dst_ptr, byte *gs_r
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (blend_mode == BLEND_MODE_Normal && a_s == 255) {
+                if (tag_blend && a_s == 255) {
                      dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
@@ -4786,7 +4876,7 @@ static void
 mark_fill_rect_add1_no_spots_normal(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i;
 
@@ -4840,7 +4930,7 @@ static void
 mark_fill_rect_add1_no_spots_fast(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
                byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
                bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
-               int alpha_g_off, int shape_off, byte shape)
+               int alpha_g_off, int shape_off, byte shape, bool isolated)
 {
     int i;
 
@@ -4905,6 +4995,7 @@ do_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
     int num_spots = buf->num_spots;
     int first_blend_spot = num_comp;
     pdf14_mark_fill_rect_fn fn;
+    bool isolated = buf->isolated;
 
     if (num_spots > 0 && !blend_valid_for_spot(blend_mode))
         first_blend_spot = num_comp - num_spots;
@@ -5010,7 +5101,7 @@ do_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
 
     fn(w, h, dst_ptr, src, num_comp, num_spots, first_blend_spot, src_alpha,
        rowstride, planestride, additive, pdev, blend_mode, overprint,
-       drawn_comps, tag_off, curr_tag, alpha_g_off, shape_off, shape);
+       drawn_comps, tag_off, curr_tag, alpha_g_off, shape_off, shape, isolated);
 
 #if 0
 /* #if RAW_DUMP */
@@ -5046,6 +5137,9 @@ template_mark_fill_rect16(int w, int h, uint16_t *gs_restrict dst_ptr, uint16_t
     /* Expand src_alpha and shape to be 0...0x10000 rather than 0...0xffff */
     int src_alpha = src_alpha_ + (src_alpha_>>15);
     int shape = shape_ + (shape_>>15);
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
 
     for (j = h; j > 0; --j) {
         for (i = w; i > 0; --i) {
@@ -5121,7 +5215,7 @@ template_mark_fill_rect16(int w, int h, uint16_t *gs_restrict dst_ptr, uint16_t
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (src[num_comp] == 65535 && blend_mode == BLEND_MODE_Normal) {
+                if (src[num_comp] == 65535 && tag_blend) {
                     dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
@@ -5323,6 +5417,9 @@ mark_fill_rect16_add1_no_spots(int w, int h, uint16_t *gs_restrict dst_ptr, uint
     int i;
     int src_alpha = src_alpha_;
     int shape = shape_;
+    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
+        blend_mode == BLEND_MODE_Compatible ||
+        blend_mode == BLEND_MODE_CompatibleOverprint;
 
     src_alpha += src_alpha>>15;
     shape += shape>>15;
@@ -5341,7 +5438,7 @@ mark_fill_rect16_add1_no_spots(int w, int h, uint16_t *gs_restrict dst_ptr, uint
             if (tag_off) {
                 /* If src alpha is 100% then set to curr_tag, else or */
                 /* other than Normal BM, we always OR */
-                if (blend_mode == BLEND_MODE_Normal && a_s == 65535) {
+                if (tag_blend && a_s == 65535) {
                      dst_ptr[tag_off] = curr_tag;
                 } else {
                     dst_ptr[tag_off] |= curr_tag;
diff --git a/base/gxclpath.c b/base/gxclpath.c
index 9a0344a..cc5a5e3 100644
--- a/base/gxclpath.c
+++ b/base/gxclpath.c
@@ -391,12 +391,12 @@ cmd_check_fill_known(gx_device_clist_writer *cdev, const gs_gstate *pgs,
      * though both parameters are passed in the state as well, this usually
      * has no effect.
      */
-    if (state_neq(overprint) || state_neq(overprint_mode) ||
+    if (state_neq(overprint) || state_neq(effective_overprint_mode) ||
         state_neq(blend_mode) || state_neq(text_knockout) ||
         state_neq(renderingintent)) {
         *punknown |= op_bm_tk_known;
         state_update(overprint);
-        state_update(overprint_mode);
+        state_update(effective_overprint_mode);
         state_update(blend_mode);
         state_update(text_knockout);
         state_update(renderingintent);


Summary of changes:
 Resource/Init/pdf_draw.ps |  63 ++++-----------
 Resource/Init/pdf_main.ps |  15 ++--
 Resource/Init/pdf_ops.ps  | 192 +++++++++++++++++++++++++++++-----------------
 base/gdevp14.c            |  42 ++++++----
 base/gdevp14.h            |   2 +-
 base/gstrans.h            |   2 +-
 base/gxblend.c            | 183 ++++++++++++++++++++++++++++++++-----------
 base/gxclpath.c           |   4 +-
 8 files changed, 317 insertions(+), 186 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.