[cairo-commit] 9 commits - src/cairo-font-face-twin.c util/Makefile.am util/waterfall
Behdad Esfahbod
behdad at kemper.freedesktop.org
Fri Dec 26 13:38:38 PST 2008
src/cairo-font-face-twin.c | 429 +++++++++++++++++++++++++++------------------
util/Makefile.am | 3
util/waterfall | 97 ++++++++++
3 files changed, 358 insertions(+), 171 deletions(-)
New commits:
commit 9332c0a8eaf266e99555df9ad7769f8b5804cbfd
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 16:38:04 2008 -0500
[util] Add waterfall
diff --git a/util/Makefile.am b/util/Makefile.am
index db40f17..895c516 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -28,4 +28,5 @@ EXTRA_DIST += \
COPYING \
xr2cairo \
cairo-api-update \
- cairo-view
+ cairo-view \
+ waterfall
diff --git a/util/waterfall b/util/waterfall
new file mode 100755
index 0000000..5a683c5
--- /dev/null
+++ b/util/waterfall
@@ -0,0 +1,97 @@
+#!/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 jumps over the lazy dog! THE QUICK BROWN FOX JUMPS 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.window.move_resize(0, 0, 1000, 1000)
+
+ 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.set_source_rgb (0, 0, 0)
+
+ cr.select_font_face (self.family, self.slant, self.weight)
+
+ for size in range (1, 60):
+ cr.set_font_size (size)
+ extents = cr.text_extents (self.text)
+ cr.move_to (-extents[0], -extents[1])
+ cr.show_text (self.text)
+ cr.translate (0, extents[3])
+
+ 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 ab1febbf22a641feb2fda4b21156b2bd45df039b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 16:35:33 2008 -0500
[twin] Resnap margin under monospace
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index cd5357d..5d5bfb0 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -449,6 +449,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
cairo_text_extents_t *metrics)
{
double x1, y1, x2, y2, x3, y3;
+ double marginl;
twin_scaled_properties_t *props;
twin_snap_info_t info;
const int8_t *b;
@@ -467,6 +468,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* small-caps */
if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
glyph += 'A' - 'a';
+ /* 28 and 42 are small and capital letter heights of the glyph data */
cairo_scale (cr, 1, 28. / 42);
}
@@ -482,15 +484,25 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
w = twin_glyph_right(b);
gw = F(w);
+ marginl = props->marginl;
+
/* monospace */
if (props->face_props->monospace) {
double monow = F(24);
double extra = props->penx + props->marginl + props->marginr;
cairo_scale (cr, (monow + extra) / (gw + extra), 1);
gw = monow;
+
+ /* resnap margin for new transform */
+ {
+ double x, y, x_scale, x_scale_inv;
+ x = 1; y = 0;
+ compute_hinting_scale (cr, x, y, &x_scale, &x_scale_inv);
+ marginl = SNAPXI (marginl);
+ }
}
- cairo_translate (cr, props->marginl, 0); /* XXX if monospace, we need to snap again */
+ cairo_translate (cr, marginl, 0);
/* stretch */
cairo_scale (cr, props->stretch, 1);
commit 3c91d9f5a2a290653a56242eed6acae4f16e99e3
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 16:30:01 2008 -0500
[twin] Adjust margins
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 2a8be3b..cd5357d 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -224,33 +224,71 @@ typedef struct _twin_scaled_properties {
double weight; /* unhinted pen width */
double penx, peny; /* hinted pen width */
+ double marginl, marginr; /* hinted side margins */
double stretch; /* stretch factor */
} twin_scaled_properties_t;
static void
-twin_compute_pen (cairo_t *cr,
- double width,
- double *penx, double *peny)
+compute_hinting_scale (cairo_t *cr,
+ double x, double y,
+ double *scale, double *inv)
+{
+ cairo_user_to_device_distance (cr, &x, &y);
+ *scale = sqrt (x*x + y*y);
+ *inv = 1 / *scale;
+}
+
+static void
+compute_hinting_scales (cairo_t *cr,
+ double *x_scale, double *x_scale_inv,
+ double *y_scale, double *y_scale_inv)
{
double x, y;
- double scale, inv;
x = 1; y = 0;
- cairo_user_to_device_distance (cr, &x, &y);
- scale = sqrt (x*x + y*y);
- inv = 1 / scale;
- *penx = round (width * scale) * inv;
- if (*penx < inv)
- *penx = inv;
+ compute_hinting_scale (cr, x, y, x_scale, x_scale_inv);
x = 0; y = 1;
- cairo_user_to_device_distance (cr, &x, &y);
- scale = sqrt (x*x + y*y);
- inv = 1 / scale;
- *peny = round (width * scale) * inv;
- if (*peny < inv)
- *peny = inv;
+ compute_hinting_scale (cr, x, y, y_scale, y_scale_inv);
+}
+
+#define SNAPXI(p) (round ((p) * x_scale) * x_scale_inv)
+#define SNAPYI(p) (round ((p) * y_scale) * y_scale_inv)
+
+/* This controls the global font size */
+#define F(g) ((g) / 72.)
+
+static void
+twin_hint_pen_and_margins(cairo_t *cr,
+ double *penx, double *peny,
+ double *marginl, double *marginr)
+{
+ double x_scale, x_scale_inv;
+ double y_scale, y_scale_inv;
+ double margin;
+
+ compute_hinting_scales (cr,
+ &x_scale, &x_scale_inv,
+ &y_scale, &y_scale_inv);
+
+ *penx = SNAPXI (*penx);
+ if (*penx < x_scale_inv)
+ *penx = x_scale_inv;
+
+ *peny = SNAPYI (*peny);
+ if (*peny < y_scale_inv)
+ *peny = y_scale_inv;
+
+ margin = *marginl + *marginr;
+ *marginl = SNAPXI (*marginl);
+ if (*marginl < x_scale_inv)
+ *marginl = x_scale_inv;
+
+ *marginr = margin - *marginl;
+ if (*marginr < 0)
+ *marginr = 0;
+ *marginr = SNAPXI (*marginr);
}
static cairo_status_t
@@ -271,13 +309,15 @@ twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
props->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;
/* weight */
- props->weight = props->face_props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
+ props->weight = props->face_props->weight * (F (4) / TWIN_WEIGHT_NORMAL);
- /* pen */
+ /* pen & margins */
+ props->penx = props->peny = props->weight;
+ props->marginl = props->marginr = F (4);
if (scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT)
- twin_compute_pen (cr, props->weight, &props->penx, &props->peny);
- else
- props->penx = props->peny = props->weight;
+ twin_hint_pen_and_margins(cr,
+ &props->penx, &props->peny,
+ &props->marginl, &props->marginr);
/* stretch */
props->stretch = 1 + .1 * ((int) props->face_props->stretch - (int) TWIN_STRETCH_NORMAL);
@@ -302,9 +342,6 @@ FREE_PROPS:
* User-font implementation
*/
-/* This controls the global font size */
-#define F(g) ((g) / 72.)
-
static cairo_status_t
twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
cairo_t *cr,
@@ -320,9 +357,6 @@ twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
#define TWIN_GLYPH_MAX_SNAP_Y 7
typedef struct {
- double x_scale, x_scale_inv;
- double y_scale, y_scale_inv;
-
int n_snap_x;
int8_t snap_x[TWIN_GLYPH_MAX_SNAP_X];
double snapped_x[TWIN_GLYPH_MAX_SNAP_X];
@@ -349,20 +383,12 @@ twin_compute_snap (cairo_t *cr,
{
int s, n;
const signed char *snap;
- double x, y;
-
- x = 1; y = 0;
- cairo_user_to_device_distance (cr, &x, &y);
- info->x_scale = sqrt (x*x + y*y);
- info->x_scale_inv = 1 / info->x_scale;
-
- x = 0; y = 1;
- cairo_user_to_device_distance (cr, &x, &y);
- info->y_scale = sqrt (x*x + y*y);
- info->y_scale_inv = 1 / info->y_scale;
+ double x_scale, x_scale_inv;
+ double y_scale, y_scale_inv;
-#define SNAPXI(p) (round ((p) * info->x_scale) * info->x_scale_inv)
-#define SNAPYI(p) (round ((p) * info->y_scale) * info->y_scale_inv)
+ compute_hinting_scales (cr,
+ &x_scale, &x_scale_inv,
+ &y_scale, &y_scale_inv);
snap = twin_glyph_snap_x (b);
n = twin_glyph_n_snap_x (b);
@@ -459,12 +485,12 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* monospace */
if (props->face_props->monospace) {
double monow = F(24);
- cairo_scale (cr, (monow+3*props->penx) / (gw+3*props->penx), 1);
+ double extra = props->penx + props->marginl + props->marginr;
+ cairo_scale (cr, (monow + extra) / (gw + extra), 1);
gw = monow;
}
- /* left margin */
- cairo_translate (cr, props->penx, 0); /* XXX if monospace, we need to snap again */
+ cairo_translate (cr, props->marginl, 0); /* XXX if monospace, we need to snap again */
/* stretch */
cairo_scale (cr, props->stretch, 1);
@@ -475,7 +501,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
info.n_snap_x = info.n_snap_y = 0;
/* advance width */
- metrics->x_advance = gw * props->stretch + props->penx * 3; /* pen width + margin */
+ metrics->x_advance = gw * props->stretch + props->penx + props->marginl + props->marginr;
/* glyph shape */
for (;;) {
commit 0b5c60bae1fb0924bbd43daab38932052e10b3be
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 15:48:46 2008 -0500
[twin] Clean up hinting
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 991951e..2a8be3b 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -316,42 +316,10 @@ twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
return twin_scaled_font_compute_properties (scaled_font, cr);
}
-static double
-_twin_snap (int8_t v, cairo_bool_t do_snap, int8_t *snap, double *snapped, int n)
-{
- int s;
-
- if (!do_snap || !n)
- return F(v);
-
- if (snap[0] == v)
- return snapped[0];
-
- for (s = 0; s < n - 1; s++)
- {
- if (snap[s+1] == v)
- return snapped[s+1];
-
- if (snap[s] <= v && v <= snap[s+1])
- {
- int before = snap[s];
- int after = snap[s+1];
- int dist = after - before;
- double snap_before = snapped[s];
- double snap_after = snapped[s+1];
- double dist_before = v - before;
- return snap_before + (snap_after - snap_before) * dist_before / dist;
- }
- }
- return F(v);
-}
-
#define TWIN_GLYPH_MAX_SNAP_X 4
#define TWIN_GLYPH_MAX_SNAP_Y 7
typedef struct {
- cairo_bool_t snap;
-
double x_scale, x_scale_inv;
double y_scale, y_scale_inv;
@@ -363,9 +331,6 @@ typedef struct {
double snapped_y[TWIN_GLYPH_MAX_SNAP_Y];
} twin_snap_info_t;
-#define SNAPXI(p) (round ((p) * info->x_scale) * info->x_scale_inv)
-#define SNAPYI(p) (round ((p) * info->y_scale) * info->y_scale_inv)
-
#define twin_glyph_left(g) ((g)[0])
#define twin_glyph_right(g) ((g)[1])
#define twin_glyph_ascent(g) ((g)[2])
@@ -378,19 +343,14 @@ typedef struct {
#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
static void
-_twin_compute_snap (cairo_t *cr,
- cairo_scaled_font_t *scaled_font,
- twin_snap_info_t *info,
- const signed char *b)
+twin_compute_snap (cairo_t *cr,
+ twin_snap_info_t *info,
+ const signed char *b)
{
int s, n;
const signed char *snap;
double x, y;
- info->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;
- if (!info->snap)
- return;
-
x = 1; y = 0;
cairo_user_to_device_distance (cr, &x, &y);
info->x_scale = sqrt (x*x + y*y);
@@ -401,6 +361,8 @@ _twin_compute_snap (cairo_t *cr,
info->y_scale = sqrt (x*x + y*y);
info->y_scale_inv = 1 / info->y_scale;
+#define SNAPXI(p) (round ((p) * info->x_scale) * info->x_scale_inv)
+#define SNAPYI(p) (round ((p) * info->y_scale) * info->y_scale_inv)
snap = twin_glyph_snap_x (b);
n = twin_glyph_n_snap_x (b);
@@ -421,8 +383,38 @@ _twin_compute_snap (cairo_t *cr,
}
}
-#define SNAPX(p) _twin_snap (p, info.snap, info.snap_x, info.snapped_x, info.n_snap_x)
-#define SNAPY(p) _twin_snap (p, info.snap, info.snap_y, info.snapped_y, info.n_snap_y)
+static double
+twin_snap (int8_t v, int n, int8_t *snap, double *snapped)
+{
+ int s;
+
+ if (!n)
+ return F(v);
+
+ if (snap[0] == v)
+ return snapped[0];
+
+ for (s = 0; s < n - 1; s++)
+ {
+ if (snap[s+1] == v)
+ return snapped[s+1];
+
+ if (snap[s] <= v && v <= snap[s+1])
+ {
+ int before = snap[s];
+ int after = snap[s+1];
+ int dist = after - before;
+ double snap_before = snapped[s];
+ double snap_after = snapped[s+1];
+ double dist_before = v - before;
+ return snap_before + (snap_after - snap_before) * dist_before / dist;
+ }
+ }
+ return F(v);
+}
+
+#define SNAPX(p) twin_snap (p, info.n_snap_x, info.snap_x, info.snapped_x)
+#define SNAPY(p) twin_snap (p, info.n_snap_y, info.snap_y, info.snapped_y)
static cairo_status_t
twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
@@ -472,12 +464,15 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
}
/* left margin */
- cairo_translate (cr, props->penx, 0);
+ cairo_translate (cr, props->penx, 0); /* XXX if monospace, we need to snap again */
/* stretch */
cairo_scale (cr, props->stretch, 1);
- _twin_compute_snap (cr, scaled_font, &info, b);
+ if (props->snap)
+ twin_compute_snap (cr, &info, b);
+ else
+ info.n_snap_x = info.n_snap_y = 0;
/* advance width */
metrics->x_advance = gw * props->stretch + props->penx * 3; /* pen width + margin */
commit 6e7a2c4ce32ddfb0e58a74fcba8c4e46e46d32a4
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 15:34:50 2008 -0500
[twin] Fix monospace for narrow glyphs
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 3b9f969..991951e 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -443,10 +443,14 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* Save glyph space, we need it when stroking */
cairo_save (cr);
- /* left margin + pen width, pen width */
- cairo_translate (cr, props->penx * 1.5, -props->peny * .5);
+ /* center the pen */
+ cairo_translate (cr, props->penx * .5, -props->peny * .5);
- cairo_scale (cr, props->stretch, 1);
+ /* small-caps */
+ if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
+ glyph += 'A' - 'a';
+ cairo_scale (cr, 1, 28. / 42);
+ }
/* slant */
if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) {
@@ -454,11 +458,6 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
cairo_transform (cr, &shear);
}
- if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
- glyph += 'A' - 'a';
- cairo_scale (cr, 1, 28. / 42);
- }
-
b = _cairo_twin_outlines +
_cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph];
g = twin_glyph_draw(b);
@@ -468,10 +467,16 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* monospace */
if (props->face_props->monospace) {
double monow = F(24);
- cairo_scale (cr, (monow+props->penx) / (gw+props->penx), 1);
+ cairo_scale (cr, (monow+3*props->penx) / (gw+3*props->penx), 1);
gw = monow;
}
+ /* left margin */
+ cairo_translate (cr, props->penx, 0);
+
+ /* stretch */
+ cairo_scale (cr, props->stretch, 1);
+
_twin_compute_snap (cr, scaled_font, &info, b);
/* advance width */
commit e8e6ae1294f11addcbc8a95db471bb48a50b0b1a
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 15:15:15 2008 -0500
[twin] Cache pen and other properties on the scaled font
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 7c446c9..3b9f969 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -159,7 +159,7 @@ parse_field (twin_face_properties_t *props,
}
static void
-props_parse (twin_face_properties_t *props,
+face_props_parse (twin_face_properties_t *props,
const char *s)
{
const char *start, *end;
@@ -180,8 +180,8 @@ props_parse (twin_face_properties_t *props,
}
static cairo_status_t
-twin_set_face_properties_from_toy (cairo_font_face_t *twin_face,
- cairo_toy_font_face_t *toy_face)
+twin_font_face_set_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;
@@ -197,7 +197,7 @@ twin_set_face_properties_from_toy (cairo_font_face_t *twin_face,
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);
+ face_props_parse (props, toy_face->family);
status = cairo_font_face_set_user_data (twin_face,
&twin_properties_key,
@@ -218,10 +218,85 @@ FREE_PROPS:
*/
typedef struct _twin_scaled_properties {
- cairo_bool_t snap;
- double penx, peny;
+ twin_face_properties_t *face_props;
+
+ cairo_bool_t snap; /* hint outlines */
+
+ double weight; /* unhinted pen width */
+ double penx, peny; /* hinted pen width */
+
+ double stretch; /* stretch factor */
} twin_scaled_properties_t;
+static void
+twin_compute_pen (cairo_t *cr,
+ double width,
+ double *penx, double *peny)
+{
+ double x, y;
+ double scale, inv;
+
+ x = 1; y = 0;
+ cairo_user_to_device_distance (cr, &x, &y);
+ scale = sqrt (x*x + y*y);
+ inv = 1 / scale;
+ *penx = round (width * scale) * inv;
+ if (*penx < inv)
+ *penx = inv;
+
+ x = 0; y = 1;
+ cairo_user_to_device_distance (cr, &x, &y);
+ scale = sqrt (x*x + y*y);
+ inv = 1 / scale;
+ *peny = round (width * scale) * inv;
+ if (*peny < inv)
+ *peny = inv;
+}
+
+static cairo_status_t
+twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
+ cairo_t *cr)
+{
+ cairo_status_t status;
+ twin_scaled_properties_t *props;
+
+ props = malloc (sizeof (twin_scaled_properties_t));
+ if (unlikely (props == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+
+ props->face_props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
+ &twin_properties_key);
+
+ props->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;
+
+ /* weight */
+ props->weight = props->face_props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
+
+ /* pen */
+ if (scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT)
+ twin_compute_pen (cr, props->weight, &props->penx, &props->peny);
+ else
+ props->penx = props->peny = props->weight;
+
+ /* stretch */
+ props->stretch = 1 + .1 * ((int) props->face_props->stretch - (int) TWIN_STRETCH_NORMAL);
+
+
+ /* Save it */
+ status = cairo_scaled_font_set_user_data (scaled_font,
+ &twin_properties_key,
+ props, free);
+ if (unlikely (status))
+ goto FREE_PROPS;
+
+ return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+ free (props);
+ return status;
+}
+
/*
* User-font implementation
@@ -238,7 +313,7 @@ twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
metrics->ascent = F (54);
metrics->descent = 1 - metrics->ascent;
- return CAIRO_STATUS_SUCCESS;
+ return twin_scaled_font_compute_properties (scaled_font, cr);
}
static double
@@ -346,39 +421,6 @@ _twin_compute_snap (cairo_t *cr,
}
}
-static void
-_twin_compute_pen (cairo_t *cr,
- cairo_scaled_font_t *scaled_font,
- double width,
- double *penx, double *peny)
-{
- double x, y;
- double scale, inv;
- cairo_bool_t hint;
-
- hint = scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT;
- if (!hint) {
- *penx = *peny = width;
- return;
- }
-
- x = 1; y = 0;
- cairo_user_to_device_distance (cr, &x, &y);
- scale = sqrt (x*x + y*y);
- inv = 1 / scale;
- *penx = round (width * scale) * inv;
- if (*penx < inv)
- *penx = inv;
-
- x = 0; y = 1;
- cairo_user_to_device_distance (cr, &x, &y);
- scale = sqrt (x*x + y*y);
- inv = 1 / scale;
- *peny = round (width * scale) * inv;
- if (*peny < inv)
- *peny = inv;
-}
-
#define SNAPX(p) _twin_snap (p, info.snap, info.snap_x, info.snapped_x, info.n_snap_x)
#define SNAPY(p) _twin_snap (p, info.snap, info.snap_y, info.snapped_y, info.n_snap_y)
@@ -389,45 +431,30 @@ 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;
+ twin_scaled_properties_t *props;
twin_snap_info_t info;
const int8_t *b;
const int8_t *g;
int8_t w;
double gw;
- double weight, stretch;
- double penx, peny;
-
- cairo_set_tolerance (cr, 0.01);
- cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
- /* Prepare face */
+ props = cairo_scaled_font_get_user_data (scaled_font, &twin_properties_key);
- props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
- &twin_properties_key);
-
- /* weight */
- weight = props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
-
- /* lock pen matrix */
- _twin_compute_pen (cr, scaled_font, weight, &penx, &peny);
+ /* Save glyph space, we need it when stroking */
cairo_save (cr);
/* left margin + pen width, pen width */
- cairo_translate (cr, penx * 1.5, -peny * .5);
+ cairo_translate (cr, props->penx * 1.5, -props->peny * .5);
- /* stretch */
- stretch = 1 + .1 * ((int) props->stretch - (int) TWIN_STRETCH_NORMAL);
- cairo_scale (cr, stretch, 1);
+ cairo_scale (cr, props->stretch, 1);
/* slant */
- if (props->slant != CAIRO_FONT_SLANT_NORMAL) {
+ if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) {
cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0};
cairo_transform (cr, &shear);
}
- if (props->smallcaps && glyph >= 'a' && glyph <= 'z') {
+ if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
glyph += 'A' - 'a';
cairo_scale (cr, 1, 28. / 42);
}
@@ -439,16 +466,16 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
gw = F(w);
/* monospace */
- if (props->monospace) {
+ if (props->face_props->monospace) {
double monow = F(24);
- cairo_scale (cr, (monow+penx) / (gw+penx), 1);
+ cairo_scale (cr, (monow+props->penx) / (gw+props->penx), 1);
gw = monow;
}
_twin_compute_snap (cr, scaled_font, &info, b);
/* advance width */
- metrics->x_advance = gw * stretch + penx * 3; /* pen width + margin */
+ metrics->x_advance = gw * props->stretch + props->penx * 3; /* pen width + margin */
/* glyph shape */
for (;;) {
@@ -485,9 +512,12 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
cairo_close_path (cr);
/* fall through */
case 'e':
- cairo_restore (cr);
- cairo_scale (cr, penx, peny);
+ cairo_restore (cr); /* restore glyph space */
+ cairo_set_tolerance (cr, 0.01);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width (cr, 1);
+ cairo_scale (cr, props->penx, props->peny);
cairo_stroke (cr);
break;
case 'X':
@@ -534,9 +564,11 @@ _cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
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)
+ status = twin_font_face_set_properties_from_toy (twin_font_face, toy_face);
+ if (status) {
+ cairo_font_face_destroy (twin_font_face);
return status;
+ }
*font_face = twin_font_face;
commit e133cc14469e8ebb8311bf8db206147f6b07786d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 14:56:32 2008 -0500
[twin] Don't stretch pen
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 5dc7102..7c446c9 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -410,10 +410,6 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* weight */
weight = props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
- /* stretch */
- stretch = 1 + .05 * ((int) props->stretch - (int) TWIN_STRETCH_NORMAL);
- cairo_scale (cr, stretch, 1);
-
/* lock pen matrix */
_twin_compute_pen (cr, scaled_font, weight, &penx, &peny);
cairo_save (cr);
@@ -421,6 +417,10 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* left margin + pen width, pen width */
cairo_translate (cr, penx * 1.5, -peny * .5);
+ /* stretch */
+ stretch = 1 + .1 * ((int) props->stretch - (int) TWIN_STRETCH_NORMAL);
+ cairo_scale (cr, stretch, 1);
+
/* slant */
if (props->slant != CAIRO_FONT_SLANT_NORMAL) {
cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0};
@@ -448,8 +448,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
_twin_compute_snap (cr, scaled_font, &info, b);
/* advance width */
- metrics->x_advance = gw + penx * 3; /* pen width + margin */
- metrics->x_advance *= stretch;
+ metrics->x_advance = gw * stretch + penx * 3; /* pen width + margin */
/* glyph shape */
for (;;) {
commit dec4d791f4cc626d1fa52d68518f787210240812
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 14:24:08 2008 -0500
[twin] Minor shuffling
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 8164063..5dc7102 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -38,8 +38,6 @@
#include <math.h>
#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.
@@ -50,6 +48,9 @@
+cairo_user_data_key_t twin_properties_key;
+
+
/*
* Face properties
*/
@@ -66,7 +67,7 @@ typedef enum {
TWIN_WEIGHT_BOLD = 700,
TWIN_WEIGHT_ULTRABOLD = 800,
TWIN_WEIGHT_HEAVY = 900
-} twin_face_wight;
+} twin_face_weight_t;
/* CSS stretch */
typedef enum {
@@ -79,24 +80,19 @@ typedef enum {
TWIN_STRETCH_EXPANDED,
TWIN_STRETCH_EXTRA_EXPANDED,
TWIN_STRETCH_ULTRA_EXPANDED
-} twin_face_stretch;
+} twin_face_stretch_t;
typedef struct _twin_face_properties {
- cairo_font_slant_t slant;
- twin_face_wight weight;
- twin_face_stretch stretch;
+ cairo_font_slant_t slant;
+ twin_face_weight_t weight;
+ twin_face_stretch_t stretch;
/* lets have some fun */
cairo_bool_t monospace;
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,
@@ -106,6 +102,9 @@ field_matches (const char *s1,
while (len && *s1 && *s2)
{
+#define TOLOWER(c) \
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
c1 = TOLOWER (*s1);
c2 = TOLOWER (*s2);
if (c1 != c2) {
@@ -131,11 +130,11 @@ parse_field (twin_face_properties_t *props,
#define MATCH(s1, var, value) \
if (field_matches (s1, s, len)) var = value
+ if (0) ;
- MATCH ("oblique", props->slant, CAIRO_FONT_SLANT_OBLIQUE);
+ else 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);
@@ -153,10 +152,10 @@ parse_field (twin_face_properties_t *props,
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 ("small-caps", props->smallcaps, TRUE);
}
static void
@@ -165,8 +164,11 @@ props_parse (twin_face_properties_t *props,
{
const char *start, *end;
+#define ISALPHA(c) \
+ (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+
for (start = end = s; *end; end++) {
- if (isalpha (*end) || *end == '-')
+ if (ISALPHA (*end) || *end == '-')
continue;
if (start < end)
@@ -192,16 +194,15 @@ twin_set_face_properties_from_toy (cairo_font_face_t *twin_face,
props->monospace = 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,
+ &twin_properties_key,
props, free);
- if (status)
+ if (unlikely (status))
goto FREE_PROPS;
return CAIRO_STATUS_SUCCESS;
@@ -212,19 +213,22 @@ FREE_PROPS:
}
-#define twin_glyph_left(g) ((g)[0])
-#define twin_glyph_right(g) ((g)[1])
-#define twin_glyph_ascent(g) ((g)[2])
-#define twin_glyph_descent(g) ((g)[3])
+/*
+ * Scaled properties
+ */
-#define twin_glyph_n_snap_x(g) ((g)[4])
-#define twin_glyph_n_snap_y(g) ((g)[5])
-#define twin_glyph_snap_x(g) (&g[6])
-#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
-#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
+typedef struct _twin_scaled_properties {
+ cairo_bool_t snap;
+ double penx, peny;
+} twin_scaled_properties_t;
-#define F(g) ((g) / 72.)
+/*
+ * User-font implementation
+ */
+
+/* This controls the global font size */
+#define F(g) ((g) / 72.)
static cairo_status_t
twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
@@ -233,42 +237,16 @@ twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
{
metrics->ascent = F (54);
metrics->descent = 1 - metrics->ascent;
- return CAIRO_STATUS_SUCCESS;
-}
-static cairo_status_t
-twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
- unsigned long unicode,
- unsigned long *glyph)
-{
- /* We use an identity charmap. Which means we could live
- * with no unicode_to_glyph method too. But we define this
- * to map all unknown chars to a single unknown glyph to
- * reduce pressure on cache. */
-
- if (likely (unicode < ARRAY_LENGTH (_cairo_twin_charmap)))
- *glyph = unicode;
- else
- *glyph = 0;
-
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_STATUS_SUCCESS;
}
-#define SNAPX(p) _twin_snap (p, info.snap, info.snap_x, info.snapped_x, info.n_snap_x)
-#define SNAPY(p) _twin_snap (p, info.snap, info.snap_y, info.snapped_y, info.n_snap_y)
-
-#define TWIN_GLYPH_MAX_SNAP_X 4
-#define TWIN_GLYPH_MAX_SNAP_Y 7
-
-#define SNAPXI(p) (round ((p) * info->x_scale) * info->x_scale_inv)
-#define SNAPYI(p) (round ((p) * info->y_scale) * info->y_scale_inv)
-
static double
_twin_snap (int8_t v, cairo_bool_t do_snap, int8_t *snap, double *snapped, int n)
{
int s;
- if (!do_snap)
+ if (!do_snap || !n)
return F(v);
if (snap[0] == v)
@@ -293,11 +271,14 @@ _twin_snap (int8_t v, cairo_bool_t do_snap, int8_t *snap, double *snapped, int n
return F(v);
}
+#define TWIN_GLYPH_MAX_SNAP_X 4
+#define TWIN_GLYPH_MAX_SNAP_Y 7
+
typedef struct {
cairo_bool_t snap;
- double x_scale, x_scale_inv, x_off;
- double y_scale, y_scale_inv, y_off;
+ double x_scale, x_scale_inv;
+ double y_scale, y_scale_inv;
int n_snap_x;
int8_t snap_x[TWIN_GLYPH_MAX_SNAP_X];
@@ -307,6 +288,20 @@ typedef struct {
double snapped_y[TWIN_GLYPH_MAX_SNAP_Y];
} twin_snap_info_t;
+#define SNAPXI(p) (round ((p) * info->x_scale) * info->x_scale_inv)
+#define SNAPYI(p) (round ((p) * info->y_scale) * info->y_scale_inv)
+
+#define twin_glyph_left(g) ((g)[0])
+#define twin_glyph_right(g) ((g)[1])
+#define twin_glyph_ascent(g) ((g)[2])
+#define twin_glyph_descent(g) ((g)[3])
+
+#define twin_glyph_n_snap_x(g) ((g)[4])
+#define twin_glyph_n_snap_y(g) ((g)[5])
+#define twin_glyph_snap_x(g) (&g[6])
+#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
+#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
+
static void
_twin_compute_snap (cairo_t *cr,
cairo_scaled_font_t *scaled_font,
@@ -384,6 +379,8 @@ _twin_compute_pen (cairo_t *cr,
*peny = inv;
}
+#define SNAPX(p) _twin_snap (p, info.snap, info.snap_x, info.snapped_x, info.n_snap_x)
+#define SNAPY(p) _twin_snap (p, info.snap, info.snap_y, info.snapped_y, info.n_snap_y)
static cairo_status_t
twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
@@ -408,7 +405,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
/* Prepare face */
props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
- &twin_face_properties_key);
+ &twin_properties_key);
/* weight */
weight = props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
@@ -504,6 +501,29 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_status_t
+twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long unicode,
+ unsigned long *glyph)
+{
+ /* We use an identity charmap. Which means we could live
+ * with no unicode_to_glyph method too. But we define this
+ * to map all unknown chars to a single unknown glyph to
+ * reduce pressure on cache. */
+
+ if (likely (unicode < ARRAY_LENGTH (_cairo_twin_charmap)))
+ *glyph = unicode;
+ else
+ *glyph = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
+/*
+ * Face constructor
+ */
+
cairo_status_t
_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face)
commit c3de08ee2fcfb0e092f0299e249b0f5fe56b87bf
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Dec 26 14:11:52 2008 -0500
[twin] Further reduce weight
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index b61e79e..8164063 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -411,7 +411,7 @@ twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
&twin_face_properties_key);
/* weight */
- weight = props->weight * (5. / 64 / TWIN_WEIGHT_NORMAL);
+ weight = props->weight * (4. / 64 / TWIN_WEIGHT_NORMAL);
/* stretch */
stretch = 1 + .05 * ((int) props->stretch - (int) TWIN_STRETCH_NORMAL);
More information about the cairo-commit
mailing list