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

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [engine/] [devfont.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
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_PALETTE:
726
                    /* reverse lookup palette entry for blend ;-)*/
727
                    palsrc = GETPALENTRY(gr_palette, src);
728
                    paldst = GETPALENTRY(gr_palette, dst);
729
                    d = REDVALUE(paldst);
730
                    r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
731
                    d = GREENVALUE(paldst);
732
                    g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
733
                    d = BLUEVALUE(paldst);
734
                    b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
735
                    *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
736
                                MWRGB(r, g, b));
737
                    break;
738
                }
739
        }
740
}
741
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
742
 
743
#if HAVE_T1LIB_SUPPORT
744
/* contributed by Vidar Hokstad*/
745
 
746
static int
747
t1lib_init(PSD psd)
748
{
749
        char **encoding;
750
        static int inited = 0;
751
 
752
        if (inited)
753
                return 1;
754
 
755
        T1_SetBitmapPad(8);
756
        if (!T1_InitLib(0))
757
                return 0;
758
 
759
        /* set default Latin1 encoding*/
760
        encoding = T1_LoadEncoding("IsoLatin1.enc");
761
        T1_SetDefaultEncoding(encoding);
762
 
763
#ifdef T1LIB_USE_AA_HIGH         
764
        T1_AASetLevel(T1_AA_HIGH);
765
#else
766
        T1_AASetLevel(T1_AA_LOW);
767
#endif   
768
#if 0
769
        /* kluge: this is required if 16bpp drawarea driver is used*/
770
        if(psd->bpp == 16)
771
                T1_AASetBitsPerPixel(16);
772
        else
773
#endif
774
                T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
775
 
776
        inited = 1;
777
        return 1;
778
}
779
 
780
static PMWT1LIBFONT
781
t1lib_createfont(const char *name, MWCOORD height, int attr)
782
{
783
        PMWT1LIBFONT    pf;
784
        int             id;
785
        char *          p;
786
        char            buf[256];
787
 
788
        /* match name against t1 font id's from t1 font database*/
789
        for(id=0; id<T1_Get_no_fonts(); ++id) {
790
                strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
791
 
792
                /* remove extension*/
793
                for(p=buf; *p; ++p) {
794
                        if(*p == '.') {
795
                                *p = 0;
796
                                break;
797
                        }
798
                }
799
 
800
                if(!strcmpi(name, buf)) {
801
                        /* allocate font structure*/
802
                        pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
803
                        if (!pf)
804
                                return NULL;
805
                        pf->fontprocs = &t1lib_procs;
806
                        GdSetFontSize((PMWFONT)pf, height);
807
                        GdSetFontRotation((PMWFONT)pf, 0);
808
                        GdSetFontAttr((PMWFONT)pf, attr, 0);
809
                        pf->fontid = id;
810
                        return pf;
811
                }
812
        }
813
        return NULL;
814
}
815
 
816
/*
817
 * Draw ascii text string using T1LIB type font
818
 */
819
static void
820
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
821
        const void *text, int cc, int flags)
