[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: gaf.git: branch: master updated (1.5.2-20090328-202-gf8a0f1c)



The branch, master has been updated
       via  f8a0f1c1b5fd42c78a7165dcfa4b5135790a24a5 (commit)
       via  e9a944c1525228fbe80b0adc3910949d650a100c (commit)
       via  21be5c504a4a48da63526fce53cce00a9a76a1eb (commit)
       via  391eb25cb8e426df8f57fac2dc2d6e3515ff2acf (commit)
      from  b9adcffad55d8f6a5633afb79b9522ba840bda22 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gschem/include/Makefile.am     |    1 +
 gschem/include/gschem.h        |    1 +
 gschem/include/gschem_pango.h  |   96 +++++++++
 gschem/include/gschem_struct.h |    2 +
 gschem/include/prototype.h     |    3 +-
 gschem/src/Makefile.am         |    1 +
 gschem/src/gschem.c            |    3 +
 gschem/src/gschem_pango.c      |  390 ++++++++++++++++++++++++++++++++++++
 gschem/src/gschem_toplevel.c   |    1 +
 gschem/src/i_callbacks.c       |    2 +
 gschem/src/o_text.c            |  431 +++++++++++++++++++++++++++++++++++-----
 gschem/src/x_event.c           |    2 +
 gschem/src/x_image.c           |    2 +
 gschem/src/x_preview.c         |    5 +
 14 files changed, 887 insertions(+), 53 deletions(-)
 create mode 100644 gschem/include/gschem_pango.h
 create mode 100644 gschem/src/gschem_pango.c


=================
 Commit Messages
=================

commit e9a944c1525228fbe80b0adc3910949d650a100c
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    gschem: Register a function with libgeda to provide accurate text bounds
    
    This allows invalidating a text object to use the correct region and,
    importantly, allows us to find accurately which text objects were need
    repainting if a given area of screen is damaged.

:100644 100644 224c07b... 81e6a3b... M	gschem/include/prototype.h
:100644 100644 718843b... 210f64c... M	gschem/src/gschem.c
:100644 100644 2c3a7ec... bce47fc... M	gschem/src/i_callbacks.c
:100644 100644 77af6b4... 7d5b783... M	gschem/src/o_text.c
:100644 100644 16b4d54... b4a6653... M	gschem/src/x_preview.c

commit 21be5c504a4a48da63526fce53cce00a9a76a1eb
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    gschem: Add custom pango renderer to handle overbars

:100644 100644 dda9158... 00b553d... M	gschem/include/Makefile.am
:100644 100644 3dabd30... ad69118... M	gschem/include/gschem.h
:000000 100644 0000000... 97f75c9... A	gschem/include/gschem_pango.h
:100644 100644 75d2047... 71a43e4... M	gschem/src/Makefile.am
:000000 100644 0000000... 2a2821e... A	gschem/src/gschem_pango.c
:100644 100644 b3f8d79... 77af6b4... M	gschem/src/o_text.c

commit 391eb25cb8e426df8f57fac2dc2d6e3515ff2acf
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    Attempt drawing text with cairo + pango
    
    We use libgeda's o_text_get_font_size_in_points() to try and match old
    gEDA font sizes. This scaling factor of 1.3 applied to the font size
    defined in the schematic reflects the fact that gEDA's old font at
    given nominal point size, is larger than most other fonts at nominally
    the same size.
    
    This (may) be due to the cap height of gEDA's font being designed to
    match its design height, rather than having the baseline height of the
    font match the design height.

:100644 100644 4ae55b7... f921fb6... M	gschem/include/gschem_struct.h
:100644 100644 0a43389... 224c07b... M	gschem/include/prototype.h
:100644 100644 c2dd999... 429eca6... M	gschem/src/gschem_toplevel.c
:100644 100644 0a2b888... b3f8d79... M	gschem/src/o_text.c
:100644 100644 5201876... 203068a... M	gschem/src/x_event.c
:100644 100644 61d3270... b088f2e... M	gschem/src/x_image.c
:100644 100644 a9c87f1... 16b4d54... M	gschem/src/x_preview.c

=========
 Changes
=========

commit e9a944c1525228fbe80b0adc3910949d650a100c
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    gschem: Register a function with libgeda to provide accurate text bounds
    
    This allows invalidating a text object to use the correct region and,
    importantly, allows us to find accurately which text objects were need
    repainting if a given area of screen is damaged.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 224c07b..81e6a3b 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -708,6 +708,7 @@ void o_select_move_to_place_list(GSCHEM_TOPLEVEL *w_current);
 void o_slot_start(GSCHEM_TOPLEVEL *w_current, OBJECT *object);
 void o_slot_end(GSCHEM_TOPLEVEL *w_current, const char *string, int len);
 /* o_text.c */
+int o_text_get_rendered_bounds(void *user_data, OBJECT *object, int *min_x, int *min_y, int *max_x, int *max_y);
 void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw_place(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current);
 void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text);
diff --git a/gschem/src/gschem.c b/gschem/src/gschem.c
index 718843b..210f64c 100644
--- a/gschem/src/gschem.c
+++ b/gschem/src/gschem.c
@@ -229,6 +229,9 @@ void main_prog(void *closure, int argc, char *argv[])
   w_current->toplevel->load_newer_backup_func = x_fileselect_load_backup;
   w_current->toplevel->load_newer_backup_data = w_current;
 
+  o_text_set_rendered_bounds_func (w_current->toplevel,
+                                   o_text_get_rendered_bounds, w_current);
+
   /* Now read in RC files. */
   g_rc_parse_gtkrc();
   g_rc_parse(w_current->toplevel, "gschemrc", rc_filename);
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index 2c3a7ec..bce47fc 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -156,6 +156,8 @@ DEFINE_I_CALLBACK(file_new_window)
   w_current->toplevel->load_newer_backup_func = x_fileselect_load_backup;
   w_current->toplevel->load_newer_backup_data = w_current;
 
