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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
3
 * T1lib Adobe type1 routines contributed by Vidar Hokstad
4
 * Freetype TrueType routines contributed by Martin Jolicoeur
5
 * Han Zi Ku routines contributed by Tanghao and Jauming
6
 *
7
 * Device-independent font and text drawing routines
8
 *
9
 * These routines do the necessary range checking, clipping, and cursor
10
 * overwriting checks, and then call the lower level device dependent
11
 * routines to actually do the drawing.  The lower level routines are
12
 * only called when it is known that all the pixels to be drawn are
13
 * within the device area and are visible.
14
 */
15
/*#define NDEBUG*/
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <assert.h>
20
#include <string.h>
21
 
22
#include "device.h"
23
#if (UNIX | DOS_DJGPP)
24
#define strcmpi strcasecmp
25
#endif
26
 
27
#if HAVE_T1LIB_SUPPORT
28
#include <t1lib.h>
29
#define T1LIB_USE_AA_HIGH
30
 
31
typedef struct {
32
        PMWFONTPROCS    fontprocs;      /* common hdr*/
33
        MWCOORD         fontsize;
34
        int             fontrotation;
35
        int             fontattr;
36
 
37
        int             fontid;         /* t1lib stuff*/
38
} MWT1LIBFONT, *PMWT1LIBFONT;
39
 
40
static int  t1lib_init(PSD psd);
41
static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
42
static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
43
                const void *text, int cc, int flags);
44
static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
45
static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
46
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
47
static void t1lib_destroyfont(PMWFONT pfont);
48
 
49
/* handling routines for MWT1LIBFONT*/
50
static MWFONTPROCS t1lib_procs = {
51
        MWTF_ASCII,                     /* routines expect ascii*/
52
        t1lib_getfontinfo,
53
        t1lib_gettextsize,
54
        NULL,                           /* gettextbits*/
55
        t1lib_destroyfont,
56
        t1lib_drawtext,
57
        NULL,                           /* setfontsize*/
58
        NULL,                           /* setfontrotation*/
59
        NULL,                           /* setfontattr*/
60
};
61
#endif
62
 
63
#ifdef T1LIB_USE_AA_HIGH
64
typedef unsigned long OUTPIXELVAL;
65
#else
66
typedef MWPIXELVAL OUTPIXELVAL;
67
#endif
68
 
69
#if HAVE_FREETYPE_SUPPORT
70
#include <freetype/freetype.h>
71
#include <freetype/ftxkern.h>
72
#include <freetype/ftnameid.h>
73
#include <freetype/ftxcmap.h>
74
#include <freetype/ftxwidth.h>
75
#include <math.h>
76
 
77
/************/
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_TRUECOLOR233:
1084
                    d = BITS(dst, 0, 0x07);
1085
                    r = (unsigned char)(((BITS(src, 0, 0x07) - d)*a)>>8) + d;
1086
                    d = BITS(dst, 3, 0x07);
1087
                    g = (unsigned char)(((BITS(src, 3, 0x07) - d)*a)>>8) + d;
1088
                    d = BITS(dst, 6, 0x03);
1089
                    b = (unsigned char)(((BITS(src, 6, 0x03) - d)*a)>>8) + d;
1090
                    *out++ = (r << 0) | (g << 3) | (b << 6);
1091
                    break;
1092
 
1093
                case MWPF_PALETTE:
1094
                    /* reverse lookup palette entry for blend ;-)*/
1095
                    palsrc = GETPALENTRY(gr_palette, src);
1096
                    paldst = GETPALENTRY(gr_palette, dst);
1097
                    d = REDVALUE(paldst);
1098
                    r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
1099
                    d = GREENVALUE(paldst);
1100
                    g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
1101
                    d = BLUEVALUE(paldst);
1102
                    b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
1103
                    *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
1104
                                MWRGB(r, g, b));
1105
                    break;
1106
                }
1107
        }
1108
}
1109
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
1110
 
1111
#if HAVE_T1LIB_SUPPORT
1112
/* contributed by Vidar Hokstad*/
1113
 
1114
static int
1115
t1lib_init(PSD psd)
1116
{
1117
        static int inited = 0;
1118
 
1119
        if (inited)
1120
                return 1;
1121
 
1122
        T1_SetBitmapPad(8);
1123
        if (!T1_InitLib(0))
1124
                return 0;
1125
#ifdef T1LIB_USE_AA_HIGH         
1126
        T1_AASetLevel(T1_AA_HIGH);
1127
#else
1128
        T1_AASetLevel(T1_AA_LOW);
1129
#endif   
1130
#if 0
1131
        /* kluge: this is required if 16bpp drawarea driver is used*/
1132
        if(psd->bpp == 16)
1133
                T1_AASetBitsPerPixel(16);
1134
        else
1135
#endif
1136
                T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
1137
 
1138
        inited = 1;
1139
        return 1;
1140
}
1141
 
1142
static PMWT1LIBFONT
1143
t1lib_createfont(const char *name, MWCOORD height, int attr)
1144
{
1145
        PMWT1LIBFONT    pf;
1146
        int             id;
1147
        char *          p;
1148
        char            buf[256];
1149
 
1150
        /* match name against t1 font id's from t1 font database*/
1151
        for(id=0; id<T1_Get_no_fonts(); ++id) {
1152
                strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
1153
 
1154
                /* remove extension*/
1155
                for(p=buf; *p; ++p) {
1156
                        if(*p == '.') {
1157
                                *p = 0;
1158
                                break;
1159
                        }
1160
                }
1161
 
1162
                if(!strcmpi(name, buf)) {
1163
                        /* allocate font structure*/
1164
                        pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
1165
                        if (!pf)
1166
                                return NULL;
1167
                        pf->fontprocs = &t1lib_procs;
1168
                        GdSetFontSize((PMWFONT)pf, height);
1169
                        GdSetFontRotation((PMWFONT)pf, 0);
1170
                        GdSetFontAttr((PMWFONT)pf, attr, 0);
1171
                        pf->fontid = id;
1172
                        return pf;
1173
                }
1174
        }
1175
        return NULL;
1176
}
1177
 
1178
/*
1179
 * Draw ascii text string using T1LIB type font
1180
 */
1181
static void
1182
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
1183
        const void *text, int cc, int flags)
