1 /* 2 * Copyright 2018 The Android Open Source Project 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 #ifndef SkGlyphRunPainter_DEFINED 9 #define SkGlyphRunPainter_DEFINED 10 11 #include "include/core/SkSurfaceProps.h" 12 #include "src/core/SkDistanceFieldGen.h" 13 #include "src/core/SkGlyphBuffer.h" 14 #include "src/core/SkGlyphRun.h" 15 #include "src/core/SkScalerContext.h" 16 #include "src/core/SkTextBlobPriv.h" 17 18 #if SK_SUPPORT_GPU 19 #include "src/gpu/text/GrSDFTControl.h" 20 class GrColorInfo; 21 namespace skgpu { namespace v1 { class SurfaceDrawContext; }} 22 #endif 23 24 class SkGlyphRunPainterInterface; 25 class SkStrikeSpec; 26 27 // round and ignorePositionMask are used to calculate the subpixel position of a glyph. 28 // The per component (x or y) calculation is: 29 // 30 // subpixelOffset = (floor((viewportPosition + rounding) & mask) >> 14) & 3 31 // 32 // where mask is either 0 or ~0, and rounding is either 33 // 1/2 for non-subpixel or 1/8 for subpixel. 34 struct SkGlyphPositionRoundingSpec { 35 SkGlyphPositionRoundingSpec(bool isSubpixel, SkAxisAlignment axisAlignment); 36 const SkVector halfAxisSampleFreq; 37 const SkIPoint ignorePositionMask; 38 const SkIPoint ignorePositionFieldMask; 39 40 private: 41 static SkVector HalfAxisSampleFreq(bool isSubpixel, SkAxisAlignment axisAlignment); 42 static SkIPoint IgnorePositionMask(bool isSubpixel, SkAxisAlignment axisAlignment); 43 static SkIPoint IgnorePositionFieldMask(bool isSubpixel, SkAxisAlignment axisAlignment); 44 }; 45 46 class SkStrikeCommon { 47 public: 48 #if defined(SK_BUILD_FOR_OHOS) 49 // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 512x512. 50 // This means that the maximum size a glyph can be is 512x512. 51 inline static constexpr uint16_t kSkSideTooBigForAtlas = 512; 52 #else 53 // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 256x256. 54 // This means that the maximum size a glyph can be is 256x256. 55 inline static constexpr uint16_t kSkSideTooBigForAtlas = 256; 56 #endif 57 }; 58 59 class SkGlyphRunListPainter { 60 public: 61 // Constructor for SkBitmpapDevice. 62 SkGlyphRunListPainter(const SkSurfaceProps& props, 63 SkColorType colorType, 64 SkColorSpace* cs, 65 SkStrikeForGPUCacheInterface* strikeCache); 66 67 #if SK_SUPPORT_GPU 68 // The following two ctors are used exclusively by the GPU, and will always use the global 69 // strike cache. 70 SkGlyphRunListPainter(const SkSurfaceProps&, const GrColorInfo&); 71 explicit SkGlyphRunListPainter(const skgpu::v1::SurfaceDrawContext&); 72 #endif // SK_SUPPORT_GPU 73 74 class BitmapDevicePainter { 75 public: 76 BitmapDevicePainter() = default; 77 BitmapDevicePainter(const BitmapDevicePainter&) = default; 78 virtual ~BitmapDevicePainter() = default; 79 80 virtual void paintPaths( 81 SkDrawableGlyphBuffer* drawables, SkScalar scale, SkPoint origin, 82 const SkPaint& paint) const = 0; 83 84 virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0; 85 virtual void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull, 86 const SkSamplingOptions&, const SkPaint&) const = 0; 87 }; 88 89 void drawForBitmapDevice( 90 const SkGlyphRunList& glyphRunList, const SkPaint& paint, const SkMatrix& deviceMatrix, 91 const BitmapDevicePainter* bitmapDevice); 92 93 #if SK_SUPPORT_GPU 94 // A nullptr for process means that the calls to the cache will be performed, but none of the 95 // callbacks will be called. 96 void processGlyphRun(const SkGlyphRun& glyphRun, 97 const SkMatrix& drawMatrix, 98 const SkPaint& drawPaint, 99 const GrSDFTControl& control, 100 SkGlyphRunPainterInterface* process, 101 const char* tag = nullptr); 102 #endif // SK_SUPPORT_GPU 103 104 private: 105 SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType, 106 SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache); 107 108 struct ScopedBuffers { 109 ScopedBuffers(SkGlyphRunListPainter* painter, size_t size); 110 // Required until C++17 copy elision 111 ScopedBuffers(const ScopedBuffers&) = default; 112 ~ScopedBuffers(); 113 SkGlyphRunListPainter* fPainter; 114 }; 115 116 ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList); 117 ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun); 118 119 // The props as on the actual device. 120 const SkSurfaceProps fDeviceProps; 121 // The props for when the bitmap device can't draw LCD text. 122 const SkSurfaceProps fBitmapFallbackProps; 123 const SkColorType fColorType; 124 const SkScalerContextFlags fScalerContextFlags; 125 126 SkStrikeForGPUCacheInterface* const fStrikeCache; 127 128 SkDrawableGlyphBuffer fDrawable; 129 SkSourceGlyphBuffer fRejects; 130 }; 131 132 // SkGlyphRunPainterInterface are all the ways that Ganesh generates glyphs. The first 133 // distinction is between Device and Source. 134 // * Device - the data in the cache is scaled to the device. There is no transformation from the 135 // cache to the screen. 136 // * Source - the data in the cache needs to be scaled from the cache to source space using the 137 // factor cacheToSourceScale. When drawn the system must combine cacheToSourceScale and the 138 // deviceView matrix to transform the cache data onto the screen. This allows zooming and 139 // simple animation to reuse the same glyph data by just changing the transform. 140 // 141 // In addition to transformation type above, Masks, Paths, SDFT, and Fallback (or really the 142 // rendering method of last resort) are the different 143 // formats of data used from the cache. 144 class SkGlyphRunPainterInterface { 145 public: 146 virtual ~SkGlyphRunPainterInterface() = default; 147 148 virtual void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 149 sk_sp<SkStrike>&& strike) = 0; 150 151 virtual void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 152 sk_sp<SkStrike>&& strike, 153 SkScalar strikeToSourceScale) = 0; 154 155 virtual void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables, 156 const SkFont& runFont, 157 SkScalar strikeToSourceScale) = 0; 158 159 virtual void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, 160 sk_sp<SkStrike>&& strike, 161 SkScalar strikeToSourceScale, 162 const SkFont& runFont, 163 SkScalar minScale, 164 SkScalar maxScale) = 0; 165 }; 166 167 #endif // SkGlyphRunPainter_DEFINED 168