summaryrefslogtreecommitdiff
path: root/gs/lib/writecff.ps
blob: ce4b5b59e6282a8cca2d415b0beb7e72a443312d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
%    Copyright (C) 1997 Aladdin Enterprises.  All rights reserved.
% 
% This file is part of Aladdin Ghostscript.
% 
% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
% or distributor accepts any responsibility for the consequences of using it,
% or for whether it serves any particular purpose or works at all, unless he
% or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
% License (the "License") for full details.
% 
% Every copy of Aladdin Ghostscript must include a copy of the License,
% normally in a plain ASCII text file named PUBLIC.  The License grants you
% the right to copy, modify and redistribute Aladdin Ghostscript, but only
% under certain conditions described in the License.  Among other things, the
% License requires that the copyright notice and this notice be preserved on
% all copies.

% $Id$
% writecff.ps
% Write out a Type 2 font as CFF.
% **************** THIS FILE DOES NOT WORK. ****************
% **************** DON'T TRY TO USE IT. ****************

currentglobal true setglobal
(gs_cff.ps) runlibfile
setglobal

50 dict begin

% ---------------- Standard strings/names ---------------- %

/FontSetInit /ProcSet findresource begin mark

/StandardSIDs StandardStrings length 1.5 mul cvi dict
dup 0 1 StandardStrings length 1 sub {
		% Stack: mark /StdSIDs dict dict index
  dup StandardStrings exch get exch put dup
} for pop

end counttomark 2 idiv { def } repeat pop

% ---------------- Standard encodings ---------------- %

% ---------------- Standard Charsets ---------------- %

% ---------------- Output utilities ---------------- %

% Free variables: f (output file), fpos (position in f).

/advance {		% <n> advance -
  fpos add /fpos exch store
} def
/next {			% <byte> next -
  f exch write 1 advance
} def
/nextstring {		% <string|name> nextstring -
  dup type /nametype eq { .namestring } if
  f 1 index writestring length advance
} def
/card8			% <card8> card8 -
  /next load
def
/card16 {		% <card16> card16 -
  dup -8 bitshift next 255 and next
} def
/offset {		% <offset> <offsize> offset -
  1 sub -1 0 { -8 mul 2 copy bitshift 255 and next pop } for pop
} def
/sid			% <sid> sid -
  /card16 load
def
/lenoffsize {		% <length> lenoffsize <offsize>
  dup 255 le { pop 1 } { -8 bitshift lenoffsize 1 add } ifelse
} def
/Index {		% [<string|name|null> ...] Index -
	% Calculate the maximum offset we need to be able to represent.
  1 1 index { dup null eq { pop } { length add } ifelse } forall lenoffsize
	% stack: items offsize
  1 index length card16
  dup next
  1 2 index {
  	% stack: items offsize pos item
    1 index 3 index offset
    dup null eq { pop } { length add } ifelse
  } forall exch offset { nextstring } forall
} def
/idIndex {		% <dict> <base> idIndex -
  1 index length array 3 -1 roll {
    3 index sub 2 index exch 3 -1 roll put
  } forall exch pop Index
} def
/stringid {		% <string|name> stringid <sid>
  StandardSIDs 1 index .knownget {
    exch pop
  } {
    sids 1 index .knownget {
      exch pop
    } {
      StandardSIDs length sids length add sids 3 -1 roll 2 index put
    } ifelse
  } ifelse
} def
/.valuetypedict mark
  /booleantype { { 1 } { 0 } ifelse intvalue }
  /arraytype { { value } forall }
  /packedarraytype 1 index
  /stringtype { stringid intvalue }
  /nametype 1 index
  /realtype { realvalue }
  /integertype { intvalue }
.dicttomark readonly def
/value {		% <obj> value -
  dup type .valuetypedict exch get exec
} def
/.realchardict mark
  48 1 57 { dup 48 sub } for	% digits
  46 10   69 11   101 11	% . E e
  45 {				% - -- handle E- specially
    dup 15 and 11 eq { 15 or 12 } {
      dup 16#bf eq { pop 255 12 } { 14 } ifelse
    } ifelse
  }
