Opened 6 months ago

Closed 6 months ago

#15609 closed defect (fixed)

Arcs are always printed as pies when using wxGtkPrinterDC

Reported by: charras Owned by:
Priority: normal Milestone:
Component: wxGTK Version: 3.0.0-rc1
Keywords: Cc:
Blocked By: Blocking:
Patch: no

Description

Under wxWidgets 2.9.5 (and 3.0 RC) and GTK only,
compiled with --with-gtkprint option
when printing arcs, there are an one inconsistency and one bug.

inconsistency:
Simples arcs are printed as pies, i.e. with a line from the center to each arc end point.
Obviously, they are drawn without these lines.

Bug:
When an ending point of the arc is + or - 90 degrees, the arc printing is broken.

the fix is easy, and here is my poor fix:

--- src/gtk/print.cpp (revision 75057)
+++ src/gtk/print.cpp (working copy)
@@ -1375,10 +1375,10 @@

else
{

alpha1 = (x1 - xc == 0) ?

  • (y1 - yc < 0) ? 90.0 : -90.0 :

+ (y1 - yc > 0) ? 90.0 : -90.0 :

atan2(double(y1-yc), double(x1-xc)) * RAD2DEG;

alpha2 = (x2 - xc == 0) ?

  • (y2 - yc < 0) ? 90.0 : -90.0 :

+ (y2 - yc > 0) ? 90.0 : -90.0 :

atan2(double(y2-yc), double(x2-xc)) * RAD2DEG;


while (alpha1 <= 0) alpha1 += 360;

@@ -1393,8 +1393,8 @@

cairo_new_path(m_cairo);


cairo_arc_negative ( m_cairo, XLOG2DEV(xc), YLOG2DEV(yc), XLOG2DEVREL((int)radius), alpha1, alpha2);

  • cairo_line_to(m_cairo, XLOG2DEV(xc), YLOG2DEV(yc));
  • cairo_close_path (m_cairo);

+ cairo_line_to(m_cairo, XLOG2DEV(xc), YLOG2DEV(yc));
+ cairo_close_path (m_cairo);

SetBrush( m_brush );
cairo_fill_preserve( m_cairo );

I am thinking try to optimize a call to atan2 is not very useful in a print function (and this optimization certainly already exists in atan2).

Thanks to wxWidgets developers for all this work.

Change History (5)

comment:1 Changed 6 months ago by vadz

  • Status changed from new to confirmed
  • Summary changed from Under GTK: Arcs are printed as pie and are broken when starting or ending at 90 degrees to Arcs are always printed as pies when using wxGtkPrinterDC

I'll apply the first correction (although in the same way it's done in source:wxWidgets/trunk/src/gtk/dcclient.cpp#L607, for consistency), thanks, but I'm not sure about the second one: AFAICS the lines are supposed to be drawn if we have a non-transparent brush, see the drawing sample "Circles" screen. So the real fix would be to add a test for this. If you could please make a (tested) patch doing this, it would be great, TIA!

comment:2 Changed 6 months ago by vadz

Ugh, actually DrawArc() implementation in wxGtkPrinterDC is completely broken. I can't really blame the person who wrote this code, because this function is very confusing and the documentation is simply wrong (I'll update it). But we can't implement it using simple circular arcs, we must use elliptic arcs to draw an arc passing by two arbitrary points and "centred" at a third one.

So, unfortunately, more changes are needed here, currently it just does the wrong thing.

comment:3 Changed 6 months ago by VZ

(In [75063]) Improve wxDC::DrawArc() documentation.

The existing documentation was flat out wrong as it is simply impossible to
pass a circle through any two arbitrary points while also fixing its centre,
explain what this function really does and also use this as an opportunity to
point people to DrawEllipticArc() which is much less confusing.

Also clarify the segments drawing logic of DrawArc() as it is quite
counterintuitive too as it depends on the brush being used and is also
different from DrawEllipticArc() which uses a simpler logic.

See #15609.

comment:4 Changed 6 months ago by VZ

(In [75064]) Fix DrawArc() implementation in wxGtkPrinterDC.

It didn't count the angles correctly when they were equal to 90 degrees.

Also simplify the code by avoiding special cases for 90 degrees anyhow, just
call atan2() directly. And also avoid converting the angles to degrees just to
convert them back to radians immediately afterwards.

See #15609.

comment:5 Changed 6 months ago by VZ

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [75065]) Don't draw the segment lines in wxGtkPrinterDC::DrawArc() unless it's filled.

The segments should only be drawn if we're filling the arc, i.e. drawing a
pie, but not if we're just drawing its outline.

Add a test of this to the printing sample.

Closes #15609.

Note: See TracTickets for help on using tickets.