1184
{
1185
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
1186
        const unsigned char *str = text;
1187
        MWCOORD         width;                  /* width of text area */
1188
        MWCOORD         height;                 /* height of text area */
1189
        MWCOORD         underliney;
1190
        GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
1191
#ifdef T1LIB_USE_AA_HIGH   
1192
        OUTPIXELVAL     gvals[17];
1193
 
1194
        /* Blending array for antialiasing. The steeper the values increase
1195
         * near the end, the sharper the characters look, but also more jagged
1196
         */
1197
        static unsigned char blend[17] = {
1198
           0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
1199
           0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
1200
        };
1201
#else   
1202
        OUTPIXELVAL     gvals[5];
1203
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1204
#endif   
1205
 
1206
        /* Check if we should throw out some fonts */
1207
 
1208
        if (pf->fontattr&MWTF_ANTIALIAS) {
1209
#ifdef T1LIB_USE_AA_HIGH      
1210
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
1211
           T1_AAHSetGrayValues(gvals);
1212
#else      
1213
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
1214
           T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
1215
#endif
1216
           g = T1_AASetString(pf->fontid,(char *)str,cc,0,
1217
                (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1218
                pf->fontsize * 1.0, 0);
1219
 
1220
           if (g && g->bits) {
1221
              /*MWPIXELVAL save = gr_background;*/
1222
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1223
              height = g->metrics.ascent - g->metrics.descent;
1224
 
1225
              if(flags & MWTF_BASELINE)
1226
                y -= g->metrics.ascent;
1227
              else if(flags & MWTF_BOTTOM)
1228
                y -= (height - 1);
1229
              underliney = y + g->metrics.ascent;
1230
 
1231
              /* FIXME: Looks damn ugly if usebg is false.
1232
               * Will be handled when using alphablending in GdArea...
1233
               */
1234
              /* clipping handled in GdArea*/
1235
              /*FIXME kluge for transparency*/
1236
              /*gr_background = gr_foreground + 1;*/
1237
              /*gr_usebg = 0;*/
1238
              GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
1239
              /*gr_background = save;*/
1240
 
1241
              if (pf->fontattr & MWTF_UNDERLINE)
1242
                   GdLine(psd, x, underliney, x+width, underliney, FALSE);
1243
 
1244
           }
1245
        } else {
1246
           /* Do non-aa drawing */
1247
           g = T1_SetString(pf->fontid,(char *)str,cc,0,
1248
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1249
                        pf->fontsize * 1.0, 0);
1250
 
1251
           if (g && g->bits) {
1252
              unsigned char * b;
1253
              int xoff;
1254
              int maxy;
1255
              int xmod;
1256
 
1257
              /* I'm sure this sorry excuse for a bitmap rendering routine can
1258
               * be optimized quite a bit ;)
1259
               */
1260
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1261
              height = g->metrics.ascent - g->metrics.descent;
1262
 
1263
              if(flags & MWTF_BASELINE)
1264
                y -= g->metrics.ascent;
1265
              else if(flags & MWTF_BOTTOM)
1266
                y -= (height - 1);
1267
              underliney = y + g->metrics.ascent;
1268
 
1269
              b = g->bits;
1270
              maxy = y + height;
1271
 
1272
/*            if ((x + width) > psd->xvirtres) {
1273
                 xmod = (x + width - psd->xvirtres + 7) >> 3;
1274
                 width = width + x + width - psd->xvirtres;
1275
              } else xmod = 0;
1276
*/
1277
              xmod = 0;
1278
              while (y < maxy) {
1279
                 unsigned char data;
1280
                 xoff = 0;
1281
                 while (xoff < width ) {
1282
                    if (!(xoff % 8)) {
1283
                       data = *b;
1284
                       b++;
1285
                    }
1286
 
1287
                    if (GdClipPoint(psd, x+xoff,y)) {
1288
                       if (gr_usebg) {
1289
                          psd->DrawPixel(psd,x+xoff,y,
1290
                              data & (1 << (xoff % 8)) ?
1291
                                    gr_foreground : gr_background);
1292
                       } else if (data & (1 << (xoff % 8))) {
1293
                          psd->DrawPixel(psd,x+xoff,y, gr_foreground);
1294
                       }
1295
                    }
1296
                    xoff++;
1297
                 }
1298
                 b += xmod;
1299
                 y++;
1300
              }
1301
              if (pf->fontattr & MWTF_UNDERLINE)
1302
                   GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
1303
           }
1304
        }
1305
 
1306
   if (g && g->bits) {
1307
           /* Save some memory */
1308
           free(g->bits);
1309
           g->bits = 0; /* Make sure T1lib doesnt try to free it again */
1310
   }
1311
 
1312
   GdFixCursor(psd);
1313
}
1314
 
1315
static MWBOOL
1316
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1317
{
1318
        int     i;
1319
        MWCOORD width, height, baseline;
1320
 
1321
        /* FIXME, guess all sizes*/
1322
        GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
1323
        pfontinfo->height = height;
1324
        pfontinfo->maxwidth = width;
1325
        pfontinfo->baseline = 0;
1326
        pfontinfo->firstchar = 32;
1327
        pfontinfo->lastchar = 255;
1328
        pfontinfo->fixed = TRUE;
1329
        for(i=0; i<256; ++i)
1330
                pfontinfo->widths[i] = width;
1331
        return TRUE;
1332
}
1333
 
1334
/* Get the width and height of passed text string in the current font*/
1335
static void
1336
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
1337
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1338
{
1339
        PMWT1LIBFONT            pf = (PMWT1LIBFONT)pfont;
1340
        const unsigned char *   str = text;
1341
        GLYPH *                 g;
1342
 
1343
        g = T1_SetString(pf->fontid, (char *)str, cc, 0,
1344
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
1345
        *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1346
        *pheight = g->metrics.ascent - g->metrics.descent;
1347
        if(g && g->bits) {
1348
                free(g->bits);
1349
                g->bits = 0;
1350
        }
1351
#if 0
1352
        BBox                    b;
1353
 
1354
        /* FIXME. Something is *VERY* wrong here */
1355
        b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
1356
 
1357
        DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
1358
        DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
1359
        *pwidth = (b.urx - b.llx);
1360
        *pheight = (b.lly - b.ury);
1361
#endif
1362
}
1363
 
1364
static void
1365
t1lib_destroyfont(PMWFONT pfont)
1366
{
1367
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
1368
 
1369
        T1_DeleteAllSizes(pf->fontid);
1370
        free(pf);
1371
}
1372
 
1373
#endif /* HAVE_T1LIB_SUPPORT*/
1374
 
1375
#if HAVE_FREETYPE_SUPPORT
1376
static OUTPIXELVAL gray_palette[5];
1377
 
1378
static int
1379
freetype_init(PSD psd)
1380
{
1381
        static int inited = 0;
1382
 
1383
        if (inited)
1384
                return 1;
1385
 
1386
        /* Init freetype library */
1387
        if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
1388
                return 0;
1389
        }
1390
 
1391
        /* Init kerning extension */
1392
        if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
1393
                return 0;
1394
 
1395
        inited = 1;
1396
        return 1;
1397
}
1398
 
1399
static PMWFREETYPEFONT
1400
freetype_createfont(const char *name, MWCOORD height, int attr)
1401
{
1402
        PMWFREETYPEFONT         pf;
1403
        unsigned short          i, n;
1404
        unsigned short          platform, encoding;
1405
        TT_Face_Properties      properties;
1406
        char *                  p;
1407
        char                    fontname[128];
1408
 
1409
        /* check for pathname prefix*/
1410
        if (strchr(name, '/') != NULL)
1411
                strcpy(fontname, name);
1412
        else {
1413
                strcpy(fontname, FREETYPE_FONT_DIR);
1414
                strcat(fontname, "/");
1415
                strcat(fontname, name);
1416
        }
1417
 
1418
        /* check for extension*/
1419
        if ((p = strrchr(fontname, '.')) == NULL ||
1420
            strcmp(p, ".ttf") != 0) {
1421
                strcat(fontname, ".ttf");
1422
        }
1423
 
1424
        /* allocate font structure*/
1425
        pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
1426
        if (!pf)
1427
                return NULL;
1428
        pf->fontprocs = &freetype_procs;
1429
 
1430
        /* Load face */
1431
        if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
1432
                goto out;
1433
 
1434
        /* Load first kerning table */
1435
        pf->can_kern = TRUE;
1436
        if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
1437
                pf->can_kern = FALSE;
1438
        else {
1439
                if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
1440
                    != TT_Err_Ok)
1441
                        pf->can_kern = FALSE;
1442
                else {
1443
                        /* Support only version 0 kerning table ... */
1444
                        if ((pf->directory.version != 0) ||
1445
                                (pf->directory.nTables <= 0) ||
1446
                                (pf->directory.tables->loaded != 1) ||
1447
                                (pf->directory.tables->version != 0) ||
1448
                                (pf->directory.tables->t.kern0.nPairs <= 0))
1449
                                        pf->can_kern = FALSE;
1450
                }
1451
        }
1452
 
1453
        /* get face properties and allocate preload arrays */
1454
        TT_Get_Face_Properties (pf->face, &properties);
1455
 
1456
#if 0
1457
        /*
1458
         * Use header information for ascent and descent
1459
         * to compute scaled ascent/descent for current font height.
1460
         */
1461
        h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
1462
                + properties.os2->sTypoLineGap;
1463
        ascent = properties.os2->sTypoAscender
1464
                + properties.os2->sTypoLineGap/2;
1465
        pf->ascent = (ascent * height + h/2) / h;
1466
        pf->descent = height - pf->ascent;
1467
#endif
1468
        /* Create a glyph container */
1469
        if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
1470
                goto out;
1471
 
1472
        /* create instance */
1473
        if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
1474
                goto out;
1475
 
1476
        /* Set the instance resolution */
1477
        if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
1478
                goto out;
1479
 
1480
        /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
1481
        n = properties.num_CharMaps;
1482
 
1483
        for (i = 0; i < n; i++) {
1484
                TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
1485
                if (((platform == TT_PLATFORM_MICROSOFT) &&
1486
                        (encoding == TT_MS_ID_UNICODE_CS)) ||
1487
                                ((platform == TT_PLATFORM_APPLE_UNICODE) &&
1488
                                        (encoding == TT_APPLE_ID_DEFAULT)))
1489
                {
1490
                        TT_Get_CharMap (pf->face, i, &pf->char_map);
1491
                        i = n + 1;
1492
                }
1493
        }
1494
        if (i == n) {
1495
                DPRINTF("freetype_createfont: no unicode map table\n");
1496
                goto out;
1497
        }
1498
 
1499
        GdSetFontSize((PMWFONT)pf, height);
1500
        GdSetFontRotation((PMWFONT)pf, 0);
1501
        GdSetFontAttr((PMWFONT)pf, attr, 0);
1502
 
1503
        return pf;
1504
 
1505
out:
1506
        free(pf);
1507
        return NULL;
1508
}
1509
 
