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.

This commit is contained in:
jean-pierre charras 2016-03-25 09:26:11 +01:00
parent b7a60fb38e
commit 92ce9c1193
9 changed files with 415 additions and 293 deletions

View File

@ -38,6 +38,7 @@ add_custom_target(
set( GAL_SRCS set( GAL_SRCS
# Common part # Common part
basic_gal.cpp
draw_panel_gal.cpp draw_panel_gal.cpp
painter.cpp painter.cpp
newstroke_font.cpp newstroke_font.cpp

131
common/basic_gal.cpp Normal file
View File

@ -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 <gr_basic.h>
#include <plot_common.h>
#include <trigo.h>
#include <basic_gal.h>
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<VECTOR2D>& aPointList )
{
if( aPointList.empty() )
return;
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
std::vector <wxPoint> 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 );
}
}

View File

@ -39,230 +39,7 @@
#include <class_drawpanel.h> #include <class_drawpanel.h>
#include <class_base_screen.h> #include <class_base_screen.h>
#include <gal/stroke_font.h> #include <basic_gal.h>
#include <gal/graphics_abstraction_layer.h>
#include <newstroke_font.h>
#include <plot_common.h>
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 <TRANSFORM_PRM> 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<VECTOR2D>& 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<VECTOR2D>& aPointList )
{
if( aPointList.empty() )
return;
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
std::vector <wxPoint> 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;
/** /**
* Function GetPensizeForBold * Function GetPensizeForBold
@ -469,45 +246,10 @@ void PLOTTER::Text( const wxPoint& aPos,
if( aColor >= 0 ) if( aColor >= 0 )
SetColor( aColor ); SetColor( aColor );
if( aMultilineAllowed ) DrawGraphicText( NULL, NULL, aPos, aColor, aText,
{ aOrient, aSize,
// EDA_TEXT needs for calculations of the position of every aH_justify, aV_justify,
// line according to orientation and justifications textPensize, aItalic, aBold, NULL, this );
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<wxPoint> 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 );
}
if( aWidth != textPensize ) if( aWidth != textPensize )
SetCurrentLineWidth( aWidth ); SetCurrentLineWidth( aWidth );

View File

@ -33,6 +33,8 @@
#include <trigo.h> // RotatePoint #include <trigo.h> // RotatePoint
#include <class_drawpanel.h> // EDA_DRAW_PANEL #include <class_drawpanel.h> // EDA_DRAW_PANEL
#include <basic_gal.h>
// Conversion to application internal units defined at build time. // Conversion to application internal units defined at build time.
#if defined( PCBNEW ) #if defined( PCBNEW )
#include <class_board_item.h> // for FMT_IU #include <class_board_item.h> // for FMT_IU
@ -46,8 +48,6 @@
#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW." #error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
#endif #endif
#include <gal/stroke_font.h>
#include <convert_to_biu.h> #include <convert_to_biu.h>
EDA_TEXT::EDA_TEXT( const wxString& text ) EDA_TEXT::EDA_TEXT( const wxString& text )
@ -90,7 +90,13 @@ EDA_TEXT::~EDA_TEXT()
int EDA_TEXT::LenSize( const wxString& aLine ) const 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 EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
{ {
EDA_RECT rect; EDA_RECT rect;
wxPoint pos;
wxArrayString strings; wxArrayString strings;
wxString text = GetShownText(); wxString text = GetShownText();
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; 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 // calculate the H and V size
int dx = LenSize( text ); int dx = KiROUND( basic_gal.GetStrokeFont().ComputeStringBoundaryLimits(
int dy = GetInterline( thickness ); 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 ); wxSize textsize = wxSize( dx, dy );
wxPoint pos = m_Pos;
if( aInvertY ) if( aInvertY )
rect.SetOrigin( m_Pos.x, -m_Pos.y ); pos.x = -pos.y;
else
rect.SetOrigin( m_Pos ); rect.SetOrigin( pos );
// The bbox vertical size returned by GetInterline( aThickness ) // The bbox vertical size returned by GetInterline( aThickness )
// includes letters like j and y and ] + interval between lines. // 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 // The interval below the last line is not usefull, and we can use its half value
// as vertical margin above the text // as vertical margin above the text
// the full interval is roughly m_Size.y * 0.4 - aThickness/2 // 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 ) if( hasOverBar )
{ { // A overbar adds an extra size to the text
// 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; // Height from the base line text of chars like [ or { double curr_height = m_Size.y * 1.15;
int extra_height = KiROUND( 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; textsize.y += extra_height;
rect.Move( wxPoint( 0, -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++ ) for( unsigned ii = 1; ii < strings.GetCount(); ii++ )
{ {
text = strings.Item( 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.x = std::max( textsize.x, dx );
textsize.y += dy; textsize.y += dy;
} }

View File

@ -97,11 +97,20 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe
} }
else else
{ {
// Every coordinate description of the Hershey format has an offset, // In stroke font, coordinates values are coded as <value> + 'R',
// <value> is an ASCII char.
// therefore every coordinate description of the Hershey format has an offset,
// it has to be subtracted // 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; point.x = (double) ( coordinate[0] - 'R' ) * STROKE_FONT_SCALE - glyphStartX;
// -10 is here to keep GAL rendering consistent with the legacy gfx stuff #define FONT_OFFSET -10
point.y = (double) ( coordinate[1] - 'R' - 10) * STROKE_FONT_SCALE; // 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 ); 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. // Static method.
// Compute the Y position of the overbar. This is the distance between // 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 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 ); 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 ) 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 ) if( dd >= (int) m_glyphBoundingBoxes.size() || dd < 0 )
dd = '?' - ' '; 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 // For italic correction, take in account italic tilt
if( m_italic ) if( m_italic )
result.x += result.y * STROKE_FONT::ITALIC_TILT; result.x += result.y * STROKE_FONT::ITALIC_TILT;
if( aTopLimit )
*aTopLimit = ymax * aGlyphSize.y;
if( aBottomLimit )
*aBottomLimit = ymin * aGlyphSize.y;
return result; return result;
} }

View File

@ -46,7 +46,8 @@
extern void IncrementLabelMember( wxString& name, int aIncrement ); 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. */ /* Names of sheet label types. */
const char* SheetLabelType[] = const char* SheetLabelType[] =

162
include/basic_gal.h Normal file
View File

@ -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 <plot_common.h>
#include <gal/stroke_font.h>
#include <gal/graphics_abstraction_layer.h>
#include <newstroke_font.h>
/*
* 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 <TRANSFORM_PRM> 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<VECTOR2D>& 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

View File

@ -269,6 +269,12 @@ public:
// ---- // ----
// Text // Text
// ---- // ----
const STROKE_FONT& GetStrokeFont() const
{
return strokeFont;
}
/** /**
* @brief Draws a vector type text using preloaded Newstroke font. * @brief Draws a vector type text using preloaded Newstroke font.
* *

View File

@ -152,12 +152,32 @@ public:
m_gal = aGal; 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. * Compute the vertical position of an overbar, sometimes used in texts.
* This is the distance between the text base line and the overbar. * This is the distance between the text base line and the overbar.
* @return the relative position of the overbar axis. * @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 * @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 ); static double GetInterline( double aGlyphHeight, double aGlyphThickness );
private: private:
GAL* m_gal; ///< Pointer to the GAL GAL* m_gal; ///< Pointer to the GAL
GLYPH_LIST m_glyphs; ///< Glyph list GLYPH_LIST m_glyphs; ///< Glyph list
std::vector<BOX2D> m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs std::vector<BOX2D> m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs
VECTOR2D m_glyphSize; ///< Size of the glyphs VECTOR2D m_glyphSize; ///< Size of the glyphs
EDA_TEXT_HJUSTIFY_T m_horizontalJustify; ///< Horizontal justification EDA_TEXT_HJUSTIFY_T m_horizontalJustify; ///< Horizontal justification
EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification
bool m_bold, m_italic, m_mirrored, m_overbar; ///< Properties of text 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 * @brief Compute the X and Y size of a given text. The text is expected to be