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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [engine/] [devfont.caching.c] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
/*
/*
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
 * T1lib Adobe type1 routines contributed by Vidar Hokstad
 * T1lib Adobe type1 routines contributed by Vidar Hokstad
 * Freetype TrueType routines contributed by Martin Jolicoeur
 * Freetype TrueType routines contributed by Martin Jolicoeur
 * Han Zi Ku routines contributed by Tanghao and Jauming
 * Han Zi Ku routines contributed by Tanghao and Jauming
 *
 *
 * Device-independent font and text drawing routines
 * Device-independent font and text drawing routines
 *
 *
 * These routines do the necessary range checking, clipping, and cursor
 * These routines do the necessary range checking, clipping, and cursor
 * overwriting checks, and then call the lower level device dependent
 * overwriting checks, and then call the lower level device dependent
 * routines to actually do the drawing.  The lower level routines are
 * routines to actually do the drawing.  The lower level routines are
 * only called when it is known that all the pixels to be drawn are
 * only called when it is known that all the pixels to be drawn are
 * within the device area and are visible.
 * within the device area and are visible.
 */
 */
/*#define NDEBUG*/
/*#define NDEBUG*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <assert.h>
#include <assert.h>
#include <string.h>
#include <string.h>
 
 
#include "device.h"
#include "device.h"
#if (UNIX | DOS_DJGPP)
#if (UNIX | DOS_DJGPP)
#define strcmpi strcasecmp
#define strcmpi strcasecmp
#endif
#endif
 
 
#if HAVE_T1LIB_SUPPORT
#if HAVE_T1LIB_SUPPORT
#include <t1lib.h>
#include <t1lib.h>
#define T1LIB_USE_AA_HIGH
#define T1LIB_USE_AA_HIGH
 
 
typedef struct {
typedef struct {
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        MWCOORD         fontsize;
        MWCOORD         fontsize;
        int             fontrotation;
        int             fontrotation;
        int             fontattr;
        int             fontattr;
 
 
        int             fontid;         /* t1lib stuff*/
        int             fontid;         /* t1lib stuff*/
} MWT1LIBFONT, *PMWT1LIBFONT;
} MWT1LIBFONT, *PMWT1LIBFONT;
 
 
static int  t1lib_init(PSD psd);
static int  t1lib_init(PSD psd);
static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
                const void *text, int cc, int flags);
                const void *text, int cc, int flags);
static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
static void t1lib_destroyfont(PMWFONT pfont);
static void t1lib_destroyfont(PMWFONT pfont);
 
 
/* handling routines for MWT1LIBFONT*/
/* handling routines for MWT1LIBFONT*/
static MWFONTPROCS t1lib_procs = {
static MWFONTPROCS t1lib_procs = {
        MWTF_ASCII,                     /* routines expect ascii*/
        MWTF_ASCII,                     /* routines expect ascii*/
        t1lib_getfontinfo,
        t1lib_getfontinfo,
        t1lib_gettextsize,
        t1lib_gettextsize,
        NULL,                           /* gettextbits*/
        NULL,                           /* gettextbits*/
        t1lib_destroyfont,
        t1lib_destroyfont,
        t1lib_drawtext,
        t1lib_drawtext,
        NULL,                           /* setfontsize*/
        NULL,                           /* setfontsize*/
        NULL,                           /* setfontrotation*/
        NULL,                           /* setfontrotation*/
        NULL,                           /* setfontattr*/
        NULL,                           /* setfontattr*/
};
};
#endif
#endif
 
 
#ifdef T1LIB_USE_AA_HIGH
#ifdef T1LIB_USE_AA_HIGH
typedef unsigned long OUTPIXELVAL;
typedef unsigned long OUTPIXELVAL;
#else
#else
typedef MWPIXELVAL OUTPIXELVAL;
typedef MWPIXELVAL OUTPIXELVAL;
#endif
#endif
 
 
#if HAVE_FREETYPE_SUPPORT
#if HAVE_FREETYPE_SUPPORT
#include <freetype/freetype.h>
#include <freetype/freetype.h>
#include <freetype/ftxkern.h>
#include <freetype/ftxkern.h>
#include <freetype/ftnameid.h>
#include <freetype/ftnameid.h>
#include <freetype/ftxcmap.h>
#include <freetype/ftxcmap.h>
#include <freetype/ftxwidth.h>
#include <freetype/ftxwidth.h>
#include <math.h>
#include <math.h>
 
 
/************/
/************/
 
 
typedef struct xTT_Glyph_Cache_ {
typedef struct xTT_Glyph_Cache_ {
 
 
  TT_Error  error;
  TT_Error  error;
  TT_Glyph  glyph;
  TT_Glyph  glyph;
  TT_UShort index;
  TT_UShort index;
  TT_UShort flags;
  TT_UShort flags;
 
 
  struct xTT_Glyph_Cache_ * l;
  struct xTT_Glyph_Cache_ * l;
  struct xTT_Glyph_Cache_ * r;
  struct xTT_Glyph_Cache_ * r;
 
 
} xTT_Glyph_Cache;
} xTT_Glyph_Cache;
 
 
typedef struct xTT_Instance_Object_ {
typedef struct xTT_Instance_Object_ {
 
 
  TT_Face     face;
  TT_Face     face;
  TT_Instance instance;
  TT_Instance instance;
 
 
  xTT_Glyph_Cache * head;
  xTT_Glyph_Cache * head;
 
 
} xTT_Instance_Object;
} xTT_Instance_Object;
 
 
typedef struct xTT_Instance_ {
typedef struct xTT_Instance_ {
 
 
  xTT_Instance_Object * instance;
  xTT_Instance_Object * instance;
 
 
} xTT_Instance;
} xTT_Instance;
 
 
typedef struct xTT_Outline_Object_ {
typedef struct xTT_Outline_Object_ {
 
 
  TT_Outline outline;
  TT_Outline outline;
  TT_BBox    bbox;
  TT_BBox    bbox;
 
 
} xTT_Outline_Object;
} xTT_Outline_Object;
 
 
typedef struct xTT_Outline_ {
typedef struct xTT_Outline_ {
 
 
  xTT_Outline_Object * outline;
  xTT_Outline_Object * outline;
 
 
} xTT_Outline;
} xTT_Outline;
 
 
typedef struct xTT_Glyph_Object_ {
typedef struct xTT_Glyph_Object_ {
 
 
  TT_Glyph * glyph;
  TT_Glyph * glyph;
 
 
  xTT_Outline_Object outline;
  xTT_Outline_Object outline;
 
 
} xTT_Glyph_Object;
} xTT_Glyph_Object;
 
 
typedef struct xTT_Glyph_ {
typedef struct xTT_Glyph_ {
 
 
  xTT_Glyph_Object * glyph;
  xTT_Glyph_Object * glyph;
 
 
} xTT_Glyph;
} xTT_Glyph;
 
 
TT_Error
TT_Error
xTT_Glyph_Cache_Find ( xTT_Instance instance,
xTT_Glyph_Cache_Find ( xTT_Instance instance,
                       xTT_Glyph glyph,
                       xTT_Glyph glyph,
                       TT_UShort glyphIndex,
                       TT_UShort glyphIndex,
                       TT_UShort loadFlags )
                       TT_UShort loadFlags )
{
{
  xTT_Glyph_Cache  * node;
  xTT_Glyph_Cache  * node;
  xTT_Glyph_Cache ** inode = &instance.instance->head;
  xTT_Glyph_Cache ** inode = &instance.instance->head;
 
 
  int miss = 0;
  int miss = 0;
 
 
  while ( 1 )
  while ( 1 )
  {
  {
    if (*inode == 0)
    if (*inode == 0)
    {
    {
      miss = 1;
      miss = 1;
 
 
      node = *inode = calloc(1,sizeof(**inode));
      node = *inode = calloc(1,sizeof(**inode));
 
 
      if (node == 0)
      if (node == 0)
        return TT_Err_Out_Of_Memory;
        return TT_Err_Out_Of_Memory;
 
 
      node->error = TT_New_Glyph(instance.instance->face,&(node->glyph));
      node->error = TT_New_Glyph(instance.instance->face,&(node->glyph));
 
 
      if (node->error == 0)
      if (node->error == 0)
        node->error = TT_Load_Glyph(instance.instance->instance,
        node->error = TT_Load_Glyph(instance.instance->instance,
                                    node->glyph,
                                    node->glyph,
                                    (node->index = glyphIndex),
                                    (node->index = glyphIndex),
                                    (node->flags = loadFlags));
                                    (node->flags = loadFlags));
 
 
      if (node->error != 0)
      if (node->error != 0)
        TT_Done_Glyph(node->glyph);
        TT_Done_Glyph(node->glyph);
    }
    }
    else
    else
    {
    {
      node = *inode;
      node = *inode;
    }
    }
 
 
    if (glyphIndex < node->index)
    if (glyphIndex < node->index)
      inode = &node->l;
      inode = &node->l;
    else if (glyphIndex > node->index)
    else if (glyphIndex > node->index)
      inode = &node->r;
      inode = &node->r;
    else if (loadFlags < node->flags)
    else if (loadFlags < node->flags)
      inode = &node->l;
      inode = &node->l;
    else if (loadFlags > node->flags)
    else if (loadFlags > node->flags)
      inode = &node->r;
      inode = &node->r;
    else
    else
    {
    {
      static int count [] = { 0, 0 };
      static int count [] = { 0, 0 };
      ++count[miss];
      ++count[miss];
      printf("\r(%s | hit %d | miss %d)",__TIME__,count[0],count[1]);
      printf("\r(%s | hit %d | miss %d)",__TIME__,count[0],count[1]);
      glyph.glyph->glyph = &node->glyph;
      glyph.glyph->glyph = &node->glyph;
      return node->error;
      return node->error;
    }
    }
  }
  }
}
}
 
 
void
void
xTT_Glyph_Cache_Free ( xTT_Glyph_Cache ** pnode )
xTT_Glyph_Cache_Free ( xTT_Glyph_Cache ** pnode )
{
{
  xTT_Glyph_Cache * node;
  xTT_Glyph_Cache * node;
 
 
  if (pnode == 0)
  if (pnode == 0)
    return;
    return;
 
 
  node = *pnode;
  node = *pnode;
 
 
  if (node == 0)
  if (node == 0)
    return;
    return;
 
 
  if (node->l)
  if (node->l)
    xTT_Glyph_Cache_Free(&node->l);
    xTT_Glyph_Cache_Free(&node->l);
 
 
  if (node->r)
  if (node->r)
    xTT_Glyph_Cache_Free(&node->r);
    xTT_Glyph_Cache_Free(&node->r);
 
 
  TT_Done_Glyph(node->glyph);
  TT_Done_Glyph(node->glyph);
  free(node);
  free(node);
 
 
  *pnode = 0;
  *pnode = 0;
}
}
 
 
TT_Error
TT_Error
xTT_New_Instance ( TT_Face face,
xTT_New_Instance ( TT_Face face,
                   xTT_Instance * instance )
                   xTT_Instance * instance )
{
{
  instance->instance = calloc(1,sizeof(*instance->instance));
  instance->instance = calloc(1,sizeof(*instance->instance));
  if (instance->instance == 0)
  if (instance->instance == 0)
    return TT_Err_Out_Of_Memory;
    return TT_Err_Out_Of_Memory;
 
 
  instance->instance->face = face;
  instance->instance->face = face;
  instance->instance->head = 0;
  instance->instance->head = 0;
 
 
  return TT_New_Instance(face,&instance->instance->instance);
  return TT_New_Instance(face,&instance->instance->instance);
}
}
 
 
TT_Error
TT_Error
xTT_Done_Instance ( xTT_Instance instance )
xTT_Done_Instance ( xTT_Instance instance )
{
{
  TT_Error error;
  TT_Error error;
 
 
  xTT_Glyph_Cache_Free(&instance.instance->head);
  xTT_Glyph_Cache_Free(&instance.instance->head);
  error = TT_Done_Instance(instance.instance->instance);
  error = TT_Done_Instance(instance.instance->instance);
 
 
  free(instance.instance);
  free(instance.instance);
 
 
  return error;
  return error;
}
}
 
 
TT_Error
TT_Error
xTT_Get_Instance_Metrics ( xTT_Instance instance,
xTT_Get_Instance_Metrics ( xTT_Instance instance,
                           TT_Instance_Metrics * imetrics )
                           TT_Instance_Metrics * imetrics )
{
{
  return TT_Get_Instance_Metrics(instance.instance->instance,imetrics);
  return TT_Get_Instance_Metrics(instance.instance->instance,imetrics);
}
}
 
 
TT_Error
TT_Error
xTT_Set_Instance_CharSize ( xTT_Instance instance,
xTT_Set_Instance_CharSize ( xTT_Instance instance,
                            TT_F26Dot6 charsize )
                            TT_F26Dot6 charsize )
{
{
  xTT_Glyph_Cache_Free(&instance.instance->head);
  xTT_Glyph_Cache_Free(&instance.instance->head);
  return TT_Set_Instance_CharSize(instance.instance->instance,charsize);
  return TT_Set_Instance_CharSize(instance.instance->instance,charsize);
}
}
 
 
TT_Error
TT_Error
xTT_Set_Instance_PixelSizes ( xTT_Instance instance,
xTT_Set_Instance_PixelSizes ( xTT_Instance instance,
                              TT_UShort pixelWidth,
                              TT_UShort pixelWidth,
                              TT_UShort pixelHeight,
                              TT_UShort pixelHeight,
                              TT_F26Dot6 pointSize )
                              TT_F26Dot6 pointSize )
{
{
  xTT_Glyph_Cache_Free(&instance.instance->head);
  xTT_Glyph_Cache_Free(&instance.instance->head);
  return TT_Set_Instance_PixelSizes(instance.instance->instance,
  return TT_Set_Instance_PixelSizes(instance.instance->instance,
                                    pixelWidth,
                                    pixelWidth,
                                    pixelHeight,
                                    pixelHeight,
                                    pointSize);
                                    pointSize);
}
}
 
 
TT_Error
TT_Error
xTT_Set_Instance_Transform_Flags ( xTT_Instance instance,
xTT_Set_Instance_Transform_Flags ( xTT_Instance instance,
                                   TT_Bool rotated,
                                   TT_Bool rotated,
                                   TT_Bool stretched )
                                   TT_Bool stretched )
{
{
  xTT_Glyph_Cache_Free(&instance.instance->head);
  xTT_Glyph_Cache_Free(&instance.instance->head);
  return TT_Set_Instance_Resolutions(instance.instance->instance,
  return TT_Set_Instance_Resolutions(instance.instance->instance,
                                     rotated,
                                     rotated,
                                     stretched);
                                     stretched);
}
}
 
 
TT_Error
TT_Error
xTT_Set_Instance_Resolutions ( xTT_Instance instance,
xTT_Set_Instance_Resolutions ( xTT_Instance instance,
                               TT_UShort xResolution,
                               TT_UShort xResolution,
                               TT_UShort yResolution )
                               TT_UShort yResolution )
{
{
  xTT_Glyph_Cache_Free(&instance.instance->head);
  xTT_Glyph_Cache_Free(&instance.instance->head);
  return TT_Set_Instance_Resolutions(instance.instance->instance,
  return TT_Set_Instance_Resolutions(instance.instance->instance,
                                     xResolution,
                                     xResolution,
                                     yResolution);
                                     yResolution);
}
}
 
 
TT_Error
TT_Error
xTT_New_Glyph ( TT_Face face,
xTT_New_Glyph ( TT_Face face,
                xTT_Glyph * glyph )
                xTT_Glyph * glyph )
{
{
  glyph->glyph = calloc(1,sizeof(*glyph->glyph));
  glyph->glyph = calloc(1,sizeof(*glyph->glyph));
  if (glyph->glyph == 0)
  if (glyph->glyph == 0)
    return TT_Err_Out_Of_Memory;
    return TT_Err_Out_Of_Memory;
  return 0;
  return 0;
}
}
 
 
TT_Error
TT_Error
xTT_Done_Glyph ( xTT_Glyph glyph )
xTT_Done_Glyph ( xTT_Glyph glyph )
{
{
  free(glyph.glyph);
  free(glyph.glyph);
  return 0;
  return 0;
}
}
 
 
TT_Error
TT_Error
xTT_Load_Glyph ( xTT_Instance instance,
xTT_Load_Glyph ( xTT_Instance instance,
                 xTT_Glyph glyph,
                 xTT_Glyph glyph,
                 TT_UShort glyphIndex,
                 TT_UShort glyphIndex,
                 TT_UShort loadFlags )
                 TT_UShort loadFlags )
{
{
  TT_Error error;
  TT_Error error;
  error = xTT_Glyph_Cache_Find(instance,glyph,glyphIndex,loadFlags);
  error = xTT_Glyph_Cache_Find(instance,glyph,glyphIndex,loadFlags);
  TT_Get_Glyph_Outline(*glyph.glyph->glyph,
  TT_Get_Glyph_Outline(*glyph.glyph->glyph,
                       &glyph.glyph->outline.outline);
                       &glyph.glyph->outline.outline);
  TT_Get_Outline_BBox(&glyph.glyph->outline.outline,
  TT_Get_Outline_BBox(&glyph.glyph->outline.outline,
                      &glyph.glyph->outline.bbox);
                      &glyph.glyph->outline.bbox);
  return error;
  return error;
}
}
 
 
TT_Error
TT_Error
xTT_Get_Glyph_Metrics ( xTT_Glyph glyph,
xTT_Get_Glyph_Metrics ( xTT_Glyph glyph,
                        TT_Glyph_Metrics * metrics )
                        TT_Glyph_Metrics * metrics )
{
{
  return TT_Get_Glyph_Metrics(*glyph.glyph->glyph,metrics);
  return TT_Get_Glyph_Metrics(*glyph.glyph->glyph,metrics);
}
}
 
 
TT_Error
TT_Error
xTT_Get_Glyph_Outline ( xTT_Glyph glyph,
xTT_Get_Glyph_Outline ( xTT_Glyph glyph,
                        xTT_Outline * outline )
                        xTT_Outline * outline )
{
{
  outline->outline = &glyph.glyph->outline;
  outline->outline = &glyph.glyph->outline;
  return 0;
  return 0;
}
}
 
 
TT_Error
TT_Error
xTT_Get_Outline_BBox ( xTT_Outline * outline,
xTT_Get_Outline_BBox ( xTT_Outline * outline,
                       TT_BBox * bbox )
                       TT_BBox * bbox )
{
{
  *bbox = outline->outline->bbox;
  *bbox = outline->outline->bbox;
  return 0;
  return 0;
}
}
 
 
void
void
xTT_Transform_Outline ( xTT_Outline * outline,
xTT_Transform_Outline ( xTT_Outline * outline,
                        TT_Matrix * matrix )
                        TT_Matrix * matrix )
{
{
  TT_Transform_Outline(&outline->outline->outline,matrix);
  TT_Transform_Outline(&outline->outline->outline,matrix);
  TT_Get_Outline_BBox(&outline->outline->outline,
  TT_Get_Outline_BBox(&outline->outline->outline,
                      &outline->outline->bbox);
                      &outline->outline->bbox);
}
}
 
 
TT_Error
TT_Error
xTT_Get_Glyph_Bitmap ( xTT_Glyph glyph,
xTT_Get_Glyph_Bitmap ( xTT_Glyph glyph,
                       TT_Raster_Map * bitmap,
                       TT_Raster_Map * bitmap,
                       TT_F26Dot6 xOffset,
                       TT_F26Dot6 xOffset,
                       TT_F26Dot6 yOffset )
                       TT_F26Dot6 yOffset )
{
{
  return TT_Get_Glyph_Bitmap(*glyph.glyph->glyph,
  return TT_Get_Glyph_Bitmap(*glyph.glyph->glyph,
                             bitmap,
                             bitmap,
                             xOffset,
                             xOffset,
                             yOffset);
                             yOffset);
}
}
 
 
TT_Error
TT_Error
xTT_Get_Glyph_Pixmap ( xTT_Glyph glyph,
xTT_Get_Glyph_Pixmap ( xTT_Glyph glyph,
                       TT_Raster_Map * pixmap,
                       TT_Raster_Map * pixmap,
                       TT_F26Dot6 xOffset,
                       TT_F26Dot6 xOffset,
                       TT_F26Dot6 yOffset )
                       TT_F26Dot6 yOffset )
{
{
  return TT_Get_Glyph_Pixmap(*glyph.glyph->glyph,
  return TT_Get_Glyph_Pixmap(*glyph.glyph->glyph,
                             pixmap,
                             pixmap,
                             xOffset,
                             xOffset,
                             yOffset);
                             yOffset);
}
}
 
 
#ifndef xTT_ALIAS
#ifndef xTT_ALIAS
#define xTT_ALIAS 1
#define xTT_ALIAS 1
#endif
#endif
 
 
#if xTT_ALIAS
#if xTT_ALIAS
 
 
#define TT_Instance                     xTT_Instance
#define TT_Instance                     xTT_Instance
#define TT_Outline                      xTT_Outline
#define TT_Outline                      xTT_Outline
#define TT_Glyph                        xTT_Glyph
#define TT_Glyph                        xTT_Glyph
 
 
#define TT_New_Instance                 xTT_New_Instance
#define TT_New_Instance                 xTT_New_Instance
#define TT_Done_Instance                xTT_Done_Instance
#define TT_Done_Instance                xTT_Done_Instance
 
 
#define TT_Get_Instance_Metrics         xTT_Get_Instance_Metrics
#define TT_Get_Instance_Metrics         xTT_Get_Instance_Metrics
#define TT_Set_Instance_CharSize        xTT_Set_Instance_CharSize
#define TT_Set_Instance_CharSize        xTT_Set_Instance_CharSize
#define TT_Set_Instance_PixelSizes      xTT_Set_Instance_PixelSizes
#define TT_Set_Instance_PixelSizes      xTT_Set_Instance_PixelSizes
#define TT_Set_Instance_Transform_Flags xTT_Set_Instance_Transform_Flags
#define TT_Set_Instance_Transform_Flags xTT_Set_Instance_Transform_Flags
#define TT_Set_Instance_Resolutions     xTT_Set_Instance_Resolutions
#define TT_Set_Instance_Resolutions     xTT_Set_Instance_Resolutions
 
 
#define TT_New_Glyph                    xTT_New_Glyph
#define TT_New_Glyph                    xTT_New_Glyph
#define TT_Done_Glyph                   xTT_Done_Glyph
#define TT_Done_Glyph                   xTT_Done_Glyph
 
 
#define TT_Load_Glyph                   xTT_Load_Glyph
#define TT_Load_Glyph                   xTT_Load_Glyph
#define TT_Get_Glyph_Metrics            xTT_Get_Glyph_Metrics
#define TT_Get_Glyph_Metrics            xTT_Get_Glyph_Metrics
#define TT_Get_Glyph_Outline            xTT_Get_Glyph_Outline
#define TT_Get_Glyph_Outline            xTT_Get_Glyph_Outline
#define TT_Get_Glyph_Bitmap             xTT_Get_Glyph_Bitmap
#define TT_Get_Glyph_Bitmap             xTT_Get_Glyph_Bitmap
#define TT_Get_Glyph_Pixmap             xTT_Get_Glyph_Pixmap
#define TT_Get_Glyph_Pixmap             xTT_Get_Glyph_Pixmap
 
 
#define TT_Get_Outline_BBox             xTT_Get_Outline_BBox
#define TT_Get_Outline_BBox             xTT_Get_Outline_BBox
#define TT_Transform_Outline            xTT_Transform_Outline
#define TT_Transform_Outline            xTT_Transform_Outline
 
 
#endif
#endif
 
 
/************/
/************/
 
 
#ifndef FREETYPE_FONT_DIR
#ifndef FREETYPE_FONT_DIR
#define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
#define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
#endif
#endif
 
 
#if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3
#if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3
#error "You must link with freetype lib version 1.3.x +, and not freetype 2. \
#error "You must link with freetype lib version 1.3.x +, and not freetype 2. \
Download it at http://www.freetype.org or http://microwindows.org"
Download it at http://www.freetype.org or http://microwindows.org"
#endif
#endif
 
 
#ifndef MWFREETYPEFONT_CACHE
#ifndef MWFREETYPEFONT_CACHE
#define MWFREETYPEFONT_CACHE 1
#define MWFREETYPEFONT_CACHE 1
#endif
#endif
 
 
#if MWFREETYPEFONT_CACHE
#if MWFREETYPEFONT_CACHE
 
 
#ifndef MWFREETYPEFONT_CACHEBITMAP
#ifndef MWFREETYPEFONT_CACHEBITMAP
#define MWFREETYPEFONT_CACHEBITMAP 1
#define MWFREETYPEFONT_CACHEBITMAP 1
#endif
#endif
 
 
typedef struct mwfreetypefontcache {
typedef struct mwfreetypefontcache {
  unsigned curchar;
  unsigned curchar;
  void * buffer;
  void * buffer;
#if MWFREETYPEFONT_CACHEBITMAP
#if MWFREETYPEFONT_CACHEBITMAP
  MWPIXELVAL fg;
  MWPIXELVAL fg;
  MWPIXELVAL bg;
  MWPIXELVAL bg;
  MWBOOL usebg;
  MWBOOL usebg;
  void * bitmap;
  void * bitmap;
#endif
#endif
  struct mwfreetypefontcache * l;
  struct mwfreetypefontcache * l;
  struct mwfreetypefontcache * r;
  struct mwfreetypefontcache * r;
} MWFREETYPEFONTCACHE;
} MWFREETYPEFONTCACHE;
 
 
#endif
#endif
 
 
typedef struct {
typedef struct {
 
 
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        MWCOORD         fontsize;
        MWCOORD         fontsize;
        int             fontrotation;
        int             fontrotation;
        int             fontattr;
        int             fontattr;
 
 
        TT_Face         face;           /* freetype stuff*/
        TT_Face         face;           /* freetype stuff*/
        TT_Instance     instance;
        TT_Instance     instance;
        TT_CharMap      char_map;
        TT_CharMap      char_map;
        TT_Kerning      directory;
        TT_Kerning      directory;
        TT_Matrix       matrix;
        TT_Matrix       matrix;
        TT_Glyph        glyph;
        TT_Glyph        glyph;
        MWBOOL          can_kern;
        MWBOOL          can_kern;
        short           last_glyph_code;
        short           last_glyph_code;
        short           last_pen_pos;
        short           last_pen_pos;
 
 
#if MWFREETYPEFONT_CACHE
#if MWFREETYPEFONT_CACHE
        MWFREETYPEFONTCACHE * glyph_cache;
        MWFREETYPEFONTCACHE * glyph_cache;
#endif
#endif
 
 
} MWFREETYPEFONT, *PMWFREETYPEFONT;
} MWFREETYPEFONT, *PMWFREETYPEFONT;
 
 
static int  freetype_init(PSD psd);
static int  freetype_init(PSD psd);
static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
                int attr);
                int attr);