822
{
823
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
824
        const unsigned char *str = text;
825
        MWCOORD         width;                  /* width of text area */
826
        MWCOORD         height;                 /* height of text area */
827
        MWCOORD         underliney;
828
        GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
829
#ifdef T1LIB_USE_AA_HIGH   
830
        OUTPIXELVAL     gvals[17];
831
 
832
        /* Blending array for antialiasing. The steeper the values increase
833
         * near the end, the sharper the characters look, but also more jagged
834
         */
835
        static unsigned char blend[17] = {
836
           0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
837
           0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
838
        };
839
#else   
840
        OUTPIXELVAL     gvals[5];
841
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
842
#endif   
843
 
844
        /* Check if we should throw out some fonts */
845
 
846
        if (pf->fontattr&MWTF_ANTIALIAS) {
847
#ifdef T1LIB_USE_AA_HIGH      
848
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
849
           T1_AAHSetGrayValues(gvals);
850
#else      
851
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
852
           T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
853
#endif
854
           g = T1_AASetString(pf->fontid,(char *)str,cc,0,
855
                (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
856
                pf->fontsize * 1.0, 0);
857
 
858
           if (g && g->bits) {
859
              /*MWPIXELVAL save = gr_background;*/
860
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
861
              height = g->metrics.ascent - g->metrics.descent;
862
 
863
              if(flags & MWTF_BASELINE)
864
                y -= g->metrics.ascent;
865
              else if(flags & MWTF_BOTTOM)
866
                y -= (height - 1);
867
              underliney = y + g->metrics.ascent;
868
 
869
              /* FIXME: Looks damn ugly if usebg is false.
870
               * Will be handled when using alphablending in GdArea...
871
               */
872
              /* clipping handled in GdArea*/
873
              /*FIXME kluge for transparency*/
874
              /*gr_background = gr_foreground + 1;*/
875
              /*gr_usebg = 0;*/
876
              GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
877
              /*gr_background = save;*/
878
 
879
              if (pf->fontattr & MWTF_UNDERLINE)
880
                   GdLine(psd, x, underliney, x+width, underliney, FALSE);
881
 
882
           }
883
        } else {
884
           /* Do non-aa drawing */
885
           g = T1_SetString(pf->fontid,(char *)str,cc,0,
886
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
887
                        pf->fontsize * 1.0, 0);
888
 
889
           if (g && g->bits) {
890
              unsigned char * b;
891
              int xoff;
892
              int maxy;
893
              int xmod;
894
 
895
              /* I'm sure this sorry excuse for a bitmap rendering routine can
896
               * be optimized quite a bit ;)
897
               */
898
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
899
              height = g->metrics.ascent - g->metrics.descent;
900
 
901
              if(flags & MWTF_BASELINE)
902
                y -= g->metrics.ascent;
903
              else if(flags & MWTF_BOTTOM)
904
                y -= (height - 1);
905
              underliney = y + g->metrics.ascent;
906
 
907
              b = g->bits;
908
              maxy = y + height;
909
 
910
/*            if ((x + width) > psd->xvirtres) {
911
                 xmod = (x + width - psd->xvirtres + 7) >> 3;
912
                 width = width + x + width - psd->xvirtres;
913
              } else xmod = 0;
914
*/
915
              xmod = 0;
916
              while (y < maxy) {
917
                 unsigned char data;
918
                 xoff = 0;
919
                 while (xoff < width ) {
920
                    if (!(xoff % 8)) {
921
                       data = *b;
922
                       b++;
923
                    }
924
 
925
                    if (GdClipPoint(psd, x+xoff,y)) {
926
                       if (gr_usebg) {
927
                          psd->DrawPixel(psd,x+xoff,y,
928
                              data & (1 << (xoff % 8)) ?
929
                                    gr_foreground : gr_background);
930
                       } else if (data & (1 << (xoff % 8))) {
931
                          psd->DrawPixel(psd,x+xoff,y, gr_foreground);
932
                       }
933
                    }
934
                    xoff++;
935
                 }
936
                 b += xmod;
937
                 y++;
938
              }
939
              if (pf->fontattr & MWTF_UNDERLINE)
940
                   GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
941
           }
942
        }
943
 
944
   if (g && g->bits) {
945
           /* Save some memory */
946
           free(g->bits);
947
           g->bits = 0; /* Make sure T1lib doesnt try to free it again */
948
   }
949
 
950
   GdFixCursor(psd);
951
}
952
 
953
static MWBOOL
954
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
955
{
956
        int     i;
957
        MWCOORD width, height, baseline;
958
 
959
        /* FIXME, guess all sizes*/
960
        GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
961
        pfontinfo->height = height;
962
        pfontinfo->maxwidth = width;
963
        pfontinfo->baseline = 0;
964
        pfontinfo->firstchar = 32;
965
        pfontinfo->lastchar = 255;
966
        pfontinfo->fixed = TRUE;
967
        for(i=0; i<256; ++i)
968
                pfontinfo->widths[i] = width;
969
        return TRUE;
970
}
971
 
972
/* Get the width and height of passed text string in the current font*/
973
static void
974
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
975
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
976
{
977
        PMWT1LIBFONT            pf = (PMWT1LIBFONT)pfont;
978
        const unsigned char *   str = text;
979
        GLYPH *                 g;
980
 
981
        g = T1_SetString(pf->fontid, (char *)str, cc, 0,
982
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
983
        *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
984
        *pheight = g->metrics.ascent - g->metrics.descent;
985
        if(g && g->bits) {
986
                free(g->bits);
987
                g->bits = 0;
988
        }
989
#if 0
990
        BBox                    b;
991
 
992
        /* FIXME. Something is *VERY* wrong here */
993
        b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
994
 
995
        DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
996
        DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
997
        *pwidth = (b.urx - b.llx);
998
        *pheight = (b.lly - b.ury);
999
#endif
1000
}
1001
 
1002
static void
1003
t1lib_destroyfont(PMWFONT pfont)
1004
{
1005
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
1006
 
1007
        T1_DeleteAllSizes(pf->fontid);
1008
        free(pf);
1009
}
1010
 
1011
#endif /* HAVE_T1LIB_SUPPORT*/
1012
 
1013
#if HAVE_FREETYPE_SUPPORT
1014
static OUTPIXELVAL gray_palette[5];
1015
 
1016
static int
1017
freetype_init(PSD psd)
1018
{
1019
        static int inited = 0;
1020
 
1021
        if (inited)
1022
                return 1;
1023
 
1024
        /* Init freetype library */
1025
        if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
1026
                return 0;
1027
        }
1028
 
1029
        /* Init kerning extension */
1030
        if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
1031
                return 0;
1032
 
1033
        inited = 1;
1034
        return 1;
1035
}
1036
 
1037
static PMWFREETYPEFONT
1038
freetype_createfont(const char *name, MWCOORD height, int attr)
1039
{
1040
        PMWFREETYPEFONT         pf;
1041
        unsigned short          i, n;
1042
        unsigned short          platform, encoding;
1043
        TT_Face_Properties      properties;
1044
        char *                  p;
1045
        char                    fontname[128];
1046
 
1047
        /* check for pathname prefix*/
1048
        if (strchr(name, '/') != NULL)
1049
                strcpy(fontname, name);
1050
        else {
1051
                strcpy(fontname, FREETYPE_FONT_DIR);
1052
                strcat(fontname, "/");
1053
                strcat(fontname, name);
1054
        }
1055
 
1056
        /* check for extension*/
1057
        if ((p = strrchr(fontname, '.')) == NULL ||
1058
            strcmp(p, ".ttf") != 0) {
1059
                strcat(fontname, ".ttf");
1060
        }
1061
 
1062
        /* allocate font structure*/
1063
        pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
1064
        if (!pf)
1065
                return NULL;
1066
        pf->fontprocs = &freetype_procs;
1067
 
1068
        /* Load face */
1069
        if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
1070
                goto out;
1071
 
1072
        /* Load first kerning table */
1073
        pf->can_kern = TRUE;
1074
        if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
1075
                pf->can_kern = FALSE;
1076
        else {
1077
                if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
1078
                    != TT_Err_Ok)
1079
                        pf->can_kern = FALSE;
1080
                else {
1081
                        /* Support only version 0 kerning table ... */
1082
                        if ((pf->directory.version != 0) ||
1083
                                (pf->directory.nTables <= 0) ||
1084
                                (pf->directory.tables->loaded != 1) ||
1085
                                (pf->directory.tables->version != 0) ||
1086
                                (pf->directory.tables->t.kern0.nPairs <= 0))
1087
                                        pf->can_kern = FALSE;
1088
                }
1089
        }
1090
 
1091
        /* get face properties and allocate preload arrays */
1092
        TT_Get_Face_Properties (pf->face, &properties);
1093
 
1094
#if 0
1095
        /*
1096
         * Use header information for ascent and descent
1097
         * to compute scaled ascent/descent for current font height.
1098
         */
1099
        h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
1100
                + properties.os2->sTypoLineGap;
1101
        ascent = properties.os2->sTypoAscender
1102
                + properties.os2->sTypoLineGap/2;
1103
        pf->ascent = (ascent * height + h/2) / h;
1104
        pf->descent = height - pf->ascent;
1105
#endif
1106
        /* Create a glyph container */
1107
        if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
1108
                goto out;
1109
 
1110
        /* create instance */
1111
        if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
1112
                goto out;
1113
 
1114
        /* Set the instance resolution */
1115
        if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
1116
                goto out;
1117
 
1118
        /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
1119
        n = properties.num_CharMaps;
1120
 
1121
        for (i = 0; i < n; i++) {
1122
                TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
1123
                if (((platform == TT_PLATFORM_MICROSOFT) &&
1124
                        (encoding == TT_MS_ID_UNICODE_CS)) ||
1125
                                ((platform == TT_PLATFORM_APPLE_UNICODE) &&
1126
                                        (encoding == TT_APPLE_ID_DEFAULT)))
1127
                {
1128
                        TT_Get_CharMap (pf->face, i, &pf->char_map);
1129
                        i = n + 1;
1130
                }
1131
        }
1132
        if (i == n) {
1133
                DPRINTF("freetype_createfont: no unicode map table\n");
1134
                goto out;
1135
        }
1136
 
1137
        GdSetFontSize((PMWFONT)pf, height);
1138
        GdSetFontRotation((PMWFONT)pf, 0);
1139
        GdSetFontAttr((PMWFONT)pf, attr, 0);
1140
 
1141
        return pf;
1142
 
1143
out:
1144
        free(pf);
1145
        return NULL;
1146
}
1147
 
1148
static int
1149
compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
1150
{
1151
        int             i = 0;
1152
        int             kernval;
1153
        int             nPairs = pf->directory.tables->t.kern0.nPairs;
1154
        TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
1155
 
1156
        if (pf->last_glyph_code != -1) {
1157
                while ((pair->left != pf->last_glyph_code)
1158
                        && (pair->right != current_glyph_code))
1159
                {
1160
                        pair++;
1161
                        i++;
1162
                        if (i == nPairs)
1163
                        break;
1164
                }
1165
 
1166
                if (i == nPairs)
1167
                        kernval = 0;
1168
                else
1169
                        /* We round the value (hence the +32) */
1170
                        kernval = (pair->value + 32) & -64;
1171
        } else
1172
                kernval = 0;
1173
 
1174
        return kernval;
1175
}
1176
 
