OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [gfx/] [mw/] [current/] [src/] [engine/] [devfont.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
3
 * T1lib Adobe type1 routines contributed by Vidar Hokstad
4
 * Freetype TrueType routines contributed by Martin Jolicoeur
5
 * Han Zi Ku routines contributed by Tanghao and Jauming
6
 *
7
 * Device-independent font and text drawing routines
8
 *
9
 * These routines do the necessary range checking, clipping, and cursor
10
 * overwriting checks, and then call the lower level device dependent
11
 * routines to actually do the drawing.  The lower level routines are
12
 * only called when it is known that all the pixels to be drawn are
13
 * within the device area and are visible.
14
 */
15
/*#define NDEBUG*/
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <assert.h>
20
#include <string.h>
21
 
22
#include "device.h"
23
#if (UNIX | DOS_DJGPP)
24
#define strcmpi strcasecmp
25
#endif
26
 
27
#if HAVE_T1LIB_SUPPORT
28
#include <t1lib.h>
29
#define T1LIB_USE_AA_HIGH
30
 
31
typedef struct {
32
        PMWFONTPROCS    fontprocs;      /* common hdr*/
33
        MWCOORD         fontsize;
34
        int             fontrotation;
35
        int             fontattr;
36
 
37
        int             fontid;         /* t1lib stuff*/
38
} MWT1LIBFONT, *PMWT1LIBFONT;
39
 
40
static int  t1lib_init(PSD psd);
41
static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
42
static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
43
                const void *text, int cc, int flags);
44
static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
45
static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
46
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
47
static void t1lib_destroyfont(PMWFONT pfont);
48
 
49
/* handling routines for MWT1LIBFONT*/
50
static MWFONTPROCS t1lib_procs = {
51
        MWTF_ASCII,                     /* routines expect ascii*/
52
        t1lib_getfontinfo,
53
        t1lib_gettextsize,
54
        NULL,                           /* gettextbits*/
55
        t1lib_destroyfont,
56
        t1lib_drawtext,
57
        NULL,                           /* setfontsize*/
58
        NULL,                           /* setfontrotation*/
59
        NULL,                           /* setfontattr*/
60
};
61
#endif
62
 
63
#ifdef T1LIB_USE_AA_HIGH
64
typedef unsigned long OUTPIXELVAL;
65
#else
66
typedef MWPIXELVAL OUTPIXELVAL;
67
#endif
68
 
69
#if HAVE_FREETYPE_SUPPORT
70
#include <freetype/freetype.h>
71
#include <freetype/ftxkern.h>
72
#include <freetype/ftnameid.h>
73
#include <freetype/ftxcmap.h>
74
#include <freetype/ftxwidth.h>
75
#include <math.h>
76
 
77
#ifndef FREETYPE_FONT_DIR
78
#define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
79
#endif
80
 
81
#if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3
82
#error "You must link with freetype lib version 1.3.x +, and not freetype 2. \
83
Download it at http://www.freetype.org or http://microwindows.org"
84
#endif
85
 
86
typedef struct {
87
        PMWFONTPROCS    fontprocs;      /* common hdr*/
88
        MWCOORD         fontsize;
89
        int             fontrotation;
90
        int             fontattr;
91
 
92
        TT_Face         face;           /* freetype stuff*/
93
        TT_Instance     instance;
94
        TT_CharMap      char_map;
95
        TT_Kerning      directory;
96
        TT_Matrix       matrix;
97
        TT_Glyph        glyph;
98
        MWBOOL          can_kern;
99
        short           last_glyph_code;
100
        short           last_pen_pos;
101
} MWFREETYPEFONT, *PMWFREETYPEFONT;
102
 
103
static int  freetype_init(PSD psd);
104
static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
105
                int attr);
106
static MWBOOL freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
107
static void freetype_gettextsize(PMWFONT pfont, const void *text,
108
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
109
static void freetype_destroyfont(PMWFONT pfont);
110
static void freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
111
                const void *text, int cc, int flags);
112
static void freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize);
113
static void freetype_setfontrotation(PMWFONT pfont, int tenthdegrees);
114
 
115
/* handling routines for MWFREETYPEFONT*/
116
static MWFONTPROCS freetype_procs = {
117
        MWTF_UC16,                      /* routines expect unicode 16*/
118
        freetype_getfontinfo,
119
        freetype_gettextsize,
120
        NULL,                           /* gettextbits*/
121
        freetype_destroyfont,
122
        freetype_drawtext,
123
        freetype_setfontsize,
124
        freetype_setfontrotation,
125
        NULL,                           /* setfontattr*/
126
};
127
 
128
static TT_Engine        engine;         /* THE ONLY freetype engine */
129
#endif /* HAVE_FREETYPE_SUPPORT*/
130
 
131
#if HAVE_HZK_SUPPORT
132
/*
133
 * 12x12 and 16x16 ascii and chinese fonts
134
 * Big5 and GB2312 encodings supported
135
 */
136
#define MAX_PATH        256
137
typedef struct {
138
        int     width;
139
        int     height;
140
        int     size;
141
        unsigned long use_count;
142
        char *  pFont;
143
        char    file[MAX_PATH + 1];
144
} HZKFONT;
145
 
146
static int use_big5=1;
147
static HZKFONT CFont[2];        /* font cache*/
148
static HZKFONT AFont[2];        /* font cache*/
149
 
150
/* jmt: moved inside MWHZKFONT*/
151
static int afont_width = 8;
152
static int cfont_width = 16;
153
static int font_height = 16;
154
static char *afont_address;
155
static char *cfont_address;
156
 
157
typedef struct {
158
        PMWFONTPROCS    fontprocs;      /* common hdr*/
159
        MWCOORD         fontsize;
160
        int             fontrotation;
161
        int             fontattr;
162
 
163
        HZKFONT         CFont;          /* hzkfont stuff */
164
        HZKFONT         AFont;
165
        int             afont_width;
166
        int             cfont_width;
167
        int             font_height;
168
        char            *afont_address;
169
        char            *cfont_address;
170
} MWHZKFONT, *PMWHZKFONT;
171
 
172
static int  hzk_init(PSD psd);
173
static PMWHZKFONT hzk_createfont(const char *name, MWCOORD height,int fontattr);
174
static MWBOOL hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
175
static void hzk_gettextsize(PMWFONT pfont, const void *text,
176
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
177
#if 0
178
static void hzk_gettextbits(PMWFONT pfont, int ch, IMAGEBITS *retmap,
179
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
180
static void hzk_setfontrotation(PMWFONT pfont, int tenthdegrees);
181
#endif
182
static void hzk_destroyfont(PMWFONT pfont);
183
static void hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
184
                const void *text, int cc, int flags);
185
static void hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize);
186
 
187
/* handling routines for MWHZKFONT*/
188
static MWFONTPROCS hzk_procs = {
189
        MWTF_ASCII,                     /* routines expect ASCII*/
190
        hzk_getfontinfo,
191
        hzk_gettextsize,
192
        NULL,                           /* hzk_gettextbits*/
193
        hzk_destroyfont,
194
        hzk_drawtext,
195
        hzk_setfontsize,
196
        NULL,                           /* setfontrotation*/
197
        NULL,                           /* setfontattr*/
198
};
199
 
200
static int
201
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
202
#endif /* HAVE_HZK_SUPPORT*/
203
 
204
static PMWFONT  gr_pfont;               /* current font*/
205
 
206
/* temp extern decls*/
207
extern MWPIXELVAL gr_foreground;
208
extern MWPIXELVAL gr_background;
209
extern MWBOOL gr_usebg;
210
 
211
static int  utf8_to_utf16(const unsigned char *utf8, int cc,
212
                unsigned short *unicode16);
213
 
214
#if FONTMAPPER
215
/* entry point for font selection*/
216
int select_font(const PMWLOGFONT plogfont, char *physname);
217
#endif
218
 
219
/*
220
 * Set the font for future calls.
221
 */
222
PMWFONT
223
GdSetFont(PMWFONT pfont)
224
{
225
        PMWFONT oldfont = gr_pfont;
226
 
227
        gr_pfont = pfont;
228
        return oldfont;
229
}
230
 
231
/*
232
 * Select a font, based on various parameters.
233
 * If plogfont is specified, name and height parms are ignored
234
 * and instead used from MWLOGFONT.
235
 *
236
 * If height is 0, return builtin font from passed name.
237
 * Otherwise find builtin font best match based on height.
238
 */
239
PMWFONT
240
GdCreateFont(PSD psd, const char *name, MWCOORD height,
241
        const PMWLOGFONT plogfont)
242
{
243
        int             i;
244
        int             fontht;
245
        int             fontno;
246
        int             fontclass;
247
        int             fontattr = 0;
248
        PMWFONT         pfont;
249
        PMWCOREFONT     pf = psd->builtin_fonts;
250
        MWFONTINFO      fontinfo;
251
        MWSCREENINFO    scrinfo;
252
        char            fontname[128];
253
 
254
        GdGetScreenInfo(psd, &scrinfo);
255
 
256
        /* if plogfont not specified, use name and height*/
257
        if (!plogfont) {
258
                if (!name)
259
                        name = MWFONT_SYSTEM_VAR;
260
                strcpy(fontname, name);
261
                fontclass = MWLF_CLASS_ANY;
262
        } else {
263
#if FONTMAPPER
264
                /* otherwise, use MWLOGFONT name and height*/
265
                fontclass = select_font(plogfont, fontname);
266
#else
267
                if (!name)
268
                        name = MWFONT_SYSTEM_VAR;
269
                strcpy(fontname, name);
270
                fontclass = MWLF_CLASS_ANY;
271
#endif
272
                height = plogfont->lfHeight;
273
                if (plogfont->lfUnderline)
274
                        fontattr = MWTF_UNDERLINE;
275
        }
276
        height = abs(height);
277
 
278
        if (!fontclass)
279
                goto first;
280
 
281
        /* use builtin screen fonts, FONT_xxx, if height is 0 */
282
        if (height == 0 || fontclass == MWLF_CLASS_ANY ||
283
            fontclass == MWLF_CLASS_BUILTIN) {
284
                for(i = 0; i < scrinfo.fonts; ++i) {
285
                        if(!strcmpi(pf[i].name, fontname)) {
286
                                pf[i].fontsize = pf[i].cfont->height;
287
                                pf[i].fontattr = fontattr;
288
                                return (PMWFONT)&pf[i];
289
                        }
290
                }
291
 
292
                /* return first builtin font*/
293
                if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
294
                        goto first;
295
        }
296
 
297
#if HAVE_HZK_SUPPORT
298
        /* Make sure the library is initialized */
299
        if (hzk_init(psd)) {
300
                pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
301
                if(pfont)
302
                        return pfont;
303
                fprintf(stderr, "hzk_createfont: %s not found\n", name);
304
        }
305
#endif
306
 
307
#if HAVE_FREETYPE_SUPPORT
308
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_FREETYPE) {
309
                if (freetype_init(psd)) {
310
                /* auto antialias for height > 14 for kaffe*/
311
                        if (plogfont && plogfont->lfHeight > 14 &&
312
                                plogfont->lfQuality)
313
                                        fontattr |= MWTF_ANTIALIAS;
314
 
315
                        pfont = (PMWFONT)freetype_createfont(fontname, height,
316
                                        fontattr);
317
                        if(pfont) {
318
                                /* temp kaffe kluge*/
319
                                pfont->fontattr |= FS_FREETYPE;
320
                                return pfont;
321
                        }
322
                        DPRINTF("freetype_createfont: %s,%d not found\n",
323
                                fontname, height);
324
                }
325
        }
