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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [engine/] [devfont.caching.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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