Skip to content

Commit c81235e

Browse files
committed
Implement more content op deserialization
1 parent 7ce4d26 commit c81235e

9 files changed

Lines changed: 150 additions & 6 deletions

File tree

examples/pdf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ int main(int argc, char** argv) {
6262

6363
size_t buffer_size;
6464
char* buffer =
65-
load_file_to_buffer(arena, "test-files/test.pdf", &buffer_size);
65+
load_file_to_buffer(arena, "test-files/embedded.pdf", &buffer_size);
6666

6767
PdfResolver* resolver;
6868
PDF_REQUIRE(

libs/pdf/include/pdf/content_op.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@
44
#include "pdf/types.h"
55

66
typedef enum {
7+
PDF_CONTENT_OP_SET_CTM, // cm
78
PDF_CONTENT_OP_BEGIN_TEXT, // BT
89
PDF_CONTENT_OP_END_TEXT, // ET
910
PDF_CONTENT_OP_SET_FONT, // Tf
1011
PDF_CONTENT_OP_NEXT_LINE, // Td
11-
PDF_CONTENT_OP_SHOW_TEXT // Tj
12+
PDF_CONTENT_OP_SET_TM, // Tm
13+
PDF_CONTENT_OP_SHOW_TEXT, // Tj
14+
PDF_CONTENT_OP_SET_GRAY // G, g
1215
} PdfContentOpKind;
1316

17+
/// Used by PDF_CONTENT_OP_SET_CTM, PDF_CONTENT_OP_SET_TM
18+
typedef struct {
19+
PdfNumber a;
20+
PdfNumber b;
21+
PdfNumber c;
22+
PdfNumber d;
23+
PdfNumber e;
24+
PdfNumber f;
25+
} PdfContentOpSetMatrix;
26+
1427
typedef struct {
1528
PdfName font;
1629
PdfNumber size;
@@ -25,13 +38,20 @@ typedef struct {
2538
PdfString text;
2639
} PdfContentOpShowText;
2740

41+
typedef struct {
42+
bool stroking;
43+
PdfNumber gray;
44+
} PdfContentOpSetGray;
45+
2846
typedef struct {
2947
PdfContentOpKind kind;
3048

3149
union {
50+
PdfContentOpSetMatrix set_matrix;
3251
PdfContentOpSetFont set_font;
3352
PdfContentOpNextLine next_line;
3453
PdfContentOpShowText show_text;
54+
PdfContentOpSetGray set_gray;
3555
} data;
3656
} PdfContentOp;
3757

libs/pdf/include/pdf/page.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef struct {
3434
PdfOpResources resources;
3535
PdfRectangle media_box;
3636
PdfOpContentsArray contents;
37+
PdfOpInteger rotate;
3738

3839
const PdfObject* raw_dict;
3940
} PdfPage;

libs/pdf/src/content_stream/op.c

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,65 @@
1313
#define DVEC_TYPE PdfContentOp
1414
#include "arena/dvec_impl.h"
1515

16-
PdfContentOp*
16+
static PdfContentOp*
1717
new_queue_op(PdfContentOpVec* operation_queue, PdfContentOpKind op) {
1818
return pdf_content_op_vec_push(
1919
operation_queue,
2020
(PdfContentOp) {.kind = op}
2121
);
2222
}
2323

24-
PdfError* pdf_deserialize_set_font_op(
24+
static PdfError* pdf_deserialize_set_matrix_op(
25+
const PdfObjectVec* operands,
26+
Arena* arena,
27+
PdfContentOpSetMatrix* deserialized
28+
) {
29+
RELEASE_ASSERT(operands);
30+
RELEASE_ASSERT(arena);
31+
RELEASE_ASSERT(deserialized);
32+
33+
PdfOperandDescriptor descriptors[] = {
34+
PDF_OPERAND(
35+
PdfContentOpSetMatrix,
36+
a,
37+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
38+
),
39+
PDF_OPERAND(
40+
PdfContentOpSetMatrix,
41+
b,
42+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
43+
),
44+
PDF_OPERAND(
45+
PdfContentOpSetMatrix,
46+
c,
47+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
48+
),
49+
PDF_OPERAND(
50+
PdfContentOpSetMatrix,
51+
d,
52+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
53+
),
54+
PDF_OPERAND(
55+
PdfContentOpSetMatrix,
56+
e,
57+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
58+
),
59+
PDF_OPERAND(
60+
PdfContentOpSetMatrix,
61+
f,
62+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
63+
)
64+
};
65+
return pdf_deserialize_operands(
66+
deserialized,
67+
descriptors,
68+
sizeof(descriptors) / sizeof(PdfOperandDescriptor),
69+
operands,
70+
arena
71+
);
72+
}
73+
74+
static PdfError* pdf_deserialize_set_font_op(
2575
const PdfObjectVec* operands,
2676
Arena* arena,
2777
PdfContentOpSetFont* deserialized
@@ -51,7 +101,7 @@ PdfError* pdf_deserialize_set_font_op(
51101
);
52102
}
53103

54-
PdfError* pdf_deserialize_next_line_op(
104+
static PdfError* pdf_deserialize_next_line_op(
55105
const PdfObjectVec* operands,
56106
Arena* arena,
57107
PdfContentOpNextLine* deserialized
@@ -81,7 +131,7 @@ PdfError* pdf_deserialize_next_line_op(
81131
);
82132
}
83133

84-
PdfError* pdf_deserialize_show_text_op(
134+
static PdfError* pdf_deserialize_show_text_op(
85135
const PdfObjectVec* operands,
86136
Arena* arena,
87137
PdfContentOpShowText* deserialized
@@ -104,6 +154,29 @@ PdfError* pdf_deserialize_show_text_op(
104154
);
105155
}
106156

157+
static PdfError* pdf_deserialize_set_gray_op(
158+
const PdfObjectVec* operands,
159+
Arena* arena,
160+
PdfContentOpSetGray* deserialized
161+
) {
162+
RELEASE_ASSERT(operands);
163+
RELEASE_ASSERT(arena);
164+
RELEASE_ASSERT(deserialized);
165+
166+
PdfOperandDescriptor descriptors[] = {PDF_OPERAND(
167+
PdfContentOpSetGray,
168+
gray,
169+
PDF_CUSTOM_FIELD(pdf_deserialize_number_wrapper)
170+
)};
171+
return pdf_deserialize_operands(
172+
deserialized,
173+
descriptors,
174+
sizeof(descriptors) / sizeof(PdfOperandDescriptor),
175+
operands,
176+
arena
177+
);
178+
}
179+
107180
PdfError* pdf_deserialize_content_op(
108181
PdfOperator op,
109182
const PdfObjectVec* operands,
@@ -115,6 +188,15 @@ PdfError* pdf_deserialize_content_op(
115188
RELEASE_ASSERT(operation_queue);
116189

117190
switch (op) {
191+
case PDF_OPERATOR_cm: {
192+
PdfContentOp* new_op =
193+
new_queue_op(operation_queue, PDF_CONTENT_OP_SET_CTM);
194+
return pdf_deserialize_set_matrix_op(
195+
operands,
196+
arena,
197+
&new_op->data.set_matrix
198+
);
199+
}
118200
case PDF_OPERATOR_BT: {
119201
new_queue_op(operation_queue, PDF_CONTENT_OP_BEGIN_TEXT);
120202
return NULL;
@@ -141,6 +223,15 @@ PdfError* pdf_deserialize_content_op(
141223
&new_op->data.next_line
142224
);
143225
}
226+
case PDF_OPERATOR_Tm: {
227+
PdfContentOp* new_op =
228+
new_queue_op(operation_queue, PDF_CONTENT_OP_SET_TM);
229+
return pdf_deserialize_set_matrix_op(
230+
operands,
231+
arena,
232+
&new_op->data.set_matrix
233+
);
234+
}
144235
case PDF_OPERATOR_Tj: {
145236
PdfContentOp* new_op =
146237
new_queue_op(operation_queue, PDF_CONTENT_OP_SHOW_TEXT);
@@ -150,6 +241,16 @@ PdfError* pdf_deserialize_content_op(
150241
&new_op->data.show_text
151242
);
152243
}
244+
case PDF_OPERATOR_g: {
245+
PdfContentOp* new_op =
246+
new_queue_op(operation_queue, PDF_CONTENT_OP_SET_GRAY);
247+
new_op->data.set_gray.stroking = false;
248+
return pdf_deserialize_set_gray_op(
249+
operands,
250+
arena,
251+
&new_op->data.set_gray
252+
);
253+
}
153254
default: {
154255
LOG_TODO("Unimplemented content stream operation: %d", op);
155256
}

libs/pdf/src/page.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ PdfError* pdf_deserialize_page(
113113
PDF_OBJECT_FIELD(PDF_OBJECT_TYPE_STREAM)
114114
)
115115
)
116+
),
117+
PDF_FIELD(
118+
PdfPage,
119+
"Rotate",
120+
rotate,
121+
PDF_OPTIONAL_FIELD(
122+
PdfOpInteger,
123+
PDF_OBJECT_FIELD(PDF_OBJECT_TYPE_INTEGER)
124+
)
116125
)
117126
};
118127

scripts/check-lite.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
scripts/format.sh
6+
scripts/clean.sh
7+
scripts/gcc-build.sh
8+
scripts/clean.sh
9+
scripts/test.sh
10+
scripts/tidy.sh
11+
12+
pre-commit run --all-files

test-files/clean-test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
mutool clean test-files/test.pdf test-files/test.pdf
44
mutool clean -z -a test-files/test.pdf test-files/compressed.pdf
5+
mutool convert -o test-files/embedded.pdf -O ascii test-files/test.pdf

test-files/compressed.pdf

0 Bytes
Binary file not shown.

test-files/embedded.pdf

101 KB
Binary file not shown.

0 commit comments

Comments
 (0)