resolve-shape-geometry.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #include "resolve-shape-geometry.h"
  2. #ifdef MSDFGEN_USE_SKIA
  3. #include <core/SkPath.h>
  4. #include <pathops/SkPathOps.h>
  5. #include "../core/Vector2.h"
  6. #include "../core/edge-segments.h"
  7. #include "../core/Contour.h"
  8. #ifdef _WIN32
  9. #pragma comment(lib, "skia.lib")
  10. #endif
  11. namespace msdfgen {
  12. SkPoint pointToSkiaPoint(Point2 p) {
  13. return SkPoint::Make((SkScalar) p.x, (SkScalar) p.y);
  14. }
  15. Point2 pointFromSkiaPoint(const SkPoint p) {
  16. return Point2((double) p.x(), (double) p.y());
  17. }
  18. void shapeToSkiaPath(SkPath &skPath, const Shape &shape) {
  19. for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
  20. if (!contour->edges.empty()) {
  21. skPath.moveTo(pointToSkiaPoint(contour->edges.front()->point(0)));
  22. for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
  23. {
  24. const LinearSegment *linearSegment = dynamic_cast<const LinearSegment *>(&**edge);
  25. if (linearSegment)
  26. skPath.lineTo(pointToSkiaPoint(linearSegment->p[1]));
  27. } {
  28. const QuadraticSegment *quadraticSegment = dynamic_cast<const QuadraticSegment *>(&**edge);
  29. if (quadraticSegment)
  30. skPath.quadTo(pointToSkiaPoint(quadraticSegment->p[1]), pointToSkiaPoint(quadraticSegment->p[2]));
  31. } {
  32. const CubicSegment *cubicSegment = dynamic_cast<const CubicSegment *>(&**edge);
  33. if (cubicSegment)
  34. skPath.cubicTo(pointToSkiaPoint(cubicSegment->p[1]), pointToSkiaPoint(cubicSegment->p[2]), pointToSkiaPoint(cubicSegment->p[3]));
  35. }
  36. }
  37. }
  38. }
  39. }
  40. void shapeFromSkiaPath(Shape &shape, const SkPath &skPath) {
  41. shape.contours.clear();
  42. Contour *contour = &shape.addContour();
  43. SkPath::Iter pathIterator(skPath, true);
  44. SkPoint edgePoints[4];
  45. for (SkPath::Verb op; (op = pathIterator.next(edgePoints)) != SkPath::kDone_Verb;) {
  46. switch (op) {
  47. case SkPath::kMove_Verb:
  48. if (!contour->edges.empty())
  49. contour = &shape.addContour();
  50. break;
  51. case SkPath::kLine_Verb:
  52. contour->addEdge(new LinearSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1])));
  53. break;
  54. case SkPath::kQuad_Verb:
  55. contour->addEdge(new QuadraticSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1]), pointFromSkiaPoint(edgePoints[2])));
  56. break;
  57. case SkPath::kCubic_Verb:
  58. contour->addEdge(new CubicSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1]), pointFromSkiaPoint(edgePoints[2]), pointFromSkiaPoint(edgePoints[3])));
  59. break;
  60. default:;
  61. }
  62. }
  63. if (contour->edges.empty())
  64. shape.contours.pop_back();
  65. }
  66. bool resolveShapeGeometry(Shape &shape) {
  67. SkPath skPath;
  68. shapeToSkiaPath(skPath, shape);
  69. if (!Simplify(skPath, &skPath))
  70. return false;
  71. // Skia's AsWinding doesn't seem to work for unknown reasons
  72. shapeFromSkiaPath(shape, skPath);
  73. shape.orientContours();
  74. return true;
  75. }
  76. }
  77. #endif