SkColor SkHSVToColor(U8CPU a, const SkScalar hsv[3]) { SkASSERT(hsv); SkScalar s = SkScalarPin(hsv[1], 0, 1); SkScalar v = SkScalarPin(hsv[2], 0, 1); U8CPU v_byte = SkScalarRoundToInt(v * 255); if (SkScalarNearlyZero(s)) { // shade of gray return SkColorSetARGB(a, v_byte, v_byte, v_byte); } SkScalar hx = (hsv[0] < 0 || hsv[0] >= SkIntToScalar(360)) ? 0 : hsv[0]/60; SkScalar w = SkScalarFloorToScalar(hx); SkScalar f = hx - w; unsigned p = SkScalarRoundToInt((SK_Scalar1 - s) * v * 255); unsigned q = SkScalarRoundToInt((SK_Scalar1 - (s * f)) * v * 255); unsigned t = SkScalarRoundToInt((SK_Scalar1 - (s * (SK_Scalar1 - f))) * v * 255); unsigned r, g, b; SkASSERT((unsigned)(w) < 6); switch ((unsigned)(w)) { case 0: r = v_byte; g = t; b = p; break; case 1: r = q; g = v_byte; b = p; break; case 2: r = p; g = v_byte; b = t; break; case 3: r = p; g = q; b = v_byte; break; case 4: r = t; g = p; b = v_byte; break; default: r = v_byte; g = p; b = q; break; } return SkColorSetARGB(a, r, g, b); }
SkHighContrast_Filter(const SkHighContrastConfig& config) { fConfig = config; // Clamp contrast to just inside -1 to 1 to avoid division by zero. fConfig.fContrast = SkScalarPin(fConfig.fContrast, -1.0f + FLT_EPSILON, 1.0f - FLT_EPSILON); }
bool ScrollableLayerAndroid::scrollTo(int x, int y) { SkIRect scrollBounds; getScrollRect(&scrollBounds); if (!scrollBounds.fRight && !scrollBounds.fBottom) return false; SkScalar newX = SkScalarPin(x, 0, scrollBounds.fRight); SkScalar newY = SkScalarPin(y, 0, scrollBounds.fBottom); // Check for no change. if (newX == scrollBounds.fLeft && newY == scrollBounds.fTop) return false; setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY); return true; }
static U16CPU SkScalarToUnit(SkScalar x) { SkScalar pin = SkScalarPin(x, 0, SK_Scalar1); #ifdef SK_SCALAR_IS_FLOAT return (int) (pin * 65535.0f); #else return pin - (pin >= 32768); #endif }
bool onClick(const SkPoint& clickPos) override { SkASSERT(fParent); SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange); int numChoices = fMax - fMin + 1; *fOutput = SkTMin(SkScalarFloorToInt(numChoices * x / fSliderRange) + fMin, fMax); return true; }
GrTextureDomain::GrTextureDomain(const SkRect& domain, Mode mode, int index) : fIndex(index) { static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1}; if (domain.contains(kFullRect) && kClamp_Mode == mode) { fMode = kIgnore_Mode; } else { fMode = mode; } if (fMode != kIgnore_Mode) { // We don't currently handle domains that are empty or don't intersect the texture. // It is OK if the domain rect is a line or point, but it should not be inverted. We do not // handle rects that do not intersect the [0..1]x[0..1] rect. SkASSERT(domain.fLeft <= domain.fRight); SkASSERT(domain.fTop <= domain.fBottom); fDomain.fLeft = SkScalarPin(domain.fLeft, kFullRect.fLeft, kFullRect.fRight); fDomain.fRight = SkScalarPin(domain.fRight, kFullRect.fLeft, kFullRect.fRight); fDomain.fTop = SkScalarPin(domain.fTop, kFullRect.fTop, kFullRect.fBottom); fDomain.fBottom = SkScalarPin(domain.fBottom, kFullRect.fTop, kFullRect.fBottom); SkASSERT(fDomain.fLeft <= fDomain.fRight); SkASSERT(fDomain.fTop <= fDomain.fBottom); } }
sk_sp<SkMaskFilter> SkBlurMaskFilter::MakeEmboss(SkScalar blurSigma, const SkScalar direction[3], SkScalar ambient, SkScalar specular) { if (direction == nullptr) { return nullptr; } SkEmbossMaskFilter::Light light; memcpy(light.fDirection, direction, sizeof(light.fDirection)); // ambient should be 0...1 as a scalar light.fAmbient = SkUnitScalarClampToByte(ambient); // specular should be 0..15.99 as a scalar static const SkScalar kSpecularMultiplier = SkIntToScalar(255) / 16; light.fSpecular = static_cast<U8CPU>(SkScalarPin(specular, 0, 16) * kSpecularMultiplier + 0.5); return SkEmbossMaskFilter::Make(blurSigma, light); }
void onDrawContent(SkCanvas* canvas) override { SkASSERT(fParent); SkScalar x = fSliderRange * (*fOutput - fMin) / (fMax - fMin); fSlider.offsetTo(SkScalarPin(x, 0.0f, fSliderRange), fSlider.fTop); SkString valueStr; valueStr.appendScalar(*fOutput); this->drawLabel(canvas, valueStr); SkPaint sliderPaint; sliderPaint.setColor(0xFFF3F3F3); canvas->drawRect(fSlider, sliderPaint); SkPaint ctrlRegionPaint; ctrlRegionPaint.setColor(0xFFFFFFFF); ctrlRegionPaint.setStyle(SkPaint::kStroke_Style); ctrlRegionPaint.setStrokeWidth(2.0f); canvas->drawRect(fCtrlRegion, ctrlRegionPaint); }
bool SkOperandInterpolator::setKeyFrame(int index, SkMSec time, const SkOperand values[], SkScalar blend) { SkASSERT(values != NULL); blend = SkScalarPin(blend, 0, SK_Scalar1); bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode)); SkASSERT(success); if (success) { SkTimeCode* timeCode = &fTimes[index]; timeCode->fTime = time; timeCode->fBlend[0] = SK_Scalar1 - blend; timeCode->fBlend[1] = 0; timeCode->fBlend[2] = 0; timeCode->fBlend[3] = SK_Scalar1 - blend; SkOperand* dst = &fValues[fElemCount * index]; memcpy(dst, values, fElemCount * sizeof(SkOperand)); } return success; }
sk_sp<SkShader> SkShader::MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode, float lerpT) { if (!src || !dst || SkScalarIsNaN(lerpT)) { return nullptr; } lerpT = SkScalarPin(lerpT, 0, 1); if (lerpT == 0) { return dst; } else if (lerpT == 1) { if (mode == SkBlendMode::kSrc) { return src; } if (mode == SkBlendMode::kDst) { return dst; } } return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode, lerpT)); }
SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( int channel, StitchData& stitchData, const SkPoint& point) const { const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); if (perlinNoiseShader.fStitchTiles) { // Set up TurbulenceInitial stitch values. stitchData = fPaintingData->fStitchDataInit; } SkScalar turbulenceFunctionResult = 0; SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX), SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY))); SkScalar ratio = SK_Scalar1; for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { SkScalar noise = noise2D(channel, stitchData, noiseVector); SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise); turbulenceFunctionResult += numer / ratio; noiseVector.fX *= 2; noiseVector.fY *= 2; ratio *= 2; if (perlinNoiseShader.fStitchTiles) { // Update stitch values stitchData.fWidth *= 2; stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; stitchData.fHeight *= 2; stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; } } // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // by fractalNoise and (turbulenceFunctionResult) by turbulence. if (perlinNoiseShader.fType == kFractalNoise_Type) { turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf; } if (channel == 3) { // Scale alpha by paint value turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; } // Clamp result return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); }
SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit) : INHERITED(desc.fLocalMatrix) , fPtsToUnit(ptsToUnit) { fPtsToUnit.getType(); // Precache so reads are threadsafe. SkASSERT(desc.fCount > 1); fGradFlags = SkToU8(desc.fGradFlags); SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); fTileMode = desc.fTileMode; fTileProc = gTileProcs[desc.fTileMode]; /* Note: we let the caller skip the first and/or last position. i.e. pos[0] = 0.3, pos[1] = 0.7 In these cases, we insert dummy entries to ensure that the final data will be bracketed by [0, 1]. i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 Thus colorCount (the caller's value, and fColorCount (our value) may differ by up to 2. In the above example: colorCount = 2 fColorCount = 4 */ fColorCount = desc.fCount; // check if we need to add in dummy start and/or end position/colors bool dummyFirst = false; bool dummyLast = false; if (desc.fPos) { dummyFirst = desc.fPos[0] != 0; dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1; fColorCount += dummyFirst + dummyLast; } if (fColorCount > kColorStorageCount) { size_t size = sizeof(SkColor) + sizeof(Rec); if (desc.fPos) { size += sizeof(SkScalar); } fOrigColors = reinterpret_cast<SkColor*>( sk_malloc_throw(size * fColorCount)); } else { fOrigColors = fStorage; } // Now copy over the colors, adding the dummies as needed { SkColor* origColors = fOrigColors; if (dummyFirst) { *origColors++ = desc.fColors[0]; } memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor)); if (dummyLast) { origColors += desc.fCount; *origColors = desc.fColors[desc.fCount - 1]; } } if (desc.fPos && fColorCount) { fOrigPos = (SkScalar*)(fOrigColors + fColorCount); fRecs = (Rec*)(fOrigPos + fColorCount); } else { fOrigPos = nullptr; fRecs = (Rec*)(fOrigColors + fColorCount); } if (fColorCount > 2) { Rec* recs = fRecs; recs->fPos = 0; // recs->fScale = 0; // unused; recs += 1; if (desc.fPos) { SkScalar* origPosPtr = fOrigPos; *origPosPtr++ = 0; /* We need to convert the user's array of relative positions into fixed-point positions and scale factors. We need these results to be strictly monotonic (no two values equal or out of order). Hence this complex loop that just jams a zero for the scale value if it sees a segment out of order, and it assures that we start at 0 and end at 1.0 */ SkScalar prev = 0; int startIndex = dummyFirst ? 0 : 1; int count = desc.fCount + dummyLast; for (int i = startIndex; i < count; i++) { // force the last value to be 1.0 SkScalar curr; if (i == desc.fCount) { // we're really at the dummyLast curr = 1; } else { curr = SkScalarPin(desc.fPos[i], 0, 1); } *origPosPtr++ = curr; recs->fPos = SkScalarToFixed(curr); SkFixed diff = SkScalarToFixed(curr - prev); if (diff > 0) { recs->fScale = (1 << 24) / diff; } else { recs->fScale = 0; // ignore this segment } // get ready for the next value prev = curr; recs += 1; } } else { // assume even distribution fOrigPos = nullptr; SkFixed dp = SK_Fixed1 / (desc.fCount - 1); SkFixed p = dp; SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp for (int i = 1; i < desc.fCount - 1; i++) { recs->fPos = p; recs->fScale = scale; recs += 1; p += dp; } recs->fPos = SK_Fixed1; recs->fScale = scale; } } else if (desc.fPos) { SkASSERT(2 == fColorCount); fOrigPos[0] = SkScalarPin(desc.fPos[0], 0, 1); fOrigPos[1] = SkScalarPin(desc.fPos[1], fOrigPos[0], 1); if (0 == fOrigPos[0] && 1 == fOrigPos[1]) { fOrigPos = nullptr; } } this->initCommon(); }
static inline GrPoint sanitizePoint(const GrPoint& pt) { GrPoint r; r.fX = SkScalarPin(pt.fX, -kMaxVertexValue, kMaxVertexValue); r.fY = SkScalarPin(pt.fY, -kMaxVertexValue, kMaxVertexValue); return r; }
bool onClick(const SkPoint& clickPos) override { SkASSERT(fParent); SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange); *fOutput = (x/fSliderRange) * (fMax - fMin) + fMin; return true; }