summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2018-01-31 00:03:38 +0000
committerVincent Sanders <vince@kyllikki.org>2018-01-31 00:03:38 +0000
commit1ca90f384d4f2311cbf0abd44d8e4e5b7a4abb37 (patch)
tree35a931f40ed6ca1a1e2420ab1f63230f05349ca1 /src
parent6b16f2446bb381be3de54d9edfe9088a8363df70 (diff)
downloadlibnspdf-1ca90f384d4f2311cbf0abd44d8e4e5b7a4abb37.tar.gz
libnspdf-1ca90f384d4f2311cbf0abd44d8e4e5b7a4abb37.tar.bz2
start actual page rendering
Diffstat (limited to 'src')
-rw-r--r--src/cos_content.c35
-rw-r--r--src/cos_content.h17
-rw-r--r--src/cos_object.c1
-rw-r--r--src/cos_object.h11
-rw-r--r--src/page.c238
5 files changed, 273 insertions, 29 deletions
diff --git a/src/cos_content.c b/src/cos_content.c
index cf5d2e0..0e14f85 100644
--- a/src/cos_content.c
+++ b/src/cos_content.c
@@ -20,7 +20,8 @@
#include "cos_content.h"
#include "pdf_doc.h"
-static const char*operator_name(enum content_operator operator)
+const char*
+nspdf__cos_content_operator_name(enum content_operator operator)
{
switch(operator) {
case CONTENT_OP_b: return "b";
@@ -135,14 +136,14 @@ copy_numbers(unsigned int wanted,
}
if ((*operand_idx) > index) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), wanted, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), wanted, *operand_idx);
while (index < (*operand_idx)) {
cos_free_object(*(operands + index));
index++;
}
} else if ((*operand_idx) < index) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), wanted, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), wanted, *operand_idx);
}
*operand_idx = 0; /* all operands freed */
@@ -174,14 +175,14 @@ copy_integers(unsigned int wanted,
}
if ((*operand_idx) > index) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), wanted, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), wanted, *operand_idx);
while (index < (*operand_idx)) {
cos_free_object(*(operands + index));
index++;
}
} else if ((*operand_idx) < index) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), wanted, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), wanted, *operand_idx);
}
*operand_idx = 0; /* all operands freed */
@@ -200,7 +201,7 @@ copy_string(struct cos_object **operands,
if ((*operand_idx) == 0) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
operation_out->u.string.length = 0;
return NSPDFERROR_OK;
}
@@ -232,7 +233,7 @@ copy_string(struct cos_object **operands,
if ((*operand_idx) > 1) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
}
/* free all operands */
@@ -254,7 +255,7 @@ copy_array(struct cos_object **operands,
if ((*operand_idx) == 0) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
operation_out->u.array.length = 0;
return NSPDFERROR_OK;
}
@@ -273,7 +274,7 @@ copy_array(struct cos_object **operands,
if ((*operand_idx) > 1) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
}
/* free all operands */
@@ -296,7 +297,7 @@ copy_name(struct cos_object **operands,
if ((*operand_idx) == 0) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
operation_out->u.name = NULL;
return NSPDFERROR_OK;
}
@@ -313,7 +314,7 @@ copy_name(struct cos_object **operands,
if ((*operand_idx) > 1) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 1, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 1, *operand_idx);
}
/* free all operands */
@@ -335,7 +336,7 @@ copy_name_number(struct cos_object **operands,
if ((*operand_idx) == 0) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
operation_out->u.namenumber.name = NULL;
return NSPDFERROR_OK;
}
@@ -361,13 +362,13 @@ copy_name_number(struct cos_object **operands,
}
} else {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
}
}
if ((*operand_idx) > 2) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
}
/* free all operands */
@@ -390,7 +391,7 @@ copy_array_int(struct cos_object **operands,
if ((*operand_idx) == 0) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
operation_out->u.namenumber.name = NULL;
return NSPDFERROR_OK;
}
@@ -418,13 +419,13 @@ copy_array_int(struct cos_object **operands,
}
} else {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
}
}
if ((*operand_idx) > 2) {
printf("operator %s that takes %d operands passed %d\n",
- operator_name(operation_out->operator), 2, *operand_idx);
+ nspdf__cos_content_operator_name(operation_out->operator), 2, *operand_idx);
}
/* free all operands */
diff --git a/src/cos_content.h b/src/cos_content.h
index e0d2dfb..09700c2 100644
--- a/src/cos_content.h
+++ b/src/cos_content.h
@@ -193,9 +193,9 @@ enum content_operator {
#define content_string_intrnl_lngth ((sizeof(float) * content_number_size) - sizeof(uint8_t *))
-struct content_operation
-{
+struct content_operation {
enum content_operator operator;
+
union {
float number[content_number_size];
@@ -231,6 +231,19 @@ struct content_operation
};
/**
+ * Synthetic parsed content object.
+ */
+struct cos_content {
+ unsigned int length; /**< number of content operations */
+ unsigned int alloc; /**< number of allocated operations */
+ struct content_operation *operations;
+};
+
+
+const char* nspdf__cos_content_operator_name(enum content_operator operator);
+
+
+/**
* convert an operator and operand list into an operation
*/
nspdferror nspdf__cos_content_convert(enum content_operator operator, struct cos_object **operands, unsigned int *operand_idx, struct content_operation *operation_out);
diff --git a/src/cos_object.c b/src/cos_object.c
index 5d7da19..52731ca 100644
--- a/src/cos_object.c
+++ b/src/cos_object.c
@@ -17,6 +17,7 @@
#include <nspdf/errors.h>
#include "xref.h"
+#include "cos_content.h"
#include "cos_object.h"
#include "cos_parse.h"
#include "pdf_doc.h"
diff --git a/src/cos_object.h b/src/cos_object.h
index 79a1c8d..632126e 100644
--- a/src/cos_object.h
+++ b/src/cos_object.h
@@ -19,6 +19,7 @@
struct nspdf_doc;
struct content_operation;
+struct cos_content;
enum cos_type {
COS_TYPE_NULL, /* 0 */
@@ -78,16 +79,6 @@ struct cos_reference {
};
-/**
- * Synthetic parsed content object.
- *
- */
-struct cos_content {
- unsigned int length; /**< number of content operations */
- unsigned int alloc; /**< number of allocated operations */
- struct content_operation *operations;
-};
-
struct cos_object {
enum cos_type type;
union {
diff --git a/src/page.c b/src/page.c
index 5b91416..e4bbae4 100644
--- a/src/page.c
+++ b/src/page.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <nspdf/page.h>
+#include "cos_content.h"
#include "cos_object.h"
#include "pdf_doc.h"
@@ -146,6 +147,170 @@ 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)
+{
+ gs->path[gs->path_idx++] = NSPDF_PATH_MOVE;
+ gs->path[gs->path_idx++] = operation->u.number[0];
+ gs->path[gs->path_idx++] = operation->u.number[1];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_l(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->path[gs->path_idx++] = NSPDF_PATH_LINE;
+ gs->path[gs->path_idx++] = operation->u.number[0];
+ gs->path[gs->path_idx++] = operation->u.number[1];
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_re(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->path[gs->path_idx++] = NSPDF_PATH_MOVE;
+ gs->path[gs->path_idx++] = operation->u.number[0]; /* x */
+ gs->path[gs->path_idx++] = operation->u.number[1]; /* y */
+ gs->path[gs->path_idx++] = NSPDF_PATH_LINE;
+ gs->path[gs->path_idx++] = operation->u.number[0] + operation->u.number[2];
+ gs->path[gs->path_idx++] = operation->u.number[1];
+ gs->path[gs->path_idx++] = NSPDF_PATH_LINE;
+ gs->path[gs->path_idx++] = operation->u.number[0] + operation->u.number[2];
+ gs->path[gs->path_idx++] = operation->u.number[1] + operation->u.number[3];
+ gs->path[gs->path_idx++] = NSPDF_PATH_LINE;
+ gs->path[gs->path_idx++] = operation->u.number[0];
+ gs->path[gs->path_idx++] = operation->u.number[1] + operation->u.number[3];
+ gs->path[gs->path_idx++] = NSPDF_PATH_CLOSE;
+
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_h(struct graphics_state *gs)
+{
+ gs->path[gs->path_idx++] = NSPDF_PATH_CLOSE;
+ 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;
+
+ render_ctx->path(&style,
+ gs->path,
+ gs->path_idx,
+ gs->param_stack[gs->param_stack_idx].ctm,
+ render_ctx->ctx);
+ gs->path_idx = 0;
+ return NSPDFERROR_OK;
+}
+
+
+static inline nspdferror
+render_operation_S(struct graphics_state *gs, struct nspdf_render_ctx* render_ctx)
+{
+ 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;
+ render_ctx->path(&style,
+ gs->path,
+ gs->path_idx,
+ gs->param_stack[gs->param_stack_idx].ctm,
+ render_ctx->ctx);
+ gs->path_idx = 0;
+ return NSPDFERROR_OK;
+}
+
+static inline nspdferror
+render_operation_w(struct content_operation *operation, struct graphics_state *gs)
+{
+ gs->param_stack[gs->param_stack_idx].line_width = operation->u.number[0];
+ return NSPDFERROR_OK;
+}
+
+/**
+ * Initialise the parameter stack
+ *
+ * allocates the initial parameter stack and initialises the defaults
+ */
+static nspdferror
+init_param_stack(struct graphics_state *gs, struct nspdf_render_ctx* render_ctx)
+{
+ gs->param_stack_alloc = 16; /* start with 16 deep parameter stack */
+ gs->param_stack_idx = 0;
+ gs->param_stack = calloc(gs->param_stack_alloc,
+ sizeof(struct graphics_state_param));
+ if (gs->param_stack == NULL) {
+ return NSPDFERROR_NOMEM;
+ }
+
+ gs->param_stack[0].ctm[0] = render_ctx->device_space[0];
+ gs->param_stack[0].ctm[1] = render_ctx->device_space[1];
+ gs->param_stack[0].ctm[2] = render_ctx->device_space[2];
+ gs->param_stack[0].ctm[3] = render_ctx->device_space[3];
+ gs->param_stack[0].ctm[4] = render_ctx->device_space[4];
+ gs->param_stack[0].ctm[5] = render_ctx->device_space[5];
+ gs->param_stack[0].line_width = 1.0;
+
+ return NSPDFERROR_OK;
+}
/* exported interface documented in nspdf/page.h */
nspdferror
@@ -156,6 +321,10 @@ nspdf_page_render(struct nspdf_doc *doc,
struct page_table_entry *page_entry;
struct cos_content *page_content; /* page operations array */
nspdferror res;
+ struct content_operation *operation;
+ unsigned int idx;
+
+ struct graphics_state gs;
page_entry = doc->page_table + page_number;
@@ -166,5 +335,74 @@ nspdf_page_render(struct nspdf_doc *doc,
printf("page %d content:%p\n", page_number, page_content);
+ gs.path_idx = 0;
+ gs.path_alloc = 8192;
+ gs.path = malloc(gs.path_alloc * sizeof(float));
+ if (gs.path == NULL) {
+ return NSPDFERROR_NOMEM;
+ }
+
+ res = init_param_stack(&gs, render_ctx);
+ if (res != NSPDFERROR_OK) {
+ free(gs.path);
+ return res;
+ }
+
+ /* iterate over operations */
+ for (idx = 0, operation = page_content->operations;
+ idx < page_content->length;
+ idx++, operation++) {
+ switch(operation->operator) {
+ case CONTENT_OP_m: /* move */
+ res = render_operation_m(operation, &gs);
+ break;
+
+ case CONTENT_OP_l: /* line */
+ res = render_operation_l(operation, &gs);
+ break;
+
+ case CONTENT_OP_re: /* rectangle */
+ res = render_operation_re(operation, &gs);
+ break;
+
+ case CONTENT_OP_h: /* close path */
+ res = render_operation_h(&gs);
+ break;
+
+ case CONTENT_OP_f:
+ case CONTENT_OP_f_:
+ case CONTENT_OP_B:
+ case CONTENT_OP_B_:
+ case CONTENT_OP_b:
+ case CONTENT_OP_b_:
+ res = render_operation_f(&gs, render_ctx);
+ break;
+
+ case CONTENT_OP_s:
+ render_operation_h(&gs);
+ res = render_operation_S(&gs, render_ctx);
+ break;
+
+ case CONTENT_OP_S:
+ res = render_operation_S(&gs, render_ctx);
+ break;
+
+ case CONTENT_OP_w:
+ res = render_operation_w(operation, &gs);
+ //printf("line width:%f\n", gs.param_stack[gs.param_stack_idx].line_width);
+ break;
+
+ default:
+ printf("operator %s\n",
+ nspdf__cos_content_operator_name(operation->operator));
+ break;
+
+ }
+
+ }
+
+ free(gs.param_stack);
+ free(gs.path);
+
return res;
}