| /* | |
| * Copyright 2013 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/SkFontTypes.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkRect.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkScalar.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/core/SkString.h" | |
| #include "include/core/SkTextBlob.h" | |
| #include "include/core/SkTypeface.h" | |
| #include "tools/Resources.h" | |
| #include "tools/ToolUtils.h" | |
| #include "tools/fonts/FontToolUtils.h" | |
| #include <string.h> | |
| namespace skiagm { | |
| static void draw_blob(SkCanvas* canvas, const SkTextBlob* blob, const SkPaint& skPaint, | |
| const SkRect& clipRect) { | |
| SkPaint clipHairline; | |
| clipHairline.setColor(SK_ColorWHITE); | |
| clipHairline.setStyle(SkPaint::kStroke_Style); | |
| SkPaint paint(skPaint); | |
| canvas->save(); | |
| canvas->drawRect(clipRect, clipHairline); | |
| paint.setAlphaf(0.125f); | |
| canvas->drawTextBlob(blob, 0, 0, paint); | |
| canvas->clipRect(clipRect); | |
| paint.setAlphaf(1.0f); | |
| canvas->drawTextBlob(blob, 0, 0, paint); | |
| canvas->restore(); | |
| } | |
| class MixedTextBlobsGM : public GM { | |
| public: | |
| MixedTextBlobsGM() { } | |
| protected: | |
| void onOnceBeforeDraw() override { | |
| fEmojiTypeface = ToolUtils::PlanetTypeface(); | |
| fEmojiText = "♁♃"; | |
| fReallyBigATypeface = ToolUtils::CreateTypefaceFromResource("fonts/ReallyBigA.ttf"); | |
| if (!fReallyBigATypeface) { | |
| fReallyBigATypeface = ToolUtils::DefaultPortableTypeface(); | |
| } | |
| SkTextBlobBuilder builder; | |
| // make textblob | |
| // Text so large we draw as paths | |
| SkFont font(ToolUtils::DefaultPortableTypeface(), 385); | |
| font.setEdging(SkFont::Edging::kAlias); | |
| const char* text = "O"; | |
| SkRect bounds; | |
| font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); | |
| SkScalar yOffset = bounds.height(); | |
| ToolUtils::add_to_text_blob(&builder, text, font, 10, yOffset); | |
| SkScalar corruptedAx = bounds.width(); | |
| SkScalar corruptedAy = yOffset; | |
| const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; | |
| const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; | |
| SkScalar xOffset = boundsHalfWidth; | |
| yOffset = boundsHalfHeight; | |
| // LCD | |
| font.setSize(32); | |
| font.setEdging(SkFont::Edging::kSubpixelAntiAlias); | |
| font.setSubpixel(true); | |
| text = "LCD!!!!!"; | |
| font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); | |
| ToolUtils::add_to_text_blob(&builder, | |
| text, | |
| font, | |
| xOffset - bounds.width() * 0.25f, | |
| yOffset - bounds.height() * 0.5f); | |
| // color emoji font with large glyph | |
| if (fEmojiTypeface) { | |
| font.setEdging(SkFont::Edging::kAlias); | |
| font.setSubpixel(false); | |
| font.setTypeface(fEmojiTypeface); | |
| font.measureText(fEmojiText, strlen(fEmojiText), SkTextEncoding::kUTF8, &bounds); | |
| ToolUtils::add_to_text_blob(&builder, fEmojiText, font, xOffset, yOffset); | |
| } | |
| // outline font with large glyph | |
| font.setSize(12); | |
| text = "aA"; | |
| font.setTypeface(fReallyBigATypeface); | |
| ToolUtils::add_to_text_blob(&builder, text, font, corruptedAx, corruptedAy); | |
| fBlob = builder.make(); | |
| } | |
| SkString getName() const override { return SkString("mixedtextblobs"); } | |
| SkISize getISize() override { return SkISize::Make(kWidth, kHeight); } | |
| void onDraw(SkCanvas* canvas) override { | |
| canvas->drawColor(SK_ColorGRAY); | |
| SkPaint paint; | |
| // setup work needed to draw text with different clips | |
| paint.setColor(SK_ColorBLACK); | |
| canvas->translate(10, 40); | |
| // compute the bounds of the text and setup some clips | |
| SkRect bounds = fBlob->bounds(); | |
| const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; | |
| const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; | |
| const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf; | |
| const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf; | |
| SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(), | |
| boundsHalfWidth, boundsHalfHeight); | |
| SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(), | |
| boundsHalfWidth, boundsHalfHeight); | |
| SkRect interiorClip = bounds; | |
| interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight); | |
| const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip}; | |
| size_t count = sizeof(clipRects) / sizeof(SkRect); | |
| for (size_t x = 0; x < count; ++x) { | |
| draw_blob(canvas, fBlob.get(), paint, clipRects[x]); | |
| if (x == (count >> 1) - 1) { | |
| canvas->translate(SkScalarFloorToScalar(bounds.width() + SkIntToScalar(25)), | |
| -(x * SkScalarFloorToScalar(bounds.height() + | |
| SkIntToScalar(25)))); | |
| } else { | |
| canvas->translate(0, SkScalarFloorToScalar(bounds.height() + SkIntToScalar(25))); | |
| } | |
| } | |
| } | |
| private: | |
| sk_sp<SkTypeface> fEmojiTypeface; | |
| sk_sp<SkTypeface> fReallyBigATypeface; | |
| const char* fEmojiText; | |
| sk_sp<SkTextBlob> fBlob; | |
| inline static constexpr int kWidth = 1250; | |
| inline static constexpr int kHeight = 700; | |
| using INHERITED = GM; | |
| }; | |
| ////////////////////////////////////////////////////////////////////////////// | |
| DEF_GM(return new MixedTextBlobsGM;) | |
| } // namespace skiagm |