Corner roundness and paint
I'd like to add rounded corners to my UI object. I have defined the _getdrawparams function, with d_boxfillcolor and d_cornersize.
My issue is: is there a way to constraint everything I paint in the _paint method to the area defined in _getdrawparams? (i.e. with the given cornersize?) More explicitely: if now inside the paint method I draw a red rectangle from (0, 0) with the width and height of my object, the corners of the objects are completely painted of red, whereas I'd like to preserve the corner roundness no matter what I ask to paint. (This is by the way a trivial example, but you can imagine more complicate examples, where I simply want to paint the portion of my object which is located next to a given corner, preserving the corner roundness).
Thanks a lot,
Daniele
Hi Daniele,
for what you are trying to achieve I don't think you can use the getdrawparams method.
As far as I can tell, getdrawparams is just a convenience method to let Max do the 'background' drawing, but it doesn't allow for any clipping of the graphic context.
The way I would go about it is something like this:
(coded from the top of my head WITHOUT testing - use with caution)
t_jgraphics *g, *g2;
t_jsurface *s;
t_rect rect;
g = (t_jgraphics *)patcherview_get_jgraphics(view);
jbox_get_rect_for_view((t_object *)x, view, &rect);
s = jgraphics_image_surface_create(JGRAPHICS_FORMAT_ARGB32, jgraphics_round(rect.width), jgraphics_round(rect.height));
g2 = jgraphics_create(s);
// do all the drawing you need using g2 - it will be clipped to the rounded rectangle later
jgraphics_destroy(g2);
jgraphics_set_source_surface(g, s, 0, 0);
jgraphics_surface_destroy(s);
jgraphics_rectangle_rounded(g, 0, 0, rect.width, rect.height, x->cornersize, x->cornersize);
jgraphics_fill(g);
Let me know if this solves your problem.
Ciao
- Luigi
Works like a charm, thanks a lot. I'll do the same for each painted layer.
Thanks again,
Daniele
...well, actually I have a problem with zooming: when I zoom the patch, I lose the good resolution of vectorial text... Is there something I can do about it, without losing the benefits I get from your clipping algorithm?
Sorry, I can't reproduce the problem.
I have an external that implements the above code and when I zoom the patch the text is displayed as expected.
Can you give me more information about the problem? What Max version are you using?
Here's a simple code that doesn't work neither in Max 5.1.9 nor in Max 6.0.7. It simply writes a line of text, and when I zoom the patch, the text is blurred (just like when you zoom a non-vectorial image). I have surely misunderstood something you have told me... Can you spot what? (Does if work for you?) I can't see any difference with your code...
Thanks again for your help!
Daniele
void myobj_paint(t_myobj *x, t_object *view){
t_jgraphics *g, *g2;
t_rect rect;
t_jsurface *s;
t_jfont *jf_text;
t_jrgba textcolor, bgcolor;
// getting rectangle dimensions
g = (t_jgraphics *) patcherview_get_jgraphics(view);
jbox_get_rect_for_view(&x->r_ob.j_box.l_box.b_ob, view, &rect);
s = jgraphics_image_surface_create(JGRAPHICS_FORMAT_ARGB32, jgraphics_round(rect.width), jgraphics_round(rect.height));
g2 = jgraphics_create(s);
// writing text
jf_text = jfont_create_debug("Arial", JGRAPHICS_FONT_SLANT_NORMAL, JGRAPHICS_FONT_WEIGHT_NORMAL, 11);
textcolor.red = textcolor.green = textcolor.blue = 0;
textcolor.alpha = 1;
bgcolor.red = bgcolor.green = bgcolor.blue = bgcolor.alpha = 1;
jgraphics_set_source_jrgba(g2, &bgcolor);
jgraphics_set_line_width(g2, 0);
jgraphics_rectangle(g2, 0, 0, rect.width, rect.height);
jgraphics_fill(g2);
t_jtextlayout *jtl;
jtl = jtextlayout_create();
jtextlayout_set(jtl, "Onset FOO, Cents FOO", jf_text, 0, 0, rect.width, rect.height, JGRAPHICS_TEXT_JUSTIFICATION_LEFT, JGRAPHICS_TEXTLAYOUT_USEELLIPSIS);
jtextlayout_settextcolor(jtl, &textcolor);
jtextlayout_draw(jtl, g2);
jtextlayout_destroy(jtl);
// destroying stuff and filling surface
jgraphics_destroy(g2);
jgraphics_set_source_surface(g, s, 0, 0);
jgraphics_surface_destroy(s);
jgraphics_rectangle_rounded(g, 0, 0, rect.width, rect.height, 6, 6);
jgraphics_fill(g);
}
Hi,
without trying it out, text display might also depend on the "Native rendering" setting of Max. Did you try whether turning that on or off would solve your problem?
Cheers,
Ádám
Yes, I had already tried that... no difference as far as I am concerned.
- Luigi
Hi nicolas, that is exactly what I also get (native text rendering doesn't change result that much).
Luigi: does it work better on your machine? If yes, why? :S
Thanks again to everybody,
Daniele
Ok, I have experimented a little bit more in depth...
No, it doesn't work better on my machine and I have the same problem.
It looks like that Max treats surfaces as bitmap images and therefore they lose all the nice properties of vector graphics. With text it's more noticeable, but even if you draw lines and circles you should see them pixelate at high zoom ratios. Of course that becomes less noticeable with filled shapes, but it's still there.
I don't think a real solution is possible, other than not using surfaces.
In Daniele's case, it would be possible to draw the text directly in the main graphic context (g) with text margins shrinking or expanding depending on the corner size. That way text will never "spill out" of the rounded corners.
In any case I am very surprised that - as far as I can tell - there's no way with the current API to clip the graphic context without losing the benefits of vector graphics.
Of course I would love to be proved wrong on this last point.
Great discussion, BTW...
Cheers.
- Luigi
Thanks Luigi for your help,
shrinking text margins is kind of a hell, plus i'd have to do the very same for anything I draw: lines, shapes... the UI object is quite complex. Clipping "by hand" is really not a path which I can follow.
I'm surprised too... Maybe someone at Cycling could make some light on some possibilities we have overlooked?
Thanks,
Daniele