1177
static TT_UShort
1178
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
1179
{
1180
        TT_Glyph_Metrics metrics;
1181
 
1182
        if (TT_Load_Glyph ( pf->instance, pf->glyph,
1183
                TT_Char_Index (pf->char_map,glyph_index),
1184
                TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1185
        {
1186
                /* Try to load default glyph: index 0 */
1187
                if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
1188
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1189
                    return 0;
1190
        }
1191
 
1192
        TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1193
        return((metrics.advance & 0xFFFFFFC0) >> 6);
1194
}
1195
 
1196
/* Render a single glyph*/
1197
static void
1198
drawchar(PMWFREETYPEFONT pf, PSD psd, TT_Glyph glyph, int x_offset,
1199
        int y_offset)
1200
{
1201
        TT_F26Dot6      xmin, ymin, xmax, ymax, x, y, z;
1202
        unsigned char   *src, *srcptr;
1203
        MWPIXELVAL      *dst, *dstptr;
1204
        MWPIXELVAL      *bitmap;
1205
        int             size, width, height;
1206
        TT_Outline      outline;
1207
        TT_BBox         bbox;
1208
        TT_Raster_Map   Raster;
1209
        TT_Error        error;
1210
        /*MWPIXELVAL    save;*/
1211
 
1212
        /* we begin by grid-fitting the bounding box */
1213
        TT_Get_Glyph_Outline (pf->glyph, &outline);
1214
        TT_Get_Outline_BBox (&outline, &bbox);
1215
 
1216
        xmin = (bbox.xMin & -64) >> 6;
1217
        ymin = (bbox.yMin & -64) >> 6;
1218
        xmax = ((bbox.xMax + 63) & -64) >> 6;
1219
        ymax = ((bbox.yMax + 63) & -64) >> 6;
1220
        width = xmax - xmin;
1221
        height = ymax - ymin;
1222
        size = width * height;
1223
 
1224
        /* now re-allocate the raster bitmap */
1225
        Raster.rows = height;
1226
        Raster.width = width;
1227
 
1228
        if (pf->fontattr&MWTF_ANTIALIAS)
1229
                Raster.cols = (Raster.width + 3) & -4;  /* pad to 32-bits */
1230
        else
1231
                Raster.cols = (Raster.width + 7) & -8;  /* pad to 64-bits ??? */
1232
 
1233
        Raster.flow = TT_Flow_Up;
1234
        Raster.size = Raster.rows * Raster.cols;
1235
        Raster.bitmap = malloc (Raster.size);
1236
 
1237
        memset (Raster.bitmap, 0, Raster.size);
1238
 
1239
        /* now render the glyph in the small pixmap */
1240
 
1241
        /* IMPORTANT NOTE: the offset parameters passed to the function     */
1242
        /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
1243
        /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
1244
        /* This is why we _did_ grid-fit the bounding box, especially xmin  */
1245
        /* and ymin.                                                        */
1246
 
1247
        if (!(pf->fontattr&MWTF_ANTIALIAS))
1248
                error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
1249
                                -xmin * 64, -ymin * 64);
1250
        else
1251
                error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
1252
                                -xmin * 64, -ymin * 64);
1253
 
1254
        if (error) {
1255
                free (Raster.bitmap);
1256
                return;
1257
        }
1258
 
1259
        bitmap = malloc (size * sizeof (MWPIXELVAL));
1260
        memset (bitmap, 0, size * sizeof (MWPIXELVAL));
1261
 
1262
        src = (char *) Raster.bitmap;
1263
        dst = bitmap + (size - width);
1264
 
1265
        for (y = ymin; y < ymax; y++) {
1266
                srcptr = src;
1267
                dstptr = dst;
1268
 
1269
                for (x = xmin; x < xmax; x++) {
1270
                        if (pf->fontattr&MWTF_ANTIALIAS)
1271
                                *dstptr++ = gray_palette[(int) *srcptr];
1272
                        else {
1273
                                for(z=0;
1274
                                    z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
1275
                                    z++) {
1276
                                        *dstptr++ = ((*srcptr << z) & 0x80)?
1277
                                                gr_foreground: gr_background;
1278
                                }
1279
                                x += 7;
1280
                        }
1281
 
1282
                        srcptr++;
1283
                }
1284
 
1285
                src += Raster.cols;
1286
                dst -= width;
1287
        }
1288
 
1289
        /* FIXME - must clear background upstairs if not gr_usebg*/
1290
        /* FIXME: GdArea problem if fg == bg*/
1291
        /*save = gr_background;*/
1292
        /*gr_background = gr_foreground + 1;*/
1293
 
1294
        /* Now draw the bitmap ... */
1295
        GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
1296
                bitmap, MWPF_PIXELVAL);
1297
 
1298
        /*gr_background = save;*/
1299
 
1300
        free (bitmap);
1301
        free (Raster.bitmap);
1302
}
1303
 
1304
/*
1305
 * Draw unicode 16 text string using FREETYPE type font
1306
 */
1307
static void
1308
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
1309
        const void *text, int cc, int flags)
1310
{
1311
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1312
        const unsigned short *  str = text;
1313
        TT_F26Dot6      x = ax, y = ay;
1314
        TT_Pos          vec_x, vec_y;
1315
        int             i;
1316
        TT_F26Dot6      startx, starty;
1317
        TT_Outline      outline;
1318
        TT_UShort       curchar;
1319
        TT_Glyph_Metrics metrics;
1320
        TT_Face_Properties properties;
1321
        TT_Instance_Metrics imetrics;
1322
        TT_F26Dot6 ascent, descent;
1323
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1324
        static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
1325
 
1326
        pf->last_glyph_code = -1;               /* reset kerning*/
1327
        pf->last_pen_pos = -32767;
1328
 
1329
        /*
1330
         * Compute instance ascent & descent values
1331
         * in fractional units (1/64th pixel)
1332
         */
1333
        TT_Get_Face_Properties (pf->face, &properties);
1334
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1335
 
1336
        ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
1337
        descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
1338
 
1339
        /*
1340
         * Offset the starting point if necessary,
1341
         * FreeType always aligns at baseline
1342
         */
1343
        if (flags&MWTF_BOTTOM) {
1344
                vec_x = 0;
1345
                vec_y = descent;
1346
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1347
                x -= vec_x / 64;
1348
                y += vec_y / 64;
1349
        } else if (flags&MWTF_TOP) {
1350
                vec_x = 0;
1351
                vec_y = ascent;
1352
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1353
                x -= vec_x / 64;
1354
                y += vec_y / 64;
1355
        }
1356
 
1357
        /* Set the "graylevels" */
1358
        if (pf->fontattr&MWTF_ANTIALIAS) {
1359
                TT_Set_Raster_Gray_Palette (engine, virtual_palette);
1360
 
1361
                alphablend(psd, gray_palette, gr_foreground, gr_background,
1362
                        blend, 5);
1363
        }
1364
 
1365
        startx = x;
1366
        starty = y;
1367
        for (i = 0; i < cc; i++) {
1368
                curchar = TT_Char_Index (pf->char_map, str[i]);
1369
 
1370
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1371
                        TTLOAD_DEFAULT) != TT_Err_Ok)
1372
                                continue;
1373
 
1374
                if (pf->fontrotation) {
1375
                        TT_Get_Glyph_Outline (pf->glyph, &outline);
1376
                        TT_Transform_Outline (&outline, &pf->matrix);
1377
                }
1378
 
1379
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1380
 
1381
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1382
                        if (pf->fontrotation) {
1383
                                vec_x = compute_kernval(pf, curchar);
1384
                                vec_y = 0;
1385
                                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1386
 
1387
                                x += vec_x / 64;
1388
                                y -= vec_y / 64;
1389
                        } else
1390
                                x += compute_kernval(pf, curchar) / 64;
1391
                }
1392
 
1393
                drawchar(pf, psd, pf->glyph, x, y);
1394
 
1395
                if (pf->fontrotation) {
1396
                        vec_x = metrics.advance;
1397
                        vec_y = 0;
1398
                        TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
1399
 
1400
                        x += vec_x / 64;
1401
                        y -= vec_y / 64;
1402
                } else {
1403
                        x += metrics.advance / 64;
1404
 
1405
                        /* Kerning point syndrome avoidance */
1406
                        if (pf->last_pen_pos > x)
1407
                                x = pf->last_pen_pos;
1408
                        pf->last_pen_pos = x;
1409
                }
1410
 
1411
                pf->last_glyph_code = curchar;
1412
        }
1413
 
1414
        if (pf->fontattr & MWTF_UNDERLINE)
1415
                GdLine(psd, startx, starty, x, y, FALSE);
1416
}
1417
 
1418
/*
1419
 * Return information about a specified font.
1420
 */
1421
static MWBOOL
1422
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1423
{
1424
        int     i;
1425
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1426
        TT_Face_Properties      properties;
1427
    TT_Instance_Metrics imetrics;
1428
    TT_UShort last_glyph_index;
1429
 
1430
        TT_Get_Face_Properties (pf->face, &properties);
1431
    TT_Get_Instance_Metrics(pf->instance, &imetrics);
1432
 
1433
    /* Fill up the fields */
1434
        pfontinfo->height = (((properties.horizontal->Ascender * \
1435
                                imetrics.y_scale)/ 0x10000) >> 6) -
1436
                            (((properties.horizontal->Descender * \
1437
                                imetrics.y_scale)/ 0x10000) >> 6);
1438
        pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
1439
                                imetrics.x_scale)/ 0x10000) >> 6;
1440
        pfontinfo->baseline = ((properties.horizontal->Ascender * \
1441
                                imetrics.y_scale)/ 0x10000) >> 6;
1442
        pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
1443
        pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
1444
        pfontinfo->fixed = properties.postscript->isFixedPitch;
1445
 
1446
    last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
1447
 
1448
    /* Doesn't work ... don't know why ....*/
