Source: libharu
Severity: wishlist
Tags: patch

Dear Maintainer,

I am working on an official Kitware-supported Debian/Ubuntu package for
the upcoming VTK 9. We are using a custom shading feature developed
in-house for libharu. We have submitted our changes upstream, but the
project has been abandoned and the patch will most likely never be
accepted. Please backport the included patch so that we can bring VTK 9
to Debian. Thank you for your support.


*** patches/0001-Add-support-for-free-form-triangle-Shading-objects.patch
>From 9e8ba2f5453552909e52fde5ec30856004a616d0 Mon Sep 17 00:00:00 2001
From: "David C. Lonie" <david.lo...@kitware.com>
Date: Wed, 10 May 2017 11:07:28 -0400
Subject: [PATCH] Add support for free-form triangle Shading objects.

---
 include/hpdf.h           |  24 ++++-
 include/hpdf_error.h     |   3 +
 include/hpdf_objects.h   |   2 +
 include/hpdf_pages.h     |   5 +
 include/hpdf_types.h     |  14 +++
 src/CMakeLists.txt       |   1 +
 src/hpdf_page_operator.c |  31 +++++++
 src/hpdf_pages.c         |  55 ++++++++++-
 src/hpdf_shading.c       | 231 +++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 362 insertions(+), 4 deletions(-)
 create mode 100644 src/hpdf_shading.c

diff --git a/include/hpdf.h b/include/hpdf.h
index e369f67..40e3c41 100644
--- a/include/hpdf.h
+++ b/include/hpdf.h
@@ -77,6 +77,7 @@ typedef HPDF_HANDLE   HPDF_Dict;
 typedef HPDF_HANDLE   HPDF_EmbeddedFile;
 typedef HPDF_HANDLE   HPDF_OutputIntent;
 typedef HPDF_HANDLE   HPDF_Xref;
+typedef HPDF_HANDLE   HPDF_Shading;
 
 #else
 
@@ -1171,6 +1172,11 @@ HPDF_EXPORT(HPDF_STATUS)
 HPDF_Page_SetExtGState  (HPDF_Page        page,
                          HPDF_ExtGState   ext_gstate);
 
+/* sh */
+HPDF_EXPORT(HPDF_STATUS)
+HPDF_Page_SetShading  (HPDF_Page    page,
+                       HPDF_Shading shading);
+
 
 /*--- Special graphic state operator --------------------------------------*/
 