.dicttomark readonly def
/realvalue {		% <real> realvalue -
  =string cvs 255 exch {
    .realchardict exch get exec
    1 index 15 and 15 ne { exch next 255 exch } if
    1 index 240 and 240 eq { 4 bitshift 240 } { 15 } ifelse sub add
  } forall next
} def
/intvalue {		% <int> intvalue -
  dup dup -107 ge exch 107 le and { 139 add next } {
    dup dup -1131 ge exch 0 lt and { neg 16#fa94 add card16 } {
      dup dup 1131 le exch 0 ge and { 16#f694 add card16 } {
	dup dup -32768 ge exch 32767 le and {
	  28 next 65535 and card16
	} {
	  29 next dup -16 bitshift 2 { 65535 and card16 } repeat
	} ifelse
      } ifelse
    } ifelse
  } ifelse
} def
/op {			% <op> op -
  dup 32 ge { 12 next 32 sub } if next
} def
/vdef {			% <obj> <op> vdef -
  exch value op
} def
/nedef {		% <obj> <default> <op> nedef -
  exch 2 index eq { pop pop } { vdef } ifelse
} def
/Dict {			% <dict> <opsdict> Dict -
  exch {
	% stack: opsdict key value
    2 index 3 -1 roll .knownget {
      dup type /integertype eq { vdef } { exec } ifelse
    } {
      pop
    } ifelse
  } forall pop
} def
/collect {		% <proc> collect <string>
  10 dict begin
  /str 500 string def
  /spos 0 def
  /fpos 0 def
  /f {
    pop length spos add /spos exch store
    spos str length eq { /str str str concatstrings def } if
    str spos str length spos sub getinterval
  } /NullEncode filter def
  exec f closefile
  str 0 spos getinterval end
} def

% Write a forward reference in a Dict, and save its position.
/forward {		% <varname> <op> <offsize> forward -
  {null null <1c 00 00> <1d 00 00 00 00>} exch get nextstring
  exch fpos store op
} def

% ------ Top (font) dictionary ------ %

/topkeyops mark
  /version 0
  /Notice 1
  /Copyright 32
  /FullName 2
  /FamilyName 3
  /Weight 4
  /isFixedPatch { false 33 nedef }
  /ItalicAngle { 0 34 nedef }
  /UnderlinePosition { -100 35 nedef }
  /UnderlineThickness { 50 36 nedef }
  /PaintType { 0 37 nedef }
  /CharstringType { 2 38 nedef }
  /FontMatrix {
    true 0 1 5 {
      2 index 1 index get {0.001 0 0 0.001 0 0} 3 -1 roll get eq and
    } for
    { pop } { 39 vdef } ifelse
  }
  /UniqueID 13
  /FontBBox 5
  /StrokeWidth { 0 40 nedef }
  /XUID 14
  /FontInfo { topkeyops Dict }
	%**** charset, Encoding
  /CharStrings { pop /charstringsoffset 17 offsetsize forward }
  /Private { pop /privateoffset 18 offsetsize forward }
.dicttomark readonly def

% ------ Private dictionary ------ %

/deltarray {		% [<num> ...] <op> deltarray -
  exch 0 exch { 1 index sub dup value add } forall pop op
} def
/privatekeyops mark
  /BlueValues { 6 deltarray }
  /OtherBlues { 7 deltarray }
  /FamilyBlues { 8 deltarray }
  /FamilyOtherBlues { 9 deltarray }
  /BlueScale { 0.039625 41 nedef }
  /BlueShift { 7 42 nedef }
  /BlueFuzz { 1 43 nedef }
  /StdHW 10
  /StdVW 11
  /StemSnapH { 44 deltarray }
  /StemSnapV { 45 deltarray }
  /ForceBold { false 46 nedef }
  /ForceBoldThreshold { 0 47 nedef }
	% Skip lenIV, it's always -1
  /LanguageGroup { 0 49 nedef }
  /ExpansionFactor { 0.06 50 nedef }
  /initialRandomSeed { 0 51 nedef }
  /Subrs { pop /subrsoffset 19 2 forward }
  /defaultWidthX { 0 20 nedef }
  /nominalWidthX { 0 21 nedef }
