/* * Copyright 2018 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkGlyphRunPainter_DEFINED #define SkGlyphRunPainter_DEFINED #include "include/core/SkSurfaceProps.h" #include "src/core/SkDistanceFieldGen.h" #include "src/core/SkGlyphBuffer.h" #include "src/core/SkGlyphRun.h" #include "src/core/SkScalerContext.h" #include "src/core/SkTextBlobPriv.h" #if SK_SUPPORT_GPU #include "src/gpu/text/GrSDFTControl.h" class GrColorInfo; namespace skgpu { namespace v1 { class SurfaceDrawContext; }} #endif class SkGlyphRunPainterInterface; class SkStrikeSpec; // round and ignorePositionMask are used to calculate the subpixel position of a glyph. // The per component (x or y) calculation is: // // subpixelOffset = (floor((viewportPosition + rounding) & mask) >> 14) & 3 // // where mask is either 0 or ~0, and rounding is either // 1/2 for non-subpixel or 1/8 for subpixel. struct SkGlyphPositionRoundingSpec { SkGlyphPositionRoundingSpec(bool isSubpixel, SkAxisAlignment axisAlignment); const SkVector halfAxisSampleFreq; const SkIPoint ignorePositionMask; const SkIPoint ignorePositionFieldMask; private: static SkVector HalfAxisSampleFreq(bool isSubpixel, SkAxisAlignment axisAlignment); static SkIPoint IgnorePositionMask(bool isSubpixel, SkAxisAlignment axisAlignment); static SkIPoint IgnorePositionFieldMask(bool isSubpixel, SkAxisAlignment axisAlignment); }; class SkStrikeCommon { public: #if defined(SK_BUILD_FOR_OHOS) // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 512x512. // This means that the maximum size a glyph can be is 512x512. inline static constexpr uint16_t kSkSideTooBigForAtlas = 512; #else // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 256x256. // This means that the maximum size a glyph can be is 256x256. inline static constexpr uint16_t kSkSideTooBigForAtlas = 256; #endif }; class SkGlyphRunListPainter { public: // Constructor for SkBitmpapDevice. SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType, SkColorSpace* cs, SkStrikeForGPUCacheInterface* strikeCache); #if SK_SUPPORT_GPU // The following two ctors are used exclusively by the GPU, and will always use the global // strike cache. SkGlyphRunListPainter(const SkSurfaceProps&, const GrColorInfo&); explicit SkGlyphRunListPainter(const skgpu::v1::SurfaceDrawContext&); #endif // SK_SUPPORT_GPU class BitmapDevicePainter { public: BitmapDevicePainter() = default; BitmapDevicePainter(const BitmapDevicePainter&) = default; virtual ~BitmapDevicePainter() = default; virtual void paintPaths( SkDrawableGlyphBuffer* drawables, SkScalar scale, SkPoint origin, const SkPaint& paint) const = 0; virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0; virtual void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull, const SkSamplingOptions&, const SkPaint&) const = 0; }; void drawForBitmapDevice( const SkGlyphRunList& glyphRunList, const SkPaint& paint, const SkMatrix& deviceMatrix, const BitmapDevicePainter* bitmapDevice); #if SK_SUPPORT_GPU // A nullptr for process means that the calls to the cache will be performed, but none of the // callbacks will be called. void processGlyphRun(const SkGlyphRun& glyphRun, const SkMatrix& drawMatrix, const SkPaint& drawPaint, const GrSDFTControl& control, SkGlyphRunPainterInterface* process, const char* tag = nullptr); #endif // SK_SUPPORT_GPU private: SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType, SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache); struct ScopedBuffers { ScopedBuffers(SkGlyphRunListPainter* painter, size_t size); // Required until C++17 copy elision ScopedBuffers(const ScopedBuffers&) = default; ~ScopedBuffers(); SkGlyphRunListPainter* fPainter; }; ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList); ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun); // The props as on the actual device. const SkSurfaceProps fDeviceProps; // The props for when the bitmap device can't draw LCD text. const SkSurfaceProps fBitmapFallbackProps; const SkColorType fColorType; const SkScalerContextFlags fScalerContextFlags; SkStrikeForGPUCacheInterface* const fStrikeCache; SkDrawableGlyphBuffer fDrawable; SkSourceGlyphBuffer fRejects; }; // SkGlyphRunPainterInterface are all the ways that Ganesh generates glyphs. The first // distinction is between Device and Source. // * Device - the data in the cache is scaled to the device. There is no transformation from the // cache to the screen. // * Source - the data in the cache needs to be scaled from the cache to source space using the // factor cacheToSourceScale. When drawn the system must combine cacheToSourceScale and the // deviceView matrix to transform the cache data onto the screen. This allows zooming and // simple animation to reuse the same glyph data by just changing the transform. // // In addition to transformation type above, Masks, Paths, SDFT, and Fallback (or really the // rendering method of last resort) are the different // formats of data used from the cache. class SkGlyphRunPainterInterface { public: virtual ~SkGlyphRunPainterInterface() = default; virtual void processDeviceMasks(const SkZip& drawables, sk_sp&& strike) = 0; virtual void processSourceMasks(const SkZip& drawables, sk_sp&& strike, SkScalar strikeToSourceScale) = 0; virtual void processSourcePaths(const SkZip& drawables, const SkFont& runFont, SkScalar strikeToSourceScale) = 0; virtual void processSourceSDFT(const SkZip& drawables, sk_sp&& strike, SkScalar strikeToSourceScale, const SkFont& runFont, SkScalar minScale, SkScalar maxScale) = 0; }; #endif // SkGlyphRunPainter_DEFINED