mirror of
https://github.com/alexkay/spek.git
synced 2025-06-09 20:02:19 +03:00
Factor out the ruler code
This commit is contained in:
parent
3feb64543e
commit
71a8cccb4b
@ -2,6 +2,7 @@ bin_PROGRAMS = spek
|
||||
|
||||
spek_SOURCES = \
|
||||
spek.vala \
|
||||
spek-ruler.vala \
|
||||
spek-source.vala \
|
||||
spek-spectrogram.vala \
|
||||
spek-window.vala
|
||||
|
86
src/spek-ruler.vala
Normal file
86
src/spek-ruler.vala
Normal file
@ -0,0 +1,86 @@
|
||||
/* spek-spectrogram.vala
|
||||
*
|
||||
* Copyright (C) 2010 Alexander Kojevnikov <alexander@kojevnikov.com>
|
||||
*
|
||||
* Spek is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Spek is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Spek. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Cairo;
|
||||
|
||||
namespace Spek {
|
||||
class Ruler : GLib.Object {
|
||||
|
||||
private string sample_label;
|
||||
private int[] factors;
|
||||
private int units;
|
||||
private UnitToPixel unit_to_pixel;
|
||||
private FormatTick format_tick;
|
||||
|
||||
public delegate double UnitToPixel (int unit);
|
||||
public delegate string FormatTick (int unit);
|
||||
|
||||
public Ruler (
|
||||
string sample_label, int[] factors, int units,
|
||||
UnitToPixel unit_to_pixel, FormatTick format_tick) {
|
||||
this.sample_label = sample_label;
|
||||
this.factors = factors;
|
||||
this.units = units;
|
||||
this.unit_to_pixel = unit_to_pixel;
|
||||
this.format_tick = format_tick;
|
||||
}
|
||||
|
||||
public void draw (Context cr) {
|
||||
// Mesure the sample label.
|
||||
TextExtents ext;
|
||||
cr.text_extents (sample_label, out ext);
|
||||
var label_width = ext.width;
|
||||
|
||||
// Select the factor to use, we want some space between the labels.
|
||||
int factor = 0;
|
||||
foreach (var f in factors) {
|
||||
if (unit_to_pixel (f) >= 1.5 * label_width) {
|
||||
factor = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the ticks.
|
||||
int[] ticks = { 0, units };
|
||||
if (factor > 0) {
|
||||
for (var tick = factor; tick < units; tick += factor) {
|
||||
if (unit_to_pixel (units - tick) < label_width) {
|
||||
break;
|
||||
}
|
||||
ticks += tick;
|
||||
}
|
||||
// TODO: `ticks = ticks[0:-1]` crashes, file a bug.
|
||||
}
|
||||
|
||||
// Draw the ticks.
|
||||
double GAP = 10;
|
||||
double TICK_LEN = 4;
|
||||
foreach (var tick in ticks) {
|
||||
var label = format_tick (tick);
|
||||
var pos = unit_to_pixel (tick);
|
||||
cr.text_extents (label, out ext);
|
||||
// TODO: use font measurements instead ext.height
|
||||
cr.move_to (pos - ext.width / 2, GAP + ext.height);
|
||||
cr.show_text (label);
|
||||
cr.move_to (pos, 0);
|
||||
cr.rel_line_to (0, TICK_LEN);
|
||||
cr.stroke ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -123,46 +123,17 @@ namespace Spek {
|
||||
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 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) {
|
||||
if (time_to_px (duration_seconds - tick, w, duration_seconds) < label_width) {
|
||||
break;
|
||||
}
|
||||
ticks += tick;
|
||||
}
|
||||
// TODO: `ticks = ticks[0:-1]` crashes, file a bug.
|
||||
}
|
||||
|
||||
// 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);
|
||||
cr.rel_line_to (0, 4);
|
||||
cr.stroke ();
|
||||
}
|
||||
// Time ruler.
|
||||
var duration_seconds = (int) (source.duration / 1000000000);
|
||||
var time_ruler = new Ruler (
|
||||
"00:00",
|
||||
{1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60},
|
||||
duration_seconds,
|
||||
unit => (w - 2 * PADDING) * unit / duration_seconds,
|
||||
unit => "%d:%02d".printf (unit / 60, unit % 60));
|
||||
cr.translate (PADDING, h - PADDING);
|
||||
time_ruler.draw (cr);
|
||||
cr.identity_matrix ();
|
||||
}
|
||||
|
||||
// Border around the spectrogram.
|
||||
@ -180,11 +151,6 @@ 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 ();
|
||||
|
Loading…
x
Reference in New Issue
Block a user