Nullptr safety & performance tweaks.

This commit is contained in:
Jeff Young
2025-09-19 21:08:01 +01:00
parent 6edae8fb1a
commit 35abc8e33e
6 changed files with 111 additions and 94 deletions
+38 -43
View File
@@ -1978,15 +1978,14 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
while( str_tok.HasMoreTokens() )
{
wxString word = str_tok.GetNextToken();
pos = renderWord( word, pos, t_size, aOrient, textMirrored, aWidth, aBold, aItalic,
aFont, aFontMetrics, aV_justify, 0 );
pos = renderWord( word, pos, t_size, aOrient, textMirrored, aWidth, aBold, aItalic, aFont,
aFontMetrics, aV_justify, 0 );
}
return;
}
// Calculate the full text bounding box for alignment
VECTOR2I full_box( aFont->StringBoundaryLimits( text, t_size, aWidth, aBold, aItalic,
aFontMetrics ) );
VECTOR2I full_box( aFont->StringBoundaryLimits( text, t_size, aWidth, aBold, aItalic, aFontMetrics ) );
if( textMirrored )
full_box.x *= -1;
@@ -2027,7 +2026,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
if( wxGetEnv( "KICAD_DEBUG_SYN_STYLE", nullptr ) )
{
int styleFlags = 0;
if( aFont && aFont->IsOutline() )
if( aFont->IsOutline() )
styleFlags = static_cast<KIFONT::OUTLINE_FONT*>( aFont )->GetFace() ? static_cast<KIFONT::OUTLINE_FONT*>( aFont )->GetFace()->style_flags : 0;
wxLogTrace( tracePdfPlotter, "renderWord enter word='%s' bold=%d italic=%d textStyle=%u styleFlags=%d", TO_UTF8( aWord ), (int) aBold, (int) aItalic, (unsigned) aTextStyle, styleFlags );
}
@@ -2040,8 +2039,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
if( aWord == wxT(" ") )
{
// Calculate space width and advance position
VECTOR2I spaceBox( aFont->StringBoundaryLimits( wxT("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;
@@ -2055,15 +2053,16 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
double wideningFactor, heightFactor;
computeTextParameters( aPosition, aWord, aOrient, aSize, aTextMirrored,
GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_BOTTOM, aWidth,
aItalic, aBold, &wideningFactor, &ctm_a, &ctm_b, &ctm_c,
&ctm_d, &ctm_e, &ctm_f, &heightFactor );
computeTextParameters( aPosition, aWord, aOrient, aSize, aTextMirrored, GR_TEXT_H_ALIGN_LEFT,
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor,
&ctm_a, &ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
// Calculate next position for word spacing
VECTOR2I bbox( aFont->StringBoundaryLimits( aWord, aSize, aWidth, aBold, aItalic, aFontMetrics ).x, 0 );
if( aTextMirrored )
bbox.x *= -1;
RotatePoint( bbox, aOrient );
VECTOR2I nextPos = aPosition + bbox;
@@ -2072,7 +2071,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// Outline fonts need: superscript +1 full font height higher; subscript +1 full font height higher
if( aTextStyle & TEXT_STYLE::SUPERSCRIPT )
{
double factor = ( aFont && aFont->IsOutline() ) ? 0.050 : 0.030; // stroke original ~0.40, outline needs +1.0
double factor = aFont->IsOutline() ? 0.050 : 0.030; // stroke original ~0.40, outline needs +1.0
VECTOR2I offset( 0, static_cast<int>( std::lround( aSize.y * factor ) ) );
RotatePoint( offset, aOrient );
ctm_e -= offset.x;
@@ -2083,7 +2082,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// For outline fonts raise by one font height versus stroke (which shifts downward slightly)
VECTOR2I offset( 0, 0 );
if( !aFont || aFont->IsStroke() )
if( aFont->IsStroke() )
offset.y = static_cast<int>( std::lround( aSize.y * 0.01 ) );
RotatePoint( offset, aOrient );
@@ -2092,9 +2091,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
}
// Render the word using existing outline font logic
bool useOutlineFont = aFont && aFont->IsOutline();
if( useOutlineFont )
if( aFont->IsOutline() )
{
std::vector<PDF_OUTLINE_FONT_RUN> outlineRuns;
@@ -2111,6 +2108,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// Apply baseline adjustment (keeping existing logic)
double baseline_factor = 0.17;
double alignment_multiplier = 1.0;
if( aV_justify == GR_TEXT_V_ALIGN_CENTER )
alignment_multiplier = 2.0;
else if( aV_justify == GR_TEXT_V_ALIGN_TOP )
@@ -2132,16 +2130,6 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
double adj_c = ctm_c;
double adj_d = ctm_d;
if( aItalic && ( !aFont || !aFont->IsOutline() ) )
{
double tilt = -ITALIC_TILT;
if( wideningFactor < 0 )
tilt = -tilt;
adj_c -= ctm_a * tilt;
adj_d -= ctm_b * tilt;
}
// Synthetic italic (shear) for outline font if requested but font not intrinsically italic
bool syntheticItalicApplied = false;
double appliedTilt = 0.0;
@@ -2150,13 +2138,15 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
double syn_a = ctm_a;
double syn_b = ctm_b;
bool wantItalic = ( aItalic || ( aTextStyle & TEXT_STYLE::ITALIC ) );
if( std::getenv( "KICAD_FORCE_SYN_ITALIC" ) )
wantItalic = true; // debug: ensure path triggers when forcing synthetic italic
bool wantBold = ( aBold || ( aTextStyle & TEXT_STYLE::BOLD ) );
bool fontIsItalic = aFont && aFont->IsOutline() && aFont->IsItalic();
bool fontIsBold = aFont && aFont->IsOutline() && aFont->IsBold();
bool fontIsFakeItalic = aFont && aFont->IsOutline() && static_cast<KIFONT::OUTLINE_FONT*>( aFont )->IsFakeItalic();
bool fontIsFakeBold = aFont && aFont->IsOutline() && static_cast<KIFONT::OUTLINE_FONT*>( aFont )->IsFakeBold();
bool wantBold = ( aBold || ( aTextStyle & TEXT_STYLE::BOLD ) );
bool fontIsItalic = aFont->IsItalic();
bool fontIsBold = aFont->IsBold();
bool fontIsFakeItalic = static_cast<KIFONT::OUTLINE_FONT*>( aFont )->IsFakeItalic();
bool fontIsFakeBold = static_cast<KIFONT::OUTLINE_FONT*>( aFont )->IsFakeBold();
// Environment overrides for testing synthetic italics:
// KICAD_FORCE_SYN_ITALIC=1 forces synthetic shear even if font has italic face
@@ -2164,6 +2154,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// otherwise treat as raw tilt factor (x += tilt*y)
bool forceSynItalic = false;
double overrideTilt = 0.0;
if( const char* envForce = std::getenv( "KICAD_FORCE_SYN_ITALIC" ) )
{
if( *envForce != '\0' && *envForce != '0' )
@@ -2173,6 +2164,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
if( const char* envTilt = std::getenv( "KICAD_SYN_ITALIC_TILT" ) )
{
std::string tiltStr( envTilt );
try
{
if( tiltStr.find( "deg" ) != std::string::npos )
@@ -2202,8 +2194,9 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// - Italic requested AND outline font
// - And either forceSynItalic env var set OR there is no REAL italic face.
// (A fake italic flag from fontconfig substitution should NOT block synthetic shear.)
bool realItalicFace = aFont && aFont->IsOutline() && aFont->IsItalic() && !fontIsFakeItalic;
if( wantItalic && aFont && aFont->IsOutline() && ( forceSynItalic || !realItalicFace ) )
bool realItalicFace = fontIsItalic && !fontIsFakeItalic;
if( wantItalic && ( forceSynItalic || !realItalicFace ) )
{
// We want to apply a horizontal shear so that x' = x + tilt * y in the glyph's
// local coordinate system BEFORE rotation. The existing text matrix columns are:
@@ -2215,6 +2208,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
// to the second column: (c', d') = (c + tilt * a, d + tilt * b).
// This produces a right-leaning italic for positive tilt.
double tilt = ( overrideTilt != 0.0 ) ? overrideTilt : ITALIC_TILT;
if( wideningFactor < 0 ) // mirrored text should mirror the shear
tilt = -tilt;
@@ -2223,12 +2217,11 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
appliedTilt = tilt;
syntheticItalicApplied = true;
wxLogTrace( tracePdfPlotter,
"Synthetic italic shear applied: tilt=%f a=%f b=%f c->%f d->%f",
wxLogTrace( tracePdfPlotter, "Synthetic italic shear applied: tilt=%f a=%f b=%f c->%f d->%f",
tilt, syn_a, syn_b, syn_c, syn_d );
}
if( wantBold && aFont && aFont->IsOutline() && !fontIsBold )
if( wantBold && !fontIsBold )
{
// Slight horizontal widening to simulate bold (~3%)
syn_a *= 1.03;
@@ -2238,7 +2231,8 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
if( syntheticItalicApplied )
{
// PDF comment to allow manual inspection in the output stream
fmt::print( m_workFile, "% syn-italic tilt={} a={} b={} c={} d={}\n", appliedTilt, syn_a, syn_b, syn_c, syn_d );
fmt::print( m_workFile, "% syn-italic tilt={} a={} b={} c={} d={}\n",
appliedTilt, syn_a, syn_b, syn_c, syn_d );
}
fmt::print( m_workFile, "q {:f} {:f} {:f} {:f} {:f} {:f} cm BT {} Tr {:g} Tz ",
@@ -2287,6 +2281,7 @@ VECTOR2I PDF_PLOTTER::renderWord( const wxString& aWord, const VECTOR2I& aPositi
if( aItalic && ( !aFont || !aFont->IsOutline() ) )
{
double tilt = -ITALIC_TILT;
if( wideningFactor < 0 )
tilt = -tilt;
@@ -2368,9 +2363,9 @@ VECTOR2I PDF_PLOTTER::renderMarkupNode( const MARKUP::NODE* aNode, const VECTOR2
{
wxString word = str_tok.GetNextToken();
nextPosition = renderWord( word, nextPosition, currentSize, aOrient, aTextMirrored,
aWidth, aBaseBold || (currentStyle & TEXT_STYLE::BOLD),
aBaseItalic || (currentStyle & TEXT_STYLE::ITALIC),
aFont, aFontMetrics, aV_justify, currentStyle );
aWidth, aBaseBold || (currentStyle & TEXT_STYLE::BOLD),
aBaseItalic || (currentStyle & TEXT_STYLE::ITALIC),
aFont, aFontMetrics, aV_justify, currentStyle );
}
}
}
@@ -2381,14 +2376,14 @@ VECTOR2I PDF_PLOTTER::renderMarkupNode( const MARKUP::NODE* aNode, const VECTOR2
VECTOR2I startPos = nextPosition;
nextPosition = renderMarkupNode( child.get(), nextPosition, currentSize, aOrient,
aTextMirrored, aWidth, aBaseBold, aBaseItalic,
aFont, aFontMetrics, aV_justify, currentStyle, aOverbars );
aTextMirrored, aWidth, aBaseBold, aBaseItalic,
aFont, aFontMetrics, aV_justify, currentStyle, aOverbars );
// Store overbar info for later rendering
if( drawOverbar )
{
VECTOR2I endPos = nextPosition;
aOverbars.push_back( { startPos, endPos, currentSize, aFont && aFont->IsOutline(), aV_justify } );
aOverbars.push_back( { startPos, endPos, currentSize, aFont->IsOutline(), aV_justify } );
}
}