1449
#if 0
1450
    if (TT_Get_Face_Widths( pf->face, 0,
1451
                            last_glyph_index, widths, NULL ) != TT_Err_Ok) {
1452
        return TRUE;
1453
    }
1454
 
1455
    for(i=0; i<=last_glyph_index; i++)
1456
                DPRINTF("widths[%d]: %d\n", i, widths[i]);
1457
#endif
1458
 
1459
    /* Get glyphs widths */
1460
        for(i=0; i<=last_glyph_index; i++)
1461
                pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
1462
 
1463
#if 0
1464
    DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
1465
    x_resolution: %d\ny_resolution: %d\n",
1466
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
1467
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
1468
 
1469
    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
1470
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
1471
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
1472
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
1473
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
1474
    Postscript Say monospaced?: %d\n",\
1475
    properties.horizontal->Ascender,
1476
    properties.horizontal->Descender,
1477
    properties.horizontal->xMax_Extent,
1478
    (properties.header->Mac_Style & 0x2)?1:0,
1479
    (properties.header->Mac_Style & 0x1)?1:0,
1480
    properties.os2->sTypoAscender,
1481
    properties.os2->sTypoDescender,
1482
    properties.os2->usWinAscent,
1483
    properties.os2->usWinDescent,
1484
    properties.os2->usFirstCharIndex,
1485
    properties.os2->usLastCharIndex,
1486
    (properties.os2->fsSelection & 0x1)?1:0,
1487
    (properties.os2->fsSelection & 0x20)?1:0,
1488
    properties.postscript->isFixedPitch,
1489
    (properties.os2->panose[3] == 9)?1:0);
1490
#endif  
1491
 
1492
        return TRUE;
1493
}
1494
 
1495
static void
1496
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
1497
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1498
{
1499
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1500
        const unsigned short *  str = text;
1501
        TT_F26Dot6      x = 0;
1502
        int             i;
1503
        TT_UShort       curchar;
1504
        TT_Glyph_Metrics metrics;
1505
        TT_Face_Properties      properties;
1506
        TT_Instance_Metrics imetrics;
1507
 
1508
        TT_Get_Face_Properties (pf->face, &properties);
1509
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1510
 
1511
        pf->last_glyph_code = -1;               /* reset kerning*/
1512
        pf->last_pen_pos = -32767;
1513
 
1514
        for (i = 0; i < cc; i++) {
1515
                curchar = TT_Char_Index (pf->char_map, str[i]);
1516
 
1517
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1518
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1519
                                continue;
1520
 
1521
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1522
 
1523
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1524
                                x += compute_kernval(pf, curchar) / 64;
1525
                }
1526
 
1527
                x += metrics.advance / 64;
1528
 
1529
                /* Kerning point syndrome avoidance */
1530
                if (pf->last_pen_pos > x)
1531
                        x = pf->last_pen_pos;
1532
                pf->last_pen_pos = x;
1533
 
1534
                pf->last_glyph_code = curchar;
1535
        }
1536
 
1537
        *pwidth = x;
1538
        *pheight =  (((properties.horizontal->Ascender *
1539
                        imetrics.y_scale)/ 0x10000) >> 6) -
1540
                    (((properties.horizontal->Descender *
1541
                    imetrics.y_scale)/ 0x10000) >> 6);
1542
        /* FIXME: is it what's required ?? */
1543
        *pbase = (((-properties.horizontal->Descender) *
1544
                    imetrics.y_scale)/ 0x10000) >> 6;
1545
}
1546
 
1547
static void
1548
freetype_destroyfont(PMWFONT pfont)
1549
{
1550
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1551
 
1552
        TT_Close_Face(pf->face);
1553
        free(pf);
1554
}
1555
 
1556
static void
1557
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
1558
{
1559
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1560
 
1561
        pf->fontsize = fontsize;
1562
 
1563
        /* We want real pixel sizes ... not points ...*/
1564
        TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
1565
                                pf->fontsize, pf->fontsize * 64 );
1566
#if 0
1567
        /* set charsize (convert to points for freetype)*/
1568
        TT_Set_Instance_CharSize (pf->instance,
1569
                ((pf->fontsize * 72 + 96/2) / 96) * 64);
1570
#endif
1571
}
1572
 
1573
static void
1574
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
1575
{
1576
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1577
        float           angle;
1578
 
1579
        pf->fontrotation = tenthdegrees;
1580
 
1581
        /* Build the rotation matrix with the given angle */
1582
        TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
1583
 
1584
        angle = pf->fontrotation * M_PI / 1800;
1585
        pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
1586
        pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
1587
        pf->matrix.xx = pf->matrix.yy;
1588
        pf->matrix.xy = -pf->matrix.yx;
1589
}
1590
 
1591
#endif /* HAVE_FREETYPE_SUPPORT*/
1592
 
1593
/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
1594
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
1595
 * On the other hand, if the UTF-8 string contains surrogate values, this
1596
 * is considered an error and returned as such.
1597
 *
1598
 * The destination array must be able to hold as many Unicode-16 characters
1599
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
1600
 * characters are ASCII characters.  No more will be needed.
1601
 *
1602
 * Copyright (c) 2000 Morten Rolland, Screen Media
1603
 */
1604
static int
1605
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
1606
{
1607
        int count = 0;
1608
        unsigned char c0, c1;
1609
        unsigned long scalar;
1610
 
1611
        while(--cc >= 0) {
1612
                c0 = *utf8++;
1613
                /*DPRINTF("Trying: %02x\n",c0);*/
1614
 
1615
                if ( c0 < 0x80 ) {
1616
                        /* Plain ASCII character, simple translation :-) */
1617
                        *unicode16++ = c0;
1618
                        count++;
1619
                        continue;
1620
                }
1621
 
1622
                if ( (c0 & 0xc0) == 0x80 )
1623
                        /* Illegal; starts with 10xxxxxx */
1624
                        return -1;
1625
 
1626
                /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
1627
                scalar = c0;
1628
                if(--cc < 0)
1629
                        return -1;
1630
                c1 = *utf8++;
1631
                /*DPRINTF("c1=%02x\n",c1);*/
1632
                if ( (c1 & 0xc0) != 0x80 )
1633
                        /* Bad byte */
1634
                        return -1;
1635
                scalar <<= 6;
1636
                scalar |= (c1 & 0x3f);
1637
 
1638
                if ( !(c0 & 0x20) ) {
1639
                        /* Two bytes UTF-8 */
1640
                        if ( scalar < 0x80 )
1641
                                return -1;      /* Overlong encoding */
1642
                        *unicode16++ = scalar & 0x7ff;
1643
                        count++;
1644
                        continue;
1645
                }
1646
 
1647
                /* c0 must be 111xxxxx if we get here => at least 3 bytes */
1648
                if(--cc < 0)
1649
                        return -1;
1650
                c1 = *utf8++;
1651
                /*DPRINTF("c1=%02x\n",c1);*/
1652
                if ( (c1 & 0xc0) != 0x80 )
1653
                        /* Bad byte */
1654
                        return -1;
1655
                scalar <<= 6;
1656
                scalar |= (c1 & 0x3f);
1657
 
1658
                if ( !(c0 & 0x10) ) {
1659
                        /*DPRINTF("####\n");*/
1660
                        /* Three bytes UTF-8 */
1661
                        if ( scalar < 0x800 )
1662
                                return -1;      /* Overlong encoding */
1663
                        if ( scalar >= 0xd800 && scalar < 0xe000 )
1664
                                return -1;      /* UTF-16 high/low halfs */
1665
                        *unicode16++ = scalar & 0xffff;
1666
                        count++;
1667
                        continue;
1668
                }
1669
 
1670
                /* c0 must be 1111xxxx if we get here => at least 4 bytes */
1671
                c1 = *utf8++;
1672
                if(--cc < 0)
1673
                        return -1;
1674
                /*DPRINTF("c1=%02x\n",c1);*/
1675
                if ( (c1 & 0xc0) != 0x80 )
1676
                        /* Bad byte */
1677
                        return -1;
1678
                scalar <<= 6;
1679
                scalar |= (c1 & 0x3f);
1680
 
1681
                if ( !(c0 & 0x08) ) {
1682
                        /* Four bytes UTF-8, needs encoding as surrogates */
1683
                        if ( scalar < 0x10000 )
1684
                                return -1;      /* Overlong encoding */
1685
                        scalar -= 0x10000;
1686
                        *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
1687
                        *unicode16++ = (scalar & 0x3ff) + 0xdc00;
1688
                        count += 2;
1689
                        continue;
1690
                }
1691
 
1692
                return -1;      /* No support for more than four byte UTF-8 */
1693
        }
1694
        return count;
1695
}
1696
 