.dicttomark readonly def

% ------ Main program ------ %

/putoffset {		% <str> <index> <offset> <offsize> putoffset -
	% The saved index points just beyond the end of the number,
	% and we wrote a zero as the placeholder.
	% Consequently, we don't need the offset size.
  pop {
    dup 0 eq { exit } if
    exch 1 sub exch 3 copy 255 and put -8 bitshift
  } loop pop pop pop
} def

/writecff {		% <file> [<font> ...] writecff -
  30 dict begin
	% The dictionary for each font contains:
	%	font - the original Type 2 font
	%	subrs - the Local Subrs Index
	%	chars - the CharStrings Index
	%	private - the Private Dict
	%	top - the Top Dict
	%	charspos - the offset of the CharStrings Dict relative to
	%	  the start of all CharStrings
	%	privatepos - the offset of the Private Dict relative to
	%	  the start of all Private Dicts
	%	subrsoffset - the offset of the Local Subrs offset
	%	  reference in the Private Dict
	%	charstringsoffset - the offset of the CharStrings offset
	%	  reference in the Top dict
	%	privateoffset - the offset of the Private Dict offset
	%	  reference in the Top dict
  [ exch { 12 dict begin /font exch cvlit def currentdict end } forall ]
  /fonts exch def
  /cff exch cvlit def

  /f cff def
  /fpos 0 def

	% We need to pre-construct all the strings so that we know
	% the offsets to fill in.

  /names { [ fonts { /font get /FontName get } forall ] Index } collect def
  /sids 20 dict def
  /subrslength 0 def		% only for estimating size
  /charslength 0 def
  /privatelength 0 def
  fonts {
    begin
    font /Private get /Subrs .knownget {
      { Index } collect
    } {
      <00 00>
    } ifelse /subrs exch def
    /subrslength subrslength subrs length add def
	%****** FOLLOWING IS WRONG, WRONG, WRONG ******%
    font /CharStrings get [ exch { exch pop } forall ] { Index } collect
    /chars exch def
    /charspos charslength def
    /charslength charslength chars length add def
    /subrsoffset null def
    font /Private get { privatekeyops Dict } collect /private exch def
    subrsoffset null ne {
      private subrsoffset private length 2 putoffset
    } if
    /privatepos privatelength def
    /privatelength privatelength private length add subrs length add def
  } forall
	% Estimate the size of a 0-based offset for the Top Dicts.
  /offsetsize subrslength charslength add privatelength add
    60000 ge { 3 } { 2 } ifelse def
  fonts {
    begin
    /charstringsoffset null def
    /privateoffset null def
    /top { font topkeyops Dict } collect def
    end
  } forall
  /strings { sids StandardSIDs length idIndex } collect def

	% Now we can write the real file.
	% Header
  DEBUG { (header ) print fpos == } if
  <01 00 04 02> nextstring
	% Name Index
  DEBUG { (names ) print fpos == } if
  names nextstring
	% Top Dicts
  DEBUG { (tops ) print fpos == } if
  /charsbase fpos fonts { /top get length add } forall strings length add def
  /privatebase charsbase charslength add def
  fonts {
    begin
    top charstringsoffset charspos charsbase add offsetsize putoffset
    top privateoffset privatepos privatebase add offsetsize putoffset
    top nextstring
    end
  } forall
	% String Index
  DEBUG { (strings ) print fpos == } if
  strings nextstring
	% Charstrings Indexes
  DEBUG { (charstrings) print } if
  /charsbase fpos def
  fonts {
    DEBUG { ( ) print fpos =only } if /chars get nextstring
  } forall
  DEBUG { () = } if
	% Private Dicts & Local Subr Indexes
  DEBUG { (privates/subrs) print } if
  fonts {
    DEBUG { ( ) print fpos =only } if dup /private get nextstring
    DEBUG { ( ) print fpos =only } if /subrs get nextstring
  } forall
  DEBUG { () = } if

  DEBUG { (end ) print fpos = flush } if
  end
} def

% ---------------- Wrap up ---------------- %

currentdict readonly end
/writecffdict exch def

/writecff {
  writecffdict begin writecff end
} def