void SkProcXfermode::xferA8(SK_RESTRICT SkAlpha dst[], const SK_RESTRICT SkPMColor src[], int count, const SK_RESTRICT SkAlpha aa[]) { SkASSERT(dst && src && count >= 0); SkXfermodeProc proc = fProc; if (NULL != proc) { if (NULL == aa) { for (int i = count - 1; i >= 0; --i) { SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); dst[i] = SkToU8(SkGetPackedA32(res)); } } else { for (int i = count - 1; i >= 0; --i) { unsigned a = aa[i]; if (0 != a) { SkAlpha dstA = dst[i]; SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); unsigned A = SkGetPackedA32(res); if (0xFF != a) { A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); } dst[i] = SkToU8(A); } } } } }
static void clamp_with_orig(uint8_t dst[], int dstRowBytes, const uint8_t src[], int srcRowBytes, int sw, int sh, SkBlurMask::Style style) { int x; while (--sh >= 0) { switch (style) { case SkBlurMask::kSolid_Style: for (x = sw - 1; x >= 0; --x) { int s = *src; int d = *dst; *dst = SkToU8(s + d - SkMulDiv255Round(s, d)); dst += 1; src += 1; } break; case SkBlurMask::kOuter_Style: for (x = sw - 1; x >= 0; --x) { if (*src) { *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src))); } dst += 1; src += 1; } break; default: SkDEBUGFAIL("Unexpected blur style here"); break; } dst += dstRowBytes - sw; src += srcRowBytes - sw; } }
/* It is necessary to average the color component of transparent pixels with their surrounding neighbors since the PDF renderer may separately re-sample the alpha and color channels when the image is not displayed at its native resolution. Since an alpha of zero gives no information about the color component, the pathological case is a white image with sharp transparency bounds - the color channel goes to black, and the should-be-transparent pixels are rendered as grey because of the separate soft mask and color resizing. e.g.: gm/bitmappremul.cpp */ static void get_neighbor_avg_color(const SkBitmap& bm, int xOrig, int yOrig, uint8_t rgb[3], SkColorType ct) { unsigned a = 0, r = 0, g = 0, b = 0; // Clamp the range to the edge of the bitmap. int ymin = SkTMax(0, yOrig - 1); int ymax = SkTMin(yOrig + 1, bm.height() - 1); int xmin = SkTMax(0, xOrig - 1); int xmax = SkTMin(xOrig + 1, bm.width() - 1); for (int y = ymin; y <= ymax; ++y) { uint32_t* scanline = bm.getAddr32(0, y); for (int x = xmin; x <= xmax; ++x) { uint32_t color = scanline[x]; a += SkGetA32Component(color, ct); r += SkGetR32Component(color, ct); g += SkGetG32Component(color, ct); b += SkGetB32Component(color, ct); } } if (a > 0) { rgb[0] = SkToU8(255 * r / a); rgb[1] = SkToU8(255 * g / a); rgb[2] = SkToU8(255 * b / a); } else { rgb[0] = rgb[1] = rgb[2] = 0; } }
/* It is necessary to average the color component of transparent pixels with their surrounding neighbors since the PDF renderer may separately re-sample the alpha and color channels when the image is not displayed at its native resolution. Since an alpha of zero gives no information about the color component, the pathological case is a white image with sharp transparency bounds - the color channel goes to black, and the should-be-transparent pixels are rendered as grey because of the separate soft mask and color resizing. e.g.: gm/bitmappremul.cpp */ static void get_neighbor_avg_color(const SkBitmap& bm, int xOrig, int yOrig, uint8_t rgb[3]) { SkASSERT(kN32_SkColorType == bm.colorType()); unsigned a = 0, r = 0, g = 0, b = 0; // Clamp the range to the edge of the bitmap. int ymin = SkTMax(0, yOrig - 1); int ymax = SkTMin(yOrig + 1, bm.height() - 1); int xmin = SkTMax(0, xOrig - 1); int xmax = SkTMin(xOrig + 1, bm.width() - 1); for (int y = ymin; y <= ymax; ++y) { SkPMColor* scanline = bm.getAddr32(0, y); for (int x = xmin; x <= xmax; ++x) { SkPMColor pmColor = scanline[x]; a += SkGetPackedA32(pmColor); r += SkGetPackedR32(pmColor); g += SkGetPackedG32(pmColor); b += SkGetPackedB32(pmColor); } } if (a > 0) { rgb[0] = SkToU8(255 * r / a); rgb[1] = SkToU8(255 * g / a); rgb[2] = SkToU8(255 * b / a); } else { rgb[0] = rgb[1] = rgb[2] = 0; } }
SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p) : fStrokeWidth(p.getStrokeWidth()) , fStrokeMiter(p.getStrokeMiter()) , fAlpha(p.getAlpha()) , fStrokeCap(SkToU8(p.getStrokeCap())) , fStrokeJoin(SkToU8(p.getStrokeJoin())) , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count) { SkASSERT(name); SkASSERT(dataSize); SkASSERT(count > 0); (void)this->remove(name, type); size_t len = strlen(name); Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1); #ifndef SK_DEBUG rec->fType = SkToU8(type); #else rec->fType = type; #endif rec->fDataLen = SkToU8(dataSize); rec->fDataCount = SkToU16(count); if (data) memcpy(rec->data(), data, dataSize * count); memcpy(rec->name(), name, len + 1); if (kPtr_Type == type) { PtrPair* pair = (PtrPair*)rec->data(); if (pair->fProc && pair->fPtr) { pair->fPtr = pair->fProc(pair->fPtr, true); } } rec->fNext = fRec; fRec = rec; return rec->data(); }
SkMaskFilter* SkBlurMaskFilter::CreateEmboss(const SkScalar direction[3], SkScalar ambient, SkScalar specular, SkScalar blurRadius) { if (direction == NULL) return NULL; // ambient should be 0...1 as a scalar int am = SkScalarToFixed(ambient) >> 8; if (am < 0) am = 0; else if (am > 0xFF) am = 0xFF; // specular should be 0..15.99 as a scalar int sp = SkScalarToFixed(specular) >> 12; if (sp < 0) sp = 0; else if (sp > 0xFF) sp = 0xFF; SkEmbossMaskFilter::Light light; memcpy(light.fDirection, direction, sizeof(light.fDirection)); light.fAmbient = SkToU8(am); light.fSpecular = SkToU8(sp); return SkNEW_ARGS(SkEmbossMaskFilter, (light, blurRadius)); }
void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { SkASSERT(count > 0); SkPMColor colors[kTempColorCount]; while ((count -= kTempColorCount) >= 0) { this->shadeSpan(x, y, colors, kTempColorCount); x += kTempColorCount; const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); int quads = kTempColorQuadCount; do { U8CPU a0 = srcA[0]; U8CPU a1 = srcA[4]; U8CPU a2 = srcA[8]; U8CPU a3 = srcA[12]; srcA += 4*4; *alpha++ = SkToU8(a0); *alpha++ = SkToU8(a1); *alpha++ = SkToU8(a2); *alpha++ = SkToU8(a3); } while (--quads != 0); } SkASSERT(count < 0); SkASSERT(count + kTempColorCount >= 0); if (count += kTempColorCount) { this->shadeSpan(x, y, colors, count); const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); do { *alpha++ = *srcA; srcA += 4; } while (--count != 0); } #if 0 do { int n = count; if (n > kTempColorCount) n = kTempColorCount; SkASSERT(n > 0); this->shadeSpan(x, y, colors, n); x += n; count -= n; const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); do { *alpha++ = *srcA; srcA += 4; } while (--n != 0); } while (count > 0); #endif }
static void rgb2yuv_32(uint8_t dst[], SkPMColor c) { int r = SkGetPackedR32(c); int g = SkGetPackedG32(c); int b = SkGetPackedB32(c); int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT; int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT; int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT; dst[0] = SkToU8(y); dst[1] = SkToU8(u + 128); dst[2] = SkToU8(v + 128); }
static void rgb2yuv_4444(uint8_t dst[], U16CPU c) { int r = SkGetPackedR4444(c); int g = SkGetPackedG4444(c); int b = SkGetPackedB4444(c); int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4); int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4); int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4); dst[0] = SkToU8(y); dst[1] = SkToU8(u + 128); dst[2] = SkToU8(v + 128); }
static void rgb2yuv_16(uint8_t dst[], U16CPU c) { int r = SkGetPackedR16(c); int g = SkGetPackedG16(c); int b = SkGetPackedB16(c); int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2); int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2); int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2); dst[0] = SkToU8(y); dst[1] = SkToU8(u + 128); dst[2] = SkToU8(v + 128); }
void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast, const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma, const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma) { const float src = (float)srcI / 255.0f; const float linSrc = srcConvert.toLuma(srcGamma, src); //Guess at the dst. The perceptual inverse provides smaller visual //discontinuities when slight changes to desaturated colors cause a channel //to map to a different correcting lut with neighboring srcI. //See https://code.google.com/p/chromium/issues/detail?id=141425#c59 . const float dst = 1.0f - src; const float linDst = dstConvert.toLuma(dstGamma, dst); //Contrast value tapers off to 0 as the src luminance becomes white const float adjustedContrast = SkScalarToFloat(contrast) * linDst; //Remove discontinuity and instability when src is close to dst. //The value 1/256 is arbitrary and appears to contain the instability. if (fabs(src - dst) < (1.0f / 256.0f)) { float ii = 0.0f; for (int i = 0; i < 256; ++i, ii += 1.0f) { float rawSrca = ii / 255.0f; float srca = apply_contrast(rawSrca, adjustedContrast); table[i] = SkToU8(sk_float_round2int(255.0f * srca)); } } else { // Avoid slow int to float conversion. float ii = 0.0f; for (int i = 0; i < 256; ++i, ii += 1.0f) { // 'rawSrca += 1.0f / 255.0f' and even // 'rawSrca = i * (1.0f / 255.0f)' can add up to more than 1.0f. // When this happens the table[255] == 0x0 instead of 0xff. // See http://code.google.com/p/chromium/issues/detail?id=146466 float rawSrca = ii / 255.0f; float srca = apply_contrast(rawSrca, adjustedContrast); SkASSERT(srca <= 1.0f); float dsta = 1.0f - srca; //Calculate the output we want. float linOut = (linSrc * srca + dsta * linDst); SkASSERT(linOut <= 1.0f); float out = dstConvert.fromLuma(dstGamma, linOut); //Undo what the blit blend will do. float result = (out - dst) / (src - dst); SkASSERT(sk_float_round2int(255.0f * result) <= 255); table[i] = SkToU8(sk_float_round2int(255.0f * result)); } } }
void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count) { SkASSERT(name); SkASSERT(dataSize); SkASSERT(count > 0); (void)this->remove(name, type); size_t len = strlen(name); Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1); #ifndef SK_DEBUG rec->fType = SkToU8(type); #else rec->fType = type; #endif rec->fDataLen = SkToU8(dataSize); rec->fDataCount = SkToU16(count); if (data) memcpy(rec->data(), data, dataSize * count); memcpy(rec->name(), name, len + 1); #ifdef SK_DEBUG rec->fName = rec->name(); switch (type) { case kS32_Type: rec->fData.fS32 = *(const int32_t*)rec->data(); break; case kScalar_Type: rec->fData.fScalar = *(const SkScalar*)rec->data(); break; case kString_Type: rec->fData.fString = (const char*)rec->data(); break; case kPtr_Type: rec->fData.fPtr = *(void**)rec->data(); break; case kBool_Type: rec->fData.fBool = *(const bool*)rec->data(); break; default: SkASSERT(!"bad type"); break; } #endif rec->fNext = fRec; fRec = rec; return rec->data(); }
void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue) { SkASSERT(middleCount >= 0); SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); int16_t* runs = fRuns; uint8_t* alpha = fAlpha; if (startAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); /* I should be able to just add alpha[x] + startAlpha. However, if the trailing edge of the previous span and the leading edge of the current span round to the same super-sampled x value, I might overflow to 256 with this add, hence the funny subtract (crud). */ unsigned tmp = alpha[x] + startAlpha; SkASSERT(tmp <= 256); alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256 runs += x + 1; alpha += x + 1; x = 0; SkDEBUGCODE(this->validate();) } if (middleCount) { SkAlphaRuns::Break(runs, alpha, x, middleCount); alpha += x; runs += x; x = 0; do { alpha[0] = SkToU8(alpha[0] + maxValue); int n = runs[0]; SkASSERT(n <= middleCount); alpha += n; runs += n; middleCount -= n; } while (middleCount > 0); SkDEBUGCODE(this->validate();) } if (stopAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); alpha[x] = SkToU8(alpha[x] + stopAlpha); SkDEBUGCODE(this->validate();) } }
SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags)) { fWidth = fHeight = 0; fLoc.set(0, 0); fParent = fFirstChild = fNextSibling = fPrevSibling = nullptr; fMatrix.setIdentity(); fContainsFocus = 0; }
SkStroke::SkStroke(const SkPaint& p, SkScalar width) { fWidth = width; fMiterLimit = p.getStrokeMiter(); fCap = (uint8_t)p.getStrokeCap(); fJoin = (uint8_t)p.getStrokeJoin(); fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); }
bool SkDrawColor::setProperty(int index, SkScriptValue& value) { SkASSERT(value.fType == SkType_Float); SkScalar scalar = value.fOperand.fScalar; switch (index) { case SK_PROPERTY(alpha): uint8_t alpha; #ifdef SK_SCALAR_IS_FLOAT alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256)); #else alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8); #endif color = SkColorSetARGB(alpha, SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(blue): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkToU8((U8CPU) scalar)); break; case SK_PROPERTY(green): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkToU8((U8CPU) scalar), SkColorGetB(color)); break; case SK_PROPERTY(hue): fHue = scalar;//RGB_to_HSV(color, kGetHue); fDirty = true; break; case SK_PROPERTY(red): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(saturation): fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation); fDirty = true; break; case SK_PROPERTY(value): fValue = scalar;//RGB_to_HSV(color, kGetValue); fDirty = true; break; default: SkASSERT(0); return false; } return true; }
static uint8_t pack_8_to_1(const uint8_t alpha[8]) { unsigned bits = 0; for (int i = 0; i < 8; ++i) { bits <<= 1; bits |= convert_8_to_1(alpha[i]); } return SkToU8(bits); }
BitmapRectBench(U8CPU alpha, SkPaint::FilterLevel filterLevel, bool slightMatrix) { fAlpha = SkToU8(alpha); fFilterLevel = filterLevel; fSlightMatrix = slightMatrix; fBitmap.setInfo(SkImageInfo::MakeN32Premul(kWidth, kHeight)); }
SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags)) { fWidth = fHeight = 0; fLoc.set(0, 0); fParent = fFirstChild = fNextSibling = fPrevSibling = NULL; fContainsFocus = 0; }
BitmapRectBench(U8CPU alpha, SkPaint::FilterLevel filterLevel, bool slightMatrix) { fAlpha = SkToU8(alpha); fFilterLevel = filterLevel; fSlightMatrix = slightMatrix; fBitmap.setConfig(SkBitmap::kARGB_8888_Config, kWidth, kHeight); }
BitmapRectBench(U8CPU alpha, SkFilterQuality filterQuality, bool slightMatrix) { fAlpha = SkToU8(alpha); fFilterQuality = filterQuality; fSlightMatrix = slightMatrix; fBitmap.setInfo(SkImageInfo::MakeN32Premul(kWidth, kHeight)); }
void SkPaint::setStrokeCap(Cap ct) { if ((unsigned)ct < kCapCount) { fBitfields.fCapType = SkToU8(ct); } else { #ifdef SK_REPORT_API_RANGE_CHECK SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); #endif } }
void SkPaint::setStrokeJoin(Join jt) { if ((unsigned)jt < kJoinCount) { fBitfields.fJoinType = SkToU8(jt); } else { #ifdef SK_REPORT_API_RANGE_CHECK SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); #endif } }
void SkPaint::setTextAlign(Align align) { if ((unsigned)align < kAlignCount) { fBitfields.fTextAlign = SkToU8(align); } else { #ifdef SK_REPORT_API_RANGE_CHECK SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); #endif } }
SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) { if (tolerance > 255) { tolerance = 255; } fTolerance = SkToU8(tolerance); fOpColor = opColor; fDistMul = (256 << 14) / (tolerance + 1); fMode = mode; }
void SkStaticTextView::setMode(Mode mode) { SkASSERT((unsigned)mode < kModeCount); if (fMode != mode) { fMode = SkToU8(mode); this->computeSize(); } }
void SkMergeImageFilter::init(SkImageFilter* const filters[], int count, const SkXfermode::Mode modes[]) { this->initAlloc(count, !!modes); for (int i = 0; i < count; ++i) { fFilters[i] = SkSafeRefReturn(filters[i]); if (modes) { fModes[i] = SkToU8(modes[i]); } } }
SkMaskFilter* SkBlurMaskFilter::CreateEmboss(SkScalar blurSigma, const SkScalar direction[3], SkScalar ambient, SkScalar specular) { if (direction == NULL) { return NULL; } // ambient should be 0...1 as a scalar int am = pin2byte(SkScalarToFixed(ambient) >> 8); // specular should be 0..15.99 as a scalar int sp = pin2byte(SkScalarToFixed(specular) >> 12); SkEmbossMaskFilter::Light light; memcpy(light.fDirection, direction, sizeof(light.fDirection)); light.fAmbient = SkToU8(am); light.fSpecular = SkToU8(sp); return SkEmbossMaskFilter::Create(blurSigma, light); }
void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) { if (modes) { this->initAllocModes(); int inputCount = this->countInputs(); for (int i = 0; i < inputCount; ++i) { fModes[i] = SkToU8(modes[i]); } } else { fModes = nullptr; } }