[gs-commits] ghostpdl branch, pdfi, updated. jbig2dec-0.14-2194-g9bd1cd9

[email protected] (Nancy Durgin)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, pdfi has been updated
       via  9bd1cd93933f77fa7ed5804299d884f1ae6dc177 (commit)
      from  c92628ee17130682263d39cbe3a8901c16f52117 (commit)

----------------------------------------------------------------------
commit 9bd1cd93933f77fa7ed5804299d884f1ae6dc177
Author: Nancy Durgin <[email protected]>
Date:   Thu Aug 29 08:29:11 2019 -0700

    Better transparency support for stroke/fill operators
    
    Changes for setup_trans, teardown_trans and BM, though the BM stuff
    isn't implemented yet.
    
    Also some refactoring of the stroke/fill reoutines to reduce duplicate code.
    
    This shows a lot of progressions, and also a few suspicious things.
    
    I noticed that a lot of my BBox's are off by like 0.5.  Need to figure
    out what is going on there.

diff --git a/pdf/pdf_gstate.c b/pdf/pdf_gstate.c
index 19cc6a6..6462d80 100644
--- a/pdf/pdf_gstate.c
+++ b/pdf/pdf_gstate.c
@@ -32,6 +32,23 @@
 #include "gslparam.h"
 #include "gstparam.h"
 
