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