Linux drawing in widget error: error in cairo_matrix_invert

7 views
Skip to first unread message

Gonzalo Garramuño

unread,
May 21, 2023, 8:26:35 AM5/21/23
to fltkc...@googlegroups.com
This piece of code (drawing on an HSV color wheel):


        imaging::Color4f hsv = color::rgb::to_hsv(color);

        int W = diameter / 2;
        int H = diameter / 2;

        fl_push_matrix();

        // Position at center of circle
        fl_translate(x() + W, y() + H);

        // Rotate base on hue
        fl_rotate(15.0 + hsv.r * 360.0f);

        // Scale based on saturation
        fl_scale(hsv.g * 0.375f, hsv.g * 0.375);

        fl_color(r, g, b);

        fl_begin_points();
        fl_vertex(0, diameter);
        fl_end_points();

        fl_pop_matrix();

returns:

error in cairo_matrix_invert

on Linux.


On Windows, it draws just fine and previously (before Cairo was the
default drawing method for fltk1.4 it was also ok).  Any ideas how to
further debug it or what might be wrong?

--
Gonzalo Garramuño
ggar...@gmail.com

imm

unread,
May 21, 2023, 8:43:15 AM5/21/23
to coredev fltk
Hi Gonzalo,

From a quick visual inspection, nothing obvious comes to mind.

I wonder if the parameters to the matrix need to be normalized or something?

Anyway, do you have (or can you make) a little standalone sample that uses that code, and I'll give it a spin once I'm near a real computer again!

Cheers,
--
Ian
From my Fairphone FP3
   

Gonzalo Garramuño

unread,
May 21, 2023, 9:18:08 AM5/21/23
to fltkc...@googlegroups.com

El 21/5/23 a las 09:43, imm escribió:
> Hi Gonzalo,
>
> From a quick visual inspection, nothing obvious comes to mind.
>
> I wonder if the parameters to the matrix need to be normalized or
> something?
>
> Anyway, do you have (or can you make) a little standalone sample that
> uses that code, and I'll give it a spin once I'm near a real computer
> again!
Find attached a program that shows the issue.  The first time
draw_pixel() is called, the matrix error does not appear.  On the second
and other calls it does.

--
Gonzalo Garramuño
ggar...@gmail.com
mrvVectorscope.cpp

Gonzalo Garramuño

unread,
May 21, 2023, 11:01:09 AM5/21/23
to fltkc...@googlegroups.com

