Forums > Dev

Sneaky bug in jgraphics_pattern_create_radial() ???

November 24, 2012 | 9:57 pm

Hi folks,

when coding UI objects I have noticed that certain types of radial gradients show significant Moire’ patterns and/or aliasing. The following code will draw a pretty generic radial gradient that exhibits the above mentioned behavior. Notice that no affine transformations are performed on the gradient. I am on MacOS 10.7 (Lion) running Max 6.0.8 and using MaxSDK 6.0.4.

Can someone confirm this ?

#include "ext.h"
#include "ext_common.h"
#include "ext_obex.h"
#include "ext_strings.h"
#include "jpatcher_api.h"
#include "jgraphics.h"

typedef struct _mygradientbug
{
	t_jbox		box;
	t_jrgba		bgcolor;
	t_jrgba		gradientcolor;
} t_mygradientbug;

t_class *mygradientbug_class;

// Class Handlers
void *mygradientbug_new(t_symbol *sym, long argc, t_atom *argv);
void mygradientbug_free(t_mygradientbug *x);

// Typed Messages
void mygradientbug_bang(t_mygradientbug *x);

// Untyped Messages
void mygradientbug_paint(t_mygradientbug *x, t_object *patcherview);
void mygradientbug_assist(t_mygradientbug *x, void *box, long msg, long idx, char *str);

int main(void)
{
	t_class *c;

	common_symbols_init();

	c = class_new("mygradientbug",
                  (method)mygradientbug_new, (method)mygradientbug_free,
				  sizeof(t_mygradientbug), (method)NULL, A_GIMME, 0);

	c->c_flags |= CLASS_FLAG_NEWDICTIONARY;
	jbox_initclass(c, 0);

	// Typed Messages
	class_addmethod(c, (method)mygradientbug_bang,      "bang",     0);

    // Untyped Messages
    class_addmethod(c, (method)mygradientbug_paint,     "paint",    A_CANT, 0);
	class_addmethod(c, (method)mygradientbug_assist,    "assist",   A_CANT, 0);

	// Attributes
	CLASS_ATTR_DEFAULT(c,                   "patching_rect",    ATTR_FLAGS_NONE, "0.0 0.0 300.0 300.0");

    CLASS_STICKY_ATTR(c,					"category",			ATTR_FLAGS_NONE, "Color");

	CLASS_ATTR_RGBA(c,						"bgcolor",			ATTR_FLAGS_NONE, t_mygradientbug, bgcolor);
	CLASS_ATTR_STYLE_LABEL(c,				"bgcolor",			ATTR_FLAGS_NONE, "rgba", "Background Color");
	CLASS_ATTR_DEFAULTNAME_SAVE(c,          "bgcolor",			ATTR_FLAGS_NONE, "0.0 0.0 0.0 1.0");
    CLASS_ATTR_FILTER_CLIP(c,				"bgcolor",          0.0, 1.0);

	CLASS_ATTR_RGBA(c,						"gradientcolor",	ATTR_FLAGS_NONE, t_mygradientbug, gradientcolor);
	CLASS_ATTR_STYLE_LABEL(c,				"gradientcolor",	ATTR_FLAGS_NONE, "rgba", "Gradient Color");
	CLASS_ATTR_DEFAULTNAME_SAVE(c,          "gradientcolor",	ATTR_FLAGS_NONE, "1.0 1.0 1.0 1.0");
    CLASS_ATTR_FILTER_CLIP(c,				"gradientcolor",    0.0, 1.0);

	CLASS_STICKY_ATTR_CLEAR(c,				"category");

	class_register(_sym_box, c);
	mygradientbug_class = c;

	return 0;
}

void *mygradientbug_new(t_symbol *sym, long argc, t_atom *argv)
{
	t_mygradientbug *x;
	t_dictionary *d;
    long flags;

    if (!(d = object_dictionaryarg(argc, argv))) {
		return NULL;
	}
	if (!(x = object_alloc(mygradientbug_class))) {
        return NULL;
    }
    flags = 0
            | JBOX_DRAWFIRSTIN
            | JBOX_NODRAWBOX
            | JBOX_DRAWINLAST
            | JBOX_GROWBOTH
            ;

    jbox_new(&x->box, flags, argc, argv);
    x->box.b_firstin = (t_object *)x;
    attr_dictionary_process(x, d);
    jbox_ready(&x->box);

	return x;
}

