Cairo confusion

65 views
Skip to first unread message

Nicholas Shea

unread,
Jan 9, 2017, 5:27:52 AM1/9/17
to fltk.general
I am having problems understanding how Cairo is implemented on Win32 with fltk-1.3.4-1. After compiling with the configure switch '--enable-cairo', the cairo_test program works perfectly and the results look impressive. However, when I recompile FLTK using the additional configure switch '--enable-cairoext', things do not turn out as expected. I understand that when autolink is true, a Cairo context is automatically created for any window and all FLTK drawing is done using Cairo. But the fltk draw primitives for an lines, arcs, vertices, e.t.c., are not anti-aliased. Is this behaviour correct? I note from browsing the FLTK sources that the actual drawing for these primitives is passed to the current graphics driver; ie fl_vertex(x,y) calls fl_graphics_driver->vertex(x,y).

I also note that the following code is commented out on line 458 of Fl_Double_Window.cxx:

458 //# if defined(FLTK_USE_CAIRO)
459 //capture gc changes automatically to update the cairo context adequately
460 //if Fl::cairo_autolink_context() Fl::cairo_make_current(this);
461 //# endif

I am not sure why this is so, although I can imagine there is probably a very good reason, and this is probably something to do with make_current.

As an aside, with reference to the Cairo box example, (previously listed in this forum). Only the first box in the group gets rendered. To correct this, I found that I had to remove FLTK's push and pop clip functions and write new code to draw the background colours. The modified code, which now works on Windows-XP, is shown below. I appreciate Windows-XP is an old operating system but perhaps this will help someone else. I would be interested to know if the unmodified code works correctly on Linux. I have attached a small jpeg screenshot to this post.

Best wishes,

Nicholas Shea

//========================================================================
/*  Demo of a simple cairo_box in a group */

#ifdef FLTK_HAVE_CAIRO
#include <config.h> // must come first for this to work on my system.
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/x.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Button.H>

#include <cairo.h>

#ifdef WIN32
#  include <cairo-win32.h>
#elif defined (__APPLE__)
#  include <cairo-quartz.h>
#else
#  include <cairo-xlib.h>
#endif

Fl_Double_Window *main_win=(Fl_Double_Window *)0;
Fl_Group *outer_group=(Fl_Group *)0;
Fl_Group *inner_grp1=(Fl_Group *)0;
Fl_Group *inner_grp2=(Fl_Group *)0;
Fl_Group *inner_grp3=(Fl_Group *)0;

/*************************************************************/
class cairo_box : public Fl_Box {
    void draw(void); // draw method
    cairo_surface_t *surface;
    cairo_t *cairo_context;
    float br, bg, bb, ba;  // Added background colours. [Nicholas Shea]
    float tr, tg, tb, ta;  // Added triangle colours. [Nicholas Shea]
    void set_cairo_cxt(int wo, int ho);
public:
    // constructor
    cairo_box(int x, int y, int w, int h) : Fl_Box(x,y,w,h) {
        surface = NULL; cairo_context = NULL;
        br = bg = bb = ba = 0.0;
        tr = tg = tb = ta = 0.0;
    }

    // Added. [Nicholas Shea]
    void set_bg_rgb(float RR, float GG, float BB, float AA)
        {br = RR; bg = GG; bb = BB; ba = AA;}
   
    // Added. [Nicholas Shea]
    void set_tri_rgb(float RR, float GG, float BB, float AA)
        {tr = RR; tg = GG; tb = BB; ta = AA;}
};
/*************************************************************/
void cairo_box::set_cairo_cxt(int wo, int ho) {
#ifdef WIN32
#warning win32 mode
    /* Get a Cairo surface for the current DC */
    HDC dc = fl_gc;         /* Exported by fltk */
    surface = cairo_win32_surface_create(dc);
#elif defined (__APPLE__)
#warning Apple Quartz mode
    /* Get a Cairo surface for the current CG context */
    CGContext *ctx = fl_gc;
    surface = cairo_quartz_surface_create_for_cg_context(ctx, wo, ho);
#else
#warning X windows mode
    // find the window enclosing this widget - probably main_win in this case!
    Fl_Group *pt = this->parent();
    while ((pt) && !(pt->as_window()))
    {
        pt = pt->parent();
    }
    if (!pt)
    {
        puts("No window context");
        return;
    }
    /* Get a Cairo surface for the box, based on the enclosing window */
    surface = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, pt->w(), pt->h());
