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