void mygradientbug_free(t_mygradientbug *x)
{
	jbox_free(&x->box);
}

void mygradientbug_bang(t_mygradientbug *x)
{
    jbox_redraw(&x->box);
}

void mygradientbug_paint(t_mygradientbug *x, t_object *patcherview)
{
	t_jgraphics *context;
    t_jpattern *pattern;
	t_rect rect;

    context = (t_jgraphics *)patcherview_get_jgraphics(patcherview);
	jbox_get_rect_for_view((t_object *)x, patcherview, &rect);

    // draw gradient
    pattern = jgraphics_pattern_create_radial(rect.width/2, rect.height/2, 0.0,
                                              rect.width,   rect.height/2, 0.0);
    jgraphics_pattern_add_color_stop_rgba(pattern, 0.0,
                                          x->bgcolor.red,
                                          x->bgcolor.green,
                                          x->bgcolor.blue,
                                          x->bgcolor.alpha);
    jgraphics_pattern_add_color_stop_rgba(pattern, 0.7,
                                          x->bgcolor.red,
                                          x->bgcolor.green,
                                          x->bgcolor.blue,
                                          x->bgcolor.alpha);
    jgraphics_pattern_add_color_stop_rgba(pattern, 0.8,
                                          x->gradientcolor.red,
                                          x->gradientcolor.green,
                                          x->gradientcolor.blue,
                                          x->gradientcolor.alpha);
    jgraphics_pattern_add_color_stop_rgba(pattern, 0.9,
                                          x->bgcolor.red,
                                          x->bgcolor.green,
                                          x->bgcolor.blue,
                                          x->bgcolor.alpha);
    jgraphics_pattern_add_color_stop_rgba(pattern, 1.0,
                                          x->bgcolor.red,
                                          x->bgcolor.green,
                                          x->bgcolor.blue,
                                          x->bgcolor.alpha);
    jgraphics_set_source(context, pattern);
    jgraphics_pattern_destroy(pattern);
    jgraphics_paint(context);
}

void mygradientbug_assist(t_mygradientbug *x, void *box, long msg, long idx, char *str)
{
	if (msg == ASSIST_INLET) {
		strncpy_zero(str, "Input", 256);
	} else if (msg == ASSIST_OUTLET) {
		strncpy_zero( str, "Output", 256);
	}
}
Attachments:
  1. mygradientbug.c

November 25, 2012 | 8:07 am

Aha! Thanks Nicolas…. that’s interesting…
You are using Max 5 and you are getting a perfect gradient with no artifacts whatsoever.

Could it be that in Max 6 something about the way gradients are generated has changed?

MacOS 10.7 (Lion) running Max 6.0.8 and using MaxSDK 6.0.4:
Here’s what I am getting:

[attachment=209028,4686]

Attachments:
  1. RadialGradient.png

November 25, 2012 | 1:16 pm

Here is another example with a scaled gradient:

void mygradientbug_paint(t_mygradientbug *x, t_object *patcherview)
{
	t_jgraphics *context;
    t_jpattern *pattern;
	t_rect rect;

    context = (t_jgraphics *)patcherview_get_jgraphics(patcherview);
	jbox_get_rect_for_view((t_object *)x, patcherview, &rect);

    // transform context so that center is at [0,0] and radius is 1
    jgraphics_scale(context, rect.width/2, rect.height/2);
    jgraphics_translate(context, 1, 1);

    // draw gradient
    jgraphics_scale(context, 0.1, 1.0);

    pattern = jgraphics_pattern_create_radial(0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
    jgraphics_pattern_add_color_stop_rgba(pattern, 0.0,
                                          x->gradientcolor.red,
                                          x->gradientcolor.green,
                                          x->gradientcolor.blue,
                                          x->gradientcolor.alpha);
    jgraphics_pattern_add_color_stop_rgba(pattern, 1.0,
                                          x->bgcolor.red,
                                          x->bgcolor.green,
                                          x->bgcolor.blue,
                                          x->bgcolor.alpha);
    jgraphics_set_source(context, pattern);
    jgraphics_pattern_destroy(pattern);
    jgraphics_paint(context);
}

[attachment=209039,4687]

Attachments:
  1. RadialGradient2.png

November 25, 2012 | 2:36 pm

Thanks for the example. I can confirm the difference.


Viewing 4 posts - 1 through 4 (of 4 total)