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:
parent
b7a60fb38e
commit
92ce9c1193
|
@ -38,6 +38,7 @@ add_custom_target(
|
|||
|
||||
set( GAL_SRCS
|
||||
# Common part
|
||||
basic_gal.cpp
|
||||
draw_panel_gal.cpp
|
||||
painter.cpp
|
||||
newstroke_font.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 <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 );
|
||||
}
|
||||
}
|
|
@ -39,230 +39,7 @@
|
|||
#include <class_drawpanel.h>
|
||||
#include <class_base_screen.h>
|
||||
|
||||
#include <gal/stroke_font.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;
|
||||
#include <basic_gal.h>
|
||||
|
||||
/**
|
||||
* 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<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 );
|
||||
}
|
||||
DrawGraphicText( NULL, NULL, aPos, aColor, aText,
|
||||
aOrient, aSize,
|
||||
aH_justify, aV_justify,
|
||||
textPensize, aItalic, aBold, NULL, this );
|
||||
|
||||
if( aWidth != textPensize )
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <trigo.h> // RotatePoint
|
||||
#include <class_drawpanel.h> // EDA_DRAW_PANEL
|
||||
|
||||
#include <basic_gal.h>
|
||||
|
||||
// Conversion to application internal units defined at build time.
|
||||
#if defined( PCBNEW )
|
||||
#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."
|
||||
#endif
|
||||
|
||||
#include <gal/stroke_font.h>
|
||||
|
||||
#include <convert_to_biu.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 <value> + 'R',
|
||||
// <value> 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;
|
||||
}
|
||||
|
|
|
@ -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[] =
|
||||
|
|
|
@ -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
|
|
@ -269,6 +269,12 @@ public:
|
|||
// ----
|
||||
// Text
|
||||
// ----
|
||||
|
||||
const STROKE_FONT& GetStrokeFont() const
|
||||
{
|
||||
return strokeFont;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draws a vector type text using preloaded Newstroke font.
|
||||
*
|
||||
|
|
|
@ -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<BOX2D> 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<BOX2D> 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
|
||||
|
|
Loading…
Reference in New Issue