326
#endif
327
 
328
#if HAVE_T1LIB_SUPPORT
329
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_T1LIB) {
330
                if (t1lib_init(psd)) {
331
                        pfont = (PMWFONT)t1lib_createfont(fontname, height,
332
                                        fontattr);
333
                        if(pfont)
334
                                return pfont;
335
                        DPRINTF("t1lib_createfont: %s,%d not found\n",
336
                                fontname, height);
337
                }
338
        }
339
#endif
340
 
341
        /* find builtin font closest in height*/
342
        if(height != 0) {
343
                fontno = 0;
344
                height = abs(height);
345
                fontht = MAX_MWCOORD;
346
                for(i = 0; i < scrinfo.fonts; ++i) {
347
                        pfont = (PMWFONT)&pf[i];
348
                        GdGetFontInfo(pfont, &fontinfo);
349
                        if(fontht > abs(height-fontinfo.height)) {
350
                                fontno = i;
351
                                fontht = abs(height-fontinfo.height);
352
                        }
353
                }
354
                pf[fontno].fontsize = pf[fontno].cfont->height;
355
                pf[fontno].fontattr = fontattr;
356
                return (PMWFONT)&pf[fontno];
357
        }
358
 
359
first:
360
        /* Return first builtin font*/
361
        pf->fontsize = pf->cfont->height;
362
        pf->fontattr = fontattr;
363
        return (PMWFONT)&pf[0];
364
}
365
 
366
/* Set the font size for the passed font*/
367
MWCOORD
368
GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
369
{
370
        MWCOORD oldfontsize = pfont->fontsize;
371
 
372
        pfont->fontsize = fontsize;
373
 
374
        if (pfont->fontprocs->SetFontSize)
375
            pfont->fontprocs->SetFontSize(pfont, fontsize);
376
 
377
        return oldfontsize;
378
}
379
 
380
/* Set the font rotation angle in tenths of degrees for the passed font*/
381
int
382
GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
383
{
384
        MWCOORD oldrotation = pfont->fontrotation;
385
 
386
        pfont->fontrotation = tenthdegrees;
387
 
388
        if (pfont->fontprocs->SetFontRotation)
389
            pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
390
 
391
        return oldrotation;
392
}
393
 
394
/*
395
 * Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
396
 * for the passed font.
397
 */
398
int
399
GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
400
{
401
        MWCOORD oldattr = pfont->fontattr;
402
 
403
        pfont->fontattr &= ~clrflags;
404
        pfont->fontattr |= setflags;
405
 
406
        if (pfont->fontprocs->SetFontAttr)
407
            pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
408
 
409
        return oldattr;
410
}
411
 
412
/* Unload and deallocate font*/
413
void
414
GdDestroyFont(PMWFONT pfont)
415
{
416
        if (pfont->fontprocs->DestroyFont)
417
                pfont->fontprocs->DestroyFont(pfont);
418
}
419
 
420
/* Return information about a specified font*/
421
MWBOOL
422
GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
423
{
424
        if(!pfont || !pfont->fontprocs->GetFontInfo)
425
                return FALSE;
426
 
427
        return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
428
}
429
 
430
/*
431
 * Convert from one encoding to another
432
 * Input cc and returned cc is character count, not bytes
433
 * Return < 0 on error or can't translate
434
 */
435
int
436
GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
437
{
438
        const unsigned char     *istr8;
439
        const unsigned short    *istr16;
440
        const unsigned long     *istr32;
441
        unsigned char           *ostr8;
442
        unsigned short          *ostr16;
443
        unsigned long           *ostr32;
444
        unsigned int            ch;
445
        int                     icc;
446
        unsigned short          buf16[512];
447
 
448
        iflags &= MWTF_PACKMASK;
449
        oflags &= MWTF_PACKMASK;
450
 
451
        /* allow -1 for len with ascii*/
452
        if(cc == -1 && (iflags == MWTF_ASCII))
453
                cc = strlen((char *)istr);
454
 
455
        /* first check for utf8 input encoding*/
456
        if(iflags == MWTF_UTF8) {
457
                /* we've only got uc16 now so convert to uc16...*/
458
                cc = utf8_to_utf16((unsigned char *)istr, cc,
459
                        oflags==MWTF_UC16?(unsigned short*) ostr: buf16);
460
 
461
                if(oflags == MWTF_UC16 || cc < 0)
462
                        return cc;
463
 
464
                /* will decode again to requested format (probably ascii)*/
465
                iflags = MWTF_UC16;
466
                istr = buf16;
467
        }
468
 
469
#if HAVE_HZK_SUPPORT
470
        if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
471
                /* only support uc16 convert to ascii now...*/
472
                cc = UC16_to_GB( istr, cc, ostr);
473
                return cc;
474
        }
475
#endif
476
 
477
        icc = cc;
478
        istr8 = istr;
479
        istr16 = istr;
480
        istr32 = istr;
481
        ostr8 = ostr;
482
        ostr16 = ostr;
483
        ostr32 = ostr;
484
 
485
        /* Convert between formats.  Note that there's no error
486
         * checking here yet.
487
         */
488
        while(--icc >= 0) {
489
                switch(iflags) {
490
                default:
491
                        ch = *istr8++;
492
                        break;
493
                case MWTF_UC16:
494
                        ch = *istr16++;
495
                        break;
496
                case MWTF_UC32:
497
                        ch = *istr32++;
498
                }
499
                switch(oflags) {
500
                default:
501
                        *ostr8++ = (unsigned char)ch;
502
                        break;
503
                case MWTF_UC16:
504
                        *ostr16++ = (unsigned short)ch;
505
                        break;
506
                case MWTF_UC32:
507
                        *ostr32++ = ch;
508
                }
509
        }
510
        return cc;
511
}
512
 
513
/* Get the width and height of passed text string in the passed font*/
514
void
515
GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
516
        MWCOORD *pheight, MWCOORD *pbase, int flags)
517
{
518
        const void *    text;
519
        unsigned long   buf[256];
520
        int             defencoding = pfont->fontprocs->encoding;
521
 
522
        /* convert encoding if required*/
523
        if((flags & MWTF_PACKMASK) != defencoding) {
524
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
525
                flags &= ~MWTF_PACKMASK;
526
                flags |= defencoding;
527
                text = buf;
528
        } else text = str;
529
 
530
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
531
                cc = strlen((char *)str);
532
 
533
        if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
534
                *pwidth = *pheight = *pbase = 0;
535
                return;
536
        }
537
 
538
        /* calc height and width of string*/
539
        pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
540
}
541
 
542
/* Draw a text string at a specifed coordinates in the foreground color
543
 * (and possibly the background color), applying clipping if necessary.
544
 * The background color is only drawn if the gr_usebg flag is set.
545
 * Use the current font.
546
 */
547
void
548
GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
549
{
550
        const void *    text;
551
        unsigned long   buf[256];
552
        int             defencoding = gr_pfont->fontprocs->encoding;
553
 
554
        /* convert encoding if required*/
555
        if((flags & MWTF_PACKMASK) != defencoding) {
556
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
557
                flags &= ~MWTF_PACKMASK;
558
                flags |= defencoding;
559
                text = buf;
560
        } else text = str;
561
 
562
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
563
                cc = strlen((char *)str);
564
 
565
        if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
566
                return;
567
 
568
        /* draw text string*/
569
        gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
570
}
571
 
572
/*
573
 * Draw ascii text using COREFONT type font.
574
 */
575
void
576
corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
577
        const void *text, int cc, int flags)
578
{
579
        const unsigned char *str = text;
580
        MWCOORD         width;                  /* width of text area */
581
        MWCOORD         height;                 /* height of text area */
582
        MWCOORD         base;                   /* baseline of text*/
583
        MWCOORD         startx, starty;
584
                                                /* bitmap for characters */
585
        MWIMAGEBITS bitmap[MAX_CHAR_HEIGHT*MAX_CHAR_WIDTH/MWIMAGE_BITSPERIMAGE];
586
 
587
        pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
588
 
589
        if(flags & MWTF_BASELINE)
590
                y -= base;
591
        else if(flags & MWTF_BOTTOM)
592
                y -= (height - 1);
593
        startx = x;
594
        starty = y + base;
595
 
596
        switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
597
        case CLIP_VISIBLE:
598
                /*
599
                 * For size considerations, there's no low-level text
600
                 * draw, so we've got to draw all text
601
                 * with per-point clipping for the time being
602
                if (gr_usebg)
603
                        psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
604
                                gr_background);
605
                psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
606
                GdFixCursor(psd);
607
                return;
608
                */
609
                break;
610
 
611
        case CLIP_INVISIBLE:
612
                return;
613
        }
614
 
615
        /* Get the bitmap for each character individually, and then display
616
         * them using clipping for each one.
617
         */
618
        while (--cc >= 0 && x < psd->xvirtres) {
619
                unsigned int ch = *str++;
620
#if HAVE_BIG5_SUPPORT
621
                /* chinese big5 decoding*/
622
                if (ch >= 0xA1 && ch <= 0xF9 && cc >= 1 &&
623
                        ((*str >= 0x40 && *str <= 0x7E) ||
624
                         (*str >= 0xA1 && *str <= 0xFE)) ) {
625
                                ch = (ch << 8) | *str++;
626
                                --cc;
627
                }
628
#endif
629
#if HAVE_GB2312_SUPPORT
630
                /* chinese gb2312 decoding*/
631
                if (ch >= 0xA1 && ch < 0xF8 && cc >= 1 &&
632
                        *str >= 0xA1 && *str < 0xFF) {
633
                                ch = (ch << 8) | *str++;
634
                                --cc;
635
                }
636
#endif
637
#if HAVE_KSC5601_SUPPORT
638
                /* Korean KSC5601 decoding */
639
                if (ch >= 0xA1 && ch <= 0xFE && cc >= 1 &&
640
                         (*str >= 0xA1 && *str <= 0xFE)) {
641
                                ch = (ch << 8) | *str++;
642
                                --cc;
643
                }
644
#endif
645
                pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
646
                        &height, &base);
647
 
648
                /* note: change to bitmap*/
649
                GdBitmap(psd, x, y, width, height, bitmap);
650
                x += width;
651
        }
652
 
653
        if (pfont->fontattr & MWTF_UNDERLINE)
654
                GdLine(psd, startx, starty, x, starty, FALSE);
655
 
656
        GdFixCursor(psd);
657
}
658
 
659
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
660
/*
661
 * Produce blend table from src and dst based on passed alpha table
662
 * Used because we don't quite yet have GdArea with alphablending,
663
 * so we pre-blend fg/bg colors for fade effect.
664
 */
665
static void
666
alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
667
        unsigned char *alpha, int count)
