[gs-commits] ghostpdl branch, pdfi, updated. jbig2dec-0.14-2624-gd4057f4

[email protected] (Nancy Durgin) Thu, 28 Nov 2019 01:10:28 +0000 (UTC)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, pdfi has been updated
       via  d4057f4c60584182a45d76a27d1480ad7be8cf1d (commit)
      from  34e65c4231a054195b23b6b60517ad7ebe20cbda (commit)

----------------------------------------------------------------------
commit d4057f4c60584182a45d76a27d1480ad7be8cf1d
Author: Nancy Durgin <[email protected]>
Date:   Wed Nov 27 15:18:58 2019 -0800

    Partial implementation of AP and Circle
    
    This renders Circle using /AP /N, for at least some cases.
    
    See file tests_private/comparefiles/annots.pdf

diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 3438140..29f10b0 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -31,8 +31,9 @@
 #include "pdf_annot.h"
 #include "pdf_colour.h"
 #include "gspath2.h"
+#include "pdf_image.h"
 
-typedef bool (*annot_func)(pdf_context *ctx, pdf_dict *annot, bool *render_done);
+typedef int (*annot_func)(pdf_context *ctx, pdf_dict *annot, pdf_dict *NormAP, bool *render_done);
 
 typedef struct {
     const char *subtype;
@@ -77,12 +78,108 @@ static int pdfi_annot_calcscale(pdf_context *ctx, pdf_dict *annot, double *xscal
     return 0;
 }
 
-/* See pdf_draw.ps/drawwidget */
-static int pdfi_annot_draw_widget(pdf_context *ctx, pdf_dict *annot, double xscale, double yscale)
+static int pdfi_annot_rect(pdf_context *ctx, pdf_dict *annot, gs_rect *rect)
 {
-    /* TODO: Implement this */
+    int code;
+    pdf_array *Rect = NULL;
 
-    return 0;
+    code = pdfi_dict_knownget_type(ctx, annot, "Rect", PDF_ARRAY, (pdf_obj **)&Rect);
+    if (code < 0) goto exit;
+
+    code = pdfi_array_to_gs_rect(ctx, Rect, rect);
+    if (code < 0) goto exit;
+
+    pdfi_normalize_rect(ctx, rect);
+
+ exit:
+    pdfi_countdown(Rect);
+    return code;
+}
+
+/* See pdf_draw.ps/drawwidget (draws the AP for any type of thingy) */
+static int pdfi_annot_draw_AP(pdf_context *ctx, pdf_dict *annot,
+                                  double xscale, double yscale,
+                                  pdf_dict *NormAP)
+{
+    int code = 0;
+    gs_rect rect;
+    pdf_array *BBox = NULL;
+    gs_rect bbox;
+    pdf_array *Matrix = NULL;
+    gs_matrix matrix;
+
+    /* TODO: Just rendering the Norm AP for now.  Lots of other convoluted things
+     *  I am not handling...
+     */
+    if (NormAP == NULL)
+        return 0;
+
+
+    code = pdfi_op_q(ctx);
+    if (code < 0)
+        return code;
+
+    /* TODO: graphicsbeginpage, textbeginpage
+     * These should match what was done at the beginning of the page,
+     * but current implementation has things kind of mixed around.
+     * Need to figure out exactly what to do.  I'd like it to be one
+     * function in both places.
+     * see pdfi_page_render()
+     */
+    /* graphicsbeginpage() */
+    /* textbeginpage() */
+    code = gs_initgraphics(ctx->pgs);
+    code = gs_setstrokeconstantalpha(ctx->pgs, 1.0);
+    code = gs_setfillconstantalpha(ctx->pgs, 1.0);
+    code = gs_setalphaisshape(ctx->pgs, 0);
+    code = gs_setblendmode(ctx->pgs, BLEND_MODE_Compatible);
+    code = gs_settextknockout(ctx->pgs, true);
+    code = gs_settextspacing(ctx->pgs, (double)0.0);
+    code = gs_settextleading(ctx->pgs, (double)0.0);
+    gs_settextrenderingmode(ctx->pgs, 0);
+    code = gs_setwordspacing(ctx->pgs, (double)0.0);
+    code = gs_settexthscaling(ctx->pgs, (double)100.0);
+    code = gs_setsmoothness(ctx->pgs, 0.02); /* Match gs code */
+    ctx->TextBlockDepth = 0;
+    /* TODO: FIXME */
+
+
+    code = pdfi_annot_rect(ctx, annot, &rect);
+    if (code < 0) goto exit;
+
+    code = gs_translate(ctx->pgs, rect.p.x, rect.p.y);
+    if (code < 0) goto exit;
+
+    code = gs_scale(ctx->pgs, xscale, yscale);
+    if (code < 0) goto exit;
+
+    code = pdfi_dict_knownget_type(ctx, NormAP, "BBox", PDF_ARRAY, (pdf_obj **)&BBox);
+    if (code < 0) goto exit;
+    if (code > 0) {
+        code = pdfi_array_to_gs_rect(ctx, BBox, &bbox);
+        if (code < 0) goto exit;
+
+        code = pdfi_dict_knownget_type(ctx, annot, "Matrix", PDF_ARRAY, (pdf_obj **)&Matrix);
+        if (code < 0) goto exit;
+
+        code = pdfi_array_to_gs_matrix(ctx, Matrix, &matrix);
+        if (code < 0) goto exit;
+
+        pdfi_bbox_transform(ctx, &bbox, &matrix);
+
+        /* Compensate for non-zero origin of BBox */
+        code = gs_translate(ctx->pgs, -bbox.p.x, -bbox.p.y);
+        if (code < 0) goto exit;
+
+    }
+    code = pdfi_do_image_or_form(ctx, NULL, ctx->CurrentPageDict, NormAP);
+    if (code < 0) goto exit;
+
+ exit:
+    (void)pdfi_op_Q(ctx);
+    pdfi_countdown(BBox);
+    pdfi_countdown(Matrix);
+    return code;
 }
 
 static int pdfi_annot_setcolor(pdf_context *ctx, pdf_dict *annot, bool *drawit)
@@ -118,7 +215,6 @@ static int pdfi_annot_strokeborder(pdf_context *ctx, pdf_dict *annot, double wid
     int code = 0;
     bool drawit;
     gs_rect rect;
-    pdf_array *Rect = NULL;
 
     if (width <= 0)
         return 0;
@@ -134,13 +230,7 @@ static int pdfi_annot_strokeborder(pdf_context *ctx, pdf_dict *annot, double wid
     code = gs_setlinewidth(ctx->pgs, width);
     if (code < 0) goto exit;
 
-    code = pdfi_dict_knownget_type(ctx, annot, "Rect", PDF_ARRAY, (pdf_obj **)&Rect);
-    if (code < 0) goto exit;
-
-    code = pdfi_array_to_gs_rect(ctx, Rect, &rect);
-    if (code < 0) goto exit;
-
-    pdfi_normalize_rect(ctx, &rect);
+    code = pdfi_annot_rect(ctx, annot, &rect);
 
     /* Stroke the rectangle */
     /* Adjust rectangle by the width */
@@ -152,7 +242,6 @@ static int pdfi_annot_strokeborder(pdf_context *ctx, pdf_dict *annot, double wid
 
  exit:
     (void)pdfi_grestore(ctx);
-    pdfi_countdown(Rect);
     return code;
 }
 
@@ -288,7 +377,29 @@ static int pdfi_annot_draw_border(pdf_context *ctx, pdf_dict *annot)
     return code;
 }
 
-static bool pdfi_annot_draw_Link(pdf_context *ctx, pdf_dict *annot, bool *render_done)
+/* Get the Normal AP dictionary/stream, if it exists
+ * Not an error if it doesn't exist, it will just be NULL
+ */
+static int pdfi_annot_get_NormAP(pdf_context *ctx, pdf_dict *annot, pdf_dict **NormAP)
+{
+    int code;
+    pdf_dict *AP = NULL;
+
+    *NormAP = NULL;
+
+    code = pdfi_dict_knownget_type(ctx, annot, "AP", PDF_DICT, (pdf_obj **)&AP);
+    if (code <= 0) goto exit;
+
+    code = pdfi_dict_knownget_type(ctx, AP, "N", PDF_DICT, (pdf_obj **)NormAP);
+    if (code > 0)
+        code = 0;
+
+ exit:
+    pdfi_countdown(AP);
+    return code;
+}
+
+static int pdfi_annot_draw_Link(pdf_context *ctx, pdf_dict *annot, pdf_dict *NormAP, bool *render_done)
 {
     int code;
     int code1;
@@ -307,7 +418,7 @@ static bool pdfi_annot_draw_Link(pdf_context *ctx, pdf_dict *annot, bool *render
     if (code < 0) goto exit;
 
     if (xscale * yscale > 0.0) {
-        code = pdfi_annot_draw_widget(ctx, annot, xscale, yscale);
+        code = pdfi_annot_draw_AP(ctx, annot, xscale, yscale, NormAP);
     } else {
         dbgmprintf(ctx->memory, "ANNOT: Ignoring annotation with scale factor of 0\n");
     }
@@ -320,19 +431,39 @@ static bool pdfi_annot_draw_Link(pdf_context *ctx, pdf_dict *annot, bool *render
     return code;
 }
 
-static bool pdfi_annot_draw_Ink(pdf_context *ctx, pdf_dict *annot, bool *render_done)
+static int pdfi_annot_draw_Ink(pdf_context *ctx, pdf_dict *annot, pdf_dict *NormAP, bool *render_done)
 {
-    return false;
+    *render_done = true;
+    return 0;
 }
 
-static bool pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, bool *render_done)
+static int pdfi_annot_draw_Circle(pdf_context *ctx, pdf_dict *annot, pdf_dict *NormAP, bool *render_done)
 {
-    return false;
+    int code = 0;
+
+    if (NormAP) {
+        *render_done = false;
+        goto exit;
+    }
+
+    /* TODO: Generate appearance (see pdf_draw.ps/Circle) */
+    *render_done = true;
+
+ exit:
+    return code;
+}
+
+/* Draws a thing of type /Widget */
+static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_dict *NormAP, bool *render_done)
+{
+    return 0;
 }
 
 annot_dispatch_t annot_dispatch[] = {
     {"Link", pdfi_annot_draw_Link},
     {"Ink", pdfi_annot_draw_Ink},
+    {"Circle", pdfi_annot_draw_Circle},
+    {"Widget", pdfi_annot_draw_Widget},
     { NULL, NULL},
 };
 
@@ -402,9 +533,10 @@ static int pdfi_annot_preserve(pdf_context *ctx, pdf_dict *annot)
 static int pdfi_annot_draw(pdf_context *ctx, pdf_dict *annot)
 {
     pdf_name *Subtype = NULL;
+    pdf_dict *NormAP = NULL;
     int code;
     annot_dispatch_t *dispatch_ptr;
-    bool render_done = false;
+    bool render_done = true;
 
     code = pdfi_dict_get_type(ctx, annot, "Subtype", PDF_NAME, (pdf_obj **)&Subtype);
     if (code != 0) {
@@ -422,24 +554,28 @@ static int pdfi_annot_draw(pdf_context *ctx, pdf_dict *annot)
     if (!pdfi_annot_check_type(ctx, Subtype))
         goto exit;
 
+    /* Get the Normal AP, if it exists */
+    code = pdfi_annot_get_NormAP(ctx, annot, &NormAP);
+    if (code < 0) goto exit;
+
     code = pdfi_gsave(ctx);
-    if (code < 0)
-        goto exit;
+    if (code < 0) goto exit;
 
     /* Draw the annotation */
     for (dispatch_ptr = annot_dispatch; dispatch_ptr->subtype; dispatch_ptr ++) {
         if (pdfi_name_is(Subtype, dispatch_ptr->subtype)) {
-            code = dispatch_ptr->func(ctx, annot, &render_done);
+            code = dispatch_ptr->func(ctx, annot, NormAP, &render_done);
             break;
         }
     }
     if (!render_done)
-        code = pdfi_annot_draw_Widget(ctx, annot, &render_done);
+        code = pdfi_annot_draw_AP(ctx, annot, 1.0, 1.0, NormAP);
 
     (void)pdfi_grestore(ctx);
 
  exit:
     pdfi_countdown(Subtype);
+    pdfi_countdown(NormAP);
     return code;
 }
 


Summary of changes:
 pdf/pdf_annot.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 161 insertions(+), 25 deletions(-)