1510
static int
1511
compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
1512
{
1513
        int             i = 0;
1514
        int             kernval;
1515
        int             nPairs = pf->directory.tables->t.kern0.nPairs;
1516
        TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
1517
 
1518
        if (pf->last_glyph_code != -1) {
1519
                while ((pair->left != pf->last_glyph_code)
1520
                        && (pair->right != current_glyph_code))
1521
                {
1522
                        pair++;
1523
                        i++;
1524
                        if (i == nPairs)
1525
                        break;
1526
                }
1527
 
1528
                if (i == nPairs)
1529
                        kernval = 0;
1530
                else
1531
                        /* We round the value (hence the +32) */
1532
                        kernval = (pair->value + 32) & -64;
1533
        } else
1534
                kernval = 0;
1535
 
1536
        return kernval;
1537
}
1538
 
1539
static TT_UShort
1540
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
1541
{
1542
        TT_Glyph_Metrics metrics;
1543
 
1544
        if (TT_Load_Glyph ( pf->instance, pf->glyph,
1545
                TT_Char_Index (pf->char_map,glyph_index),
1546
                TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1547
        {
1548
                /* Try to load default glyph: index 0 */
1549
                if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
1550
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1551
                    return 0;
1552
        }
1553
 
1554
        TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1555
        return((metrics.advance & 0xFFFFFFC0) >> 6);
1556
}
1557
 
1558
static MWFREETYPEFONTCACHE *
1559
find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
1560
{
1561
  MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;
1562
 
1563
  while (1)
1564
    {
1565
      if (*inode == 0)
1566
        {
1567
          *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
1568
          (*inode)->curchar = curchar;
1569
        }
1570
 
1571
      if (curchar < (*inode)->curchar)
1572
        inode = &(*inode)->l;
1573
      else if (curchar > (*inode)->curchar)
1574
        inode = &(*inode)->r;
1575
      else
1576
        return *inode;
1577
    }
1578
}
1579
 
1580
static void
1581
free_cache_glyph ( MWFREETYPEFONTCACHE * node )
1582
{
1583
  if (node->l != 0)
1584
    free_cache_glyph(node->l);
1585
 
1586
  if (node->r != 0)
1587
    free_cache_glyph(node->r);
1588
 
1589
  free(node);
1590
}
1591
 
1592
/* Render a single glyph*/
1593
static void
1594
drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
1595
        int y_offset)
1596
{
1597
        TT_F26Dot6      xmin, ymin, xmax, ymax, x, y, z;
1598
        unsigned char   *src, *srcptr;
1599
        MWPIXELVAL      *dst, *dstptr;
1600
        MWPIXELVAL      *bitmap;
1601
        int             size, width, height;
1602
        TT_Outline      outline;
1603
        TT_BBox         bbox;
1604
        TT_Raster_Map   Raster;
1605
        TT_Error        error;
1606
        /*MWPIXELVAL    save;*/
1607
        MWFREETYPEFONTCACHE * cache;
1608
 
1609
        /* we begin by grid-fitting the bounding box */
1610
        TT_Get_Glyph_Outline (pf->glyph, &outline);
1611
        TT_Get_Outline_BBox (&outline, &bbox);
1612
 
1613
        xmin = (bbox.xMin & -64) >> 6;
1614
        ymin = (bbox.yMin & -64) >> 6;
1615
        xmax = ((bbox.xMax + 63) & -64) >> 6;
1616
        ymax = ((bbox.yMax + 63) & -64) >> 6;
1617
        width = xmax - xmin;
1618
        height = ymax - ymin;
1619
        size = width * height;
1620
 
1621
        /* now re-allocate the raster bitmap */
1622
        Raster.rows = height;
1623
        Raster.width = width;
1624
 
1625
        if (pf->fontattr&MWTF_ANTIALIAS)
1626
                Raster.cols = (Raster.width + 3) & -4;  /* pad to 32-bits */
1627
        else
1628
                Raster.cols = (Raster.width + 7) & -8;  /* pad to 64-bits ??? */
1629
 
1630
        cache = find_cache_glyph(pf,curchar);
1631
        /* SDR: if cache is 0 here, something really really bad happened */
1632
 
1633
        Raster.flow = TT_Flow_Up;
1634
        Raster.size = Raster.rows * Raster.cols;
1635
        Raster.bitmap = cache->buffer;
1636
 
1637
        if (Raster.bitmap == 0)
1638
          {
1639
            Raster.bitmap = malloc (Raster.size);
1640
 
1641
            memset (Raster.bitmap, 0, Raster.size);
1642
 
1643
            /* now render the glyph in the small pixmap */
1644
 
1645
            /* IMPORTANT NOTE: the offset parameters passed to the function     */
1646
            /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
1647
            /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
1648
            /* This is why we _did_ grid-fit the bounding box, especially xmin  */
1649
            /* and ymin.                                                        */
1650
 
1651
            if (!(pf->fontattr&MWTF_ANTIALIAS))
1652
              error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
1653
                                           -xmin * 64, -ymin * 64);
1654
            else
1655
              error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
1656
                                           -xmin * 64, -ymin * 64);
1657
 
1658
            if (error) {
1659
              free (Raster.bitmap);
1660
              return;
1661
            }
1662
 
1663
            cache->buffer = Raster.bitmap;
1664
          }
1665
 
1666
#if MWFREETYPEFONT_CACHEBITMAP
1667
        if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) ||
1668
            (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) ||
1669
            (gr_usebg != cache->usebg))
1670
          {
1671
            if (cache->bitmap)
1672
              {
1673
                free(cache->bitmap);
1674
                cache->bitmap = 0;
1675
              }
1676
          }
1677
 
1678
        bitmap = cache->bitmap;
1679
#else
1680
        bitmap = 0;
1681
#endif
1682
 
1683
        if (bitmap == 0)
1684
          {
1685
            bitmap = malloc (size * sizeof (MWPIXELVAL));
1686
            memset (bitmap, 0, size * sizeof (MWPIXELVAL));
1687
 
1688
            src = (char *) Raster.bitmap;
1689
            dst = bitmap + (size - width);
1690
 
1691
            for (y = ymin; y < ymax; y++)
1692
              {
1693
                srcptr = src;
1694
                dstptr = dst;
1695
 
1696
                for (x = xmin; x < xmax; x++)
1697
                  {
1698
                    if (pf->fontattr&MWTF_ANTIALIAS)
1699
                      *dstptr++ = gray_palette[(int) *srcptr];
1700
                    else
1701
                      {
1702
                        for ( z=0;
1703
                              z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
1704
                              z++ )
1705
                            *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
1706
                        x += 7;
1707
                      }
1708
 
1709
                    srcptr++;
1710
                  }
1711
 
1712
                src += Raster.cols;
1713
                dst -= width;
1714
              }
1715
#if MWFREETYPEFONT_CACHEBITMAP
1716
            cache->fg = gr_foreground;
1717
            cache->bg = gr_background;
1718
            cache->usebg = gr_usebg;
1719
            cache->bitmap = bitmap;
1720
#endif
1721
          }
