Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / gschem / src / gschem_pango.c
blobffa2994b4f798a1f78744a1678c99a380c7552fb
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 2008-2010 gEDA Contributors (see ChangeLog for details)
4 * Copyright (C) 2000 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * This file based on GDK's gdkpango.c (LGPL V2+)
22 * Copyright (C) 2000 Red Hat, Inc.
25 #include <config.h>
27 #include "gschem.h"
29 #include <math.h>
30 #include <pango/pangocairo.h>
31 #include <gschem_pango.h>
33 #define MAGIC_OVERBAR_POS_CONSTANT 0.8
35 struct _GschemPangoRendererPrivate
37 cairo_surface_t *surface;
39 /* GschemPangoRenderer specific state */
40 gboolean overbar;
42 cairo_t *cr;
45 static PangoAttrType gschem_pango_attr_overbar_type;
47 enum {
48 PROP_0,
49 PROP_CR
52 G_DEFINE_TYPE (GschemPangoRenderer, gschem_pango_renderer, PANGO_TYPE_RENDERER)
54 static void
55 gschem_pango_renderer_finalize (GObject *object)
57 G_OBJECT_CLASS (gschem_pango_renderer_parent_class)->finalize (object);
60 static GObject*
61 gschem_pango_renderer_constructor (GType type,
62 guint n_construct_properties,
63 GObjectConstructParam *construct_params)
65 GObject *object;
66 GschemPangoRenderer *gschem_renderer;
68 object = G_OBJECT_CLASS (gschem_pango_renderer_parent_class)->constructor (type,
69 n_construct_properties,
70 construct_params);
72 gschem_renderer = GSCHEM_PANGO_RENDERER (object);
74 if (gschem_renderer->priv->cr == NULL) {
75 g_warning ("Cairo context must be specified at construct time for GschemPangoRenderer");
78 return object;
81 static cairo_t *
82 get_cairo_context (GschemPangoRenderer *gschem_renderer,
83 PangoRenderPart part)
85 GschemPangoRendererPrivate *priv = gschem_renderer->priv;
87 return priv->cr;
90 static void
91 gschem_pango_renderer_draw_glyphs (PangoRenderer *renderer,
92 PangoFont *font,
93 PangoGlyphString *glyphs,
94 int x,
95 int y)
97 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
98 GschemPangoRendererPrivate *priv = gschem_renderer->priv;
99 cairo_t *cr;
101 cr = get_cairo_context (gschem_renderer,
102 PANGO_RENDER_PART_FOREGROUND);
105 if (priv->overbar) {
106 double rx, ry, rwidth, rheight, cheight;
107 PangoFontMetrics *metrics;
108 PangoRectangle logical;
109 int underline_thickness;
111 /* Make the thickness the same as for the font's underline */
112 metrics = pango_font_get_metrics (font, NULL);
113 underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
114 pango_font_metrics_unref (metrics);
116 pango_glyph_string_extents (glyphs, font, NULL, &logical);
118 rx = x;
119 ry = y - logical.height * MAGIC_OVERBAR_POS_CONSTANT;
120 rwidth = logical.width;
121 rheight = underline_thickness;
123 cheight = rheight / PANGO_SCALE;
125 /* Allow the overbar to fade out as it becomes < 1px high */
126 if (cheight > 1.0)
127 cheight = (int)(cheight);
129 /* \note The +1 on width is a hack to ensure hinting doesn't
130 * sometimes cause the overbars to be broken by a 1px gap
131 * if the overbar spans multiple calls to this function.
133 cairo_rectangle (cr,
134 (int)(rx / PANGO_SCALE), (int)(ry / PANGO_SCALE),
135 (int)(rwidth / PANGO_SCALE) + 1, cheight);
136 cairo_fill (cr);
139 cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
140 pango_cairo_show_glyph_string (cr, font, glyphs);
143 static void
144 gschem_pango_renderer_draw_rectangle (PangoRenderer *renderer,
145 PangoRenderPart part,
146 int x,
147 int y,
148 int width,
149 int height)
151 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
152 cairo_t *cr;
154 cr = get_cairo_context (gschem_renderer, part);
156 cairo_rectangle (cr,
157 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
158 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
159 cairo_fill (cr);
162 static void
163 gschem_pango_renderer_draw_error_underline (PangoRenderer *renderer,
164 int x,
165 int y,
166 int width,
167 int height)
169 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
170 cairo_t *cr;
172 cr = get_cairo_context (gschem_renderer, PANGO_RENDER_PART_UNDERLINE);
174 pango_cairo_show_error_underline (cr,
175 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
176 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
179 static void
180 gschem_pango_renderer_part_changed (PangoRenderer *renderer,
181 PangoRenderPart part)
185 static void
186 gschem_pango_renderer_begin (PangoRenderer *renderer)
190 static void
191 gschem_pango_renderer_end (PangoRenderer *renderer)
195 static void
196 gschem_pango_renderer_prepare_run (PangoRenderer *renderer,
197 PangoLayoutRun *run)
199 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
200 gboolean overbar = FALSE;
201 gboolean changed = FALSE;
202 GSList *l;
204 for (l = run->item->analysis.extra_attrs; l; l = l->next) {
205 PangoAttribute *attr = l->data;
207 /* overbar_type isn't necessarily initialized, but it is 0,
208 * which is an invalid type so won't occur.
210 if (attr->klass->type == gschem_pango_attr_overbar_type) {
211 overbar = ((GschemPangoAttrOverbar*)attr)->overbar;
215 if (overbar != gschem_renderer->priv->overbar) {
216 gschem_renderer->priv->overbar = overbar;
217 changed = TRUE;
220 if (changed)
221 pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
223 PANGO_RENDERER_CLASS (gschem_pango_renderer_parent_class)->prepare_run (renderer, run);
226 static void
227 gschem_pango_renderer_set_property (GObject *object, guint prop_id,
228 const GValue *value, GParamSpec *pspec)
230 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (object);
232 switch (prop_id) {
233 case PROP_CR:
234 gschem_renderer->priv->cr = g_value_get_pointer (value);
235 break;
236 default:
237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
238 break;
242 static void
243 gschem_pango_renderer_get_property (GObject *object, guint prop_id,
244 GValue *value, GParamSpec *pspec)
246 GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (object);
248 switch (prop_id) {
249 case PROP_CR:
250 g_value_set_pointer (value, gschem_renderer->priv->cr);
251 break;
252 default:
253 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
254 break;
258 static void
259 gschem_pango_renderer_init (GschemPangoRenderer *renderer)
261 renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
262 GSCHEM_TYPE_PANGO_RENDERER,
263 GschemPangoRendererPrivate);
266 static void
267 gschem_pango_renderer_class_init (GschemPangoRendererClass *klass)
269 GObjectClass *object_class = G_OBJECT_CLASS (klass);
271 PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
273 renderer_class->draw_glyphs = gschem_pango_renderer_draw_glyphs;
274 renderer_class->draw_rectangle = gschem_pango_renderer_draw_rectangle;
275 renderer_class->draw_error_underline = gschem_pango_renderer_draw_error_underline;
276 renderer_class->part_changed = gschem_pango_renderer_part_changed;
277 renderer_class->begin = gschem_pango_renderer_begin;
278 renderer_class->end = gschem_pango_renderer_end;
279 renderer_class->prepare_run = gschem_pango_renderer_prepare_run;
281 object_class->finalize = gschem_pango_renderer_finalize;
282 object_class->constructor = gschem_pango_renderer_constructor;
283 object_class->set_property = gschem_pango_renderer_set_property;
284 object_class->get_property = gschem_pango_renderer_get_property;
286 g_object_class_install_property (object_class,
287 PROP_CR,
288 g_param_spec_pointer ("cr",
289 _("cairo context"),
290 _("the cairo context for the renderer"),
291 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
292 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
293 G_PARAM_STATIC_BLURB));
295 g_type_class_add_private (object_class, sizeof (GschemPangoRendererPrivate));
299 * \brief Create a new PangoRenderer
301 * Create a new #PangoRenderer. Normally you can use the results
302 * of gschem_pango_renderer_get_default() rather than creating a new renderer.
304 * \param [in] cr a cairo renderer
305 * \return a newly created #PangoRenderer. Free with g_object_unref().
307 PangoRenderer *
308 gschem_pango_renderer_new (cairo_t *cr)
310 return g_object_new (GSCHEM_TYPE_PANGO_RENDERER, "cr", cr, NULL);
313 void
314 gschem_pango_show_layout (cairo_t *cr,
315 PangoLayout *pl)
317 static PangoRenderer *renderer = NULL;
318 static cairo_t *cr_cache = NULL;
319 double x_off, y_off;
321 if (cr_cache != cr && renderer != NULL) {
322 g_object_unref (renderer);
323 renderer = NULL;
326 if (renderer == NULL) {
327 renderer = gschem_pango_renderer_new (cr);
328 cr_cache = cr;
331 cairo_get_current_point (cr, &x_off, &y_off);
333 pango_renderer_draw_layout (renderer, pl, x_off * PANGO_SCALE, y_off * PANGO_SCALE);
337 /* GschemPangoAttrOverbar */
339 static PangoAttribute *
340 gschem_pango_attr_overbar_copy (const PangoAttribute *attr)
342 const GschemPangoAttrOverbar *e = (const GschemPangoAttrOverbar*) attr;
344 return gschem_pango_attr_overbar_new (e->overbar);
347 static void
348 gschem_pango_attr_overbar_destroy (PangoAttribute *attr)
350 g_free (attr);
353 static gboolean
354 gschem_pango_attr_overbar_compare (const PangoAttribute *attr1,
355 const PangoAttribute *attr2)
357 const GschemPangoAttrOverbar *e1 = (const GschemPangoAttrOverbar*) attr1;
358 const GschemPangoAttrOverbar *e2 = (const GschemPangoAttrOverbar*) attr2;
360 return e1->overbar == e2->overbar;
364 * Creates a new attribute flagging a region as being drawn with overbar or not
366 * \param [in] overbar if the region should be drawn with an overbar
367 * \return a new #PangoAttribute
369 PangoAttribute *
370 gschem_pango_attr_overbar_new (gboolean overbar)
372 GschemPangoAttrOverbar *result;
374 static PangoAttrClass klass = { 0,
375 gschem_pango_attr_overbar_copy,
376 gschem_pango_attr_overbar_destroy,
377 gschem_pango_attr_overbar_compare };
379 if (!klass.type)
380 klass.type = gschem_pango_attr_overbar_type =
381 pango_attr_type_register ("GschemPangoAttrOverbar");
383 result = g_new (GschemPangoAttrOverbar, 1);
384 result->attr.klass = &klass;
385 result->overbar = overbar;
387 return (PangoAttribute *)result;