Winspool DocumentProperties and DeviceCapabilities should now work on
[wine] / graphics / psdrv / text.c
1 /*
2  *      PostScript driver text functions
3  *
4  *      Copyright 1998  Huw D M Davies
5  *
6  */
7 #include <string.h>
8 #include "psdrv.h"
9 #include "debugtools.h"
10 #include "winspool.h"
11
12 DEFAULT_DEBUG_CHANNEL(psdrv)
13
14 /***********************************************************************
15  *           PSDRV_ExtTextOut
16  */
17 BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
18                    const RECT *lprect, LPCSTR str, UINT count,
19                    const INT *lpDx )
20 {
21     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
22     char *strbuf;
23     SIZE sz;
24
25     TRACE("(x=%d, y=%d, flags=0x%08x, str='%.*s', count=%d)\n", x, y,
26           flags, (int)count, str, count);
27
28     strbuf = (char *)HeapAlloc( PSDRV_Heap, 0, count + 1);
29     if(!strbuf) {
30         WARN("HeapAlloc failed\n");
31         return FALSE;
32     }
33
34     if(dc->w.textAlign & TA_UPDATECP) {
35         x = dc->w.CursPosX;
36         y = dc->w.CursPosY;
37     }
38
39     x = XLPTODP(dc, x);
40     y = YLPTODP(dc, y);
41
42     GetTextExtentPoint32A(dc->hSelf, str, count, &sz);
43     sz.cx = XLSTODS(dc, sz.cx);
44     sz.cy = YLSTODS(dc, sz.cy);
45
46     switch(dc->w.textAlign & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
47     case TA_LEFT:
48         if(dc->w.textAlign & TA_UPDATECP)
49             dc->w.CursPosX = XDPTOLP(dc, x + sz.cx);
50         break;
51
52     case TA_CENTER:
53         x -= sz.cx/2;
54         break;
55
56     case TA_RIGHT:
57         x -= sz.cx;
58         if(dc->w.textAlign & TA_UPDATECP)
59             dc->w.CursPosX = XDPTOLP(dc, x);
60         break;
61     }
62
63     switch(dc->w.textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
64     case TA_TOP:
65         y += physDev->font.tm.tmAscent;
66         break;
67
68     case TA_BASELINE:
69         break;
70
71     case TA_BOTTOM:
72         y -= physDev->font.tm.tmDescent;
73         break;
74     }
75
76     memcpy(strbuf, str, count);
77     *(strbuf + count) = '\0';
78     
79     PSDRV_SetFont(dc);
80
81     PSDRV_WriteMoveTo(dc, x, y);
82     PSDRV_WriteShow(dc, strbuf, strlen(strbuf));
83
84     /*
85      * Underline and strikeout attributes.
86      */
87     if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) {
88
89         /* Get the thickness and the position for the underline attribute */
90         /* We'll use the same thickness for the strikeout attribute       */
91
92         float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale;
93         float pos   = -physDev->font.afm->UnderlinePosition * physDev->font.scale;
94         SIZE size;
95         INT escapement =  physDev->font.escapement;
96
97         TRACE("Position = %f Thickness %f Escapement %d\n",
98               pos, thick, escapement);
99
100         /* Get the width of the text */
101
102         PSDRV_GetTextExtentPoint(dc, strbuf, strlen(strbuf), &size);
103         size.cx = XLSTODS(dc, size.cx);
104
105         /* Do the underline */
106
107         if (physDev->font.tm.tmUnderlined) {
108             if (escapement != 0)  /* rotated text */
109             {
110                 PSDRV_WriteGSave(dc);  /* save the graphics state */
111                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
112
113                 /* temporarily rotate the coord system */
114                 PSDRV_WriteRotate(dc, -escapement/10); 
115                 
116                 /* draw the underline relative to the starting point */
117                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
118             }
119             else
120                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
121
122             PSDRV_WriteFill(dc);
123
124             if (escapement != 0)  /* rotated text */
125                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
126         }
127
128         /* Do the strikeout */
129
130         if (physDev->font.tm.tmStruckOut) {
131             pos = -physDev->font.tm.tmAscent / 2;
132
133             if (escapement != 0)  /* rotated text */
134             {
135                 PSDRV_WriteGSave(dc);  /* save the graphics state */
136                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
137
138                 /* temporarily rotate the coord system */
139                 PSDRV_WriteRotate(dc, -escapement/10);
140
141                 /* draw the underline relative to the starting point */
142                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
143             }
144             else
145                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
146
147             PSDRV_WriteFill(dc);
148
149             if (escapement != 0)  /* rotated text */
150                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
151         }
152     }
153
154     HeapFree(PSDRV_Heap, 0, strbuf);
155     return TRUE;
156 }