* app/diapsftrenderer.c: including ftoutln.h
[dia.git] / app / diapsft2renderer.c
blob3d30757d4ed5d9e8b4eb0a8f7e57fc048f7206ef
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
21 #include <string.h>
23 #include "font.h"
25 #include "diapsft2renderer.h"
27 #include <pango/pango.h>
28 #include <pango/pangoft2.h>
29 /* I'd really rather avoid this */
30 #include <freetype/ftglyph.h>
31 #include <freetype/ftoutln.h>
33 #define DPI 300
35 /* These routines stolen mercilessly from PAPS
36 * http://imagic.weizmann.ac.il/~dov/freesw/paps
38 /* Information passed in user data when drawing outlines */
39 typedef struct _OutlineInfo OutlineInfo;
40 struct _OutlineInfo {
41 FILE *OUT;
42 FT_Vector glyph_origin;
43 int dpi;
46 void postscript_contour_headers(FILE *OUT, int dpi_x, int dpi_y);
47 void postscript_draw_contour(DiaPsRenderer *renderer,
48 int dpi_x,
49 PangoLayoutLine *pango_line,
50 double x_pos,
51 double y_pos
53 void draw_bezier_outline(DiaPsRenderer *renderer,
54 int dpi_x,
55 FT_Face face,
56 FT_UInt glyph_index,
57 double pos_x,
58 double pos_y
60 /* Countour traveling functions */
61 static int paps_move_to( FT_Vector* to,
62 void *user_data);
63 static int paps_line_to( FT_Vector* to,
64 void *user_data);
65 static int paps_conic_to( FT_Vector* control,
66 FT_Vector* to,
67 void *user_data);
68 static int paps_cubic_to( FT_Vector* control1,
69 FT_Vector* control2,
70 FT_Vector* to,
71 void *user_data);
73 static void dia_ps_ft2_renderer_class_init (DiaPsFt2RendererClass *klass);
75 static gpointer parent_class = NULL;
77 static void
78 set_font(DiaRenderer *self, DiaFont *font, real height)
80 DiaPsFt2Renderer *renderer = DIA_PS_FT2_RENDERER(self);
82 renderer->current_font = font;
83 /* Dammit! We have a random factor once again! */
84 renderer->current_height = height*4.3;
85 pango_context_set_font_description(dia_font_get_context(), font->pfd);
88 /* ********************************************************* */
89 /* String rendering using PangoFt2 */
90 /* ********************************************************* */
91 /* Such a big mark really is a sign that this should go in its own file:) */
92 /* And so it did. */
94 /*======================================================================
95 outline traversing functions.
96 ----------------------------------------------------------------------*/
97 static int paps_move_to( FT_Vector* to,
98 void *user_data)
100 OutlineInfo *outline_info = (OutlineInfo*)user_data;
101 fprintf(outline_info->OUT, "%d %d moveto\n",
102 to->x ,
103 to->y );
104 return 0;
107 static int paps_line_to( FT_Vector* to,
108 void *user_data)
110 OutlineInfo *outline_info = (OutlineInfo*)user_data;
111 fprintf(outline_info->OUT, "%d %d lineto\n",
112 to->x ,
113 to->y );
114 return 0;
117 static int paps_conic_to( FT_Vector* control,
118 FT_Vector* to,
119 void *user_data)
121 OutlineInfo *outline_info = (OutlineInfo*)user_data;
122 fprintf(outline_info->OUT, "%d %d %d %d conicto\n",
123 control->x ,
124 control->y ,
125 to->x ,
126 to->y );
127 return 0;
130 static int paps_cubic_to( FT_Vector* control1,
131 FT_Vector* control2,
132 FT_Vector* to,
133 void *user_data)
135 OutlineInfo *outline_info = (OutlineInfo*)user_data;
136 fprintf(outline_info->OUT,
137 "%d %d %d %d %d %d curveto\n",
138 control1->x ,
139 control1->y ,
140 control2->x ,
141 control2->y ,
142 to->x ,
143 to->y );
144 return 0;
147 /* These must go in the prologue section */
148 void postscript_contour_headers(FILE *OUT, int dpi_x, int dpi_y)
150 /* /dpi_x needed for /conicto */
151 fprintf(OUT,
152 "/dpi_x %d def\n"
153 "/dpi_y %d def\n", dpi_x, dpi_y);
154 /* Outline support */
155 fprintf(OUT,
156 "/conicto {\n"
157 " /to_y exch def\n"
158 " /to_x exch def\n"
159 " /conic_cntrl_y exch def\n"
160 " /conic_cntrl_x exch def\n"
161 " currentpoint\n"
162 " /p0_y exch def\n"
163 " /p0_x exch def\n"
164 " /p1_x p0_x conic_cntrl_x p0_x sub 2 3 div mul add def\n"
165 " /p1_y p0_y conic_cntrl_y p0_y sub 2 3 div mul add def\n"
166 " /p2_x p1_x to_x p0_x sub 1 3 div mul add def\n"
167 " /p2_y p1_y to_y p0_y sub 1 3 div mul add def\n"
168 " p1_x p1_y p2_x p2_y to_x to_y curveto\n"
169 "} bind def\n"
170 "/start_ol { gsave 1.1 dpi_x div dup scale} bind def\n"
171 "/end_ol { closepath fill grestore } bind def\n"
176 /* postscript_draw_contour() dumps out the information of a line. It shows how
177 to access the ft font information out of the pango font info.
179 void postscript_draw_contour(DiaPsRenderer *renderer,
180 int dpi_x,
181 PangoLayoutLine *pango_line,
182 double line_start_pos_x,
183 double line_start_pos_y)
185 GSList *runs_list;
186 int num_runs = 0;
187 PangoRectangle ink_rect, logical_rect;
188 int byte_width;
189 FT_Bitmap bitmap;
190 guchar *buf;
192 /* First calculate number of runs in text */
193 runs_list = pango_line->runs;
194 while(runs_list)
196 PangoLayoutRun *run = runs_list->data;
197 num_runs++;
198 runs_list = runs_list->next;
200 /* Loop over the runs and output font info */
201 runs_list = pango_line->runs;
202 while(runs_list)
204 PangoLayoutRun *run = runs_list->data;
205 PangoItem *item = run->item;
206 PangoGlyphString *glyphs = run->glyphs;
207 PangoAnalysis *analysis = &item->analysis;
208 PangoFont *font = analysis->font;
210 PangoFont *font = pango_context_load_font(renderer->context,
211 renderer->current_font->pfd);
213 FT_Face ft_face;
214 int bidi_level;
215 int num_glyphs;
216 int glyph_idx;
218 if (font == NULL) {
219 fprintf(stderr, "No font found\n");
220 continue;
222 ft_face = pango_ft2_font_get_face(font);
223 if (ft_face == NULL) {
224 fprintf(stderr, "Failed to get face for font %s\n",
225 pango_font_description_to_string(pango_font_describe(font)));
226 continue;
230 printf("Got face %s (PS %s) for font %s (diafont %s)\n",
231 ft_face->family_name,
232 FT_Get_Postscript_Name(ft_face),
233 pango_font_description_to_string(pango_font_describe(font)),
234 dia_font_get_family(renderer->current_font));
237 bidi_level = item->analysis.level;
238 num_glyphs = glyphs->num_glyphs;
240 for (glyph_idx=0; glyph_idx<num_glyphs; glyph_idx++)
242 PangoGlyphGeometry geometry = glyphs->glyphs[glyph_idx].geometry;
243 double pos_x;
244 double pos_y;
245 double scale = 2.54/PANGO_SCALE/dpi_x;/*72.0 / PANGO_SCALE / dpi_x;*/
247 pos_x = line_start_pos_x + 1.0* geometry.x_offset * scale;
248 pos_y = line_start_pos_y - 1.0*geometry.y_offset * scale;
250 line_start_pos_x += 1.0 * geometry.width * scale;
253 printf("Drawing glyph %d: index %d at %f, %f (w %d)\n", glyph_idx,
254 glyphs->glyphs[glyph_idx].glyph, pos_x, pos_y,
255 geometry.width);
257 draw_bezier_outline(renderer,
258 dpi_x,
259 ft_face,
260 (FT_UInt)(glyphs->glyphs[glyph_idx].glyph),
261 pos_x, pos_y
265 runs_list = runs_list->next;
270 void draw_bezier_outline(DiaPsRenderer *renderer,
271 int dpi_x,
272 FT_Face face,
273 FT_UInt glyph_index,
274 double pos_x,
275 double pos_y
278 FT_Int load_flags = FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP;
279 FT_Glyph glyph;
280 FT_Error error;
282 /* Need to transform */
284 /* Output outline */
285 FT_Outline_Funcs outlinefunc =
287 paps_move_to,
288 paps_line_to,
289 paps_conic_to,
290 paps_cubic_to
292 OutlineInfo outline_info;
294 outline_info.glyph_origin.x = pos_x;
295 outline_info.glyph_origin.y = pos_y;
296 outline_info.dpi = dpi_x;
297 outline_info.OUT = renderer->file;
299 fprintf(renderer->file,
300 "gsave %f %f translate %f %f scale\n",
301 pos_x, pos_y, 2.54/72.0, -2.54/72.0);
302 fprintf(renderer->file, "start_ol\n");
304 if ((error=FT_Load_Glyph(face, glyph_index, load_flags))) {
305 fprintf(stderr, "Can't load glyph: %d\n", error);
306 return;
308 FT_Get_Glyph (face->glyph, &glyph);
309 FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
310 &outlinefunc, &outline_info);
311 fprintf(renderer->file, "end_ol grestore \n");
313 FT_Done_Glyph (glyph);
316 static void
317 draw_string(DiaRenderer *self,
318 const char *text,
319 Point *pos, Alignment alignment,
320 Color *color)
322 //DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
323 DiaPsFt2Renderer *renderer = DIA_PS_FT2_RENDERER(self);
324 PangoLayout *layout;
325 int width;
326 int line, linecount;
327 double xpos = pos->x, ypos = pos->y;
328 PangoAttrList* list;
329 PangoAttribute* attr;
330 guint length;
332 if ((!text)||(text == (const char *)(1))) return;
334 lazy_setcolor(DIA_PS_RENDERER(renderer),color);
336 /* Make sure the letters aren't too wide. */
337 layout = dia_font_scaled_build_layout(text, renderer->current_font,
338 renderer->current_height/0.7,
339 20.0);
341 dia_font_set_height(renderer->current_font, renderer->current_height);
342 layout = pango_layout_new(dia_font_get_context());
344 length = text ? strlen(text) : 0;
345 pango_layout_set_text(layout,text,length);
347 list = pango_attr_list_new();
349 attr = pango_attr_font_desc_new(renderer->current_font->pfd);
350 attr->start_index = 0;
351 attr->end_index = length;
352 pango_attr_list_insert(list,attr);
354 pango_layout_set_attributes(layout,list);
355 pango_attr_list_unref(list);
357 pango_layout_set_indent(layout,0);
358 pango_layout_set_justify(layout,FALSE);
360 switch (alignment) {
361 case ALIGN_LEFT:
362 pango_layout_set_alignment(layout,PANGO_ALIGN_LEFT);
363 break;
364 case ALIGN_CENTER:
365 pango_layout_set_alignment(layout,PANGO_ALIGN_CENTER);
366 break;
367 case ALIGN_RIGHT:
368 pango_layout_set_alignment(layout,PANGO_ALIGN_RIGHT);
369 break;
372 pango_layout_get_size(layout, &width, NULL);
373 linecount = pango_layout_get_line_count(layout);
374 for (line = 0; line < linecount; line++) {
375 PangoLayoutLine *layoutline = pango_layout_get_line(layout, line);
376 real width, xoff = 0.0;
377 PangoRectangle rectangle;
379 pango_layout_line_get_extents(layoutline, &rectangle, NULL);
380 width = rectangle.width;
382 switch (alignment) {
383 case ALIGN_LEFT:
384 xoff = 0.0;
385 break;
386 case ALIGN_CENTER:
387 xoff = width/2.0;
388 break;
389 case ALIGN_RIGHT:
390 xoff = width;
391 break;
393 xoff *= 2.54/PANGO_SCALE/DPI /* dpi_x */;
395 postscript_draw_contour(DIA_PS_RENDERER(renderer),
396 DPI, /* dpi_x */
397 layoutline,
398 xpos-xoff, ypos);
399 /* xpos should be adjusted for align and/or RTL */
400 ypos += 10;/* Some line height thing??? */
404 static void
405 dump_fonts (DiaPsRenderer *renderer)
407 postscript_contour_headers(renderer->file, DPI, DPI);
410 GType
411 dia_ps_ft2_renderer_get_type (void)
413 static GType object_type = 0;
415 if (!object_type)
417 static const GTypeInfo object_info =
419 sizeof (DiaPsFt2RendererClass),
420 (GBaseInitFunc) NULL,
421 (GBaseFinalizeFunc) NULL,
422 (GClassInitFunc) dia_ps_ft2_renderer_class_init,
423 NULL, /* class_finalize */
424 NULL, /* class_data */
425 sizeof (DiaPsFt2Renderer),
426 0, /* n_preallocs */
427 NULL /* init */
430 object_type = g_type_register_static (DIA_TYPE_PS_RENDERER,
431 "DiaPsFt2Renderer",
432 &object_info, 0);
435 return object_type;
438 static void
439 dia_ps_ft2_renderer_finalize (GObject *object)
441 DiaPsFt2Renderer *dia_ps_ft2_renderer = DIA_PS_FT2_RENDERER (object);
443 G_OBJECT_CLASS (parent_class)->finalize (object);
446 static void
447 dia_ps_ft2_renderer_class_init (DiaPsFt2RendererClass *klass)
449 GObjectClass *object_class = G_OBJECT_CLASS (klass);
450 DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass);
451 DiaPsRendererClass *ps_renderer_class = DIA_PS_RENDERER_CLASS (klass);
453 parent_class = g_type_class_peek_parent (klass);
455 object_class->finalize = dia_ps_ft2_renderer_finalize;
457 renderer_class->set_font = set_font;
458 renderer_class->draw_string = draw_string;
460 /* ps specific */
461 ps_renderer_class->dump_fonts = dump_fonts;