/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/plugin/pango/gvtextlayout_pango.c

Go to the documentation of this file.
00001   /* $Id: gvtextlayout_pango.c,v 1.37 2008/03/09 02:35:38 ellson Exp $ $Revision: 1.37 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*********************************************************
00005 *       This software is part of the graphviz package    *
00006 *               http://www.graphviz.org/                 *
00007 *                                                        *
00008 *           Copyright (c) 1994-2004 AT&T Corp.           *
00009 *               and is licensed under the                *
00010 *           Common Public License, Version 1.0           *
00011 *                     by AT&T Corp.                      *
00012 *                                                        *
00013 *       Information and Software Systems Research        *
00014 *             AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #ifdef HAVE_CONFIG_H
00018 #include "config.h"
00019 #endif
00020 
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include "gvplugin_textlayout.h"
00024 
00025 #ifdef HAVE_PANGOCAIRO
00026 #include <pango/pangocairo.h>
00027 #ifdef HAVE_FONTCONFIG
00028 #include <pango/pangofc-font.h>
00029 #endif
00030 
00031 static void pango_free_layout (void *layout)
00032 {
00033     g_object_unref((PangoLayout*)layout);
00034 }
00035 
00036 #define FONT_DPI 96.
00037 
00038 extern char* psfontResolve (PostscriptAlias* pa);
00039 
00040 static boolean pango_textlayout(textpara_t * para, char **fontpath)
00041 {
00042     static char buf[1024];  /* returned in fontpath, only good until next call */
00043     static PangoFontMap *fontmap;
00044     static PangoContext *context;
00045     static PangoFontDescription *desc;
00046     static char *fontname;
00047     static double fontsize;
00048     char *fnt, *psfnt = NULL;
00049     PangoLayout *layout;
00050     PangoRectangle logical_rect;
00051     PangoLayoutIter* iter;
00052         cairo_font_options_t* options;
00053 #ifdef ENABLE_PANGO_MARKUP
00054     PangoAttrList *attrs;
00055     GError *error = NULL;
00056 #endif
00057     char *text;
00058     double textlayout_scale;
00059 
00060     if (!context) {
00061         fontmap = pango_cairo_font_map_get_default();
00062         context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap));
00063         options=cairo_font_options_create();
00064         cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY);
00065         cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL);
00066         cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON);
00067         cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR);
00068         pango_cairo_context_set_font_options(context, options);
00069 
00070         g_object_unref(fontmap);
00071     }
00072 
00073     if (!fontname || strcmp(fontname, para->fontname) != 0 || fontsize != para->fontsize) {
00074         fontname = para->fontname;
00075         fontsize = para->fontsize;
00076         pango_font_description_free (desc);
00077 
00078         if (para->postscript_alias) {
00079             psfnt = fnt = psfontResolve (para->postscript_alias);
00080         }
00081         else
00082             fnt = fontname;
00083 
00084         desc = pango_font_description_from_string(fnt);
00085         /* all text layout is done at a scale of 96ppi */
00086         pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE));
00087 
00088         if (fontpath) {  /* -v support */
00089             PangoFont *font;
00090 
00091             font = pango_font_map_load_font(fontmap, context, desc);
00092 
00093             buf[0] = '\0';
00094             if (psfnt)
00095                 strcat(buf, "(ps) ");
00096 #ifdef HAVE_FONTCONFIG
00097             {
00098                 FT_Face face;
00099                 PangoFcFont *fcfont;
00100                 FT_Stream stream;
00101                 FT_StreamDesc streamdesc;
00102                 fcfont = PANGO_FC_FONT(font);
00103                 if (fcfont) {
00104                     face = pango_fc_font_lock_face(fcfont);
00105                     if (face) {
00106                         strcat(buf, "\"");
00107                         strcat(buf, face->family_name);
00108                         strcat(buf, ", ");
00109                         strcat(buf, face->style_name);
00110                         strcat(buf, "\" ");
00111     
00112                         stream = face->stream;
00113                         if (stream) {
00114                             streamdesc = stream->pathname;
00115                             if (streamdesc.pointer)
00116                                 strcat(buf, (char*)streamdesc.pointer);
00117                             else
00118                                 strcat(buf, "*no pathname available*");
00119                         }
00120                         else
00121                             strcat(buf, "*no stream available*");
00122                     }
00123                     pango_fc_font_unlock_face(fcfont);
00124                 }
00125                 else
00126                     strcat(buf, "*not using fontconfig*");
00127             }
00128 #else
00129             {
00130                 PangoFontDescription *tdesc;
00131                 char *tfont;
00132                 
00133                 tdesc = pango_font_describe(font);
00134                 tfont = pango_font_description_to_string(tdesc);
00135                 strcat(buf, "\"");
00136                 strcat(buf, tfont);
00137                 strcat(buf, "\" ");
00138                 g_free(tfont);
00139             }
00140 #endif
00141             *fontpath = buf;
00142         }
00143     }
00144 
00145 #ifdef ENABLE_PANGO_MARKUP
00146     if (! pango_parse_markup (para->str, -1, 0, &attrs, &text, NULL, &error))
00147         die(error->message);
00148 #else
00149     text = para->str;
00150 #endif
00151 
00152     layout = pango_layout_new (context);
00153     para->layout = (void *)layout;    /* layout free with textpara - see labels.c */
00154     para->free_layout = pango_free_layout;    /* function for freeing pango layout */
00155 
00156     pango_layout_set_text (layout, text, -1);
00157     pango_layout_set_font_description (layout, desc);
00158 #ifdef ENABLE_PANGO_MARKUP
00159     pango_layout_set_attributes (layout, attrs);
00160 #endif
00161 
00162     pango_layout_get_extents (layout, NULL, &logical_rect);
00163 
00164     /* if pango doesn't like the font then it sets width=0 but height = garbage */
00165     if (logical_rect.width == 0)
00166         logical_rect.height = 0;
00167 
00168     textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE);
00169     para->width = ROUND(logical_rect.width * textlayout_scale);
00170     para->height = ROUND(logical_rect.height * textlayout_scale);
00171 
00172     /* The y offset from baseline to 0,0 of the bitmap representation */
00173     iter = pango_layout_get_iter (layout);
00174     para->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale;
00175 
00176     /* The distance below midline for y centering of text strings */
00177     para->yoffset_centerline = 0.1 * para->fontsize;
00178 
00179     pango_layout_iter_free (iter);
00180     if (logical_rect.width == 0)
00181         return FALSE;
00182     return TRUE;
00183 }
00184 
00185 static gvtextlayout_engine_t pango_textlayout_engine = {
00186     pango_textlayout,
00187 };
00188 #endif
00189 
00190 gvplugin_installed_t gvtextlayout_pango_types[] = {
00191 #ifdef HAVE_PANGOCAIRO
00192     {0, "textlayout", 10, &pango_textlayout_engine, NULL},
00193 #endif
00194     {0, NULL, 0, NULL, NULL}
00195 };

Generated on Mon Mar 31 19:03:28 2008 for Graphviz by  doxygen 1.5.1