668
{
669
        unsigned int    a, d;
670
        unsigned char   r, g, b;
671
        MWCOLORVAL      palsrc, paldst;
672
        extern MWPALENTRY gr_palette[256];
673
 
674
        while (--count >= 0) {
675
            a = *alpha++;
676
 
677
#define BITS(pixel,shift,mask)  (((pixel)>>shift)&(mask))
678
            if(a == 0)
679
                *out++ = dst;
680
            else if(a == 255)
681
                *out++ = src;
682
            else
683
                switch(psd->pixtype) {
684
                case MWPF_TRUECOLOR0888:
685
                case MWPF_TRUECOLOR888:
686
                    d = BITS(dst, 16, 0xff);
687
                    r = (unsigned char)(((BITS(src, 16, 0xff) - d)*a)>>8) + d;
688
                    d = BITS(dst, 8, 0xff);
689
                    g = (unsigned char)(((BITS(src, 8, 0xff) - d)*a)>>8) + d;
690
                    d = BITS(dst, 0, 0xff);
691
                    b = (unsigned char)(((BITS(src, 0, 0xff) - d)*a)>>8) + d;
692
                    *out++ = (r << 16) | (g << 8) | b;
693
                    break;
694
 
695
                case MWPF_TRUECOLOR565:
696
                    d = BITS(dst, 11, 0x1f);
697
                    r = (unsigned char)(((BITS(src, 11, 0x1f) - d)*a)>>8) + d;
698
                    d = BITS(dst, 5, 0x3f);
699
                    g = (unsigned char)(((BITS(src, 5, 0x3f) - d)*a)>>8) + d;
700
                    d = BITS(dst, 0, 0x1f);
701
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
702
                    *out++ = (r << 11) | (g << 5) | b;
703
                    break;
704
 
705
                case MWPF_TRUECOLOR555:
706
                    d = BITS(dst, 10, 0x1f);
707
                    r = (unsigned char)(((BITS(src, 10, 0x1f) - d)*a)>>8) + d;
708
                    d = BITS(dst, 5, 0x1f);
709
                    g = (unsigned char)(((BITS(src, 5, 0x1f) - d)*a)>>8) + d;
710
                    d = BITS(dst, 0, 0x1f);
711
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
712
                    *out++ = (r << 10) | (g << 5) | b;
713
                    break;
714
 
715
                case MWPF_TRUECOLOR332:
716
                    d = BITS(dst, 5, 0x07);
717
                    r = (unsigned char)(((BITS(src, 5, 0x07) - d)*a)>>8) + d;
718
                    d = BITS(dst, 2, 0x07);
719
                    g = (unsigned char)(((BITS(src, 2, 0x07) - d)*a)>>8) + d;
720
                    d = BITS(dst, 0, 0x03);
721
                    b = (unsigned char)(((BITS(src, 0, 0x03) - d)*a)>>8) + d;
722
                    *out++ = (r << 5) | (g << 2) | b;
723
                    break;
724
 
725
                case MWPF_TRUECOLOR233:
726
                    d = BITS(dst, 0, 0x07);
727
                    r = (unsigned char)(((BITS(src, 0, 0x07) - d)*a)>>8) + d;
728
                    d = BITS(dst, 3, 0x07);
729
                    g = (unsigned char)(((BITS(src, 3, 0x07) - d)*a)>>8) + d;
730
                    d = BITS(dst, 6, 0x03);
731
                    b = (unsigned char)(((BITS(src, 6, 0x03) - d)*a)>>8) + d;
732
                    *out++ = (b << 6) | (g << 3) | r;
733
                    break;
734
 
735
                case MWPF_PALETTE:
736
                    /* reverse lookup palette entry for blend ;-)*/
737
                    palsrc = GETPALENTRY(gr_palette, src);
738
                    paldst = GETPALENTRY(gr_palette, dst);
739
                    d = REDVALUE(paldst);
740
                    r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
741
                    d = GREENVALUE(paldst);
742
                    g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
743
                    d = BLUEVALUE(paldst);
744
                    b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
745
                    *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
746
                                MWRGB(r, g, b));
747
                    break;
748
                }
749
        }
750
}
751
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
752
 
753
#if HAVE_T1LIB_SUPPORT
754
/* contributed by Vidar Hokstad*/
755
 
756
static int
757
t1lib_init(PSD psd)
758
{
759
        char **encoding;
760
        static int inited = 0;
761
 
762
        if (inited)
763
                return 1;
764
 
765
        T1_SetBitmapPad(8);
766
        if (!T1_InitLib(0))
767
                return 0;
768
 
769
        /* set default Latin1 encoding*/
770
        encoding = T1_LoadEncoding("IsoLatin1.enc");
771
        T1_SetDefaultEncoding(encoding);
772
 
773
#ifdef T1LIB_USE_AA_HIGH         
774
        T1_AASetLevel(T1_AA_HIGH);
775
#else
776
        T1_AASetLevel(T1_AA_LOW);
777
#endif   
778
#if 0
779
        /* kluge: this is required if 16bpp drawarea driver is used*/
780
        if(psd->bpp == 16)
781
                T1_AASetBitsPerPixel(16);
782
        else
783
#endif
784
                T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
785
 
786
        inited = 1;
787
        return 1;
788
}
789
 
790
static PMWT1LIBFONT
791
t1lib_createfont(const char *name, MWCOORD height, int attr)
792
{
793
        PMWT1LIBFONT    pf;
794
        int             id;
795
        char *          p;
796
        char            buf[256];
797
 
798
        /* match name against t1 font id's from t1 font database*/
799
        for(id=0; id<T1_Get_no_fonts(); ++id) {
800
                strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
801
 
802
                /* remove extension*/
803
                for(p=buf; *p; ++p) {
804
                        if(*p == '.') {
805
                                *p = 0;
806
                                break;
807
                        }
808
                }
809
 
810
                if(!strcmpi(name, buf)) {
811
                        /* allocate font structure*/
812
                        pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
813
                        if (!pf)
814
                                return NULL;
815
                        pf->fontprocs = &t1lib_procs;
816
                        GdSetFontSize((PMWFONT)pf, height);
817
                        GdSetFontRotation((PMWFONT)pf, 0);
818
                        GdSetFontAttr((PMWFONT)pf, attr, 0);
819
                        pf->fontid = id;
820
                        return pf;
821
                }
822
        }
823
        return NULL;
824
}
825
 
826
/*
827
 * Draw ascii text string using T1LIB type font
828
 */
829
static void
830
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
831
        const void *text, int cc, int flags)
