mo' better debugging of canvas "structure" via Item::dump and derivatives
[ardour.git] / libs / canvas / text.cc
1 #include <cairomm/cairomm.h>
2 #include <gtkmm/label.h>
3
4 #include "pbd/xml++.h"
5
6 #include "canvas/text.h"
7 #include "canvas/canvas.h"
8 #include "canvas/utils.h"
9
10 using namespace std;
11 using namespace ArdourCanvas;
12
13 Text::Text (Group* parent)
14         : Item (parent)
15         , _color (0x000000ff)
16         , _font_description (0)
17         , _alignment (Pango::ALIGN_LEFT)
18         , _width (0)
19         , _height (0)
20         , _need_redraw (false)
21 {
22
23 }
24
25 Text::~Text ()
26 {
27         delete _font_description;
28 }
29
30 void
31 Text::set (string const & text)
32 {
33         begin_change ();
34         
35         _text = text;
36
37         _need_redraw = true;
38         _bounding_box_dirty = true;
39
40         end_change ();
41 }
42
43 void
44 Text::redraw (Cairo::RefPtr<Cairo::Context> context) const
45 {
46         Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (context);
47
48         layout->set_text (_text);
49
50         if (_font_description) {
51                 layout->set_font_description (*_font_description);
52         }
53
54         layout->set_alignment (_alignment);
55         
56         Pango::Rectangle ink_rect = layout->get_ink_extents();
57         
58         _origin.x = ink_rect.get_x() / Pango::SCALE;
59         _origin.y = ink_rect.get_y() / Pango::SCALE;
60
61         _width = _origin.x + ((ink_rect.get_width() + Pango::SCALE / 2) / Pango::SCALE);
62         _height = _origin.y + ((ink_rect.get_height() + Pango::SCALE / 2) / Pango::SCALE);
63         
64         _image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _width, _height);
65
66         Cairo::RefPtr<Cairo::Context> img_context = Cairo::Context::create (_image);
67
68         /* and draw, in the appropriate color of course */
69
70         set_source_rgba (img_context, _color);
71         
72         std::cerr << "render " << _text << " as " 
73                   << ((_color >> 24) & 0xff) / 255.0
74                   << ((_color >> 16) & 0xff) / 255.0
75                   << ((_color >>  8) & 0xff) / 255.0
76                   << ((_color >>  0) & 0xff) / 255.
77                   << std::endl;
78
79         layout->show_in_cairo_context (img_context);
80
81         /* text has now been rendered in _image and is ready for blit in
82          * ::render 
83          */
84
85         _need_redraw = false;
86 }
87
88 void
89 Text::compute_bounding_box () const
90 {
91         if (!_canvas || !_canvas->context () || _text.empty()) {
92                 _bounding_box = boost::optional<Rect> ();
93                 _bounding_box_dirty = false;
94                 return;
95         }
96
97         redraw (_canvas->context());
98
99         _bounding_box = Rect (_origin.x, _origin.y, _width - _origin.x, _height - _origin.y);
100         _bounding_box_dirty = false;
101
102         cerr << "bbox for " << _text << " = " << _bounding_box << endl;
103 }
104
105 void
106 Text::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
107 {
108         if (_text.empty()) {
109                 return;
110         }
111
112         if (_need_redraw) {
113                 redraw (context);
114         }
115         
116         cerr << " with " << _origin  << " and " << _width << " x " << _height << " render " << _text << endl;
117
118         context->set_source (_image, 0, 0);
119         context->rectangle (0, 0, _width, _height);
120         context->fill ();
121 }
122
123 XMLNode *
124 Text::get_state () const
125 {
126         XMLNode* node = new XMLNode ("Text");
127 #ifdef CANVAS_DEBUG
128         if (!name.empty ()) {
129                 node->add_property ("name", name);
130         }
131 #endif
132         return node;
133 }
134
135 void
136 Text::set_state (XMLNode const * /*node*/)
137 {
138         /* XXX */
139 }
140
141 void
142 Text::set_alignment (Pango::Alignment alignment)
143 {
144         begin_change ();
145         
146         _alignment = alignment;
147         _need_redraw = true;
148         _bounding_box_dirty = true;
149         end_change ();
150 }
151
152 void
153 Text::set_font_description (Pango::FontDescription font_description)
154 {
155         begin_change ();
156         
157         _font_description = new Pango::FontDescription (font_description);
158         _need_redraw = true;
159
160         _bounding_box_dirty = true;
161         end_change ();
162 }
163
164 void
165 Text::set_color (Color color)
166 {
167         begin_change ();
168
169         _color = color;
170         _need_redraw = true;
171
172         end_change ();
173 }
174
175                 
176 void
177 Text::dump (ostream& o) const
178 {
179         Item::dump (o);
180
181         o << _canvas->indent() << '\t' << " text = " << _text << endl
182           << _canvas->indent() << " color = " << _color;
183
184         o << endl;
185 }