+/* Returns in brace_width the width of the brace */
+static void
+_draw_brace (score_t *score, cairo_t *cr,
+ score_brace_t *brace, int *brace_width)
+{
+ cairo_glyph_t brace_glyph;
+ cairo_text_extents_t brace_extents;
+ double top, bottom;
+
+ if (brace->num_staves == 0)
+ return;
+
+ cairo_save (cr);
+
+ top = score->staves[brace->first_staff]->y_pos;
+ bottom = score->staves[brace->first_staff + brace->num_staves - 1]->y_pos + score->staff_height;
+
+ cairo_select_font_face (cr, "Gonville-Brace", 0, 0);
+
+ /* XXX: This hard-coded glyph index is pretty ugly. We should
+ * figure out how to lookup the glyph we want, (though, as it
+ * turns out, this brace font pretty much just has numbered glyph
+ * names for different sizes, so it wouldn't be all that different
+ * than just the bare index here). */
+ brace_glyph.index = 300;
+ brace_glyph.x = 0;
+ brace_glyph.y = top + (bottom - top) / 2.0 + score->line_width / 2.0;
+
+ /* XXX: This font size (in conjunction with the glyph selection)
+ * is a rough guess at best. We should figure out how the brace
+ * font is intended to be used and actually measure to find the
+ * correctly-sized glyph. */
+ cairo_set_font_size (cr, (bottom - top) / 3.85);
+
+ cairo_glyph_extents (cr, &brace_glyph, 1, &brace_extents);
+
+ /* Subtract space for brace itself */
+ cairo_translate (cr, -brace_extents.x_bearing, 0);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+ cairo_show_glyphs (cr, &brace_glyph, 1);
+
+ cairo_restore (cr);
+
+ *brace_width = (int) -brace_extents.x_bearing;
+}
+
+/* Line containing middle C for the given clef. */
+static int
+_score_clef_c_line (score_clef_t clef)
+{
+ switch (clef)
+ {
+ default:
+ case SCORE_CLEF_G:
+ return 5;
+ case SCORE_CLEF_F:
+ return -1;
+ }
+}
+
+static double
+_score_note_to_line (score_staff_t *staff, score_note_t *note)
+{
+ score_pitch_name_t name = SCORE_PITCH_NAME (note->pitch);
+ int c_line = _score_clef_c_line (staff->clef);
+
+ return c_line - (name - SCORE_PITCH_NAME_C) / 2.0 - 3.5 * (note->octave - 4);
+}
+
+/* chord->width is updated as a side effect */
+static void
+_draw_chord (score_t *score, cairo_t *cr,
+ score_staff_t *staff, score_chord_t *chord)
+{
+ cairo_text_extents_t chord_extents;
+ double total_staff_height;
+
+ /* XXX: The staff should manage this height itself. */
+ total_staff_height = (staff->upper_ledger_lines * score->space_height +
+ score->staff_height +
+ staff->lower_ledger_lines * score->space_height);
+
+ cairo_save (cr);
+
+ cairo_text_extents (cr, chord->name, &chord_extents);
+
+ cairo_select_font_face (cr, "serif", 0, 0);
+ cairo_set_font_size (cr, score->space_height * 3);
+
+ if (staff->clef == SCORE_CLEF_G)
+ cairo_move_to (cr, 0, - score->space_height * 0.5);
+ else
+ cairo_move_to (cr, 0, score->space_height * 0.5 + total_staff_height + chord_extents.y_bearing);
+
+ cairo_show_text (cr, chord->name);
+
+ chord->width = chord_extents.x_advance;
+
+ cairo_restore (cr);
+}
+
+static void
+_draw_note (score_t *score, cairo_t *cr,
+ score_staff_t *staff, score_note_t *note)