+  o_text_set_rendered_bounds_func (w_current->toplevel,
+                                   o_text_get_rendered_bounds, w_current);
   x_window_setup (w_current);
 
   page = x_window_open_page (w_current, NULL);
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index 77af6b4..7d5b783 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -193,6 +193,105 @@ static PangoFontMetrics *setup_pango_return_metrics (GSCHEM_TOPLEVEL *w_current,
 }
 
 
+static void rotate_vector (double x, double y, double angle,
+                           double *rx, double *ry)
+{
+  double costheta = cos (angle * M_PI / 180.);
+  double sintheta = sin (angle * M_PI / 180.);
+
+  *rx = costheta * x - sintheta * y;
+  *ry = sintheta * x + costheta * y;
+}
+
+
+static void expand_bounds (int *left, int *top, int *right, int *bottom,
+                           int new_x, int new_y)
+{
+  *left =   MIN (*left,   new_x);
+  *right =  MAX (*right,  new_x);
+  *top =    MIN (*top,    new_y);
+  *bottom = MAX (*bottom, new_y);
+}
+
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+int o_text_get_rendered_bounds (void *user_data, OBJECT *o_current,
+                                int *min_x, int *min_y,
+                                int *max_x, int *max_y)
+{
+  GSCHEM_TOPLEVEL *w_current = user_data;
+  TOPLEVEL *toplevel = w_current->toplevel;
+  PangoLayout *layout;
+  cairo_t *cr;
+  double x, y;
+  PangoFontMetrics *font_metrics;
+  PangoRectangle logical_rect;
+  PangoRectangle inked_rect;
+  int angle;
+  double rx, ry;
+  double tleft, ttop, tright, tbottom;
+  int left, right, top, bottom;
+
+  g_return_val_if_fail (o_current != NULL, FALSE);
+  g_return_val_if_fail (o_current->text != NULL, FALSE);
+
+  if (o_current->visibility == INVISIBLE &&
+      !toplevel->show_hidden_text)
+    return FALSE;
+
+  if (o_current->text->disp_string == NULL)
+    return FALSE;
+
+  cr = gdk_cairo_create (w_current->drawable);
+  layout = pango_cairo_create_layout (cr);
+
+  font_metrics = setup_pango_return_metrics (w_current, layout, 1., o_current);
+
+  pango_layout_get_pixel_extents (layout, &inked_rect, &logical_rect);
+  calculate_position (o_current, font_metrics, logical_rect, inked_rect, &x, &y);
+  pango_font_metrics_unref (font_metrics);
+
+  tleft = x + inked_rect.x;
+  tright = x + inked_rect.x + inked_rect.width;
+  /* Deliberately include bounds up to the height of the logical rect,
+   * since we draw overbars in that space. In the unlikely event that
+   * the inked rect extends above the logical (inked_rect.y is -ve),
+   * do take that into account.
+   */
+  ttop = -y - (inked_rect.y < 0 ? inked_rect.y : 0.);
+  tbottom = -y - inked_rect.y - inked_rect.height;
+
+  angle = o_current->text->angle;
+  /* Special case turns upside down text back upright */
+  if (angle == 180)
+    angle = 0;
+
+  rotate_vector (tleft, ttop, angle, &rx, &ry);
+  left = right = rx;
+  top = bottom = ry;
+  rotate_vector (tright, ttop, angle, &rx, &ry);
+  expand_bounds (&left, &top, &right, &bottom, rx, ry);
+  rotate_vector (tleft, tbottom, angle, &rx, &ry);
+  expand_bounds (&left, &top, &right, &bottom, rx, ry);
+  rotate_vector (tright, tbottom, angle, &rx, &ry);
+  expand_bounds (&left, &top, &right, &bottom, rx, ry);
+
+  *min_x = o_current->text->x + left;
+  *max_x = o_current->text->x + right;
+  *min_y = o_current->text->y + top;
+  *max_y = o_current->text->y + bottom;
+
+  g_object_unref (layout);
+  cairo_destroy (cr);
+
+  return TRUE;
+}
+
+
 #ifdef DEBUG_TEXT
 static void draw_construction_lines (GSCHEM_TOPLEVEL *w_current,
                                      double x, double y,
diff --git a/gschem/src/x_preview.c b/gschem/src/x_preview.c
index 16b4d54..b4a6653 100644
--- a/gschem/src/x_preview.c
+++ b/gschem/src/x_preview.c
@@ -368,6 +368,9 @@ preview_init (Preview *preview)
     x_fileselect_load_backup;
   preview_w_current->toplevel->load_newer_backup_data =
     preview_w_current;
+  o_text_set_rendered_bounds_func (preview_w_current->toplevel,
+                                   o_text_get_rendered_bounds,
+                                   preview_w_current);
 
   i_vars_set (preview_w_current);
 

commit 21be5c504a4a48da63526fce53cce00a9a76a1eb
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    gschem: Add custom pango renderer to handle overbars

diff --git a/gschem/include/Makefile.am b/gschem/include/Makefile.am
index dda9158..00b553d 100644
--- a/gschem/include/Makefile.am
+++ b/gschem/include/Makefile.am
@@ -12,6 +12,7 @@ noinst_HEADERS = \
 	gschem_action.h \
 	gschem_defines.h \
 	gschem_dialog.h \
+	gschem_pango.h \
 	gschem_struct.h
 
 MOSTLYCLEANFILES = *.log core FILE *~
diff --git a/gschem/include/gschem.h b/gschem/include/gschem.h
index 3dabd30..ad69118 100644
--- a/gschem/include/gschem.h
+++ b/gschem/include/gschem.h
@@ -10,6 +10,7 @@
 #include "gschem_accel_label.h"
 #include "gschem_action.h"
 #include "gschem_dialog.h"
+#include "gschem_pango.h"
 #include "i_vars.h"
 #include "x_preview.h"
 #include "x_compselect.h"
diff --git a/gschem/include/gschem_pango.h b/gschem/include/gschem_pango.h
new file mode 100644
index 0000000..97f75c9
--- /dev/null
+++ b/gschem/include/gschem_pango.h
@@ -0,0 +1,96 @@
+/* gEDA - GPL Electronic Design Automation
+ * gschem - gEDA Schematic Capture
+ * Copyright (C) 2008 gEDA Contributors (see ChangeLog for details)
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * 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 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * This file based on GDK's gdkpango.h (LGPL V2+)
+ * Copyright (C) 2000 Red Hat, Inc.
+ */
+
+#ifndef __GSCHEM_PANGO_H__
+#define __GSCHEM_PANGO_H__
+
+#include <gdk/gdktypes.h>
+
+G_BEGIN_DECLS
+
+/* Pango interaction */
+
+typedef struct _GschemPangoRenderer        GschemPangoRenderer;
+typedef struct _GschemPangoRendererClass   GschemPangoRendererClass;
+typedef struct _GschemPangoRendererPrivate GschemPangoRendererPrivate;
+
+#define GSCHEM_TYPE_PANGO_RENDERER            (gschem_pango_renderer_get_type())
+#define GSCHEM_PANGO_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GSCHEM_TYPE_PANGO_RENDERER, GschemPangoRenderer))
+#define GSCHEM_IS_PANGO_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GSCHEM_TYPE_PANGO_RENDERER))
+#define GSCHEM_PANGO_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSCHEM_TYPE_PANGO_RENDERER, GschemPangoRendererClass))
+#define GSCHEM_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSCHEM_TYPE_PANGO_RENDERER))
+#define GSCHEM_PANGO_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GSCHEM_TYPE_PANGO_RENDERER, GschemPangoRendererClass))
+
+/**
+ * GschemPangoRenderer:
+ *
+ * #GschemPangoRenderer is a subclass of #PangoRenderer used for rendering
+ * text of gschem TEXT objects.
+ *
+ * Pango functions like pango_renderer_draw_layout() and
+ * pango_renderer_draw_layout_line() are then used to draw objects with
+ * the renderer.
+ **/
+struct _GschemPangoRenderer
+{
+  /*< private >*/
+  PangoRenderer parent_instance;
+
+  GschemPangoRendererPrivate *priv;
+};
+
+
+struct _GschemPangoRendererClass
+{
+  /*< private >*/
+  PangoRendererClass parent_class;
+};
+
+GType gschem_pango_renderer_get_type (void) G_GNUC_CONST;
+
+PangoRenderer *gschem_pango_renderer_new      (cairo_t *cr);
+
+void gschem_pango_show_layout                 (cairo_t     *cr,
+                                               PangoLayout *pl);
+
+void gschem_pango_renderer_set_overbar        (GschemPangoRenderer *gdk_renderer,
+                                               gboolean             overbar);
+
+/************************************************************************/
+
+/* Attributes use to render text with overbars */
+
+typedef struct _GschemPangoAttrOverbar GschemPangoAttrOverbar;
+
+struct _GschemPangoAttrOverbar
+{
+  PangoAttribute attr;
+  gboolean overbar;
+};
+
+PangoAttribute *gschem_pango_attr_overbar_new (gboolean overbar);
+
+G_END_DECLS
+
+#endif /* __GSCHEM_PANGO_H__ */
diff --git a/gschem/src/Makefile.am b/gschem/src/Makefile.am
index 75d2047..71a43e4 100644
--- a/gschem/src/Makefile.am
+++ b/gschem/src/Makefile.am
@@ -14,6 +14,7 @@ gschem_SOURCES = \
 	gschem_action.c \
 	gschem_cairo.c \
 	gschem_dialog.c \
+	gschem_pango.c \
 	gschem_toplevel.c \
 	i_basic.c \
 	i_callbacks.c \
diff --git a/gschem/src/gschem_pango.c b/gschem/src/gschem_pango.c
new file mode 100644
index 0000000..2a2821e
--- /dev/null
+++ b/gschem/src/gschem_pango.c
@@ -0,0 +1,390 @@
+/* gEDA - GPL Electronic Design Automation
+ * gschem - gEDA Schematic Capture
+ * Copyright (C) 2008 gEDA Contributors (see ChangeLog for details)
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * 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 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * This file based on GDK's gdkpango.c (LGPL V2+)
+ * Copyright (C) 2000 Red Hat, Inc.
+ */
+
+#include <config.h>
+
+#include "gschem.h"
+
+#include <math.h>
+#include <pango/pangocairo.h>
+#include <gschem_pango.h>
+
+#define MAGIC_OVERBAR_POS_CONSTANT 0.8
+
+struct _GschemPangoRendererPrivate
+{
+  cairo_surface_t *surface;
+
+  /* GschemPangoRenderer specific state */
+  gboolean overbar;
+
+  cairo_t *cr;
+};
+
+static PangoAttrType gschem_pango_attr_overbar_type;
+
+enum {
+  PROP_0,
+  PROP_CR
+};
+
+G_DEFINE_TYPE (GschemPangoRenderer, gschem_pango_renderer, PANGO_TYPE_RENDERER)
+
+static void
+gschem_pango_renderer_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gschem_pango_renderer_parent_class)->finalize (object);
+}
+
+static GObject*
+gschem_pango_renderer_constructor (GType                  type,
+                                   guint                  n_construct_properties,
+                                   GObjectConstructParam *construct_params)
+{
+  GObject *object;
+  GschemPangoRenderer *gschem_renderer;
+
+  object = G_OBJECT_CLASS (gschem_pango_renderer_parent_class)->constructor (type,
+                                                                             n_construct_properties,
+                                                                             construct_params);
+
+  gschem_renderer = GSCHEM_PANGO_RENDERER (object);
+
+  if (gschem_renderer->priv->cr == NULL) {
+    g_warning ("Cairo context must be specified at construct time for GschemPangoRenderer");
+  }
+
+  return object;
+}
+
+static cairo_t *
+get_cairo_context (GschemPangoRenderer *gschem_renderer,
+                   PangoRenderPart   part)
+{
+  GschemPangoRendererPrivate *priv = gschem_renderer->priv;
+
+  return priv->cr;
+}
+
+static void
+gschem_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
+                                   PangoFont        *font,
+                                   PangoGlyphString *glyphs,
+                                   int               x,
+                                   int               y)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
+  GschemPangoRendererPrivate *priv = gschem_renderer->priv;
+  cairo_t *cr;
+
+  cr = get_cairo_context (gschem_renderer,
+                          PANGO_RENDER_PART_FOREGROUND);
+
+
+  if (priv->overbar) {
+    double rx, ry, rwidth, rheight, cheight;
+    PangoFontMetrics *metrics;
+    PangoRectangle logical;
+    int underline_thickness;
+
+    /* Make the thickness the same as for the font's underline */
+    metrics = pango_font_get_metrics (font, NULL);
+    underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+    pango_font_metrics_unref (metrics);
+
+    pango_glyph_string_extents (glyphs, font, NULL, &logical);
+
+    rx = x;
+    ry = y - logical.height * MAGIC_OVERBAR_POS_CONSTANT;
+    rwidth = logical.width;
+    rheight = underline_thickness;
+
+    cheight = rheight / PANGO_SCALE;
+
+    /* Allow the overbar to fade out as it becomes < 1px high */
+    if (cheight > 1.0)
+      cheight = (int)(cheight);
+
+    /* \note The +1 on width is a hack to ensure hinting doesn't
+     *       sometimes cause the overbars to be broken by a 1px gap
+     *       if the overbar spans multiple calls to this function.
+     */
+    cairo_rectangle (cr,
+                     (int)(rx / PANGO_SCALE), (int)(ry / PANGO_SCALE),
+                     (int)(rwidth / PANGO_SCALE) + 1, cheight);
+    cairo_fill (cr);
+  }
+
+  cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
+  pango_cairo_show_glyph_string (cr, font, glyphs);
+}
+
+static void
+gschem_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
+                                      PangoRenderPart   part,
+                                      int               x,
+                                      int               y,
+                                      int               width,
+                                      int               height)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
+  cairo_t *cr;
+
+  cr = get_cairo_context (gschem_renderer, part);
+
+  cairo_rectangle (cr,
+                   (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
+                   (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+  cairo_fill (cr);
+}
+
+static void
+gschem_pango_renderer_draw_error_underline (PangoRenderer    *renderer,
+                                            int               x,
+                                            int               y,
+                                            int               width,
+                                            int               height)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
+  cairo_t *cr;
+
+  cr = get_cairo_context (gschem_renderer, PANGO_RENDER_PART_UNDERLINE);
+
+  pango_cairo_show_error_underline (cr,
+        (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
+        (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+}
+
+static void
+gschem_pango_renderer_part_changed (PangoRenderer   *renderer,
+                                    PangoRenderPart  part)
+{
+}
+
+static void
+gschem_pango_renderer_begin (PangoRenderer *renderer)
+{
+}
+
+static void
+gschem_pango_renderer_end (PangoRenderer *renderer)
+{
+}
+
+static void
+gschem_pango_renderer_prepare_run (PangoRenderer  *renderer,
+                                   PangoLayoutRun *run)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
+  gboolean overbar = FALSE;
+  gboolean changed = FALSE;
+  GSList *l;
+
+  for (l = run->item->analysis.extra_attrs; l; l = l->next) {
+    PangoAttribute *attr = l->data;
+
+    /* overbar_type isn't necessarily initialized, but it is 0,
+     * which is an invalid type so won't occur.
+     */
+    if (attr->klass->type == gschem_pango_attr_overbar_type) {
+      overbar = ((GschemPangoAttrOverbar*)attr)->overbar;
+    }
+  }
+
+  if (overbar != gschem_renderer->priv->overbar) {
+    gschem_renderer->priv->overbar = overbar;
+    changed = TRUE;
+  }
+
+  if (changed)
+    pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
+
+  PANGO_RENDERER_CLASS (gschem_pango_renderer_parent_class)->prepare_run (renderer, run);
+}
+
+static void
+gschem_pango_renderer_set_property (GObject *object, guint prop_id,
+                                    const GValue *value, GParamSpec *pspec)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (object);
+
+  switch (prop_id) {
+    case PROP_CR:
+      gschem_renderer->priv->cr = g_value_get_pointer (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gschem_pango_renderer_get_property (GObject *object, guint prop_id,
+                                    GValue *value, GParamSpec *pspec)
+{
+  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (object);
+
+  switch (prop_id) {
+    case PROP_CR:
+      g_value_set_pointer (value, gschem_renderer->priv->cr);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gschem_pango_renderer_init (GschemPangoRenderer *renderer)
+{
+  renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
+                                                GSCHEM_TYPE_PANGO_RENDERER,
+                                                GschemPangoRendererPrivate);
+}
+
+static void
+gschem_pango_renderer_class_init (GschemPangoRendererClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+  renderer_class->draw_glyphs = gschem_pango_renderer_draw_glyphs;
+  renderer_class->draw_rectangle = gschem_pango_renderer_draw_rectangle;
+  renderer_class->draw_error_underline = gschem_pango_renderer_draw_error_underline;
+  renderer_class->part_changed = gschem_pango_renderer_part_changed;
+  renderer_class->begin = gschem_pango_renderer_begin;
+  renderer_class->end = gschem_pango_renderer_end;
+  renderer_class->prepare_run = gschem_pango_renderer_prepare_run;
+
+  object_class->finalize = gschem_pango_renderer_finalize;
+  object_class->constructor = gschem_pango_renderer_constructor;
+  object_class->set_property = gschem_pango_renderer_set_property;
+  object_class->get_property = gschem_pango_renderer_get_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_CR,
+                                   g_param_spec_pointer ("cr",
+                                                         _("cairo context"),
+                                                         _("the cairo context for the renderer"),
+                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+                                                         G_PARAM_STATIC_BLURB));
+
+  g_type_class_add_private (object_class, sizeof (GschemPangoRendererPrivate));
+}
+
+/*!
+ * gschem_pango_renderer_new:
+ * @cr: a #cairo renderer
+ *
+ * Creates a new #PangoRenderer for @cr. Normally you can use the results
+ * of gschem_pango_renderer_get_default() rather than creating a new renderer.
+ *
+ * Return value: a newly created #PangoRenderer. Free with g_object_unref().
+ */
+PangoRenderer *
+gschem_pango_renderer_new (cairo_t *cr)
+{
+  return g_object_new (GSCHEM_TYPE_PANGO_RENDERER, "cr", cr, NULL);
+}
+
+void
+gschem_pango_show_layout (cairo_t     *cr,
+                          PangoLayout *pl)
+{
+  static PangoRenderer *renderer = NULL;
+  static cairo_t *cr_cache = NULL;
+  double x_off, y_off;
+
+  if (cr_cache != cr && renderer != NULL) {
+    g_object_unref (renderer);
+    renderer = NULL;
+  }
+
+  if (renderer == NULL) {
+    renderer = gschem_pango_renderer_new (cr);
+    cr_cache = cr;
+  }
+
+  cairo_get_current_point (cr, &x_off, &y_off);
+
+  pango_renderer_draw_layout (renderer, pl, x_off * PANGO_SCALE, y_off * PANGO_SCALE);
+}
+
+
+/* GschemPangoAttrOverbar */
+
+static PangoAttribute *
+gschem_pango_attr_overbar_copy (const PangoAttribute *attr)
+{
+  const GschemPangoAttrOverbar *e = (const GschemPangoAttrOverbar*) attr;
+
+  return gschem_pango_attr_overbar_new (e->overbar);
+}
+
+static void
+gschem_pango_attr_overbar_destroy (PangoAttribute *attr)
+{
+  g_free (attr);
+}
+
+static gboolean
+gschem_pango_attr_overbar_compare (const PangoAttribute *attr1,
+                                   const PangoAttribute *attr2)
+{
+  const GschemPangoAttrOverbar *e1 = (const GschemPangoAttrOverbar*) attr1;
+  const GschemPangoAttrOverbar *e2 = (const GschemPangoAttrOverbar*) attr2;
+
+  return e1->overbar == e2->overbar;
+}
+
+/*!
+ * gschem_pango_attr_overbar_new:
+ * @overbar: if the region should be drawn with an overbar
+ *
+ * Creates a new attribute flagging a region as being drawn with overbar or not
+ *
+ * Return value: new #PangoAttribute
+ */
+PangoAttribute *
+gschem_pango_attr_overbar_new (gboolean overbar)
+{
+  GschemPangoAttrOverbar *result;
+
+  static PangoAttrClass klass = { 0,
+                                  gschem_pango_attr_overbar_copy,
+                                  gschem_pango_attr_overbar_destroy,
+                                  gschem_pango_attr_overbar_compare };
+
+  if (!klass.type)
+    klass.type = gschem_pango_attr_overbar_type =
+      pango_attr_type_register ("GschemPangoAttrOverbar");
+
+  result = g_new (GschemPangoAttrOverbar, 1);
+  result->attr.klass = &klass;
+  result->overbar = overbar;
+
+  return (PangoAttribute *)result;
+}
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index b3f8d79..77af6b4 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -46,6 +46,58 @@
 #undef DEBUG_TEXT
 
 
+char *unescape_text_and_overbars (char *text, PangoAttrList *attrs)
+{
+  char *p, *sp, *strip_text;
+  char *overbar_start = NULL;
+  int escape = FALSE;
+
+  /* The unescaped text is alwasys shorter than the original
+     string, so just allocate the same ammount of memory. */
+  sp = strip_text = g_malloc (strlen (text) + 1);
+
+  for (p = text; p != NULL; p++) {
+    int finish_overbar = FALSE;
+
+    /* If we find an escape character "\", we note it and continue looping */
+    if (!escape && *p == '\\') {
+      escape = TRUE;
+      continue;
+    }
+
+    if (escape && *p == '_') {
+      /* Overbar start or end sequence */
+      if (overbar_start != NULL) {
+        finish_overbar = TRUE;
+      } else {
+        overbar_start = sp;
+      }
+    } else {
+      /* just append the character, which may have been escaped */
+      *sp++ = *p;
+    }
+    escape = FALSE;
+
+    if (overbar_start != NULL &&
+        (finish_overbar || *p == '\0')) {
+      PangoAttribute *attr;
+
+      attr = gschem_pango_attr_overbar_new (TRUE);
+      attr->start_index = overbar_start - strip_text;
+      attr->end_index = sp - strip_text;
+      pango_attr_list_insert (attrs, attr);
+      overbar_start = NULL;
+    }
+
+    /* end of the string, stop iterating */
+    if (*p == '\0')
+      break;
+  }
+
+  return strip_text;
+}
+
+
 static void calculate_position (OBJECT *object,
                                 PangoFontMetrics *font_metrics,
                                 PangoRectangle logical_rect,
@@ -104,9 +156,11 @@ static PangoFontMetrics *setup_pango_return_metrics (GSCHEM_TOPLEVEL *w_current,
   PangoContext *context;
   PangoFontDescription *desc;
   PangoFontMetrics *font_metrics;
+  PangoAttrList *attrs;
   cairo_font_options_t *options;
   double font_size_pt;
   char *font_string;
+  char *unescaped;
 
   context = pango_layout_get_context (layout);
 
@@ -128,7 +182,12 @@ static PangoFontMetrics *setup_pango_return_metrics (GSCHEM_TOPLEVEL *w_current,
   font_metrics = pango_context_get_metrics (context, desc, NULL);
   pango_font_description_free (desc);
 
-  pango_layout_set_text (layout, o_current->text->disp_string, -1);
+  attrs = pango_attr_list_new ();
+  unescaped = unescape_text_and_overbars (o_current->text->disp_string, attrs);
+  pango_layout_set_text (layout, unescaped, -1);
+  g_free (unescaped);
+  pango_layout_set_attributes (layout, attrs);
+  pango_attr_list_unref (attrs);
 
   return font_metrics;
 }
@@ -259,7 +318,7 @@ static void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
    *     the grid lines, and ensures consistency with other lines when the
    *     page view is zoomed out. */
   cairo_move_to (cr, x + 0.5, y + 0.5);
-  pango_cairo_show_layout (cr, w_current->pl);
+  gschem_pango_show_layout (cr, w_current->pl);
 
 #ifdef DEBUG_TEXT
   draw_construction_lines (w_current, x, y, font_metrics, logical_rect);

commit 391eb25cb8e426df8f57fac2dc2d6e3515ff2acf
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    Attempt drawing text with cairo + pango
    
    We use libgeda's o_text_get_font_size_in_points() to try and match old
    gEDA font sizes. This scaling factor of 1.3 applied to the font size
    defined in the schematic reflects the fact that gEDA's old font at
    given nominal point size, is larger than most other fonts at nominally
    the same size.
    
    This (may) be due to the cap height of gEDA's font being designed to
    match its design height, rather than having the baseline height of the
    font match the design height.

diff --git a/gschem/include/gschem_struct.h b/gschem/include/gschem_struct.h
index 4ae55b7..f921fb6 100644
--- a/gschem/include/gschem_struct.h
+++ b/gschem/include/gschem_struct.h
@@ -79,6 +79,8 @@ struct st_gschem_toplevel {
   GdkWindow *window;                    /* drawing_area's X drawable */
   GdkPixmap *drawable;                  /* drawable to paint onto */
   cairo_t *cr;                          /* Cairo surface */
+  PangoLayout *pl;                      /* Pango layout */
+
   int win_width, win_height;            /* Actual size of window (?) */
 
   /* ------------- */
diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 0a43389..224c07b 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -708,8 +708,6 @@ void o_select_move_to_place_list(GSCHEM_TOPLEVEL *w_current);
 void o_slot_start(GSCHEM_TOPLEVEL *w_current, OBJECT *object);
 void o_slot_end(GSCHEM_TOPLEVEL *w_current, const char *string, int len);
 /* o_text.c */
-void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
-void o_text_draw_rectangle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw_place(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current);
 void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text);
diff --git a/gschem/src/gschem_toplevel.c b/gschem/src/gschem_toplevel.c
index c2dd999..429eca6 100644
--- a/gschem/src/gschem_toplevel.c
+++ b/gschem/src/gschem_toplevel.c
@@ -97,6 +97,7 @@ GSCHEM_TOPLEVEL *gschem_toplevel_new ()
   w_current->window = NULL;
   w_current->drawable = NULL;
   w_current->cr = NULL;
+  w_current->pl = NULL;
   w_current->win_width = 0;
   w_current->win_height = 0;
 
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index 0a2b888..b3f8d79 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -37,77 +37,239 @@
 
 #define MINIMUM_MARK_SMALL_DIST 1
 
+#if 1
+# define FONT_NAME "Arial"
+#else
+# define FONT_NAME "Helvetica"
+#endif
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
-{
-  TOPLEVEL *toplevel = w_current->toplevel;
-  int left, right, top, bottom;
+#undef DEBUG_TEXT
 
-  g_return_if_fail (o_current != NULL);
-  g_return_if_fail (o_current->text != NULL);
 
-  if (o_current->visibility == INVISIBLE && toplevel->show_hidden_text &&
-      o_current->text->prim_objs == NULL) {
-    o_text_recreate(toplevel, o_current);
+static void calculate_position (OBJECT *object,
+                                PangoFontMetrics *font_metrics,
+                                PangoRectangle logical_rect,
+                                PangoRectangle inked_rect,
+                                double *x, double *y)
+{
+  double temp;
+  double y_lower, y_middle, y_upper;
+  double x_left,  x_middle, x_right;
+  double descent = pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE;
+
+  x_left   = 0;
+  x_middle = -logical_rect.width / 2.;
+  x_right  = -logical_rect.width;
+
+  /*! \note Ideally, we would be using just font / logical metrics for vertical
+   *        alignment, however this way seems to be more backward compatible
+   *        with the old gschem rendering.
+   *
+   *        Lower alignment is at the baseline of the bottom text line, whereas
+   *        middle and upper alignment is based upon the inked extents of the
+   *        entire text block.
+   */
+  y_upper  = -inked_rect.y;                     /* Top of inked extents */
+  y_middle = y_upper - inked_rect.height / 2.;  /* Middle of inked extents */
+  y_lower  = descent - logical_rect.height;     /* Baseline of bottom line */
+
+  /* Special case flips attachment point to opposite corner when
+   * the text is rotated to 180 degrees, since the drawing code
+   * does not rotate the text to be shown upside down.
+   */
+  if (object->text->angle == 180) {
+    temp = y_lower; y_lower = y_upper; y_upper = temp;
+    temp = x_left;  x_left  = x_right; x_right = temp;
   }
-  
-  o_redraw(w_current, o_current->text->prim_objs, TRUE);
 
-  world_get_object_glist_bounds (toplevel, o_current->text->prim_objs,
-                                 &left, &top, &right, &bottom);
-  o_current->w_left   = left;
-  o_current->w_top    = top;
-  o_current->w_right  = right;
-  o_current->w_bottom = bottom;
+  switch (object->text->alignment) {
+    default:
+      /* Fall through to LOWER_left case */
+    case LOWER_LEFT:    *y = y_lower;  *x = x_left;   break;
+    case MIDDLE_LEFT:   *y = y_middle; *x = x_left;   break;
+    case UPPER_LEFT:    *y = y_upper;  *x = x_left;   break;
+    case LOWER_MIDDLE:  *y = y_lower;  *x = x_middle; break;
+    case MIDDLE_MIDDLE: *y = y_middle; *x = x_middle; break;
+    case UPPER_MIDDLE:  *y = y_upper;  *x = x_middle; break;
+    case LOWER_RIGHT:   *y = y_lower;  *x = x_right;  break;
+    case MIDDLE_RIGHT:  *y = y_middle; *x = x_right;  break;
+    case UPPER_RIGHT:   *y = y_upper;  *x = x_right;  break;
+  }
+}
 
+
+static PangoFontMetrics *setup_pango_return_metrics (GSCHEM_TOPLEVEL *w_current, PangoLayout *layout,
+                                                     double scale_factor, OBJECT *o_current)
+{
+  PangoContext *context;
+  PangoFontDescription *desc;
+  PangoFontMetrics *font_metrics;
+  cairo_font_options_t *options;
+  double font_size_pt;
+  char *font_string;
+
+  context = pango_layout_get_context (layout);
+
+  /* Switch off metric hinting, set medium outline hinting */
+  options = cairo_font_options_create ();
+  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+  cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_MEDIUM);
+  pango_cairo_context_set_font_options (context, options);
+  cairo_font_options_destroy (options);
+
+  pango_cairo_context_set_resolution (context, 1000. * scale_factor);
+  font_size_pt = o_text_get_font_size_in_points (w_current->toplevel,
+                                                 o_current);
+  font_string = g_strdup_printf ("%s %f\n", FONT_NAME, font_size_pt);
+  desc = pango_font_description_from_string (font_string);
+  g_free (font_string);
+
+  pango_layout_set_font_description (layout, desc);
+  font_metrics = pango_context_get_metrics (context, desc, NULL);
+  pango_font_description_free (desc);
+
+  pango_layout_set_text (layout, o_current->text->disp_string, -1);
+
+  return font_metrics;
 }
 
+
+#ifdef DEBUG_TEXT
+static void draw_construction_lines (GSCHEM_TOPLEVEL *w_current,
+                                     double x, double y,
+                                     PangoFontMetrics *font_metrics,
+                                     PangoRectangle logical_rect)
+{
+  double px = 1.;
+  double dashlength;
+  double ascent = pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE;
+  double descent = pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE;
+  cairo_t *cr = w_current->cr;
+
+  /* Pick an arbitrary size constant for the construction lines */
+  /* Includes * 10 factor for precision */
+  px = SCREENabs (w_current, 4 * 10);
+
+  /* Threshold the drawing to be above a certain size */
+  if (px < 2.)
+    return;
+
+  px = px / 10.;
+
+  /* baseline, descent, ascent, height */
+  cairo_set_line_width (cr, 2 * px);
+  dashlength = 9 * px;
+  cairo_set_dash (cr, &dashlength, 1, 0);
+
+  /* Underline logical text rect in green, y coord is as gschem text origin */
+  cairo_set_source_rgba (cr, 0, 0.6, 0, 0.5);
+  cairo_move_to (cr, x + logical_rect.x, y + ascent);
+  cairo_rel_line_to (cr, logical_rect.width, 0);
+  cairo_stroke (cr);
+
+  /* Underline descent height in red */
+  cairo_set_source_rgba (cr, 1, 0, 0, 1);
+  cairo_move_to (cr, x + logical_rect.x, y + ascent + descent);
+  cairo_rel_line_to (cr, logical_rect.width, 0);
+  cairo_stroke (cr);
+
+  /* Overbar ascent height in yellow */
+  cairo_set_source_rgba (cr, 1, 1, 0, 1);
+  cairo_move_to (cr, x + logical_rect.x, y);
+  cairo_rel_line_to (cr, logical_rect.width, 0);
+  cairo_stroke (cr);
+
+  /* extents: width & height in blue */
+  cairo_set_source_rgba (cr, 0, 0, 0.75, 0.5);
+  cairo_set_line_width (cr, px);
+  dashlength = 3 * px;
+  cairo_set_dash (cr, &dashlength, 1, 0);
+  cairo_rectangle (cr, x + logical_rect.x, y + logical_rect.y,
+                   logical_rect.width, logical_rect.height);
+  cairo_stroke (cr);
+
+  /* show layout origin point in black */
+  cairo_arc (cr, x, y, 3 * px, 0, 2 * M_PI);
+  cairo_set_source_rgba (cr, 0.0, 0, 0, 0.5);
+  cairo_fill (cr);
+
+  /* text's advance in blue */
+  cairo_set_source_rgba (cr, 0, 0, 0.75, 0.5);
+  cairo_arc (cr, x + logical_rect.x + logical_rect.width, y + logical_rect.height - descent,
+             3 * px, 0, 2 * M_PI);
+  cairo_fill (cr);
+
+  /* reference point in red */
+  cairo_arc (cr, x, y + ascent, 3 * px, 0, 2 * M_PI);
+  cairo_set_source_rgba (cr, 0.75, 0, 0, 0.5);
+  cairo_fill (cr);
+}
+#endif
+
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
  *
  */
-void o_text_draw_rectangle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
+static void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
+                                 int dx, int dy, COLOR *color)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int left=0, right=0, top=0, bottom=0;
-  GdkColor *color;
+  cairo_t *cr = w_current->cr;
+  int sx, sy;
+  double x, y;
+  PangoFontMetrics *font_metrics;
+  PangoRectangle logical_rect;
+  PangoRectangle inked_rect;
 
-  if (o_current->visibility == INVISIBLE && toplevel->show_hidden_text &&
-      o_current->text->prim_objs == NULL) {
-    o_text_recreate(toplevel, o_current);
-  }
+  g_return_if_fail (o_current != NULL);
+  g_return_if_fail (o_current->text != NULL);
 
-  /* text is too small so go through and draw a rectangle in
-     it's place */
+  if (o_current->visibility == INVISIBLE &&
+      !toplevel->show_hidden_text)
+    return;
 
-  /* NOTE THAT THE TOP AND BOTTOM ARE REVERSED THROUGHT THE WHOLE OF GEDA FOR WORLD COORDS */
-  WORLDtoSCREEN (w_current, o_current->w_left, o_current->w_bottom, &left, &top);
-  WORLDtoSCREEN (w_current, o_current->w_right, o_current->w_top, &right, &bottom);
+  if (o_current->text->disp_string == NULL)
+    return;
 
-  if (toplevel->override_color != -1 ) {  /* Override */
-    color = x_get_color (toplevel->override_color);
-  } else {
-    color = x_get_color (o_current->color);
-  }
-  gdk_gc_set_foreground(w_current->gc, color);
+  font_metrics =
+    setup_pango_return_metrics (w_current, w_current->pl,
+                                toplevel->page_current->to_screen_x_constant,
+                                o_current);
 
-  if (toplevel->DONT_REDRAW == 0) {
-    gdk_draw_rectangle (w_current->drawable,
-                        w_current->gc,
-                        FALSE,
-                        left,
-                        top,
-                        right - left,
-                        bottom - top);
+  pango_layout_get_pixel_extents (w_current->pl, &inked_rect, &logical_rect);
+  calculate_position (o_current, font_metrics, logical_rect, inked_rect, &x, &y);
+
+  cairo_save (cr);
+
+  WORLDtoSCREEN (w_current, o_current->text->x + dx,
+                            o_current->text->y + dy, &sx, &sy);
+  cairo_translate (cr, sx, sy);
+
+  /* Special case turns upside-down text back upright */
+  if (o_current->text->angle != 180) {
+    cairo_rotate (cr, - M_PI * o_current->text->angle / 180.);
   }
+
+  gschem_cairo_set_source_color (w_current, color);
+
+  /* NB: Shift the position by 0.5px to match the hinting applied to single
+   *     pixel wide lines. This means the text will sit correctly on top of
+   *     the grid lines, and ensures consistency with other lines when the
+   *     page view is zoomed out. */
+  cairo_move_to (cr, x + 0.5, y + 0.5);
+  pango_cairo_show_layout (cr, w_current->pl);
+
+#ifdef DEBUG_TEXT
+  draw_construction_lines (w_current, x, y, font_metrics, logical_rect);
+#endif
+
+  pango_font_metrics_unref (font_metrics);
+  cairo_restore (cr);
 }
 
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
@@ -129,7 +291,9 @@ void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   }
 
   if (!w_current->fast_mousepan || !w_current->doing_pan) {
-    o_text_draw_lowlevel(w_current, o_current);
+
+    o_text_draw_lowlevel (w_current, o_current, 0, 0,
+                          o_drawing_color (w_current, o_current));
 
     /* Indicate on the schematic that the text is invisible by */
     /* drawing a little I on the screen at the origin */
@@ -168,14 +332,19 @@ void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
                        screen_y1+small_dist);
       }
     }
-    
   } else {
-    if (w_current->doing_pan) {
-      o_text_draw_rectangle(w_current, o_current);
-      return;
-    }
+    /* draw a box in it's place */
+    gschem_cairo_box (w_current, 0,
+                      o_current->w_left,  o_current->w_bottom,
+                      o_current->w_right, o_current->w_top);
+
+    gschem_cairo_set_source_color (w_current,
+                                   o_drawing_color (w_current, o_current));
+    gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
+
+    return;
   }
-	
+
   /* return if text origin marker displaying is disabled */ 
   if (w_current->text_origin_marker == FALSE) {
     return;
@@ -239,10 +408,12 @@ void o_text_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_cu
   if ((factor < w_current->text_display_zoomfactor) ||
       o_current->text->size >= 12 ||
       w_current->text_feedback == ALWAYS) {
-    o_glist_draw_place (w_current, dx, dy, o_current->text->prim_objs);
+
+    o_text_draw_lowlevel (w_current, o_current, dx, dy,
+                          x_color_lookup_dark (o_current->color));
+
   } else {
-    /* text is too small so go through and draw a line in
-       it's place */
+    /* text is too small so draw a box in it's place */
 
     gschem_cairo_box (w_current, 0,
                       o_current->w_left  + dx, o_current->w_bottom + dy,
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 5201876..203068a 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -61,8 +61,10 @@ gint x_event_expose(GtkWidget *widget, GdkEventExpose *event,
   /* nasty global variable */
   global_window_current = w_current;
 
+  if (w_current->pl != NULL) g_object_unref( w_current->pl );
   if (w_current->cr != NULL) cairo_destroy( w_current->cr );
   w_current->cr = gdk_cairo_create( widget->window );
+  w_current->pl = pango_cairo_create_layout (w_current->cr);
 
   gdk_region_get_rectangles (event->region, &rectangles, &n_rectangles);
   o_redraw_rects (w_current, rectangles, n_rectangles);
diff --git a/gschem/src/x_image.c b/gschem/src/x_image.c
index 61d3270..b088f2e 100644
--- a/gschem/src/x_image.c
+++ b/gschem/src/x_image.c
@@ -652,6 +652,7 @@ GdkPixbuf *x_image_get_pixbuf (GSCHEM_TOPLEVEL *w_current)
   new_w_current.window = gdk_pixmap_new (w_current->window, size_x, size_y, -1);
   new_w_current.drawable = new_w_current.window;
   new_w_current.cr = gdk_cairo_create (new_w_current.window);
+  new_w_current.pl = pango_cairo_create_layout (new_w_current.cr);
 
   new_w_current.grid = 0;
   new_w_current.text_origin_marker = FALSE;
@@ -732,6 +733,7 @@ GdkPixbuf *x_image_get_pixbuf (GSCHEM_TOPLEVEL *w_current)
   }
 
   if (new_w_current.cr != NULL) cairo_destroy (new_w_current.cr);
+  if (new_w_current.pl != NULL) g_object_unref (new_w_current.pl);
   if (new_w_current.window != NULL) {
     g_object_unref(new_w_current.window);
   }
diff --git a/gschem/src/x_preview.c b/gschem/src/x_preview.c
index a9c87f1..16b4d54 100644
--- a/gschem/src/x_preview.c
+++ b/gschem/src/x_preview.c
@@ -125,7 +125,9 @@ preview_callback_expose (GtkWidget *widget,
   int n_rectangles;
 
   if (preview_w_current->cr != NULL) cairo_destroy (preview_w_current->cr);
+  if (preview_w_current->pl != NULL) g_object_unref (preview_w_current->pl);
   preview_w_current->cr = gdk_cairo_create (widget->window);
+  preview_w_current->pl = pango_cairo_create_layout (preview_w_current->cr);
 
   gdk_region_get_rectangles (event->region, &rectangles, &n_rectangles);
   o_redraw_rects (preview_w_current, rectangles, n_rectangles);




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs