summaryrefslogtreecommitdiff
path: root/src/gui/painting/qpsprinter.ps
blob: ef3f42970bdf8e177687d0ba3a1a48bdc125111e (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
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
% the postscript header we use for our qpsprinter in uncompressed and commented form.
% use the makepsheader perl script to generate a compressed version of this header
% you can then paste into qpsprinter.cpp
%
% some compression of the code is done by the makepsheader script, so we don't need to 
% write too criptically here. 

/BD  {bind def} bind def
/d2 {dup dup} BD
/ED {exch def} BD
/D0 {0 ED} BD

/F  {setfont} BD
/RL {rlineto} BD
/CM {currentmatrix} BD
/SM {setmatrix} BD
/TR {translate} BD
/SD {setdash} BD
/SC {aload pop setrgbcolor} BD
/CR {currentfile read pop} BD
/i  {index} BD
/scs {setcolorspace} BD
/DB {dict dup begin} BD
/DE {end def} BD
/ie {ifelse} BD
/gs {gsave} BD
/gr {grestore} BD

% these use PDF syntax
/w {setlinewidth} BD
/d {setdash} BD
/J {setlinecap} BD
/j {setlinejoin} BD
/scn {3 array astore /BCol exch def} BD
/SCN {3 array astore /PCol exch def} BD
/cm {6 array astore concat} BD

/m  {moveto} BD
/l  {lineto} BD
/c  {curveto} BD
/h  {closepath} BD

/W  {clip} BD
/W* {eoclip} BD
/n {newpath} BD
% ENDUNCOMPRESSED: Warning: leave this line in. 
% Everything before this line will be left untouched by the compression

/q  {gsave 10 dict begin} BD
/Q  {end grestore} BD

% PDF operators
/re { % PDF re operator
  4 2 roll  % w h x y
  moveto % w h
  dup % w h h
  0 exch rlineto % w h
  exch 0 rlineto % h
  0 exch neg rlineto
  closepath
} bind def

/S {
  gsave
    PCol SC stroke
  grestore
  newpath
} BD

% PDF text operators
/BT {gsave 10 dict begin /_m matrix currentmatrix def BCol SC} BD
/ET {end grestore} BD
/Tf {
  /_fs exch def
  findfont
  [ _fs 0 0 _fs 0 0 ]  
  makefont
  setfont
} BD
/Tm {6 array astore concat} BD
/Td {translate} BD
/Tj {0 0 moveto show} BD
/BDC {pop pop} BD
/EMC {} BD

% old operators

/BSt 0 def                             % brush style
/WFi false def                 % winding fill

/BCol  [ 1 1 1 ] def                   % brush color
/PCol  [ 0 0 0 ] def                   % pen color
/BDArr [                             % Brush dense patterns
  0.94
  0.88
  0.63
  0.50
  0.37 
  0.12 
  0.06 
] def

% -- level3 true/false
/level3 {
  /languagelevel where {
    pop
    languagelevel 3 ge 
  } { false } ifelse
} bind def


%% image drawing routines

% defines for QCI
/QCIgray D0 /QCIcolor D0 /QCIindex D0

% this method prints color images if colorimage is available, otherwise
% converts the string to a grayscale image and uses the reular postscript image
% operator for printing.
% Arguments are the same as for the image operator:
% 
%     width height bits/sample matrix datasrc QCI -
/QCI {
  /colorimage where {
    pop
    false 3 colorimage
  }{  % the hard way, based on PD code by John Walker <kelvin@autodesk.com>
    exec /QCIcolor exch def
    /QCIgray QCIcolor length 3 idiv string def
    0 1 QCIcolor length 3 idiv 1 sub
    { /QCIindex exch def
      /_x QCIindex 3 mul def
      QCIgray QCIindex
      QCIcolor _x       get 0.30 mul
      QCIcolor _x 1 add get 0.59 mul
      QCIcolor _x 2 add get 0.11 mul
      add add cvi
      put
    } for
    QCIgray image
  } ifelse
} bind def

% general image drawing routine, used from the postscript driver
%
% Draws images with and without mask with 1, 8 and 24(rgb) bits depth.
%
%     width height matrix image 1|8|24 mask|false x y di
%
% width and height specify the width/height of the image,
% matrix a transformation matrix, image a procedure holding the image data
% (same for mask) and x/y an additional translation.
%
% ### should move the translation into the matrix!!!
/di 
{
  gsave
    translate
    1 index 1 eq { % bitmap
      pop pop % get rid of mask and depth
      false 3 1 roll % width height false matrix image
      BCol SC
      imagemask
    } { 
      dup false ne { 
	% have a mask, see if we can use it
	level3
      } { 
	false 
      } ifelse

      {
	% languagelevel3, we can use image mask and dicts

	% store the image mask
	/_ma exch def
	% select colorspace according to 8|24 bit depth and set the decode array /dc
	8 eq {
	  /_dc [0 1] def
	  /DeviceGray
	} {
	  /_dc [0 1 0 1 0 1] def
	  /DeviceRGB
	} ifelse
	setcolorspace
	% the image data
	/_im exch def
	% transformation matrix
	/_mt exch def
	% width and height
	/_h exch def
	/_w exch def
	% and the combined image dict
	<<
	  /ImageType 3
	  % the image dict
	  /DataDict <<
              /ImageType 1
	      /Width _w
	      /Height _h
	      /ImageMatrix _mt
	      /DataSource _im
	      /BitsPerComponent 8
	      /Decode _dc
	  >> 
	  % the mask dictionary
	  /MaskDict <<
             /ImageType 1
	     /Width _w
	     /Height _h
	     /ImageMatrix _mt
	     /DataSource _ma
	     /BitsPerComponent 1
	     /Decode [0 1]
	  >> 
	  /InterleaveType 3
	>> 
	image
      } {
	pop % no mask or can't use it, get rid of it
	8 % width height image 8|24 8 matrix
	4 1 roll
	8 eq { % grayscale
	  image
	} { %color
	  QCI
	} ifelse
      } ifelse
    } ifelse
  grestore    
} bind def


/BF {                                % brush fill
  gsave
    BSt 1 eq                          % solid brush?
    {
      BCol SC
      WFi { fill } { eofill } ifelse
    } if
    BSt 2 ge BSt 8 le and             % dense pattern?
    {
      BDArr BSt 2 sub get /_sc exch def 
      % the following line scales the brush color according to the pattern. the higher the pattern the lighter the color.
      BCol 
      { 
	1. exch sub _sc mul 1. exch sub 
      } forall 
      3 array astore
      SC 
      WFi { fill } { eofill } ifelse
    } if
    BSt 9 ge BSt 14 le and            % brush pattern?
    {
      WFi { clip } { eoclip } ifelse
      pathbbox                        % left upper right lower
      3 index 3 index translate
      4 2 roll                        % right lower left upper
      3 2 roll                        % right left upper lower
      exch                            % left right lower upper
      sub /_h exch def
      sub /_w exch def
      BCol SC
      0.3 setlinewidth
      newpath
      BSt 9 eq BSt 11 eq or           % horiz or cross pattern
      { 0 4 _h
	{ dup 0 exch moveto _w exch lineto } for
      } if
      BSt 10 eq BSt 11 eq or          % vert or cross pattern
      { 0 4 _w
	{ dup 0 moveto _h lineto } for
      } if
      BSt 12 eq BSt 14 eq or          % F-diag or diag cross
      { _w _h gt
	{ 0 6 _w _h add
	  { dup 0 moveto _h sub _h lineto } for
	} { 0 6 _w _h add
	  { dup 0 exch moveto _w sub _w exch lineto } for
	} ifelse
      } if
      BSt 13 eq BSt 14 eq or          % B-diag or diag cross
      { _w _h gt
	{ 0 6 _w _h add
	  { dup _h moveto _h sub 0 lineto } for
	} { 0 6 _w _h add
	  { dup _w exch moveto _w sub 0 exch lineto } for
	} ifelse
      } if
      stroke
    } if
    BSt 15 eq
    {
    } if
    BSt 24 eq                         % TexturePattern
    {
    } if
  grestore
} bind def

% more PDF operators
/f { /WFi true def BF newpath } bind def
/f* { /WFi false def BF newpath } bind def
/B { /WFi true def BF S newpath } bind def
/B* { /WFi false def BF S newpath } bind def

%% start of page
/QI {
  /C save def
  pageinit
  q
  newpath
} bind def

%% end of page
/QP {
  Q                                % show page
  C restore
  showpage
} bind def

% merges one key value pair into the page device dict
%
%    key value SPD -
/SPD {
  /setpagedevice where {
    << 3 1 roll >>
    setpagedevice
  } { pop pop } ifelse
} bind def


% font handling

/T1AddMapping { % basefont [glyphname ...] T1AddMapping -
  10 dict begin
    /glyphs exch def
    /fnt exch def
    /current fnt /NumGlyphs get def
    /CMap fnt /CMap get def

    0 1 glyphs length 1 sub % 0 1 (num glyphs - 1)
    {
      glyphs exch get /gn exch def

      current dup                                 % glyph_index glyph_index
      256 mod /min exch def                       % glyph_index
      256 idiv /maj exch def                      % -
      CMap dup maj get dup                        % cmap cmap_maj cmap_maj
      null eq {
	pop 256 array 
	0 1 255 {1 index exch /.notdef put} for
      } if
      dup                                         % cmap cmap_maj cmap_maj
      min gn put                                  % cmap cmap_maj
      maj exch put                                % -

      /current current 1 add def
    } for

    fnt /CMap CMap put
    fnt /NumGlyphs current put
  end 
} def

/T1AddGlyphs { % basefont [glyphname charstring ...] T1AddGlyphs -
  10 dict begin
    /glyphs exch def
    /fnt exch def
    /current fnt /NumGlyphs get def
    /CMap fnt /CMap get def
    /CharStrings fnt /CharStrings get def

    0 1 glyphs length 2 idiv 1 sub % 0 1 (num glyphs - 1)
    {
      2 mul dup
      glyphs exch get /gn exch def
      1 add
      glyphs exch get /cs exch def

      current dup                                 % glyph_index glyph_index
      256 mod /min exch def                       % glyph_index
      256 idiv /maj exch def                      % -
      CMap dup maj get dup                        % cmap cmap_maj cmap_maj
      null eq {
	pop 256 array 
	0 1 255 {1 index exch /.notdef put} for
      } if
      dup                                         % cmap cmap_maj cmap_maj
      min gn put                                  % cmap cmap_maj
      maj exch put                                % -

      CharStrings gn cs put
      /current current 1 add def
    } for

    fnt /CharStrings CharStrings put
    fnt /CMap CMap put
    fnt /NumGlyphs current put
  end 
} def



/StringAdd { % string1 string2 stringadd result
  1 index length 1 index length add
  string
  3 1 roll
  2 index 0 3 index putinterval
  2 index 2 index length 2 index putinterval 
  pop pop
} def


/T1Setup { % fontname T1Setup -
10 dict begin
  dup /FontName exch def
  (-Base) StringAdd cvx cvn /Font exch def
  /MaxPage Font /NumGlyphs get 1 sub 256 idiv def

  /FDepVector MaxPage 1 add array def
  /Encoding MaxPage 1 add array def

  0 1 MaxPage {
    dup Encoding exch dup put
 

    dup /Page exch def
    FontName (-) StringAdd 
    exch 
    20 string cvs StringAdd % page fontname
    cvn

    Font 0 dict copy dup dup /CMap get 
    Page get 
    /Encoding exch put definefont 
    FDepVector exch Page exch put
  } for 

  FontName cvn <<
    /FontType 0
    /FMapType 2
    /FontMatrix[1 0 0 1 0 0]
    /Encoding Encoding
    /FDepVector FDepVector
    >> definefont pop
  end
} def