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#include "samplecode/Sample.h" 8 9#include "include/core/SkCanvas.h" 10#include "include/core/SkColorFilter.h" 11#include "include/core/SkColorPriv.h" 12#include "include/core/SkGraphics.h" 13#include "include/core/SkPath.h" 14#include "include/core/SkRegion.h" 15#include "include/core/SkShader.h" 16#include "include/core/SkStream.h" 17#include "include/core/SkTextBlob.h" 18#include "include/core/SkTime.h" 19#include "include/core/SkTypeface.h" 20#include "include/effects/SkGradientShader.h" 21#include "include/utils/SkRandom.h" 22#include "modules/skshaper/include/SkShaper.h" 23#include "src/core/SkOSFile.h" 24#include "src/shaders/SkColorShader.h" 25#include "src/utils/SkUTF.h" 26 27typedef std::unique_ptr<SkShaper> (*ShaperFactory)(); 28 29static const char gText[] = 30 "When in the Course of human events it becomes necessary for one people " 31 "to dissolve the political bands which have connected them with another " 32 "and to assume among the powers of the earth, the separate and equal " 33 "station to which the Laws of Nature and of Nature's God entitle them, " 34 "a decent respect to the opinions of mankind requires that they should " 35 "declare the causes which impel them to the separation."; 36 37class TextBoxView : public Sample { 38 SkString fName; 39public: 40 TextBoxView(ShaperFactory fact, const char suffix[]) : fShaper(fact()) { 41 fName.printf("TextBox_%s", suffix); 42 } 43 44protected: 45 SkString name() override { return fName; } 46 47 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) { 48 SkAutoCanvasRestore acr(canvas, true); 49 50 canvas->clipRect(SkRect::MakeWH(w, h)); 51 canvas->drawColor(bg); 52 53 SkScalar margin = 20; 54 55 SkPaint paint; 56 paint.setColor(fg); 57 58 for (int i = 9; i < 24; i += 2) { 59 SkShaper::PurgeCaches(); 60 SkTextBlobBuilderRunHandler builder(gText, { margin, margin }); 61 SkFont srcFont(nullptr, SkIntToScalar(i)); 62 srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias); 63 srcFont.setSubpixel(true); 64 65 const char* utf8 = gText; 66 size_t utf8Bytes = sizeof(gText) - 1; 67 68 std::unique_ptr<SkShaper::BiDiRunIterator> bidi( 69 SkShaper::MakeBiDiRunIterator(utf8, utf8Bytes, 0xfe)); 70 if (!bidi) { 71 return; 72 } 73 74 std::unique_ptr<SkShaper::LanguageRunIterator> language( 75 SkShaper::MakeStdLanguageRunIterator(utf8, utf8Bytes)); 76 if (!language) { 77 return; 78 } 79 80 SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y'); 81 std::unique_ptr<SkShaper::ScriptRunIterator> script( 82 SkShaper::MakeScriptRunIterator(utf8, utf8Bytes, undeterminedScript)); 83 if (!script) { 84 return; 85 } 86 87 std::unique_ptr<SkShaper::FontRunIterator> font( 88 SkShaper::MakeFontMgrRunIterator(utf8, utf8Bytes, srcFont, SkFontMgr::RefDefault(), 89 "Arial", SkFontStyle::Bold(), &*language)); 90 if (!font) { 91 return; 92 } 93 94 fShaper->shape(utf8, utf8Bytes, *font, *bidi, *script, *language, w - margin, &builder); 95 canvas->drawTextBlob(builder.makeBlob(), 0, 0, paint); 96 97 canvas->translate(0, builder.endPoint().y()); 98 } 99 } 100 101 void onDrawContent(SkCanvas* canvas) override { 102 SkScalar width = this->width() / 3; 103 drawTest(canvas, width, this->height(), SK_ColorBLACK, SK_ColorWHITE); 104 canvas->translate(width, 0); 105 drawTest(canvas, width, this->height(), SK_ColorWHITE, SK_ColorBLACK); 106 canvas->translate(width, 0); 107 drawTest(canvas, width, this->height()/2, SK_ColorGRAY, SK_ColorWHITE); 108 canvas->translate(0, this->height()/2); 109 drawTest(canvas, width, this->height()/2, SK_ColorGRAY, SK_ColorBLACK); 110 } 111 112private: 113 std::unique_ptr<SkShaper> fShaper; 114 using INHERITED = Sample; 115}; 116 117DEF_SAMPLE( return new TextBoxView([](){ return SkShaper::Make(); }, "default"); ); 118#ifdef SK_SHAPER_CORETEXT_AVAILABLE 119DEF_SAMPLE( return new TextBoxView(SkShaper::MakeCoreText, "coretext"); ); 120#endif 121 122class SampleShaper : public Sample { 123public: 124 SampleShaper() {} 125 126protected: 127 SkString name() override { return SkString("shaper"); } 128 129 void drawTest(SkCanvas* canvas, const char str[], SkScalar size, 130 std::unique_ptr<SkShaper> shaper) { 131 if (!shaper) return; 132 133 SkTextBlobBuilderRunHandler builder(str, {0, 0}); 134 SkFont srcFont; 135 srcFont.setSize(size); 136 srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias); 137 srcFont.setSubpixel(true); 138 139 size_t len = strlen(str); 140 141 std::unique_ptr<SkShaper::BiDiRunIterator> bidi( 142 SkShaper::MakeBiDiRunIterator(str, len, 0xfe)); 143 if (!bidi) { 144 return; 145 } 146 147 std::unique_ptr<SkShaper::LanguageRunIterator> language( 148 SkShaper::MakeStdLanguageRunIterator(str, len)); 149 if (!language) { 150 return; 151 } 152 153 SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y'); 154 std::unique_ptr<SkShaper::ScriptRunIterator> script( 155 SkShaper::MakeScriptRunIterator(str, len, undeterminedScript)); 156 if (!script) { 157 return; 158 } 159 160 std::unique_ptr<SkShaper::FontRunIterator> font( 161 SkShaper::MakeFontMgrRunIterator(str, len, srcFont, SkFontMgr::RefDefault(), 162 "Arial", SkFontStyle::Bold(), &*language)); 163 if (!font) { 164 return; 165 } 166 167 shaper->shape(str, len, *font, *bidi, *script, *language, 2000, &builder); 168 169 canvas->drawTextBlob(builder.makeBlob(), 0, 0, SkPaint()); 170 } 171 172 void onDrawContent(SkCanvas* canvas) override { 173 canvas->translate(10, 30); 174 175 const char text[] = "world"; 176 177 for (SkScalar size = 30; size <= 30; size += 10) { 178 this->drawTest(canvas, text, size, SkShaper::Make()); 179 canvas->translate(0, size + 5); 180 #ifdef SK_SHAPER_CORETEXT_AVAILABLE 181 this->drawTest(canvas, text, size, SkShaper::MakeCoreText()); 182 #endif 183 canvas->translate(0, size*2); 184 } 185 } 186 187private: 188 using INHERITED = Sample; 189}; 190DEF_SAMPLE( return new SampleShaper; ); 191