1697
#if HAVE_HZK_SUPPORT
1698
 
1699
/* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
1700
 * a single 2-byte UC16 character is encoded into a surrogate pair.
1701
 * return -1 ,if error;
1702
 * The destination array must be able to hold as many
1703
 * as there are Unicode-16 characters.
1704
 *
1705
 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
1706
 */
1707
static int
1708
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
1709
{
1710
        FILE* fp;
1711
        char buffer[256];
1712
        unsigned char *uc16p;
1713
        int i=0,j=0, k;
1714
        unsigned char *filebuffer;
1715
        unsigned short *uc16pp,*table;
1716
        unsigned short uc16px;
1717
        int length=31504;
1718
 
1719
        if (use_big5)
1720
                length=54840;
1721
 
1722
        uc16p=(unsigned char *) uc16;
1723
        uc16pp=(unsigned short *) uc16;
1724
 
1725
        strcpy(buffer,HZK_FONT_DIR);
1726
        if (use_big5)
1727
                strcat(buffer,"/BG2UBG.KU");
1728
        else
1729
                strcat(buffer,"/UGB2GB.KU");
1730
        if(!(fp = fopen(buffer, "rb")))
1731
        {
1732
                 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
1733
                 return -1;
1734
        }
1735
 
1736
        filebuffer= (unsigned char *)malloc ( length);
1737
 
1738
        if(fread(filebuffer, sizeof(char),length, fp) < length) {
1739
                  fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
1740
                  fclose(fp);
1741
                  return -1;
1742
        }
1743
        fclose(fp);
1744
 
1745
        if (use_big5)
1746
        {
1747
                table=(unsigned short *)filebuffer;
1748
                while(1)
1749
                {
1750
                        if(j>=cc)
1751
                        {
1752
                                ascii[i]=0;
1753
                                break;
1754
                        }
1755
                        uc16px=*uc16pp;
1756
                        if((uc16px)<=0x00ff)
1757
                        {
1758
                                ascii[i]=(char)(*uc16pp);
1759
                                i++;
1760
                        }
1761
                        else
1762
                        {
1763
                                ascii[i]=0xa1; ascii[i+1]=0x40;
1764
                                for (k=0; k<13710; k++)
1765
                                {
1766
                                        if (*(table+(k*2+1))==(uc16px))
1767
                                        {
1768
                                                ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
1769
                                                ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
1770
                                                break;
1771
                                        }
1772
                                }
1773
                                i+=2;
1774
                        }
1775
                        uc16pp++; j++;
1776
                }
1777
        }
1778
        else
1779
        {
1780
        while(1)
1781
        {
1782
                if(j>=cc)
1783
                {
1784
                        ascii[i]=0;
1785
                        break;
1786
                }
1787
                if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
1788
                {
1789
                        ascii[i]=0;
1790
                        break;
1791
                }
1792
                else
1793
                {
1794
                        if(*((uc16p)+j+1)==0)
1795
                        {
1796
                                ascii[i]=*((uc16p)+j);
1797
                                i++;
1798
                                j+=2;
1799
                        }
1800
                        else
1801
                        {
1802
                        /* to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
1803
                        {
1804
                                int p1=0,p2=length-4,p;
1805
                                unsigned int c1,c2,c,d;
1806
                                c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
1807
                                c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
1808
                                d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
1809
                                if(c1==d)
1810
                                {
1811
                                        ascii[i]=filebuffer[p1+2];
1812
                                        ascii[i+1]=filebuffer[p1+3];
1813
                                        goto findit;
1814
                                }
1815
                                if(c2==d)
1816
                                {
1817
                                        ascii[i]=filebuffer[p2+2];
1818
                                        ascii[i+1]=filebuffer[p2+3];
1819
                                        goto findit;
1820
                                }
1821
                                while(1)
1822
                                {
1823
                                        p=(((p2-p1)/2+p1)>>2)<<2;
1824
                                        c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
1825
                                        if(d==c)        /* find it*/
1826
                                        {
1827
                                                ascii[i]=filebuffer[p+2];
1828
                                                ascii[i+1]=filebuffer[p+3];
1829
                                                break;
1830
                                        }
1831
                                        else if(p2<=p1+4)       /* can't find.*/
1832
                                        {
1833
                                                ascii[i]='.';   /* ((uc16p)+j);*/
1834
                                                ascii[i+1]='.'; /* ((uc16p)+j+1);*/
1835
                                                break;
1836
                                        }
1837
                                        else if(d<c)
1838
                                        {
1839
                                                p2=p;
1840
                                                c2=c;
1841
                                        }
1842
                                        else
1843
                                        {
1844
                                                p1=p;
1845
                                                c1=c;
1846
                                        }
1847
                                }
1848
                        }
1849
                        findit:
1850
                        i+=2;
1851
                        j+=2;
1852
                        }
1853
                }
1854
        }
1855
        }
1856
        free(filebuffer);
1857
 
1858
        return i;
1859
}
1860
 
1861
/************************** functions definition ******************************/
1862
 
1863
static int hzk_id( PMWHZKFONT pf )
1864
{
1865
        switch(pf->font_height)
1866
        {
1867
        case 12:
1868
                return 0;
1869
        case 16: default:
1870
                return 1;
1871
        }
1872
}
1873
 
1874
/* This function get Chinese font info from etc file.*/
1875
static MWBOOL GetCFontInfo( PMWHZKFONT pf )
1876
{
1877
        int charset;
1878
 
1879
        if (use_big5)
1880
                charset=(13094+408);
1881
        else
1882
                charset=8178;
1883
 
1884
        CFont[hzk_id(pf)].width = pf->cfont_width;
1885
        pf->CFont.width = pf->cfont_width;
1886
 
1887
        CFont[hzk_id(pf)].height = pf->font_height;
1888
        pf->CFont.height = pf->font_height;
1889
 
1890
        CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
1891
                pf->CFont.height * charset;
1892
        pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
1893
 
1894
        if(pf->CFont.size < charset * 8)
1895
                return FALSE;
1896
 
1897
        strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
1898
        strcpy(pf->CFont.file,HZK_FONT_DIR);
1899
 
1900
        if(pf->font_height==16)
1901
        {
1902
                strcat(CFont[hzk_id(pf)].file,"/hzk16");
1903
                strcat(pf->CFont.file,"/hzk16");
1904
        }
1905
        else
1906
        {
1907
                strcat(CFont[hzk_id(pf)].file,"/hzk12");
1908
                strcat(pf->CFont.file,"/hzk12");
1909
        }
1910
 
1911
        if (use_big5)
1912
        {
1913
                CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
1914
                pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
1915
        }
1916
 
1917
        return TRUE;
1918
}
1919
 
1920
/* This function get ASCII font info from etc file.*/
1921
static MWBOOL GetAFontInfo( PMWHZKFONT pf )
1922
{
1923
        AFont[hzk_id(pf)].width = pf->afont_width;
1924
        pf->AFont.width = pf->afont_width;
1925
 
1926
        AFont[hzk_id(pf)].height = pf->font_height;
1927
        pf->AFont.height = pf->font_height;
1928
 
1929
        AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
1930
                pf->AFont.height * 255;
1931
        pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
1932
 
1933
        if(pf->AFont.size < 255 * 8)
1934
                return FALSE;
1935
 
1936
        strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
1937
        strcpy(pf->AFont.file,HZK_FONT_DIR);
1938
 
1939
        if(pf->font_height==16)
1940
        {
1941
                strcat(AFont[hzk_id(pf)].file,"/asc16");
1942
                strcat(pf->AFont.file,"/asc16");
1943
        }
1944
        else
1945
        {
1946
                strcat(AFont[hzk_id(pf)].file,"/asc12");
1947
                strcat(pf->AFont.file,"/asc12");
1948
        }
1949
        return TRUE;
1950
}
1951
 