static MWBOOL freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static MWBOOL freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void freetype_gettextsize(PMWFONT pfont, const void *text,
static void freetype_gettextsize(PMWFONT pfont, const void *text,
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
static void freetype_destroyfont(PMWFONT pfont);
static void freetype_destroyfont(PMWFONT pfont);
static void freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
static void freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
                const void *text, int cc, int flags);
                const void *text, int cc, int flags);
static void freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize);
static void freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize);
static void freetype_setfontrotation(PMWFONT pfont, int tenthdegrees);
static void freetype_setfontrotation(PMWFONT pfont, int tenthdegrees);
 
 
/* handling routines for MWFREETYPEFONT*/
/* handling routines for MWFREETYPEFONT*/
static MWFONTPROCS freetype_procs = {
static MWFONTPROCS freetype_procs = {
        MWTF_UC16,                      /* routines expect unicode 16*/
        MWTF_UC16,                      /* routines expect unicode 16*/
        freetype_getfontinfo,
        freetype_getfontinfo,
        freetype_gettextsize,
        freetype_gettextsize,
        NULL,                           /* gettextbits*/
        NULL,                           /* gettextbits*/
        freetype_destroyfont,
        freetype_destroyfont,
        freetype_drawtext,
        freetype_drawtext,
        freetype_setfontsize,
        freetype_setfontsize,
        freetype_setfontrotation,
        freetype_setfontrotation,
        NULL,                           /* setfontattr*/
        NULL,                           /* setfontattr*/
};
};
 
 
static TT_Engine        engine;         /* THE ONLY freetype engine */
static TT_Engine        engine;         /* THE ONLY freetype engine */
#endif /* HAVE_FREETYPE_SUPPORT*/
#endif /* HAVE_FREETYPE_SUPPORT*/
 
 
#if HAVE_HZK_SUPPORT
#if HAVE_HZK_SUPPORT
/*
/*
 * 12x12 and 16x16 ascii and chinese fonts
 * 12x12 and 16x16 ascii and chinese fonts
 * Big5 and GB2312 encodings supported
 * Big5 and GB2312 encodings supported
 */
 */
#define MAX_PATH        256
#define MAX_PATH        256
typedef struct {
typedef struct {
        int     width;
        int     width;
        int     height;
        int     height;
        int     size;
        int     size;
        unsigned long use_count;
        unsigned long use_count;
        char *  pFont;
        char *  pFont;
        char    file[MAX_PATH + 1];
        char    file[MAX_PATH + 1];
} HZKFONT;
} HZKFONT;
 
 
static int use_big5=1;
static int use_big5=1;
static HZKFONT CFont[2];        /* font cache*/
static HZKFONT CFont[2];        /* font cache*/
static HZKFONT AFont[2];        /* font cache*/
static HZKFONT AFont[2];        /* font cache*/
 
 
/*jmt: moved inside MWHZKFONT*/
/*jmt: moved inside MWHZKFONT*/
static int afont_width = 8;
static int afont_width = 8;
static int cfont_width = 16;
static int cfont_width = 16;
static int font_height = 16;
static int font_height = 16;
static char *afont_address;
static char *afont_address;
static char *cfont_address;
static char *cfont_address;
 
 
typedef struct {
typedef struct {
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        PMWFONTPROCS    fontprocs;      /* common hdr*/
        MWCOORD         fontsize;
        MWCOORD         fontsize;
        int             fontrotation;
        int             fontrotation;
        int             fontattr;
        int             fontattr;
 
 
        HZKFONT         CFont;          /* hzkfont stuff */
        HZKFONT         CFont;          /* hzkfont stuff */
        HZKFONT         AFont;
        HZKFONT         AFont;
        int             afont_width;
        int             afont_width;
        int             cfont_width;
        int             cfont_width;
        int             font_height;
        int             font_height;
        char            *afont_address;
        char            *afont_address;
        char            *cfont_address;
        char            *cfont_address;
} MWHZKFONT, *PMWHZKFONT;
} MWHZKFONT, *PMWHZKFONT;
 
 
static int  hzk_init(PSD psd);
static int  hzk_init(PSD psd);
static PMWHZKFONT hzk_createfont(const char *name, MWCOORD height,int fontattr);
static PMWHZKFONT hzk_createfont(const char *name, MWCOORD height,int fontattr);
static MWBOOL hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static MWBOOL hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void hzk_gettextsize(PMWFONT pfont, const void *text,
static void hzk_gettextsize(PMWFONT pfont, const void *text,
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
                int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
/*static void hzk_gettextbits(PMWFONT pfont, int ch, IMAGEBITS *retmap,
/*static void hzk_gettextbits(PMWFONT pfont, int ch, IMAGEBITS *retmap,
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);*/
                MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);*/
static void hzk_destroyfont(PMWFONT pfont);
static void hzk_destroyfont(PMWFONT pfont);
static void hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
static void hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
                const void *text, int cc, int flags);
                const void *text, int cc, int flags);
static void hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize);
static void hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize);
/*static void hzk_setfontrotation(PMWFONT pfont, int tenthdegrees);*/
/*static void hzk_setfontrotation(PMWFONT pfont, int tenthdegrees);*/
 
 
/* handling routines for MWHZKFONT*/
/* handling routines for MWHZKFONT*/
static MWFONTPROCS hzk_procs = {
static MWFONTPROCS hzk_procs = {
        MWTF_ASCII,                     /* routines expect ASCII*/
        MWTF_ASCII,                     /* routines expect ASCII*/
        hzk_getfontinfo,
        hzk_getfontinfo,
        hzk_gettextsize,
        hzk_gettextsize,
        NULL,                           /* hzk_gettextbits*/
        NULL,                           /* hzk_gettextbits*/
        hzk_destroyfont,
        hzk_destroyfont,
        hzk_drawtext,
        hzk_drawtext,
        hzk_setfontsize,
        hzk_setfontsize,
        NULL,                           /* setfontrotation*/
        NULL,                           /* setfontrotation*/
        NULL,                           /* setfontattr*/
        NULL,                           /* setfontattr*/
};
};
 
 
static int
static int
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
#endif /* HAVE_HZK_SUPPORT*/
#endif /* HAVE_HZK_SUPPORT*/
 
 
static PMWFONT  gr_pfont;               /* current font*/
static PMWFONT  gr_pfont;               /* current font*/
 
 
/* temp extern decls*/
/* temp extern decls*/
extern MWPIXELVAL gr_foreground;
extern MWPIXELVAL gr_foreground;
extern MWPIXELVAL gr_background;
extern MWPIXELVAL gr_background;
extern MWBOOL gr_usebg;
extern MWBOOL gr_usebg;
 
 
static int  utf8_to_utf16(const unsigned char *utf8, int cc,
static int  utf8_to_utf16(const unsigned char *utf8, int cc,
                unsigned short *unicode16);
                unsigned short *unicode16);
 
 
#if FONTMAPPER
#if FONTMAPPER
/* entry point for font selection*/
/* entry point for font selection*/
int select_font(const PMWLOGFONT plogfont, char *physname);
int select_font(const PMWLOGFONT plogfont, char *physname);
#endif
#endif
 
 
/*
/*
 * Set the font for future calls.
 * Set the font for future calls.
 */
 */
PMWFONT
PMWFONT
GdSetFont(PMWFONT pfont)
GdSetFont(PMWFONT pfont)
{
{
        PMWFONT oldfont = gr_pfont;
        PMWFONT oldfont = gr_pfont;
        gr_pfont = pfont;
        gr_pfont = pfont;
        return oldfont;
        return oldfont;
}
}
 
 
/*
/*
 * Select a font, based on various parameters.
 * Select a font, based on various parameters.
 * If plogfont is specified, name and height parms are ignored
 * If plogfont is specified, name and height parms are ignored
 * and instead used from MWLOGFONT.
 * and instead used from MWLOGFONT.
 *
 *
 * If height is 0, return builtin font from passed name.
 * If height is 0, return builtin font from passed name.
 * Otherwise find builtin font best match based on height.
 * Otherwise find builtin font best match based on height.
 */
 */
PMWFONT
PMWFONT
GdCreateFont(PSD psd, const char *name, MWCOORD height,
GdCreateFont(PSD psd, const char *name, MWCOORD height,
        const PMWLOGFONT plogfont)
        const PMWLOGFONT plogfont)
{
{
        int             i;
        int             i;
        int             fontht;
        int             fontht;
        int             fontno;
        int             fontno;
        int             fontclass;
        int             fontclass;
        int             fontattr = 0;
        int             fontattr = 0;
        PMWFONT         pfont;
        PMWFONT         pfont;
        PMWCOREFONT     pf = psd->builtin_fonts;
        PMWCOREFONT     pf = psd->builtin_fonts;
        MWFONTINFO      fontinfo;
        MWFONTINFO      fontinfo;
        MWSCREENINFO    scrinfo;
        MWSCREENINFO    scrinfo;
        char            fontname[128];
        char            fontname[128];
 
 
        GdGetScreenInfo(psd, &scrinfo);
        GdGetScreenInfo(psd, &scrinfo);
 
 
        /* if plogfont not specified, use name and height*/
        /* if plogfont not specified, use name and height*/
        if (!plogfont) {
        if (!plogfont) {
                if (!name)
                if (!name)
                        name = MWFONT_SYSTEM_VAR;
                        name = MWFONT_SYSTEM_VAR;
                strcpy(fontname, name);
                strcpy(fontname, name);
                fontclass = MWLF_CLASS_ANY;
                fontclass = MWLF_CLASS_ANY;
        } else {
        } else {
#if FONTMAPPER
#if FONTMAPPER
                /* otherwise, use MWLOGFONT name and height*/
                /* otherwise, use MWLOGFONT name and height*/
                fontclass = select_font(plogfont, fontname);
                fontclass = select_font(plogfont, fontname);
#else
#else
                if (!name)
                if (!name)
                        name = MWFONT_SYSTEM_VAR;
                        name = MWFONT_SYSTEM_VAR;
                strcpy(fontname, name);
                strcpy(fontname, name);
                fontclass = MWLF_CLASS_ANY;
                fontclass = MWLF_CLASS_ANY;
#endif
#endif
                height = plogfont->lfHeight;
                height = plogfont->lfHeight;
                if (plogfont->lfUnderline)
                if (plogfont->lfUnderline)
                        fontattr = MWTF_UNDERLINE;
                        fontattr = MWTF_UNDERLINE;
        }
        }
        height = abs(height);
        height = abs(height);
 
 
        if (!fontclass)
        if (!fontclass)
                goto first;
                goto first;
 
 
        /* use builtin screen fonts, FONT_xxx, if height is 0 */
        /* use builtin screen fonts, FONT_xxx, if height is 0 */
        if (height == 0 || fontclass == MWLF_CLASS_ANY ||
        if (height == 0 || fontclass == MWLF_CLASS_ANY ||
            fontclass == MWLF_CLASS_BUILTIN) {
            fontclass == MWLF_CLASS_BUILTIN) {
                for(i = 0; i < scrinfo.fonts; ++i) {
                for(i = 0; i < scrinfo.fonts; ++i) {
                        if(!strcmpi(pf[i].name, fontname)) {
                        if(!strcmpi(pf[i].name, fontname)) {
                                pf[i].fontsize = pf[i].cfont->height;
                                pf[i].fontsize = pf[i].cfont->height;
                                pf[i].fontattr = fontattr;
                                pf[i].fontattr = fontattr;
                                return (PMWFONT)&pf[i];
                                return (PMWFONT)&pf[i];
                        }
                        }
                }
                }
 
 
                /* return first builtin font*/
                /* return first builtin font*/
                if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
                if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
                        goto first;
                        goto first;
        }
        }
 
 
#if HAVE_HZK_SUPPORT
#if HAVE_HZK_SUPPORT
        /* Make sure the library is initialized */
        /* Make sure the library is initialized */
        if (hzk_init(psd)) {
        if (hzk_init(psd)) {
                pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
                pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
                if(pfont)
                if(pfont)
                        return pfont;
                        return pfont;
                printf("hzk_createfont: %s not found\n", name);
                printf("hzk_createfont: %s not found\n", name);
        }
        }
#endif
#endif
 
 
#if HAVE_FREETYPE_SUPPORT
#if HAVE_FREETYPE_SUPPORT
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_FREETYPE) {
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_FREETYPE) {
                if (freetype_init(psd)) {
                if (freetype_init(psd)) {
                /* auto antialias for height > 14 for kaffe*/
                /* auto antialias for height > 14 for kaffe*/
                        if (plogfont && plogfont->lfHeight > 14 &&
                        if (plogfont && plogfont->lfHeight > 14 &&
                                plogfont->lfQuality)
                                plogfont->lfQuality)
                                        fontattr |= MWTF_ANTIALIAS;
                                        fontattr |= MWTF_ANTIALIAS;
 
 
                        pfont = (PMWFONT)freetype_createfont(fontname, height,
                        pfont = (PMWFONT)freetype_createfont(fontname, height,
                                        fontattr);
                                        fontattr);
                        if(pfont) {
                        if(pfont) {
                                /* temp kaffe kluge*/
                                /* temp kaffe kluge*/
                                pfont->fontattr |= FS_FREETYPE;
                                pfont->fontattr |= FS_FREETYPE;
                                return pfont;
                                return pfont;
                        }
                        }
                        DPRINTF("freetype_createfont: %s,%d not found\n",
                        DPRINTF("freetype_createfont: %s,%d not found\n",
                                fontname, height);
                                fontname, height);
                }
                }
        }
        }
