Skip to content

Commit

Permalink
Sync changes from vkd
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Jan 8, 2024
1 parent c03ae14 commit b8874d2
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/core/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <stdexcept>
#include <cstring>

// #define USE_INTERNAL_TTF
#define USE_INTERNAL_TTF

class CanvasTexture
{
Expand Down
120 changes: 102 additions & 18 deletions src/core/truetypefont.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@

// #define DUMP_GLYPH

#include "core/truetypefont.h"
#include "core/pathfill.h"
#include <algorithm>
#include <cmath>

#ifdef DUMP_GLYPH
#include <fstream>
#endif

TrueTypeFont::TrueTypeFont(std::vector<uint8_t> initdata) : data(std::move(initdata))
{
if (data.size() > 0x7fffffff)
Expand Down Expand Up @@ -47,7 +53,9 @@ TrueTypeFont::TrueTypeFont(std::vector<uint8_t> initdata) : data(std::move(initd

glyf = directory.GetRecord("glyf");

LoadGlyph(GetGlyphIndex(32), 13.0);
#ifdef DUMP_GLYPH
LoadGlyph(GetGlyphIndex('6'), 13.0);
#endif
}

TrueTypeTextMetrics TrueTypeFont::GetTextMetrics(double height) const
Expand Down Expand Up @@ -97,45 +105,72 @@ TrueTypeGlyph TrueTypeFont::LoadGlyph(uint32_t glyphIndex, double height) const
TTF_SimpleGlyph g;
LoadGlyph(g, glyphIndex);

int numberOfContours = g.endPtsOfContours.size();

// Create glyph path:
PathFillDesc path;
path.fill_mode = PathFillMode::winding;

int startPoint = 0;
int numberOfContours = g.endPtsOfContours.size();
for (int i = 0; i < numberOfContours; i++)
{
int endPoint = g.endPtsOfContours[i];
if (endPoint < startPoint)
throw std::runtime_error("Invalid glyph");

int pos = startPoint;
while (pos <= endPoint)
bool prevIsControlPoint;
bool isControlPoint = !(g.flags[endPoint] & TTF_ON_CURVE_POINT);
bool nextIsControlPoint = !(g.flags[startPoint] & TTF_ON_CURVE_POINT);
if (isControlPoint)
{
if (pos == startPoint)
Point nextpoint(g.points[startPoint].x, g.points[startPoint].y);
if (nextIsControlPoint)
{
path.MoveTo(Point(g.points[pos].x, g.points[pos].y) * scale);
pos++;
Point curpoint(g.points[endPoint].x, g.points[endPoint].y);
Point midpoint = (curpoint + nextpoint) / 2;
path.MoveTo(midpoint * scale);
prevIsControlPoint = isControlPoint;
}
else if (g.flags[pos] & TTF_ON_CURVE_POINT)
else
{
if (g.flags[pos - 1] & TTF_ON_CURVE_POINT)
path.MoveTo(Point(g.points[startPoint].x, g.points[startPoint].y) * scale);
prevIsControlPoint = false;
}
}
else
{
path.MoveTo(Point(g.points[endPoint].x, g.points[endPoint].y) * scale);
prevIsControlPoint = isControlPoint;
}

int pos = startPoint;
while (pos <= endPoint)
{
int nextpos = pos + 1 <= endPoint ? pos + 1 : startPoint;
bool isControlPoint = !(g.flags[pos] & TTF_ON_CURVE_POINT);
bool nextIsControlPoint = !(g.flags[nextpos] & TTF_ON_CURVE_POINT);
Point curpoint(g.points[pos].x, g.points[pos].y);
if (isControlPoint)
{
Point nextpoint(g.points[nextpos].x, g.points[nextpos].y);
if (nextIsControlPoint)
{
path.LineTo(Point(g.points[pos].x, g.points[pos].y) * scale);
Point midpoint = (curpoint + nextpoint) / 2;
path.BezierTo(curpoint * scale, midpoint * scale);
prevIsControlPoint = isControlPoint;
pos++;
}
else
{
path.BezierTo(Point(g.points[pos - 1].x, g.points[pos - 1].y) * scale, Point(g.points[pos].x, g.points[pos].y) * scale);
path.BezierTo(curpoint * scale, nextpoint * scale);
prevIsControlPoint = false;
pos += 2;
}
pos++;
}
else
{
Point lastcontrolpoint(g.points[pos].x, g.points[pos].y);
Point controlpoint(g.points[pos - 1].x, g.points[pos - 1].y);
Point midpoint = (lastcontrolpoint + controlpoint) / 2;
path.BezierTo(lastcontrolpoint * scale, midpoint * scale);
if (!prevIsControlPoint)
path.LineTo(curpoint * scale);
prevIsControlPoint = isControlPoint;
pos++;
}
}
Expand Down Expand Up @@ -181,6 +216,55 @@ TrueTypeGlyph TrueTypeFont::LoadGlyph(uint32_t glyphIndex, double height) const
}
}

#ifdef DUMP_GLYPH
std::string svgxmlstart = R"(<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="1000px" height="1000px" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg" version="1.1">
<path fill-rule="evenodd" d=")";
std::string svgxmlend = R"(" fill="red" />
</svg>)";

std::ofstream out("c:\\development\\glyph.svg");
out << svgxmlstart;

for (auto& subpath : path.subpaths)
{
size_t pos = 0;
out << "M" << subpath.points[pos].x << " " << subpath.points[pos].y << " ";
pos++;
for (PathFillCommand cmd : subpath.commands)
{
int count = 0;
if (cmd == PathFillCommand::line)
{
out << "L";
count = 1;
}
else if (cmd == PathFillCommand::quadradic)
{
out << "Q";
count = 2;
}
else if (cmd == PathFillCommand::cubic)
{
out << "C";
count = 3;
}

for (int i = 0; i < count; i++)
{
out << subpath.points[pos].x << " " << subpath.points[pos].y << " ";
pos++;
}
}
if (subpath.closed)
out << "Z";
}

out << svgxmlend;
out.close();
#endif

TrueTypeGlyph glyph;

// Rasterize the glyph
Expand All @@ -192,7 +276,7 @@ TrueTypeGlyph TrueTypeFont::LoadGlyph(uint32_t glyphIndex, double height) const

// TBD: gridfit or not?
glyph.advanceWidth = (int)std::round(advanceWidth * scale * scaleX);
glyph.leftSideBearing = (int)std::round(lsb * scale * scaleX + bboxMin.x);
glyph.leftSideBearing = (int)std::round(bboxMin.x);
glyph.yOffset = (int)std::round(bboxMin.y);

return glyph;
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/listview/listview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void ListView::OnMouseWheel(const Point& pos, EInputKey key)
}
else if (key == IK_MouseWheelDown)
{
scrollbar->SetPosition(std::max(scrollbar->GetPosition() + 20.0, scrollbar->GetMax()));
scrollbar->SetPosition(std::min(scrollbar->GetPosition() + 20.0, scrollbar->GetMax()));
}
}

Expand Down

0 comments on commit b8874d2

Please sign in to comment.