summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2018-02-04 23:49:28 +0000
committerVincent Sanders <vince@kyllikki.org>2018-02-04 23:49:28 +0000
commit4a18ec928fa6e6e2231fcef76e91eb1a4d57f588 (patch)
tree6dcf59d845f5d1447e7fe091f52791113cfa0031
parenteeb93199c64db0c47dc73bb1b5a3c7d16d8172e2 (diff)
downloadlibnspdf-4a18ec928fa6e6e2231fcef76e91eb1a4d57f588.tar.gz
libnspdf-4a18ec928fa6e6e2231fcef76e91eb1a4d57f588.tar.bz2
implement CTM matrix transform
-rw-r--r--src/page.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/page.c b/src/page.c
index 0d12fc2..5156430 100644
--- a/src/page.c
+++ b/src/page.c
@@ -348,6 +348,64 @@ render_operation_w(struct content_operation *operation, struct graphics_state *g
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];
+ gs->param_stack_idx++;
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_Q(struct graphics_state *gs)
+{
+ if (gs->param_stack_idx > 0) {
+ gs->param_stack_idx--;
+ }
+ 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 |
+ */
+ 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;
+}
+
/**
* Initialise the parameter stack
*
@@ -454,6 +512,18 @@ nspdf_page_render(struct nspdf_doc *doc,
//printf("line width:%f\n", gs.param_stack[gs.param_stack_idx].line_width);
break;
+ case CONTENT_OP_q: /* push parameter stack */
+ res = render_operation_q(&gs);
+ break;
+
+ case CONTENT_OP_Q: /* pop parameter stack */
+ res = render_operation_Q(&gs);
+ break;
+
+ case CONTENT_OP_cm: /* change matrix */
+ res = render_operation_cm(operation, &gs);
+ break;
+
default:
printf("operator %s\n",
nspdf__cos_content_operator_name(operation->operator));