26#include <harfbuzz/hb.h> 
   27#include <harfbuzz/hb-ft.h> 
   34#include FT_SFNT_NAMES_H 
   35#include FT_TRUETYPE_TABLES_H 
   63    TT_OS2* os2 = 
reinterpret_cast<TT_OS2*
>( FT_Get_Sfnt_Table( 
m_face, FT_SFNT_OS2 ) );
 
   70    if( os2->fsType == FT_FSTYPE_INSTALLABLE_EMBEDDING )
 
   74    if( os2->fsType & FT_FSTYPE_BITMAP_EMBEDDING_ONLY )
 
   78    if( os2->fsType & FT_FSTYPE_EDITABLE_EMBEDDING )
 
   82    if( os2->fsType & FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING )
 
 
   91                                      const std::vector<wxString>* aEmbeddedFiles,
 
   92                                      bool aForDrawingSheet )
 
   94    std::unique_ptr<OUTLINE_FONT> font = std::make_unique<OUTLINE_FONT>();
 
  101    fc::FF_RESULT retval = 
Fontconfig()->
FindFont( aFontName, fontFile, faceIndex, aBold, aItalic,
 
  104    if( retval == fc::FF_RESULT::FF_ERROR )
 
  107    if( retval == fc::FF_RESULT::FF_MISSING_BOLD || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
 
  110    if( retval == fc::FF_RESULT::FF_MISSING_ITAL || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
 
  113    if( font->loadFace( fontFile, faceIndex ) != 0 )
 
  116    font->m_fontName = aFontName;       
 
  117    font->m_fontFileName = fontFile;
 
  118    font->m_forDrawingSheet = aForDrawingSheet;
 
  120    return font.release();
 
 
  128    FT_Error e = FT_New_Face( 
m_freeType, aFontFileName.mb_str( wxConvUTF8 ), aFaceIndex, &
m_face );
 
  132        FT_Select_Charmap( 
m_face, FT_Encoding::FT_ENCODING_UNICODE );
 
 
  148    double glyphToFontHeight = 1.0;
 
  153    return aFontMetrics.
GetInterline( aGlyphHeight * glyphToFontHeight );
 
 
  161    case FT_ORIENTATION_TRUETYPE:   
return c.
m_Winding == 1;
 
  162    case FT_ORIENTATION_POSTSCRIPT: 
return c.
m_Winding == -1;
 
  163    default:                        
return false;
 
 
  181    for( 
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
 
  183        BOX2D bbox = glyph->BoundingBox();
 
  186        if( minX > bbox.
GetX() )
 
  189        if( minY > bbox.
GetY() )
 
 
  207                                     const wxString& aText, 
const VECTOR2I& aPosition,
 
  209                                     const METRICS& aFontMetrics )
 const 
  211    wxArrayString         strings;
 
  212    std::vector<VECTOR2I> positions;
 
  213    std::vector<VECTOR2I> extents;
 
  219    getLinePositions( aText, aPosition, strings, positions, extents, aAttrs, aFontMetrics );
 
  221    for( 
size_t i = 0; i < strings.GetCount(); i++ )
 
  223        (void) 
drawMarkup( 
nullptr, aGlyphs, strings.Item( i ), positions[i], aAttrs.
m_Size,
 
 
  230                                        const wxString& aText, 
const VECTOR2I& aSize,
 
  232                                        bool aMirror, 
const VECTOR2I& aOrigin,
 
  237    constexpr double TAB_WIDTH = 4 * 0.6;
 
  245        aBBox->
SetEnd( aPosition );
 
  248    for( wxUniChar c : aText )
 
  253            if( !textRun.IsEmpty() )
 
  255                position = 
getTextAsGlyphs( aBBox, aGlyphs, textRun, aSize, position, aAngle,
 
  256                                            aMirror, aOrigin, aTextStyle );
 
  260            int tabWidth = 
KiROUND( aSize.
x * TAB_WIDTH );
 
  261            int currentIntrusion = ( position.
x - aOrigin.
x ) % tabWidth;
 
  263            position.
x += tabWidth - currentIntrusion;
 
  271    if( !textRun.IsEmpty() )
 
  273        position = 
getTextAsGlyphs( aBBox, aGlyphs, textRun, aSize, position, aAngle, aMirror,
 
  274                                    aOrigin, aTextStyle );
 
 
  282                                        const wxString& aText, 
const VECTOR2I& aSize,
 
  284                                        bool aMirror, 
const VECTOR2I& aOrigin,
 
  290                                    aOrigin, aTextStyle );
 
 
  332    static std::unordered_map<HARFBUZZ_CACHE_KEY, HARFBUZZ_CACHE_ENTRY> s_harfbuzzCache;
 
  334    std::string textUtf8 = 
UTF8( aText );
 
  341        hb_buffer_t* buf = hb_buffer_create();
 
  342        hb_buffer_add_utf8( buf, textUtf8.c_str(), -1, 0, -1 );
 
  343        hb_buffer_guess_segment_properties( buf );  
 
  346        hb_font_t* referencedFont = hb_ft_font_create_referenced( aFace );
 
  347        hb_ft_font_set_funcs( referencedFont );
 
  348        hb_shape( referencedFont, buf, 
nullptr, 0 );
 
  350        unsigned int         glyphCount;
 
  351        hb_glyph_info_t*     glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
 
  352        hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
 
  354        entry.
m_GlyphInfo.assign( glyphInfo, glyphInfo + glyphCount );
 
  358        hb_buffer_destroy( buf );
 
  359        hb_font_destroy( referencedFont );
 
 
  407                                                std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
 
  408                                                const wxString& aText, 
const VECTOR2I& aSize,
 
  410                                                bool aMirror, 
const VECTOR2I& aOrigin,
 
  426    unsigned int glyphCount = 
static_cast<unsigned int>( hbShape.
m_GlyphInfo.size() );
 
  427    const hb_glyph_info_t* glyphInfo = hbShape.
m_GlyphInfo.data();
 
  436        aGlyphs->reserve( glyphCount );
 
  440    static std::unordered_map<GLYPH_CACHE_KEY, GLYPH_DATA> s_glyphCache;
 
  442    for( 
unsigned int i = 0; i < glyphCount; i++ )
 
  445        if( i > 0 && glyphInfo[i].cluster == glyphInfo[i-1].cluster )
 
  460                    const float angle = (float)( -
M_PI * 12.0f ) / 180.0f;
 
  461                    matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
 
  462                    matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
 
  463                    matrix.yx = (FT_Fixed) ( 0 * 0x10000L );  
 
  464                    matrix.yy = (FT_Fixed) ( 1 * 0x10000L );
 
  466                    FT_Set_Transform( face, &matrix, 
nullptr );
 
  469                FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
 
  472                    FT_Outline_Embolden( &face->glyph->outline, 1 << 6 );
 
  479                    BOX2D   tofuBox( { scaler * 0.03, 0.0 },
 
  480                                     { hb_advance - scaler * 0.02, scaler * 0.72 } );
 
  487                    outline.
m_Points.push_back( tofuBox.GetPosition() );
 
  488                    outline.
m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
 
  489                    outline.
m_Points.push_back( tofuBox.GetSize() );
 
  490                    outline.
m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
 
  491                    glyphData.
m_Contours.push_back( std::move( outline ) );
 
  494                    tofuBox.Move( { scaler * 0.06, scaler * 0.06 } );
 
  495                    tofuBox.SetSize( { tofuBox.GetWidth() - scaler * 0.06,
 
  496                                       tofuBox.GetHeight() - scaler * 0.06 } );
 
  499                    hole.
m_Points.push_back( tofuBox.GetPosition() );
 
  500                    hole.
m_Points.push_back( { tofuBox.GetSize().x, tofuBox.GetPosition().y } );
 
  501                    hole.
m_Points.push_back( tofuBox.GetSize() );
 
  502                    hole.
m_Points.push_back( { tofuBox.GetPosition().x, tofuBox.GetSize().y } );
 
  503                    glyphData.
m_Contours.push_back( std::move( hole ) );
 
  507            std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
 
  508            std::vector<SHAPE_LINE_CHAIN>  holes;
 
  512                std::vector<VECTOR2D> points = c.
m_Points;
 
  530                        pt.
x = aOrigin.
x - ( pt.
x - aOrigin.
x );
 
  541                    holes.push_back( std::move( shape ) );
 
  543                    glyph->AddOutline( std::move( shape ) );
 
  548                bool added_hole = 
false;
 
  550                if( hole.PointCount() )
 
  552                    for( 
int ii = 0; ii < glyph->OutlineCount(); ++ii )
 
  554                        if( glyph->Outline( ii ).PointInside( hole.GetPoint( 0 ) ) )
 
  556                            glyph->AddHole( std::move( hole ), ii );
 
  566                        glyph->AddOutline( std::move( hole ) );
 
  572                glyph->CacheTriangulation( 
false, 
false );
 
  580            aGlyphs->push_back( std::move( glyph ) );
 
  583        const hb_glyph_position_t& pos = glyphPos[i];
 
  590    VECTOR2I extents( 
cursor.x * scaleFactor.
x, ( ascender + descender ) * abs( scaleFactor.
y ) );
 
  595        aBBox->
Merge( aPosition + extents );
 
  597    return VECTOR2I( aPosition.
x + cursorDisplacement.
x, aPosition.
y + cursorDisplacement.
y );
 
 
  601#undef OUTLINEFONT_RENDER_AS_PIXELS 
  602#ifdef OUTLINEFONT_RENDER_AS_PIXELS 
  606void OUTLINE_FONT::RenderToOpenGLCanvas( 
KIGFX::OPENGL_GAL& aGal, 
const wxString& aString,
 
  608                                         const EDA_ANGLE& aOrientation, 
bool aIsMirrored )
 const 
  610    hb_buffer_t* buf = hb_buffer_create();
 
  611    hb_buffer_add_utf8( buf, 
UTF8( aString ).c_str(), -1, 0, -1 );
 
  614    hb_buffer_guess_segment_properties( buf );
 
  616    unsigned int         glyphCount;
 
  617    hb_glyph_info_t*     glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
 
  618    hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
 
  622    hb_font_t*           referencedFont = hb_ft_font_create_referenced( 
m_face );
 
  624    hb_ft_font_set_funcs( referencedFont );
 
  625    hb_shape( referencedFont, buf, 
nullptr, 0 );
 
  627    const double mirror_factor = ( aIsMirrored ? 1 : -1 );
 
  628    const double x_scaleFactor = mirror_factor * aGlyphSize.
x / mScaler;
 
  629    const double y_scaleFactor = aGlyphSize.
y / mScaler;
 
  631    hb_position_t cursor_x = 0;
 
  632    hb_position_t cursor_y = 0;
 
  634    for( 
unsigned int i = 0; i < glyphCount; i++ )
 
  636        const hb_glyph_position_t& pos = glyphPos[i];
 
  637        int                  codepoint = glyphInfo[i].codepoint;
 
  639        FT_Error e = FT_Load_Glyph( 
m_face, codepoint, FT_LOAD_DEFAULT );
 
  643        e = FT_Get_Glyph( 
m_face->glyph, &glyph );
 
  646        wxPoint pt( aPosition );
 
  647        pt.x += ( cursor_x >> 6 ) * x_scaleFactor;
 
  648        pt.y += ( cursor_y >> 6 ) * y_scaleFactor;
 
  650        cursor_x += pos.x_advance;
 
  651        cursor_y += pos.y_advance;
 
  654    hb_buffer_destroy( buf );
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
constexpr void SetOrigin(const Vec &pos)
 
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
 
constexpr coord_type GetY() const
 
constexpr coord_type GetX() const
 
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
 
constexpr coord_type GetRight() const
 
constexpr void SetEnd(coord_type x, coord_type y)
 
constexpr coord_type GetBottom() const
 
void getLinePositions(const wxString &aText, const VECTOR2I &aPosition, wxArrayString &aTextLines, std::vector< VECTOR2I > &aPositions, std::vector< VECTOR2I > &aExtents, const TEXT_ATTRIBUTES &aAttrs, const METRICS &aFontMetrics) const
 
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 METRICS &aFontMetrics) const
 
double GetInterline(double aFontHeight) const
 
bool OutlineToSegments(std::vector< CONTOUR > *aContours)
 
VECTOR2I getTextAsGlyphsUnlocked(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
 
static std::mutex m_freeTypeMutex
Mutex for freetype access, FT_Library and FT_Face are not thread safe.
 
double GetInterline(double aGlyphHeight, const METRICS &aFontMetrics) const override
Compute the distance (interline) between 2 lines of text (for multiline texts).
 
static FT_Library m_freeType
 
BOX2I getBoundingBox(const std::vector< std::unique_ptr< GLYPH > > &aGlyphs) const
 
FT_Error loadFace(const wxString &aFontFileName, int aFaceIndex)
 
static constexpr double m_superscriptVerticalOffset
 
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
 
int faceSize(int aSize) const
 
void GetLinesAsGlyphs(std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aPosition, const TEXT_ATTRIBUTES &aAttrs, const METRICS &aFontMetrics) const
 
static OUTLINE_FONT * LoadFont(const wxString &aFontFileName, bool aBold, bool aItalic, const std::vector< wxString > *aEmbeddedFiles, bool aForDrawingSheet)
Load an outline font.
 
static constexpr double m_outlineFontSizeCompensation
 
EMBEDDING_PERMISSION GetEmbeddingPermission() const
 
int subscriptSize() const
 
static constexpr double m_subscriptVerticalOffset
 
OpenGL implementation of the Graphics Abstraction Layer.
 
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 ReservePoints(size_t aSize)
Allocate a number of points all at once (for performance).
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
 
FF_RESULT FindFont(const wxString &aFontName, wxString &aFontFile, int &aFaceIndex, bool aBold, bool aItalic, const std::vector< wxString > *aEmbeddedFiles=nullptr)
Given a fully-qualified font name ("Times:Bold:Italic") find the closest matching font and return its...
 
unsigned int TEXT_STYLE_FLAGS
 
bool IsSuperscript(TEXT_STYLE_FLAGS aFlags)
 
bool IsSubscript(TEXT_STYLE_FLAGS aFlags)
 
FONTCONFIG * Fontconfig()
 
static constexpr std::size_t hash_val(const Types &... args)
 
constexpr int GLYPH_RESOLUTION
 
constexpr double GLYPH_SIZE_SCALER
 
static bool contourIsHole(const CONTOUR &c)
 
static bool contourIsFilled(const CONTOUR &c)
 
static const HARFBUZZ_CACHE_ENTRY & getHarfbuzzShape(FT_Face aFace, const wxString &aText, int aScaler)
 
bool operator==(const GLYPH_CACHE_KEY &rhs) const
 
std::vector< hb_glyph_info_t > m_GlyphInfo
 
std::vector< hb_glyph_position_t > m_GlyphPositions
 
bool operator==(const HARFBUZZ_CACHE_KEY &rhs) const
 
std::vector< VECTOR2D > m_Points
 
FT_Orientation m_Orientation
 
std::vector< CONTOUR > m_Contours
 
std::vector< std::unique_ptr< SHAPE_POLY_SET::TRIANGULATED_POLYGON > > m_TriangulationData
 
std::size_t operator()(const GLYPH_CACHE_KEY &k) const
 
std::size_t operator()(const HARFBUZZ_CACHE_KEY &k) const
 
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D