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.
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>
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
;
42 FT_Vector glyph_origin
;
46 void postscript_contour_headers(FILE *OUT
, int dpi_x
, int dpi_y
);
47 void postscript_draw_contour(DiaPsRenderer
*renderer
,
49 PangoLayoutLine
*pango_line
,
53 void draw_bezier_outline(DiaPsRenderer
*renderer
,
60 /* Countour traveling functions */
61 static int paps_move_to( FT_Vector
* to
,
63 static int paps_line_to( FT_Vector
* to
,
65 static int paps_conic_to( FT_Vector
* control
,
68 static int paps_cubic_to( FT_Vector
* control1
,
73 static void dia_ps_ft2_renderer_class_init (DiaPsFt2RendererClass
*klass
);
75 static gpointer parent_class
= NULL
;
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:) */
94 /*======================================================================
95 outline traversing functions.
96 ----------------------------------------------------------------------*/
97 static int paps_move_to( FT_Vector
* to
,
100 OutlineInfo
*outline_info
= (OutlineInfo
*)user_data
;
101 fprintf(outline_info
->OUT
, "%d %d moveto\n",
107 static int paps_line_to( FT_Vector
* to
,
110 OutlineInfo
*outline_info
= (OutlineInfo
*)user_data
;
111 fprintf(outline_info
->OUT
, "%d %d lineto\n",
117 static int paps_conic_to( FT_Vector
* control
,
121 OutlineInfo
*outline_info
= (OutlineInfo
*)user_data
;
122 fprintf(outline_info
->OUT
, "%d %d %d %d conicto\n",
130 static int paps_cubic_to( FT_Vector
* control1
,
135 OutlineInfo
*outline_info
= (OutlineInfo
*)user_data
;
136 fprintf(outline_info
->OUT
,
137 "%d %d %d %d %d %d curveto\n",
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 */
153 "/dpi_y %d def\n", dpi_x
, dpi_y
);
154 /* Outline support */
159 " /conic_cntrl_y exch def\n"
160 " /conic_cntrl_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"
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
,
181 PangoLayoutLine
*pango_line
,
182 double line_start_pos_x
,
183 double line_start_pos_y
)
187 PangoRectangle ink_rect
, logical_rect
;
192 /* First calculate number of runs in text */
193 runs_list
= pango_line
->runs
;
196 PangoLayoutRun
*run
= runs_list
->data
;
198 runs_list
= runs_list
->next
;
200 /* Loop over the runs and output font info */
201 runs_list
= pango_line
->runs
;
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);
219 fprintf(stderr
, "No font found\n");
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
)));
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
;
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,
257 draw_bezier_outline(renderer
,
260 (FT_UInt
)(glyphs
->glyphs
[glyph_idx
].glyph
),
265 runs_list
= runs_list
->next
;
270 void draw_bezier_outline(DiaPsRenderer
*renderer
,
278 FT_Int load_flags
= FT_LOAD_DEFAULT
|FT_LOAD_NO_BITMAP
;
282 /* Need to transform */
285 FT_Outline_Funcs outlinefunc
=
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
);
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
);
317 draw_string(DiaRenderer
*self
,
319 Point
*pos
, Alignment alignment
,
322 //DiaPsRenderer *renderer = DIA_PS_RENDERER(self);
323 DiaPsFt2Renderer
*renderer
= DIA_PS_FT2_RENDERER(self
);
327 double xpos
= pos
->x
, ypos
= pos
->y
;
329 PangoAttribute
* attr
;
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,
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);
362 pango_layout_set_alignment(layout
,PANGO_ALIGN_LEFT
);
365 pango_layout_set_alignment(layout
,PANGO_ALIGN_CENTER
);
368 pango_layout_set_alignment(layout
,PANGO_ALIGN_RIGHT
);
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
;
393 xoff
*= 2.54/PANGO_SCALE
/DPI
/* dpi_x */;
395 postscript_draw_contour(DIA_PS_RENDERER(renderer
),
399 /* xpos should be adjusted for align and/or RTL */
400 ypos
+= 10;/* Some line height thing??? */
405 dump_fonts (DiaPsRenderer
*renderer
)
407 postscript_contour_headers(renderer
->file
, DPI
, DPI
);
411 dia_ps_ft2_renderer_get_type (void)
413 static GType object_type
= 0;
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
),
430 object_type
= g_type_register_static (DIA_TYPE_PS_RENDERER
,
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
);
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
;
461 ps_renderer_class
->dump_fonts
= dump_fonts
;