resolve-shape-geometry.cpp 3.1 KB

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