1722
 
1723
        /* Now draw the bitmap ... */
1724
        GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
1725
                bitmap, MWPF_PIXELVAL);
1726
 
1727
#if !MWFREETYPEFONT_CACHEBITMAP
1728
        free(bitmap);
1729
#endif
1730
}
1731
 
1732
/*
1733
 * Draw unicode 16 text string using FREETYPE type font
1734
 */
1735
static void
1736
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
1737
        const void *text, int cc, int flags)
1738
{
1739
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1740
        const unsigned short *  str = text;
1741
        TT_F26Dot6      x = ax, y = ay;
1742
        TT_Pos          vec_x, vec_y;
1743
        int             i;
1744
        TT_F26Dot6      startx, starty;
1745
        TT_Outline      outline;
1746
        TT_UShort       curchar;
1747
        TT_Glyph_Metrics metrics;
1748
        TT_Face_Properties properties;
1749
        TT_Instance_Metrics imetrics;
1750
        TT_F26Dot6 ascent, descent;
1751
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1752
        static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
1753
 
1754
        pf->last_glyph_code = -1;               /* reset kerning*/
1755
        pf->last_pen_pos = -32767;
1756
 
1757
        /*
1758
         * Compute instance ascent & descent values
1759
         * in fractional units (1/64th pixel)
1760
         */
1761
        TT_Get_Face_Properties (pf->face, &properties);
1762
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1763
 
1764
        ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
1765
        descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
1766
 
1767
        /*
1768
         * Offset the starting point if necessary,
1769
         * FreeType always aligns at baseline
1770
         */
1771
        if (flags&MWTF_BOTTOM) {
1772
                vec_x = 0;
1773
                vec_y = descent;
1774
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1775
                x -= vec_x / 64;
1776
                y += vec_y / 64;
1777
        } else if (flags&MWTF_TOP) {
1778
                vec_x = 0;
1779
                vec_y = ascent;
1780
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1781
                x -= vec_x / 64;
1782
                y += vec_y / 64;
1783
        }
1784
 
1785
        /* Set the "graylevels" */
1786
        if (pf->fontattr&MWTF_ANTIALIAS) {
1787
                TT_Set_Raster_Gray_Palette (engine, virtual_palette);
1788
 
1789
                alphablend(psd, gray_palette, gr_foreground, gr_background,
1790
                        blend, 5);
1791
        }
1792
 
1793
        startx = x;
1794
        starty = y;
1795
        for (i = 0; i < cc; i++) {
1796
                curchar = TT_Char_Index (pf->char_map, str[i]);
1797
 
1798
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1799
                        TTLOAD_DEFAULT) != TT_Err_Ok)
1800
                                continue;
1801
 
1802
                if (pf->fontrotation) {
1803
                        TT_Get_Glyph_Outline (pf->glyph, &outline);
1804
                        TT_Transform_Outline (&outline, &pf->matrix);
1805
                }
1806
 
1807
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1808
 
1809
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1810
                        if (pf->fontrotation) {
1811
                                vec_x = compute_kernval(pf, curchar);
1812
                                vec_y = 0;
1813
                                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1814
 
1815
                                x += vec_x / 64;
1816
                                y -= vec_y / 64;
1817
                        } else
1818
                                x += compute_kernval(pf, curchar) / 64;
1819
                }
1820
 
1821
                drawchar(pf, psd, curchar, x, y);
1822
 
1823
                if (pf->fontrotation) {
1824
                        vec_x = metrics.advance;
1825
                        vec_y = 0;
1826
                        TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
1827
 
1828
                        x += vec_x / 64;
1829
                        y -= vec_y / 64;
1830
                } else {
1831
                        x += metrics.advance / 64;
1832
 
1833
                        /* Kerning point syndrome avoidance */
1834
                        if (pf->last_pen_pos > x)
1835
                                x = pf->last_pen_pos;
1836
                        pf->last_pen_pos = x;
1837
                }
1838
 
1839
                pf->last_glyph_code = curchar;
1840
        }
1841
 
1842
        if (pf->fontattr & MWTF_UNDERLINE)
1843
                GdLine(psd, startx, starty, x, y, FALSE);
1844
}
1845
 
1846
/*
1847
 * Return information about a specified font.
1848
 */
1849
static MWBOOL
1850
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1851
{
1852
        int     i;
1853
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1854
        TT_Face_Properties      properties;
1855
        TT_Instance_Metrics imetrics;
1856
        TT_UShort last_glyph_index;
1857
 
1858
        TT_Get_Face_Properties (pf->face, &properties);
1859
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1860
 
1861
        /* Fill up the fields */
1862
        pfontinfo->height = (((properties.horizontal->Ascender * \
1863
                                imetrics.y_scale)/ 0x10000) >> 6) -
1864
                            (((properties.horizontal->Descender * \
1865
                                imetrics.y_scale)/ 0x10000) >> 6);
1866
        pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
1867
                                imetrics.x_scale)/ 0x10000) >> 6;
1868
        pfontinfo->baseline = ((properties.horizontal->Ascender * \
1869
                                imetrics.y_scale)/ 0x10000) >> 6;
1870
        pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
1871
        pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
1872
        pfontinfo->fixed = properties.postscript->isFixedPitch;
1873
 
1874
        last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
1875
 
1876
        /* Doesn't work ... don't know why ....*/
1877
#if 0
1878
        if (TT_Get_Face_Widths( pf->face, 0,
1879
                                last_glyph_index, widths, NULL ) != TT_Err_Ok) {
1880
          return TRUE;
1881
        }
1882
 
1883
        for(i=0; i<=last_glyph_index; i++)
1884
          DPRINTF("widths[%d]: %d\n", i, widths[i]);
1885
#endif
1886
 
1887
        /* Get glyphs widths */
1888
        for(i=0; i<=last_glyph_index; i++)
1889
          pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
1890
 
1891
#if 0
1892
        DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
1893
    x_resolution: %d\ny_resolution: %d\n",
1894
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
1895
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
1896
 
1897
    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
1898
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
1899
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
1900
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
1901
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
1902
    Postscript Say monospaced?: %d\n",\
1903
    properties.horizontal->Ascender,
1904
    properties.horizontal->Descender,
1905
    properties.horizontal->xMax_Extent,
1906
    (properties.header->Mac_Style & 0x2)?1:0,
1907
    (properties.header->Mac_Style & 0x1)?1:0,
1908
    properties.os2->sTypoAscender,
1909
    properties.os2->sTypoDescender,
1910
    properties.os2->usWinAscent,
1911
    properties.os2->usWinDescent,
1912
    properties.os2->usFirstCharIndex,
1913
    properties.os2->usLastCharIndex,
1914
    (properties.os2->fsSelection & 0x1)?1:0,
1915
    (properties.os2->fsSelection & 0x20)?1:0,
1916
    properties.postscript->isFixedPitch,
1917
    (properties.os2->panose[3] == 9)?1:0);
1918
#endif  
1919
 
1920
        return TRUE;
1921
}
1922
 
