2012-09-18 20:32:34 +00:00
/*
* Copyright 2012 Google Inc .
*
* Use of this source code is governed by a BSD - style license that can be
* found in the LICENSE file .
*/
2019-04-23 17:05:21 +00:00
# include "gm/gm.h"
2019-05-01 21:28:53 +00:00
# include "include/core/SkBitmap.h"
# include "include/core/SkCanvas.h"
2019-04-23 17:05:21 +00:00
# include "include/core/SkColor.h"
2019-05-01 21:28:53 +00:00
# include "include/core/SkFont.h"
# include "include/core/SkImageFilter.h"
# include "include/core/SkPaint.h"
# include "include/core/SkPoint.h"
# include "include/core/SkRect.h"
# include "include/core/SkScalar.h"
# include "include/core/SkShader.h"
# include "include/core/SkSize.h"
# include "include/core/SkString.h"
# include "include/core/SkTileMode.h"
# include "include/core/SkTypeface.h"
2019-04-23 17:05:21 +00:00
# include "include/effects/SkGradientShader.h"
2019-08-02 19:21:23 +00:00
# include "include/effects/SkImageFilters.h"
2019-04-23 17:05:21 +00:00
# include "tools/ToolUtils.h"
2012-09-18 20:32:34 +00:00
2020-01-15 05:02:37 +00:00
# include <vector>
2012-09-18 20:32:34 +00:00
namespace skiagm {
2020-01-15 05:02:37 +00:00
enum KernelFixture {
kBasic_KernelFixture ,
kLarge_KernelFixture
} ;
2012-09-18 20:32:34 +00:00
class MatrixConvolutionGM : public GM {
public :
2020-01-15 05:02:37 +00:00
MatrixConvolutionGM ( SkColor colorOne , SkColor colorTwo , KernelFixture kernelFixture , const char * nameSuffix )
: fNameSuffix ( nameSuffix ) ,
fKernelFixture ( kernelFixture ) {
2012-09-18 20:32:34 +00:00
this - > setBGColor ( 0x00000000 ) ;
2016-12-27 16:04:12 +00:00
fColors [ 0 ] = colorOne ;
fColors [ 1 ] = colorTwo ;
2012-09-18 20:32:34 +00:00
}
protected :
2014-04-30 13:20:45 +00:00
2015-09-03 20:32:33 +00:00
SkString onShortName ( ) override {
2016-12-27 16:04:12 +00:00
return SkStringPrintf ( " matrixconvolution%s " , fNameSuffix ) ;
2012-09-18 20:32:34 +00:00
}
2015-09-03 20:32:33 +00:00
void makeBitmap ( ) {
2016-12-27 16:04:12 +00:00
// Draw our bitmap in N32, so legacy devices get "premul" values they understand
2018-07-10 19:50:11 +00:00
fBitmap . allocN32Pixels ( 80 , 80 ) ;
SkCanvas canvas ( fBitmap ) ;
2012-09-18 20:32:34 +00:00
canvas . clear ( 0x00000000 ) ;
SkPaint paint ;
paint . setColor ( 0xFFFFFFFF ) ;
2019-01-08 14:38:02 +00:00
SkPoint pts [ 2 ] = { { 0 , 0 } ,
{ 0 , 80.0f } } ;
SkScalar pos [ 2 ] = { 0 , 80.0f } ;
2016-03-13 21:13:58 +00:00
paint . setShader ( SkGradientShader : : MakeLinear (
2019-04-03 14:27:45 +00:00
pts , fColors , pos , 2 , SkTileMode : : kClamp ) ) ;
2019-03-20 16:12:10 +00:00
SkFont font ( ToolUtils : : create_portable_typeface ( ) , 180.0f ) ;
2019-01-08 14:38:02 +00:00
canvas . drawString ( " e " , - 10.0f , 80.0f , font , paint ) ;
2012-09-18 20:32:34 +00:00
}
2015-09-03 20:32:33 +00:00
SkISize onISize ( ) override {
2014-06-10 06:59:03 +00:00
return SkISize : : Make ( 500 , 300 ) ;
2012-09-18 20:32:34 +00:00
}
2020-01-15 05:02:37 +00:00
sk_sp < SkImageFilter > makeFilter ( const SkIPoint & kernelOffset , SkTileMode tileMode ,
bool convolveAlpha , const SkIRect * cropRect = nullptr ) {
switch ( fKernelFixture ) {
case kBasic_KernelFixture : {
// All 1s except center value, which is -7 (sum of 1).
std : : vector < SkScalar > kernel ( 9 , SkIntToScalar ( 1 ) ) ;
kernel [ 4 ] = SkIntToScalar ( - 7 ) ;
return SkImageFilters : : MatrixConvolution ( { 3 , 3 } , kernel . data ( ) , /* gain */ 0.3f , /* bias */ SkIntToScalar ( 100 ) , kernelOffset , tileMode , convolveAlpha , nullptr , cropRect ) ;
}
case kLarge_KernelFixture : {
2020-05-05 01:27:57 +00:00
// Intentionally go over the MAX_KERNEL_SIZE limit and trigger CPU fallback.
2020-01-15 05:02:37 +00:00
// All 1s except center value, which is -47 (sum of 1).
std : : vector < SkScalar > kernel ( 49 , SkIntToScalar ( 1 ) ) ;
kernel [ 24 ] = SkIntToScalar ( - 47 ) ;
return SkImageFilters : : MatrixConvolution ( { 7 , 7 } , kernel . data ( ) , /* gain */ 0.3f , /* bias */ SkIntToScalar ( 100 ) , kernelOffset , tileMode , convolveAlpha , nullptr , cropRect ) ;
}
default :
return nullptr ;
}
}
2014-03-12 16:36:08 +00:00
void draw ( SkCanvas * canvas , int x , int y , const SkIPoint & kernelOffset ,
2019-08-02 19:21:23 +00:00
SkTileMode tileMode , bool convolveAlpha ,
const SkIRect * cropRect = nullptr ) {
2012-09-18 20:32:34 +00:00
SkPaint paint ;
2020-01-15 05:02:37 +00:00
paint . setImageFilter ( this - > makeFilter ( kernelOffset , tileMode , convolveAlpha , cropRect ) ) ;
2013-01-14 16:27:50 +00:00
canvas - > save ( ) ;
2013-10-18 20:08:14 +00:00
canvas - > translate ( SkIntToScalar ( x ) , SkIntToScalar ( y ) ) ;
2018-05-17 15:17:39 +00:00
const SkRect layerBounds = SkRect : : MakeIWH ( fBitmap . width ( ) , fBitmap . height ( ) ) ;
canvas - > clipRect ( layerBounds ) ;
// This GM is, in part, intended to display the wrapping behavior of the
// matrix image filter. The only (rational) way to achieve that for repeat mode
// is to create a tight layer.
canvas - > saveLayer ( layerBounds , & paint ) ;
canvas - > drawBitmap ( fBitmap , 0 , 0 , nullptr ) ;
canvas - > restore ( ) ;
2013-01-14 16:27:50 +00:00
canvas - > restore ( ) ;
2012-09-18 20:32:34 +00:00
}
2015-09-03 20:32:33 +00:00
void onOnceBeforeDraw ( ) override {
this - > makeBitmap ( ) ;
}
void onDraw ( SkCanvas * canvas ) override {
2015-04-09 18:13:24 +00:00
canvas - > clear ( SK_ColorBLACK ) ;
2014-03-12 16:36:08 +00:00
SkIPoint kernelOffset = SkIPoint : : Make ( 1 , 0 ) ;
2019-08-02 19:21:23 +00:00
SkIRect rect = fBitmap . bounds ( ) ;
2012-10-04 17:18:20 +00:00
for ( int x = 10 ; x < 310 ; x + = 100 ) {
2019-08-02 19:21:23 +00:00
this - > draw ( canvas , x , 10 , kernelOffset , SkTileMode : : kClamp , true , & rect ) ;
this - > draw ( canvas , x , 110 , kernelOffset , SkTileMode : : kDecal , true , & rect ) ;
this - > draw ( canvas , x , 210 , kernelOffset , SkTileMode : : kRepeat , true , & rect ) ;
2014-03-12 16:36:08 +00:00
kernelOffset . fY + + ;
2012-09-18 20:32:34 +00:00
}
2014-03-12 16:36:08 +00:00
kernelOffset . fY = 1 ;
2019-08-02 19:21:23 +00:00
SkIRect smallRect = SkIRect : : MakeXYWH ( 10 , 5 , 60 , 60 ) ;
this - > draw ( canvas , 310 , 10 , kernelOffset , SkTileMode : : kClamp , true , & smallRect ) ;
this - > draw ( canvas , 310 , 110 , kernelOffset , SkTileMode : : kDecal , true , & smallRect ) ;
this - > draw ( canvas , 310 , 210 , kernelOffset , SkTileMode : : kRepeat , true , & smallRect ) ;
this - > draw ( canvas , 410 , 10 , kernelOffset , SkTileMode : : kClamp , false , & rect ) ;
this - > draw ( canvas , 410 , 110 , kernelOffset , SkTileMode : : kDecal , false , & rect ) ;
this - > draw ( canvas , 410 , 210 , kernelOffset , SkTileMode : : kRepeat , false , & rect ) ;
2012-09-18 20:32:34 +00:00
}
private :
SkBitmap fBitmap ;
2016-12-27 16:04:12 +00:00
SkColor fColors [ 2 ] ;
const char * fNameSuffix ;
2020-01-15 05:02:37 +00:00
KernelFixture fKernelFixture ;
2015-09-03 20:32:33 +00:00
typedef GM INHERITED ;
2012-09-18 20:32:34 +00:00
} ;
//////////////////////////////////////////////////////////////////////////////
2020-01-15 05:02:37 +00:00
DEF_GM ( return new MatrixConvolutionGM ( 0xFFFFFFFF , 0x40404040 , KernelFixture : : kBasic_KernelFixture , " " ) ; )
DEF_GM ( return new MatrixConvolutionGM ( 0xFFFF0000 , 0xFF00FF00 , KernelFixture : : kBasic_KernelFixture , " _color " ) ; )
DEF_GM ( return new MatrixConvolutionGM ( 0xFFFFFFFF , 0x40404040 , KernelFixture : : kLarge_KernelFixture , " _big " ) ; )
DEF_GM ( return new MatrixConvolutionGM ( 0xFFFF0000 , 0xFF00FF00 , KernelFixture : : kLarge_KernelFixture , " _big_color " ) ; )
2012-09-18 20:32:34 +00:00
}