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(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
[];
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
)
64 Run
*run
= HeapAlloc(GetProcessHeap(),0,sizeof(Run
)*array_size
);
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]);
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(dev
->hdc
, &tm
);
88 offset
+= PSDRV_XWStoDS(dev
, tm
.tmAscent
- tm
.tmInternalLeading
);
94 GetTextExtentPointW(dev
->hdc
, str
, start
, &size
);
95 offset
+= PSDRV_XWStoDS(dev
, 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( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*lprect
, LPCWSTR str
, UINT count
,
135 PSDRV_PDEVICE
*physDev
= get_psdrv_dev( dev
);
137 BOOL bClipped
= FALSE
;
138 BOOL bOpaque
= FALSE
;
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
))
154 PSDRV_WriteGSave(dev
);
155 PSDRV_WriteRectangle(dev
, lprect
->left
, lprect
->top
, lprect
->right
- lprect
->left
,
156 lprect
->bottom
- lprect
->top
);
159 PSDRV_WriteSetColor(dev
, &physDev
->bkColor
);
160 PSDRV_WriteFill(dev
);
162 PSDRV_WriteGRestore(dev
);
163 PSDRV_ResetClip(dev
);
166 while (i
< run_count
)
170 if (i
!= run_count
- 1)
171 cnt
= runs
[i
+1].start
- runs
[i
].start
;
173 cnt
= count
- runs
[i
].start
;
175 PSDRV_SetFont(dev
, runs
[i
].vertical
);
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
);
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
);
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
);
198 PSDRV_ResetClip(dev
);
201 HeapFree(GetProcessHeap(),0,runs
);
205 /***********************************************************************
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
);
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 );
224 PSDRV_WriteMoveTo(dev
, x
, y
);
227 if(physDev
->font
.fontloc
== Download
)
228 PSDRV_WriteDownloadGlyphShow(dev
, str
, count
);
230 PSDRV_WriteBuiltinGlyphShow(dev
, str
, count
);
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);
240 PSDRV_WriteBuiltinGlyphShow(dev
, str
+ i
, 1);
243 offset
.x
+= lpDx
[i
* 2];
244 offset
.y
+= lpDx
[i
* 2 + 1];
248 PSDRV_WriteMoveTo(dev
, x
+ offset
.x
, y
+ offset
.y
);
250 if(physDev
->font
.fontloc
== Download
)
251 PSDRV_WriteDownloadGlyphShow(dev
, str
+ i
, 1);
253 PSDRV_WriteBuiltinGlyphShow(dev
, str
+ i
, 1);
256 HeapFree( GetProcessHeap(), 0, glyphs
);