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 PSDRV_SetClip(physDev
);
52 /* set clipping and/or draw background */
53 if ((flags
& (ETO_CLIPPED
| ETO_OPAQUE
)) && (lprect
!= NULL
))
56 LPtoDP( physDev
->hdc
, (POINT
*)&rect
, 2 );
57 PSDRV_WriteGSave(physDev
);
58 PSDRV_WriteRectangle(physDev
, rect
.left
, rect
.top
, rect
.right
- rect
.left
,
59 rect
.bottom
- rect
.top
);
61 if (flags
& ETO_OPAQUE
)
64 PSDRV_WriteGSave(physDev
);
65 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
66 PSDRV_WriteFill(physDev
);
67 PSDRV_WriteGRestore(physDev
);
70 if (flags
& ETO_CLIPPED
)
73 PSDRV_WriteClip(physDev
);
76 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, !(bClipped
&& bOpaque
), lpDx
);
77 PSDRV_WriteGRestore(physDev
);
81 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, TRUE
, lpDx
);
84 PSDRV_ResetClip(physDev
);
88 /***********************************************************************
91 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
, LPCWSTR str
,
92 UINT count
, BOOL bDrawBackground
, const INT
*lpDx
)
100 UINT align
= GetTextAlign( physDev
->hdc
);
103 double cosEsc
, sinEsc
;
109 GetObjectW(GetCurrentObject(physDev
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
110 if(lf
.lfEscapement
!= 0) {
111 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
112 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
118 if(physDev
->font
.fontloc
== Download
) {
119 if(flags
& ETO_GLYPH_INDEX
)
120 glyphs
= (LPWORD
)str
;
122 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
123 GetGlyphIndicesW(physDev
->hdc
, str
, count
, glyphs
, 0);
127 if(align
& TA_UPDATECP
) {
134 LPtoDP(physDev
->hdc
, &pt
, 1);
138 if(physDev
->font
.fontloc
== Download
)
139 GetTextExtentPointI(physDev
->hdc
, glyphs
, count
, &sz
);
141 GetTextExtentPoint32W(physDev
->hdc
, str
, count
, &sz
);
143 if((char_extra
= GetTextCharacterExtra(physDev
->hdc
)) != 0) {
147 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
148 for(i
= 0; i
< count
; i
++) {
150 deltas
[i
] = lpDx
[i
] + char_extra
;
152 if(physDev
->font
.fontloc
== Download
)
153 GetTextExtentPointI(physDev
->hdc
, glyphs
+ i
, 1, &tmpsz
);
155 GetTextExtentPoint32W(physDev
->hdc
, str
+ i
, 1, &tmpsz
);
156 deltas
[i
] = tmpsz
.cx
;
165 /* Get the width of the last char and add on all the offsets */
166 if(physDev
->font
.fontloc
== Download
)
167 GetTextExtentPointI(physDev
->hdc
, glyphs
+ count
- 1, 1, &tmpsz
);
169 GetTextExtentPoint32W(physDev
->hdc
, str
+ count
- 1, 1, &tmpsz
);
170 for(i
= 0; i
< count
-1; i
++)
171 tmpsz
.cx
+= deltas
[i
];
172 sz
.cx
= tmpsz
.cx
; /* sz.cy remains untouched */
175 sz
.cx
= PSDRV_XWStoDS(physDev
, sz
.cx
);
176 sz
.cy
= PSDRV_YWStoDS(physDev
, sz
.cy
);
178 GetTextMetricsW(physDev
->hdc
, &tm
);
179 ascent
= PSDRV_YWStoDS(physDev
, tm
.tmAscent
);
180 descent
= PSDRV_YWStoDS(physDev
, tm
.tmDescent
);
182 TRACE("textAlign = %x\n", align
);
183 switch(align
& (TA_LEFT
| TA_CENTER
| TA_RIGHT
) ) {
185 if(align
& TA_UPDATECP
)
188 pt
.x
= x
+ sz
.cx
* cosEsc
;
189 pt
.y
= y
- sz
.cx
* sinEsc
;
190 DPtoLP( physDev
->hdc
, &pt
, 1 );
197 x
-= sz
.cx
* cosEsc
/ 2;
198 y
+= sz
.cx
* sinEsc
/ 2;
204 if(align
& TA_UPDATECP
)
209 DPtoLP( physDev
->hdc
, &pt
, 1 );
216 switch(align
& (TA_TOP
| TA_BASELINE
| TA_BOTTOM
) ) {
218 y
+= ascent
* cosEsc
;
219 x
+= ascent
* sinEsc
;
226 y
-= descent
* cosEsc
;
227 x
-= descent
* sinEsc
;
231 if ((GetBkMode( physDev
->hdc
) != TRANSPARENT
) && bDrawBackground
)
233 PSDRV_WriteGSave(physDev
);
234 PSDRV_WriteNewPath(physDev
);
235 PSDRV_WriteRectangle(physDev
, x
, y
- ascent
, sz
.cx
,
237 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
238 PSDRV_WriteFill(physDev
);
239 PSDRV_WriteGRestore(physDev
);
242 PSDRV_WriteMoveTo(physDev
, x
, y
);
245 if(physDev
->font
.fontloc
== Download
)
246 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
, count
);
248 PSDRV_WriteBuiltinGlyphShow(physDev
, str
, count
);
252 float dx
= 0.0, dy
= 0.0;
253 float cos_theta
= cos(physDev
->font
.escapement
* M_PI
/ 1800.0);
254 float sin_theta
= sin(physDev
->font
.escapement
* M_PI
/ 1800.0);
255 for(i
= 0; i
< count
-1; i
++) {
256 TRACE("lpDx[%d] = %d\n", i
, deltas
[i
]);
257 if(physDev
->font
.fontloc
== Download
)
258 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
260 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
261 dx
+= deltas
[i
] * cos_theta
;
262 dy
-= deltas
[i
] * sin_theta
;
263 PSDRV_WriteMoveTo(physDev
, x
+ PSDRV_XWStoDS(physDev
, dx
),
264 y
+ PSDRV_YWStoDS(physDev
, dy
));
266 if(physDev
->font
.fontloc
== Download
)
267 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
269 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
271 HeapFree(GetProcessHeap(), 0, deltas
);
275 * Underline and strikeout attributes.
277 if ((tm
.tmUnderlined
) || (tm
.tmStruckOut
)) {
279 /* Get the thickness and the position for the underline attribute */
280 /* We'll use the same thickness for the strikeout attribute */
282 INT escapement
= physDev
->font
.escapement
;
284 /* Do the underline */
286 if (tm
.tmUnderlined
) {
287 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
288 if (escapement
!= 0) /* rotated text */
290 PSDRV_WriteGSave(physDev
); /* save the graphics state */
291 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
293 /* temporarily rotate the coord system */
294 PSDRV_WriteRotate(physDev
, -escapement
/10);
296 /* draw the underline relative to the starting point */
297 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.underlinePosition
,
298 sz
.cx
, physDev
->font
.underlineThickness
);
301 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.underlinePosition
,
302 sz
.cx
, physDev
->font
.underlineThickness
);
304 PSDRV_WriteFill(physDev
);
306 if (escapement
!= 0) /* rotated text */
307 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
310 /* Do the strikeout */
312 if (tm
.tmStruckOut
) {
313 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
314 if (escapement
!= 0) /* rotated text */
316 PSDRV_WriteGSave(physDev
); /* save the graphics state */
317 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
319 /* temporarily rotate the coord system */
320 PSDRV_WriteRotate(physDev
, -escapement
/10);
322 /* draw the line relative to the starting point */
323 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.strikeoutPosition
,
324 sz
.cx
, physDev
->font
.strikeoutThickness
);
327 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.strikeoutPosition
,
328 sz
.cx
, physDev
->font
.strikeoutThickness
);
330 PSDRV_WriteFill(physDev
);
332 if (escapement
!= 0) /* rotated text */
333 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
337 if(glyphs
&& glyphs
!= str
) HeapFree(GetProcessHeap(), 0, glyphs
);