• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
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 "include/core/SkMallocPixelRef.h"
9 
10 #include "include/core/SkData.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/private/SkMalloc.h"
13 #include "src/core/SkSafeMath.h"
14 
sk_calloc_throw(size_t count,size_t elemSize)15 void* sk_calloc_throw(size_t count, size_t elemSize) {
16     return sk_calloc_throw(SkSafeMath::Mul(count, elemSize));
17 }
18 
sk_malloc_throw(size_t count,size_t elemSize)19 void* sk_malloc_throw(size_t count, size_t elemSize) {
20     return sk_malloc_throw(SkSafeMath::Mul(count, elemSize));
21 }
22 
sk_realloc_throw(void * buffer,size_t count,size_t elemSize)23 void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize) {
24     return sk_realloc_throw(buffer, SkSafeMath::Mul(count, elemSize));
25 }
26 
sk_malloc_canfail(size_t count,size_t elemSize)27 void* sk_malloc_canfail(size_t count, size_t elemSize) {
28     return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize));
29 }
30 
31 ///////////////////////////////////////////////////////////////////////////////////////////////////
32 
is_valid(const SkImageInfo & info)33 static bool is_valid(const SkImageInfo& info) {
34     if (info.width() < 0 || info.height() < 0 ||
35         (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
36         (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
37     {
38         return false;
39     }
40     return true;
41 }
42 
MakeAllocate(const SkImageInfo & info,size_t rowBytes)43 sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, size_t rowBytes) {
44     if (rowBytes == 0) {
45         rowBytes = info.minRowBytes();
46         // rowBytes can still be zero, if it overflowed (width * bytesPerPixel > size_t)
47         // or if colortype is unknown
48     }
49     if (!is_valid(info) || !info.validRowBytes(rowBytes)) {
50         return nullptr;
51     }
52     size_t size = 0;
53     if (!info.isEmpty() && rowBytes) {
54         size = info.computeByteSize(rowBytes);
55         if (SkImageInfo::ByteSizeOverflowed(size)) {
56             return nullptr;
57         }
58     }
59     void* addr = sk_calloc_canfail(size);
60     if (nullptr == addr) {
61         return nullptr;
62     }
63 
64     struct PixelRef final : public SkPixelRef {
65         PixelRef(int w, int h, void* s, size_t r) : SkPixelRef(w, h, s, r) {}
66         ~PixelRef() override { sk_free(this->pixels()); }
67     };
68     return sk_sp<SkPixelRef>(new PixelRef(info.width(), info.height(), addr, rowBytes));
69 }
70 
MakeWithData(const SkImageInfo & info,size_t rowBytes,sk_sp<SkData> data)71 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
72                                                  size_t rowBytes,
73                                                  sk_sp<SkData> data) {
74     SkASSERT(data != nullptr);
75     if (!is_valid(info)) {
76         return nullptr;
77     }
78     // TODO: what should we return if computeByteSize returns 0?
79     // - the info was empty?
80     // - we overflowed computing the size?
81     if ((rowBytes < info.minRowBytes()) || (data->size() < info.computeByteSize(rowBytes))) {
82         return nullptr;
83     }
84     struct PixelRef final : public SkPixelRef {
85         sk_sp<SkData> fData;
86         PixelRef(int w, int h, void* s, size_t r, sk_sp<SkData> d)
87             : SkPixelRef(w, h, s, r), fData(std::move(d)) {}
88     };
89     void* pixels = const_cast<void*>(data->data());
90     sk_sp<SkPixelRef> pr(new PixelRef(info.width(), info.height(), pixels, rowBytes,
91                                       std::move(data)));
92     pr->setImmutable(); // since we were created with (immutable) data
93     return pr;
94 }
95