1923
static void
1924
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
1925
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1926
{
1927
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1928
        const unsigned short *  str = text;
1929
        TT_F26Dot6      x = 0;
1930
        int             i;
1931
        TT_UShort       curchar;
1932
        TT_Glyph_Metrics metrics;
1933
        TT_Face_Properties      properties;
1934
        TT_Instance_Metrics imetrics;
1935
 
1936
        TT_Get_Face_Properties (pf->face, &properties);
1937
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
1938
 
1939
        pf->last_glyph_code = -1;               /* reset kerning*/
1940
        pf->last_pen_pos = -32767;
1941
 
1942
        for (i = 0; i < cc; i++) {
1943
                curchar = TT_Char_Index (pf->char_map, str[i]);
1944
 
1945
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1946
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1947
                                continue;
1948
 
1949
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1950
 
1951
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1952
                                x += compute_kernval(pf, curchar) / 64;
1953
                }
1954
 
1955
                x += metrics.advance / 64;
1956
 
1957
                /* Kerning point syndrome avoidance */
1958
                if (pf->last_pen_pos > x)
1959
                        x = pf->last_pen_pos;
1960
                pf->last_pen_pos = x;
1961
 
1962
                pf->last_glyph_code = curchar;
1963
        }
1964
 
1965
        *pwidth = x;
1966
        *pheight =  (((properties.horizontal->Ascender *
1967
                        imetrics.y_scale)/ 0x10000) >> 6) -
1968
                    (((properties.horizontal->Descender *
1969
                    imetrics.y_scale)/ 0x10000) >> 6);
1970
        /* FIXME: is it what's required ?? */
1971
        *pbase = (((-properties.horizontal->Descender) *
1972
                    imetrics.y_scale)/ 0x10000) >> 6;
1973
}
1974
 
1975
static void
1976
freetype_destroyfont(PMWFONT pfont)
1977
{
1978
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1979
 
1980
        TT_Close_Face(pf->face);
1981
 
1982
        /*----------*/
1983
 
1984
        if (pf->glyph_cache != 0)
1985
          free_cache_glyph(pf->glyph_cache);
1986
 
1987
        /*----------*/
1988
 
1989
        free(pf);
1990
}
1991
 
1992
static void
1993
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
1994
{
1995
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1996
 
1997
        pf->fontsize = fontsize;
1998
 
1999
        /* We want real pixel sizes ... not points ...*/
2000
        TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
2001
                                pf->fontsize, pf->fontsize * 64 );
2002
#if 0
2003
        /* set charsize (convert to points for freetype)*/
2004
        TT_Set_Instance_CharSize (pf->instance,
2005
                ((pf->fontsize * 72 + 96/2) / 96) * 64);
2006
#endif
2007
}
2008
 
2009
static void
2010
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
2011
{
2012
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2013
        float           angle;
2014
 
2015
        pf->fontrotation = tenthdegrees;
2016
 
2017
        /* Build the rotation matrix with the given angle */
2018
        TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
2019
 
2020
        angle = pf->fontrotation * M_PI / 1800;
2021
        pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
2022
        pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
2023
        pf->matrix.xx = pf->matrix.yy;
2024
        pf->matrix.xy = -pf->matrix.yx;
2025
}
2026
 
2027
#endif /* HAVE_FREETYPE_SUPPORT*/
2028
 
2029
/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
2030
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
2031
 * On the other hand, if the UTF-8 string contains surrogate values, this
2032
 * is considered an error and returned as such.
2033
 *
2034
 * The destination array must be able to hold as many Unicode-16 characters
2035
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
2036
 * characters are ASCII characters.  No more will be needed.
2037
 *
2038
 * Copyright (c) 2000 Morten Rolland, Screen Media
2039
 */
2040
static int
2041
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
2042
{
2043
        int count = 0;
2044
        unsigned char c0, c1;
2045
        unsigned long scalar;
2046
 
2047
        while(--cc >= 0) {
2048
                c0 = *utf8++;
2049
                /*DPRINTF("Trying: %02x\n",c0);*/
2050
 
2051
                if ( c0 < 0x80 ) {
2052
                        /* Plain ASCII character, simple translation :-) */
2053
                        *unicode16++ = c0;
2054
                        count++;
2055
                        continue;
2056
                }
2057
 
2058
                if ( (c0 & 0xc0) == 0x80 )
2059
                        /* Illegal; starts with 10xxxxxx */
2060
                        return -1;
2061
 
2062
                /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
2063
                scalar = c0;
2064
                if(--cc < 0)
2065
                        return -1;
2066
                c1 = *utf8++;
2067
                /*DPRINTF("c1=%02x\n",c1);*/
2068
                if ( (c1 & 0xc0) != 0x80 )
2069
                        /* Bad byte */
2070
                        return -1;
2071
                scalar <<= 6;
2072
                scalar |= (c1 & 0x3f);
2073
 
2074
                if ( !(c0 & 0x20) ) {
2075
                        /* Two bytes UTF-8 */
2076
                        if ( scalar < 0x80 )
2077
                                return -1;      /* Overlong encoding */
2078
                        *unicode16++ = scalar & 0x7ff;
2079
                        count++;
2080
                        continue;
2081
                }
2082
 
2083
                /* c0 must be 111xxxxx if we get here => at least 3 bytes */
2084
                if(--cc < 0)
2085
                        return -1;
2086
                c1 = *utf8++;
2087
                /*DPRINTF("c1=%02x\n",c1);*/
2088
                if ( (c1 & 0xc0) != 0x80 )
2089
                        /* Bad byte */
2090
                        return -1;
2091
                scalar <<= 6;
2092
                scalar |= (c1 & 0x3f);
2093
 
2094
                if ( !(c0 & 0x10) ) {
2095
                        /*DPRINTF("####\n");*/
2096
                        /* Three bytes UTF-8 */
2097
                        if ( scalar < 0x800 )
2098
                                return -1;      /* Overlong encoding */
2099
                        if ( scalar >= 0xd800 && scalar < 0xe000 )
2100
                                return -1;      /* UTF-16 high/low halfs */
2101
                        *unicode16++ = scalar & 0xffff;
2102
                        count++;
2103
                        continue;
2104
                }
2105
 
2106
                /* c0 must be 1111xxxx if we get here => at least 4 bytes */
2107
                c1 = *utf8++;
2108
                if(--cc < 0)
2109
                        return -1;
2110
                /*DPRINTF("c1=%02x\n",c1);*/
2111
                if ( (c1 & 0xc0) != 0x80 )
2112
                        /* Bad byte */
2113
                        return -1;
2114
                scalar <<= 6;
2115
                scalar |= (c1 & 0x3f);
2116
 
2117
                if ( !(c0 & 0x08) ) {
2118
                        /* Four bytes UTF-8, needs encoding as surrogates */
2119
                        if ( scalar < 0x10000 )
2120
                                return -1;      /* Overlong encoding */
2121
                        scalar -= 0x10000;
2122
                        *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
2123
                        *unicode16++ = (scalar & 0x3ff) + 0xdc00;
2124
                        count += 2;
2125
                        continue;
2126
                }
2127
 
2128
                return -1;      /* No support for more than four byte UTF-8 */
2129
        }
2130
        return count;
2131
}
2132
 
2133
#if HAVE_HZK_SUPPORT
2134
 
2135
/* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
2136
 * a single 2-byte UC16 character is encoded into a surrogate pair.
2137
 * return -1 ,if error;
2138
 * The destination array must be able to hold as many
2139
 * as there are Unicode-16 characters.
2140
 *
2141
 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
2142
 */
