Skip to content

Commit

Permalink
Font loading, reverseorder fixed, binary removed
Browse files Browse the repository at this point in the history
  • Loading branch information
Chlumsky committed Dec 7, 2016
1 parent 4e443d8 commit 2ab2e61
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 98 deletions.
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ The following comparison demonstrates the improvement in image quality.
![demo-sdf16](https://cloud.githubusercontent.com/assets/18639794/14770360/20c51156-0a70-11e6-8f03-ed7632d07997.png)
![demo-sdf32](https://cloud.githubusercontent.com/assets/18639794/14770361/251a4406-0a70-11e6-95a7-e30e235ac729.png)

## New in version 1.2
- Option to specify that shape is defined in reverse order (-reverseorder)
- Option to set a seed for the edge coloring heuristic (-seed \<n\>), which can be used to adjust the output
- Fixed parsing of glyph contours starting that start with a curve control point.

## Getting started

The project can be used either as a library or as a console program. is divided into two parts, **[core](core)**
Expand Down
137 changes: 51 additions & 86 deletions ext/import-font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <queue>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H

#ifdef _WIN32
#pragma comment(lib, "freetype.lib")
Expand Down Expand Up @@ -35,6 +36,44 @@ class FontHandle {

};

struct FtContext {
Point2 position;
Shape *shape;
Contour *contour;
};

static Point2 ftPoint2(const FT_Vector &vector) {
return Point2(vector.x/64., vector.y/64.);
}

static int ftMoveTo(const FT_Vector *to, void *user) {
FtContext *context = reinterpret_cast<FtContext *>(user);
context->contour = &context->shape->addContour();
context->position = ftPoint2(*to);
return 0;
}

static int ftLineTo(const FT_Vector *to, void *user) {
FtContext *context = reinterpret_cast<FtContext *>(user);
context->contour->addEdge(new LinearSegment(context->position, ftPoint2(*to)));
context->position = ftPoint2(*to);
return 0;
}

static int ftConicTo(const FT_Vector *control, const FT_Vector *to, void *user) {
FtContext *context = reinterpret_cast<FtContext *>(user);
context->contour->addEdge(new QuadraticSegment(context->position, ftPoint2(*control), ftPoint2(*to)));
context->position = ftPoint2(*to);
return 0;
}

static int ftCubicTo(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *user) {
FtContext *context = reinterpret_cast<FtContext *>(user);
context->contour->addEdge(new CubicSegment(context->position, ftPoint2(*control1), ftPoint2(*control2), ftPoint2(*to)));
context->position = ftPoint2(*to);
return 0;
}

FreetypeHandle * initializeFreetype() {
FreetypeHandle *handle = new FreetypeHandle;
FT_Error error = FT_Init_FreeType(&handle->library);
Expand Down Expand Up @@ -85,14 +124,6 @@ bool getFontWhitespaceWidth(double &spaceAdvance, double &tabAdvance, FontHandle
}

bool loadGlyph(Shape &output, FontHandle *font, int unicode, double *advance) {
enum PointType {
NONE = 0,
PATH_POINT,
QUADRATIC_POINT,
CUBIC_POINT,
CUBIC_POINT2
};

if (!font)
return false;
FT_Error error = FT_Load_Char(font->face, unicode, FT_LOAD_NO_SCALE);
Expand All @@ -103,84 +134,18 @@ bool loadGlyph(Shape &output, FontHandle *font, int unicode, double *advance) {
if (advance)
*advance = font->face->glyph->advance.x/64.;

int last = -1;
// For each contour
for (int i = 0; i < font->face->glyph->outline.n_contours; ++i) {

Contour &contour = output.addContour();
int first = last+1;
int firstPathPoint = -1;
last = font->face->glyph->outline.contours[i];

PointType state = NONE;
Point2 startPoint;
Point2 controlPoint[2];

// For each point on the contour
for (int round = 0, index = first; round == 0; ++index) {
if (index > last) {
REQUIRE(firstPathPoint >= 0);
index = first;
}
// Close contour
if (index == firstPathPoint)
++round;

Point2 point(font->face->glyph->outline.points[index].x/64., font->face->glyph->outline.points[index].y/64.);
PointType pointType = font->face->glyph->outline.tags[index]&1 ? PATH_POINT : font->face->glyph->outline.tags[index]&2 ? CUBIC_POINT : QUADRATIC_POINT;

switch (state) {
case NONE:
if (pointType == PATH_POINT) {
firstPathPoint = index;
startPoint = point;
state = PATH_POINT;
}
break;
case PATH_POINT:
if (pointType == PATH_POINT) {
contour.addEdge(new LinearSegment(startPoint, point));
startPoint = point;
} else {
controlPoint[0] = point;
state = pointType;
}
break;
case QUADRATIC_POINT:
REQUIRE(pointType != CUBIC_POINT);
if (pointType == PATH_POINT) {
contour.addEdge(new QuadraticSegment(startPoint, controlPoint[0], point));
startPoint = point;
state = PATH_POINT;
} else {
Point2 midPoint = .5*controlPoint[0]+.5*point;
contour.addEdge(new QuadraticSegment(startPoint, controlPoint[0], midPoint));
startPoint = midPoint;
controlPoint[0] = point;
}
break;
case CUBIC_POINT:
REQUIRE(pointType == CUBIC_POINT);
controlPoint[1] = point;
state = CUBIC_POINT2;
break;
case CUBIC_POINT2:
REQUIRE(pointType != QUADRATIC_POINT);
if (pointType == PATH_POINT) {
contour.addEdge(new CubicSegment(startPoint, controlPoint[0], controlPoint[1], point));
startPoint = point;
} else {
Point2 midPoint = .5*controlPoint[1]+.5*point;
contour.addEdge(new CubicSegment(startPoint, controlPoint[0], controlPoint[1], midPoint));
startPoint = midPoint;
controlPoint[0] = point;
}
state = pointType;
break;
}

}
}
FtContext context = { };
context.shape = &output;
FT_Outline_Funcs ftFunctions;
ftFunctions.move_to = &ftMoveTo;
ftFunctions.line_to = &ftLineTo;
ftFunctions.conic_to = &ftConicTo;
ftFunctions.cubic_to = &ftCubicTo;
ftFunctions.shift = 0;
ftFunctions.delta = 0;
error = FT_Outline_Decompose(&font->face->glyph->outline, &ftFunctions, &context);
if (error)
return false;
return true;
}

Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 5 additions & 5 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.2 (2016-07-20) - standalone console program
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.3 (2016-12-07) - standalone console program
* --------------------------------------------------------------------------------------------
* A utility by Viktor Chlumsky, (c) 2014 - 2016
*
Expand Down Expand Up @@ -134,16 +134,16 @@ static void parseColoring(Shape &shape, const char *edgeAssignment) {
static void invertColor(Bitmap<FloatRGB> &bitmap) {
for (int y = 0; y < bitmap.height(); ++y)
for (int x = 0; x < bitmap.width(); ++x) {
bitmap(x, y).r = .5f-bitmap(x, y).r;
bitmap(x, y).g = .5f-bitmap(x, y).g;
bitmap(x, y).b = .5f-bitmap(x, y).b;
bitmap(x, y).r = 1.f-bitmap(x, y).r;
bitmap(x, y).g = 1.f-bitmap(x, y).g;
bitmap(x, y).b = 1.f-bitmap(x, y).b;
}
}

static void invertColor(Bitmap<float> &bitmap) {
for (int y = 0; y < bitmap.height(); ++y)
for (int x = 0; x < bitmap.width(); ++x)
bitmap(x, y) = .5f-bitmap(x, y);
bitmap(x, y) = 1.f-bitmap(x, y);
}

static bool writeTextBitmap(FILE *file, const float *values, int cols, int rows) {
Expand Down
Binary file removed msdfgen.exe
Binary file not shown.
4 changes: 2 additions & 2 deletions msdfgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#pragma once

/*
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.2 (2016-07-20)
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.3 (2016-12-07)
* ---------------------------------------------------------------
* A utility by Viktor Chlumsky, (c) 2014 - 2016
*
Expand All @@ -24,7 +24,7 @@
#include "core/save-bmp.h"
#include "core/shape-description.h"

#define MSDFGEN_VERSION "1.2"
#define MSDFGEN_VERSION "1.3"

namespace msdfgen {

Expand Down

0 comments on commit 2ab2e61

Please sign in to comment.