#endif
    /* Store the cairo context */
    cairo_context = cairo_create(surface);

    /* All Cairo co-ordinates are shifted by 0.5 pixels to correct anti-aliasing */
#ifndef __APPLE__ // Apple Quartz does not need the offset nudge, it seems...
    cairo_translate(cairo_context, 0.5, 0.5);
#endif

}
/*************************************************************/
void cairo_box::draw(void) {
    float xo = x(); // origin is current window position for Fl_Box
    float yo = y();
    float wo = w()-1;
    float ho = h()-1;

    /* draw the base widget */
   
    // Commented out push clips because on Win32 they have the adverse
    // effect of only drawing in the first cairo_box (class above).
    // Consequently, the other two boxes are never rendered.
    // I don't know if this is particular to Win32 or not.  [Nicholas Shea]
   
    //fl_push_no_clip(); /* remove any clipping region set by the expose events... */
    //fl_push_clip(xo, yo, wo, ho); /* reset local clipping */

    // Commented out fl_color and fl_rectf [Nicholas Shea]
    //fl_color(FL_CYAN);
    //fl_rectf(xo, yo, wo, ho);
    // set cairo context
    set_cairo_cxt(wo, ho);
   
    // Commented out get_color. [Nicholas Shea]
    //unsigned char r,g,b;
     //Fl::get_color( FL_CYAN, r, g, b );
     cairo_set_source_rgba(cairo_context, br, bg, bb, ba);
     cairo_rectangle(cairo_context, x(),y(),wo,ho);
     cairo_fill( cairo_context );
   

     cairo_set_source_rgba(cairo_context, tr, tg, tb, ta);
    // draw a triangle pointing upwards
    float x1, y1, x2, y2, x3, y3;
    x1 = xo + wo/2.0; y1 = yo;
    x2 = xo + wo; y2 = yo + ho;
    x3 = xo; y3 = y2;
   
    cairo_new_path(cairo_context);
    cairo_move_to(cairo_context, x1, y1);
    cairo_line_to(cairo_context, x2, y2);
    cairo_line_to(cairo_context, x3, y3);
    cairo_line_to(cairo_context, x1, y1);
    cairo_fill(cairo_context);

    // release the cairo context
    cairo_destroy(cairo_context);
    cairo_surface_destroy(surface);
    cairo_context = NULL;

    // Commented out pop clips. [Nicholas Shea]
    //fl_pop_clip(); // remove the local clip region
    //fl_pop_clip(); // remove the "no_clip" region
} // draw method

/*************************************************************/
cairo_box *cairo1=(cairo_box *)0;
cairo_box *cairo2=(cairo_box *)0;
cairo_box *cairo3=(cairo_box *)0;
/*************************************************************/
static void cb_Quit(Fl_Button*, void*) {
   main_win->hide();
}

/*************************************************************/
int main(int argc, char **argv) {
    main_win = new Fl_Double_Window(500, 500);
    main_win->begin();

    Fl_Button* o = new Fl_Button(430, 460, 60, 30, "Quit");
    o->box(FL_THIN_UP_BOX);
    o->callback((Fl_Callback*)cb_Quit);

    outer_group = new Fl_Group(5, 5, 490, 450);
    outer_group->begin();

    inner_grp1 = new Fl_Group(5, 5, 160, 450);
    inner_grp1->begin();
    cairo1 = new cairo_box(7, 7, 156, 446);
    cairo1->box(FL_FLAT_BOX);
    cairo1->set_bg_rgb(0.0,0.0,0.0,1);
    cairo1->set_tri_rgb(1.0,0,0,0.7);
    inner_grp1->end();
    inner_grp1->box(FL_DOWN_BOX);

    inner_grp2 = new Fl_Group(165, 5, 160, 450);
    inner_grp2->begin();
    cairo2 = new cairo_box(167, 7, 156, 446);
    cairo2->box(FL_FLAT_BOX);
    cairo2->set_tri_rgb(1.0,1.0,0.0,1);
    cairo2->set_bg_rgb(0,0,1.0,1);
    inner_grp2->end();
    inner_grp2->box(FL_DOWN_BOX);

    inner_grp3 = new Fl_Group(325, 5, 170, 450);
    inner_grp3->begin();
    cairo3 = new cairo_box(327, 7, 166, 446);
    cairo3->box(FL_FLAT_BOX);
    cairo3->set_bg_rgb(0.5,0.75,0.25,1);
    cairo3->set_tri_rgb(0,0,1.0,1);
    inner_grp3->end();
    inner_grp3->box(FL_DOWN_BOX);

    outer_group->end();

    main_win->end();
    main_win->resizable(outer_group);
    main_win->label("Cairo Box Test");
    main_win->show(argc, argv);

    return Fl::run();
}