2143
static int
2144
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
2145
{
2146
        FILE* fp;
2147
        char buffer[256];
2148
        unsigned char *uc16p;
2149
        int i=0,j=0, k;
2150
        unsigned char *filebuffer;
2151
        unsigned short *uc16pp,*table;
2152
        unsigned short uc16px;
2153
        int length=31504;
2154
 
2155
        if (use_big5)
2156
                length=54840;
2157
 
2158
        uc16p=(unsigned char *) uc16;
2159
        uc16pp=(unsigned short *) uc16;
2160
 
2161
        strcpy(buffer,HZK_FONT_DIR);
2162
        if (use_big5)
2163
                strcat(buffer,"/BG2UBG.KU");
2164
        else
2165
                strcat(buffer,"/UGB2GB.KU");
2166
        if(!(fp = fopen(buffer, "rb")))
2167
        {
2168
                 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
2169
                 return -1;
2170
        }
2171
 
2172
        filebuffer= (unsigned char *)malloc ( length);
2173
 
2174
        if(fread(filebuffer, sizeof(char),length, fp) < length) {
2175
                  fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
2176
                  fclose(fp);
2177
                  return -1;
2178
        }
2179
        fclose(fp);
2180
 
2181
        if (use_big5)
2182
        {
2183
                table=(unsigned short *)filebuffer;
2184
                while(1)
2185
                {
2186
                        if(j>=cc)
2187
                        {
2188
                                ascii[i]=0;
2189
                                break;
2190
                        }
2191
                        uc16px=*uc16pp;
2192
                        if((uc16px)<=0x00ff)
2193
                        {
2194
                                ascii[i]=(char)(*uc16pp);
2195
                                i++;
2196
                        }
2197
                        else
2198
                        {
2199
                                ascii[i]=0xa1; ascii[i+1]=0x40;
2200
                                for (k=0; k<13710; k++)
2201
                                {
2202
                                        if (*(table+(k*2+1))==(uc16px))
2203
                                        {
2204
                                                ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
2205
                                                ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
2206
                                                break;
2207
                                        }
2208
                                }
2209
                                i+=2;
2210
                        }
2211
                        uc16pp++; j++;
2212
                }
2213
        }
2214
        else
2215
        {
2216
        while(1)
2217
        {
2218
                if(j>=cc)
2219
                {
2220
                        ascii[i]=0;
2221
                        break;
2222
                }
2223
                if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
2224
                {
2225
                        ascii[i]=0;
2226
                        break;
2227
                }
2228
                else
2229
                {
2230
                        if(*((uc16p)+j+1)==0)
2231
                        {
2232
                                ascii[i]=*((uc16p)+j);
2233
                                i++;
2234
                                j+=2;
2235
                        }
2236
                        else
2237
                        {
2238
                        /*       to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
2239
                        {
2240
                                int p1=0,p2=length-4,p;
2241
                                unsigned int c1,c2,c,d;
2242
                                c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
2243
                                c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
2244
                                d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
2245
                                if(c1==d)
2246
                                {
2247
                                        ascii[i]=filebuffer[p1+2];
2248
                                        ascii[i+1]=filebuffer[p1+3];
2249
                                        goto findit;
2250
                                }
2251
                                if(c2==d)
2252
                                {
2253
                                        ascii[i]=filebuffer[p2+2];
2254
                                        ascii[i+1]=filebuffer[p2+3];
2255
                                        goto findit;
2256
                                }
2257
                                while(1)
2258
                                {
2259
                                        p=(((p2-p1)/2+p1)>>2)<<2;
2260
                                        c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
2261
                                        if(d==c)        /*find it*/
2262
                                        {
2263
                                                ascii[i]=filebuffer[p+2];
2264
                                                ascii[i+1]=filebuffer[p+3];
2265
                                                break;
2266
                                        }
2267
                                        else if(p2<=p1+4) /*can't find.*/
2268
                                        {
2269
                                                ascii[i]='.';/*((uc16p)+j);*/
2270
                                                ascii[i+1]='.';/*((uc16p)+j+1);*/
2271
                                                break;
2272
                                        }
2273
                                        else if(d<c)
2274
                                        {
2275
                                                p2=p;
2276
                                                c2=c;
2277
                                        }
2278
                                        else
2279
                                        {
2280
                                                p1=p;
2281
                                                c1=c;
2282
                                        }
2283
                                }
2284
                        }
2285
                        findit:
2286
                        i+=2;
2287
                        j+=2;
2288
                        }
2289
                }
2290
        }
2291
        }
2292
        free(filebuffer);
2293
 
2294
        return i;
2295
}
2296
 
2297
/************************** functions definition ******************************/
2298
 
2299
static int hzk_id( PMWHZKFONT pf )
2300
{
2301
        switch(pf->font_height)
2302
        {
2303
        case 12:
2304
                return 0;
2305
        case 16: default:
2306
                return 1;
2307
        }
2308
}
2309
 
2310
/* This function get Chinese font info from etc file.*/
2311
static MWBOOL GetCFontInfo( PMWHZKFONT pf )
2312
{
2313
        int charset;
2314
 
2315
        if (use_big5)
2316
                charset=(13094+408);
2317
        else
2318
                charset=8178;
2319
 
2320
        CFont[hzk_id(pf)].width = pf->cfont_width;
2321
        pf->CFont.width = pf->cfont_width;
2322
 
2323
        CFont[hzk_id(pf)].height = pf->font_height;
2324
        pf->CFont.height = pf->font_height;
2325
 
2326
        CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
2327
                pf->CFont.height * charset;
2328
        pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
2329
 
2330
        if(pf->CFont.size < charset * 8)
2331
                return FALSE;
2332
 
2333
        strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
2334
        strcpy(pf->CFont.file,HZK_FONT_DIR);
2335
 
2336
        if(pf->font_height==16)
2337
        {
2338
                strcat(CFont[hzk_id(pf)].file,"/hzk16");
2339
                strcat(pf->CFont.file,"/hzk16");
2340
        }
2341
        else
2342
        {
2343
                strcat(CFont[hzk_id(pf)].file,"/hzk12");
2344
                strcat(pf->CFont.file,"/hzk12");
2345
        }
2346
 
2347
        if (use_big5)
2348
        {
2349
                CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
2350
                pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
2351
        }
2352
 
2353
        return TRUE;
2354
}
2355
 
2356
/* This function get ASCII font info from etc file.*/
2357
static MWBOOL GetAFontInfo( PMWHZKFONT pf )
2358
{
2359
        AFont[hzk_id(pf)].width = pf->afont_width;
2360
        pf->AFont.width = pf->afont_width;
2361
 
2362
        AFont[hzk_id(pf)].height = pf->font_height;
2363
        pf->AFont.height = pf->font_height;
2364
 
2365
        AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
2366
                pf->AFont.height * 255;
2367
        pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
2368
 
2369
        if(pf->AFont.size < 255 * 8)
2370
                return FALSE;
2371
 
2372
        strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
2373
        strcpy(pf->AFont.file,HZK_FONT_DIR);
2374
 
2375
        if(pf->font_height==16)
2376
        {
2377
                strcat(AFont[hzk_id(pf)].file,"/asc16");
2378
                strcat(pf->AFont.file,"/asc16");
2379
        }
2380
        else
2381
        {
2382
                strcat(AFont[hzk_id(pf)].file,"/asc12");
2383
                strcat(pf->AFont.file,"/asc12");
2384
        }
2385
        return TRUE;
2386
}
2387
 
