Path: blob/master/thirdparty/msdfgen/core/rasterization.cpp
9903 views
1#include "rasterization.h"23#include <vector>4#include "arithmetics.hpp"56namespace msdfgen {78void rasterize(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, FillRule fillRule) {9Scanline scanline;10for (int y = 0; y < output.height; ++y) {11int row = shape.inverseYAxis ? output.height-y-1 : y;12shape.scanline(scanline, projection.unprojectY(y+.5));13for (int x = 0; x < output.width; ++x)14*output(x, row) = (float) scanline.filled(projection.unprojectX(x+.5), fillRule);15}16}1718void distanceSignCorrection(const BitmapRef<float, 1> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {19Scanline scanline;20for (int y = 0; y < sdf.height; ++y) {21int row = shape.inverseYAxis ? sdf.height-y-1 : y;22shape.scanline(scanline, projection.unprojectY(y+.5));23for (int x = 0; x < sdf.width; ++x) {24bool fill = scanline.filled(projection.unprojectX(x+.5), fillRule);25float &sd = *sdf(x, row);26if ((sd > .5f) != fill)27sd = 1.f-sd;28}29}30}3132template <int N>33static void multiDistanceSignCorrection(const BitmapRef<float, N> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {34int w = sdf.width, h = sdf.height;35if (!(w && h))36return;37Scanline scanline;38bool ambiguous = false;39std::vector<char> matchMap;40matchMap.resize(w*h);41char *match = &matchMap[0];42for (int y = 0; y < h; ++y) {43int row = shape.inverseYAxis ? h-y-1 : y;44shape.scanline(scanline, projection.unprojectY(y+.5));45for (int x = 0; x < w; ++x) {46bool fill = scanline.filled(projection.unprojectX(x+.5), fillRule);47float *msd = sdf(x, row);48float sd = median(msd[0], msd[1], msd[2]);49if (sd == .5f)50ambiguous = true;51else if ((sd > .5f) != fill) {52msd[0] = 1.f-msd[0];53msd[1] = 1.f-msd[1];54msd[2] = 1.f-msd[2];55*match = -1;56} else57*match = 1;58if (N >= 4 && (msd[3] > .5f) != fill)59msd[3] = 1.f-msd[3];60++match;61}62}63// This step is necessary to avoid artifacts when whole shape is inverted64if (ambiguous) {65match = &matchMap[0];66for (int y = 0; y < h; ++y) {67int row = shape.inverseYAxis ? h-y-1 : y;68for (int x = 0; x < w; ++x) {69if (!*match) {70int neighborMatch = 0;71if (x > 0) neighborMatch += *(match-1);72if (x < w-1) neighborMatch += *(match+1);73if (y > 0) neighborMatch += *(match-w);74if (y < h-1) neighborMatch += *(match+w);75if (neighborMatch < 0) {76float *msd = sdf(x, row);77msd[0] = 1.f-msd[0];78msd[1] = 1.f-msd[1];79msd[2] = 1.f-msd[2];80}81}82++match;83}84}85}86}8788void distanceSignCorrection(const BitmapRef<float, 3> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {89multiDistanceSignCorrection(sdf, shape, projection, fillRule);90}9192void distanceSignCorrection(const BitmapRef<float, 4> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {93multiDistanceSignCorrection(sdf, shape, projection, fillRule);94}9596// Legacy API9798void rasterize(const BitmapRef<float, 1> &output, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {99rasterize(output, shape, Projection(scale, translate), fillRule);100}101102void distanceSignCorrection(const BitmapRef<float, 1> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {103distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);104}105106void distanceSignCorrection(const BitmapRef<float, 3> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {107distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);108}109110void distanceSignCorrection(const BitmapRef<float, 4> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {111distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);112}113114}115116117