Finish any pending WaitCommEvents if the event mask is set to 0.
[wine.git] / dlls / wineps / text.c
blob56c8fa63f8703aa56b84f0a489155214ad229cbf
1 /*
2 * PostScript driver text functions
4 * Copyright 1998 Huw D M Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <string.h>
21 #include "psdrv.h"
22 #include "wine/debug.h"
23 #include "winspool.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
27 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
28 BOOL bDrawBackground, const INT *lpDx);
30 /***********************************************************************
31 * PSDRV_ExtTextOut
33 BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
34 const RECT *lprect, LPCWSTR str, UINT count,
35 const INT *lpDx )
37 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
38 BOOL bResult = TRUE;
39 BOOL bClipped = FALSE;
40 BOOL bOpaque = FALSE;
41 RECT rect;
43 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x, y,
44 flags, debugstr_wn(str, count), count, lpDx);
46 /* write font if not already written */
47 PSDRV_SetFont(dc);
49 /* set clipping and/or draw background */
50 if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL))
52 rect.left = INTERNAL_XWPTODP(dc, lprect->left, lprect->top);
53 rect.right = INTERNAL_XWPTODP(dc, lprect->right, lprect->bottom);
54 rect.top = INTERNAL_YWPTODP(dc, lprect->left, lprect->top);
55 rect.bottom = INTERNAL_YWPTODP(dc, lprect->right, lprect->bottom);
57 PSDRV_WriteGSave(dc);
58 PSDRV_WriteRectangle(dc, rect.left, rect.top, rect.right - rect.left,
59 rect.bottom - rect.top);
61 if (flags & ETO_OPAQUE)
63 bOpaque = TRUE;
64 PSDRV_WriteGSave(dc);
65 PSDRV_WriteSetColor(dc, &physDev->bkColor);
66 PSDRV_WriteFill(dc);
67 PSDRV_WriteGRestore(dc);
70 if (flags & ETO_CLIPPED)
72 bClipped = TRUE;
73 PSDRV_WriteClip(dc);
76 bResult = PSDRV_Text(dc, x, y, str, count, !(bClipped && bOpaque), lpDx);
77 PSDRV_WriteGRestore(dc);
79 else
81 bResult = PSDRV_Text(dc, x, y, str, count, TRUE, lpDx);
84 return bResult;
87 /***********************************************************************
88 * PSDRV_Text
90 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
91 BOOL bDrawBackground, const INT *lpDx)
93 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
94 LPWSTR strbuf;
95 SIZE sz;
97 if (!count)
98 return TRUE;
100 strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR));
101 if(!strbuf) {
102 WARN("HeapAlloc failed\n");
103 return FALSE;
106 if(dc->textAlign & TA_UPDATECP) {
107 x = dc->CursPosX;
108 y = dc->CursPosY;
111 x = INTERNAL_XWPTODP(dc, x, y);
112 y = INTERNAL_YWPTODP(dc, x, y);
114 GetTextExtentPoint32W(dc->hSelf, str, count, &sz);
115 if(lpDx) {
116 SIZE tmpsz;
117 INT i;
118 /* Get the width of the last char and add on all the offsets */
119 GetTextExtentPoint32W(dc->hSelf, str + count - 1, 1, &tmpsz);
120 for(i = 0; i < count-1; i++)
121 tmpsz.cx += lpDx[i];
122 sz.cx = tmpsz.cx; /* sz.cy remains untouched */
125 sz.cx = INTERNAL_XWSTODS(dc, sz.cx);
126 sz.cy = INTERNAL_YWSTODS(dc, sz.cy);
127 TRACE("textAlign = %x\n", dc->textAlign);
128 switch(dc->textAlign & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
129 case TA_LEFT:
130 if(dc->textAlign & TA_UPDATECP) {
131 dc->CursPosX = INTERNAL_XDPTOWP(dc, x + sz.cx, y);
133 break;
135 case TA_CENTER:
136 x -= sz.cx/2;
137 break;
139 case TA_RIGHT:
140 x -= sz.cx;
141 if(dc->textAlign & TA_UPDATECP) {
142 dc->CursPosX = INTERNAL_XDPTOWP(dc, x, y);
144 break;
147 switch(dc->textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
148 case TA_TOP:
149 y += physDev->font.tm.tmAscent;
150 break;
152 case TA_BASELINE:
153 break;
155 case TA_BOTTOM:
156 y -= physDev->font.tm.tmDescent;
157 break;
160 memcpy(strbuf, str, count * sizeof(WCHAR));
161 *(strbuf + count) = '\0';
163 if ((dc->backgroundMode != TRANSPARENT) && (bDrawBackground != FALSE))
165 PSDRV_WriteGSave(dc);
166 PSDRV_WriteNewPath(dc);
167 PSDRV_WriteRectangle(dc, x, y - physDev->font.tm.tmAscent, sz.cx,
168 physDev->font.tm.tmAscent +
169 physDev->font.tm.tmDescent);
170 PSDRV_WriteSetColor(dc, &physDev->bkColor);
171 PSDRV_WriteFill(dc);
172 PSDRV_WriteGRestore(dc);
175 PSDRV_WriteMoveTo(dc, x, y);
177 if(!lpDx)
178 PSDRV_WriteGlyphShow(dc, strbuf, lstrlenW(strbuf));
179 else {
180 INT i;
181 float dx = 0.0, dy = 0.0;
182 float cos_theta = cos(physDev->font.escapement * M_PI / 1800.0);
183 float sin_theta = sin(physDev->font.escapement * M_PI / 1800.0);
184 for(i = 0; i < count-1; i++) {
185 TRACE("lpDx[%d] = %d\n", i, lpDx[i]);
186 PSDRV_WriteGlyphShow(dc, &strbuf[i], 1);
187 dx += lpDx[i] * cos_theta;
188 dy -= lpDx[i] * sin_theta;
189 PSDRV_WriteMoveTo(dc, x + INTERNAL_XWSTODS(dc, dx),
190 y + INTERNAL_YWSTODS(dc, dy));
192 PSDRV_WriteGlyphShow(dc, &strbuf[i], 1);
196 * Underline and strikeout attributes.
198 if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) {
200 /* Get the thickness and the position for the underline attribute */
201 /* We'll use the same thickness for the strikeout attribute */
203 float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale;
204 float pos = -physDev->font.afm->UnderlinePosition * physDev->font.scale;
205 SIZE size;
206 INT escapement = physDev->font.escapement;
208 TRACE("Position = %f Thickness %f Escapement %d\n",
209 pos, thick, escapement);
211 /* Get the width of the text */
213 PSDRV_GetTextExtentPoint(dc, strbuf, lstrlenW(strbuf), &size);
214 size.cx = INTERNAL_XWSTODS(dc, size.cx);
216 /* Do the underline */
218 if (physDev->font.tm.tmUnderlined) {
219 PSDRV_WriteNewPath(dc); /* will be closed by WriteRectangle */
220 if (escapement != 0) /* rotated text */
222 PSDRV_WriteGSave(dc); /* save the graphics state */
223 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
225 /* temporarily rotate the coord system */
226 PSDRV_WriteRotate(dc, -escapement/10);
228 /* draw the underline relative to the starting point */
229 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
231 else
232 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
234 PSDRV_WriteFill(dc);
236 if (escapement != 0) /* rotated text */
237 PSDRV_WriteGRestore(dc); /* restore the graphics state */
240 /* Do the strikeout */
242 if (physDev->font.tm.tmStruckOut) {
243 pos = -physDev->font.tm.tmAscent / 2;
244 PSDRV_WriteNewPath(dc); /* will be closed by WriteRectangle */
245 if (escapement != 0) /* rotated text */
247 PSDRV_WriteGSave(dc); /* save the graphics state */
248 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
250 /* temporarily rotate the coord system */
251 PSDRV_WriteRotate(dc, -escapement/10);
253 /* draw the underline relative to the starting point */
254 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
256 else
257 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
259 PSDRV_WriteFill(dc);
261 if (escapement != 0) /* rotated text */
262 PSDRV_WriteGRestore(dc); /* restore the graphics state */
266 HeapFree(PSDRV_Heap, 0, strbuf);
267 return TRUE;