+static const char *blend_mode_names[] = {
+    GS_BLEND_MODE_NAMES, 0
+};
+
+int pdfi_get_blend_mode(pdf_context *ctx, pdf_name *name, gs_blend_mode_t *mode)
+{
+    const char **p;
+
+    for (p = blend_mode_names; *p; ++p) {
+        if (pdfi_name_is(name, *p)) {
+            *mode = p - blend_mode_names;
+            return 0;
+        }
+    }
+    return -1;
+}
+
 void pdfi_gstate_smask_install(pdfi_int_gstate *igs, gs_memory_t *memory, pdf_dict *SMask, gs_gstate *gstate)
 {
     void *client_data_save;
@@ -741,27 +758,20 @@ static int GS_SA(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict
     return 0;
 }
 
-static const char *blend_mode_names[] = {
-    GS_BLEND_MODE_NAMES, 0
-};
-
 static int GS_BM(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict *page_dict)
 {
     pdf_name *n;
-    const char **p;
     int code;
+    gs_blend_mode_t mode;
 
     code = pdfi_dict_get_type(ctx, GS, "BM", PDF_NAME, (pdf_obj **)&n);
     if (code < 0)
         return code;
 
-    for (p = blend_mode_names; *p; ++p) {
-        if (pdfi_name_is(n, *p)) {
-            pdfi_countdown(n);
-            return gs_setblendmode(ctx->pgs, p - blend_mode_names);
-        }
-    }
+    code = pdfi_get_blend_mode(ctx, n, &mode);
     pdfi_countdown(n);
+    if (code == 0)
+        return gs_setblendmode(ctx->pgs, mode);
     return_error(gs_error_undefined);
 }
 
diff --git a/pdf/pdf_gstate.h b/pdf/pdf_gstate.h
index d5c9947..e2333b4 100644
--- a/pdf/pdf_gstate.h
+++ b/pdf/pdf_gstate.h
@@ -29,6 +29,8 @@ int pdfi_gstate_set_client(pdf_context *ctx);
 void pdfi_gstate_smask_install(pdfi_int_gstate *igs, gs_memory_t *memory, pdf_dict *SMask, gs_gstate *gstate);
 void pdfi_gstate_smask_free(pdfi_int_gstate *igs);
 
+int pdfi_get_blend_mode(pdf_context *ctx, pdf_name *name, gs_blend_mode_t *mode);
+
 int pdfi_concat(pdf_context *ctx);
 int pdfi_gsave(pdf_context *ctx);
 int pdfi_grestore(pdf_context *ctx);
diff --git a/pdf/pdf_path.c b/pdf/pdf_path.c
index 7ead98a..936f065 100644
--- a/pdf/pdf_path.c
+++ b/pdf/pdf_path.c
@@ -128,15 +128,20 @@ int pdfi_lineto (pdf_context *ctx)
 
 int pdfi_fill(pdf_context *ctx)
 {
-    int code;
+    int code, code1;
+    pdfi_trans_state_t state;
 
     if (ctx->TextBlockDepth != 0)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
     gs_swapcolors(ctx->pgs);
-    code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-    if (code == 0)
+    code = pdfi_trans_setup(ctx, &state, TRANSPARENCY_Caller_Fill, gs_getfillconstantalpha(ctx->pgs));
+    if (code == 0) {
         code = gs_fill(ctx->pgs);
+        code1 = pdfi_trans_teardown(ctx, &state);
+        if (code == 0)
+            code = code1;
+    }
     gs_swapcolors(ctx->pgs);
     if(code < 0 && ctx->pdfstoponerror)
         return code;
@@ -146,15 +151,20 @@ int pdfi_fill(pdf_context *ctx)
 
 int pdfi_eofill(pdf_context *ctx)
 {
-    int code;
+    int code, code1;
+    pdfi_trans_state_t state;
 
     if (ctx->TextBlockDepth != 0)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
     gs_swapcolors(ctx->pgs);
-    code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-    if (code == 0)
+    code = pdfi_trans_setup(ctx, &state, TRANSPARENCY_Caller_EOFill, gs_getfillconstantalpha(ctx->pgs));
+    if (code == 0) {
         code = gs_eofill(ctx->pgs);
+        code1 = pdfi_trans_teardown(ctx, &state);
+        if (code == 0)
+            code = code1;
+    }
     gs_swapcolors(ctx->pgs);
     if(code < 0 && ctx->pdfstoponerror)
         return code;
@@ -164,13 +174,19 @@ int pdfi_eofill(pdf_context *ctx)
 
 int pdfi_stroke(pdf_context *ctx)
 {
-    int code = pdfi_trans_set_params(ctx, ctx->pgs->strokeconstantalpha);
+    int code, code1;
+    pdfi_trans_state_t state;
 
     if (ctx->TextBlockDepth != 0)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
-    if (code == 0)
+    code = pdfi_trans_setup(ctx, &state, TRANSPARENCY_Caller_Stroke, gs_getstrokeconstantalpha(ctx->pgs));
+    if (code == 0) {
         code = gs_stroke(ctx->pgs);
+        code1 = pdfi_trans_teardown(ctx, &state);
+        if (code == 0)
+            code = code1;
+    }
     if(code < 0 && ctx->pdfstoponerror)
         return code;
     else
@@ -186,10 +202,7 @@ int pdfi_closepath_stroke(pdf_context *ctx)
 
     code = gs_closepath(ctx->pgs);
     if (code == 0)
-        code = pdfi_trans_set_params(ctx, ctx->pgs->strokeconstantalpha);
-    if (code == 0) {
-        code = gs_stroke(ctx->pgs);
-    }
+        code = pdfi_stroke(ctx);
     if(code < 0 && ctx->pdfstoponerror)
         return code;
     else
@@ -363,28 +376,8 @@ int pdfi_b(pdf_context *ctx)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
     code = gs_closepath(ctx->pgs);
-    if (code >= 0) {
-        code = pdfi_gsave(ctx);
-        if (code >= 0) {
-            gs_swapcolors(ctx->pgs);
-            code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-            if (code == 0)
-                code = gs_fill(ctx->pgs);
-            gs_swapcolors(ctx->pgs);
-            if (code >= 0) {
-                code = pdfi_grestore(ctx);
-                if (code >= 0)
-                    code = pdfi_trans_set_params(ctx, ctx->pgs->strokeconstantalpha);
-                if (code >= 0)
-                    code = gs_stroke(ctx->pgs);
-            } else
-                (void)pdfi_grestore(ctx);
-        }
-    }
     if (code >= 0)
-       code = gs_newpath(ctx->pgs);
-    else
-        (void)gs_newpath(ctx->pgs);
+        code = pdfi_B(ctx);
     if(code < 0 && ctx->pdfstoponerror)
         return code;
     else
@@ -399,101 +392,87 @@ int pdfi_b_star(pdf_context *ctx)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
     code = gs_closepath(ctx->pgs);
-    if (code >= 0) {
-        code = pdfi_gsave(ctx);
-        if (code >= 0) {
-            gs_swapcolors(ctx->pgs);
-            code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-            if (code == 0)
-                code = gs_eofill(ctx->pgs);
-            gs_swapcolors(ctx->pgs);
-            if (code >= 0) {
-                code = pdfi_grestore(ctx);
-                if (code >= 0)
-                    code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-                if (code >= 0)
-                    code = gs_stroke(ctx->pgs);
-            } else
-                (void)pdfi_grestore(ctx);
-        }
-    }
     if (code >= 0)
-       code = gs_newpath(ctx->pgs);
-    else
-        (void)gs_newpath(ctx->pgs);
+        code = pdfi_B_star(ctx);
     if(code < 0 && ctx->pdfstoponerror)
         return code;
     else
         return 0;
 }
 
-int pdfi_B(pdf_context *ctx)
+/* common code for B and B* */
+static int pdfi_B_inner(pdf_context *ctx, bool use_eofill)
 {
-    int code;
+    int code, code1;
+    pdfi_trans_state_t state;
+    bool started_group = false;
 
     if (ctx->TextBlockDepth != 0)
         ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
 
+#if 1
+    if (ctx->page_has_transparency) {
+        code = gs_setopacityalpha(ctx->pgs, 1.0);
+        if (code < 0)
+            return code;
+        code = pdfi_trans_begin_group(ctx, true, true, true);
+        if (code < 0)
+            return code;
+        started_group = true;
+    }
+#endif
+
     code = pdfi_gsave(ctx);
-    if (code >= 0) {
-        gs_swapcolors(ctx->pgs);
-        code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-        if (code == 0)
+    if (code < 0)
+        goto exit;
+    gs_swapcolors(ctx->pgs);
+    code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
+    if (code == 0) {
+        if (use_eofill)
+            code = gs_eofill(ctx->pgs);
+        else
             code = gs_fill(ctx->pgs);
-        gs_swapcolors(ctx->pgs);
-        if (code >= 0) {
-            code = pdfi_grestore(ctx);
-            if (code >= 0)
-                code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-            if (code >= 0)
-                code = gs_stroke(ctx->pgs);
-        } else {
-            (void)pdfi_grestore(ctx);
-        }
-    } else {
-        (void)pdfi_grestore(ctx);
     }
+    gs_swapcolors(ctx->pgs);
+    code1 = pdfi_grestore(ctx);
+    if (code == 0)
+        code = code1;
+    if (code < 0)
+        goto exit;
+
+    code = pdfi_trans_set_params(ctx, gs_getstrokeconstantalpha(ctx->pgs));
+    if (code < 0)
+        goto exit;
+    code = pdfi_trans_setup(ctx, &state, TRANSPARENCY_Caller_Stroke, gs_getstrokeconstantalpha(ctx->pgs));
     if (code >= 0)
-       code = gs_newpath(ctx->pgs);
-    else
-        (void)gs_newpath(ctx->pgs);
+        code = gs_stroke(ctx->pgs);
+    code1 = pdfi_trans_teardown(ctx, &state);
+    if (code == 0)
+        code = code1;
+
+ exit:
+    if (started_group)
+        code1 = pdfi_trans_end_simple_group(ctx);
+    if (code == 0)
+        code = code1;
+
+    if (code < 0)
+        gs_newpath(ctx->pgs);
+
     if(code < 0 && ctx->pdfstoponerror)
         return code;
     else
         return 0;
 }
 
+int pdfi_B(pdf_context *ctx)
+{
+    return pdfi_B_inner(ctx, false);
+}
+
 int pdfi_B_star(pdf_context *ctx)
 {
-    int code;
-
-    if (ctx->TextBlockDepth != 0)
-        ctx->pdf_warnings |= W_PDF_OPINVALIDINTEXT;
-
-    code = pdfi_gsave(ctx);
-    if (code >= 0) {
-        gs_swapcolors(ctx->pgs);
-        code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-        if (code == 0)
-            code = gs_eofill(ctx->pgs);
-        gs_swapcolors(ctx->pgs);
-        if (code >= 0) {
-            code = pdfi_grestore(ctx);
-            if (code >= 0)
-                code = pdfi_trans_set_params(ctx, gs_getfillconstantalpha(ctx->pgs));
-            if (code >= 0)
-                code = gs_stroke(ctx->pgs);
-        } else {
-            (void)pdfi_grestore(ctx);
-        }
-    } else {
-        (void)pdfi_grestore(ctx);
-    }
-    if (code >= 0)
-       code = gs_newpath(ctx->pgs);
-    else
-        (void)gs_newpath(ctx->pgs);
-    return code;
+    return pdfi_B_inner(ctx, true);
 }
 
 int pdfi_clip(pdf_context *ctx)
diff --git a/pdf/pdf_trans.c b/pdf/pdf_trans.c
index 324ef8a..f8974c9 100644
--- a/pdf/pdf_trans.c
+++ b/pdf/pdf_trans.c
@@ -253,6 +253,26 @@ static int pdfi_transparency_group_common(pdf_context *ctx, pdf_dict *page_dict,
     return gs_begin_transparency_group(ctx->pgs, &params, (const gs_rect *)bbox, group_type);
 }
 
+int pdfi_trans_begin_group(pdf_context *ctx, bool stroked_bbox, bool isolated, bool knockout)
+{
+    gs_transparency_group_params_t params;
+    gs_rect bbox;
+    int code;
+
+    gs_trans_group_params_init(&params);
+    params.Isolated = isolated;
+    params.Knockout = knockout;
+
+    code = pdfi_get_current_bbox(ctx, &bbox, stroked_bbox);
+    if (code < 0)
+        return code;
+
+    code = gs_begin_transparency_group(ctx->pgs, &params, &bbox, PDF14_BEGIN_TRANS_GROUP);
+    if (code >=  0)
+        ctx->current_stream_save.group_depth++;
+    return code;
+}
+
 int pdfi_trans_begin_page_group(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *group_dict)
 {
     gs_rect bbox;
@@ -330,6 +350,17 @@ int pdfi_trans_end_group(pdf_context *ctx)
     return code;
 }
 
+/* Ends group with no grestore (needs a better name, but whatever) */
+int pdfi_trans_end_simple_group(pdf_context *ctx)
+{
+    int code;
+
+    code = gs_end_transparency_group(ctx->pgs);
+    ctx->current_stream_save.group_depth--;
+
+    return code;
+}
+
 
 int pdfi_trans_begin_isolated_group(pdf_context *ctx, bool image_with_SMask)
 {
@@ -375,6 +406,62 @@ int pdfi_trans_end_smask_notify(pdf_context *ctx)
     return gs_begin_transparency_mask(ctx->pgs, &params, &bbox, false);
 }
 
+int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state,
+                     pdfi_transparency_caller_t caller, double alpha)
+{
+    pdfi_int_gstate *igs = (pdfi_int_gstate *)ctx->pgs->client_data;
+    int code;
+    bool stroked_bbox;
+
+    memset(state, 0, sizeof(*state));
+
+    if (!ctx->page_has_transparency)
+        return 0;
+
+    code = pdfi_trans_set_params(ctx, alpha);
+    if (code != 0)
+        return 0;
+
+    if (igs->SMask == NULL || caller == TRANSPARENCY_Caller_Image) {
+        state->GroupPushed = false;
+        return 0;
+    }
+
+    /* TODO: error handling... */
+    stroked_bbox = (caller == TRANSPARENCY_Caller_Stroke);
+    code = pdfi_trans_begin_group(ctx, stroked_bbox, true, false);
+    state->GroupPushed = true;
+    state->saveOA = gs_currentopacityalpha(ctx->pgs);
+    state->saveSA = gs_currentshapealpha(ctx->pgs);
+    code = gs_setopacityalpha(ctx->pgs, 1.0);
+    code = gs_setshapealpha(ctx->pgs, 1.0);
+    return code;
+}
+
+int pdfi_trans_teardown(pdf_context *ctx, pdfi_trans_state_t *state)
+{
+    int code = 0;
+
+    if (!ctx->page_has_transparency)
+        return 0;
+
+    if (state->GroupPushed) {
+        code = pdfi_trans_end_group(ctx);
+        code = gs_setopacityalpha(ctx->pgs, state->saveOA);
+        code = gs_setshapealpha(ctx->pgs, state->saveSA);
+    }
+
+    /* TODO:
+  % Also, if we changed the BM, restore it (AFTER the group was popped)
+  .currentblendmode /CompatibleOverprint eq {
+    % restore the blendmode
+    saveBM .setblendmode
+  } if
+    */
+
+    return code;
+}
+
 int pdfi_trans_set_params(pdf_context *ctx, double alpha)
 {
     pdfi_int_gstate *igs = (pdfi_int_gstate *)ctx->pgs->client_data;
@@ -397,3 +484,27 @@ int pdfi_trans_set_params(pdf_context *ctx, double alpha)
 
     return 0;
 }
+
+/* Get current bbox, possibly from stroking current path (utility function) */
+int pdfi_get_current_bbox(pdf_context *ctx, gs_rect *bbox, bool stroked)
+{
+    int code, code1;
+
+    if (stroked) {
+        code = pdfi_gsave(ctx);
+        if (code < 0)
+            return code;
+        code = gs_strokepath(ctx->pgs);
+        if (code < 0)
+            goto exit;
+    }
+    code = gs_upathbbox(ctx->pgs, bbox, false);
+
+ exit:
+    if (stroked) {
+        code1 = pdfi_grestore(ctx);
+        if (code == 0)
+            code = code1;
+    }
+    return code;
+}
diff --git a/pdf/pdf_trans.h b/pdf/pdf_trans.h
index 0d57a3b..2fcaa6e 100644
--- a/pdf/pdf_trans.h
+++ b/pdf/pdf_trans.h
@@ -16,12 +16,38 @@
 #ifndef PDF_TRANSPARENCY_OPERATORS
 #define PDF_TRANSPARENCY_OPERATORS
 
+/* these names are to match the PS code (pdf_ops.ps/OPSaveDstack, setup_trans, teardown_trans) */
+typedef struct {
+    bool GroupPushed;
+    bool ChangeBM;
+    float saveOA;
+    float saveSA;
+    gs_blend_mode_t saveBM;
+} pdfi_trans_state_t;
+
+typedef enum {
+    TRANSPARENCY_CALLER_Other,
+    TRANSPARENCY_Caller_Image,
+    TRANSPARENCY_Caller_Stroke,
+    TRANSPARENCY_Caller_Fill,
+    TRANSPARENCY_Caller_EOFill
+} pdfi_transparency_caller_t;
+
+int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state, pdfi_transparency_caller_t caller,
+                     double alpha);
+int pdfi_trans_teardown(pdf_context *ctx, pdfi_trans_state_t *state);
+
+int pdfi_trans_begin_group(pdf_context *ctx, bool stroked_bbox, bool isolated, bool knockout);
 int pdfi_trans_begin_page_group(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *group_dict);
 int pdfi_trans_begin_form_group(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *form_dict);
 int pdfi_trans_end_group(pdf_context *ctx);
+int pdfi_trans_end_simple_group(pdf_context *ctx);
 int pdfi_trans_set_params(pdf_context *ctx, double alpha);
 int pdfi_trans_begin_isolated_group(pdf_context *ctx, bool image_with_SMask);
 int pdfi_trans_end_isolated_group(pdf_context *ctx);
 int pdfi_trans_end_smask_notify(pdf_context *ctx);
 
+/* Utility func that probably goes somewhere else */
+int pdfi_get_current_bbox(pdf_context *ctx, gs_rect *bbox, bool stroked);
+
 #endif


Summary of changes:
 pdf/pdf_gstate.c |  32 ++++++----
 pdf/pdf_gstate.h |   2 +
 pdf/pdf_path.c   | 187 ++++++++++++++++++++++++-------------------------------
 pdf/pdf_trans.c  | 111 +++++++++++++++++++++++++++++++++
 pdf/pdf_trans.h  |  26 ++++++++
 5 files changed, 243 insertions(+), 115 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.