1 /* 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 8 #include "GrGpu.h" 9 #include "GrPathRendering.h" 10 #include "SkDescriptor.h" 11 #include "SkScalerContext.h" 12 #include "SkGlyph.h" 13 #include "SkMatrix.h" 14 #include "SkTypeface.h" 15 #include "GrPathRange.h" 16 17 const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) { 18 switch (fill) { 19 default: 20 SK_ABORT("Unexpected path fill."); 21 case GrPathRendering::kWinding_FillType: { 22 constexpr static GrUserStencilSettings kWindingStencilPass( 23 GrUserStencilSettings::StaticInit< 24 0xffff, 25 GrUserStencilTest::kAlwaysIfInClip, 26 0xffff, 27 GrUserStencilOp::kIncWrap, 28 GrUserStencilOp::kIncWrap, 29 0xffff>() 30 ); 31 return kWindingStencilPass; 32 } 33 case GrPathRendering::kEvenOdd_FillType: { 34 constexpr static GrUserStencilSettings kEvenOddStencilPass( 35 GrUserStencilSettings::StaticInit< 36 0xffff, 37 GrUserStencilTest::kAlwaysIfInClip, 38 0xffff, 39 GrUserStencilOp::kInvert, 40 GrUserStencilOp::kInvert, 41 0xffff>() 42 ); 43 return kEvenOddStencilPass; 44 } 45 } 46 } 47 48 class GlyphGenerator : public GrPathRange::PathGenerator { 49 public: 50 GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects, 51 const SkDescriptor& desc) 52 : fScalerContext(typeface.createScalerContext(effects, &desc)) 53 #ifdef SK_DEBUG 54 , fDesc(desc.copy()) 55 #endif 56 {} 57 58 int getNumPaths() override { 59 return fScalerContext->getGlyphCount(); 60 } 61 62 void generatePath(int glyphID, SkPath* out) override { 63 fScalerContext->getPath(glyphID, out); 64 } 65 #ifdef SK_DEBUG 66 bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; } 67 #endif 68 private: 69 const std::unique_ptr<SkScalerContext> fScalerContext; 70 #ifdef SK_DEBUG 71 const std::unique_ptr<SkDescriptor> fDesc; 72 #endif 73 }; 74 75 sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface, 76 const SkScalerContextEffects& effects, 77 const SkDescriptor* desc, 78 const GrStyle& style) { 79 if (nullptr == typeface) { 80 typeface = SkTypeface::GetDefaultTypeface(); 81 SkASSERT(nullptr != typeface); 82 } 83 84 if (desc) { 85 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc)); 86 return this->createPathRange(generator.get(), style); 87 } 88 89 SkScalerContextRec rec; 90 memset(&rec, 0, sizeof(rec)); 91 rec.fFontID = typeface->uniqueID(); 92 rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths; 93 rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1; 94 // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking. 95 96 SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1)); 97 SkDescriptor* genericDesc = ad.getDesc(); 98 99 genericDesc->init(); 100 genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 101 genericDesc->computeChecksum(); 102 103 // No effects, so we make a dummy struct 104 SkScalerContextEffects noEffects; 105 106 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc)); 107 return this->createPathRange(generator.get(), style); 108 } 109 110 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) { 111 fGpu->handleDirtyContext(); 112 this->onStencilPath(args, path); 113 } 114 115 void GrPathRendering::drawPath(const GrPipeline& pipeline, 116 const GrPrimitiveProcessor& primProc, 117 // Cover pass settings in pipeline. 118 const GrStencilSettings& stencilPassSettings, 119 const GrPath* path) { 120 fGpu->handleDirtyContext(); 121 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) { 122 fGpu->xferBarrier(pipeline.renderTarget(), barrierType); 123 } 124 this->onDrawPath(pipeline, primProc, stencilPassSettings, path); 125 } 126 127 void GrPathRendering::drawPaths(const GrPipeline& pipeline, 128 const GrPrimitiveProcessor& primProc, 129 // Cover pass settings in pipeline. 130 const GrStencilSettings& stencilPassSettings, 131 const GrPathRange* pathRange, 132 const void* indices, 133 PathIndexType indexType, 134 const float transformValues[], 135 PathTransformType transformType, 136 int count) { 137 fGpu->handleDirtyContext(); 138 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) { 139 fGpu->xferBarrier(pipeline.renderTarget(), barrierType); 140 } 141 #ifdef SK_DEBUG 142 pathRange->assertPathsLoaded(indices, indexType, count); 143 #endif 144 this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType, 145 transformValues, transformType, count); 146 } 147