| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkMagnifierImageFilter.h" |
| 9 |
| 8 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| 9 #include "SkMagnifierImageFilter.h" | |
| 10 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 11 #include "SkDevice.h" | |
| 12 #include "SkReadBuffer.h" | 12 #include "SkReadBuffer.h" |
| 13 #include "SkSpecialImage.h" |
| 13 #include "SkWriteBuffer.h" | 14 #include "SkWriteBuffer.h" |
| 14 #include "SkValidationUtils.h" | 15 #include "SkValidationUtils.h" |
| 15 | 16 |
| 16 //////////////////////////////////////////////////////////////////////////////// | 17 //////////////////////////////////////////////////////////////////////////////// |
| 17 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
| 19 #include "GrContext.h" |
| 20 #include "GrDrawContext.h" |
| 18 #include "GrInvariantOutput.h" | 21 #include "GrInvariantOutput.h" |
| 19 #include "effects/GrSingleTextureEffect.h" | 22 #include "effects/GrSingleTextureEffect.h" |
| 20 #include "glsl/GrGLSLFragmentProcessor.h" | 23 #include "glsl/GrGLSLFragmentProcessor.h" |
| 21 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 24 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 22 #include "glsl/GrGLSLProgramDataManager.h" | 25 #include "glsl/GrGLSLProgramDataManager.h" |
| 23 #include "glsl/GrGLSLUniformHandler.h" | 26 #include "glsl/GrGLSLUniformHandler.h" |
| 24 | 27 |
| 25 class GrMagnifierEffect : public GrSingleTextureEffect { | 28 class GrMagnifierEffect : public GrSingleTextureEffect { |
| 26 | 29 |
| 27 public: | 30 public: |
| 28 static GrFragmentProcessor* Create(GrTexture* texture, | 31 static GrFragmentProcessor* Create(GrTexture* texture, |
| 29 const SkRect& bounds, | 32 const SkRect& bounds, |
| 30 float xOffset, | 33 float xOffset, |
| 31 float yOffset, | 34 float yOffset, |
| 32 float xInvZoom, | 35 float xInvZoom, |
| 33 float yInvZoom, | 36 float yInvZoom, |
| 34 float xInvInset, | 37 float xInvInset, |
| 35 float yInvInset) { | 38 float yInvInset) { |
| 36 return new GrMagnifierEffect(texture, bounds, xOffset, yOffset, xInvZoom
, yInvZoom, xInvInset, | 39 return new GrMagnifierEffect(texture, bounds, |
| 37 yInvInset); | 40 xOffset, yOffset, |
| 41 xInvZoom, yInvZoom, |
| 42 xInvInset, yInvInset); |
| 38 } | 43 } |
| 39 | 44 |
| 40 virtual ~GrMagnifierEffect() {}; | 45 ~GrMagnifierEffect() override {}; |
| 41 | 46 |
| 42 const char* name() const override { return "Magnifier"; } | 47 const char* name() const override { return "Magnifier"; } |
| 43 | 48 |
| 44 const SkRect& bounds() const { return fBounds; } // Bounds of source imag
e. | 49 const SkRect& bounds() const { return fBounds; } // Bounds of source imag
e. |
| 45 // Offset to apply to zoomed pixels, (srcRect position / texture size). | 50 // Offset to apply to zoomed pixels, (srcRect position / texture size). |
| 46 float x_offset() const { return fXOffset; } | 51 float xOffset() const { return fXOffset; } |
| 47 float y_offset() const { return fYOffset; } | 52 float yOffset() const { return fYOffset; } |
| 48 | 53 |
| 49 // Scale to apply to zoomed pixels (srcRect size / bounds size). | 54 // Scale to apply to zoomed pixels (srcRect size / bounds size). |
| 50 float x_inv_zoom() const { return fXInvZoom; } | 55 float xInvZoom() const { return fXInvZoom; } |
| 51 float y_inv_zoom() const { return fYInvZoom; } | 56 float yInvZoom() const { return fYInvZoom; } |
| 52 | 57 |
| 53 // 1/radius over which to transition from unzoomed to zoomed pixels (bounds
size / inset). | 58 // 1/radius over which to transition from unzoomed to zoomed pixels (bounds
size / inset). |
| 54 float x_inv_inset() const { return fXInvInset; } | 59 float xInvInset() const { return fXInvInset; } |
| 55 float y_inv_inset() const { return fYInvInset; } | 60 float yInvInset() const { return fYInvInset; } |
| 56 | 61 |
| 57 private: | 62 private: |
| 58 GrMagnifierEffect(GrTexture* texture, | 63 GrMagnifierEffect(GrTexture* texture, |
| 59 const SkRect& bounds, | 64 const SkRect& bounds, |
| 60 float xOffset, | 65 float xOffset, |
| 61 float yOffset, | 66 float yOffset, |
| 62 float xInvZoom, | 67 float xInvZoom, |
| 63 float yInvZoom, | 68 float yInvZoom, |
| 64 float xInvInset, | 69 float xInvInset, |
| 65 float yInvInset) | 70 float yInvInset) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 165 |
| 161 fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor); | 166 fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor); |
| 162 SkString modulate; | 167 SkString modulate; |
| 163 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); | 168 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); |
| 164 fragBuilder->codeAppend(modulate.c_str()); | 169 fragBuilder->codeAppend(modulate.c_str()); |
| 165 } | 170 } |
| 166 | 171 |
| 167 void GrGLMagnifierEffect::onSetData(const GrGLSLProgramDataManager& pdman, | 172 void GrGLMagnifierEffect::onSetData(const GrGLSLProgramDataManager& pdman, |
| 168 const GrProcessor& effect) { | 173 const GrProcessor& effect) { |
| 169 const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); | 174 const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); |
| 170 pdman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); | 175 pdman.set2f(fOffsetVar, zoom.xOffset(), zoom.yOffset()); |
| 171 pdman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom()); | 176 pdman.set2f(fInvZoomVar, zoom.xInvZoom(), zoom.yInvZoom()); |
| 172 pdman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset()); | 177 pdman.set2f(fInvInsetVar, zoom.xInvInset(), zoom.yInvInset()); |
| 173 pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(), | 178 pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(), |
| 174 zoom.bounds().width(), zoom.bounds().height()); | 179 zoom.bounds().width(), zoom.bounds().height()); |
| 175 } | 180 } |
| 176 | 181 |
| 177 ///////////////////////////////////////////////////////////////////// | 182 ///////////////////////////////////////////////////////////////////// |
| 178 | 183 |
| 179 void GrMagnifierEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, | 184 void GrMagnifierEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
| 180 GrProcessorKeyBuilder* b) const { | 185 GrProcessorKeyBuilder* b) const { |
| 181 GrGLMagnifierEffect::GenKey(*this, caps, b); | 186 GrGLMagnifierEffect::GenKey(*this, caps, b); |
| 182 } | 187 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 231 |
| 227 void GrMagnifierEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const
{ | 232 void GrMagnifierEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const
{ |
| 228 this->updateInvariantOutputForModulation(inout); | 233 this->updateInvariantOutputForModulation(inout); |
| 229 } | 234 } |
| 230 | 235 |
| 231 #endif | 236 #endif |
| 232 | 237 |
| 233 //////////////////////////////////////////////////////////////////////////////// | 238 //////////////////////////////////////////////////////////////////////////////// |
| 234 | 239 |
| 235 sk_sp<SkImageFilter> SkMagnifierImageFilter::Make(const SkRect& srcRect, SkScala
r inset, | 240 sk_sp<SkImageFilter> SkMagnifierImageFilter::Make(const SkRect& srcRect, SkScala
r inset, |
| 236 sk_sp<SkImageFilter> input) { | 241 sk_sp<SkImageFilter> input, |
| 242 const CropRect* cropRect) { |
| 237 | 243 |
| 238 if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) { | 244 if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) { |
| 239 return nullptr; | 245 return nullptr; |
| 240 } | 246 } |
| 241 // Negative numbers in src rect are not supported | 247 // Negative numbers in src rect are not supported |
| 242 if (srcRect.fLeft < 0 || srcRect.fTop < 0) { | 248 if (srcRect.fLeft < 0 || srcRect.fTop < 0) { |
| 243 return nullptr; | 249 return nullptr; |
| 244 } | 250 } |
| 245 return sk_sp<SkImageFilter>(new SkMagnifierImageFilter(srcRect, inset, std::
move(input))); | 251 return sk_sp<SkImageFilter>(new SkMagnifierImageFilter(srcRect, inset, |
| 252 std::move(input), |
| 253 cropRect)); |
| 246 } | 254 } |
| 247 | 255 |
| 248 | 256 |
| 249 SkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar i
nset, | 257 SkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, |
| 250 sk_sp<SkImageFilter> input) | 258 SkScalar inset, |
| 251 : INHERITED(&input, 1, nullptr) | 259 sk_sp<SkImageFilter> input, |
| 260 const CropRect* cropRect) |
| 261 : INHERITED(&input, 1, cropRect) |
| 252 , fSrcRect(srcRect) | 262 , fSrcRect(srcRect) |
| 253 , fInset(inset) { | 263 , fInset(inset) { |
| 254 SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); | 264 SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); |
| 255 } | 265 } |
| 256 | 266 |
| 257 #if SK_SUPPORT_GPU | |
| 258 bool SkMagnifierImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, | |
| 259 GrTexture* texture, const SkMat
rix&, | |
| 260 const SkIRect&bounds) const { | |
| 261 if (fp) { | |
| 262 SkScalar yOffset = texture->origin() == kTopLeft_GrSurfaceOrigin ? fSrcR
ect.y() : | |
| 263 texture->height() - fSrcRect.height() * texture->height() / bounds.he
ight() | |
| 264 - fSrcRect.y(); | |
| 265 int boundsY = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? bounds.y
() : | |
| 266 (texture->height() - bounds.height()); | |
| 267 SkRect effectBounds = SkRect::MakeXYWH( | |
| 268 SkIntToScalar(bounds.x()) / texture->width(), | |
| 269 SkIntToScalar(boundsY) / texture->height(), | |
| 270 SkIntToScalar(texture->width()) / bounds.width(), | |
| 271 SkIntToScalar(texture->height()) / bounds.height()); | |
| 272 SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; | |
| 273 *fp = GrMagnifierEffect::Create(texture, | |
| 274 effectBounds, | |
| 275 fSrcRect.x() / texture->width(), | |
| 276 yOffset / texture->height(), | |
| 277 fSrcRect.width() / bounds.width(), | |
| 278 fSrcRect.height() / bounds.height(), | |
| 279 bounds.width() * invInset, | |
| 280 bounds.height() * invInset); | |
| 281 } | |
| 282 return true; | |
| 283 } | |
| 284 #endif | |
| 285 | |
| 286 sk_sp<SkFlattenable> SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) { | 267 sk_sp<SkFlattenable> SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) { |
| 287 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); | 268 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); |
| 288 SkRect src; | 269 SkRect src; |
| 289 buffer.readRect(&src); | 270 buffer.readRect(&src); |
| 290 return Make(src, buffer.readScalar(), common.getInput(0)); | 271 return Make(src, buffer.readScalar(), common.getInput(0), &common.cropRect()
); |
| 291 } | 272 } |
| 292 | 273 |
| 293 void SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { | 274 void SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { |
| 294 this->INHERITED::flatten(buffer); | 275 this->INHERITED::flatten(buffer); |
| 295 buffer.writeRect(fSrcRect); | 276 buffer.writeRect(fSrcRect); |
| 296 buffer.writeScalar(fInset); | 277 buffer.writeScalar(fInset); |
| 297 } | 278 } |
| 298 | 279 |
| 299 bool SkMagnifierImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitma
p& src, | 280 sk_sp<SkSpecialImage> SkMagnifierImageFilter::onFilterImage(SkSpecialImage* sour
ce, |
| 300 const Context&, SkBitmap* d
st, | 281 const Context& ctx, |
| 301 SkIPoint* offset) const { | 282 SkIPoint* offset) co
nst { |
| 302 if ((src.colorType() != kN32_SkColorType) || | 283 SkIPoint inputOffset = SkIPoint::Make(0, 0); |
| 303 (fSrcRect.width() >= src.width()) || | 284 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset))
; |
| 304 (fSrcRect.height() >= src.height())) { | 285 if (!input) { |
| 305 return false; | 286 return nullptr; |
| 306 } | 287 } |
| 307 | 288 |
| 308 SkAutoLockPixels alp(src); | 289 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y
(), |
| 309 SkASSERT(src.getPixels()); | 290 input->width(), input->height(
)); |
| 310 if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { | 291 |
| 311 return false; | 292 SkIRect bounds; |
| 293 if (!this->applyCropRect(ctx, inputBounds, &bounds)) { |
| 294 return nullptr; |
| 312 } | 295 } |
| 313 | 296 |
| 314 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.heigh
t())); | 297 SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; |
| 315 if (!device) { | 298 |
| 316 return false; | 299 SkScalar invXZoom = fSrcRect.width() / bounds.width(); |
| 300 SkScalar invYZoom = fSrcRect.height() / bounds.height(); |
| 301 |
| 302 |
| 303 #if SK_SUPPORT_GPU |
| 304 if (source->isTextureBacked()) { |
| 305 GrContext* context = source->getContext(); |
| 306 |
| 307 sk_sp<GrTexture> inputTexture(input->asTextureRef(context)); |
| 308 SkASSERT(inputTexture); |
| 309 |
| 310 offset->fX = bounds.left(); |
| 311 offset->fY = bounds.top(); |
| 312 bounds.offset(-inputOffset); |
| 313 |
| 314 SkScalar yOffset = inputTexture->origin() == kTopLeft_GrSurfaceOrigin |
| 315 ? fSrcRect.y() |
| 316 : inputTexture->height() - |
| 317 fSrcRect.height() * inputTexture->height() / bounds.height
() - fSrcRect.y(); |
| 318 int boundsY = inputTexture->origin() == kTopLeft_GrSurfaceOrigin |
| 319 ? bounds.y() |
| 320 : inputTexture->height() - bounds.height(); |
| 321 SkRect effectBounds = SkRect::MakeXYWH( |
| 322 SkIntToScalar(bounds.x()) / inputTexture->width(), |
| 323 SkIntToScalar(boundsY) / inputTexture->height(), |
| 324 SkIntToScalar(inputTexture->width()) / bounds.width(), |
| 325 SkIntToScalar(inputTexture->height()) / bounds.height()); |
| 326 // SRGBTODO: Handle sRGB here |
| 327 sk_sp<GrFragmentProcessor> fp(GrMagnifierEffect::Create( |
| 328 inputTexture.get(), |
| 329 effectBounds, |
| 330 fSrcRect.x() / inputText
ure->width(), |
| 331 yOffset / inputTexture->
height(), |
| 332 invXZoom, |
| 333 invYZoom, |
| 334 bounds.width() * invInse
t, |
| 335 bounds.height() * invIns
et)); |
| 336 if (!fp) { |
| 337 return nullptr; |
| 338 } |
| 339 |
| 340 return DrawWithFP(context, std::move(fp), bounds, source->internal_getPr
oxy()); |
| 317 } | 341 } |
| 318 *dst = device->accessBitmap(false); | 342 #endif |
| 319 SkAutoLockPixels alp_dst(*dst); | |
| 320 | 343 |
| 321 SkScalar inv_inset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; | 344 SkBitmap inputBM; |
| 322 | 345 |
| 323 SkScalar inv_x_zoom = fSrcRect.width() / src.width(); | 346 if (!input->getROPixels(&inputBM)) { |
| 324 SkScalar inv_y_zoom = fSrcRect.height() / src.height(); | 347 return nullptr; |
| 348 } |
| 325 | 349 |
| 326 SkColor* sptr = src.getAddr32(0, 0); | 350 if ((inputBM.colorType() != kN32_SkColorType) || |
| 327 SkColor* dptr = dst->getAddr32(0, 0); | 351 (fSrcRect.width() >= inputBM.width()) || (fSrcRect.height() >= inputBM.h
eight())) { |
| 328 int width = src.width(), height = src.height(); | 352 return nullptr; |
| 329 for (int y = 0; y < height; ++y) { | 353 } |
| 330 for (int x = 0; x < width; ++x) { | 354 |
| 331 SkScalar x_dist = SkMin32(x, width - x - 1) * inv_inset; | 355 SkAutoLockPixels alp(inputBM); |
| 332 SkScalar y_dist = SkMin32(y, height - y - 1) * inv_inset; | 356 SkASSERT(inputBM.getPixels()); |
| 357 if (!inputBM.getPixels() || inputBM.width() <= 0 || inputBM.height() <= 0) { |
| 358 return nullptr; |
| 359 } |
| 360 |
| 361 const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.h
eight()); |
| 362 |
| 363 SkBitmap dst; |
| 364 if (!dst.tryAllocPixels(info)) { |
| 365 return nullptr; |
| 366 } |
| 367 |
| 368 SkAutoLockPixels dstLock(dst); |
| 369 |
| 370 SkColor* dptr = dst.getAddr32(0, 0); |
| 371 int dstWidth = dst.width(), dstHeight = dst.height(); |
| 372 for (int y = 0; y < dstHeight; ++y) { |
| 373 for (int x = 0; x < dstWidth; ++x) { |
| 374 SkScalar x_dist = SkMin32(x, dstWidth - x - 1) * invInset; |
| 375 SkScalar y_dist = SkMin32(y, dstHeight - y - 1) * invInset; |
| 333 SkScalar weight = 0; | 376 SkScalar weight = 0; |
| 334 | 377 |
| 335 static const SkScalar kScalar2 = SkScalar(2); | 378 static const SkScalar kScalar2 = SkScalar(2); |
| 336 | 379 |
| 337 // To create a smooth curve at the corners, we need to work on | 380 // To create a smooth curve at the corners, we need to work on |
| 338 // a square twice the size of the inset. | 381 // a square twice the size of the inset. |
| 339 if (x_dist < kScalar2 && y_dist < kScalar2) { | 382 if (x_dist < kScalar2 && y_dist < kScalar2) { |
| 340 x_dist = kScalar2 - x_dist; | 383 x_dist = kScalar2 - x_dist; |
| 341 y_dist = kScalar2 - y_dist; | 384 y_dist = kScalar2 - y_dist; |
| 342 | 385 |
| 343 SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + | 386 SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + |
| 344 SkScalarSquare(y_dist)); | 387 SkScalarSquare(y_dist)); |
| 345 dist = SkMaxScalar(kScalar2 - dist, 0); | 388 dist = SkMaxScalar(kScalar2 - dist, 0); |
| 346 weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); | 389 weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); |
| 347 } else { | 390 } else { |
| 348 SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), | 391 SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), |
| 349 SkScalarSquare(y_dist)); | 392 SkScalarSquare(y_dist)); |
| 350 weight = SkMinScalar(sqDist, SK_Scalar1); | 393 weight = SkMinScalar(sqDist, SK_Scalar1); |
| 351 } | 394 } |
| 352 | 395 |
| 353 SkScalar x_interp = SkScalarMul(weight, (fSrcRect.x() + x * inv_x_zo
om)) + | 396 SkScalar x_interp = SkScalarMul(weight, (fSrcRect.x() + x * invXZoom
)) + |
| 354 (SK_Scalar1 - weight) * x; | 397 (SK_Scalar1 - weight) * x; |
| 355 SkScalar y_interp = SkScalarMul(weight, (fSrcRect.y() + y * inv_y_zo
om)) + | 398 SkScalar y_interp = SkScalarMul(weight, (fSrcRect.y() + y * invYZoom
)) + |
| 356 (SK_Scalar1 - weight) * y; | 399 (SK_Scalar1 - weight) * y; |
| 357 | 400 |
| 358 int x_val = SkTPin(SkScalarFloorToInt(x_interp), 0, width - 1); | 401 int x_val = SkTPin(bounds.x() + SkScalarFloorToInt(x_interp), 0, inp
utBM.width() - 1); |
| 359 int y_val = SkTPin(SkScalarFloorToInt(y_interp), 0, height - 1); | 402 int y_val = SkTPin(bounds.y() + SkScalarFloorToInt(y_interp), 0, inp
utBM.height() - 1); |
| 360 | 403 |
| 361 *dptr = sptr[y_val * width + x_val]; | 404 *dptr = *inputBM.getAddr32(x_val, y_val); |
| 362 dptr++; | 405 dptr++; |
| 363 } | 406 } |
| 364 } | 407 } |
| 365 return true; | 408 |
| 409 offset->fX = bounds.left(); |
| 410 offset->fY = bounds.top(); |
| 411 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), |
| 412 SkIRect::MakeWH(bounds.width(), bounds
.height()), |
| 413 dst); |
| 366 } | 414 } |
| 367 | 415 |
| 368 #ifndef SK_IGNORE_TO_STRING | 416 #ifndef SK_IGNORE_TO_STRING |
| 369 void SkMagnifierImageFilter::toString(SkString* str) const { | 417 void SkMagnifierImageFilter::toString(SkString* str) const { |
| 370 str->appendf("SkMagnifierImageFilter: ("); | 418 str->appendf("SkMagnifierImageFilter: ("); |
| 371 str->appendf("src: (%f,%f,%f,%f) ", | 419 str->appendf("src: (%f,%f,%f,%f) ", |
| 372 fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBotto
m); | 420 fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBotto
m); |
| 373 str->appendf("inset: %f", fInset); | 421 str->appendf("inset: %f", fInset); |
| 374 str->append(")"); | 422 str->append(")"); |
| 375 } | 423 } |
| 376 #endif | 424 #endif |
| OLD | NEW |