KiCad PCB EDA Suite
outline_font.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2021 Ola Rinta-Koski <[email protected]>
5 * Copyright (C) 2021-2022 Kicad Developers, see AUTHORS.txt for contributors.
6 *
7 * Outline font class
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <limits>
28#include <pgm_base.h>
30#include <harfbuzz/hb.h>
31#include <harfbuzz/hb-ft.h>
32#include <bezier_curves.h>
34#include <eda_text.h>
35#include <font/fontconfig.h>
36#include <font/outline_font.h>
37#include FT_GLYPH_H
38#include FT_BBOX_H
39#include <trigo.h>
40#include <font/fontconfig.h>
42
43using namespace KIFONT;
44
45
46FT_Library OUTLINE_FONT::m_freeType = nullptr;
47
48OUTLINE_FONT::OUTLINE_FONT() :
49 m_face(NULL),
50 m_faceSize( 16 ),
51 m_fakeBold( false ),
52 m_fakeItal( false )
53{
54 if( !m_freeType )
55 FT_Init_FreeType( &m_freeType );
56}
57
58
60{
61 if( !m_freeType )
62 FT_Init_FreeType( &m_freeType );
63
64 FT_Int major = 0;
65 FT_Int minor = 0;
66 FT_Int patch = 0;
67 FT_Library_Version( m_freeType, &major, &minor, &patch );
68
69 return wxString::Format( "%d.%d.%d", major, minor, patch );
70}
71
72
74{
75 return wxString::FromUTF8( HB_VERSION_STRING );
76}
77
78
80{
82}
83
84
86{
87 return wxString::Format( "FreeType %s HarfBuzz %s", FreeTypeVersion(), HarfBuzzVersion() );
88}
89
90
91OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, bool aItalic )
92{
93 OUTLINE_FONT* font = new OUTLINE_FONT();
94
95 wxString fontFile;
96 using fc = fontconfig::FONTCONFIG;
97
98 fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, aBold, aItalic );
99
100 if( retval == fc::FF_RESULT::FF_MISSING_BOLD || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
101 font->SetFakeBold();
102
103 if( retval == fc::FF_RESULT::FF_MISSING_ITAL || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
104 font->SetFakeItal();
105
106 if( retval != fc::FF_RESULT::FF_ERROR )
107 (void) font->loadFace( fontFile );
108
109 font->m_fontName = aFontName; // Keep asked-for name, even if we substituted.
110 font->m_fontFileName = fontFile;
111
112 return font;
113}
114
115
116FT_Error OUTLINE_FONT::loadFace( const wxString& aFontFileName )
117{
118 // TODO: check that going from wxString to char* with UTF-8
119 // conversion for filename makes sense on any/all platforms
120 FT_Error e = FT_New_Face( m_freeType, aFontFileName.mb_str( wxConvUTF8 ), 0, &m_face );
121
122 if( !e )
123 {
124 FT_Select_Charmap( m_face, FT_Encoding::FT_ENCODING_UNICODE );
125 // params:
126 // m_face = handle to face object
127 // 0 = char width in 1/64th of points ( 0 = same as char height )
128 // faceSize() = char height in 1/64th of points
129 // GLYPH_RESOLUTION = horizontal device resolution (288dpi, 4x default)
130 // 0 = vertical device resolution ( 0 = same as horizontal )
131 FT_Set_Char_Size( m_face, 0, faceSize(), GLYPH_RESOLUTION, 0 );
132 }
133
134 return e;
135}
136
137
142double OUTLINE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight ) const
143{
144 // The overbar on actual text is positioned above the bounding box of the glyphs. However,
145 // that's expensive to calculate so we use an estimation here (as this is only used for
146 // calculating bounding boxes).
147 return aGlyphHeight * m_outlineFontSizeCompensation;
148}
149
150
155double OUTLINE_FONT::ComputeUnderlineVerticalPosition( double aGlyphHeight ) const
156{
157 return aGlyphHeight * m_underlineOffsetScaler;
158}
159
160
165double OUTLINE_FONT::GetInterline( double aGlyphHeight, double aLineSpacing ) const
166{
167 double pitch = INTERLINE_PITCH_RATIO;
168
169 if( GetFace()->units_per_EM )
170 pitch = GetFace()->height / GetFace()->units_per_EM;
171
172 double interline = aLineSpacing * aGlyphHeight * pitch * m_outlineFontSizeCompensation;
173
174 // FONT TODO this hack is an attempt to fix interline spacing by eyeballing it
175 static constexpr double interlineHackMultiplier = 1.2;
176 interline *= interlineHackMultiplier;
177
178 return interline;
179}
180
181
182static bool contourIsFilled( const CONTOUR& c )
183{
184 switch( c.m_Orientation )
185 {
186 case FT_ORIENTATION_TRUETYPE: return c.m_Winding == 1;
187 case FT_ORIENTATION_POSTSCRIPT: return c.m_Winding == -1;
188 default: return false;
189 }
190}
191
192
193static bool contourIsHole( const CONTOUR& c )
194{
195 return !contourIsFilled( c );
196}
197
198
199BOX2I OUTLINE_FONT::getBoundingBox( const std::vector<std::unique_ptr<GLYPH>>& aGlyphs ) const
200{
201 int minX = INT_MAX;
202 int minY = INT_MAX;
203 int maxX = INT_MIN;
204 int maxY = INT_MIN;
205
206 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
207 {
208 BOX2D bbox = glyph->BoundingBox();
209 bbox.Normalize();
210
211 if( minX > bbox.GetX() )
212 minX = bbox.GetX();
213
214 if( minY > bbox.GetY() )
215 minY = bbox.GetY();
216
217 if( maxX < bbox.GetRight() )
218 maxX = bbox.GetRight();
219
220 if( maxY < bbox.GetBottom() )
221 maxY = bbox.GetBottom();
222 }
223
224 BOX2I ret;
225 ret.SetOrigin( minX, minY );
226 ret.SetEnd( maxX, maxY );
227 return ret;
228}
229
230
231void OUTLINE_FONT::GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
232 const wxString& aText, const VECTOR2I& aPosition,
233 const TEXT_ATTRIBUTES& aAttrs ) const
234{
235 wxArrayString strings;
236 std::vector<VECTOR2I> positions;
237 std::vector<VECTOR2I> extents;
238 TEXT_STYLE_FLAGS textStyle = 0;
239
240 if( aAttrs.m_Italic )
241 textStyle |= TEXT_STYLE::ITALIC;
242
243 getLinePositions( aText, aPosition, strings, positions, extents, aAttrs );
244
245 for( size_t i = 0; i < strings.GetCount(); i++ )
246 {
247 (void) drawMarkup( nullptr, aGlyphs, strings.Item( i ), positions[i], aAttrs.m_Size,
248 aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, textStyle );
249 }
250}
251
252
253VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
254 const wxString& aText, const VECTOR2I& aSize,
255 const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
256 bool aMirror, const VECTOR2I& aOrigin,
257 TEXT_STYLE_FLAGS aTextStyle ) const
258{
259 // HarfBuzz needs further processing to split tab-delimited text into text runs.
260
261 constexpr double TAB_WIDTH = 4 * 0.6;
262
263 VECTOR2I position = aPosition;
264 wxString textRun;
265
266 if( aBBox )
267 {
268 aBBox->SetOrigin( aPosition );
269 aBBox->SetEnd( aPosition );
270 }
271
272 for( wxUniChar c : aText )
273 {
274 // Handle tabs as locked to the nearest 4th column (in space-widths).
275 if( c == '\t' )
276 {
277 if( !textRun.IsEmpty() )
278 {
279 position = getTextAsGlyphs( aBBox, aGlyphs, textRun, aSize, position, aAngle,
280 aMirror, aOrigin, aTextStyle );
281 textRun.clear();
282 }
283
284 int tabWidth = KiROUND( aSize.x * TAB_WIDTH );
285 int currentIntrusion = ( position.x - aOrigin.x ) % tabWidth;
286
287 position.x += tabWidth - currentIntrusion;
288 }
289 else
290 {
291 textRun += c;
292 }
293 }
294
295 if( !textRun.IsEmpty() )
296 {
297 position = getTextAsGlyphs( aBBox, aGlyphs, textRun, aSize, position, aAngle, aMirror,
298 aOrigin, aTextStyle );
299 }
300
301 return position;
302}
303
304
305double OUTLINE_FONT::getOverbarOffset( int ascender, int height, int thickness ) const
306{
307 double thicknessRatio = abs( (double) thickness ) / (double) height;
308 double ascenderRatio = (double) ascender / (double) height;
309
310 if( thicknessRatio < 0.05 )
311 return 0.04;
312 else if( ascenderRatio < 0.78 )
313 return 0.00;
314 else if( ascenderRatio < 0.80 )
315 return -0.03;
316 else
317 return -0.06;
318}
319
320
321VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
322 const wxString& aText, const VECTOR2I& aSize,
323 const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
324 bool aMirror, const VECTOR2I& aOrigin,
325 TEXT_STYLE_FLAGS aTextStyle ) const
326{
327 VECTOR2D glyphSize = aSize;
328 FT_Face face = m_face;
329 double scaler = faceSize();
330
331 if( IsSubscript( aTextStyle ) || IsSuperscript( aTextStyle ) )
332 {
333 scaler = subscriptSize();
334 }
335
336 // set glyph resolution so that FT_Load_Glyph() results are good enough for decomposing
337 FT_Set_Char_Size( face, 0, scaler, GLYPH_RESOLUTION, 0 );
338
339 hb_buffer_t* buf = hb_buffer_create();
340 hb_buffer_add_utf8( buf, UTF8( aText ).c_str(), -1, 0, -1 );
341 hb_buffer_guess_segment_properties( buf ); // guess direction, script, and language based on
342 // contents
343
344 unsigned int glyphCount;
345 hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
346 hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
347
348 hb_font_t* referencedFont = hb_ft_font_create_referenced( face );
349 hb_ft_font_set_funcs( referencedFont );
350 hb_shape( referencedFont, buf, nullptr, 0 );
351
352 VECTOR2D scaleFactor( glyphSize.x / faceSize(), -glyphSize.y / faceSize() );
353 scaleFactor = scaleFactor * m_outlineFontSizeCompensation;
354
355 VECTOR2I cursor( 0, 0 );
356
357 for( unsigned int i = 0; i < glyphCount; i++ )
358 {
359 // Don't process glyphs that were already included in a previous cluster
360 if( i > 0 && glyphInfo[i].cluster == glyphInfo[i-1].cluster )
361 continue;
362
363 if( aGlyphs )
364 {
365 if( m_fakeItal )
366 {
367 FT_Matrix matrix;
368 // Create a 12 degree slant
369 const float angle = ( -M_PI * 12 ) / 180.0f;
370 matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
371 matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
372 matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
373 matrix.yy = (FT_Fixed) ( 1 * 0x10000L );
374
375 FT_Set_Transform(face, &matrix,0);
376 }
377
378 FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
379
380 if( m_fakeBold )
381 FT_Outline_Embolden( &face->glyph->outline, 1 << 6 );
382
383 // contours is a collection of all outlines in the glyph; for example the 'o' glyph
384 // generally contains 2 contours, one for the glyph outline and one for the hole
385 CONTOURS contours;
386
387 OUTLINE_DECOMPOSER decomposer( face->glyph->outline );
388 decomposer.OutlineToSegments( &contours );
389
390 std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
391 std::vector<SHAPE_LINE_CHAIN> holes;
392
393 for( CONTOUR& c : contours )
394 {
395 GLYPH_POINTS points = c.m_Points;
396 SHAPE_LINE_CHAIN shape;
397
398 for( const VECTOR2D& v : points )
399 {
400 VECTOR2D pt( v + cursor );
401
402 if( IsSubscript( aTextStyle ) )
403 pt.y += m_subscriptVerticalOffset * scaler;
404 else if( IsSuperscript( aTextStyle ) )
405 pt.y += m_superscriptVerticalOffset * scaler;
406
407 pt *= scaleFactor;
408 pt += aPosition;
409
410 if( aMirror )
411 pt.x = aOrigin.x - ( pt.x - aOrigin.x );
412
413 if( !aAngle.IsZero() )
414 RotatePoint( pt, aOrigin, aAngle );
415
416 shape.Append( pt.x, pt.y );
417 }
418
419 shape.SetClosed( true );
420
421 if( contourIsHole( c ) )
422 holes.push_back( std::move( shape ) );
423 else
424 glyph->AddOutline( std::move( shape ) );
425 }
426
427 for( SHAPE_LINE_CHAIN& hole : holes )
428 {
429 if( hole.PointCount() )
430 {
431 for( int ii = 0; ii < glyph->OutlineCount(); ++ii )
432 {
433 if( glyph->Outline( ii ).PointInside( hole.GetPoint( 0 ) ) )
434 {
435 glyph->AddHole( std::move( hole ), ii );
436 break;
437 }
438 }
439 }
440 }
441
442 // FONT TODO we might not want to do Fracture() here;
443 // knockout text (eg. silkscreen labels with a background) will
444 // need to do that after the contours have been turned into holes
445 // and vice versa
446 if( glyph->HasHoles() )
447 glyph->Fracture( SHAPE_POLY_SET::PM_FAST ); // FONT TODO verify aFastMode
448
449 aGlyphs->push_back( std::move( glyph ) );
450 }
451
452 hb_glyph_position_t& pos = glyphPos[i];
453 cursor.x += ( pos.x_advance * GLYPH_SIZE_SCALER );
454 cursor.y += ( pos.y_advance * GLYPH_SIZE_SCALER );
455 }
456
457 int ascender = abs( face->size->metrics.ascender * GLYPH_SIZE_SCALER );
458 int height = abs( face->size->metrics.height * GLYPH_SIZE_SCALER );
459 int descender = abs( face->size->metrics.descender * GLYPH_SIZE_SCALER );
460 VECTOR2I extents( cursor.x * scaleFactor.x, ( ascender + descender ) * abs( scaleFactor.y ) );
461
462 // Font metrics don't include all descenders and diacriticals, so beef them up just a little.
463 extents.y *= 1.05;
464
465 if( IsOverbar( aTextStyle ) )
466 {
467 std::vector<std::unique_ptr<GLYPH>> underscoreGlyphs;
468
469 getTextAsGlyphs( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
470 { 0, 0 }, aTextStyle & ~TEXT_STYLE::OVERBAR );
471
472 OUTLINE_GLYPH* underscoreGlyph = static_cast<OUTLINE_GLYPH*>( underscoreGlyphs[0].get() );
473 BOX2I underscoreBBox;
474
475 for( const VECTOR2I& pt : underscoreGlyph->Outline( 0 ).CPoints() )
476 underscoreBBox.Merge( pt );
477
478 int barThickness = underscoreBBox.GetHeight();
479
480 // Shorten the bar a little so its rounded ends don't make it over-long
481 double barTrim = barThickness / 2.0;
482 double barOffset = getOverbarOffset( ascender, height, barThickness / scaleFactor.y );
483
484 VECTOR2I topLeft( aPosition );
485 VECTOR2I topRight( aPosition );
486
487 topLeft.y += ascender * scaleFactor.y * ( 1.0 + barOffset );
488 topRight.y = topLeft.y;
489
490 topLeft.x += barTrim;
491 topRight.x += extents.x - barTrim;
492
493 extents.y *= ( 1.0 + barOffset + barOffset );
494 extents.x += barTrim;
495
496 if( IsItalic() )
497 {
498 topLeft.x += aSize.y * ITALIC_TILT;
499 topRight.x += aSize.y * ITALIC_TILT;
500 extents.x += aSize.y * ITALIC_TILT;
501 }
502
503 if( aMirror )
504 {
505 topLeft.x = aOrigin.x - ( topLeft.x - aOrigin.x );
506 topRight.x = aOrigin.x - ( topRight.x - aOrigin.x );
507 }
508
509 if( !aAngle.IsZero() )
510 {
511 RotatePoint( topLeft, aOrigin, aAngle );
512 RotatePoint( topRight, aOrigin, aAngle );
513 }
514
515 if( aGlyphs )
516 {
517 int maxError = KiROUND( barThickness / 48 );
518 SHAPE_POLY_SET poly;
519
520 TransformOvalToPolygon( poly, topLeft, topRight, barThickness, maxError, ERROR_INSIDE );
521
522 std::unique_ptr<OUTLINE_GLYPH> overbarGlyph = std::make_unique<OUTLINE_GLYPH>( poly );
523 aGlyphs->push_back( std::move( overbarGlyph ) );
524 }
525 }
526
527 hb_buffer_destroy( buf );
528 hb_font_destroy( referencedFont );
529
530 VECTOR2I cursorDisplacement( cursor.x * scaleFactor.x, -cursor.y * scaleFactor.y );
531
532 if( aBBox )
533 aBBox->Merge( aPosition + extents );
534
535 return VECTOR2I( aPosition.x + cursorDisplacement.x, aPosition.y + cursorDisplacement.y );
536}
537
538
539#undef OUTLINEFONT_RENDER_AS_PIXELS
540#ifdef OUTLINEFONT_RENDER_AS_PIXELS
541/*
542 * WIP: eeschema (and PDF output?) should use pixel rendering instead of linear segmentation
543 */
544void OUTLINE_FONT::RenderToOpenGLCanvas( KIGFX::OPENGL_GAL& aGal, const wxString& aString,
545 const VECTOR2D& aGlyphSize, const VECTOR2I& aPosition,
546 const EDA_ANGLE& aOrientation, bool aIsMirrored ) const
547{
548 hb_buffer_t* buf = hb_buffer_create();
549 hb_buffer_add_utf8( buf, UTF8( aString ).c_str(), -1, 0, -1 );
550 hb_buffer_guess_segment_properties( buf ); // guess direction, script, and language based on contents
551
552 unsigned int glyphCount;
553 hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
554 hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
555 hb_font_t* referencedFont = hb_ft_font_create_referenced( m_face );
556
557 hb_ft_font_set_funcs( referencedFont );
558 hb_shape( referencedFont, buf, nullptr, 0 );
559
560 const double mirror_factor = ( aIsMirrored ? 1 : -1 );
561 const double x_scaleFactor = mirror_factor * aGlyphSize.x / mScaler;
562 const double y_scaleFactor = aGlyphSize.y / mScaler;
563
564 hb_position_t cursor_x = 0;
565 hb_position_t cursor_y = 0;
566
567 for( unsigned int i = 0; i < glyphCount; i++ )
568 {
569 hb_glyph_position_t& pos = glyphPos[i];
570 int codepoint = glyphInfo[i].codepoint;
571
572 FT_Error e = FT_Load_Glyph( m_face, codepoint, FT_LOAD_DEFAULT );
573 // TODO handle FT_Load_Glyph error
574
575 FT_Glyph glyph;
576 e = FT_Get_Glyph( m_face->glyph, &glyph );
577 // TODO handle FT_Get_Glyph error
578
579 wxPoint pt( aPosition );
580 pt.x += ( cursor_x >> 6 ) * x_scaleFactor;
581 pt.y += ( cursor_y >> 6 ) * y_scaleFactor;
582
583 cursor_x += pos.x_advance;
584 cursor_y += pos.y_advance;
585 }
586
587 hb_buffer_destroy( buf );
588}
589#endif //OUTLINEFONT_RENDER_AS_PIXELS
void SetOrigin(const Vec &pos)
Definition: box2.h:202
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetY() const
Definition: box2.h:181
coord_type GetX() const
Definition: box2.h:180
coord_type GetRight() const
Definition: box2.h:189
coord_type GetBottom() const
Definition: box2.h:190
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:255
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
bool IsZero() const
Definition: eda_angle.h:169
wxString m_fontName
Font name.
Definition: font.h:262
wxString m_fontFileName
Font file name.
Definition: font.h:263
void getLinePositions(const wxString &aText, const VECTOR2I &aPosition, wxArrayString &aTextLines, std::vector< VECTOR2I > &aPositions, std::vector< VECTOR2I > &aExtents, const TEXT_ATTRIBUTES &aAttrs) const
Definition: font.cpp:94
VECTOR2I drawMarkup(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle) const
Definition: font.cpp:233
static constexpr double INTERLINE_PITCH_RATIO
Definition: font.h:256
void OutlineToSegments(CONTOURS *aContours)
Class OUTLINE_FONT implements outline font drawing.
Definition: outline_font.h:50
FT_Error loadFace(const wxString &aFontFileName)
static FT_Library m_freeType
Definition: outline_font.h:138
BOX2I getBoundingBox(const std::vector< std::unique_ptr< GLYPH > > &aGlyphs) const
static constexpr double m_superscriptVerticalOffset
Definition: outline_font.h:181
static wxString FreeTypeVersion()
VECTOR2I getTextAsGlyphs(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aSize, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle) const
VECTOR2I GetTextAsGlyphs(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aSize, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle) const override
Convert text string to an array of GLYPHs.
const FT_Face & GetFace() const
Definition: outline_font.h:116
double GetInterline(double aGlyphHeight=0.0, double aLineSpacing=1.0) const override
Compute the distance (interline) between 2 lines of text (for multiline texts).
static wxString FontConfigVersion()
bool IsItalic() const override
Definition: outline_font.h:69
void GetLinesAsGlyphs(std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aPosition, const TEXT_ATTRIBUTES &aAttrs) const
double ComputeUnderlineVerticalPosition(double aGlyphHeight) const override
Compute the vertical position of an underline.
double getOverbarOffset(int ascender, int height, int thickness) const
int faceSize() const
Definition: outline_font.h:171
static constexpr double m_outlineFontSizeCompensation
Definition: outline_font.h:153
static constexpr double m_underlineOffsetScaler
Definition: outline_font.h:165
double ComputeOverbarVerticalPosition(double aGlyphHeight) const override
Compute the vertical position of an overbar.
int subscriptSize() const
Definition: outline_font.h:178
static wxString FontLibraryVersion()
static wxString HarfBuzzVersion()
static OUTLINE_FONT * LoadFont(const wxString &aFontFileName, bool aBold, bool aItalic)
Load an outline font.
static constexpr double m_subscriptVerticalOffset
Definition: outline_font.h:180
OpenGL implementation of the Graphics Abstraction Layer.
Definition: opengl_gal.h:70
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:71
static wxString Version()
Definition: fontconfig.cpp:40
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:423
TEXT_STYLE
Definition: font.h:44
@ OVERBAR
Definition: font.h:49
@ ITALIC
Definition: font.h:46
unsigned int TEXT_STYLE_FLAGS
Definition: font.h:63
bool IsOverbar(TEXT_STYLE_FLAGS aFlags)
Definition: font.h:90
bool IsSuperscript(TEXT_STYLE_FLAGS aFlags)
Definition: font.h:78
static constexpr double ITALIC_TILT
Tilt factor for italic style (this is the scaling factor on dY relative coordinates to give a tilted ...
Definition: font.h:60
bool IsSubscript(TEXT_STYLE_FLAGS aFlags)
Definition: font.h:84
FONTCONFIG * Fontconfig()
Definition: fontconfig.cpp:52
@ ERROR_INSIDE
Definition: font.h:100
constexpr int GLYPH_RESOLUTION
Definition: glyph.h:41
std::vector< CONTOUR > CONTOURS
constexpr double GLYPH_SIZE_SCALER
Definition: glyph.h:42
std::vector< VECTOR2D > GLYPH_POINTS
Definition: glyph.h:110
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:412
static bool contourIsHole(const CONTOUR &c)
static bool contourIsFilled(const CONTOUR &c)
see class PGM_BASE
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
FT_Orientation m_Orientation
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618