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 SkAutoDescriptor ad; 90 SkDescriptor* genericDesc = 91 SkScalerContext::MakeDescriptorForPaths(typeface->uniqueID(), &ad); 92 93 // No effects, so we make a dummy struct 94 SkScalerContextEffects noEffects; 95 96 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc)); 97 return this->createPathRange(generator.get(), style); 98 } 99 100 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) { 101 fGpu->handleDirtyContext(); 102 this->onStencilPath(args, path); 103 } 104 105 void GrPathRendering::drawPath(const GrPipeline& pipeline, 106 const GrPrimitiveProcessor& primProc, 107 // Cover pass settings in pipeline. 108 const GrStencilSettings& stencilPassSettings, 109 const GrPath* path) { 110 fGpu->handleDirtyContext(); 111 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) { 112 fGpu->xferBarrier(pipeline.renderTarget(), barrierType); 113 } 114 this->onDrawPath(pipeline, primProc, stencilPassSettings, path); 115 } 116 117 void GrPathRendering::drawPaths(const GrPipeline& pipeline, 118 const GrPrimitiveProcessor& primProc, 119 // Cover pass settings in pipeline. 120 const GrStencilSettings& stencilPassSettings, 121 const GrPathRange* pathRange, 122 const void* indices, 123 PathIndexType indexType, 124 const float transformValues[], 125 PathTransformType transformType, 126 int count) { 127 fGpu->handleDirtyContext(); 128 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) { 129 fGpu->xferBarrier(pipeline.renderTarget(), barrierType); 130 } 131 #ifdef SK_DEBUG 132 pathRange->assertPathsLoaded(indices, indexType, count); 133 #endif 134 this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType, 135 transformValues, transformType, count); 136 } 137