Logo Search packages:      
Sourcecode: gretl version File versions

gtkpsfont.c

/* gtkpsfont - PostScript Fonts handling
 * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
 *
 * Some code borrowed from
 * DiaCanvas -- a technical canvas widget
 * Copyright (C) 1999 Arjan Molenaar
 * Dia -- an diagram creation/manipulation program
 * Copyright (C) 1998 Alexander Larsson
 *
 * and Xfig
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <pango/pango.h>
#include "gtkpsfontpango.h"

#define FONTCACHE_SIZE 17
#define NUM_X11_FONTS 2

static GtkPSFont font_data[] = 
{
  { "Times-Roman",
    "Times-Roman",
    "Times-Roman",
    "times, Medium",
    NULL,
    FALSE, FALSE, FALSE
  }, 
  { "Times-Italic",
    "Times-Italic",
    "Times-Roman",
    "times, Medium Italic",
    NULL,
    TRUE, FALSE, FALSE
  }, 
  { "Times-Bold",
    "Times-Bold",
    "Times-Roman",
    "times, Bold",
    NULL,
    FALSE, TRUE, FALSE
  }, 
  { "Times-BoldItalic",
    "Times-BoldItalic",
    "Times-Roman",
    "times, Bold Italic",
    NULL,
    TRUE, TRUE, FALSE
  }, 
  { "AvantGarde-Book",
    "AvantGarde-Book",
    "AvantGarde",
    "avantgarde",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "AvantGarde-BookOblique",
    "AvantGarde-BookOblique",
    "AvantGarde",
    "avantgarde, Oblique",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "AvantGarde-Demi",
    "AvantGarde-Demi",
    "AvantGarde",
    "avantgarde, Semi-Bold",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "AvantGarde-DemiOblique",
    "AvantGarde-DemiOblique",
    "AvantGarde",
    "avantgarde, Semi-Bold Oblique",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Bookman-Light",
    "Bookman-Light",
    "Bookman",
    "bookman",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "Bookman-LightItalic",
    "Bookman-LightItalic",
    "Bookman",
    "bookman, Light Italic",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "Bookman-Demi",
    "Bookman-Demi",
    "Bookman",
    "bookman, Semi-Bold", 
    NULL,
    FALSE, TRUE, FALSE
  },
  { "Bookman-DemiItalic",
    "Bookman-DemiItalic",
    "Bookman",
    "bookman, Semi-Bold Italic", 
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Courier",
    "Courier",
    "Courier",
    "courier",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "Courier-Oblique",
    "Courier-Oblique",
    "Courier",
    "courier, Italic",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "Courier-Bold",
    "Courier-Bold",
    "Courier",
    "courier, Bold",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "Courier-BoldOblique",
    "Courier-BoldOblique",
    "Courier",
    "courier, Bold Oblique",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Helvetica",
    "Helvetica",
    "Helvetica",
    "helvetica, Medium",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "Helvetica-Oblique",
    "Helvetica-Oblique",
    "Helvetica",
    "helvetica, Medium Oblique",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "Helvetica-Bold",
    "Helvetica-Bold",
    "Helvetica",
    "helvetica, Bold",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "Helvetica-BoldOblique",
    "Helvetica-BoldOblique",
    "Helvetica",
    "helvetica, Bold Oblique",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Helvetica-Narrow",
    "Helvetica-Narrow",
    "Helvetica-Narrow",
    "helvetica, Medium Condensed",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "Helvetica-Narrow-Oblique",
    "Helvetica-Narrow-Oblique",
    "Helvetica-Narrow",
    "helvetica, Medium Oblique Condensed",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "Helvetica-Narrow-Bold",
    "Helvetica-Narrow-Bold",
    "Helvetica-Narrow",
    "helvetica, Bold Condensed",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "Helvetica-Narrow-BoldOblique",
    "Helvetica-Narrow-BoldOblique",
    "Helvetica-Narrow",
    "helvetica, Bold Oblique Condensed",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "NewCenturySchoolbook-Roman",
    "NewCenturySchlbk-Roman",
    "NewCenturySchlbk",
    "new century schoolbook, Medium",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "NewCenturySchoolbook-Italic",
    "NewCenturySchlbk-Italic",
    "NewCenturySchlbk",
    "new century schoolbook, Medium Italic",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "NewCenturySchoolbook-Bold",
    "NewCenturySchlbk-Bold",
    "NewCenturySchlbk",
    "new century schoolbook, Bold",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "NewCenturySchoolbook-BoldItalic",
    "NewCenturySchlbk-BoldItalic",
    "NewCenturySchlbk",
    "new century schoolbook, Bold Italic",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Palatino-Roman",
    "Palatino-Roman",
    "Palatino",
    "palatino, Medium",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "Palatino-Italic",
    "Palatino-Italic",
    "Palatino",
    "palatino, Medium Italic",
    NULL,
    TRUE, FALSE, FALSE
  },
  { "Palatino-Bold",
    "Palatino-Bold",
    "Palatino",
    "palatino, Bold",
    NULL,
    FALSE, TRUE, FALSE
  },
  { "Palatino-BoldItalic",
    "Palatino-BoldItalic",
    "Palatino",
    "palatino, Bold Italic",
    NULL,
    TRUE, TRUE, FALSE
  },
  { "Symbol",
    "Symbol",
    "Symbol",
    "symbol",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "ZapfChancery-MediumItalic",
    "ZapfChancery-MediumItalic",
    "ZapfChancery",
    "zapf chancery, Medium Italic",
    NULL,
    FALSE, FALSE, FALSE
  },
  { "ZapfDingbats",
    "ZapfDingbats",
    "ZapfDingbats",
    "zapf dingbats, Medium",
    NULL,
    FALSE, FALSE, FALSE
  },
};

#define NUM_FONTS (sizeof(font_data)/sizeof(GtkPSFont))

static GList *user_fonts;
static gboolean psfont_init = FALSE;
static GList *psfont_families;
static gint numf;
static gint psfont_refcount = 0;

#ifdef G_PLATFORM_WIN32
static const char *default_font = "sans";
#else
static const char *default_font = "fixed";
#endif

static GtkPSFont *find_psfont       (const gchar *name);

gint 
gtk_psfont_init()
{
  GtkPSFont *data = NULL;
  GList *fonts;
  gint i, j;
  gboolean new_family = TRUE;

  psfont_refcount++;

/*  if(psfont_refcount > 1) printf("PS fonts already initilized\n");;
*/
  if(psfont_refcount > 1) return FALSE;