832
{
833
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
834
        const unsigned char *str = text;
835
        MWCOORD         width;                  /* width of text area */
836
        MWCOORD         height;                 /* height of text area */
837
        MWCOORD         underliney;
838
        GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
839
#ifdef T1LIB_USE_AA_HIGH   
840
        OUTPIXELVAL     gvals[17];
841
 
842
        /* Blending array for antialiasing. The steeper the values increase
843
         * near the end, the sharper the characters look, but also more jagged
844
         */
845
        static unsigned char blend[17] = {
846
           0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
847
           0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
848
        };
849
#else   
850
        OUTPIXELVAL     gvals[5];
851
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
852
#endif   
853
 
854
        /* Check if we should throw out some fonts */
855
 
856
        if (pf->fontattr&MWTF_ANTIALIAS) {
857
#ifdef T1LIB_USE_AA_HIGH      
858
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
859
           T1_AAHSetGrayValues(gvals);
860
#else      
861
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
862
           T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
863
#endif
864
           g = T1_AASetString(pf->fontid,(char *)str,cc,0,
865
                (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
866
                pf->fontsize * 1.0, 0);
867
 
868
           if (g && g->bits) {
869
              /*MWPIXELVAL save = gr_background;*/
870
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
871
              height = g->metrics.ascent - g->metrics.descent;
872
 
873
              if(flags & MWTF_BASELINE)
874
                y -= g->metrics.ascent;
875
              else if(flags & MWTF_BOTTOM)
876
                y -= (height - 1);
877
              underliney = y + g->metrics.ascent;
878
 
879
              /* FIXME: Looks damn ugly if usebg is false.
880
               * Will be handled when using alphablending in GdArea...
881
               */
882
              /* clipping handled in GdArea*/
883
              /*FIXME kluge for transparency*/
884
              /*gr_background = gr_foreground + 1;*/
885
              /*gr_usebg = 0;*/
886
              GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
887
              /*gr_background = save;*/
888
 
889
              if (pf->fontattr & MWTF_UNDERLINE)
890
                   GdLine(psd, x, underliney, x+width, underliney, FALSE);
891
 
892
           }
893
        } else {
894
           /* Do non-aa drawing */
895
           g = T1_SetString(pf->fontid,(char *)str,cc,0,
896
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
897
                        pf->fontsize * 1.0, 0);
898
 
899
           if (g && g->bits) {
900
              unsigned char * b;
901
              int xoff;
902
              int maxy;
903
              int xmod;
904
 
905
              /* I'm sure this sorry excuse for a bitmap rendering routine can
906
               * be optimized quite a bit ;)
907
               */
908
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
909
              height = g->metrics.ascent - g->metrics.descent;
910
 
911
              if(flags & MWTF_BASELINE)
912
                y -= g->metrics.ascent;
913
              else if(flags & MWTF_BOTTOM)
914
                y -= (height - 1);
915
              underliney = y + g->metrics.ascent;
916
 
917
              b = g->bits;
918
              maxy = y + height;
919
 
920
/*            if ((x + width) > psd->xvirtres) {
921
                 xmod = (x + width - psd->xvirtres + 7) >> 3;
922
                 width = width + x + width - psd->xvirtres;
923
              } else xmod = 0;
924
*/
925
              xmod = 0;
926
              while (y < maxy) {
927
                 unsigned char data;
928
                 xoff = 0;
929
                 while (xoff < width ) {
930
                    if (!(xoff % 8)) {
931
                       data = *b;
932
                       b++;
933
                    }
934
 
935
                    if (GdClipPoint(psd, x+xoff,y)) {
936
                       if (gr_usebg) {
937
                          psd->DrawPixel(psd,x+xoff,y,
938
                              data & (1 << (xoff % 8)) ?
939
                                    gr_foreground : gr_background);
940
                       } else if (data & (1 << (xoff % 8))) {
941
                          psd->DrawPixel(psd,x+xoff,y, gr_foreground);
942
                       }
943
                    }
944
                    xoff++;
945
                 }
946
                 b += xmod;
947
                 y++;
948
              }
949
              if (pf->fontattr & MWTF_UNDERLINE)
950
                   GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
951
           }
952
        }
953
 
954
   if (g && g->bits) {
955
           /* Save some memory */
956
           free(g->bits);
957
           g->bits = 0; /* Make sure T1lib doesnt try to free it again */
958
   }
959
 
960
   GdFixCursor(psd);
961
}
962
 
963
static MWBOOL
964
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
965
{
966
        int     i;
967
        MWCOORD width, height, baseline;
968
 
969
        /* FIXME, guess all sizes*/
970
        GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
971
        pfontinfo->height = height;
972
        pfontinfo->maxwidth = width;
973
        pfontinfo->baseline = 0;
974
        pfontinfo->firstchar = 32;
975
        pfontinfo->lastchar = 255;
976
        pfontinfo->fixed = TRUE;
977
        for(i=0; i<256; ++i)
978
                pfontinfo->widths[i] = width;
979
        return TRUE;
980
}
981
 
982
/* Get the width and height of passed text string in the current font*/
983
static void
984
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
985
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
986
{
987
        PMWT1LIBFONT            pf = (PMWT1LIBFONT)pfont;
988
        const unsigned char *   str = text;
989
        GLYPH *                 g;
990
 
991
        g = T1_SetString(pf->fontid, (char *)str, cc, 0,
992
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
993
        *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
994
        *pheight = g->metrics.ascent - g->metrics.descent;
995
        if(g && g->bits) {
996
                free(g->bits);
997
                g->bits = 0;
998
        }
999
#if 0
1000
        BBox                    b;
1001
 
1002
        /* FIXME. Something is *VERY* wrong here */
1003
        b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
1004
 
1005
        DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
1006
        DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
1007
        *pwidth = (b.urx - b.llx);
1008
        *pheight = (b.lly - b.ury);
1009
#endif
1010
}
1011
 
1012
static void
1013
t1lib_destroyfont(PMWFONT pfont)
1014
{
1015
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
1016
 
1017
        T1_DeleteAllSizes(pf->fontid);
1018
        free(pf);
1019
}
1020
 
1021
#endif /* HAVE_T1LIB_SUPPORT*/
1022
 
1023
#if HAVE_FREETYPE_SUPPORT
1024
static OUTPIXELVAL gray_palette[5];
1025
 
1026
static int
1027
freetype_init(PSD psd)
1028
{
1029
        static int inited = 0;
1030
 
1031
        if (inited)
1032
                return 1;
1033
 
1034
        /* Init freetype library */
1035
        if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
1036
                return 0;
1037
        }
1038
 
1039
        /* Init kerning extension */
1040
        if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
1041
                return 0;
1042
 
1043
        inited = 1;
1044
        return 1;
1045
}
1046
 
1047
static PMWFREETYPEFONT
1048
freetype_createfont(const char *name, MWCOORD height, int attr)
1049
{
1050
        PMWFREETYPEFONT         pf;
1051
        unsigned short          i, n;
1052
        unsigned short          platform, encoding;
1053
        TT_Face_Properties      properties;
1054
        char *                  p;
1055
        char                    fontname[128];
1056
 
1057
        /* check for pathname prefix*/
1058
        if (strchr(name, '/') != NULL)
1059
                strcpy(fontname, name);
1060
        else {
1061
                strcpy(fontname, FREETYPE_FONT_DIR);
1062
                strcat(fontname, "/");
1063
                strcat(fontname, name);
1064
        }
1065
 
1066
        /* check for extension*/
1067
        if ((p = strrchr(fontname, '.')) == NULL ||
1068
            strcmp(p, ".ttf") != 0) {
1069
                strcat(fontname, ".ttf");
1070
        }
1071
 
1072
        /* allocate font structure*/
1073
        pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
1074
        if (!pf)
1075
                return NULL;
1076
        pf->fontprocs = &freetype_procs;
1077
 
1078
        /* Load face */
1079
        if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
1080
                goto out;
1081
 
1082
        /* Load first kerning table */
1083
        pf->can_kern = TRUE;
1084
        if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
1085
                pf->can_kern = FALSE;
1086
        else {
1087
                if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
1088
                    != TT_Err_Ok)
1089
                        pf->can_kern = FALSE;
1090
                else {
1091
                        /* Support only version 0 kerning table ... */
1092
                        if ((pf->directory.version != 0) ||
1093
                                (pf->directory.nTables <= 0) ||
1094
                                (pf->directory.tables->loaded != 1) ||
1095
                                (pf->directory.tables->version != 0) ||
1096
                                (pf->directory.tables->t.kern0.nPairs <= 0))
1097
                                        pf->can_kern = FALSE;
1098
                }
1099
        }
1100
 
1101
        /* get face properties and allocate preload arrays */
1102
        TT_Get_Face_Properties (pf->face, &properties);
1103
 
1104
#if 0
1105
        /*
1106
         * Use header information for ascent and descent
1107
         * to compute scaled ascent/descent for current font height.
1108
         */
1109
        h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
1110
                + properties.os2->sTypoLineGap;
1111
        ascent = properties.os2->sTypoAscender
1112
                + properties.os2->sTypoLineGap/2;
1113
        pf->ascent = (ascent * height + h/2) / h;
1114
        pf->descent = height - pf->ascent;
1115
#endif
1116
        /* Create a glyph container */
1117
        if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
1118
                goto out;
1119
 
1120
        /* create instance */
1121
        if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
1122
                goto out;
1123
 
1124
        /* Set the instance resolution */
1125
        if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
1126
                goto out;
1127
 
1128
        /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
1129
        n = properties.num_CharMaps;
1130
 
1131
        for (i = 0; i < n; i++) {
1132
                TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
1133
                if (((platform == TT_PLATFORM_MICROSOFT) &&
1134
                        (encoding == TT_MS_ID_UNICODE_CS)) ||
1135
                                ((platform == TT_PLATFORM_APPLE_UNICODE) &&
1136
                                        (encoding == TT_APPLE_ID_DEFAULT)))
1137
                {
1138
                        TT_Get_CharMap (pf->face, i, &pf->char_map);
1139
                        i = n + 1;
1140
                }
1141
        }
1142
        if (i == n) {
1143
                DPRINTF("freetype_createfont: no unicode map table\n");
1144
                goto out;
1145
        }
1146
 
1147
        GdSetFontSize((PMWFONT)pf, height);
1148
        GdSetFontRotation((PMWFONT)pf, 0);
1149
        GdSetFontAttr((PMWFONT)pf, attr, 0);
1150
 
1151
        return pf;
1152
 
1153
out:
1154
        free(pf);
1155
        return NULL;
1156
}
1157
 
1158
static int
1159
compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
1160
{
1161
        int             i = 0;
1162
        int             kernval;
1163
        int             nPairs = pf->directory.tables->t.kern0.nPairs;
1164
        TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
1165
 
1166
        if (pf->last_glyph_code != -1) {
1167
                while ((pair->left != pf->last_glyph_code)
1168
                        && (pair->right != current_glyph_code))
1169
                {
1170
                        pair++;
1171
                        i++;
1172
                        if (i == nPairs)
1173
                        break;
1174
                }
1175
 
1176
                if (i == nPairs)
1177
                        kernval = 0;
1178
                else
1179
                        /* We round the value (hence the +32) */
1180
                        kernval = (pair->value + 32) & -64;
1181
        } else
1182
                kernval = 0;
1183
 
1184
        return kernval;
1185
}
1186
 
1187
static TT_UShort
1188
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
1189
{
1190
        TT_Glyph_Metrics metrics;
1191
 
1192
        if (TT_Load_Glyph ( pf->instance, pf->glyph,
1193
                TT_Char_Index (pf->char_map,glyph_index),
1194
                TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1195
        {
1196
                /* Try to load default glyph: index 0 */
1197
                if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
1198
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1199
                    return 0;
1200
        }
1201
 
1202
        TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1203
        return((metrics.advance & 0xFFFFFFC0) >> 6);
1204
}
1205
 
1206
/* Render a single glyph*/
1207
static void
1208
drawchar(PMWFREETYPEFONT pf, PSD psd, TT_Glyph glyph, int x_offset,
1209
        int y_offset)
1210
{
1211
        TT_F26Dot6      xmin, ymin, xmax, ymax, x, y, z;
1212
        unsigned char   *src, *srcptr;
1213
        MWPIXELVAL      *dst, *dstptr;
1214
        MWPIXELVAL      *bitmap;
1215
        int             size, width, height;
1216
        TT_Outline      outline;
1217
        TT_BBox         bbox;
1218
        TT_Raster_Map   Raster;
1219
        TT_Error        error;
1220
        /*MWPIXELVAL    save;*/
1221
 
1222
        /* we begin by grid-fitting the bounding box */
1223
        TT_Get_Glyph_Outline (pf->glyph, &outline);
1224
        TT_Get_Outline_BBox (&outline, &bbox);
1225
 
1226
        xmin = (bbox.xMin & -64) >> 6;
1227
        ymin = (bbox.yMin & -64) >> 6;
1228
        xmax = ((bbox.xMax + 63) & -64) >> 6;
1229
        ymax = ((bbox.yMax + 63) & -64) >> 6;
1230
        width = xmax - xmin;
1231
        height = ymax - ymin;
1232
        size = width * height;
1233
 
1234
        /* now re-allocate the raster bitmap */
1235
        Raster.rows = height;
1236
        Raster.width = width;
1237
 
1238
        if (pf->fontattr&MWTF_ANTIALIAS)
1239
                Raster.cols = (Raster.width + 3) & -4;  /* pad to 32-bits */
1240
        else
1241
                Raster.cols = (Raster.width + 7) & -8;  /* pad to 64-bits ??? */
1242
 
1243
        Raster.flow = TT_Flow_Up;
1244
        Raster.size = Raster.rows * Raster.cols;
1245
        Raster.bitmap = malloc (Raster.size);
1246
 
1247
        memset (Raster.bitmap, 0, Raster.size);
1248
 
1249
        /* now render the glyph in the small pixmap */
1250
 
1251
        /* IMPORTANT NOTE: the offset parameters passed to the function     */
1252
        /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
1253
        /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
1254
        /* This is why we _did_ grid-fit the bounding box, especially xmin  */
1255
        /* and ymin.                                                        */
1256
 
1257
        if (!(pf->fontattr&MWTF_ANTIALIAS))
1258
                error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
1259
                                -xmin * 64, -ymin * 64);
1260
        else
1261
                error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
1262
                                -xmin * 64, -ymin * 64);
1263
 
1264
        if (error) {
1265
                free (Raster.bitmap);
1266
                return;
1267
        }
1268
 
1269
        bitmap = malloc (size * sizeof (MWPIXELVAL));
1270
        memset (bitmap, 0, size * sizeof (MWPIXELVAL));
1271
 
1272
        src = (char *) Raster.bitmap;
1273
        dst = bitmap + (size - width);
1274
 
1275
        for (y = ymin; y < ymax; y++) {
1276
                srcptr = src;
1277
                dstptr = dst;
1278
 
1279
                for (x = xmin; x < xmax; x++) {
1280
                        if (pf->fontattr&MWTF_ANTIALIAS)
1281
                                *dstptr++ = gray_palette[(int) *srcptr];
1282
                        else {
1283
                                for(z=0;
1284
                                    z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
1285
                                    z++) {
1286
                                        *dstptr++ = ((*srcptr << z) & 0x80)?
1287
                                                gr_foreground: gr_background;
1288
                                }
1289
                                x += 7;
1290
                        }
1291
 
1292
                        srcptr++;
1293
                }
1294
 
1295
                src += Raster.cols;
1296
                dst -= width;
1297
        }
1298
 
1299
        /* FIXME - must clear background upstairs if not gr_usebg*/
1300
        /* FIXME: GdArea problem if fg == bg*/
1301
        /*save = gr_background;*/
1302
        /*gr_background = gr_foreground + 1;*/
1303
 
1304
        /* Now draw the bitmap ... */
1305
        GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
1306
                bitmap, MWPF_PIXELVAL);
1307
 
1308
        /*gr_background = save;*/
1309
 
1310
        free (bitmap);
1311
        free (Raster.bitmap);
1312
}
1313
 
1314
/*
1315
 * Draw unicode 16 text string using FREETYPE type font
1316
 */
1317
static void
1318
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
1319
        const void *text, int cc, int flags)
