Path: blob/master/thirdparty/msdfgen/core/Scanline.cpp
9902 views
1#include "Scanline.h"23#include <cstdlib>4#include "arithmetics.hpp"56namespace msdfgen {78static int compareIntersections(const void *a, const void *b) {9return sign(reinterpret_cast<const Scanline::Intersection *>(a)->x-reinterpret_cast<const Scanline::Intersection *>(b)->x);10}1112bool interpretFillRule(int intersections, FillRule fillRule) {13switch (fillRule) {14case FILL_NONZERO:15return intersections != 0;16case FILL_ODD:17return intersections&1;18case FILL_POSITIVE:19return intersections > 0;20case FILL_NEGATIVE:21return intersections < 0;22}23return false;24}2526double Scanline::overlap(const Scanline &a, const Scanline &b, double xFrom, double xTo, FillRule fillRule) {27double total = 0;28bool aInside = false, bInside = false;29int ai = 0, bi = 0;30double ax = !a.intersections.empty() ? a.intersections[ai].x : xTo;31double bx = !b.intersections.empty() ? b.intersections[bi].x : xTo;32while (ax < xFrom || bx < xFrom) {33double xNext = min(ax, bx);34if (ax == xNext && ai < (int) a.intersections.size()) {35aInside = interpretFillRule(a.intersections[ai].direction, fillRule);36ax = ++ai < (int) a.intersections.size() ? a.intersections[ai].x : xTo;37}38if (bx == xNext && bi < (int) b.intersections.size()) {39bInside = interpretFillRule(b.intersections[bi].direction, fillRule);40bx = ++bi < (int) b.intersections.size() ? b.intersections[bi].x : xTo;41}42}43double x = xFrom;44while (ax < xTo || bx < xTo) {45double xNext = min(ax, bx);46if (aInside == bInside)47total += xNext-x;48if (ax == xNext && ai < (int) a.intersections.size()) {49aInside = interpretFillRule(a.intersections[ai].direction, fillRule);50ax = ++ai < (int) a.intersections.size() ? a.intersections[ai].x : xTo;51}52if (bx == xNext && bi < (int) b.intersections.size()) {53bInside = interpretFillRule(b.intersections[bi].direction, fillRule);54bx = ++bi < (int) b.intersections.size() ? b.intersections[bi].x : xTo;55}56x = xNext;57}58if (aInside == bInside)59total += xTo-x;60return total;61}6263Scanline::Scanline() : lastIndex(0) { }6465void Scanline::preprocess() {66lastIndex = 0;67if (!intersections.empty()) {68qsort(&intersections[0], intersections.size(), sizeof(Intersection), compareIntersections);69int totalDirection = 0;70for (std::vector<Intersection>::iterator intersection = intersections.begin(); intersection != intersections.end(); ++intersection) {71totalDirection += intersection->direction;72intersection->direction = totalDirection;73}74}75}7677void Scanline::setIntersections(const std::vector<Intersection> &intersections) {78this->intersections = intersections;79preprocess();80}8182#ifdef MSDFGEN_USE_CPP1183void Scanline::setIntersections(std::vector<Intersection> &&intersections) {84this->intersections = (std::vector<Intersection> &&) intersections;85preprocess();86}87#endif8889int Scanline::moveTo(double x) const {90if (intersections.empty())91return -1;92int index = lastIndex;93if (x < intersections[index].x) {94do {95if (index == 0) {96lastIndex = 0;97return -1;98}99--index;100} while (x < intersections[index].x);101} else {102while (index < (int) intersections.size()-1 && x >= intersections[index+1].x)103++index;104}105lastIndex = index;106return index;107}108109int Scanline::countIntersections(double x) const {110return moveTo(x)+1;111}112113int Scanline::sumIntersections(double x) const {114int index = moveTo(x);115if (index >= 0)116return intersections[index].direction;117return 0;118}119120bool Scanline::filled(double x, FillRule fillRule) const {121return interpretFillRule(sumIntersections(x), fillRule);122}123124}125126127