1515#include  " include/core/SkPoint.h" 
1616#include  " include/core/SkRect.h" 
1717#include  " include/effects/SkDashPathEffect.h" 
18+ #include  " include/effects/SkGradientShader.h" 
1819#include  " include/effects/SkImageFilters.h" 
1920
2021#include  " src/core/SkImageFilterTypes.h" 
2122#include  " src/core/SkImageFilter_Base.h" 
23+ #include  " src/core/SkMatrixPriv.h" 
2224
2325#include  " tools/ToolUtils.h" 
2426
@@ -58,6 +60,17 @@ static float print_info(SkCanvas* canvas,
5860    return  y;
5961}
6062
63+ static  void  print_label (SkCanvas* canvas, float  x, float  y, float  value) {
64+     SkFont font (nullptr , 12 );
65+     SkPaint text;
66+     text.setAntiAlias (true );
67+ 
68+     SkString label;
69+     label.printf (" %.3f"  , value);
70+ 
71+     canvas->drawString (label, x, y + kLineHeight  / 2 .f , font, text);
72+ }
73+ 
6174static  SkPaint line_paint (SkColor color, bool  dashed = false ) {
6275    SkPaint paint;
6376    paint.setColor (color);
@@ -84,6 +97,71 @@ static SkPath create_axis_path(const SkRect& rect, float axisSpace) {
8497    return  localSpace;
8598}
8699
100+ static  const  SkColor4f kScaleGradientColors [] =
101+                 { { 0 .05f , 0 .0f , 6 .f ,  1 .f  },   //  Severe downscaling, s < 1/8, log(s) < -3
102+                   { 0 .6f ,  0 .6f , 0 .8f , 0 .6f  },  //  Okay downscaling,   s < 1/2, log(s) < -1
103+                   { 1 .f ,   1 .f ,  1 .f ,  0 .2f  },  //  No scaling,         s = 1,   log(s) = 0
104+                   { 0 .95f , 0 .6f , 0 .5f , 0 .6f  },  //  Okay upscaling,     s > 2,   log(s) > 1
105+                   { 0 .8f ,  0 .1f , 0 .f ,  1 .f  } }; //  Severe upscaling,   s > 8,   log(s) > 3
106+ static  const  SkScalar kLogScaleFactors [] = { -3 .f , -1 .f , 0 .f , 1 .f , 3 .f  };
107+ static  const  SkScalar kGradientStops [] = { 0 .f , 0 .33333f , 0 .5f , 0 .66667f , 1 .f  };
108+ static  const  int  kStopCount  = (int ) SK_ARRAY_COUNT(kScaleGradientColors );
109+ 
110+ static  void  draw_scale_key (SkCanvas* canvas, float  y) {
111+     SkRect key = SkRect::MakeXYWH (15 .f , y + 30 .f , 15 .f , 100 .f );
112+     SkPoint pts[] = {{key.centerX (), key.fTop }, {key.centerX (), key.fBottom }};
113+     sk_sp<SkShader> gradient = SkGradientShader::MakeLinear (
114+             pts, kScaleGradientColors , nullptr , kGradientStops , kStopCount , SkTileMode::kClamp ,
115+             SkGradientShader::kInterpolateColorsInPremul_Flag , nullptr );
116+     SkPaint keyPaint;
117+     keyPaint.setShader (gradient);
118+     canvas->drawRect (key, keyPaint);
119+     for  (int  i = 0 ; i < kStopCount ; ++i) {
120+         print_label (canvas, key.fRight  + 5 .f , key.fTop  + kGradientStops [i] * key.height (),
121+                     SkScalarPow (2 .f , kLogScaleFactors [i]));
122+     }
123+ }
124+ 
125+ static  void  draw_scale_factors (SkCanvas* canvas, const  skif::Mapping& mapping, const  SkRect& rect) {
126+     SkPoint testPoints[5 ];
127+     testPoints[0 ] = {rect.centerX (), rect.centerY ()};
128+     rect.toQuad (testPoints + 1 );
129+     for  (int  i = 0 ; i < 5 ; ++i) {
130+         float  scale = SkMatrixPriv::DifferentialScale (
131+                 mapping.deviceMatrix (),
132+                 SkPoint (mapping.paramToLayer (skif::ParameterSpace<SkPoint>(testPoints[i]))));
133+         SkColor4f color = {0 .f , 0 .f , 0 .f , 1 .f };
134+ 
135+         if  (SkScalarIsFinite (scale)) {
136+             float  logScale = SkScalarLog2 (scale);
137+             for  (int  j = 0 ; j <= kStopCount ; ++j) {
138+                 if  (j == kStopCount ) {
139+                     color = kScaleGradientColors [j - 1 ];
140+                     break ;
141+                 } else  if  (kLogScaleFactors [j] >= logScale) {
142+                     if  (j == 0 ) {
143+                         color = kScaleGradientColors [0 ];
144+                     } else  {
145+                         SkScalar t = (logScale - kLogScaleFactors [j - 1 ]) /
146+                                     (kLogScaleFactors [j] - kLogScaleFactors [j - 1 ]);
147+ 
148+                         SkColor4f a = kScaleGradientColors [j - 1 ] * (1 .f  - t);
149+                         SkColor4f b = kScaleGradientColors [j] * t;
150+                         color = {a.fR  + b.fR , a.fG  + b.fG , a.fB  + b.fB , a.fA  + b.fA };
151+                     }
152+                     break ;
153+                 }
154+             }
155+         }
156+ 
157+         SkPaint p;
158+         p.setAntiAlias (true );
159+         p.setColor4f (color, nullptr );
160+         canvas->drawRect (SkRect::MakeLTRB (testPoints[i].fX  - 4 .f , testPoints[i].fY  - 4 .f ,
161+                                           testPoints[i].fX  + 4 .f , testPoints[i].fY  + 4 .f ), p);
162+     }
163+ }
164+ 
87165class  FilterBoundsSample  : public  Sample  {
88166public: 
89167    FilterBoundsSample () {}
@@ -114,6 +192,9 @@ class FilterBoundsSample : public Sample {
114192        //  Add axis lines, to show perspective distortion
115193        canvas->drawPath (create_axis_path (localContentRect, 10 .f ), line_paint (SK_ColorGRAY));
116194
195+         //  Visualize scale factors at the four corners and center of the local rect
196+         draw_scale_factors (canvas, mapping, localContentRect);
197+ 
117198        //  The device content rect, e.g. the clip bounds if 'localContentRect' were used as a clip
118199        //  before the draw or saveLayer, representing what the filter must cover if it affects
119200        //  transparent black or doesn't have a local content hint.
@@ -146,10 +227,13 @@ class FilterBoundsSample : public Sample {
146227        canvas->drawRect (SkRect::Make (SkIRect (hintedOutputBounds)), line_paint (SK_ColorBLUE));
147228
148229        canvas->resetMatrix ();
149-         print_info (canvas, SkIRect (mapping.paramToLayer (contentBounds).roundOut ()),
230+         float  y =  print_info (canvas, SkIRect (mapping.paramToLayer (contentBounds).roundOut ()),
150231                           devContentRect.roundOut (),
151232                           SkIRect (hintedOutputBounds),
152233                           SkIRect (unhintedLayerBounds));
234+ 
235+         //  Draw color key for layer visualization
236+         draw_scale_key (canvas, y);
153237    }
154238
155239    SkString name () override  { return  SkString (" FilterBounds"  ); }
0 commit comments