[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, ¶ms, (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(¶ms);
+ 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, ¶ms, &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, ¶ms, &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(-)