/*
* gnome-print-pango.c
*
* Copyright (C) 2003-2004 Jean Bréfort <jean.brefort@normalesup.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#include "gchempaint-config.h"
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
#include <gtk/gtktextlayout.h>
#include "gnome-print-pango.h"
#include <string.h>
#ifdef GP_HAS_PANGO
# include <libgnomeprint/gnome-print-pango.h>
# define TEXT_ZOOM_FACTOR (4. / 3.)
void pango_layout_print (GnomePrintContext *gpc, PangoLayout* pl)
{
PangoAttrList *attrs = pango_layout_get_attributes (pl);
PangoLayout *layout = (PangoLayout*) gnome_print_pango_create_layout (gpc);
const char *text = pango_layout_get_text (pl);
int w1, w2, h1, h2, l;
double zoom, extra_space;
PangoFontDescription const *desc = pango_layout_get_font_description (pl);
PangoAttribute *pa;
PangoAttrList *pal = (attrs)? pango_attr_list_copy (attrs): pango_attr_list_new ();
l = strlen (text);
pango_layout_set_text (layout, text, l);
if (desc)
pango_layout_set_font_description (layout, desc);
pango_layout_set_attributes (layout, pal);
pango_layout_get_size (pl, &w1, &h1);
pango_layout_get_size (layout, &w2, &h2);
zoom = (double) h1 / (double) h2;
extra_space = w1 / zoom - w2;
if (l > 1) {
pa = pango_attr_letter_spacing_new ((int) extra_space / l);
pa->start_index = 0;
pa->end_index = l;
pango_attr_list_insert (pal, pa);
pango_layout_set_attributes (layout, pal);
}
pango_attr_list_unref (pal);
gnome_print_gsave (gpc);
gnome_print_scale (gpc, zoom, -zoom); /* not so good. Why is zoom necessary to get the same size ? Have a look at resolution */
gnome_print_moveto (gpc, 0., 0.);
gnome_print_pango_layout (gpc, layout);
gnome_print_grestore (gpc);
g_object_unref (layout);
}
#else
void gpc_print_pango_layout_print (GnomePrintContext *gpc, PangoLayout* pl) {
gint i, top, bottom;
GnomeFont *font;
GnomeFontFace *face;
GnomeGlyphList *glyph_list;
GSList *extra_attrs_list;
PangoFontDescription *desc;
PangoGlyphItem *item;
PangoRectangle logical_rect, ink_rect, rect;
PangoLayout *layout;
ArtDRect art_rect;
const char *text = pango_layout_get_text (pl);
gboolean foreground_set;
guint16 foreground_red = 0, foreground_green = 0, foreground_blue = 0;
gboolean background_set;
guint16 background_red = 0, background_green = 0, background_blue = 0;
PangoLayoutIter *iter = pango_layout_get_iter (pl);
gdouble scale[6] = {1., 0., 0., 1., 0., 0.};
gdouble hscale, space;
gboolean strikethrough, underline, slant;
GtkTextAppearance* appearance;
int underline_type;
PangoAlignment align = pango_layout_get_alignment (pl);
double zoom;
pango_layout_get_extents (pl, NULL, &logical_rect);
gnome_print_gsave (gpc);
switch (align) {
case PANGO_ALIGN_CENTER:
gnome_print_translate (gpc, - (double) logical_rect.width / 2., 0.);
break;
case PANGO_ALIGN_RIGHT:
gnome_print_translate (gpc, - (double) logical_rect.width, 0.);
break;
default:
break;
}
do {
item = pango_layout_iter_get_run (iter);
if (!item) break;
strikethrough = underline = foreground_set = background_set = FALSE;
appearance = NULL;
desc = pango_font_describe (item->item->analysis.font);
face = gnome_font_face_find_closest_from_weight_slant (
pango_font_description_get_family (desc),
(GnomeFontWeight) pango_font_description_get_weight (desc),
(pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL));
font = gnome_font_face_get_font (face,
pango_font_description_get_size(desc) / PANGO_SCALE, 72, 72);
if (font == NULL)
{
g_warning ("No font file for font.");
continue;
}
glyph_list = gnome_glyphlist_new ();
extra_attrs_list = item->item->analysis.extra_attrs;
top = pango_layout_iter_get_baseline(iter) / PANGO_SCALE;
pango_layout_iter_get_char_extents (iter, &logical_rect);
bottom = 0;
while (extra_attrs_list)
{
PangoAttribute *attr = extra_attrs_list->data;
PangoAttrType attr_type = attr->klass->type;
switch (attr_type) {
case PANGO_ATTR_STYLE:
g_warning("style");
break;
case PANGO_ATTR_RISE:
bottom = ((PangoAttrInt *) attr)->value / PANGO_SCALE;
break;
case PANGO_ATTR_FOREGROUND:
foreground_set = TRUE;
foreground_red = ((PangoAttrColor *) attr)->color.red;
foreground_green = ((PangoAttrColor *) attr)->color.green;
foreground_blue = ((PangoAttrColor *) attr)->color.blue;
break;
case PANGO_ATTR_BACKGROUND:
background_set = TRUE;
background_red = ((PangoAttrColor *) attr)->color.red;
background_green = ((PangoAttrColor *) attr)->color.green;
background_blue = ((PangoAttrColor *) attr)->color.blue;
break;
case PANGO_ATTR_UNDERLINE:
underline_type = ((PangoAttrInt *) attr)->value;
underline = TRUE;
break;
case PANGO_ATTR_STRIKETHROUGH:
strikethrough = TRUE;
break;
case PANGO_ATTR_SHAPE:
g_warning ("Pango attribute PANGO_ATTR_SHAPE not supported", attr_type);
break;
case PANGO_ATTR_SCALE:
g_warning ("Pango attribute PANGO_ATTR_SCALE not supported", attr_type);
break;
default:
if (attr_type == gtk_text_attr_appearance_type)
appearance = &((GtkTextAttrAppearance *)attr)->appearance;
break;
}
extra_attrs_list = extra_attrs_list->next;
}
pango_layout_iter_get_run_extents (iter, &ink_rect, &logical_rect);
layout = pango_layout_new (pango_layout_get_context (pl));
pango_layout_set_font_description (layout, desc);
pango_layout_set_text (layout, text + item->item->offset, item->item->length);
pango_layout_get_extents (layout, &rect, NULL);
g_object_unref (layout);
if (background_set)
{
gnome_print_setrgbcolor (gpc, (float) background_red / 0xFFFF,
(float) background_green / 0xFFFF, (float) background_blue / 0xFFFF);
gnome_print_rect_filled (gpc, logical_rect.x / PANGO_SCALE,
logical_rect.y / PANGO_SCALE,
(float) logical_rect.width / PANGO_SCALE,
(float) + logical_rect.height / PANGO_SCALE);
}
gnome_print_setrgbcolor (gpc, (float) foreground_red / 0xFFFF,
(float) foreground_green / 0xFFFF, (float) foreground_blue / 0xFFFF);
if (strikethrough || (appearance && appearance->strikethrough)) {
gnome_print_setlinewidth (gpc, .75);
gnome_print_setlinecap (gpc, 0);
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top - (0.22 * logical_rect.height) / PANGO_SCALE);
gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- bottom + top - (0.22 * logical_rect.height) / PANGO_SCALE);
gnome_print_stroke (gpc);
}
if (underline) {
gnome_print_setlinewidth (gpc, .75);
gnome_print_setlinecap (gpc, 0);
switch (underline_type) {
case PANGO_UNDERLINE_NONE:
break;
case PANGO_UNDERLINE_DOUBLE:
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top + 3.0);
gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- bottom + top + 3.0);
gnome_print_stroke (gpc);
/* Fall through */
case PANGO_UNDERLINE_SINGLE:
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top + 1.0);
gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- bottom + top + 1.0);
gnome_print_stroke (gpc);
break;
case PANGO_UNDERLINE_LOW:
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top + logical_rect.y / PANGO_SCALE + 1.0);
gnome_print_lineto (gpc, (logical_rect.x + logical_rect.width) / PANGO_SCALE,
- bottom + top + logical_rect.y / PANGO_SCALE + 1.0);
gnome_print_stroke (gpc);
break;
}
}
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top);
gnome_glyphlist_font (glyph_list, font);
for (i = 0; i < item->glyphs->num_glyphs; i++)
{
gnome_glyphlist_glyph (glyph_list, item->glyphs->glyphs[i].glyph);
}
gnome_glyphlist_bbox (glyph_list, scale, 0, &art_rect);
slant = (pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL) && !gnome_font_face_is_italic (face);
zoom = ((double) ink_rect.height) / PANGO_SCALE / (art_rect.y1 - art_rect.y0);
if (item->glyphs->num_glyphs > 1) {
space = (((double) ink_rect.width / PANGO_SCALE / zoom - art_rect.x1 + art_rect.x0) - ((slant)? top * 0.15 / zoom: 0.))
/ item->glyphs->num_glyphs;
gnome_glyphlist_unref (glyph_list);
glyph_list = gnome_glyphlist_new ();
gnome_print_moveto (gpc, logical_rect.x / PANGO_SCALE,
- bottom + top);
gnome_glyphlist_font (glyph_list, font);
gnome_glyphlist_letterspace (glyph_list, space);
for (i = 0; i < item->glyphs->num_glyphs; i++)
{
gnome_glyphlist_glyph (glyph_list, item->glyphs->glyphs[i].glyph);
}
}
gnome_print_gsave(gpc);
if (slant) {
/*simulate slanted font*/
double matrix [6] = {
zoom,
0., .15 * zoom, -zoom, .0, .0};
gnome_print_concat (gpc, matrix);
} else
gnome_print_scale(gpc, zoom, -zoom);
gnome_print_glyphlist (gpc, glyph_list);
gnome_print_grestore(gpc);
gnome_glyphlist_unref (glyph_list);
} while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
gnome_print_grestore (gpc);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1