| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gm/gm.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkColor.h" |
| #include "include/core/SkFont.h" |
| #include "include/core/SkFontStyle.h" |
| #include "include/core/SkFontTypes.h" |
| #include "include/core/SkMatrix.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkScalar.h" |
| #include "include/core/SkString.h" |
| #include "include/core/SkTypeface.h" |
| #include "include/core/SkTypes.h" |
| #include "include/private/base/SkTemplates.h" |
| #include "include/private/base/SkTo.h" |
| #include "src/core/SkMatrixPriv.h" |
| #include "tools/ToolUtils.h" |
| |
| #include <string.h> |
| |
| class PerspTextGM : public skiagm::GM { |
| public: |
| PerspTextGM(bool minimal) : fMinimal(minimal) { |
| this->setBGColor(0xFFFFFFFF); |
| } |
| |
| protected: |
| |
| SkString onShortName() override { |
| return SkString(fMinimal ? "persptext_minimal" : "persptext"); |
| } |
| |
| SkISize onISize() override { |
| return SkISize::Make(1024, 768); |
| } |
| |
| //#define TEST_PERSP_CHECK |
| |
| void onDraw(SkCanvas* canvas) override { |
| |
| canvas->clear(0xffffffff); |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| |
| SkFont font(ToolUtils::create_portable_typeface("serif", SkFontStyle())); |
| font.setSubpixel(true); |
| font.setSize(32); |
| font.setBaselineSnap(false); |
| |
| const char* text = "Hamburgefons"; |
| const size_t textLen = strlen(text); |
| |
| SkScalar textWidth = font.measureText(text, textLen, SkTextEncoding::kUTF8, |
| nullptr, nullptr); |
| SkScalar textHeight = font.getMetrics(nullptr); |
| |
| SkScalar x = 10, y = textHeight + 5.f; |
| const int kSteps = 8; |
| float kMinimalFactor = fMinimal ? 32.f : 1.f; |
| for (auto pm : {PerspMode::kX, PerspMode::kY, PerspMode::kXY}) { |
| for (int i = 0; i < kSteps; ++i) { |
| canvas->save(); |
| #ifdef TEST_PERSP_CHECK |
| // draw non-perspective text in the background for comparison |
| paint.setColor(SK_ColorRED); |
| canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); |
| #endif |
| |
| SkMatrix persp = SkMatrix::I(); |
| switch (pm) { |
| case PerspMode::kX: |
| if (fMinimal) { |
| persp.setPerspX(i*0.0005f/kSteps/kMinimalFactor); |
| } else { |
| persp.setPerspX(i*0.00025f/kSteps); |
| } |
| break; |
| case PerspMode::kY: |
| persp.setPerspY(i*0.0025f/kSteps/kMinimalFactor); |
| break; |
| case PerspMode::kXY: |
| persp.setPerspX(i*-0.00025f/kSteps/kMinimalFactor); |
| persp.setPerspY(i*-0.00125f/kSteps/kMinimalFactor); |
| break; |
| } |
| persp = SkMatrix::Concat(persp, SkMatrix::Translate(-x, -y)); |
| persp = SkMatrix::Concat(SkMatrix::Translate(x, y), persp); |
| canvas->concat(persp); |
| |
| paint.setColor(SK_ColorBLACK); |
| #ifdef TEST_PERSP_CHECK |
| // Draw text as red if it is nearly affine |
| SkRect bounds = SkRect::MakeXYWH(0, -textHeight, textWidth, textHeight); |
| bounds.offset(x, y); |
| if (SkMatrixPriv::NearlyAffine(persp, bounds, SK_Scalar1/(1 << 4))) { |
| paint.setColor(SK_ColorRED); |
| } |
| #endif |
| canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); |
| |
| y += textHeight + 5.f; |
| canvas->restore(); |
| } |
| |
| x += textWidth + 10.f; |
| y = textHeight + 5.f; |
| } |
| |
| } |
| |
| private: |
| enum class PerspMode { kX, kY, kXY }; |
| bool fMinimal; |
| }; |
| |
| DEF_GM(return new PerspTextGM(true);) |
| DEF_GM(return new PerspTextGM(false);) |