36 std::function<
const float&(
const float&,
const float& ) > comparator );
39 float aStep,
const float* aCurvePoints,
float aSegmentationThreshold,
40 std::vector< VECTOR2D >& aGeneratedPoints );
42 const VECTOR2D& aEnd,
float aOffset,
float aStep,
const float* aCurvePoints,
43 float aSegmentationThreshold, std::vector< VECTOR2D >& aGeneratedPoints );
62 FILE* fp = wxFopen( aFileName, wxT(
"rb" ) );
82 std::string str(
reinterpret_cast<char*
>( aMemBuffer.GetData() ), aMemBuffer.GetDataLen() );
83 wxCHECK( str.data()[aMemBuffer.GetDataLen()] ==
'\0',
false );
97 [](
unsigned int color )
102 for( NSVGshape* shape =
m_parsedImage->shapes; shape !=
nullptr; shape = shape->next )
104 if( !( shape->flags & NSVG_FLAGS_VISIBLE ) )
107 if( shape->stroke.type == NSVG_PAINT_NONE && shape->fill.type == NSVG_PAINT_NONE )
110 double lineWidth = shape->stroke.type != NSVG_PAINT_NONE ? shape->strokeWidth : -1;
111 bool filled = shape->fill.type != NSVG_PAINT_NONE && alpha( shape->fill.color ) > 0;
115 if( shape->fill.type == NSVG_PAINT_COLOR )
117 unsigned int icolor = shape->fill.color;
119 fillColor.
r = std::clamp( ( icolor >> 0 ) & 0xFF, 0u, 255u ) / 255.0;
120 fillColor.
g = std::clamp( ( icolor >> 8 ) & 0xFF, 0u, 255u ) / 255.0;
121 fillColor.
b = std::clamp( ( icolor >> 16 ) & 0xFF, 0u, 255u ) / 255.0;
122 fillColor.
a = std::clamp( ( icolor >> 24 ) & 0xFF, 0u, 255u ) / 255.0;
131 if( shape->stroke.type == NSVG_PAINT_COLOR )
133 unsigned int icolor = shape->stroke.color;
135 strokeColor.
r = std::clamp( ( icolor >> 0 ) & 0xFF, 0u, 255u ) / 255.0;
136 strokeColor.
g = std::clamp( ( icolor >> 8 ) & 0xFF, 0u, 255u ) / 255.0;
137 strokeColor.
b = std::clamp( ( icolor >> 16 ) & 0xFF, 0u, 255u ) / 255.0;
138 strokeColor.
a = std::clamp( ( icolor >> 24 ) & 0xFF, 0u, 255u ) / 255.0;
147 if( shape->strokeDashCount > 0 )
149 float* dashArray = shape->strokeDashArray;
154 const float dashThreshold = shape->strokeWidth * 1.9f;
156 for(
int i = 0; i < shape->strokeDashCount; i += 2 )
158 if( dashArray[i] < dashThreshold )
164 if( dotCount > 0 && dashCount == 0 )
166 else if( dotCount == 0 && dashCount > 0 )
168 else if( dotCount == 1 && dashCount == 1 )
170 else if( dotCount == 2 && dashCount == 1 )
178 switch( shape->fillRule )
189 if( filled && !
path->closed )
195 const bool closed =
true;
208 const bool closed =
path->closed || filled;
227 wxASSERT_MSG(
false, wxT(
"Image must have been loaded before checking height" ) );
239 wxASSERT_MSG(
false, wxT(
"Image must have been loaded before checking width" ) );
253 wxASSERT_MSG(
false, wxT(
"Image must have been loaded before getting bbox" ) );
257 for( NSVGshape* shape =
m_parsedImage->shapes; shape !=
nullptr; shape = shape->next )
260 float( &bounds )[4] = shape->bounds;
262 shapeBbox.
SetOrigin( bounds[0], bounds[1] );
263 shapeBbox.
SetEnd( bounds[2], bounds[3] );
265 bbox.
Merge( shapeBbox );
273 std::vector<VECTOR2D>& aGeneratedPoints )
279 if( aGeneratedPoints.size() == 0 || aGeneratedPoints.back() != start )
280 aGeneratedPoints.push_back( start );
283 aGeneratedPoints.push_back(
end );
288 std::vector<VECTOR2D>& aGeneratedPoints )
290 const int pointsPerSegment = 4;
291 const int curveSpecificPointsPerSegment = 3;
292 const int curveSpecificCoordinatesPerSegment = 2 * curveSpecificPointsPerSegment;
293 const float* currentPoints = aPoints;
294 int remainingPoints = aNumPoints;
296 while( remainingPoints >= pointsPerSegment )
299 currentPoints += curveSpecificCoordinatesPerSegment;
300 remainingPoints -= curveSpecificPointsPerSegment;
309 bool drewPolygon =
false;
314 std::vector<VECTOR2D> collectedPathPoints;
319 if( collectedPathPoints.size() > 2 )
321 DrawPolygon( collectedPathPoints, aStroke, aFilled, aFillColor );
339 const int pointsPerSegment = 4;
340 const int curveSpecificPointsPerSegment = 3;
341 const int curveSpecificCoordinatesPerSegment = 2 * curveSpecificPointsPerSegment;
342 const float* currentCoords = aCoords;
343 int remainingPoints = aNumPoints;
345 while( remainingPoints >= pointsPerSegment )
355 currentCoords += curveSpecificCoordinatesPerSegment;
356 remainingPoints -= curveSpecificPointsPerSegment;
372 unsigned int numLineStartPoints = aPoints.size() - 1;
374 for(
unsigned int pointIndex = 0; pointIndex < numLineStartPoints; ++pointIndex )
381 return VECTOR2D( aPointCoordinates[0], aPointCoordinates[1] );
387 const int coordinatesPerPoint = 2;
389 auto firstCubicPoint =
getPoint( aPoints );
390 auto secondCubicPoint =
getPoint( aPoints + 1 * coordinatesPerPoint );
391 auto thirdCubicPoint =
getPoint( aPoints + 2 * coordinatesPerPoint );
392 auto fourthCubicPoint =
getPoint( aPoints + 3 * coordinatesPerPoint );
394 auto firstQuadraticPoint =
getPointInLine( firstCubicPoint, secondCubicPoint, aStep );
395 auto secondQuadraticPoint =
getPointInLine( secondCubicPoint, thirdCubicPoint, aStep );
396 auto thirdQuadraticPoint =
getPointInLine( thirdCubicPoint, fourthCubicPoint, aStep );
398 auto firstLinearPoint =
getPointInLine( firstQuadraticPoint, secondQuadraticPoint, aStep );
399 auto secondLinearPoint =
getPointInLine( secondQuadraticPoint, thirdQuadraticPoint, aStep );
401 return getPointInLine( firstLinearPoint, secondLinearPoint, aStep );
408 return aLineStart + ( aLineEnd - aLineStart ) * aDistance;
414 using comparatorFunction =
const float&(*)(
const float&,
const float& );
416 auto minimumComparator =
static_cast< comparatorFunction
>( &std::min );
417 auto maximumComparator =
static_cast< comparatorFunction
>( &std::max );
421 VECTOR2D boundingBoxDimensions = maximum - minimum;
423 return 0.001 * std::max( boundingBoxDimensions.
x, boundingBoxDimensions.
y );
428 std::function<
const float&(
const float&,
const float& ) > comparator )
430 float x = aCurvePoints[0];
431 float y = aCurvePoints[1];
433 for(
int pointIndex = 1; pointIndex < 3; ++pointIndex )
435 x = comparator( x, aCurvePoints[ 2 * pointIndex ] );
436 y = comparator( y, aCurvePoints[ 2 * pointIndex + 1 ] );
444 float aStep,
const float* aCurvePoints,
445 float aSegmentationThreshold,
446 std::vector< VECTOR2D >& aGeneratedPoints )
451 if( distanceToPreviousSegment > aSegmentationThreshold )
454 aSegmentationThreshold, aGeneratedPoints );
460 const VECTOR2D& aEnd,
float aOffset,
float aStep,
461 const float* aCurvePoints,
float aSegmentationThreshold,
462 std::vector< VECTOR2D >& aGeneratedPoints )
464 float newStep = aStep / 2.f;
465 float offsetAfterMiddle = aOffset + aStep;
467 segmentBezierCurve( aStart, aMiddle, aOffset, newStep, aCurvePoints, aSegmentationThreshold,
470 aGeneratedPoints.push_back( aMiddle );
473 aSegmentationThreshold, aGeneratedPoints );
480 auto lineDirection = aLineEnd - aLineStart;
485 if( lineDirection.x == 0.0 && lineDirection.y == 0.0 )
488 auto lineNormal = lineDirection.Perpendicular().Resize( 1.f );
489 auto lineStartToPoint = aPoint - aLineStart;
491 auto distance = lineNormal.Dot( lineStartToPoint );
constexpr void SetOrigin(const Vec &pos)
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr void SetEnd(coord_type x, coord_type y)
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
static const COLOR4D BLACK
GRAPHICS_IMPORTER * m_importer
Importer used to create objects representing the imported shapes.
A clone of IMPORTED_STROKE, but with floating-point width.
A color representation with 4 components: red, green, blue, alpha.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
void DrawPolygon(const std::vector< VECTOR2D > &aPoints, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor)
virtual BOX2D GetImageBBox() const override
Return image bounding box from original imported file.
GRAPHICS_IMPORTER_BUFFER m_internalImporter
struct NSVGimage * m_parsedImage
void DrawLineSegments(const std::vector< VECTOR2D > &aPoints, const IMPORTED_STROKE &aStroke)
bool Import() override
Actually imports the file.
virtual double GetImageWidth() const override
Return image width from original imported file.
bool LoadFromMemory(const wxMemoryBuffer &aMemBuffer) override
Set memory buffer with content for import.
bool Load(const wxString &aFileName) override
Load file for import.
virtual double GetImageHeight() const override
Return image height from original imported file.
void DrawSplinePath(const float *aPoints, int aNumPoints, const IMPORTED_STROKE &aStroke)
Draw a path made up of cubic Bezier curves, adding them as real bezier curves.
void DrawPath(const float *aPoints, int aNumPoints, bool aClosedPath, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor)
void ReportMsg(const wxString &aMessage) override
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
LINE_STYLE
Dashed line types.
static void segmentBezierCurve(const VECTOR2D &aStart, const VECTOR2D &aEnd, float aOffset, float aStep, const float *aCurvePoints, float aSegmentationThreshold, std::vector< VECTOR2D > &aGeneratedPoints)
static float distanceFromPointToLine(const VECTOR2D &aPoint, const VECTOR2D &aLineStart, const VECTOR2D &aLineEnd)
static VECTOR2D getPointInLine(const VECTOR2D &aLineStart, const VECTOR2D &aLineEnd, float aDistance)
static VECTOR2D getBezierPoint(const float *aCurvePoints, float aStep)
static VECTOR2D calculateBezierBoundingBoxExtremity(const float *aCurvePoints, std::function< const float &(const float &, const float &) > comparator)
static void GatherInterpolatedCubicBezierCurve(const float *aPoints, std::vector< VECTOR2D > &aGeneratedPoints)
static void createNewBezierCurveSegments(const VECTOR2D &aStart, const VECTOR2D &aMiddle, const VECTOR2D &aEnd, float aOffset, float aStep, const float *aCurvePoints, float aSegmentationThreshold, std::vector< VECTOR2D > &aGeneratedPoints)
static VECTOR2D getPoint(const float *aPointCoordinates)
static float calculateBezierSegmentationThreshold(const float *aCurvePoints)
static void GatherInterpolatedCubicBezierPath(const float *aPoints, int aNumPoints, std::vector< VECTOR2D > &aGeneratedPoints)
VECTOR2< double > VECTOR2D