1ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com/* 2ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com * Copyright 2013 Google Inc. 3ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com * 4ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 5ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com * found in the LICENSE file. 6ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com */ 7ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 8ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkBuffer.h" 9ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein#include "SkOnce.h" 10ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkPath.h" 11ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkPathRef.h" 120735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma#include <limits> 13ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 143e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com////////////////////////////////////////////////////////////////////////////// 156bd5284415bd983b0628c4941dff5def40018f5abungemanSkPathRef::Editor::Editor(sk_sp<SkPathRef>* pathRef, 163e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int incReserveVerbs, 173e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int incReservePoints) 183e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com{ 193e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if ((*pathRef)->unique()) { 203e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->incReserve(incReserveVerbs, incReservePoints); 213e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } else { 22385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary SkPathRef* copy = new SkPathRef; 233e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com copy->copy(**pathRef, incReserveVerbs, incReservePoints); 243e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pathRef->reset(copy); 253e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 266bd5284415bd983b0628c4941dff5def40018f5abungeman fPathRef = pathRef->get(); 2784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco fPathRef->callGenIDChangeListeners(); 283e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fPathRef->fGenerationID = 0; 293e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) 30ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com} 31ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 323e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com////////////////////////////////////////////////////////////////////////////// 33709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org 3484cd621670a357484e1674e06d3d8d6f929a4ab2senorblancoSkPathRef::~SkPathRef() { 3584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco this->callGenIDChangeListeners(); 3684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(this->validate();) 3784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco sk_free(fPoints); 3884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco 3996fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkDEBUGCODE(fPoints = nullptr;) 4096fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkDEBUGCODE(fVerbs = nullptr;) 4184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(fVerbCnt = 0x9999999;) 4284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(fPointCnt = 0xAAAAAAA;) 4384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(fPointCnt = 0xBBBBBBB;) 4484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;) 4584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco SkDEBUGCODE(fEditorsAttached = 0x7777777;) 4684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco} 4784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco 48ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtkleinstatic SkPathRef* gEmpty = nullptr; 49ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein 501f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.orgSkPathRef* SkPathRef::CreateEmpty() { 51ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein static SkOnce once; 52ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein once([]{ 53ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein gEmpty = new SkPathRef; 54ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein gEmpty->computeBounds(); // Avoids races later to be the first to do this. 55ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein }); 56ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein return SkRef(gEmpty); 571f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org} 581f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org 5978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomonstatic void transform_dir_and_start(const SkMatrix& matrix, bool isRRect, bool* isCCW, 6078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon unsigned* start) { 6178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int inStart = *start; 6278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int rm = 0; 6378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (isRRect) { 6478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Degenerate rrect indices to oval indices and remember the remainder. 6578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Ovals have one index per side whereas rrects have two. 6678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon rm = inStart & 0b1; 6778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon inStart /= 2; 6878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 6978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Is the antidiagonal non-zero (otherwise the diagonal is zero) 7078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int antiDiag; 7178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Is the non-zero value in the top row (either kMScaleX or kMSkewX) negative 7278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int topNeg; 7378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Are the two non-zero diagonal or antidiagonal values the same sign. 7478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int sameSign; 7578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (matrix.get(SkMatrix::kMScaleX) != 0) { 7678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon antiDiag = 0b00; 7778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (matrix.get(SkMatrix::kMScaleX) > 0) { 7878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon topNeg = 0b00; 7978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b01 : 0b00; 8078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } else { 8178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon topNeg = 0b10; 8278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b00 : 0b01; 8378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 8478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } else { 8578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon antiDiag = 0b01; 8678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (matrix.get(SkMatrix::kMSkewX) > 0) { 8778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon topNeg = 0b00; 8878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b01 : 0b00; 8978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } else { 9078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon topNeg = 0b10; 9178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b00 : 0b01; 9278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 9378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 9478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (sameSign != antiDiag) { 9578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // This is a rotation (and maybe scale). The direction is unchanged. 9678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Trust me on the start computation (or draw yourself some pictures) 9778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon *start = (inStart + 4 - (topNeg | antiDiag)) % 4; 9878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon SkASSERT(*start < 4); 9978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (isRRect) { 10078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon *start = 2 * *start + rm; 10178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 10278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } else { 10378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // This is a mirror (and maybe scale). The direction is reversed. 10478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon *isCCW = !*isCCW; 10578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Trust me on the start computation (or draw yourself some pictures) 10678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon *start = (6 + (topNeg | antiDiag) - inStart) % 4; 10778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon SkASSERT(*start < 4); 10878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (isRRect) { 10978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon *start = 2 * *start + (rm ? 0 : 1); 11078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 11178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 11278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon} 11378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon 1146bd5284415bd983b0628c4941dff5def40018f5abungemanvoid SkPathRef::CreateTransformedCopy(sk_sp<SkPathRef>* dst, 1153e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com const SkPathRef& src, 1163e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com const SkMatrix& matrix) { 11703087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(src.validate();) 1183e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (matrix.isIdentity()) { 1196bd5284415bd983b0628c4941dff5def40018f5abungeman if (dst->get() != &src) { 1203e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com src.ref(); 1213e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com dst->reset(const_cast<SkPathRef*>(&src)); 12203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE((*dst)->validate();) 1233e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 1243e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return; 125ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com } 1263e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 127b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com if (!(*dst)->unique()) { 128385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary dst->reset(new SkPathRef); 129b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com } 130b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com 1316bd5284415bd983b0628c4941dff5def40018f5abungeman if (dst->get() != &src) { 1323e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt, src.fConicWeights.count()); 133cc881dafcbd00e8a811c47c14b472acdba5dd6c6mtklein sk_careful_memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), 134cc881dafcbd00e8a811c47c14b472acdba5dd6c6mtklein src.fVerbCnt * sizeof(uint8_t)); 1353e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*dst)->fConicWeights = src.fConicWeights; 1363e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 1373e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 138b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com SkASSERT((*dst)->countPoints() == src.countPoints()); 139b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com SkASSERT((*dst)->countVerbs() == src.countVerbs()); 140b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com SkASSERT((*dst)->fConicWeights.count() == src.fConicWeights.count()); 141b06e88dc6505412cc2b1a5f0bfb0f669465e1f8erobertphillips@google.com 1423e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com // Need to check this here in case (&src == dst) 1433e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.countPoints() > 1; 1443e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 1453e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); 1463e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 1473e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com /* 14878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * Here we optimize the bounds computation, by noting if the bounds are 14978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * already known, and if so, we just transform those as well and mark 15078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * them as "known", rather than force the transformed path to have to 15178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * recompute them. 15278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * 15378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * Special gotchas if the path is effectively empty (<= 1 point) or 15478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * if it is non-finite. In those cases bounds need to stay empty, 15578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon * regardless of the matrix. 15678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon */ 1573e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (canXformBounds) { 1583e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*dst)->fBoundsIsDirty = false; 1593e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (src.fIsFinite) { 1605c9c9be1f540e1895e65fbd244caae9135972143mtklein matrix.mapRect(&(*dst)->fBounds, src.fBounds); 1615c9c9be1f540e1895e65fbd244caae9135972143mtklein if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) { 1625c9c9be1f540e1895e65fbd244caae9135972143mtklein (*dst)->fBounds.setEmpty(); 1633e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 1643e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } else { 1653e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*dst)->fIsFinite = false; 1665c9c9be1f540e1895e65fbd244caae9135972143mtklein (*dst)->fBounds.setEmpty(); 1673e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 1683e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } else { 1693e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*dst)->fBoundsIsDirty = true; 1703e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 1713e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 1726b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com (*dst)->fSegmentMask = src.fSegmentMask; 1736b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 174466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com // It's an oval only if it stays a rect. 175da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark bool rectStaysRect = matrix.rectStaysRect(); 176da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark (*dst)->fIsOval = src.fIsOval && rectStaysRect; 177da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark (*dst)->fIsRRect = src.fIsRRect && rectStaysRect; 17878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if ((*dst)->fIsOval || (*dst)->fIsRRect) { 17978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon unsigned start = src.fRRectOrOvalStartIdx; 18078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon bool isCCW = SkToBool(src.fRRectOrOvalIsCCW); 18178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon transform_dir_and_start(matrix, (*dst)->fIsRRect, &isCCW, &start); 18278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon (*dst)->fRRectOrOvalIsCCW = isCCW; 18378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon (*dst)->fRRectOrOvalStartIdx = start; 18478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 185466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com 18603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE((*dst)->validate();) 187ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com} 188ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 189e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed// Given the verb array, deduce the required number of pts and conics, 190e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed// or if an invalid verb is encountered, return false. 191e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reedstatic bool deduce_pts_conics(const uint8_t verbs[], int vCount, int* ptCountPtr, 192e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed int* conicCountPtr) { 193e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed int ptCount = 0; 194e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed int conicCount = 0; 195e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed for (int i = 0; i < vCount; ++i) { 196e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed switch (verbs[i]) { 197e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kMove_Verb: 198e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kLine_Verb: 199e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed ptCount += 1; 200e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed break; 201e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kConic_Verb: 202e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed conicCount += 1; 203e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed // fall-through 204e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kQuad_Verb: 205e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed ptCount += 2; 206e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed break; 207e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kCubic_Verb: 208e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed ptCount += 3; 209e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed break; 210e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed case SkPath::kClose_Verb: 211e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed break; 212e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed default: 213e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed return false; 214e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed } 215e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed } 216e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed *ptCountPtr = ptCount; 217e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed *conicCountPtr = conicCount; 218e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed return true; 219e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed} 220e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed 221fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.orgSkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) { 222709b02534681f8ab8d17f144713f276e10d13385Hal Canary std::unique_ptr<SkPathRef> ref(new SkPathRef); 223466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com 224466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com int32_t packed; 225466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com if (!buffer->readS32(&packed)) { 22696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 227466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com } 228466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com 229466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; 230da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark uint8_t segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; 231da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark bool isOval = (packed >> kIsOval_SerializationShift) & 1; 232da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark bool isRRect = (packed >> kIsRRect_SerializationShift) & 1; 233709b02534681f8ab8d17f144713f276e10d13385Hal Canary if (isOval && isRRect) { 234709b02534681f8ab8d17f144713f276e10d13385Hal Canary // Fuzzing generates data with both oval and rrect flags set; abort early in this case/ 235709b02534681f8ab8d17f144713f276e10d13385Hal Canary return nullptr; 236709b02534681f8ab8d17f144713f276e10d13385Hal Canary } 23778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon bool rrectOrOvalIsCCW = (packed >> kRRectOrOvalIsCCW_SerializationShift) & 1; 23878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon unsigned rrectOrOvalStartIdx = (packed >> kRRectOrOvalStartIdx_SerializationShift) & 0x7; 239ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 2408f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org int32_t verbCount, pointCount, conicCount; 2410735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma ptrdiff_t maxPtrDiff = std::numeric_limits<ptrdiff_t>::max(); 2428f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org if (!buffer->readU32(&(ref->fGenerationID)) || 2438f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org !buffer->readS32(&verbCount) || 244f8aec588bfd2df17130ee93593a8f4ae781afe1fajuma verbCount < 0 || 2450735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma static_cast<uint32_t>(verbCount) > maxPtrDiff/sizeof(uint8_t) || 2468f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org !buffer->readS32(&pointCount) || 247f8aec588bfd2df17130ee93593a8f4ae781afe1fajuma pointCount < 0 || 2480735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma static_cast<uint32_t>(pointCount) > maxPtrDiff/sizeof(SkPoint) || 2490735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount > 2500735de67c8a0812ae2fd103ae1bd7f2157c6a0b2ajuma static_cast<size_t>(maxPtrDiff) || 251f8aec588bfd2df17130ee93593a8f4ae781afe1fajuma !buffer->readS32(&conicCount) || 252f8aec588bfd2df17130ee93593a8f4ae781afe1fajuma conicCount < 0) { 25396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2548f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org } 255ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 2568f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org ref->resetToSize(verbCount, pointCount, conicCount); 257ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com SkASSERT(verbCount == ref->countVerbs()); 258ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com SkASSERT(pointCount == ref->countPoints()); 259ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com SkASSERT(conicCount == ref->fConicWeights.count()); 2608f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org 2618f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) || 2628f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) || 2638f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) || 2648f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org !buffer->read(&ref->fBounds, sizeof(SkRect))) { 26596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2668f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org } 267e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed 268e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed // Check that the verbs are valid, and imply the correct number of pts and conics 269e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed { 270e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed int pCount, cCount; 271e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed if (!deduce_pts_conics(ref->verbsMemBegin(), ref->countVerbs(), &pCount, &cCount) || 272e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed pCount != ref->countPoints() || cCount != ref->fConicWeights.count()) { 273709b02534681f8ab8d17f144713f276e10d13385Hal Canary return nullptr; 274709b02534681f8ab8d17f144713f276e10d13385Hal Canary } 275709b02534681f8ab8d17f144713f276e10d13385Hal Canary // Check that the bounds match the serialized bounds. 276709b02534681f8ab8d17f144713f276e10d13385Hal Canary SkRect bounds; 277709b02534681f8ab8d17f144713f276e10d13385Hal Canary if (ComputePtBounds(&bounds, *ref) != SkToBool(ref->fIsFinite) || bounds != ref->fBounds) { 278e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed return nullptr; 279e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed } 280e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed } 281e3374d68932ce5bd1e6a50b05a6764a543c00c39Mike Reed 282ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com ref->fBoundsIsDirty = false; 2836b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 2846b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // resetToSize clears fSegmentMask and fIsOval 2856b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com ref->fSegmentMask = segmentMask; 286466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com ref->fIsOval = isOval; 287da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark ref->fIsRRect = isRRect; 28878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon ref->fRRectOrOvalIsCCW = rrectOrOvalIsCCW; 28978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon ref->fRRectOrOvalStartIdx = rrectOrOvalStartIdx; 290709b02534681f8ab8d17f144713f276e10d13385Hal Canary return ref.release(); 291ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com} 292ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 2936bd5284415bd983b0628c4941dff5def40018f5abungemanvoid SkPathRef::Rewind(sk_sp<SkPathRef>* pathRef) { 2943e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if ((*pathRef)->unique()) { 29503087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE((*pathRef)->validate();) 29684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco (*pathRef)->callGenIDChangeListeners(); 2973e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite 2983e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fVerbCnt = 0; 2993e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fPointCnt = 0; 3003e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fFreeSpace = (*pathRef)->currSize(); 3013e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fGenerationID = 0; 3023e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->fConicWeights.rewind(); 3036b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com (*pathRef)->fSegmentMask = 0; 304466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com (*pathRef)->fIsOval = false; 305da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark (*pathRef)->fIsRRect = false; 30603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE((*pathRef)->validate();) 3073e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } else { 3083e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int oldVCnt = (*pathRef)->countVerbs(); 3093e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int oldPCnt = (*pathRef)->countPoints(); 310385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary pathRef->reset(new SkPathRef); 3113e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt); 3123e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 3133e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 3143e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 3153e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.combool SkPathRef::operator== (const SkPathRef& ref) const { 31603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 31703087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(ref.validate();) 3186b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 3196b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // We explicitly check fSegmentMask as a quick-reject. We could skip it, 3206b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // since it is only a cache of info in the fVerbs, but its a fast way to 3216b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // notice a difference 3226b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com if (fSegmentMask != ref.fSegmentMask) { 3236b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com return false; 3246b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 3256b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 3263e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID; 3273e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com#ifdef SK_RELEASE 3283e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (genIDMatch) { 3293e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return true; 3303e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 3313e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com#endif 3323e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (fPointCnt != ref.fPointCnt || 3333e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fVerbCnt != ref.fVerbCnt) { 3343e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(!genIDMatch); 3353e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return false; 3363e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 337d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein if (0 == ref.fVerbCnt) { 338d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein SkASSERT(0 == ref.fPointCnt); 339d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein return true; 340d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein } 341d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein SkASSERT(this->verbsMemBegin() && ref.verbsMemBegin()); 3423e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (0 != memcmp(this->verbsMemBegin(), 3433e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com ref.verbsMemBegin(), 3443e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com ref.fVerbCnt * sizeof(uint8_t))) { 3453e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(!genIDMatch); 3463e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return false; 3473e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 348d4897591fddf8f2a4860066449fb7dd8b0cc7b77mtklein SkASSERT(this->points() && ref.points()); 3493e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (0 != memcmp(this->points(), 3503e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com ref.points(), 3513e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com ref.fPointCnt * sizeof(SkPoint))) { 3523e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(!genIDMatch); 3533e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return false; 3543e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 3553e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (fConicWeights != ref.fConicWeights) { 3563e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(!genIDMatch); 3573e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return false; 3583e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 3593e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return true; 3603e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 3613e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 3626b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.comvoid SkPathRef::writeToBuffer(SkWBuffer* buffer) const { 36303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 364ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com SkDEBUGCODE(size_t beforePos = buffer->pos();) 365ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 366ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com // Call getBounds() to ensure (as a side-effect) that fBounds 367ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com // and fIsFinite are computed. 368ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com const SkRect& bounds = this->getBounds(); 369ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 37078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon int32_t packed = ((fRRectOrOvalStartIdx & 7) << kRRectOrOvalStartIdx_SerializationShift) | 37178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon ((fRRectOrOvalIsCCW & 1) << kRRectOrOvalIsCCW_SerializationShift) | 37278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon ((fIsFinite & 1) << kIsFinite_SerializationShift) | 3736b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com ((fIsOval & 1) << kIsOval_SerializationShift) | 374da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark ((fIsRRect & 1) << kIsRRect_SerializationShift) | 3756b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com (fSegmentMask << kSegmentMask_SerializationShift); 376ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write32(packed); 377ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 378ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com // TODO: write gen ID here. Problem: We don't know if we're cross process or not from 379ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com // SkWBuffer. Until this is fixed we write 0. 380ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write32(0); 381ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write32(fVerbCnt); 382ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write32(fPointCnt); 383ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write32(fConicWeights.count()); 384ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); 385ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); 386ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write(fConicWeights.begin(), fConicWeights.bytes()); 387ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com buffer->write(&bounds, sizeof(bounds)); 388ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com 389ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize()); 390ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com} 3913e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 3926b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.comuint32_t SkPathRef::writeSize() const { 3933e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return uint32_t(5 * sizeof(uint32_t) + 3943e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fVerbCnt * sizeof(uint8_t) + 3953e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fPointCnt * sizeof(SkPoint) + 3963e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fConicWeights.bytes() + 3973e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com sizeof(SkRect)); 3983e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 3993e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 40050df4d013f840749f70d1759c23c4217e727fd54skia.committer@gmail.comvoid SkPathRef::copy(const SkPathRef& ref, 40150df4d013f840749f70d1759c23c4217e727fd54skia.committer@gmail.com int additionalReserveVerbs, 4023e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int additionalReservePoints) { 40303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 4043e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), 4053e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com additionalReserveVerbs, additionalReservePoints); 406cc881dafcbd00e8a811c47c14b472acdba5dd6c6mtklein sk_careful_memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt*sizeof(uint8_t)); 407cc881dafcbd00e8a811c47c14b472acdba5dd6c6mtklein sk_careful_memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); 4083e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fConicWeights = ref.fConicWeights; 4093e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fBoundsIsDirty = ref.fBoundsIsDirty; 4103e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (!fBoundsIsDirty) { 4113e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fBounds = ref.fBounds; 4123e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fIsFinite = ref.fIsFinite; 4133e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 4146b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask = ref.fSegmentMask; 415466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com fIsOval = ref.fIsOval; 416da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fIsRRect = ref.fIsRRect; 41778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon fRRectOrOvalIsCCW = ref.fRRectOrOvalIsCCW; 41878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon fRRectOrOvalStartIdx = ref.fRRectOrOvalStartIdx; 41903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 4203e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 4213e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 4228e7b19d0f04f286ec283747ec128e9696c842858caryclark 4238e7b19d0f04f286ec283747ec128e9696c842858caryclarkvoid SkPathRef::interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef* out) const { 4248e7b19d0f04f286ec283747ec128e9696c842858caryclark const SkScalar* inValues = &ending.getPoints()->fX; 4258e7b19d0f04f286ec283747ec128e9696c842858caryclark SkScalar* outValues = &out->getPoints()->fX; 4268e7b19d0f04f286ec283747ec128e9696c842858caryclark int count = out->countPoints() * 2; 4278e7b19d0f04f286ec283747ec128e9696c842858caryclark for (int index = 0; index < count; ++index) { 4288e7b19d0f04f286ec283747ec128e9696c842858caryclark outValues[index] = outValues[index] * weight + inValues[index] * (1 - weight); 4298e7b19d0f04f286ec283747ec128e9696c842858caryclark } 4308e7b19d0f04f286ec283747ec128e9696c842858caryclark out->fBoundsIsDirty = true; 4318e7b19d0f04f286ec283747ec128e9696c842858caryclark out->fIsOval = false; 4328e7b19d0f04f286ec283747ec128e9696c842858caryclark out->fIsRRect = false; 4338e7b19d0f04f286ec283747ec128e9696c842858caryclark} 4348e7b19d0f04f286ec283747ec128e9696c842858caryclark 43596f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.comSkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb, 43696f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com int numVbs, 4376b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkScalar** weights) { 4386b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // This value is just made-up for now. When count is 4, calling memset was much 4396b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // slower than just writing the loop. This seems odd, and hopefully in the 4406b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // future this will appear to have been a fluke... 4416b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16; 4426b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 4436b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGCODE(this->validate();) 4446b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com int pCnt; 4456b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com bool dirtyAfterEdit = true; 4466b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com switch (verb) { 4476b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kMove_Verb: 4486b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = numVbs; 4496b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com dirtyAfterEdit = false; 4506b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4516b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kLine_Verb: 4526b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kLine_SegmentMask; 4536b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = numVbs; 4546b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4556b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kQuad_Verb: 4566b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kQuad_SegmentMask; 4576b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 2 * numVbs; 4586b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4596b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kConic_Verb: 4606b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kConic_SegmentMask; 4616b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 2 * numVbs; 4626b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4636b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kCubic_Verb: 4646b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kCubic_SegmentMask; 4656b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 3 * numVbs; 4666b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4676b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kClose_Verb: 4686b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb"); 4696b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 0; 4706b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com dirtyAfterEdit = false; 4716b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 4726b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kDone_Verb: 4736b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGFAIL("growForRepeatedVerb called for kDone"); 4746b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // fall through 4756b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com default: 4766b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGFAIL("default should not be reached"); 4776b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 0; 4786b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com dirtyAfterEdit = false; 4796b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 4806b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 4816b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint); 4826b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com this->makeSpace(space); 4836b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 4846b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkPoint* ret = fPoints + fPointCnt; 4856b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com uint8_t* vb = fVerbs - fVerbCnt; 4866b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 4876b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to 4886b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com // be 0, the compiler will remove the test/branch entirely. 4896b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) { 4906b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com memset(vb - numVbs, verb, numVbs); 4916b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } else { 4926b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com for (int i = 0; i < numVbs; ++i) { 4936b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com vb[~i] = verb; 4946b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 4956b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 4966b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 4976b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fVerbCnt += numVbs; 4986b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fPointCnt += pCnt; 4996b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fFreeSpace -= space; 5006b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fBoundsIsDirty = true; // this also invalidates fIsFinite 5016b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com if (dirtyAfterEdit) { 5026b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fIsOval = false; 503da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fIsRRect = false; 5046b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 5056b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 5066b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com if (SkPath::kConic_Verb == verb) { 50749f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(weights); 5086b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com *weights = fConicWeights.append(numVbs); 5096b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 5106b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 5116b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGCODE(this->validate();) 5126b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com return ret; 5136b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com} 5146b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 5156b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.comSkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) { 51603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 5173e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com int pCnt; 518466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com bool dirtyAfterEdit = true; 5193e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com switch (verb) { 5203e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kMove_Verb: 5213e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 1; 522466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com dirtyAfterEdit = false; 5233e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com break; 5243e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kLine_Verb: 5256b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kLine_SegmentMask; 5263e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 1; 5273e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com break; 5283e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kQuad_Verb: 5296b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kQuad_SegmentMask; 5306b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com pCnt = 2; 5316b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 5323e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kConic_Verb: 5336b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kConic_SegmentMask; 5343e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 2; 5353e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com break; 5363e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kCubic_Verb: 5376b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com fSegmentMask |= SkPath::kCubic_SegmentMask; 5383e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 3; 5393e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com break; 5403e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kClose_Verb: 5413e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 0; 542466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com dirtyAfterEdit = false; 5433e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com break; 5443e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com case SkPath::kDone_Verb: 5453e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkDEBUGFAIL("growForVerb called for kDone"); 5463e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com // fall through 5473e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com default: 5483e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkDEBUGFAIL("default is not reached"); 549466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com dirtyAfterEdit = false; 5503e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com pCnt = 0; 5513e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 5523e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); 5533e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com this->makeSpace(space); 5543e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com this->fVerbs[~fVerbCnt] = verb; 5553e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkPoint* ret = fPoints + fPointCnt; 5563e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fVerbCnt += 1; 5573e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fPointCnt += pCnt; 5583e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fFreeSpace -= space; 5593e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fBoundsIsDirty = true; // this also invalidates fIsFinite 560466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com if (dirtyAfterEdit) { 561466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com fIsOval = false; 562da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fIsRRect = false; 563466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com } 5646b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 5656b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com if (SkPath::kConic_Verb == verb) { 5666b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com *fConicWeights.append() = weight; 5676b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 5686b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 56903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com SkDEBUGCODE(this->validate();) 5703e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return ret; 5713e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 5723e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 5731ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.orguint32_t SkPathRef::genID() const { 5743e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(!fEditorsAttached); 5751ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org static const uint32_t kMask = (static_cast<int64_t>(1) << SkPath::kPathRefGenIDBitCnt) - 1; 5763e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (!fGenerationID) { 5773e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (0 == fPointCnt && 0 == fVerbCnt) { 5783e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fGenerationID = kEmptyGenID; 5793e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } else { 5803e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com static int32_t gPathRefGenerationID; 5813e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com // do a loop in case our global wraps around, as we never want to return a 0 or the 5823e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com // empty ID 5833e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com do { 5841ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMask; 5853e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } while (fGenerationID <= kEmptyGenID); 5863e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 5873e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 5883e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com return fGenerationID; 5893e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 5903e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 59184cd621670a357484e1674e06d3d8d6f929a4ab2senorblancovoid SkPathRef::addGenIDChangeListener(GenIDChangeListener* listener) { 592ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein if (nullptr == listener || this == gEmpty) { 593385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary delete listener; 59484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco return; 59584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco } 59684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco *fGenIDChangeListeners.append() = listener; 59784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco} 59884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco 59984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco// we need to be called *before* the genID gets changed or zerod 60084cd621670a357484e1674e06d3d8d6f929a4ab2senorblancovoid SkPathRef::callGenIDChangeListeners() { 60184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 60284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco fGenIDChangeListeners[i]->onChange(); 60384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco } 60484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco 60584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco // Listeners get at most one shot, so whether these triggered or not, blow them away. 60684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco fGenIDChangeListeners.deleteAll(); 60784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco} 60884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco 609da707bf5635c70d4c3c284a0b05d92489b76788ecaryclarkSkRRect SkPathRef::getRRect() const { 610da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark const SkRect& bounds = this->getBounds(); 611da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; 612da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark Iter iter(*this); 613da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkPoint pts[4]; 614da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark uint8_t verb = iter.next(pts); 615da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(SkPath::kMove_Verb == verb); 616da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 617da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark if (SkPath::kConic_Verb == verb) { 618da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkVector v1_0 = pts[1] - pts[0]; 619da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkVector v2_1 = pts[2] - pts[1]; 620da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkVector dxdy; 621da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark if (v1_0.fX) { 622da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(!v2_1.fX && !v1_0.fY); 623da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY)); 624da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } else if (!v1_0.fY) { 625da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(!v2_1.fX || !v2_1.fY); 626da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY)); 627da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } else { 628da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(!v2_1.fY); 629da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY)); 630da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } 631da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkRRect::Corner corner = 632da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1].fX == bounds.fLeft ? 633da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1].fY == bounds.fTop ? 634da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkRRect::kUpperLeft_Corner : SkRRect::kLowerLeft_Corner : 635da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1].fY == bounds.fTop ? 636da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkRRect::kUpperRight_Corner : SkRRect::kLowerRight_Corner; 637da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(!radii[corner].fX && !radii[corner].fY); 638da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark radii[corner] = dxdy; 639da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } else { 640da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT((verb == SkPath::kLine_Verb 641da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY))) 642da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark || verb == SkPath::kClose_Verb); 643da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } 644da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } 645da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkRRect rrect; 646da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark rrect.setRectRadii(bounds, radii); 647da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark return rrect; 648da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark} 649da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 650da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark/////////////////////////////////////////////////////////////////////////////// 651da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 652da707bf5635c70d4c3c284a0b05d92489b76788ecaryclarkSkPathRef::Iter::Iter() { 653da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark#ifdef SK_DEBUG 654da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fPts = nullptr; 655da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fConicWeights = nullptr; 656da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark#endif 657da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark // need to init enough to make next() harmlessly return kDone_Verb 658da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fVerbs = nullptr; 659da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fVerbStop = nullptr; 660da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark} 661da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 662da707bf5635c70d4c3c284a0b05d92489b76788ecaryclarkSkPathRef::Iter::Iter(const SkPathRef& path) { 663da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark this->setPathRef(path); 664da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark} 665da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 666da707bf5635c70d4c3c284a0b05d92489b76788ecaryclarkvoid SkPathRef::Iter::setPathRef(const SkPathRef& path) { 667da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fPts = path.points(); 668da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fVerbs = path.verbs(); 669da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fVerbStop = path.verbsMemBegin(); 6706942442ef7cc018ac136dd379ad6a30902a060e5caryclark fConicWeights = path.conicWeights(); 6716942442ef7cc018ac136dd379ad6a30902a060e5caryclark if (fConicWeights) { 6726942442ef7cc018ac136dd379ad6a30902a060e5caryclark fConicWeights -= 1; // begin one behind 6736942442ef7cc018ac136dd379ad6a30902a060e5caryclark } 674da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark} 675da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 676da707bf5635c70d4c3c284a0b05d92489b76788ecaryclarkuint8_t SkPathRef::Iter::next(SkPoint pts[4]) { 677da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(pts); 678da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark if (fVerbs == fVerbStop) { 679da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark return (uint8_t) SkPath::kDone_Verb; 680da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } 681da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 682da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark // fVerbs points one beyond next verb so decrement first. 683da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark unsigned verb = *(--fVerbs); 684da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark const SkPoint* srcPts = fPts; 685da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 686da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark switch (verb) { 687da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kMove_Verb: 688da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[0] = srcPts[0]; 689da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark srcPts += 1; 690da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 691da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kLine_Verb: 692da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[0] = srcPts[-1]; 693da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1] = srcPts[0]; 694da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark srcPts += 1; 695da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 696da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kConic_Verb: 697da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fConicWeights += 1; 698da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark // fall-through 699da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kQuad_Verb: 700da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[0] = srcPts[-1]; 701da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1] = srcPts[0]; 702da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[2] = srcPts[1]; 703da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark srcPts += 2; 704da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 705da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kCubic_Verb: 706da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[0] = srcPts[-1]; 707da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[1] = srcPts[0]; 708da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[2] = srcPts[1]; 709da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark pts[3] = srcPts[2]; 710da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark srcPts += 3; 711da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 712da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kClose_Verb: 713da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 714da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark case SkPath::kDone_Verb: 715da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark SkASSERT(fVerbs == fVerbStop); 716da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark break; 717da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark } 718da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark fPts = srcPts; 719da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark return (uint8_t) verb; 720da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark} 721da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark 7222028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclarkuint8_t SkPathRef::Iter::peek() const { 7232028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark const uint8_t* next = fVerbs - 1; 7242028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark return next <= fVerbStop ? (uint8_t) SkPath::kDone_Verb : *next; 7252028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark} 7262028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark 72703087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 7280c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark 7290c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark#include "SkNx.h" 7300c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark 7313e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.comvoid SkPathRef::validate() const { 7323e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); 7333e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints) >= 0); 73496fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT((nullptr == fPoints) == (nullptr == fVerbs)); 73596fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace)); 73696fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace)); 73796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(!(nullptr == fPoints && fPointCnt)); 73896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(!(nullptr == fVerbs && fVerbCnt)); 7393e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(this->currSize() == 7403e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt); 7413e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com 74278d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (fIsOval || fIsRRect) { 74378d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon // Currently we don't allow both of these to be set, even though ovals are round rects. 74478d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon SkASSERT(fIsOval != fIsRRect); 74578d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon if (fIsOval) { 74678d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon SkASSERT(fRRectOrOvalStartIdx < 4); 74778d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } else { 74878d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon SkASSERT(fRRectOrOvalStartIdx < 8); 74978d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 75078d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon } 75178d58d1084f0390c1c0f9123ac6e48efcd226f39bsalomon 7525c9c9be1f540e1895e65fbd244caae9135972143mtklein if (!fBoundsIsDirty && !fBounds.isEmpty()) { 7533e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com bool isFinite = true; 7540c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark Sk2s leftTop = Sk2s(fBounds.fLeft, fBounds.fTop); 7550c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark Sk2s rightBot = Sk2s(fBounds.fRight, fBounds.fBottom); 7563e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com for (int i = 0; i < fPointCnt; ++i) { 7570c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark Sk2s point = Sk2s(fPoints[i].fX, fPoints[i].fY); 758f1cdead599715dbae30278bffa4528bd1664f61frobertphillips#ifdef SK_DEBUG 759f1cdead599715dbae30278bffa4528bd1664f61frobertphillips if (fPoints[i].isFinite() && 7600c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark ((point < leftTop).anyTrue() || (point > rightBot).anyTrue())) { 761f1cdead599715dbae30278bffa4528bd1664f61frobertphillips SkDebugf("bounds: %f %f %f %f\n", 762f1cdead599715dbae30278bffa4528bd1664f61frobertphillips fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 763f1cdead599715dbae30278bffa4528bd1664f61frobertphillips for (int j = 0; j < fPointCnt; ++j) { 764f1cdead599715dbae30278bffa4528bd1664f61frobertphillips if (i == j) { 765f1cdead599715dbae30278bffa4528bd1664f61frobertphillips SkDebugf("*"); 766f1cdead599715dbae30278bffa4528bd1664f61frobertphillips } 767f1cdead599715dbae30278bffa4528bd1664f61frobertphillips SkDebugf("%f %f\n", fPoints[j].fX, fPoints[j].fY); 768f1cdead599715dbae30278bffa4528bd1664f61frobertphillips } 769f1cdead599715dbae30278bffa4528bd1664f61frobertphillips } 770f1cdead599715dbae30278bffa4528bd1664f61frobertphillips#endif 771f1cdead599715dbae30278bffa4528bd1664f61frobertphillips 7720e912464cecf50cc152c3fb93c2aac31c8a99cacrobertphillips SkASSERT(!fPoints[i].isFinite() || 7730c52b1740e9714bdfaa111bec923a3f61a55d5b4caryclark (!(point < leftTop).anyTrue() && !(point > rightBot).anyTrue())); 7743e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com if (!fPoints[i].isFinite()) { 7753e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com isFinite = false; 7763e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 7773e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 7783e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com SkASSERT(SkToBool(fIsFinite) == isFinite); 7793e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com } 7806b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com 7816b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com#ifdef SK_DEBUG_PATH 7826b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com uint32_t mask = 0; 7836b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com for (int i = 0; i < fVerbCnt; ++i) { 7846b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com switch (fVerbs[~i]) { 7856b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kMove_Verb: 7866b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 7876b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kLine_Verb: 7886b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com mask |= SkPath::kLine_SegmentMask; 7896b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 7906b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kQuad_Verb: 7916b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com mask |= SkPath::kQuad_SegmentMask; 7926b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 7936b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kConic_Verb: 7946b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com mask |= SkPath::kConic_SegmentMask; 7956b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 7966b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kCubic_Verb: 7976b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com mask |= SkPath::kCubic_SegmentMask; 7986b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 7996b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kClose_Verb: 8006b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 8016b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com case SkPath::kDone_Verb: 8026b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGFAIL("Done verb shouldn't be recorded."); 8036b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 8046b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com default: 8056b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkDEBUGFAIL("Unknown Verb"); 8066b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com break; 8076b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 8086b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com } 8096b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com SkASSERT(mask == fSegmentMask); 8106b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com#endif // SK_DEBUG_PATH 8113e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com} 81203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 813