1952
/* This function load system font into memory.*/
1953
static MWBOOL LoadFont( PMWHZKFONT pf )
1954
{
1955
        FILE* fp;
1956
 
1957
        if(!GetCFontInfo(pf))
1958
        {
1959
                fprintf (stderr, "Get Chinese HZK font info failure!\n");
1960
                return FALSE;
1961
        }
1962
        if(CFont[hzk_id(pf)].pFont == NULL)     /* check font cache*/
1963
        {
1964
 
1965
 
1966
                /* Allocate system memory for Chinese font.*/
1967
                if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
1968
                {
1969
                        fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
1970
                        return FALSE;
1971
                }
1972
 
1973
                /* Open font file and read information to the system memory.*/
1974
                fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
1975
                if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
1976
                {
1977
                        fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
1978
                        return FALSE;
1979
                }
1980
                if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
1981
                {
1982
                        fprintf (stderr, "Error in reading Chinese HZK font file!\n");
1983
                        fclose(fp);
1984
                        return FALSE;
1985
                }
1986
 
1987
                fclose(fp);
1988
 
1989
                CFont[hzk_id(pf)].use_count=0;
1990
 
1991
                fprintf (stderr, "done.\n" );
1992
 
1993
        }
1994
        cfont_address = CFont[hzk_id(pf)].pFont;
1995
        pf->cfont_address = CFont[hzk_id(pf)].pFont;
1996
        pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
1997
 
1998
        CFont[hzk_id(pf)].use_count++;
1999
 
2000
        if(!GetAFontInfo(pf))
2001
        {
2002
               fprintf (stderr, "Get ASCII HZK font info failure!\n");
2003
               return FALSE;
2004
        }
2005
        if(AFont[hzk_id(pf)].pFont == NULL)     /* check font cache*/
2006
        {
2007
 
2008
 
2009
                /* Allocate system memory for ASCII font.*/
2010
                if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
2011
                {
2012
                        fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
2013
                        free(CFont[hzk_id(pf)].pFont);
2014
                        CFont[hzk_id(pf)].pFont = NULL;
2015
                        return FALSE;
2016
                }
2017
 
2018
                /* Load ASCII font information to the near memory.*/
2019
                fprintf (stderr, "Loading ASCII HZK font..." );
2020
                if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
2021
                {
2022
                        fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
2023
                        return FALSE;
2024
                }
2025
                if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
2026
                {
2027
                        fprintf (stderr, "Error in reading ASCII HZK font file!\n");
2028
                        fclose(fp);
2029
                        return FALSE;
2030
                }
2031
 
2032
                fclose(fp);
2033
 
2034
                AFont[hzk_id(pf)].use_count=0;
2035
 
2036
                fprintf (stderr, "done.\n" );
2037
 
2038
        }
2039
        afont_address = AFont[hzk_id(pf)].pFont;
2040
        pf->afont_address = AFont[hzk_id(pf)].pFont;
2041
        pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
2042
 
2043
        AFont[hzk_id(pf)].use_count++;
2044
 
2045
        return TRUE;
2046
}
2047
 
2048
/* This function unload system font from memory.*/
2049
static void UnloadFont( PMWHZKFONT pf )
2050
{
2051
        CFont[hzk_id(pf)].use_count--;
2052
        AFont[hzk_id(pf)].use_count--;
2053
 
2054
        if (!CFont[hzk_id(pf)].use_count)
2055
        {
2056
                free(pf->CFont.pFont);
2057
                free(pf->AFont.pFont);
2058
 
2059
                CFont[hzk_id(pf)].pFont = NULL;
2060
                AFont[hzk_id(pf)].pFont = NULL;
2061
        }
2062
}
2063
 
2064
static int
2065
hzk_init(PSD psd)
2066
{
2067
        /* FIXME: *.KU file should be opened and
2068
         * read in here...*/
2069
        return 1;
2070
}
2071
 
2072
static PMWHZKFONT
2073
hzk_createfont(const char *name, MWCOORD height, int attr)
2074
{
2075
        PMWHZKFONT      pf;
2076
 
2077
        if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
2078
                return FALSE;
2079
 
2080
        /*printf("hzk_createfont(%s,%d)\n",name,height);*/
2081
 
2082
        use_big5=name[2]-'K';
2083
 
2084
        /* allocate font structure*/
2085
        pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
2086
        if (!pf)
2087
                return NULL;
2088
        pf->fontprocs = &hzk_procs;
2089
 
2090
        pf->fontsize=height;
2091
#if 0
2092
        GdSetFontSize((PMWFONT)pf, height);
2093
#endif
2094
        GdSetFontRotation((PMWFONT)pf, 0);
2095
        GdSetFontAttr((PMWFONT)pf, attr, 0);
2096
 
2097
        if(height==12)
2098
        {
2099
                afont_width = 6;
2100
                cfont_width = 12;
2101
                font_height = 12;
2102
 
2103
                pf->afont_width = 6;
2104
                pf->cfont_width = 12;
2105
                pf->font_height = 12;
2106
        }
2107
        else
2108
        {
2109
                afont_width = 8;
2110
                cfont_width = 16;
2111
                font_height = 16;
2112
 
2113
                pf->afont_width = 8;
2114
                pf->cfont_width = 16;
2115
                pf->font_height = 16;
2116
        }
2117
 
2118
        /* Load the font library to the system memory.*/
2119
        if(!LoadFont(pf))
2120
                return FALSE;
2121
 
2122
        return pf;
2123
}
2124
 
2125
int IsBig5(int i)
2126
{
2127
        if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
2128
            (i>=0xa440 && i<=0xc67e) || /* a440-c67e        */
2129
            (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
2130
            (i>=0xc940 && i<=0xf9fe))   /* c940-f9fe        */
2131
                return 1;
2132
        else
2133
                return 0;
2134
}
2135
 
2136
/*
2137
 * following several function is used in hzk_drawtext
2138
 */
2139
 
2140
static int getnextchar(char* s, unsigned char* cc)
2141
{
2142
        if( s[0] == '\0') return 0;
2143
 
2144
        cc[0] = (unsigned char)(*s);
2145
        cc[1] = (unsigned char)(*(s + 1));
2146
 
2147
        if (use_big5)
2148
        {
2149
                if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
2150
                        return 1;
2151
        }
2152
        else
2153
        {
2154
                if( ((unsigned char)cc[0] > 0xa0) &&
2155
                    ((unsigned char)cc[1] > 0xa0) )
2156
                        return 1;
2157
        }
2158
 
2159
        cc[1] = '\0';
2160
 
2161
        return 1;
2162
}
2163
 
2164
static void
2165
expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
2166
{
2167
        int i=0;
2168
        int c1, c2, seq;
2169
        int x,y;
2170
        unsigned char *font;
2171
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2172
 
2173
        int pixelsize;
2174
        pixelsize=sizeof(MWPIXELVAL);
2175
 
2176
        c1 = c[0];
2177
        c2 = c[1];
2178
        if (use_big5)
2179
        {
2180
                seq=0;
2181
                /* ladd=loby-(if(loby<127)?64:98)*/
2182
                c2-=(c2<127?64:98);
2183
 
2184
                /* hadd=(hiby-164)*157*/
2185
                if (c1>=0xa4)   /* standard font*/
2186
                {
2187
                        seq=(((c1-164)*157)+c2);
2188
                        if (seq>=5809) seq-=408;
2189
                }
2190
 
2191
                /* hadd=(hiby-161)*157*/
2192
                if (c1<=0xa3)   /* special font*/
2193
                        seq=(((c1-161)*157)+c2)+13094;
2194
        }
2195
        else
2196
                seq=((c1 - 161)*94 + c2 - 161);
2197
 
2198
        font = pf->cfont_address + ((seq) *
2199
                  (pf->font_height * ((pf->cfont_width + 7) / 8)));
2200
 
2201
        for (y = 0; y < pf->font_height; y++)
2202
                for (x = 0; x < pf->cfont_width; x++)
2203
                {
2204
                        if (x % 8 == 0)
2205
                                b = *font++;
2206
 
2207
                        if (b & (128 >> (x % 8)))   /* pixel */
2208
                                bitmap[i++]=fg;
2209
                        else
2210
                                bitmap[i++]=bg;
2211
                }
2212
}
2213
 