1320
{
1321
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1322
        const unsigned short *  str = text;
1323
        TT_F26Dot6      x = ax, y = ay;
1324
        TT_Pos          vec_x, vec_y;
1325
        int             i;
1326
        TT_F26Dot6      startx, starty;
1327
        TT_Outline      outline;
1328
        TT_UShort       curchar;
1329
        TT_Glyph_Metrics metrics;
1330
        TT_Face_Properties properties;
1331
        TT_Instance_Metrics imetrics;
1332
        TT_F26Dot6 ascent, descent;
1333
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1334
        static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
1335
 
1336
        pf->last_glyph_code = -1;               /* reset kerning*/
1337
        pf->last_pen_pos = -32767;
1338
 
1339
        /*
1340
         * Compute instance ascent & descent values
1341
         * in fractional units (1/64th pixel)
1342
         */
1343
        TT_Get_Face_Properties (pf->face, &properties);
1344
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1345
 
1346
        ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
1347
        descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
1348
 
1349
        /*
1350
         * Offset the starting point if necessary,
1351
         * FreeType always aligns at baseline
1352
         */
1353
        if (flags&MWTF_BOTTOM) {
1354
                vec_x = 0;
1355
                vec_y = descent;
1356
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1357
                x -= vec_x / 64;
1358
                y += vec_y / 64;
1359
        } else if (flags&MWTF_TOP) {
1360
                vec_x = 0;
1361
                vec_y = ascent;
1362
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1363
                x -= vec_x / 64;
1364
                y += vec_y / 64;
1365
        }
1366
 
1367
        /* Set the "graylevels" */
1368
        if (pf->fontattr&MWTF_ANTIALIAS) {
1369
                TT_Set_Raster_Gray_Palette (engine, virtual_palette);
1370
 
1371
                alphablend(psd, gray_palette, gr_foreground, gr_background,
1372
                        blend, 5);
1373
        }
1374
 
1375
        startx = x;
1376
        starty = y;
1377
        for (i = 0; i < cc; i++) {
1378
                curchar = TT_Char_Index (pf->char_map, str[i]);
1379
 
1380
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1381
                        TTLOAD_DEFAULT) != TT_Err_Ok)
1382
                                continue;
1383
 
1384
                if (pf->fontrotation) {
1385
                        TT_Get_Glyph_Outline (pf->glyph, &outline);
1386
                        TT_Transform_Outline (&outline, &pf->matrix);
1387
                }
1388
 
1389
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1390
 
1391
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1392
                        if (pf->fontrotation) {
1393
                                vec_x = compute_kernval(pf, curchar);
1394
                                vec_y = 0;
1395
                                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1396
 
1397
                                x += vec_x / 64;
1398
                                y -= vec_y / 64;
1399
                        } else
1400
                                x += compute_kernval(pf, curchar) / 64;
1401
                }
1402
 
1403
                drawchar(pf, psd, pf->glyph, x, y);
1404
 
1405
                if (pf->fontrotation) {
1406
                        vec_x = metrics.advance;
1407
                        vec_y = 0;
1408
                        TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
1409
 
1410
                        x += vec_x / 64;
1411
                        y -= vec_y / 64;
1412
                } else {
1413
                        x += metrics.advance / 64;
1414
 
1415
                        /* Kerning point syndrome avoidance */
1416
                        if (pf->last_pen_pos > x)
1417
                                x = pf->last_pen_pos;
1418
                        pf->last_pen_pos = x;
1419
                }
1420
 
1421
                pf->last_glyph_code = curchar;
1422
        }
1423
 
1424
        if (pf->fontattr & MWTF_UNDERLINE)
1425
                GdLine(psd, startx, starty, x, y, FALSE);
1426
}
1427
 
1428
/*
1429
 * Return information about a specified font.
1430
 */
1431
static MWBOOL
1432
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1433
{
1434
        int     i;
1435
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1436
        TT_Face_Properties      properties;
1437
    TT_Instance_Metrics imetrics;
1438
    TT_UShort last_glyph_index;
1439
 
1440
        TT_Get_Face_Properties (pf->face, &properties);
1441
    TT_Get_Instance_Metrics(pf->instance, &imetrics);
1442
 
1443
    /* Fill up the fields */
1444
        pfontinfo->height = (((properties.horizontal->Ascender * \
1445
                                imetrics.y_scale)/ 0x10000) >> 6) -
1446
                            (((properties.horizontal->Descender * \
1447
                                imetrics.y_scale)/ 0x10000) >> 6);
1448
        pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
1449
                                imetrics.x_scale)/ 0x10000) >> 6;
1450
        pfontinfo->baseline = ((properties.horizontal->Ascender * \
1451
                                imetrics.y_scale)/ 0x10000) >> 6;
1452
        pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
1453
        pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
1454
        pfontinfo->fixed = properties.postscript->isFixedPitch;
1455
 
1456
    last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
1457
 
1458
    /* Doesn't work ... don't know why ....*/
1459
#if 0
1460
    if (TT_Get_Face_Widths( pf->face, 0,
1461
                            last_glyph_index, widths, NULL ) != TT_Err_Ok) {
1462
        return TRUE;
1463
    }
1464
 
1465
    for(i=0; i<=last_glyph_index; i++)
1466
                DPRINTF("widths[%d]: %d\n", i, widths[i]);
1467
#endif
1468
 
1469
    /* Get glyphs widths */
1470
        for(i=0; i<=last_glyph_index; i++)
1471
                pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
1472
 
1473
#if 0
1474
    DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
1475
    x_resolution: %d\ny_resolution: %d\n",
1476
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
1477
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
1478
 
1479
    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
1480
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
1481
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
1482
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
1483
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
1484
    Postscript Say monospaced?: %d\n",\
1485
    properties.horizontal->Ascender,
1486
    properties.horizontal->Descender,
1487
    properties.horizontal->xMax_Extent,
1488
    (properties.header->Mac_Style & 0x2)?1:0,
1489
    (properties.header->Mac_Style & 0x1)?1:0,
1490
    properties.os2->sTypoAscender,
1491
    properties.os2->sTypoDescender,
1492
    properties.os2->usWinAscent,
1493
    properties.os2->usWinDescent,
1494
    properties.os2->usFirstCharIndex,
1495
    properties.os2->usLastCharIndex,
1496
    (properties.os2->fsSelection & 0x1)?1:0,
1497
    (properties.os2->fsSelection & 0x20)?1:0,
1498
    properties.postscript->isFixedPitch,
1499
    (properties.os2->panose[3] == 9)?1:0);
1500
#endif  
1501
 
1502
        return TRUE;
1503
}
1504
 
1505
static void
1506
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
1507
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1508
{
1509
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1510
        const unsigned short *  str = text;
1511
        TT_F26Dot6      x = 0;
1512
        int             i;
1513
        TT_UShort       curchar;
1514
        TT_Glyph_Metrics metrics;
1515
        TT_Face_Properties      properties;
1516
        TT_Instance_Metrics imetrics;
1517
 
1518
        TT_Get_Face_Properties (pf->face, &properties);
1519
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1520
 
1521
        pf->last_glyph_code = -1;               /* reset kerning*/
1522
        pf->last_pen_pos = -32767;
1523
 
1524
        for (i = 0; i < cc; i++) {
1525
                curchar = TT_Char_Index (pf->char_map, str[i]);
1526
 
1527
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1528
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1529
                                continue;
1530
 
1531
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1532
 
1533
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1534
                                x += compute_kernval(pf, curchar) / 64;
1535
                }
1536
 
1537
                x += metrics.advance / 64;
1538
 
1539
                /* Kerning point syndrome avoidance */
1540
                if (pf->last_pen_pos > x)
1541
                        x = pf->last_pen_pos;
1542
                pf->last_pen_pos = x;
1543
 
1544
                pf->last_glyph_code = curchar;
1545
        }
1546
 
1547
        *pwidth = x;
1548
        *pheight =  (((properties.horizontal->Ascender *
1549
                        imetrics.y_scale)/ 0x10000) >> 6) -
1550
                    (((properties.horizontal->Descender *
1551
                    imetrics.y_scale)/ 0x10000) >> 6);
1552
        /* FIXME: is it what's required ?? */
1553
        *pbase = (((-properties.horizontal->Descender) *
1554
                    imetrics.y_scale)/ 0x10000) >> 6;
1555
}
1556
 
1557
static void
1558
freetype_destroyfont(PMWFONT pfont)
1559
{
1560
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1561
 
1562
        TT_Close_Face(pf->face);
1563
        free(pf);
1564
}
1565
 
1566
static void
1567
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
1568
{
1569
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1570
 
1571
        pf->fontsize = fontsize;
1572
 
1573
        /* We want real pixel sizes ... not points ...*/
1574
        TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
1575
                                pf->fontsize, pf->fontsize * 64 );
1576
#if 0
1577
        /* set charsize (convert to points for freetype)*/
1578
        TT_Set_Instance_CharSize (pf->instance,
1579
                ((pf->fontsize * 72 + 96/2) / 96) * 64);
1580
#endif
1581
}
1582
 
1583
static void
1584
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
1585
{
1586
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1587
        float           angle;
1588
 
1589
        pf->fontrotation = tenthdegrees;
1590
 
1591
        /* Build the rotation matrix with the given angle */
1592
        TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
1593
 
1594
        angle = pf->fontrotation * M_PI / 1800;
1595
        pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
1596
        pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
1597
        pf->matrix.xx = pf->matrix.yy;
1598
        pf->matrix.xy = -pf->matrix.yx;
1599
}
1600
 
1601
#endif /* HAVE_FREETYPE_SUPPORT*/
1602
 
1603
/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
1604
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
1605
 * On the other hand, if the UTF-8 string contains surrogate values, this
1606
 * is considered an error and returned as such.
1607
 *
1608
 * The destination array must be able to hold as many Unicode-16 characters
1609
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
1610
 * characters are ASCII characters.  No more will be needed.
1611
 *
1612
 * Copyright (c) 2000 Morten Rolland, Screen Media
1613
 */
