Add bezier rendering.

This commit is contained in:
jmsgrogan 2023-01-11 08:26:08 +00:00
parent b7f75f903e
commit 1eeaebd0a9
3 changed files with 65 additions and 33 deletions

View file

@ -1,21 +1,22 @@
#include "FontGlyph.h" #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) void GlyphRunOutlines::startFeature(const Point& point, bool isFilled)
{ {
GlyphRunOutline feature; GlyphRunFeature feature;
feature.mFilled = isFilled; feature.mFilled = isFilled;
feature.mPoints.push_back(point);
mFeatures.push_back(feature);
}
const std::vector<GlyphRunOutline> GlyphRunOutlines::getFeatures() const GlyphRunSegment segment;
{ segment.mType = GlyphRunSegment::Type::POINT;
return mFeatures; segment.mPoints.push_back(point);
feature.mSegments.push_back(segment);
mFeatures.push_back(feature);
} }
std::string GlyphRunOutlines::toPostScriptPath() std::string GlyphRunOutlines::toPostScriptPath()
@ -23,15 +24,31 @@ std::string GlyphRunOutlines::toPostScriptPath()
std::string path; std::string path;
for (const auto& feature : mFeatures) for (const auto& feature : mFeatures)
{ {
if (feature.mPoints.empty()) if (feature.mSegments.empty())
{ {
continue; continue;
} }
auto last_point = feature.mPoints[0];
path += "M" + std::to_string(last_point.getX()) + " " + std::to_string(last_point.getY()) + " "; auto start_point = feature.mSegments[0].mPoints[0];
for (std::size_t idx = 1; idx < feature.mPoints.size(); idx++) 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 "; path += "z ";
} }

View file

@ -7,23 +7,33 @@
#include <vector> #include <vector>
#include <string> #include <string>
struct GlyphRunOutline struct GlyphRunSegment
{
enum class Type
{
POINT,
LINE,
BEZIER
};
std::vector<Point> mPoints;
Type mType{ Type::LINE };
};
struct GlyphRunFeature
{ {
bool mFilled{ true }; bool mFilled{ true };
std::vector<Point> mPoints; std::vector<GlyphRunSegment> mSegments;
}; };
class GlyphRunOutlines class GlyphRunOutlines
{ {
public: public:
void addToFeature(const Point& point); void addSegment(const GlyphRunSegment& point);
void startFeature(const Point& point, bool isFilled); void startFeature(const Point& point, bool isFilled);
const std::vector<GlyphRunOutline> getFeatures() const;
std::string toPostScriptPath(); std::string toPostScriptPath();
private: private:
std::vector<GlyphRunOutline> mFeatures; std::vector<GlyphRunFeature> mFeatures;
}; };
class FontGlyph class FontGlyph

View file

@ -56,59 +56,64 @@ ULONG __stdcall GlyphOutlineGeometrySink::Release()
void __stdcall GlyphOutlineGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) 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) void __stdcall GlyphOutlineGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags)
{ {
MLOG_INFO("SetSegmentFlags");
if (vertexFlags == D2D1_PATH_SEGMENT_NONE) if (vertexFlags == D2D1_PATH_SEGMENT_NONE)
{ {
MLOG_INFO("D2D1_PATH_SEGMENT_NONE");
} }
else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_UNSTROKED) 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) 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) else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_DWORD)
{ {
MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_DWORD");
} }
else else
{ {
MLOG_INFO("UKNOWN");
} }
} }
void __stdcall GlyphOutlineGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) 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); 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) 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++) for (UINT32 idx = 0; idx < pointsCount; idx++)
{ {
auto point = points[idx]; auto point = points[idx];
MLOG_INFO("Adding point: " << point.x << " " << point.y); segment.mPoints.push_back(Point(point.x, point.y));
mGlyphRunOutline->addToFeature(Point(point.x, point.y));
} }
mGlyphRunOutline->addSegment(segment);
} }
void __stdcall GlyphOutlineGeometrySink::AddBeziers(_In_reads_(beziersCount) CONST D2D1_BEZIER_SEGMENT* beziers, UINT32 beziersCount) 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) void __stdcall GlyphOutlineGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd)
{ {
MLOG_INFO("EndFigure");
} }
HRESULT __stdcall GlyphOutlineGeometrySink::Close() HRESULT __stdcall GlyphOutlineGeometrySink::Close()