[cairo] Cairo and ISO C++

Behdad Esfahbod behdad at behdad.org
Tue Jan 14 02:20:42 PST 2014

Ok.  Let me try to explain this again.  I use the Python binding syntax just
to avoid typing cairo_ all over.

Imagine you have this code:


This example will currently render text at font size 20,30 (X and Y
respectively).  This is not ideal, because, we want people to be able to
freely use transformations (scale, translate, rotate, etc) to construct paths
and set state, but we generally don't want the matrix itself to affect results
of operations.  In other words, we want the transformation matrix at the time
the user called set_font_size() to be locked down, because that's what their
intention was, NOT whatever matrix happens to be current at the time
show_text() is called.

Now note that effective text size this case turns out to be non-uniform.  Ie,
it's different in X and Y directions.  That's not an issue from an API point
of view since set_font_size() is sugar around set_font_matrix.  It's possible
to set a full matrix for font size.

Now, if we want to fix the above case in a wrapper, we can do this:

def fixed_set_font_size(cr, size):
  m = cr.get_matrix()
  f = cr.get_font_matrix()
  combined = m.multiply(f) # Or the other way around?

def fixed_show_text(cr, text):
  # Our font matrix is in device space

The problem is, we need to do the same wrapping for any API that uses font
matrix / size.  That's tedious, and breaks with cairo_scaled_font_t model.

It's easier to fix for line width in the wrapper layer I guess.


On 14-01-14 06:03 PM, Sergey K. wrote:
> Hi, Behdad
> Sorry but your message is a bit vague for me in several places.
> You wrote, for instance:
> During stroke() / show_text/glyphs/...(), cairo_save(), set transformation
> matrix to identity.
> Q1: What a value should we take as "identity"? The initial? Could you be so
> kind to give an example (at least in a general manner that you used in the
> previous messages)?
> Q2: Well. Suppose, I have changed the matrix to identity. But I'd like to
> paint a bigger (scale(2)) picture and, consequently, a bigger text on it. Will
> it happen if I reset a matrix before stroke() / show_text?
> Q3: And if you are sure that the answer to Q2 is "yes, of cource". Why dont' a
> cairo team realize the "manual thechnique" of locking the line width / font
> size (which you have described below) but automatically not manually?
> Regards,
> Sergey
> Вторник, 14 января 2014, 16:40 +08:00 от Behdad Esfahbod <behdad at behdad.org>:
>     On 14-01-02 02:51 AM, Herb Sutter wrote:
>     > Thanks Behdad,
>     >
>     >> During cairo's development, there were some decisions made that we
>     >> regretted later on. I was going to suggest that those be revisited for
>     >> standardization, but reading the documents you linked, I think that will go
>     >> down the same design-by-committee path that you are trying to avoid.
>     >
>     > It sounds like those would be good to know about regardless, if you
>     could share.
>     >
>     > Actually we mainly want to avoid that for the initial proposal, but if
>     there are known 'errata' that would be good to know about. Possibly they
>     could be addressed in the C++ wrapping, if they can be addressed without
>     changing Cairo. Alternatively, perhaps this would be a good point to
>     consider addressing some of them in Cairo as well if you think that's
>     proper, given that if this standardization process bears fruit the
>     audience of the Cairo API will expand to a lot of new users. In any event
>     I think it would be good to know about them.
>     Bill already mentioned most of what I had in mind. To reiterate: Currently
>     when one sets line width and font size, those are recorded in user-space, and
>     as such following transformation matrix changes will change the final line
>     width / font size. This is unintuitive and troublesome. Example:
>       set_line_width (10)
>       scale (2)
>       move_to / line_to / ...
>       stroke ()
>     The stroke will now have width 20, not 10.
>     To fix this, we want to lock the line width / font size in device space at the
>     time they are set. To fix these in the wrapper is not impossible:
>       - During set_line_width / set_font_size, multiply them by the current
>     transformation matrix and set to *that*,
>       - During stroke() / show_text/glyphs/...(), cairo_save(), set transformation
>     matrix to identity, stroke/show_text/..., and cairo_restore(),
>     There are a few problems with this:
>       - For font_size: show_text/glyphs/... take glyph coordinates, so we need to
>     multiply those by the current transformation matrix before resetting the
>     matrix. Alternatively, we can transform the font matrix by inverse of current
>     transformation matrix and set that before the operation.
>       - For line_width there are more problems:
>         * Currently the set/get_line_width operate on a single number. Whereas
>     the stroke shape after a transformation matrix becomes an ellipse, so we
>     cannot express that with a single number. We can try saving the
>     transformation matrix at the time of set_line_width, and before calling
>     stroke(), set that matrix. But tracking this with cairo_save()/restore()
>     becomes tricky. Also, this has implications on dashed lines. I think the
>     dash pattern also suffers from the same shortcomings.
>     To summarize: there's a reason we have not fixed these in cairo itself: they
>     are tricky to resolve now. Perhaps others have ideas? Perhaps we can add
>     ugly-named new functions with the more useful semantics?
>     behdad
>     -- 
>     cairo mailing list
>     cairo at cairographics.org <sentmsg?compose&To=cairo at cairographics.org>
>     http://lists.cairographics.org/mailman/listinfo/cairo
> С уважением,
> СК


More information about the cairo mailing list