@@ -1450,7 +1456,23 @@ HPDF_Page_SetCMYKStroke  (HPDF_Page  page,
 
 /*--- Shading patterns ---------------------------------------------------*/
 
-/* sh --not implemented yet */
+/* Notes for docs:
+ * - ShadingType must be HPDF_SHADING_FREE_FORM_TRIANGLE_MESH (the only
+ *   defined option...)
+ * - colorSpace must be HPDF_CS_DEVICE_RGB for now.
+ */
+HPDF_EXPORT(HPDF_Shading)
+HPDF_Shading_New  (HPDF_Doc         pdf,
+                   HPDF_ShadingType type,
+                   HPDF_ColorSpace  colorSpace,
+                   HPDF_REAL xMin, HPDF_REAL xMax,
+                   HPDF_REAL yMin, HPDF_REAL yMax);
+
+HPDF_EXPORT(HPDF_STATUS)
+HPDF_Shading_AddVertexRGB(HPDF_Shading shading,
+                          HPDF_Shading_FreeFormTriangleMeshEdgeFlag edgeFlag,
+                          HPDF_REAL x, HPDF_REAL y,
+                          HPDF_UINT8 r, HPDF_UINT8 g, HPDF_UINT8 b);
 
 /*--- In-line images -----------------------------------------------------*/
 
diff --git a/include/hpdf_error.h b/include/hpdf_error.h
index b04e2cd..ef4fa61 100644
--- a/include/hpdf_error.h
+++ b/include/hpdf_error.h
@@ -145,6 +145,9 @@ extern "C" {
 #define HPDF_INVALID_U3D_DATA                     0x1083
 #define HPDF_NAME_CANNOT_GET_NAMES                0x1084
 #define HPDF_INVALID_ICC_COMPONENT_NUM            0x1085
+/*                                                0x1086 */
+/*                                                0x1087 */
+#define HPDF_INVALID_SHADING_TYPE                 0x1088
 
 /*---------------------------------------------------------------------------*/
 
diff --git a/include/hpdf_objects.h b/include/hpdf_objects.h
index 525adda..b16de02 100644
--- a/include/hpdf_objects.h
+++ b/include/hpdf_objects.h
@@ -61,6 +61,7 @@ extern "C" {
 #define  HPDF_OSUBCLASS_EXT_GSTATE_R  0x0B00  /* read only object */
 #define  HPDF_OSUBCLASS_NAMEDICT      0x0C00
 #define  HPDF_OSUBCLASS_NAMETREE      0x0D00
+#define  HPDF_OSUBCLASS_SHADING       0x0E00
 
 
 
@@ -595,6 +596,7 @@ typedef HPDF_Array HPDF_Destination;
 typedef HPDF_Dict  HPDF_U3D;
 typedef HPDF_Dict  HPDF_OutputIntent;
 typedef HPDF_Dict  HPDF_JavaScript;
+typedef HPDF_Dict  HPDF_Shading;
 
 #ifdef __cplusplus
 }
diff --git a/include/hpdf_pages.h b/include/hpdf_pages.h
index 44b816c..60b1d84 100644
--- a/include/hpdf_pages.h
+++ b/include/hpdf_pages.h
@@ -55,6 +55,7 @@ typedef struct _HPDF_PageAttr_Rec {
     HPDF_Dict          fonts;
     HPDF_Dict          xobjects;
     HPDF_Dict          ext_gstates;
+    HPDF_Dict          shadings;
     HPDF_GState        gstate;
     HPDF_Point         str_pos;
     HPDF_Point         cur_pos;
@@ -101,6 +102,10 @@ const char*
 HPDF_Page_GetExtGStateName  (HPDF_Page       page,
                              HPDF_ExtGState  gstate);
 
+const char*
+HPDF_Page_GetShadingName  (HPDF_Page    page,
+                           HPDF_Shading shading);
+
 
 HPDF_Box
 HPDF_Page_GetMediaBox  (HPDF_Page    page);
diff --git a/include/hpdf_types.h b/include/hpdf_types.h
index 8b3e0a8..a2e2157 100644
--- a/include/hpdf_types.h
+++ b/include/hpdf_types.h
@@ -557,6 +557,20 @@ typedef enum _HPDF_NameDictKey {
     HPDF_NAME_EOF
 } HPDF_NameDictKey;
 
+/*----------------------------------------------------------------------------*/
+
+typedef enum _HPDF_ShadingType {
+  HPDF_SHADING_FREE_FORM_TRIANGLE_MESH = 4 /* TODO the rest */
+} HPDF_ShadingType;
+
+typedef enum _HPDF_Shading_FreeFormTriangleMeshEdgeFlag {
+  HPDF_FREE_FORM_TRI_MESH_EDGEFLAG_NO_CONNECTION = 0,
+  HPDF_FREE_FORM_TRI_MESH_EDGEFLAG_BC,
+  HPDF_FREE_FORM_TRI_MESH_EDGEFLAG_AC
+} HPDF_Shading_FreeFormTriangleMeshEdgeFlag;
+
+/*----------------------------------------------------------------------------*/
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9d2a604..71c7d10 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -56,6 +56,7 @@ set(
        hpdf_page_operator.c
        hpdf_pages.c
        hpdf_real.c
+       hpdf_shading.c
        hpdf_streams.c
        hpdf_string.c
        hpdf_u3d.c
diff --git a/src/hpdf_page_operator.c b/src/hpdf_page_operator.c
index 23f5920..dda1078 100644
--- a/src/hpdf_page_operator.c
+++ b/src/hpdf_page_operator.c
@@ -312,6 +312,37 @@ HPDF_Page_SetExtGState  (HPDF_Page        page,
     return ret;
 }
 
+/* sh */
+HPDF_EXPORT(HPDF_STATUS)
+HPDF_Page_SetShading  (HPDF_Page    page,
+                       HPDF_Shading shading)
+{
+    HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
+    HPDF_PageAttr attr;
+    const char *local_name;
+
+    HPDF_PTRACE ((" HPDF_Page_SetShading\n"));
+
+    if (ret != HPDF_OK)
+        return ret;
+
+    if (page->mmgr != shading->mmgr)
+        return HPDF_RaiseError (page->error, HPDF_INVALID_OBJECT, 0);
+
+    attr = (HPDF_PageAttr)page->attr;
+    local_name = HPDF_Page_GetShadingName (page, shading);
+
+    if (!local_name)
+        return HPDF_CheckError (page->error);
+
+    if (HPDF_Stream_WriteEscapeName (attr->stream, local_name) != HPDF_OK)
+        return HPDF_CheckError (page->error);
+
+    if (HPDF_Stream_WriteStr (attr->stream, " sh\012") != HPDF_OK)
+        return HPDF_CheckError (page->error);
+
+    return ret;
+}
 
 /*--- Special graphic state operator --------------------------------------*/
 
diff --git a/src/hpdf_pages.c b/src/hpdf_pages.c
index fcc9b5c..c0a7c4f 100644
--- a/src/hpdf_pages.c
+++ b/src/hpdf_pages.c
@@ -514,7 +514,7 @@ HPDF_Page_GetLocalFontName  (HPDF_Page  page,
     /* search font-object from font-resource */
     key = HPDF_Dict_GetKeyByObj (attr->fonts, font);
     if (!key) {
-        /* if the font is not resisterd in font-resource, register font to
+        /* if the font is not registered in font-resource, register font to
          * font-resource.
          */
         char fontName[HPDF_LIMIT_MAX_NAME_LEN + 1];
@@ -603,7 +603,7 @@ HPDF_Page_GetXObjectName  (HPDF_Page     page,
     /* search xobject-object from xobject-resource */
     key = HPDF_Dict_GetKeyByObj (attr->xobjects, xobj);
     if (!key) {
-        /* if the xobject is not resisterd in xobject-resource, register
+        /* if the xobject is not registered in xobject-resource, register
          * xobject to xobject-resource.
          */
         char xobj_name[HPDF_LIMIT_MAX_NAME_LEN + 1];
@@ -654,7 +654,7 @@ HPDF_Page_GetExtGStateName  (HPDF_Page       page,
     /* search ext_gstate-object from ext_gstate-resource */
     key = HPDF_Dict_GetKeyByObj (attr->ext_gstates, state);
     if (!key) {
-        /* if the ext-gstate is not resisterd in ext-gstate resource, register
+        /* if the ext-gstate is not registered in ext-gstate resource, register
          *  to ext-gstate resource.
          */
         char ext_gstate_name[HPDF_LIMIT_MAX_NAME_LEN + 1];
@@ -673,6 +673,55 @@ HPDF_Page_GetExtGStateName  (HPDF_Page       page,
     return key;
 }
 
+const char*
+HPDF_Page_GetShadingName  (HPDF_Page    page,
+                           HPDF_Shading shading)
+{
+    HPDF_PageAttr attr = (HPDF_PageAttr )page->attr;
+    const char *key;
+
+    HPDF_PTRACE((" HPDF_Page_GetShadingName\n"));
+
+    if (!attr->shadings) {
+        HPDF_Dict resources;
+        HPDF_Dict shadings;
+
+        resources = HPDF_Page_GetInheritableItem (page, "Resources",
+                                                  HPDF_OCLASS_DICT);
+        if (!resources)
+            return NULL;
+
+        shadings = HPDF_Dict_New (page->mmgr);
+        if (!shadings)
+            return NULL;
+
+        if (HPDF_Dict_Add (resources, "Shading", shadings) != HPDF_OK)
+            return NULL;
+
+        attr->shadings = shadings;
+    }
+
+    /* search shading-object from shading-resource */
+    key = HPDF_Dict_GetKeyByObj (attr->shadings, shading);
+    if (!key) {
+        /* if the shading is not registered in shadings resource, register
+         *  to shadings resource.
+         */
+        char shading_str[HPDF_LIMIT_MAX_NAME_LEN + 1];
+        char *ptr;
+        char *end_ptr = shading_str + HPDF_LIMIT_MAX_NAME_LEN;
+
+        ptr = (char *)HPDF_StrCpy (shading_str, "Sh", end_ptr);
+        HPDF_IToA (ptr, attr->shadings->list->count, end_ptr);
+
+        if (HPDF_Dict_Add (attr->shadings, shading_str, shading) != HPDF_OK)
+            return NULL;
+
+        key = HPDF_Dict_GetKeyByObj (attr->shadings, shading);
+    }
+
+    return key;
+}
 
 static HPDF_STATUS
 AddAnnotation  (HPDF_Page        page,
diff --git a/src/hpdf_shading.c b/src/hpdf_shading.c
new file mode 100644
index 0000000..53204c0
--- /dev/null
+++ b/src/hpdf_shading.c
@@ -0,0 +1,231 @@
+/*
+ * << Haru Free PDF Library >> -- hpdf_shading.c
+ *
+ * URL: http://libharu.org
+ *
+ * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_ka...@est.hi-ho.ne.jp>
+ * Copyright (c) 2007-2009 Antony Dovgal <t...@daylessday.org>
+ * Copyright (c) 2017 Kitware <kitw...@kitware.com>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ * It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#include "hpdf.h"
+#include "hpdf_utils.h"
+
+#include "assert.h"
+
+typedef struct _RGBVertex
+{
+  HPDF_UINT8 EdgeFlag;
+  HPDF_UINT32 X;
+  HPDF_UINT32 Y;
+  HPDF_UINT8 RGB[3];
+} RGBVertex;
+
+static const char *COL_CMYK = "DeviceCMYK";
+static const char *COL_RGB = "DeviceRGB";
+static const char *COL_GRAY = "DeviceGray";
+
+/* bbox is filled with xMin, xMax, yMin, yMax */
+static HPDF_BOOL _GetDecodeArrayVertexValues(HPDF_Shading shading,
+                                             HPDF_REAL *bbox)
+{
+  HPDF_Array decodeArray;
+  HPDF_Real r;
+  int i;
+
+  if (!shading) {
+    return HPDF_FALSE;
+  }
+
+  decodeArray = (HPDF_Array)(HPDF_Dict_GetItem(shading, "Decode",
+                                               HPDF_OCLASS_ARRAY));
+  if (!decodeArray) {
+    return HPDF_FALSE;
+  }
+
+  for (i = 0; i < 4; ++i)
+  {
+    r = HPDF_Array_GetItem(decodeArray, i, HPDF_OCLASS_REAL);
+    if (!r) {
+      return HPDF_FALSE;
+    }
+
+    bbox[i] = r->value;
+  }
+
+  return HPDF_TRUE;
+}
+
+static void UINT32Swap (HPDF_UINT32  *value)
+{
+  HPDF_BYTE b[4];
+
+  HPDF_MemCpy (b, (HPDF_BYTE *)value, 4);
+  *value = (HPDF_UINT32)((HPDF_UINT32)b[0] << 24 |
+           (HPDF_UINT32)b[1] << 16 |
+           (HPDF_UINT32)b[2] << 8 |
+           (HPDF_UINT32)b[3]);
+}
+
+/* Encode a position coordinate for writing */
+static HPDF_UINT32 _EncodeValue(HPDF_REAL x, HPDF_REAL xMin, HPDF_REAL xMax)
+{
+  HPDF_DOUBLE norm = (x - xMin) / (xMax - xMin);
+  HPDF_DOUBLE max = (HPDF_DOUBLE)(0xFFFFFFFF);
+  HPDF_UINT32 enc = (HPDF_UINT32)(norm * max);
+  UINT32Swap(&enc);
+  return enc;
+}
+
+HPDF_EXPORT(HPDF_Shading)
+HPDF_Shading_New  (HPDF_Doc         pdf,
+                   HPDF_ShadingType type,
+                   HPDF_ColorSpace  colorSpace,
+                   HPDF_REAL xMin, HPDF_REAL xMax,
+                   HPDF_REAL yMin, HPDF_REAL yMax)
+{
+  HPDF_Shading shading;
+  HPDF_Array decodeArray;
+  HPDF_STATUS ret = HPDF_OK;
+  int i;
+
+  HPDF_PTRACE((" HPDF_Shading_New\n"));
+
+  if (!HPDF_HasDoc(pdf)) {
+    return NULL;
+  }
+
+  /* Validate shading type: */
+  switch (type)
+  {
+    case HPDF_SHADING_FREE_FORM_TRIANGLE_MESH:
+      break;
+
+    default:
+      HPDF_SetError (pdf->mmgr->error, HPDF_INVALID_SHADING_TYPE, 0);
+      return NULL;
+  }
+
+  decodeArray = HPDF_Array_New(pdf->mmgr);
+  if (!decodeArray) {
+    return NULL;
+  }
+
+  /* X-range */
+  ret += HPDF_Array_AddReal(decodeArray, xMin);
+  ret += HPDF_Array_AddReal(decodeArray, xMax);
+
+  /* Y-range */
+  ret += HPDF_Array_AddReal(decodeArray, yMin);
+  ret += HPDF_Array_AddReal(decodeArray, yMax);
+
+  const char *colName = NULL;
+  switch (colorSpace) {
+    case HPDF_CS_DEVICE_RGB:
+      colName = COL_RGB;
+      for (i = 0; i < 3; ++i) {
+        ret += HPDF_Array_AddReal(decodeArray, 0.0);
+        ret += HPDF_Array_AddReal(decodeArray, 1.0);
+      }
+      break;
+
+    default:
+      HPDF_SetError(pdf->mmgr->error, HPDF_INVALID_COLOR_SPACE, 0);
+      return NULL;
+  }
+
+  if (ret != HPDF_OK) {
+    return NULL;
+  }
+
+  shading = HPDF_DictStream_New(pdf->mmgr, pdf->xref);
+  if (!shading) {
+    return NULL;
+  }
+
+  shading->header.obj_class |= HPDF_OSUBCLASS_SHADING;
+  ret += HPDF_Dict_AddNumber(shading, "ShadingType", type);
+  ret += HPDF_Dict_AddName(shading, "ColorSpace", colName);
+
+  switch (type)
+  {
+    case HPDF_SHADING_FREE_FORM_TRIANGLE_MESH:
+      ret += HPDF_Dict_AddNumber(shading, "BitsPerCoordinate", 32);
+      ret += HPDF_Dict_AddNumber(shading, "BitsPerComponent", 8);
+      ret += HPDF_Dict_AddNumber(shading, "BitsPerFlag", 8);
+      ret += HPDF_Dict_Add(shading, "Decode", decodeArray);
+      break;
+
+    default:
+      HPDF_SetError (pdf->mmgr->error, HPDF_INVALID_SHADING_TYPE, 0);
+      return NULL;
+  }
+
+  if (ret != HPDF_OK) {
+    return NULL;
+  }
+
+  return shading;
+}
+
+HPDF_EXPORT(HPDF_STATUS)
+HPDF_Shading_AddVertexRGB(HPDF_Shading shading,
+                          HPDF_Shading_FreeFormTriangleMeshEdgeFlag edgeFlag,
+                          HPDF_REAL x, HPDF_REAL y,
+                          HPDF_UINT8 r, HPDF_UINT8 g, HPDF_UINT8 b)
+{
+  HPDF_STATUS ret = HPDF_OK;
+  RGBVertex vert;
+  float bbox[4];
+
+  HPDF_PTRACE((" HPDF_Shading_AddVertexRGB\n"));
+
+  if (!shading) {
+    return HPDF_INVALID_OBJECT;
+  }
+
+  if (_GetDecodeArrayVertexValues(shading, bbox) != HPDF_TRUE) {
+    return HPDF_SetError(shading->error, HPDF_INVALID_OBJECT, 0);
+  }
+
+  vert.EdgeFlag = (HPDF_UINT8)edgeFlag;
+  vert.X = _EncodeValue(x, bbox[0], bbox[1]);
+  vert.Y = _EncodeValue(y, bbox[2], bbox[3]);
+  vert.RGB[0] = r;
+  vert.RGB[1] = g;
+  vert.RGB[2] = b;
+
+  ret = HPDF_Stream_Write(shading->stream,
+                          (HPDF_BYTE*)(&vert.EdgeFlag), sizeof(vert.EdgeFlag));
+  if (ret != HPDF_OK)
+  {
+    return ret;
+  }
+
+  ret = HPDF_Stream_Write(shading->stream,
+                          (HPDF_BYTE*)(&vert.X), sizeof(vert.X));
+  if (ret != HPDF_OK)
+  {
+    return ret;
+  }
+
+  ret = HPDF_Stream_Write(shading->stream,
+                          (HPDF_BYTE*)(&vert.Y), sizeof(vert.Y));
+  if (ret != HPDF_OK)
+  {
+    return ret;
+  }
+
+  ret = HPDF_Stream_Write(shading->stream,
+                          (HPDF_BYTE*)(&vert.RGB), sizeof(vert.RGB));
+
+  return ret;
+}
-- 
2.16.2



-- System Information:
Debian Release: buster/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.15.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Reply via email to