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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
32 typedef struct tagRun
{
39 static BOOL
PSDRV_Text(print_ctx
*ctx
, INT x
, INT y
, UINT flags
,
40 LPCWSTR str
, UINT count
,
41 BOOL bDrawBackground
, const INT
*lpDx
);
43 extern const unsigned short vertical_orientation_table
[];
45 static BOOL
check_unicode_tategaki(WCHAR uchar
)
47 unsigned short orientation
= vertical_orientation_table
[vertical_orientation_table
[vertical_orientation_table
[uchar
>> 8]+((uchar
>> 4) & 0x0f)]+ (uchar
& 0xf)];
49 /* Type: U or Type: Tu */
50 /* TODO Type: Tr, Normally the logic for Tr would be that if
51 Typographical substitution occurs, then do not rotate. However
52 we have no facility at present to determine if GetGlyphIndices is
53 successfully performing substitutions (well formed font) or not.
54 Thus we are erroring on the side of the font being well formed,
55 doing typographical substitution, and so we are not doing rotation */
56 return (orientation
== 1 || orientation
== 2 || orientation
== 3);
59 static Run
* build_vertical_runs(print_ctx
*ctx
, UINT flags
, LPCWSTR str
, UINT count
, INT
*run_count
)
64 Run
*run
= HeapAlloc(GetProcessHeap(),0,sizeof(Run
)*array_size
);
68 if (count
&& str
&& (!(flags
& ETO_GLYPH_INDEX
)) && GetObjectW( GetCurrentObject(ctx
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
) && (lf
.lfFaceName
[0] == '@'))
70 last_vert
= check_unicode_tategaki(str
[0]);
76 while (end
< count
&& check_unicode_tategaki(str
[end
]) == last_vert
)
79 run
[index
].start
= start
;
80 run
[index
].vertical
= last_vert
;
84 if (run
[index
].vertical
)
87 GetTextMetricsW(ctx
->hdc
, &tm
);
88 offset
+= PSDRV_XWStoDS(ctx
, tm
.tmAscent
- tm
.tmInternalLeading
);
94 GetTextExtentPointW(ctx
->hdc
, str
, start
, &size
);
95 offset
+= PSDRV_XWStoDS(ctx
, size
.cx
);
101 angle
= (lf
.lfEscapement
/ 10.0) * M_PI
/ 180.0;
102 run
[index
].y
= -offset
* sin(angle
);
103 run
[index
].x
= -offset
* cos(angle
);
107 if (index
>= array_size
)
110 run
= HeapReAlloc(GetProcessHeap(), 0, run
, sizeof(Run
)*array_size
);
114 last_vert
= check_unicode_tategaki(str
[end
]);
129 /***********************************************************************
132 BOOL
PSDRV_ExtTextOut( print_ctx
*ctx
, INT x
, INT y
, UINT flags
, const RECT
*lprect
, LPCWSTR str
, UINT count
,
136 BOOL bClipped
= FALSE
;
137 BOOL bOpaque
= FALSE
;
142 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x
, y
,
143 flags
, debugstr_wn(str
, count
), count
, lpDx
);
145 if(ctx
->job
.id
== 0) return FALSE
;
147 runs
= build_vertical_runs(ctx
, flags
, str
, count
, &run_count
);
149 /* set draw background */
150 if ((flags
& ETO_OPAQUE
) && (lprect
!= NULL
))
153 PSDRV_WriteGSave(ctx
);
154 PSDRV_WriteRectangle(ctx
, lprect
->left
, lprect
->top
, lprect
->right
- lprect
->left
,
155 lprect
->bottom
- lprect
->top
);
158 PSDRV_WriteSetColor(ctx
, &ctx
->bkColor
);
159 PSDRV_WriteFill(ctx
);
161 PSDRV_WriteGRestore(ctx
);
162 PSDRV_ResetClip(ctx
);
165 while (i
< run_count
)
169 if (i
!= run_count
- 1)
170 cnt
= runs
[i
+1].start
- runs
[i
].start
;
172 cnt
= count
- runs
[i
].start
;
174 PSDRV_SetFont(ctx
, runs
[i
].vertical
);
179 if ((flags
& ETO_CLIPPED
) && (lprect
!= NULL
))
181 PSDRV_WriteGSave(ctx
);
183 PSDRV_WriteRectangle(ctx
, lprect
->left
, lprect
->top
, lprect
->right
- lprect
->left
,
184 lprect
->bottom
- lprect
->top
);
187 PSDRV_WriteClip(ctx
);
189 bResult
= PSDRV_Text(ctx
, runs
[i
].x
+x
, runs
[i
].y
+y
, flags
, &str
[runs
[i
].start
], cnt
, !(bClipped
&& bOpaque
), (lpDx
)?&lpDx
[runs
[i
].start
]:NULL
);
191 PSDRV_WriteGRestore(ctx
);
194 bResult
= PSDRV_Text(ctx
, runs
[i
].x
+x
, runs
[i
].y
+y
, flags
, &str
[runs
[i
].start
], cnt
, TRUE
, (lpDx
)?&lpDx
[runs
[i
].start
]:NULL
);
197 PSDRV_ResetClip(ctx
);
200 HeapFree(GetProcessHeap(),0,runs
);
204 /***********************************************************************
207 static BOOL
PSDRV_Text(print_ctx
*ctx
, INT x
, INT y
, UINT flags
, LPCWSTR str
,
208 UINT count
, BOOL bDrawBackground
, const INT
*lpDx
)
215 if(ctx
->font
.fontloc
== Download
&& !(flags
& ETO_GLYPH_INDEX
))
217 glyphs
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(WORD
) );
218 GetGlyphIndicesW( ctx
->hdc
, str
, count
, glyphs
, 0 );
222 PSDRV_WriteMoveTo(ctx
, x
, y
);
225 if(ctx
->font
.fontloc
== Download
)
226 PSDRV_WriteDownloadGlyphShow(ctx
, str
, count
);
228 PSDRV_WriteBuiltinGlyphShow(ctx
, str
, count
);
232 POINT offset
= {0, 0};
234 for(i
= 0; i
< count
-1; i
++) {
235 if(ctx
->font
.fontloc
== Download
)
236 PSDRV_WriteDownloadGlyphShow(ctx
, str
+ i
, 1);
238 PSDRV_WriteBuiltinGlyphShow(ctx
, str
+ i
, 1);
241 offset
.x
+= lpDx
[i
* 2];
242 offset
.y
+= lpDx
[i
* 2 + 1];
246 PSDRV_WriteMoveTo(ctx
, x
+ offset
.x
, y
+ offset
.y
);
248 if(ctx
->font
.fontloc
== Download
)
249 PSDRV_WriteDownloadGlyphShow(ctx
, str
+ i
, 1);
251 PSDRV_WriteBuiltinGlyphShow(ctx
, str
+ i
, 1);
254 HeapFree( GetProcessHeap(), 0, glyphs
);