2214
static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
2215
{
2216
        int i=0;
2217
        int x,y;
2218
        unsigned char *font;
2219
        int pixelsize;
2220
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2221
 
2222
        pixelsize=sizeof(MWPIXELVAL);
2223
 
2224
        font = pf->afont_address + c * (pf->font_height *
2225
                ((pf->afont_width + 7) / 8));
2226
 
2227
        for (y = 0; y < pf->font_height; y++)
2228
                for (x = 0; x < pf->afont_width; x++)
2229
                {
2230
                        if (x % 8 == 0)
2231
                                b = *font++;
2232
                        if (b & (128 >> (x % 8)))       /* pixel */
2233
                                bitmap[i++]=fg;
2234
                        else
2235
                                bitmap[i++]=bg;
2236
                }
2237
}
2238
 
2239
/*
2240
 * Draw ASCII text string using HZK type font
2241
 */
2242
static void
2243
hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
2244
        const void *text, int cc, int flags)
2245
{
2246
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2247
 
2248
        unsigned char c[2];
2249
        MWPIXELVAL *bitmap;
2250
        unsigned char s1[3];
2251
        char *s,*sbegin;
2252
 
2253
        s=(char *)text;
2254
 
2255
        if(cc==1)
2256
        {
2257
                s1[0]=*((unsigned char*)text);
2258
                s1[1]=0x0;
2259
                s1[2]=0x0;
2260
                s=s1;
2261
        }
2262
 
2263
        sbegin=s;
2264
        bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
2265
                        sizeof(MWPIXELVAL));
2266
 
2267
        while( getnextchar(s, c) )
