spek

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

commit c1b81582a1093bd24eda658234988d477952577c
parent ef4001f76df5aa346a60e0041d404756d1edfc1a
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Tue, 22 Jun 2010 19:57:24 +1000

Use Pango to render text

Diffstat:
Msrc/spek-ruler.vala | 20+++++++++++---------
Msrc/spek-spectrogram.vala | 67++++++++++++++++++++++---------------------------------------------
2 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/src/spek-ruler.vala b/src/spek-ruler.vala @@ -17,6 +17,7 @@ */ using Cairo; +using Pango; namespace Spek { class Ruler : GLib.Object { @@ -42,11 +43,12 @@ namespace Spek { this.format_tick = format_tick; } - public void draw (Context cr, bool horizontal) { + public void draw (Cairo.Context cr, Pango.Layout layout, bool horizontal) { // Mesure the sample label. - TextExtents ext; - cr.text_extents (sample_label, out ext); - var size = horizontal ? ext.width : ext.height; + int w, h; + layout.set_text (sample_label, -1); + layout.get_pixel_size (out w, out h); + var size = horizontal ? w : h; // Select the factor to use, we want some space between the labels. int factor = 0; @@ -75,14 +77,14 @@ namespace Spek { foreach (var tick in ticks) { var label = format_tick (tick); var pos = unit_to_pixel (horizontal ? tick : units - tick); - cr.text_extents (label, out ext); - // TODO: use font measurements instead ext.height + layout.set_text (label, -1); + layout.get_pixel_size (out w, out h); if (horizontal) { - cr.move_to (pos - ext.width / 2, GAP + ext.height); + cr.move_to (pos - w / 2, GAP + h); } else { - cr.move_to (-ext.width - GAP, pos + ext.height / 2); + cr.move_to (-w - GAP, pos + h / 2); } - cr.show_text (label); + cairo_show_layout_line (cr, layout.get_line (0)); if (horizontal) { cr.move_to (pos, 0); cr.rel_line_to (0, TICK_LEN); diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala @@ -19,6 +19,7 @@ using Cairo; using Gdk; using Gtk; +using Pango; namespace Spek { class Spectrogram : DrawingArea { @@ -60,7 +61,7 @@ namespace Spek { public void save (string file_name) { var surface = new ImageSurface (Format.RGB24, allocation.width, allocation.height); - draw (new Context (surface)); + draw (new Cairo.Context (surface)); surface.write_to_png (file_name); } @@ -136,7 +137,7 @@ namespace Spek { return true; } - private void draw (Context cr) { + private void draw (Cairo.Context cr) { double w = allocation.width; double h = allocation.height; @@ -156,8 +157,9 @@ namespace Spek { 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); + var layout = cairo_create_layout (cr); + layout.set_font_description (FontDescription.from_string ("Sans 8")); + layout.set_width (-1); // Time ruler. var duration_seconds = (int) (source.duration / 1000000000); @@ -169,7 +171,7 @@ namespace Spek { unit => (w - LPAD - RPAD) * unit / duration_seconds, unit => "%d:%02d".printf (unit / 60, unit % 60)); cr.translate (LPAD, h - BPAD); - time_ruler.draw (cr, true); + time_ruler.draw (cr, layout, true); cr.identity_matrix (); // Frequency ruler. @@ -178,25 +180,30 @@ namespace Spek { "00 kHz", {1000, 2000, 5000, 10000, 20000}, freq, - 4.0, + 3.0, unit => (h - TPAD - BPAD) * unit / freq, unit => "%d kHz".printf (unit / 1000)); cr.translate (LPAD, TPAD); - rate_ruler.draw (cr, false); + rate_ruler.draw (cr, layout, false); cr.identity_matrix (); // File properties. - cr.set_font_size (11.0); cr.move_to (LPAD, TPAD - GAP); - cr.show_text (trim (cr, info, w - LPAD - RPAD, true)); - FontExtents ext; - cr.font_extents (out ext); + layout.set_font_description (FontDescription.from_string ("Sans 9")); + layout.set_width ((int) (w - LPAD - RPAD) * Pango.SCALE); + layout.set_ellipsize (EllipsizeMode.END); + layout.set_text (info, -1); + cairo_show_layout_line (cr, layout.get_line (0)); + int text_width, text_height; + layout.get_pixel_size (out text_width, out text_height); // File name. - cr.select_font_face ("sans-serif", FontSlant.NORMAL, FontWeight.BOLD); - cr.set_font_size (12.0); - cr.move_to (LPAD, TPAD - 2 * GAP - ext.ascent); - cr.show_text (trim (cr, file_name, w - LPAD - RPAD, false)); + cr.move_to (LPAD, TPAD - 2 * GAP - text_height); + layout.set_font_description (FontDescription.from_string ("Sans Bold 10")); + layout.set_width ((int) (w - LPAD - RPAD) * Pango.SCALE); + layout.set_ellipsize (EllipsizeMode.START); + layout.set_text (file_name, -1); + cairo_show_layout_line (cr, layout.get_line (0)); } // Border around the spectrogram. @@ -214,36 +221,6 @@ namespace Spek { cr.identity_matrix (); } - // Trim `s` so that it fits into `length`. - private string trim (Context cr, string s, double length, bool end) { - if (length <= 0.0) { - return ""; - } - - // Check if the entire string fits. - TextExtents ext; - cr.text_extents (s, out ext); - if (ext.width <= length) { - return s; - } - - // Binary search FTW! - var fix = "..."; - long i = 0; - long k = s.length; - while (k - i > 1) { - var j = (i + k) / 2; - cr.text_extents (end ? s[0:j] + fix : fix + s[j:s.length], out ext); - if (end != (ext.width > length)) { - i = j; - } else { - k = j; - } - } - - return end ? s[0:i] + fix : fix + s[k:s.length]; - } - 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 ();