static cairo_status_t twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, 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; const int8_t *g; int8_t w; double gw; props = cairo_scaled_font_get_user_data (scaled_font, &twin_properties_key); /* Save glyph space, we need it when stroking */ cairo_save (cr); /* center the pen */ cairo_translate (cr, props->penx * .5, -props->peny * .5); /* 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); } /* slant */ if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) { cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0}; cairo_transform (cr, &shear); } b = _cairo_twin_outlines + _cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph]; g = twin_glyph_draw(b); 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, marginl, 0); /* stretch */ cairo_scale (cr, props->stretch, 1); 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 + props->marginl + props->marginr; /* glyph shape */ for (;;) { switch (*g++) { case 'M': cairo_close_path (cr); /* fall through */ case 'm': x1 = SNAPX(*g++); y1 = SNAPY(*g++); cairo_move_to (cr, x1, y1); continue; case 'L': cairo_close_path (cr); /* fall through */ case 'l': x1 = SNAPX(*g++); y1 = SNAPY(*g++); cairo_line_to (cr, x1, y1); continue; case 'C': cairo_close_path (cr); /* fall through */ case 'c': x1 = SNAPX(*g++); y1 = SNAPY(*g++); x2 = SNAPX(*g++); y2 = SNAPY(*g++); x3 = SNAPX(*g++); y3 = SNAPY(*g++); cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); continue; case 'E': cairo_close_path (cr); /* fall through */ case 'e': 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': /* filler */ continue; } break; } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *metrics) { double x1, y1, x2, y2, x3, y3; 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); struct { cairo_bool_t snap; int snap_x; int snap_y; int n_snap_x; int n_snap_y; } info = {FALSE}; cairo_set_line_width (cr, 0.06); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); for (;;) { switch (*g++) { case 'M': cairo_close_path (cr); /* fall through */ case 'm': x1 = FX(*g++); y1 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); } cairo_move_to (cr, x1, y1); continue; case 'L': cairo_close_path (cr); /* fall through */ case 'l': x1 = FX(*g++); y1 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); } cairo_line_to (cr, x1, y1); continue; case 'C': cairo_close_path (cr); /* fall through */ case 'c': x1 = FX(*g++); y1 = FY(*g++); x2 = FX(*g++); y2 = FY(*g++); x3 = FX(*g++); y3 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); x2 = SNAPX (x2); y2 = SNAPY (y2); x3 = SNAPX (x3); y3 = SNAPY (y3); } cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); continue; case 'E': cairo_close_path (cr); /* fall through */ case 'e': cairo_stroke (cr); break; case 'X': /* filler */ continue; } break; } 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 */; if (info.snap) metrics->x_advance = SNAPI (SNAPX (metrics->x_advance)); return CAIRO_STATUS_SUCCESS; }