#endif
#endif
 
 
#if HAVE_T1LIB_SUPPORT
#if HAVE_T1LIB_SUPPORT
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_T1LIB) {
        if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_T1LIB) {
                if (t1lib_init(psd)) {
                if (t1lib_init(psd)) {
                        pfont = (PMWFONT)t1lib_createfont(fontname, height,
                        pfont = (PMWFONT)t1lib_createfont(fontname, height,
                                        fontattr);
                                        fontattr);
                        if(pfont)
                        if(pfont)
                                return pfont;
                                return pfont;
                        DPRINTF("t1lib_createfont: %s,%d not found\n",
                        DPRINTF("t1lib_createfont: %s,%d not found\n",
                                fontname, height);
                                fontname, height);
                }
                }
        }
        }
#endif
#endif
 
 
        /* find builtin font closest in height*/
        /* find builtin font closest in height*/
        if(height != 0) {
        if(height != 0) {
                fontno = 0;
                fontno = 0;
                height = abs(height);
                height = abs(height);
                fontht = MAX_MWCOORD;
                fontht = MAX_MWCOORD;
                for(i = 0; i < scrinfo.fonts; ++i) {
                for(i = 0; i < scrinfo.fonts; ++i) {
                        pfont = (PMWFONT)&pf[i];
                        pfont = (PMWFONT)&pf[i];
                        GdGetFontInfo(pfont, &fontinfo);
                        GdGetFontInfo(pfont, &fontinfo);
                        if(fontht > abs(height-fontinfo.height)) {
                        if(fontht > abs(height-fontinfo.height)) {
                                fontno = i;
                                fontno = i;
                                fontht = abs(height-fontinfo.height);
                                fontht = abs(height-fontinfo.height);
                        }
                        }
                }
                }
                pf[fontno].fontsize = pf[fontno].cfont->height;
                pf[fontno].fontsize = pf[fontno].cfont->height;
                pf[fontno].fontattr = fontattr;
                pf[fontno].fontattr = fontattr;
                return (PMWFONT)&pf[fontno];
                return (PMWFONT)&pf[fontno];
        }
        }
 
 
first:
first:
        /* Return first builtin font*/
        /* Return first builtin font*/
        pf->fontsize = pf->cfont->height;
        pf->fontsize = pf->cfont->height;
        pf->fontattr = fontattr;
        pf->fontattr = fontattr;
        return (PMWFONT)&pf[0];
        return (PMWFONT)&pf[0];
}
}
 
 
/* Set the font size for the passed font*/
/* Set the font size for the passed font*/
MWCOORD
MWCOORD
GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
{
{
        MWCOORD oldfontsize = pfont->fontsize;
        MWCOORD oldfontsize = pfont->fontsize;
 
 
        pfont->fontsize = fontsize;
        pfont->fontsize = fontsize;
 
 
        if (pfont->fontprocs->SetFontSize)
        if (pfont->fontprocs->SetFontSize)
            pfont->fontprocs->SetFontSize(pfont, fontsize);
            pfont->fontprocs->SetFontSize(pfont, fontsize);
 
 
        return oldfontsize;
        return oldfontsize;
}
}
 
 
/* Set the font rotation angle in tenths of degrees for the passed font*/
/* Set the font rotation angle in tenths of degrees for the passed font*/
int
int
GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
{
{
        MWCOORD oldrotation = pfont->fontrotation;
        MWCOORD oldrotation = pfont->fontrotation;
 
 
        pfont->fontrotation = tenthdegrees;
        pfont->fontrotation = tenthdegrees;
 
 
        if (pfont->fontprocs->SetFontRotation)
        if (pfont->fontprocs->SetFontRotation)
            pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
            pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
 
 
        return oldrotation;
        return oldrotation;
}
}
 
 
/*
/*
 * Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
 * Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
 * for the passed font.
 * for the passed font.
 */
 */
int
int
GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
{
{
        MWCOORD oldattr = pfont->fontattr;
        MWCOORD oldattr = pfont->fontattr;
 
 
        pfont->fontattr &= ~clrflags;
        pfont->fontattr &= ~clrflags;
        pfont->fontattr |= setflags;
        pfont->fontattr |= setflags;
 
 
        if (pfont->fontprocs->SetFontAttr)
        if (pfont->fontprocs->SetFontAttr)
            pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
            pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
 
 
        return oldattr;
        return oldattr;
}
}
 
 
/* Unload and deallocate font*/
/* Unload and deallocate font*/
void
void
GdDestroyFont(PMWFONT pfont)
GdDestroyFont(PMWFONT pfont)
{
{
        if (pfont->fontprocs->DestroyFont)
        if (pfont->fontprocs->DestroyFont)
                pfont->fontprocs->DestroyFont(pfont);
                pfont->fontprocs->DestroyFont(pfont);
}
}
 
 
/* Return information about a specified font*/
/* Return information about a specified font*/
MWBOOL
MWBOOL
GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
{
        if(!pfont || !pfont->fontprocs->GetFontInfo)
        if(!pfont || !pfont->fontprocs->GetFontInfo)
                return FALSE;
                return FALSE;
 
 
        return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
        return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
}
}
 
 
/*
/*
 * Convert from one encoding to another
 * Convert from one encoding to another
 * Input cc and returned cc is character count, not bytes
 * Input cc and returned cc is character count, not bytes
 * Return < 0 on error or can't translate
 * Return < 0 on error or can't translate
 */
 */
int
int
GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
{
{
        const unsigned char     *istr8;
        const unsigned char     *istr8;
        const unsigned short    *istr16;
        const unsigned short    *istr16;
        const unsigned long     *istr32;
        const unsigned long     *istr32;
        unsigned char           *ostr8;
        unsigned char           *ostr8;
        unsigned short          *ostr16;
        unsigned short          *ostr16;
        unsigned long           *ostr32;
        unsigned long           *ostr32;
        unsigned int            ch;
        unsigned int            ch;
        int                     icc;
        int                     icc;
        unsigned short          buf16[512];
        unsigned short          buf16[512];
 
 
        iflags &= MWTF_PACKMASK;
        iflags &= MWTF_PACKMASK;
        oflags &= MWTF_PACKMASK;
        oflags &= MWTF_PACKMASK;
 
 
        /* allow -1 for len with ascii*/
        /* allow -1 for len with ascii*/
        if(cc == -1 && (iflags == MWTF_ASCII))
        if(cc == -1 && (iflags == MWTF_ASCII))
                cc = strlen((char *)istr);
                cc = strlen((char *)istr);
 
 
        /* first check for utf8 input encoding*/
        /* first check for utf8 input encoding*/
        if(iflags == MWTF_UTF8) {
        if(iflags == MWTF_UTF8) {
                /* we've only got uc16 now so convert to uc16...*/
                /* we've only got uc16 now so convert to uc16...*/
                cc = utf8_to_utf16((unsigned char *)istr, cc,
                cc = utf8_to_utf16((unsigned char *)istr, cc,
                        oflags==MWTF_UC16?(unsigned short*) ostr: buf16);
                        oflags==MWTF_UC16?(unsigned short*) ostr: buf16);
 
 
                if(oflags == MWTF_UC16 || cc < 0)
                if(oflags == MWTF_UC16 || cc < 0)
                        return cc;
                        return cc;
 
 
                /* will decode again to requested format (probably ascii)*/
                /* will decode again to requested format (probably ascii)*/
                iflags = MWTF_UC16;
                iflags = MWTF_UC16;
                istr = buf16;
                istr = buf16;
        }
        }
 
 
#if HAVE_HZK_SUPPORT
#if HAVE_HZK_SUPPORT
        if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
        if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
                /* only support uc16 convert to ascii now...*/
                /* only support uc16 convert to ascii now...*/
                cc = UC16_to_GB( istr, cc, ostr);
                cc = UC16_to_GB( istr, cc, ostr);
                return cc;
                return cc;
        }
        }
#endif
#endif
 
 
        icc = cc;
        icc = cc;
        istr8 = istr;
        istr8 = istr;
        istr16 = istr;
        istr16 = istr;
        istr32 = istr;
        istr32 = istr;
        ostr8 = ostr;
        ostr8 = ostr;
        ostr16 = ostr;
        ostr16 = ostr;
        ostr32 = ostr;
        ostr32 = ostr;
 
 
        /* Convert between formats.  Note that there's no error
        /* Convert between formats.  Note that there's no error
         * checking here yet.
         * checking here yet.
         */
         */
        while(--icc >= 0) {
        while(--icc >= 0) {
                switch(iflags) {
                switch(iflags) {
                default:
                default:
                        ch = *istr8++;
                        ch = *istr8++;
                        break;
                        break;
                case MWTF_UC16:
                case MWTF_UC16:
                        ch = *istr16++;
                        ch = *istr16++;
                        break;
                        break;
                case MWTF_UC32:
                case MWTF_UC32:
                        ch = *istr32++;
                        ch = *istr32++;
                }
                }
                switch(oflags) {
                switch(oflags) {
                default:
                default:
                        *ostr8++ = (unsigned char)ch;
                        *ostr8++ = (unsigned char)ch;
                        break;
                        break;
                case MWTF_UC16:
                case MWTF_UC16:
                        *ostr16++ = (unsigned short)ch;
                        *ostr16++ = (unsigned short)ch;
                        break;
                        break;
                case MWTF_UC32:
                case MWTF_UC32:
                        *ostr32++ = ch;
                        *ostr32++ = ch;
                }
                }
        }
        }
        return cc;
        return cc;
}
}
 
 
/* Get the width and height of passed text string in the passed font*/
/* Get the width and height of passed text string in the passed font*/
void
void
GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
        MWCOORD *pheight, MWCOORD *pbase, int flags)
        MWCOORD *pheight, MWCOORD *pbase, int flags)
{
{
        const void *    text;
        const void *    text;
        unsigned long   buf[256];
        unsigned long   buf[256];
        int             defencoding = pfont->fontprocs->encoding;
        int             defencoding = pfont->fontprocs->encoding;
 
 
        /* convert encoding if required*/
        /* convert encoding if required*/
        if((flags & MWTF_PACKMASK) != defencoding) {
        if((flags & MWTF_PACKMASK) != defencoding) {
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                flags &= ~MWTF_PACKMASK;
                flags &= ~MWTF_PACKMASK;
                flags |= defencoding;
                flags |= defencoding;
                text = buf;
                text = buf;
        } else text = str;
        } else text = str;
 
 
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
                cc = strlen((char *)str);
                cc = strlen((char *)str);
 
 
        if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
        if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
                *pwidth = *pheight = *pbase = 0;
                *pwidth = *pheight = *pbase = 0;
                return;
                return;
        }
        }
 
 
        /* calc height and width of string*/
        /* calc height and width of string*/
        pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
        pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
}
}
 
 
/* Draw a text string at a specifed coordinates in the foreground color
/* Draw a text string at a specifed coordinates in the foreground color
 * (and possibly the background color), applying clipping if necessary.
 * (and possibly the background color), applying clipping if necessary.
 * The background color is only drawn if the gr_usebg flag is set.
 * The background color is only drawn if the gr_usebg flag is set.
 * Use the current font.
 * Use the current font.
 */
 */
void
void
GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
{
{
        const void *    text;
        const void *    text;
        unsigned long   buf[256];
        unsigned long   buf[256];
        int             defencoding = gr_pfont->fontprocs->encoding;
        int             defencoding = gr_pfont->fontprocs->encoding;
 
 
        /* convert encoding if required*/
        /* convert encoding if required*/
        if((flags & MWTF_PACKMASK) != defencoding) {
        if((flags & MWTF_PACKMASK) != defencoding) {
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                flags &= ~MWTF_PACKMASK;
                flags &= ~MWTF_PACKMASK;
                flags |= defencoding;
                flags |= defencoding;
                text = buf;
                text = buf;
        } else text = str;
        } else text = str;
 
 
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
        if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
                cc = strlen((char *)str);
                cc = strlen((char *)str);
 
 
        if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
        if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
                return;
                return;
 
 
        /* draw text string*/
        /* draw text string*/
        gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
        gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
}
}
 
 
/*
/*
 * Draw ascii text using COREFONT type font.
 * Draw ascii text using COREFONT type font.
 */
 */
void
void
corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
        const void *text, int cc, int flags)
        const void *text, int cc, int flags)
{
{
        const unsigned char *str = text;
        const unsigned char *str = text;
        MWCOORD         width;                  /* width of text area */
        MWCOORD         width;                  /* width of text area */
        MWCOORD         height;                 /* height of text area */
        MWCOORD         height;                 /* height of text area */
        MWCOORD         base;                   /* baseline of text*/
        MWCOORD         base;                   /* baseline of text*/
        MWCOORD         startx, starty;
        MWCOORD         startx, starty;
                                                /* bitmap for characters */
                                                /* bitmap for characters */
        MWIMAGEBITS bitmap[MAX_CHAR_HEIGHT*MAX_CHAR_WIDTH/MWIMAGE_BITSPERIMAGE];
        MWIMAGEBITS bitmap[MAX_CHAR_HEIGHT*MAX_CHAR_WIDTH/MWIMAGE_BITSPERIMAGE];
 
 
        pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
        pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
 
 
        if(flags & MWTF_BASELINE)
        if(flags & MWTF_BASELINE)
                y -= base;
                y -= base;
        else if(flags & MWTF_BOTTOM)
        else if(flags & MWTF_BOTTOM)
                y -= (height - 1);
                y -= (height - 1);
        startx = x;
        startx = x;
        starty = y + base;
        starty = y + base;
 
 
        switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
        switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
        case CLIP_VISIBLE:
        case CLIP_VISIBLE:
                /*
                /*
                 * For size considerations, there's no low-level text
                 * For size considerations, there's no low-level text
                 * draw, so we've got to draw all text
                 * draw, so we've got to draw all text
                 * with per-point clipping for the time being
                 * with per-point clipping for the time being
                if (gr_usebg)
                if (gr_usebg)
                        psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
                        psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
                                gr_background);
                                gr_background);
                psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
                psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
                GdFixCursor(psd);
                GdFixCursor(psd);
                return;
                return;
                */
                */
                break;
                break;
 
 
        case CLIP_INVISIBLE:
        case CLIP_INVISIBLE:
                return;
                return;
        }
        }
 
 
        /* Get the bitmap for each character individually, and then display
        /* Get the bitmap for each character individually, and then display
         * them using clipping for each one.
         * them using clipping for each one.
         */
         */
        while (--cc >= 0 && x < psd->xvirtres) {
        while (--cc >= 0 && x < psd->xvirtres) {
                unsigned int ch = *str++;
                unsigned int ch = *str++;
#if HAVE_BIG5_SUPPORT
#if HAVE_BIG5_SUPPORT
                /* chinese big5 decoding*/
                /* chinese big5 decoding*/
                if (ch >= 0xA1 && ch <= 0xF9 && cc >= 1 &&
                if (ch >= 0xA1 && ch <= 0xF9 && cc >= 1 &&
                        ((*str >= 0x40 && *str <= 0x7E) ||
                        ((*str >= 0x40 && *str <= 0x7E) ||
                         (*str >= 0xA1 && *str <= 0xFE)) ) {
                         (*str >= 0xA1 && *str <= 0xFE)) ) {
                                ch = (ch << 8) | *str++;
                                ch = (ch << 8) | *str++;
                                --cc;
                                --cc;
                }
                }
#endif
#endif
#if HAVE_GB2312_SUPPORT
#if HAVE_GB2312_SUPPORT
                /* chinese gb2312 decoding*/
                /* chinese gb2312 decoding*/
                if (ch >= 0xA1 && ch < 0xF8 && cc >= 1 &&
                if (ch >= 0xA1 && ch < 0xF8 && cc >= 1 &&
                        *str >= 0xA1 && *str < 0xFF) {
                        *str >= 0xA1 && *str < 0xFF) {
                                ch = (ch << 8) | *str++;
                                ch = (ch << 8) | *str++;
                                --cc;
                                --cc;
                }
                }
#endif
#endif
                pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
                pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
                        &height, &base);
                        &height, &base);
 
 
                /* note: change to bitmap*/
                /* note: change to bitmap*/
                GdBitmap(psd, x, y, width, height, bitmap);
                GdBitmap(psd, x, y, width, height, bitmap);
                x += width;
                x += width;
        }
        }
 
 
        if (pfont->fontattr & MWTF_UNDERLINE)
        if (pfont->fontattr & MWTF_UNDERLINE)
                GdLine(psd, startx, starty, x, starty, FALSE);
                GdLine(psd, startx, starty, x, starty, FALSE);
 
 
        GdFixCursor(psd);
        GdFixCursor(psd);
}
}
 
 
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
/*
/*
 * Produce blend table from src and dst based on passed alpha table
 * Produce blend table from src and dst based on passed alpha table
 * Used because we don't quite yet have GdArea with alphablending,
 * Used because we don't quite yet have GdArea with alphablending,
 * so we pre-blend fg/bg colors for fade effect.
 * so we pre-blend fg/bg colors for fade effect.
 */
 */
