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
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
34 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
35 LPCWSTR str
, UINT count
,
36 BOOL bDrawBackground
, const INT
*lpDx
);
38 /***********************************************************************
41 BOOL
PSDRV_ExtTextOut( PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
,
42 const RECT
*lprect
, LPCWSTR str
, UINT count
,
43 const INT
*lpDx
, INT breakExtra
)
46 BOOL bClipped
= FALSE
;
50 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x
, y
,
51 flags
, debugstr_wn(str
, count
), count
, lpDx
);
53 /* write font if not already written */
54 PSDRV_SetFont(physDev
);
56 PSDRV_SetClip(physDev
);
58 /* set clipping and/or draw background */
59 if ((flags
& (ETO_CLIPPED
| ETO_OPAQUE
)) && (lprect
!= NULL
))
62 LPtoDP( physDev
->hdc
, (POINT
*)&rect
, 2 );
63 PSDRV_WriteGSave(physDev
);
64 PSDRV_WriteRectangle(physDev
, rect
.left
, rect
.top
, rect
.right
- rect
.left
,
65 rect
.bottom
- rect
.top
);
67 if (flags
& ETO_OPAQUE
)
70 PSDRV_WriteGSave(physDev
);
71 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
72 PSDRV_WriteFill(physDev
);
73 PSDRV_WriteGRestore(physDev
);
76 if (flags
& ETO_CLIPPED
)
79 PSDRV_WriteClip(physDev
);
82 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, !(bClipped
&& bOpaque
), lpDx
);
83 PSDRV_WriteGRestore(physDev
);
87 bResult
= PSDRV_Text(physDev
, x
, y
, flags
, str
, count
, TRUE
, lpDx
);
90 PSDRV_ResetClip(physDev
);
94 /***********************************************************************
97 static BOOL
PSDRV_Text(PSDRV_PDEVICE
*physDev
, INT x
, INT y
, UINT flags
, LPCWSTR str
,
98 UINT count
, BOOL bDrawBackground
, const INT
*lpDx
)
105 UINT align
= GetTextAlign( physDev
->hdc
);
108 double cosEsc
, sinEsc
;
114 GetObjectW(GetCurrentObject(physDev
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
115 if(lf
.lfEscapement
!= 0) {
116 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
117 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
123 if(physDev
->font
.fontloc
== Download
) {
124 if(flags
& ETO_GLYPH_INDEX
)
125 glyphs
= (LPWORD
)str
;
127 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
128 GetGlyphIndicesW(physDev
->hdc
, str
, count
, glyphs
, 0);
134 if(align
& TA_UPDATECP
) GetCurrentPositionEx( physDev
->hdc
, &pt
);
135 LPtoDP(physDev
->hdc
, &pt
, 1);
139 if(physDev
->font
.fontloc
== Download
)
140 GetTextExtentPointI(physDev
->hdc
, glyphs
, count
, &sz
);
142 GetTextExtentPoint32W(physDev
->hdc
, str
, count
, &sz
);
144 if((char_extra
= GetTextCharacterExtra(physDev
->hdc
)) != 0) {
148 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
149 for(i
= 0; i
< count
; i
++) {
151 deltas
[i
] = lpDx
[i
] + char_extra
;
153 if(physDev
->font
.fontloc
== Download
)
154 GetTextExtentPointI(physDev
->hdc
, glyphs
+ i
, 1, &tmpsz
);
156 GetTextExtentPoint32W(physDev
->hdc
, str
+ i
, 1, &tmpsz
);
157 deltas
[i
] = tmpsz
.cx
;
166 /* Get the width of the last char and add on all the offsets */
167 if(physDev
->font
.fontloc
== Download
)
168 GetTextExtentPointI(physDev
->hdc
, glyphs
+ count
- 1, 1, &tmpsz
);
170 GetTextExtentPoint32W(physDev
->hdc
, str
+ count
- 1, 1, &tmpsz
);
171 for(i
= 0; i
< count
-1; i
++)
172 tmpsz
.cx
+= deltas
[i
];
173 sz
.cx
= tmpsz
.cx
; /* sz.cy remains untouched */
176 sz
.cx
= PSDRV_XWStoDS(physDev
, sz
.cx
);
177 sz
.cy
= PSDRV_YWStoDS(physDev
, sz
.cy
);
179 GetTextMetricsW(physDev
->hdc
, &tm
);
180 ascent
= abs(PSDRV_YWStoDS(physDev
, tm
.tmAscent
));
181 descent
= abs(PSDRV_YWStoDS(physDev
, tm
.tmDescent
));
183 TRACE("textAlign = %x\n", align
);
184 switch(align
& (TA_LEFT
| TA_CENTER
| TA_RIGHT
) ) {
186 if(align
& TA_UPDATECP
)
189 pt
.x
= x
+ sz
.cx
* cosEsc
;
190 pt
.y
= y
- sz
.cx
* sinEsc
;
191 DPtoLP( physDev
->hdc
, &pt
, 1 );
192 MoveToEx( physDev
->hdc
, pt
.x
, pt
.y
, NULL
);
197 x
-= sz
.cx
* cosEsc
/ 2;
198 y
+= sz
.cx
* sinEsc
/ 2;
204 if(align
& TA_UPDATECP
)
209 DPtoLP( physDev
->hdc
, &pt
, 1 );
210 MoveToEx( physDev
->hdc
, pt
.x
, pt
.y
, NULL
);
215 switch(align
& (TA_TOP
| TA_BASELINE
| TA_BOTTOM
) ) {
217 y
+= ascent
* cosEsc
;
218 x
+= ascent
* sinEsc
;
225 y
-= descent
* cosEsc
;
226 x
-= descent
* sinEsc
;
230 if ((GetBkMode( physDev
->hdc
) != TRANSPARENT
) && bDrawBackground
)
232 PSDRV_WriteGSave(physDev
);
233 PSDRV_WriteNewPath(physDev
);
234 PSDRV_WriteRectangle(physDev
, x
, y
- ascent
, sz
.cx
,
236 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
237 PSDRV_WriteFill(physDev
);
238 PSDRV_WriteGRestore(physDev
);
241 PSDRV_WriteMoveTo(physDev
, x
, y
);
244 if(physDev
->font
.fontloc
== Download
)
245 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
, count
);
247 PSDRV_WriteBuiltinGlyphShow(physDev
, str
, count
);
251 float dx
= 0.0, dy
= 0.0;
252 float cos_theta
= cos(physDev
->font
.escapement
* M_PI
/ 1800.0);
253 float sin_theta
= sin(physDev
->font
.escapement
* M_PI
/ 1800.0);
254 for(i
= 0; i
< count
-1; i
++) {
255 TRACE("lpDx[%d] = %d\n", i
, deltas
[i
]);
256 if(physDev
->font
.fontloc
== Download
)
257 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
259 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
260 dx
+= deltas
[i
] * cos_theta
;
261 dy
-= deltas
[i
] * sin_theta
;
262 PSDRV_WriteMoveTo(physDev
, x
+ PSDRV_XWStoDS(physDev
, dx
),
263 y
+ PSDRV_YWStoDS(physDev
, dy
));
265 if(physDev
->font
.fontloc
== Download
)
266 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
268 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
270 HeapFree(GetProcessHeap(), 0, deltas
);
274 * Underline and strikeout attributes.
276 if ((tm
.tmUnderlined
) || (tm
.tmStruckOut
)) {
278 /* Get the thickness and the position for the underline attribute */
279 /* We'll use the same thickness for the strikeout attribute */
281 INT escapement
= physDev
->font
.escapement
;
283 /* Do the underline */
285 if (tm
.tmUnderlined
) {
286 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
287 if (escapement
!= 0) /* rotated text */
289 PSDRV_WriteGSave(physDev
); /* save the graphics state */
290 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
292 /* temporarily rotate the coord system */
293 PSDRV_WriteRotate(physDev
, -escapement
/10);
295 /* draw the underline relative to the starting point */
296 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.underlinePosition
,
297 sz
.cx
, physDev
->font
.underlineThickness
);
300 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.underlinePosition
,
301 sz
.cx
, physDev
->font
.underlineThickness
);
303 PSDRV_WriteFill(physDev
);
305 if (escapement
!= 0) /* rotated text */
306 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
309 /* Do the strikeout */
311 if (tm
.tmStruckOut
) {
312 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
313 if (escapement
!= 0) /* rotated text */
315 PSDRV_WriteGSave(physDev
); /* save the graphics state */
316 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
318 /* temporarily rotate the coord system */
319 PSDRV_WriteRotate(physDev
, -escapement
/10);
321 /* draw the line relative to the starting point */
322 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.strikeoutPosition
,
323 sz
.cx
, physDev
->font
.strikeoutThickness
);
326 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.strikeoutPosition
,
327 sz
.cx
, physDev
->font
.strikeoutThickness
);
329 PSDRV_WriteFill(physDev
);
331 if (escapement
!= 0) /* rotated text */
332 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
336 if(glyphs
&& glyphs
!= str
) HeapFree(GetProcessHeap(), 0, glyphs
);