Fix PDF plotting of text containing tab characters
The PDF plotter's renderWord function now properly handles tab characters within text. Previously, tabs were passed to HarfBuzz or the stroke font encoder which would render them as zero-width or small-width glyphs, causing text alignment issues. The fix splits text at tab boundaries and calculates proper tab stop positions using the same algorithm as the font rendering code (TAB_WIDTH = 4 * 0.6 font units), advancing the cursor to the next tab stop for each tab character encountered. Fixes https://gitlab.com/kicad/code/kicad/-/issues/22606
This commit is contained in:
@@ -2085,10 +2085,11 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
|
||||
return aPosition;
|
||||
|
||||
// If the word is just a space character, advance position by space width and continue
|
||||
if( aWord == wxT(" ") )
|
||||
if( aWord == wxT( " " ) )
|
||||
{
|
||||
// Calculate space width and advance position
|
||||
VECTOR2I spaceBox( aFont->StringBoundaryLimits( "n", aSize, aWidth, aBold, aItalic, aFontMetrics ).x / 2, 0 );
|
||||
VECTOR2I spaceBox( aFont->StringBoundaryLimits( "n", aSize, aWidth, aBold, aItalic,
|
||||
aFontMetrics ).x / 2, 0 );
|
||||
|
||||
if( aTextMirrored )
|
||||
spaceBox.x *= -1;
|
||||
@@ -2098,6 +2099,51 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
|
||||
return aPosition + rotatedSpaceBox;
|
||||
}
|
||||
|
||||
// If the word contains tab characters, we need to handle them specially.
|
||||
// Split by tabs and render each segment, advancing to the next tab stop for each tab.
|
||||
if( aWord.Contains( wxT( '\t' ) ) )
|
||||
{
|
||||
constexpr double TAB_WIDTH = 4 * 0.6;
|
||||
|
||||
VECTOR2I pos = aPosition;
|
||||
wxString segment;
|
||||
|
||||
for( wxUniChar c : aWord )
|
||||
{
|
||||
if( c == '\t' )
|
||||
{
|
||||
if( !segment.IsEmpty() )
|
||||
{
|
||||
pos = renderWord( segment, pos, aSize, aOrient, aTextMirrored, aWidth, aBold,
|
||||
aItalic, aFont, aFontMetrics, aV_justify, aTextStyle );
|
||||
segment.clear();
|
||||
}
|
||||
|
||||
int tabWidth = KiROUND( aSize.x * TAB_WIDTH );
|
||||
int currentIntrusion = ( pos.x - aPosition.x ) % tabWidth;
|
||||
VECTOR2I tabAdvance( tabWidth - currentIntrusion, 0 );
|
||||
|
||||
if( aTextMirrored )
|
||||
tabAdvance.x *= -1;
|
||||
|
||||
RotatePoint( tabAdvance, aOrient );
|
||||
pos += tabAdvance;
|
||||
}
|
||||
else
|
||||
{
|
||||
segment += c;
|
||||
}
|
||||
}
|
||||
|
||||
if( !segment.IsEmpty() )
|
||||
{
|
||||
pos = renderWord( segment, pos, aSize, aOrient, aTextMirrored, aWidth, aBold, aItalic,
|
||||
aFont, aFontMetrics, aV_justify, aTextStyle );
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Compute transformation parameters for this word
|
||||
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
|
||||
double wideningFactor, heightFactor;
|
||||
|
||||
Reference in New Issue
Block a user