static void
static void
alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
        unsigned char *alpha, int count)
        unsigned char *alpha, int count)
{
{
        unsigned int    a, d;
        unsigned int    a, d;
        unsigned char   r, g, b;
        unsigned char   r, g, b;
        MWCOLORVAL      palsrc, paldst;
        MWCOLORVAL      palsrc, paldst;
        extern MWPALENTRY gr_palette[256];
        extern MWPALENTRY gr_palette[256];
 
 
        while (--count >= 0) {
        while (--count >= 0) {
            a = *alpha++;
            a = *alpha++;
 
 
#define BITS(pixel,shift,mask)  (((pixel)>>shift)&(mask))
#define BITS(pixel,shift,mask)  (((pixel)>>shift)&(mask))
            if(a == 0)
            if(a == 0)
                *out++ = dst;
                *out++ = dst;
            else if(a == 255)
            else if(a == 255)
                *out++ = src;
                *out++ = src;
            else
            else
                switch(psd->pixtype) {
                switch(psd->pixtype) {
                case MWPF_TRUECOLOR0888:
                case MWPF_TRUECOLOR0888:
                case MWPF_TRUECOLOR888:
                case MWPF_TRUECOLOR888:
                    d = BITS(dst, 16, 0xff);
                    d = BITS(dst, 16, 0xff);
                    r = (unsigned char)(((BITS(src, 16, 0xff) - d)*a)>>8) + d;
                    r = (unsigned char)(((BITS(src, 16, 0xff) - d)*a)>>8) + d;
                    d = BITS(dst, 8, 0xff);
                    d = BITS(dst, 8, 0xff);
                    g = (unsigned char)(((BITS(src, 8, 0xff) - d)*a)>>8) + d;
                    g = (unsigned char)(((BITS(src, 8, 0xff) - d)*a)>>8) + d;
                    d = BITS(dst, 0, 0xff);
                    d = BITS(dst, 0, 0xff);
                    b = (unsigned char)(((BITS(src, 0, 0xff) - d)*a)>>8) + d;
                    b = (unsigned char)(((BITS(src, 0, 0xff) - d)*a)>>8) + d;
                    *out++ = (r << 16) | (g << 8) | b;
                    *out++ = (r << 16) | (g << 8) | b;
                    break;
                    break;
 
 
                case MWPF_TRUECOLOR565:
                case MWPF_TRUECOLOR565:
                    d = BITS(dst, 11, 0x1f);
                    d = BITS(dst, 11, 0x1f);
                    r = (unsigned char)(((BITS(src, 11, 0x1f) - d)*a)>>8) + d;
                    r = (unsigned char)(((BITS(src, 11, 0x1f) - d)*a)>>8) + d;
                    d = BITS(dst, 5, 0x3f);
                    d = BITS(dst, 5, 0x3f);
                    g = (unsigned char)(((BITS(src, 5, 0x3f) - d)*a)>>8) + d;
                    g = (unsigned char)(((BITS(src, 5, 0x3f) - d)*a)>>8) + d;
                    d = BITS(dst, 0, 0x1f);
                    d = BITS(dst, 0, 0x1f);
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
                    *out++ = (r << 11) | (g << 5) | b;
                    *out++ = (r << 11) | (g << 5) | b;
                    break;
                    break;
 
 
                case MWPF_TRUECOLOR555:
                case MWPF_TRUECOLOR555:
                    d = BITS(dst, 10, 0x1f);
                    d = BITS(dst, 10, 0x1f);
                    r = (unsigned char)(((BITS(src, 10, 0x1f) - d)*a)>>8) + d;
                    r = (unsigned char)(((BITS(src, 10, 0x1f) - d)*a)>>8) + d;
                    d = BITS(dst, 5, 0x1f);
                    d = BITS(dst, 5, 0x1f);
                    g = (unsigned char)(((BITS(src, 5, 0x1f) - d)*a)>>8) + d;
                    g = (unsigned char)(((BITS(src, 5, 0x1f) - d)*a)>>8) + d;
                    d = BITS(dst, 0, 0x1f);
                    d = BITS(dst, 0, 0x1f);
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
                    b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
                    *out++ = (r << 10) | (g << 5) | b;
                    *out++ = (r << 10) | (g << 5) | b;
                    break;
                    break;
 
 
                case MWPF_TRUECOLOR332:
                case MWPF_TRUECOLOR332:
                    d = BITS(dst, 5, 0x07);
                    d = BITS(dst, 5, 0x07);
                    r = (unsigned char)(((BITS(src, 5, 0x07) - d)*a)>>8) + d;
                    r = (unsigned char)(((BITS(src, 5, 0x07) - d)*a)>>8) + d;
                    d = BITS(dst, 2, 0x07);
                    d = BITS(dst, 2, 0x07);
                    g = (unsigned char)(((BITS(src, 2, 0x07) - d)*a)>>8) + d;
                    g = (unsigned char)(((BITS(src, 2, 0x07) - d)*a)>>8) + d;
                    d = BITS(dst, 0, 0x03);
                    d = BITS(dst, 0, 0x03);
                    b = (unsigned char)(((BITS(src, 0, 0x03) - d)*a)>>8) + d;
                    b = (unsigned char)(((BITS(src, 0, 0x03) - d)*a)>>8) + d;
                    *out++ = (r << 5) | (g << 2) | b;
                    *out++ = (r << 5) | (g << 2) | b;
                    break;
                    break;
 
 
                case MWPF_PALETTE:
                case MWPF_PALETTE:
                    /* reverse lookup palette entry for blend ;-)*/
                    /* reverse lookup palette entry for blend ;-)*/
                    palsrc = GETPALENTRY(gr_palette, src);
                    palsrc = GETPALENTRY(gr_palette, src);
                    paldst = GETPALENTRY(gr_palette, dst);
                    paldst = GETPALENTRY(gr_palette, dst);
                    d = REDVALUE(paldst);
                    d = REDVALUE(paldst);
                    r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
                    r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
                    d = GREENVALUE(paldst);
                    d = GREENVALUE(paldst);
                    g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
                    g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
                    d = BLUEVALUE(paldst);
                    d = BLUEVALUE(paldst);
                    b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
                    b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
                    *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
                    *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
                                MWRGB(r, g, b));
                                MWRGB(r, g, b));
                    break;
                    break;
                }
                }
        }
        }
}
}
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
 
 
#if HAVE_T1LIB_SUPPORT
#if HAVE_T1LIB_SUPPORT
/* contributed by Vidar Hokstad*/
/* contributed by Vidar Hokstad*/
 
 
static int
static int
t1lib_init(PSD psd)
t1lib_init(PSD psd)
{
{
        static int inited = 0;
        static int inited = 0;
 
 
        if (inited)
        if (inited)
                return 1;
                return 1;
 
 
        T1_SetBitmapPad(8);
        T1_SetBitmapPad(8);
        if (!T1_InitLib(0))
        if (!T1_InitLib(0))
                return 0;
                return 0;
#ifdef T1LIB_USE_AA_HIGH         
#ifdef T1LIB_USE_AA_HIGH         
        T1_AASetLevel(T1_AA_HIGH);
        T1_AASetLevel(T1_AA_HIGH);
#else
#else
        T1_AASetLevel(T1_AA_LOW);
        T1_AASetLevel(T1_AA_LOW);
#endif   
#endif   
#if 0
#if 0
        /* kluge: this is required if 16bpp drawarea driver is used*/
        /* kluge: this is required if 16bpp drawarea driver is used*/
        if(psd->bpp == 16)
        if(psd->bpp == 16)
                T1_AASetBitsPerPixel(16);
                T1_AASetBitsPerPixel(16);
        else
        else
#endif
#endif
                T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
                T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
 
 
        inited = 1;
        inited = 1;
        return 1;
        return 1;
}
}
 
 
static PMWT1LIBFONT
static PMWT1LIBFONT
t1lib_createfont(const char *name, MWCOORD height, int attr)
t1lib_createfont(const char *name, MWCOORD height, int attr)
{
{
        PMWT1LIBFONT    pf;
        PMWT1LIBFONT    pf;
        int             id;
        int             id;
        char *          p;
        char *          p;
        char            buf[256];
        char            buf[256];
 
 
        /* match name against t1 font id's from t1 font database*/
        /* match name against t1 font id's from t1 font database*/
        for(id=0; id<T1_Get_no_fonts(); ++id) {
        for(id=0; id<T1_Get_no_fonts(); ++id) {
                strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
                strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
 
 
                /* remove extension*/
                /* remove extension*/
                for(p=buf; *p; ++p) {
                for(p=buf; *p; ++p) {
                        if(*p == '.') {
                        if(*p == '.') {
                                *p = 0;
                                *p = 0;
                                break;
                                break;
                        }
                        }
                }
                }
 
 
                if(!strcmpi(name, buf)) {
                if(!strcmpi(name, buf)) {
                        /* allocate font structure*/
                        /* allocate font structure*/
                        pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
                        pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
                        if (!pf)
                        if (!pf)
                                return NULL;
                                return NULL;
                        pf->fontprocs = &t1lib_procs;
                        pf->fontprocs = &t1lib_procs;
                        GdSetFontSize((PMWFONT)pf, height);
                        GdSetFontSize((PMWFONT)pf, height);
                        GdSetFontRotation((PMWFONT)pf, 0);
                        GdSetFontRotation((PMWFONT)pf, 0);
                        GdSetFontAttr((PMWFONT)pf, attr, 0);
                        GdSetFontAttr((PMWFONT)pf, attr, 0);
                        pf->fontid = id;
                        pf->fontid = id;
                        return pf;
                        return pf;
                }
                }
        }
        }
        return NULL;
        return NULL;
}
}
 
 
/*
/*
 * Draw ascii text string using T1LIB type font
 * Draw ascii text string using T1LIB type font
 */
 */
