/* * 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 "SkDistanceFieldGen.h" #include "SkGlyphRun.h" #include "SkScalerContext.h" #include "SkSurfaceProps.h" #include "SkTextBlobPriv.h" #if SK_SUPPORT_GPU class GrColorSpaceInfo; class GrRenderTargetContext; #endif class SkStrikeInterface { public: virtual ~SkStrikeInterface() = default; virtual SkVector rounding() const = 0; virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0; virtual bool hasImage(const SkGlyph& glyph) = 0; virtual bool hasPath(const SkGlyph& glyph) = 0; }; class SkStrikeCommon { public: static SkVector PixelRounding(bool isSubpixel, SkAxisAlignment axisAlignment); // This assumes that position has the appropriate rounding term applied. static SkIPoint SubpixelLookup(SkAxisAlignment axisAlignment, SkPoint position); // 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. static constexpr uint16_t kSkSideTooBigForAtlas = 256; static bool GlyphTooBigForAtlas(const SkGlyph& glyph); }; class SkGlyphRunListPainter { public: // Constructor for SkBitmpapDevice. SkGlyphRunListPainter( const SkSurfaceProps& props, SkColorType colorType, SkScalerContextFlags flags); #if SK_SUPPORT_GPU SkGlyphRunListPainter(const SkSurfaceProps&, const GrColorSpaceInfo&); explicit SkGlyphRunListPainter(const GrRenderTargetContext& renderTargetContext); #endif struct PathAndPos { const SkPath* path; SkPoint position; }; struct GlyphAndPos { const SkGlyph* glyph; SkPoint position; }; class BitmapDevicePainter { public: virtual ~BitmapDevicePainter() = default; virtual void paintPaths(SkSpan<const PathAndPos> pathsAndPositions, SkScalar scale, const SkPaint& paint) const = 0; virtual void paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const = 0; }; void drawForBitmapDevice( const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix, const BitmapDevicePainter* bitmapDevice); template <typename EmptiesT, typename MasksT, typename PathsT> void drawGlyphRunAsBMPWithPathFallback( SkStrikeInterface* cache, const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix, EmptiesT&& processEmpties, MasksT&& processMasks, PathsT&& processPaths); enum NeedsTransform : bool { kTransformDone = false, kDoTransform = true }; using ARGBFallback = std::function<void(const SkPaint& fallbackPaint, // The run paint maybe with a new text size const SkFont& fallbackFont, SkSpan<const SkGlyphID> fallbackGlyphIDs, // Colored glyphs SkSpan<const SkPoint> fallbackPositions, // Positions of above glyphs SkScalar fallbackTextScale, // Scale factor for glyph const SkMatrix& glyphCacheMatrix, // Matrix of glyph cache NeedsTransform handleTransformLater)>; // Positions / glyph transformed // Draw glyphs as paths with fallback to scaled ARGB glyphs if color is needed. // PerPath - perPath(const SkGlyph&, SkPoint position) // FallbackARGB - fallbackARGB(SkSpan<const SkGlyphID>, SkSpan<const SkPoint>) // For each glyph that is not ARGB call perPath. If the glyph is ARGB then store the glyphID // and the position in fallback vectors. After all the glyphs are processed, pass the // fallback glyphIDs and positions to fallbackARGB. template <typename PerEmptyT, typename PerPath> void drawGlyphRunAsPathWithARGBFallback( SkStrikeInterface* cache, const SkGlyphRun& glyphRun, SkPoint origin, const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar textScale, PerEmptyT&& perEmpty, PerPath&& perPath, ARGBFallback&& fallbackARGB); template <typename PerEmptyT, typename PerSDFT, typename PerPathT> void drawGlyphRunAsSDFWithARGBFallback( SkStrikeInterface* cache, const SkGlyphRun& glyphRun, SkPoint origin, const SkPaint& runPaint, const SkMatrix& viewMatrix, SkScalar textRatio, PerEmptyT&& perEmpty, PerSDFT&& perSDF, PerPathT&& perPath, ARGBFallback&& perFallback); // TODO: Make this the canonical check for Skia. static bool ShouldDrawAsPath(const SkPaint& paint, const SkFont& font, const SkMatrix& matrix); private: struct ScopedBuffers { ScopedBuffers(SkGlyphRunListPainter* painter, int size); ~ScopedBuffers(); SkGlyphRunListPainter* fPainter; }; ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList); // TODO: Remove once I can hoist ensureBuffers above the list for loop in all cases. ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun); void processARGBFallback( SkScalar maxGlyphDimension, const SkPaint& fallbackPaint, const SkFont& fallbackFont, const SkMatrix& viewMatrix, SkScalar textScale, ARGBFallback argbFallback); // 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; int fMaxRunSize{0}; SkAutoTMalloc<SkPoint> fPositions; SkAutoTMalloc<GlyphAndPos> fMasks; std::vector<GlyphAndPos> fPaths; // Vectors for tracking ARGB fallback information. std::vector<SkGlyphID> fARGBGlyphsIDs; std::vector<SkPoint> fARGBPositions; }; #endif // SkGlyphRunPainter_DEFINED