> > I was busy trying to use the cairo graphics library in xcircuit, when I came
> > across a few minor issues.
> 
> Actually I have wanted such an interface for a long time but never got
> around to doing it myself.  I would like to see how well the Cairo
> package works!  If you can get me the code when you are done (or
> earlier), I will torture-test it for you. . .

Dear Tim,

Hereby the cleaned up version of the cairo rendering.
I tested it with:
./configure --without-tcl --without-tk --with-cairo
This patch also includes the patch I send you earlier this week.
To keep the patch at a reasonable size I removed all the generated files by
the autoconf/automake tools. Please regenerate them by:
autoreconf -fi

What follows is an explanation of what I did, so that if you like it, you know 
what to do for the tcl/tk stuff. Also there might be other ways to solve it,
but at least you should be able to understand what I did.

First the cairo_surface and cairo_context need to be created. For now I only
added it to xtgui.c:GUI_init. It should be trivial to add it to the other
toolkits.
The resize event should also resize the cairo_surface. This is done in
events.c:resizearea. The resizing of the surface is dependent on the surface
type. For now I put cairo_xlib_surface_set_size just there, but I think it
should be a call to a function in the toolkit dependent files.

As for the actual drawing commands, I first started making wrappers for the
X function calls to cairo calls. This gave somewhat acceptable results, but
the wrappers became very awkward. Furthermore, the use of integer coordinates
for drawing prevented the real use of anti-aliased drawing.
The internal xcircuit primitives match really well to the cairo primitives, so
I ended up by reimplementing most of the drawing functions.
Most of the UDraw... functions in functions.c, as well as text,c:UDrawChar have
now been made conditional on HAVE_CAIRO. Their implementation for cairo has been
moved to cairo.c.
Preferably only the actual drawing should be moved, but I ended up copying quite
a bit of xcircuit logic embedded within the drawing functions. For now it is
fine, but having the same code in two places will mean, that only one of these
two will be maintained.
In principle everything should be equal to the original behavior, with two
exceptions. First, the stipple fill has been replaced by transparency. Second,
just for fun, I added a transparency fill to the UDrawBox, which will show
up when selecting an area.

The drawing of the grids has been separated from events.c:drawwindow to a
separate function events.c:draw_grids, resp. cairo.c:draw_grids

By doing all of the above, essentially all X drawing calls have been removed.
The only ones left are SetForeground and SetFunction. The first is converted to
a cairo_set_source_rgb call. The SetFunction fulfills no purpose anymore, since
cairo cannot do XOR drawing, so it is completely removed by defining it as an
empty statement.

The fact that cairo cannot perform XOR drawing (in the X meaning of XOR) poses
another problem. To work around this problem, every change causes a redraw of
the full screen. I looked in other cairo applications and in essence this full
redraw is what they all did. I added two flags to areawin to indicated whether 
redraw is needed and whether a redraw is currently ongoing, called redraw_needed
and redraw_ongoing. If a drawing action takes place and we are not currently
redrawing, it will raise the redraw_needed flag.
At certain places the redraw_needed flag is checked and a full redraw of the
window is performed. An optimization might be to only redraw the areas that
actually changed, instead of everything.
Ofcourse the events.c:drawwindow sets and resets the redraw_ongoing flag.
The check for redraw_needed is added to the end of
    elements.c:trackarc
    elements.c:trackbox
    elements.c:trackwire
    elements.c:trackelement
    events.c:eventdispatch
    events.c:keyhandler
    events.c:xlib_drag (I did not check xctk_drag yet)
Some more changes due to XOR are at the end of events.c:drawwindow, where the
XOR drawing of elements was prepared and in selection.c:gendrawselected

Due to fully redrawing the window every time, performing everything without
double buffering causes a lot of flicker. Double buffering with cairo is
therefore performed always and not made dependent on DOUBLEBUFFER.
Cairo uses the cairo_push/pop_group to perform double buffering.

Cairo also supports clipmasks. Though I did implement this feature I did not
test it yet. I essentially disabled all the clipmask stuff in
    events.c:resizearea
    graphic.c:UDrawGraphic
    xcircuit.c:create_new_window
    xtgui.c:GUI_init
And I changed the reset of the clipmask in
    events.c:placeselects
    selection.c:geneasydraw

One step further is to use proper fonts instead of the line drawing fonts.
The fontinfo structure has been extended with four members, three for the cairo
toy font api (cairo_family, slant and weight) and a pointer to a table of
strings (utf8encoding). These string represent the UTF-8 encodings of each
character. The toy font api should probably disappear and be replaced by a
pointer to a cairo_font_face_t. The changes mainly appear in
    fontfile.c:loadfontfile
    text.c:ULength
    cairo.c:UDrawChar
If the font family name cannot be recognized, the cairo_family name is set to
NULL and the 'old' way of xcircuit is used to render the fonts.
The .xfe files probably need to be extended to optionally include a filename
of the font (probably use the URW-fonts).

grep TODO *.[ch]
For the fonts to match I had to use a factor of 40 this is just determined
by eyeballing. There should be a proper explanation for this factor.
The graphic.c and render.c have not yet been updated.
Also the copybackground() in events.c:drawwindow has been disabled for cairo and
is replaced by an empty background.
The cairo.c file currently has excessive use of matrix and line settings, as
well as cairo_save/restore calls. Most of these could be removed, but to be sure
the drawing stays the same, I kept them for now. With the proper use of
cairo_scale, cairo_translate, etc., I think most of the references to DCTM would
disappear.

Finally, as for the copyright, I notice you use the GPL2 copyright. This might
not apply to utf8encoding.c. Please read the comments in the top of the file
utf8encodings.c. The source for the encoding tables I used states:
"Unicode, Inc. hereby grants the right to freely use the information [...]
as long as this notice remains attached."

Regards Erik.


_______________________________________________
Xcircuit-dev mailing list
Xcircuit-dev@opencircuitdesign.com
http://www.opencircuitdesign.com/mailman/listinfo/xcircuit-dev

Reply via email to