rasterization.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "rasterization.h"
  2. #include <vector>
  3. #include "arithmetics.hpp"
  4. namespace msdfgen {
  5. void rasterize(BitmapSection<float, 1> output, const Shape &shape, const Projection &projection, FillRule fillRule) {
  6. output.reorient(shape.getYAxisOrientation());
  7. Scanline scanline;
  8. for (int y = 0; y < output.height; ++y) {
  9. shape.scanline(scanline, projection.unprojectY(y+.5));
  10. for (int x = 0; x < output.width; ++x)
  11. *output(x, y) = (float) scanline.filled(projection.unprojectX(x+.5), fillRule);
  12. }
  13. }
  14. void distanceSignCorrection(BitmapSection<float, 1> sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  15. sdf.reorient(shape.getYAxisOrientation());
  16. Scanline scanline;
  17. for (int y = 0; y < sdf.height; ++y) {
  18. shape.scanline(scanline, projection.unprojectY(y+.5));
  19. for (int x = 0; x < sdf.width; ++x) {
  20. bool fill = scanline.filled(projection.unprojectX(x+.5), fillRule);
  21. float &sd = *sdf(x, y);
  22. if ((sd > .5f) != fill)
  23. sd = 1.f-sd;
  24. }
  25. }
  26. }
  27. template <int N>
  28. static void multiDistanceSignCorrection(BitmapSection<float, N> sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  29. int w = sdf.width, h = sdf.height;
  30. if (!(w && h))
  31. return;
  32. sdf.reorient(shape.getYAxisOrientation());
  33. Scanline scanline;
  34. bool ambiguous = false;
  35. std::vector<char> matchMap;
  36. matchMap.resize(w*h);
  37. char *match = &matchMap[0];
  38. for (int y = 0; y < h; ++y) {
  39. shape.scanline(scanline, projection.unprojectY(y+.5));
  40. for (int x = 0; x < w; ++x) {
  41. bool fill = scanline.filled(projection.unprojectX(x+.5), fillRule);
  42. float *msd = sdf(x, y);
  43. float sd = median(msd[0], msd[1], msd[2]);
  44. if (sd == .5f)
  45. ambiguous = true;
  46. else if ((sd > .5f) != fill) {
  47. msd[0] = 1.f-msd[0];
  48. msd[1] = 1.f-msd[1];
  49. msd[2] = 1.f-msd[2];
  50. *match = -1;
  51. } else
  52. *match = 1;
  53. if (N >= 4 && (msd[3] > .5f) != fill)
  54. msd[3] = 1.f-msd[3];
  55. ++match;
  56. }
  57. }
  58. // This step is necessary to avoid artifacts when whole shape is inverted
  59. if (ambiguous) {
  60. match = &matchMap[0];
  61. for (int y = 0; y < h; ++y) {
  62. for (int x = 0; x < w; ++x) {
  63. if (!*match) {
  64. int neighborMatch = 0;
  65. if (x > 0) neighborMatch += *(match-1);
  66. if (x < w-1) neighborMatch += *(match+1);
  67. if (y > 0) neighborMatch += *(match-w);
  68. if (y < h-1) neighborMatch += *(match+w);
  69. if (neighborMatch < 0) {
  70. float *msd = sdf(x, y);
  71. msd[0] = 1.f-msd[0];
  72. msd[1] = 1.f-msd[1];
  73. msd[2] = 1.f-msd[2];
  74. }
  75. }
  76. ++match;
  77. }
  78. }
  79. }
  80. }
  81. void distanceSignCorrection(BitmapSection<float, 3> sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  82. multiDistanceSignCorrection(sdf, shape, projection, fillRule);
  83. }
  84. void distanceSignCorrection(BitmapSection<float, 4> sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  85. multiDistanceSignCorrection(sdf, shape, projection, fillRule);
  86. }
  87. // Legacy API
  88. void rasterize(const BitmapSection<float, 1> &output, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  89. rasterize(output, shape, Projection(scale, translate), fillRule);
  90. }
  91. void distanceSignCorrection(const BitmapSection<float, 1> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  92. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  93. }
  94. void distanceSignCorrection(const BitmapSection<float, 3> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  95. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  96. }
  97. void distanceSignCorrection(const BitmapSection<float, 4> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  98. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  99. }
  100. }