El 21/5/23 a las 10:18, Gonzalo Garramuño escribió:
> Find attached a program that shows the issue.  The first time
> draw_pixel() is called, the matrix error does not appear.  On the
> second and other calls it does.
>
Ok.  The issue is with fl_scale.  It seems our Cairo implementation
scales points with fl_scale() instead of always drawing them at one
pixel size like GDI+ on Windows or Quartz on macOS. (or.. it tries to
invert the matrix and it can't as the scale is sometimes 0).  This is a
different behavior than the other platforms and it should be changed or
at least documented.

I google for drawing points in cairo, and it turns out there's no
function to do it, but you need to draw a filled rectangle.  Are we
doing that?

--
Gonzalo Garramuño
ggar...@gmail.com

Manolo

unread,
May 21, 2023, 3:07:46 PM5/21/23
to fltk.coredev
The example program calls function fl_scale(double x, double y) with null x and y.
These values are not in the range of meaningful values for a scaling operation.
I see that other platforms accept that in the context of the example program,
but I see that as a happy border effect an FLTK app should not rely on.

Why does the example program call fl_scale(0, 0) in the first place?

About how the Cairo backend of FLTK draw points :
it draws a filled rectangle of size 1 unit as shown by this code fragment
  void Fl_Cairo_Graphics_Driver::point(int x, int y) {
    rectf(x, y, 1, 1);
  }

Gonzalo Garramuño

unread,
May 21, 2023, 4:32:47 PM5/21/23
to fltkc...@googlegroups.com

El 21/5/23 a las 16:07, Manolo escribió:
> The example program calls function fl_scale(double x, double y) with
> null x and y.
Correct, as a side effect of not initializing the values.
> These values are not in the range of meaningful values for a scaling
> operation.
> I see that other platforms accept that in the context of the example
> program,
> but I see that as a happy border effect an FLTK app should not rely on.
>
> Why does the example program call fl_scale(0, 0) in the first place?

The example program is a (simplified) vectorscope, which measures the
color saturation in a wheel.  Black, grays and white are in the 0,0
coordinate, while all other hues are rotated and scaled based on their
saturation level (closer to the outbound squares).

>
> About how the Cairo backend of FLTK draw points :
> it draws a filled rectangle of size 1 unit as shown by this code fragment
>   void Fl_Cairo_Graphics_Driver::point(int x, int y) {
>     rectf(x, y, 1, 1);
>   }

Right, but that 1,1 gets transformed by the matrix so it never draws one
pixel.

I've switched to calculate the matrix transform myself instead of
calling the cairo transformations and then calling rectf(x,y,1,1); with
the calculated positions.

--
Gonzalo Garramuño
ggar...@gmail.com

Greg Ercolano

unread,
May 21, 2023, 8:20:12 PM5/21/23
to fltkc...@googlegroups.com

On 5/21/23 13:30, Gonzalo Garramuño wrote:

El 21/5/23 a las 16:07, Manolo escribió:
The example program calls function fl_scale(double x, double y) with null x and y.
Correct, as a side effect of not initializing the values.


    A scale of 0.0 does sound bad, and I might expect that to cause a matrix error.

    If you just add a check in your code so the x,y scale never gets below, for example, 0.1,
    does that fix the app?


Greg Ercolano

unread,
May 21, 2023, 9:52:15 PM5/21/23
to fltkc...@googlegroups.com

    FWIW I was able to get your app to work by adding the above scale check,
    adding colorbar pixels, and drawing dots with fl_begin_complex_polygon() / fl_circle(),
    the attached code gives me:



Pretty close to the old tektronix vectorscopes, but without the NTSC orientations:



I suppose digital vectorscopes don't have to bother with that old
ntsc weirdness, though I thought maybe they'd keep it for consistency (shrug),
with the zero axis being at the far left, representing the "vomit yellow" of
colorburst, and then rotating clockwise through the color circle towards
yellow, red, magenta, etc. This way a grayscale (zero chroma) ended up
as a straight horizontal line going to the left.

vectorscope.cpp

Greg Ercolano

unread,
May 21, 2023, 10:50:33 PM5/21/23
to fltkc...@googlegroups.com


On 5/21/23 18:52, Greg Ercolano wrote:
I suppose digital vectorscopes don't have to bother with that old
ntsc weirdness, though I thought maybe they'd keep it for consistency (shrug),
with the zero axis being at the far left, representing the "vomit yellow" of
colorburst, and then rotating clockwise through the color circle towards
yellow, red, magenta, etc. This way a grayscale (zero chroma) ended up
as a straight horizontal line going to the left.


    Oops, I'm wrong about that last bit with a grayscale; on a vectorscope a grayscale
    would just be a dot at the center, lol.

    It was colorburst I was thinking of that marched to the left on a vector scope,
    and they had a special target for it so you wouldn't mistake it for part of the visible image.

    Since all NTSC signals had colorburst in them, even a completely black image,
    it would be seen at all times on a vectorscope as a short line from the center
    off to the left (red circle below).

    Colorburst was normally never seen as a color since it was hidden in horizontal blanking,
    but could be made visible in the handy "cross pulse" mode of most studio monitors:

   

    Burst was an unmistakeable mustard/vomit yellow bar in the blanking area.

Gonzalo Garramuño

unread,
May 23, 2023, 5:45:24 PM5/23/23
to fltkc...@googlegroups.com

El 5/21/2023 a las 10:52 PM, Greg Ercolano escribió:
>
>     FWIW I was able to get your app to work by adding the above scale
> check,
>     adding colorbar pixels, and drawing dots with
> fl_begin_complex_polygon() / fl_circle(),
>     the attached code gives me:
>
Thanks, Greg.  I switched from using FLTK functions for calculating the
matrix transform to using an actual matrix class and a vector multiply
to position my point, which I drew with fl_rectf as I needed the
function to be fast (ie. no anti-aliasing of circles).

--
Gonzalo Garramuño
ggar...@gmail.com

Reply all
Reply to author
Forward
0 new messages