user32/tests: Link directly to imm32.
[wine.git] / dlls / wineps.drv / text.c
blob767b1529c243753892c2cf28c29c0904d05497e5
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(PHYSDEV dev, 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[] DECLSPEC_HIDDEN;
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(PHYSDEV dev, 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(dev->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(dev->hdc, &tm);
88 offset += PSDRV_XWStoDS(dev, tm.tmAscent - tm.tmInternalLeading);
91 if (start > 0)
93 SIZE size;
94 GetTextExtentPointW(dev->hdc, str, start, &size);
95 offset += PSDRV_XWStoDS(dev, 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 CDECL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count,
133 const INT *lpDx )
135 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
136 BOOL bResult = TRUE;
137 BOOL bClipped = FALSE;
138 BOOL bOpaque = FALSE;
139 Run *runs = NULL;
140 int run_count = 0;
141 int i = 0;
143 TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x, y,
144 flags, debugstr_wn(str, count), count, lpDx);
146 if(physDev->job.id == 0) return FALSE;
148 runs = build_vertical_runs(dev, flags, str, count, &run_count);
150 /* set draw background */
151 if ((flags & ETO_OPAQUE) && (lprect != NULL))
153 PSDRV_SetClip(dev);
154 PSDRV_WriteGSave(dev);
155 PSDRV_WriteRectangle(dev, lprect->left, lprect->top, lprect->right - lprect->left,
156 lprect->bottom - lprect->top);
158 bOpaque = TRUE;
159 PSDRV_WriteSetColor(dev, &physDev->bkColor);
160 PSDRV_WriteFill(dev);
162 PSDRV_WriteGRestore(dev);
163 PSDRV_ResetClip(dev);
166 while (i < run_count)
168 int cnt;
170 if (i != run_count - 1)
171 cnt = runs[i+1].start- runs[i].start;
172 else
173 cnt = count - runs[i].start;
175 PSDRV_SetFont(dev, runs[i].vertical);
177 PSDRV_SetClip(dev);
179 /* set clipping */
180 if ((flags & ETO_CLIPPED) && (lprect != NULL))
182 PSDRV_WriteGSave(dev);
184 PSDRV_WriteRectangle(dev, lprect->left, lprect->top, lprect->right - lprect->left,
185 lprect->bottom - lprect->top);
187 bClipped = TRUE;
188 PSDRV_WriteClip(dev);
190 bResult = PSDRV_Text(dev, runs[i].x+x, runs[i].y+y, flags, &str[runs[i].start], cnt, !(bClipped && bOpaque), (lpDx)?&lpDx[runs[i].start]:NULL);
192 PSDRV_WriteGRestore(dev);
194 else
195 bResult = PSDRV_Text(dev, runs[i].x+x, runs[i].y+y, flags, &str[runs[i].start], cnt, TRUE, (lpDx)?&lpDx[runs[i].start]:NULL);
197 i++;
198 PSDRV_ResetClip(dev);
201 HeapFree(GetProcessHeap(),0,runs);
202 return bResult;
205 /***********************************************************************
206 * PSDRV_Text
208 static BOOL PSDRV_Text(PHYSDEV dev, INT x, INT y, UINT flags, LPCWSTR str,
209 UINT count, BOOL bDrawBackground, const INT *lpDx)
211 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
212 WORD *glyphs = NULL;
214 if (!count)
215 return TRUE;
217 if(physDev->font.fontloc == Download && !(flags & ETO_GLYPH_INDEX))
219 glyphs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WORD) );
220 GetGlyphIndicesW( dev->hdc, str, count, glyphs, 0 );
221 str = glyphs;
224 PSDRV_WriteMoveTo(dev, x, y);
226 if(!lpDx) {
227 if(physDev->font.fontloc == Download)
228 PSDRV_WriteDownloadGlyphShow(dev, str, count);
229 else
230 PSDRV_WriteBuiltinGlyphShow(dev, str, count);
232 else {
233 UINT i;
234 POINT offset = {0, 0};
236 for(i = 0; i < count-1; i++) {
237 if(physDev->font.fontloc == Download)
238 PSDRV_WriteDownloadGlyphShow(dev, str + i, 1);
239 else
240 PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1);
241 if(flags & ETO_PDY)
243 offset.x += lpDx[i * 2];
244 offset.y += lpDx[i * 2 + 1];
246 else
247 offset.x += lpDx[i];
248 PSDRV_WriteMoveTo(dev, x + offset.x, y + offset.y);
250 if(physDev->font.fontloc == Download)
251 PSDRV_WriteDownloadGlyphShow(dev, str + i, 1);
252 else
253 PSDRV_WriteBuiltinGlyphShow(dev, str + i, 1);
256 HeapFree( GetProcessHeap(), 0, glyphs );
257 return TRUE;