1614
static int
1615
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
1616
{
1617
        int count = 0;
1618
        unsigned char c0, c1;
1619
        unsigned long scalar;
1620
 
1621
        while(--cc >= 0) {
1622
                c0 = *utf8++;
1623
                /*DPRINTF("Trying: %02x\n",c0);*/
1624
 
1625
                if ( c0 < 0x80 ) {
1626
                        /* Plain ASCII character, simple translation :-) */
1627
                        *unicode16++ = c0;
1628
                        count++;
1629
                        continue;
1630
                }
1631
 
1632
                if ( (c0 & 0xc0) == 0x80 )
1633
                        /* Illegal; starts with 10xxxxxx */
1634
                        return -1;
1635
 
1636
                /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
1637
                scalar = c0;
1638
                if(--cc < 0)
1639
                        return -1;
1640
                c1 = *utf8++;
1641
                /*DPRINTF("c1=%02x\n",c1);*/
1642
                if ( (c1 & 0xc0) != 0x80 )
1643
                        /* Bad byte */
1644
                        return -1;
1645
                scalar <<= 6;
1646
                scalar |= (c1 & 0x3f);
1647
 
1648
                if ( !(c0 & 0x20) ) {
1649
                        /* Two bytes UTF-8 */
1650
                        if ( scalar < 0x80 )
1651
                                return -1;      /* Overlong encoding */
1652
                        *unicode16++ = scalar & 0x7ff;
1653
                        count++;
1654
                        continue;
1655
                }
1656
 
1657
                /* c0 must be 111xxxxx if we get here => at least 3 bytes */
1658
                if(--cc < 0)
1659
                        return -1;
1660
                c1 = *utf8++;
1661
                /*DPRINTF("c1=%02x\n",c1);*/
1662
                if ( (c1 & 0xc0) != 0x80 )
1663
                        /* Bad byte */
1664
                        return -1;
1665
                scalar <<= 6;
1666
                scalar |= (c1 & 0x3f);
1667
 
1668
                if ( !(c0 & 0x10) ) {
1669
                        /*DPRINTF("####\n");*/
1670
                        /* Three bytes UTF-8 */
1671
                        if ( scalar < 0x800 )
1672
                                return -1;      /* Overlong encoding */
1673
                        if ( scalar >= 0xd800 && scalar < 0xe000 )
1674
                                return -1;      /* UTF-16 high/low halfs */
1675
                        *unicode16++ = scalar & 0xffff;
1676
                        count++;
1677
                        continue;
1678
                }
1679
 
1680
                /* c0 must be 1111xxxx if we get here => at least 4 bytes */
1681
                c1 = *utf8++;
1682
                if(--cc < 0)
1683
                        return -1;
1684
                /*DPRINTF("c1=%02x\n",c1);*/
1685
                if ( (c1 & 0xc0) != 0x80 )
1686
                        /* Bad byte */
1687
                        return -1;
1688
                scalar <<= 6;
1689
                scalar |= (c1 & 0x3f);
1690
 
1691
                if ( !(c0 & 0x08) ) {
1692
                        /* Four bytes UTF-8, needs encoding as surrogates */
1693
                        if ( scalar < 0x10000 )
1694
                                return -1;      /* Overlong encoding */
1695
                        scalar -= 0x10000;
1696
                        *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
1697
                        *unicode16++ = (scalar & 0x3ff) + 0xdc00;
1698
                        count += 2;
1699
                        continue;
1700
                }
1701
 
1702
                return -1;      /* No support for more than four byte UTF-8 */
1703
        }
1704
        return count;
1705
}
1706
 
1707
#if HAVE_HZK_SUPPORT
1708
 
1709
/* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
1710
 * a single 2-byte UC16 character is encoded into a surrogate pair.
1711
 * return -1 ,if error;
1712
 * The destination array must be able to hold as many
1713
 * as there are Unicode-16 characters.
1714
 *
1715
 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
1716
 */
1717
static int
1718
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
1719
{
1720
        FILE* fp;
1721
        char buffer[256];
1722
        unsigned char *uc16p;
1723
        int i=0,j=0, k;
1724
        unsigned char *filebuffer;
1725
        unsigned short *uc16pp,*table;
1726
        unsigned short uc16px;
1727
        int length=31504;
1728
 
1729
        if (use_big5)
1730
                length=54840;
1731
 
1732
        uc16p=(unsigned char *) uc16;
1733
        uc16pp=(unsigned short *) uc16;
1734
 
1735
        strcpy(buffer,HZK_FONT_DIR);
1736
        if (use_big5)
1737
                strcat(buffer,"/BG2UBG.KU");
1738
        else
1739
                strcat(buffer,"/UGB2GB.KU");
1740
        if(!(fp = fopen(buffer, "rb")))
1741
        {
1742
                 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
1743
                 return -1;
1744
        }
1745
 
1746
        filebuffer= (unsigned char *)malloc ( length);
1747
 
1748
        if(fread(filebuffer, sizeof(char),length, fp) < length) {
1749
                  fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
1750
                  fclose(fp);
1751
                  return -1;
1752
        }
1753
        fclose(fp);
1754
 
1755
        if (use_big5)
1756
        {
1757
                table=(unsigned short *)filebuffer;
1758
                while(1)
1759
                {
1760
                        if(j>=cc)
1761
                        {
1762
                                ascii[i]=0;
1763
                                break;
1764
                        }
1765
                        uc16px=*uc16pp;
1766
                        if((uc16px)<=0x00ff)
1767
                        {
1768
                                ascii[i]=(char)(*uc16pp);
1769
                                i++;
1770
                        }
1771
                        else
1772
                        {
1773
                                ascii[i]=0xa1; ascii[i+1]=0x40;
1774
                                for (k=0; k<13710; k++)
1775
                                {
1776
                                        if (*(table+(k*2+1))==(uc16px))
1777
                                        {
1778
                                                ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
1779
                                                ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
1780
                                                break;
1781
                                        }
1782
                                }
1783
                                i+=2;
1784
                        }
1785
                        uc16pp++; j++;
1786
                }
1787
        }
1788
        else
1789
        {
1790
        while(1)
1791
        {
1792
                if(j>=cc)
1793
                {
1794
                        ascii[i]=0;
1795
                        break;
1796
                }
1797
                if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
1798
                {
1799
                        ascii[i]=0;
1800
                        break;
1801
                }
1802
                else
1803
                {
1804
                        if(*((uc16p)+j+1)==0)
1805
                        {
1806
                                ascii[i]=*((uc16p)+j);
1807
                                i++;
1808
                                j+=2;
1809
                        }
1810
                        else
1811
                        {
1812
                        /* to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
1813
                        {
1814
                                int p1=0,p2=length-4,p;
1815
                                unsigned int c1,c2,c,d;
1816
                                c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
1817
                                c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
1818
                                d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
1819
                                if(c1==d)
1820
                                {
1821
                                        ascii[i]=filebuffer[p1+2];
1822
                                        ascii[i+1]=filebuffer[p1+3];
1823
                                        goto findit;
1824
                                }
1825
                                if(c2==d)
1826
                                {
1827
                                        ascii[i]=filebuffer[p2+2];
1828
                                        ascii[i+1]=filebuffer[p2+3];
1829
                                        goto findit;
1830
                                }
1831
                                while(1)
1832
                                {
1833
                                        p=(((p2-p1)/2+p1)>>2)<<2;
1834
                                        c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
1835
                                        if(d==c)        /* find it*/
1836
                                        {
1837
                                                ascii[i]=filebuffer[p+2];
1838
                                                ascii[i+1]=filebuffer[p+3];
1839
                                                break;
1840
                                        }
1841
                                        else if(p2<=p1+4)       /* can't find.*/
1842
                                        {
1843
                                                ascii[i]='.';   /* ((uc16p)+j);*/
1844
                                                ascii[i+1]='.'; /* ((uc16p)+j+1);*/
1845
                                                break;
1846
                                        }
1847
                                        else if(d<c)
1848
                                        {
1849
                                                p2=p;
1850
                                                c2=c;
1851
                                        }
1852
                                        else
1853
                                        {
1854
                                                p1=p;
1855
                                                c1=c;
1856
                                        }
1857
                                }
1858
                        }
1859
                        findit:
1860
                        i+=2;
1861
                        j+=2;
1862
                        }
1863
                }
1864
        }
1865
        }
1866
        free(filebuffer);
1867
 
1868
        return i;
1869
}
1870
 
1871
/************************** functions definition ******************************/
1872
 
1873
static int hzk_id( PMWHZKFONT pf )
1874
{
1875
        switch(pf->font_height)
1876
        {
1877
        case 12:
1878
                return 0;
1879
        case 16: default:
1880
                return 1;
1881
        }
1882
}
1883
 
1884
/* This function get Chinese font info from etc file.*/
1885
static MWBOOL GetCFontInfo( PMWHZKFONT pf )
1886
{
1887
        int charset;
1888
 
1889
        if (use_big5)
1890
                charset=(13094+408);
1891
        else
1892
                charset=8178;
1893
 
1894
        CFont[hzk_id(pf)].width = pf->cfont_width;
1895
        pf->CFont.width = pf->cfont_width;
1896
 
1897
        CFont[hzk_id(pf)].height = pf->font_height;
1898
        pf->CFont.height = pf->font_height;
1899
 
1900
        CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
1901
                pf->CFont.height * charset;
1902
        pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
1903
 
1904
        if(pf->CFont.size < charset * 8)
1905
                return FALSE;
1906
 
1907
        strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
1908
        strcpy(pf->CFont.file,HZK_FONT_DIR);
1909
 
1910
        if(pf->font_height==16)
1911
        {
1912
                strcat(CFont[hzk_id(pf)].file,"/hzk16");
1913
                strcat(pf->CFont.file,"/hzk16");
1914
        }
1915
        else
1916
        {
1917
                strcat(CFont[hzk_id(pf)].file,"/hzk12");
1918
                strcat(pf->CFont.file,"/hzk12");
1919
        }
1920
 
1921
        if (use_big5)
1922
        {
1923
                CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
1924
                pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
1925
        }
1926
 
1927
        return TRUE;
1928
}
1929
 
1930
/* This function get ASCII font info from etc file.*/
1931
static MWBOOL GetAFontInfo( PMWHZKFONT pf )
1932
{
1933
        AFont[hzk_id(pf)].width = pf->afont_width;
1934
        pf->AFont.width = pf->afont_width;
1935
 
1936
        AFont[hzk_id(pf)].height = pf->font_height;
1937
        pf->AFont.height = pf->font_height;
1938
 
1939
        AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
1940
                pf->AFont.height * 255;
1941
        pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
1942
 
1943
        if(pf->AFont.size < 255 * 8)
1944
                return FALSE;
1945
 
1946
        strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
1947
        strcpy(pf->AFont.file,HZK_FONT_DIR);
1948
 
1949
        if(pf->font_height==16)
1950
        {
1951
                strcat(AFont[hzk_id(pf)].file,"/asc16");
1952
                strcat(pf->AFont.file,"/asc16");
1953
        }
1954
        else
1955
        {
1956
                strcat(AFont[hzk_id(pf)].file,"/asc12");
1957
                strcat(pf->AFont.file,"/asc12");
1958
        }
1959
        return TRUE;
1960
}
1961
 
