rasterization.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "rasterization.h"
  2. #include <vector>
  3. #include "arithmetics.hpp"
  4. namespace msdfgen {
  5. void rasterize(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, FillRule fillRule) {
  6. Scanline scanline;
  7. for (int y = 0; y < output.height; ++y) {
  8. int row = shape.inverseYAxis ? output.height-y-1 : y;
  9. shape.scanline(scanline, projection.unprojectY(y+.5));
  10. for (int x = 0; x < output.width; ++x)
  11. *output(x, row) = (float) scanline.filled(projection.unprojectX(x+.5), fillRule);
  12. }
  13. }
  14. void distanceSignCorrection(const BitmapRef<float, 1> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  15. Scanline scanline;
  16. for (int y = 0; y < sdf.height; ++y) {
  17. int row = shape.inverseYAxis ? sdf.height-y-1 : 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, row);
  22. if ((sd > .5f) != fill)
  23. sd = 1.f-sd;
  24. }
  25. }
  26. }
  27. template <int N>
  28. static void multiDistanceSignCorrection(const BitmapRef<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. Scanline scanline;
  33. bool ambiguous = false;
  34. std::vector<char> matchMap;
  35. matchMap.resize(w*h);
  36. char *match = &matchMap[0];
  37. for (int y = 0; y < h; ++y) {
  38. int row = shape.inverseYAxis ? h-y-1 : 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, row);
  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. int row = shape.inverseYAxis ? h-y-1 : y;
  63. for (int x = 0; x < w; ++x) {
  64. if (!*match) {
  65. int neighborMatch = 0;
  66. if (x > 0) neighborMatch += *(match-1);
  67. if (x < w-1) neighborMatch += *(match+1);
  68. if (y > 0) neighborMatch += *(match-w);
  69. if (y < h-1) neighborMatch += *(match+w);
  70. if (neighborMatch < 0) {
  71. float *msd = sdf(x, row);
  72. msd[0] = 1.f-msd[0];
  73. msd[1] = 1.f-msd[1];
  74. msd[2] = 1.f-msd[2];
  75. }
  76. }
  77. ++match;
  78. }
  79. }
  80. }
  81. }
  82. void distanceSignCorrection(const BitmapRef<float, 3> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  83. multiDistanceSignCorrection(sdf, shape, projection, fillRule);
  84. }
  85. void distanceSignCorrection(const BitmapRef<float, 4> &sdf, const Shape &shape, const Projection &projection, FillRule fillRule) {
  86. multiDistanceSignCorrection(sdf, shape, projection, fillRule);
  87. }
  88. // Legacy API
  89. void rasterize(const BitmapRef<float, 1> &output, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  90. rasterize(output, shape, Projection(scale, translate), fillRule);
  91. }
  92. void distanceSignCorrection(const BitmapRef<float, 1> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  93. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  94. }
  95. void distanceSignCorrection(const BitmapRef<float, 3> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  96. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  97. }
  98. void distanceSignCorrection(const BitmapRef<float, 4> &sdf, const Shape &shape, const Vector2 &scale, const Vector2 &translate, FillRule fillRule) {
  99. distanceSignCorrection(sdf, shape, Projection(scale, translate), fillRule);
  100. }
  101. }