1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 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#include "src/core/SkPathPriv.h" 8cb93a386Sopenharmony_ci#include "src/pathops/SkOpEdgeBuilder.h" 9cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsCommon.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_cibool TightBounds(const SkPath& path, SkRect* result) { 12cb93a386Sopenharmony_ci SkRect moveBounds = { SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin }; 13cb93a386Sopenharmony_ci bool wellBehaved = true; 14cb93a386Sopenharmony_ci for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) { 15cb93a386Sopenharmony_ci switch (verb) { 16cb93a386Sopenharmony_ci case SkPathVerb::kMove: 17cb93a386Sopenharmony_ci moveBounds.fLeft = std::min(moveBounds.fLeft, pts[0].fX); 18cb93a386Sopenharmony_ci moveBounds.fTop = std::min(moveBounds.fTop, pts[0].fY); 19cb93a386Sopenharmony_ci moveBounds.fRight = std::max(moveBounds.fRight, pts[0].fX); 20cb93a386Sopenharmony_ci moveBounds.fBottom = std::max(moveBounds.fBottom, pts[0].fY); 21cb93a386Sopenharmony_ci break; 22cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 23cb93a386Sopenharmony_ci case SkPathVerb::kConic: 24cb93a386Sopenharmony_ci if (!wellBehaved) { 25cb93a386Sopenharmony_ci break; 26cb93a386Sopenharmony_ci } 27cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fX, pts[1].fX, pts[2].fX); 28cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fY, pts[1].fY, pts[2].fY); 29cb93a386Sopenharmony_ci break; 30cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 31cb93a386Sopenharmony_ci if (!wellBehaved) { 32cb93a386Sopenharmony_ci break; 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fX, pts[1].fX, pts[3].fX); 35cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fY, pts[1].fY, pts[3].fY); 36cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fX, pts[2].fX, pts[3].fX); 37cb93a386Sopenharmony_ci wellBehaved &= between(pts[0].fY, pts[2].fY, pts[3].fY); 38cb93a386Sopenharmony_ci break; 39cb93a386Sopenharmony_ci default: 40cb93a386Sopenharmony_ci break; 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci if (wellBehaved) { 44cb93a386Sopenharmony_ci *result = path.getBounds(); 45cb93a386Sopenharmony_ci return true; 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci SkSTArenaAlloc<4096> allocator; // FIXME: constant-ize, tune 48cb93a386Sopenharmony_ci SkOpContour contour; 49cb93a386Sopenharmony_ci SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour); 50cb93a386Sopenharmony_ci SkOpGlobalState globalState(contourList, &allocator SkDEBUGPARAMS(false) 51cb93a386Sopenharmony_ci SkDEBUGPARAMS(nullptr)); 52cb93a386Sopenharmony_ci // turn path into list of segments 53cb93a386Sopenharmony_ci SkOpEdgeBuilder builder(path, contourList, &globalState); 54cb93a386Sopenharmony_ci if (!builder.finish()) { 55cb93a386Sopenharmony_ci return false; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci if (!SortContourList(&contourList, false, false)) { 58cb93a386Sopenharmony_ci *result = moveBounds; 59cb93a386Sopenharmony_ci return true; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci SkOpContour* current = contourList; 62cb93a386Sopenharmony_ci SkPathOpsBounds bounds = current->bounds(); 63cb93a386Sopenharmony_ci while ((current = current->next())) { 64cb93a386Sopenharmony_ci bounds.add(current->bounds()); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci *result = bounds; 67cb93a386Sopenharmony_ci if (!moveBounds.isEmpty()) { 68cb93a386Sopenharmony_ci result->join(moveBounds); 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci return true; 71cb93a386Sopenharmony_ci} 72