#endif
/* end of file */
//========================================================================



cairo_test_3.JPG

Manfred Herr

unread,
Jan 9, 2017, 9:12:07 AM1/9/17
to fltk.general
On Linux I had problems using both parameters enable-cairo and enable-cairoext the same time. See my post to this group:

https://groups.google.com/d/msg/fltkgeneral/x80qQ6wt0s4/sEiLA4zTBwAJ

What I've learned is that cairo intergration in FLTK needs some redesign.

Albrecht Schlosser

unread,
Jan 9, 2017, 10:22:19 AM1/9/17
to fltkg...@googlegroups.com
On 09.01.2017 11:27 Nicholas Shea wrote:
> I am having problems understanding how Cairo is implemented on Win32
> with fltk-1.3.4-1. After compiling with the configure switch
> '--enable-cairo', the cairo_test program works perfectly and the results
> look impressive.

I'd say this is the recommended way to use Cairo *if* you want to use
FLTK's builtin Cairo support. I don't know much about Cairo, but I read
often that Ian (another FLTK dev) who appears to know much more about
Cairo doesn't like this implementation.

Note: Although I don't know much about Cairo itself I agree with Ian
that FLTK's internal implementation of Cairo support is questionable
from a technical point of view. See more comments below.

> However, when I recompile FLTK using the additional
> configure switch '--enable-cairoext', things do not turn out as
> expected. I understand that when autolink is true, a Cairo context is
> automatically created for any window

That's true so far. But this is not done automatically. You still need
to call Fl::cairo_autolink_context(true); to enable the automatic Cairo
context for all windows. Note that this implies (in FLTK 1.3.x) a
dependency on libfltk_cairo for all programs, even a simple hello
program that doesn't use Cairo at all.

Using --enable-cairoext is generally not recommended, unless you know
exactly what you do (and why you're doing it).

> and all FLTK drawing is done using Cairo.

That's not correct. FLTK does NOT use Cairo to draw anything on its own.

But, as far as I understand it, FLTK creates and provides a FLTK context
that you can use for any window.

Now comes a little guessing ;-)

Basically the autolink feature only calls Fl::cairo_make_current() for you.

You can (AFAICT) use this Cairo context by calling Fl::cairo_cc() or
maybe something else. Docs state:
"You can use Fl::cairo_cc() to get the current cairo context anytime."

But, since I don't know Cairo, I'm not sure about that part.

</guessing> ;-)

> But the fltk draw primitives for an lines, arcs, vertices,
> e.t.c., are not anti-aliased. Is this behaviour correct? I note from
> browsing the FLTK sources that the actual drawing for these primitives
> is passed to the current graphics driver; ie fl_vertex(x,y) calls
> fl_graphics_driver->vertex(x,y).

That's correct, see above. There's no internal Cairo drawing.

> I also note that the following code is commented out on line 458 of
> Fl_Double_Window.cxx:
>
> 458 //# if defined(FLTK_USE_CAIRO)
> 459 //capture gc changes automatically to update the cairo context
> adequately
> 460 //if Fl::cairo_autolink_context() Fl::cairo_make_current(this);
> 461 //# endif
>
> I am not sure why this is so, although I can imagine there is probably a
> very good reason, and this is probably something to do with make_current.

Sorry, I can't tell why this is so.

> As an aside, with reference to the Cairo box example, (previously listed
> in this forum). Only the first box in the group gets rendered. To
> correct this, I found that I had to remove FLTK's push and pop clip
> functions and write new code to draw the background colours. The
> modified code, which now works on Windows-XP, is shown below. I
> appreciate Windows-XP is an old operating system but perhaps this will
> help someone else. I would be interested to know if the unmodified code
> works correctly on Linux. I have attached a small jpeg screenshot to
> this post.

I tried the posted example code on Linux and it worked after I ...

(1) added #define FLTK_HAVE_CAIRO and
(2) tweaked the linker command line a little bit.

