32#include <wx/strconv.h>
33#include <wx/translation.h>
43 constexpr double CAPITAL_HEIGHT = 0.75;
47 int32_t strokeCharWidthPercent(
char aChar,
bool aProportional )
53 static const wxCSConv cp1252( wxFONTENCODING_CP1252 );
55 const char bytes[2] = { aChar,
'\0' };
56 wxString
text( bytes, cp1252 );
57 int index =
text.IsEmpty() ? -1 :
static_cast<int>(
text[0].GetValue() ) -
' ';
62 return KiROUND( font->GetGlyphBoundingBox(
index ).GetEnd().x * CAPITAL_HEIGHT * 100.0 );
67 int32_t narrow( int64_t aValue )
69 if( aValue < std::numeric_limits<int32_t>::min() || aValue > std::numeric_limits<int32_t>::max() )
70 THROW_IO_ERROR(
_(
"Easy-PC text metrics are outside the supported range." ) );
72 return static_cast<int32_t
>( aValue );
77 void rotate( int32_t& aX, int32_t& aY, int32_t aAngle,
const VECTOR2I& aCentre )
79 int64_t reach =
std::abs( int64_t( aX ) - aCentre.
x ) +
std::abs( int64_t( aY ) - aCentre.
y );
81 narrow(
std::abs( int64_t( aCentre.
x ) ) + reach );
82 narrow(
std::abs( int64_t( aCentre.
y ) ) + reach );
88 bool flipsUpright( int32_t aAngle )
90 return aAngle > 135000 && aAngle <= 305000;
103 void Include( int32_t aX, int32_t aY )
105 Left = Empty ? aX : std::min( Left, aX );
106 Right = Empty ? aX : std::max( Right, aX );
107 Bottom = Empty ? aY : std::min( Bottom, aY );
108 Top = Empty ? aY : std::max( Top, aY );
158 for(
size_t i = aBegin; i < aEnd; ++i )
161 return w != 0 ? narrow( w ) :
m_height;
166 int aHAlign,
int aVAlign )
const
169 const size_t n =
text.size();
176 auto bar = [&](
size_t aPos )
178 return aPos + 1 < n &&
text[aPos] ==
'_' &&
text[aPos + 1] ==
'_';
181 std::vector<int64_t> widths;
184 for(
bool first =
true;; first = false )
193 bool newLine =
text[begin] ==
'\n' ||
text[begin] ==
'\r';
199 if( begin < n &&
text[begin] !=
text[begin - 1] && (
text[begin] ==
'\n' ||
text[begin] ==
'\r' ) )
211 if( first || newLine )
212 widths.push_back( 0 );
214 widths.back() = narrow( widths.back() +
RunWidth(
text, begin,
end ) );
217 int64_t baseline = aAnchor.
y;
226 for(
size_t i = 0; i < widths.size(); ++i )
231 int64_t x = aAnchor.
x;
238 box.Include( narrow( x ), narrow( baseline ) );
239 box.Include( narrow( x + widths[i] ), narrow( baseline +
linePitch() ) );
242 int64_t grow = ( int64_t(
m_penWidth ) + 1 ) >> 1;
243 box.Left = narrow( box.Left - grow );
244 box.Bottom = narrow( box.Bottom - grow );
245 box.Right = narrow( box.Right + grow );
246 box.Top = narrow( box.Top + grow );
250 int32_t
left = narrow( 2 * int64_t( aAnchor.
x ) - box.Right );
251 box.Right = narrow( 2 * int64_t( aAnchor.
x ) - box.Left );
259 { box.Right, box.Top }, { box.Left, box.Bottom }, { box.Right, box.Bottom }, { box.Left, box.Top }
265 rotate( c.x, c.y, aAngle, aAnchor );
266 rotated.Include( c.x, c.y );
279 int aHAlign,
bool aKeepUpright )
const
281 if( !aKeepUpright || aText.IsEmpty() || !flipsUpright( aAngle ) )
284 BOX2I box =
TextBox( aText, aAnchor, 0,
false, aHAlign );
293 x = narrow( 2 * int64_t( aAnchor.
x ) - x );
295 rotate( x, y, aAngle, aAnchor );
302 static const wxCSConv cp1252( wxFONTENCODING_CP1252 );
305 bytes.reserve( aText.length() );
307 for( wxUniChar ch : aText )
311 bytes.push_back(
static_cast<char>( ch.GetValue() ) );
315 wxCharBuffer one = wxString( ch ).mb_str( cp1252 );
316 bytes.push_back( one.length() == 1 ? one.data()[0] :
'\0' );
339 if( !aKeepUpright || !flipsUpright( aAngle ) )
349 bool overbar =
false;
351 for(
size_t i = 0; i < aText.length(); ++i )
353 wxUniChar c = aText[i];
354 wxUniChar
next = i + 1 < aText.length() ? aText[i + 1] : wxUniChar( 0 );
356 if( c ==
'_' &&
next ==
'_' )
358 out += overbar ? wxS(
"}" ) : wxS(
"~{" );
362 else if( c ==
'\n' || c ==
'\r' )
370 else if( c ==
'~' &&
next ==
'{' )
373 out += wxS(
"~~{}{" );
376 else if( c ==
'}' && overbar )
379 out += wxS(
"}}~{" );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr const Vec GetEnd() const
constexpr const Vec & GetOrigin() const
constexpr void SetEnd(coord_type x, coord_type y)
int32_t linePitch() const
int32_t m_interlinePercent
int32_t m_charWidthPercent
int32_t RunWidth(const std::string &aText, size_t aBegin, size_t aEnd) const
Width of bytes [aBegin, aEnd); a run that measures 0 is one height wide.
static std::string Encode(const wxString &aText)
The CP1252 bytes of aText; characters CP1252 lacks become 0.
int32_t charWidth(char aChar) const
TEXT_METRICS(const SOURCE_TEXT_STYLE &aStyle)
void checkMeasurable() const
BOX2I TextBox(const wxString &aText, const VECTOR2I &aAnchor, int32_t aAngle, bool aMirrored, int aHAlign, int aVAlign=TEXT_V_BASELINE) const
Every line's cell, inflated by half the pen width, mirrored about the anchor and bounded after rotati...
VECTOR2I UprightAnchor(const wxString &aText, const VECTOR2I &aAnchor, int32_t aAngle, bool aMirrored, int aHAlign, bool aKeepUpright) const
When aKeepUpright and UprightRotation turns the text, the anchor moves to the far end of the first li...
static STROKE_FONT * LoadFont(const wxString &aFontName)
Load a stroke font.
The design document and the design parameter tables the importers use.
Easy-PC's text measurement, so text lands where Easy-PC draws it.
Design units of 100 nm and angles of thousandths of a degree, anticlockwise from +X with Y up.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
bool TextStaysUpright(const SOURCE_DESIGN &aDesign, bool aSchematic)
Whether aDesign's text is drawn upright: the design's flag, which old schematics imply,...
int32_t UprightRotation(int32_t aAngle, bool aKeepUpright)
With text kept upright, an angle above 135 and up to 305 degrees turns by 180.
void PointRotate(double aPx, double aPy, int32_t aAngle, double aCx, double aCy, int32_t &aOutX, int32_t &aOutY)
Rotate aPx, aPy anticlockwise by aAngle about aCx, aCy as Easy-PC places points: in double with exact...
@ PRODUCT_DESIGNSPARK_CREATOR
@ PRODUCT_DESIGNSPARK_PRO
wxString ToKiCadMarkup(const wxString &aText)
A displayed string in KiCad's markup.
constexpr int ANGLE_FULL_TURN
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
The document: OLE items, then the design.
A TrueType font, which the importers cannot measure.
VECTOR2< int32_t > VECTOR2I