static void
static void
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
        const void *text, int cc, int flags)
        const void *text, int cc, int flags)
{
{
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
        const unsigned char *str = text;
        const unsigned char *str = text;
        MWCOORD         width;                  /* width of text area */
        MWCOORD         width;                  /* width of text area */
        MWCOORD         height;                 /* height of text area */
        MWCOORD         height;                 /* height of text area */
        MWCOORD         underliney;
        MWCOORD         underliney;
        GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
        GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
#ifdef T1LIB_USE_AA_HIGH   
#ifdef T1LIB_USE_AA_HIGH   
        OUTPIXELVAL     gvals[17];
        OUTPIXELVAL     gvals[17];
 
 
        /* Blending array for antialiasing. The steeper the values increase
        /* Blending array for antialiasing. The steeper the values increase
         * near the end, the sharper the characters look, but also more jagged
         * near the end, the sharper the characters look, but also more jagged
         */
         */
        static unsigned char blend[17] = {
        static unsigned char blend[17] = {
           0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
           0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
           0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
           0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
        };
        };
#else   
#else   
        OUTPIXELVAL     gvals[5];
        OUTPIXELVAL     gvals[5];
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
#endif   
#endif   
 
 
        /* Check if we should throw out some fonts */
        /* Check if we should throw out some fonts */
 
 
        if (pf->fontattr&MWTF_ANTIALIAS) {
        if (pf->fontattr&MWTF_ANTIALIAS) {
#ifdef T1LIB_USE_AA_HIGH      
#ifdef T1LIB_USE_AA_HIGH      
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
           T1_AAHSetGrayValues(gvals);
           T1_AAHSetGrayValues(gvals);
#else      
#else      
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
           alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
           T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
           T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
#endif
#endif
           g = T1_AASetString(pf->fontid,(char *)str,cc,0,
           g = T1_AASetString(pf->fontid,(char *)str,cc,0,
                (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
                (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
                pf->fontsize * 1.0, 0);
                pf->fontsize * 1.0, 0);
 
 
           if (g && g->bits) {
           if (g && g->bits) {
              /*MWPIXELVAL save = gr_background;*/
              /*MWPIXELVAL save = gr_background;*/
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
              height = g->metrics.ascent - g->metrics.descent;
              height = g->metrics.ascent - g->metrics.descent;
 
 
              if(flags & MWTF_BASELINE)
              if(flags & MWTF_BASELINE)
                y -= g->metrics.ascent;
                y -= g->metrics.ascent;
              else if(flags & MWTF_BOTTOM)
              else if(flags & MWTF_BOTTOM)
                y -= (height - 1);
                y -= (height - 1);
              underliney = y + g->metrics.ascent;
              underliney = y + g->metrics.ascent;
 
 
              /* FIXME: Looks damn ugly if usebg is false.
              /* FIXME: Looks damn ugly if usebg is false.
               * Will be handled when using alphablending in GdArea...
               * Will be handled when using alphablending in GdArea...
               */
               */
              /* clipping handled in GdArea*/
              /* clipping handled in GdArea*/
              /*FIXME kluge for transparency*/
              /*FIXME kluge for transparency*/
              /*gr_background = gr_foreground + 1;*/
              /*gr_background = gr_foreground + 1;*/
              /*gr_usebg = 0;*/
              /*gr_usebg = 0;*/
              GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
              GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
              /*gr_background = save;*/
              /*gr_background = save;*/
 
 
              if (pf->fontattr & MWTF_UNDERLINE)
              if (pf->fontattr & MWTF_UNDERLINE)
                   GdLine(psd, x, underliney, x+width, underliney, FALSE);
                   GdLine(psd, x, underliney, x+width, underliney, FALSE);
 
 
           }
           }
        } else {
        } else {
           /* Do non-aa drawing */
           /* Do non-aa drawing */
           g = T1_SetString(pf->fontid,(char *)str,cc,0,
           g = T1_SetString(pf->fontid,(char *)str,cc,0,
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
                        pf->fontsize * 1.0, 0);
                        pf->fontsize * 1.0, 0);
 
 
           if (g && g->bits) {
           if (g && g->bits) {
              unsigned char * b;
              unsigned char * b;
              int xoff;
              int xoff;
              int maxy;
              int maxy;
              int xmod;
              int xmod;
 
 
              /* I'm sure this sorry excuse for a bitmap rendering routine can
              /* I'm sure this sorry excuse for a bitmap rendering routine can
               * be optimized quite a bit ;)
               * be optimized quite a bit ;)
               */
               */
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
              width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
              height = g->metrics.ascent - g->metrics.descent;
              height = g->metrics.ascent - g->metrics.descent;
 
 
              if(flags & MWTF_BASELINE)
              if(flags & MWTF_BASELINE)
                y -= g->metrics.ascent;
                y -= g->metrics.ascent;
              else if(flags & MWTF_BOTTOM)
              else if(flags & MWTF_BOTTOM)
                y -= (height - 1);
                y -= (height - 1);
              underliney = y + g->metrics.ascent;
              underliney = y + g->metrics.ascent;
 
 
              b = g->bits;
              b = g->bits;
              maxy = y + height;
              maxy = y + height;
 
 
/*            if ((x + width) > psd->xvirtres) {
/*            if ((x + width) > psd->xvirtres) {
                 xmod = (x + width - psd->xvirtres + 7) >> 3;
                 xmod = (x + width - psd->xvirtres + 7) >> 3;
                 width = width + x + width - psd->xvirtres;
                 width = width + x + width - psd->xvirtres;
              } else xmod = 0;
              } else xmod = 0;
*/
*/
              xmod = 0;
              xmod = 0;
              while (y < maxy) {
              while (y < maxy) {
                 unsigned char data;
                 unsigned char data;
                 xoff = 0;
                 xoff = 0;
                 while (xoff < width ) {
                 while (xoff < width ) {
                    if (!(xoff % 8)) {
                    if (!(xoff % 8)) {
                       data = *b;
                       data = *b;
                       b++;
                       b++;
                    }
                    }
 
 
                    if (GdClipPoint(psd, x+xoff,y)) {
                    if (GdClipPoint(psd, x+xoff,y)) {
                       if (gr_usebg) {
                       if (gr_usebg) {
                          psd->DrawPixel(psd,x+xoff,y,
                          psd->DrawPixel(psd,x+xoff,y,
                              data & (1 << (xoff % 8)) ?
                              data & (1 << (xoff % 8)) ?
                                    gr_foreground : gr_background);
                                    gr_foreground : gr_background);
                       } else if (data & (1 << (xoff % 8))) {
                       } else if (data & (1 << (xoff % 8))) {
                          psd->DrawPixel(psd,x+xoff,y, gr_foreground);
                          psd->DrawPixel(psd,x+xoff,y, gr_foreground);
                       }
                       }
                    }
                    }
                    xoff++;
                    xoff++;
                 }
                 }
                 b += xmod;
                 b += xmod;
                 y++;
                 y++;
              }
              }
              if (pf->fontattr & MWTF_UNDERLINE)
              if (pf->fontattr & MWTF_UNDERLINE)
                   GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
                   GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
           }
           }
        }
        }
 
 
   if (g && g->bits) {
   if (g && g->bits) {
           /* Save some memory */
           /* Save some memory */
           free(g->bits);
           free(g->bits);
           g->bits = 0; /* Make sure T1lib doesnt try to free it again */
           g->bits = 0; /* Make sure T1lib doesnt try to free it again */
   }
   }
 
 
   GdFixCursor(psd);
   GdFixCursor(psd);
}
}
 
 
static MWBOOL
static MWBOOL
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
{
        int     i;
        int     i;
        MWCOORD width, height, baseline;
        MWCOORD width, height, baseline;
 
 
        /* FIXME, guess all sizes*/
        /* FIXME, guess all sizes*/
        GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
        GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
        pfontinfo->height = height;
        pfontinfo->height = height;
        pfontinfo->maxwidth = width;
        pfontinfo->maxwidth = width;
        pfontinfo->baseline = 0;
        pfontinfo->baseline = 0;
        pfontinfo->firstchar = 32;
        pfontinfo->firstchar = 32;
        pfontinfo->lastchar = 255;
        pfontinfo->lastchar = 255;
        pfontinfo->fixed = TRUE;
        pfontinfo->fixed = TRUE;
        for(i=0; i<256; ++i)
        for(i=0; i<256; ++i)
                pfontinfo->widths[i] = width;
                pfontinfo->widths[i] = width;
        return TRUE;
        return TRUE;
}
}
 
 
/* Get the width and height of passed text string in the current font*/
/* Get the width and height of passed text string in the current font*/
static void
static void
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
{
{
        PMWT1LIBFONT            pf = (PMWT1LIBFONT)pfont;
        PMWT1LIBFONT            pf = (PMWT1LIBFONT)pfont;
        const unsigned char *   str = text;
        const unsigned char *   str = text;
        GLYPH *                 g;
        GLYPH *                 g;
 
 
        g = T1_SetString(pf->fontid, (char *)str, cc, 0,
        g = T1_SetString(pf->fontid, (char *)str, cc, 0,
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
                        (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
        *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
        *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
        *pheight = g->metrics.ascent - g->metrics.descent;
        *pheight = g->metrics.ascent - g->metrics.descent;
        if(g && g->bits) {
        if(g && g->bits) {
                free(g->bits);
                free(g->bits);
                g->bits = 0;
                g->bits = 0;
        }
        }
#if 0
#if 0
        BBox                    b;
        BBox                    b;
 
 
        /* FIXME. Something is *VERY* wrong here */
        /* FIXME. Something is *VERY* wrong here */
        b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
        b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
 
 
        DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
        DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
        DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
        DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
        *pwidth = (b.urx - b.llx);
        *pwidth = (b.urx - b.llx);
        *pheight = (b.lly - b.ury);
        *pheight = (b.lly - b.ury);
#endif
#endif
}
}
 
 
static void
static void
t1lib_destroyfont(PMWFONT pfont)
t1lib_destroyfont(PMWFONT pfont)
{
{
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
        PMWT1LIBFONT    pf = (PMWT1LIBFONT)pfont;
 
 
        T1_DeleteAllSizes(pf->fontid);
        T1_DeleteAllSizes(pf->fontid);
        free(pf);
        free(pf);
}
}
 
 
#endif /* HAVE_T1LIB_SUPPORT*/
#endif /* HAVE_T1LIB_SUPPORT*/
 
 
#if HAVE_FREETYPE_SUPPORT
#if HAVE_FREETYPE_SUPPORT
static OUTPIXELVAL gray_palette[5];
static OUTPIXELVAL gray_palette[5];
 
 
static int
static int
freetype_init(PSD psd)
freetype_init(PSD psd)
{
{
        static int inited = 0;
        static int inited = 0;
 
 
        if (inited)
        if (inited)
                return 1;
                return 1;
 
 
        /* Init freetype library */
        /* Init freetype library */
        if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
        if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
                return 0;
                return 0;
        }
        }
 
 
        /* Init kerning extension */
        /* Init kerning extension */
        if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
        if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
                return 0;
                return 0;
 
 
        inited = 1;
        inited = 1;
        return 1;
        return 1;
}
}
 
 
static PMWFREETYPEFONT
static PMWFREETYPEFONT
freetype_createfont(const char *name, MWCOORD height, int attr)
freetype_createfont(const char *name, MWCOORD height, int attr)
{
{
        PMWFREETYPEFONT         pf;
        PMWFREETYPEFONT         pf;
        unsigned short          i, n;
        unsigned short          i, n;
        unsigned short          platform, encoding;
        unsigned short          platform, encoding;
        TT_Face_Properties      properties;
        TT_Face_Properties      properties;
        char *                  p;
        char *                  p;
        char                    fontname[128];
        char                    fontname[128];
 
 
        /* check for pathname prefix*/
        /* check for pathname prefix*/
        if (strchr(name, '/') != NULL)
        if (strchr(name, '/') != NULL)
                strcpy(fontname, name);
                strcpy(fontname, name);
        else {
        else {
                strcpy(fontname, FREETYPE_FONT_DIR);
                strcpy(fontname, FREETYPE_FONT_DIR);
                strcat(fontname, "/");
                strcat(fontname, "/");
                strcat(fontname, name);
                strcat(fontname, name);
        }
        }
 
 
        /* check for extension*/
        /* check for extension*/
        if ((p = strrchr(fontname, '.')) == NULL ||
        if ((p = strrchr(fontname, '.')) == NULL ||
            strcmp(p, ".ttf") != 0) {
            strcmp(p, ".ttf") != 0) {
                strcat(fontname, ".ttf");
                strcat(fontname, ".ttf");
        }
        }
 
 
        /* allocate font structure*/
        /* allocate font structure*/
        pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
        pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
        if (!pf)
        if (!pf)
                return NULL;
                return NULL;
        pf->fontprocs = &freetype_procs;
        pf->fontprocs = &freetype_procs;
 
 
        /* Load face */
        /* Load face */
        if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
        if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
                goto out;
                goto out;
 
 
        /* Load first kerning table */
        /* Load first kerning table */
        pf->can_kern = TRUE;
        pf->can_kern = TRUE;
        if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
        if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
                pf->can_kern = FALSE;
                pf->can_kern = FALSE;
        else {
        else {
                if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
                if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
                    != TT_Err_Ok)
                    != TT_Err_Ok)
                        pf->can_kern = FALSE;
                        pf->can_kern = FALSE;
                else {
                else {
                        /* Support only version 0 kerning table ... */
                        /* Support only version 0 kerning table ... */
                        if ((pf->directory.version != 0) ||
                        if ((pf->directory.version != 0) ||
                                (pf->directory.nTables <= 0) ||
                                (pf->directory.nTables <= 0) ||
                                (pf->directory.tables->loaded != 1) ||
                                (pf->directory.tables->loaded != 1) ||
                                (pf->directory.tables->version != 0) ||
                                (pf->directory.tables->version != 0) ||
                                (pf->directory.tables->t.kern0.nPairs <= 0))
                                (pf->directory.tables->t.kern0.nPairs <= 0))
                                        pf->can_kern = FALSE;
                                        pf->can_kern = FALSE;
                }
                }
        }
        }
 
 
        /* get face properties and allocate preload arrays */
        /* get face properties and allocate preload arrays */
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Face_Properties (pf->face, &properties);
 
 
#if 0
#if 0
        /*
        /*
         * Use header information for ascent and descent
         * Use header information for ascent and descent
         * to compute scaled ascent/descent for current font height.
         * to compute scaled ascent/descent for current font height.
         */
         */
        h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
        h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
                + properties.os2->sTypoLineGap;
                + properties.os2->sTypoLineGap;
        ascent = properties.os2->sTypoAscender
        ascent = properties.os2->sTypoAscender
                + properties.os2->sTypoLineGap/2;
                + properties.os2->sTypoLineGap/2;
        pf->ascent = (ascent * height + h/2) / h;
        pf->ascent = (ascent * height + h/2) / h;
        pf->descent = height - pf->ascent;
        pf->descent = height - pf->ascent;
#endif
#endif
        /* Create a glyph container */
        /* Create a glyph container */
        if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
        if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
                goto out;
                goto out;
 
 
        /* create instance */
        /* create instance */
        if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
        if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
                goto out;
                goto out;
 
 
        /* Set the instance resolution */
        /* Set the instance resolution */
        if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
        if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
                goto out;
                goto out;
 
 
        /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
        /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
        n = properties.num_CharMaps;
        n = properties.num_CharMaps;
 
 
        for (i = 0; i < n; i++) {
        for (i = 0; i < n; i++) {
                TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
                TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
                if (((platform == TT_PLATFORM_MICROSOFT) &&
                if (((platform == TT_PLATFORM_MICROSOFT) &&
                        (encoding == TT_MS_ID_UNICODE_CS)) ||
                        (encoding == TT_MS_ID_UNICODE_CS)) ||
                                ((platform == TT_PLATFORM_APPLE_UNICODE) &&
                                ((platform == TT_PLATFORM_APPLE_UNICODE) &&
                                        (encoding == TT_APPLE_ID_DEFAULT)))
                                        (encoding == TT_APPLE_ID_DEFAULT)))
                {
                {
                        TT_Get_CharMap (pf->face, i, &pf->char_map);
                        TT_Get_CharMap (pf->face, i, &pf->char_map);
                        i = n + 1;
                        i = n + 1;
                }
                }
        }
        }
        if (i == n) {
        if (i == n) {
                DPRINTF("freetype_createfont: no unicode map table\n");
                DPRINTF("freetype_createfont: no unicode map table\n");
                goto out;
                goto out;
        }
        }
 
 
        GdSetFontSize((PMWFONT)pf, height);
        GdSetFontSize((PMWFONT)pf, height);
        GdSetFontRotation((PMWFONT)pf, 0);
        GdSetFontRotation((PMWFONT)pf, 0);
        GdSetFontAttr((PMWFONT)pf, attr, 0);
        GdSetFontAttr((PMWFONT)pf, attr, 0);
 
 
        return pf;
        return pf;
 
 
out:
out:
        free(pf);
        free(pf);
        return NULL;
        return NULL;
}
}
 
 
static int
static int
compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
{
{
        int             i = 0;
        int             i = 0;
        int             kernval;
        int             kernval;
        int             nPairs = pf->directory.tables->t.kern0.nPairs;
        int             nPairs = pf->directory.tables->t.kern0.nPairs;
        TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
        TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
 
 
        if (pf->last_glyph_code != -1) {
        if (pf->last_glyph_code != -1) {
                while ((pair->left != pf->last_glyph_code)
                while ((pair->left != pf->last_glyph_code)
                        && (pair->right != current_glyph_code))
                        && (pair->right != current_glyph_code))
                {
                {
                        pair++;
                        pair++;
                        i++;
                        i++;
                        if (i == nPairs)
                        if (i == nPairs)
                        break;
                        break;
                }
                }
 
 
                if (i == nPairs)
                if (i == nPairs)
                        kernval = 0;
                        kernval = 0;
                else
                else
                        /* We round the value (hence the +32) */
                        /* We round the value (hence the +32) */
                        kernval = (pair->value + 32) & -64;
                        kernval = (pair->value + 32) & -64;
        } else
        } else
                kernval = 0;
                kernval = 0;
 
 
        return kernval;
        return kernval;
}
}
 
 
static TT_UShort
static TT_UShort
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
{
{
        TT_Glyph_Metrics metrics;
        TT_Glyph_Metrics metrics;
 
 
        if (TT_Load_Glyph ( pf->instance, pf->glyph,
        if (TT_Load_Glyph ( pf->instance, pf->glyph,
                TT_Char_Index (pf->char_map,glyph_index),
                TT_Char_Index (pf->char_map,glyph_index),
                TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
        {
        {
                /* Try to load default glyph: index 0 */
                /* Try to load default glyph: index 0 */
                if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
                if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                    return 0;
                    return 0;
        }
        }
 
 
        TT_Get_Glyph_Metrics (pf->glyph, &metrics);
        TT_Get_Glyph_Metrics (pf->glyph, &metrics);
        return((metrics.advance & 0xFFFFFFC0) >> 6);
        return((metrics.advance & 0xFFFFFFC0) >> 6);
}
}
 
 
static MWFREETYPEFONTCACHE *
static MWFREETYPEFONTCACHE *
find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
{
{
  MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;
  MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;
 
 
  while (1)
  while (1)
    {
    {
      if (*inode == 0)
      if (*inode == 0)
        {
        {
          *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
          *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
          (*inode)->curchar = curchar;
          (*inode)->curchar = curchar;
        }
        }
 
 
      if (curchar < (*inode)->curchar)
      if (curchar < (*inode)->curchar)
        inode = &(*inode)->l;
        inode = &(*inode)->l;
      else if (curchar > (*inode)->curchar)
      else if (curchar > (*inode)->curchar)
        inode = &(*inode)->r;
        inode = &(*inode)->r;
      else
      else
        return *inode;
        return *inode;
    }
    }
}
}
 
 
static void
static void
free_cache_glyph ( MWFREETYPEFONTCACHE * node )
free_cache_glyph ( MWFREETYPEFONTCACHE * node )
{
{
  if (node->l != 0)
  if (node->l != 0)
    free_cache_glyph(node->l);
    free_cache_glyph(node->l);
 
 
  if (node->r != 0)
  if (node->r != 0)
    free_cache_glyph(node->r);
    free_cache_glyph(node->r);
 
 
  free(node);
  free(node);
}
}
 
 
/* Render a single glyph*/
/* Render a single glyph*/
static void
static void
drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
        int y_offset)
        int y_offset)
{
{
        TT_F26Dot6      xmin, ymin, xmax, ymax, x, y, z;
        TT_F26Dot6      xmin, ymin, xmax, ymax, x, y, z;
        unsigned char   *src, *srcptr;
        unsigned char   *src, *srcptr;
        MWPIXELVAL      *dst, *dstptr;
        MWPIXELVAL      *dst, *dstptr;
        MWPIXELVAL      *bitmap;
        MWPIXELVAL      *bitmap;
        int             size, width, height;
        int             size, width, height;
        TT_Outline      outline;
        TT_Outline      outline;
        TT_BBox         bbox;
        TT_BBox         bbox;
        TT_Raster_Map   Raster;
        TT_Raster_Map   Raster;
        TT_Error        error;
        TT_Error        error;
        /*MWPIXELVAL    save;*/
        /*MWPIXELVAL    save;*/
        MWFREETYPEFONTCACHE * cache;
        MWFREETYPEFONTCACHE * cache;
 
 
        /* we begin by grid-fitting the bounding box */
        /* we begin by grid-fitting the bounding box */
        TT_Get_Glyph_Outline (pf->glyph, &outline);
        TT_Get_Glyph_Outline (pf->glyph, &outline);
        TT_Get_Outline_BBox (&outline, &bbox);
        TT_Get_Outline_BBox (&outline, &bbox);
 
 
        xmin = (bbox.xMin & -64) >> 6;
        xmin = (bbox.xMin & -64) >> 6;
        ymin = (bbox.yMin & -64) >> 6;
        ymin = (bbox.yMin & -64) >> 6;
        xmax = ((bbox.xMax + 63) & -64) >> 6;
        xmax = ((bbox.xMax + 63) & -64) >> 6;
        ymax = ((bbox.yMax + 63) & -64) >> 6;
        ymax = ((bbox.yMax + 63) & -64) >> 6;
        width = xmax - xmin;
        width = xmax - xmin;
        height = ymax - ymin;
        height = ymax - ymin;
        size = width * height;
        size = width * height;
 
 
        /* now re-allocate the raster bitmap */
        /* now re-allocate the raster bitmap */
        Raster.rows = height;
        Raster.rows = height;
        Raster.width = width;
        Raster.width = width;
 
 
        if (pf->fontattr&MWTF_ANTIALIAS)
        if (pf->fontattr&MWTF_ANTIALIAS)
                Raster.cols = (Raster.width + 3) & -4;  /* pad to 32-bits */
                Raster.cols = (Raster.width + 3) & -4;  /* pad to 32-bits */
        else
        else
                Raster.cols = (Raster.width + 7) & -8;  /* pad to 64-bits ??? */
                Raster.cols = (Raster.width + 7) & -8;  /* pad to 64-bits ??? */
 
 
        cache = find_cache_glyph(pf,curchar);
        cache = find_cache_glyph(pf,curchar);
        /* SDR: if cache is 0 here, something really really bad happened */
        /* SDR: if cache is 0 here, something really really bad happened */
 
 
        Raster.flow = TT_Flow_Up;
        Raster.flow = TT_Flow_Up;
        Raster.size = Raster.rows * Raster.cols;
        Raster.size = Raster.rows * Raster.cols;
        Raster.bitmap = cache->buffer;
        Raster.bitmap = cache->buffer;
 
 
        if (Raster.bitmap == 0)
        if (Raster.bitmap == 0)
          {
          {
            Raster.bitmap = malloc (Raster.size);
            Raster.bitmap = malloc (Raster.size);
 
 
            memset (Raster.bitmap, 0, Raster.size);
            memset (Raster.bitmap, 0, Raster.size);
 
 
            /* now render the glyph in the small pixmap */
            /* now render the glyph in the small pixmap */
 
 
            /* IMPORTANT NOTE: the offset parameters passed to the function     */
            /* IMPORTANT NOTE: the offset parameters passed to the function     */
            /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
            /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
            /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
            /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
            /* This is why we _did_ grid-fit the bounding box, especially xmin  */
            /* This is why we _did_ grid-fit the bounding box, especially xmin  */
            /* and ymin.                                                        */
            /* and ymin.                                                        */
 
 
            if (!(pf->fontattr&MWTF_ANTIALIAS))
            if (!(pf->fontattr&MWTF_ANTIALIAS))
              error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
              error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
                                           -xmin * 64, -ymin * 64);
                                           -xmin * 64, -ymin * 64);
            else
            else
              error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
              error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
                                           -xmin * 64, -ymin * 64);
                                           -xmin * 64, -ymin * 64);
 
 
            if (error) {
            if (error) {
              free (Raster.bitmap);
              free (Raster.bitmap);
              return;
              return;
            }
            }
 
 
            cache->buffer = Raster.bitmap;
            cache->buffer = Raster.bitmap;
          }
          }
 
 
#if MWFREETYPEFONT_CACHEBITMAP
#if MWFREETYPEFONT_CACHEBITMAP
        if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) ||
        if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) ||
            (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) ||
            (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) ||
            (gr_usebg != cache->usebg))
            (gr_usebg != cache->usebg))
          {
          {
            if (cache->bitmap)
            if (cache->bitmap)
              {
              {
                free(cache->bitmap);
                free(cache->bitmap);
                cache->bitmap = 0;
                cache->bitmap = 0;
              }
              }
          }
          }
 
 
        bitmap = cache->bitmap;
        bitmap = cache->bitmap;
#else
#else
        bitmap = 0;
        bitmap = 0;
#endif
#endif
 
 
        if (bitmap == 0)
        if (bitmap == 0)
          {
          {
            bitmap = malloc (size * sizeof (MWPIXELVAL));
            bitmap = malloc (size * sizeof (MWPIXELVAL));
            memset (bitmap, 0, size * sizeof (MWPIXELVAL));
            memset (bitmap, 0, size * sizeof (MWPIXELVAL));
 
 
            src = (char *) Raster.bitmap;
            src = (char *) Raster.bitmap;
            dst = bitmap + (size - width);
            dst = bitmap + (size - width);
 
 
            for (y = ymin; y < ymax; y++)
            for (y = ymin; y < ymax; y++)
              {
              {
                srcptr = src;
                srcptr = src;
                dstptr = dst;
                dstptr = dst;
 
 
                for (x = xmin; x < xmax; x++)
                for (x = xmin; x < xmax; x++)
                  {
                  {
                    if (pf->fontattr&MWTF_ANTIALIAS)
                    if (pf->fontattr&MWTF_ANTIALIAS)
                      *dstptr++ = gray_palette[(int) *srcptr];
                      *dstptr++ = gray_palette[(int) *srcptr];
                    else
                    else
                      {
                      {
                        for ( z=0;
                        for ( z=0;
                              z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
                              z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
                              z++ )
                              z++ )
                            *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
                            *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
                        x += 7;
                        x += 7;
                      }
                      }
 
 
                    srcptr++;
                    srcptr++;
                  }
                  }
 
 
                src += Raster.cols;
                src += Raster.cols;
                dst -= width;
                dst -= width;
              }
              }
#if MWFREETYPEFONT_CACHEBITMAP
#if MWFREETYPEFONT_CACHEBITMAP
            cache->fg = gr_foreground;
            cache->fg = gr_foreground;
            cache->bg = gr_background;
            cache->bg = gr_background;
            cache->usebg = gr_usebg;
            cache->usebg = gr_usebg;
            cache->bitmap = bitmap;
            cache->bitmap = bitmap;
#endif
#endif
          }
          }
 
 
        /* Now draw the bitmap ... */
        /* Now draw the bitmap ... */
        GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
        GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
                bitmap, MWPF_PIXELVAL);
                bitmap, MWPF_PIXELVAL);
 
 
#if !MWFREETYPEFONT_CACHEBITMAP
#if !MWFREETYPEFONT_CACHEBITMAP
        free(bitmap);
        free(bitmap);
#endif
#endif
}
}
 
 
/*
/*
 * Draw unicode 16 text string using FREETYPE type font
 * Draw unicode 16 text string using FREETYPE type font
 */
 */