First I tried fltk-config --use-cairo --compile cairo_test.cxx

but this didn't work (likely because of library order and (1) above.
Here's what I came up with on my Linux system:

g++ -I.. -I/usr/include/cairo -I/usr/include/glib-2.0
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1
-I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/cairo
-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT
-DFLTK_HAVE_CAIRO -o 'cairo_test' 'cairo_test.cxx' ../lib/libfltk.a
../lib/libfltk_cairo.a -lcairo -lpixman-1 -lXrender -lXcursor -lXfixes
-lXext -lXft -lfontconfig -lXinerama -lpthread -ldl -lm -lcairo
-lpixman-1 -lX11

I don't know why you had to change the code as you described (box
drawing, background, etc.).

BTW: your demo code doesn't use any of the extended features added by
--enable-cairoext. In fact the program also worked when I configured
FLTK w/o --enable-cairoext.

In fact, as it stands, the demo code does not even use anything provided
by FLTK's Cairo support, since it creates its own Cairo context. Hence,
it does also work with configure --disable-cairo (default). I tried it.
Here's the compiler and linker command used in this case, w/o libfltk_cairo:

g++ \
-I.. \
-I/usr/include/cairo \
-I/usr/include/glib-2.0 \
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
-I/usr/include/pixman-1 \
-I/usr/include/freetype2 \
-D_LARGEFILE_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_THREAD_SAFE \
-D_REENTRANT \
-DFLTK_HAVE_CAIRO \
-o 'cairo_test' \
'cairo_test.cxx' \
../lib/libfltk.a \
-lcairo \
-lpixman-1 \
-lXrender \
-lXcursor \
-lXfixes \
-lXext \
-lXft \
-lfontconfig \
-lXinerama \
-lpthread \
-ldl \
-lm \
-lcairo \
-lpixman-1 \
-lX11


I'll add some more comments to excerpts of your code below.

> //========================================================================
> /* Demo of a simple cairo_box in a group */
>
> #ifdef FLTK_HAVE_CAIRO

This needs to be defined somewhere.

> #include <config.h> // must come first for this to work on my system.

That's one of the reasons why FLTK's Cairo support is broken and needs
to be redesigned. You should never (have to) #include the file
'config.h' used by the FLTK library. This file is for internal use only
and is not installed with 'make install', hence not available to end users.

