[cairo-commit] 6 commits - src/cairo-font-face-twin.c src/cairo-font-face-twin-data.c src/cairoint.h src/cairo-user-font.c util/cairo-view util/Makefile.am

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Dec 23 10:49:09 PST 2008


 src/cairo-font-face-twin-data.c |    2 
 src/cairo-font-face-twin.c      |  228 +++++++++++++++++++++++++++++++++++++---
 src/cairo-user-font.c           |    4 
 src/cairoint.h                  |    6 -
 util/Makefile.am                |    3 
 util/cairo-view                 |  113 +++++++++++++++++++
 6 files changed, 331 insertions(+), 25 deletions(-)

New commits:
commit 52cc31a7fa6570e538762631359a92e7b717710e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Dec 23 13:48:52 2008 -0500

    [util] Add cairo-view

diff --git a/util/Makefile.am b/util/Makefile.am
index f272e4c..db40f17 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -27,4 +27,5 @@ malloc_stats_la_LIBADD  = $(backtrace_symbols_la_LIBADD) backtrace-symbols.lo
 EXTRA_DIST += \
 	COPYING \
 	xr2cairo \
-	cairo-api-update
+	cairo-api-update \
+	cairo-view
diff --git a/util/cairo-view b/util/cairo-view
new file mode 100755
index 0000000..83d5702
--- /dev/null
+++ b/util/cairo-view
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+
+import sys
+import cairo
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gtk.gdk
+import pango
+import gobject
+
+class CairoView(gtk.Window):
+    def __init__(self, family="", slant=0, weight=0, size=18, text="The Quick Brown Fox Jumped Over The Lazy Dog!"):
+        gtk.Widget.__init__ (self)
+
+	self.family = family
+	if slant == "italic":
+	    self.slant = cairo.FONT_SLANT_ITALIC
+	elif slant == "oblique":
+	    self.slant = cairo.FONT_SLANT_OBLIQUE
+	else:
+	    self.slant = cairo.FONT_SLANT_NORMAL
+	if weight == "bold":
+	    self.weight = cairo.FONT_WEIGHT_BOLD
+	else:
+	    self.weight = cairo.FONT_WEIGHT_NORMAL
+	self.size = float (size)
+	self.text = text
+
+    def do_realize(self):
+        self.set_flags(self.flags() | gtk.REALIZED)
+
+        self.window = gtk.gdk.Window(
+            self.get_parent_window(),
+            width=self.allocation.width,
+            height=self.allocation.height,
+            window_type=gtk.gdk.WINDOW_CHILD,
+            wclass=gtk.gdk.INPUT_OUTPUT,
+            event_mask=self.get_events() | gtk.gdk.EXPOSURE_MASK)
+
+        self.window.set_user_data(self)
+
+        self.style.attach(self.window)
+
+        self.style.set_background(self.window, gtk.STATE_NORMAL)
+
+	self.width, self.height = self.draw ()
+        self.window.move_resize(0, 0, self.width, self.height)
+
+    def do_unrealize(self):
+        self.window.destroy()
+
+    def do_expose_event(self, event):
+    	self.draw (event)
+
+        return False
+
+    def draw(self, event = None):
+
+        cr = self.window.cairo_create()
+	if event:
+		cr.rectangle(event.area.x, event.area.y,
+			     event.area.width, event.area.height)
+		cr.clip()
+
+    	cr.set_source_rgb (1, 1, 1)
+	cr.paint ()
+
+	cr.select_font_face (self.family, self.slant, self.weight)
+	cr.set_font_size (self.size)
+
+	PAD = 30
+
+        extents = cr.text_extents (self.text)
+	cr.translate (PAD-extents[0], PAD-extents[1])
+
+	font_extents = cr.font_extents ()
+	cr.rectangle (0, -font_extents[0], extents[4], font_extents[2])
+	cr.move_to (-PAD, 0)
+	cr.line_to (extents[2]+PAD, 0)
+	cr.set_source_rgba (1, 0, 0, .7)
+	cr.stroke ()
+
+	cr.rectangle (*extents[:4])
+	cr.set_source_rgba (0, 1, 0, .7)
+	cr.stroke ()
+
+	cr.move_to (0, 0)
+        cr.set_source_rgb (0, 0, 0)
+        cr.show_text (self.text)
+
+	return int (extents[2]) + 2 * PAD, int (extents[3]) + 2 * PAD
+
+    def run(self):
+
+	self.props.allow_shrink = True
+        self.connect("destroy", gtk.main_quit)
+        self.show()
+
+        gtk.main()
+
+gobject.type_register(CairoView)
+
+def main(args):
+
+    if len (args) == 1:
+	print "usage: cairo-view family [slant [weight [size [text]]]]"
+	sys.exit (1)
+    cv= CairoView (*args[1:])
+    cv.run()
+
+if __name__ == "__main__":
+    main(sys.argv)
commit 418c7ef133840c10eb0be7e75c7dd11533fbe897
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Dec 23 02:39:17 2008 -0500

    [twin] Adjust font extents

diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 83be2d5..ade41e6 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -234,8 +234,8 @@ FREE_PROPS:
 #define SNAPI(p)	(p)
 #define SNAPH(p)	(p)
 
-#define FX(g)		((g) / 64.)
-#define FY(g)		((g) / 64.)
+#define FX(g)		((g) / 72.)
+#define FY(g)		((g) / 72.)
 
 
 static cairo_status_t
@@ -243,8 +243,8 @@ twin_scaled_font_init (cairo_scaled_font_t  *scaled_font,
 		       cairo_t              *cr,
 		       cairo_font_extents_t *metrics)
 {
-  metrics->ascent  = FY (50);
-  metrics->descent = FY (14);
+  metrics->ascent  = FY (52);
+  metrics->descent = 1 - metrics->ascent;
   return CAIRO_STATUS_SUCCESS;
 }
 
commit 96e41c28e980f313c51a0eed81681e7e48752797
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Dec 20 23:30:59 2008 -0500

    [twin] Minor cleanup

diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 52c951d..83be2d5 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -258,7 +258,7 @@ twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
      * to map all unknown chars to a single unknown glyph to
      * reduce pressure on cache. */
 
-    if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
+    if (likely (unicode < ARRAY_LENGTH (_cairo_twin_charmap)))
 	*glyph = unicode;
     else
 	*glyph = 0;
@@ -283,9 +283,8 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
 {
     double x1, y1, x2, y2, x3, y3;
     twin_face_properties_t *props;
-    const int8_t *b = _cairo_twin_outlines +
-		      _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
-    const int8_t *g = twin_glyph_draw(b);
+    const int8_t *b;
+    const int8_t *g;
 
     struct {
       cairo_bool_t snap;
@@ -295,6 +294,10 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
       int n_snap_y;
     } info = {FALSE};
 
+    b = _cairo_twin_outlines +
+	_cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph];
+    g = twin_glyph_draw(b);
+
     props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
 					   &twin_face_properties_key);
     cairo_set_tolerance (cr, 0.01);
commit 556f6ce364d81f9309162d21deb86a3d5b8b9a6e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Dec 20 23:16:53 2008 -0500

    [twin] close_path the Q

diff --git a/src/cairo-font-face-twin-data.c b/src/cairo-font-face-twin-data.c
index dbc1bd2..cc43870 100644
--- a/src/cairo-font-face-twin-data.c
+++ b/src/cairo-font-face-twin-data.c
@@ -541,7 +541,7 @@ const int8_t _cairo_twin_outlines[] = {
     'c', 0, -13, 2, 0, 16, 0,
     'c', 30, 0, 32, -13, 32, -21,
     'c', 32, -29, 30, -42, 16, -42,
-    'm', 18, -8,
+    'M', 18, -8,
     'l', 30, 4,
     'e',
 /* 0x52 'R'  offset 1981 */
commit 6929ed800d19f359af7436636e8adc6203083a10
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Dec 20 20:25:01 2008 -0500

    [twin] Fix serif option parsing.  Also make serif and weight do something

diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 5cdbdd5..52c951d 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -127,7 +127,7 @@ parse_field (twin_face_properties_t *props,
 	     const char *s,
 	     int len)
 {
-    cairo_bool_t sans, serif;
+    cairo_bool_t sans = FALSE, serif = FALSE;
 
 #define MATCH(s1, var, value) \
 	if (field_matches (s1, s, len)) var = value
@@ -180,6 +180,8 @@ props_parse (twin_face_properties_t *props,
 		parse_field (props, start, end - start);
 	start = end + 1;
     }
+    if (start < end)
+	    parse_field (props, start, end - start);
 }
 
 static cairo_status_t
@@ -280,6 +282,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
 			       cairo_text_extents_t *metrics)
 {
     double x1, y1, x2, y2, x3, y3;
+    twin_face_properties_t *props;
     const int8_t *b = _cairo_twin_outlines +
 		      _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
     const int8_t *g = twin_glyph_draw(b);
@@ -292,10 +295,19 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
       int n_snap_y;
     } info = {FALSE};
 
+    props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
+					   &twin_face_properties_key);
     cairo_set_tolerance (cr, 0.01);