static void
static void
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
        const void *text, int cc, int flags)
        const void *text, int cc, int flags)
{
{
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        const unsigned short *  str = text;
        const unsigned short *  str = text;
        TT_F26Dot6      x = ax, y = ay;
        TT_F26Dot6      x = ax, y = ay;
        TT_Pos          vec_x, vec_y;
        TT_Pos          vec_x, vec_y;
        int             i;
        int             i;
        TT_F26Dot6      startx, starty;
        TT_F26Dot6      startx, starty;
        TT_Outline      outline;
        TT_Outline      outline;
        TT_UShort       curchar;
        TT_UShort       curchar;
        TT_Glyph_Metrics metrics;
        TT_Glyph_Metrics metrics;
        TT_Face_Properties properties;
        TT_Face_Properties properties;
        TT_Instance_Metrics imetrics;
        TT_Instance_Metrics imetrics;
        TT_F26Dot6 ascent, descent;
        TT_F26Dot6 ascent, descent;
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
        static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
        static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
        static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
 
 
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_pen_pos = -32767;
        pf->last_pen_pos = -32767;
 
 
        /*
        /*
         * Compute instance ascent & descent values
         * Compute instance ascent & descent values
         * in fractional units (1/64th pixel)
         * in fractional units (1/64th pixel)
         */
         */
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
 
 
        ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
        ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
        descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
        descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
 
 
        /*
        /*
         * Offset the starting point if necessary,
         * Offset the starting point if necessary,
         * FreeType always aligns at baseline
         * FreeType always aligns at baseline
         */
         */
        if (flags&MWTF_BOTTOM) {
        if (flags&MWTF_BOTTOM) {
                vec_x = 0;
                vec_x = 0;
                vec_y = descent;
                vec_y = descent;
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
                x -= vec_x / 64;
                x -= vec_x / 64;
                y += vec_y / 64;
                y += vec_y / 64;
        } else if (flags&MWTF_TOP) {
        } else if (flags&MWTF_TOP) {
                vec_x = 0;
                vec_x = 0;
                vec_y = ascent;
                vec_y = ascent;
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
                x -= vec_x / 64;
                x -= vec_x / 64;
                y += vec_y / 64;
                y += vec_y / 64;
        }
        }
 
 
        /* Set the "graylevels" */
        /* Set the "graylevels" */
        if (pf->fontattr&MWTF_ANTIALIAS) {
        if (pf->fontattr&MWTF_ANTIALIAS) {
                TT_Set_Raster_Gray_Palette (engine, virtual_palette);
                TT_Set_Raster_Gray_Palette (engine, virtual_palette);
 
 
                alphablend(psd, gray_palette, gr_foreground, gr_background,
                alphablend(psd, gray_palette, gr_foreground, gr_background,
                        blend, 5);
                        blend, 5);
        }
        }
 
 
        startx = x;
        startx = x;
        starty = y;
        starty = y;
        for (i = 0; i < cc; i++) {
        for (i = 0; i < cc; i++) {
                curchar = TT_Char_Index (pf->char_map, str[i]);
                curchar = TT_Char_Index (pf->char_map, str[i]);
 
 
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                        TTLOAD_DEFAULT) != TT_Err_Ok)
                        TTLOAD_DEFAULT) != TT_Err_Ok)
                                continue;
                                continue;
 
 
                if (pf->fontrotation) {
                if (pf->fontrotation) {
                        TT_Get_Glyph_Outline (pf->glyph, &outline);
                        TT_Get_Glyph_Outline (pf->glyph, &outline);
                        TT_Transform_Outline (&outline, &pf->matrix);
                        TT_Transform_Outline (&outline, &pf->matrix);
                }
                }
 
 
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
 
 
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
                        if (pf->fontrotation) {
                        if (pf->fontrotation) {
                                vec_x = compute_kernval(pf, curchar);
                                vec_x = compute_kernval(pf, curchar);
                                vec_y = 0;
                                vec_y = 0;
                                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
                                TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
 
 
                                x += vec_x / 64;
                                x += vec_x / 64;
                                y -= vec_y / 64;
                                y -= vec_y / 64;
                        } else
                        } else
                                x += compute_kernval(pf, curchar) / 64;
                                x += compute_kernval(pf, curchar) / 64;
                }
                }
 
 
                drawchar(pf, psd, curchar, x, y);
                drawchar(pf, psd, curchar, x, y);
 
 
                if (pf->fontrotation) {
                if (pf->fontrotation) {
                        vec_x = metrics.advance;
                        vec_x = metrics.advance;
                        vec_y = 0;
                        vec_y = 0;
                        TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
                        TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
 
 
                        x += vec_x / 64;
                        x += vec_x / 64;
                        y -= vec_y / 64;
                        y -= vec_y / 64;
                } else {
                } else {
                        x += metrics.advance / 64;
                        x += metrics.advance / 64;
 
 
                        /* Kerning point syndrome avoidance */
                        /* Kerning point syndrome avoidance */
                        if (pf->last_pen_pos > x)
                        if (pf->last_pen_pos > x)
                                x = pf->last_pen_pos;
                                x = pf->last_pen_pos;
                        pf->last_pen_pos = x;
                        pf->last_pen_pos = x;
                }
                }
 
 
                pf->last_glyph_code = curchar;
                pf->last_glyph_code = curchar;
        }
        }
 
 
        if (pf->fontattr & MWTF_UNDERLINE)
        if (pf->fontattr & MWTF_UNDERLINE)
                GdLine(psd, startx, starty, x, y, FALSE);
                GdLine(psd, startx, starty, x, y, FALSE);
}
}
 
 
/*
/*
 * Return information about a specified font.
 * Return information about a specified font.
 */
 */
static MWBOOL
static MWBOOL
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
{
        int     i;
        int     i;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        TT_Face_Properties      properties;
        TT_Face_Properties      properties;
        TT_Instance_Metrics imetrics;
        TT_Instance_Metrics imetrics;
        TT_UShort last_glyph_index;
        TT_UShort last_glyph_index;
 
 
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
 
 
        /* Fill up the fields */
        /* Fill up the fields */
        pfontinfo->height = (((properties.horizontal->Ascender * \
        pfontinfo->height = (((properties.horizontal->Ascender * \
                                imetrics.y_scale)/ 0x10000) >> 6) -
                                imetrics.y_scale)/ 0x10000) >> 6) -
                            (((properties.horizontal->Descender * \
                            (((properties.horizontal->Descender * \
                                imetrics.y_scale)/ 0x10000) >> 6);
                                imetrics.y_scale)/ 0x10000) >> 6);
        pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
        pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
                                imetrics.x_scale)/ 0x10000) >> 6;
                                imetrics.x_scale)/ 0x10000) >> 6;
        pfontinfo->baseline = ((properties.horizontal->Ascender * \
        pfontinfo->baseline = ((properties.horizontal->Ascender * \
                                imetrics.y_scale)/ 0x10000) >> 6;
                                imetrics.y_scale)/ 0x10000) >> 6;
        pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
        pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
        pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
        pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
        pfontinfo->fixed = properties.postscript->isFixedPitch;
        pfontinfo->fixed = properties.postscript->isFixedPitch;
 
 
        last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
        last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
 
 
        /* Doesn't work ... don't know why ....*/
        /* Doesn't work ... don't know why ....*/
#if 0
#if 0
        if (TT_Get_Face_Widths( pf->face, 0,
        if (TT_Get_Face_Widths( pf->face, 0,
                                last_glyph_index, widths, NULL ) != TT_Err_Ok) {
                                last_glyph_index, widths, NULL ) != TT_Err_Ok) {
          return TRUE;
          return TRUE;
        }
        }
 
 
        for(i=0; i<=last_glyph_index; i++)
        for(i=0; i<=last_glyph_index; i++)
          DPRINTF("widths[%d]: %d\n", i, widths[i]);
          DPRINTF("widths[%d]: %d\n", i, widths[i]);
#endif
#endif
 
 
        /* Get glyphs widths */
        /* Get glyphs widths */
        for(i=0; i<=last_glyph_index; i++)
        for(i=0; i<=last_glyph_index; i++)
          pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
          pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
 
 
#if 0
#if 0
        DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
        DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
    x_resolution: %d\ny_resolution: %d\n",
    x_resolution: %d\ny_resolution: %d\n",
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
 
 
    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
    Postscript Say monospaced?: %d\n",\
    Postscript Say monospaced?: %d\n",\
    properties.horizontal->Ascender,
    properties.horizontal->Ascender,
    properties.horizontal->Descender,
    properties.horizontal->Descender,
    properties.horizontal->xMax_Extent,
    properties.horizontal->xMax_Extent,
    (properties.header->Mac_Style & 0x2)?1:0,
    (properties.header->Mac_Style & 0x2)?1:0,
    (properties.header->Mac_Style & 0x1)?1:0,
    (properties.header->Mac_Style & 0x1)?1:0,
    properties.os2->sTypoAscender,
    properties.os2->sTypoAscender,
    properties.os2->sTypoDescender,
    properties.os2->sTypoDescender,
    properties.os2->usWinAscent,
    properties.os2->usWinAscent,
    properties.os2->usWinDescent,
    properties.os2->usWinDescent,
    properties.os2->usFirstCharIndex,
    properties.os2->usFirstCharIndex,
    properties.os2->usLastCharIndex,
    properties.os2->usLastCharIndex,
    (properties.os2->fsSelection & 0x1)?1:0,
    (properties.os2->fsSelection & 0x1)?1:0,
    (properties.os2->fsSelection & 0x20)?1:0,
    (properties.os2->fsSelection & 0x20)?1:0,
    properties.postscript->isFixedPitch,
    properties.postscript->isFixedPitch,
    (properties.os2->panose[3] == 9)?1:0);
    (properties.os2->panose[3] == 9)?1:0);
#endif  
#endif  
 
 
        return TRUE;
        return TRUE;
}
}
 
 
static void
static void
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
{
{
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        const unsigned short *  str = text;
        const unsigned short *  str = text;
        TT_F26Dot6      x = 0;
        TT_F26Dot6      x = 0;
        int             i;
        int             i;
        TT_UShort       curchar;
        TT_UShort       curchar;
        TT_Glyph_Metrics metrics;
        TT_Glyph_Metrics metrics;
        TT_Face_Properties      properties;
        TT_Face_Properties      properties;
        TT_Instance_Metrics imetrics;
        TT_Instance_Metrics imetrics;
 
 
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
 
 
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_pen_pos = -32767;
        pf->last_pen_pos = -32767;
 
 
        for (i = 0; i < cc; i++) {
        for (i = 0; i < cc; i++) {
                curchar = TT_Char_Index (pf->char_map, str[i]);
                curchar = TT_Char_Index (pf->char_map, str[i]);
 
 
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                                continue;
                                continue;
 
 
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
 
 
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
                                x += compute_kernval(pf, curchar) / 64;
                                x += compute_kernval(pf, curchar) / 64;
                }
                }
 
 
                x += metrics.advance / 64;
                x += metrics.advance / 64;
 
 
                /* Kerning point syndrome avoidance */
                /* Kerning point syndrome avoidance */
                if (pf->last_pen_pos > x)
                if (pf->last_pen_pos > x)
                        x = pf->last_pen_pos;
                        x = pf->last_pen_pos;
                pf->last_pen_pos = x;
                pf->last_pen_pos = x;
 
 
                pf->last_glyph_code = curchar;
                pf->last_glyph_code = curchar;
        }
        }
 
 
        *pwidth = x;
        *pwidth = x;
        *pheight =  (((properties.horizontal->Ascender *
        *pheight =  (((properties.horizontal->Ascender *
                        imetrics.y_scale)/ 0x10000) >> 6) -
                        imetrics.y_scale)/ 0x10000) >> 6) -
                    (((properties.horizontal->Descender *
                    (((properties.horizontal->Descender *
                    imetrics.y_scale)/ 0x10000) >> 6);
                    imetrics.y_scale)/ 0x10000) >> 6);
        /* FIXME: is it what's required ?? */
        /* FIXME: is it what's required ?? */
        *pbase = (((-properties.horizontal->Descender) *
        *pbase = (((-properties.horizontal->Descender) *
                    imetrics.y_scale)/ 0x10000) >> 6;
                    imetrics.y_scale)/ 0x10000) >> 6;
}
}
 
 
static void
static void
freetype_destroyfont(PMWFONT pfont)
freetype_destroyfont(PMWFONT pfont)
{
{
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
 
 
        TT_Close_Face(pf->face);
        TT_Close_Face(pf->face);
 
 
        /*----------*/
        /*----------*/
 
 
        if (pf->glyph_cache != 0)
        if (pf->glyph_cache != 0)
          free_cache_glyph(pf->glyph_cache);
          free_cache_glyph(pf->glyph_cache);
 
 
        /*----------*/
        /*----------*/
 
 
        free(pf);
        free(pf);
}
}
 
 
static void
static void
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
{
{
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
 
 
        pf->fontsize = fontsize;
        pf->fontsize = fontsize;
 
 
        /* We want real pixel sizes ... not points ...*/
        /* We want real pixel sizes ... not points ...*/
        TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
        TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
                                pf->fontsize, pf->fontsize * 64 );
                                pf->fontsize, pf->fontsize * 64 );
#if 0
#if 0
        /* set charsize (convert to points for freetype)*/
        /* set charsize (convert to points for freetype)*/
        TT_Set_Instance_CharSize (pf->instance,
        TT_Set_Instance_CharSize (pf->instance,
                ((pf->fontsize * 72 + 96/2) / 96) * 64);
                ((pf->fontsize * 72 + 96/2) / 96) * 64);
#endif
#endif
}
}
 
 
static void
static void
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
{
{
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        float           angle;
        float           angle;
 
 
        pf->fontrotation = tenthdegrees;
        pf->fontrotation = tenthdegrees;
 
 
        /* Build the rotation matrix with the given angle */
        /* Build the rotation matrix with the given angle */
        TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
        TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
 
 
        angle = pf->fontrotation * M_PI / 1800;
        angle = pf->fontrotation * M_PI / 1800;
        pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
        pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
        pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
        pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
        pf->matrix.xx = pf->matrix.yy;
        pf->matrix.xx = pf->matrix.yy;
        pf->matrix.xy = -pf->matrix.yx;
        pf->matrix.xy = -pf->matrix.yx;
}
}
 
 
#endif /* HAVE_FREETYPE_SUPPORT*/
#endif /* HAVE_FREETYPE_SUPPORT*/
 
 
/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
 * On the other hand, if the UTF-8 string contains surrogate values, this
 * On the other hand, if the UTF-8 string contains surrogate values, this
 * is considered an error and returned as such.
 * is considered an error and returned as such.
 *
 *
 * The destination array must be able to hold as many Unicode-16 characters
 * The destination array must be able to hold as many Unicode-16 characters
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
 * characters are ASCII characters.  No more will be needed.
 * characters are ASCII characters.  No more will be needed.
 *
 *
 * Copyright (c) 2000 Morten Rolland, Screen Media
 * Copyright (c) 2000 Morten Rolland, Screen Media
 */
 */
static int
static int
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
{
{
        int count = 0;
        int count = 0;
        unsigned char c0, c1;
        unsigned char c0, c1;
        unsigned long scalar;
        unsigned long scalar;
 
 
        while(--cc >= 0) {
        while(--cc >= 0) {
                c0 = *utf8++;
                c0 = *utf8++;
                /*DPRINTF("Trying: %02x\n",c0);*/
                /*DPRINTF("Trying: %02x\n",c0);*/
 
 
                if ( c0 < 0x80 ) {
                if ( c0 < 0x80 ) {
                        /* Plain ASCII character, simple translation :-) */
                        /* Plain ASCII character, simple translation :-) */
                        *unicode16++ = c0;
                        *unicode16++ = c0;
                        count++;
                        count++;
                        continue;
                        continue;
                }
                }
 
 
                if ( (c0 & 0xc0) == 0x80 )
                if ( (c0 & 0xc0) == 0x80 )
                        /* Illegal; starts with 10xxxxxx */
                        /* Illegal; starts with 10xxxxxx */
                        return -1;
                        return -1;
 
 
                /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
                /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
                scalar = c0;
                scalar = c0;
                if(--cc < 0)
                if(--cc < 0)
                        return -1;
                        return -1;
                c1 = *utf8++;
                c1 = *utf8++;
                /*DPRINTF("c1=%02x\n",c1);*/
                /*DPRINTF("c1=%02x\n",c1);*/
                if ( (c1 & 0xc0) != 0x80 )
                if ( (c1 & 0xc0) != 0x80 )
                        /* Bad byte */
                        /* Bad byte */
                        return -1;
                        return -1;
                scalar <<= 6;
                scalar <<= 6;
                scalar |= (c1 & 0x3f);
                scalar |= (c1 & 0x3f);
 
 
                if ( !(c0 & 0x20) ) {
                if ( !(c0 & 0x20) ) {
                        /* Two bytes UTF-8 */
                        /* Two bytes UTF-8 */
                        if ( scalar < 0x80 )
                        if ( scalar < 0x80 )
                                return -1;      /* Overlong encoding */
                                return -1;      /* Overlong encoding */
                        *unicode16++ = scalar & 0x7ff;
                        *unicode16++ = scalar & 0x7ff;
                        count++;
                        count++;
                        continue;
                        continue;
                }
                }
 
 
                /* c0 must be 111xxxxx if we get here => at least 3 bytes */
                /* c0 must be 111xxxxx if we get here => at least 3 bytes */
                if(--cc < 0)
                if(--cc < 0)
                        return -1;
                        return -1;
                c1 = *utf8++;
                c1 = *utf8++;
                /*DPRINTF("c1=%02x\n",c1);*/
                /*DPRINTF("c1=%02x\n",c1);*/
                if ( (c1 & 0xc0) != 0x80 )
                if ( (c1 & 0xc0) != 0x80 )
                        /* Bad byte */
                        /* Bad byte */
                        return -1;
                        return -1;
                scalar <<= 6;
                scalar <<= 6;
                scalar |= (c1 & 0x3f);
                scalar |= (c1 & 0x3f);
 
 
                if ( !(c0 & 0x10) ) {
                if ( !(c0 & 0x10) ) {
                        /*DPRINTF("####\n");*/
                        /*DPRINTF("####\n");*/
                        /* Three bytes UTF-8 */
                        /* Three bytes UTF-8 */
                        if ( scalar < 0x800 )
                        if ( scalar < 0x800 )
                                return -1;      /* Overlong encoding */
                                return -1;      /* Overlong encoding */
                        if ( scalar >= 0xd800 && scalar < 0xe000 )
                        if ( scalar >= 0xd800 && scalar < 0xe000 )
                                return -1;      /* UTF-16 high/low halfs */
                                return -1;      /* UTF-16 high/low halfs */
                        *unicode16++ = scalar & 0xffff;
                        *unicode16++ = scalar & 0xffff;
                        count++;
                        count++;
                        continue;
                        continue;
                }
                }
 
 
                /* c0 must be 1111xxxx if we get here => at least 4 bytes */
                /* c0 must be 1111xxxx if we get here => at least 4 bytes */
                c1 = *utf8++;
                c1 = *utf8++;
                if(--cc < 0)
                if(--cc < 0)
                        return -1;
                        return -1;
                /*DPRINTF("c1=%02x\n",c1);*/
                /*DPRINTF("c1=%02x\n",c1);*/
                if ( (c1 & 0xc0) != 0x80 )
                if ( (c1 & 0xc0) != 0x80 )
                        /* Bad byte */
                        /* Bad byte */
                        return -1;
                        return -1;
                scalar <<= 6;
                scalar <<= 6;
                scalar |= (c1 & 0x3f);
                scalar |= (c1 & 0x3f);
 
 
                if ( !(c0 & 0x08) ) {
                if ( !(c0 & 0x08) ) {
                        /* Four bytes UTF-8, needs encoding as surrogates */
                        /* Four bytes UTF-8, needs encoding as surrogates */
                        if ( scalar < 0x10000 )
                        if ( scalar < 0x10000 )
                                return -1;      /* Overlong encoding */
                                return -1;      /* Overlong encoding */
                        scalar -= 0x10000;
                        scalar -= 0x10000;
                        *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
                        *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
                        *unicode16++ = (scalar & 0x3ff) + 0xdc00;
                        *unicode16++ = (scalar & 0x3ff) + 0xdc00;
                        count += 2;
                        count += 2;
                        continue;
                        continue;
                }
                }
 
 
                return -1;      /* No support for more than four byte UTF-8 */
                return -1;      /* No support for more than four byte UTF-8 */
        }
        }
        return count;
        return count;
}
}
 
 
#if HAVE_HZK_SUPPORT
#if HAVE_HZK_SUPPORT
 
 
/* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
/* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
 * a single 2-byte UC16 character is encoded into a surrogate pair.
 * a single 2-byte UC16 character is encoded into a surrogate pair.
 * return -1 ,if error;
 * return -1 ,if error;
 * The destination array must be able to hold as many
 * The destination array must be able to hold as many
 * as there are Unicode-16 characters.
 * as there are Unicode-16 characters.
 *
 *
 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
 */
 */