2268
        {
2269
                if( c[1] != '\0')
2270
                {
2271
                        expandcchar(pf, gr_background,gr_foreground,
2272
                            c, bitmap);
2273
                        /* Now draw the bitmap ... */
2274
 
2275
                        if (flags&MWTF_TOP)
2276
                                GdArea(psd,ax, ay, pf->cfont_width,
2277
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2278
                        else
2279
                                GdArea(psd,ax, ay-pf->font_height+2,
2280
                                        pf->cfont_width, pf->font_height,
2281
                                        bitmap, MWPF_PIXELVAL);
2282
 
2283
                        s += 2;
2284
                        ax += pf->cfont_width;
2285
                }
2286
                else
2287
                {
2288
                        expandchar(pf, gr_background,gr_foreground,
2289
                           c[0], bitmap);
2290
                        /* Now draw the bitmap ... */
2291
 
2292
                        if (flags&MWTF_TOP)
2293
                                GdArea(psd,ax, ay, pf->afont_width,
2294
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2295
                        else
2296
                                GdArea(psd,ax, ay-pf->font_height+2,
2297
                                        pf->afont_width, pf->font_height,
2298
                                        bitmap, MWPF_PIXELVAL);
2299
 
2300
                        s += 1;
2301
                        ax += pf->afont_width;
2302
                }
2303
 
2304
                if(s>=sbegin+cc)break;
2305
        }
2306
 
2307
        FREEA(bitmap);
2308
}
2309
 
2310
/*
2311
 * Return information about a specified font.
2312
 */
2313
static MWBOOL
2314
hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
2315
{
2316
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2317
 
2318
        int i;
2319
 
2320
        pfontinfo->height = pf->font_height;
2321
        pfontinfo->maxwidth = pf->cfont_width;
2322
        pfontinfo->baseline = pf->font_height-2;
2323
        pfontinfo->firstchar = 0;
2324
        pfontinfo->lastchar = 0;
2325
        pfontinfo->fixed = TRUE;
2326
 
2327
        for(i=0; i<=256; i++)
2328
                pfontinfo->widths[i] = pf->afont_width;
2329
 
2330
        return TRUE;
2331
}
2332
 
2333
static void
2334
hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
2335
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
2336
{
2337
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2338
 
2339
        unsigned char c[2];
2340
        char *s,*sbegin;
2341
        unsigned char s1[3];
2342
 
2343
        int ax=0;
2344
        s=(char *)text;
2345
        if(cc==0)
2346
        {
2347
                *pwidth = 0;
2348
                *pheight = pf->font_height;
2349
                *pbase = pf->font_height-2;
2350
 
2351
        }
2352
        if(cc==1)
2353
        {
2354
                s1[0]=*((unsigned char*)text);
2355
                s1[1]=0x0;
2356
                s1[2]=0x0;
2357
                s=s1;
2358
        }
2359
        sbegin=s;
2360
        while( getnextchar(s, c) )
2361
        {
2362
                if( c[1] != '\0')
2363
                {
2364
                        s += 2;
2365
                        ax += pf->cfont_width;
2366
                }
2367
                else
2368
                {
2369
                        s += 1;
2370
                        ax += pf->afont_width;
2371
                }
2372
                if(s>=sbegin+cc) {
2373
                        /*fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
2374
                        break;
2375
                }
2376
 
2377
        }
2378
        /*fprintf(stderr,"ax=%d,\n",ax);*/
2379
 
2380
        *pwidth = ax;
2381
        *pheight = pf->font_height;
2382
        *pbase = pf->font_height-2;
2383
}
2384
 
2385
static void
2386
hzk_destroyfont(PMWFONT pfont)
2387
{
2388
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2389
        UnloadFont(pf);
2390
        free(pf);
2391
}
2392
 
2393
static void
2394
hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
2395
{
2396
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2397
        /* jmt: hzk_setfontsize not supported*/
2398
        /* & pf->fontsize can't be changed*/
2399
        /* because of hzk_id() :p*/
2400
        pf->fontsize=pf->font_height;
2401
}
2402
#endif /* HAVE_HZK_SUPPORT*/
2403
 
2404
/* FIXME: this routine should work for all font renderers...*/
2405
int
2406
GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
2407
        int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
2408
        MWCOORD *pbase, int flags)
2409
{
2410
#ifdef HAVE_FREETYPE_SUPPORT
2411
        unsigned short  buf[256];
2412
        unsigned short* text;
2413
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2414
        int             defencoding = pf->fontprocs->encoding;
2415
        int             x = 0;
2416
        int             i;
2417
        TT_UShort       curchar;
2418
        TT_Glyph_Metrics metrics;
2419
        TT_Face_Properties      properties;
2420
        TT_Instance_Metrics imetrics;
2421
 
2422
        if ((cc<0)||(!str))
2423
        {
2424
                *pwidth = *pheight = *pbase = 0;
2425
                return 0;
2426
        }
2427
        /* convert encoding if required*/
2428
        if((flags & MWTF_PACKMASK) != defencoding)
2429
        {
2430
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
2431
                flags &= ~MWTF_PACKMASK;
2432
                flags |= defencoding;
2433
                text=buf;
2434
        } else text =(unsigned short*)str;
2435
        if(cc <= 0)
2436
        {
2437
                *pwidth = *pheight = *pbase = 0;
2438
                return 0;
2439
        }
2440
 
2441
        TT_Get_Face_Properties (pf->face, &properties);
2442
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
2443
 
2444
        pf->last_glyph_code = -1;               /* reset kerning*/
2445
        pf->last_pen_pos = -32767;
2446
        if (lpnFit)
2447
             *lpnFit=-1;
2448
        for (i = 0; i < cc; i++)
2449
        {
2450
                curchar = TT_Char_Index (pf->char_map,text[i]);
2451
 
2452
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
2453
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
2454
                {
2455
                     fprintf(stderr, "Unable to load glyph with index=%d\n",curchar);
2456
                        return 0;
2457
                }
2458
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
2459
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
2460
                {
2461
                        x += compute_kernval(pf, curchar) / 64;
2462
                }
2463
                x += metrics.advance / 64;
2464
                if((lpnFit)&&(alpDx))
2465
                {
2466
                        if (x<=nMaxExtent)
2467
                             alpDx[i]=x;
2468
                        else
2469
                             if (*lpnFit==-1)
2470
                                        (*lpnFit)=i;
2471
                }
2472
                /* Kerning point syndrome avoidance */
2473
                if (pf->last_pen_pos > x)
2474
                        x = pf->last_pen_pos;
2475
                pf->last_pen_pos = x;
2476
                pf->last_glyph_code = curchar;
2477
        }
2478
        if ((lpnFit)&&(*lpnFit==-1))
2479
                *lpnFit=cc;
2480
        *pwidth = x;
2481
        *pheight = (((properties.horizontal->Ascender *
2482
                        imetrics.y_scale)/ 0x10000) >> 6) -
2483
                            (((properties.horizontal->Descender *
2484
                            imetrics.y_scale)/ 0x10000) >> 6);
2485
        /* FIXME: is it what's required ??*/
2486
        if (pbase)
2487
                *pbase = (((-properties.horizontal->Descender) *
2488
                            imetrics.y_scale)/ 0x10000) >> 6;
2489
        return 1;
2490
#else /* HAVE_FREETYPE_SUPPORT*/
2491
        *pwidth = *pheight = *pbase = 0;
2492
        return 0;
2493
#endif
2494
}
2495
 
2496
#ifdef HAVE_FREETYPE_SUPPORT
2497
#include <dirent.h>
2498
/*
2499
 * This function is taken almost verbatim from ftdump.c from
2500
 * the freetype library (version 1.3.1)
2501
 */
2502
static char *
2503
tt_lookup_name(TT_Face face)
2504
{
2505
        TT_Face_Properties prop;
2506
        unsigned short i, n;
2507
        unsigned short platform, encoding, language, id;
2508
        char *string;
2509
        char *name_buffer;
2510
        unsigned short string_len;
2511
        int j, found;
2512
        int index = 4; /* I dont know why as yet.. */
2513
        int name_len;
2514
 
2515
 
2516
        TT_Get_Face_Properties(face, &prop);
2517
        n = prop.num_Names;
2518
 
2519
        for ( i = 0; i < n; i++ ) {
2520
                TT_Get_Name_ID( face, i, &platform, &encoding, &language, &id );
2521
                TT_Get_Name_String( face, i, &string, &string_len );
2522
 
2523
                if (id == index ) {
2524
                        /* The following code was inspired from Mark Leisher's */
2525
                        /* ttf2bdf package                                     */
2526
                        found = 0;
2527
 
2528
                        /* Try to find a Microsoft English name */
2529
                        if ( platform == 3 )
2530
                                for ( j = 1; j >= 0; j-- )
2531
                                        if ( encoding == j )  /* Microsoft ? */
2532
                                                if ( (language & 0x3FF) == 0x009 ) {
2533
                                                        /* English language */
2534
                                                        found = 1;
2535
                                                        break;
2536
                                                }
2537
 
2538
                        if ( !found && platform == 0 && language == 0 )
2539
                                found = 1;
2540
 
2541
                        /* Found a Unicode Name. */
2542
                        if ( found ) {
2543
                                if ( string_len > 512 )
2544
                                        string_len = 512;
2545
 
2546
                                name_len = 0;
2547
                                name_buffer = (char*)malloc((string_len / 2) + 1);
2548
 
2549
                                for ( i = 1; i < string_len; i += 2 )
2550
                                        name_buffer[name_len++] = string[i];
2551
 
2552
                                name_buffer[name_len] = '\0';
2553
 
2554
                                return name_buffer;
2555
                        }
2556
                }
2557
        }
2558
 
2559
        /* Not found */
2560
        return NULL;
2561
}
2562
 
2563
static char *
2564
get_tt_name(char *p)
2565
{
2566
        TT_Face face;
2567
        char *ret;
2568
 
2569
        /*printf("Trying to open: %s!\n",p);*/
2570
 
2571
        if (TT_Open_Face(engine, p, &face) != TT_Err_Ok) {
2572
                fprintf(stderr, "Error opening font: %s\n", p);
2573
                return NULL;
2574
        }
2575
 
2576
        ret = tt_lookup_name(face);
2577
 
2578
        TT_Close_Face(face);
2579
 
2580
        return ret;
2581
}
2582
 
2583
void
2584
GdFreeFontList(MWFONTLIST ***fonts, int n)
2585
{
2586
        int i;
2587
        MWFONTLIST *g, **list = *fonts;
2588
 
2589
        for (i = 0; i < n; i++) {
2590
                g = list[i];
2591
                if(g) {
2592
                        if(g->mwname)
2593
                                free(g->mwname);
2594
                        if(g->ttname)
2595
                                free(g->ttname);
2596
                        free(g);
2597
                }
2598
        }
2599
        free(list);
2600
        *fonts = 0;
2601
}
2602
 
2603
void
2604
GdGetFontList(MWFONTLIST ***fonts, int *numfonts)
2605
{
2606
        DIR *dir;
2607
        struct dirent *dent;
2608
        char *p, *ftmp;
2609
        int pl, idx = 0;
2610
        MWFONTLIST **list;
2611
 
2612
 
2613
        if (TT_Err_Ok != TT_Init_FreeType(&engine)) {
2614
                fprintf(stderr, "Unable to initialize freetype\n");
2615
                *numfonts = -1;
2616
                return ;
2617
        }
2618
 
2619
        dir = opendir(FREETYPE_FONT_DIR);
2620
 
2621
        if (dir <= 0) {
2622
                fprintf(stderr, "Error opening font directory\n");
2623
                *numfonts = -1;
2624
                return ;
2625
        }
2626
 
2627
        /* get the number of strings we need to allocate */
2628
        while ((dent = readdir(dir)) != NULL) {
2629
                p = strrchr(dent->d_name, '.');
2630
                if (strcasecmp(p, ".ttf") == 0)
2631
                        idx++;
2632
        }
2633
 
2634
        *numfonts = idx;
2635
        rewinddir(dir);
2636
 
2637
        /* allocate strings */
2638
        list = (MWFONTLIST**)malloc(idx * sizeof(MWFONTLIST*));
2639
        for (pl = 0; pl < idx; pl++)
2640
                list[pl] = (MWFONTLIST*)malloc(sizeof(MWFONTLIST));
2641
 
2642
        *fonts = list;
2643
 
2644
        idx = 0;
2645
 
2646
        while ((dent = readdir(dir)) != NULL) {
2647
                /* check extension */
2648
                p = strrchr(dent->d_name, '.');
2649
 
2650
                if (strcasecmp(p, ".ttf") == 0) {
2651
 
2652
                        /* get full path */
2653
                        p = 0;
2654
                        pl = strlen(FREETYPE_FONT_DIR) + strlen(dent->d_name) *
2655
                                                sizeof(char) + 2;
2656
                        p = (char*)malloc(pl);
2657
                        p = (char*)memset(p, '\0', pl);
2658
                        p = (char*)strcat(p, FREETYPE_FONT_DIR);
2659
                        p = (char*)strcat(p, "/");
2660
                        p = (char*)strcat(p, dent->d_name);
2661
 
2662
 
2663
                        if((ftmp = get_tt_name(p)) != NULL) {
2664
                                list[idx]->ttname = ftmp;
2665
                                list[idx]->mwname = malloc(strlen(dent->d_name) + 1);
2666
                                list[idx]->mwname = strcpy(list[idx]->mwname, dent->d_name);
2667
 
2668
                                idx++;
2669
                        }
2670
 
2671
                        free(p);
2672
                }
2673
        }
2674
 
2675
        closedir(dir);
2676
}
2677
#else /* !HAVE_FREETYPE_SUPPORT*/
2678
 
2679
void
2680
GdFreeFontList(MWFONTLIST ***fonts, int n)
2681
{
2682
}
2683
 
2684
void
2685
GdGetFontList(MWFONTLIST ***fonts, int *numfonts)
2686
{
2687
        *numfonts = -1;
2688
}
2689
#endif /* !HAVE_FREETYPE_SUPPORT*/

powered by: WebSVN 2.1.0

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