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 "SkFixed.h" 9#include "SkReadBuffer.h" 10#include "SkString.h" 11#include "SkTableMaskFilter.h" 12#include "SkWriteBuffer.h" 13 14class SkTableMaskFilterImpl : public SkMaskFilterBase { 15public: 16 explicit SkTableMaskFilterImpl(const uint8_t table[256]); 17 18 SkMask::Format getFormat() const override; 19 bool filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*) const override; 20 21 SK_TO_STRING_OVERRIDE() 22 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTableMaskFilterImpl) 23 24protected: 25 ~SkTableMaskFilterImpl() override; 26 27 void flatten(SkWriteBuffer&) const override; 28 29private: 30 SkTableMaskFilterImpl(); 31 32 uint8_t fTable[256]; 33 34 typedef SkMaskFilter INHERITED; 35}; 36 37SkTableMaskFilterImpl::SkTableMaskFilterImpl() { 38 for (int i = 0; i < 256; i++) { 39 fTable[i] = i; 40 } 41} 42 43SkTableMaskFilterImpl::SkTableMaskFilterImpl(const uint8_t table[256]) { 44 memcpy(fTable, table, sizeof(fTable)); 45} 46 47SkTableMaskFilterImpl::~SkTableMaskFilterImpl() {} 48 49bool SkTableMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, 50 const SkMatrix&, SkIPoint* margin) const { 51 if (src.fFormat != SkMask::kA8_Format) { 52 return false; 53 } 54 55 dst->fBounds = src.fBounds; 56 dst->fRowBytes = SkAlign4(dst->fBounds.width()); 57 dst->fFormat = SkMask::kA8_Format; 58 dst->fImage = nullptr; 59 60 if (src.fImage) { 61 dst->fImage = SkMask::AllocImage(dst->computeImageSize()); 62 63 const uint8_t* srcP = src.fImage; 64 uint8_t* dstP = dst->fImage; 65 const uint8_t* table = fTable; 66 int dstWidth = dst->fBounds.width(); 67 int extraZeros = dst->fRowBytes - dstWidth; 68 69 for (int y = dst->fBounds.height() - 1; y >= 0; --y) { 70 for (int x = dstWidth - 1; x >= 0; --x) { 71 dstP[x] = table[srcP[x]]; 72 } 73 srcP += src.fRowBytes; 74 // we can't just inc dstP by rowbytes, because if it has any 75 // padding between its width and its rowbytes, we need to zero those 76 // so that the bitters can read those safely if that is faster for 77 // them 78 dstP += dstWidth; 79 for (int i = extraZeros - 1; i >= 0; --i) { 80 *dstP++ = 0; 81 } 82 } 83 } 84 85 if (margin) { 86 margin->set(0, 0); 87 } 88 return true; 89} 90 91SkMask::Format SkTableMaskFilterImpl::getFormat() const { 92 return SkMask::kA8_Format; 93} 94 95void SkTableMaskFilterImpl::flatten(SkWriteBuffer& wb) const { 96 wb.writeByteArray(fTable, 256); 97} 98 99sk_sp<SkFlattenable> SkTableMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { 100 uint8_t table[256]; 101 if (!buffer.readByteArray(table, 256)) { 102 return nullptr; 103 } 104 return sk_sp<SkFlattenable>(SkTableMaskFilter::Create(table)); 105} 106 107/////////////////////////////////////////////////////////////////////////////// 108 109SkMaskFilter* SkTableMaskFilter::Create(const uint8_t table[256]) { 110 return new SkTableMaskFilterImpl(table); 111} 112 113SkMaskFilter* SkTableMaskFilter::CreateGamma(SkScalar gamma) { 114 uint8_t table[256]; 115 MakeGammaTable(table, gamma); 116 return new SkTableMaskFilterImpl(table); 117} 118 119SkMaskFilter* SkTableMaskFilter::CreateClip(uint8_t min, uint8_t max) { 120 uint8_t table[256]; 121 MakeClipTable(table, min, max); 122 return new SkTableMaskFilterImpl(table); 123} 124 125void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) { 126 const float dx = 1 / 255.0f; 127 const float g = SkScalarToFloat(gamma); 128 129 float x = 0; 130 for (int i = 0; i < 256; i++) { 131 // float ee = powf(x, g) * 255; 132 table[i] = SkTPin(sk_float_round2int(powf(x, g) * 255), 0, 255); 133 x += dx; 134 } 135} 136 137void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min, 138 uint8_t max) { 139 if (0 == max) { 140 max = 1; 141 } 142 if (min >= max) { 143 min = max - 1; 144 } 145 SkASSERT(min < max); 146 147 SkFixed scale = (1 << 16) * 255 / (max - min); 148 memset(table, 0, min + 1); 149 for (int i = min + 1; i < max; i++) { 150 int value = SkFixedRoundToInt(scale * (i - min)); 151 SkASSERT(value <= 255); 152 table[i] = value; 153 } 154 memset(table + max, 255, 256 - max); 155 156#if 0 157 int j; 158 for (j = 0; j < 256; j++) { 159 if (table[j]) { 160 break; 161 } 162 } 163 SkDebugf("%d %d start [%d]", min, max, j); 164 for (; j < 256; j++) { 165 SkDebugf(" %d", table[j]); 166 } 167 SkDebugf("\n\n"); 168#endif 169} 170 171#ifndef SK_IGNORE_TO_STRING 172void SkTableMaskFilterImpl::toString(SkString* str) const { 173 str->append("SkTableMaskFilter: ("); 174 175 str->append("table: "); 176 for (int i = 0; i < 255; ++i) { 177 str->appendf("%d, ", fTable[i]); 178 } 179 str->appendf("%d", fTable[255]); 180 181 str->append(")"); 182} 183#endif 184