1962
/* This function load system font into memory.*/
1963
static MWBOOL LoadFont( PMWHZKFONT pf )
1964
{
1965
        FILE* fp;
1966
 
1967
        if(!GetCFontInfo(pf))
1968
        {
1969
                fprintf (stderr, "Get Chinese HZK font info failure!\n");
1970
                return FALSE;
1971
        }
1972
        if(CFont[hzk_id(pf)].pFont == NULL)     /* check font cache*/
1973
        {
1974
 
1975
 
1976
                /* Allocate system memory for Chinese font.*/
1977
                if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
1978
                {
1979
                        fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
1980
                        return FALSE;
1981
                }
1982
 
1983
                /* Open font file and read information to the system memory.*/
1984
                fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
1985
                if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
1986
                {
1987
                        fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
1988
                        return FALSE;
1989
                }
1990
                if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
1991
                {
1992
                        fprintf (stderr, "Error in reading Chinese HZK font file!\n");
1993
                        fclose(fp);
1994
                        return FALSE;
1995
                }
1996
 
1997
                fclose(fp);
1998
 
1999
                CFont[hzk_id(pf)].use_count=0;
2000
 
2001
                fprintf (stderr, "done.\n" );
2002
 
2003
        }
2004
        cfont_address = CFont[hzk_id(pf)].pFont;
2005
        pf->cfont_address = CFont[hzk_id(pf)].pFont;
2006
        pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
2007
 
2008
        CFont[hzk_id(pf)].use_count++;
2009
 
2010
        if(!GetAFontInfo(pf))
2011
        {
2012
               fprintf (stderr, "Get ASCII HZK font info failure!\n");
2013
               return FALSE;
2014
        }
2015
        if(AFont[hzk_id(pf)].pFont == NULL)     /* check font cache*/
2016
        {
2017
 
2018
 
2019
                /* Allocate system memory for ASCII font.*/
2020
                if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
2021
                {
2022
                        fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
2023
                        free(CFont[hzk_id(pf)].pFont);
2024
                        CFont[hzk_id(pf)].pFont = NULL;
2025
                        return FALSE;
2026
                }
2027
 
2028
                /* Load ASCII font information to the near memory.*/
2029
                fprintf (stderr, "Loading ASCII HZK font..." );
2030
                if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
2031
                {
2032
                        fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
2033
                        return FALSE;
2034
                }
2035
                if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
2036
                {
2037
                        fprintf (stderr, "Error in reading ASCII HZK font file!\n");
2038
                        fclose(fp);
2039
                        return FALSE;
2040
                }
2041
 
2042
                fclose(fp);
2043
 
2044
                AFont[hzk_id(pf)].use_count=0;
2045
 
2046
                fprintf (stderr, "done.\n" );
2047
 
2048
        }
2049
        afont_address = AFont[hzk_id(pf)].pFont;
2050
        pf->afont_address = AFont[hzk_id(pf)].pFont;
2051
        pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
2052
 
2053
        AFont[hzk_id(pf)].use_count++;
2054
 
2055
        return TRUE;
2056
}
2057
 
2058
/* This function unload system font from memory.*/
2059
static void UnloadFont( PMWHZKFONT pf )
2060
{
2061
        CFont[hzk_id(pf)].use_count--;
2062
        AFont[hzk_id(pf)].use_count--;
2063
 
2064
        if (!CFont[hzk_id(pf)].use_count)
2065
        {
2066
                free(pf->CFont.pFont);
2067
                free(pf->AFont.pFont);
2068
 
2069
                CFont[hzk_id(pf)].pFont = NULL;
2070
                AFont[hzk_id(pf)].pFont = NULL;
2071
        }
2072
}
2073
 
2074
static int
2075
hzk_init(PSD psd)
2076
{
2077
        /* FIXME: *.KU file should be opened and
2078
         * read in here...*/
2079
        return 1;
2080
}
2081
 
2082
static PMWHZKFONT
2083
hzk_createfont(const char *name, MWCOORD height, int attr)
2084
{
2085
        PMWHZKFONT      pf;
2086
 
2087
        if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
2088
                return FALSE;
2089
 
2090
        /*printf("hzk_createfont(%s,%d)\n",name,height);*/
2091
 
2092
        use_big5=name[2]-'K';
2093
 
2094
        /* allocate font structure*/
2095
        pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
2096
        if (!pf)
2097
                return NULL;
2098
        pf->fontprocs = &hzk_procs;
2099
 
2100
        pf->fontsize=height;
2101
#if 0
2102
        GdSetFontSize((PMWFONT)pf, height);
2103
#endif
2104
        GdSetFontRotation((PMWFONT)pf, 0);
2105
        GdSetFontAttr((PMWFONT)pf, attr, 0);
2106
 
2107
        if(height==12)
2108
        {
2109
                afont_width = 6;
2110
                cfont_width = 12;
2111
                font_height = 12;
2112
 
2113
                pf->afont_width = 6;
2114
                pf->cfont_width = 12;
2115
                pf->font_height = 12;
2116
        }
2117
        else
2118
        {
2119
                afont_width = 8;
2120
                cfont_width = 16;
2121
                font_height = 16;
2122
 
2123
                pf->afont_width = 8;
2124
                pf->cfont_width = 16;
2125
                pf->font_height = 16;
2126
        }
2127
 
2128
        /* Load the font library to the system memory.*/
2129
        if(!LoadFont(pf))
2130
                return FALSE;
2131
 
2132
        return pf;
2133
}
2134
 
2135
int IsBig5(int i)
2136
{
2137
        if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
2138
            (i>=0xa440 && i<=0xc67e) || /* a440-c67e        */
2139
            (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
2140
            (i>=0xc940 && i<=0xf9fe))   /* c940-f9fe        */
2141
                return 1;
2142
        else
2143
                return 0;
2144
}
2145
 
2146
/*
2147
 * following several function is used in hzk_drawtext
2148
 */
2149
 
2150
static int getnextchar(char* s, unsigned char* cc)
2151
{
2152
        if( s[0] == '\0') return 0;
2153
 
2154
        cc[0] = (unsigned char)(*s);
2155
        cc[1] = (unsigned char)(*(s + 1));
2156
 
2157
        if (use_big5)
2158
        {
2159
                if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
2160
                        return 1;
2161
        }
2162
        else
2163
        {
2164
                if( ((unsigned char)cc[0] > 0xa0) &&
2165
                    ((unsigned char)cc[1] > 0xa0) )
2166
                        return 1;
2167
        }
2168
 
2169
        cc[1] = '\0';
2170
 
2171
        return 1;
2172
}
2173
 
2174
static void
2175
expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
2176
{
2177
        int i=0;
2178
        int c1, c2, seq;
2179
        int x,y;
2180
        unsigned char *font;
2181
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2182
 
2183
        int pixelsize;
2184
        pixelsize=sizeof(MWPIXELVAL);
2185
 
2186
        c1 = c[0];
2187
        c2 = c[1];
2188
        if (use_big5)
2189
        {
2190
                seq=0;
2191
                /* ladd=loby-(if(loby<127)?64:98)*/
2192
                c2-=(c2<127?64:98);
2193
 
2194
                /* hadd=(hiby-164)*157*/
2195
                if (c1>=0xa4)   /* standard font*/
2196
                {
2197
                        seq=(((c1-164)*157)+c2);
2198
                        if (seq>=5809) seq-=408;
2199
                }
2200
 
2201
                /* hadd=(hiby-161)*157*/
2202
                if (c1<=0xa3)   /* special font*/
2203
                        seq=(((c1-161)*157)+c2)+13094;
2204
        }
2205
        else
2206
                seq=((c1 - 161)*94 + c2 - 161);
2207
 
2208
        font = pf->cfont_address + ((seq) *
2209
                  (pf->font_height * ((pf->cfont_width + 7) / 8)));
2210
 
2211
        for (y = 0; y < pf->font_height; y++)
2212
                for (x = 0; x < pf->cfont_width; x++)
2213
                {
2214
                        if (x % 8 == 0)
2215
                                b = *font++;
2216
 
2217
                        if (b & (128 >> (x % 8)))   /* pixel */
2218
                                bitmap[i++]=fg;
2219
                        else
2220
                                bitmap[i++]=bg;
2221
                }
2222
}
2223
 
2224
static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
2225
{
2226
        int i=0;
2227
        int x,y;
2228
        unsigned char *font;
2229
        int pixelsize;
2230
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2231
 
2232
        pixelsize=sizeof(MWPIXELVAL);
2233
 
2234
        font = pf->afont_address + c * (pf->font_height *
2235
                ((pf->afont_width + 7) / 8));
2236
 
2237
        for (y = 0; y < pf->font_height; y++)
2238
                for (x = 0; x < pf->afont_width; x++)
2239
                {
2240
                        if (x % 8 == 0)
2241
                                b = *font++;
2242
                        if (b & (128 >> (x % 8)))       /* pixel */
2243
                                bitmap[i++]=fg;
2244
                        else
2245
                                bitmap[i++]=bg;
2246
                }
2247
}
2248
 
2249
/*
2250
 * Draw ASCII text string using HZK type font
2251
 */
2252
static void
2253
hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
2254
        const void *text, int cc, int flags)
2255
{
2256
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2257
 
2258
        unsigned char c[2];
2259
        MWPIXELVAL *bitmap;
2260
        unsigned char s1[3];
2261
        char *s,*sbegin;
2262
 
2263
        s=(char *)text;
2264
 
2265
        if(cc==1)
2266
        {
2267
                s1[0]=*((unsigned char*)text);
2268
                s1[1]=0x0;
2269
                s1[2]=0x0;
2270
                s=s1;
2271
        }
2272
 
2273
        sbegin=s;
2274
        bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
2275
                        sizeof(MWPIXELVAL));
2276
 
2277
        while( getnextchar(s, c) )
