#include "score.h"
-void
-score_init (score_t *score)
+struct score
+{
+ /* Height of a single staff */
+ int staff_height;
+
+ /* Height of one space within a staff */
+ int space_height;
+
+ /* Minimal line width for staff lines */
+ int line_width;
+
+ /* Full width of staff */
+ int width;
+};
+
+score_t *
+score_create (void *ctx)
{
- score->space_height = 6;
+ score_t *score;
+
+ score = talloc (ctx, score_t);
+ score_set_staff_height (score, 24);
+
+ return score;
+}
+
+int
+score_set_staff_height (score_t *score, int height)
+{
+ score->space_height = (int) height / 4;
+ score->staff_height = score->space_height * 4;
+
+ score->line_width = score->space_height / 10;
+ if (score->line_width == 0)
+ score->line_width = 1;
+
+ return score->staff_height;
}
void
-_draw_staff (score_t *score, cairo_t *cr)
+score_set_width (score_t *score, int width)
+{
+ score->width = width;
+}
+
+typedef enum score_clef
+{
+ SCORE_CLEF_G,
+ SCORE_CLEF_F
+} score_clef_t;
+
+static void
+_draw_staff (score_t *score, cairo_t *cr, score_clef_t clef)
{
int i;
+ cairo_glyph_t glyph;
cairo_save (cr);
- for (i = 0; i < 5; i++) {
- cairo_move_to (cr, 0, i * score->space_height + 0.5);
+ cairo_select_font_face (cr, "Gonville-26", 0, 0);
+
+ cairo_set_font_size (cr, score->staff_height);
+
+ /* XXX: The hard-coded glyph indices here are very ugly. We should
+ * figure out how to lookup glyphs by name from this font. */
+ switch (clef) {
+ case SCORE_CLEF_G:
+ default:
+ glyph.index = 46;
+ glyph.y = 3 * score->space_height;
+ break;
+ case SCORE_CLEF_F:
+ glyph.index = 45;
+ glyph.y = 1 * score->space_height;
+ break;
+ }
+ glyph.x = 3 * score->line_width;
+ glyph.y += 1;
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+ cairo_show_glyphs (cr, &glyph, 1);
+
+ cairo_rectangle (cr,
+ score->line_width / 2.0,
+ score->line_width / 2.0,
+ score->width - score->line_width,
+ score->space_height * 4);
+
+ for (i = 1; i < 4; i++) {
+ cairo_move_to (cr, 0, i * score->space_height + score->line_width / 2.0);
cairo_rel_line_to (cr, score->width, 0);
}
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, score->line_width);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
cairo_stroke (cr);
cairo_restore (cr);
}
-void
-score_set_width (score_t *score, int width)
+static void
+_draw_grand_staff (score_t *score, cairo_t *cr)
{
- score->width = width;
+#define BRACE_GLYPHS 1
+ cairo_glyph_t brace;
+ cairo_text_extents_t brace_extents;
+ cairo_save (cr);
+
+ /* Brace test */
+ 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.index = 300;
+ brace.x = 0;
+ brace.y = (score->staff_height * 3) / 2 + 1;
+
+ /* 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, (score->staff_height * 3) / 3.85);
+
+ cairo_glyph_extents (cr, &brace, 1, &brace_extents);
+
+ cairo_translate (cr, -brace_extents.x_bearing, 0);
+ score->width += brace_extents.x_bearing;
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+ cairo_show_glyphs (cr, &brace, 1);
+
+ cairo_translate (cr, 2, 0);
+ score->width -= 2;
+
+ /* Vertical lines at each end */
+ cairo_rectangle (cr,
+ score->line_width / 2.0,
+ score->line_width / 2.0,
+ score->width - score->line_width,
+ score->staff_height * 3);
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
+ cairo_set_line_width (cr, score->line_width);
+ cairo_stroke (cr);
+
+ /* Top staff */
+ _draw_staff (score, cr, SCORE_CLEF_G);
+
+ /* Bottom staff */
+ cairo_translate (cr, 0, score->staff_height * 2);
+ _draw_staff (score, cr, SCORE_CLEF_F);
+
+ cairo_restore (cr);
}
void
score_draw (score_t *score, cairo_t *cr)
{
- _draw_staff (score, cr);
+ _draw_grand_staff (score, cr);
}