@@ -31,7 +31,7 @@ rl_newline: [CRLF | LF | CR]
31
31
ch_number: #[bitset! #{ 000000000000FFC0 } ] ;charset "0123456789"
32
32
ch_delimiter: #[bitset! #{ 0000000004C1000A0000001400000014 } ] ;charset "()<>[]{}/%"
33
33
ch_str-valid: #[bitset! [not bits #{ 00EC000000C0000000000008 } ]] ;complement charset "^/^M^-^H^L()\"
34
- sp: #[bitset! #{ 0040000080 } ] ;charset " ^-"
34
+ ch_sp: #[bitset! #{ 0040000080 } ] ;charset " ^-"
35
35
ch_newline: #[bitset! #{ 0024 } ] ;charset CRLF
36
36
ch_spnl: #[bitset! #{ 0064000080 } ] ;charset " ^-^/^L^M"
37
37
ch_hex: #[bitset! #{ 000000000000FFC07FFFFFE07FFFFFE0 } ] ;charset [#"0" - #"9" #"a" - #"z" #"A" - #"Z"]
@@ -122,12 +122,12 @@ rl_string: [
122
122
(value: to string! value)
123
123
]
124
124
rl_ref-id: [
125
- copy n1 some ch_number some sp
125
+ copy n1 some ch_number some ch_sp
126
126
copy n2 some ch_number
127
127
(ref-id: as-pair n1: load n1 n2: load n2) ; ?? ref-id)
128
128
]
129
129
rl_reference: [
130
- rl_ref-id some sp #"R" (value: ref-id)
130
+ rl_ref-id some ch_sp #"R" (value: ref-id)
131
131
]
132
132
133
133
*stack: copy []
@@ -201,7 +201,7 @@ rl_array: [
201
201
202
202
rl_obj: [
203
203
rl_ref-id (obj-id: ref-id );? obj-id)
204
- some sp
204
+ some ch_sp
205
205
"obj"
206
206
any ch_spnl
207
207
rl_value
@@ -266,7 +266,7 @@ rl_import-object: [
266
266
]
267
267
268
268
rl_pdf: [
269
- "%PDF-" copy value some ch_not-newline rl_newline
269
+ "%PDF-" copy value [ some ch_number #"." some ch_number] any ch_sp rl_newline
270
270
(pdf/version: to string! value)
271
271
any ch_spnl
272
272
opt rl_comment
@@ -399,8 +399,10 @@ emit-val: func[val][
399
399
emit-obj : func [ obj] [
400
400
out: insert out "<<"
401
401
foreach [key val] obj [
402
- out: insert insert out "/" form key
403
- emit-val val
402
+ unless none? val [
403
+ out: insert insert out "/" form key
404
+ emit-val val
405
+ ]
404
406
]
405
407
out: insert out ">>"
406
408
]
@@ -417,8 +419,14 @@ get-xref-count: function[xrefs n][
417
419
to integer! n
418
420
]
419
421
420
- emit-stream : func [ obj] [
421
- unless obj/spec/Filter [
422
+ emit-stream : func [ obj [object! ]] [
423
+ unless find obj 'spec [
424
+ extend obj 'spec # (Length: 0 )
425
+ ]
426
+ unless any [
427
+ obj/spec/Filter
428
+ 300 > length? obj/data ; don't use compression on tiny strings
429
+ ][
422
430
obj/spec/Filter: 'FlateDecode
423
431
obj/data: compress /zlib obj/data
424
432
]
@@ -427,6 +435,8 @@ emit-stream: func[obj][
427
435
out: insert insert insert out "stream^M^/ " obj/data "^M^/ endstream"
428
436
]
429
437
438
+ rebol-version-str: rejoin ["Rebol/" system/product " Version " system/version ]
439
+
430
440
431
441
remove-metadata : function [ pdf [object! ]] [
432
442
if all [
@@ -598,39 +608,82 @@ register-codec [
598
608
system/options/log/pdf > 0
599
609
map? info: try [pdf/objects/ (pdf/trailer/info )]
600
610
][
601
- sys/log/info 'PDF ["Author: ^[ [m" info/Author ]
602
- sys/log/info 'PDF ["Title: ^[ [m" info/Title ]
603
- sys/log/info 'PDF ["Created: ^[ [m" info/CreationDate ]
604
- sys/log/info 'PDF ["Modified:^[ [m" info/ModDate ]
605
- sys/log/info 'PDF ["Producer:^[ [m" info/Producer ]
606
- sys/log/info 'PDF ["Creator: ^[ [m" info/Creator ]
611
+ if info /Author [ sys/log/info 'PDF ["Author: ^[ [m" info/Author ] ]
612
+ if info /Title [ sys/log/info 'PDF ["Title: ^[ [m" info/Title ] ]
613
+ if info /CreationDate [ sys/log/info 'PDF ["Created: ^[ [m" info/CreationDate ] ]
614
+ if info /ModDate [ sys/log/info 'PDF ["Modified:^[ [m" info/ModDate ] ]
615
+ if info /Producer [ sys/log/info 'PDF ["Producer:^[ [m" info/Producer ] ]
616
+ if info /Creator [ sys/log/info 'PDF ["Creator: ^[ [m" info/Creator ] ]
607
617
]
608
618
also pdf pdf: none ; return result and release the internal value
609
619
]
610
620
encode : func [
611
621
pdf [object! ]
612
- /local xref xref-pos i n last-obj-id
622
+ /local xref xref-pos i n last-obj-id version trailer objects info root
613
623
] [
614
624
;@@ TODO!
615
625
;-- This is just very simple encoder with not linearized output!
616
626
;-- It does no input validity checks so user is responsible to provide
617
627
;-- well formated pdf input object.
618
628
629
+ ;- validate minimal requirements...
630
+ objects: select pdf 'objects
631
+ unless any [map? objects block? objects][
632
+ sys/log/error 'PDF "Missing valid objects list!"
633
+ return none
634
+ ]
635
+ trailer: select pdf 'trailer
636
+ unless trailer [
637
+ extend pdf 'trailer trailer: # (Info: #[none] Root: #[none])
638
+ ]
639
+ unless root: trailer/Root [
640
+ sys/log/debug 'PDF "Trying to locate `Catalog` in PDF objects."
641
+ foreach [ref obj] pdf/objects [
642
+ if all [map? obj obj/Type = 'Catalog][
643
+ trailer/Root: ref
644
+ break
645
+ ]
646
+ ]
647
+ ]
648
+ unless root: trailer/Root [
649
+ sys/log/error 'PDF "Missing required `Catalog` object!"
650
+ return none
651
+ ]
652
+ if info: pick pdf/objects trailer/Info [
653
+ unless info/CreationDate [info/CreationDate: now]
654
+ if any [not info/Creator info/Creator = "Rebol" ] [ info/Creator: rebol-version-str ]
655
+ if any [not info/Producer info/Producer = "Rebol" ] [ info/Producer: rebol-version-str ]
656
+
657
+
658
+ info/ModDate: now
659
+ ]
660
+
661
+ unless version: select pdf 'version [ version: @1.3 ]
662
+ if decimal? version [version: form version]
663
+ unless parse version [some ch_number #"." some ch_number end][
664
+ sys/log/error 'PDF ["Invalid PDF version:" mold version]
665
+ return none
666
+ ]
667
+
668
+ ;- File header..
619
669
out: make binary! any [select pdf 'file-size 60000 ]
620
- out: insert out ajoin ["%PDF-" pdf/version "^M %" ]
621
- out: insert out #{ E2E3CFD3 }
622
- out: insert out "^M^/ "
670
+ out: insert out ajoin ["%PDF-" version "^M %" ]
671
+ out: insert out #{ E2E3CFD30D0A } ;= %âãÏÓ
623
672
xref: copy []
673
+
674
+
675
+ ;- File body
624
676
foreach [ref obj] pdf/objects [
625
677
append xref reduce [ref -1 + index? out]
626
678
out: insert insert out form-ref ref " obj^M "
627
679
emit-val obj
628
680
629
681
out: insert out "^M endobj^M "
630
682
]
683
+
684
+ ;- Cross-Reference Table
631
685
xref-pos: out
632
686
sort/skip xref 2
633
- ;? xref
634
687
i: 0
635
688
n: get-xref-count xref i
636
689
out: insert out ajoin [
@@ -656,8 +709,9 @@ register-codec [
656
709
++ i
657
710
]
658
711
]
712
+ ;- File Trailer
659
713
out: insert out "trailer^M^/ "
660
- emit-val pdf / trailer
714
+ emit-val trailer
661
715
out: insert out ajoin ["^M^/ startxref^M^/ " -1 + index? xref-pos "^M^/ %%EOF^M^/ " ]
662
716
663
717
head out
0 commit comments