void SkGridView::onSizeChange() { fScrollBar->setHeight(this->height()); fScrollBar->setLoc(this->locX() + this->width() - fScrollBar->width(), 0); if (fCellSize.equals(0, 0)) { fVisibleCount.set(0, 0); return; } SkScalar rows = SkScalarDiv(this->height(), fCellSize.fY); SkScalar cols = SkScalarDiv(this->width(), fCellSize.fX); int y = SkScalarFloor(rows); int x = SkScalarFloor(cols); y = check_count(y, rows); x = check_count(x, cols); if (!fVisibleCount.equals(x, y)) { fVisibleCount.set(x, y); this->ensureSelectionIsVisible(); // this->dirtyStrCache(); } }
IntRect OpaqueRegionSkia::asRect() const { // Returns the largest enclosed rect. int left = SkScalarCeil(m_opaqueRect.fLeft); int top = SkScalarCeil(m_opaqueRect.fTop); int right = SkScalarFloor(m_opaqueRect.fRight); int bottom = SkScalarFloor(m_opaqueRect.fBottom); return IntRect(left, top, right-left, bottom-top); }
static bool HitTestPath(const SkPath& path, SkScalar x, SkScalar y) { SkRegion rgn, clip; int ix = SkScalarFloor(x); int iy = SkScalarFloor(y); clip.setRect(ix, iy, ix + 1, iy + 1); bool contains = rgn.setPath(path, clip); return contains; }
static SkColor HSV_to_RGB(SkColor color, HSV_Choice choice, SkScalar hsv) { SkScalar hue = choice == kGetHue ? hsv : RGB_to_HSV(color, kGetHue); SkScalar saturation = choice == kGetSaturation ? hsv : RGB_to_HSV(color, kGetSaturation); SkScalar value = choice == kGetValue ? hsv : RGB_to_HSV(color, kGetValue); value *= 255; SkScalar red SK_INIT_TO_AVOID_WARNING; SkScalar green SK_INIT_TO_AVOID_WARNING; SkScalar blue SK_INIT_TO_AVOID_WARNING; if (saturation == 0) // color is on black-and-white center line red = green = blue = value; else { //SkScalar fraction = SkScalarMod(hue, 60 * SK_Scalar1); int sextant = SkScalarFloor(hue / 60); SkScalar fraction = hue / 60 - SkIntToScalar(sextant); SkScalar p = SkScalarMul(value , SK_Scalar1 - saturation); SkScalar q = SkScalarMul(value, SK_Scalar1 - SkScalarMul(saturation, fraction)); SkScalar t = SkScalarMul(value, SK_Scalar1 - SkScalarMul(saturation, SK_Scalar1 - fraction)); switch (sextant % 6) { case 0: red = value; green = t; blue = p; break; case 1: red = q; green = value; blue = p; break; case 2: red = p; green = value; blue = t; break; case 3: red = p; green = q; blue = value; break; case 4: red = t; green = p; blue = value; break; case 5: red = value; green = p; blue = q; break; } } //used to say SkToU8((U8CPU) red) etc return SkColorSetARGB(SkColorGetA(color), SkScalarRound(red), SkScalarRound(green), SkScalarRound(blue)); }
void SkListView::ensureVisibleRowCount() { SkScalar height = this->height(); int n = 0; if (height > 0) { n = 1; height -= fHeights[kSelected_Height]; if (height > 0) { SkScalar count = SkScalarDiv(height, fHeights[kNormal_Height]); n += SkScalarFloor(count); if (count - SkIntToScalar(n) > SK_Scalar1*3/4) n += 1; // SkDebugf("count %g, n %d\n", count/65536., n); } } if (fVisibleRowCount != n) { if (fScrollBar) fScrollBar->setShown(n); fVisibleRowCount = n; this->ensureSelectionIsVisible(); this->dirtyCache(kAnimCount_DirtyFlag | kAnimContent_DirtyFlag); } }
void SkListView::onSizeChange() { SkScalar count = SkScalarDiv(this->height(), fRowHeight); int n = SkScalarFloor(count); // only want to show rows that are mostly visible if (n == 0 || count - SkIntToScalar(n) > SK_Scalar1*75/100) n += 1; if (fVisibleRowCount != n) { fVisibleRowCount = n; this->ensureSelectionIsVisible(); this->dirtyStrCache(); } }
static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) { NPE_CHECK_RETURN_ZERO(env, paint); SkPaint::FontMetrics metrics; GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics); int ascent = SkScalarRound(metrics.fAscent); int descent = SkScalarRound(metrics.fDescent); int leading = SkScalarRound(metrics.fLeading); if (metricsObj) { SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class)); env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop)); env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent); env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent); env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom)); env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading); } return descent - ascent + leading; }
void SkDisplayMath::executeFunction(SkDisplayable* target, int index, SkTDArray<SkScriptValue>& parameters, SkDisplayTypes type, SkScriptValue* scriptValue) { if (scriptValue == NULL) return; SkASSERT(target == this); SkScriptValue* array = parameters.begin(); SkScriptValue* end = parameters.end(); SkScalar input = parameters[0].fOperand.fScalar; SkScalar scalarResult; switch (index) { case SK_FUNCTION(abs): scalarResult = SkScalarAbs(input); break; case SK_FUNCTION(acos): scalarResult = SkScalarACos(input); break; case SK_FUNCTION(asin): scalarResult = SkScalarASin(input); break; case SK_FUNCTION(atan): scalarResult = SkScalarATan2(input, SK_Scalar1); break; case SK_FUNCTION(atan2): scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar); break; case SK_FUNCTION(ceil): scalarResult = SkIntToScalar(SkScalarCeil(input)); break; case SK_FUNCTION(cos): scalarResult = SkScalarCos(input); break; case SK_FUNCTION(exp): scalarResult = SkScalarExp(input); break; case SK_FUNCTION(floor): scalarResult = SkIntToScalar(SkScalarFloor(input)); break; case SK_FUNCTION(log): scalarResult = SkScalarLog(input); break; case SK_FUNCTION(max): scalarResult = -SK_ScalarMax; while (array < end) { scalarResult = SkMaxScalar(scalarResult, array->fOperand.fScalar); array++; } break; case SK_FUNCTION(min): scalarResult = SK_ScalarMax; while (array < end) { scalarResult = SkMinScalar(scalarResult, array->fOperand.fScalar); array++; } break; case SK_FUNCTION(pow): // not the greatest -- but use x^y = e^(y * ln(x)) scalarResult = SkScalarLog(input); scalarResult = SkScalarMul(parameters[1].fOperand.fScalar, scalarResult); scalarResult = SkScalarExp(scalarResult); break; case SK_FUNCTION(random): scalarResult = fRandom.nextUScalar1(); break; case SK_FUNCTION(round): scalarResult = SkIntToScalar(SkScalarRound(input)); break; case SK_FUNCTION(sin): scalarResult = SkScalarSin(input); break; case SK_FUNCTION(sqrt): { SkASSERT(parameters.count() == 1); SkASSERT(type == SkType_Float); scalarResult = SkScalarSqrt(input); } break; case SK_FUNCTION(tan): scalarResult = SkScalarTan(input); break; default: SkASSERT(0); scalarResult = SK_ScalarNaN; } scriptValue->fOperand.fScalar = scalarResult; scriptValue->fType = SkType_Float; }
bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) { // we do nothing if the src wants to be filled, or if our dashlength is 0 if (rec->isFillStyle() || fInitialDashLength < 0) { return false; } SkPathMeasure meas(src, false); const SkScalar* intervals = fIntervals; SkScalar dashCount = 0; SpecialLineRec lineRec; const bool specialLine = lineRec.init(src, dst, rec, meas.getLength(), fCount >> 1, fIntervalLength); do { bool skipFirstSegment = meas.isClosed(); bool addedSegment = false; SkScalar length = meas.getLength(); int index = fInitialDashIndex; SkScalar scale = SK_Scalar1; // Since the path length / dash length ratio may be arbitrarily large, we can exert // significant memory pressure while attempting to build the filtered path. To avoid this, // we simply give up dashing beyond a certain threshold. // // The original bug report (http://crbug.com/165432) is based on a path yielding more than // 90 million dash segments and crashing the memory allocator. A limit of 1 million // segments seems reasonable: at 2 verbs per segment * 9 bytes per verb, this caps the // maximum dash memory overhead at roughly 17MB per path. static const SkScalar kMaxDashCount = 1000000; dashCount += length * (fCount >> 1) / fIntervalLength; if (dashCount > kMaxDashCount) { dst->reset(); return false; } if (fScaleToFit) { if (fIntervalLength >= length) { scale = SkScalarDiv(length, fIntervalLength); } else { SkScalar div = SkScalarDiv(length, fIntervalLength); int n = SkScalarFloor(div); scale = SkScalarDiv(length, n * fIntervalLength); } } // Using double precision to avoid looping indefinitely due to single precision rounding // (for extreme path_length/dash_length ratios). See test_infinite_dash() unittest. double distance = 0; double dlen = SkScalarMul(fInitialDashLength, scale); while (distance < length) { SkASSERT(dlen >= 0); addedSegment = false; if (is_even(index) && dlen > 0 && !skipFirstSegment) { addedSegment = true; if (specialLine) { lineRec.addSegment(SkDoubleToScalar(distance), SkDoubleToScalar(distance + dlen), dst); } else { meas.getSegment(SkDoubleToScalar(distance), SkDoubleToScalar(distance + dlen), dst, true); } } distance += dlen; // clear this so we only respect it the first time around skipFirstSegment = false; // wrap around our intervals array if necessary index += 1; SkASSERT(index <= fCount); if (index == fCount) { index = 0; } // fetch our next dlen dlen = SkScalarMul(intervals[index], scale); } // extend if we ended on a segment and we need to join up with the (skipped) initial segment if (meas.isClosed() && is_even(fInitialDashIndex) && fInitialDashLength > 0) { meas.getSegment(0, SkScalarMul(fInitialDashLength, scale), dst, !addedSegment); } } while (meas.nextContour()); return true; }
bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) { // we do nothing if the src wants to be filled, or if our dashlength is 0 if (*width < 0 || fInitialDashLength < 0) return false; SkPathMeasure meas(src, false); const SkScalar* intervals = fIntervals; do { bool skipFirstSegment = meas.isClosed(); bool addedSegment = false; SkScalar length = meas.getLength(); int index = fInitialDashIndex; SkScalar scale = SK_Scalar1; if (fScaleToFit) { if (fIntervalLength >= length) scale = SkScalarDiv(length, fIntervalLength); else { SkScalar div = SkScalarDiv(length, fIntervalLength); int n = SkScalarFloor(div); scale = SkScalarDiv(length, n * fIntervalLength); } } SkScalar distance = 0; SkScalar dlen = SkScalarMul(fInitialDashLength, scale); while (distance < length) { SkASSERT(dlen >= 0); addedSegment = false; if (is_even(index) && dlen > 0 && !skipFirstSegment) { addedSegment = true; meas.getSegment(distance, distance + dlen, dst, true); } distance += dlen; // clear this so we only respect it the first time around skipFirstSegment = false; // wrap around our intervals array if necessary index += 1; SkASSERT(index <= fCount); if (index == fCount) index = 0; // fetch our next dlen dlen = SkScalarMul(intervals[index], scale); } // extend if we ended on a segment and we need to join up with the (skipped) initial segment if (meas.isClosed() && is_even(fInitialDashIndex) && fInitialDashLength > 0) meas.getSegment(0, SkScalarMul(fInitialDashLength, scale), dst, !addedSegment); } while (meas.nextContour()); return true; }
JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { if (JSVAL_IS_INT(id) == 0) return JS_TRUE; SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj); SkDisplayable* displayable = p->fDisplayable; SkDisplayTypes displayableType = displayable->getType(); int members; const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members); int idIndex = JSVAL_TO_INT(id); SkASSERT(idIndex >= 0 && idIndex < members); info = &info[idIndex]; SkDisplayTypes infoType = (SkDisplayTypes) info->fType; SkScalar scalar = 0; S32 s32 = 0; SkString* string= NULL; JSString *str; if (infoType == SkType_MemberProperty) { infoType = info->propertyType(); switch (infoType) { case SkType_Scalar: { SkScriptValue scriptValue; bool success = displayable->getProperty(info->propertyIndex(), &scriptValue); SkASSERT(scriptValue.fType == SkType_Scalar); scalar = scriptValue.fOperand.fScalar; } break; default: SkASSERT(0); // !!! unimplemented } } else { SkASSERT(info->fCount == 1); switch (infoType) { case SkType_Boolean: case SkType_Color: case SkType_S32: s32 = *(S32*) info->memberData(displayable); break; case SkType_String: info->getString(displayable, &string); break; case SkType_Scalar: SkOperand operand; info->getValue(displayable, &operand, 1); scalar = operand.fScalar; break; default: SkASSERT(0); // !!! unimplemented } } switch (infoType) { case SkType_Boolean: *vp = BOOLEAN_TO_JSVAL(s32); break; case SkType_Color: case SkType_S32: *vp = INT_TO_JSVAL(s32); break; case SkType_Scalar: if (SkScalarFraction(scalar) == 0) *vp = INT_TO_JSVAL(SkScalarFloor(scalar)); else #ifdef SK_SCALAR_IS_FLOAT *vp = DOUBLE_TO_JSVAL(scalar); #else *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f ); #endif break; case SkType_String: str = JS_NewStringCopyN(cx, string->c_str(), string->size()); *vp = STRING_TO_JSVAL(str); break; default: SkASSERT(0); // !!! unimplemented } return JS_TRUE; }
bool SkScriptRuntime::executeTokens(unsigned char* opCode) { SkOperand2 operand[2]; // 1=accumulator and 2=operand SkScriptEngine2::TypeOp op; size_t ref; int index, size; int registerLoad; SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; do { switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { case SkScriptEngine2::kArrayToken: // create an array operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/); break; case SkScriptEngine2::kArrayIndex: // array accessor index = operand[1].fS32; if (index >= operand[0].fArray->count()) { fError = kArrayIndexOutOfBounds; return false; } operand[0] = operand[0].fArray->begin()[index]; break; case SkScriptEngine2::kArrayParam: // array initializer, or function param *operand[0].fArray->append() = operand[1]; break; case SkScriptEngine2::kCallback: memcpy(&index, opCode, sizeof(index)); opCode += sizeof(index); callBack = fCallBackArray[index]; break; case SkScriptEngine2::kFunctionCall: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack; if (callBackFunction->invoke(ref, operand[0].fArray, /* params */ &operand[0] /* result */) == false) { fError = kFunctionCallFailed; return false; } } break; case SkScriptEngine2::kMemberOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack; if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) { fError = kMemberOpFailed; return false; } } break; case SkScriptEngine2::kPropertyOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack; if (callBackProperty->getResult(ref, &operand[0])== false) { fError = kPropertyOpFailed; return false; } } break; case SkScriptEngine2::kAccumulatorPop: fRunStack.pop(&operand[0]); break; case SkScriptEngine2::kAccumulatorPush: *fRunStack.push() = operand[0]; break; case SkScriptEngine2::kIntegerAccumulator: case SkScriptEngine2::kIntegerOperand: registerLoad = op - SkScriptEngine2::kIntegerAccumulator; memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t)); opCode += sizeof(int32_t); break; case SkScriptEngine2::kScalarAccumulator: case SkScriptEngine2::kScalarOperand: registerLoad = op - SkScriptEngine2::kScalarAccumulator; memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar)); opCode += sizeof(SkScalar); break; case SkScriptEngine2::kStringAccumulator: case SkScriptEngine2::kStringOperand: { SkString* strPtr = new SkString(); track(strPtr); registerLoad = op - SkScriptEngine2::kStringAccumulator; memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); strPtr->set((char*) opCode, size); opCode += size; operand[registerLoad].fString = strPtr; } break; case SkScriptEngine2::kStringTrack: // call after kObjectToValue track(operand[0].fString); break; case SkScriptEngine2::kBoxToken: { SkOperand2::OpType type; memcpy(&type, opCode, sizeof(type)); opCode += sizeof(type); SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack; if (callBackBox->convert(type, &operand[0]) == false) return false; } break; case SkScriptEngine2::kUnboxToken: case SkScriptEngine2::kUnboxToken2: { SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack; if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false) return false; } break; case SkScriptEngine2::kIfOp: case SkScriptEngine2::kLogicalAndInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 == 0) opCode += size; // skip to else (or end of if predicate) break; case SkScriptEngine2::kElseOp: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); opCode += size; // if true: after predicate, always skip to end of else break; case SkScriptEngine2::kLogicalOrInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 != 0) opCode += size; // skip to kToBool opcode after || predicate break; // arithmetic conversion ops case SkScriptEngine2::kFlipOpsOp: SkTSwap(operand[0], operand[1]); break; case SkScriptEngine2::kIntToString: case SkScriptEngine2::kIntToString2: case SkScriptEngine2::kScalarToString: case SkScriptEngine2::kScalarToString2:{ SkString* strPtr = new SkString(); track(strPtr); if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2) strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32); else strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar); operand[0].fString = strPtr; } break; case SkScriptEngine2::kIntToScalar: case SkScriptEngine2::kIntToScalar2: operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); break; case SkScriptEngine2::kStringToInt: if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == false) return false; break; case SkScriptEngine2::kStringToScalar: case SkScriptEngine2::kStringToScalar2: if (SkParse::FindScalar(operand[0].fString->c_str(), &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == false) return false; break; case SkScriptEngine2::kScalarToInt: operand[0].fS32 = SkScalarFloor(operand[0].fScalar); break; // arithmetic ops case SkScriptEngine2::kAddInt: operand[0].fS32 += operand[1].fS32; break; case SkScriptEngine2::kAddScalar: operand[0].fScalar += operand[1].fScalar; break; case SkScriptEngine2::kAddString: // if (fTrackString.find(operand[1].fString) < 0) { // operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString)); // track(operand[1].fString); // } operand[0].fString->append(*operand[1].fString); break; case SkScriptEngine2::kBitAndInt: operand[0].fS32 &= operand[1].fS32; break; case SkScriptEngine2::kBitNotInt: operand[0].fS32 = ~operand[0].fS32; break; case SkScriptEngine2::kBitOrInt: operand[0].fS32 |= operand[1].fS32; break; case SkScriptEngine2::kDivideInt: SkASSERT(operand[1].fS32 != 0); if (operand[1].fS32 == 0) operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 : operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32; else if (operand[1].fS32 != 0) // throw error on divide by zero? operand[0].fS32 /= operand[1].fS32; break; case SkScriptEngine2::kDivideScalar: if (operand[1].fScalar == 0) operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN : operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax; else operand[0].fScalar = SkScalarDiv(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kEqualInt: operand[0].fS32 = operand[0].fS32 == operand[1].fS32; break; case SkScriptEngine2::kEqualScalar: operand[0].fS32 = operand[0].fScalar == operand[1].fScalar; break; case SkScriptEngine2::kEqualString: operand[0].fS32 = *operand[0].fString == *operand[1].fString; break; case SkScriptEngine2::kGreaterEqualInt: operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; break; case SkScriptEngine2::kGreaterEqualScalar: operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar; break; case SkScriptEngine2::kGreaterEqualString: operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0; break; case SkScriptEngine2::kToBool: operand[0].fS32 = !! operand[0].fS32; break; case SkScriptEngine2::kLogicalNotInt: operand[0].fS32 = ! operand[0].fS32; break; case SkScriptEngine2::kMinusInt: operand[0].fS32 = -operand[0].fS32; break; case SkScriptEngine2::kMinusScalar: operand[0].fScalar = -operand[0].fScalar; break; case SkScriptEngine2::kModuloInt: operand[0].fS32 %= operand[1].fS32; break; case SkScriptEngine2::kModuloScalar: operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kMultiplyInt: operand[0].fS32 *= operand[1].fS32; break; case SkScriptEngine2::kMultiplyScalar: operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kShiftLeftInt: operand[0].fS32 <<= operand[1].fS32; break; case SkScriptEngine2::kShiftRightInt: operand[0].fS32 >>= operand[1].fS32; break; case SkScriptEngine2::kSubtractInt: operand[0].fS32 -= operand[1].fS32; break; case SkScriptEngine2::kSubtractScalar: operand[0].fScalar -= operand[1].fScalar; break; case SkScriptEngine2::kXorInt: operand[0].fS32 ^= operand[1].fS32; break; case SkScriptEngine2::kEnd: goto done; case SkScriptEngine2::kNop: SkASSERT(0); default: break; } } while (true); done: fRunStack.push(operand[0]); return true; }
bool MCGBlurBox(const SkMask& p_src, SkScalar p_x_radius, SkScalar p_y_radius, SkScalar p_x_spread, SkScalar p_y_spread, SkMask& r_dst) { int t_pass_count; t_pass_count = 3; // Maximum amount of spread is 254 pixels. int x_spread, y_spread; x_spread = SkMin32(SkScalarFloor(p_x_radius * p_x_spread), 254); y_spread = SkMin32(SkScalarFloor(p_y_radius * p_y_spread), 254); p_x_radius -= x_spread; p_y_radius -= y_spread; int rx, ry; rx = SkScalarCeil(p_x_radius); ry = SkScalarCeil(p_y_radius); SkScalar px, py; px = rx; py = ry; int wx, wy; wx = 255 - SkScalarRound((SkIntToScalar(rx) - px) * 255); wy = 255 - SkScalarRound((SkIntToScalar(ry) - py) * 255); int t_pad_x, t_pad_y; t_pad_x = rx + x_spread; t_pad_y = ry + y_spread; r_dst . fBounds . set(p_src . fBounds . fLeft - t_pad_x, p_src . fBounds . fTop - t_pad_y, p_src . fBounds . fRight + t_pad_x, p_src . fBounds . fBottom + t_pad_y); r_dst . fRowBytes = r_dst . fBounds . width(); r_dst . fFormat = SkMask::kA8_Format; r_dst . fImage = NULL; if (p_src . fImage == NULL) return true; size_t t_dst_size; t_dst_size = r_dst . computeImageSize(); if (t_dst_size == 0) return false; int sw, sh; sw = p_src . fBounds . width(); sh = p_src . fBounds . height(); const uint8_t *sp; sp = p_src . fImage; uint8_t *dp; dp = SkMask::AllocImage(t_dst_size); if (dp == nil) return false; uint8_t *tp; tp = SkMask::AllocImage(t_dst_size); if (tp == nil) { SkMask::FreeImage(dp); return false; } int w, h; w = sw; h = sh; if (wx == 255) { if (t_pass_count == 3) { int r; r = rx; bool t_has_spread; t_has_spread = false; if (x_spread != 0 || y_spread != 0) { //w = dilateMask(sp, p_src . fRowBytes, tp, x_spread, w, h, true); //h = dilateMask(tp, h, dp, y_spread, h, w, true); dilateDistanceXY(sp, dp, x_spread, y_spread, w, h, w, h); t_has_spread = true; } int trx; trx = (r + 2) / 3; r -= trx; int rx_lo, rx_hi; rx_lo = rx_hi = trx; w = boxBlur(t_has_spread ? dp : sp, t_has_spread ? w : p_src . fRowBytes, tp, rx_lo, rx_hi, w, h, false); trx = (r + 1) / 2; r -= trx; rx_lo = rx_hi = trx; w = boxBlur(tp, w, dp, rx_hi, rx_lo, w, h, false); trx = r; rx_lo = rx_hi = trx; w = boxBlur(dp, w, tp, rx_hi, rx_hi, w, h, true); } else w = boxBlur(sp, p_src . fRowBytes, tp, rx, rx, w, h, true); } else { if (t_pass_count == 3) { int r; r = rx; bool t_has_spread; t_has_spread = false; if (x_spread != 0 || y_spread != 0) { //w = dilateMask(sp, p_src . fRowBytes, tp, x_spread, w, h, true); //h = dilateMask(tp, h, dp, y_spread, h, w, true); dilateDistanceXY(sp, dp, x_spread, y_spread, w, h, w, h); t_has_spread = true; } int trx; trx = (r + 2) / 3; r -= trx; w = boxBlurInterp(t_has_spread ? dp : sp, t_has_spread ? w : p_src . fRowBytes, tp, trx, w, h, false, wx); trx = (r + 1) / 2; r -= trx; w = boxBlurInterp(tp, w, dp, trx, w, h, false, wx); trx = r; w = boxBlurInterp(dp, w, tp, trx, w, h, true, wx); } else w = boxBlurInterp(sp, p_src . fRowBytes, tp, rx, w, h, true, wx); } if (wy == 255) { if (t_pass_count == 3) { int r; r = ry; int sry; sry = (r + 2) / 3; r -= sry; int ry_lo, ry_hi; ry_lo = ry_hi = sry; h = boxBlur(tp, h, dp, ry_lo, ry_hi, h, w, false); sry = (r + 1) / 2; r -= sry; ry_lo = ry_hi = sry; h = boxBlur(dp, h, tp, ry_hi, ry_lo, h, w, false); sry = r; ry_lo = ry_hi = sry; h = boxBlur(tp, h, dp, ry_hi, ry_hi, h, w, true); } else h = boxBlur(tp, h, dp, ry, ry, h, w, true); } else { if (t_pass_count == 3) { int r; r = ry; int sry; sry = (r + 2) / 3; r -= sry; h = boxBlurInterp(tp, h, dp, sry, h, w, false, wy); sry = (r + 1) / 2; r -= sry; h = boxBlurInterp(dp, h, tp, sry, h, w, false, wy); sry = r; h = boxBlurInterp(tp, h, dp, sry, h, w, true, wy); } else w = boxBlurInterp(tp, h, dp, rx, h, w, true, wy); } SkMask::FreeImage(tp); r_dst . fImage = dp; return true; }