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 "SkGlyph.h" 12 #include "SkMatrix.h" 13 #include "SkTypeface.h" 14 #include "GrPathRange.h" 15 16 const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) { 17 switch (fill) { 18 default: 19 SkFAIL("Unexpected path fill."); 20 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 47 class GlyphGenerator : public GrPathRange::PathGenerator { 48 public: 49 GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects, 50 const SkDescriptor& desc) 51 : fScalerContext(typeface.createScalerContext(effects, &desc)) 52 #ifdef SK_DEBUG 53 , fDesc(desc.copy()) 54 #endif 55 {} 56 57 int getNumPaths() override { 58 return fScalerContext->getGlyphCount(); 59 } 60 61 void generatePath(int glyphID, SkPath* out) override { 62 fScalerContext->getPath(glyphID, out); 63 } 64 #ifdef SK_DEBUG 65 bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; } 66 #endif 67 private: 68 const std::unique_ptr<SkScalerContext> fScalerContext; 69 #ifdef SK_DEBUG 70 const std::unique_ptr<SkDescriptor> fDesc; 71 #endif 72 }; 73 74 sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface, 75 const SkScalerContextEffects& effects, 76 const SkDescriptor* desc, 77 const GrStyle& style) { 78 if (nullptr == typeface) { 79 typeface = SkTypeface::GetDefaultTypeface(); 80 SkASSERT(nullptr != typeface); 81 } 82 83 if (desc) { 84 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc)); 85 return this->createPathRange(generator.get(), style); 86 } 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(); 101 102 // No effects, so we make a dummy struct 103 SkScalerContextEffects noEffects; 104 105 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc)); 106 return this->createPathRange(generator.get(), style); 107 } 108 109 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) { 110 fGpu->handleDirtyContext(); 111 this->onStencilPath(args, path); 112 } 113 114 void 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())) { 121 fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType); 122 } 123 this->onDrawPath(pipeline, primProc, stencilPassSettings, path); 124 } 125 126 void 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())) { 138 fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType); 139 } 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 } 146