|  | /* | 
|  | * Copyright 2007 The Android Open Source Project | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "SkMask.h" | 
|  |  | 
|  | #include "SkMalloc.h" | 
|  |  | 
|  | //#define TRACK_SKMASK_LIFETIME | 
|  |  | 
|  | /** returns the product if it is positive and fits in 31 bits. Otherwise this | 
|  | returns 0. | 
|  | */ | 
|  | static int32_t safeMul32(int32_t a, int32_t b) { | 
|  | int64_t size = sk_64_mul(a, b); | 
|  | if (size > 0 && sk_64_isS32(size)) { | 
|  | return sk_64_asS32(size); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | size_t SkMask::computeImageSize() const { | 
|  | return safeMul32(fBounds.height(), fRowBytes); | 
|  | } | 
|  |  | 
|  | size_t SkMask::computeTotalImageSize() const { | 
|  | size_t size = this->computeImageSize(); | 
|  | if (fFormat == SkMask::k3D_Format) { | 
|  | size = safeMul32(SkToS32(size), 3); | 
|  | } | 
|  | return size; | 
|  | } | 
|  |  | 
|  | #ifdef TRACK_SKMASK_LIFETIME | 
|  | static int gCounter; | 
|  | #endif | 
|  |  | 
|  | /** We explicitly use this allocator for SkBimap pixels, so that we can | 
|  | freely assign memory allocated by one class to the other. | 
|  | */ | 
|  | uint8_t* SkMask::AllocImage(size_t size) { | 
|  | #ifdef TRACK_SKMASK_LIFETIME | 
|  | SkDebugf("SkMask::AllocImage %d\n", gCounter++); | 
|  | #endif | 
|  | size_t aligned_size = std::numeric_limits<size_t>::max(); | 
|  |  | 
|  | // Expand size to next multiple of four. | 
|  | size_t adjustment = 3; | 
|  | if (size + adjustment > size) { | 
|  | aligned_size = (size + adjustment) & ~adjustment; | 
|  | } | 
|  | return static_cast<uint8_t*>(sk_malloc_throw(aligned_size)); | 
|  | } | 
|  |  | 
|  | /** We explicitly use this allocator for SkBimap pixels, so that we can | 
|  | freely assign memory allocated by one class to the other. | 
|  | */ | 
|  | void SkMask::FreeImage(void* image) { | 
|  | #ifdef TRACK_SKMASK_LIFETIME | 
|  | if (image) { | 
|  | SkDebugf("SkMask::FreeImage  %d\n", --gCounter); | 
|  | } | 
|  | #endif | 
|  | sk_free(image); | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | static const int gMaskFormatToShift[] = { | 
|  | ~0, // BW -- not supported | 
|  | 0,  // A8 | 
|  | 0,  // 3D | 
|  | 2,  // ARGB32 | 
|  | 1,  // LCD16 | 
|  | }; | 
|  |  | 
|  | static int maskFormatToShift(SkMask::Format format) { | 
|  | SkASSERT((unsigned)format < SK_ARRAY_COUNT(gMaskFormatToShift)); | 
|  | SkASSERT(SkMask::kBW_Format != format); | 
|  | return gMaskFormatToShift[format]; | 
|  | } | 
|  |  | 
|  | void* SkMask::getAddr(int x, int y) const { | 
|  | SkASSERT(kBW_Format != fFormat); | 
|  | SkASSERT(fBounds.contains(x, y)); | 
|  | SkASSERT(fImage); | 
|  |  | 
|  | char* addr = (char*)fImage; | 
|  | addr += (y - fBounds.fTop) * fRowBytes; | 
|  | addr += (x - fBounds.fLeft) << maskFormatToShift(fFormat); | 
|  | return addr; | 
|  | } |