blob: 0e947d5570a5b20703316193ba17cade6aac8280 [file] [log] [blame]
cdalton855d83f2014-09-18 13:51:53 -07001/*
2 * Copyright 2014 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
Robert Phillips646e4292017-06-13 12:44:56 -04008#include "GrGpu.h"
cdalton855d83f2014-09-18 13:51:53 -07009#include "GrPathRendering.h"
10#include "SkDescriptor.h"
11#include "SkGlyph.h"
12#include "SkMatrix.h"
13#include "SkTypeface.h"
14#include "GrPathRange.h"
15
cdalton193d9cf2016-05-12 11:52:02 -070016const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
17 switch (fill) {
18 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040019 SK_ABORT("Unexpected path fill.");
cdalton193d9cf2016-05-12 11:52:02 -070020 case GrPathRendering::kWinding_FillType: {
21 constexpr static GrUserStencilSettings kWindingStencilPass(
22 GrUserStencilSettings::StaticInit<
23 0xffff,
24 GrUserStencilTest::kAlwaysIfInClip,
25 0xffff,
26 GrUserStencilOp::kIncWrap,
27 GrUserStencilOp::kIncWrap,
28 0xffff>()
29 );
30 return kWindingStencilPass;
31 }
32 case GrPathRendering::kEvenOdd_FillType: {
33 constexpr static GrUserStencilSettings kEvenOddStencilPass(
34 GrUserStencilSettings::StaticInit<
35 0xffff,
36 GrUserStencilTest::kAlwaysIfInClip,
37 0xffff,
38 GrUserStencilOp::kInvert,
39 GrUserStencilOp::kInvert,
40 0xffff>()
41 );
42 return kEvenOddStencilPass;
43 }
44 }
45}
46
cdalton855d83f2014-09-18 13:51:53 -070047class GlyphGenerator : public GrPathRange::PathGenerator {
48public:
reeda9322c22016-04-12 06:47:05 -070049 GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects,
50 const SkDescriptor& desc)
51 : fScalerContext(typeface.createScalerContext(effects, &desc))
kkinnunen50b58e62015-05-18 23:02:07 -070052#ifdef SK_DEBUG
53 , fDesc(desc.copy())
54#endif
cdalton7d5c9502015-10-03 13:28:35 -070055 {}
cdalton855d83f2014-09-18 13:51:53 -070056
mtklein36352bf2015-03-25 18:17:31 -070057 int getNumPaths() override {
cdalton855d83f2014-09-18 13:51:53 -070058 return fScalerContext->getGlyphCount();
59 }
60
mtklein36352bf2015-03-25 18:17:31 -070061 void generatePath(int glyphID, SkPath* out) override {
Ben Wagner6e9ac122016-11-11 14:31:06 -050062 fScalerContext->getPath(glyphID, out);
cdalton855d83f2014-09-18 13:51:53 -070063 }
kkinnunen50b58e62015-05-18 23:02:07 -070064#ifdef SK_DEBUG
bsalomonc5d07fa2016-05-17 10:17:45 -070065 bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; }
kkinnunen50b58e62015-05-18 23:02:07 -070066#endif
cdalton855d83f2014-09-18 13:51:53 -070067private:
bungeman7cfd46a2016-10-20 16:06:52 -040068 const std::unique_ptr<SkScalerContext> fScalerContext;
kkinnunen50b58e62015-05-18 23:02:07 -070069#ifdef SK_DEBUG
bungeman520ced62016-10-18 08:03:42 -040070 const std::unique_ptr<SkDescriptor> fDesc;
kkinnunen50b58e62015-05-18 23:02:07 -070071#endif
cdalton855d83f2014-09-18 13:51:53 -070072};
73
Robert Phillips67d52cf2017-06-05 13:38:13 -040074sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface,
75 const SkScalerContextEffects& effects,
76 const SkDescriptor* desc,
77 const GrStyle& style) {
halcanary96fcdcc2015-08-27 07:41:13 -070078 if (nullptr == typeface) {
cdalton855d83f2014-09-18 13:51:53 -070079 typeface = SkTypeface::GetDefaultTypeface();
halcanary96fcdcc2015-08-27 07:41:13 -070080 SkASSERT(nullptr != typeface);
cdalton855d83f2014-09-18 13:51:53 -070081 }
82
83 if (desc) {
Hal Canary144caf52016-11-07 17:57:18 -050084 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc));
85 return this->createPathRange(generator.get(), style);
cdalton855d83f2014-09-18 13:51:53 -070086 }
87
88 SkScalerContextRec rec;
89 memset(&rec, 0, sizeof(rec));
90 rec.fFontID = typeface->uniqueID();
91 rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths;
92 rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1;
93 // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking.
94
95 SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
96 SkDescriptor* genericDesc = ad.getDesc();
97
98 genericDesc->init();
99 genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
100 genericDesc->computeChecksum();
Robert Phillips646e4292017-06-13 12:44:56 -0400101
reeda9322c22016-04-12 06:47:05 -0700102 // No effects, so we make a dummy struct
103 SkScalerContextEffects noEffects;
cdalton855d83f2014-09-18 13:51:53 -0700104
Hal Canary144caf52016-11-07 17:57:18 -0500105 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
106 return this->createPathRange(generator.get(), style);
cdalton855d83f2014-09-18 13:51:53 -0700107}
Robert Phillips646e4292017-06-13 12:44:56 -0400108
109void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
110 fGpu->handleDirtyContext();
111 this->onStencilPath(args, path);
112}
113
114void GrPathRendering::drawPath(const GrPipeline& pipeline,
115 const GrPrimitiveProcessor& primProc,
116 // Cover pass settings in pipeline.
117 const GrStencilSettings& stencilPassSettings,
118 const GrPath* path) {
119 fGpu->handleDirtyContext();
120 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400121 fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
Robert Phillips646e4292017-06-13 12:44:56 -0400122 }
123 this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
124}
125
126void GrPathRendering::drawPaths(const GrPipeline& pipeline,
127 const GrPrimitiveProcessor& primProc,
128 // Cover pass settings in pipeline.
129 const GrStencilSettings& stencilPassSettings,
130 const GrPathRange* pathRange,
131 const void* indices,
132 PathIndexType indexType,
133 const float transformValues[],
134 PathTransformType transformType,
135 int count) {
136 fGpu->handleDirtyContext();
137 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400138 fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
Robert Phillips646e4292017-06-13 12:44:56 -0400139 }
140#ifdef SK_DEBUG
141 pathRange->assertPathsLoaded(indices, indexType, count);
142#endif
143 this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
144 transformValues, transformType, count);
145}