/*  printf("Initializing PS fonts\n");;
*/

  psfont_init = TRUE;
  psfont_families = NULL;
  numf = 0;

  for(i = 0; i < NUM_FONTS; i++){
    new_family = TRUE;
    for(j = 0; j < numf; j++){
       if(strcmp(font_data[i].family, (gchar *)g_list_nth_data(psfont_families, j)) == 0)
         new_family = FALSE;
    }
    if(new_family){
         numf = numf + 1;
         psfont_families = g_list_append(psfont_families, font_data[i].family);
    }     
  }

  fonts = user_fonts;
  while(fonts){
    data = (GtkPSFont *) fonts->data;
    new_family = TRUE;
    for(j = 0; j < numf; j++){
       if(strcmp(data->family, (gchar *)g_list_nth_data(psfont_families, j)) == 0) 
         new_family = FALSE;
    }
    if(new_family){
         numf = numf + 1;
         psfont_families = g_list_append(psfont_families, data->family);
    }     
    fonts = fonts->next;
  }

  return TRUE;
}


void 
gtk_psfont_unref()
{
  GList *list;

  psfont_refcount--;

  if(psfont_refcount > 0) return;

  list = psfont_families;
  while(list){
    psfont_families = g_list_remove_link(psfont_families, list);
    g_list_free_1(list);
    list = psfont_families;
  }

  list = user_fonts;
  while(list){
    user_fonts = g_list_remove_link(user_fonts, list);
    g_list_free_1(list);
    list = user_fonts;
  }

  psfont_init = FALSE;
}

