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