KiCad PCB EDA Suite
Loading...
Searching...
No Matches
outline_decomposer.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 The 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, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <advanced_config.h>
25#include <bezier_curves.h>
26
27using namespace KIFONT;
28
30 m_outline( aOutline ),
31 m_contours( nullptr )
32{
33}
34
35
36static VECTOR2D toVector2D( const FT_Vector* aFreeTypeVector )
37{
38 return VECTOR2D( (double) aFreeTypeVector->x * GLYPH_SIZE_SCALER,
39 (double) aFreeTypeVector->y * GLYPH_SIZE_SCALER );
40}
41
42
44{
45 CONTOUR contour;
46 contour.m_Orientation = FT_Outline_Get_Orientation( &m_outline );
47 m_contours->push_back( std::move( contour ) );
48}
49
50
52{
53 // don't add repeated points
54 if( m_contours->back().m_Points.empty() || m_contours->back().m_Points.back() != p )
55 m_contours->back().m_Points.push_back( p );
56}
57
58
59int OUTLINE_DECOMPOSER::moveTo( const FT_Vector* aEndPoint, void* aCallbackData )
60{
61 OUTLINE_DECOMPOSER* decomposer = static_cast<OUTLINE_DECOMPOSER*>( aCallbackData );
62
63 decomposer->m_lastEndPoint = toVector2D( aEndPoint );
64
65 decomposer->newContour();
66 decomposer->addContourPoint( decomposer->m_lastEndPoint );
67
68 return 0;
69}
70
71
72int OUTLINE_DECOMPOSER::lineTo( const FT_Vector* aEndPoint, void* aCallbackData )
73{
74 OUTLINE_DECOMPOSER* decomposer = static_cast<OUTLINE_DECOMPOSER*>( aCallbackData );
75
76 decomposer->m_lastEndPoint = toVector2D( aEndPoint );
77
78 decomposer->addContourPoint( decomposer->m_lastEndPoint );
79
80 return 0;
81}
82
83
84int OUTLINE_DECOMPOSER::quadraticTo( const FT_Vector* aControlPoint, const FT_Vector* aEndPoint,
85 void* aCallbackData )
86{
87 return cubicTo( aControlPoint, nullptr, aEndPoint, aCallbackData );
88}
89
90
91int OUTLINE_DECOMPOSER::cubicTo( const FT_Vector* aFirstControlPoint,
92 const FT_Vector* aSecondControlPoint, const FT_Vector* aEndPoint,
93 void* aCallbackData )
94{
95 OUTLINE_DECOMPOSER* decomposer = static_cast<OUTLINE_DECOMPOSER*>( aCallbackData );
96
97 std::vector<VECTOR2D> bezier;
98 bezier.push_back( decomposer->m_lastEndPoint );
99 bezier.push_back( toVector2D( aFirstControlPoint ) );
100
101 if( aSecondControlPoint )
102 {
103 // aSecondControlPoint == nullptr for quadratic Beziers
104 bezier.push_back( toVector2D( aSecondControlPoint ) );
105 }
106
107 bezier.push_back( toVector2D( aEndPoint ) );
108
109 std::vector<VECTOR2D> result;
110 BEZIER_POLY converter( bezier );
111 converter.GetPoly( result, ADVANCED_CFG::GetCfg().m_FontErrorSize );
112
113 for( const VECTOR2D& p : result )
114 decomposer->addContourPoint( p );
115
116 decomposer->m_lastEndPoint = toVector2D( aEndPoint );
117
118 return 0;
119}
120
121
122bool OUTLINE_DECOMPOSER::OutlineToSegments( std::vector<CONTOUR>* aContours )
123{
124 m_contours = aContours;
125
126 FT_Outline_Funcs callbacks;
127
128 callbacks.move_to = moveTo;
129 callbacks.line_to = lineTo;
130 callbacks.conic_to = quadraticTo;
131 callbacks.cubic_to = cubicTo;
132 callbacks.shift = 0;
133 callbacks.delta = 0;
134
135 FT_Error e = FT_Outline_Decompose( &m_outline, &callbacks, this );
136
137 if( e )
138 return false;
139
140 for( CONTOUR& c : *m_contours )
141 c.m_Winding = winding( c.m_Points );
142
143 return true;
144}
145
146
147int OUTLINE_DECOMPOSER::winding( const std::vector<VECTOR2D>& aContour ) const
148{
149 // -1 == counterclockwise, 1 == clockwise
150
151 const int cw = 1;
152 const int ccw = -1;
153
154 if( aContour.size() < 2 )
155 {
156 // zero or one points, so not a clockwise contour - in fact not a contour at all
157 //
158 // It could also be argued that a contour needs 3 extremum points at a minimum to be
159 // considered a proper contour (ie. a glyph (subpart) outline, or a hole)
160 return 0;
161 }
162
163 double sum = 0.0;
164 size_t len = aContour.size();
165
166 for( size_t i = 0; i < len - 1; i++ )
167 {
168 VECTOR2D p1 = aContour[ i ];
169 VECTOR2D p2 = aContour[ i + 1 ];
170
171 sum += ( ( p2.x - p1.x ) * ( p2.y + p1.y ) );
172 }
173
174 sum += ( ( aContour[0].x - aContour[len - 1].x ) * ( aContour[0].y + aContour[len - 1].y ) );
175
176 if( sum > 0.0 )
177 return cw;
178 if( sum < 0.0 )
179 return ccw;
180
181 return 0;
182}
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
void addContourPoint(const VECTOR2D &p)
OUTLINE_DECOMPOSER(FT_Outline &aOutline)
std::vector< CONTOUR > * m_contours
static int cubicTo(const FT_Vector *aFirstControlPoint, const FT_Vector *aSecondControlPoint, const FT_Vector *aEndPoint, void *aCallbackData)
static int moveTo(const FT_Vector *aEndPoint, void *aCallbackData)
bool OutlineToSegments(std::vector< CONTOUR > *aContours)
static int lineTo(const FT_Vector *aEndPoint, void *aCallbackData)
static int quadraticTo(const FT_Vector *aControlPoint, const FT_Vector *aEndPoint, void *aCallbackData)
int winding(const std::vector< VECTOR2D > &aContour) const
constexpr double GLYPH_SIZE_SCALER
static VECTOR2D toVector2D(const FT_Vector *aFreeTypeVector)
FT_Orientation m_Orientation
bool cw
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D
Definition vector2d.h:682