diff options
-rw-r--r-- | gm/3dgm.cpp | 3 | ||||
-rw-r--r-- | gn/samples.gni | 1 | ||||
-rw-r--r-- | samplecode/SampleGlyphTransform.cpp | 81 | ||||
-rw-r--r-- | src/gpu/ops/GrAtlasTextOp.cpp | 12 | ||||
-rw-r--r-- | src/gpu/text/GrTextBlob.cpp | 3 | ||||
-rw-r--r-- | src/gpu/text/GrTextBlob.h | 5 |
6 files changed, 97 insertions, 8 deletions
diff --git a/gm/3dgm.cpp b/gm/3dgm.cpp index 93c6f92281..8014c246d3 100644 --- a/gm/3dgm.cpp +++ b/gm/3dgm.cpp @@ -173,6 +173,9 @@ protected: SkString onShortName() override { return SkString("3dgm"); } bool onAnimate(const SkAnimTimer& timer) override { + if (!fAnim) { + return false; + } SkScalar dur = fAnim->duration(); fAnimT = fmod(timer.secs(), dur) / dur; return true; diff --git a/gn/samples.gni b/gn/samples.gni index b5728b3bfd..1a4002f82c 100644 --- a/gn/samples.gni +++ b/gn/samples.gni @@ -50,6 +50,7 @@ samples_sources = [ "$_samplecode/SampleFlutterAnimate.cpp", "$_samplecode/SampleFontScalerTest.cpp", "$_samplecode/SampleFuzz.cpp", + "$_samplecode/SampleGlyphTransform.cpp", "$_samplecode/SampleGradients.cpp", "$_samplecode/SampleHairCurves.cpp", "$_samplecode/SampleHairline.cpp", diff --git a/samplecode/SampleGlyphTransform.cpp b/samplecode/SampleGlyphTransform.cpp new file mode 100644 index 0000000000..b5d44f8bfc --- /dev/null +++ b/samplecode/SampleGlyphTransform.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "SampleCode.h" +#include "sk_tool_utils.h" + +#include "SkAnimTimer.h" +#include "SkCanvas.h" +#include "SkPath.h" +#include "SkRandom.h" +#include "SkRRect.h" +#include "SkTypeface.h" + +// Implementation in C++ of Animated Emoji +// See https://t.d3fc.io/status/705212795936247808 + +class GlyphTransformView : public SampleView { +public: + GlyphTransformView() {} + +protected: + void onOnceBeforeDraw() override { + fEmojiFont.fTypeface = sk_tool_utils::emoji_typeface(); + fEmojiFont.fText = sk_tool_utils::emoji_sample_text(); + } + + // overrides from SkEventSink + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "Glyph Transform"); + return true; + } + return this->INHERITED::onQuery(evt); + } + + void onDrawContent(SkCanvas* canvas) override { + SkPaint paint; + paint.setTypeface(fEmojiFont.fTypeface); + const char* text = fEmojiFont.fText; + + canvas->scale(4, 4); + + canvas->drawLine(0, 200, 600, 200, paint); + SkMatrix ctm; + ctm.setRotate(SkRadiansToDegrees(fRotate)); + ctm.postScale(fScale, fScale); + ctm.postTranslate(fTranslate.fX, fTranslate.fY); + canvas->concat(ctm); + canvas->drawString(text, 0, 0, paint); + } + + bool onAnimate(const SkAnimTimer& timer) override { + double t = timer.secs(); + + fTranslate.set(99 + sin(t / 3.0e3) - t / 1024, 200 + sin(t / 999) / t); + fScale = 4.5 - t*t / 99; + fRotate = sin(t / 734); + + return true; + } + +private: + struct EmojiFont { + sk_sp<SkTypeface> fTypeface; + const char* fText; + } fEmojiFont; + + SkVector fTranslate; + SkScalar fScale; + SkScalar fRotate; + + typedef SampleView INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static SkView* MyFactory() { return new GlyphTransformView; } +static SkViewRegister reg(MyFactory); diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 82f4b54c10..a83e025a50 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -25,11 +25,6 @@ static const int kDistanceAdjustLumShift = 5; void GrAtlasTextOp::init() { const Geometry& geo = fGeoData[0]; - SkRect bounds; - geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX, geo.fY); - // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds - // we treat this as a set of non-AA rects rendered with a texture. - this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo); if (this->usesDistanceFields()) { bool isLCD = this->isLCD(); @@ -51,6 +46,13 @@ void GrAtlasTextOp::init() { fNeedsGlyphTransform = true; } + + SkRect bounds; + geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX, geo.fY, + fNeedsGlyphTransform); + // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds + // we treat this as a set of non-AA rects rendered with a texture. + this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo); } void GrAtlasTextOp::visitProxies(const VisitProxyFunc& func) const { diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp index c3d06e81fd..b6fc3ce170 100644 --- a/src/gpu/text/GrTextBlob.cpp +++ b/src/gpu/text/GrTextBlob.cpp @@ -353,7 +353,8 @@ void GrTextBlob::flush(GrTextUtils::Target* target, const SkSurfaceProps& props, skipClip = true; // We only need to do clipping work if the subrun isn't contained by the clip SkRect subRunBounds; - this->computeSubRunBounds(&subRunBounds, runIndex, subRun, viewMatrix, x, y); + this->computeSubRunBounds(&subRunBounds, runIndex, subRun, viewMatrix, x, y, + false); if (!clipRRect.getBounds().contains(subRunBounds)) { // If the subrun is completely outside, don't add an op for it if (!clipRRect.getBounds().intersects(subRunBounds)) { diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h index 49615a92ed..e34ab88ef2 100644 --- a/src/gpu/text/GrTextBlob.h +++ b/src/gpu/text/GrTextBlob.h @@ -210,7 +210,8 @@ public: SkScalar y); void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex, - const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { + const SkMatrix& viewMatrix, SkScalar x, SkScalar y, + bool needsGlyphTransform) { // We don't yet position distance field text on the cpu, so we have to map the vertex bounds // into device space. // We handle vertex bounds differently for distance field text and bitmap text because @@ -219,7 +220,7 @@ public: const Run& run = fRuns[runIndex]; const Run::SubRunInfo& subRun = run.fSubRunInfo[subRunIndex]; *outBounds = subRun.vertexBounds(); - if (subRun.drawAsDistanceFields()) { + if (needsGlyphTransform) { // Distance field text is positioned with the (X,Y) as part of the glyph position, // and currently the view matrix is applied on the GPU outBounds->offset(x - fInitialX, y - fInitialY); |