X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Ftext.cc;h=438413080a2d7a539283bf157980e5f0d15f126a;hb=007e6bb15b63506a1789fc2159386b48da413130;hp=feb88e199649c7ad9edb44dd4b2b54ad4a07f0fe;hpb=19bd6419157119b976393a0c5966b4be4c962119;p=ardour.git diff --git a/libs/canvas/text.cc b/libs/canvas/text.cc index feb88e1996..438413080a 100644 --- a/libs/canvas/text.cc +++ b/libs/canvas/text.cc @@ -1,5 +1,29 @@ +/* + Copyright (C) 2011-2013 Paul Davis + Author: Carl Hetherington + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include #include -#include "pbd/xml++.h" + +#include "pbd/stacktrace.h" + #include "canvas/text.h" #include "canvas/canvas.h" #include "canvas/utils.h" @@ -9,9 +33,13 @@ using namespace ArdourCanvas; Text::Text (Group* parent) : Item (parent) - , _font_description (0) , _color (0x000000ff) + , _font_description (0) , _alignment (Pango::ALIGN_LEFT) + , _width (0) + , _height (0) + , _need_redraw (false) + , _clamped_width (COORD_MAX) { } @@ -27,67 +55,113 @@ Text::set (string const & text) begin_change (); _text = text; - + + _need_redraw = true; _bounding_box_dirty = true; + end_change (); } void -Text::compute_bounding_box () const +Text::redraw (Cairo::RefPtr context) const { - if (!_canvas || !_canvas->context ()) { - _bounding_box = boost::optional (); - _bounding_box_dirty = false; + if (_text.empty()) { return; } - - Pango::Rectangle const r = layout (_canvas->context())->get_ink_extents (); - - _bounding_box = Rect ( - r.get_x() / Pango::SCALE, - r.get_y() / Pango::SCALE, - (r.get_x() + r.get_width()) / Pango::SCALE, - (r.get_y() + r.get_height()) / Pango::SCALE - ); - - _bounding_box_dirty = false; + + Glib::RefPtr layout = Pango::Layout::create (context); + + _redraw (layout); } -Glib::RefPtr -Text::layout (Cairo::RefPtr context) const +void +Text::redraw (Glib::RefPtr context) const { + if (_text.empty()) { + return; + } + Glib::RefPtr layout = Pango::Layout::create (context); + _redraw (layout); +} + +void +Text::_redraw (Glib::RefPtr layout) const +{ layout->set_text (_text); + if (_font_description) { layout->set_font_description (*_font_description); } + layout->set_alignment (_alignment); - return layout; + + int w; + int h; + + layout->get_size (w, h); + + _width = w / Pango::SCALE; + _height = h / Pango::SCALE; + + _image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _width, _height); + + Cairo::RefPtr img_context = Cairo::Context::create (_image); + + /* and draw, in the appropriate color of course */ + + set_source_rgba (img_context, _color); + + layout->show_in_cairo_context (img_context); + + /* text has now been rendered in _image and is ready for blit in + * ::render + */ + + _need_redraw = false; } void Text::render (Rect const & /*area*/, Cairo::RefPtr context) const { - set_source_rgba (context, _color); - layout (context)->show_in_cairo_context (context); + if (_text.empty()) { + return; + } + + if (_need_redraw) { + redraw (context); + } + + Rect self = item_to_window (Rect (0, 0, min (_clamped_width, _width), _height)); + + context->rectangle (self.x0, self.y0, self.width(), self.height()); + context->set_source (_image, self.x0, self.y0); + context->fill (); } -XMLNode * -Text::get_state () const +void +Text::clamp_width (double w) { - XMLNode* node = new XMLNode ("Text"); -#ifdef CANVAS_DEBUG - if (!name.empty ()) { - node->add_property ("name", name); - } -#endif - return node; + _clamped_width = w; } void -Text::set_state (XMLNode const * /*node*/) +Text::compute_bounding_box () const { - /* XXX */ + if (!_canvas || _text.empty()) { + _bounding_box = boost::optional (); + _bounding_box_dirty = false; + return; + } + + if (_bounding_box_dirty) { + if (_need_redraw || !_image) { + Glib::RefPtr context = Glib::wrap (gdk_pango_context_get()); // context now owns C object and will free it + redraw (context); + } + _bounding_box = Rect (0, 0, min (_clamped_width, (double) _image->get_width()), _image->get_height()); + _bounding_box_dirty = false; + } } void @@ -96,7 +170,7 @@ Text::set_alignment (Pango::Alignment alignment) begin_change (); _alignment = alignment; - + _need_redraw = true; _bounding_box_dirty = true; end_change (); } @@ -107,6 +181,7 @@ Text::set_font_description (Pango::FontDescription font_description) begin_change (); _font_description = new Pango::FontDescription (font_description); + _need_redraw = true; _bounding_box_dirty = true; end_change (); @@ -118,8 +193,19 @@ Text::set_color (Color color) begin_change (); _color = color; + _need_redraw = true; end_change (); } +void +Text::dump (ostream& o) const +{ + Item::dump (o); + + o << _canvas->indent() << '\t' << " text = " << _text << endl + << _canvas->indent() << " color = " << _color; + + o << endl; +}