1/*
2 * Copyright 1992, 1993 by TOSHIBA Corp.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of TOSHIBA not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission. TOSHIBA make no representations about the
11 * suitability of this software for any purpose.  It is provided "as is"
12 * without express or implied warranty.
13 *
14 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 * SOFTWARE.
21 *
22 * Author: Katsuhisa Yano	TOSHIBA Corp.
23 *			   	mopi@osa.ilab.toshiba.co.jp
24 */
25/*
26 * Copyright 1995 by FUJITSU LIMITED
27 * This is source code modified by FUJITSU LIMITED under the Joint
28 * Development Agreement for the CDE/Motif PST.
29 */
30/*
31 * Modifiers: Jeff Walls, Paul Anderson (HEWLETT-PACKARD)
32 */
33
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37#include "Xlibint.h"
38#include "XomGeneric.h"
39#include <stdio.h>
40
41/* For VW/UDC */
42
43static int
44is_rotate(
45    XOC		oc,
46    XFontStruct	*font)
47{
48    XOCGenericPart	*gen = XOC_GENERIC(oc);
49    FontSet		font_set;
50    VRotate		vrotate;
51    int			font_set_count;
52    int			vrotate_num;
53
54    font_set = gen->font_set;
55    font_set_count = gen->font_set_num;
56    for( ; font_set_count-- ; font_set++) {
57	if((font_set->vrotate_num > 0) && (font_set->vrotate)) {
58	    vrotate = font_set->vrotate;
59	    vrotate_num = font_set->vrotate_num;
60	    for( ; vrotate_num-- ; vrotate++)
61		if(vrotate->font == font)
62		    return True;
63	}
64    }
65    return False;
66}
67
68static int
69is_codemap(
70    XOC		oc,
71    XFontStruct	*font)
72{
73    XOCGenericPart	*gen = XOC_GENERIC(oc);
74    FontSet		font_set;
75    FontData		vmap;
76    int			font_set_count;
77    int			vmap_num;
78
79    font_set = gen->font_set;
80    font_set_count = gen->font_set_num;
81    for( ; font_set_count-- ; font_set++) {
82	if(font_set->vmap_num > 0) {
83	    vmap = font_set->vmap;
84	    vmap_num = font_set->vmap_num;
85	    for( ; vmap_num-- ; vmap++)
86		if(vmap->font == font)
87		    return True;
88	}
89    }
90    return False;
91}
92
93static int
94draw_vertical(
95    Display	*dpy,
96    Drawable	d,
97    XOC		oc,
98    GC		gc,
99    XFontStruct	*font,
100    Bool	is_xchar2b,
101    int		x, int y,
102    XPointer	text,
103    int		length)
104{
105    XChar2b	*buf2b;
106    char	*buf;
107    int		wx = 0, wy = 0;
108    int		direction = 0;
109    int		font_ascent_return = 0, font_descent_return = 0;
110    int		i;
111    XCharStruct	overall;
112
113    wy = y;
114    if (is_xchar2b) {
115	for(i = 0, buf2b = (XChar2b *) text ; i < length ; i++, buf2b++) {
116	    if(is_rotate(oc, font) == True) {
117		XTextExtents16(font, buf2b, 1,
118			       &direction, &font_ascent_return,
119			       &font_descent_return, &overall);
120		wx = x - (int)((overall.rbearing - overall.lbearing) >> 1) -
121			 (int) overall.lbearing;
122		wy += overall.ascent;
123		XDrawString16(dpy, d, gc, wx, wy, buf2b, 1);
124		wy += overall.descent;
125	    } else {
126		wx = x - (int)((font->max_bounds.rbearing -
127				font->min_bounds.lbearing) >> 1) -
128			 (int) font->min_bounds.lbearing;
129		wy += font->max_bounds.ascent;
130		XDrawString16(dpy, d, gc, wx, wy, buf2b, 1);
131		wy += font->max_bounds.descent;
132	    }
133	}
134    } else {
135	for(i = 0, buf = (char *)text ; i < length && *buf ; i++, buf++) {
136	    if(is_rotate(oc, font) == True) {
137		XTextExtents(font, buf, 1,
138			     &direction, &font_ascent_return,
139			     &font_descent_return, &overall);
140		wx = x - (int)((overall.rbearing - overall.lbearing) >> 1) -
141			 (int) overall.lbearing;
142		wy += overall.ascent;
143		XDrawString(dpy, d, gc, wx, wy, buf, 1);
144		wy += overall.descent;
145	    } else {
146		wx = x - (int)((font->max_bounds.rbearing -
147				font->min_bounds.lbearing) >> 1) -
148			 (int) font->min_bounds.lbearing;
149		wy += font->max_bounds.ascent;
150		XDrawString(dpy, d, gc, wx, wy, buf, 1);
151		wy += font->max_bounds.descent;
152	    }
153	}
154    }
155    return wy;
156}
157
158#define VMAP          0
159#define VROTATE       1
160#define FONTSCOPE     2
161
162static int
163DrawStringWithFontSet(
164    Display *dpy,
165    Drawable d,
166    XOC oc,
167    FontSet fs,
168    GC gc,
169    int x, int y,
170    XPointer text,
171    int length)
172{
173    XFontStruct *font;
174    Bool is_xchar2b;
175    unsigned char *ptr;
176    int ptr_len, char_len = 0;
177    FontData fd;
178    int ret = 0;
179
180    ptr = (unsigned char *)text;
181    is_xchar2b = fs->is_xchar2b;
182
183    while (length > 0) {
184        fd = _XomGetFontDataFromFontSet(fs,
185			ptr,length,&ptr_len,is_xchar2b,FONTSCOPE);
186	if(ptr_len <= 0)
187	    break;
188
189       /* First, see if the "Best Match" font for the FontSet was set.
190	* If it was, use that font.  If it was not set, then use the
191	* font defined by font_set->font_data[0] (which is what
192	* _XomGetFontDataFromFontSet() always seems to return for
193	* non-VW text).  Note that given the new algorithm in
194	* parse_fontname() and parse_fontdata(), fs->font will
195	* *always* contain good data.   We should probably remove
196	* the check for "fd->font", but we won't :-) -- jjw/pma (HP)
197	*/
198        if((font = fs->font) == (XFontStruct *) NULL){
199
200	    if(fd == (FontData) NULL ||
201	       (font = fd->font) == (XFontStruct *) NULL)
202		break;
203        }
204
205	switch(oc->core.orientation) {
206	  case XOMOrientation_LTR_TTB:
207	  case XOMOrientation_RTL_TTB:
208            XSetFont(dpy, gc, font->fid);
209
210	    if (is_xchar2b) {
211		char_len = ptr_len / sizeof(XChar2b);
212		XDrawString16(dpy, d, gc, x, y, (XChar2b *)ptr, char_len);
213		x += XTextWidth16(font, (XChar2b *)ptr, char_len);
214            } else {
215		char_len = ptr_len;
216		XDrawString(dpy, d, gc, x, y, (char *)ptr, char_len);
217		x += XTextWidth(font, (char *)ptr, char_len);
218	    }
219	    break;
220	  case XOMOrientation_TTB_RTL:
221	  case XOMOrientation_TTB_LTR:
222	    if(fs->font == font) {
223		fd = _XomGetFontDataFromFontSet(fs,
224			ptr,length,&ptr_len,is_xchar2b,VMAP);
225		if(ptr_len <= 0)
226		    break;
227		if(fd == (FontData) NULL ||
228		   (font = fd->font) == (XFontStruct *) NULL)
229		    break;
230
231		if(is_codemap(oc, fd->font) == False) {
232		    fd = _XomGetFontDataFromFontSet(fs,
233			     ptr,length,&ptr_len,is_xchar2b,VROTATE);
234		    if(ptr_len <= 0)
235			break;
236		    if(fd == (FontData) NULL ||
237		       (font = fd->font) == (XFontStruct *) NULL)
238			break;
239		}
240	    }
241
242	    if(is_xchar2b)
243		char_len = ptr_len / sizeof(XChar2b);
244	    else
245		char_len = ptr_len;
246            XSetFont(dpy, gc, font->fid);
247	    y = draw_vertical(dpy, d, oc, gc, font, is_xchar2b, x, y,
248			       (char *)ptr, char_len);
249	    break;
250
251	  case XOMOrientation_Context:
252	    /* never used? */
253	    break;
254	}
255
256	if(char_len <= 0)
257	    break;
258
259        length -= char_len;
260        ptr += ptr_len;
261    }
262
263    switch(oc->core.orientation) {
264      case XOMOrientation_LTR_TTB:
265      case XOMOrientation_RTL_TTB:
266	ret = x;
267	break;
268      case XOMOrientation_TTB_RTL:
269      case XOMOrientation_TTB_LTR:
270	ret = y;
271	break;
272      case XOMOrientation_Context:
273	/* not used? */
274	break;
275    }
276    return ret;
277}
278
279/* For VW/UDC */
280
281int
282_XomGenericDrawString(
283    Display *dpy,
284    Drawable d,
285    XOC oc,
286    GC gc,
287    int x, int y,
288    XOMTextType type,
289    XPointer text,
290    int length)
291{
292    XlcConv conv;
293    XFontStruct *font;
294    Bool is_xchar2b;
295/* VW/UDC */
296    XPointer args[3];
297    FontSet fs;
298/* VW/UDC */
299    XChar2b xchar2b_buf[BUFSIZ], *buf;
300    int start_x = x;
301    int start_y = y;
302    int left = 0, buf_len = 0;
303    int next = 0;
304
305    conv = _XomInitConverter(oc, type);
306    if (conv == NULL)
307	return -1;
308
309    args[0] = (XPointer) &font;
310    args[1] = (XPointer) &is_xchar2b;
311    args[2] = (XPointer) &fs;
312
313    while (length > 0) {
314	buf = xchar2b_buf;
315	left = buf_len = BUFSIZ;
316
317	if (_XomConvert(oc, conv, (XPointer *) &text, &length,
318			(XPointer *) &buf, &left, args, 3) < 0)
319	    break;
320	buf_len -= left;
321
322/* For VW/UDC */
323	next = DrawStringWithFontSet(dpy, d, oc, fs, gc, x, y,
324				     (XPointer)xchar2b_buf, buf_len);
325
326	switch(oc->core.orientation) {
327	  case XOMOrientation_LTR_TTB:
328	  case XOMOrientation_RTL_TTB:
329	    x = next;
330	    break;
331	  case XOMOrientation_TTB_RTL:
332	  case XOMOrientation_TTB_LTR:
333	    y = next;
334	    break;
335          case XOMOrientation_Context:
336	    /* not used */
337	    break;
338	}
339/* For VW/UDC */
340    }
341
342    x -= start_x;
343    y -= start_y;
344
345    return x;
346}
347
348int
349_XmbGenericDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
350		      _Xconst char *text, int length)
351{
352    return _XomGenericDrawString(dpy, d, oc, gc, x, y, XOMMultiByte,
353				 (XPointer) text, length);
354}
355
356int
357_XwcGenericDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
358		      _Xconst wchar_t *text, int length)
359{
360    return _XomGenericDrawString(dpy, d, oc, gc, x, y, XOMWideChar,
361				 (XPointer) text, length);
362}
363
364int
365_Xutf8GenericDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
366			_Xconst char *text, int length)
367{
368    return _XomGenericDrawString(dpy, d, oc, gc, x, y, XOMUtf8String,
369				 (XPointer) text, length);
370}
371