KiCad PCB EDA Suite
cairo_gal.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
5  * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
6  * Copyright (C) 2017 CERN
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * CAIRO_GAL - Graphics Abstraction Layer for Cairo
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 #include <wx/image.h>
30 #include <wx/log.h>
31 
32 #include <gal/cairo/cairo_gal.h>
34 #include <gal/definitions.h>
36 
37 #include <limits>
38 
39 #include <pixman.h>
40 
41 using namespace KIGFX;
42 
43 
44 
46  wxWindow* aParent, wxEvtHandler* aMouseListener,
47  wxEvtHandler* aPaintListener, const wxString& aName ) :
48  GAL( aDisplayOptions ),
49  wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
50 {
51  parentWindow = aParent;
52  mouseListener = aMouseListener;
53  paintListener = aPaintListener;
54 
55  // Initialise grouping
56  isGrouping = false;
57  isElementAdded = false;
58  groupCounter = 0;
59  currentGroup = nullptr;
60 
61  // Initialise compositing state
62  mainBuffer = 0;
63  overlayBuffer = 0;
64  validCompositor = false;
66 
67  // Initialise Cairo state
68  cairo_matrix_init_identity( &cairoWorldScreenMatrix );
69  currentContext = nullptr;
70  context = nullptr;
71  surface = nullptr;
72  isInitialized = false;
73 
74  // Connecting the event handlers
75  Connect( wxEVT_PAINT, wxPaintEventHandler( CAIRO_GAL::onPaint ) );
76 
77  // Mouse events are skipped to the parent
78  Connect( wxEVT_MOTION, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
79  Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
80  Connect( wxEVT_LEFT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
81  Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
82  Connect( wxEVT_MIDDLE_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
83  Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
84  Connect( wxEVT_MIDDLE_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
85  Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
86  Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
87  Connect( wxEVT_RIGHT_DCLICK, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
88  Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
89 #if defined _WIN32 || defined _WIN64
90  Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) );
91 #endif
92 
93  SetSize( aParent->GetSize() );
94  screenSize = VECTOR2I( aParent->GetSize() );
95 
96  // Grid color settings are different in Cairo and OpenGL
97  SetGridColor( COLOR4D( 0.1, 0.1, 0.1, 0.8 ) );
99 
100  // Allocate memory for pixel storage
101  allocateBitmaps();
102 }
103 
104 
106 {
107  deinitSurface();
108  deleteBitmaps();
109 
110  ClearCache();
111 }
112 
113 
115 {
116  bool refresh = false;
117 
118  if( super::updatedGalDisplayOptions( aOptions ) )
119  {
120  Refresh();
121  refresh = true;
122  }
123 
124  return refresh;
125 }
126 
127 
129 {
130  initSurface();
131 
132  if( !validCompositor )
133  setCompositor();
134 
135  compositor->SetMainContext( context );
136  compositor->SetBuffer( mainBuffer );
137 }
138 
139 
141 {
142  // Force remaining objects to be drawn
143  Flush();
144 
145  // Merge buffers on the screen
146  compositor->DrawBuffer( mainBuffer );
147  compositor->DrawBuffer( overlayBuffer );
148 
149  // Now translate the raw context data from the format stored
150  // by cairo into a format understood by wxImage.
151  pixman_image_t* dstImg = pixman_image_create_bits(PIXMAN_r8g8b8,
152  screenSize.x, screenSize.y, (uint32_t*)wxOutput, wxBufferWidth * 3 );
153  pixman_image_t* srcImg = pixman_image_create_bits(PIXMAN_a8b8g8r8,
154  screenSize.x, screenSize.y, (uint32_t*)bitmapBuffer, wxBufferWidth * 4 );
155 
156  pixman_image_composite (PIXMAN_OP_SRC, srcImg, NULL, dstImg,
157  0, 0, 0, 0, 0, 0, screenSize.x, screenSize.y );
158 
159  // Free allocated memory
160  pixman_image_unref( srcImg );
161  pixman_image_unref( dstImg );
162 
163  wxImage img( wxBufferWidth, screenSize.y, (unsigned char*) wxOutput, true );
164  wxBitmap bmp( img );
165  wxMemoryDC mdc( bmp );
166  wxClientDC clientDC( this );
167 
168  // Now it is the time to blit the mouse cursor
169  blitCursor( mdc );
170  clientDC.Blit( 0, 0, screenSize.x, screenSize.y, &mdc, 0, 0, wxCOPY );
171 
172  deinitSurface();
173 }
174 
175 
176 void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
177 {
178  cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
179  cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
180  flushPath();
181  isElementAdded = true;
182 }
183 
184 
185 void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
186  double aWidth )
187 {
188  if( isFillEnabled )
189  {
190  // Filled tracks mode
191  SetLineWidth( aWidth );
192 
193  cairo_move_to( currentContext, (double) aStartPoint.x, (double) aStartPoint.y );
194  cairo_line_to( currentContext, (double) aEndPoint.x, (double) aEndPoint.y );
195  cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
196  cairo_stroke( currentContext );
197  }
198  else
199  {
200  // Outline mode for tracks
201  VECTOR2D startEndVector = aEndPoint - aStartPoint;
202  double lineAngle = atan2( startEndVector.y, startEndVector.x );
203  double lineLength = startEndVector.EuclideanNorm();
204 
205  cairo_save( currentContext );
206 
207  cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
208 
209  cairo_translate( currentContext, aStartPoint.x, aStartPoint.y );
210  cairo_rotate( currentContext, lineAngle );
211 
212  cairo_arc( currentContext, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 );
213  cairo_arc( currentContext, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 );
214 
215  cairo_move_to( currentContext, 0.0, aWidth / 2.0 );
216  cairo_line_to( currentContext, lineLength, aWidth / 2.0 );
217 
218  cairo_move_to( currentContext, 0.0, -aWidth / 2.0 );
219  cairo_line_to( currentContext, lineLength, -aWidth / 2.0 );
220 
221  cairo_restore( currentContext );
222  flushPath();
223  }
224 
225  isElementAdded = true;
226 }
227 
228 
229 void CAIRO_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
230 {
231  cairo_new_sub_path( currentContext );
232  cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI );
233  flushPath();
234  isElementAdded = true;
235 }
236 
237 
238 void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
239  double aEndAngle )
240 {
241  SWAP( aStartAngle, >, aEndAngle );
242 
243  cairo_new_sub_path( currentContext );
244  cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
245 
246  if( isFillEnabled )
247  {
248  VECTOR2D startPoint( cos( aStartAngle ) * aRadius + aCenterPoint.x,
249  sin( aStartAngle ) * aRadius + aCenterPoint.y );
250  VECTOR2D endPoint( cos( aEndAngle ) * aRadius + aCenterPoint.x,
251  sin( aEndAngle ) * aRadius + aCenterPoint.y );
252 
253  cairo_move_to( currentContext, aCenterPoint.x, aCenterPoint.y );
254  cairo_line_to( currentContext, startPoint.x, startPoint.y );
255  cairo_line_to( currentContext, endPoint.x, endPoint.y );
256  cairo_close_path( currentContext );
257  }
258 
259  flushPath();
260 
261  isElementAdded = true;
262 }
263 
264 
265 void CAIRO_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
266  double aEndAngle, double aWidth )
267 {
268  SWAP( aStartAngle, >, aEndAngle );
269 
270  if( isFillEnabled )
271  {
272  // Filled segments mode
273  SetLineWidth( aWidth );
274  cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
275  cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
276  cairo_stroke( currentContext );
277  }
278  else
279  {
280  double width = aWidth / 2.0;
281  VECTOR2D startPoint( cos( aStartAngle ) * aRadius,
282  sin( aStartAngle ) * aRadius );
283  VECTOR2D endPoint( cos( aEndAngle ) * aRadius,
284  sin( aEndAngle ) * aRadius );
285 
286  cairo_save( currentContext );
287 
288  cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
289 
290  cairo_translate( currentContext, aCenterPoint.x, aCenterPoint.y );
291 
292  cairo_new_sub_path( currentContext );
293  cairo_arc( currentContext, 0, 0, aRadius - width, aStartAngle, aEndAngle );
294 
295  cairo_new_sub_path( currentContext );
296  cairo_arc( currentContext, 0, 0, aRadius + width, aStartAngle, aEndAngle );
297 
298  cairo_new_sub_path( currentContext );
299  cairo_arc_negative( currentContext, startPoint.x, startPoint.y, width, aStartAngle, aStartAngle + M_PI );
300 
301  cairo_new_sub_path( currentContext );
302  cairo_arc( currentContext, endPoint.x, endPoint.y, width, aEndAngle, aEndAngle + M_PI );
303 
304  cairo_restore( currentContext );
305  flushPath();
306  }
307 
308  isElementAdded = true;
309 }
310 
311 
312 void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
313 {
314  // Calculate the diagonal points
315  VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y );
316  VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
317 
318  // The path is composed from 4 segments
319  cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
320  cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y );
321  cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
322  cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
323  cairo_close_path( currentContext );
324  flushPath();
325 
326  isElementAdded = true;
327 }
328 
329 
330 void CAIRO_GAL::DrawPolygon( const SHAPE_POLY_SET& aPolySet )
331 {
332  for( int i = 0; i < aPolySet.OutlineCount(); ++i )
333  drawPoly( aPolySet.COutline( i ) );
334 }
335 
336 
337 void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
338  const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
339 {
340  cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
341  cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
342  aControlPointB.y, aEndPoint.x, aEndPoint.y );
343  cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
344 
345  flushPath();
346  isElementAdded = true;
347 }
348 
349 
350 void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
351 {
352  screenSize = VECTOR2I( aWidth, aHeight );
353 
354  // Recreate the bitmaps
355  deleteBitmaps();
356  allocateBitmaps();
357 
358  if( validCompositor )
359  compositor->Resize( aWidth, aHeight );
360 
361  validCompositor = false;
362 
363  SetSize( wxSize( aWidth, aHeight ) );
364 }
365 
366 
367 bool CAIRO_GAL::Show( bool aShow )
368 {
369  bool s = wxWindow::Show( aShow );
370 
371  if( aShow )
372  wxWindow::Raise();
373 
374  return s;
375 }
376 
377 
379 {
380  storePath();
381 }
382 
383 
384 void CAIRO_GAL::ClearScreen( const COLOR4D& aColor )
385 {
386  backgroundColor = aColor;
387  cairo_set_source_rgb( currentContext, aColor.r, aColor.g, aColor.b );
388  cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y );
389  cairo_fill( currentContext );
390 }
391 
392 
393 void CAIRO_GAL::SetIsFill( bool aIsFillEnabled )
394 {
395  storePath();
396  isFillEnabled = aIsFillEnabled;
397 
398  if( isGrouping )
399  {
400  GROUP_ELEMENT groupElement;
401  groupElement.command = CMD_SET_FILL;
402  groupElement.argument.boolArg = aIsFillEnabled;
403  currentGroup->push_back( groupElement );
404  }
405 }
406 
407 
408 void CAIRO_GAL::SetIsStroke( bool aIsStrokeEnabled )
409 {
410  storePath();
411  isStrokeEnabled = aIsStrokeEnabled;
412 
413  if( isGrouping )
414  {
415  GROUP_ELEMENT groupElement;
416  groupElement.command = CMD_SET_STROKE;
417  groupElement.argument.boolArg = aIsStrokeEnabled;
418  currentGroup->push_back( groupElement );
419  }
420 }
421 
422 
423 void CAIRO_GAL::SetStrokeColor( const COLOR4D& aColor )
424 {
425  storePath();
426  strokeColor = aColor;
427 
428  if( isGrouping )
429  {
430  GROUP_ELEMENT groupElement;
431  groupElement.command = CMD_SET_STROKECOLOR;
432  groupElement.argument.dblArg[0] = strokeColor.r;
433  groupElement.argument.dblArg[1] = strokeColor.g;
434  groupElement.argument.dblArg[2] = strokeColor.b;
435  groupElement.argument.dblArg[3] = strokeColor.a;
436  currentGroup->push_back( groupElement );
437  }
438 }
439 
440 
441 void CAIRO_GAL::SetFillColor( const COLOR4D& aColor )
442 {
443  storePath();
444  fillColor = aColor;
445 
446  if( isGrouping )
447  {
448  GROUP_ELEMENT groupElement;
449  groupElement.command = CMD_SET_FILLCOLOR;
450  groupElement.argument.dblArg[0] = fillColor.r;
451  groupElement.argument.dblArg[1] = fillColor.g;
452  groupElement.argument.dblArg[2] = fillColor.b;
453  groupElement.argument.dblArg[3] = fillColor.a;
454  currentGroup->push_back( groupElement );
455  }
456 }
457 
458 
459 void CAIRO_GAL::SetLineWidth( double aLineWidth )
460 {
461  storePath();
462 
463  lineWidth = aLineWidth;
464 
465  if( isGrouping )
466  {
467  GROUP_ELEMENT groupElement;
468  groupElement.command = CMD_SET_LINE_WIDTH;
469  groupElement.argument.dblArg[0] = aLineWidth;
470  currentGroup->push_back( groupElement );
471  }
472  else
473  {
474  // Make lines appear at least 1 pixel wide, no matter of zoom
475  double x = 1.0, y = 1.0;
476  cairo_device_to_user_distance( currentContext, &x, &y );
477  double minWidth = std::min( fabs( x ), fabs( y ) );
478  cairo_set_line_width( currentContext, std::max( aLineWidth, minWidth ) );
479  }
480 }
481 
482 
483 void CAIRO_GAL::SetLayerDepth( double aLayerDepth )
484 {
485  super::SetLayerDepth( aLayerDepth );
486 
487  if( isInitialized )
488  storePath();
489 }
490 
491 
492 void CAIRO_GAL::Transform( const MATRIX3x3D& aTransformation )
493 {
494  cairo_matrix_t cairoTransformation;
495 
496  cairo_matrix_init( &cairoTransformation,
497  aTransformation.m_data[0][0],
498  aTransformation.m_data[1][0],
499  aTransformation.m_data[0][1],
500  aTransformation.m_data[1][1],
501  aTransformation.m_data[0][2],
502  aTransformation.m_data[1][2] );
503 
504  cairo_transform( currentContext, &cairoTransformation );
505 }
506 
507 
508 void CAIRO_GAL::Rotate( double aAngle )
509 {
510  storePath();
511 
512  if( isGrouping )
513  {
514  GROUP_ELEMENT groupElement;
515  groupElement.command = CMD_ROTATE;
516  groupElement.argument.dblArg[0] = aAngle;
517  currentGroup->push_back( groupElement );
518  }
519  else
520  {
521  cairo_rotate( currentContext, aAngle );
522  }
523 }
524 
525 
526 void CAIRO_GAL::Translate( const VECTOR2D& aTranslation )
527 {
528  storePath();
529 
530  if( isGrouping )
531  {
532  GROUP_ELEMENT groupElement;
533  groupElement.command = CMD_TRANSLATE;
534  groupElement.argument.dblArg[0] = aTranslation.x;
535  groupElement.argument.dblArg[1] = aTranslation.y;
536  currentGroup->push_back( groupElement );
537  }
538  else
539  {
540  cairo_translate( currentContext, aTranslation.x, aTranslation.y );
541  }
542 }
543 
544 
545 void CAIRO_GAL::Scale( const VECTOR2D& aScale )
546 {
547  storePath();
548 
549  if( isGrouping )
550  {
551  GROUP_ELEMENT groupElement;
552  groupElement.command = CMD_SCALE;
553  groupElement.argument.dblArg[0] = aScale.x;
554  groupElement.argument.dblArg[1] = aScale.y;
555  currentGroup->push_back( groupElement );
556  }
557  else
558  {
559  cairo_scale( currentContext, aScale.x, aScale.y );
560  }
561 }
562 
563 
565 {
566  storePath();
567 
568  if( isGrouping )
569  {
570  GROUP_ELEMENT groupElement;
571  groupElement.command = CMD_SAVE;
572  currentGroup->push_back( groupElement );
573  }
574  else
575  {
576  cairo_save( currentContext );
577  }
578 }
579 
580 
582 {
583  storePath();
584 
585  if( isGrouping )
586  {
587  GROUP_ELEMENT groupElement;
588  groupElement.command = CMD_RESTORE;
589  currentGroup->push_back( groupElement );
590  }
591  else
592  {
593  cairo_restore( currentContext );
594  }
595 }
596 
597 
599 {
600  initSurface();
601 
602  // If the grouping is started: the actual path is stored in the group, when
603  // a attribute was changed or when grouping stops with the end group method.
604  storePath();
605 
606  GROUP group;
607  int groupNumber = getNewGroupNumber();
608  groups.insert( std::make_pair( groupNumber, group ) );
609  currentGroup = &groups[groupNumber];
610  isGrouping = true;
611 
612  return groupNumber;
613 }
614 
615 
617 {
618  storePath();
619  isGrouping = false;
620 
621  deinitSurface();
622 }
623 
624 
625 void CAIRO_GAL::DrawGroup( int aGroupNumber )
626 {
627  // This method implements a small Virtual Machine - all stored commands
628  // are executed; nested calling is also possible
629 
630  storePath();
631 
632  for( GROUP::iterator it = groups[aGroupNumber].begin();
633  it != groups[aGroupNumber].end(); ++it )
634  {
635  switch( it->command )
636  {
637  case CMD_SET_FILL:
638  isFillEnabled = it->argument.boolArg;
639  break;
640 
641  case CMD_SET_STROKE:
642  isStrokeEnabled = it->argument.boolArg;
643  break;
644 
645  case CMD_SET_FILLCOLOR:
646  fillColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2],
647  it->argument.dblArg[3] );
648  break;
649 
650  case CMD_SET_STROKECOLOR:
651  strokeColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2],
652  it->argument.dblArg[3] );
653  break;
654 
655  case CMD_SET_LINE_WIDTH:
656  {
657  // Make lines appear at least 1 pixel wide, no matter of zoom
658  double x = 1.0, y = 1.0;
659  cairo_device_to_user_distance( currentContext, &x, &y );
660  double minWidth = std::min( fabs( x ), fabs( y ) );
661  cairo_set_line_width( currentContext, std::max( it->argument.dblArg[0], minWidth ) );
662  }
663  break;
664 
665 
666  case CMD_STROKE_PATH:
667  cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b );
668  cairo_append_path( currentContext, it->cairoPath );
669  cairo_stroke( currentContext );
670  break;
671 
672  case CMD_FILL_PATH:
673  cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
674  cairo_append_path( currentContext, it->cairoPath );
675  cairo_fill( currentContext );
676  break;
677 
678  /*
679  case CMD_TRANSFORM:
680  cairo_matrix_t matrix;
681  cairo_matrix_init( &matrix, it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2],
682  it->argument.dblArg[3], it->argument.dblArg[4], it->argument.dblArg[5] );
683  cairo_transform( currentContext, &matrix );
684  break;
685  */
686 
687  case CMD_ROTATE:
688  cairo_rotate( currentContext, it->argument.dblArg[0] );
689  break;
690 
691  case CMD_TRANSLATE:
692  cairo_translate( currentContext, it->argument.dblArg[0], it->argument.dblArg[1] );
693  break;
694 
695  case CMD_SCALE:
696  cairo_scale( currentContext, it->argument.dblArg[0], it->argument.dblArg[1] );
697  break;
698 
699  case CMD_SAVE:
700  cairo_save( currentContext );
701  break;
702 
703  case CMD_RESTORE:
704  cairo_restore( currentContext );
705  break;
706 
707  case CMD_CALL_GROUP:
708  DrawGroup( it->argument.intArg );
709  break;
710  }
711  }
712 }
713 
714 
715 void CAIRO_GAL::ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor )
716 {
717  storePath();
718 
719  for( GROUP::iterator it = groups[aGroupNumber].begin();
720  it != groups[aGroupNumber].end(); ++it )
721  {
722  if( it->command == CMD_SET_FILLCOLOR || it->command == CMD_SET_STROKECOLOR )
723  {
724  it->argument.dblArg[0] = aNewColor.r;
725  it->argument.dblArg[1] = aNewColor.g;
726  it->argument.dblArg[2] = aNewColor.b;
727  it->argument.dblArg[3] = aNewColor.a;
728  }
729  }
730 }
731 
732 
733 void CAIRO_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth )
734 {
735  // Cairo does not have any possibilities to change the depth coordinate of stored items,
736  // it depends only on the order of drawing
737 }
738 
739 
740 void CAIRO_GAL::DeleteGroup( int aGroupNumber )
741 {
742  storePath();
743 
744  // Delete the Cairo paths
745  std::deque<GROUP_ELEMENT>::iterator it, end;
746 
747  for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it )
748  {
749  if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH )
750  {
751  cairo_path_destroy( it->cairoPath );
752  }
753  }
754 
755  // Delete the group
756  groups.erase( aGroupNumber );
757 }
758 
759 
761 {
762  for( int i = groups.size() - 1; i >= 0; --i )
763  {
764  DeleteGroup( i );
765  }
766 }
767 
768 
770 {
771  // Copy the current bitmap to the backup buffer
772  int offset = 0;
773 
774  for( int j = 0; j < screenSize.y; j++ )
775  {
776  for( int i = 0; i < stride; i++ )
777  {
778  bitmapBufferBackup[offset + i] = bitmapBuffer[offset + i];
779  offset += stride;
780  }
781  }
782 }
783 
784 
786 {
787  int offset = 0;
788 
789  for( int j = 0; j < screenSize.y; j++ )
790  {
791  for( int i = 0; i < stride; i++ )
792  {
793  bitmapBuffer[offset + i] = bitmapBufferBackup[offset + i];
794  offset += stride;
795  }
796  }
797 }
798 
799 
801 {
802  // If the compositor is not set, that means that there is a recaching process going on
803  // and we do not need the compositor now
804  if( !validCompositor )
805  return;
806 
807  // Cairo grouping prevents display of overlapping items on the same layer in the lighter color
808  if( isInitialized )
809  storePath();
810 
811  switch( aTarget )
812  {
813  default:
814  case TARGET_CACHED:
815  case TARGET_NONCACHED:
816  compositor->SetBuffer( mainBuffer );
817  break;
818 
819  case TARGET_OVERLAY:
820  compositor->SetBuffer( overlayBuffer );
821  break;
822  }
823 
824  currentTarget = aTarget;
825 }
826 
827 
829 {
830  return currentTarget;
831 }
832 
833 
835 {
836  // Save the current state
837  unsigned int currentBuffer = compositor->GetBuffer();
838 
839  switch( aTarget )
840  {
841  // Cached and noncached items are rendered to the same buffer
842  default:
843  case TARGET_CACHED:
844  case TARGET_NONCACHED:
845  compositor->SetBuffer( mainBuffer );
846  break;
847 
848  case TARGET_OVERLAY:
849  compositor->SetBuffer( overlayBuffer );
850  break;
851  }
852 
853  compositor->ClearBuffer();
854 
855  // Restore the previous state
856  compositor->SetBuffer( currentBuffer );
857 }
858 
859 
860 void CAIRO_GAL::DrawCursor( const VECTOR2D& aCursorPosition )
861 {
862  cursorPosition = aCursorPosition;
863 }
864 
865 
866 void CAIRO_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
867 {
868  cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
869  cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
870  cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
871  cairo_stroke( currentContext );
872 }
873 
874 
876 {
877  if( isFillEnabled )
878  {
879  cairo_set_source_rgba( currentContext,
881 
882  if( isStrokeEnabled )
883  cairo_fill_preserve( currentContext );
884  else
885  cairo_fill( currentContext );
886  }
887 
888  if( isStrokeEnabled )
889  {
890  cairo_set_source_rgba( currentContext,
892  cairo_stroke( currentContext );
893  }
894 }
895 
896 
898 {
899  if( isElementAdded )
900  {
901  isElementAdded = false;
902 
903  if( !isGrouping )
904  {
905  if( isFillEnabled )
906  {
907  cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
908  cairo_fill_preserve( currentContext );
909  }
910 
911  if( isStrokeEnabled )
912  {
913  cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g,
914  strokeColor.b );
915  cairo_stroke_preserve( currentContext );
916  }
917  }
918  else
919  {
920  // Copy the actual path, append it to the global path list
921  // then check, if the path needs to be stroked/filled and
922  // add this command to the group list;
923  if( isStrokeEnabled )
924  {
925  GROUP_ELEMENT groupElement;
926  groupElement.cairoPath = cairo_copy_path( currentContext );
927  groupElement.command = CMD_STROKE_PATH;
928  currentGroup->push_back( groupElement );
929  }
930 
931  if( isFillEnabled )
932  {
933  GROUP_ELEMENT groupElement;
934  groupElement.cairoPath = cairo_copy_path( currentContext );
935  groupElement.command = CMD_FILL_PATH;
936  currentGroup->push_back( groupElement );
937  }
938  }
939 
940  cairo_new_path( currentContext );
941  }
942 }
943 
944 
945 void CAIRO_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
946 {
947  PostPaint();
948 }
949 
950 
951 void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
952 {
953  // Post the mouse event to the event listener registered in constructor, if any
954  if( mouseListener )
955  wxPostEvent( mouseListener, aEvent );
956 }
957 
958 
959 void CAIRO_GAL::blitCursor( wxMemoryDC& clientDC )
960 {
961  if( !IsCursorEnabled() )
962  return;
963 
964  auto p = ToScreen( cursorPosition );
965 
966  const auto cColor = getCursorColor();
967  const int cursorSize = fullscreenCursor ? 8000 : 80;
968 
969  wxColour color( cColor.r * cColor.a * 255, cColor.g * cColor.a * 255,
970  cColor.b * cColor.a * 255, 255 );
971  clientDC.SetPen( wxPen( color ) );
972  clientDC.DrawLine( p.x - cursorSize / 2, p.y, p.x + cursorSize / 2, p.y );
973  clientDC.DrawLine( p.x, p.y - cursorSize / 2, p.x, p.y + cursorSize / 2 );
974 }
975 
976 
978 {
980  while( ( ( wxBufferWidth * 3 ) % 4 ) != 0 ) wxBufferWidth++;
981 
982  // Create buffer, use the system independent Cairo context backend
983  stride = cairo_format_stride_for_width( GAL_FORMAT, wxBufferWidth );
985 
986  bitmapBuffer = new unsigned int[bufferSize];
987  bitmapBufferBackup = new unsigned int[bufferSize];
988  wxOutput = new unsigned char[wxBufferWidth * 3 * screenSize.y];
989 }
990 
991 
993 {
994  delete[] bitmapBuffer;
995  delete[] bitmapBufferBackup;
996  delete[] wxOutput;
997 }
998 
999 
1001 {
1002  if( isInitialized )
1003  return;
1004 
1005  // Create the Cairo surface
1006  surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
1008  context = cairo_create( surface );
1009 #ifdef __WXDEBUG__
1010  cairo_status_t status = cairo_status( context );
1011  wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) );
1012 #endif /* __WXDEBUG__ */
1014 
1015  cairo_set_antialias( context, CAIRO_ANTIALIAS_NONE );
1016 
1017  // Clear the screen
1019 
1020  // Compute the world <-> screen transformations
1022 
1023  cairo_matrix_init( &cairoWorldScreenMatrix, worldScreenMatrix.m_data[0][0],
1026  worldScreenMatrix.m_data[1][2] );
1027 
1028  cairo_set_matrix( context, &cairoWorldScreenMatrix );
1029 
1030  // Start drawing with a new path
1031  cairo_new_path( context );
1032  isElementAdded = true;
1033 
1034  cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
1035  cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
1036 
1037  lineWidth = 0;
1038 
1039  isInitialized = true;
1040 }
1041 
1042 
1044 {
1045  if( !isInitialized )
1046  return;
1047 
1048  // Destroy Cairo objects
1049  cairo_destroy( context );
1050  cairo_surface_destroy( surface );
1051 
1052  isInitialized = false;
1053 }
1054 
1055 
1057 {
1058  // Recreate the compositor with the new Cairo context
1059  compositor.reset( new CAIRO_COMPOSITOR( &currentContext ) );
1060  compositor->Resize( screenSize.x, screenSize.y );
1061 
1062  // Prepare buffers
1063  mainBuffer = compositor->CreateBuffer();
1064  overlayBuffer = compositor->CreateBuffer();
1065 
1066  validCompositor = true;
1067 }
1068 
1069 
1070 void CAIRO_GAL::drawPoly( const std::deque<VECTOR2D>& aPointList )
1071 {
1072  // Iterate over the point list and draw the segments
1073  std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
1074 
1075  cairo_move_to( currentContext, it->x, it->y );
1076 
1077  for( ++it; it != aPointList.end(); ++it )
1078  {
1079  cairo_line_to( currentContext, it->x, it->y );
1080  }
1081 
1082  flushPath();
1083  isElementAdded = true;
1084 }
1085 
1086 
1087 void CAIRO_GAL::drawPoly( const VECTOR2D aPointList[], int aListSize )
1088 {
1089  // Iterate over the point list and draw the segments
1090  const VECTOR2D* ptr = aPointList;
1091 
1092  cairo_move_to( currentContext, ptr->x, ptr->y );
1093 
1094  for( int i = 0; i < aListSize; ++i )
1095  {
1096  ++ptr;
1097  cairo_line_to( currentContext, ptr->x, ptr->y );
1098  }
1099 
1100  flushPath();
1101  isElementAdded = true;
1102 }
1103 
1104 
1105 void CAIRO_GAL::drawPoly( const SHAPE_LINE_CHAIN& aLineChain )
1106 {
1107  if( aLineChain.PointCount() < 2 )
1108  return;
1109 
1110  auto numPoints = aLineChain.PointCount();
1111 
1112  if( aLineChain.IsClosed() )
1113  numPoints += 1;
1114 
1115  const VECTOR2I start = aLineChain.CPoint( 0 );
1116  cairo_move_to( currentContext, start.x, start.y );
1117 
1118  for( int i = 1; i < numPoints; ++i )
1119  {
1120  const VECTOR2I& p = aLineChain.CPoint( i );
1121  cairo_line_to( currentContext, p.x, p.y );
1122  }
1123 
1124  flushPath();
1125  isElementAdded = true;
1126 }
1127 
1128 
1130 {
1131  wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
1132  wxT( "There are no free slots to store a group" ) );
1133 
1134  while( groups.find( groupCounter ) != groups.end() )
1135  groupCounter++;
1136 
1137  return groupCounter++;
1138 }
virtual void ClearScreen(const COLOR4D &aColor) override
Clear the screen.
Definition: cairo_gal.cpp:384
unsigned int groupCounter
Counter used for generating keys for groups.
Definition: cairo_gal.h:334
Definition: colors.h:57
virtual void DeleteGroup(int aGroupNumber) override
Delete the group from the memory.
Definition: cairo_gal.cpp:740
bool IsCursorEnabled() const
Returns information about cursor visibility.
void initSurface()
Prepare Cairo surfaces for drawing.
Definition: cairo_gal.cpp:1000
VECTOR2D cursorPosition
Current cursor position (world coordinates)
virtual void SetLayerDepth(double aLayerDepth) override
Set the depth of the layer (position on the z-axis)
Definition: cairo_gal.cpp:483
virtual void EndDrawing() override
End the drawing, needs to be called for every new frame.
Definition: cairo_gal.cpp:140
bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions) override
Cairo-specific update handlers
Definition: cairo_gal.cpp:114
Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
Definition: class_module.h:58
CAIRO_GAL(GAL_DISPLAY_OPTIONS &aDisplayOptions, wxWindow *aParent, wxEvtHandler *aMouseListener=NULL, wxEvtHandler *aPaintListener=NULL, const wxString &aName=wxT("CairoCanvas"))
Constructor CAIRO_GAL.
Definition: cairo_gal.cpp:45
virtual void ResizeScreen(int aWidth, int aHeight) override
Resizes the canvas.
Definition: cairo_gal.cpp:350
void deinitSurface()
Destroy Cairo surfaces when are not needed anymore.
Definition: cairo_gal.cpp:1043
Scale the context.
Definition: cairo_gal.h:311
int PointCount() const
Function PointCount()
void onPaint(wxPaintEvent &aEvent)
Paint event handler.
Definition: cairo_gal.cpp:945
cairo_path_t * cairoPath
Pointer to a Cairo path.
Definition: cairo_gal.h:326
void drawPoly(const std::deque< VECTOR2D > &aPointList)
Drawing polygons & polylines is the same in cairo, so here is the common code.
Definition: cairo_gal.cpp:1070
virtual ~CAIRO_GAL()
Definition: cairo_gal.cpp:105
bool boolArg
A bool argument.
Definition: cairo_gal.h:323
virtual void SetIsFill(bool aIsFillEnabled) override
Enable/disable fill.
Definition: cairo_gal.cpp:393
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle) override
Draw an arc.
Definition: cairo_gal.cpp:238
void setCompositor()
Prepare the compositor.
Definition: cairo_gal.cpp:1056
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a rectangle.
Definition: cairo_gal.cpp:312
virtual void SetStrokeColor(const COLOR4D &aColor) override
Set the stroke color.
Definition: cairo_gal.cpp:423
void PostPaint()
Function PostPaint posts an event to m_paint_listener.
Definition: cairo_gal.h:255
double g
Green component.
Definition: color4d.h:287
COLOR4D fillColor
The fill color.
virtual void BeginDrawing() override
Begin the drawing, needs to be called for every new frame.
Definition: cairo_gal.cpp:128
Set the stroke path.
Definition: cairo_gal.h:306
virtual void Flush() override
Force all remaining objects to be drawn.
Definition: cairo_gal.cpp:378
bool isInitialized
Are Cairo image & surface ready to use.
Definition: cairo_gal.h:345
virtual void Restore() override
Restore the context.
Definition: cairo_gal.cpp:581
int OutlineCount() const
Returns the number of outlines in the set
virtual void RestoreScreen() override
Restore the screen contents.
Definition: cairo_gal.cpp:785
unsigned int overlayBuffer
Handle to the overlay buffer.
Definition: cairo_gal.h:284
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
virtual void Translate(const VECTOR2D &aTranslation) override
Translate the context.
Definition: cairo_gal.cpp:526
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius) override
Draw a circle using world coordinates.
Definition: cairo_gal.cpp:229
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
bool validCompositor
Compositor initialization flag.
Definition: cairo_gal.h:286
VECTOR2D ToScreen(const VECTOR2D &aPoint) const
Compute the point position in screen coordinates from given world coordinates.
double b
Blue component.
Definition: color4d.h:288
double dblArg[MAX_CAIRO_ARGUMENTS]
Arguments for Cairo commands.
Definition: cairo_gal.h:322
Class that handles multitarget rendering (ie.
Auxiliary rendering target (noncached)
Definition: definitions.h:42
T m_data[3][3]
Definition: matrix3x3.h:64
GROUP * currentGroup
Currently used group.
Definition: cairo_gal.h:335
virtual void SetFillColor(const COLOR4D &aColor) override
Set the fill color.
Definition: cairo_gal.cpp:441
Translate the context.
Definition: cairo_gal.h:310
virtual void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth) override
Draw a rounded segment.
Definition: cairo_gal.cpp:185
union KIGFX::CAIRO_GAL::GROUP_ELEMENT::@51 argument
RENDER_TARGET currentTarget
Current rendering target.
Definition: cairo_gal.h:285
unsigned char * wxOutput
wxImage comaptible buffer
Definition: cairo_gal.h:293
double lineWidth
The line width.
unsigned int getNewGroupNumber()
Returns a valid key that can be used as a new group number.
Definition: cairo_gal.cpp:1129
void SetGridColor(const COLOR4D &aGridColor)
Set the grid color.
double a
Alpha component.
Definition: color4d.h:289
virtual void ClearTarget(RENDER_TARGET aTarget) override
Clears the target for rendering.
Definition: cairo_gal.cpp:834
bool isGrouping
Is grouping enabled ?
Definition: cairo_gal.h:330
bool fullscreenCursor
Shape of the cursor (fullscreen or small cross)
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:295
bool isStrokeEnabled
Are the outlines stroked ?
COLOR4D getCursorColor() const
Gets the actual cursor color to draw.
void Refresh()
Class SHAPE_POLY_SET.
std::shared_ptr< CAIRO_COMPOSITOR > compositor
Object for layers compositing.
Definition: cairo_gal.h:282
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
std::map< int, GROUP > groups
List of graphic groups.
Definition: cairo_gal.h:333
Enable/disable stroking.
Definition: cairo_gal.h:302
virtual void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle, double aWidth) override
Draw an arc segment.
Definition: cairo_gal.cpp:265
COLOR4D strokeColor
The color of the outlines.
void storePath()
Store the actual path.
Definition: cairo_gal.cpp:897
virtual void Transform(const MATRIX3x3D &aTransformation) override
Transform the context.
Definition: cairo_gal.cpp:492
Items that may change while the view stays the same (noncached)
Definition: definitions.h:43
virtual void Scale(const VECTOR2D &aScale) override
Scale the context.
Definition: cairo_gal.cpp:545
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor) override
Changes the color used to draw the group.
Definition: cairo_gal.cpp:715
virtual void Rotate(double aAngle) override
Rotate the context.
Definition: cairo_gal.cpp:508
Type definition for an graphics group element.
Definition: cairo_gal.h:318
GRAPHICS_COMMAND command
Command to execute.
Definition: cairo_gal.h:320
Restore the transformation matrix.
Definition: cairo_gal.h:313
virtual void ClearCache() override
Delete all data created during caching of graphic items.
Definition: cairo_gal.cpp:760
cairo_surface_t * surface
Cairo surface.
Definition: cairo_gal.h:341
virtual void SetIsStroke(bool aIsStrokeEnabled) override
Enable/disable stroked outlines.
Definition: cairo_gal.cpp:408
COLOR4D backgroundColor
Background color.
Definition: cairo_gal.h:346
cairo_t * context
Cairo image.
Definition: cairo_gal.h:340
bool isElementAdded
Was an graphic element added ?
Definition: cairo_gal.h:331
virtual void SetLineWidth(double aLineWidth) override
Set the line width.
Definition: cairo_gal.cpp:459
MATRIX3x3D worldScreenMatrix
World transformation.
wxEvtHandler * paintListener
Paint listener.
Definition: cairo_gal.h:291
virtual void SetTarget(RENDER_TARGET aTarget) override
Sets the target for rendering.
Definition: cairo_gal.cpp:800
unsigned int * bitmapBuffer
Storage of the cairo image.
Definition: cairo_gal.h:342
void skipMouseEvent(wxMouseEvent &aEvent)
Mouse event handler, forwards the event to the child.
Definition: cairo_gal.cpp:951
static const cairo_format_t GAL_FORMAT
Format used to store pixels.
Definition: cairo_gal.h:405
virtual bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions)
Function updatedGalDisplayOptions.
Rotate the context.
Definition: cairo_gal.h:309
bool isFillEnabled
Is filling of graphic objects enabled ?
virtual void DrawCursor(const VECTOR2D &aCursorPosition) override
Draw the cursor.
Definition: cairo_gal.cpp:860
int stride
Stride value for Cairo.
Definition: cairo_gal.h:344
virtual void DrawCurve(const VECTOR2D &startPoint, const VECTOR2D &controlPointA, const VECTOR2D &controlPointB, const VECTOR2D &endPoint) override
Draw a cubic bezier spline.
Definition: cairo_gal.cpp:337
cairo_matrix_t cairoWorldScreenMatrix
Cairo world to screen transformation matrix.
Definition: cairo_gal.h:338
virtual bool Show(bool aShow) override
Shows/hides the GAL canvas.
Definition: cairo_gal.cpp:367
unsigned int * bitmapBufferBackup
Backup storage of the cairo image.
Definition: cairo_gal.h:343
Enable/disable filling.
Definition: cairo_gal.h:301
Main rendering target (cached)
Definition: definitions.h:41
#define max(a, b)
Definition: auxiliary.h:86
virtual RENDER_TARGET GetTarget() const override
Gets the currently used target for rendering.
Definition: cairo_gal.cpp:828
Class SHAPE_LINE_CHAIN.
virtual void SaveScreen() override
Save the screen contents.
Definition: cairo_gal.cpp:769
virtual void ChangeGroupDepth(int aGroupNumber, int aDepth) override
Changes the depth (Z-axis position) of the group.
Definition: cairo_gal.cpp:733
VECTOR2I screenSize
Screen size in screen coordinates.
#define SWAP(varA, condition, varB)
Swap the variables if a condition is met.
Definition: definitions.h:31
virtual void DrawGroup(int aGroupNumber) override
Draw the stored group.
Definition: cairo_gal.cpp:625
bool IsClosed() const
Function IsClosed()
cairo_t * currentContext
Currently used Cairo context for drawing.
Definition: cairo_gal.h:339
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a line.
Definition: cairo_gal.cpp:176
virtual void drawGridLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a grid line (usually a simplified line function).
Definition: cairo_gal.cpp:866
void deleteBitmaps()
Allocate the bitmaps for drawing.
Definition: cairo_gal.cpp:992
unsigned int bufferSize
Size of buffers cairoOutput, bitmapBuffers.
Definition: cairo_gal.h:292
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList) override
Draw a polygon.
Definition: cairo_gal.h:131
double r
Red component.
Definition: color4d.h:286
virtual int BeginGroup() override
Begin a group.
Definition: cairo_gal.cpp:598
RENDER_TARGET
RENDER_TARGET: Possible rendering targets.
Definition: definitions.h:39
std::deque< GROUP_ELEMENT > GROUP
A graphic group type definition.
Definition: cairo_gal.h:332
Set the fill path.
Definition: cairo_gal.h:307
wxEvtHandler * mouseListener
Mouse listener.
Definition: cairo_gal.h:290
void allocateBitmaps()
Allocate the bitmaps for drawing.
Definition: cairo_gal.cpp:977
virtual void blitCursor(wxMemoryDC &clientDC)
Blits cursor into the current screen.
Definition: cairo_gal.cpp:959
unsigned int mainBuffer
Handle to the main buffer.
Definition: cairo_gal.h:283
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
wxWindow * parentWindow
Parent window.
Definition: cairo_gal.h:289
virtual void EndGroup() override
End the group.
Definition: cairo_gal.cpp:616
Save the transformation matrix.
Definition: cairo_gal.h:312
#define min(a, b)
Definition: auxiliary.h:85
Class GAL is the abstract interface for drawing on a 2D-surface.
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
virtual void Save() override
Save the context.
Definition: cairo_gal.cpp:564