ddraw: Set dwMaxVertexCount to 2048.
[wine.git] / dlls / wineps.drv / text.c
blob4041f2175d6bc1741f52f214c97d5ca47618517c
1 /*
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
20 #include <string.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <math.h>
25 #include "windef.h"
26 #include "wingdi.h"
27 #include "psdrv.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
32 typedef struct tagRun {
33 INT start;
34 BOOL vertical;
35 INT x;
36 INT y;
37 }Run;
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)
61 BOOL last_vert;
62 INT start, end;
63 INT array_size = 5;
64 Run *run = HeapAlloc(GetProcessHeap(),0,sizeof(Run)*array_size);
65 int index = 0;
66 LOGFONTW lf;
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]);
71 start = end = 0;
72 while (start < count)
74 int offset = 0;
76 while (end < count && check_unicode_tategaki(str[end]) == last_vert)
77 end++;
79 run[index].start = start;
80 run[index].vertical = last_vert;
81 run[index].x = 0;
82 run[index].y = 0;
84 if (run[index].vertical)
86 TEXTMETRICW tm;
87 GetTextMetricsW(ctx->hdc, &tm);
88 offset += PSDRV_XWStoDS(ctx, tm.tmAscent - tm.tmInternalLeading);
91 if (start > 0)
93 SIZE size;
94 GetTextExtentPointW(ctx->hdc, str, start, &size);
95 offset += PSDRV_XWStoDS(ctx, size.cx);
98 if (offset)
100 double angle;
101 angle = (lf.lfEscapement / 10.0) * M_PI / 180.0;
102 run[index].y = -offset * sin(angle);
103 run[index].x = -offset * cos(angle);
106 index ++;
107 if (index >= array_size)
109 array_size *=2;
110 run = HeapReAlloc(GetProcessHeap(), 0, run, sizeof(Run)*array_size);
112 start = end;
113 if (start < count)
114 last_vert = check_unicode_tategaki(str[end]);
117 else
119 run[0].start = 0;
120 run[0].vertical = 0;
121 run[0].x = 0;
122 run[0].y = 0;
123 index = 1;
125 *run_count = index;
126 return run;
129 /***********************************************************************
130 * PSDRV_ExtTextOut
132 BOOL PSDRV_ExtTextOut( print_ctx *ctx, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count,
133 const INT *lpDx )
135 BOOL bResult = TRUE;
136 BOOL bClipped = FALSE;
137 BOOL bOpaque = FALSE;
138 Run *runs = NULL;
139 int run_count = 0;
140 int i = 0;
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))
152 PSDRV_SetClip(ctx);
153 PSDRV_WriteGSave(ctx);
154 PSDRV_WriteRectangle(ctx, lprect->left, lprect->top, lprect->right - lprect->left,
155 lprect->bottom - lprect->top);
157 bOpaque = TRUE;
158 PSDRV_WriteSetColor(ctx, &ctx->bkColor);
159 PSDRV_WriteFill(ctx);
161 PSDRV_WriteGRestore(ctx);
162 PSDRV_ResetClip(ctx);
165 while (i < run_count)
167 int cnt;
169 if (i != run_count - 1)
170 cnt = runs[i+1].start- runs[i].start;
171 else
172 cnt = count - runs[i].start;
174 PSDRV_SetFont(ctx, runs[i].vertical);
176 PSDRV_SetClip(ctx);
178 /* set clipping */
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);
186 bClipped = TRUE;
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);
193 else
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);
196 i++;
197 PSDRV_ResetClip(ctx);
200 HeapFree(GetProcessHeap(),0,runs);
201 return bResult;
204 /***********************************************************************
205 * PSDRV_Text
207 static BOOL PSDRV_Text(print_ctx *ctx, INT x, INT y, UINT flags, LPCWSTR str,
208 UINT count, BOOL bDrawBackground, const INT *lpDx)
210 WORD *glyphs = NULL;
212 if (!count)
213 return TRUE;
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 );
219 str = glyphs;
222 PSDRV_WriteMoveTo(ctx, x, y);
224 if(!lpDx) {
225 if(ctx->font.fontloc == Download)
226 PSDRV_WriteDownloadGlyphShow(ctx, str, count);
227 else
228 PSDRV_WriteBuiltinGlyphShow(ctx, str, count);
230 else {
231 UINT i;
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);
237 else
238 PSDRV_WriteBuiltinGlyphShow(ctx, str + i, 1);
239 if(flags & ETO_PDY)
241 offset.x += lpDx[i * 2];
242 offset.y += lpDx[i * 2 + 1];
244 else
245 offset.x += lpDx[i];
246 PSDRV_WriteMoveTo(ctx, x + offset.x, y + offset.y);
248 if(ctx->font.fontloc == Download)
249 PSDRV_WriteDownloadGlyphShow(ctx, str + i, 1);
250 else
251 PSDRV_WriteBuiltinGlyphShow(ctx, str + i, 1);
254 HeapFree( GetProcessHeap(), 0, glyphs );
255 return TRUE;