static int
static int
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
{
{
        FILE* fp;
        FILE* fp;
        char buffer[256];
        char buffer[256];
        unsigned char *uc16p;
        unsigned char *uc16p;
        int i=0,j=0, k;
        int i=0,j=0, k;
        unsigned char *filebuffer;
        unsigned char *filebuffer;
        unsigned short *uc16pp,*table;
        unsigned short *uc16pp,*table;
        unsigned short uc16px;
        unsigned short uc16px;
        int length=31504;
        int length=31504;
 
 
        if (use_big5)
        if (use_big5)
                length=54840;
                length=54840;
 
 
        uc16p=(unsigned char *) uc16;
        uc16p=(unsigned char *) uc16;
        uc16pp=(unsigned short *) uc16;
        uc16pp=(unsigned short *) uc16;
 
 
        strcpy(buffer,HZK_FONT_DIR);
        strcpy(buffer,HZK_FONT_DIR);
        if (use_big5)
        if (use_big5)
                strcat(buffer,"/BG2UBG.KU");
                strcat(buffer,"/BG2UBG.KU");
        else
        else
                strcat(buffer,"/UGB2GB.KU");
                strcat(buffer,"/UGB2GB.KU");
        if(!(fp = fopen(buffer, "rb")))
        if(!(fp = fopen(buffer, "rb")))
        {
        {
                 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
                 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
                 return -1;
                 return -1;
        }
        }
 
 
        filebuffer= (unsigned char *)malloc ( length);
        filebuffer= (unsigned char *)malloc ( length);
 
 
        if(fread(filebuffer, sizeof(char),length, fp) < length) {
        if(fread(filebuffer, sizeof(char),length, fp) < length) {
                  fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
                  fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
                  fclose(fp);
                  fclose(fp);
                  return -1;
                  return -1;
        }
        }
        fclose(fp);
        fclose(fp);
 
 
        if (use_big5)
        if (use_big5)
        {
        {
                table=(unsigned short *)filebuffer;
                table=(unsigned short *)filebuffer;
                while(1)
                while(1)
                {
                {
                        if(j>=cc)
                        if(j>=cc)
                        {
                        {
                                ascii[i]=0;
                                ascii[i]=0;
                                break;
                                break;
                        }
                        }
                        uc16px=*uc16pp;
                        uc16px=*uc16pp;
                        if((uc16px)<=0x00ff)
                        if((uc16px)<=0x00ff)
                        {
                        {
                                ascii[i]=(char)(*uc16pp);
                                ascii[i]=(char)(*uc16pp);
                                i++;
                                i++;
                        }
                        }
                        else
                        else
                        {
                        {
                                ascii[i]=0xa1; ascii[i+1]=0x40;
                                ascii[i]=0xa1; ascii[i+1]=0x40;
                                for (k=0; k<13710; k++)
                                for (k=0; k<13710; k++)
                                {
                                {
                                        if (*(table+(k*2+1))==(uc16px))
                                        if (*(table+(k*2+1))==(uc16px))
                                        {
                                        {
                                                ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
                                                ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
                                                ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
                                                ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
                                                break;
                                                break;
                                        }
                                        }
                                }
                                }
                                i+=2;
                                i+=2;
                        }
                        }
                        uc16pp++; j++;
                        uc16pp++; j++;
                }
                }
        }
        }
        else
        else
        {
        {
        while(1)
        while(1)
        {
        {
                if(j>=cc)
                if(j>=cc)
                {
                {
                        ascii[i]=0;
                        ascii[i]=0;
                        break;
                        break;
                }
                }
                if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
                if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
                {
                {
                        ascii[i]=0;
                        ascii[i]=0;
                        break;
                        break;
                }
                }
                else
                else
                {
                {
                        if(*((uc16p)+j+1)==0)
                        if(*((uc16p)+j+1)==0)
                        {
                        {
                                ascii[i]=*((uc16p)+j);
                                ascii[i]=*((uc16p)+j);
                                i++;
                                i++;
                                j+=2;
                                j+=2;
                        }
                        }
                        else
                        else
                        {
                        {
                        /*       to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
                        /*       to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
                        {
                        {
                                int p1=0,p2=length-4,p;
                                int p1=0,p2=length-4,p;
                                unsigned int c1,c2,c,d;
                                unsigned int c1,c2,c,d;
                                c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
                                c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
                                c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
                                c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
                                d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
                                d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
                                if(c1==d)
                                if(c1==d)
                                {
                                {
                                        ascii[i]=filebuffer[p1+2];
                                        ascii[i]=filebuffer[p1+2];
                                        ascii[i+1]=filebuffer[p1+3];
                                        ascii[i+1]=filebuffer[p1+3];
                                        goto findit;
                                        goto findit;
                                }
                                }
                                if(c2==d)
                                if(c2==d)
                                {
                                {
                                        ascii[i]=filebuffer[p2+2];
                                        ascii[i]=filebuffer[p2+2];
                                        ascii[i+1]=filebuffer[p2+3];
                                        ascii[i+1]=filebuffer[p2+3];
                                        goto findit;
                                        goto findit;
                                }
                                }
                                while(1)
                                while(1)
                                {
                                {
                                        p=(((p2-p1)/2+p1)>>2)<<2;
                                        p=(((p2-p1)/2+p1)>>2)<<2;
                                        c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
                                        c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
                                        if(d==c)        /*find it*/
                                        if(d==c)        /*find it*/
                                        {
                                        {
                                                ascii[i]=filebuffer[p+2];
                                                ascii[i]=filebuffer[p+2];
                                                ascii[i+1]=filebuffer[p+3];
                                                ascii[i+1]=filebuffer[p+3];
                                                break;
                                                break;
                                        }
                                        }
                                        else if(p2<=p1+4) /*can't find.*/
                                        else if(p2<=p1+4) /*can't find.*/
                                        {
                                        {
                                                ascii[i]='.';/*((uc16p)+j);*/
                                                ascii[i]='.';/*((uc16p)+j);*/
                                                ascii[i+1]='.';/*((uc16p)+j+1);*/
                                                ascii[i+1]='.';/*((uc16p)+j+1);*/
                                                break;
                                                break;
                                        }
                                        }
                                        else if(d<c)
                                        else if(d<c)
                                        {
                                        {
                                                p2=p;
                                                p2=p;
                                                c2=c;
                                                c2=c;
                                        }
                                        }
                                        else
                                        else
                                        {
                                        {
                                                p1=p;
                                                p1=p;
                                                c1=c;
                                                c1=c;
                                        }
                                        }
                                }
                                }
                        }
                        }
                        findit:
                        findit:
                        i+=2;
                        i+=2;
                        j+=2;
                        j+=2;
                        }
                        }
                }
                }
        }
        }
        }
        }
        free(filebuffer);
        free(filebuffer);
 
 
        return i;
        return i;
}
}
 
 
/************************** functions definition ******************************/
/************************** functions definition ******************************/
 
 
static int hzk_id( PMWHZKFONT pf )
static int hzk_id( PMWHZKFONT pf )
{
{
        switch(pf->font_height)
        switch(pf->font_height)
        {
        {
        case 12:
        case 12:
                return 0;
                return 0;
        case 16: default:
        case 16: default:
                return 1;
                return 1;
        }
        }
}
}
 
 
/* This function get Chinese font info from etc file.*/
/* This function get Chinese font info from etc file.*/
static MWBOOL GetCFontInfo( PMWHZKFONT pf )
static MWBOOL GetCFontInfo( PMWHZKFONT pf )
{
{
        int charset;
        int charset;
 
 
        if (use_big5)
        if (use_big5)
                charset=(13094+408);
                charset=(13094+408);
        else
        else
                charset=8178;
                charset=8178;
 
 
        CFont[hzk_id(pf)].width = pf->cfont_width;
        CFont[hzk_id(pf)].width = pf->cfont_width;
        pf->CFont.width = pf->cfont_width;
        pf->CFont.width = pf->cfont_width;
 
 
        CFont[hzk_id(pf)].height = pf->font_height;
        CFont[hzk_id(pf)].height = pf->font_height;
        pf->CFont.height = pf->font_height;
        pf->CFont.height = pf->font_height;
 
 
        CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
        CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
                pf->CFont.height * charset;
                pf->CFont.height * charset;
        pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
        pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
 
 
        if(pf->CFont.size < charset * 8)
        if(pf->CFont.size < charset * 8)
                return FALSE;
                return FALSE;
 
 
        strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
        strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
        strcpy(pf->CFont.file,HZK_FONT_DIR);
        strcpy(pf->CFont.file,HZK_FONT_DIR);
 
 
        if(pf->font_height==16)
        if(pf->font_height==16)
        {
        {
                strcat(CFont[hzk_id(pf)].file,"/hzk16");
                strcat(CFont[hzk_id(pf)].file,"/hzk16");
                strcat(pf->CFont.file,"/hzk16");
                strcat(pf->CFont.file,"/hzk16");
        }
        }
        else
        else
        {
        {
                strcat(CFont[hzk_id(pf)].file,"/hzk12");
                strcat(CFont[hzk_id(pf)].file,"/hzk12");
                strcat(pf->CFont.file,"/hzk12");
                strcat(pf->CFont.file,"/hzk12");
        }
        }
 
 
        if (use_big5)
        if (use_big5)
        {
        {
                CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
                CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
                pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
                pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
        }
        }
 
 
        return TRUE;
        return TRUE;
}
}
 
 
/* This function get ASCII font info from etc file.*/
/* This function get ASCII font info from etc file.*/
static MWBOOL GetAFontInfo( PMWHZKFONT pf )
static MWBOOL GetAFontInfo( PMWHZKFONT pf )
{
{
        AFont[hzk_id(pf)].width = pf->afont_width;
        AFont[hzk_id(pf)].width = pf->afont_width;
        pf->AFont.width = pf->afont_width;
        pf->AFont.width = pf->afont_width;
 
 
        AFont[hzk_id(pf)].height = pf->font_height;
        AFont[hzk_id(pf)].height = pf->font_height;
        pf->AFont.height = pf->font_height;
        pf->AFont.height = pf->font_height;
 
 
        AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
        AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
                pf->AFont.height * 255;
                pf->AFont.height * 255;
        pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
        pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
 
 
        if(pf->AFont.size < 255 * 8)
        if(pf->AFont.size < 255 * 8)
                return FALSE;
                return FALSE;
 
 
        strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
        strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
        strcpy(pf->AFont.file,HZK_FONT_DIR);
        strcpy(pf->AFont.file,HZK_FONT_DIR);
 
 
        if(pf->font_height==16)
        if(pf->font_height==16)
        {
        {
                strcat(AFont[hzk_id(pf)].file,"/asc16");
                strcat(AFont[hzk_id(pf)].file,"/asc16");
                strcat(pf->AFont.file,"/asc16");
                strcat(pf->AFont.file,"/asc16");
        }
        }
        else
        else
        {
        {
                strcat(AFont[hzk_id(pf)].file,"/asc12");
                strcat(AFont[hzk_id(pf)].file,"/asc12");
                strcat(pf->AFont.file,"/asc12");
                strcat(pf->AFont.file,"/asc12");
        }
        }
        return TRUE;
        return TRUE;
}
}
 
 
/* This function load system font into memory.*/
/* This function load system font into memory.*/
static MWBOOL LoadFont( PMWHZKFONT pf )
static MWBOOL LoadFont( PMWHZKFONT pf )
{
{
        FILE* fp;
        FILE* fp;
 
 
        if(!GetCFontInfo(pf))
        if(!GetCFontInfo(pf))
        {
        {
                fprintf (stderr, "Get Chinese HZK font info failure!\n");
                fprintf (stderr, "Get Chinese HZK font info failure!\n");
                return FALSE;
                return FALSE;
        }
        }
        if(CFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
        if(CFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
        {
        {
 
 
 
 
                /* Allocate system memory for Chinese font.*/
                /* Allocate system memory for Chinese font.*/
                if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
                if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
                {
                {
                        fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
                        fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
                        return FALSE;
                        return FALSE;
                }
                }
 
 
                /* Open font file and read information to the system memory.*/
                /* Open font file and read information to the system memory.*/
                fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
                fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
                if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
                if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
                {
                {
                        fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
                        fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
                        return FALSE;
                        return FALSE;
                }
                }
                if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
                if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
                {
                {
                        fprintf (stderr, "Error in reading Chinese HZK font file!\n");
                        fprintf (stderr, "Error in reading Chinese HZK font file!\n");
                        fclose(fp);
                        fclose(fp);
                        return FALSE;
                        return FALSE;
                }
                }
 
 
                fclose(fp);
                fclose(fp);
 
 
                CFont[hzk_id(pf)].use_count=0;
                CFont[hzk_id(pf)].use_count=0;
 
 
                fprintf (stderr, "done.\n" );
                fprintf (stderr, "done.\n" );
 
 
        }
        }
        cfont_address = CFont[hzk_id(pf)].pFont;
        cfont_address = CFont[hzk_id(pf)].pFont;
        pf->cfont_address = CFont[hzk_id(pf)].pFont;
        pf->cfont_address = CFont[hzk_id(pf)].pFont;
        pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
        pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
 
 
        CFont[hzk_id(pf)].use_count++;
        CFont[hzk_id(pf)].use_count++;
 
 
        if(!GetAFontInfo(pf))
        if(!GetAFontInfo(pf))
        {
        {
               fprintf (stderr, "Get ASCII HZK font info failure!\n");
               fprintf (stderr, "Get ASCII HZK font info failure!\n");
               return FALSE;
               return FALSE;
        }
        }
        if(AFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
        if(AFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
        {
        {
 
 
 
 
                /* Allocate system memory for ASCII font.*/
                /* Allocate system memory for ASCII font.*/
                if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
                if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
                {
                {
                        fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
                        fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
                        free(CFont[hzk_id(pf)].pFont);
                        free(CFont[hzk_id(pf)].pFont);
                        CFont[hzk_id(pf)].pFont = NULL;
                        CFont[hzk_id(pf)].pFont = NULL;
                        return FALSE;
                        return FALSE;
                }
                }
 
 
                /* Load ASCII font information to the near memory.*/
                /* Load ASCII font information to the near memory.*/
                fprintf (stderr, "Loading ASCII HZK font..." );
                fprintf (stderr, "Loading ASCII HZK font..." );
                if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
                if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
                {
                {
                        fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
                        fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
                        return FALSE;
                        return FALSE;
                }
                }
                if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
                if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
                {
                {
                        fprintf (stderr, "Error in reading ASCII HZK font file!\n");
                        fprintf (stderr, "Error in reading ASCII HZK font file!\n");
                        fclose(fp);
                        fclose(fp);
                        return FALSE;
                        return FALSE;
                }
                }
 
 
                fclose(fp);
                fclose(fp);
 
 
                AFont[hzk_id(pf)].use_count=0;
                AFont[hzk_id(pf)].use_count=0;
 
 
                fprintf (stderr, "done.\n" );
                fprintf (stderr, "done.\n" );
 
 
        }
        }
        afont_address = AFont[hzk_id(pf)].pFont;
        afont_address = AFont[hzk_id(pf)].pFont;
        pf->afont_address = AFont[hzk_id(pf)].pFont;
        pf->afont_address = AFont[hzk_id(pf)].pFont;
        pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
        pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
 
 
        AFont[hzk_id(pf)].use_count++;
        AFont[hzk_id(pf)].use_count++;
 
 
        return TRUE;
        return TRUE;
}
}
 
 
/* This function unload system font from memory.*/
/* This function unload system font from memory.*/
static void UnloadFont( PMWHZKFONT pf )
static void UnloadFont( PMWHZKFONT pf )
{
{
        CFont[hzk_id(pf)].use_count--;
        CFont[hzk_id(pf)].use_count--;
        AFont[hzk_id(pf)].use_count--;
        AFont[hzk_id(pf)].use_count--;
 
 
        if (!CFont[hzk_id(pf)].use_count)
        if (!CFont[hzk_id(pf)].use_count)
        {
        {
                free(pf->CFont.pFont);
                free(pf->CFont.pFont);
                free(pf->AFont.pFont);
                free(pf->AFont.pFont);
 
 
                CFont[hzk_id(pf)].pFont = NULL;
                CFont[hzk_id(pf)].pFont = NULL;
                AFont[hzk_id(pf)].pFont = NULL;
                AFont[hzk_id(pf)].pFont = NULL;
        }
        }
}
}
 
 
static int
static int
hzk_init(PSD psd)
hzk_init(PSD psd)
{
{
        /* FIXME: *.KU file should be opened and
        /* FIXME: *.KU file should be opened and
         * read in here...*/
         * read in here...*/
        return 1;
        return 1;
}
}
 
 
static PMWHZKFONT
static PMWHZKFONT
hzk_createfont(const char *name, MWCOORD height, int attr)
hzk_createfont(const char *name, MWCOORD height, int attr)
{
{
        PMWHZKFONT      pf;
        PMWHZKFONT      pf;
 
 
        if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
        if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
                return FALSE;
                return FALSE;
 
 
printf("hzk_createfont(%s,%d)\n",name,height);
printf("hzk_createfont(%s,%d)\n",name,height);
 
 
        use_big5=name[2]-'K';
        use_big5=name[2]-'K';
 
 
        /* allocate font structure*/
        /* allocate font structure*/
        pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
        pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
        if (!pf)
        if (!pf)
                return NULL;
                return NULL;
        pf->fontprocs = &hzk_procs;
        pf->fontprocs = &hzk_procs;
 
 
        pf->fontsize=height;
        pf->fontsize=height;
        /*GdSetFontSize((PMWFONT)pf, height);*/
        /*GdSetFontSize((PMWFONT)pf, height);*/
        GdSetFontRotation((PMWFONT)pf, 0);
        GdSetFontRotation((PMWFONT)pf, 0);
        GdSetFontAttr((PMWFONT)pf, attr, 0);
        GdSetFontAttr((PMWFONT)pf, attr, 0);
 
 
        if(height==12)
        if(height==12)
        {
        {
                afont_width = 6;
                afont_width = 6;
                cfont_width = 12;
                cfont_width = 12;
                font_height = 12;
                font_height = 12;
 
 
                pf->afont_width = 6;
                pf->afont_width = 6;
                pf->cfont_width = 12;
                pf->cfont_width = 12;
                pf->font_height = 12;
                pf->font_height = 12;
        }
        }
        else
        else
        {
        {
                afont_width = 8;
                afont_width = 8;
                cfont_width = 16;
                cfont_width = 16;
                font_height = 16;
                font_height = 16;
 
 
                pf->afont_width = 8;
                pf->afont_width = 8;
                pf->cfont_width = 16;
                pf->cfont_width = 16;
                pf->font_height = 16;
                pf->font_height = 16;
        }
        }
 
 
        /* Load the font library to the system memory.*/
        /* Load the font library to the system memory.*/
        if(!LoadFont(pf))
        if(!LoadFont(pf))
                return FALSE;
                return FALSE;
 
 
        return pf;
        return pf;
}
}
 
 
int IsBig5(int i)
int IsBig5(int i)
{
{
        if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
        if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
            (i>=0xa440 && i<=0xc67e) || /* a440-c67e        */
            (i>=0xa440 && i<=0xc67e) || /* a440-c67e        */
            (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
            (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
            (i>=0xc940 && i<=0xf9fe))   /* c940-f9fe        */
            (i>=0xc940 && i<=0xf9fe))   /* c940-f9fe        */
                return 1;
                return 1;
        else
        else
                return 0;
                return 0;
}
}
 
 
/*
/*
 * following several function is used in hzk_drawtext
 * following several function is used in hzk_drawtext
 */
 */
 
 
static int getnextchar(char* s, unsigned char* cc)
static int getnextchar(char* s, unsigned char* cc)
{
{
        if( s[0] == '\0') return 0;
        if( s[0] == '\0') return 0;
 
 
        cc[0] = (unsigned char)(*s);
        cc[0] = (unsigned char)(*s);
        cc[1] = (unsigned char)(*(s + 1));
        cc[1] = (unsigned char)(*(s + 1));
 
 
        if (use_big5)
        if (use_big5)
        {
        {
                if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
                if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
                        return 1;
                        return 1;
        }
        }
        else
        else
        {
        {
                if( ((unsigned char)cc[0] > 0xa0) &&
                if( ((unsigned char)cc[0] > 0xa0) &&
                    ((unsigned char)cc[1] > 0xa0) )
                    ((unsigned char)cc[1] > 0xa0) )
                        return 1;
                        return 1;
        }
        }
 
 
        cc[1] = '\0';
        cc[1] = '\0';
 
 
        return 1;
        return 1;
}
}
 
 
static void
static void
expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
{
{
        int i=0;
        int i=0;
        int c1, c2, seq;
        int c1, c2, seq;
        int x,y;
        int x,y;
        unsigned char *font;
        unsigned char *font;
        int b = 0;               /* keep gcc happy with b = 0 - MW */
        int b = 0;               /* keep gcc happy with b = 0 - MW */
 
 
        int pixelsize;
        int pixelsize;
        pixelsize=sizeof(MWPIXELVAL);
        pixelsize=sizeof(MWPIXELVAL);
 
 
        c1 = c[0];
        c1 = c[0];
        c2 = c[1];
        c2 = c[1];
        if (use_big5)
        if (use_big5)
        {
        {
                seq=0;
                seq=0;
                /*ladd=loby-(if(loby<127)?64:98)*/
                /*ladd=loby-(if(loby<127)?64:98)*/
                c2-=(c2<127?64:98);
                c2-=(c2<127?64:98);
 
 
                /*hadd=(hiby-164)*157*/
                /*hadd=(hiby-164)*157*/
                if (c1>=0xa4)/*standard font*/
                if (c1>=0xa4)/*standard font*/
                {
                {
                        seq=(((c1-164)*157)+c2);
                        seq=(((c1-164)*157)+c2);
                        if (seq>=5809) seq-=408;
                        if (seq>=5809) seq-=408;
                }
                }
 
 
                /*hadd=(hiby-161)*157*/
                /*hadd=(hiby-161)*157*/
                if (c1<=0xa3)/*special font*/
                if (c1<=0xa3)/*special font*/
                        seq=(((c1-161)*157)+c2)+13094;
                        seq=(((c1-161)*157)+c2)+13094;
        }
        }
        else
        else
                seq=((c1 - 161)*94 + c2 - 161);
                seq=((c1 - 161)*94 + c2 - 161);
 
 
        font = pf->cfont_address + ((seq) *
        font = pf->cfont_address + ((seq) *
                  (pf->font_height * ((pf->cfont_width + 7) / 8)));
                  (pf->font_height * ((pf->cfont_width + 7) / 8)));
 
 
        for (y = 0; y < pf->font_height; y++)
        for (y = 0; y < pf->font_height; y++)
                for (x = 0; x < pf->cfont_width; x++)
                for (x = 0; x < pf->cfont_width; x++)
                {
                {
                        if (x % 8 == 0)
                        if (x % 8 == 0)
                                b = *font++;
                                b = *font++;
 
 
                        if (b & (128 >> (x % 8)))   /* pixel */
                        if (b & (128 >> (x % 8)))   /* pixel */
                                bitmap[i++]=fg;
                                bitmap[i++]=fg;
                        else
                        else
                                bitmap[i++]=bg;
                                bitmap[i++]=bg;
                }
                }
}
}
 
 
static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
{
{
        int i=0;
        int i=0;
        int x,y;
        int x,y;
        unsigned char *font;
        unsigned char *font;
        int pixelsize;
        int pixelsize;
        int b = 0;               /* keep gcc happy with b = 0 - MW */
        int b = 0;               /* keep gcc happy with b = 0 - MW */
 
 
        pixelsize=sizeof(MWPIXELVAL);
        pixelsize=sizeof(MWPIXELVAL);
 
 
        font = pf->afont_address + c * (pf->font_height *
        font = pf->afont_address + c * (pf->font_height *
                ((pf->afont_width + 7) / 8));
                ((pf->afont_width + 7) / 8));
 
 
        for (y = 0; y < pf->font_height; y++)
        for (y = 0; y < pf->font_height; y++)
                for (x = 0; x < pf->afont_width; x++)
                for (x = 0; x < pf->afont_width; x++)
                {
                {
                        if (x % 8 == 0)
                        if (x % 8 == 0)
                                b = *font++;
                                b = *font++;
                        if (b & (128 >> (x % 8)))       /* pixel */
                        if (b & (128 >> (x % 8)))       /* pixel */
                                bitmap[i++]=fg;
                                bitmap[i++]=fg;
                        else
                        else
                                bitmap[i++]=bg;
                                bitmap[i++]=bg;
                }
                }
}
}
 
 
/*
/*
 * Draw ASCII text string using HZK type font
 * Draw ASCII text string using HZK type font
 */
 */
static void
static void
hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
        const void *text, int cc, int flags)
        const void *text, int cc, int flags)
{
{
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
 
 
        unsigned char c[2];
        unsigned char c[2];
        MWPIXELVAL *bitmap;
        MWPIXELVAL *bitmap;
        unsigned char s1[3];
        unsigned char s1[3];
        char *s,*sbegin;
        char *s,*sbegin;
 
 
        s=(char *)text;
        s=(char *)text;
 
 
        if(cc==1)
        if(cc==1)
        {
        {
                s1[0]=*((unsigned char*)text);
                s1[0]=*((unsigned char*)text);
                s1[1]=0x0;
                s1[1]=0x0;
                s1[2]=0x0;
                s1[2]=0x0;
                s=s1;
                s=s1;
        }
        }
 
 
        sbegin=s;
        sbegin=s;
        bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
        bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
                        sizeof(MWPIXELVAL));
                        sizeof(MWPIXELVAL));
 
 
        while( getnextchar(s, c) )
        while( getnextchar(s, c) )
        {
        {
                if( c[1] != '\0')
                if( c[1] != '\0')
                {
                {
                        expandcchar(pf, gr_background,gr_foreground,
                        expandcchar(pf, gr_background,gr_foreground,
                            c, bitmap);
                            c, bitmap);
                        /* Now draw the bitmap ... */
                        /* Now draw the bitmap ... */
 
 
                        if (flags&MWTF_TOP)
                        if (flags&MWTF_TOP)
                                GdArea(psd,ax, ay, pf->cfont_width,
                                GdArea(psd,ax, ay, pf->cfont_width,
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
                        else
                        else
                                GdArea(psd,ax, ay-pf->font_height+2,
                                GdArea(psd,ax, ay-pf->font_height+2,
                                        pf->cfont_width, pf->font_height,
                                        pf->cfont_width, pf->font_height,
                                        bitmap, MWPF_PIXELVAL);
                                        bitmap, MWPF_PIXELVAL);
 
 
                        s += 2;
                        s += 2;
                        ax += pf->cfont_width;
                        ax += pf->cfont_width;
                }
                }
                else
                else
                {
                {
                        expandchar(pf, gr_background,gr_foreground,
                        expandchar(pf, gr_background,gr_foreground,
                           c[0], bitmap);
                           c[0], bitmap);
                        /* Now draw the bitmap ... */
                        /* Now draw the bitmap ... */
 
 
                        if (flags&MWTF_TOP)
                        if (flags&MWTF_TOP)
                                GdArea(psd,ax, ay, pf->afont_width,
                                GdArea(psd,ax, ay, pf->afont_width,
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
                                        pf->font_height, bitmap, MWPF_PIXELVAL);
                        else
                        else
                                GdArea(psd,ax, ay-pf->font_height+2,
                                GdArea(psd,ax, ay-pf->font_height+2,
                                        pf->afont_width, pf->font_height,
                                        pf->afont_width, pf->font_height,
                                        bitmap, MWPF_PIXELVAL);
                                        bitmap, MWPF_PIXELVAL);
 
 
                        s += 1;
                        s += 1;
                        ax += pf->afont_width;
                        ax += pf->afont_width;
                }
                }
 
 
                if(s>=sbegin+cc)break;
                if(s>=sbegin+cc)break;
        }
        }
 
 
        FREEA(bitmap);
        FREEA(bitmap);
}
}
 
 
/*
/*
 * Return information about a specified font.
 * Return information about a specified font.
 */
 */
static MWBOOL
static MWBOOL
hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
{
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
 
 
        int i;
        int i;
 
 
        pfontinfo->height = pf->font_height;
        pfontinfo->height = pf->font_height;
        pfontinfo->maxwidth = pf->cfont_width;
        pfontinfo->maxwidth = pf->cfont_width;
        pfontinfo->baseline = pf->font_height-2;
        pfontinfo->baseline = pf->font_height-2;
        pfontinfo->firstchar = 0;
        pfontinfo->firstchar = 0;
        pfontinfo->lastchar = 0;
        pfontinfo->lastchar = 0;
        pfontinfo->fixed = TRUE;
        pfontinfo->fixed = TRUE;
 
 
        for(i=0; i<=256; i++)
        for(i=0; i<=256; i++)
                pfontinfo->widths[i] = pf->afont_width;
                pfontinfo->widths[i] = pf->afont_width;
 
 
        return TRUE;
        return TRUE;
}
}
 
 
static void
static void
hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
        MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
{
{
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
 
 
        unsigned char c[2];
        unsigned char c[2];
        char *s,*sbegin;
        char *s,*sbegin;
        unsigned char s1[3];
        unsigned char s1[3];
 
 
        int ax=0;
        int ax=0;
 
 
 
 
 
 
        s=(char *)text;
        s=(char *)text;
        if(cc==0)
        if(cc==0)
        {
        {
                *pwidth = 0;
                *pwidth = 0;
                *pheight = pf->font_height;
                *pheight = pf->font_height;
                *pbase = pf->font_height-2;
                *pbase = pf->font_height-2;
 
 
        }
        }
        if(cc==1)
        if(cc==1)
        {
        {
                s1[0]=*((unsigned char*)text);
                s1[0]=*((unsigned char*)text);
                s1[1]=0x0;
                s1[1]=0x0;
                s1[2]=0x0;
                s1[2]=0x0;
                s=s1;
                s=s1;
        }
        }
        sbegin=s;
        sbegin=s;
        while( getnextchar(s, c) )
        while( getnextchar(s, c) )
        {
        {
                if( c[1] != '\0')
                if( c[1] != '\0')
                {
                {
                        s += 2;
                        s += 2;
                        ax += pf->cfont_width;
                        ax += pf->cfont_width;
                }
                }
                else
                else
                {
                {
                        s += 1;
                        s += 1;
                        ax += pf->afont_width;
                        ax += pf->afont_width;
                }
                }
                if(s>=sbegin+cc)break;
                if(s>=sbegin+cc)break;
                /*      fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
                /*      fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
 
 
        }
        }
/*      fprintf(stderr,"ax=%d,\n",ax);*/
/*      fprintf(stderr,"ax=%d,\n",ax);*/
 
 
        *pwidth = ax;
        *pwidth = ax;
        *pheight = pf->font_height;
        *pheight = pf->font_height;
        *pbase = pf->font_height-2;
        *pbase = pf->font_height-2;
}
}
 
 
static void
static void
hzk_destroyfont(PMWFONT pfont)
hzk_destroyfont(PMWFONT pfont)
{
{
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
 
 
        UnloadFont(pf);
        UnloadFont(pf);
        free(pf);
        free(pf);
}
}
 
 
static void
static void
hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
{
{
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
        PMWHZKFONT pf=(PMWHZKFONT)pfont;
 
 
        /*jmt: hzk_setfontsize not supported*/
        /*jmt: hzk_setfontsize not supported*/
        /*jmt: & pf->fontsize can't be changed*/
        /*jmt: & pf->fontsize can't be changed*/
        /*jmt: because of hzk_id() :p*/
        /*jmt: because of hzk_id() :p*/
        pf->fontsize=pf->font_height;
        pf->fontsize=pf->font_height;
}
}
#endif /* HAVE_HZK_SUPPORT*/
#endif /* HAVE_HZK_SUPPORT*/
 
 
/* FIXME: this routine should work for all font renderers...*/
/* FIXME: this routine should work for all font renderers...*/
int
int
GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
        int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
        int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
        MWCOORD *pbase, int flags)
        MWCOORD *pbase, int flags)
{
{
#ifdef HAVE_FREETYPE_SUPPORT
#ifdef HAVE_FREETYPE_SUPPORT
        unsigned short  buf[256];
        unsigned short  buf[256];
        unsigned short* text;
        unsigned short* text;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
        int             defencoding = pf->fontprocs->encoding;
        int             defencoding = pf->fontprocs->encoding;
        int             x = 0;
        int             x = 0;
        int             i;
        int             i;
        TT_UShort       curchar;
        TT_UShort       curchar;
        TT_Glyph_Metrics metrics;
        TT_Glyph_Metrics metrics;
        TT_Face_Properties      properties;
        TT_Face_Properties      properties;
        TT_Instance_Metrics imetrics;
        TT_Instance_Metrics imetrics;
 
 
        if ((cc<0)||(!str))
        if ((cc<0)||(!str))
        {
        {
                *pwidth = *pheight = *pbase = 0;
                *pwidth = *pheight = *pbase = 0;
                return 0;
                return 0;
        }
        }
        /* convert encoding if required*/
        /* convert encoding if required*/
        if((flags & MWTF_PACKMASK) != defencoding)
        if((flags & MWTF_PACKMASK) != defencoding)
        {
        {
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
                flags &= ~MWTF_PACKMASK;
                flags &= ~MWTF_PACKMASK;
                flags |= defencoding;
                flags |= defencoding;
                text=buf;
                text=buf;
        } else text =(unsigned short*)str;
        } else text =(unsigned short*)str;
        if(cc <= 0)
        if(cc <= 0)
        {
        {
                *pwidth = *pheight = *pbase = 0;
                *pwidth = *pheight = *pbase = 0;
                return 0;
                return 0;
        }
        }
 
 
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Face_Properties (pf->face, &properties);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
        TT_Get_Instance_Metrics(pf->instance, &imetrics);
 
 
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_glyph_code = -1;               /* reset kerning*/
        pf->last_pen_pos = -32767;
        pf->last_pen_pos = -32767;
        if (lpnFit)
        if (lpnFit)
             *lpnFit=-1;
             *lpnFit=-1;
        for (i = 0; i < cc; i++)
        for (i = 0; i < cc; i++)
        {
        {
                curchar = TT_Char_Index (pf->char_map,text[i]);
                curchar = TT_Char_Index (pf->char_map,text[i]);
 
 
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                        TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
                {
                {
                     printf("Unable to load glyph with index=%d\n",curchar);
                     printf("Unable to load glyph with index=%d\n",curchar);
                        return 0;
                        return 0;
                }
                }
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
                TT_Get_Glyph_Metrics (pf->glyph, &metrics);
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
                if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
                {
                {
                        x += compute_kernval(pf, curchar) / 64;
                        x += compute_kernval(pf, curchar) / 64;
                }
                }
                x += metrics.advance / 64;
                x += metrics.advance / 64;
                if((lpnFit)&&(alpDx))
                if((lpnFit)&&(alpDx))
                {
                {
                        if (x<=nMaxExtent)
                        if (x<=nMaxExtent)
                             alpDx[i]=x;
                             alpDx[i]=x;
                        else
                        else
                             if (*lpnFit==-1)
                             if (*lpnFit==-1)
                                        (*lpnFit)=i;
                                        (*lpnFit)=i;
                }
                }
                /* Kerning point syndrome avoidance */
                /* Kerning point syndrome avoidance */
                if (pf->last_pen_pos > x)
                if (pf->last_pen_pos > x)
                        x = pf->last_pen_pos;
                        x = pf->last_pen_pos;
                pf->last_pen_pos = x;
                pf->last_pen_pos = x;
                pf->last_glyph_code = curchar;
                pf->last_glyph_code = curchar;
        }
        }
        if ((lpnFit)&&(*lpnFit==-1))
        if ((lpnFit)&&(*lpnFit==-1))
                *lpnFit=cc;
                *lpnFit=cc;
        *pwidth = x;
        *pwidth = x;
        *pheight = (((properties.horizontal->Ascender *
        *pheight = (((properties.horizontal->Ascender *
                        imetrics.y_scale)/ 0x10000) >> 6) -
                        imetrics.y_scale)/ 0x10000) >> 6) -
                            (((properties.horizontal->Descender *
                            (((properties.horizontal->Descender *
                            imetrics.y_scale)/ 0x10000) >> 6);
                            imetrics.y_scale)/ 0x10000) >> 6);
        /*FIXME: is it what's required ??*/
        /*FIXME: is it what's required ??*/
        if (pbase)
        if (pbase)
                *pbase = (((-properties.horizontal->Descender) *
                *pbase = (((-properties.horizontal->Descender) *
                            imetrics.y_scale)/ 0x10000) >> 6;
                            imetrics.y_scale)/ 0x10000) >> 6;
        return 1;
        return 1;
#else /* HAVE_FREETYPE_SUPPORT*/
#else /* HAVE_FREETYPE_SUPPORT*/
        *pwidth = *pheight = *pbase = 0;
        *pwidth = *pheight = *pbase = 0;
        return 0;
        return 0;
#endif
#endif
}
}
 
 

powered by: WebSVN 2.1.0

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