GtkPSFont *
gtk_psfont_get_by_name(const gchar *name)
{
  GtkPSFont *font;

  font = find_psfont(name);

  if (font == NULL) {
    font = find_psfont(default_font);
    if (font == NULL) {
      g_warning ("Error, couldn't locate default font. Shouldn't happen.");
    } else {
      g_message ("Postscript font %s not found, using %s instead.",
             name, default_font);
    }
  }

  return (GtkPSFont *)font;
}

GdkFont *
gtk_psfont_get_gdkfont(GtkPSFont *font, gint height)
{
  PangoFontDescription *font_desc;
  gchar *font_string;
  GdkFont *gdkfont;

  g_return_val_if_fail (font != NULL, NULL);

  if (height <= 0) height = 1;

  font_desc = gtk_psfont_get_font_description(font, height);
  gdkfont = font_desc ? gdk_font_from_description(font_desc) : NULL;
  if (font_desc)
    pango_font_description_free(font_desc);

  if (!gdkfont) {
    font_string = g_strdup_printf("%s %i", default_font, height);
    font_desc = pango_font_description_from_string(font_string);
    g_free(font_string);
    gdkfont = font_desc ? gdk_font_from_description(font_desc) : NULL;
    if (font_desc)
      pango_font_description_free(font_desc);

    if (gdkfont)
      g_message ("Pango font %s %i (PS font %s) not found, using %s instead.",
             font->pango_description, height, font->fontname, default_font);
    else
      g_warning ("Error, couldn't locate default font. Shouldn't happen.");
  }

  return gdkfont;
}

PangoFontDescription *
gtk_psfont_get_font_description(GtkPSFont *font, gint height)
{
  PangoFontDescription *font_desc, *desc;
  PangoContext *context = gdk_pango_context_get();
  PangoFontset *pffontset;
  PangoFont *pffont;
  gchar *font_string;

  g_return_val_if_fail (font != NULL, NULL);

  if (height <= 0) height = 1;
 
  font_string = g_strdup_printf("%s %i", font->pango_description, height);
  font_desc = pango_font_description_from_string(font_string);
  g_free(font_string);

  if (!font_desc) {
    font_string = g_strdup_printf("%s %i", default_font, height);
    font_desc = pango_font_description_from_string(font_string);
    g_free(font_string);
    if (font_desc)
      g_message ("Font %s not describable, using %s instead.",
             font->fontname, default_font);
    else
      g_warning ("Error, couldn't describe default font. Shouldn't happen.");
  }

  /* Loading via the pango fontset facility means that pango.aliases is used */
  if (font_desc) {
    pffontset = pango_context_load_fontset(context, font_desc,
      pango_context_get_language(context));
    if (pffontset) {
      pffont = pango_fontset_get_font(pffontset, g_utf8_get_char(" "));
      if (pffont) {
      desc = pango_font_describe(pffont);
      g_object_unref(G_OBJECT(pffont));
      if (desc) {
        pango_font_description_free(font_desc);
        font_desc = desc;
      }
      }
      g_object_unref(G_OBJECT(pffontset));
    }
  }

  return font_desc;
}


const gchar *
gtk_psfont_get_psfontname(GtkPSFont *font)
{

  g_return_val_if_fail (font != NULL, NULL);

  return font->psname;
}

void
gtk_psfont_add_font (const gchar *fontname, 
                     const gchar *psname, const gchar *family,
                     const gchar *pango_description,
                     gboolean italic, gboolean bold)
{
  GtkPSFont *font;

  font = g_new0(GtkPSFont, 1);

  font->fontname = g_strdup(fontname); 
  font->psname = g_strdup(psname); 
  font->family = g_strdup(family); 
  font->pango_description = g_strdup(pango_description); 
  font->i18n_latinfamily = NULL;
  font->italic = italic;
  font->bold = bold;
  font->vertical = FALSE;

  user_fonts = g_list_append(user_fonts, font);
}

