1 /* 2 * Copyright 2011 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/SkFont.h" 12 #include "include/core/SkFontStyle.h" 13 #include "include/core/SkFontTypes.h" 14 #include "include/core/SkMatrix.h" 15 #include "include/core/SkPaint.h" 16 #include "include/core/SkPoint.h" 17 #include "include/core/SkRect.h" 18 #include "include/core/SkScalar.h" 19 #include "include/core/SkString.h" 20 #include "include/core/SkTypeface.h" 21 #include "include/core/SkTypes.h" 22 #include "include/private/base/SkTemplates.h" 23 #include "include/private/base/SkTo.h" 24 #include "src/core/SkMatrixPriv.h" 25 #include "tools/ToolUtils.h" 26 #include "tools/fonts/FontToolUtils.h" 27 28 #include <string.h> 29 30 class PerspTextGM : public skiagm::GM { 31 public: PerspTextGM(bool minimal)32 PerspTextGM(bool minimal) : fMinimal(minimal) { 33 this->setBGColor(0xFFFFFFFF); 34 } 35 36 protected: getName() const37 SkString getName() const override { 38 return SkString(fMinimal ? "persptext_minimal" : "persptext"); 39 } 40 getISize()41 SkISize getISize() override { return SkISize::Make(1024, 768); } 42 43 // #define TEST_PERSP_CHECK 44 onDraw(SkCanvas * canvas)45 void onDraw(SkCanvas* canvas) override { 46 47 canvas->clear(0xffffffff); 48 49 SkPaint paint; 50 paint.setAntiAlias(true); 51 52 SkFont font(ToolUtils::CreatePortableTypeface("serif", SkFontStyle())); 53 font.setSubpixel(true); 54 font.setSize(32); 55 font.setBaselineSnap(false); 56 57 const char* text = "Hamburgefons"; 58 const size_t textLen = strlen(text); 59 60 SkScalar textWidth = font.measureText(text, textLen, SkTextEncoding::kUTF8, 61 nullptr, nullptr); 62 SkScalar textHeight = font.getMetrics(nullptr); 63 64 SkScalar x = 10, y = textHeight + 5.f; 65 const int kSteps = 8; 66 float kMinimalFactor = fMinimal ? 32.f : 1.f; 67 for (auto pm : {PerspMode::kX, PerspMode::kY, PerspMode::kXY}) { 68 for (int i = 0; i < kSteps; ++i) { 69 canvas->save(); 70 #ifdef TEST_PERSP_CHECK 71 // draw non-perspective text in the background for comparison 72 paint.setColor(SK_ColorRED); 73 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); 74 #endif 75 76 SkMatrix persp = SkMatrix::I(); 77 switch (pm) { 78 case PerspMode::kX: 79 if (fMinimal) { 80 persp.setPerspX(i*0.0005f/kSteps/kMinimalFactor); 81 } else { 82 persp.setPerspX(i*0.00025f/kSteps); 83 } 84 break; 85 case PerspMode::kY: 86 persp.setPerspY(i*0.0025f/kSteps/kMinimalFactor); 87 break; 88 case PerspMode::kXY: 89 persp.setPerspX(i*-0.00025f/kSteps/kMinimalFactor); 90 persp.setPerspY(i*-0.00125f/kSteps/kMinimalFactor); 91 break; 92 } 93 persp = SkMatrix::Concat(persp, SkMatrix::Translate(-x, -y)); 94 persp = SkMatrix::Concat(SkMatrix::Translate(x, y), persp); 95 canvas->concat(persp); 96 97 paint.setColor(SK_ColorBLACK); 98 #ifdef TEST_PERSP_CHECK 99 // Draw text as red if it is nearly affine 100 SkRect bounds = SkRect::MakeXYWH(0, -textHeight, textWidth, textHeight); 101 bounds.offset(x, y); 102 if (SkMatrixPriv::NearlyAffine(persp, bounds, SK_Scalar1/(1 << 4))) { 103 paint.setColor(SK_ColorRED); 104 } 105 #endif 106 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); 107 108 y += textHeight + 5.f; 109 canvas->restore(); 110 } 111 112 x += textWidth + 10.f; 113 y = textHeight + 5.f; 114 } 115 116 } 117 118 private: 119 enum class PerspMode { kX, kY, kXY }; 120 bool fMinimal; 121 }; 122 123 DEF_GM(return new PerspTextGM(true);) 124 DEF_GM(return new PerspTextGM(false);) 125