From 1eeaebd0a9ee6e9c182a825c46aaeb82616c557f Mon Sep 17 00:00:00 2001 From: jmsgrogan Date: Wed, 11 Jan 2023 08:26:08 +0000 Subject: [PATCH] Add bezier rendering. --- src/fonts/FontGlyph.cpp | 45 ++++++++++++++++-------- src/fonts/FontGlyph.h | 22 ++++++++---- src/fonts/directx/DirectWriteHelpers.cpp | 31 +++++++++------- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/fonts/FontGlyph.cpp b/src/fonts/FontGlyph.cpp index f1e9907..a51414d 100644 --- a/src/fonts/FontGlyph.cpp +++ b/src/fonts/FontGlyph.cpp @@ -1,21 +1,22 @@ #include "FontGlyph.h" -void GlyphRunOutlines::addToFeature(const Point& point) +void GlyphRunOutlines::addSegment(const GlyphRunSegment& segment) { - mFeatures[mFeatures.size() - 1].mPoints.push_back(point); + mFeatures[mFeatures.size() - 1].mSegments.push_back(segment); } void GlyphRunOutlines::startFeature(const Point& point, bool isFilled) { - GlyphRunOutline feature; + GlyphRunFeature feature; feature.mFilled = isFilled; - feature.mPoints.push_back(point); - mFeatures.push_back(feature); -} -const std::vector GlyphRunOutlines::getFeatures() const -{ - return mFeatures; + GlyphRunSegment segment; + segment.mType = GlyphRunSegment::Type::POINT; + segment.mPoints.push_back(point); + + feature.mSegments.push_back(segment); + + mFeatures.push_back(feature); } std::string GlyphRunOutlines::toPostScriptPath() @@ -23,15 +24,31 @@ std::string GlyphRunOutlines::toPostScriptPath() std::string path; for (const auto& feature : mFeatures) { - if (feature.mPoints.empty()) + if (feature.mSegments.empty()) { continue; } - auto last_point = feature.mPoints[0]; - path += "M" + std::to_string(last_point.getX()) + " " + std::to_string(last_point.getY()) + " "; - for (std::size_t idx = 1; idx < feature.mPoints.size(); idx++) + + auto start_point = feature.mSegments[0].mPoints[0]; + path += "M" + std::to_string(start_point.getX()) + " " + std::to_string(start_point.getY()) + " "; + + for (std::size_t idx = 1; idx < feature.mSegments.size(); idx++) { - path += "L" + std::to_string(feature.mPoints[idx].getX()) + " " + std::to_string(feature.mPoints[idx].getY()) + " "; + if (feature.mSegments[idx].mType == GlyphRunSegment::Type::LINE) + { + for (const auto& point : feature.mSegments[idx].mPoints) + { + path += "L" + std::to_string(point.getX()) + " " + std::to_string(point.getY()) + " "; + } + } + else if (feature.mSegments[idx].mType == GlyphRunSegment::Type::BEZIER) + { + path += "C"; + for (const auto& point : feature.mSegments[idx].mPoints) + { + path += std::to_string(point.getX()) + " " + std::to_string(point.getY()) + " "; + } + } } path += "z "; } diff --git a/src/fonts/FontGlyph.h b/src/fonts/FontGlyph.h index 170758b..124800f 100644 --- a/src/fonts/FontGlyph.h +++ b/src/fonts/FontGlyph.h @@ -7,23 +7,33 @@ #include #include -struct GlyphRunOutline +struct GlyphRunSegment +{ + enum class Type + { + POINT, + LINE, + BEZIER + }; + std::vector mPoints; + Type mType{ Type::LINE }; +}; + +struct GlyphRunFeature { bool mFilled{ true }; - std::vector mPoints; + std::vector mSegments; }; class GlyphRunOutlines { public: - void addToFeature(const Point& point); + void addSegment(const GlyphRunSegment& point); void startFeature(const Point& point, bool isFilled); - const std::vector getFeatures() const; - std::string toPostScriptPath(); private: - std::vector mFeatures; + std::vector mFeatures; }; class FontGlyph diff --git a/src/fonts/directx/DirectWriteHelpers.cpp b/src/fonts/directx/DirectWriteHelpers.cpp index d2db26a..2bdd7b6 100644 --- a/src/fonts/directx/DirectWriteHelpers.cpp +++ b/src/fonts/directx/DirectWriteHelpers.cpp @@ -56,59 +56,64 @@ ULONG __stdcall GlyphOutlineGeometrySink::Release() void __stdcall GlyphOutlineGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) { - MLOG_INFO("SetFillMode: " << bool(fillMode == D2D1_FILL_MODE_ALTERNATE)); + //MLOG_INFO("SetFillMode: " << bool(fillMode == D2D1_FILL_MODE_ALTERNATE)); } void __stdcall GlyphOutlineGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) { - MLOG_INFO("SetSegmentFlags"); if (vertexFlags == D2D1_PATH_SEGMENT_NONE) { - MLOG_INFO("D2D1_PATH_SEGMENT_NONE"); } else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_UNSTROKED) { - MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_UNSTROKED"); } else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) { - MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN"); } else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_DWORD) { - MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_DWORD"); } else { - MLOG_INFO("UKNOWN"); } } void __stdcall GlyphOutlineGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) { - MLOG_INFO("BeginFigure, is filled: " << bool(figureBegin == D2D1_FIGURE_BEGIN_FILLED)); mGlyphRunOutline->startFeature(Point(startPoint.x, startPoint.y), figureBegin == D2D1_FIGURE_BEGIN_FILLED); } void __stdcall GlyphOutlineGeometrySink::AddLines(_In_reads_(pointsCount) CONST D2D1_POINT_2F* points, UINT32 pointsCount) { - MLOG_INFO("AddLines"); + GlyphRunSegment segment; + segment.mType = GlyphRunSegment::Type::LINE; for (UINT32 idx = 0; idx < pointsCount; idx++) { auto point = points[idx]; - MLOG_INFO("Adding point: " << point.x << " " << point.y); - mGlyphRunOutline->addToFeature(Point(point.x, point.y)); + segment.mPoints.push_back(Point(point.x, point.y)); } + mGlyphRunOutline->addSegment(segment); } void __stdcall GlyphOutlineGeometrySink::AddBeziers(_In_reads_(beziersCount) CONST D2D1_BEZIER_SEGMENT* beziers, UINT32 beziersCount) { - MLOG_INFO("AddBeziers"); + for (UINT32 idx = 0; idx < beziersCount; idx++) + { + GlyphRunSegment segment; + segment.mType = GlyphRunSegment::Type::BEZIER; + + auto bezier = beziers[idx]; + segment.mPoints.push_back(Point(bezier.point1.x, bezier.point1.y)); + segment.mPoints.push_back(Point(bezier.point2.x, bezier.point2.y)); + segment.mPoints.push_back(Point(bezier.point3.x, bezier.point3.y)); + + mGlyphRunOutline->addSegment(segment); + } } void __stdcall GlyphOutlineGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) { - MLOG_INFO("EndFigure"); + } HRESULT __stdcall GlyphOutlineGeometrySink::Close()