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 "SkMorphologyImageFilter.h" | 8 #include "SkMorphologyImageFilter.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 */ | 279 */ |
280 class GrMorphologyEffect : public Gr1DKernelEffect { | 280 class GrMorphologyEffect : public Gr1DKernelEffect { |
281 | 281 |
282 public: | 282 public: |
283 | 283 |
284 enum MorphologyType { | 284 enum MorphologyType { |
285 kErode_MorphologyType, | 285 kErode_MorphologyType, |
286 kDilate_MorphologyType, | 286 kDilate_MorphologyType, |
287 }; | 287 }; |
288 | 288 |
289 static GrFragmentProcessor* Create(GrTexture* tex, Direction dir, int radius , | 289 static GrFragmentProcessor* Create(GrTexture* tex, Direction dir, int radius , bool useBounds, float bounds[2], |
Justin Novosad
2014/12/22 20:11:11
Instead of having useBounds, you should consider h
cwallez
2015/01/19 21:34:38
Done.
| |
290 MorphologyType type) { | 290 MorphologyType type) { |
291 return SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, type)); | 291 return SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, useBounds, boun ds, type)); |
292 } | 292 } |
293 | 293 |
294 virtual ~GrMorphologyEffect(); | 294 virtual ~GrMorphologyEffect(); |
295 | 295 |
296 MorphologyType type() const { return fType; } | 296 MorphologyType type() const { return fType; } |
297 bool useBounds() const { return fUseBounds; } | |
298 const float* bounds() const { return fBounds; } | |
Justin Novosad
2014/12/22 20:11:11
"Bounds" are usually SkRect throughout skia. Perha
cwallez
2015/01/19 21:34:39
This is not an actual x-y par but more like a min-
| |
297 | 299 |
298 static const char* Name() { return "Morphology"; } | 300 static const char* Name() { return "Morphology"; } |
299 | 301 |
300 typedef GrGLMorphologyEffect GLProcessor; | 302 typedef GrGLMorphologyEffect GLProcessor; |
301 | 303 |
302 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERR IDE; | 304 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERR IDE; |
303 | 305 |
304 protected: | 306 protected: |
305 | 307 |
306 MorphologyType fType; | 308 MorphologyType fType; |
309 bool fUseBounds; | |
310 float fBounds[2]; | |
307 | 311 |
308 private: | 312 private: |
309 virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE; | 313 virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE; |
310 | 314 |
311 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE RRIDE; | 315 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE RRIDE; |
312 | 316 |
313 GrMorphologyEffect(GrTexture*, Direction, int radius, MorphologyType); | 317 GrMorphologyEffect(GrTexture*, Direction, int radius, bool useBounds, float bounds[2], MorphologyType); |
314 | 318 |
315 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 319 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
316 | 320 |
317 typedef Gr1DKernelEffect INHERITED; | 321 typedef Gr1DKernelEffect INHERITED; |
318 }; | 322 }; |
319 | 323 |
320 /////////////////////////////////////////////////////////////////////////////// | 324 /////////////////////////////////////////////////////////////////////////////// |
321 | 325 |
322 class GrGLMorphologyEffect : public GrGLFragmentProcessor { | 326 class GrGLMorphologyEffect : public GrGLFragmentProcessor { |
323 public: | 327 public: |
324 GrGLMorphologyEffect (const GrBackendProcessorFactory&, const GrProcessor&); | 328 GrGLMorphologyEffect (const GrBackendProcessorFactory&, const GrProcessor&); |
325 | 329 |
326 virtual void emitCode(GrGLFPBuilder*, | 330 virtual void emitCode(GrGLFPBuilder*, |
327 const GrFragmentProcessor&, | 331 const GrFragmentProcessor&, |
328 const char* outputColor, | 332 const char* outputColor, |
329 const char* inputColor, | 333 const char* inputColor, |
330 const TransformedCoordsArray&, | 334 const TransformedCoordsArray&, |
331 const TextureSamplerArray&) SK_OVERRIDE; | 335 const TextureSamplerArray&) SK_OVERRIDE; |
332 | 336 |
333 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKe yBuilder* b); | 337 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKe yBuilder* b); |
334 | 338 |
335 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O VERRIDE; | 339 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O VERRIDE; |
336 | 340 |
337 private: | 341 private: |
338 int width() const { return GrMorphologyEffect::WidthFromRadius(fRadius); } | 342 int width() const { return GrMorphologyEffect::WidthFromRadius(fRadius); } |
339 | 343 |
340 int fRadius; | 344 int fRadius; |
345 Gr1DKernelEffect::Direction fDirection; | |
346 bool fUseBounds; | |
341 GrMorphologyEffect::MorphologyType fType; | 347 GrMorphologyEffect::MorphologyType fType; |
342 GrGLProgramDataManager::UniformHandle fImageIncrementUni; | 348 GrGLProgramDataManager::UniformHandle fPixelSizeUni; |
349 GrGLProgramDataManager::UniformHandle fBoundsUni; | |
343 | 350 |
344 typedef GrGLFragmentProcessor INHERITED; | 351 typedef GrGLFragmentProcessor INHERITED; |
345 }; | 352 }; |
346 | 353 |
347 GrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendProcessorFactory& fact ory, | 354 GrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendProcessorFactory& fact ory, |
348 const GrProcessor& proc) | 355 const GrProcessor& proc) |
349 : INHERITED(factory) { | 356 : INHERITED(factory) { |
350 const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>(); | 357 const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>(); |
351 fRadius = m.radius(); | 358 fRadius = m.radius(); |
359 fDirection = m.direction(); | |
360 fUseBounds = m.useBounds(); | |
352 fType = m.type(); | 361 fType = m.type(); |
353 } | 362 } |
354 | 363 |
355 void GrGLMorphologyEffect::emitCode(GrGLFPBuilder* builder, | 364 void GrGLMorphologyEffect::emitCode(GrGLFPBuilder* builder, |
356 const GrFragmentProcessor&, | 365 const GrFragmentProcessor&, |
357 const char* outputColor, | 366 const char* outputColor, |
358 const char* inputColor, | 367 const char* inputColor, |
359 const TransformedCoordsArray& coords, | 368 const TransformedCoordsArray& coords, |
360 const TextureSamplerArray& samplers) { | 369 const TextureSamplerArray& samplers) { |
361 fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visib ility, | 370 fPixelSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility , |
362 kVec2f_GrSLType, "ImageIncrement"); | 371 kFloat_GrSLType, "PixelSize"); |
372 const char* pixelSizeInc = builder->getUniformCStr(fPixelSizeUni); | |
373 fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
374 kVec2f_GrSLType, "Bounds"); | |
375 const char* bounds = builder->getUniformCStr(fBoundsUni); | |
363 | 376 |
364 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 377 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
365 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); | 378 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); |
366 const char* func; | 379 const char* func; |
367 switch (fType) { | 380 switch (fType) { |
368 case GrMorphologyEffect::kErode_MorphologyType: | 381 case GrMorphologyEffect::kErode_MorphologyType: |
369 fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor); | 382 fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor); |
370 func = "min"; | 383 func = "min"; |
371 break; | 384 break; |
372 case GrMorphologyEffect::kDilate_MorphologyType: | 385 case GrMorphologyEffect::kDilate_MorphologyType: |
373 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); | 386 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); |
374 func = "max"; | 387 func = "max"; |
375 break; | 388 break; |
376 default: | 389 default: |
377 SkFAIL("Unexpected type"); | 390 SkFAIL("Unexpected type"); |
378 func = ""; // suppress warning | 391 func = ""; // suppress warning |
379 break; | 392 break; |
380 } | 393 } |
381 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | |
382 | 394 |
383 fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str( ), fRadius, imgInc); | 395 const char* dir; |
384 fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width() ); | 396 switch (fDirection) { |
397 case Gr1DKernelEffect::kX_Direction: | |
398 dir = "x"; | |
399 break; | |
400 case Gr1DKernelEffect::kY_Direction: | |
401 dir = "y"; | |
402 break; | |
403 default: | |
404 SkFAIL("Unknown filter direction."); | |
405 dir = ""; // suppress warning | |
406 } | |
407 | |
408 // vec2 coord = coord2D; | |
409 fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); | |
410 // coord.x -= radius * pixelSize; | |
411 fsBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, fRadius, pixelS izeInc); | |
412 if (fUseBounds) { | |
413 // highBound = min(highBound, coord.x + (width-1) * pixelSize); | |
414 fsBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %d * %s);", | |
415 bounds, dir, width() - 1, pixelSizeInc); | |
416 // coord.x = max(lowBound, coord.x); | |
417 fsBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, bound s, dir); | |
418 } | |
419 fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width()); | |
385 fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor) ; | 420 fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor) ; |
386 fsBuilder->appendTextureLookup(samplers[0], "coord"); | 421 fsBuilder->appendTextureLookup(samplers[0], "coord"); |
387 fsBuilder->codeAppend(");\n"); | 422 fsBuilder->codeAppend(");\n"); |
388 fsBuilder->codeAppendf("\t\t\tcoord += %s;\n", imgInc); | 423 // coord.x += pixelSize; |
424 fsBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc); | |
425 if (fUseBounds) { | |
426 // coord.x = min(highBound, coord.x); | |
427 fsBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir , dir); | |
428 } | |
389 fsBuilder->codeAppend("\t\t}\n"); | 429 fsBuilder->codeAppend("\t\t}\n"); |
390 SkString modulate; | 430 SkString modulate; |
391 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); | 431 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); |
392 fsBuilder->codeAppend(modulate.c_str()); | 432 fsBuilder->codeAppend(modulate.c_str()); |
393 } | 433 } |
394 | 434 |
395 void GrGLMorphologyEffect::GenKey(const GrProcessor& proc, | 435 void GrGLMorphologyEffect::GenKey(const GrProcessor& proc, |
396 const GrGLCaps&, GrProcessorKeyBuilder* b) { | 436 const GrGLCaps&, GrProcessorKeyBuilder* b) { |
397 const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>(); | 437 const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>(); |
398 uint32_t key = static_cast<uint32_t>(m.radius()); | 438 uint32_t key = static_cast<uint32_t>(m.radius()); |
399 key |= (m.type() << 8); | 439 key |= (m.type() << 8); |
440 key |= (m.direction() << 9); | |
441 if (m.useBounds()) key |= 1 << 10; | |
400 b->add32(key); | 442 b->add32(key); |
401 } | 443 } |
402 | 444 |
403 void GrGLMorphologyEffect::setData(const GrGLProgramDataManager& pdman, | 445 void GrGLMorphologyEffect::setData(const GrGLProgramDataManager& pdman, |
404 const GrProcessor& proc) { | 446 const GrProcessor& proc) { |
405 const Gr1DKernelEffect& kern = proc.cast<Gr1DKernelEffect>(); | 447 const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>(); |
406 GrTexture& texture = *kern.texture(0); | 448 GrTexture& texture = *m.texture(0); |
407 // the code we generated was for a specific kernel radius | 449 // the code we generated was for a specific kernel radius, direction and bou nd usage |
408 SkASSERT(kern.radius() == fRadius); | 450 SkASSERT(m.radius() == fRadius); |
409 float imageIncrement[2] = { 0 }; | 451 SkASSERT(m.direction() == fDirection); |
410 switch (kern.direction()) { | 452 SkASSERT(m.useBounds() == fUseBounds); |
453 | |
454 float pixelSize = 0.0f; | |
455 switch (fDirection) { | |
411 case Gr1DKernelEffect::kX_Direction: | 456 case Gr1DKernelEffect::kX_Direction: |
412 imageIncrement[0] = 1.0f / texture.width(); | 457 pixelSize = 1.0f / texture.width(); |
413 break; | 458 break; |
414 case Gr1DKernelEffect::kY_Direction: | 459 case Gr1DKernelEffect::kY_Direction: |
415 imageIncrement[1] = 1.0f / texture.height(); | 460 pixelSize = 1.0f / texture.height(); |
416 break; | 461 break; |
417 default: | 462 default: |
418 SkFAIL("Unknown filter direction."); | 463 SkFAIL("Unknown filter direction."); |
419 } | 464 } |
420 pdman.set2fv(fImageIncrementUni, 1, imageIncrement); | 465 pdman.set1f(fPixelSizeUni, pixelSize); |
466 | |
467 if (fUseBounds) { | |
468 const float* bounds = m.bounds(); | |
469 if (fDirection && texture.origin() == kBottomLeft_GrSurfaceOrigin) { | |
470 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]); | |
471 } else { | |
472 pdman.set2f(fBoundsUni, bounds[0], bounds[1]); | |
473 } | |
474 } | |
421 } | 475 } |
422 | 476 |
423 /////////////////////////////////////////////////////////////////////////////// | 477 /////////////////////////////////////////////////////////////////////////////// |
424 | 478 |
425 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, | 479 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, |
426 Direction direction, | 480 Direction direction, |
427 int radius, | 481 int radius, |
482 bool useBounds, | |
483 float bounds[2], | |
428 MorphologyType type) | 484 MorphologyType type) |
429 : Gr1DKernelEffect(texture, direction, radius) | 485 : Gr1DKernelEffect(texture, direction, radius) |
430 , fType(type) { | 486 , fType(type), fUseBounds(useBounds) { |
487 fBounds[0] = bounds[0]; | |
488 fBounds[1] = bounds[1]; | |
431 } | 489 } |
432 | 490 |
433 GrMorphologyEffect::~GrMorphologyEffect() { | 491 GrMorphologyEffect::~GrMorphologyEffect() { |
434 } | 492 } |
435 | 493 |
436 const GrBackendFragmentProcessorFactory& GrMorphologyEffect::getFactory() const { | 494 const GrBackendFragmentProcessorFactory& GrMorphologyEffect::getFactory() const { |
437 return GrTBackendFragmentProcessorFactory<GrMorphologyEffect>::getInstance() ; | 495 return GrTBackendFragmentProcessorFactory<GrMorphologyEffect>::getInstance() ; |
438 } | 496 } |
439 | 497 |
440 bool GrMorphologyEffect::onIsEqual(const GrFragmentProcessor& sBase) const { | 498 bool GrMorphologyEffect::onIsEqual(const GrFragmentProcessor& sBase) const { |
441 const GrMorphologyEffect& s = sBase.cast<GrMorphologyEffect>(); | 499 const GrMorphologyEffect& s = sBase.cast<GrMorphologyEffect>(); |
442 return (this->radius() == s.radius() && | 500 return (this->radius() == s.radius() && |
443 this->direction() == s.direction() && | 501 this->direction() == s.direction() && |
502 this->useBounds() == s.useBounds() && | |
444 this->type() == s.type()); | 503 this->type() == s.type()); |
445 } | 504 } |
446 | 505 |
447 void GrMorphologyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) cons t { | 506 void GrMorphologyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) cons t { |
448 // This is valid because the color components of the result of the kernel al l come | 507 // This is valid because the color components of the result of the kernel al l come |
449 // exactly from existing values in the source texture. | 508 // exactly from existing values in the source texture. |
450 this->updateInvariantOutputForModulation(inout); | 509 this->updateInvariantOutputForModulation(inout); |
451 } | 510 } |
452 | 511 |
453 /////////////////////////////////////////////////////////////////////////////// | 512 /////////////////////////////////////////////////////////////////////////////// |
454 | 513 |
455 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMorphologyEffect); | 514 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMorphologyEffect); |
456 | 515 |
516 static float unusedBounds[2] = {0.0f, 0.0f}; | |
517 | |
457 GrFragmentProcessor* GrMorphologyEffect::TestCreate(SkRandom* random, | 518 GrFragmentProcessor* GrMorphologyEffect::TestCreate(SkRandom* random, |
458 GrContext*, | 519 GrContext*, |
459 const GrDrawTargetCaps&, | 520 const GrDrawTargetCaps&, |
460 GrTexture* textures[]) { | 521 GrTexture* textures[]) { |
461 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : | 522 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : |
462 GrProcessorUnitTest::kAlphaTextureIdx; | 523 GrProcessorUnitTest::kAlphaTextureIdx; |
463 Direction dir = random->nextBool() ? kX_Direction : kY_Direction; | 524 Direction dir = random->nextBool() ? kX_Direction : kY_Direction; |
464 static const int kMaxRadius = 10; | 525 static const int kMaxRadius = 10; |
465 int radius = random->nextRangeU(1, kMaxRadius); | 526 int radius = random->nextRangeU(1, kMaxRadius); |
466 MorphologyType type = random->nextBool() ? GrMorphologyEffect::kErode_Morpho logyType : | 527 MorphologyType type = random->nextBool() ? GrMorphologyEffect::kErode_Morpho logyType : |
467 GrMorphologyEffect::kDilate_Morph ologyType; | 528 GrMorphologyEffect::kDilate_Morph ologyType; |
468 | 529 |
469 return GrMorphologyEffect::Create(textures[texIdx], dir, radius, type); | 530 return GrMorphologyEffect::Create(textures[texIdx], dir, radius, false, unus edBounds, type); |
470 } | 531 } |
471 | 532 |
472 namespace { | 533 namespace { |
473 | 534 |
535 | |
536 void apply_morphology_rect(GrContext* context, | |
537 GrTexture* texture, | |
538 const SkIRect& srcRect, | |
539 const SkIRect& dstRect, | |
540 int radius, | |
541 GrMorphologyEffect::MorphologyType morphType, | |
542 bool useBounds, | |
543 float bounds[2], | |
544 Gr1DKernelEffect::Direction direction) { | |
545 GrPaint paint; | |
546 paint.addColorProcessor(GrMorphologyEffect::Create(texture, | |
547 direction, | |
548 radius, | |
549 useBounds, | |
550 bounds, | |
551 morphType))->unref(); | |
552 context->drawRectToRect(paint, SkRect::Make(dstRect), SkRect::Make(srcRect)) ; | |
553 } | |
554 | |
474 void apply_morphology_pass(GrContext* context, | 555 void apply_morphology_pass(GrContext* context, |
475 GrTexture* texture, | 556 GrTexture* texture, |
476 const SkIRect& srcRect, | 557 const SkIRect& srcRect, |
477 const SkIRect& dstRect, | 558 const SkIRect& dstRect, |
478 int radius, | 559 int radius, |
479 GrMorphologyEffect::MorphologyType morphType, | 560 GrMorphologyEffect::MorphologyType morphType, |
480 Gr1DKernelEffect::Direction direction) { | 561 Gr1DKernelEffect::Direction direction) { |
481 GrPaint paint; | 562 float bounds[2] = { 0.0f, 1.0f }; |
482 paint.addColorProcessor(GrMorphologyEffect::Create(texture, | 563 SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; |
483 direction, | 564 SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; |
484 radius, | 565 SkIRect upperSrcRect = srcRect, upperDstRect = dstRect; |
485 morphType))->unref(); | 566 if (direction == Gr1DKernelEffect::kX_Direction) { |
486 context->drawRectToRect(paint, SkRect::Make(dstRect), SkRect::Make(srcRect)) ; | 567 bounds[0] = (SkIntToScalar(srcRect.left()) + 0.5f) / texture->width(); |
568 bounds[1] = (SkIntToScalar(srcRect.right()) - 0.5f) / texture->width(); | |
569 lowerSrcRect.fRight = srcRect.left() + radius; | |
570 lowerDstRect.fRight = dstRect.left() + radius; | |
571 upperSrcRect.fLeft = srcRect.right() - radius; | |
572 upperDstRect.fLeft = dstRect.right() - radius; | |
573 middleSrcRect.inset(radius, 0); | |
574 middleDstRect.inset(radius, 0); | |
575 } else { | |
576 bounds[0] = (SkIntToScalar(srcRect.top()) + 0.5f) / texture->height(); | |
577 bounds[1] = (SkIntToScalar(srcRect.bottom()) - 0.5f) / texture->height() ; | |
578 lowerSrcRect.fBottom = srcRect.top() + radius; | |
579 lowerDstRect.fBottom = dstRect.top() + radius; | |
580 upperSrcRect.fTop = srcRect.bottom() - radius; | |
581 upperDstRect.fTop = dstRect.bottom() - radius; | |
582 middleSrcRect.inset(0, radius); | |
583 middleDstRect.inset(0, radius); | |
584 } | |
585 if (middleSrcRect.fLeft - middleSrcRect.fRight >= 0) { | |
586 // radius covers srcRect; use bounds over entire draw | |
587 apply_morphology_rect(context, texture, srcRect, dstRect, radius, | |
588 morphType, true, bounds, direction); | |
589 } else { | |
590 // Draw upper and lower margins with bounds; middle without. | |
591 apply_morphology_rect(context, texture, lowerSrcRect, lowerDstRect, radi us, | |
592 morphType, true, bounds, direction); | |
593 apply_morphology_rect(context, texture, upperSrcRect, upperDstRect, radi us, | |
594 morphType, true, bounds, direction); | |
595 apply_morphology_rect(context, texture, middleSrcRect, middleDstRect, ra dius, | |
596 morphType, false, bounds, direction); | |
597 } | |
487 } | 598 } |
488 | 599 |
489 bool apply_morphology(const SkBitmap& input, | 600 bool apply_morphology(const SkBitmap& input, |
490 const SkIRect& rect, | 601 const SkIRect& rect, |
491 GrMorphologyEffect::MorphologyType morphType, | 602 GrMorphologyEffect::MorphologyType morphType, |
492 SkISize radius, | 603 SkISize radius, |
493 SkBitmap* dst) { | 604 SkBitmap* dst) { |
494 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); | 605 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); |
495 SkASSERT(srcTexture); | 606 SkASSERT(srcTexture); |
496 GrContext* context = srcTexture->getContext(); | 607 GrContext* context = srcTexture->getContext(); |
(...skipping 13 matching lines...) Expand all Loading... | |
510 SkIRect srcRect = rect; | 621 SkIRect srcRect = rect; |
511 | 622 |
512 if (radius.fWidth > 0) { | 623 if (radius.fWidth > 0) { |
513 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox _ScratchTexMatch); | 624 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox _ScratchTexMatch); |
514 if (NULL == texture) { | 625 if (NULL == texture) { |
515 return false; | 626 return false; |
516 } | 627 } |
517 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); | 628 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); |
518 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fWid th, | 629 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fWid th, |
519 morphType, Gr1DKernelEffect::kX_Direction); | 630 morphType, Gr1DKernelEffect::kX_Direction); |
520 SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, | 631 /*SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, |
Justin Novosad
2014/12/22 20:11:11
Don't commit commented code
cwallez
2015/01/19 21:34:39
Done.
| |
521 dstRect.width(), radius.fHeight); | 632 dstRect.width(), radius.fHeight); |
522 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT ype ? | 633 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT ype ? |
523 SK_ColorWHITE : | 634 SK_ColorWHITE : |
524 SK_ColorTRANSPARENT; | 635 SK_ColorTRANSPARENT; |
525 context->clear(&clearRect, clearColor, false, texture->asRenderTarget()) ; | 636 context->clear(&clearRect, clearColor, false, texture->asRenderTarget()) ;*/ |
526 srcTexture.reset(texture); | 637 srcTexture.reset(texture); |
527 srcRect = dstRect; | 638 srcRect = dstRect; |
528 } | 639 } |
529 if (radius.fHeight > 0) { | 640 if (radius.fHeight > 0) { |
530 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox _ScratchTexMatch); | 641 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox _ScratchTexMatch); |
531 if (NULL == texture) { | 642 if (NULL == texture) { |
532 return false; | 643 return false; |
533 } | 644 } |
534 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); | 645 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); |
535 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fHei ght, | 646 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fHei ght, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
590 SkBitmap* result, SkIPoint* offset) con st { | 701 SkBitmap* result, SkIPoint* offset) con st { |
591 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); | 702 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); |
592 } | 703 } |
593 | 704 |
594 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, | 705 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
595 SkBitmap* result, SkIPoint* offset) cons t { | 706 SkBitmap* result, SkIPoint* offset) cons t { |
596 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); | 707 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); |
597 } | 708 } |
598 | 709 |
599 #endif | 710 #endif |
OLD | NEW |