From 92ce9c1193f79f5968fde2067a90c992c0972a6d Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 25 Mar 2016 09:26:11 +0100 Subject: [PATCH] Rework on class EDA_TEXT and related classes and draw text functions. More work: remove useless or duplicate code (from legacy graphic text plot functions). Move basic_gal code to separate files. --- common/CMakeLists.txt | 1 + common/basic_gal.cpp | 131 +++++++++++ common/drawtxt.cpp | 268 +---------------------- common/eda_text.cpp | 43 ++-- common/gal/stroke_font.cpp | 53 ++++- eeschema/sch_text.cpp | 3 +- include/basic_gal.h | 162 ++++++++++++++ include/gal/graphics_abstraction_layer.h | 6 + include/gal/stroke_font.h | 41 +++- 9 files changed, 415 insertions(+), 293 deletions(-) create mode 100644 common/basic_gal.cpp create mode 100644 include/basic_gal.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index dae7441c0f..74fe696323 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -38,6 +38,7 @@ add_custom_target( set( GAL_SRCS # Common part + basic_gal.cpp draw_panel_gal.cpp painter.cpp newstroke_font.cpp diff --git a/common/basic_gal.cpp b/common/basic_gal.cpp new file mode 100644 index 0000000000..3e538125b4 --- /dev/null +++ b/common/basic_gal.cpp @@ -0,0 +1,131 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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 + */ + +/** + * @brief Implement a very basic GAL used to draw, plot and convert texts in segments + * for DRC funstions, using the common GAL functions. + * Draw functions use wxDC. + * Plot functions use a PLOTTER + * Convert texts in segments use a callback function created by the caller + * @file basic_gal.cpp + */ + +#include +#include +#include + +#include + +using namespace KIGFX; + +BASIC_GAL basic_gal; + +const VECTOR2D BASIC_GAL::transform( const VECTOR2D& aPoint ) const +{ + VECTOR2D point = aPoint + m_transform.m_moveOffset - m_transform.m_rotCenter; + point = point.Rotate( m_transform.m_rotAngle ) + m_transform.m_rotCenter; + return point; +} + +void BASIC_GAL::DrawPolyline( const std::deque& aPointList ) +{ + if( aPointList.empty() ) + return; + + std::deque::const_iterator it = aPointList.begin(); + std::vector polyline_corners; + + for( ; it != aPointList.end(); ++it ) + { + VECTOR2D corner = transform(*it); + polyline_corners.push_back( wxPoint( corner.x, corner.y ) ); + } + + if( m_DC ) + { + if( isFillEnabled ) + { + GRPoly( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners.size(), + &polyline_corners[0], 0, GetLineWidth(), m_Color, m_Color ); + } + else + { + for( unsigned ii = 1; ii < polyline_corners.size(); ++ii ) + { + GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners[ii-1], + polyline_corners[ii], GetLineWidth(), m_Color ); + } + } + } + else if( m_plotter ) + { + m_plotter->MoveTo( polyline_corners[0] ); + + for( unsigned ii = 1; ii < polyline_corners.size(); ii++ ) + { + m_plotter->LineTo( polyline_corners[ii] ); + } + + m_plotter->PenFinish(); + } + else if( m_callback ) + { + for( unsigned ii = 1; ii < polyline_corners.size(); ii++ ) + { + m_callback( polyline_corners[ii-1].x, polyline_corners[ii-1].y, + polyline_corners[ii].x, polyline_corners[ii].y ); + } + } +} + +void BASIC_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) +{ + VECTOR2D startVector = transform( aStartPoint ); + VECTOR2D endVector = transform( aEndPoint ); + + if( m_DC ) + { + if( isFillEnabled ) + { + GRLine( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y, + endVector.x, endVector.y, GetLineWidth(), m_Color ); + } + else + { + GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y, + endVector.x, endVector.y, GetLineWidth(), 0, m_Color ); + } + } + else if( m_plotter ) + { + m_plotter->MoveTo( wxPoint( startVector.x, startVector.y ) ); + m_plotter->LineTo( wxPoint( endVector.x, endVector.y ) ); + m_plotter->PenFinish(); + } + else if( m_callback ) + { + m_callback( startVector.x, startVector.y, + endVector.x, endVector.y ); + } +} diff --git a/common/drawtxt.cpp b/common/drawtxt.cpp index 0114eb3724..080181cc61 100644 --- a/common/drawtxt.cpp +++ b/common/drawtxt.cpp @@ -39,230 +39,7 @@ #include #include -#include - -#include -#include - -#include - -using namespace KIGFX; - -/* - * class BASIC_GAL is a minimal GAL implementation to draw, plot and convert - * stroke texts to a set of segments for DRC tests. - * Currently it allows to use GAL and STROKE_FONT methods in legacy draw mode - * (using wxDC functions) in plot functions only for texts. - * - * The main purpose is to avoid duplicate code to do the same thing in GAL canvas - * legacy canvas, plotter canvas and DRC. - * - * It will be certainly removed when a full GAL canvas using wxDC is implemented - * (or at least restricted to plotter and DRC "canvas") - */ - -struct TRANSFORM_PRM // A helper class to transfort coordinates in BASIC_GAL canvas -{ - VECTOR2D m_rotCenter; - VECTOR2D m_moveOffset; - double m_rotAngle; -}; - -class BASIC_GAL: public GAL -{ -public: - wxDC* m_DC; - EDA_COLOR_T m_Color; - -private: - TRANSFORM_PRM m_transform; - std::stack m_transformHistory; - -public: - BASIC_GAL() - { - m_DC = NULL; - m_Color = RED; - m_plotter = NULL; - m_callback = NULL; - } - - void SetPlotter( PLOTTER* aPlotter ) - { - m_plotter = aPlotter; - } - - void SetCallback( void (* aCallback)( int x0, int y0, int xf, int yf ) ) - { - m_callback = aCallback; - } - - /// Set a clip box for drawings - /// If NULL, no clip will be made - void SetClipBox( EDA_RECT* aClipBox ) - { - m_isClipped = aClipBox != NULL; - - if( aClipBox ) - m_clipBox = *aClipBox; - } - - /// @brief Save the context. - virtual void Save() - { - m_transformHistory.push( m_transform ); - } - - virtual void Restore() - { - m_transform = m_transformHistory.top(); - m_transformHistory.pop(); - } - - - /** - * @brief Draw a polyline - * @param aPointList is a list of 2D-Vectors containing the polyline points. - */ - virtual void DrawPolyline( const std::deque& aPointList ); - - /** 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 Translate the context. - * - * @param aTranslation is the translation vector. - */ - virtual void Translate( const VECTOR2D& aTranslation ) - { - m_transform.m_moveOffset += aTranslation; - } - - /** - * @brief Rotate the context. - * - * @param aAngle is the rotation angle in radians. - */ - virtual void Rotate( double aAngle ) - { - m_transform.m_rotAngle = aAngle * M_PI/1800; - m_transform.m_rotCenter = m_transform.m_moveOffset; - } - -private: - // Apply the roation/translation transform to aPoint - const VECTOR2D transform( const VECTOR2D& aPoint ) const; - - // A clip box, to clip drawings in a wxDC (mandatory to avoid draw issues) - EDA_RECT m_clipBox; // The clip box - bool m_isClipped; // Allows/disallows clipping - - // When calling the draw functions outside a wxDC, to get the basic drawings - // lines / polylines ..., a callback function (used in DRC) to store - // coordinates of each segment: - void (* m_callback)( int x0, int y0, int xf, int yf ); - - // When calling the draw functions for plot, the plotter acts as a wxDC - // to plot basic items - PLOTTER* m_plotter; -}; - - -const VECTOR2D BASIC_GAL::transform( const VECTOR2D& aPoint ) const -{ - VECTOR2D point = aPoint + m_transform.m_moveOffset - m_transform.m_rotCenter; - point = point.Rotate( m_transform.m_rotAngle ) + m_transform.m_rotCenter; - return point; -} - -void BASIC_GAL::DrawPolyline( const std::deque& aPointList ) -{ - if( aPointList.empty() ) - return; - - std::deque::const_iterator it = aPointList.begin(); - std::vector polyline_corners; - - for( ; it != aPointList.end(); ++it ) - { - VECTOR2D corner = transform(*it); - polyline_corners.push_back( wxPoint( corner.x, corner.y ) ); - } - - if( m_DC ) - { - if( isFillEnabled ) - { - GRPoly( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners.size(), - &polyline_corners[0], 0, GetLineWidth(), m_Color, m_Color ); - } - else - { - for( unsigned ii = 1; ii < polyline_corners.size(); ++ii ) - { - GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners[ii-1], - polyline_corners[ii], GetLineWidth(), m_Color ); - } - } - } - else if( m_plotter ) - { - m_plotter->MoveTo( polyline_corners[0] ); - - for( unsigned ii = 1; ii < polyline_corners.size(); ii++ ) - { - m_plotter->LineTo( polyline_corners[ii] ); - } - - m_plotter->PenFinish(); - } - else if( m_callback ) - { - for( unsigned ii = 1; ii < polyline_corners.size(); ii++ ) - { - m_callback( polyline_corners[ii-1].x, polyline_corners[ii-1].y, - polyline_corners[ii].x, polyline_corners[ii].y ); - } - } -} - -void BASIC_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) -{ - VECTOR2D startVector = transform( aStartPoint ); - VECTOR2D endVector = transform( aEndPoint ); - - if( m_DC ) - { - if( isFillEnabled ) - { - GRLine( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y, - endVector.x, endVector.y, GetLineWidth(), m_Color ); - } - else - { - GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y, - endVector.x, endVector.y, GetLineWidth(), 0, m_Color ); - } - } - else if( m_plotter ) - { - m_plotter->MoveTo( wxPoint( startVector.x, startVector.y ) ); - m_plotter->LineTo( wxPoint( endVector.x, endVector.y ) ); - m_plotter->PenFinish(); - } - else if( m_callback ) - { - m_callback( startVector.x, startVector.y, - endVector.x, endVector.y ); - } -} - - -BASIC_GAL basic_gal; +#include /** * Function GetPensizeForBold @@ -469,45 +246,10 @@ void PLOTTER::Text( const wxPoint& aPos, if( aColor >= 0 ) SetColor( aColor ); - if( aMultilineAllowed ) - { - // EDA_TEXT needs for calculations of the position of every - // line according to orientation and justifications - wxArrayString strings; - EDA_TEXT* multilineText = new EDA_TEXT( aText ); - multilineText->SetSize( aSize ); - multilineText->SetTextPosition( aPos ); - multilineText->SetOrientation( aOrient ); - multilineText->SetHorizJustify( aH_justify ); - multilineText->SetVertJustify( aV_justify ); - multilineText->SetThickness( aWidth ); - multilineText->SetMultilineAllowed( aMultilineAllowed ); - - std::vector positions; - wxStringSplit( aText, strings, '\n' ); - positions.reserve( strings.Count() ); - - multilineText->GetPositionsOfLinesOfMultilineText( - positions, strings.Count() ); - - for( unsigned ii = 0; ii < strings.Count(); ii++ ) - { - wxString& txt = strings.Item( ii ); - DrawGraphicText( NULL, NULL, positions[ii], aColor, txt, - aOrient, aSize, - aH_justify, aV_justify, - textPensize, aItalic, aBold, NULL, this ); - } - - delete multilineText; - } - else - { - DrawGraphicText( NULL, NULL, aPos, aColor, aText, - aOrient, aSize, - aH_justify, aV_justify, - textPensize, aItalic, aBold, NULL, this ); - } + DrawGraphicText( NULL, NULL, aPos, aColor, aText, + aOrient, aSize, + aH_justify, aV_justify, + textPensize, aItalic, aBold, NULL, this ); if( aWidth != textPensize ) SetCurrentLineWidth( aWidth ); diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 4d1bf0ce16..f6c3c52635 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -33,6 +33,8 @@ #include // RotatePoint #include // EDA_DRAW_PANEL +#include + // Conversion to application internal units defined at build time. #if defined( PCBNEW ) #include // for FMT_IU @@ -46,8 +48,6 @@ #error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW." #endif -#include - #include EDA_TEXT::EDA_TEXT( const wxString& text ) @@ -90,7 +90,13 @@ EDA_TEXT::~EDA_TEXT() int EDA_TEXT::LenSize( const wxString& aLine ) const { - return GraphicTextWidth( aLine, m_Size, m_Italic, m_Bold ); + basic_gal.SetItalic( m_Italic ); + basic_gal.SetBold( m_Bold ); + basic_gal.SetGlyphSize( VECTOR2D( m_Size ) ); + + VECTOR2D tsize = basic_gal.GetTextLineSize( aLine ); + + return KiROUND( tsize.x ); } @@ -123,7 +129,6 @@ int EDA_TEXT::GetInterline( int aTextThickness ) const EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const { EDA_RECT rect; - wxPoint pos; wxArrayString strings; wxString text = GetShownText(); int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; @@ -157,30 +162,35 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const } // calculate the H and V size - int dx = LenSize( text ); - int dy = GetInterline( thickness ); + int dx = KiROUND( basic_gal.GetStrokeFont().ComputeStringBoundaryLimits( + text, VECTOR2D( m_Size ), double( thickness ) ).x ); + int dy = GetInterline( thickness ); - // Creates bounding box (rectangle) for an horizontal text + // Creates bounding box (rectangle) for an horizontal + // and left and top justified text. the bounding box will be moved later + // according to the catual text options wxSize textsize = wxSize( dx, dy ); + wxPoint pos = m_Pos; if( aInvertY ) - rect.SetOrigin( m_Pos.x, -m_Pos.y ); - else - rect.SetOrigin( m_Pos ); + pos.x = -pos.y; + + rect.SetOrigin( pos ); // The bbox vertical size returned by GetInterline( aThickness ) // includes letters like j and y and ] + interval between lines. // The interval below the last line is not usefull, and we can use its half value // as vertical margin above the text // the full interval is roughly m_Size.y * 0.4 - aThickness/2 - rect.Move( wxPoint( 0, thickness/4 - KiROUND( m_Size.y * 0.2 ) ) ); + rect.Move( wxPoint( 0, thickness/4 - KiROUND( m_Size.y * 0.22 ) ) ); if( hasOverBar ) - { - // A overbar adds an extra size to the text - double curr_height = m_Size.y * 1.15; // Height from the base line text of chars like [ or { + { // A overbar adds an extra size to the text + // Height from the base line text of chars like [ or { + double curr_height = m_Size.y * 1.15; int extra_height = KiROUND( - KIGFX::STROKE_FONT::ComputeOverbarVerticalPosition( m_Size.y, thickness ) - curr_height ); + basic_gal.GetStrokeFont().ComputeOverbarVerticalPosition( m_Size.y, thickness ) - curr_height ); + extra_height += thickness/2; textsize.y += extra_height; rect.Move( wxPoint( 0, -extra_height ) ); } @@ -192,7 +202,8 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const for( unsigned ii = 1; ii < strings.GetCount(); ii++ ) { text = strings.Item( ii ); - dx = LenSize( text ); + dx = KiROUND( basic_gal.GetStrokeFont().ComputeStringBoundaryLimits( + text, VECTOR2D( m_Size ), double( thickness ) ).x ); textsize.x = std::max( textsize.x, dx ); textsize.y += dy; } diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index d490ccb28c..6bb8360885 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -97,11 +97,20 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe } else { - // Every coordinate description of the Hershey format has an offset, + // In stroke font, coordinates values are coded as + 'R', + // is an ASCII char. + // therefore every coordinate description of the Hershey format has an offset, // it has to be subtracted + // Note: + // * the stroke coordinates are stored in reduced form (-1.0 to +1.0), + // and the actual size is stroke coordinate * glyph size + // * a few shapes have a height slightly bigger than 1.0 ( like '{' '[' ) point.x = (double) ( coordinate[0] - 'R' ) * STROKE_FONT_SCALE - glyphStartX; - // -10 is here to keep GAL rendering consistent with the legacy gfx stuff - point.y = (double) ( coordinate[1] - 'R' - 10) * STROKE_FONT_SCALE; + #define FONT_OFFSET -10 + // FONT_OFFSET is here for historical reasons, due to the way the stroke font + // was built. It allows shapes coordinates like W M ... to be >= 0 + // Only shapes like j y have coordinates < 0 + point.y = (double) ( coordinate[1] - 'R' + FONT_OFFSET ) * STROKE_FONT_SCALE; pointList.push_back( point ); } @@ -371,7 +380,7 @@ void STROKE_FONT::drawSingleLineText( const UTF8& aText ) } -double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) +double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const { // Static method. // Compute the Y position of the overbar. This is the distance between @@ -389,8 +398,18 @@ double STROKE_FONT::computeOverbarVerticalPosition() const VECTOR2D STROKE_FONT::computeTextLineSize( const UTF8& aText ) const +{ + return ComputeStringBoundaryLimits( aText, m_glyphSize, m_gal->GetLineWidth() ); +} + + +VECTOR2D STROKE_FONT::ComputeStringBoundaryLimits( const UTF8& aText, VECTOR2D aGlyphSize, + double aGlyphThickness, + double* aTopLimit, double* aBottomLimit ) const { VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y ); + double ymax = 0.0; + double ymin = 0.0; for( UTF8::uni_iter it = aText.ubegin(), end = aText.uend(); it < end; ++it ) { @@ -411,12 +430,36 @@ VECTOR2D STROKE_FONT::computeTextLineSize( const UTF8& aText ) const if( dd >= (int) m_glyphBoundingBoxes.size() || dd < 0 ) dd = '?' - ' '; - result.x += m_glyphSize.x * m_glyphBoundingBoxes[dd].GetEnd().x; + const BOX2D& box = m_glyphBoundingBoxes[dd]; + + result.x += box.GetEnd().x; + + // Calculate Y min and Y max + if( aTopLimit ) + { + ymax = std::max( ymax, box.GetY() ); + ymax = std::max( ymax, box.GetEnd().y ); + } + + if( aBottomLimit ) + { + ymin = std::min( ymin, box.GetY() ); + ymin = std::min( ymin, box.GetEnd().y ); + } } + result.x *= aGlyphSize.x; + result.x += aGlyphThickness; + // For italic correction, take in account italic tilt if( m_italic ) result.x += result.y * STROKE_FONT::ITALIC_TILT; + if( aTopLimit ) + *aTopLimit = ymax * aGlyphSize.y; + + if( aBottomLimit ) + *aBottomLimit = ymin * aGlyphSize.y; + return result; } diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index 4f8fd8444f..73d7840fdf 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -46,7 +46,8 @@ extern void IncrementLabelMember( wxString& name, int aIncrement ); -#define DRAW_BBOX 0 // Only for tests: set to 1 to draw the bounding box of labels +// Only for tests: set DRAW_BBOX to 1 to draw the bounding box of labels +#define DRAW_BBOX 0 /* Names of sheet label types. */ const char* SheetLabelType[] = diff --git a/include/basic_gal.h b/include/basic_gal.h new file mode 100644 index 0000000000..f282cfff0b --- /dev/null +++ b/include/basic_gal.h @@ -0,0 +1,162 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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 BASIC_GAL_H +#define BASIC_GAL_H + +#include + +#include +#include +#include + +/* + * class BASIC_GAL is a minimal GAL implementation to draw, plot and convert + * stroke texts to a set of segments for DRC tests, and to calculate text sizes. + * + * Currently it allows to use GAL and STROKE_FONT methods in legacy draw mode + * (using wxDC functions) in plot functions only for texts. + * It is used also to calculate the text bounding boxes + * + * The main purpose is to avoid duplicate code to do the same thing in GAL canvas + * legacy canvas, plotter canvas and DRC. + * + * It will be certainly removed when a full GAL canvas using wxDC is implemented + * (or at least restricted to plotter and DRC "canvas") + */ + +struct TRANSFORM_PRM // A helper class to transform coordinates in BASIC_GAL canvas +{ + VECTOR2D m_rotCenter; + VECTOR2D m_moveOffset; + double m_rotAngle; +}; + +class BASIC_GAL: public KIGFX::GAL +{ +public: + wxDC* m_DC; + EDA_COLOR_T m_Color; + +private: + TRANSFORM_PRM m_transform; + std::stack m_transformHistory; + +public: + BASIC_GAL() + { + m_DC = NULL; + m_Color = RED; + m_plotter = NULL; + m_callback = NULL; + } + + void SetPlotter( PLOTTER* aPlotter ) + { + m_plotter = aPlotter; + } + + void SetCallback( void (* aCallback)( int x0, int y0, int xf, int yf ) ) + { + m_callback = aCallback; + } + + /// Set a clip box for drawings + /// If NULL, no clip will be made + void SetClipBox( EDA_RECT* aClipBox ) + { + m_isClipped = aClipBox != NULL; + + if( aClipBox ) + m_clipBox = *aClipBox; + } + + /// @brief Save the context. + virtual void Save() + { + m_transformHistory.push( m_transform ); + } + + virtual void Restore() + { + m_transform = m_transformHistory.top(); + m_transformHistory.pop(); + } + + + /** + * @brief Draw a polyline + * @param aPointList is a list of 2D-Vectors containing the polyline points. + */ + virtual void DrawPolyline( const std::deque& aPointList ); + + /** 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 Translate the context. + * + * @param aTranslation is the translation vector. + */ + virtual void Translate( const VECTOR2D& aTranslation ) + { + m_transform.m_moveOffset += aTranslation; + } + + /** + * @brief Rotate the context. + * + * @param aAngle is the rotation angle in radians. + */ + virtual void Rotate( double aAngle ) + { + m_transform.m_rotAngle = aAngle * M_PI/1800; + m_transform.m_rotCenter = m_transform.m_moveOffset; + } + +private: + // Apply the roation/translation transform to aPoint + const VECTOR2D transform( const VECTOR2D& aPoint ) const; + + // A clip box, to clip drawings in a wxDC (mandatory to avoid draw issues) + EDA_RECT m_clipBox; // The clip box + bool m_isClipped; // Allows/disallows clipping + + // When calling the draw functions outside a wxDC, to get the basic drawings + // lines / polylines ..., a callback function (used in DRC) to store + // coordinates of each segment: + void (* m_callback)( int x0, int y0, int xf, int yf ); + + // When calling the draw functions for plot, the plotter acts as a wxDC + // to plot basic items + PLOTTER* m_plotter; +}; + + +extern BASIC_GAL basic_gal; + +#endif // define BASIC_GAL_H diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 40611f4006..0046bf4fcb 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -269,6 +269,12 @@ public: // ---- // Text // ---- + + const STROKE_FONT& GetStrokeFont() const + { + return strokeFont; + } + /** * @brief Draws a vector type text using preloaded Newstroke font. * diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index c4fbf96aa9..67319fcc1c 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -152,12 +152,32 @@ public: m_gal = aGal; } + /** + * Compute the boundary limits of aText (the bbox of all shapes). + * The overbar is not taken in account, by ~ are skipped. + * @return a VECTOR2D giving the h size of line, and the V glyph size + * and ( if aTopLimit or aBottomLimit not NULL ) the top and bottom + * limits of the text. + */ + VECTOR2D ComputeStringBoundaryLimits( const UTF8& aText, VECTOR2D aGlyphSize, + double aGlyphThickness, + double* aTopLimit = NULL, double* aBottomLimit = NULL ) const; + + /** + * @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 the text size. + */ + VECTOR2D ComputeTextLineSize( 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. */ - static double ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ); + double ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const; /** * @brief Compute the X and Y size of a given text. The text is expected to be @@ -168,14 +188,19 @@ public: */ static double GetInterline( double aGlyphHeight, double aGlyphThickness ); + + private: - GAL* m_gal; ///< Pointer to the GAL - GLYPH_LIST m_glyphs; ///< Glyph list - std::vector m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs - VECTOR2D m_glyphSize; ///< Size of the glyphs - EDA_TEXT_HJUSTIFY_T m_horizontalJustify; ///< Horizontal justification - EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification - bool m_bold, m_italic, m_mirrored, m_overbar; ///< Properties of text + GAL* m_gal; ///< Pointer to the GAL + GLYPH_LIST m_glyphs; ///< Glyph list + std::vector m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs + VECTOR2D m_glyphSize; ///< Size of the glyphs + EDA_TEXT_HJUSTIFY_T m_horizontalJustify; ///< Horizontal justification + EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification + bool m_bold; + bool m_italic; + bool m_mirrored; + bool m_overbar; ///< Properties of text /** * @brief Compute the X and Y size of a given text. The text is expected to be