2278
        {
2279
                if( c[1] != '\0')
2280
                {
2281
                        expandcchar(pf, gr_background,gr_foreground,
2282
                            c, bitmap);
2283
                        /* Now draw the bitmap ... */
2284
 
2285
                        if (flags&MWTF_TOP)
2286
                                GdArea(psd,ax, ay, pf->cfont_width,
2287
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2288
                        else
2289
                                GdArea(psd,ax, ay-pf->font_height+2,
2290
                                        pf->cfont_width, pf->font_height,
2291
                                        bitmap, MWPF_PIXELVAL);
2292
 
2293
                        s += 2;
2294
                        ax += pf->cfont_width;
2295
                }
2296
                else
2297
                {
2298
                        expandchar(pf, gr_background,gr_foreground,
2299
                           c[0], bitmap);
2300
                        /* Now draw the bitmap ... */
2301
 
2302
                        if (flags&MWTF_TOP)
2303
                                GdArea(psd,ax, ay, pf->afont_width,
2304
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2305
                        else
2306
                                GdArea(psd,ax, ay-pf->font_height+2,
2307
                                        pf->afont_width, pf->font_height,
2308
                                        bitmap, MWPF_PIXELVAL);
2309
 
2310
                        s += 1;
2311
                        ax += pf->afont_width;
2312
                }
2313
 
2314
                if(s>=sbegin+cc)break;
2315
        }
2316
 
2317
        FREEA(bitmap);
2318
}
2319
 
2320
/*
2321
 * Return information about a specified font.
2322
 */
2323
static MWBOOL
2324
hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
2325
{
2326
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2327
 
2328
        int i;
2329
 
2330
        pfontinfo->height = pf->font_height;
2331
        pfontinfo->maxwidth = pf->cfont_width;
2332
        pfontinfo->baseline = pf->font_height-2;
2333
        pfontinfo->firstchar = 0;
2334
        pfontinfo->lastchar = 0;
2335
        pfontinfo->fixed = TRUE;
2336
 
2337
        for(i=0; i<=256; i++)
2338
                pfontinfo->widths[i] = pf->afont_width;
2339
 
2340
        return TRUE;
2341
}
2342
 
2343
static void
2344
hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
2345
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
2346
{
2347
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2348
 
2349
        unsigned char c[2];
2350
        char *s,*sbegin;
2351
        unsigned char s1[3];
2352
 
2353
        int ax=0;
2354
        s=(char *)text;
2355
        if(cc==0)
2356
        {
2357
                *pwidth = 0;
2358
                *pheight = pf->font_height;
2359
                *pbase = pf->font_height-2;
2360
 
2361
        }
2362
        if(cc==1)
2363
        {
2364
                s1[0]=*((unsigned char*)text);
2365
                s1[1]=0x0;
2366
                s1[2]=0x0;
2367
                s=s1;
2368
        }
2369
        sbegin=s;
2370
        while( getnextchar(s, c) )
2371
        {
2372
                if( c[1] != '\0')
2373
                {
2374
                        s += 2;
2375
                        ax += pf->cfont_width;
2376
                }
2377
                else
2378
                {
2379
                        s += 1;
2380
                        ax += pf->afont_width;
2381
                }
2382
                if(s>=sbegin+cc) {
2383
                        /*fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
2384
                        break;
2385
                }
2386
 
2387
        }
2388
        /*fprintf(stderr,"ax=%d,\n",ax);*/
2389
 
2390
        *pwidth = ax;
2391
        *pheight = pf->font_height;
2392
        *pbase = pf->font_height-2;
2393
}
2394
 
2395
static void
2396
hzk_destroyfont(PMWFONT pfont)
2397
{
2398
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2399
        UnloadFont(pf);
2400
        free(pf);
2401
}
2402
 
2403
static void
2404
hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
2405
{
2406
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2407
        /* jmt: hzk_setfontsize not supported*/
2408
        /* & pf->fontsize can't be changed*/
2409
        /* because of hzk_id() :p*/
2410
        pf->fontsize=pf->font_height;
2411
}
2412
#endif /* HAVE_HZK_SUPPORT*/
2413
 
2414
/* FIXME: this routine should work for all font renderers...*/
2415
int
2416
GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
2417
        int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
2418
        MWCOORD *pbase, int flags)
2419
{
2420
#ifdef HAVE_FREETYPE_SUPPORT
2421
        unsigned short  buf[256];
2422
        unsigned short* text;
2423
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2424
        int             defencoding = pf->fontprocs->encoding;
2425
        int             x = 0;
2426
        int             i;
2427
        TT_UShort       curchar;
2428
        TT_Glyph_Metrics metrics;
2429
        TT_Face_Properties      properties;
2430
        TT_Instance_Metrics imetrics;
2431
 
2432
        if ((cc<0)||(!str))
2433
        {
2434
                *pwidth = *pheight = *pbase = 0;
2435
                return 0;
2436
        }
2437
        /* convert encoding if required*/
2438
        if((flags & MWTF_PACKMASK) != defencoding)
2439
        {
2440
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
2441
                flags &= ~MWTF_PACKMASK;
2442
                flags |= defencoding;
2443
                text=buf;
2444
        } else text =(unsigned short*)str;
2445
        if(cc <= 0)
2446
        {
2447
                *pwidth = *pheight = *pbase = 0;
2448
                return 0;
2449
        }
2450
 
2451
        TT_Get_Face_Properties (pf->face, &properties);
2452
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
2453
 
2454
        pf->last_glyph_code = -1;               /* reset kerning*/
2455
        pf->last_pen_pos = -32767;
2456
        if (lpnFit)
2457
             *lpnFit=-1;
2458
        for (i = 0; i < cc; i++)
2459
        {
2460
                curchar = TT_Char_Index (pf->char_map,text[i]);
2461
 
2462
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
2463
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
2464
                {
2465
                     fprintf(stderr, "Unable to load glyph with index=%d\n",curchar);
2466
                        return 0;
2467
                }
2468
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
2469
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
2470
                {
2471
                        x += compute_kernval(pf, curchar) / 64;
2472
                }
2473
                x += metrics.advance / 64;
2474
                if((lpnFit)&&(alpDx))
2475
                {
2476
                        if (x<=nMaxExtent)
2477
                             alpDx[i]=x;
2478
                        else
2479
                             if (*lpnFit==-1)
2480
                                        (*lpnFit)=i;
2481
                }
2482
                /* Kerning point syndrome avoidance */
2483
                if (pf->last_pen_pos > x)
2484
                        x = pf->last_pen_pos;
2485
                pf->last_pen_pos = x;
2486
                pf->last_glyph_code = curchar;
2487
        }
2488
        if ((lpnFit)&&(*lpnFit==-1))
2489
                *lpnFit=cc;
2490
        *pwidth = x;
2491
        *pheight = (((properties.horizontal->Ascender *
2492
                        imetrics.y_scale)/ 0x10000) >> 6) -
2493
                            (((properties.horizontal->Descender *
2494
                            imetrics.y_scale)/ 0x10000) >> 6);
2495
        /* FIXME: is it what's required ??*/
2496
        if (pbase)
2497
                *pbase = (((-properties.horizontal->Descender) *
2498
                            imetrics.y_scale)/ 0x10000) >> 6;
2499
        return 1;
2500
#else /* HAVE_FREETYPE_SUPPORT*/
2501
        *pwidth = *pheight = *pbase = 0;
2502
        return 0;
2503
#endif
2504
}
2505
 
2506
#ifdef HAVE_FREETYPE_SUPPORT
2507
#include <dirent.h>
2508
/*
2509
 * This function is taken almost verbatim from ftdump.c from
2510
 * the freetype library (version 1.3.1)
2511
 */
2512
static char *
2513
tt_lookup_name(TT_Face face)
2514
{
2515
        TT_Face_Properties prop;
2516
        unsigned short i, n;
2517
        unsigned short platform, encoding, language, id;
2518
        char *string;
2519
        char *name_buffer;
2520
        unsigned short string_len;
2521
        int j, found;
2522
        int index = 4; /* I dont know why as yet.. */
2523
        int name_len;
2524
 
2525
 
2526
        TT_Get_Face_Properties(face, &prop);
2527
        n = prop.num_Names;
2528
 
2529
        for ( i = 0; i < n; i++ ) {
2530
                TT_Get_Name_ID( face, i, &platform, &encoding, &language, &id );
2531
                TT_Get_Name_String( face, i, &string, &string_len );
2532
 
2533
                if (id == index ) {
2534
                        /* The following code was inspired from Mark Leisher's */
2535
                        /* ttf2bdf package                                     */
2536
                        found = 0;
2537
 
2538
                        /* Try to find a Microsoft English name */
2539
                        if ( platform == 3 )
2540
                                for ( j = 1; j >= 0; j-- )
2541
                                        if ( encoding == j )  /* Microsoft ? */
2542
                                                if ( (language & 0x3FF) == 0x009 ) {
2543
                                                        /* English language */
2544
                                                        found = 1;
2545
                                                        break;
2546
                                                }
2547
 
2548
                        if ( !found && platform == 0 && language == 0 )
2549
                                found = 1;
2550
 
2551
                        /* Found a Unicode Name. */
2552
                        if ( found ) {
2553
                                if ( string_len > 512 )
2554
                                        string_len = 512;
2555
 
2556
                                name_len = 0;
2557
                                name_buffer = (char*)malloc((string_len / 2) + 1);
2558
 
2559
                                for ( i = 1; i < string_len; i += 2 )
2560
                                        name_buffer[name_len++] = string[i];
2561
 
2562
                                name_buffer[name_len] = '\0';
2563
 
2564
                                return name_buffer;
2565
                        }
2566
                }
2567
        }
2568
 
2569
        /* Not found */
2570
        return NULL;
2571
}
2572
 
2573
static char *
2574
get_tt_name(char *p)
2575
{
2576
        TT_Face face;
2577
        char *ret;
2578
 
2579
        /*printf("Trying to open: %s!\n",p);*/
2580
 
2581
        if (TT_Open_Face(engine, p, &face) != TT_Err_Ok) {
2582
                fprintf(stderr, "Error opening font: %s\n", p);
2583
                return NULL;
2584
        }
2585
 
2586
        ret = tt_lookup_name(face);
2587
 
2588
        TT_Close_Face(face);
2589
 
2590
        return ret;
2591
}
2592
 
2593
void
2594
GdFreeFontList(MWFONTLIST ***fonts, int n)
2595
{
2596
        int i;
2597
        MWFONTLIST *g, **list = *fonts;
2598
 
2599
        for (i = 0; i < n; i++) {
2600
                g = list[i];
2601
                if(g) {
2602
                        if(g->mwname)
2603
                                free(g->mwname);
2604
                        if(g->ttname)
2605
                                free(g->ttname);
2606
                        free(g);
2607
                }
2608
        }
2609
        free(list);
2610
        *fonts = 0;
2611
}
2612
 
2613
void
2614
GdGetFontList(MWFONTLIST ***fonts, int *numfonts)
2615
{
2616
        DIR *dir;
2617
        struct dirent *dent;
2618
        char *p, *ftmp;
2619
        int pl, idx = 0;
2620
        MWFONTLIST **list;
2621
 
2622
 
2623
        if (TT_Err_Ok != TT_Init_FreeType(&engine)) {
2624
                fprintf(stderr, "Unable to initialize freetype\n");
2625
                *numfonts = -1;
2626
                return ;
2627
        }
2628
 
2629
        dir = opendir(FREETYPE_FONT_DIR);
2630
 
2631
        if (dir <= 0) {
2632
                fprintf(stderr, "Error opening font directory\n");
2633
                *numfonts = -1;
2634
                return ;
2635
        }
2636
 
2637
        /* get the number of strings we need to allocate */
2638
        while ((dent = readdir(dir)) != NULL) {
2639
                p = strrchr(dent->d_name, '.');
2640
                if (strcasecmp(p, ".ttf") == 0)
2641
                        idx++;
2642
        }
2643
 
2644
        *numfonts = idx;
2645
        rewinddir(dir);
2646
 
2647
        /* allocate strings */
2648
        list = (MWFONTLIST**)malloc(idx * sizeof(MWFONTLIST*));
2649
        for (pl = 0; pl < idx; pl++)
2650
                list[pl] = (MWFONTLIST*)malloc(sizeof(MWFONTLIST));
2651
 
2652
        *fonts = list;
2653
 
2654
        idx = 0;
2655
 
2656
        while ((dent = readdir(dir)) != NULL) {
2657
                /* check extension */
2658
                p = strrchr(dent->d_name, '.');
2659
 
2660
                if (strcasecmp(p, ".ttf") == 0) {
2661
 
2662
                        /* get full path */
2663
                        p = 0;
2664
                        pl = strlen(FREETYPE_FONT_DIR) + strlen(dent->d_name) *
2665
                                                sizeof(char) + 2;
2666
                        p = (char*)malloc(pl);
2667
                        p = (char*)memset(p, '\0', pl);
2668
                        p = (char*)strcat(p, FREETYPE_FONT_DIR);
2669
                        p = (char*)strcat(p, "/");
2670
                        p = (char*)strcat(p, dent->d_name);
2671
 
2672
 
2673
                        if((ftmp = get_tt_name(p)) != NULL) {
2674
                                list[idx]->ttname = ftmp;
2675
                                list[idx]->mwname = malloc(strlen(dent->d_name) + 1);
2676
                                list[idx]->mwname = strcpy(list[idx]->mwname, dent->d_name);
2677
 
2678
                                idx++;
2679
                        }
2680
 
2681
                        free(p);
2682
                }
2683
        }
2684
 
2685
        closedir(dir);
2686
}
2687
#else /* !HAVE_FREETYPE_SUPPORT*/
2688
 
2689
void
2690
GdFreeFontList(MWFONTLIST ***fonts, int n)
2691
{
2692
}
2693
 
2694
void
2695
GdGetFontList(MWFONTLIST ***fonts, int *numfonts)
2696
{
2697
        *numfonts = -1;
2698
}
2699
#endif /* !HAVE_FREETYPE_SUPPORT*/

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.