resolve-shape-geometry.cpp 3.7 KB

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