Hi creak,
I'm not a fulltime programmer, so happy for you to ignore comments if
someone more intelligent has other advice...
Ian
On 25/11/13 09:28, creak ml wrote:
And for those interested, here is the code that, apparently, is better
(I'm not sure since I found it only by experimentation):
bool BenchMarkArea::on_draw(Cairo::RefPtr<Cairo::Context> const& cr)
{
I'd argue your first problem is here. Simple rule: when using a
Cairo::Context, encase everything you do in save/ restore. If you
don't, you have to manually keep track of the context state, which is
difficult/ practically impossible in many cases.
cr->set_antialias(Cairo::ANTIALIAS_NONE);
// ... [skipping boring parts, variables initializations] ...
libbench::BenchVector const& benches = benchList.GetBenches();
for(libbench::BenchVector::const_iterator it = benches.begin(); it
!= benches.end(); ++it)
{
libbench::Bench const& bench = *it;
double benchLeft = leftMargin + bench.m_startTime * m_timeToPx;
double benchWidth = (bench.m_stopTime - bench.m_startTime) *
m_timeToPx;
// Filter unnecessary drawings; too small or outside of the
default clip area.
if(benchWidth < 1.0 || !cr->in_clip(benchLeft, benchTop))
continue;
And again, why not save() here, so that you can return to the Context
within a loop as many times as required? You'll keep the current clip
area within that save(), and probably could set the Pango::Layout
outside this loop so you can reuse it instead of redefining it every
time you enter the loop.
// Want to start as new.
cr->begin_new_path();
// Add rectangle.
cr->rectangle(benchLeft, benchTop, benchWidth, 20.0);
// Fill in yellow-ish and preserve path (for stroke).
cr->set_line_width(1.0);
cr->set_source_rgb(1.0, 0.8, 0.5);
cr->fill_preserve();
// Stroke in black preserve path (for text clipping).
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->stroke_preserve();
If you aren't going to use the path again, why are you preserving it?
That's a waste of memory because you're keeping track of something you
no longer need.
// No need to draw text if there is no space left for it.
if(benchWidth > 2.0)
{
//
http://developer.gnome.org/pangomm/unstable/classPango_1_1Layout.html
Glib::RefPtr<Pango::Layout> layout =
create_pango_layout(bench.GetName());
layout->set_font_description(m_font);
// Get the text dimensions.
int text_width;
int text_height;
layout->get_pixel_size(text_width, text_height);
// Save because we'll need to make a clip reset and good
practice tells us to
// surround these kind of stuff with save/restore.
cr->save();
I'm not sure clipping speeds up things that much in this scenario.
You've still got to draw the entire scene; if it's a static picture,
then you may as well draw it all at once, and clipping will require
greater resources than just drawing. I can see a point in clipping ot
prevent offscreen elements from being computed, but not for onscreen...
but could easily be wrong on that.
// Clip so that text drawing will be done inside the box.
cr->clip();
// Position the text in the middle and draw.
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->move_to(benchLeft + (benchWidth - text_width) / 2,
benchTop + (20.0 - text_height) / 2);
layout->show_in_cairo_context(cr);
// Reset clip and restore.
cr->reset_clip();
cr->restore();
}
}
// Everything is under control.
return true;
}
I still have some questions though, I suppose it's not necessary to
reset the clip since we restore the context just after...
And since I'll have to draw thousands of these kind of little boxes,
do you have some advice to have the fastest drawing method possible?
For instance, is it better to set all the paths and then filling and
stroking them, or dealing with several small paths are more efficient?
Thanks a lot!
--
Romain "Creak" Failliot
2013/11/24 creak ml <creak...@gmail.com <mailto:creak...@gmail.com>>
Ok, changed my gmail parameters, now I'll reply all ;)
_____
Thanks for the answer. Indeed I did read these documentations (of
course not all of them, but the interesting parts I hope).
I think I found why I had very strange results.
In the documentation, the description of cr->rectangle() says that
it "adds a closed-subpath".
The "adds" words got me thinking and, correct me if I'm wrong,
when you have several different paths to draw, it's a good thing
to call cr->begin_new_path() before every new path, isn't it?
I don't think I've seen this in the tutorials.
--
Romain "Creak" Failliot
2013/11/23 Ian Martin <martin...@vodafone.co.nz
<mailto:martin...@vodafone.co.nz>>
On 24/11/13 07:50, creak ml wrote:
Hi!
I'm using a Gtk::DrawingArea to do some a special profiling
drawing tool.
At some point, I want to draw a box, fill it with a color,
stroke it in black and write a text on it (and not drawing
out of the box). I succeeded in a way, but I'm not sure it's
the perfect way of doing it.
Since the drawings in this DrawingArea will be pretty
intensive, I'd like to have some advice from you because I'm
a bit lost with what save, restore and *_preserve methods do...
Here the (simplified) code of the drawing:
// In the on_draw() method.
// cr is a Cairo::RefPtr<Cairo::Context> const&.
// For each box I've got to draw.
// Set the rectangle bounds.
cr->rectangle(rectX, rectY, rectWidth, rectHeight);
// Save it, fill, preserve and restore.
cr->save();
cr->set_source_rgb(1.0, 0.8, 0.5);
cr->fill_preserve();
cr->restore();
// Save it again, stroke, preserve and restore.
cr->save();
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->set_line_width(1.0);
cr->stroke_preserve();
cr->restore();
// Initialize pango font.
Pango::FontDescription font;
font.set_family("DejaVu Sans");
font.set_size(12 * PANGO_SCALE);
font.set_stretch(Pango::STRETCH_CONDENSED);
// Initialize pango layout.
Glib::RefPtr<Pango::Layout> layout =
create_pango_layout(text);
layout->set_font_description(font);
// Get the text dimensions.
int textWidth;
int textHeight;
layout->get_pixel_size(textWidth, textHeight);
// Position the text in the middle.
// Save, clip, set color, move to the middle, draw text,
reset clip, restore.
cr->save();
cr->clip();
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->move_to(rectX + (rectWidth - textWidth) / 2, rectY +
(rectHeight - textHeight) / 2);
layout->show_in_cairo_context(cr);
cr->reset_clip();
cr->restore();
Trust me, if I remove one save/restore or one preserve, the
draw is becoming pretty f*cked up.
Maybe a first thing would be to cache the font.
Do you have other ideas, GTKMM gurus? ;)
Cheers,
Creak
Hi Creak,
I assume you found the manual-
https://developer.gnome.org/gtkmm-tutorial/unstable/index.html
and have read the chapter on drawing? It should answer your
questions. The online (or offline, if you've got the docs )
reference manualhttps://developer.gnome.org/gtkmm/unstable/
<https://developer.gnome.org/gtkmm/unstable/> lists all the
functions including the ones you're asking about; generally
the *mm documentation is of a high standard. Make sure you're
using references for the version you're using; there's been a
number of changes between version 2 and 3 of gtkmm.
tldr: a Cairo::context has a set of attributes at any point in
time, including clip regions, colour for background and
foreground, line size, etc. By encasing all writes to the
Context in save and restore, you prevent your code from
modifying the base context. With that understanding, you may
want to encase your code slightly differently; for instance,
saving before clipping, then saving/ restoring around each
paint (the save / restore functions push the context onto a
stack, so you can have effectively unlimited depth).
The *_preserve functions write to the context but preserve the
path they write on, which is lost with the other (stroke and
fill) methods. Useful if you want to e..g. stroke in one
colour and fill in another. Have a look at the examples in
the manual for ideas.
HTH,
Ian.
_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org <mailto:gtkmm-list@gnome.org>
https://mail.gnome.org/mailman/listinfo/gtkmm-list
_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list
_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list