1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/tessellate/Tessellation.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 11cb93a386Sopenharmony_ci#include "src/core/SkGeometry.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h" 14cb93a386Sopenharmony_ci#include "src/gpu/tessellate/CullTest.h" 15cb93a386Sopenharmony_ci#include "src/gpu/tessellate/MiddleOutPolygonTriangulator.h" 16cb93a386Sopenharmony_ci#include "src/gpu/tessellate/WangsFormula.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_cinamespace skgpu { 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_cinamespace { 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci// Writes a new path, chopping as necessary so no verbs require more segments than 23cb93a386Sopenharmony_ci// kMaxTessellationSegmentsPerCurve. Curves completely outside the viewport are flattened into 24cb93a386Sopenharmony_ci// lines. 25cb93a386Sopenharmony_ciclass PathChopper { 26cb93a386Sopenharmony_cipublic: 27cb93a386Sopenharmony_ci PathChopper(const SkMatrix& matrix, const SkRect& viewport) 28cb93a386Sopenharmony_ci : fCullTest(viewport, matrix) 29cb93a386Sopenharmony_ci , fVectorXform(matrix) { 30cb93a386Sopenharmony_ci fPath.setIsVolatile(true); 31cb93a386Sopenharmony_ci } 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci SkPath path() const { return fPath; } 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci void moveTo(SkPoint p) { fPath.moveTo(p); } 36cb93a386Sopenharmony_ci void lineTo(SkPoint p1) { fPath.lineTo(p1); } 37cb93a386Sopenharmony_ci void close() { fPath.close(); } 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci void quadTo(const SkPoint p[3]) { 40cb93a386Sopenharmony_ci if (!fCullTest.areVisible3(p)) { 41cb93a386Sopenharmony_ci this->lineTo(p[2]); 42cb93a386Sopenharmony_ci return; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci float n = wangs_formula::quadratic_pow4(kTessellationPrecision, p, fVectorXform); 45cb93a386Sopenharmony_ci if (n > pow4(kMaxTessellationSegmentsPerCurve)) { 46cb93a386Sopenharmony_ci SkPoint chops[5]; 47cb93a386Sopenharmony_ci SkChopQuadAtHalf(p, chops); 48cb93a386Sopenharmony_ci this->quadTo(chops); 49cb93a386Sopenharmony_ci this->quadTo(chops + 2); 50cb93a386Sopenharmony_ci return; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci fPath.quadTo(p[1], p[2]); 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci void conicTo(const SkPoint p[3], float w) { 56cb93a386Sopenharmony_ci if (!fCullTest.areVisible3(p)) { 57cb93a386Sopenharmony_ci this->lineTo(p[2]); 58cb93a386Sopenharmony_ci return; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci float n = wangs_formula::conic_pow2(kTessellationPrecision, p, w, fVectorXform); 61cb93a386Sopenharmony_ci if (n > pow2(kMaxTessellationSegmentsPerCurve)) { 62cb93a386Sopenharmony_ci SkConic chops[2]; 63cb93a386Sopenharmony_ci if (!SkConic(p,w).chopAt(.5, chops)) { 64cb93a386Sopenharmony_ci this->lineTo(p[2]); 65cb93a386Sopenharmony_ci return; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci this->conicTo(chops[0].fPts, chops[0].fW); 68cb93a386Sopenharmony_ci this->conicTo(chops[1].fPts, chops[1].fW); 69cb93a386Sopenharmony_ci return; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci fPath.conicTo(p[1], p[2], w); 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci void cubicTo(const SkPoint p[4]) { 75cb93a386Sopenharmony_ci if (!fCullTest.areVisible4(p)) { 76cb93a386Sopenharmony_ci this->lineTo(p[3]); 77cb93a386Sopenharmony_ci return; 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci float n = wangs_formula::cubic_pow4(kTessellationPrecision, p, fVectorXform); 80cb93a386Sopenharmony_ci if (n > pow4(kMaxTessellationSegmentsPerCurve)) { 81cb93a386Sopenharmony_ci SkPoint chops[7]; 82cb93a386Sopenharmony_ci SkChopCubicAtHalf(p, chops); 83cb93a386Sopenharmony_ci this->cubicTo(chops); 84cb93a386Sopenharmony_ci this->cubicTo(chops + 3); 85cb93a386Sopenharmony_ci return; 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci fPath.cubicTo(p[1], p[2], p[3]); 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ciprivate: 91cb93a386Sopenharmony_ci const CullTest fCullTest; 92cb93a386Sopenharmony_ci const wangs_formula::VectorXform fVectorXform; 93cb93a386Sopenharmony_ci SkPath fPath; 94cb93a386Sopenharmony_ci}; 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci} // namespace 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ciSkPath PreChopPathCurves(const SkPath& path, const SkMatrix& matrix, const SkRect& viewport) { 99cb93a386Sopenharmony_ci PathChopper chopper(matrix, viewport); 100cb93a386Sopenharmony_ci for (auto [verb, p, w] : SkPathPriv::Iterate(path)) { 101cb93a386Sopenharmony_ci switch (verb) { 102cb93a386Sopenharmony_ci case SkPathVerb::kMove: 103cb93a386Sopenharmony_ci chopper.moveTo(p[0]); 104cb93a386Sopenharmony_ci break; 105cb93a386Sopenharmony_ci case SkPathVerb::kLine: 106cb93a386Sopenharmony_ci chopper.lineTo(p[1]); 107cb93a386Sopenharmony_ci break; 108cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 109cb93a386Sopenharmony_ci chopper.quadTo(p); 110cb93a386Sopenharmony_ci break; 111cb93a386Sopenharmony_ci case SkPathVerb::kConic: 112cb93a386Sopenharmony_ci chopper.conicTo(p, *w); 113cb93a386Sopenharmony_ci break; 114cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 115cb93a386Sopenharmony_ci chopper.cubicTo(p); 116cb93a386Sopenharmony_ci break; 117cb93a386Sopenharmony_ci case SkPathVerb::kClose: 118cb93a386Sopenharmony_ci chopper.close(); 119cb93a386Sopenharmony_ci break; 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci return chopper.path(); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci} // namespace skgpu 126