void
gtk_psfont_add_i18n_font (const gchar *fontname, 
                         const gchar *psname, const gchar *family,
                         const gchar *i18n_latinfamily, 
                         const gchar *pango_description,
                         gboolean italic, gboolean bold, gboolean vertical)
{
  GtkPSFont *font;

  font = g_new0(GtkPSFont, 1);

  font->fontname = g_strdup(fontname); 
  font->psname = g_strdup(psname); 
  font->family = g_strdup(family); 
  font->pango_description = g_strdup(pango_description); 
  font->i18n_latinfamily = g_strdup(i18n_latinfamily);
  font->italic = italic;
  font->bold = bold;
  font->vertical = vertical;

  user_fonts = g_list_append(user_fonts, font);
}


static GtkPSFont *
find_psfont(const gchar *name)
{
  GtkPSFont *fontdata = NULL;
  GtkPSFont *data = NULL;
  GList *fonts;
  gint i;

  /* user_fonts should be superior to font_data, the built-in default
     settings because user_fonts is supposed to store a more appropriate
     existent xfont than font_data.
  */

  fonts = user_fonts;
  while(fonts){
    data = (GtkPSFont *) fonts->data;
    if(strcmp(name, data->fontname) == 0) {
      fontdata = data;
      break;
    }
    if(strcmp(name, data->psname) == 0) {
      fontdata = data;
      break;
    }
    fonts = fonts->next;
  }

  if(fontdata == NULL) {
    for(i = 0; i < NUM_FONTS; i++){
      if(strcmp(name, font_data[i].fontname) == 0) { 
      fontdata = &font_data[i];
      break;
      }
      if(strcmp(name, font_data[i].psname) == 0) { 
      fontdata = &font_data[i];
       break;
      }
    }
  }
  
  return fontdata;
}

GtkPSFont *
gtk_psfont_get_by_family(const gchar *name, gboolean italic, gboolean bold)
{
  GtkPSFont *fontdata = NULL;
  GtkPSFont *data = NULL;
  GtkPSFont *return_data = NULL;
  GList *fonts;
  gint i;

  /* user_fonts should be superior to font_data, the built-in default
     settings because user_fonts is supposed to store a more appropriate
     existent xfont than font_data.
  */

  fonts = user_fonts;
  while(fonts){
    data = (GtkPSFont *) fonts->data;
    if(strcmp(name, data->family) == 0) {
      return_data = data;
      if(data->italic == italic && data->bold == bold){
      fontdata = data;
      break;
      }
    }
    fonts = fonts->next;
  }
    
  if(fontdata == NULL) {
    for(i = 0; i < NUM_FONTS; i++){
      if(strcmp(name, font_data[i].family) == 0) { 
      return_data = &font_data[i];
      if(font_data[i].italic == italic && font_data[i].bold == bold){
        fontdata = &font_data[i];
        break;
      }
      }
    }
  }

  if(!fontdata) fontdata = return_data;
  return fontdata;
}


void
gtk_psfont_get_families(GList **families, gint *num_families)
{
  if(!psfont_init || psfont_refcount == 0){
    g_warning("PS fonts have not been initialized. Use gtk_psfont_init first.");
    return;
  }

  *families = psfont_families;
  *num_families = numf;
}

/* get the width, ascent and descent of a character. */
void
gtk_psfont_get_char_size(GtkPSFont *psfont,
                         GdkFont *font,
                         GdkFont *latin_font,
                         GdkWChar wc,
                         gint *width,
                         gint *ascent,
                         gint *descent)
{
  GdkFont *dfont;
  gint w, a, d, w0;
  
  if (psfont->i18n_latinfamily && psfont->vertical && wc > 0x7f) {
    /* vertical-writing CJK postscript fonts. */
    w = (font->ascent + font->descent);
    w0 = gdk_char_width_wc(font, wc);
    d = w0 * font->descent / w;
    a = w0 - d;
  } else {
    if (psfont->i18n_latinfamily && wc <= 0x7f)
      dfont = latin_font;
    else
      dfont = font;
    w = gdk_char_width_wc(dfont, wc);
    a = dfont->ascent;
    d = dfont->descent;
  }

  if (width != NULL) *width = w;
  if (ascent != NULL) *ascent = a;
  if (descent != NULL) *descent = d;
}


Generated by  Doxygen 1.6.0   Back to index