Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: src/effects/SkMagnifierImageFilter.cpp

Issue 1882943002: Switch SkMagnifierImageFilter over to new onFilterImage interface (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: update Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/effects/SkMagnifierImageFilter.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « include/effects/SkMagnifierImageFilter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698