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
23 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
28 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
29 LPCWSTR str
, UINT count
,
30 BOOL bDrawBackground
, const INT
*lpDx
);
32 /***********************************************************************
35 BOOL
PSDRV_ExtTextOut( PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
36 const RECT
*lprect
, LPCWSTR str
, UINT count
,
40 BOOL bClipped
= FALSE
;
44 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x
, y
,
45 flags
, debugstr_wn(str
, count
), count
, lpDx
);
47 /* write font if not already written */
48 PSDRV_SetFont(physDev
);
50 /* set clipping and/or draw background */
51 if ((flags
& (ETO_CLIPPED
| ETO_OPAQUE
)) && (lprect
!= NULL
))
54 LPtoDP( physDev
->hdc
, (POINT
*)&rect
, 2 );
55 PSDRV_WriteGSave(physDev
);
56 PSDRV_WriteRectangle(physDev
, rect
.left
, rect
.top
, rect
.right
- rect
.left
,
57 rect
.bottom
- rect
.top
);
59 if (flags
& ETO_OPAQUE
)
62 PSDRV_WriteGSave(physDev
);
63 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
64 PSDRV_WriteFill(physDev
);
65 PSDRV_WriteGRestore(physDev
);
68 if (flags
& ETO_CLIPPED
)
71 PSDRV_WriteClip(physDev
);
74 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, !(bClipped
&& bOpaque
), lpDx
);
75 PSDRV_WriteGRestore(physDev
);
79 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, TRUE
, lpDx
);
85 /***********************************************************************
88 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
, LPCWSTR str
,
89 UINT count
, BOOL bDrawBackground
, const INT
*lpDx
)
97 UINT align
= GetTextAlign( physDev
->hdc
);
103 if(physDev
->font
.fontloc
== Download
) {
104 if(flags
& ETO_GLYPH_INDEX
)
105 glyphs
= (LPWORD
)str
;
107 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
108 GetGlyphIndicesW(physDev
->hdc
, str
, count
, glyphs
, 0);
112 if(align
& TA_UPDATECP
) {
119 LPtoDP(physDev
->hdc
, &pt
, 1);
123 if(physDev
->font
.fontloc
== Download
)
124 GetTextExtentPointI(physDev
->hdc
, glyphs
, count
, &sz
);
126 GetTextExtentPoint32W(physDev
->hdc
, str
, count
, &sz
);
131 /* Get the width of the last char and add on all the offsets */
132 if(physDev
->font
.fontloc
== Download
)
133 GetTextExtentPointI(physDev
->hdc
, glyphs
+ count
- 1, 1, &tmpsz
);
135 GetTextExtentPoint32W(physDev
->hdc
, str
+ count
- 1, 1, &tmpsz
);
136 for(i
= 0; i
< count
-1; i
++)
138 sz
.cx
= tmpsz
.cx
; /* sz.cy remains untouched */
141 sz
.cx
= INTERNAL_XWSTODS(dc
, sz
.cx
);
142 sz
.cy
= INTERNAL_YWSTODS(dc
, sz
.cy
);
144 GetTextMetricsW(physDev
->hdc
, &tm
);
145 ascent
= INTERNAL_YWSTODS(dc
, tm
.tmAscent
);
146 descent
= INTERNAL_YWSTODS(dc
, tm
.tmDescent
);
148 TRACE("textAlign = %x\n", align
);
149 switch(align
& (TA_LEFT
| TA_CENTER
| TA_RIGHT
) ) {
151 if(align
& TA_UPDATECP
)
156 DPtoLP( physDev
->hdc
, &pt
, 1 );
167 if(align
& TA_UPDATECP
)
172 DPtoLP( physDev
->hdc
, &pt
, 1 );
178 switch(align
& (TA_TOP
| TA_BASELINE
| TA_BOTTOM
) ) {
191 if ((GetBkMode( physDev
->hdc
) != TRANSPARENT
) && bDrawBackground
)
193 PSDRV_WriteGSave(physDev
);
194 PSDRV_WriteNewPath(physDev
);
195 PSDRV_WriteRectangle(physDev
, x
, y
- ascent
, sz
.cx
,
197 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
198 PSDRV_WriteFill(physDev
);
199 PSDRV_WriteGRestore(physDev
);
202 PSDRV_WriteMoveTo(physDev
, x
, y
);
205 if(physDev
->font
.fontloc
== Download
)
206 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
, count
);
208 PSDRV_WriteBuiltinGlyphShow(physDev
, str
, count
);
212 float dx
= 0.0, dy
= 0.0;
213 float cos_theta
= cos(physDev
->font
.escapement
* M_PI
/ 1800.0);
214 float sin_theta
= sin(physDev
->font
.escapement
* M_PI
/ 1800.0);
215 for(i
= 0; i
< count
-1; i
++) {
216 TRACE("lpDx[%d] = %d\n", i
, lpDx
[i
]);
217 if(physDev
->font
.fontloc
== Download
)
218 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
220 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
221 dx
+= lpDx
[i
] * cos_theta
;
222 dy
-= lpDx
[i
] * sin_theta
;
223 PSDRV_WriteMoveTo(physDev
, x
+ INTERNAL_XWSTODS(dc
, dx
),
224 y
+ INTERNAL_YWSTODS(dc
, dy
));
226 if(physDev
->font
.fontloc
== Download
)
227 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
229 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
233 * Underline and strikeout attributes.
235 if ((tm
.tmUnderlined
) || (tm
.tmStruckOut
)) {
237 /* Get the thickness and the position for the underline attribute */
238 /* We'll use the same thickness for the strikeout attribute */
240 INT escapement
= physDev
->font
.escapement
;
242 /* Do the underline */
244 if (tm
.tmUnderlined
) {
245 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
246 if (escapement
!= 0) /* rotated text */
248 PSDRV_WriteGSave(physDev
); /* save the graphics state */
249 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
251 /* temporarily rotate the coord system */
252 PSDRV_WriteRotate(physDev
, -escapement
/10);
254 /* draw the underline relative to the starting point */
255 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.underlinePosition
,
256 sz
.cx
, physDev
->font
.underlineThickness
);
259 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.underlinePosition
,
260 sz
.cx
, physDev
->font
.underlineThickness
);
262 PSDRV_WriteFill(physDev
);
264 if (escapement
!= 0) /* rotated text */
265 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
268 /* Do the strikeout */
270 if (tm
.tmStruckOut
) {
271 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
272 if (escapement
!= 0) /* rotated text */
274 PSDRV_WriteGSave(physDev
); /* save the graphics state */
275 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
277 /* temporarily rotate the coord system */
278 PSDRV_WriteRotate(physDev
, -escapement
/10);
280 /* draw the line relative to the starting point */
281 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.strikeoutPosition
,
282 sz
.cx
, physDev
->font
.strikeoutThickness
);
285 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.strikeoutPosition
,
286 sz
.cx
, physDev
->font
.strikeoutThickness
);
288 PSDRV_WriteFill(physDev
);
290 if (escapement
!= 0) /* rotated text */
291 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
295 if(glyphs
&& glyphs
!= str
) HeapFree(GetProcessHeap(), 0, glyphs
);