SkMask.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #include "src/core/SkMask.h"
  8. #include "include/private/SkMalloc.h"
  9. #include "include/private/SkTo.h"
  10. #include "src/core/SkSafeMath.h"
  11. /** returns the product if it is positive and fits in 31 bits. Otherwise this
  12. returns 0.
  13. */
  14. static int32_t safeMul32(int32_t a, int32_t b) {
  15. int64_t size = sk_64_mul(a, b);
  16. if (size > 0 && SkTFitsIn<int32_t>(size)) {
  17. return size;
  18. }
  19. return 0;
  20. }
  21. size_t SkMask::computeImageSize() const {
  22. return safeMul32(fBounds.height(), fRowBytes);
  23. }
  24. size_t SkMask::computeTotalImageSize() const {
  25. size_t size = this->computeImageSize();
  26. if (fFormat == SkMask::k3D_Format) {
  27. size = safeMul32(SkToS32(size), 3);
  28. }
  29. return size;
  30. }
  31. /** We explicitly use this allocator for SkBimap pixels, so that we can
  32. freely assign memory allocated by one class to the other.
  33. */
  34. uint8_t* SkMask::AllocImage(size_t size, AllocType at) {
  35. size_t aligned_size = SkSafeMath::Align4(size);
  36. unsigned flags = SK_MALLOC_THROW;
  37. if (at == kZeroInit_Alloc) {
  38. flags |= SK_MALLOC_ZERO_INITIALIZE;
  39. }
  40. return static_cast<uint8_t*>(sk_malloc_flags(aligned_size, flags));
  41. }
  42. /** We explicitly use this allocator for SkBimap pixels, so that we can
  43. freely assign memory allocated by one class to the other.
  44. */
  45. void SkMask::FreeImage(void* image) {
  46. sk_free(image);
  47. }
  48. SkMask SkMask::PrepareDestination(int radiusX, int radiusY, const SkMask& src) {
  49. SkSafeMath safe;
  50. SkMask dst;
  51. // dstW = srcW + 2 * radiusX;
  52. size_t dstW = safe.add(src.fBounds.width(), safe.add(radiusX, radiusX));
  53. // dstH = srcH + 2 * radiusY;
  54. size_t dstH = safe.add(src.fBounds.height(), safe.add(radiusY, radiusY));
  55. if (!SkTFitsIn<int>(dstW) || !SkTFitsIn<int>(dstH)) {
  56. dst.fBounds.setEmpty();
  57. dst.fRowBytes = 0;
  58. } else {
  59. dst.fBounds.set(0, 0, SkTo<int>(dstW), SkTo<int>(dstH));
  60. dst.fBounds.offset(src.fBounds.x(), src.fBounds.y());
  61. dst.fBounds.offset(-radiusX, -radiusY);
  62. dst.fRowBytes = SkTo<uint32_t>(dstW);
  63. }
  64. dst.fImage = nullptr;
  65. dst.fFormat = SkMask::kA8_Format;
  66. size_t toAlloc = safe.mul(dstW, dstH);
  67. if (safe && src.fImage != nullptr) {
  68. dst.fImage = SkMask::AllocImage(toAlloc);
  69. }
  70. return dst;
  71. }
  72. ///////////////////////////////////////////////////////////////////////////////
  73. static const int gMaskFormatToShift[] = {
  74. ~0, // BW -- not supported
  75. 0, // A8
  76. 0, // 3D
  77. 2, // ARGB32
  78. 1, // LCD16
  79. 0, // SDF
  80. };
  81. static int maskFormatToShift(SkMask::Format format) {
  82. SkASSERT((unsigned)format < SK_ARRAY_COUNT(gMaskFormatToShift));
  83. SkASSERT(SkMask::kBW_Format != format);
  84. return gMaskFormatToShift[format];
  85. }
  86. void* SkMask::getAddr(int x, int y) const {
  87. SkASSERT(kBW_Format != fFormat);
  88. SkASSERT(fBounds.contains(x, y));
  89. SkASSERT(fImage);
  90. char* addr = (char*)fImage;
  91. addr += (y - fBounds.fTop) * fRowBytes;
  92. addr += (x - fBounds.fLeft) << maskFormatToShift(fFormat);
  93. return addr;
  94. }