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) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * Graphics Abstraction Layer (GAL) - base class
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
25  */
26 
27 #ifndef GRAPHICSABSTRACTIONLAYER_H_
28 #define GRAPHICSABSTRACTIONLAYER_H_
29 
30 #include <deque>
31 #include <stack>
32 #include <limits>
33 #include <cmath>
34 
35 #include <math/matrix3x3.h>
36 
37 #include <gal/color4d.h>
38 #include <gal/cursors.h>
39 #include <gal/definitions.h>
40 #include <gal/stroke_font.h>
41 #include <gal/gal_display_options.h>
42 #include <newstroke_font.h>
43 
44 class SHAPE_LINE_CHAIN;
45 class SHAPE_POLY_SET;
46 class BITMAP_BASE;
47 
48 namespace KIGFX
49 {
50 
51 /**
52  * Abstract interface for drawing on a 2D-surface.
53  *
54  * The functions are optimized for drawing shapes of an EDA-program such as KiCad. Most methods
55  * are abstract and need to be implemented by a lower layer, for example by a Cairo or OpenGL
56  * implementation.  Almost all methods use world coordinates as arguments. The board design is
57  * defined in world space units for drawing purposes these are transformed to screen units with
58  * this layer. So zooming is handled here as well.
59  *
60  */
61 class GAL : GAL_DISPLAY_OPTIONS_OBSERVER
62 {
63     // These friend declarations allow us to hide routines that should not be called.  The
64     // corresponding RAII objects must be used instead.
65     friend class GAL_CONTEXT_LOCKER;
66     friend class GAL_UPDATE_CONTEXT;
67     friend class GAL_DRAWING_CONTEXT;
68 
69 public:
70     // Constructor / Destructor
71     GAL( GAL_DISPLAY_OPTIONS& aOptions );
72     virtual ~GAL();
73 
74     /// Return the initialization status for the canvas.
IsInitialized()75     virtual bool IsInitialized() const { return true; }
76 
77     /// Return true if the GAL canvas is visible on the screen.
IsVisible()78     virtual bool IsVisible() const { return true; }
79 
80     /// Return true if the GAL engine is a Cairo based type.
IsCairoEngine()81     virtual bool IsCairoEngine() { return false; }
82 
83     /// Return true if the GAL engine is a OpenGL based type.
IsOpenGlEngine()84     virtual bool IsOpenGlEngine() { return false; }
85 
86     // ---------------
87     // Drawing methods
88     // ---------------
89 
90     /**
91      * Draw a line.
92      *
93      * Start and end points are defined as 2D-Vectors.
94      *
95      * @param aStartPoint   is the start point of the line.
96      * @param aEndPoint     is the end point of the line.
97      */
DrawLine(const VECTOR2D & aStartPoint,const VECTOR2D & aEndPoint)98     virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {};
99 
100     /**
101      * Draw a rounded segment.
102      *
103      * Start and end points are defined as 2D-Vectors.
104      *
105      * @param aStartPoint   is the start point of the segment.
106      * @param aEndPoint     is the end point of the segment.
107      * @param aWidth        is a width of the segment
108      */
DrawSegment(const VECTOR2D & aStartPoint,const VECTOR2D & aEndPoint,double aWidth)109     virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
110                               double aWidth ) {};
111 
112     /**
113      * Draw a polyline
114      *
115      * @param aPointList is a list of 2D-Vectors containing the polyline points.
116      */
DrawPolyline(const std::deque<VECTOR2D> & aPointList)117     virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) {};
DrawPolyline(const VECTOR2D aPointList[],int aListSize)118     virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {};
DrawPolyline(const SHAPE_LINE_CHAIN & aLineChain)119     virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) {};
120 
121     /**
122      * Draw a circle using world coordinates.
123      *
124      * @param aCenterPoint is the center point of the circle.
125      * @param aRadius is the radius of the circle.
126      */
DrawCircle(const VECTOR2D & aCenterPoint,double aRadius)127     virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) {};
128 
129     /**
130      * Draw an arc.
131      *
132      * @param aCenterPoint  is the center point of the arc.
133      * @param aRadius       is the arc radius.
134      * @param aStartAngle   is the start angle of the arc.
135      * @param aEndAngle     is the end angle of the arc.
136      */
DrawArc(const VECTOR2D & aCenterPoint,double aRadius,double aStartAngle,double aEndAngle)137     virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
138                           double aEndAngle ) {};
139 
140     /**
141      * Draw an arc segment.
142      *
143      * This method differs from DrawArc() in what happens when fill/stroke are on or off.
144      * DrawArc() draws a "pie piece" when fill is turned on, and a thick stroke when fill is off.
145      * DrawArcSegment() with fill *on* behaves like DrawArc() with fill *off*.
146      * DrawArcSegment() with fill *off* draws the outline of what it would have drawn with fill on.
147      *
148      * TODO: Unify Arc routines
149      *
150      * @param aCenterPoint  is the center point of the arc.
151      * @param aRadius       is the arc radius.
152      * @param aStartAngle   is the start angle of the arc.
153      * @param aEndAngle     is the end angle of the arc.
154      * @param aWidth        is the thickness of the arc (pen size).
155      * @param aMaxError     is the max allowed error to create segments to approximate a circle.
156      *  It has meaning only for back ends that can't draw a true arc, and use segments to approximate.
157      */
DrawArcSegment(const VECTOR2D & aCenterPoint,double aRadius,double aStartAngle,double aEndAngle,double aWidth,double aMaxError)158     virtual void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
159                                  double aEndAngle, double aWidth, double aMaxError ) {};
160 
161     /**
162      * Draw a rectangle.
163      *
164      * @param aStartPoint   is the start point of the rectangle.
165      * @param aEndPoint     is the end point of the rectangle.
166      */
DrawRectangle(const VECTOR2D & aStartPoint,const VECTOR2D & aEndPoint)167     virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {};
168 
169     /**
170      * Draw a polygon.
171      *
172      * @param aPointList is the list of the polygon points.
173      */
DrawPolygon(const std::deque<VECTOR2D> & aPointList)174     virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) {};
DrawPolygon(const VECTOR2D aPointList[],int aListSize)175     virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) {};
176     virtual void DrawPolygon( const SHAPE_POLY_SET& aPolySet, bool aStrokeTriangulation = false ) {};
DrawPolygon(const SHAPE_LINE_CHAIN & aPolySet)177     virtual void DrawPolygon( const SHAPE_LINE_CHAIN& aPolySet ) {};
178 
179     /**
180      * Draw a cubic bezier spline.
181      *
182      * @param startPoint    is the start point of the spline.
183      * @param controlPointA is the first control point.
184      * @param controlPointB is the second control point.
185      * @param endPoint      is the end point of the spline.
186      * @param aFilterValue  is used by Bezier to segments approximation, if
187      * the Bezier curve is not supported and needs a curve to polyline conversion.
188      * aFilterValue = 0 means no filtering.
189      */
190     virtual void DrawCurve( const VECTOR2D& startPoint,    const VECTOR2D& controlPointA,
191                             const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
192                             double aFilterValue = 0.0 ) {};
193 
194     /**
195      * Draw a bitmap image.
196      */
DrawBitmap(const BITMAP_BASE & aBitmap)197     virtual void DrawBitmap( const BITMAP_BASE& aBitmap ) {};
198 
199     // --------------
200     // Screen methods
201     // --------------
202 
203     /// Resize the canvas.
ResizeScreen(int aWidth,int aHeight)204     virtual void ResizeScreen( int aWidth, int aHeight ) {};
205 
206     /// Show/hide the GAL canvas
Show(bool aShow)207     virtual bool Show( bool aShow ) { return true; };
208 
209     /// Return GAL canvas size in pixels
GetScreenPixelSize()210     const VECTOR2I& GetScreenPixelSize() const
211     {
212         return m_screenSize;
213     }
214 
215     /// Force all remaining objects to be drawn.
Flush()216     virtual void Flush() {};
217 
SetClearColor(const COLOR4D & aColor)218     void SetClearColor( const COLOR4D& aColor )
219     {
220         m_clearColor = aColor;
221     }
222 
GetClearColor()223     const COLOR4D& GetClearColor( ) const
224     {
225         return m_clearColor;
226     }
227 
228     /**
229      * Clear the screen.
230      *
231      * @param aColor is the color used for clearing.
232      */
ClearScreen()233     virtual void ClearScreen() {};
234 
235     // -----------------
236     // Attribute setting
237     // -----------------
238 
239     /**
240      * Enable/disable fill.
241      *
242      * @param aIsFillEnabled is true, when the graphics objects should be filled, else false.
243      */
SetIsFill(bool aIsFillEnabled)244     virtual void SetIsFill( bool aIsFillEnabled )
245     {
246         m_isFillEnabled = aIsFillEnabled;
247     }
248 
249     /**
250      * Enable/disable stroked outlines.
251      *
252      * @param aIsStrokeEnabled is true, if the outline of an object should be stroked.
253      */
SetIsStroke(bool aIsStrokeEnabled)254     virtual void SetIsStroke( bool aIsStrokeEnabled )
255     {
256         m_isStrokeEnabled = aIsStrokeEnabled;
257     }
258 
259     /**
260      * Set the fill color.
261      *
262      * @param aColor is the color for filling.
263      */
SetFillColor(const COLOR4D & aColor)264     virtual void SetFillColor( const COLOR4D& aColor )
265     {
266         m_fillColor = aColor;
267     }
268 
269     /**
270      * Get the fill color.
271      *
272      * @return the color for filling a outline.
273      */
GetFillColor()274     inline const COLOR4D& GetFillColor() const
275     {
276         return m_fillColor;
277     }
278 
279     /**
280      * Set the stroke color.
281      *
282      * @param aColor is the color for stroking the outline.
283      */
SetStrokeColor(const COLOR4D & aColor)284     virtual void SetStrokeColor( const COLOR4D& aColor )
285     {
286         m_strokeColor = aColor;
287     }
288 
289     /**
290      * Get the stroke color.
291      *
292      * @return the color for stroking the outline.
293      */
GetStrokeColor()294     inline const COLOR4D& GetStrokeColor() const
295     {
296         return m_strokeColor;
297     }
298 
299     /**
300      * Set the line width.
301      *
302      * @param aLineWidth is the line width.
303      */
SetLineWidth(float aLineWidth)304     virtual void SetLineWidth( float aLineWidth )
305     {
306         m_lineWidth = aLineWidth;
307     }
308 
309     /**
310      * Get the line width.
311      *
312      * @return the actual line width.
313      */
GetLineWidth()314     inline float GetLineWidth() const
315     {
316         return m_lineWidth;
317     }
318 
319     /**
320      * Set the depth of the layer (position on the z-axis)
321      *
322      * @param aLayerDepth the layer depth for the objects.
323      */
SetLayerDepth(double aLayerDepth)324     virtual void SetLayerDepth( double aLayerDepth )
325     {
326         assert( aLayerDepth <= m_depthRange.y );
327         assert( aLayerDepth >= m_depthRange.x );
328 
329         m_layerDepth = aLayerDepth;
330     }
331 
332     // ----
333     // Text
334     // ----
335 
GetStrokeFont()336     const STROKE_FONT& GetStrokeFont() const
337     {
338         return m_strokeFont;
339     }
340 
341     /**
342      * Draw a vector type text using preloaded Newstroke font.
343      *
344      * @param aText is the text to be drawn.
345      * @param aPosition is the text position in world coordinates.
346      * @param aRotationAngle is the text rotation angle.
347      */
StrokeText(const wxString & aText,const VECTOR2D & aPosition,double aRotationAngle)348     virtual void StrokeText( const wxString& aText, const VECTOR2D& aPosition,
349                              double aRotationAngle )
350     {
351         m_strokeFont.Draw( aText, aPosition, aRotationAngle );
352     }
353 
354     /**
355      * Draw a text using a bitmap font. It should be faster than StrokeText(),
356      * but can be used only for non-Gerber elements.
357      *
358      * @param aText is the text to be drawn.
359      * @param aPosition is the text position in world coordinates.
360      * @param aRotationAngle is the text rotation angle.
361      */
BitmapText(const wxString & aText,const VECTOR2D & aPosition,double aRotationAngle)362     virtual void BitmapText( const wxString& aText, const VECTOR2D& aPosition,
363                              double aRotationAngle )
364     {
365         // Fallback: use stroke font
366 
367         // Handle flipped view
368         if( m_globalFlipX )
369             textProperties.m_mirrored = !textProperties.m_mirrored;
370 
371         // Bitmap font is slightly smaller and slightly heavier than the stroke font so we
372         // compensate a bit before stroking
373         float    saveLineWidth = m_lineWidth;
374         VECTOR2D saveGlyphSize = textProperties.m_glyphSize;
375         {
376             m_lineWidth *= 1.2f;
377             textProperties.m_glyphSize = textProperties.m_glyphSize * 0.8;
378 
379             StrokeText( aText, aPosition, aRotationAngle );
380         }
381         m_lineWidth = saveLineWidth;
382         textProperties.m_glyphSize = saveGlyphSize;
383 
384         if( m_globalFlipX )
385             textProperties.m_mirrored = !textProperties.m_mirrored;
386     }
387 
388     /**
389      * Compute the X and Y size of a given text. The text is expected to be a only one line text.
390      *
391      * @param aText is the text string (one line).
392      * @return is the text size.
393      */
394     VECTOR2D GetTextLineSize( const UTF8& aText ) const;
395 
396     /**
397      * Loads attributes of the given text (bold/italic/underline/mirrored and so on).
398      *
399      * @param aText is the text item.
400      */
401     virtual void SetTextAttributes( const EDA_TEXT* aText );
402 
403     /**
404      * Reset text attributes to default styling.
405      *
406      * Normally, custom attributes will be set individually after this,
407      * otherwise you can use SetTextAttributes()
408      */
409     void ResetTextAttributes();
410 
411     /**
412      * Set the font glyph size.
413      *
414      * @param aGlyphSize is the new font glyph size.
415      */
SetGlyphSize(const VECTOR2D & aSize)416     inline void SetGlyphSize( const VECTOR2D& aSize ) { textProperties.m_glyphSize = aSize; }
GetGlyphSize()417     const VECTOR2D& GetGlyphSize() const { return textProperties.m_glyphSize; }
418 
419     /**
420      * Set bold property of current font.
421      *
422      * @param aBold tells if the font should be bold or not.
423      */
SetFontBold(bool aBold)424     inline void SetFontBold( bool aBold ) { textProperties.m_bold = aBold;  }
IsFontBold()425     inline bool IsFontBold() const { return textProperties.m_bold; }
426 
427     /**
428      * Set italic property of current font.
429      *
430      * @param aItalic tells if the font should be italic or not.
431      */
SetFontItalic(bool aItalic)432     inline void SetFontItalic( bool aItalic ) { textProperties.m_italic = aItalic; }
IsFontItalic()433     inline bool IsFontItalic() const { return textProperties.m_italic; }
434 
SetFontUnderlined(bool aUnderlined)435     inline void SetFontUnderlined( bool aUnderlined ) { textProperties.m_underlined = aUnderlined; }
IsFontUnderlined()436     inline bool IsFontUnderlined() const { return textProperties.m_underlined; }
437 
438     /**
439      * Set a mirrored property of text.
440      *
441      * @param aMirrored tells if the text should be mirrored or not.
442      */
SetTextMirrored(bool aMirrored)443     inline void SetTextMirrored( bool aMirrored ) { textProperties.m_mirrored = aMirrored; }
IsTextMirrored()444     inline bool IsTextMirrored() const { return textProperties.m_mirrored; }
445 
446     /**
447      * Set the horizontal justify for text drawing.
448      *
449      * @param aHorizontalJustify is the horizontal justify value.
450      */
SetHorizontalJustify(const EDA_TEXT_HJUSTIFY_T aHorizontalJustify)451     inline void SetHorizontalJustify( const EDA_TEXT_HJUSTIFY_T aHorizontalJustify )
452     {
453         textProperties.m_horizontalJustify = aHorizontalJustify;
454     }
455 
456     /**
457      * Return current text horizontal justification setting.
458      */
GetHorizontalJustify()459     inline EDA_TEXT_HJUSTIFY_T GetHorizontalJustify() const
460     {
461         return textProperties.m_horizontalJustify;
462     }
463 
464     /**
465      * Set the vertical justify for text drawing.
466      *
467      * @param aVerticalJustify is the vertical justify value.
468      */
SetVerticalJustify(const EDA_TEXT_VJUSTIFY_T aVerticalJustify)469     inline void SetVerticalJustify( const EDA_TEXT_VJUSTIFY_T aVerticalJustify )
470     {
471         textProperties.m_verticalJustify = aVerticalJustify;
472     }
473 
474     /**
475      * Returns current text vertical justification setting.
476      */
GetVerticalJustify()477     inline EDA_TEXT_VJUSTIFY_T GetVerticalJustify() const
478     {
479         return textProperties.m_verticalJustify;
480     }
481 
482 
483     // --------------
484     // Transformation
485     // --------------
486 
487     /**
488      * Transform the context.
489      *
490      * @param aTransformation is the transformation matrix.
491      */
Transform(const MATRIX3x3D & aTransformation)492     virtual void Transform( const MATRIX3x3D& aTransformation ) {};
493 
494     /**
495      * Rotate the context.
496      *
497      * @param aAngle is the rotation angle in radians.
498      */
Rotate(double aAngle)499     virtual void Rotate( double aAngle ) {};
500 
501     /**
502      * Translate the context.
503      *
504      * @param aTranslation is the translation vector.
505      */
Translate(const VECTOR2D & aTranslation)506     virtual void Translate( const VECTOR2D& aTranslation ) {};
507 
508     /**
509      * Scale the context.
510      *
511      * @param aScale is the scale factor for the x- and y-axis.
512      */
Scale(const VECTOR2D & aScale)513     virtual void Scale( const VECTOR2D& aScale ) {};
514 
515     /// Save the context.
Save()516     virtual void Save() {};
517 
518     /// Restore the context.
Restore()519     virtual void Restore() {};
520 
521     // --------------------------------------------
522     // Group methods
523     // ---------------------------------------------
524 
525     /**
526      * Begin a group.
527      *
528      * A group is a collection of graphic items.
529      * Hierarchical groups are possible, attributes and transformations can be used.
530      *
531      * @return the number of the group.
532      */
BeginGroup()533     virtual int BeginGroup() { return 0; };
534 
535     /// End the group.
EndGroup()536     virtual void EndGroup() {};
537 
538     /**
539      * Draw the stored group.
540      *
541      * @param aGroupNumber is the group number.
542      */
DrawGroup(int aGroupNumber)543     virtual void DrawGroup( int aGroupNumber ) {};
544 
545     /**
546      * Change the color used to draw the group.
547      *
548      * @param aGroupNumber is the group number.
549      * @param aNewColor is the new color.
550      */
ChangeGroupColor(int aGroupNumber,const COLOR4D & aNewColor)551     virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor ) {};
552 
553     /**
554      * Change the depth (Z-axis position) of the group.
555      *
556      * @param aGroupNumber is the group number.
557      * @param aDepth is the new depth.
558      */
ChangeGroupDepth(int aGroupNumber,int aDepth)559     virtual void ChangeGroupDepth( int aGroupNumber, int aDepth ) {};
560 
561     /**
562      * Delete the group from the memory.
563      *
564      * @param aGroupNumber is the group number.
565      */
DeleteGroup(int aGroupNumber)566     virtual void DeleteGroup( int aGroupNumber ) {};
567 
568     /**
569      * Delete all data created during caching of graphic items.
570      */
ClearCache()571     virtual void ClearCache() {};
572 
573     // --------------------------------------------------------
574     // Handling the world <-> screen transformation
575     // --------------------------------------------------------
576 
577     /// Compute the world <-> screen transformation matrix
578     virtual void ComputeWorldScreenMatrix();
579 
580     /**
581      * Get the world <-> screen transformation matrix.
582      *
583      * @return the transformation matrix.
584      */
GetWorldScreenMatrix()585     const MATRIX3x3D& GetWorldScreenMatrix() const
586     {
587         return m_worldScreenMatrix;
588     }
589 
590     /**
591      * Get the screen <-> world transformation matrix.
592      *
593      * @return the transformation matrix.
594      */
GetScreenWorldMatrix()595     const MATRIX3x3D& GetScreenWorldMatrix() const
596     {
597         return m_screenWorldMatrix;
598     }
599 
600     /**
601      * Set the world <-> screen transformation matrix.
602      *
603      * @param aMatrix is the 3x3 world <-> screen transformation matrix.
604      */
SetWorldScreenMatrix(const MATRIX3x3D & aMatrix)605     inline void SetWorldScreenMatrix( const MATRIX3x3D& aMatrix )
606     {
607         m_worldScreenMatrix = aMatrix;
608     }
609 
610     /**
611      * @return the bounding box of the world that is displayed on screen at the moment
612      */
613     BOX2D GetVisibleWorldExtents() const;
614 
615     /**
616      * Set the unit length.
617      *
618      * This defines the length [inch] per one integer. For instance a value 0.001 means
619      * that the coordinate [1000, 1000] corresponds with a point at (1 inch, 1 inch) or
620      * 1 mil resolution per integer.
621      *
622      * @param aWorldUnitLength is the world Unit length.
623      */
SetWorldUnitLength(double aWorldUnitLength)624     inline void SetWorldUnitLength( double aWorldUnitLength )
625     {
626         m_worldUnitLength = aWorldUnitLength;
627     }
628 
SetScreenSize(const VECTOR2I & aSize)629     inline void SetScreenSize( const VECTOR2I& aSize )
630     {
631         m_screenSize = aSize;
632     }
633 
634     /**
635      * Set the dots per inch of the screen.
636      *
637      * This value depends on the user screen, it should be configurable by the application.
638      * For instance a typical notebook with HD+ resolution (1600x900) has 106 DPI.
639      *
640      * @param aScreenDPI are the screen DPI.
641      */
SetScreenDPI(double aScreenDPI)642     inline void SetScreenDPI( double aScreenDPI )
643     {
644         m_screenDPI = aScreenDPI;
645     }
646 
647     /**
648      * Set the Point in world space to look at.
649      *
650      * This point corresponds with the center of the actual drawing area.
651      *
652      * @param aPoint is the look at point (center of the actual drawing area).
653      */
SetLookAtPoint(const VECTOR2D & aPoint)654     inline void SetLookAtPoint( const VECTOR2D& aPoint )
655     {
656         m_lookAtPoint = aPoint;
657     }
658 
659     /**
660      * Get the look at point.
661      *
662      * @return the look at point.
663      */
GetLookAtPoint()664     inline const VECTOR2D& GetLookAtPoint() const
665     {
666         return m_lookAtPoint;
667     }
668 
669     /**
670      * Set the zoom factor of the scene.
671      *
672      * @param aZoomFactor is the zoom factor.
673      */
SetZoomFactor(double aZoomFactor)674     inline void SetZoomFactor( double aZoomFactor )
675     {
676         m_zoomFactor = aZoomFactor;
677     }
678 
679     /**
680      * Get the zoom factor
681      *
682      * @return the zoom factor.
683      */
GetZoomFactor()684     inline double GetZoomFactor() const
685     {
686         return m_zoomFactor;
687     }
688 
689     /**
690      * Set the rotation angle.
691      *
692      * @param aRotation is the new rotation angle (radians).
693      */
SetRotation(double aRotation)694     void SetRotation( double aRotation )
695     {
696         m_rotation = aRotation;
697     }
698 
699     /**
700      * Get the rotation angle.
701      *
702      * @return The rotation angle (radians).
703      */
GetRotation()704     double GetRotation() const
705     {
706         return m_rotation;
707     }
708 
709     /**
710      * Set the range of the layer depth.
711      *
712      * Usually required for the OpenGL implementation, any object outside this range is not drawn.
713      *
714      * @param aDepthRange is the depth range where component x is the near clipping plane and y
715      *                    is the far clipping plane.
716      */
SetDepthRange(const VECTOR2D & aDepthRange)717     inline void SetDepthRange( const VECTOR2D& aDepthRange )
718     {
719         m_depthRange = aDepthRange;
720     }
721 
722     /**
723      * Return the minimum depth in the currently used range (the top).
724      */
GetMinDepth()725     inline double GetMinDepth() const
726     {
727         return m_depthRange.x;
728     }
729 
730     /**
731      * Return the maximum depth in the currently used range (the bottom).
732      */
GetMaxDepth()733     inline double GetMaxDepth() const
734     {
735         return m_depthRange.y;
736     }
737 
738     /**
739      * Get the world scale.
740      *
741      * @return the actual world scale factor.
742      */
GetWorldScale()743     inline double GetWorldScale() const
744     {
745         return m_worldScale;
746     }
747 
748     /**
749      * Sets flipping of the screen.
750      *
751      * @param xAxis is the flip flag for the X axis.
752      * @param yAxis is the flip flag for the Y axis.
753      */
SetFlip(bool xAxis,bool yAxis)754     inline void SetFlip( bool xAxis, bool yAxis )
755     {
756         m_globalFlipX = xAxis;
757         m_globalFlipY = yAxis;
758     }
759 
760     /**
761      * Return true if flip flag for the X axis is set.
762      */
IsFlippedX()763     bool IsFlippedX() const
764     {
765         return m_globalFlipX;
766     }
767 
768     /**
769      * Return true if flip flag for the Y axis is set.
770      */
IsFlippedY()771     bool IsFlippedY() const
772     {
773         return m_globalFlipY;
774     }
775 
776     // ---------------------------
777     // Buffer manipulation methods
778     // ---------------------------
779 
780     /**
781      * Set the target for rendering.
782      *
783      * @param aTarget is the new target for rendering.
784      */
SetTarget(RENDER_TARGET aTarget)785     virtual void SetTarget( RENDER_TARGET aTarget ) {};
786 
787     /**
788      * Get the currently used target for rendering.
789      *
790      * @return The current rendering target.
791      */
GetTarget()792     virtual RENDER_TARGET GetTarget() const { return TARGET_CACHED; };
793 
794     /**
795      * Clear the target for rendering.
796      *
797      * @param aTarget is the target to be cleared.
798      */
ClearTarget(RENDER_TARGET aTarget)799     virtual void ClearTarget( RENDER_TARGET aTarget ) {};
800 
801     /**
802      * Return true if the target exists.
803      *
804      * @param aTarget is the target to be checked.
805      */
HasTarget(RENDER_TARGET aTarget)806     virtual bool HasTarget( RENDER_TARGET aTarget )
807     {
808         return true;
809     };
810 
811     /**
812      * Set negative draw mode in the renderer.
813      *
814      * When negative mode is enabled, drawn items will subtract from
815      * previously drawn items.  This is mainly needed for Gerber
816      * negative item support in Cairo, since unlike in OpenGL, objects
817      * drawn with zero opacity on top of other objects would not normally
818      * mask objects in Cairo.  This method is a no-op in OpenGL.
819      *
820      * @param aSetting is true if negative mode should be enabled
821      */
SetNegativeDrawMode(bool aSetting)822     virtual void SetNegativeDrawMode( bool aSetting ) {};
823 
824     /**
825      * Begins rendering of a differential layer. Used by gerbview's differential mode.
826      *
827      * Differential layers have their drawn objects blended onto the lower layers
828      * differently so we need to end drawing of current objects and start a new
829      * set to be completed with a different blend mode.
830      */
StartDiffLayer()831     virtual void StartDiffLayer() {};
832 
833     /**
834      * Ends rendering of a differential layer. Objects drawn after the StartDiffLayer()
835      * will be drawn and composited with a differential blend mode, then drawing is
836      * returned to normal.
837      */
EndDiffLayer()838     virtual void EndDiffLayer() {};
839 
840     /**
841      * Begins rendering in a new layer that will be copied to the main
842      * layer in EndNegativesLayer().
843      *
844      * For Cairo, layers with negative items need a new layer so when
845      * negative layers _CLEAR sections it doesn't delete drawings on layers
846      * below them. No-op in OpenGL
847      */
StartNegativesLayer()848     virtual void StartNegativesLayer(){};
849 
850     /**
851      * Ends rendering of a negatives layer and draws it to the main layer.
852      * No-op in OpenGL.
853      */
EndNegativesLayer()854     virtual void EndNegativesLayer(){};
855 
856     // -------------
857     // Grid methods
858     // -------------
859 
860     /**
861      * Set the visibility setting of the grid.
862      *
863      * @param aVisibility is the new visibility setting of the grid.
864      */
SetGridVisibility(bool aVisibility)865     void SetGridVisibility( bool aVisibility ) { m_gridVisibility = aVisibility; }
866 
GetGridVisibility()867     bool GetGridVisibility() const { return m_gridVisibility; }
868 
GetGridSnapping()869     bool GetGridSnapping() const
870     {
871         return m_options.m_gridSnapping == KIGFX::GRID_SNAPPING::ALWAYS ||
872                  ( m_gridVisibility && m_options.m_gridSnapping == KIGFX::GRID_SNAPPING::WITH_GRID );
873     }
874 
875     /**
876      * Set the origin point for the grid.
877      *
878      * @param aGridOrigin is a vector containing the grid origin point, in world coordinates.
879      */
SetGridOrigin(const VECTOR2D & aGridOrigin)880     inline void SetGridOrigin( const VECTOR2D& aGridOrigin )
881     {
882         m_gridOrigin = aGridOrigin;
883 
884         if( m_gridSize.x == 0.0 || m_gridSize.y == 0.0 )
885         {
886             m_gridOffset = VECTOR2D( 0.0, 0.0);
887         }
888         else
889         {
890             m_gridOffset = VECTOR2D( (long) m_gridOrigin.x % (long) m_gridSize.x,
891                                      (long) m_gridOrigin.y % (long) m_gridSize.y );
892         }
893     }
894 
GetGridOrigin()895     inline const VECTOR2D& GetGridOrigin() const
896     {
897         return m_gridOrigin;
898     }
899 
900     /**
901      * Set the grid size.
902      *
903      * @param aGridSize is a vector containing the grid size in x and y direction.
904      */
SetGridSize(const VECTOR2D & aGridSize)905     inline void SetGridSize( const VECTOR2D& aGridSize )
906     {
907         m_gridSize = aGridSize;
908 
909         // Avoid stupid grid size values: a grid size  should be >= 1 in internal units
910         m_gridSize.x = std::max( 1.0, m_gridSize.x );
911         m_gridSize.y = std::max( 1.0, m_gridSize.y );
912 
913         m_gridOffset = VECTOR2D( (long) m_gridOrigin.x % (long) m_gridSize.x,
914                                  (long) m_gridOrigin.y % (long) m_gridSize.y );
915     }
916 
917     /**
918      * Return the grid size.
919      *
920      * @return A vector containing the grid size in x and y direction.
921      */
GetGridSize()922     inline const VECTOR2D& GetGridSize() const
923     {
924         return m_gridSize;
925     }
926 
927     /**
928      * Set the grid color.
929      *
930      * @param aGridColor is the grid color, it should have a low alpha value for the best effect.
931      */
SetGridColor(const COLOR4D & aGridColor)932     inline void SetGridColor( const COLOR4D& aGridColor )
933     {
934         m_gridColor = aGridColor;
935     }
936 
937     /**
938      * Set the axes color.
939      *
940      * @param aAxesColor is the color to draw the axes if enabled.
941      */
SetAxesColor(const COLOR4D & aAxesColor)942     inline void SetAxesColor( const COLOR4D& aAxesColor )
943     {
944         m_axesColor = aAxesColor;
945     }
946 
947     /**
948      * Enable drawing the axes.
949      */
SetAxesEnabled(bool aAxesEnabled)950     inline void SetAxesEnabled( bool aAxesEnabled )
951     {
952         m_axesEnabled = aAxesEnabled;
953     }
954 
955     /**
956      * Draw every tick line wider.
957      *
958      * @param aInterval increase the width of every aInterval line, if 0 do not use this feature.
959      */
SetCoarseGrid(int aInterval)960     inline void SetCoarseGrid( int aInterval )
961     {
962         m_gridTick = aInterval;
963     }
964 
965     /**
966      * Get the grid line width.
967      *
968      * @return the grid line width
969      */
GetGridLineWidth()970     inline float GetGridLineWidth() const
971     {
972         return m_gridLineWidth;
973     }
974 
975     ///< Draw the grid
DrawGrid()976     virtual void DrawGrid() {};
977 
978     /**
979      * For a given point it returns the nearest point belonging to the grid in world coordinates.
980      *
981      * @param aPoint is the point for which the grid point is searched.
982      * @return The nearest grid point in world coordinates.
983      */
984     VECTOR2D GetGridPoint( const VECTOR2D& aPoint ) const;
985 
986     /**
987      * Compute the point position in world coordinates from given screen coordinates.
988      *
989      * @param aPoint the point position in screen coordinates.
990      * @return the point position in world coordinates.
991      */
ToWorld(const VECTOR2D & aPoint)992     inline VECTOR2D ToWorld( const VECTOR2D& aPoint ) const
993     {
994         return VECTOR2D( m_screenWorldMatrix * aPoint );
995     }
996 
997     /**
998      * Compute the point position in screen coordinates from given world coordinates.
999      *
1000      * @param aPoint the point position in world coordinates.
1001      * @return the point position in screen coordinates.
1002      */
ToScreen(const VECTOR2D & aPoint)1003     inline VECTOR2D ToScreen( const VECTOR2D& aPoint ) const
1004     {
1005         return VECTOR2D( m_worldScreenMatrix * aPoint );
1006     }
1007 
1008     /**
1009      * Set the cursor in the native panel.
1010      *
1011      * @param aCursor is the cursor to use in the native panel
1012      * @return true if the cursor was updated, false if the cursor given was already set
1013      */
1014     virtual bool SetNativeCursorStyle( KICURSOR aCursor );
1015 
1016     /**
1017      * Enable/disable cursor.
1018      *
1019      * @param aCursorEnabled is true if the cursor should be drawn, else false.
1020      */
SetCursorEnabled(bool aCursorEnabled)1021     inline void SetCursorEnabled( bool aCursorEnabled )
1022     {
1023         m_isCursorEnabled = aCursorEnabled;
1024     }
1025 
1026     /**
1027      * Return information about cursor visibility.
1028      *
1029      * @return True if cursor is visible.
1030      */
IsCursorEnabled()1031     bool IsCursorEnabled() const
1032     {
1033         return m_isCursorEnabled || m_forceDisplayCursor;
1034     }
1035 
1036     /**
1037      * Set the cursor color.
1038      *
1039      * @param aCursorColor is the color of the cursor.
1040      */
SetCursorColor(const COLOR4D & aCursorColor)1041     inline void SetCursorColor( const COLOR4D& aCursorColor )
1042     {
1043         m_cursorColor = aCursorColor;
1044     }
1045 
1046     /**
1047      * Draw the cursor.
1048      *
1049      * @param aCursorPosition is the cursor position in screen coordinates.
1050      */
DrawCursor(const VECTOR2D & aCursorPosition)1051     virtual void DrawCursor( const VECTOR2D& aCursorPosition ) {};
1052 
1053     /**
1054      * Change the current depth to deeper, so it is possible to draw objects right beneath
1055      * other.
1056      */
AdvanceDepth()1057     inline void AdvanceDepth()
1058     {
1059         m_layerDepth -= 0.05;
1060     }
1061 
1062     /**
1063      * Store current drawing depth on the depth stack.
1064      */
PushDepth()1065     inline void PushDepth()
1066     {
1067         m_depthStack.push( m_layerDepth );
1068     }
1069 
1070     /**
1071      * Restore previously stored drawing depth for the depth stack.
1072      */
PopDepth()1073     inline void PopDepth()
1074     {
1075         m_layerDepth = m_depthStack.top();
1076         m_depthStack.pop();
1077     }
1078 
1079     virtual void EnableDepthTest( bool aEnabled = false ) {};
1080 
1081     /**
1082      * Checks the state of the context lock
1083      * @return True if the context is currently locked
1084      */
IsContextLocked()1085     virtual bool IsContextLocked()
1086     {
1087         return false;
1088     }
1089 
1090 
1091     /// Use GAL_CONTEXT_LOCKER RAII object unless you know what you're doing.
LockContext(int aClientCookie)1092     virtual void LockContext( int aClientCookie ) {}
1093 
UnlockContext(int aClientCookie)1094     virtual void UnlockContext( int aClientCookie ) {}
1095 
1096     /// Start/end drawing functions, draw calls can be only made in between the calls
1097     /// to BeginDrawing()/EndDrawing(). Normally you should create a GAL_DRAWING_CONTEXT RAII
1098     /// object, but I'm leaving these functions public for more precise (i.e. timing/profiling)
1099     /// control of the drawing process - Tom
1100 
1101     /// Begin the drawing, needs to be called for every new frame.
1102     /// Use GAL_DRAWING_CONTEXT RAII object unless you know what you're doing.
BeginDrawing()1103     virtual void BeginDrawing() {};
1104 
1105     /// End the drawing, needs to be called for every new frame.
1106     /// Use GAL_DRAWING_CONTEXT RAII object unless you know what you're doing.
EndDrawing()1107     virtual void EndDrawing() {};
1108 protected:
1109 
1110     /// Enable item update mode.
1111     /// Private: use GAL_UPDATE_CONTEXT RAII object
beginUpdate()1112     virtual void beginUpdate() {}
1113 
1114     /// Disable item update mode.
endUpdate()1115     virtual void endUpdate() {}
1116 
1117 
1118 
1119     /// Compute the scaling factor for the world->screen matrix
computeWorldScale()1120     inline void computeWorldScale()
1121     {
1122         m_worldScale = m_screenDPI * m_worldUnitLength * m_zoomFactor;
1123     }
1124 
1125     /**
1126      * compute minimum grid spacing from the grid settings
1127      *
1128      * @return the minimum spacing to use for drawing the grid
1129      */
1130     double computeMinGridSpacing() const;
1131 
1132     /// Possible depth range
1133     static const int MIN_DEPTH;
1134     static const int MAX_DEPTH;
1135 
1136     /// Depth level on which the grid is drawn
1137     static const int GRID_DEPTH;
1138 
1139     /**
1140      * Get the actual cursor color to draw
1141      */
1142     COLOR4D getCursorColor() const;
1143 
1144     // ---------------
1145     // Settings observer interface
1146     // ---------------
1147     /**
1148      * Handler for observer settings changes.
1149      */
1150     void OnGalDisplayOptionsChanged( const GAL_DISPLAY_OPTIONS& aOptions ) override;
1151 
1152     /**
1153      * Handle updating display options.
1154      *
1155      * Derived classes should call up to this to set base-class methods.
1156      *
1157      * @return true if the new settings changed something. Derived classes can use this
1158      *         information to refresh themselves
1159      */
1160     virtual bool updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions );
1161 
1162     GAL_DISPLAY_OPTIONS& m_options;
1163     UTIL::LINK           m_observerLink;
1164 
1165     std::stack<double>   m_depthStack;         ///< Stored depth values
1166     VECTOR2I             m_screenSize;         ///< Screen size in screen coordinates
1167 
1168     double               m_worldUnitLength;    ///< The unit length of the world coordinates [inch]
1169     double               m_screenDPI;          ///< The dots per inch of the screen
1170     VECTOR2D             m_lookAtPoint;        ///< Point to be looked at in world space
1171 
1172     double               m_zoomFactor;         ///< The zoom factor
1173     double               m_rotation;           ///< Rotation transformation (radians)
1174     MATRIX3x3D           m_worldScreenMatrix;  ///< World transformation
1175     MATRIX3x3D           m_screenWorldMatrix;  ///< Screen transformation
1176     double               m_worldScale;         ///< The scale factor world->screen
1177 
1178     bool                 m_globalFlipX;        ///< Flag for X axis flipping
1179     bool                 m_globalFlipY;        ///< Flag for Y axis flipping
1180 
1181     float                m_lineWidth;          ///< The line width
1182 
1183     bool                 m_isFillEnabled;      ///< Is filling of graphic objects enabled ?
1184     bool                 m_isStrokeEnabled;    ///< Are the outlines stroked ?
1185 
1186     COLOR4D              m_fillColor;          ///< The fill color
1187     COLOR4D              m_strokeColor;        ///< The color of the outlines
1188     COLOR4D              m_clearColor;
1189 
1190     double               m_layerDepth;         ///< The actual layer depth
1191     VECTOR2D             m_depthRange;         ///< Range of the depth
1192 
1193     // Grid settings
1194     bool                 m_gridVisibility;     ///< Should the grid be shown
1195     GRID_STYLE           m_gridStyle;          ///< Grid display style
1196     VECTOR2D             m_gridSize;           ///< The grid size
1197     VECTOR2D             m_gridOrigin;         ///< The grid origin
1198     VECTOR2D             m_gridOffset;         ///< The grid offset to compensate cursor position
1199     COLOR4D              m_gridColor;          ///< Color of the grid
1200     COLOR4D              m_axesColor;          ///< Color of the axes
1201     bool                 m_axesEnabled;        ///< Should the axes be drawn
1202     int                  m_gridTick;           ///< Every tick line gets the double width
1203     float                m_gridLineWidth;      ///< Line width of the grid
1204     int                  m_gridMinSpacing;     ///< Minimum screen size of the grid (pixels)
1205                                                ///< below which the grid is not drawn
1206 
1207     // Cursor settings
1208     bool                 m_isCursorEnabled;    ///< Is the cursor enabled?
1209     bool                 m_forceDisplayCursor; ///< Always show cursor
1210     COLOR4D              m_cursorColor;        ///< Cursor color
1211     bool                 m_fullscreenCursor;   ///< Shape of the cursor (fullscreen or small cross)
1212     VECTOR2D             m_cursorPosition;     ///< Current cursor position (world coordinates)
1213 
1214     STROKE_FONT          m_strokeFont;         ///< Instance of object that stores information
1215                                                ///< about how to draw texts
1216 
1217     KICURSOR             m_currentNativeCursor; ///< Current cursor
1218 
1219 private:
1220     struct TEXT_PROPERTIES
1221     {
1222         VECTOR2D            m_glyphSize;            ///< Size of the glyphs
1223         EDA_TEXT_HJUSTIFY_T m_horizontalJustify;    ///< Horizontal justification
1224         EDA_TEXT_VJUSTIFY_T m_verticalJustify;      ///< Vertical justification
1225         bool                m_bold;
1226         bool                m_italic;
1227         bool                m_underlined;
1228         bool                m_mirrored;
1229     } textProperties;
1230 };
1231 
1232 
1233 class GAL_CONTEXT_LOCKER
1234 {
1235 public:
GAL_CONTEXT_LOCKER(GAL * aGal)1236     GAL_CONTEXT_LOCKER( GAL* aGal ) :
1237         m_gal( aGal )
1238     {
1239         m_cookie = rand();
1240         m_gal->LockContext( m_cookie );
1241     }
1242 
~GAL_CONTEXT_LOCKER()1243     ~GAL_CONTEXT_LOCKER()
1244     {
1245         m_gal->UnlockContext( m_cookie );
1246     }
1247 
1248 protected:
1249     GAL* m_gal;
1250     int  m_cookie;
1251 };
1252 
1253 
1254 class GAL_UPDATE_CONTEXT : public GAL_CONTEXT_LOCKER
1255 {
1256 public:
GAL_UPDATE_CONTEXT(GAL * aGal)1257     GAL_UPDATE_CONTEXT( GAL* aGal ) :
1258             GAL_CONTEXT_LOCKER( aGal )
1259     {
1260         m_gal->beginUpdate();
1261     }
1262 
~GAL_UPDATE_CONTEXT()1263     ~GAL_UPDATE_CONTEXT()
1264     {
1265         m_gal->endUpdate();
1266     }
1267 };
1268 
1269 
1270 class GAL_DRAWING_CONTEXT : public GAL_CONTEXT_LOCKER
1271 {
1272 public:
GAL_DRAWING_CONTEXT(GAL * aGal)1273     GAL_DRAWING_CONTEXT( GAL* aGal ) :
1274             GAL_CONTEXT_LOCKER( aGal )
1275     {
1276         m_gal->BeginDrawing();
1277     }
1278 
~GAL_DRAWING_CONTEXT()1279     ~GAL_DRAWING_CONTEXT()
1280     {
1281         m_gal->EndDrawing();
1282     }
1283 };
1284 
1285 
1286 };    // namespace KIGFX
1287 
1288 #endif /* GRAPHICSABSTRACTIONLAYER_H_ */
1289