From 12098fe113418fec44ed1794262cce58e1df97b4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 3 Dec 2013 11:00:52 +0100 Subject: [PATCH 1/6] Fixed non ASCII characters drawing using GAL. --- common/gal/stroke_font.cpp | 14 +++++++------- common/worksheet_viewitem.cpp | 2 +- include/gal/graphics_abstraction_layer.h | 2 +- include/gal/stroke_font.h | 4 ++-- pcbnew/pcb_painter.cpp | 13 ++++++------- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index 2ec1b43a0d..bf4b7a09bc 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -142,7 +142,7 @@ BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLY } -void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRotationAngle ) +void STROKE_FONT::Draw( std::wstring aText, const VECTOR2D& aPosition, double aRotationAngle ) { // By default overbar is turned off m_overbar = false; @@ -156,7 +156,7 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo // Split multiline strings into separate ones and draw them line by line size_t newlinePos = aText.find( '\n' ); - if( newlinePos != std::string::npos ) + if( newlinePos != std::wstring::npos ) { VECTOR2D nextlinePosition = VECTOR2D( 0.0, m_glyphSize.y * LINE_HEIGHT_RATIO ); @@ -233,7 +233,7 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 ); } - for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( std::wstring::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { if( *chIt == '~' ) { @@ -244,7 +244,7 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo GLYPH_LIST::iterator glyphIt = m_glyphs.begin(); std::deque::iterator bbIt = m_glyphBoundingBoxes.begin(); - unsigned dd = (unsigned) ((unsigned char) *chIt ) - (unsigned) ' '; + unsigned dd = *chIt - ' '; if( dd >= m_glyphBoundingBoxes.size() ) dd = '?' - ' '; @@ -292,17 +292,17 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo } -VECTOR2D STROKE_FONT::computeTextSize( const std::string& aText ) const +VECTOR2D STROKE_FONT::computeTextSize( const std::wstring& aText ) const { VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y ); - for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( std::wstring::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { if( *chIt == '~' ) continue; std::deque::const_iterator bbIt = m_glyphBoundingBoxes.begin(); - unsigned dd = (unsigned) ((unsigned char)*chIt) - (unsigned) ' '; + unsigned dd = *chIt - ' '; if( dd >= m_glyphBoundingBoxes.size() ) dd = '?' - ' '; diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp index 5ad38bc46a..7ecf6de8d7 100644 --- a/common/worksheet_viewitem.cpp +++ b/common/worksheet_viewitem.cpp @@ -191,7 +191,7 @@ void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) ); aGal->SetLineWidth( aItem->GetThickness() ); aGal->SetTextAttributes( aItem ); - aGal->StrokeText( std::string( aItem->GetText().mb_str() ), position, 0.0 ); + aGal->StrokeText( std::wstring( aItem->GetText().wc_str() ), position, 0.0 ); } diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index f374979531..e5f35eb191 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -277,7 +277,7 @@ public: * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ - inline virtual void StrokeText( const std::string& aText, const VECTOR2D& aPosition, + inline virtual void StrokeText( const std::wstring& aText, const VECTOR2D& aPosition, double aRotationAngle ) { strokeFont.Draw( aText, aPosition, aRotationAngle ); diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index 50882ee142..5ea5dc4fea 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -73,7 +73,7 @@ public: * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ - void Draw( std::string aText, const VECTOR2D& aPosition, double aRotationAngle ); + void Draw( std::wstring aText, const VECTOR2D& aPosition, double aRotationAngle ); /** * @brief Set the scale factor of the font for the glyph size. @@ -180,7 +180,7 @@ private: * @param aText is the text string. * @return is the text size. */ - VECTOR2D computeTextSize( const std::string& aText ) const; + VECTOR2D computeTextSize( const std::wstring& aText ) const; static const double LINE_HEIGHT_RATIO; }; diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 692f73f5e7..5c06adbb85 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -280,7 +280,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) if( !net ) return; - std::string netName = std::string( net->GetShortNetname().mb_str() ); + std::wstring netName = std::wstring( net->GetShortNetname().wc_str() ); VECTOR2D textPosition = start + line / 2.0; // center of the track double textOrientation = -atan( line.y / line.x ); double textSize = std::min( static_cast( width ), length / netName.length() ); @@ -456,7 +456,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) VECTOR2D namesize( tsize, tsize ); m_gal->SetGlyphSize( namesize ); m_gal->SetLineWidth( namesize.x / 12.0 ); - m_gal->StrokeText( std::string( aPad->GetShortNetname().mb_str() ), + m_gal->StrokeText( std::wstring( aPad->GetShortNetname().wc_str() ), textpos, 0.0 ); } @@ -474,8 +474,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) m_gal->SetGlyphSize( numsize ); m_gal->SetLineWidth( numsize.x / 12.0 ); - m_gal->StrokeText( std::string( aPad->GetPadName().mb_str() ), - textpos, 0.0 ); + m_gal->StrokeText( std::wstring( aPad->GetPadName().wc_str() ), textpos, 0.0 ); } m_gal->Restore(); @@ -720,7 +719,7 @@ void PCB_PAINTER::draw( const TEXTE_PCB* aText, int aLayer ) m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); + m_gal->StrokeText( std::wstring( aText->GetText().wc_str() ), position, orientation ); } @@ -736,7 +735,7 @@ void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer ) m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); + m_gal->StrokeText( std::wstring( aText->GetText().wc_str() ), position, orientation ); } @@ -836,7 +835,7 @@ void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer ) m_gal->SetLineWidth( text.GetThickness() ); m_gal->SetTextAttributes( &text ); - m_gal->StrokeText( std::string( text.GetText().mb_str() ), position, orientation ); + m_gal->StrokeText( std::wstring( text.GetText().wc_str() ), position, orientation ); } From 0a51662c0b9e58d4c5f7838f87b70c15a21a2695 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Dec 2013 16:00:24 +0100 Subject: [PATCH 2/6] Changed std::wstring to wxString. --- common/gal/stroke_font.cpp | 17 +++++++++-------- include/gal/graphics_abstraction_layer.h | 2 +- include/gal/stroke_font.h | 4 ++-- pcbnew/pcb_painter.cpp | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index bf4b7a09bc..15dddf4d86 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -26,6 +26,7 @@ #include #include +#include using namespace KIGFX; @@ -142,7 +143,7 @@ BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLY } -void STROKE_FONT::Draw( std::wstring aText, const VECTOR2D& aPosition, double aRotationAngle ) +void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ) { // By default overbar is turned off m_overbar = false; @@ -154,14 +155,14 @@ void STROKE_FONT::Draw( std::wstring aText, const VECTOR2D& aPosition, double aR m_gal->Rotate( -aRotationAngle ); // Split multiline strings into separate ones and draw them line by line - size_t newlinePos = aText.find( '\n' ); + int newlinePos = aText.Find( '\n' ); - if( newlinePos != std::wstring::npos ) + if( newlinePos != wxNOT_FOUND ) { VECTOR2D nextlinePosition = VECTOR2D( 0.0, m_glyphSize.y * LINE_HEIGHT_RATIO ); - Draw( aText.substr( newlinePos + 1 ), nextlinePosition, 0.0 ); - aText = aText.substr( 0, newlinePos ); + Draw( aText.Mid( newlinePos + 1 ), nextlinePosition, 0.0 ); + aText = aText.Mid( 0, newlinePos ); } // Compute the text size @@ -233,7 +234,7 @@ void STROKE_FONT::Draw( std::wstring aText, const VECTOR2D& aPosition, double aR m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 ); } - for( std::wstring::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { if( *chIt == '~' ) { @@ -292,11 +293,11 @@ void STROKE_FONT::Draw( std::wstring aText, const VECTOR2D& aPosition, double aR } -VECTOR2D STROKE_FONT::computeTextSize( const std::wstring& aText ) const +VECTOR2D STROKE_FONT::computeTextSize( const wxString& aText ) const { VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y ); - for( std::wstring::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { if( *chIt == '~' ) continue; diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index e5f35eb191..7745dfa172 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -277,7 +277,7 @@ public: * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ - inline virtual void StrokeText( const std::wstring& aText, const VECTOR2D& aPosition, + inline virtual void StrokeText( const wxString& aText, const VECTOR2D& aPosition, double aRotationAngle ) { strokeFont.Draw( aText, aPosition, aRotationAngle ); diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index 5ea5dc4fea..5caa4502f9 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -73,7 +73,7 @@ public: * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ - void Draw( std::wstring aText, const VECTOR2D& aPosition, double aRotationAngle ); + void Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ); /** * @brief Set the scale factor of the font for the glyph size. @@ -180,7 +180,7 @@ private: * @param aText is the text string. * @return is the text size. */ - VECTOR2D computeTextSize( const std::wstring& aText ) const; + VECTOR2D computeTextSize( const wxString& aText ) const; static const double LINE_HEIGHT_RATIO; }; diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 5c06adbb85..902c21f991 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -719,7 +719,7 @@ void PCB_PAINTER::draw( const TEXTE_PCB* aText, int aLayer ) m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::wstring( aText->GetText().wc_str() ), position, orientation ); + m_gal->StrokeText( aText->GetText(), position, orientation ); } @@ -735,7 +735,7 @@ void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer ) m_gal->SetStrokeColor( strokeColor ); m_gal->SetLineWidth( aText->GetThickness() ); m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::wstring( aText->GetText().wc_str() ), position, orientation ); + m_gal->StrokeText( aText->GetText(), position, orientation ); } From c04eb822b7a169f91d67fa26bcef3742e1c31b7d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Dec 2013 16:29:54 +0100 Subject: [PATCH 3/6] Glyphs and their bounding boxes are held in vectors instead of deque. Moved scaling of font glyphs to the moment when they are created (eliminated a few multiplications unnecessary variables). Changed some magic numbers into constants. --- common/gal/stroke_font.cpp | 207 ++++++++++++++++++++----------------- include/gal/stroke_font.h | 61 ++++++++--- 2 files changed, 158 insertions(+), 110 deletions(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index 15dddf4d86..47166c81f3 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -30,9 +30,9 @@ using namespace KIGFX; - -const double STROKE_FONT::LINE_HEIGHT_RATIO = 1.6; - +const double STROKE_FONT::OVERBAR_HEIGHT = 0.45; +const double STROKE_FONT::BOLD_FACTOR = 1.3; +const double STROKE_FONT::HERSHEY_SCALE = 1.0 / 21.0; STROKE_FONT::STROKE_FONT( GAL* aGal ) : m_gal( aGal ), @@ -41,7 +41,6 @@ STROKE_FONT::STROKE_FONT( GAL* aGal ) : m_mirrored( false ) { // Default values - m_scaleFactor = 1.0 / 21.0; m_glyphSize = VECTOR2D( 10.0, 10.0 ); m_verticalJustify = GR_TEXT_VJUSTIFY_BOTTOM; m_horizontalJustify = GR_TEXT_HJUSTIFY_LEFT; @@ -57,6 +56,8 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe { m_glyphs.clear(); m_glyphBoundingBoxes.clear(); + m_glyphs.resize( aNewStrokeFontSize ); + m_glyphBoundingBoxes.resize( aNewStrokeFontSize ); for( int j = 0; j < aNewStrokeFontSize; j++ ) { @@ -82,8 +83,8 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe if( i < 2 ) { // The first two values contain the width of the char - glyphStartX = coordinate[0] - 'R'; - glyphEndX = coordinate[1] - 'R'; + glyphStartX = ( coordinate[0] - 'R' ) * HERSHEY_SCALE; + glyphEndX = ( coordinate[1] - 'R' ) * HERSHEY_SCALE; glyphBoundingX = VECTOR2D( 0, glyphEndX - glyphStartX ); } else if( ( coordinate[0] == ' ' ) && ( coordinate[1] == 'R' ) ) @@ -98,8 +99,8 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe { // Every coordinate description of the Hershey format has an offset, // it has to be subtracted - point.x = (double) ( coordinate[0] - 'R' ) - glyphStartX; - point.y = (double) ( coordinate[1] - 'R' ) - 11.0; + point.x = (double) ( coordinate[0] - 'R' ) * HERSHEY_SCALE - glyphStartX; + point.y = (double) ( coordinate[1] - 'R' ) * HERSHEY_SCALE; pointList.push_back( point ); } @@ -109,16 +110,22 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe if( pointList.size() > 0 ) glyph.push_back( pointList ); - m_glyphs.push_back( glyph ); + m_glyphs[j] = glyph; // Compute the bounding box of the glyph - m_glyphBoundingBoxes.push_back( computeBoundingBox( glyph, glyphBoundingX ) ); + m_glyphBoundingBoxes[j] = computeBoundingBox( glyph, glyphBoundingX ); } return true; } +int STROKE_FONT::getInterline() const +{ + return ( m_glyphSize.y * 14 ) / 10 + m_gal->GetLineWidth(); +} + + BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLYPHBoundingX ) const { BOX2D boundingBox; @@ -145,115 +152,134 @@ BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLY void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ) { - // By default overbar is turned off - m_overbar = false; - // Context needs to be saved before any transformations m_gal->Save(); m_gal->Translate( aPosition ); - m_gal->Rotate( -aRotationAngle ); - // Split multiline strings into separate ones and draw them line by line - int newlinePos = aText.Find( '\n' ); + // Single line height + int lineHeight = getInterline(); - if( newlinePos != wxNOT_FOUND ) - { - VECTOR2D nextlinePosition = VECTOR2D( 0.0, m_glyphSize.y * LINE_HEIGHT_RATIO ); - - Draw( aText.Mid( newlinePos + 1 ), nextlinePosition, 0.0 ); - aText = aText.Mid( 0, newlinePos ); - } - - // Compute the text size - VECTOR2D textsize = computeTextSize( aText ); - - // Adjust the text position to the given alignment - switch( m_horizontalJustify ) - { - case GR_TEXT_HJUSTIFY_CENTER: - m_gal->Translate( VECTOR2D( -textsize.x / 2.0, 0 ) ); - break; - - case GR_TEXT_HJUSTIFY_RIGHT: - if( !m_mirrored ) - m_gal->Translate( VECTOR2D( -textsize.x, 0 ) ); - - break; - - case GR_TEXT_HJUSTIFY_LEFT: - if( m_mirrored ) - m_gal->Translate( VECTOR2D( -textsize.x, 0 ) ); - - break; - - default: - break; - } + // The overall height of all lines of text + double textBlockHeight = lineHeight * ( linesCount( aText ) - 1 ); switch( m_verticalJustify ) { case GR_TEXT_VJUSTIFY_CENTER: - m_gal->Translate( VECTOR2D( 0, textsize.y / 2.0 ) ); - break; - - case GR_TEXT_VJUSTIFY_TOP: - m_gal->Translate( VECTOR2D( 0, textsize.y ) ); + m_gal->Translate( VECTOR2D( 0, -textBlockHeight / 2.0 ) ); break; case GR_TEXT_VJUSTIFY_BOTTOM: + m_gal->Translate( VECTOR2D( 0, -textBlockHeight ) ); + break; + + case GR_TEXT_VJUSTIFY_TOP: break; default: break; } - double xOffset, glyphSizeX; - - if( m_mirrored ) - { - // In case of mirrored text invert the X scale of points and their X direction - // (m_glyphSize.x) and start drawing from the position where text normally should end - // (textsize.x) - xOffset = textsize.x; - glyphSizeX = -m_glyphSize.x; - } - else - { - xOffset = 0.0; - glyphSizeX = m_glyphSize.x; - } - double scaleY = m_scaleFactor * m_glyphSize.y; - double scaleX = m_scaleFactor * glyphSizeX; + m_gal->Rotate( -aRotationAngle ); m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); if( m_bold ) + m_gal->SetLineWidth( m_gal->GetLineWidth() * BOLD_FACTOR ); + + // Split multiline strings into separate ones and draw them line by line + int begin = 0; + int newlinePos = aText.find( '\n' ); + + while( newlinePos != wxNOT_FOUND ) { - m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 ); + size_t length = newlinePos - begin; + drawSingleLineText( aText.Mid( begin, length ) ); + m_gal->Translate( VECTOR2D( 0.0, lineHeight ) ); + + begin = newlinePos + 1; + newlinePos = aText.find( '\n', begin + 1 ); + } + + // Draw the last (or the only one) line + drawSingleLineText( aText.Mid( begin ) ); + + m_gal->Restore(); +} + + +void STROKE_FONT::drawSingleLineText( const wxString& aText ) +{ + // By default the overbar is turned off + m_overbar = false; + + double xOffset; + VECTOR2D glyphSize( m_glyphSize ); + + // Compute the text size + VECTOR2D textSize = computeTextSize( aText ); + + m_gal->Save(); + + // Adjust the text position to the given alignment + switch( m_horizontalJustify ) + { + case GR_TEXT_HJUSTIFY_CENTER: + m_gal->Translate( VECTOR2D( -textSize.x / 2.0, 0 ) ); + break; + + case GR_TEXT_HJUSTIFY_RIGHT: + if( !m_mirrored ) + m_gal->Translate( VECTOR2D( -textSize.x, 0 ) ); + break; + + case GR_TEXT_HJUSTIFY_LEFT: + if( m_mirrored ) + m_gal->Translate( VECTOR2D( -textSize.x, 0 ) ); + break; + + default: + break; + } + + + if( m_mirrored ) + { + // In case of mirrored text invert the X scale of points and their X direction + // (m_glyphSize.x) and start drawing from the position where text normally should end + // (textSize.x) + xOffset = textSize.x; + glyphSize.x = -m_glyphSize.x; + } else + { + xOffset = 0.0; } for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { + // Toggle overbar if( *chIt == '~' ) { m_overbar = !m_overbar; continue; } - GLYPH_LIST::iterator glyphIt = m_glyphs.begin(); - std::deque::iterator bbIt = m_glyphBoundingBoxes.begin(); - unsigned dd = *chIt - ' '; - if( dd >= m_glyphBoundingBoxes.size() ) + if( dd >= m_glyphBoundingBoxes.size() || dd < 0 ) dd = '?' - ' '; - advance( glyphIt, dd ); - advance( bbIt, dd ); + GLYPH& glyph = m_glyphs[dd]; + BOX2D& bbox = m_glyphBoundingBoxes[dd]; - GLYPH glyph = *glyphIt; + if( m_overbar ) + { + VECTOR2D startOverbar( xOffset, -getInterline() * OVERBAR_HEIGHT ); + VECTOR2D endOverbar( xOffset + glyphSize.x * bbox.GetEnd().x, + -getInterline() * OVERBAR_HEIGHT ); + m_gal->DrawLine( startOverbar, endOverbar ); + } for( GLYPH::iterator pointListIt = glyph.begin(); pointListIt != glyph.end(); pointListIt++ ) @@ -263,7 +289,7 @@ void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotat for( std::deque::iterator pointIt = pointListIt->begin(); pointIt != pointListIt->end(); pointIt++ ) { - VECTOR2D pointPos( pointIt->x * scaleX + xOffset, pointIt->y * scaleY ); + VECTOR2D pointPos( pointIt->x * glyphSize.x + xOffset, pointIt->y * glyphSize.y ); if( m_italic ) { @@ -278,15 +304,7 @@ void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotat m_gal->DrawPolyline( pointListScaled ); } - if( m_overbar ) - { - VECTOR2D startOverbar( xOffset, -textsize.y * 1.2 ); - VECTOR2D endOverbar( xOffset + m_scaleFactor * glyphSizeX * bbIt->GetEnd().x, - -textsize.y * 1.2 ); - m_gal->DrawLine( startOverbar, endOverbar ); - } - - xOffset += m_scaleFactor * glyphSizeX * bbIt->GetEnd().x; + xOffset += glyphSize.x * bbox.GetEnd().x; } m_gal->Restore(); @@ -299,18 +317,19 @@ VECTOR2D STROKE_FONT::computeTextSize( const wxString& aText ) const for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) { + wxASSERT_MSG( *chIt != '\n', + wxT( "This function is intended to work with single line strings" ) ); + if( *chIt == '~' ) continue; - std::deque::const_iterator bbIt = m_glyphBoundingBoxes.begin(); + // Index in the bounding boxes table unsigned dd = *chIt - ' '; - if( dd >= m_glyphBoundingBoxes.size() ) + if( dd >= m_glyphBoundingBoxes.size() || dd < 0 ) dd = '?' - ' '; - advance( bbIt, dd ); - - result.x += m_scaleFactor * m_glyphSize.x * bbIt->GetEnd().x; + result.x += m_glyphSize.x * m_glyphBoundingBoxes[dd].GetEnd().x; } return result; diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index 5caa4502f9..684eb80a61 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -39,7 +39,7 @@ namespace KIGFX class GAL; typedef std::deque< std::deque > GLYPH; -typedef std::deque GLYPH_LIST; +typedef std::vector GLYPH_LIST; /** * @brief Class STROKE_FONT implements stroke font drawing. @@ -55,8 +55,6 @@ public: /// Destructor ~STROKE_FONT(); - // TODO Load font from a text file - /** * @brief Load the new stroke font. * @@ -75,16 +73,6 @@ public: */ void Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ); - /** - * @brief Set the scale factor of the font for the glyph size. - * - * @param aScaleFactor is the scale factor of the font. - */ - inline void SetScaleFactor( const double aScaleFactor ) - { - m_scaleFactor = aScaleFactor; - } - /** * @brief Set the glyph size. * @@ -158,13 +146,19 @@ public: private: GAL* m_gal; ///< Pointer to the GAL GLYPH_LIST m_glyphs; ///< Glyph list - std::deque m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs - double m_scaleFactor; ///< Scale factor for the glyph + 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 + /** + * @brief Returns a single line height using current settings. + * + * @return The line height. + */ + int getInterline() const; + /** * @brief Compute the bounding box of a given glyph. * @@ -174,6 +168,14 @@ private: */ BOX2D computeBoundingBox( const GLYPH& aGlyph, const VECTOR2D& aGlyphBoundingX ) const; + /** + * @brief Draws a single line of text. Multiline texts should be split before using the + * function. + * + * @param aText is the text to be drawn. + */ + void drawSingleLineText( const wxString& aText ); + /** * @brief Compute the size of a given text. * @@ -182,7 +184,34 @@ private: */ VECTOR2D computeTextSize( const wxString& aText ) const; - static const double LINE_HEIGHT_RATIO; + /** + * @brief Returns number of lines for a given text. + * + * @param aText is the text to be checked. + * @return Number of lines of aText. + */ + unsigned int linesCount( const wxString& aText ) const + { + wxString::const_iterator it, itEnd; + unsigned int lines = 1; + + for( it = aText.begin(), itEnd = aText.end(); it != itEnd; ++it ) + { + if( *it == '\n' ) + ++lines; + } + + return lines; + } + + ///> Factor that determines relative height of overbar. + static const double OVERBAR_HEIGHT; + + ///> Factor that determines relative line width for bold text. + static const double BOLD_FACTOR; + + ///> Scale factor for the glyph + static const double HERSHEY_SCALE; }; } // namespace KIGFX From 384abca49ecf228d63b72ad0ca75fd73b85da8aa Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Dec 2013 16:58:32 +0100 Subject: [PATCH 4/6] Tilda handling for STROKE_FONT class. --- common/gal/stroke_font.cpp | 37 ++++++++++++++++++++++--------------- include/gal/stroke_font.h | 5 ++--- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index 47166c81f3..a809c6fed1 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -3,6 +3,8 @@ * * Copyright (C) 2012 Torsten Hueter, torstenhtr gmx.de * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 CERN + * @author Maciej Suminski * * Stroke font class * @@ -47,11 +49,6 @@ STROKE_FONT::STROKE_FONT( GAL* aGal ) : } -STROKE_FONT::~STROKE_FONT() -{ -} - - bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNewStrokeFontSize ) { m_glyphs.clear(); @@ -190,7 +187,7 @@ void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotat // Split multiline strings into separate ones and draw them line by line int begin = 0; - int newlinePos = aText.find( '\n' ); + int newlinePos = aText.Find( '\n' ); while( newlinePos != wxNOT_FOUND ) { @@ -203,7 +200,8 @@ void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotat } // Draw the last (or the only one) line - drawSingleLineText( aText.Mid( begin ) ); + if( !aText.IsEmpty() ) + drawSingleLineText( aText.Mid( begin ) ); m_gal->Restore(); } @@ -243,7 +241,6 @@ void STROKE_FONT::drawSingleLineText( const wxString& aText ) break; } - if( m_mirrored ) { // In case of mirrored text invert the X scale of points and their X direction @@ -256,13 +253,18 @@ void STROKE_FONT::drawSingleLineText( const wxString& aText ) xOffset = 0.0; } - for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); ++chIt ) { // Toggle overbar if( *chIt == '~' ) { - m_overbar = !m_overbar; - continue; + if( ++chIt == aText.end() ) + break; + + if( *chIt != '~' ) // It was a single tilda, it toggles overbar + m_overbar = !m_overbar; + + // If it is a double tilda, just process the second one } unsigned dd = *chIt - ' '; @@ -282,12 +284,12 @@ void STROKE_FONT::drawSingleLineText( const wxString& aText ) } for( GLYPH::iterator pointListIt = glyph.begin(); pointListIt != glyph.end(); - pointListIt++ ) + ++pointListIt ) { std::deque pointListScaled; for( std::deque::iterator pointIt = pointListIt->begin(); - pointIt != pointListIt->end(); pointIt++ ) + pointIt != pointListIt->end(); ++pointIt ) { VECTOR2D pointPos( pointIt->x * glyphSize.x + xOffset, pointIt->y * glyphSize.y ); @@ -315,13 +317,18 @@ VECTOR2D STROKE_FONT::computeTextSize( const wxString& aText ) const { VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y ); - for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); ++chIt ) { wxASSERT_MSG( *chIt != '\n', wxT( "This function is intended to work with single line strings" ) ); + // If it is double tilda, then it is displayed as a single tilda + // If it is single tilda, then it is toggling overbar, so we need to skip it if( *chIt == '~' ) - continue; + { + if( ++chIt == aText.end() ) + break; + } // Index in the bounding boxes table unsigned dd = *chIt - ' '; diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index 684eb80a61..a3619783f2 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -3,6 +3,8 @@ * * Copyright (C) 2012 Torsten Hueter, torstenhtr gmx.de * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 CERN + * @author Maciej Suminski * * Stroke font class * @@ -52,9 +54,6 @@ public: /// Constructor STROKE_FONT( GAL* aGal ); - /// Destructor - ~STROKE_FONT(); - /** * @brief Load the new stroke font. * From 940fc985e7ee2330b2302dd0af5e883afb21474a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Dec 2013 17:00:29 +0100 Subject: [PATCH 5/6] DIfferent handling of italic texts, depending on the mirroring setting. --- common/gal/stroke_font.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index a809c6fed1..f9549ce070 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -297,7 +297,10 @@ void STROKE_FONT::drawSingleLineText( const wxString& aText ) { // FIXME should be done other way - referring to the lowest Y value of point // because now italic fonts are translated a bit - pointPos.x += pointPos.y * 0.1; + if( m_mirrored ) + pointPos.x += pointPos.y * 0.1; + else + pointPos.x -= pointPos.y * 0.1; } pointListScaled.push_back( pointPos ); From bee41d9491a4a8b8787b9608e3fc06834bbdf61e Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Thu, 5 Dec 2013 12:59:27 -0600 Subject: [PATCH 6/6] Switch STROKE_FONT::Draw() to take "const wxString&" rather than "wxString" by value. --- common/gal/stroke_font.cpp | 2 +- include/gal/stroke_font.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index f9549ce070..302e8b3293 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -147,7 +147,7 @@ BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLY } -void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ) +void STROKE_FONT::Draw( const wxString& aText, const VECTOR2D& aPosition, double aRotationAngle ) { // Context needs to be saved before any transformations m_gal->Save(); diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index a3619783f2..afa8d7f61c 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -70,7 +70,7 @@ public: * @param aPosition is the text position in world coordinates. * @param aRotationAngle is the text rotation angle. */ - void Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ); + void Draw( const wxString& aText, const VECTOR2D& aPosition, double aRotationAngle ); /** * @brief Set the glyph size.