|
Graphviz
2.31.20130523.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include <stdlib.h> 00019 #include <string.h> 00020 #include "gvplugin_textlayout.h" 00021 00022 #ifdef HAVE_PANGOCAIRO 00023 #include <pango/pangocairo.h> 00024 #include "gvgetfontlist.h" 00025 #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE 00026 #include <pango/pangofc-font.h> 00027 #endif 00028 00029 #define N_NEW(n,t) (t*)malloc((n)*sizeof(t)) 00030 00031 static void pango_free_layout (void *layout) 00032 { 00033 g_object_unref((PangoLayout*)layout); 00034 } 00035 00036 static char* pango_psfontResolve (PostscriptAlias* pa) 00037 { 00038 static char buf[1024]; 00039 strcpy(buf, pa->family); 00040 strcat(buf, ","); 00041 if (pa->weight) { 00042 strcat(buf, " "); 00043 strcat(buf, pa->weight); 00044 } 00045 if (pa->stretch) { 00046 strcat(buf, " "); 00047 strcat(buf, pa->stretch); 00048 } 00049 if (pa->style) { 00050 strcat(buf, " "); 00051 strcat(buf, pa->style); 00052 } 00053 return buf; 00054 } 00055 00056 #define FONT_DPI 96. 00057 00058 #define ENABLE_PANGO_MARKUP 00059 #ifdef ENABLE_PANGO_MARKUP 00060 #define FULL_MARKUP "<span weight=\"bold\" style=\"italic\" underline=\"single\"><sup><sub></sub></sup></span>" 00061 #endif 00062 00063 static boolean pango_textlayout(textpara_t * para, char **fontpath) 00064 { 00065 static char buf[1024]; /* returned in fontpath, only good until next call */ 00066 static PangoFontMap *fontmap; 00067 static PangoContext *context; 00068 static PangoFontDescription *desc; 00069 static char *fontname; 00070 static double fontsize; 00071 static gv_font_map* gv_fmap; 00072 char *fnt, *psfnt = NULL; 00073 PangoLayout *layout; 00074 PangoRectangle logical_rect; 00075 cairo_font_options_t* options; 00076 PangoFont *font; 00077 #ifdef ENABLE_PANGO_MARKUP 00078 PangoAttrList *attrs; 00079 GError *error = NULL; 00080 int flags; 00081 #endif 00082 char *text; 00083 double textlayout_scale; 00084 00085 if (!context) { 00086 fontmap = pango_cairo_font_map_new(); 00087 gv_fmap = get_font_mapping(fontmap); 00088 context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); 00089 options=cairo_font_options_create(); 00090 cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); 00091 cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); 00092 cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); 00093 cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); 00094 pango_cairo_context_set_font_options(context, options); 00095 pango_cairo_context_set_resolution(context, FONT_DPI); 00096 cairo_font_options_destroy(options); 00097 g_object_unref(fontmap); 00098 } 00099 00100 if (!fontname || strcmp(fontname, para->fontname) != 0 || fontsize != para->fontsize) { 00101 fontname = para->fontname; 00102 fontsize = para->fontsize; 00103 pango_font_description_free (desc); 00104 00105 if (para->postscript_alias) { 00106 psfnt = fnt = gv_fmap[para->postscript_alias->xfig_code].gv_font; 00107 if(!psfnt) 00108 psfnt = fnt = pango_psfontResolve (para->postscript_alias); 00109 } 00110 else 00111 fnt = fontname; 00112 00113 desc = pango_font_description_from_string(fnt); 00114 /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ 00115 pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); 00116 00117 if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ 00118 const char *fontclass; 00119 00120 fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); 00121 00122 buf[0] = '\0'; 00123 if (psfnt) { 00124 strcat(buf, "(ps:pango "); 00125 strcat(buf, psfnt); 00126 strcat(buf, ") "); 00127 } 00128 strcat(buf, "("); 00129 strcat(buf, fontclass); 00130 strcat(buf, ") "); 00131 #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE 00132 if (strcmp(fontclass, "PangoCairoFcFont") == 0) { 00133 FT_Face face; 00134 PangoFcFont *fcfont; 00135 FT_Stream stream; 00136 FT_StreamDesc streamdesc; 00137 fcfont = PANGO_FC_FONT(font); 00138 face = pango_fc_font_lock_face(fcfont); 00139 if (face) { 00140 strcat(buf, "\""); 00141 strcat(buf, face->family_name); 00142 strcat(buf, ", "); 00143 strcat(buf, face->style_name); 00144 strcat(buf, "\" "); 00145 00146 stream = face->stream; 00147 if (stream) { 00148 streamdesc = stream->pathname; 00149 if (streamdesc.pointer) 00150 strcat(buf, (char*)streamdesc.pointer); 00151 else 00152 strcat(buf, "*no pathname available*"); 00153 } 00154 else 00155 strcat(buf, "*no stream available*"); 00156 } 00157 pango_fc_font_unlock_face(fcfont); 00158 } 00159 else 00160 #endif 00161 { 00162 PangoFontDescription *tdesc; 00163 char *tfont; 00164 00165 tdesc = pango_font_describe(font); 00166 tfont = pango_font_description_to_string(tdesc); 00167 strcat(buf, "\""); 00168 strcat(buf, tfont); 00169 strcat(buf, "\" "); 00170 g_free(tfont); 00171 } 00172 *fontpath = buf; 00173 } 00174 } 00175 00176 #ifdef ENABLE_PANGO_MARKUP 00177 if ((para->font) && (flags = para->font->flags)) { 00178 char* markup = N_NEW(strlen(para->str) + sizeof(FULL_MARKUP), char); 00179 strcpy(markup,"<span"); 00180 00181 if (flags & HTML_BF) 00182 strcat(markup," weight=\"bold\""); 00183 if (flags & HTML_IF) 00184 strcat(markup," style=\"italic\""); 00185 if (flags & HTML_UL) 00186 strcat(markup," underline=\"single\""); 00187 strcat (markup,">"); 00188 00189 if (flags & HTML_SUP) 00190 strcat(markup,"<sup>"); 00191 if (flags & HTML_SUB) 00192 strcat(markup,"<sub>"); 00193 00194 strcat (markup,para->str); 00195 00196 if (flags & HTML_SUB) 00197 strcat(markup,"</sub>"); 00198 if (flags & HTML_SUP) 00199 strcat(markup,"</sup>"); 00200 00201 strcat (markup,"</span>"); 00202 if (!pango_parse_markup (markup, -1, 0, &attrs, &text, NULL, &error)) { 00203 fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); 00204 text = para->str; 00205 attrs = NULL; 00206 } 00207 free (markup); 00208 } 00209 else { 00210 text = para->str; 00211 attrs = NULL; 00212 } 00213 #else 00214 text = para->str; 00215 #endif 00216 00217 layout = pango_layout_new (context); 00218 para->layout = (void *)layout; /* layout free with textpara - see labels.c */ 00219 para->free_layout = pango_free_layout; /* function for freeing pango layout */ 00220 00221 pango_layout_set_text (layout, text, -1); 00222 pango_layout_set_font_description (layout, desc); 00223 #ifdef ENABLE_PANGO_MARKUP 00224 if (attrs) 00225 pango_layout_set_attributes (layout, attrs); 00226 #endif 00227 00228 pango_layout_get_extents (layout, NULL, &logical_rect); 00229 00230 /* if pango doesn't like the font then it sets width=0 but height = garbage */ 00231 if (logical_rect.width == 0) 00232 logical_rect.height = 0; 00233 00234 textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE); 00235 para->width = (int)(logical_rect.width * textlayout_scale + 1); /* round up so that width/height are never too small */ 00236 para->height = (int)(logical_rect.height * textlayout_scale + 1); 00237 00238 /* FIXME -- Horrible kluge !!! */ 00239 00240 /* For now we are using pango for single line blocks only. 00241 * The logical_rect.height seems to be too high from the font metrics on some platforms. 00242 * Use an assumed height based on the point size. 00243 */ 00244 00245 para->height = (int)(para->fontsize * 1.1 + .5); 00246 00247 /* The y offset from baseline to 0,0 of the bitmap representation */ 00248 #if defined PANGO_VERSION_MAJOR && (PANGO_VERSION_MAJOR >= 1) 00249 para->yoffset_layout = pango_layout_get_baseline (layout) * textlayout_scale; 00250 #else 00251 { 00252 /* do it the hard way on rhel5/centos5 */ 00253 PangoLayoutIter *iter = pango_layout_get_iter (layout); 00254 para->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale; 00255 } 00256 #endif 00257 00258 /* The distance below midline for y centering of text strings */ 00259 para->yoffset_centerline = 0.2 * para->fontsize; 00260 00261 if (logical_rect.width == 0) 00262 return FALSE; 00263 return TRUE; 00264 } 00265 00266 static gvtextlayout_engine_t pango_textlayout_engine = { 00267 pango_textlayout, 00268 }; 00269 #endif 00270 00271 gvplugin_installed_t gvtextlayout_pango_types[] = { 00272 #ifdef HAVE_PANGOCAIRO 00273 {0, "textlayout", 10, &pango_textlayout_engine, NULL}, 00274 #endif 00275 {0, NULL, 0, NULL, NULL} 00276 };
1.7.5