No longer directly accessing debuggee memory.
[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 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
15                        BOOL bDrawBackground);
16
17 /***********************************************************************
18  *           PSDRV_ExtTextOut
19  */
20 BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
21                        const RECT *lprect, LPCWSTR str, UINT count,
22                        const INT *lpDx )
23 {
24     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
25     BOOL bResult = TRUE;
26     BOOL bClipped = FALSE;
27     BOOL bOpaque = FALSE;
28     RECT rect;
29
30     TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d)\n", x, y,
31           flags, debugstr_wn(str, count), count);
32
33     /* write font if not already written */
34     PSDRV_SetFont(dc);
35
36     /* set clipping and/or draw background */
37     if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL))
38     {
39         rect.left = XLPTODP(dc, lprect->left);
40         rect.right = XLPTODP(dc, lprect->right);
41         rect.top = YLPTODP(dc, lprect->top);
42         rect.bottom = YLPTODP(dc, lprect->bottom);
43
44         PSDRV_WriteGSave(dc);
45         PSDRV_WriteRectangle(dc, rect.left, rect.top, rect.right - rect.left, 
46                              rect.bottom - rect.top);
47
48         if (flags & ETO_OPAQUE)
49         {
50             bOpaque = TRUE;
51             PSDRV_WriteGSave(dc);
52             PSDRV_WriteSetColor(dc, &physDev->bkColor);
53             PSDRV_WriteFill(dc);
54             PSDRV_WriteGRestore(dc);
55         }
56
57         if (flags & ETO_CLIPPED)
58         {
59             bClipped = TRUE;
60             PSDRV_WriteClip(dc);
61         }
62
63         bResult = PSDRV_Text(dc, x, y, str, count, !(bClipped && bOpaque)); 
64         PSDRV_WriteGRestore(dc);
65     }
66     else
67     {
68         bResult = PSDRV_Text(dc, x, y, str, count, TRUE); 
69     }
70
71     return bResult;
72 }
73
74 /***********************************************************************
75  *           PSDRV_Text
76  */
77 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
78                        BOOL bDrawBackground)
79 {
80     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
81     LPWSTR strbuf;
82     SIZE sz;
83
84     strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR));
85     if(!strbuf) {
86         WARN("HeapAlloc failed\n");
87         return FALSE;
88     }
89
90     if(dc->w.textAlign & TA_UPDATECP) {
91         x = dc->w.CursPosX;
92         y = dc->w.CursPosY;
93     }
94
95     x = XLPTODP(dc, x);
96     y = YLPTODP(dc, y);
97
98     GetTextExtentPoint32W(dc->hSelf, str, count, &sz);
99     sz.cx = XLSTODS(dc, sz.cx);
100     sz.cy = YLSTODS(dc, sz.cy);
101
102     switch(dc->w.textAlign & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
103     case TA_LEFT:
104         if(dc->w.textAlign & TA_UPDATECP)
105             dc->w.CursPosX = XDPTOLP(dc, x + sz.cx);
106         break;
107
108     case TA_CENTER:
109         x -= sz.cx/2;
110         break;
111
112     case TA_RIGHT:
113         x -= sz.cx;
114         if(dc->w.textAlign & TA_UPDATECP)
115             dc->w.CursPosX = XDPTOLP(dc, x);
116         break;
117     }
118
119     switch(dc->w.textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
120     case TA_TOP:
121         y += physDev->font.tm.tmAscent;
122         break;
123
124     case TA_BASELINE:
125         break;
126
127     case TA_BOTTOM:
128         y -= physDev->font.tm.tmDescent;
129         break;
130     }
131
132     memcpy(strbuf, str, count * sizeof(WCHAR));
133     *(strbuf + count) = '\0';
134     
135     if ((dc->w.backgroundMode != TRANSPARENT) && (bDrawBackground != FALSE))
136     {
137         PSDRV_WriteGSave(dc);
138         PSDRV_WriteNewPath(dc);
139         PSDRV_WriteRectangle(dc, x, y - physDev->font.tm.tmAscent, sz.cx, 
140                              physDev->font.tm.tmAscent + 
141                              physDev->font.tm.tmDescent);
142         PSDRV_WriteSetColor(dc, &physDev->bkColor);
143         PSDRV_WriteFill(dc);
144         PSDRV_WriteGRestore(dc);
145     }
146
147     PSDRV_WriteMoveTo(dc, x, y);
148     PSDRV_WriteShow(dc, strbuf, lstrlenW(strbuf));
149
150     /*
151      * Underline and strikeout attributes.
152      */
153     if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) {
154
155         /* Get the thickness and the position for the underline attribute */
156         /* We'll use the same thickness for the strikeout attribute       */
157
158         float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale;
159         float pos   = -physDev->font.afm->UnderlinePosition * physDev->font.scale;
160         SIZE size;
161         INT escapement =  physDev->font.escapement;
162
163         TRACE("Position = %f Thickness %f Escapement %d\n",
164               pos, thick, escapement);
165
166         /* Get the width of the text */
167
168         PSDRV_GetTextExtentPoint(dc, strbuf, lstrlenW(strbuf), &size);
169         size.cx = XLSTODS(dc, size.cx);
170
171         /* Do the underline */
172
173         if (physDev->font.tm.tmUnderlined) {
174             if (escapement != 0)  /* rotated text */
175             {
176                 PSDRV_WriteGSave(dc);  /* save the graphics state */
177                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
178
179                 /* temporarily rotate the coord system */
180                 PSDRV_WriteRotate(dc, -escapement/10); 
181                 
182                 /* draw the underline relative to the starting point */
183                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
184             }
185             else
186                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
187
188             PSDRV_WriteFill(dc);
189
190             if (escapement != 0)  /* rotated text */
191                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
192         }
193
194         /* Do the strikeout */
195
196         if (physDev->font.tm.tmStruckOut) {
197             pos = -physDev->font.tm.tmAscent / 2;
198
199             if (escapement != 0)  /* rotated text */
200             {
201                 PSDRV_WriteGSave(dc);  /* save the graphics state */
202                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
203
204                 /* temporarily rotate the coord system */
205                 PSDRV_WriteRotate(dc, -escapement/10);
206
207                 /* draw the underline relative to the starting point */
208                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
209             }
210             else
211                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
212
213             PSDRV_WriteFill(dc);
214
215             if (escapement != 0)  /* rotated text */
216                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
217         }
218     }
219
220     HeapFree(PSDRV_Heap, 0, strbuf);
221     return TRUE;
222 }