However, it defines some essential platform specific constants used
later in the public header files. Sigh. :-(
This will hopefully be improved in FLTK 1.4, but I don't know yet the
exact (best) way how to do this.

> void cairo_box::set_cairo_cxt(int wo, int ho) {
...
> /* Get a Cairo surface for the box, based on the enclosing window */
> surface = cairo_xlib_surface_create(fl_display, fl_window,
> fl_visual->visual, pt->w(), pt->h());
> #endif
> /* Store the cairo context */
> cairo_context = cairo_create(surface);

Here you (i.e. the demo code) created its own Cairo context, not using
FLTK's Cairo features at all.

> void cairo_box::draw(void) {
> ...
> // Commented out push clips because on Win32 they have the adverse
> // effect of only drawing in the first cairo_box (class above).
> // Consequently, the other two boxes are never rendered.
> // I don't know if this is particular to Win32 or not. [Nicholas Shea]
>
> //fl_push_no_clip(); /* remove any clipping region set by the expose
> events... */

You might want to leave fl_push_no_clip(); because it can't do any harm
and makes sure you can always draw to the entire window.

> //fl_push_clip(xo, yo, wo, ho); /* reset local clipping */

Don't know why this was used. Seems okay to remove.

> // Commented out fl_color and fl_rectf [Nicholas Shea]

Can't say anything to the Cairo related code following here...

(code elided).

Nicholas Shea

unread,
Jan 9, 2017, 2:27:44 PM1/9/17
to fltk.general

Thank you Manfred, yes, I read this post not so long ago, and that's why I included <config.h> in the sample code. In fact, I also read somewhere else of a patch that #included <config.h> before any other FLTK header, although as Albrecht explains below, this is not desirable. Thanks for your reply.

Nicholas Shea

unread,
Jan 9, 2017, 3:14:13 PM1/9/17
to fltk.general, Albrech...@online.de


On Monday, January 9, 2017 at 3:22:19 PM UTC, Albrecht Schlosser wrote:
On 09.01.2017 11:27 Nicholas Shea wrote:
> I am having problems understanding how Cairo is implemented on Win32
> with fltk-1.3.4-1. After compiling with the configure switch
> '--enable-cairo', the cairo_test program works perfectly and the results
> look impressive.

I'd say this is the recommended way to use Cairo *if* you want to use
FLTK's builtin Cairo support. I don't know much about Cairo, but I read
often that Ian (another FLTK dev) who appears to know much more about
Cairo doesn't like this implementation.

Note: Although I don't know much about Cairo itself I agree with Ian
that FLTK's internal implementation of Cairo support is questionable
from a technical point of view. See more comments below.

> However, when I recompile FLTK using the additional
> configure switch '--enable-cairoext', things do not turn out as
> expected. I understand that when autolink is true, a Cairo context is
> automatically created for any window

That's true so far. But this is not done automatically. You still need
to call Fl::cairo_autolink_context(true); to enable the automatic Cairo
context for all windows.

 Yes, I did that in my main function with another program, but it did not do what I expected; ie use Cairo for all FLTK drawing, e.t.c.
 
Note that this implies (in FLTK 1.3.x) a
dependency on libfltk_cairo for all programs, even a simple hello
program that doesn't use Cairo at all.

Using --enable-cairoext is generally not recommended, unless you know
exactly what you do (and why you're doing it).

> and all FLTK drawing is done using Cairo.

That's not correct. FLTK does NOT use Cairo to draw anything on its own.

Ah, that's interesting and answers my main question. Although it would be impressive if the FLTK drawing functions mapped to Cairo equivalents when configured with --enable-cairoext and Fl::cairo_autolink_context is  true. But as I gleaned from the Cairo documentation, whilst Cairo makes an excellent job of rendering PostScript type operations on screen, very few of those routines are implemented for printing; in fact, Cairo's PS printing support is quite minimal and doesn't even extend to things like line cap styles. FLTK's PS printing support is far superior.

I tried the posted example code on Linux and it worked after I ...

(1) added #define FLTK_HAVE_CAIRO and
(2) tweaked the linker command line a little bit.

First I tried fltk-config --use-cairo --compile cairo_test.cxx

but this didn't work (likely because of library order and (1) above.
Here's what I came up with on my Linux system:

g++ -I.. -I/usr/include/cairo -I/usr/include/glib-2.0
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1
-I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/cairo
-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT
-DFLTK_HAVE_CAIRO -o 'cairo_test' 'cairo_test.cxx' ../lib/libfltk.a
../lib/libfltk_cairo.a -lcairo -lpixman-1 -lXrender -lXcursor -lXfixes
-lXext -lXft -lfontconfig -lXinerama -lpthread -ldl -lm -lcairo
-lpixman-1 -lX11


If I recall (I'm not at my computer), I just edited $(FLTKLINKCAIRO) in the makeinclude file to ensure the correct libs were brought in when compiling my programs in the test directory. (Anything I want to test, I usually put in there and remake). Of course linking to Cairo increases the executable size (on my system, by about 10 MB).
 
I don't know why you had to change the code as you described (box
drawing, background, etc.).

Because with the original (unmodified) code sample, only the first box in the group is drawn with Cairo. The other two boxes have cyan backgrounds drawn with FLTK but with no Cairo triangle at all. I to be honest, I am still not sure if this is a bug with FLTK's use of Cairo, or a bug in the original sample code.

BTW: your demo code doesn't use any of the extended features added by
--enable-cairoext. In fact the program also worked when I configured
FLTK w/o --enable-cairoext.

Yes, I realise this; I added the demo code as an aside to my main question. Perhaps I should have put in another post.
 
In fact, as it stands, the demo code does not even use anything provided
by FLTK's Cairo support, since it creates its own Cairo context.
Hence,
it does also work with configure --disable-cairo (default). I tried it.

Now that is a surprise :)  I thought this would have turned Cairo off entirely, so that the module would not compile into the library.  Despite all these caveats, I am impressed with using Cairo in FLTK, and much prefer this combination to the other larger UI libraries. Thank you Albrecht for your helpful comments on my code sample: I will leave fl_push_no_clip() in future for the reason you gave. Best wishes,

Nicholas.


Ian MacArthur

unread,
Jan 9, 2017, 6:09:50 PM1/9/17
to fltkg...@googlegroups.com

> On 9 Jan 2017, at 10:27, Nicholas Shea wrote:
>
> I am having problems understanding how Cairo is implemented on Win32 with fltk-1.3.4-1. After compiling with the configure switch '--enable-cairo', the cairo_test program works perfectly and the results look impressive. However, when I recompile FLTK using the additional configure switch '--enable-cairoext', things do not turn out as expected.


Sorry, I’m late to the party. I see Albrecht has already pitched in with some notes, I’ll add a few thoughts of my own, FWIW.

First off, I don’t think that '--enable-cairoext’ does anything useful at this stage, I’d suggest you just ignore it.
The '--enable-cairo’ does make it easier to attach a cairo context to a fltk window, so is useful in that respect, but to be honest I never use it, it is *almost* as easy just to attach the Cairo context “by hand”, which is what I tend to do (when I use Cairo at all, which is less often now; more on that later...)



> I understand that when autolink is true, a Cairo context is automatically created for any window and all FLTK drawing is done using Cairo.

No, the fltk drawing is not done using Cairo; what it does is make it easier to use Cairo drawing calls in a fltk window, but all the stock fltk calls render via their usual path.


> But the fltk draw primitives for an lines, arcs, vertices, e.t.c., are not anti-aliased. Is this behaviour correct?

That is correct, but not what you expected, I think.

Now that 1.4 is underway, a Nice Thing To Have would be a true Cairo backend, that actually does what you expect. We do not have that.

>
> As an aside, with reference to the Cairo box example, (previously listed in this forum).

Hmm, that looks a lot like a hacked about version of code I posted way back when, to illustrate how to render with Cairo into a fltk window *without* using the --enable-cairo mode.
Only, somehow, bodged to use the fltk Cairo extension.
Odd. Don’t know what that’s about.

Ah, I see from Albrecht’s response that the code works for him *without* fltk’s Cairo extension at all, which sounds about right; that would be consistent with what I was demonstrating at the time, I imagine.

Anyway:

What is it you are trying to draw?

In my experience, Cairo does a lovely job, but is often (painfully) slow and is seldom accelerated by the GPU drivers on host systems.

If I need anti-aliased drawing now (on any platform other than OSX, where it Just Works for all drawing anyway) then I tend to use glew (or some other GL wrangler) to set up an anti-aliased context in an FL_GL_Window and render into that.
That (so far anyway) has produced code that seems to take advantage of the GPU acceleration on a wide range pf platforms, and is pretty portable.

My old Cairo code tended to have a lot of #ifdef stuff for handling platform differences, though I think they did try to clean up the API a bit and make it more consistent across platforms since then.

So, depending on what you want to draw, it may be that GL is a better option. (Cairo text handling is arguably better though, at least on X11 hosts!)

Not that I draw anything very complicated mind you, and I’m certainly not pushing the envelope in GL coding!




Nicholas Shea

unread,
Jan 10, 2017, 4:45:13 AM1/10/17
to fltk.general


On Monday, January 9, 2017 at 11:09:50 PM UTC, Ian MacArthur wrote:

First off, I don’t think that '--enable-cairoext’ does anything useful at this stage, I’d suggest you just ignore it.
The '--enable-cairo’ does make it easier to attach a cairo context to a fltk window, so is useful in that respect, but to be honest I never use it, it is *almost* as easy just to attach the Cairo context “by hand”, which is what I tend to do (when I use Cairo at all, which is less often now; more on that later...)

I see. Thanks for that advice.
 
> I understand that when autolink is true, a Cairo context is automatically created for any window and all FLTK drawing is done using Cairo.

No, the fltk drawing is not done using Cairo; what it does is make it easier to use Cairo drawing calls in a fltk window, but all the stock fltk calls render via their usual path.

Yes, I understand that now.
 
> But the fltk draw primitives for an lines, arcs, vertices, e.t.c., are not anti-aliased. Is this behaviour correct?

That is correct, but not what you expected, I think.

Now that 1.4 is underway, a Nice Thing To Have would be a true Cairo backend, that actually does what you expect. We do not have that.

It would be a valuable addition to the codebase, although --enable-cairoext for all FLTK windows would surely increase the executable size (on Windows-XP by about 10MB for the "Hello World" application). In my case, this is because I link statically to the Cairo library and all its static dependencies. I modified FLTK's makeinclude thus:

# libraries to link with:
AUDIOLIBS    = -lwinmm
CAIROLIBS    = -lcairo -lpixman-1 -lfontconfig -lfreetype -lpng12 -lexpat -lmsimg32 -lz
CAIROFLAGS    = -II:/TDM_DEVEL/MinGW/include/cairo -II:/TDM_DEVEL/MinGW/include/pixman-1 -II:/TDM_DEVEL/MinGW/include -II:/TDM_DEVEL/MinGW/include/freetype2 -II:/TDM_DEVEL/MinGW/include/libpng12 
DSOFLAGS    = -L. -mwindows  -Wl,-no-undefined -Wl,-Bsymbolic-functions -Wl,-gc-sections
LDFLAGS        = $(OPTIM) -mwindows
LDLIBS        =  -lole32 -luuid -lcomctl32
GLDLIBS        = -lglu32 -lopengl32  -lole32 -luuid -lcomctl32
LINKFLTK    = ../lib/libfltk.a
LINKFLTKGL    = ../lib/libfltk_gl.a
LINKFLTKFORMS    = ../lib/libfltk_forms.a ../lib/libfltk.a
LINKFLTKIMG    = ../lib/libfltk_images.a ../lib/libfltk.a $(IMAGELIBS)
LINKFLTKCAIRO    = ../lib/libfltk_cairo.a $(CAIROLIBS)
FLTKCAIROOPTION = -L ../cairo -lfltk_cairo
LINKSHARED    =  ../lib/libfltk_cairo.a ../lib/libfltk_images.a ../lib/libfltk_forms.a ../lib/libfltk.a $(IMAGELIBS) $(CAIROLIBS)
And in the test directory makefile, I have:

cairo_test_3$(EXEEXT): cairo_test_3.o
    echo Linking $@...
    $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(CAIROFLAGS) $(LDFLAGS) -o $@ cairo_test_3.o $(LINKFLTK) $(LINKFLTKCAIRO) $(GLDLIBS)
    $(OSX_ONLY) ../fltk-config --post $@

Obviously, when --enable-cairoext is true, all the other link commands were also changed to use $(CAIROFLAGS) and $(LINKFLTKCAIRO)

> As an aside, with reference to the Cairo box example, (previously listed in this forum).

Hmm, that looks a lot like a hacked about version of code I posted way back when, to illustrate how to render with Cairo into a fltk window *without* using the --enable-cairo mode.
Only, somehow, bodged to use the fltk Cairo extension.
Odd. Don’t know what that’s about.

Ah, I see from Albrecht’s response that the code works for him *without* fltk’s Cairo extension at all, which sounds about right; that would be consistent with what I was demonstrating at the time, I imagine.

Anyway:

What is it you are trying to draw?

I am trying to render engineering drawings for geodesic struts and hubs in a plan window. I want to use Cairo for the context in an Fl_scroll. One issue is that that maximum dimension at 100 percent is twenty feet. This is not a problem using FLTK, but will be using Cairo due to memory issues, unless I can work out a way just to create the visible context. I have attached a screen shot of this plan window using FLTK. Note that the rulers are drawn into the context. It works nicely but I need to draw some complex constructions involving curves, intersections, arrows, e.t.c., (http://sourceforge.net/projects/geodesica/)

In my experience, Cairo does a lovely job, but is often (painfully) slow and is seldom accelerated by the GPU drivers on host systems.
 
Hmm, that could be a problem and one I did not foresee.
 
If I need anti-aliased drawing now (on any platform other than OSX, where it Just Works for all drawing anyway) then I tend to use glew (or some other GL wrangler) to set up an anti-aliased context in an FL_GL_Window and render into that. 
That (so far anyway) has produced code that seems to take advantage of the GPU acceleration on a wide range pf platforms, and is pretty portable.
 
That is certainly a viable option as I use OpenGL for the main window display.
 
My old Cairo code tended to have a lot of #ifdef stuff for handling platform differences, though I think they did try to clean up the API a bit and make it more consistent across platforms since then.

So, depending on what you want to draw, it may be that GL is a better option. (Cairo text handling is arguably better though, at least on X11 hosts!)

Not that I draw anything very complicated mind you, and I’m certainly not pushing the envelope in GL coding!

Thank for your input Ian. The ruler code you posted in this forum a while ago was very useful in getting me off the ground with my own implementation.
plan_window.png
Reply all
Reply to author
Forward
0 new messages