2388
/* This function load system font into memory.*/
2389
static MWBOOL LoadFont( PMWHZKFONT pf )
2390
{
2391
        FILE* fp;
2392
 
2393
        if(!GetCFontInfo(pf))
2394
        {
2395
                fprintf (stderr, "Get Chinese HZK font info failure!\n");
2396
                return FALSE;
2397
        }
2398
        if(CFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2399
        {
2400
 
2401
 
2402
                /* Allocate system memory for Chinese font.*/
2403
                if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
2404
                {
2405
                        fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
2406
                        return FALSE;
2407
                }
2408
 
2409
                /* Open font file and read information to the system memory.*/
2410
                fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
2411
                if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
2412
                {
2413
                        fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
2414
                        return FALSE;
2415
                }
2416
                if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
2417
                {
2418
                        fprintf (stderr, "Error in reading Chinese HZK font file!\n");
2419
                        fclose(fp);
2420
                        return FALSE;
2421
                }
2422
 
2423
                fclose(fp);
2424
 
2425
                CFont[hzk_id(pf)].use_count=0;
2426
 
2427
                fprintf (stderr, "done.\n" );
2428
 
2429
        }
2430
        cfont_address = CFont[hzk_id(pf)].pFont;
2431
        pf->cfont_address = CFont[hzk_id(pf)].pFont;
2432
        pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
2433
 
2434
        CFont[hzk_id(pf)].use_count++;
2435
 
2436
        if(!GetAFontInfo(pf))
2437
        {
2438
               fprintf (stderr, "Get ASCII HZK font info failure!\n");
2439
               return FALSE;
2440
        }
2441
        if(AFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2442
        {
2443
 
2444
 
2445
                /* Allocate system memory for ASCII font.*/
2446
                if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
2447
                {
2448
                        fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
2449
                        free(CFont[hzk_id(pf)].pFont);
2450
                        CFont[hzk_id(pf)].pFont = NULL;
2451
                        return FALSE;
2452
                }
2453
 
2454
                /* Load ASCII font information to the near memory.*/
2455
                fprintf (stderr, "Loading ASCII HZK font..." );
2456
                if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
2457
                {
2458
                        fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
2459
                        return FALSE;
2460
                }
2461
                if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
2462
                {
2463
                        fprintf (stderr, "Error in reading ASCII HZK font file!\n");
2464
                        fclose(fp);
2465
                        return FALSE;
2466
                }
2467
 
2468
                fclose(fp);
2469
 
2470
                AFont[hzk_id(pf)].use_count=0;
2471
 
2472
                fprintf (stderr, "done.\n" );
2473
 
2474
        }
2475
        afont_address = AFont[hzk_id(pf)].pFont;
2476
        pf->afont_address = AFont[hzk_id(pf)].pFont;
2477
        pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
2478
 
2479
        AFont[hzk_id(pf)].use_count++;
2480
 
2481
        return TRUE;
2482
}
2483
 
2484
/* This function unload system font from memory.*/
2485
static void UnloadFont( PMWHZKFONT pf )
2486
{
2487
        CFont[hzk_id(pf)].use_count--;
2488
        AFont[hzk_id(pf)].use_count--;
2489
 
2490
        if (!CFont[hzk_id(pf)].use_count)
2491
        {
2492
                free(pf->CFont.pFont);
2493
                free(pf->AFont.pFont);
2494
 
2495
                CFont[hzk_id(pf)].pFont = NULL;
2496
                AFont[hzk_id(pf)].pFont = NULL;
2497
        }
2498
}
2499
 
2500
static int
2501
hzk_init(PSD psd)
2502
{
2503
        /* FIXME: *.KU file should be opened and
2504
         * read in here...*/
2505
        return 1;
2506
}
2507
 
2508
static PMWHZKFONT
2509
hzk_createfont(const char *name, MWCOORD height, int attr)
2510
{
2511
        PMWHZKFONT      pf;
2512
 
2513
        if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
2514
                return FALSE;
2515
 
2516
printf("hzk_createfont(%s,%d)\n",name,height);
2517
 
2518
        use_big5=name[2]-'K';
2519
 
2520
        /* allocate font structure*/
2521
        pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
2522
        if (!pf)
2523
                return NULL;
2524
        pf->fontprocs = &hzk_procs;
2525
 
2526
        pf->fontsize=height;
2527
        /*GdSetFontSize((PMWFONT)pf, height);*/
2528
        GdSetFontRotation((PMWFONT)pf, 0);
2529
        GdSetFontAttr((PMWFONT)pf, attr, 0);
2530
 
2531
        if(height==12)
2532
        {
2533
                afont_width = 6;
2534
                cfont_width = 12;
2535
                font_height = 12;
2536
 
2537
                pf->afont_width = 6;
2538
                pf->cfont_width = 12;
2539
                pf->font_height = 12;
2540
        }
2541
        else
2542
        {
2543
                afont_width = 8;
2544
                cfont_width = 16;
2545
                font_height = 16;
2546
 
2547
                pf->afont_width = 8;
2548
                pf->cfont_width = 16;
2549
                pf->font_height = 16;
2550
        }
2551
 
2552
        /* Load the font library to the system memory.*/
2553
        if(!LoadFont(pf))
2554
                return FALSE;
2555
 
2556
        return pf;
2557
}
2558
 
2559
int IsBig5(int i)
2560
{
2561
        if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
2562
            (i>=0xa440 && i<=0xc67e) || /* a440-c67e        */
2563
            (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
2564
            (i>=0xc940 && i<=0xf9fe))   /* c940-f9fe        */
2565
                return 1;
2566
        else
2567
                return 0;
2568
}
2569
 
2570
/*
2571
 * following several function is used in hzk_drawtext
2572
 */
2573
 
2574
static int getnextchar(char* s, unsigned char* cc)
2575
{
2576
        if( s[0] == '\0') return 0;
2577
 
2578
        cc[0] = (unsigned char)(*s);
2579
        cc[1] = (unsigned char)(*(s + 1));
2580
 
2581
        if (use_big5)
2582
        {
2583
                if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
2584
                        return 1;
2585
        }
2586
        else
2587
        {
2588
                if( ((unsigned char)cc[0] > 0xa0) &&
2589
                    ((unsigned char)cc[1] > 0xa0) )
2590
                        return 1;
2591
        }
2592
 
2593
        cc[1] = '\0';
2594
 
2595
        return 1;
2596
}
2597
 
2598
static void
2599
expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
2600
{
2601
        int i=0;
2602
        int c1, c2, seq;
2603
        int x,y;
2604
        unsigned char *font;
2605
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2606
 
2607
        int pixelsize;
2608
        pixelsize=sizeof(MWPIXELVAL);
2609
 
2610
        c1 = c[0];
2611
        c2 = c[1];
2612
        if (use_big5)
2613
        {
2614
                seq=0;
2615
                /*ladd=loby-(if(loby<127)?64:98)*/
2616
                c2-=(c2<127?64:98);
2617
 
2618
                /*hadd=(hiby-164)*157*/
2619
                if (c1>=0xa4)/*standard font*/
2620
                {
2621
                        seq=(((c1-164)*157)+c2);
2622
                        if (seq>=5809) seq-=408;
2623
                }
2624
 
2625
                /*hadd=(hiby-161)*157*/
2626
                if (c1<=0xa3)/*special font*/
2627
                        seq=(((c1-161)*157)+c2)+13094;
2628
        }
2629
        else
2630
                seq=((c1 - 161)*94 + c2 - 161);
2631
 
2632
        font = pf->cfont_address + ((seq) *
2633
                  (pf->font_height * ((pf->cfont_width + 7) / 8)));
2634
 
2635
        for (y = 0; y < pf->font_height; y++)
2636
                for (x = 0; x < pf->cfont_width; x++)
2637
                {
2638
                        if (x % 8 == 0)
2639
                                b = *font++;
2640
 
2641
                        if (b & (128 >> (x % 8)))   /* pixel */
2642
                                bitmap[i++]=fg;
2643
                        else
2644
                                bitmap[i++]=bg;
2645
                }
2646
}
2647
 
2648
static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
2649
{
2650
        int i=0;
2651
        int x,y;
2652
        unsigned char *font;
2653
        int pixelsize;
2654
        int b = 0;               /* keep gcc happy with b = 0 - MW */
2655
 
2656
        pixelsize=sizeof(MWPIXELVAL);
2657
 
2658
        font = pf->afont_address + c * (pf->font_height *
2659
                ((pf->afont_width + 7) / 8));
2660
 
2661
        for (y = 0; y < pf->font_height; y++)
2662
                for (x = 0; x < pf->afont_width; x++)
2663
                {
2664
                        if (x % 8 == 0)
2665
                                b = *font++;
2666
                        if (b & (128 >> (x % 8)))       /* pixel */
2667
                                bitmap[i++]=fg;
2668
                        else
2669
                                bitmap[i++]=bg;
2670
                }
2671
}
2672
 
2673
/*
2674
 * Draw ASCII text string using HZK type font
2675
 */
2676
static void
2677
hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
2678
        const void *text, int cc, int flags)
2679
{
2680
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2681
 
2682
        unsigned char c[2];
2683
        MWPIXELVAL *bitmap;
2684
        unsigned char s1[3];
2685
        char *s,*sbegin;
2686
 
2687
        s=(char *)text;
2688
 
2689
        if(cc==1)
2690
        {
2691
                s1[0]=*((unsigned char*)text);
2692
                s1[1]=0x0;
2693
                s1[2]=0x0;
2694
                s=s1;
2695
        }
2696
 
2697
        sbegin=s;
2698
        bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
2699
                        sizeof(MWPIXELVAL));
2700
 
2701
        while( getnextchar(s, c) )
2702
        {
2703
                if( c[1] != '\0')
2704
                {
2705
                        expandcchar(pf, gr_background,gr_foreground,
2706
                            c, bitmap);
2707
                        /* Now draw the bitmap ... */
2708
 
2709
                        if (flags&MWTF_TOP)
2710
                                GdArea(psd,ax, ay, pf->cfont_width,
2711
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2712
                        else
2713
                                GdArea(psd,ax, ay-pf->font_height+2,
2714
                                        pf->cfont_width, pf->font_height,
2715
                                        bitmap, MWPF_PIXELVAL);
2716
 
2717
                        s += 2;
2718
                        ax += pf->cfont_width;
2719
                }
2720
                else
2721
                {
2722
                        expandchar(pf, gr_background,gr_foreground,
2723
                           c[0], bitmap);
2724
                        /* Now draw the bitmap ... */
2725
 
2726
                        if (flags&MWTF_TOP)
2727
                                GdArea(psd,ax, ay, pf->afont_width,
2728
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
2729
                        else
2730
                                GdArea(psd,ax, ay-pf->font_height+2,
2731
                                        pf->afont_width, pf->font_height,
2732
                                        bitmap, MWPF_PIXELVAL);
2733
 
2734
                        s += 1;
2735
                        ax += pf->afont_width;
2736
                }
2737
 
2738
                if(s>=sbegin+cc)break;
2739
        }
2740
 
2741
        FREEA(bitmap);
2742
}
2743
 
2744
/*
2745
 * Return information about a specified font.
2746
 */
2747
static MWBOOL
2748
hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
2749
{
2750
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2751
 
2752
        int i;
2753
 
2754
        pfontinfo->height = pf->font_height;
2755
        pfontinfo->maxwidth = pf->cfont_width;
2756
        pfontinfo->baseline = pf->font_height-2;
2757
        pfontinfo->firstchar = 0;
2758
        pfontinfo->lastchar = 0;
2759
        pfontinfo->fixed = TRUE;
2760
 
2761
        for(i=0; i<=256; i++)
2762
                pfontinfo->widths[i] = pf->afont_width;
2763
 
2764
        return TRUE;
2765
}
2766
 
2767
static void
2768
hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
2769
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
2770
{
2771
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2772
 
2773
        unsigned char c[2];
2774
        char *s,*sbegin;
2775
        unsigned char s1[3];
2776
 
2777
        int ax=0;
2778
 
2779
 
2780
 
2781
        s=(char *)text;
2782
        if(cc==0)
2783
        {
2784
                *pwidth = 0;
2785
                *pheight = pf->font_height;
2786
                *pbase = pf->font_height-2;
2787
 
2788
        }
2789
        if(cc==1)
2790
        {
2791
                s1[0]=*((unsigned char*)text);
2792
                s1[1]=0x0;
2793
                s1[2]=0x0;
2794
                s=s1;
2795
        }
2796
        sbegin=s;
2797
        while( getnextchar(s, c) )
2798
        {
2799
                if( c[1] != '\0')
2800
                {
2801
                        s += 2;
2802
                        ax += pf->cfont_width;
2803
                }
2804
                else
2805
                {
2806
                        s += 1;
2807
                        ax += pf->afont_width;
2808
                }
2809
                if(s>=sbegin+cc)break;
2810
                /*      fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
2811
 
2812
        }
2813
/*      fprintf(stderr,"ax=%d,\n",ax);*/
2814
 
2815
        *pwidth = ax;
2816
        *pheight = pf->font_height;
2817
        *pbase = pf->font_height-2;
2818
}
2819
 
2820
static void
2821
hzk_destroyfont(PMWFONT pfont)
2822
{
2823
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2824
 
2825
        UnloadFont(pf);
2826
        free(pf);
2827
}
2828
 
2829
static void
2830
hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
2831
{
2832
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
2833
 
2834
        /*jmt: hzk_setfontsize not supported*/
2835
        /*jmt: & pf->fontsize can't be changed*/
2836
        /*jmt: because of hzk_id() :p*/
2837
        pf->fontsize=pf->font_height;
2838
}
2839
#endif /* HAVE_HZK_SUPPORT*/
2840
 
2841
/* FIXME: this routine should work for all font renderers...*/
2842
int
2843
GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
2844
        int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
2845
        MWCOORD *pbase, int flags)
2846
{
2847
#ifdef HAVE_FREETYPE_SUPPORT
2848
        unsigned short  buf[256];
2849
        unsigned short* text;
2850
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2851
        int             defencoding = pf->fontprocs->encoding;
2852
        int             x = 0;
2853
        int             i;
2854
        TT_UShort       curchar;
2855
        TT_Glyph_Metrics metrics;
2856
        TT_Face_Properties      properties;
2857
        TT_Instance_Metrics imetrics;
2858
 
2859
        if ((cc<0)||(!str))
2860
        {
2861
                *pwidth = *pheight = *pbase = 0;
2862
                return 0;
2863
        }
2864
        /* convert encoding if required*/
2865
        if((flags & MWTF_PACKMASK) != defencoding)
2866
        {
2867
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
2868
                flags &= ~MWTF_PACKMASK;
2869
                flags |= defencoding;
2870
                text=buf;
2871
        } else text =(unsigned short*)str;
2872
        if(cc <= 0)
2873
        {
2874
                *pwidth = *pheight = *pbase = 0;
2875
                return 0;
2876
        }
2877
 
2878
        TT_Get_Face_Properties (pf->face, &properties);
2879
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
2880
 
2881
        pf->last_glyph_code = -1;               /* reset kerning*/
2882
        pf->last_pen_pos = -32767;
2883
        if (lpnFit)
2884
             *lpnFit=-1;
2885
        for (i = 0; i < cc; i++)
2886
        {
2887
                curchar = TT_Char_Index (pf->char_map,text[i]);
2888
 
2889
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
2890
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
2891
                {
2892
                     printf("Unable to load glyph with index=%d\n",curchar);
2893
                        return 0;
2894
                }
2895
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
2896
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
2897
                {
2898
                        x += compute_kernval(pf, curchar) / 64;
2899
                }
2900
                x += metrics.advance / 64;
2901
                if((lpnFit)&&(alpDx))
2902
                {
2903
                        if (x<=nMaxExtent)
2904
                             alpDx[i]=x;
2905
                        else
2906
                             if (*lpnFit==-1)
2907
                                        (*lpnFit)=i;
2908
                }
2909
                /* Kerning point syndrome avoidance */
2910
                if (pf->last_pen_pos > x)
2911
                        x = pf->last_pen_pos;
2912
                pf->last_pen_pos = x;
2913
                pf->last_glyph_code = curchar;
2914
        }
2915
        if ((lpnFit)&&(*lpnFit==-1))
2916
                *lpnFit=cc;
2917
        *pwidth = x;
2918
        *pheight = (((properties.horizontal->Ascender *
2919
                        imetrics.y_scale)/ 0x10000) >> 6) -
2920
                            (((properties.horizontal->Descender *
2921
                            imetrics.y_scale)/ 0x10000) >> 6);
2922
        /*FIXME: is it what's required ??*/
2923
        if (pbase)
2924
                *pbase = (((-properties.horizontal->Descender) *
2925
                            imetrics.y_scale)/ 0x10000) >> 6;
2926
        return 1;
2927
#else /* HAVE_FREETYPE_SUPPORT*/
2928
        *pwidth = *pheight = *pbase = 0;
2929
        return 0;
2930
#endif
2931
}

powered by: WebSVN 2.1.0

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