]> git.cworth.org Git - scherzo/commitdiff
Allow computer-keyboard input of accidentals, and draw accidentals.
authorCarl Worth <cworth@cworth.org>
Sun, 22 Sep 2013 22:15:03 +0000 (15:15 -0700)
committerCarl Worth <cworth@cworth.org>
Sun, 22 Sep 2013 22:15:03 +0000 (15:15 -0700)
All accidentals are drawn assuming the key of C major, for now. That is,
natural symbols will not be drawn, but all other accidental symbols will
be drawn.

No care is taken to avoid accidentals colliding with each other when drawn.

scherzo.c
score.c

index b0f2c44ac05d1d96018c12f57874c96eb7bfa8de..b9a463368b86129dd1eee0cdd74cdabcecf7b561 100644 (file)
--- a/scherzo.c
+++ b/scherzo.c
@@ -60,9 +60,11 @@ typedef struct scherzo
     score_staff_t *bass;
     score_chord_t *chord;
 
     score_staff_t *bass;
     score_chord_t *chord;
 
-    /* This is for a "computer keyboard". Any "piano keyboard" key
-     * knows its own octave. */
+    /* The word "keyboard" here is referring to a "computer
+     * keyboard". Any "piano keyboard" key knows its own octave and
+     * accidental already. */
     int keyboard_octave;
     int keyboard_octave;
+    score_pitch_accidental_t keyboard_accidental;
 
     int midi_fd;
     snd_midi_event_t *snd_midi_event;
 
     int midi_fd;
     snd_midi_event_t *snd_midi_event;
@@ -215,9 +217,17 @@ on_key_press_event (GtkWidget *widget,
     case GDK_KEY_space:
        scherzo_press_pedal (scherzo);
        break;
     case GDK_KEY_space:
        scherzo_press_pedal (scherzo);
        break;
+    case GDK_KEY_Up:
+       if (scherzo->keyboard_accidental < SCORE_PITCH_ACCIDENTAL_DOUBLE_SHARP)
+           scherzo->keyboard_accidental++;
+       break;
+    case GDK_KEY_Down:
+       if (scherzo->keyboard_accidental > SCORE_PITCH_ACCIDENTAL_DOUBLE_FLAT)
+           scherzo->keyboard_accidental--;
+       break;
     }
 
     }
 
