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).