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
22 #include "wine/debug.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 /***********************************************************************
33 BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
34 const RECT *lprect, LPCWSTR str, UINT count,
37 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
39 BOOL bClipped = FALSE;
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 */
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);
58 PSDRV_WriteRectangle(dc, rect.left, rect.top, rect.right - rect.left,
59 rect.bottom - rect.top);
61 if (flags & ETO_OPAQUE)
65 PSDRV_WriteSetColor(dc, &physDev->bkColor);
67 PSDRV_WriteGRestore(dc);
70 if (flags & ETO_CLIPPED)
76 bResult = PSDRV_Text(dc, x, y, str, count, !(bClipped && bOpaque), lpDx);
77 PSDRV_WriteGRestore(dc);
81 bResult = PSDRV_Text(dc, x, y, str, count, TRUE, lpDx);
87 /***********************************************************************
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;
100 strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR));
102 WARN("HeapAlloc failed\n");
106 if(dc->textAlign & TA_UPDATECP) {
111 x = INTERNAL_XWPTODP(dc, x, y);
112 y = INTERNAL_YWPTODP(dc, x, y);
114 GetTextExtentPoint32W(dc->hSelf, str, count, &sz);
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++)
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) ) {
130 if(dc->textAlign & TA_UPDATECP) {
131 dc->CursPosX = INTERNAL_XDPTOWP(dc, x + sz.cx, y);
141 if(dc->textAlign & TA_UPDATECP) {
142 dc->CursPosX = INTERNAL_XDPTOWP(dc, x, y);
147 switch(dc->textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
149 y += physDev->font.tm.tmAscent;
156 y -= physDev->font.tm.tmDescent;
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);
172 PSDRV_WriteGRestore(dc);
175 PSDRV_WriteMoveTo(dc, x, y);
178 PSDRV_WriteGlyphShow(dc, strbuf, lstrlenW(strbuf));
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;
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);
232 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
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);
257 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
261 if (escapement != 0) /* rotated text */
262 PSDRV_WriteGRestore(dc); /* restore the graphics state */
266 HeapFree(PSDRV_Heap, 0, strbuf);