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
);
105 if(physDev
->font
.fontloc
== Download
) {
106 if(flags
& ETO_GLYPH_INDEX
)
107 glyphs
= (LPWORD
)str
;
109 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
110 GetGlyphIndicesW(physDev
->hdc
, str
, count
, glyphs
, 0);
114 if(align
& TA_UPDATECP
) {
121 LPtoDP(physDev
->hdc
, &pt
, 1);
125 if(physDev
->font
.fontloc
== Download
)
126 GetTextExtentPointI(physDev
->hdc
, glyphs
, count
, &sz
);
128 GetTextExtentPoint32W(physDev
->hdc
, str
, count
, &sz
);
130 if((char_extra
= GetTextCharacterExtra(physDev
->hdc
)) != 0) {
134 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
135 for(i
= 0; i
< count
; i
++) {
136 deltas
[i
] = char_extra
;
138 deltas
[i
] += lpDx
[i
];
140 if(physDev
->font
.fontloc
== Download
)
141 GetTextExtentPointI(physDev
->hdc
, glyphs
+ i
, 1, &tmpsz
);
143 GetTextExtentPoint32W(physDev
->hdc
, str
+ i
, 1, &tmpsz
);
144 deltas
[i
] += tmpsz
.cx
;
153 /* Get the width of the last char and add on all the offsets */
154 if(physDev
->font
.fontloc
== Download
)
155 GetTextExtentPointI(physDev
->hdc
, glyphs
+ count
- 1, 1, &tmpsz
);
157 GetTextExtentPoint32W(physDev
->hdc
, str
+ count
- 1, 1, &tmpsz
);
158 for(i
= 0; i
< count
-1; i
++)
159 tmpsz
.cx
+= deltas
[i
];
160 sz
.cx
= tmpsz
.cx
; /* sz.cy remains untouched */
163 sz
.cx
= INTERNAL_XWSTODS(dc
, sz
.cx
);
164 sz
.cy
= INTERNAL_YWSTODS(dc
, sz
.cy
);
166 GetTextMetricsW(physDev
->hdc
, &tm
);
167 ascent
= INTERNAL_YWSTODS(dc
, tm
.tmAscent
);
168 descent
= INTERNAL_YWSTODS(dc
, tm
.tmDescent
);
170 TRACE("textAlign = %x\n", align
);
171 switch(align
& (TA_LEFT
| TA_CENTER
| TA_RIGHT
) ) {
173 if(align
& TA_UPDATECP
)
178 DPtoLP( physDev
->hdc
, &pt
, 1 );
189 if(align
& TA_UPDATECP
)
194 DPtoLP( physDev
->hdc
, &pt
, 1 );
200 switch(align
& (TA_TOP
| TA_BASELINE
| TA_BOTTOM
) ) {
213 if ((GetBkMode( physDev
->hdc
) != TRANSPARENT
) && bDrawBackground
)
215 PSDRV_WriteGSave(physDev
);
216 PSDRV_WriteNewPath(physDev
);
217 PSDRV_WriteRectangle(physDev
, x
, y
- ascent
, sz
.cx
,
219 PSDRV_WriteSetColor(physDev
, &physDev
->bkColor
);
220 PSDRV_WriteFill(physDev
);
221 PSDRV_WriteGRestore(physDev
);
224 PSDRV_WriteMoveTo(physDev
, x
, y
);
227 if(physDev
->font
.fontloc
== Download
)
228 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
, count
);
230 PSDRV_WriteBuiltinGlyphShow(physDev
, str
, count
);
234 float dx
= 0.0, dy
= 0.0;
235 float cos_theta
= cos(physDev
->font
.escapement
* M_PI
/ 1800.0);
236 float sin_theta
= sin(physDev
->font
.escapement
* M_PI
/ 1800.0);
237 for(i
= 0; i
< count
-1; i
++) {
238 TRACE("lpDx[%d] = %d\n", i
, deltas
[i
]);
239 if(physDev
->font
.fontloc
== Download
)
240 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
242 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
243 dx
+= deltas
[i
] * cos_theta
;
244 dy
-= deltas
[i
] * sin_theta
;
245 PSDRV_WriteMoveTo(physDev
, x
+ INTERNAL_XWSTODS(dc
, dx
),
246 y
+ INTERNAL_YWSTODS(dc
, dy
));
248 if(physDev
->font
.fontloc
== Download
)
249 PSDRV_WriteDownloadGlyphShow(physDev
, glyphs
+ i
, 1);
251 PSDRV_WriteBuiltinGlyphShow(physDev
, str
+ i
, 1);
253 HeapFree(GetProcessHeap(), 0, deltas
);
257 * Underline and strikeout attributes.
259 if ((tm
.tmUnderlined
) || (tm
.tmStruckOut
)) {
261 /* Get the thickness and the position for the underline attribute */
262 /* We'll use the same thickness for the strikeout attribute */
264 INT escapement
= physDev
->font
.escapement
;
266 /* Do the underline */
268 if (tm
.tmUnderlined
) {
269 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
270 if (escapement
!= 0) /* rotated text */
272 PSDRV_WriteGSave(physDev
); /* save the graphics state */
273 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
275 /* temporarily rotate the coord system */
276 PSDRV_WriteRotate(physDev
, -escapement
/10);
278 /* draw the underline relative to the starting point */
279 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.underlinePosition
,
280 sz
.cx
, physDev
->font
.underlineThickness
);
283 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.underlinePosition
,
284 sz
.cx
, physDev
->font
.underlineThickness
);
286 PSDRV_WriteFill(physDev
);
288 if (escapement
!= 0) /* rotated text */
289 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
292 /* Do the strikeout */
294 if (tm
.tmStruckOut
) {
295 PSDRV_WriteNewPath(physDev
); /* will be closed by WriteRectangle */
296 if (escapement
!= 0) /* rotated text */
298 PSDRV_WriteGSave(physDev
); /* save the graphics state */
299 PSDRV_WriteMoveTo(physDev
, x
, y
); /* move to the start */
301 /* temporarily rotate the coord system */
302 PSDRV_WriteRotate(physDev
, -escapement
/10);
304 /* draw the line relative to the starting point */
305 PSDRV_WriteRRectangle(physDev
, 0, -physDev
->font
.strikeoutPosition
,
306 sz
.cx
, physDev
->font
.strikeoutThickness
);
309 PSDRV_WriteRectangle(physDev
, x
, y
- physDev
->font
.strikeoutPosition
,
310 sz
.cx
, physDev
->font
.strikeoutThickness
);
312 PSDRV_WriteFill(physDev
);
314 if (escapement
!= 0) /* rotated text */
315 PSDRV_WriteGRestore(physDev
); /* restore the graphics state */
319 if(glyphs
&& glyphs
!= str
) HeapFree(GetProcessHeap(), 0, glyphs
);