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