Path: blob/master/thirdparty/msdfgen/core/msdfgen.cpp
9902 views
1#include "../msdfgen.h"23#include <vector>4#include "edge-selectors.h"5#include "contour-combiners.h"6#include "ShapeDistanceFinder.h"78namespace msdfgen {910template <typename DistanceType>11class DistancePixelConversion;1213template <>14class DistancePixelConversion<double> {15DistanceMapping mapping;16public:17typedef BitmapRef<float, 1> BitmapRefType;18inline explicit DistancePixelConversion(DistanceMapping mapping) : mapping(mapping) { }19inline void operator()(float *pixels, double distance) const {20*pixels = float(mapping(distance));21}22};2324template <>25class DistancePixelConversion<MultiDistance> {26DistanceMapping mapping;27public:28typedef BitmapRef<float, 3> BitmapRefType;29inline explicit DistancePixelConversion(DistanceMapping mapping) : mapping(mapping) { }30inline void operator()(float *pixels, const MultiDistance &distance) const {31pixels[0] = float(mapping(distance.r));32pixels[1] = float(mapping(distance.g));33pixels[2] = float(mapping(distance.b));34}35};3637template <>38class DistancePixelConversion<MultiAndTrueDistance> {39DistanceMapping mapping;40public:41typedef BitmapRef<float, 4> BitmapRefType;42inline explicit DistancePixelConversion(DistanceMapping mapping) : mapping(mapping) { }43inline void operator()(float *pixels, const MultiAndTrueDistance &distance) const {44pixels[0] = float(mapping(distance.r));45pixels[1] = float(mapping(distance.g));46pixels[2] = float(mapping(distance.b));47pixels[3] = float(mapping(distance.a));48}49};5051template <class ContourCombiner>52void generateDistanceField(const typename DistancePixelConversion<typename ContourCombiner::DistanceType>::BitmapRefType &output, const Shape &shape, const SDFTransformation &transformation) {53DistancePixelConversion<typename ContourCombiner::DistanceType> distancePixelConversion(transformation.distanceMapping);54#ifdef MSDFGEN_USE_OPENMP55#pragma omp parallel56#endif57{58ShapeDistanceFinder<ContourCombiner> distanceFinder(shape);59bool rightToLeft = false;60#ifdef MSDFGEN_USE_OPENMP61#pragma omp for62#endif63for (int y = 0; y < output.height; ++y) {64int row = shape.inverseYAxis ? output.height-y-1 : y;65for (int col = 0; col < output.width; ++col) {66int x = rightToLeft ? output.width-col-1 : col;67Point2 p = transformation.unproject(Point2(x+.5, y+.5));68typename ContourCombiner::DistanceType distance = distanceFinder.distance(p);69distancePixelConversion(output(x, row), distance);70}71rightToLeft = !rightToLeft;72}73}74}7576void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const SDFTransformation &transformation, const GeneratorConfig &config) {77if (config.overlapSupport)78generateDistanceField<OverlappingContourCombiner<TrueDistanceSelector> >(output, shape, transformation);79else80generateDistanceField<SimpleContourCombiner<TrueDistanceSelector> >(output, shape, transformation);81}8283void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, const SDFTransformation &transformation, const GeneratorConfig &config) {84if (config.overlapSupport)85generateDistanceField<OverlappingContourCombiner<PerpendicularDistanceSelector> >(output, shape, transformation);86else87generateDistanceField<SimpleContourCombiner<PerpendicularDistanceSelector> >(output, shape, transformation);88}8990void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, const SDFTransformation &transformation, const MSDFGeneratorConfig &config) {91if (config.overlapSupport)92generateDistanceField<OverlappingContourCombiner<MultiDistanceSelector> >(output, shape, transformation);93else94generateDistanceField<SimpleContourCombiner<MultiDistanceSelector> >(output, shape, transformation);95msdfErrorCorrection(output, shape, transformation, config);96}9798void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, const SDFTransformation &transformation, const MSDFGeneratorConfig &config) {99if (config.overlapSupport)100generateDistanceField<OverlappingContourCombiner<MultiAndTrueDistanceSelector> >(output, shape, transformation);101else102generateDistanceField<SimpleContourCombiner<MultiAndTrueDistanceSelector> >(output, shape, transformation);103msdfErrorCorrection(output, shape, transformation, config);104}105106void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, Range range, const GeneratorConfig &config) {107if (config.overlapSupport)108generateDistanceField<OverlappingContourCombiner<TrueDistanceSelector> >(output, shape, SDFTransformation(projection, range));109else110generateDistanceField<SimpleContourCombiner<TrueDistanceSelector> >(output, shape, SDFTransformation(projection, range));111}112113void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, Range range, const GeneratorConfig &config) {114if (config.overlapSupport)115generateDistanceField<OverlappingContourCombiner<PerpendicularDistanceSelector> >(output, shape, SDFTransformation(projection, range));116else117generateDistanceField<SimpleContourCombiner<PerpendicularDistanceSelector> >(output, shape, SDFTransformation(projection, range));118}119120void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, const Projection &projection, Range range, const MSDFGeneratorConfig &config) {121if (config.overlapSupport)122generateDistanceField<OverlappingContourCombiner<MultiDistanceSelector> >(output, shape, SDFTransformation(projection, range));123else124generateDistanceField<SimpleContourCombiner<MultiDistanceSelector> >(output, shape, SDFTransformation(projection, range));125msdfErrorCorrection(output, shape, SDFTransformation(projection, range), config);126}127128void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, const Projection &projection, Range range, const MSDFGeneratorConfig &config) {129if (config.overlapSupport)130generateDistanceField<OverlappingContourCombiner<MultiAndTrueDistanceSelector> >(output, shape, SDFTransformation(projection, range));131else132generateDistanceField<SimpleContourCombiner<MultiAndTrueDistanceSelector> >(output, shape, SDFTransformation(projection, range));133msdfErrorCorrection(output, shape, SDFTransformation(projection, range), config);134}135136// Legacy API137138void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, Range range, const GeneratorConfig &config) {139generatePSDF(output, shape, SDFTransformation(projection, range), config);140}141142void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {143generateSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));144}145146void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {147generatePSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));148}149150void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {151generatePSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));152}153154void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, const ErrorCorrectionConfig &errorCorrectionConfig, bool overlapSupport) {155generateMSDF(output, shape, Projection(scale, translate), range, MSDFGeneratorConfig(overlapSupport, errorCorrectionConfig));156}157158void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, const ErrorCorrectionConfig &errorCorrectionConfig, bool overlapSupport) {159generateMTSDF(output, shape, Projection(scale, translate), range, MSDFGeneratorConfig(overlapSupport, errorCorrectionConfig));160}161162// Legacy version163164void generateSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate) {165DistanceMapping distanceMapping(range);166#ifdef MSDFGEN_USE_OPENMP167#pragma omp parallel for168#endif169for (int y = 0; y < output.height; ++y) {170int row = shape.inverseYAxis ? output.height-y-1 : y;171for (int x = 0; x < output.width; ++x) {172double dummy;173Point2 p = Vector2(x+.5, y+.5)/scale-translate;174SignedDistance minDistance;175for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)176for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {177SignedDistance distance = (*edge)->signedDistance(p, dummy);178if (distance < minDistance)179minDistance = distance;180}181*output(x, row) = float(distanceMapping(minDistance.distance));182}183}184}185186void generatePSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate) {187DistanceMapping distanceMapping(range);188#ifdef MSDFGEN_USE_OPENMP189#pragma omp parallel for190#endif191for (int y = 0; y < output.height; ++y) {192int row = shape.inverseYAxis ? output.height-y-1 : y;193for (int x = 0; x < output.width; ++x) {194Point2 p = Vector2(x+.5, y+.5)/scale-translate;195SignedDistance minDistance;196const EdgeHolder *nearEdge = NULL;197double nearParam = 0;198for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)199for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {200double param;201SignedDistance distance = (*edge)->signedDistance(p, param);202if (distance < minDistance) {203minDistance = distance;204nearEdge = &*edge;205nearParam = param;206}207}208if (nearEdge)209(*nearEdge)->distanceToPerpendicularDistance(minDistance, p, nearParam);210*output(x, row) = float(distanceMapping(minDistance.distance));211}212}213}214215void generatePseudoSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate) {216generatePSDF_legacy(output, shape, range, scale, translate);217}218219void generateMSDF_legacy(const BitmapRef<float, 3> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, ErrorCorrectionConfig errorCorrectionConfig) {220DistanceMapping distanceMapping(range);221#ifdef MSDFGEN_USE_OPENMP222#pragma omp parallel for223#endif224for (int y = 0; y < output.height; ++y) {225int row = shape.inverseYAxis ? output.height-y-1 : y;226for (int x = 0; x < output.width; ++x) {227Point2 p = Vector2(x+.5, y+.5)/scale-translate;228229struct {230SignedDistance minDistance;231const EdgeHolder *nearEdge;232double nearParam;233} r, g, b;234r.nearEdge = g.nearEdge = b.nearEdge = NULL;235r.nearParam = g.nearParam = b.nearParam = 0;236237for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)238for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {239double param;240SignedDistance distance = (*edge)->signedDistance(p, param);241if ((*edge)->color&RED && distance < r.minDistance) {242r.minDistance = distance;243r.nearEdge = &*edge;244r.nearParam = param;245}246if ((*edge)->color&GREEN && distance < g.minDistance) {247g.minDistance = distance;248g.nearEdge = &*edge;249g.nearParam = param;250}251if ((*edge)->color&BLUE && distance < b.minDistance) {252b.minDistance = distance;253b.nearEdge = &*edge;254b.nearParam = param;255}256}257258if (r.nearEdge)259(*r.nearEdge)->distanceToPerpendicularDistance(r.minDistance, p, r.nearParam);260if (g.nearEdge)261(*g.nearEdge)->distanceToPerpendicularDistance(g.minDistance, p, g.nearParam);262if (b.nearEdge)263(*b.nearEdge)->distanceToPerpendicularDistance(b.minDistance, p, b.nearParam);264output(x, row)[0] = float(distanceMapping(r.minDistance.distance));265output(x, row)[1] = float(distanceMapping(g.minDistance.distance));266output(x, row)[2] = float(distanceMapping(b.minDistance.distance));267}268}269270errorCorrectionConfig.distanceCheckMode = ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE;271msdfErrorCorrection(output, shape, Projection(scale, translate), range, MSDFGeneratorConfig(false, errorCorrectionConfig));272}273274void generateMTSDF_legacy(const BitmapRef<float, 4> &output, const Shape &shape, Range range, const Vector2 &scale, const Vector2 &translate, ErrorCorrectionConfig errorCorrectionConfig) {275DistanceMapping distanceMapping(range);276#ifdef MSDFGEN_USE_OPENMP277#pragma omp parallel for278#endif279for (int y = 0; y < output.height; ++y) {280int row = shape.inverseYAxis ? output.height-y-1 : y;281for (int x = 0; x < output.width; ++x) {282Point2 p = Vector2(x+.5, y+.5)/scale-translate;283284SignedDistance minDistance;285struct {286SignedDistance minDistance;287const EdgeHolder *nearEdge;288double nearParam;289} r, g, b;290r.nearEdge = g.nearEdge = b.nearEdge = NULL;291r.nearParam = g.nearParam = b.nearParam = 0;292293for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)294for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {295double param;296SignedDistance distance = (*edge)->signedDistance(p, param);297if (distance < minDistance)298minDistance = distance;299if ((*edge)->color&RED && distance < r.minDistance) {300r.minDistance = distance;301r.nearEdge = &*edge;302r.nearParam = param;303}304if ((*edge)->color&GREEN && distance < g.minDistance) {305g.minDistance = distance;306g.nearEdge = &*edge;307g.nearParam = param;308}309if ((*edge)->color&BLUE && distance < b.minDistance) {310b.minDistance = distance;311b.nearEdge = &*edge;312b.nearParam = param;313}314}315316if (r.nearEdge)317(*r.nearEdge)->distanceToPerpendicularDistance(r.minDistance, p, r.nearParam);318if (g.nearEdge)319(*g.nearEdge)->distanceToPerpendicularDistance(g.minDistance, p, g.nearParam);320if (b.nearEdge)321(*b.nearEdge)->distanceToPerpendicularDistance(b.minDistance, p, b.nearParam);322output(x, row)[0] = float(distanceMapping(r.minDistance.distance));323output(x, row)[1] = float(distanceMapping(g.minDistance.distance));324output(x, row)[2] = float(distanceMapping(b.minDistance.distance));325output(x, row)[3] = float(distanceMapping(minDistance.distance));326}327}328329errorCorrectionConfig.distanceCheckMode = ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE;330msdfErrorCorrection(output, shape, Projection(scale, translate), range, MSDFGeneratorConfig(false, errorCorrectionConfig));331}332333}334335336