spek

Acoustic spectrum analyser
git clone http://git.hanabi.in/repos/spek.git
Log | Files | Refs | README

commit 5ef71cbb9bcd9f4dff30b33ec7a3e348b01f29e2
parent f625d32a6e5393de4757ed930caf5ff802fb2008
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Sun, 16 May 2010 19:30:53 +1000

Auto-fitting duration ticks

Diffstat:
Msrc/spek-spectrogram.vala | 44+++++++++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 7 deletions(-)

diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala @@ -116,21 +116,46 @@ namespace Spek { cr.paint (); cr.identity_matrix (); - // Time ruler. - int64[] time_points = {0, source.duration}; + // Prepare to draw the time ruler. cr.set_source_rgb (1, 1, 1); cr.set_line_width (1); cr.set_antialias (Antialias.NONE); cr.select_font_face ("sans-serif", FontSlant.NORMAL, FontWeight.NORMAL); cr.set_font_size (10.0); + + // Mesure the label text. TextExtents ext; cr.text_extents ("00:00", out ext); - double tick_width = ext.width; - foreach (var pt in time_points) { - var seconds = (int) (pt / 1000000000); - var label = "%d:%02d".printf (seconds / 60, seconds % 60); - var pos = PADDING + (w - 2 * PADDING) * pt / source.duration; + double label_width = ext.width; + + // Select the factor to use, we want some space between the labels. + int duration_seconds = (int) (source.duration / 1000000000); + int[] time_factors = {1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60}; + int time_factor = 0; + foreach (var factor in time_factors) { + if (time_to_px (factor, w, duration_seconds) >= 1.5 * label_width) { + time_factor = factor; + break; + } + } + + // Add the ticks. + int[] ticks = { 0, duration_seconds }; + if (time_factor > 0) { + for (var tick = time_factor; tick < duration_seconds; tick += time_factor) { + ticks += tick; + } + // The last item should be skipped, it's too close to the end tick. + // TODO: `ticks = ticks[0:-1]` crashes, file a bug. + ticks = ticks[0:ticks.length - 1]; + } + + // Draw the ticks. + foreach (var tick in ticks) { + var label = "%d:%02d".printf (tick / 60, tick % 60); + var pos = PADDING + time_to_px (tick, w, duration_seconds); cr.text_extents (label, out ext); + // TODO: use font measurements instead ext.height cr.move_to (pos - ext.width / 2, h - PADDING + GAP + ext.height); cr.show_text (label); cr.move_to (pos, h - PADDING); @@ -154,6 +179,11 @@ namespace Spek { cr.identity_matrix (); } + // TODO: factor out the ruler logic and pass this as an anonymous method. + private double time_to_px (int time, double w, int duration_seconds) { + return (w - 2 * PADDING) * time / duration_seconds; + } + private void put_pixel (ImageSurface surface, int x, int y, uint32 color) { var i = y * surface.get_stride () + x * 4; unowned uchar[] data = surface.get_data ();