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