static inline void add_cubic_segments(const SkPoint pts[4], SkPath::Direction dir, SegmentArray* segments) { SkSTArray<15, SkPoint, true> quads; GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); int count = quads.count(); for (int q = 0; q < count; q += 3) { add_quad_segment(&quads[q], segments); } }
static bool get_segments(const SkPath& path, const SkMatrix& m, SegmentArray* segments, SkPoint* fanPt, int* vCount, int* iCount, SkRect* devBounds) { SkPath::Iter iter(path, true); // This renderer over-emphasizes very thin path regions. We use the distance // to the path from the sample to compute coverage. Every pixel intersected // by the path will be hit and the maximum distance is sqrt(2)/2. We don't // notice that the sample may be close to a very thin area of the path and // thus should be very light. This is particularly egregious for degenerate // line paths. We detect paths that are very close to a line (zero area) and // draw nothing. DegenerateTestData degenerateData; SkPath::Direction dir; // get_direction can fail for some degenerate paths. if (!get_direction(path, m, &dir)) { return false; } for (;;) { SkPoint pts[4]; SkPath::Verb verb = iter.next(pts); switch (verb) { case SkPath::kMove_Verb: m.mapPoints(pts, 1); update_degenerate_test(°enerateData, pts[0]); devBounds->set(pts->fX, pts->fY, pts->fX, pts->fY); break; case SkPath::kLine_Verb: { m.mapPoints(&pts[1], 1); update_degenerate_test(°enerateData, pts[1]); add_line_to_segment(pts[1], segments, devBounds); break; } case SkPath::kQuad_Verb: m.mapPoints(pts, 3); update_degenerate_test(°enerateData, pts[1]); update_degenerate_test(°enerateData, pts[2]); add_quad_segment(pts, segments, devBounds); break; case SkPath::kCubic_Verb: { m.mapPoints(pts, 4); update_degenerate_test(°enerateData, pts[1]); update_degenerate_test(°enerateData, pts[2]); update_degenerate_test(°enerateData, pts[3]); add_cubic_segments(pts, dir, segments, devBounds); break; }; case SkPath::kDone_Verb: if (degenerateData.isDegenerate()) { return false; } else { compute_vectors(segments, fanPt, dir, vCount, iCount); return true; } default: break; } } }