1/*
2 * Copyright 2007 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkMask.h"
9
10//#define TRACK_SKMASK_LIFETIME
11
12/** returns the product if it is positive and fits in 31 bits. Otherwise this
13    returns 0.
14 */
15static int32_t safeMul32(int32_t a, int32_t b) {
16    int64_t size = sk_64_mul(a, b);
17    if (size > 0 && sk_64_isS32(size)) {
18        return sk_64_asS32(size);
19    }
20    return 0;
21}
22
23size_t SkMask::computeImageSize() const {
24    return safeMul32(fBounds.height(), fRowBytes);
25}
26
27size_t SkMask::computeTotalImageSize() const {
28    size_t size = this->computeImageSize();
29    if (fFormat == SkMask::k3D_Format) {
30        size = safeMul32(SkToS32(size), 3);
31    }
32    return size;
33}
34
35#ifdef TRACK_SKMASK_LIFETIME
36    static int gCounter;
37#endif
38
39/** We explicitly use this allocator for SkBimap pixels, so that we can
40    freely assign memory allocated by one class to the other.
41*/
42uint8_t* SkMask::AllocImage(size_t size) {
43#ifdef TRACK_SKMASK_LIFETIME
44    SkDebugf("SkMask::AllocImage %d\n", gCounter++);
45#endif
46    return (uint8_t*)sk_malloc_throw(SkAlign4(size));
47}
48
49/** We explicitly use this allocator for SkBimap pixels, so that we can
50    freely assign memory allocated by one class to the other.
51*/
52void SkMask::FreeImage(void* image) {
53#ifdef TRACK_SKMASK_LIFETIME
54    if (image) {
55        SkDebugf("SkMask::FreeImage  %d\n", --gCounter);
56    }
57#endif
58    sk_free(image);
59}
60
61///////////////////////////////////////////////////////////////////////////////
62
63static const int gMaskFormatToShift[] = {
64    ~0, // BW -- not supported
65    0,  // A8
66    0,  // 3D
67    2,  // ARGB32
68    1,  // LCD16
69};
70
71static int maskFormatToShift(SkMask::Format format) {
72    SkASSERT((unsigned)format < SK_ARRAY_COUNT(gMaskFormatToShift));
73    SkASSERT(SkMask::kBW_Format != format);
74    return gMaskFormatToShift[format];
75}
76
77void* SkMask::getAddr(int x, int y) const {
78    SkASSERT(kBW_Format != fFormat);
79    SkASSERT(fBounds.contains(x, y));
80    SkASSERT(fImage);
81
82    char* addr = (char*)fImage;
83    addr += (y - fBounds.fTop) * fRowBytes;
84    addr += (x - fBounds.fLeft) << maskFormatToShift(fFormat);
85    return addr;
86}
87