1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "gm/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkColor.h" 11 #include "include/core/SkImage.h" 12 #include "include/core/SkPaint.h" 13 #include "include/core/SkRRect.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkSize.h" 16 #include "include/core/SkString.h" 17 #include "include/core/SkSurface.h" 18 #include "include/core/SkTypes.h" 19 20 namespace skiagm { 21 22 // Draw various width thin rects at 1/8 horizontal pixel increments 23 class ThinRectsGM : public GM { 24 public: ThinRectsGM(bool round)25 ThinRectsGM(bool round) : fRound(round) { 26 this->setBGColor(0xFF000000); 27 } 28 29 protected: getName() const30 SkString getName() const override { return SkString(fRound ? "thinroundrects" : "thinrects"); } 31 getISize()32 SkISize getISize() override { return SkISize::Make(240, 320); } 33 onDraw(SkCanvas * canvas)34 void onDraw(SkCanvas* canvas) override { 35 36 SkPaint white; 37 white.setColor(SK_ColorWHITE); 38 white.setAntiAlias(true); 39 40 SkPaint green; 41 green.setColor(SK_ColorGREEN); 42 green.setAntiAlias(true); 43 44 for (int i = 0; i < 8; ++i) { 45 canvas->save(); 46 canvas->translate(i*0.125f, i*40.0f); 47 this->drawVertRects(canvas, white); 48 49 canvas->translate(40.0f, 0.0f); 50 this->drawVertRects(canvas, green); 51 canvas->restore(); 52 53 canvas->save(); 54 canvas->translate(80.0f, i*40.0f + i*0.125f); 55 this->drawHorizRects(canvas, white); 56 57 canvas->translate(40.0f, 0.0f); 58 this->drawHorizRects(canvas, green); 59 canvas->restore(); 60 61 canvas->save(); 62 canvas->translate(160.0f + i*0.125f, 63 i*40.0f + i*0.125f); 64 this->drawSquares(canvas, white); 65 66 canvas->translate(40.0f, 0.0f); 67 this->drawSquares(canvas, green); 68 canvas->restore(); 69 } 70 } 71 72 private: drawVertRects(SkCanvas * canvas,const SkPaint & p)73 void drawVertRects(SkCanvas* canvas, const SkPaint& p) { 74 constexpr SkRect vertRects[] = { 75 { 1, 1, 5.0f, 21 }, // 4 pix wide 76 { 8, 1, 10.0f, 21 }, // 2 pix wide 77 { 13, 1, 14.0f, 21 }, // 1 pix wide 78 { 17, 1, 17.5f, 21 }, // 1/2 pix wide 79 { 21, 1, 21.25f, 21 }, // 1/4 pix wide 80 { 25, 1, 25.125f, 21 }, // 1/8 pix wide 81 { 29, 1, 29.0f, 21 } // 0 pix wide 82 }; 83 84 static constexpr SkVector radii[4] = {{1/32.f, 2/32.f}, {3/32.f, 1/32.f}, {2/32.f, 3/32.f}, 85 {1/32.f, 3/32.f}}; 86 SkRRect rrect; 87 for (size_t j = 0; j < std::size(vertRects); ++j) { 88 if (fRound) { 89 rrect.setRectRadii(vertRects[j], radii); 90 canvas->drawRRect(rrect, p); 91 } else { 92 canvas->drawRect(vertRects[j], p); 93 } 94 } 95 } 96 drawHorizRects(SkCanvas * canvas,const SkPaint & p)97 void drawHorizRects(SkCanvas* canvas, const SkPaint& p) { 98 constexpr SkRect horizRects[] = { 99 { 1, 1, 21, 5.0f }, // 4 pix high 100 { 1, 8, 21, 10.0f }, // 2 pix high 101 { 1, 13, 21, 14.0f }, // 1 pix high 102 { 1, 17, 21, 17.5f }, // 1/2 pix high 103 { 1, 21, 21, 21.25f }, // 1/4 pix high 104 { 1, 25, 21, 25.125f }, // 1/8 pix high 105 { 1, 29, 21, 29.0f } // 0 pix high 106 }; 107 108 SkRRect rrect; 109 for (size_t j = 0; j < std::size(horizRects); ++j) { 110 if (fRound) { 111 rrect.setNinePatch(horizRects[j], 1/32.f, 2/32.f, 3/32.f, 4/32.f); 112 canvas->drawRRect(rrect, p); 113 } else { 114 canvas->drawRect(horizRects[j], p); 115 } 116 } 117 } 118 drawSquares(SkCanvas * canvas,const SkPaint & p)119 void drawSquares(SkCanvas* canvas, const SkPaint& p) { 120 constexpr SkRect squares[] = { 121 { 1, 1, 5.0f, 5.0f }, // 4 pix 122 { 8, 8, 10.0f, 10.0f }, // 2 pix 123 { 13, 13, 14.0f, 14.0f }, // 1 pix 124 { 17, 17, 17.5f, 17.5f }, // 1/2 pix 125 { 21, 21, 21.25f, 21.25f }, // 1/4 pix 126 { 25, 25, 25.125f, 25.125f }, // 1/8 pix 127 { 29, 29, 29.0f, 29.0f } // 0 pix 128 }; 129 130 SkRRect rrect; 131 for (size_t j = 0; j < std::size(squares); ++j) { 132 if (fRound) { 133 rrect.setRectXY(squares[j], 1/32.f, 2/32.f); 134 canvas->drawRRect(rrect, p); 135 } else { 136 canvas->drawRect(squares[j], p); 137 } 138 } 139 } 140 141 const bool fRound; 142 143 using INHERITED = GM; 144 }; 145 146 ////////////////////////////////////////////////////////////////////////////// 147 148 DEF_GM( return new ThinRectsGM(false); ) 149 DEF_GM( return new ThinRectsGM(true); ) 150 151 } // namespace skiagm 152 153 DEF_SIMPLE_GM_CAN_FAIL(clipped_thinrect, canvas, errorMsg, 256, 256) { 154 auto zoomed = canvas->makeSurface(canvas->imageInfo().makeWH(10, 10)); 155 if (!zoomed) { 156 errorMsg->printf("makeSurface not supported"); 157 return skiagm::DrawResult::kSkip; 158 } 159 auto zoomedCanvas = zoomed->getCanvas(); 160 161 SkPaint p; 162 p.setColor(SK_ColorRED); 163 p.setAntiAlias(true); 164 p.setStyle(SkPaint::kFill_Style); 165 zoomedCanvas->save(); 166 zoomedCanvas->clipRect(SkRect::MakeXYWH(0, 5, 256, 10), true /*doAntialias*/); 167 zoomedCanvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 5.5), p); 168 zoomedCanvas->restore(); 169 170 // Zoom-in. Should see one line of red representing zoomed in 1/2px coverage and *not* 171 // two lines of varying coverage from hairline rendering. 172 auto img = zoomed->makeImageSnapshot(); 173 canvas->drawImageRect(img, SkRect::MakeXYWH(0, 10, 200, 200), SkSamplingOptions()); 174 return skiagm::DrawResult::kOk; 175 } 176