-    pitch = SCORE_PITCH (pitch_name, SCORE_PITCH_ACCIDENTAL_NATURAL);
+    pitch = SCORE_PITCH (pitch_name, scherzo->keyboard_accidental);
 
     if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
        (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
 
     if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
        (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
@@ -285,7 +295,7 @@ on_key_release_event (unused (GtkWidget *widget),
        break;
     }
 
        break;
     }
 
-    pitch = SCORE_PITCH (pitch_name, SCORE_PITCH_ACCIDENTAL_NATURAL);
+    pitch = SCORE_PITCH (pitch_name, scherzo->keyboard_accidental);
 
     if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
        (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
 
     if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
        (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
@@ -989,8 +999,9 @@ main (int argc, char *argv[])
 
     scherzo.chord = NULL;
 
 
     scherzo.chord = NULL;
 
-    /* Default to octave 4 for computer keyboard keypresses. */
+    /* Default to octave 4 and natural for computer keyboard keypresses. */
     scherzo.keyboard_octave = 4;
     scherzo.keyboard_octave = 4;
+    scherzo.keyboard_accidental = SCORE_PITCH_ACCIDENTAL_NATURAL;
 
     note_group_init (scherzo.ctx, &scherzo.notes_pressed);
     note_group_init (scherzo.ctx, &scherzo.notes_pedaled);
 
     note_group_init (scherzo.ctx, &scherzo.notes_pressed);
     note_group_init (scherzo.ctx, &scherzo.notes_pedaled);
diff --git a/score.c b/score.c
index ac0d346522715896fc3c2e478a3a215a2b32619e..25187ba06e19a7ead61a27aae5fc77b6c351828e 100644 (file)
--- a/score.c
+++ b/score.c
@@ -218,12 +218,13 @@ _draw_note (score_t *score, cairo_t *cr,
            score_staff_t *staff, score_note_t *note)
 {
     double line;
            score_staff_t *staff, score_note_t *note)
 {
     double line;
-    cairo_glyph_t note_glyph;
+    cairo_glyph_t note_glyph[2];
     static double extend_factor = 0.25;
     static double extend_factor = 0.25;
+    cairo_text_extents_t extents;
+    int num_glyphs = 0;
 
 
-    void _draw_ledger_line (double line, double width) {
-       cairo_move_to (cr,
-                      - width * extend_factor / 2.0,
+    void _draw_ledger_line (double line, double offset, double width) {
+       cairo_move_to (cr, offset - extend_factor * width / 2.0,
                       score->space_height * line + score->line_width / 2.0);
        cairo_rel_line_to (cr, (1 + extend_factor) * width, 0);
        cairo_stroke (cr);
                       score->space_height * line + score->line_width / 2.0);
        cairo_rel_line_to (cr, (1 + extend_factor) * width, 0);
        cairo_stroke (cr);
@@ -231,6 +232,11 @@ _draw_note (score_t *score, cairo_t *cr,
 
     cairo_save (cr);
 
 
     cairo_save (cr);
 
+    /* Move right so that X==0 is natural position for non-displaced
+     * noteheads.
+     */
+    cairo_translate (cr, score->space_height, 0);
+
     /* Which line should the note appear on? Line 0 is the top line of
      * the staff and increasing downwards. (Negative values indicate a
      * note on a ledger line above the staff). Values half way between
     /* Which line should the note appear on? Line 0 is the top line of
      * the staff and increasing downwards. (Negative values indicate a
      * note on a ledger line above the staff). Values half way between
@@ -243,12 +249,45 @@ _draw_note (score_t *score, cairo_t *cr,
 
     /* XXX: The hard-coded glyph indices here are very ugly. We should
      * figure out how to lookup glyphs by name from this font. */
 
     /* XXX: The hard-coded glyph indices here are very ugly. We should
      * figure out how to lookup glyphs by name from this font. */
+    switch (SCORE_PITCH_ACCIDENTAL (note->pitch)) {
+    case SCORE_PITCH_ACCIDENTAL_DOUBLE_FLAT:
+           note_glyph[num_glyphs].index = 77;
+           break;
+    case SCORE_PITCH_ACCIDENTAL_FLAT:
+           note_glyph[num_glyphs].index = 68;
+           break;
+    case SCORE_PITCH_ACCIDENTAL_NATURAL:
+           note_glyph[num_glyphs].index = 101;
+           break;
+    case SCORE_PITCH_ACCIDENTAL_SHARP:
+           note_glyph[num_glyphs].index = 134;
+           break;
+    case SCORE_PITCH_ACCIDENTAL_DOUBLE_SHARP:
+           note_glyph[num_glyphs].index = 142;
+           break;
+    }
+
+    if (SCORE_PITCH_ACCIDENTAL (note->pitch) != SCORE_PITCH_ACCIDENTAL_NATURAL)
+    {
+           note_glyph[num_glyphs].x = 0;
+
+           note_glyph[num_glyphs].y = score->space_height * line;
+
+           num_glyphs++;
+
+           cairo_glyph_extents (cr, note_glyph, num_glyphs, &extents);
+
+#define ACCIDENTAL_NOTE_SPACING (score->space_height * .15)
+
+           note_glyph[0].x = - (extents.width + ACCIDENTAL_NOTE_SPACING);
+    }
+
     switch (note->duration) {
     case SCORE_DURATION_1:
     switch (note->duration) {
     case SCORE_DURATION_1:
-       note_glyph.index = 127;
+       note_glyph[num_glyphs].index = 127;
        break;
     case SCORE_DURATION_2:
        break;
     case SCORE_DURATION_2:
-       note_glyph.index = 85;
+       note_glyph[num_glyphs].index = 85;
        break;
     case SCORE_DURATION_4:
     case SCORE_DURATION_8:
        break;
     case SCORE_DURATION_4:
     case SCORE_DURATION_8:
@@ -257,24 +296,28 @@ _draw_note (score_t *score, cairo_t *cr,
     case SCORE_DURATION_64:
     case SCORE_DURATION_128:
     default:
     case SCORE_DURATION_64:
     case SCORE_DURATION_128:
     default:
-       note_glyph.index = 84;
+       note_glyph[num_glyphs].index = 84;
     }
 
     }
 
-    note_glyph.x = 0;
-    note_glyph.y = score->space_height * line;
+    note_glyph[num_glyphs].x = 0;
+    note_glyph[num_glyphs].y = score->space_height * line;
+
+    num_glyphs++;
 
     if (line < 0 || line > 4) {
 
     if (line < 0 || line > 4) {
+       double offset, width;
        int i;
        int i;
-       cairo_text_extents_t note_extents;
 
 
-       cairo_glyph_extents (cr, &note_glyph, 1, &note_extents);
+       cairo_glyph_extents (cr, note_glyph, num_glyphs, &extents);
+       offset = note_glyph[0].x + extents.x_bearing;
+       width = extents.width;
 
        if (line < 0) {
            for (i = -1; i >= line; i--)
 
        if (line < 0) {
            for (i = -1; i >= line; i--)
-               _draw_ledger_line (i, note_extents.width);
+               _draw_ledger_line (i, offset, width);
        } else {
            for (i = 5; i <= line; i++)
        } else {
            for (i = 5; i <= line; i++)
-               _draw_ledger_line (i, note_extents.width);
+               _draw_ledger_line (i, offset, width);
        }
     }
 
        }
     }
 
@@ -282,7 +325,7 @@ _draw_note (score_t *score, cairo_t *cr,
                          note->color.r,
                          note->color.g,
                          note->color.b);
                          note->color.r,
                          note->color.g,
                          note->color.b);
-    cairo_show_glyphs (cr, &note_glyph, 1);
+    cairo_show_glyphs (cr, note_glyph, num_glyphs);
 
     cairo_restore (cr);
 }
 
     cairo_restore (cr);
 }