/* * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2012 Torsten Hueter, torstenhtr gmx.de * Copyright (C) 2016 Kicad Developers, see change_log.txt for contributors. * * Graphics Abstraction Layer (GAL) - base class * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef GRAPHICSABSTRACTIONLAYER_H_ #define GRAPHICSABSTRACTIONLAYER_H_ #include #include #include #include #include #include #include #include namespace KIGFX { /** * GridStyle: Type definition of the grid style */ enum GRID_STYLE { GRID_STYLE_LINES, ///< Use lines for the grid GRID_STYLE_DOTS ///< Use dots for the grid }; /** * @brief Class GAL is the abstract interface for drawing on a 2D-surface. * * The functions are optimized for drawing shapes of an EDA-program such as KiCad. Most methods * are abstract and need to be implemented by a lower layer, for example by a cairo or OpenGL implementation. *
* Almost all methods use world coordinates as arguments. The board design is defined in world space units; * for drawing purposes these are transformed to screen units with this layer. So zooming is handled here as well. * */ class GAL { public: // Constructor / Destructor GAL(); virtual ~GAL(); /// @brief Returns the initalization status for the canvas. virtual bool IsInitialized() const { return true; } // --------------- // Drawing methods // --------------- /// @brief Begin the drawing, needs to be called for every new frame. virtual void BeginDrawing() {}; /// @brief End the drawing, needs to be called for every new frame. virtual void EndDrawing() {}; /** * @brief Draw a line. * * Start and end points are defined as 2D-Vectors. * * @param aStartPoint is the start point of the line. * @param aEndPoint is the end point of the line. */ virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {}; /** * @brief Draw a rounded segment. * * Start and end points are defined as 2D-Vectors. * * @param aStartPoint is the start point of the segment. * @param aEndPoint is the end point of the segment. * @param aWidth is a width of the segment */ virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ) {}; /** * @brief Draw a polyline * * @param aPointList is a list of 2D-Vectors containing the polyline points. */ virtual void DrawPolyline( const std::deque& aPointList ) {}; virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {}; /** * @brief Draw a circle using world coordinates. * * @param aCenterPoint is the center point of the circle. * @param aRadius is the radius of the circle. */ virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) {}; /** * @brief Draw an arc. * * @param aCenterPoint is the center point of the arc. * @param aRadius is the arc radius. * @param aStartAngle is the start angle of the arc. * @param aEndAngle is the end angle of the arc. */ virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) {}; /** * @brief Draw a rectangle. * * @param aStartPoint is the start point of the rectangle. * @param aEndPoint is the end point of the rectangle. */ virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {}; /** * @brief Draw a polygon. * * @param aPointList is the list of the polygon points. */ virtual void DrawPolygon( const std::deque& aPointList ) {}; virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) {}; /** * @brief Draw a cubic bezier spline. * * @param startPoint is the start point of the spline. * @param controlPointA is the first control point. * @param controlPointB is the second control point. * @param endPoint is the end point of the spline. */ virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA, const VECTOR2D& controlPointB, const VECTOR2D& endPoint ) {}; // -------------- // Screen methods // -------------- /// @brief Resizes the canvas. virtual void ResizeScreen( int aWidth, int aHeight ) {}; /// @brief Shows/hides the GAL canvas virtual bool Show( bool aShow ) { return true; }; /// @brief Returns GAL canvas size in pixels const VECTOR2I& GetScreenPixelSize() const { return screenSize; } /// @brief Force all remaining objects to be drawn. virtual void Flush() {}; /** * @brief Clear the screen. * @param aColor is the color used for clearing. */ virtual void ClearScreen( const COLOR4D& aColor ) {}; // ----------------- // Attribute setting // ----------------- /** * @brief Enable/disable fill. * * @param aIsFillEnabled is true, when the graphics objects should be filled, else false. */ inline virtual void SetIsFill( bool aIsFillEnabled ) { isFillEnabled = aIsFillEnabled; } /** * @brief Enable/disable stroked outlines. * * @param aIsStrokeEnabled is true, if the outline of an object should be stroked. */ inline virtual void SetIsStroke( bool aIsStrokeEnabled ) { isStrokeEnabled = aIsStrokeEnabled; } /** * @brief Set the fill color. * * @param aColor is the color for filling. */ inline virtual void SetFillColor( const COLOR4D& aColor ) { fillColor = aColor; } /** * @brief Set the stroke color. * * @param aColor is the color for stroking the outline. */ inline virtual void SetStrokeColor( const COLOR4D& aColor ) { strokeColor = aColor; } /** * @brief Get the stroke color. * * @return the color for stroking the outline. */ inline const COLOR4D& GetStrokeColor() const { return strokeColor; } /** * @brief Set the line width. * * @param aLineWidth is the line width. */ inline virtual void SetLineWidth( double aLineWidth ) { lineWidth = aLineWidth; } /** * @brief Get the line width. * * @return the actual line width. */ inline double GetLineWidth() const { return lineWidth; } /** * @brief Set the depth of the layer (position on the z-axis) * * @param aLayerDepth the layer depth for the objects. */ inline virtual void SetLayerDepth( double aLayerDepth ) { assert( aLayerDepth <= depthRange.y ); assert( aLayerDepth >= depthRange.x ); layerDepth = aLayerDepth; } // ---- // Text // ---- const STROKE_FONT& GetStrokeFont() const { return strokeFont; } /** * @brief Draws a vector type text using preloaded Newstroke font. * * @param aText is the text to be drawn. * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ inline virtual void StrokeText( const wxString& aText, const VECTOR2D& aPosition, double aRotationAngle ) { strokeFont.Draw( aText, aPosition, aRotationAngle ); } /** * @brief Compute the X and Y size of a given text. The text is expected to be * a only one line text. * * @param aText is the text string (one line). * @return is the text size. */ VECTOR2D GetTextLineSize( const UTF8& aText ) const; /** * Compute the vertical position of an overbar, sometimes used in texts. * This is the distance between the text base line and the overbar. * @return the relative position of the overbar axis. */ double GetOverbarVerticalPosition() const { return strokeFont.computeOverbarVerticalPosition(); } /** * @brief Loads attributes of the given text (bold/italic/underline/mirrored and so on). * * @param aText is the text item. */ virtual void SetTextAttributes( const EDA_TEXT* aText ); /// @copydoc STROKE_FONT::SetGlyphSize() inline void SetGlyphSize( const VECTOR2D aGlyphSize ) { strokeFont.SetGlyphSize( aGlyphSize ); } /// @copydoc STROKE_FONT::SetBold() inline void SetBold( const bool aBold ) { strokeFont.SetBold( aBold ); } /// @copydoc STROKE_FONT::SetItalic() inline void SetItalic( const bool aItalic ) { strokeFont.SetItalic( aItalic ); } /// @copydoc STROKE_FONT::SetMirrored() inline void SetMirrored( const bool aMirrored ) { strokeFont.SetMirrored( aMirrored ); } /// @copydoc STROKE_FONT::SetHorizontalJustify() inline void SetHorizontalJustify( const EDA_TEXT_HJUSTIFY_T aHorizontalJustify ) { strokeFont.SetHorizontalJustify( aHorizontalJustify ); } /// @copydoc STROKE_FONT::SetVerticalJustify() inline void SetVerticalJustify( const EDA_TEXT_VJUSTIFY_T aVerticalJustify ) { strokeFont.SetVerticalJustify( aVerticalJustify ); } // -------------- // Transformation // -------------- /** * @brief Transform the context. * * @param aTransformation is the ransformation matrix. */ virtual void Transform( const MATRIX3x3D& aTransformation ) {}; /** * @brief Rotate the context. * * @param aAngle is the rotation angle in radians. */ virtual void Rotate( double aAngle ) {}; /** * @brief Translate the context. * * @param aTranslation is the translation vector. */ virtual void Translate( const VECTOR2D& aTranslation ) {}; /** * @brief Scale the context. * * @param aScale is the scale factor for the x- and y-axis. */ virtual void Scale( const VECTOR2D& aScale ) {}; /// @brief Save the context. virtual void Save() {}; /// @brief Restore the context. virtual void Restore() {}; // -------------------------------------------- // Group methods // --------------------------------------------- /** * @brief Begin a group. * * A group is a collection of graphic items. * Hierarchical groups are possible, attributes and transformations can be used. * * @return the number of the group. */ virtual int BeginGroup() { return 0; }; /// @brief End the group. virtual void EndGroup() {}; /** * @brief Draw the stored group. * * @param aGroupNumber is the group number. */ virtual void DrawGroup( int aGroupNumber ) {}; /** * @brief Changes the color used to draw the group. * * @param aGroupNumber is the group number. * @param aNewColor is the new color. */ virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor ) {}; /** * @brief Changes the depth (Z-axis position) of the group. * * @param aGroupNumber is the group number. * @param aDepth is the new depth. */ virtual void ChangeGroupDepth( int aGroupNumber, int aDepth ) {}; /** * @brief Delete the group from the memory. * * @param aGroupNumber is the group number. */ virtual void DeleteGroup( int aGroupNumber ) {}; /** * @brief Delete all data created during caching of graphic items. */ virtual void ClearCache() {}; // -------------------------------------------------------- // Handling the world <-> screen transformation // -------------------------------------------------------- /// @brief Compute the world <-> screen transformation matrix virtual void ComputeWorldScreenMatrix(); /** * @brief Get the world <-> screen transformation matrix. * * @return the transformation matrix. */ const MATRIX3x3D& GetWorldScreenMatrix() const { return worldScreenMatrix; } /** * @brief Get the screen <-> world transformation matrix. * * @return the transformation matrix. */ const MATRIX3x3D& GetScreenWorldMatrix() const { return screenWorldMatrix; } /** * @brief Set the world <-> screen transformation matrix. * * @param aMatrix is the 3x3 world <-> screen transformation matrix. */ inline void SetWorldScreenMatrix( const MATRIX3x3D& aMatrix ) { worldScreenMatrix = aMatrix; } /** * @brief Set the unit length. * * This defines the length [inch] per one integer. For instance a value 0.001 means * that the coordinate [1000, 1000] corresponds with a point at (1 inch, 1 inch) or * 1 mil resolution per integer. * * @param aWorldUnitLength is the world Unit length. */ inline void SetWorldUnitLength( double aWorldUnitLength ) { worldUnitLength = aWorldUnitLength; } /** * @brief Set the dots per inch of the screen. * * This value depends on the user screen, it should be configurable by the application. * For instance a typical notebook with HD+ resolution (1600x900) has 106 DPI. * * @param aScreenDPI are the screen DPI. */ inline void SetScreenDPI( double aScreenDPI ) { screenDPI = aScreenDPI; } /** * @brief Set the Point in world space to look at. * * This point corresponds with the center of the actual drawing area. * * @param aPoint is the look at point (center of the actual drawing area). */ inline void SetLookAtPoint( const VECTOR2D& aPoint ) { lookAtPoint = aPoint; } /** * @brief Get the look at point. * * @return the look at point. */ inline const VECTOR2D& GetLookAtPoint() const { return lookAtPoint; } /** * @brief Set the zoom factor of the scene. * * @param aZoomFactor is the zoom factor. */ inline void SetZoomFactor( double aZoomFactor ) { zoomFactor = aZoomFactor; } /** * @brief Get the zoom factor * * @return the zoom factor. */ inline double GetZoomFactor() const { return zoomFactor; } /** * @brief Set the range of the layer depth. * * Usually required for the OpenGL implementation, any object outside this range is not drawn. * * @param aDepthRange is the depth range where component x is the near clipping plane and y * is the far clipping plane. */ inline void SetDepthRange( const VECTOR2D& aDepthRange ) { depthRange = aDepthRange; } /** * @brief Returns the minimum depth in the currently used range (the top). */ inline double GetMinDepth() const { return depthRange.x; } /** * @brief Returns the maximum depth in the currently used range (the bottom). */ inline double GetMaxDepth() const { return depthRange.y; } /** * @brief Get the world scale. * * @return the actual world scale factor. */ inline double GetWorldScale() const { return worldScale; } /** * @brief Sets flipping of the screen. * * @param xAxis is the flip flag for the X axis. * @param yAxis is the flip flag for the Y axis. */ inline void SetFlip( bool xAxis, bool yAxis ) { if( xAxis ) flipX = -1.0; // flipped else flipX = 1.0; // regular if( yAxis ) flipY = -1.0; // flipped else flipY = 1.0; // regular } // --------------------------- // Buffer manipulation methods // --------------------------- /** * @brief Save the screen contents. */ virtual void SaveScreen() {}; /** * @brief Restore the screen contents. */ virtual void RestoreScreen() {}; /** * @brief Sets the target for rendering. * * @param aTarget is the new target for rendering. */ virtual void SetTarget( RENDER_TARGET aTarget ) {}; /** * @brief Gets the currently used target for rendering. * * @return The current rendering target. */ virtual RENDER_TARGET GetTarget() const { return TARGET_CACHED; }; /** * @brief Clears the target for rendering. * * @param aTarget is the target to be cleared. */ virtual void ClearTarget( RENDER_TARGET aTarget ) {}; // ------------- // Grid methods // ------------- /** * @brief Sets the visibility setting of the grid. * * @param aVisibility is the new visibility setting of the grid. */ inline void SetGridVisibility( bool aVisibility ) { gridVisibility = aVisibility; } /** * @brief Set the origin point for the grid. * * @param aGridOrigin is a vector containing the grid origin point, in world coordinates. */ inline void SetGridOrigin( const VECTOR2D& aGridOrigin ) { gridOrigin = aGridOrigin; if( gridSize.x == 0.0 || gridSize.y == 0.0 ) gridOffset = VECTOR2D(0.0, 0.0); else gridOffset = VECTOR2D( (long) gridOrigin.x % (long) gridSize.x, (long) gridOrigin.y % (long) gridSize.y ); } /** * @brief Set the threshold for grid drawing. * * @param aThreshold is the minimum grid cell size (in pixels) for which the grid is drawn. */ inline void SetGridDrawThreshold( int aThreshold ) { gridDrawThreshold = aThreshold; } /** * @brief Set the grid size. * * @param aGridSize is a vector containing the grid size in x and y direction. */ inline void SetGridSize( const VECTOR2D& aGridSize ) { gridSize = aGridSize; gridOffset = VECTOR2D( (long) gridOrigin.x % (long) gridSize.x, (long) gridOrigin.y % (long) gridSize.y ); } /** * @brief Returns the grid size. * * @return A vector containing the grid size in x and y direction. */ inline const VECTOR2D& GetGridSize() const { return gridSize; } /** * @brief Set the grid color. * * @param aGridColor is the grid color, it should have a low alpha value for the best effect. */ inline void SetGridColor( const COLOR4D& aGridColor ) { gridColor = aGridColor; } /** * @brief Draw every tick line wider. * * @param aInterval increase the width of every aInterval line, if 0 do not use this feature. */ inline void SetCoarseGrid( int aInterval ) { gridTick = aInterval; } /** * @brief Get the grid line width. * * @return the grid line width */ inline double GetGridLineWidth() const { return gridLineWidth; } /** * @brief Set the grid line width. * * @param aGridLineWidth is the rid line width. */ inline void SetGridLineWidth( double aGridLineWidth ) { gridLineWidth = aGridLineWidth; } ///> @brief Draw the grid void DrawGrid(); /** * Function GetGridPoint() * For a given point it returns the nearest point belonging to the grid in world coordinates. * * @param aPoint is the point for which the grid point is searched. * @return The nearest grid point in world coordinates. */ VECTOR2D GetGridPoint( const VECTOR2D& aPoint ) const; /** * @brief Change the grid display style. * * @param aGridStyle is the new style for grid. */ inline virtual void SetGridStyle( GRID_STYLE aGridStyle ) { gridStyle = aGridStyle; } /** * @brief Compute the point position in world coordinates from given screen coordinates. * * @param aPoint the pointposition in screen coordinates. * @return the point position in world coordinates. */ inline VECTOR2D ToWorld( const VECTOR2D& aPoint ) const { return VECTOR2D( screenWorldMatrix * aPoint ); } /** * @brief Compute the point position in screen coordinates from given world coordinates. * * @param aPoint the pointposition in world coordinates. * @return the point position in screen coordinates. */ inline VECTOR2D ToScreen( const VECTOR2D& aPoint ) const { return VECTOR2D( worldScreenMatrix * aPoint ); } /** * @brief Enable/disable cursor. * * @param aCursorEnabled is true if the cursor should be drawn, else false. */ inline void SetCursorEnabled( bool aCursorEnabled ) { isCursorEnabled = aCursorEnabled; } /** * @brief Set the cursor color. * * @param aCursorColor is the color of the cursor. */ inline void SetCursorColor( const COLOR4D& aCursorColor ) { cursorColor = aCursorColor; } /** * @brief Returns the cursor size. * * @return The current cursor size (in pixels). */ inline unsigned int GetCursorSize() const { return cursorSize; } /** * @brief Set the cursor size. * * @param aCursorSize is the size of the cursor expressed in pixels. */ virtual inline void SetCursorSize( unsigned int aCursorSize ) { cursorSize = aCursorSize; } /** * @brief Draw the cursor. * * @param aCursorPosition is the cursor position in screen coordinates. */ virtual void DrawCursor( const VECTOR2D& aCursorPosition ) {}; /** * @brief Changes the current depth to deeper, so it is possible to draw objects right beneath * other. */ inline void AdvanceDepth() { layerDepth -= 0.001; } /** * @brief Stores current drawing depth on the depth stack. */ inline void PushDepth() { depthStack.push( layerDepth ); } /** * @brief Restores previously stored drawing depth for the depth stack. */ inline void PopDepth() { layerDepth = depthStack.top(); depthStack.pop(); } static const double METRIC_UNIT_LENGTH; protected: std::stack depthStack; ///< Stored depth values VECTOR2I screenSize; ///< Screen size in screen coordinates double worldUnitLength; ///< The unit length of the world coordinates [inch] double screenDPI; ///< The dots per inch of the screen VECTOR2D lookAtPoint; ///< Point to be looked at in world space double zoomFactor; ///< The zoom factor MATRIX3x3D worldScreenMatrix; ///< World transformation MATRIX3x3D screenWorldMatrix; ///< Screen transformation double worldScale; ///< The scale factor world->screen double flipX; ///< Flag for X axis flipping double flipY; ///< Flag for Y axis flipping double lineWidth; ///< The line width bool isFillEnabled; ///< Is filling of graphic objects enabled ? bool isStrokeEnabled; ///< Are the outlines stroked ? COLOR4D fillColor; ///< The fill color COLOR4D strokeColor; ///< The color of the outlines double layerDepth; ///< The actual layer depth VECTOR2D depthRange; ///< Range of the depth // Grid settings bool gridVisibility; ///< Should the grid be shown GRID_STYLE gridStyle; ///< Grid display style VECTOR2D gridSize; ///< The grid size VECTOR2D gridOrigin; ///< The grid origin VECTOR2D gridOffset; ///< The grid offset to compensate cursor position COLOR4D gridColor; ///< Color of the grid int gridTick; ///< Every tick line gets the double width double gridLineWidth; ///< Line width of the grid int gridDrawThreshold; ///< Minimum screen size of the grid (pixels) ///< below which the grid is not drawn // Cursor settings bool isCursorEnabled; ///< Is the cursor enabled? COLOR4D cursorColor; ///< Cursor color unsigned int cursorSize; ///< Size of the cursor in pixels VECTOR2D cursorPosition; ///< Current cursor position (world coordinates) /// Instance of object that stores information about how to draw texts STROKE_FONT strokeFont; /// Compute the scaling factor for the world->screen matrix inline void ComputeWorldScale() { worldScale = screenDPI * worldUnitLength * zoomFactor; } /** * @brief Draw a grid line (usually a simplified line function). * * @param aStartPoint is the start point of the line. * @param aEndPoint is the end point of the line. */ virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {}; /// Possible depth range static const int MIN_DEPTH; static const int MAX_DEPTH; /// Depth level on which the grid is drawn static const int GRID_DEPTH; }; } // namespace KIGFX #endif /* GRAPHICSABSTRACTIONLAYER_H_ */