-    cairo_set_line_width (cr, 0.066);
-    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
-    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    /* The weight is tuned to match DejaVu Sans' */
+    cairo_set_line_width (cr, props->weight * (5.5 / 64 / TWIN_WEIGHT_NORMAL));
+
+    cairo_set_miter_limit (cr, M_SQRT2);
+    cairo_set_line_join (cr, props->serif ?
+			     CAIRO_LINE_JOIN_MITER :
+			     CAIRO_LINE_JOIN_ROUND);
+    cairo_set_line_cap (cr, props->serif ?
+			    CAIRO_LINE_CAP_SQUARE :
+			    CAIRO_LINE_CAP_ROUND);
 
     for (;;) {
 	switch (*g++) {
commit d423339fcef3c41225196c4371fb2c133ca61144
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Dec 20 19:39:58 2008 -0500

    [twin] Add face properties
    
    Just parse them now.  We don't use them yet.

diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 5ac2cd2..5cdbdd5 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -36,15 +36,188 @@
 
 #include "cairoint.h"
 
+#include <ctype.h>
+
 /*
  * This file implements a user-font rendering the decendant of the Hershey
  * font coded by Keith Packard for use in the Twin window system.
  * The actual font data is in cairo-font-face-twin-data.c
  *
- * Ported to cairo user font by Behdad Esfahbod.
+ * Ported to cairo user font and extended by Behdad Esfahbod.
  */
 
 
+
+/*
+ * Face properties
+ */
+
+/* We synthesize multiple faces from the twin data.  Here is the parameters. */
+
+/* CSS weight */
+typedef enum {
+  TWIN_WEIGHT_ULTRALIGHT = 200,
+  TWIN_WEIGHT_LIGHT = 300,
+  TWIN_WEIGHT_NORMAL = 400,
+  TWIN_WEIGHT_MEDIUM = 500,
+  TWIN_WEIGHT_SEMIBOLD = 600,
+  TWIN_WEIGHT_BOLD = 700,
+  TWIN_WEIGHT_ULTRABOLD = 800,
+  TWIN_WEIGHT_HEAVY = 900
+} twin_face_wight;
+
+/* CSS stretch */
+typedef enum {
+  TWIN_STRETCH_ULTRA_CONDENSED,
+  TWIN_STRETCH_EXTRA_CONDENSED,
+  TWIN_STRETCH_CONDENSED,
+  TWIN_STRETCH_SEMI_CONDENSED,
+  TWIN_STRETCH_NORMAL,
+  TWIN_STRETCH_SEMI_EXPANDED,
+  TWIN_STRETCH_EXPANDED,
+  TWIN_STRETCH_EXTRA_EXPANDED,
+  TWIN_STRETCH_ULTRA_EXPANDED
+} twin_face_stretch;
+
+
+typedef struct _twin_face_properties {
+    cairo_font_slant_t slant;
+    twin_face_wight    weight;
+    twin_face_stretch  stretch;
+
+    /* lets have some fun */
+    cairo_bool_t monospace;
+    cairo_bool_t serif;
+    cairo_bool_t smallcaps;
+} twin_face_properties_t;
+
+cairo_user_data_key_t twin_face_properties_key;
+
+#define TOLOWER(c) \
+   (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+static cairo_bool_t
+field_matches (const char *s1,
+               const char *s2,
+               int len)
+{
+  int c1, c2;
+
+  while (len && *s1 && *s2)
+    {
+      c1 = TOLOWER (*s1);
+      c2 = TOLOWER (*s2);
+      if (c1 != c2) {
+        if (c1 == '-') {
+          s1++;
+          continue;
+        }
+        return FALSE;
+      }
+      s1++; s2++;
+      len--;
+    }
+
+  return len == 0 && *s1 == '\0';
+}
+
+
+static void
+parse_field (twin_face_properties_t *props,
+	     const char *s,
+	     int len)
+{
+    cairo_bool_t sans, serif;
+
+#define MATCH(s1, var, value) \
+	if (field_matches (s1, s, len)) var = value
+
+
+         MATCH ("oblique",    props->slant, CAIRO_FONT_SLANT_OBLIQUE);
+    else MATCH ("italic",     props->slant, CAIRO_FONT_SLANT_ITALIC);
+
+
+    else MATCH ("ultra-light", props->weight, TWIN_WEIGHT_ULTRALIGHT);
+    else MATCH ("light",       props->weight, TWIN_WEIGHT_LIGHT);
+    else MATCH ("medium",      props->weight, TWIN_WEIGHT_NORMAL);
+    else MATCH ("semi-bold",   props->weight, TWIN_WEIGHT_SEMIBOLD);
+    else MATCH ("bold",        props->weight, TWIN_WEIGHT_BOLD);
+    else MATCH ("ultra-bold",  props->weight, TWIN_WEIGHT_ULTRABOLD);
+    else MATCH ("heavy",       props->weight, TWIN_WEIGHT_HEAVY);
+
+    else MATCH ("ultra-condensed", props->stretch, TWIN_STRETCH_ULTRA_CONDENSED);
+    else MATCH ("extra-condensed", props->stretch, TWIN_STRETCH_EXTRA_CONDENSED);
+    else MATCH ("condensed",       props->stretch, TWIN_STRETCH_CONDENSED);
+    else MATCH ("semi-condensed",  props->stretch, TWIN_STRETCH_SEMI_CONDENSED);
+    else MATCH ("semi-expanded",   props->stretch, TWIN_STRETCH_SEMI_EXPANDED);
+    else MATCH ("expanded",        props->stretch, TWIN_STRETCH_EXPANDED);
+    else MATCH ("extra-expanded",  props->stretch, TWIN_STRETCH_EXTRA_EXPANDED);
+    else MATCH ("ultra-expanded",  props->stretch, TWIN_STRETCH_ULTRA_EXPANDED);
+
+    else MATCH ("small-caps", props->smallcaps, TRUE);
+
+    else MATCH ("mono",       props->monospace, TRUE);
+    else MATCH ("monospace",  props->monospace, TRUE);
+
+    else MATCH ("sans",       sans, TRUE);
+    else MATCH ("sans-serif", sans, TRUE);
+    else MATCH ("serif",      serif, TRUE);
+
+    props->serif = serif && !sans;
+}
+
+static void
+props_parse (twin_face_properties_t *props,
+	     const char *s)
+{
+    const char *start, *end;
+
+    for (start = end = s; *end; end++) {
+	if (isalpha (*end) || *end == '-')
+	    continue;
+
+	if (start < end)
+		parse_field (props, start, end - start);
+	start = end + 1;
+    }
+}
+
+static cairo_status_t
+twin_set_face_properties_from_toy (cairo_font_face_t *twin_face,
+				   cairo_toy_font_face_t *toy_face)
+{
+    cairo_status_t status;
+    twin_face_properties_t *props;
+
+    props = malloc (sizeof (twin_face_properties_t));
+    if (unlikely (props == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    props->stretch  = TWIN_STRETCH_NORMAL;
+    props->monospace = FALSE;
+    props->serif = FALSE;
+    props->smallcaps = FALSE;
+
+    /* fill in props */
+    props->slant = toy_face->slant;
+    props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
+		    TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
+    props_parse (props, toy_face->family);
+
+    status = cairo_font_face_set_user_data (twin_face,
+					    &twin_face_properties_key,
+					    props, free);
+    if (status)
+	goto FREE_PROPS;
+
+    return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+    free (props);
+    return status;
+}
+
+
 #define twin_glyph_left(g)      ((g)[0])
 #define twin_glyph_right(g)     ((g)[1])
 #define twin_glyph_ascent(g)    ((g)[2])
@@ -187,7 +360,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
     }
 
     metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
-    metrics->x_advance +=  cairo_get_line_width (cr)/* XXX 2*x.margin */;
+    metrics->x_advance +=  2*cairo_get_line_width (cr)/* XXX 2*x.margin */;
     if (info.snap)
 	metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
 
@@ -195,16 +368,22 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
     return CAIRO_STATUS_SUCCESS;
 }
 
-cairo_font_face_t *
-_cairo_font_face_twin_create (cairo_font_slant_t slant,
-			      cairo_font_weight_t weight)
+cairo_status_t
+_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				      cairo_font_face_t      **font_face)
 {
+    cairo_status_t status;
     cairo_font_face_t *twin_font_face;
 
     twin_font_face = cairo_user_font_face_create ();
     cairo_user_font_face_set_init_func             (twin_font_face, twin_scaled_font_init);
     cairo_user_font_face_set_render_glyph_func     (twin_font_face, twin_scaled_font_render_glyph);
     cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
+    status = twin_set_face_properties_from_toy (twin_font_face, toy_face);
+    if (status)
+	return status;
+
+    *font_face = twin_font_face;
 
-    return twin_font_face;
+    return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 9bfdedc..fe475ab 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -339,9 +339,7 @@ static cairo_status_t
 _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
 				      cairo_font_face_t      **font_face)
 {
-    *font_face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base),
-					       cairo_toy_font_face_get_weight (&toy_face->base));
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
 }
 
 static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
diff --git a/src/cairoint.h b/src/cairoint.h
index 6914b11..882cfe4 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1393,9 +1393,9 @@ _cairo_toy_font_face_get_implementation (cairo_font_face_t *font_face);
 
 /* cairo-font-face-twin.c */
 
-cairo_private cairo_font_face_t *
-_cairo_font_face_twin_create (cairo_font_slant_t slant,
-			      cairo_font_weight_t weight);
+cairo_private cairo_status_t
+_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				      cairo_font_face_t      **font_face);
 
 /* cairo-font-face-twin-data.c */
 


More information about the cairo-commit mailing list