Topic: Cairo calling

Jeff,
Thanks to the Simply Fortran magic, I have been able to call
Cairo graphics library (almost) directly from Fortran. I just created SF project
with two files:
(fortran code )
!!!
program cairo_two
    use iso_c_binding
    implicit none
    !
    interface
        subroutine spiral_png (a, b) bind (c, name = 'spiral_png')
            ! plots spiral shape with label text at position a, b
            use iso_c_binding
            real(c_float), value :: a, b
        end subroutine
    end interface
    !
    real a, b
    a = 40.0
    b = 60.0
    print *, "Fortran calling Cairo void function spiral_png"
    call spiral_png(a, b)
end program
!!!
(and C-code)
!!!
/* C source to be compiled by SF, no main function */
#include <cairo.h>
#define _USE_MATH_DEFINES
#include <math.h>
/* spiral png*/
void spiral_png(float a, float b) {
    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 800, 800);
    cairo_t *cr = cairo_create(surface);
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_paint(cr);
    cairo_set_source_rgb(cr, 0, 0, 0);
    for (int i = 0; i <= 10000; i++) {
        double x = 400 + cos(2 * M_PI * i / 500) * 140 + cos(2 * M_PI * i / 10000) * 220;
        double y = 400 + sin(2 * M_PI * i / 500) * 140 + sin(2 * M_PI * i / 10000) * 220;
        if (i == 0)
            cairo_move_to(cr, x, y);
        else
            cairo_line_to(cr, x, y);
    }
    cairo_close_path(cr);
    cairo_stroke(cr);
    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr, 40.0);
    cairo_move_to(cr, a, b);
    cairo_show_text(cr, "Spiral");
    cairo_surface_write_to_png(surface, "spiral.png");
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
}
!!!!
Project compiles and PNG file with a nice plot is created.
My question is: How to draw on window created by AppGraphics?
Win32/GDI/C programming is high above me, but I tried blindly:
...
#include <cairo-win32.h>
#include <appgraphics.h>
...
void spiral_gdi(float a, float b) {
    int wiha;
    wiha = initwindow(800, 800,
                        "Cairo drawing",
                        DEFAULT_POSITION, DEFAULT_POSITION,
                        FALSE,
                        TRUE);
    HDC dc = GetDC(wiha);
    cairo_surface_t *surface = cairo_win32_surface_create(dc);
    ReleaseDC(wiha, dc);
...
...
I don't know if it has any sense, since I have got compile error
(..undefined reference to `initwindow').
Any help is appreciated,
Carlos,
BTW, Cairo binaries came from https://github.com/preshing/cairo-windows/releases

Re: Cairo calling

Carlos,

AppGraphics doesn't expose any of the Windows API, so applying a cairo surface to an AppGraphics window would be a problem.  Specifically, the initwindow call returns an integer that corresponds to an internal library array that tracks the windows handle (the HWND value) internally only.  There isn't a supported way of retrieving this value.

The problem actually gets messier because, even if we did provide a way to get the handle, using a cairo surface probably still wouldn't work.  In order to effectively apply static display of drawn graphics in an AppGraphics window, the library dispatches a new thread to handle presenting the window and responding to Windows messages.  The actual drawing requested by the user is always performed on an internal bitmap which is then copied to the actual visual window whenever painting is requested.  If you tried to attach a cairo surface to an AppGraphics window, this automatic, threaded redrawing would actually overwrite the cairo surface over and over again. 

So while the window handle isn't exposed to the user at all (making calls to GetDC difficult), the actual architecture of AppGraphics would make this task fail anyway.

However, I do understand wanting to use cairo.  Creating and managing a window in Windows is difficult, though.  Let me see if I can think of a good way to do this instead of working through AppGraphics.  There's only a bit of C code to get a window open and attach cairo to the drawing context.

Jeff Armstrong
Approximatrix, LLC

Re: Cairo calling

Alternatives:

(1) Use Appgraphics!  Brilliant, and built into SF.

(2) Use the fantastic, free, DISLIN library.
     Full 'Windows' style facilities, text, vectors, bitmaps, GUIs.

Both of the above can be used completely withing Fortran source files.
No Java, or C.  Nothing but Fortran calls and functions.

Re: Cairo calling

Jeff,
I think that your approach, in which AppGraphics doesn't expose any of the Windows API to the user,
is actually an advantage. It would be nice, however, if AppGraphics supported also png files.
John,
You are right, AppGraphics is great, but Cairo lines and shapes are somehow "nicer".  As regards
dislin , I use it quite often, but at some point I would like to create my own simple 2d plot module for SF.
Carlos

Re: Cairo calling

Cairo, I believe, performs anti-aliasing while drawing, so it will almost certainly look "nicer" than AppGraphics.

Jeff Armstrong
Approximatrix, LLC

Re: Cairo calling

Where is the best place to go to teach myself how to use CG with Fortran?
Will is be any good for creating a GUI?

Re: Cairo calling

John,
The best way to learn Cairo is to install  GTK for Fortran package.
Cairo is included, it is even used for drawing the GUI controls.
Moreover, for GUI creation you can use very nice program called Glade.
I believe that the Simply Fortran IDE itself is written in GTK.
For me, however,  GTK is an overkill, since I program only in win.
Carlos

Re: Cairo calling

Carlos Herrera wrote:

I believe that the Simply Fortran IDE itself is written in GTK.

Simply Fortran for GNU/Linux and macOS is indeed written using GTK+ for its user interface.  Simply Fortran for Windows uses the Windows API directly for its user interface and does not use any GTK+ code.

Jeff Armstrong
Approximatrix, LLC

Re: Cairo calling

Carlos Herrera wrote:

...for GUI creation you can use very nice program called Glade.
I believe that the Simply Fortran IDE itself is written in GTK

I looked at Glade a year or two ago and it certainly seemed like an excellent visual graphical way to construct GUIs, but I backed away from it at the time because I formed the impression that it resulted in object code that could not be linked with the Fortran .o files to create a single final executable but needed a separate component at runtime, in addition to the linked Fortran executable.  I would love to discover now that I was mistaken about that.  Was I?
—-
John

Re: Cairo calling

John,
I used GTK+, however not with Fortran, but with compiler called FreeBasic. As far as I remember, Glade
produced a text file (with extension .ui) where the GUI elements were described in a readable markup
language called XML. Then this file was read, during compilation, by gtk_builder_add_from_file command.
The resulting exe was of course dynamically linked to GTK+ dll libraries.
Carlos

11 (edited by JohnWasilewski 2020-10-20 01:40:24)

Re: Cairo calling

Useless fact no 376.5.

Did you realise, Carlos, the user of CAIRO graphics and initiator of the Simply Fortran forum thread, CAIRO Calling, that your name, CA(rlos) HERRerA sounds a little bit like the Arabic 'القاهرة' ?

it means the name of probably the most most important Arabic city in history.

Pronounced something along the lines of, (Al) QAHiRRa
We call it 'The [city of] Cairo'!
---
John