+
+ return extents.width;
+}
+
+/* Draw the accidental from 'pitch' only (no notehead) at the correct
+ * position as if drawing a note at 'pitch'.
+ *
+ * Returns the width of the drawn glyph.
+ */
+static double
+_draw_accidental (score_t *score,
+ cairo_t *cr,
+ score_staff_t *staff,
+ pitch_t pitch)
+{
+ score_note_t note;
+
+ note.staff = staff;
+ note.pitch = pitch;
+
+ /* A duration of 0 indicates to draw only the accidental. */
+ note.duration = 0;
+
+ note.color.r = 0.0;
+ note.color.g = 0.0;
+ note.color.b = 0.0;
+
+ return _draw_note (score, cr, staff, ¬e);
+}
+
+static void
+_draw_sharps_key_signature (score_t *score, cairo_t *cr,
+ score_staff_t *staff, int num_sharps)
+{
+ pitch_t pitch;
+ double width;
+ int i;
+
+ /* These octave numbers are correct for treble clef. For bass
+ * clef, subtract two.
+ */
+ pitch_t sharps_order[] = {
+ PITCH_LITERAL (F, SHARP, 5),
+ PITCH_LITERAL (C, SHARP, 5),
+ PITCH_LITERAL (G, SHARP, 5),
+ PITCH_LITERAL (D, SHARP, 5),
+ PITCH_LITERAL (A, SHARP, 4),
+ PITCH_LITERAL (E, SHARP, 5),
+ PITCH_LITERAL (B, SHARP, 4)
+ };
+
+ for (i = 0; i < num_sharps; i++) {
+ pitch = sharps_order[i];
+
+ if (staff->clef == SCORE_CLEF_BASS)
+ pitch = pitch_lower_by_octaves (pitch, 2);
+
+ width = _draw_accidental (score, cr, staff, pitch);
+
+#define KEY_SIGNATURE_ACCIDENTAL_SPACING (score->space_height * .15)
+ cairo_translate (cr, ceil (width + KEY_SIGNATURE_ACCIDENTAL_SPACING), 0);
+ }
+}
+
+static void
+_draw_flats_key_signature (score_t *score, cairo_t *cr,
+ score_staff_t *staff, int num_flats)
+{
+ pitch_t pitch;
+ double width;
+ int i;
+
+ /* These octave numbers are correct for treble clef. For bass
+ * clef, subtract two.
+ */
+ pitch_name_t flats_order[] = {
+ PITCH_LITERAL (B, FLAT, 4),
+ PITCH_LITERAL (E, FLAT, 5),
+ PITCH_LITERAL (A, FLAT, 4),
+ PITCH_LITERAL (D, FLAT, 5),
+ PITCH_LITERAL (G, FLAT, 4),
+ PITCH_LITERAL (C, FLAT, 5),
+ PITCH_LITERAL (F, FLAT, 4),
+ };
+
+ for (i = 0; i < num_flats; i++) {
+ pitch = flats_order[i];
+
+ if (staff->clef == SCORE_CLEF_BASS)
+ pitch = pitch_lower_by_octaves (pitch, 2);
+
+ width = _draw_accidental (score, cr, staff, pitch);
+
+ cairo_translate (cr, ceil (width + KEY_SIGNATURE_ACCIDENTAL_SPACING), 0);
+ }
+}
+
+static void
+_draw_key_signature (score_t *score, cairo_t *cr,
+ score_staff_t *staff, pitch_t key)
+{
+ int i;
+
+ pitch_t sharp_keys[] = {
+ PITCH_CLASS_LITERAL (C, NATURAL),
+ PITCH_CLASS_LITERAL (G, NATURAL),
+ PITCH_CLASS_LITERAL (D, NATURAL),
+ PITCH_CLASS_LITERAL (A, NATURAL),
+ PITCH_CLASS_LITERAL (E, NATURAL),
+ PITCH_CLASS_LITERAL (B, NATURAL),
+ PITCH_CLASS_LITERAL (F, SHARP),
+ PITCH_CLASS_LITERAL (C, SHARP),
+ };
+
+ pitch_t flat_keys[] = {
+ PITCH_CLASS_LITERAL (C, NATURAL),
+ PITCH_CLASS_LITERAL (F, NATURAL),
+ PITCH_CLASS_LITERAL (B, FLAT),
+ PITCH_CLASS_LITERAL (E, FLAT),
+ PITCH_CLASS_LITERAL (A, FLAT),
+ PITCH_CLASS_LITERAL (D, FLAT),
+ PITCH_CLASS_LITERAL (G, FLAT),
+ PITCH_CLASS_LITERAL (C, FLAT)
+ };
+
+ for (i = 0; i < ARRAY_SIZE (sharp_keys); i++) {
+ if (sharp_keys[i] == key) {
+ _draw_sharps_key_signature (score, cr, staff, i);
+ return;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE (flat_keys); i++) {
+ if (flat_keys[i] == key) {
+ _draw_flats_key_signature (score, cr, staff, i);
+ return;
+ }
+ }
+
+ fprintf (stderr, "Internal error: Not a key: %s\n", pitch_string (key));
+ exit (1);