2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
8 #include <aros/debug.h>
9 #include <aros/printertag.h>
11 #include <clib/alib_protos.h>
12 #include <devices/printer.h>
13 #include <devices/prtgfx.h>
15 #include <proto/graphics.h>
17 static struct Library
*GfxBase
;
19 static LONG
ps_Init(struct PrinterData
*pd
);
20 static VOID
ps_Expunge(VOID
);
21 static LONG
ps_Open(union printerIO
*ior
);
22 static VOID
ps_Close(union printerIO
*ior
);
24 static LONG
ps_Render(SIPTR ct
, LONG x
, LONG y
, LONG status
);
25 static LONG
ps_ConvFunc(UBYTE
*buf
, UBYTE c
, LONG crlf_flag
);
26 static LONG
ps_DoPreferences(union printerIO
*ior
, LONG command
);
27 static VOID
ps_CallErrHook(union printerIO
*ior
, struct Hook
*hook
);
28 static LONG
ps_DoSpecial(UWORD
*command
, UBYTE output_buffer
[],
29 BYTE
*current_line_position
,
30 BYTE
*current_line_spacing
,
31 BYTE
*crlf_flag
, UBYTE params
[]);
33 static struct TagItem PED_TagList
[] = {
34 { PRTA_8BitGuns
, TRUE
}, /* 0 */
35 { PRTA_NewColor
, TRUE
}, /* 1 */
36 { PRTA_ColorSize
, 3 }, /* 2 */
37 { PRTA_NoScaling
, TRUE
}, /* 3 */
38 { PRTA_MixBWColor
, FALSE
}, /* 4 */
39 { PRTA_LeftBorder
, 0 }, /* 5 */
40 { PRTA_TopBorder
, 0 }, /* 6 */
44 static CONST_STRPTR PED_Commands
[] = {
45 "\377", /* 0 aRIS (reset) */
46 "", /* 1 aRIN (initialize) */
47 "\n", /* 2 aIND (linefeed) */
48 "\r\n", /* 3 aNEL (CR/LF) */
49 "\377", /* 4 aRI (reverse LF) */
50 "\377", /* 5 aSGR0 (Courier) */
51 "\377", /* 6 aSGR3 (italics) */
52 "\377", /* 7 aSGR23 (no italics) */
53 "\377", /* 8 aSGR4 (underline) */
54 "\377", /* 9 aSGR24 (no underline) */
55 "\377", /* 10 aSGR1 (boldface) */
56 "\377", /* 11 aSGR21 (no boldface) */
57 "\377", /* 12 aSFC (set text color) */
58 "\377", /* 13 aSBC (set background color) */
59 "\377", /* 14 aSHORP0 (normal pitch) */
60 "\377", /* 15 aSHORP2 (elite) */
61 "\377", /* 16 aSHORP1 (no elite) */
62 "\377", /* 17 aSHORP4 (condensed) */
63 "\377", /* 18 aSHORP3 (no condensed) */
64 "\377", /* 19 aSHORP6 (enlarge) */
65 "\377", /* 20 aSHORT5 (no enlarge) */
66 "\377", /* 21 aDEN6 (shadow) */
67 "\377", /* 22 aDEN5 (no shadow) */
68 "\377", /* 23 aDEN4 (double strike) */
69 "\377", /* 24 aDEN3 (no double strike) */
70 "\377", /* 25 aDEN2 (NLQ) */
71 "\377", /* 26 aDEN1 (no NLQ) */
72 "\377", /* 27 aSUS2 (superscript) */
73 "\377", /* 28 aSUS1 (no superscript) */
74 "\377", /* 29 aSUS4 (subscript) */
75 "\377", /* 30 aSUS3 (no subscript) */
76 "\377", /* 31 aSUS0 (normal) */
77 "\377", /* 32 aPLU (partial line up) */
78 "\377", /* 33 aPLD (partial line down) */
79 "\377", /* 34 aFNT0 (Courier) */
80 "\377", /* 35 aFNT1 (Helvetica) */
81 "\377", /* 36 aFNT2 (Font 2) */
82 "\377", /* 37 aFNT3 (Font 3) */
83 "\377", /* 38 aFNT4 (Font 4) */
84 "\377", /* 39 aFNT5 (Font 5) */
85 "\377", /* 40 aFNT6 (Font 6) */
86 "\377", /* 41 aFNT7 (Font 7) */
87 "\377", /* 42 aFNT8 (Font 8) */
88 "\377", /* 43 aFNT9 (Font 9) */
89 "\377", /* 44 aFNT10 (Font 10) */
90 "\377", /* 45 aPROP2 (proportional) */
91 "\377", /* 46 aPROP1 (no proportional) */
92 "\377", /* 47 aPROP0 (default proportion) */
93 "\377", /* 48 aTSS (set proportional offset) */
94 "\377", /* 49 aJFY5 (left justify) */
95 "\377", /* 50 aJFY7 (right justify) */
96 "\377", /* 51 aJFY6 (full justify) */
97 "\377", /* 52 aJFY0 (no justify) */
98 "\377", /* 53 aJFY3 (letter space) */
99 "\377", /* 54 aJFY1 (word fill) */
100 "\377", /* 55 aVERP0 (1/8" line spacing) */
101 "\377", /* 56 aVERP1 (1/6" line spacing) */
102 "\377", /* 57 aSLPP (form length) */
103 "\377", /* 58 aPERF (skip n perfs) */
104 "\377", /* 59 aPERF0 (no skip perfs) */
105 "\377", /* 60 aLMS (left margin) */
106 "\377", /* 61 aRMS (right margin) */
107 "\377", /* 62 aTMS (top margin) */
108 "\377", /* 63 aBMS (bot margin) */
109 "\377", /* 64 aSTBM (top & bottom margin) */
110 "\377", /* 65 aSLRM (left & right margin) */
111 "\377", /* 66 aCAM (no margins) */
112 "\377", /* 67 aHTS (horizontal tabs) */
113 "\377", /* 68 aVTS (vertical tabs) */
114 "\377", /* 69 aTBC0 (clear horizontal tab) */
115 "\377", /* 70 aTBC3 (clear all horiz. tabs) */
116 "\377", /* 71 aTBC1 (clear vertical tab) */
117 "\377", /* 72 aTBC4 (clear all vertical tabs) */
118 "\377", /* 73 aTBCALL (clear all tabs) */
119 "\377", /* 74 aTBSALL (default tabs) */
120 "\377", /* 75 aEXTEND (extended chars) */
121 "\377", /* 76 aRAW (next N chars are literal) */
124 static CONST_STRPTR PED_8BitChars
[] = {
224 AROS_PRINTER_TAG(PED
, 44, 0,
225 .ped_PrinterName
= "PostScript",
227 .ped_Expunge
= ps_Expunge
,
229 .ped_Close
= ps_Close
,
231 /* Settings for a 'graphics only' printer */
232 .ped_PrinterClass
= PPC_COLORGFX
| PPCF_EXTENDED
,
233 .ped_MaxColumns
= 0, /* Set during render */
234 .ped_ColorClass
= PCC_BGR
,
235 .ped_NumCharSets
= 2,
237 .ped_MaxXDots
= 0, /* Set during render */
238 .ped_MaxYDots
= 0, /* Set during render */
239 .ped_XDotsInch
= 0, /* Set during render */
240 .ped_YDotsInch
= 0, /* Set during render */
241 .ped_Commands
= (STRPTR
*)PED_Commands
, /* No ANSI commands */
242 .ped_DoSpecial
= ps_DoSpecial
,
243 .ped_Render
= ps_Render
,
244 .ped_TimeoutSecs
= 1000, /* For print-to-file timeouts */
245 .ped_8BitChars
= (STRPTR
*)PED_8BitChars
,
247 .ped_ConvFunc
= ps_ConvFunc
,
248 .ped_TagList
= &PED_TagList
[0],
249 .ped_DoPreferences
= ps_DoPreferences
,
250 .ped_CallErrHook
= ps_CallErrHook
,
253 struct PrinterData
*PD
;
255 static LONG
ps_Init(struct PrinterData
*pd
)
257 D(bug("ps_Init: pd=%p\n", pd
));
259 GfxBase
= OpenLibrary("graphics.library", 0);
263 static VOID
ps_Expunge(VOID
)
265 D(bug("ps_Expunge\n"));
267 CloseLibrary(GfxBase
);
270 static void PWrite(const char *format
, ...)
276 static char buff_a
[16];
277 static char buff_b
[16];
278 static char *buff
= &buff_a
[0];
280 #define PFLUSH() do { \
281 PD->pd_PWrite(buff, len); \
282 if (buff == &buff_a[0]) \
289 #define PUTC(c) do { \
291 if (len >= 16) PFLUSH(); \
294 va_start(args
, format
);
296 for (; *format
; format
++) {
299 if (*format
== '%') {
308 lval
= va_arg(args
, LONG
);
319 out
[olen
++] = lval
% 10;
323 PUTC(out
[olen
] + '0');
347 static BOOL ps_HeaderSent
;
349 static void ps_SendHeader(void)
351 const TEXT header
[] =
353 "/Courier findfont 12 scalefont setfont\n"
354 "5 %d moveto gsave\n"
357 if (!ps_HeaderSent
) {
358 PWrite(header
, PED
->ped_MaxYDots
* 72 / PED
->ped_YDotsInch
- 36);
359 ps_HeaderSent
= TRUE
;
364 static LONG
ps_Open(union printerIO
*ior
)
366 D(bug("ps_Open: ior=%p\n", ior
));
368 ps_HeaderSent
= FALSE
;
373 static VOID
ps_Close(union printerIO
*ior
)
376 PWrite(") show showpage grestore\n");
377 D(bug("ps_Close: ior=%p\n", ior
));
380 VOID
color_get(struct ColorMap
*cm
,
386 UWORD hibits
= ((UWORD
*)cm
->ColorTable
)[index
];
388 ULONG red8
= (hibits
& 0x0f00) >> 4;
389 ULONG green8
= (hibits
& 0x00f0);
390 ULONG blue8
= (hibits
& 0x000f) << 4;
392 if (cm
->Type
> COLORMAP_TYPE_V1_2
) {
393 UWORD lobits
= ((UWORD
*)cm
->LowColorBits
)[index
];
395 red8
|= (lobits
& 0x0f00) >> 8;
396 green8
|= (lobits
& 0x00f0) >> 4;
397 blue8
|= (lobits
& 0x000f);
405 static LONG ps_PrintBufLen
;
407 static LONG
ps_RenderInit(struct IODRPReq
*io
, LONG x
, LONG y
)
409 D(bug("ps_RenderInit: Dump raster %dx%d pixels, io_RastPort=%p\n", x
, y
, io
->io_RastPort
));
410 D(bug("\t@%dx%d (%dx%d) => @%dx%d\n",
411 io
->io_SrcX
, io
->io_SrcY
, io
->io_SrcWidth
,
412 io
->io_SrcHeight
, io
->io_DestCols
, io
->io_DestRows
));
416 ps_PrintBufLen
= io
->io_SrcWidth
;
417 PD
->pd_PrintBuf
= AllocMem(ps_PrintBufLen
* 6, MEMF_ANY
);
418 if (PD
->pd_PrintBuf
== NULL
)
419 return PDERR_BUFFERMEMORY
;
421 /* Write a postscript colorimage */
422 PWrite(") show grestore gsave\n");
423 PWrite("%d %d translate\n", PD
->pd_Preferences
.PrintXOffset
* PED
->ped_XDotsInch
/ 10 +
424 (PED
->ped_MaxXDots
- x
) / 2,
425 (PED
->ped_MaxYDots
- y
) / 2);
426 PWrite("%d %d scale\n", x
, y
);
427 PWrite("%d %d 8 [%d 0 0 %d 0 %d]\n",
428 io
->io_SrcWidth
, io
->io_SrcHeight
,
429 io
->io_SrcWidth
, -io
->io_SrcHeight
, io
->io_SrcHeight
);
435 static UBYTE
tohex(UBYTE val
)
438 return (val
< 10) ? ('0' + val
) : ('a' + val
- 10);
441 static LONG
ps_RenderTransfer(struct PrtInfo
*pi
, LONG x
, LONG y
)
443 UBYTE
*ptr
= PD
->pd_PrintBuf
;
444 UBYTE
*src
= (UBYTE
*)pi
->pi_ColorInt
;
447 for (x
= 0; x
< ps_PrintBufLen
; x
++, src
+= 3, ptr
+= 6) {
449 for (i
= 0; i
< 3; i
++) {
450 ptr
[i
*2+0] = tohex(src
[2-i
]>>4);
451 ptr
[i
*2+1] = tohex(src
[2-i
]>>0);
458 static LONG
ps_RenderFlush(LONG rows
)
460 PD
->pd_PWrite(PD
->pd_PrintBuf
, ps_PrintBufLen
* 6);
461 PD
->pd_PWrite("\n", 1);
465 static LONG
ps_RenderClear(void)
467 memset(PD
->pd_PrintBuf
, '0', ps_PrintBufLen
* 6);
471 static LONG
ps_RenderPreInit(struct IODRPReq
*io
, LONG flags
)
473 ULONG dpiX
= 0, dpiY
= 0;
477 switch (flags
& SPECIAL_DENSITYMASK
) {
478 case SPECIAL_DENSITY1
:
482 case SPECIAL_DENSITY2
:
486 case SPECIAL_DENSITY3
:
490 case SPECIAL_DENSITY4
:
494 case SPECIAL_DENSITY5
:
498 case SPECIAL_DENSITY6
:
502 case SPECIAL_DENSITY7
:
508 /* Set up for the page size */
509 switch (PD
->pd_Preferences
.PaperSize
) {
510 /* PaperSize (in um) */
511 case US_LETTER
: width
= 2159; height
= 2794; break; /* 8.5"x11" */
512 case US_LEGAL
: width
= 2159; height
= 3556; break; /* 8.5"x14" */
513 case N_TRACTOR
: width
= 2413; height
= 2794; break; /* 9.5"x11" */
514 case W_TRACTOR
: width
= 3774; height
= 2794; break; /* 14.86"x11" */
516 case EURO_A0
: width
= 8410; height
= 11890; break; /* A0: 841 x 1189 */
517 case EURO_A1
: width
= 5940; height
= 8410; break; /* A1: 594 x 841 */
518 case EURO_A2
: width
= 4200; height
= 5940; break; /* A2: 420 x 594 */
519 case EURO_A3
: width
= 2970; height
= 4200; break; /* A3: 297 x 420 */
520 case EURO_A4
: width
= 2100; height
= 2970; break; /* A4: 210 x 297 */
521 case EURO_A5
: width
= 1480; height
= 2100; break; /* A5: 148 x 210 */
522 case EURO_A6
: width
= 1050; height
= 1480; break; /* A6: 105 x 148 */
523 case EURO_A7
: width
= 740; height
= 1050; break; /* A7: 74 x 105 */
524 case EURO_A8
: width
= 520; height
= 740; break; /* A8: 52 x 74 */
525 case CUSTOM
: width
= PD
->pd_Preferences
.PrintMaxWidth
* 254 / 10;
526 height
= PD
->pd_Preferences
.PrintMaxHeight
* 254 / 10;
528 default: return PDERR_CANCEL
;
531 PED
->ped_MaxColumns
= width
* 10 / 254;
532 PED
->ped_XDotsInch
= dpiX
;
533 PED
->ped_YDotsInch
= dpiY
;
534 PED
->ped_MaxXDots
= width
* dpiX
/ 254;
535 PED
->ped_MaxYDots
= height
* dpiY
/ 254;
540 static LONG
ps_RenderClose(struct IODRPReq
*io
, ULONG flags
)
542 if (ps_PrintBufLen
) {
543 PWrite(">}\nfalse 3 colorimage\n");
544 PWrite("grestore (\n");
545 FreeMem(PD
->pd_PrintBuf
, ps_PrintBufLen
* 6);
546 PD
->pd_PrintBuf
=NULL
;
554 static LONG
ps_Render(SIPTR ct
, LONG x
, LONG y
, LONG status
)
556 LONG err
= PDERR_NOERR
;
560 D(bug("PRS_INIT: ct=%p, x=%d, y=%d\n", ct
, x
, y
));
561 err
= ps_RenderInit((struct IODRPReq
*)ct
, x
, y
);
564 D(bug("PRS_TRANSFER: ct=%p, x=%d, y=%d\n", ct
, x
, y
));
565 err
= ps_RenderTransfer((struct PrtInfo
*)ct
, x
, y
);
568 D(bug("PRS_FLUSH: ct=%p, x=%d, y=%d\n", ct
, x
, y
));
569 err
= ps_RenderFlush(y
);
572 D(bug("PRS_CLEAR: ct=%p, x=%d, y=%d\n", ct
, x
, y
));
573 err
= ps_RenderClear();
576 D(bug("PRS_CLOSE: ct=%p, x=0x%0x, y=%d\n", ct
, x
, y
));
577 err
= ps_RenderClose((struct IODRPReq
*)ct
, x
);
580 D(bug("PRS_PREINIT: ct=%p, x=0x%0x, y=%d\n", ct
, x
, y
));
581 err
= ps_RenderPreInit((struct IODRPReq
*)ct
, x
);
584 D(bug("PRS_CONVERT: ct=%p, x=0x%0x, y=%d\n", ct
, x
, y
));
588 D(bug("PRS_CORRECT: ct=%p, x=0x%0x, y=%d\n", ct
, x
, y
));
592 D(bug("PRS_xxxx(%d): ct=%p, x=0x%0x, y=%d\n", status
, ct
, x
, y
));
601 static LONG
ps_DoSpecial(UWORD
*command
, UBYTE output_buffer
[],
602 BYTE
*current_line_position
,
603 BYTE
*current_line_spacing
,
604 BYTE
*crlf_flag
, UBYTE params
[])
606 D(bug("ps_DoSpecial: command=0x%04x, output_buffer=%p, current_line_position=%d, current_line_spacing=%d, crlf_flag=%d, params=%s\n",
607 *command
, output_buffer
, *current_line_position
, *current_line_spacing
, *crlf_flag
, params
));
609 if (*command
== aRIN
) {
613 if (*command
== aRIS
) {
614 PD
->pd_PWaitEnabled
= '\375';
617 if (*command
== aIND
) {
618 strcpy(output_buffer
, "\\\n) show\n"
619 /* Get current point => x=5, y=currentline */
620 "currentpoint exch pop 5 exch moveto\n"
622 return strlen(output_buffer
);
625 if (*command
== aNEL
) {
626 strcpy(output_buffer
, "\\\n) show\n"
627 /* Get current point => x=5, y=currentline-11 */
628 "currentpoint exch pop 5 exch 11 sub moveto\n"
630 return strlen(output_buffer
);
637 static LONG
ps_ConvFunc(UBYTE
*buf
, UBYTE c
, LONG crlf_flag
)
639 D(bug("ps_ConvFunc: %p '%c' %d\n", buf
, c
, crlf_flag
));
641 if (c
< 0x1f || c
> 0x7f)
644 if (c
== '(' || c
== ')') {
651 if (c
>= ' ' && c
< 127) {
658 *(buf
++) = ((c
>> 6) & 7) + '0';
659 *(buf
++) = ((c
>> 3) & 7) + '0';
660 *(buf
++) = ((c
>> 0) & 7) + '0';
665 static LONG
ps_DoPreferences(union printerIO
*ior
, LONG command
)
667 D(bug("ps_DoPreferences: ior=%p, command=%d\n"));
671 static VOID
ps_CallErrHook(union printerIO
*ior
, struct Hook
*hook
)
673 D(bug("ps_CallErrHook: ior=%p, hook=%p\n", ior
, hook
));