Gitweb links:
...log
http://git.netsurf-browser.org/libnspdf.git/shortlog/d8835327fcc498795ac6...
...commit
http://git.netsurf-browser.org/libnspdf.git/commit/d8835327fcc498795ac66b...
...tree
http://git.netsurf-browser.org/libnspdf.git/tree/d8835327fcc498795ac66bed...
The branch, master has been updated
via d8835327fcc498795ac66bed330e741cef12ce29 (commit)
via f022fe68dcb0703e01e6530263e3177ffec1c083 (commit)
via 14ff03cff7400945afc3cd13d2f82e4450a3241e (commit)
from c4dd67804afc84fde84402649e5b32f2b00680c3 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libnspdf.git/commit/?id=d8835327fcc498795a...
commit d8835327fcc498795ac66bed330e741cef12ce29
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
implement colour setting operations in render
diff --git a/src/graphics_state.h b/src/graphics_state.h
index ec158e0..e5cc2bf 100644
--- a/src/graphics_state.h
+++ b/src/graphics_state.h
@@ -29,16 +29,29 @@ struct graphics_state_color {
enum graphics_state_colorspace space;
union {
float gray; /* default is 0 - black */
- float rgb[3];
- float cmyk[3];
- };
+ struct {
+ float r;
+ float g;
+ float b;
+ } rgb;
+ struct {
+ float c;
+ float m;
+ float y;
+ float k;
+ } cmyk;
+ } u;
};
struct graphics_state_param {
float ctm[6]; /* current transform matrix */
/* clipping path */
- struct graphics_state_color stroke_colour;
- struct graphics_state_color other_colour;
+ struct {
+ struct graphics_state_color colour;
+ } stroke;
+ struct {
+ struct graphics_state_color colour;
+ } other;
/* text state */
float line_width;
unsigned int line_cap;
diff --git a/src/page.c b/src/page.c
index eb80f0f..984228b 100644
--- a/src/page.c
+++ b/src/page.c
@@ -330,13 +330,67 @@ render_operation_h(struct graphics_state *gs)
}
static inline nspdferror
+gsc_to_device(struct graphics_state_color * gsc, uint32_t *c_out)
+{
+ uint32_t c;
+ unsigned int v;
+
+ switch (gsc->space) {
+ case GSDeviceGray:
+ v = gsc->u.gray * 255.0;
+ v = v & 0xff;
+ c = v | (v << 8) | (v << 16);
+ break;
+
+ case GSDeviceRGB:
+ v = gsc->u.rgb.r * 255.0;
+ c = v & 0xff;
+ v = gsc->u.rgb.g * 255.0;
+ v = v & 0xff;
+ c |= v << 8;
+ v = gsc->u.rgb.b * 255.0;
+ v = v & 0xff;
+ c |= v << 16;
+ break;
+
+ case GSDeviceCMYK:
+ /* no color profile, this will look shocking */
+ v = (1.0 - ((gsc->u.cmyk.c * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ c = v & 0xff;
+ v = (1.0 - ((gsc->u.cmyk.m * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ v = v & 0xff;
+ c |= v << 8;
+ v = (1.0 - ((gsc->u.cmyk.y * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ v = v & 0xff;
+ c |= v << 16;
+ /* if (c != 0) printf("setting %f %f %f %f %x\n",
+ gsc->u.cmyk.c,
+ gsc->u.cmyk.m,
+ gsc->u.cmyk.y,
+ gsc->u.cmyk.k,
+ c);
+ */
+ break;
+
+ default:
+ c = 0;
+ break;
+ }
+
+ *c_out = c;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
render_operation_f(struct graphics_state *gs, struct nspdf_render_ctx* render_ctx)
{
struct nspdf_style style;
style.stroke_type = NSPDF_OP_TYPE_NONE;
style.stroke_colour = 0x01000000;
+
style.fill_type = NSPDF_OP_TYPE_SOLID;
- style.fill_colour = 0;
+ gsc_to_device(&gs->param_stack[gs->param_stack_idx].other.colour,
&style.fill_colour);
render_ctx->path(&style,
gs->path,
@@ -344,6 +398,7 @@ render_operation_f(struct graphics_state *gs, struct nspdf_render_ctx*
render_ct
gs->param_stack[gs->param_stack_idx].ctm,
render_ctx->ctx);
gs->path_idx = 0;
+
return NSPDFERROR_OK;
}
@@ -353,11 +408,13 @@ render_operation_S(struct graphics_state *gs, struct
nspdf_render_ctx* render_ct
{
struct nspdf_style style;
- style.stroke_type = NSPDF_OP_TYPE_SOLID;
- style.stroke_colour = 0;
- style.stroke_width = gs->param_stack[gs->param_stack_idx].line_width;
style.fill_type = NSPDF_OP_TYPE_NONE;
style.fill_colour = 0x01000000;
+
+ style.stroke_type = NSPDF_OP_TYPE_SOLID;
+ style.stroke_width = gs->param_stack[gs->param_stack_idx].line_width;
+ gsc_to_device(&gs->param_stack[gs->param_stack_idx].stroke.colour,
&style.stroke_colour);
+
render_ctx->path(&style,
gs->path,
gs->path_idx,
@@ -435,6 +492,186 @@ render_operation_cm(struct content_operation *operation, struct
graphics_state *
gs->param_stack[gs->param_stack_idx].ctm);
}
+
+static inline nspdferror
+set_gsc_grey(struct graphics_state_color *gsc, float gray)
+{
+ /* bounds check */
+ if (gray < 0.0) {
+ gray = 0.0;
+ } else if (gray > 1.0) {
+ gray = 1.0;
+ }
+
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = gray;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_G(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_grey(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0]);
+}
+
+static inline nspdferror
+render_operation_g(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_grey(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0]);
+}
+
+static inline nspdferror
+set_gsc_rgb(struct graphics_state_color *gsc, float r, float g, float b)
+{
+ /* bounds check */
+ if (r < 0.0) {
+ r = 0.0;
+ } else if (r > 1.0) {
+ r = 1.0;
+ }
+ if (g < 0.0) {
+ g = 0.0;
+ } else if (g > 1.0) {
+ g = 1.0;
+ }
+ if (b < 0.0) {
+ b = 0.0;
+ } else if (b > 1.0) {
+ b = 1.0;
+ }
+
+ gsc->space = GSDeviceRGB;
+ gsc->u.rgb.r = r;
+ gsc->u.rgb.g = g;
+ gsc->u.rgb.b = b;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_RG(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_rgb(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2]);
+}
+
+static inline nspdferror
+render_operation_rg(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_rgb(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2]);
+}
+
+static inline nspdferror
+set_gsc_cmyk(struct graphics_state_color *gsc, float c, float m, float y, float k)
+{
+ /* bounds check */
+ if (c < 0.0) {
+ c = 0.0;
+ } else if (c > 1.0) {
+ c = 1.0;
+ }
+ if (y < 0.0) {
+ y = 0.0;
+ } else if (y > 1.0) {
+ y = 1.0;
+ }
+ if (m < 0.0) {
+ m = 0.0;
+ } else if (m > 1.0) {
+ m = 1.0;
+ }
+ if (k < 0.0) {
+ k = 0.0;
+ } else if (k > 1.0) {
+ k = 1.0;
+ }
+
+ gsc->space = GSDeviceCMYK;
+ gsc->u.cmyk.c = c;
+ gsc->u.cmyk.m = m;
+ gsc->u.cmyk.y = y;
+ gsc->u.cmyk.k = k;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_K(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cmyk(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2],
+ operation->u.number[3]);
+}
+
+static inline nspdferror
+render_operation_k(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cmyk(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2],
+ operation->u.number[3]);
+}
+
+static inline nspdferror
+set_gsc_cs(struct graphics_state_color *gsc, const char *spacename)
+{
+ if (strcmp(spacename, "DeviceGray") == 0) {
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = 0.0;
+ } else if (strcmp(spacename, "DeviceRGB") == 0) {
+ gsc->space = GSDeviceRGB;
+ gsc->u.rgb.r = 0.0;
+ gsc->u.rgb.g = 0.0;
+ gsc->u.rgb.b = 0.0;
+ } else if (strcmp(spacename, "DeviceCMYK") == 0) {
+ gsc->space = GSDeviceCMYK;
+ gsc->u.cmyk.c = 0.0;
+ gsc->u.cmyk.m = 0.0;
+ gsc->u.cmyk.y = 0.0;
+ gsc->u.cmyk.k = 1.0;
+ } else {
+ /** \todo colourspace from name defined in the ColorSpace subdictionary of the
current resource dictionary */
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = 0.0;
+
+ }
+ //printf("cs %s %d\n", spacename, gsc->space);
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_CS(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cs(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.name);
+}
+
+static inline nspdferror
+render_operation_cs(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cs(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.name);
+}
+
/**
* Initialise the parameter stack
*
@@ -574,6 +811,44 @@ nspdf_page_render(struct nspdf_doc *doc,
res = render_operation_cm(operation, &gs);
break;
+ /* colour operators */
+ case CONTENT_OP_G: /* gray stroking colour */
+ res = render_operation_G(operation, &gs);
+ break;
+
+ case CONTENT_OP_g: /* gray non-stroking colour */
+ res = render_operation_g(operation, &gs);
+ break;
+
+ case CONTENT_OP_RG: /* rgb stroking colour */
+ res = render_operation_RG(operation, &gs);
+ break;
+
+ case CONTENT_OP_rg: /* rgb non-stroking colour */
+ res = render_operation_rg(operation, &gs);
+ break;
+
+ case CONTENT_OP_K: /* CMYK stroking colour */
+ res = render_operation_K(operation, &gs);
+ break;
+
+ case CONTENT_OP_k: /* CMYK non-stroking colour */
+ res = render_operation_k(operation, &gs);
+ break;
+
+ case CONTENT_OP_CS: /* change stroking colourspace */
+ res = render_operation_CS(operation, &gs);
+ break;
+
+ case CONTENT_OP_cs: /* change non-stroking colourspace */
+ res = render_operation_cs(operation, &gs);
+ break;
+
+ //case CONTENT_OP_SC:
+ //case CONTENT_OP_sc:
+ //case CONTENT_OP_SCN:
+ //case CONTENT_OP_scn:
+
default:
printf("operator %s\n",
nspdf__cos_content_operator_name(operation->operator));
commitdiff
http://git.netsurf-browser.org/libnspdf.git/commit/?id=f022fe68dcb0703e01...
commit f022fe68dcb0703e01e6530263e3177ffec1c083
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
extend graphics state operation implementation
diff --git a/src/graphics_state.h b/src/graphics_state.h
new file mode 100644
index 0000000..ec158e0
--- /dev/null
+++ b/src/graphics_state.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of libnspdf.
+ *
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf PDF library graphics state
+ */
+
+#ifndef NSPDF__GRAPHICS_STATE_H_
+#define NSPDF__GRAPHICS_STATE_H_
+
+/**
+ * colourspaces
+ * \todo extend this with full list from section 4.5.2
+ */
+enum graphics_state_colorspace {
+ GSDeviceGray = 0, /* Default */
+ GSDeviceRGB,
+ GSDeviceCMYK,
+};
+
+struct graphics_state_color {
+ enum graphics_state_colorspace space;
+ union {
+ float gray; /* default is 0 - black */
+ float rgb[3];
+ float cmyk[3];
+ };
+};
+
+struct graphics_state_param {
+ float ctm[6]; /* current transform matrix */
+ /* clipping path */
+ struct graphics_state_color stroke_colour;
+ struct graphics_state_color other_colour;
+ /* text state */
+ float line_width;
+ unsigned int line_cap;
+ unsigned int line_join;
+ float miter_limit;
+ /* dash pattern */
+ /* rendering intent RelativeColorimetric */
+ bool stroke_adjustment;
+ /* blend mode: Normal */
+ /* soft mask */
+ /* alpha constant */
+ /* alpha source */
+
+ /* device dependant */
+ bool overprint;
+ float overprint_mode;
+ /* black generation */
+ /* undercolor removal */
+ /* transfer */
+ /* halftone */
+ float flatness;
+ float smoothness;
+};
+
+struct graphics_state {
+ float *path; /* current path */
+ unsigned int path_idx; /* current index into path */
+ unsigned int path_alloc; /* current number of path elements allocated */
+
+ struct graphics_state_param *param_stack; /* parameter stack */
+ unsigned int param_stack_idx;
+ unsigned int param_stack_alloc;
+};
+
+#endif
diff --git a/src/page.c b/src/page.c
index 08d993c..eb80f0f 100644
--- a/src/page.c
+++ b/src/page.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <nspdf/page.h>
+#include "graphics_state.h"
#include "cos_content.h"
#include "cos_object.h"
#include "pdf_doc.h"
@@ -32,6 +33,65 @@ struct page_table_entry {
};
/**
+ * multiply pdf matricies
+ *
+ * pdf specifies its 3 x 3 transform matrix as six values and three constants
+ * | t[0] t[1] 0 |
+ * Mt = | t[2] t[3] 0 |
+ * | t[4] t[5] 1 |
+ *
+ * this multiples two such matricies together
+ * Mo = Ma * Mb
+ *
+ * Basic matrix expansion is
+ * | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
+ * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
+ * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
+ *
+ * With the a and b arrays substituted
+ * | o[0] o[1] 0 |
+ * | o[2] o[3] 0 | =
+ * | o[4] o[5] 1 |
+ *
+ * | a[0] a[1] 0 | | b[0] b[1] 0 |
+ * | a[2] a[3] 0 | * | b[2] b[3] 0 | =
+ * | a[4] a[5] 1 | | b[4] b[5] 1 |
+ *
+ * | a[0]*b[0]+a[1]*b[2] a[0]*b[1]+a[1]*b[3] 0 |
+ * | a[2]*b[0]+a[3]*b[2] a[2]*b[1]+a[3]*b[3] 0 |
+ * | a[4]*b[0]+a[5]*b[2]+b[4] a[4]*b[1]+a[5]*b[3]+b[5] 1 |
+ *
+ * \param a The array of six values for matrix a
+ * \param b The array of six values for matrix b
+ * \param o An array to receive six values resulting from Ma * Mb may be same array as a
or b
+ * \return NSPDFERROR_OK on success
+ */
+static nspdferror
+pdf_matrix_multiply(float *a, float *b, float *o)
+{
+ float out[6]; /* result matrix array */
+
+ out[0] = a[0]*b[0] + a[1]*b[2];
+ out[1] = a[0]*b[1] + a[1]*b[3];
+ out[2] = a[2]*b[0] + a[3]*b[2];
+ out[3] = a[2]*b[1] + a[3]*b[3];
+ out[4] = a[4]*b[0] + a[5]*b[2] + b[4];
+ out[5] = a[4]*b[1] + a[5]*b[3] + b[5];
+
+ /* calculate and then assign output to allow input and output arrays to
+ * overlap
+ */
+ o[0] = out[0];
+ o[1] = out[1];
+ o[2] = out[2];
+ o[3] = out[3];
+ o[4] = out[4];
+ o[5] = out[5];
+
+ return NSPDFERROR_OK;
+}
+
+/**
* recursively decodes a page tree
*/
nspdferror
@@ -210,53 +270,6 @@ nspdf_page_count(struct nspdf_doc *doc, unsigned int *pages_out)
return NSPDFERROR_OK;
}
-/**
- * colourspaces
- * \todo extend this with full list from section 4.5.2
- */
-enum graphics_state_colorspace {
- GSDeviceGray = 0, /* Default */
- GSDeviceRGB,
- GSDeviceCMYK,
-};
-
-struct graphics_state_color {
- enum graphics_state_colorspace space;
- union {
- float gray; /* default is 0 - black */
- float rgb[3];
- float cmyk[3];
- };
-};
-
-struct graphics_state_param {
- float ctm[6]; /* current transform matrix */
- /* clipping path */
- struct graphics_state_color stroke_colour;
- struct graphics_state_color other_colour;
- /* text state */
- float line_width;
- unsigned int line_cap;
- unsigned int line_join;
- float miter_limit;
- /* dash pattern */
- /* rendering intent RelativeColorimetric */
- bool stroke_adjustment;
- /* blend mode: Normal */
- /* soft mask */
- /* alpha constant */
- /* alpha source */
-};
-
-struct graphics_state {
- float *path; /* current path */
- unsigned int path_idx; /* current index into path */
- unsigned int path_alloc; /* current number of path elements allocated */
-
- struct graphics_state_param *param_stack; /* parameter stack */
- unsigned int param_stack_idx;
- unsigned int param_stack_alloc;
-};
static inline nspdferror
render_operation_m(struct content_operation *operation, struct graphics_state *gs)
@@ -362,6 +375,34 @@ render_operation_w(struct content_operation *operation, struct
graphics_state *g
}
static inline nspdferror
+render_operation_i(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].flatness = operation->u.number[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_M(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].miter_limit = operation->u.number[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_j(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].line_join = operation->u.i[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_J(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].line_cap = operation->u.i[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
render_operation_q(struct graphics_state *gs)
{
gs->param_stack[gs->param_stack_idx + 1] =
gs->param_stack[gs->param_stack_idx];
@@ -379,64 +420,6 @@ render_operation_Q(struct graphics_state *gs)
}
-/**
- * multiply pdf matricies
- *
- * pdf specifies its 3 x 3 transform matrix as six values and three constants
- * | t[0] t[1] 0 |
- * Mt = | t[2] t[3] 0 |
- * | t[4] t[5] 1 |
- *
- * this multiples two such matricies together
- * Mo = Ma * Mb
- *
- * Basic matrix expansion is
- * | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
- * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
- * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
- *
- * With the a and b arrays substituted
- * | o[0] o[1] 0 |
- * | o[2] o[3] 0 | =
- * | o[4] o[5] 1 |
- *
- * | a[0] a[1] 0 | | b[0] b[1] 0 |
- * | a[2] a[3] 0 | * | b[2] b[3] 0 | =
- * | a[4] a[5] 1 | | b[4] b[5] 1 |
- *
- * | a[0]*b[0]+a[1]*b[2] a[0]*b[1]+a[1]*b[3] 0 |
- * | a[2]*b[0]+a[3]*b[2] a[2]*b[1]+a[3]*b[3] 0 |
- * | a[4]*b[0]+a[5]*b[2]+b[4] a[4]*b[1]+a[5]*b[3]+b[5] 1 |
- *
- * \param a The array of six values for matrix a
- * \param b The array of six values for matrix b
- * \param o An array to receive six values resulting from Ma * Mb may be same array as a
or b
- * \return NSPDFERROR_OK on success
- */
-static nspdferror
-pdf_matrix_multiply(float *a, float *b, float *o)
-{
- float out[6]; /* result matrix array */
-
- out[0] = a[0]*b[0] + a[1]*b[2];
- out[1] = a[0]*b[1] + a[1]*b[3];
- out[2] = a[2]*b[0] + a[3]*b[2];
- out[3] = a[2]*b[1] + a[3]*b[3];
- out[4] = a[4]*b[0] + a[5]*b[2] + b[4];
- out[5] = a[4]*b[1] + a[5]*b[3] + b[5];
-
- /* calculate and then assign output to allow input and output arrays to
- * overlap
- */
- o[0] = out[0];
- o[1] = out[1];
- o[2] = out[2];
- o[3] = out[3];
- o[4] = out[4];
- o[5] = out[5];
-
- return NSPDFERROR_OK;
-}
/**
* pre-multiply matrix
@@ -519,6 +502,7 @@ nspdf_page_render(struct nspdf_doc *doc,
idx < page_content->length;
idx++, operation++) {
switch(operation->operator) {
+ /* path operations */
case CONTENT_OP_m: /* move */
res = render_operation_m(operation, &gs);
break;
@@ -557,9 +541,25 @@ nspdf_page_render(struct nspdf_doc *doc,
res = render_operation_S(&gs, render_ctx);
break;
- case CONTENT_OP_w:
+ /* graphics state operations */
+ case CONTENT_OP_w: /* line width */
res = render_operation_w(operation, &gs);
- //printf("line width:%f\n",
gs.param_stack[gs.param_stack_idx].line_width);
+ break;
+
+ case CONTENT_OP_i: /* flatness */
+ res = render_operation_i(operation, &gs);
+ break;
+
+ case CONTENT_OP_j: /* line join style */
+ res = render_operation_j(operation, &gs);
+ break;
+
+ case CONTENT_OP_J: /* line cap style */
+ res = render_operation_J(operation, &gs);
+ break;
+
+ case CONTENT_OP_M: /* miter limit */
+ res = render_operation_M(operation, &gs);
break;
case CONTENT_OP_q: /* push parameter stack */
commitdiff
http://git.netsurf-browser.org/libnspdf.git/commit/?id=14ff03cff7400945af...
commit 14ff03cff7400945afc3cd13d2f82e4450a3241e
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
split out pdf matrix multiplication
diff --git a/src/page.c b/src/page.c
index c5ea8b8..08d993c 100644
--- a/src/page.c
+++ b/src/page.c
@@ -378,45 +378,78 @@ render_operation_Q(struct graphics_state *gs)
return NSPDFERROR_OK;
}
+
+/**
+ * multiply pdf matricies
+ *
+ * pdf specifies its 3 x 3 transform matrix as six values and three constants
+ * | t[0] t[1] 0 |
+ * Mt = | t[2] t[3] 0 |
+ * | t[4] t[5] 1 |
+ *
+ * this multiples two such matricies together
+ * Mo = Ma * Mb
+ *
+ * Basic matrix expansion is
+ * | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
+ * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
+ * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
+ *
+ * With the a and b arrays substituted
+ * | o[0] o[1] 0 |
+ * | o[2] o[3] 0 | =
+ * | o[4] o[5] 1 |
+ *
+ * | a[0] a[1] 0 | | b[0] b[1] 0 |
+ * | a[2] a[3] 0 | * | b[2] b[3] 0 | =
+ * | a[4] a[5] 1 | | b[4] b[5] 1 |
+ *
+ * | a[0]*b[0]+a[1]*b[2] a[0]*b[1]+a[1]*b[3] 0 |
+ * | a[2]*b[0]+a[3]*b[2] a[2]*b[1]+a[3]*b[3] 0 |
+ * | a[4]*b[0]+a[5]*b[2]+b[4] a[4]*b[1]+a[5]*b[3]+b[5] 1 |
+ *
+ * \param a The array of six values for matrix a
+ * \param b The array of six values for matrix b
+ * \param o An array to receive six values resulting from Ma * Mb may be same array as a
or b
+ * \return NSPDFERROR_OK on success
+ */
+static nspdferror
+pdf_matrix_multiply(float *a, float *b, float *o)
+{
+ float out[6]; /* result matrix array */
+
+ out[0] = a[0]*b[0] + a[1]*b[2];
+ out[1] = a[0]*b[1] + a[1]*b[3];
+ out[2] = a[2]*b[0] + a[3]*b[2];
+ out[3] = a[2]*b[1] + a[3]*b[3];
+ out[4] = a[4]*b[0] + a[5]*b[2] + b[4];
+ out[5] = a[4]*b[1] + a[5]*b[3] + b[5];
+
+ /* calculate and then assign output to allow input and output arrays to
+ * overlap
+ */
+ o[0] = out[0];
+ o[1] = out[1];
+ o[2] = out[2];
+ o[3] = out[3];
+ o[4] = out[4];
+ o[5] = out[5];
+
+ return NSPDFERROR_OK;
+}
+
/**
* pre-multiply matrix
*/
static inline nspdferror
render_operation_cm(struct content_operation *operation, struct graphics_state *gs)
{
- float M[6]; /* result matrix */
- /* M' = Mt * M */
- /* M' = Mo * Mc where Mo is operation and Mc is graphics state ctm */
- /* | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
- * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
- * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
- *
- * | o[0] o[1] 0 | | c[0] c[1] 0 | | o[0]*c[0]+o[1]*c[2] o[0]*c[1]+o[1]*c[3]
0 |
- * | o[2] o[3] 0 | * | c[2] c[3] 0 | = | o[2]*c[0]+o[3]*c[2] o[2]*c[1]+o[3]*c[3]
0 |
- * | o[4] o[5] 1 | | c[4] c[5] 1 | | o[4]*c[0]+o[5]*c[2]+c[4]
o[4]*c[1]+o[5]*c[3]+c[5] 1 |
+ /* Mres = Mop * Mctm
+ * where Mop is operation and Mctm is graphics state ctm
*/
- M[0] = operation->u.number[0] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[1] *
gs->param_stack[gs->param_stack_idx].ctm[2];
- M[1] = operation->u.number[0] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[1] *
gs->param_stack[gs->param_stack_idx].ctm[3];
- M[2] = operation->u.number[2] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[3] *
gs->param_stack[gs->param_stack_idx].ctm[2];
- M[3] = operation->u.number[2] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[3] *
gs->param_stack[gs->param_stack_idx].ctm[3];
- M[4] = operation->u.number[4] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[5] * gs->param_stack[gs->param_stack_idx].ctm[2]
+
- gs->param_stack[gs->param_stack_idx].ctm[4];
- M[5] = operation->u.number[4] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[5] * gs->param_stack[gs->param_stack_idx].ctm[3]
+
- gs->param_stack[gs->param_stack_idx].ctm[5];
-
- gs->param_stack[gs->param_stack_idx].ctm[0] = M[0];
- gs->param_stack[gs->param_stack_idx].ctm[1] = M[1];
- gs->param_stack[gs->param_stack_idx].ctm[2] = M[2];
- gs->param_stack[gs->param_stack_idx].ctm[3] = M[3];
- gs->param_stack[gs->param_stack_idx].ctm[4] = M[4];
- gs->param_stack[gs->param_stack_idx].ctm[5] = M[5];
- return NSPDFERROR_OK;
+ return pdf_matrix_multiply(operation->u.number,
+ gs->param_stack[gs->param_stack_idx].ctm,
+ gs->param_stack[gs->param_stack_idx].ctm);
}
/**
-----------------------------------------------------------------------
Summary of changes:
src/graphics_state.h | 89 ++++++++++
src/page.c | 476 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 481 insertions(+), 84 deletions(-)
create mode 100644 src/graphics_state.h
diff --git a/src/graphics_state.h b/src/graphics_state.h
new file mode 100644
index 0000000..e5cc2bf
--- /dev/null
+++ b/src/graphics_state.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of libnspdf.
+ *
+ * Licensed under the MIT License,
+ *
http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf PDF library graphics state
+ */
+
+#ifndef NSPDF__GRAPHICS_STATE_H_
+#define NSPDF__GRAPHICS_STATE_H_
+
+/**
+ * colourspaces
+ * \todo extend this with full list from section 4.5.2
+ */
+enum graphics_state_colorspace {
+ GSDeviceGray = 0, /* Default */
+ GSDeviceRGB,
+ GSDeviceCMYK,
+};
+
+struct graphics_state_color {
+ enum graphics_state_colorspace space;
+ union {
+ float gray; /* default is 0 - black */
+ struct {
+ float r;
+ float g;
+ float b;
+ } rgb;
+ struct {
+ float c;
+ float m;
+ float y;
+ float k;
+ } cmyk;
+ } u;
+};
+
+struct graphics_state_param {
+ float ctm[6]; /* current transform matrix */
+ /* clipping path */
+ struct {
+ struct graphics_state_color colour;
+ } stroke;
+ struct {
+ struct graphics_state_color colour;
+ } other;
+ /* text state */
+ float line_width;
+ unsigned int line_cap;
+ unsigned int line_join;
+ float miter_limit;
+ /* dash pattern */
+ /* rendering intent RelativeColorimetric */
+ bool stroke_adjustment;
+ /* blend mode: Normal */
+ /* soft mask */
+ /* alpha constant */
+ /* alpha source */
+
+ /* device dependant */
+ bool overprint;
+ float overprint_mode;
+ /* black generation */
+ /* undercolor removal */
+ /* transfer */
+ /* halftone */
+ float flatness;
+ float smoothness;
+};
+
+struct graphics_state {
+ float *path; /* current path */
+ unsigned int path_idx; /* current index into path */
+ unsigned int path_alloc; /* current number of path elements allocated */
+
+ struct graphics_state_param *param_stack; /* parameter stack */
+ unsigned int param_stack_idx;
+ unsigned int param_stack_alloc;
+};
+
+#endif
diff --git a/src/page.c b/src/page.c
index c5ea8b8..984228b 100644
--- a/src/page.c
+++ b/src/page.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <nspdf/page.h>
+#include "graphics_state.h"
#include "cos_content.h"
#include "cos_object.h"
#include "pdf_doc.h"
@@ -32,6 +33,65 @@ struct page_table_entry {
};
/**
+ * multiply pdf matricies
+ *
+ * pdf specifies its 3 x 3 transform matrix as six values and three constants
+ * | t[0] t[1] 0 |
+ * Mt = | t[2] t[3] 0 |
+ * | t[4] t[5] 1 |
+ *
+ * this multiples two such matricies together
+ * Mo = Ma * Mb
+ *
+ * Basic matrix expansion is
+ * | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
+ * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
+ * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
+ *
+ * With the a and b arrays substituted
+ * | o[0] o[1] 0 |
+ * | o[2] o[3] 0 | =
+ * | o[4] o[5] 1 |
+ *
+ * | a[0] a[1] 0 | | b[0] b[1] 0 |
+ * | a[2] a[3] 0 | * | b[2] b[3] 0 | =
+ * | a[4] a[5] 1 | | b[4] b[5] 1 |
+ *
+ * | a[0]*b[0]+a[1]*b[2] a[0]*b[1]+a[1]*b[3] 0 |
+ * | a[2]*b[0]+a[3]*b[2] a[2]*b[1]+a[3]*b[3] 0 |
+ * | a[4]*b[0]+a[5]*b[2]+b[4] a[4]*b[1]+a[5]*b[3]+b[5] 1 |
+ *
+ * \param a The array of six values for matrix a
+ * \param b The array of six values for matrix b
+ * \param o An array to receive six values resulting from Ma * Mb may be same array as a
or b
+ * \return NSPDFERROR_OK on success
+ */
+static nspdferror
+pdf_matrix_multiply(float *a, float *b, float *o)
+{
+ float out[6]; /* result matrix array */
+
+ out[0] = a[0]*b[0] + a[1]*b[2];
+ out[1] = a[0]*b[1] + a[1]*b[3];
+ out[2] = a[2]*b[0] + a[3]*b[2];
+ out[3] = a[2]*b[1] + a[3]*b[3];
+ out[4] = a[4]*b[0] + a[5]*b[2] + b[4];
+ out[5] = a[4]*b[1] + a[5]*b[3] + b[5];
+
+ /* calculate and then assign output to allow input and output arrays to
+ * overlap
+ */
+ o[0] = out[0];
+ o[1] = out[1];
+ o[2] = out[2];
+ o[3] = out[3];
+ o[4] = out[4];
+ o[5] = out[5];
+
+ return NSPDFERROR_OK;
+}
+
+/**
* recursively decodes a page tree
*/
nspdferror
@@ -210,53 +270,6 @@ nspdf_page_count(struct nspdf_doc *doc, unsigned int *pages_out)
return NSPDFERROR_OK;
}
-/**
- * colourspaces
- * \todo extend this with full list from section 4.5.2
- */
-enum graphics_state_colorspace {
- GSDeviceGray = 0, /* Default */
- GSDeviceRGB,
- GSDeviceCMYK,
-};
-
-struct graphics_state_color {
- enum graphics_state_colorspace space;
- union {
- float gray; /* default is 0 - black */
- float rgb[3];
- float cmyk[3];
- };
-};
-
-struct graphics_state_param {
- float ctm[6]; /* current transform matrix */
- /* clipping path */
- struct graphics_state_color stroke_colour;
- struct graphics_state_color other_colour;
- /* text state */
- float line_width;
- unsigned int line_cap;
- unsigned int line_join;
- float miter_limit;
- /* dash pattern */
- /* rendering intent RelativeColorimetric */
- bool stroke_adjustment;
- /* blend mode: Normal */
- /* soft mask */
- /* alpha constant */
- /* alpha source */
-};
-
-struct graphics_state {
- float *path; /* current path */
- unsigned int path_idx; /* current index into path */
- unsigned int path_alloc; /* current number of path elements allocated */
-
- struct graphics_state_param *param_stack; /* parameter stack */
- unsigned int param_stack_idx;
- unsigned int param_stack_alloc;
-};
static inline nspdferror
render_operation_m(struct content_operation *operation, struct graphics_state *gs)
@@ -317,13 +330,67 @@ render_operation_h(struct graphics_state *gs)
}
static inline nspdferror
+gsc_to_device(struct graphics_state_color * gsc, uint32_t *c_out)
+{
+ uint32_t c;
+ unsigned int v;
+
+ switch (gsc->space) {
+ case GSDeviceGray:
+ v = gsc->u.gray * 255.0;
+ v = v & 0xff;
+ c = v | (v << 8) | (v << 16);
+ break;
+
+ case GSDeviceRGB:
+ v = gsc->u.rgb.r * 255.0;
+ c = v & 0xff;
+ v = gsc->u.rgb.g * 255.0;
+ v = v & 0xff;
+ c |= v << 8;
+ v = gsc->u.rgb.b * 255.0;
+ v = v & 0xff;
+ c |= v << 16;
+ break;
+
+ case GSDeviceCMYK:
+ /* no color profile, this will look shocking */
+ v = (1.0 - ((gsc->u.cmyk.c * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ c = v & 0xff;
+ v = (1.0 - ((gsc->u.cmyk.m * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ v = v & 0xff;
+ c |= v << 8;
+ v = (1.0 - ((gsc->u.cmyk.y * (1.0 - gsc->u.cmyk.k)) + gsc->u.cmyk.k)) *
255.0;
+ v = v & 0xff;
+ c |= v << 16;
+ /* if (c != 0) printf("setting %f %f %f %f %x\n",
+ gsc->u.cmyk.c,
+ gsc->u.cmyk.m,
+ gsc->u.cmyk.y,
+ gsc->u.cmyk.k,
+ c);
+ */
+ break;
+
+ default:
+ c = 0;
+ break;
+ }
+
+ *c_out = c;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
render_operation_f(struct graphics_state *gs, struct nspdf_render_ctx* render_ctx)
{
struct nspdf_style style;
style.stroke_type = NSPDF_OP_TYPE_NONE;
style.stroke_colour = 0x01000000;
+
style.fill_type = NSPDF_OP_TYPE_SOLID;
- style.fill_colour = 0;
+ gsc_to_device(&gs->param_stack[gs->param_stack_idx].other.colour,
&style.fill_colour);
render_ctx->path(&style,
gs->path,
@@ -331,6 +398,7 @@ render_operation_f(struct graphics_state *gs, struct nspdf_render_ctx*
render_ct
gs->param_stack[gs->param_stack_idx].ctm,
render_ctx->ctx);
gs->path_idx = 0;
+
return NSPDFERROR_OK;
}
@@ -340,11 +408,13 @@ render_operation_S(struct graphics_state *gs, struct
nspdf_render_ctx* render_ct
{
struct nspdf_style style;
- style.stroke_type = NSPDF_OP_TYPE_SOLID;
- style.stroke_colour = 0;
- style.stroke_width = gs->param_stack[gs->param_stack_idx].line_width;
style.fill_type = NSPDF_OP_TYPE_NONE;
style.fill_colour = 0x01000000;
+
+ style.stroke_type = NSPDF_OP_TYPE_SOLID;
+ style.stroke_width = gs->param_stack[gs->param_stack_idx].line_width;
+ gsc_to_device(&gs->param_stack[gs->param_stack_idx].stroke.colour,
&style.stroke_colour);
+
render_ctx->path(&style,
gs->path,
gs->path_idx,
@@ -362,6 +432,34 @@ render_operation_w(struct content_operation *operation, struct
graphics_state *g
}
static inline nspdferror
+render_operation_i(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].flatness = operation->u.number[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_M(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].miter_limit = operation->u.number[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_j(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].line_join = operation->u.i[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_J(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].line_cap = operation->u.i[0];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
render_operation_q(struct graphics_state *gs)
{
gs->param_stack[gs->param_stack_idx + 1] =
gs->param_stack[gs->param_stack_idx];
@@ -378,47 +476,202 @@ render_operation_Q(struct graphics_state *gs)
return NSPDFERROR_OK;
}
+
+
/**
* pre-multiply matrix
*/
static inline nspdferror
render_operation_cm(struct content_operation *operation, struct graphics_state *gs)
{
- float M[6]; /* result matrix */
- /* M' = Mt * M */
- /* M' = Mo * Mc where Mo is operation and Mc is graphics state ctm */
- /* | a b c | | A B C | | aA+bP+cU aB+bQ+cV aC+bR+cW |
- * | p q r | * | P Q R | = | pA+qP+rU pB+qQ+rV pC+qR+rW |
- * | u v w | | U V W | | uA+vP+wU uB+vQ+wV uC+vR+wW |
- *
- * | o[0] o[1] 0 | | c[0] c[1] 0 | | o[0]*c[0]+o[1]*c[2] o[0]*c[1]+o[1]*c[3]
0 |
- * | o[2] o[3] 0 | * | c[2] c[3] 0 | = | o[2]*c[0]+o[3]*c[2] o[2]*c[1]+o[3]*c[3]
0 |
- * | o[4] o[5] 1 | | c[4] c[5] 1 | | o[4]*c[0]+o[5]*c[2]+c[4]
o[4]*c[1]+o[5]*c[3]+c[5] 1 |
+ /* Mres = Mop * Mctm
+ * where Mop is operation and Mctm is graphics state ctm
*/
- M[0] = operation->u.number[0] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[1] *
gs->param_stack[gs->param_stack_idx].ctm[2];
- M[1] = operation->u.number[0] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[1] *
gs->param_stack[gs->param_stack_idx].ctm[3];
- M[2] = operation->u.number[2] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[3] *
gs->param_stack[gs->param_stack_idx].ctm[2];
- M[3] = operation->u.number[2] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[3] *
gs->param_stack[gs->param_stack_idx].ctm[3];
- M[4] = operation->u.number[4] * gs->param_stack[gs->param_stack_idx].ctm[0]
+
- operation->u.number[5] * gs->param_stack[gs->param_stack_idx].ctm[2]
+
- gs->param_stack[gs->param_stack_idx].ctm[4];
- M[5] = operation->u.number[4] * gs->param_stack[gs->param_stack_idx].ctm[1]
+
- operation->u.number[5] * gs->param_stack[gs->param_stack_idx].ctm[3]
+
- gs->param_stack[gs->param_stack_idx].ctm[5];
-
- gs->param_stack[gs->param_stack_idx].ctm[0] = M[0];
- gs->param_stack[gs->param_stack_idx].ctm[1] = M[1];
- gs->param_stack[gs->param_stack_idx].ctm[2] = M[2];
- gs->param_stack[gs->param_stack_idx].ctm[3] = M[3];
- gs->param_stack[gs->param_stack_idx].ctm[4] = M[4];
- gs->param_stack[gs->param_stack_idx].ctm[5] = M[5];
+ return pdf_matrix_multiply(operation->u.number,
+ gs->param_stack[gs->param_stack_idx].ctm,
+ gs->param_stack[gs->param_stack_idx].ctm);
+}
+
+
+static inline nspdferror
+set_gsc_grey(struct graphics_state_color *gsc, float gray)
+{
+ /* bounds check */
+ if (gray < 0.0) {
+ gray = 0.0;
+ } else if (gray > 1.0) {
+ gray = 1.0;
+ }
+
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = gray;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_G(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_grey(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0]);
+}
+
+static inline nspdferror
+render_operation_g(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_grey(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0]);
+}
+
+static inline nspdferror
+set_gsc_rgb(struct graphics_state_color *gsc, float r, float g, float b)
+{
+ /* bounds check */
+ if (r < 0.0) {
+ r = 0.0;
+ } else if (r > 1.0) {
+ r = 1.0;
+ }
+ if (g < 0.0) {
+ g = 0.0;
+ } else if (g > 1.0) {
+ g = 1.0;
+ }
+ if (b < 0.0) {
+ b = 0.0;
+ } else if (b > 1.0) {
+ b = 1.0;
+ }
+
+ gsc->space = GSDeviceRGB;
+ gsc->u.rgb.r = r;
+ gsc->u.rgb.g = g;
+ gsc->u.rgb.b = b;
+
return NSPDFERROR_OK;
}
+static inline nspdferror
+render_operation_RG(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_rgb(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2]);
+}
+
+static inline nspdferror
+render_operation_rg(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_rgb(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2]);
+}
+
+static inline nspdferror
+set_gsc_cmyk(struct graphics_state_color *gsc, float c, float m, float y, float k)
+{
+ /* bounds check */
+ if (c < 0.0) {
+ c = 0.0;
+ } else if (c > 1.0) {
+ c = 1.0;
+ }
+ if (y < 0.0) {
+ y = 0.0;
+ } else if (y > 1.0) {
+ y = 1.0;
+ }
+ if (m < 0.0) {
+ m = 0.0;
+ } else if (m > 1.0) {
+ m = 1.0;
+ }
+ if (k < 0.0) {
+ k = 0.0;
+ } else if (k > 1.0) {
+ k = 1.0;
+ }
+
+ gsc->space = GSDeviceCMYK;
+ gsc->u.cmyk.c = c;
+ gsc->u.cmyk.m = m;
+ gsc->u.cmyk.y = y;
+ gsc->u.cmyk.k = k;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_K(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cmyk(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2],
+ operation->u.number[3]);
+}
+
+static inline nspdferror
+render_operation_k(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cmyk(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.number[0],
+ operation->u.number[1],
+ operation->u.number[2],
+ operation->u.number[3]);
+}
+
+static inline nspdferror
+set_gsc_cs(struct graphics_state_color *gsc, const char *spacename)
+{
+ if (strcmp(spacename, "DeviceGray") == 0) {
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = 0.0;
+ } else if (strcmp(spacename, "DeviceRGB") == 0) {
+ gsc->space = GSDeviceRGB;
+ gsc->u.rgb.r = 0.0;
+ gsc->u.rgb.g = 0.0;
+ gsc->u.rgb.b = 0.0;
+ } else if (strcmp(spacename, "DeviceCMYK") == 0) {
+ gsc->space = GSDeviceCMYK;
+ gsc->u.cmyk.c = 0.0;
+ gsc->u.cmyk.m = 0.0;
+ gsc->u.cmyk.y = 0.0;
+ gsc->u.cmyk.k = 1.0;
+ } else {
+ /** \todo colourspace from name defined in the ColorSpace subdictionary of the
current resource dictionary */
+ gsc->space = GSDeviceGray;
+ gsc->u.gray = 0.0;
+
+ }
+ //printf("cs %s %d\n", spacename, gsc->space);
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_CS(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cs(&gs->param_stack[gs->param_stack_idx].stroke.colour,
+ operation->u.name);
+}
+
+static inline nspdferror
+render_operation_cs(struct content_operation *operation,
+ struct graphics_state *gs)
+{
+ return set_gsc_cs(&gs->param_stack[gs->param_stack_idx].other.colour,
+ operation->u.name);
+}
+
/**
* Initialise the parameter stack
*
@@ -486,6 +739,7 @@ nspdf_page_render(struct nspdf_doc *doc,
idx < page_content->length;
idx++, operation++) {
switch(operation->operator) {
+ /* path operations */
case CONTENT_OP_m: /* move */
res = render_operation_m(operation, &gs);
break;
@@ -524,9 +778,25 @@ nspdf_page_render(struct nspdf_doc *doc,
res = render_operation_S(&gs, render_ctx);
break;
- case CONTENT_OP_w:
+ /* graphics state operations */
+ case CONTENT_OP_w: /* line width */
res = render_operation_w(operation, &gs);
- //printf("line width:%f\n",
gs.param_stack[gs.param_stack_idx].line_width);
+ break;
+
+ case CONTENT_OP_i: /* flatness */
+ res = render_operation_i(operation, &gs);
+ break;
+
+ case CONTENT_OP_j: /* line join style */
+ res = render_operation_j(operation, &gs);
+ break;
+
+ case CONTENT_OP_J: /* line cap style */
+ res = render_operation_J(operation, &gs);
+ break;
+
+ case CONTENT_OP_M: /* miter limit */
+ res = render_operation_M(operation, &gs);
break;
case CONTENT_OP_q: /* push parameter stack */
@@ -541,6 +811,44 @@ nspdf_page_render(struct nspdf_doc *doc,
res = render_operation_cm(operation, &gs);
break;
+ /* colour operators */
+ case CONTENT_OP_G: /* gray stroking colour */
+ res = render_operation_G(operation, &gs);
+ break;
+
+ case CONTENT_OP_g: /* gray non-stroking colour */
+ res = render_operation_g(operation, &gs);
+ break;
+
+ case CONTENT_OP_RG: /* rgb stroking colour */
+ res = render_operation_RG(operation, &gs);
+ break;
+
+ case CONTENT_OP_rg: /* rgb non-stroking colour */
+ res = render_operation_rg(operation, &gs);
+ break;
+
+ case CONTENT_OP_K: /* CMYK stroking colour */
+ res = render_operation_K(operation, &gs);
+ break;
+
+ case CONTENT_OP_k: /* CMYK non-stroking colour */
+ res = render_operation_k(operation, &gs);
+ break;
+
+ case CONTENT_OP_CS: /* change stroking colourspace */
+ res = render_operation_CS(operation, &gs);
+ break;
+
+ case CONTENT_OP_cs: /* change non-stroking colourspace */
+ res = render_operation_cs(operation, &gs);
+ break;
+
+ //case CONTENT_OP_SC:
+ //case CONTENT_OP_sc:
+ //case CONTENT_OP_SCN:
+ //case CONTENT_OP_scn:
+
default:
printf("operator %s\n",
nspdf__cos_content_operator_name(operation->operator));
--
PDF Manipulation Library