1 /* libs/corecg/SkRegionPriv.h 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #ifndef SkRegionPriv_DEFINED 19 #define SkRegionPriv_DEFINED 20 21 #include "SkRegion.h" 22 #include "SkThread.h" 23 24 #define assert_sentinel(value, isSentinel) \ 25 SkASSERT(((value) == SkRegion::kRunTypeSentinel) == isSentinel) 26 27 //SkDEBUGCODE(extern int32_t gRgnAllocCounter;) 28 29 struct SkRegion::RunHead { 30 int32_t fRefCnt; 31 int32_t fRunCount; 32 AllocRunHead33 static RunHead* Alloc(int count) 34 { 35 //SkDEBUGCODE(sk_atomic_inc(&gRgnAllocCounter);) 36 //SkDEBUGF(("************** gRgnAllocCounter::alloc %d\n", gRgnAllocCounter)); 37 38 SkASSERT(count >= SkRegion::kRectRegionRuns); 39 40 RunHead* head = (RunHead*)sk_malloc_throw(sizeof(RunHead) + count * sizeof(RunType)); 41 head->fRefCnt = 1; 42 head->fRunCount = count; 43 return head; 44 } 45 isComplexRunHead46 bool isComplex() const 47 { 48 return this != SkRegion_gEmptyRunHeadPtr && this != SkRegion_gRectRunHeadPtr; 49 } 50 writable_runsRunHead51 SkRegion::RunType* writable_runs() 52 { 53 SkASSERT(this->isComplex()); 54 SkASSERT(fRefCnt == 1); 55 return (SkRegion::RunType*)(this + 1); 56 } readonly_runsRunHead57 const SkRegion::RunType* readonly_runs() const 58 { 59 SkASSERT(this->isComplex()); 60 return (const SkRegion::RunType*)(this + 1); 61 } 62 ensureWritableRunHead63 RunHead* ensureWritable() 64 { 65 SkASSERT(this->isComplex()); 66 67 RunHead* writable = this; 68 if (fRefCnt > 1) 69 { 70 // We need to alloc & copy the current region before we call 71 // sk_atomic_dec because it could be freed in the meantime, 72 // otherwise. 73 writable = Alloc(fRunCount); 74 memcpy(writable->writable_runs(), this->readonly_runs(), 75 fRunCount * sizeof(RunType)); 76 77 // fRefCount might have changed since we last checked. 78 // If we own the last reference at this point, we need to 79 // free the memory. 80 if (sk_atomic_dec(&fRefCnt) == 1) 81 { 82 sk_free(this); 83 } 84 } 85 return writable; 86 } 87 }; 88 89 #endif 90