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
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
33 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
34 LPCWSTR str
, UINT count
,
35 BOOL bDrawBackground
, const INT
*lpDx
);
37 /***********************************************************************
40 BOOL
PSDRV_ExtTextOut( PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
41 const RECT
*lprect
, LPCWSTR str
, UINT count
,
42 const INT
*lpDx
, INT breakExtra
)
45 BOOL bClipped
= FALSE
;
49 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x
, y
,
50 flags
, debugstr_wn(str
, count
), count
, lpDx
);
52 /* write font if not already written */
53 PSDRV_SetFont(physDev
);
55 PSDRV_SetClip(physDev
);
57 /* set clipping and/or draw background */
58 if ((flags
& (ETO_CLIPPED
| ETO_OPAQUE
)) && (lprect
!= NULL
))
61 LPtoDP( physDev
->hdc
, (POINT
*)&rect
, 2 );
62 PSDRV_WriteGSave(physDev
);
63 PSDRV_WriteRectangle(physDev
, rect
.left
, rect
.top
, rect
.right
- rect
.left
,
64 rect
.bottom
- rect
.top
);
66 if (flags
& ETO_OPAQUE
)
69 PSDRV_WriteGSave(physDev
);
70 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
71 PSDRV_WriteFill(physDev
);
72 PSDRV_WriteGRestore(physDev
);
75 if (flags
& ETO_CLIPPED
)
78 PSDRV_WriteClip(physDev
);
81 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, !(bClipped
&& bOpaque
), lpDx
);
82 PSDRV_WriteGRestore(physDev
);
86 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, TRUE
, lpDx
);
89 PSDRV_ResetClip(physDev
);
93 /***********************************************************************
96 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
, LPCWSTR str
,
97 UINT count
, BOOL bDrawBackground
, const INT
*lpDx
)
104 UINT align
= GetTextAlign( physDev
->hdc
);
107 double cosEsc
, sinEsc
;
113 GetObjectW(GetCurrentObject(physDev
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
114 if(lf
.lfEscapement
!= 0) {
115 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
116 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
122 if(physDev
->font
.fontloc
== Download
) {
123 if(flags
& ETO_GLYPH_INDEX
)
124 glyphs
= (LPWORD
)str
;
126 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
127 GetGlyphIndicesW(physDev
->hdc
, str
, count
, glyphs
, 0);
133 if(align
& TA_UPDATECP
) GetCurrentPositionEx( physDev
->hdc
, &pt
);
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 );
191 MoveToEx( physDev
->hdc
, pt
.x
, pt
.y
, NULL
);
196 x
-= sz
.cx
* cosEsc
/ 2;
197 y
+= sz
.cx
* sinEsc
/ 2;
203 if(align
& TA_UPDATECP
)
208 DPtoLP( physDev
->hdc
, &pt
, 1 );
209 MoveToEx( physDev
->hdc
, pt
.x
, pt
.y
, NULL
);
214 switch(align
& (TA_TOP
| TA_BASELINE
| TA_BOTTOM
) ) {
216 y
+= ascent
* cosEsc
;
217 x
+= ascent
* sinEsc
;
224 y
-= descent
* cosEsc
;
225 x
-= descent
* sinEsc
;
229 if ((GetBkMode( physDev
->hdc
) != TRANSPARENT
) && bDrawBackground
)
231 PSDRV_WriteGSave(physDev
);
232 PSDRV_WriteNewPath(physDev
);
233 PSDRV_WriteRectangle(physDev
, x
, y
- ascent
, sz
.cx
,
235 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
236 PSDRV_WriteFill(physDev
);
237 PSDRV_WriteGRestore(physDev
);
240 PSDRV_WriteMoveTo(physDev
, x
, y
);
243 if(physDev
->font
.fontloc
== Download
)
244 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
, count
);
246 PSDRV_WriteBuiltinGlyphShow(physDev
, str
, count
);
250 float dx
= 0.0, dy
= 0.0;
251 float cos_theta
= cos(physDev
->font
.escapement
* M_PI
/ 1800.0);
252 float sin_theta
= sin(physDev
->font
.escapement
* M_PI
/ 1800.0);
253 for(i
= 0; i
< count
-1; i
++) {
254 TRACE("lpDx[%d] = %d\n", i
, deltas
[i
]);
255 if(physDev
->font
.fontloc
== Download
)
256 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
258 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
259 dx
+= deltas
[i
] * cos_theta
;
260 dy
-= deltas
[i
] * sin_theta
;
261 PSDRV_WriteMoveTo(physDev
, x
+ PSDRV_XWStoDS(physDev
, dx
),
262 y
+ PSDRV_YWStoDS(physDev
, dy
));
264 if(physDev
->font
.fontloc
== Download
)
265 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
267 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
269 HeapFree(GetProcessHeap(), 0, deltas
);
273 * Underline and strikeout attributes.
275 if ((tm
.tmUnderlined
) || (tm
.tmStruckOut
)) {
277 /* Get the thickness and the position for the underline attribute */
278 /* We'll use the same thickness for the strikeout attribute */
280 INT escapement
= physDev
->font
.escapement
;
282 /* Do the underline */
284 if (tm
.tmUnderlined
) {
285 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
286 if (escapement
!= 0) /* rotated text */
288 PSDRV_WriteGSave(physDev
); /* save the graphics state */
289 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
291 /* temporarily rotate the coord system */
292 PSDRV_WriteRotate(physDev
, -escapement
/10);
294 /* draw the underline relative to the starting point */
295 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.underlinePosition
,
296 sz
.cx
, physDev
->font
.underlineThickness
);
299 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.underlinePosition
,
300 sz
.cx
, physDev
->font
.underlineThickness
);
302 PSDRV_WriteFill(physDev
);
304 if (escapement
!= 0) /* rotated text */
305 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
308 /* Do the strikeout */
310 if (tm
.tmStruckOut
) {
311 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
312 if (escapement
!= 0) /* rotated text */
314 PSDRV_WriteGSave(physDev
); /* save the graphics state */
315 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
317 /* temporarily rotate the coord system */
318 PSDRV_WriteRotate(physDev
, -escapement
/10);
320 /* draw the line relative to the starting point */
321 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.strikeoutPosition
,
322 sz
.cx
, physDev
->font
.strikeoutThickness
);
325 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.strikeoutPosition
,
326 sz
.cx
, physDev
->font
.strikeoutThickness
);
328 PSDRV_WriteFill(physDev
);
330 if (escapement
!= 0) /* rotated text */
331 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
335 if(glyphs
&& glyphs
!= str
) HeapFree(GetProcessHeap(), 0, glyphs
);