diff options
Diffstat (limited to 'gfx/skia/skia/src/text/GlyphRun.h')
-rw-r--r-- | gfx/skia/skia/src/text/GlyphRun.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/text/GlyphRun.h b/gfx/skia/skia/src/text/GlyphRun.h new file mode 100644 index 0000000000..cc8980f824 --- /dev/null +++ b/gfx/skia/skia/src/text/GlyphRun.h @@ -0,0 +1,183 @@ +/* + * 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 SkGlyphRun_DEFINED +#define SkGlyphRun_DEFINED + +#include <functional> +#include <optional> +#include <vector> + +#include "include/core/SkFont.h" +#include "include/core/SkPaint.h" +#include "include/core/SkPoint.h" +#include "include/core/SkRSXform.h" +#include "include/core/SkSpan.h" +#include "include/core/SkTypes.h" +#include "include/private/base/SkTemplates.h" +#include "src/base/SkZip.h" + +class SkBaseDevice; +class SkCanvas; +class SkGlyph; +class SkTextBlob; +class SkTextBlobRunIterator; + +namespace sktext { +class GlyphRunBuilder; +class GlyphRunList; + +class GlyphRun { +public: + GlyphRun(const SkFont& font, + SkSpan<const SkPoint> positions, + SkSpan<const SkGlyphID> glyphIDs, + SkSpan<const char> text, + SkSpan<const uint32_t> clusters, + SkSpan<const SkVector> scaledRotations); + + GlyphRun(const GlyphRun& glyphRun, const SkFont& font); + + size_t runSize() const { return fSource.size(); } + SkSpan<const SkPoint> positions() const { return fSource.get<1>(); } + SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); } + SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; } + const SkFont& font() const { return fFont; } + SkSpan<const uint32_t> clusters() const { return fClusters; } + SkSpan<const char> text() const { return fText; } + SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; } + +private: + // GlyphIDs and positions. + const SkZip<const SkGlyphID, const SkPoint> fSource; + // Original text from SkTextBlob if present. Will be empty of not present. + const SkSpan<const char> fText; + // Original clusters from SkTextBlob if present. Will be empty if not present. + const SkSpan<const uint32_t> fClusters; + // Possible RSXForm information + const SkSpan<const SkVector> fScaledRotations; + // Font for this run modified to have glyph encoding and left alignment. + SkFont fFont; +}; + +class GlyphRunList { + SkSpan<const GlyphRun> fGlyphRuns; + +public: + // Blob maybe null. + GlyphRunList(const SkTextBlob* blob, + SkRect bounds, + SkPoint origin, + SkSpan<const GlyphRun> glyphRunList, + GlyphRunBuilder* builder); + + GlyphRunList(const GlyphRun& glyphRun, + const SkRect& bounds, + SkPoint origin, + GlyphRunBuilder* builder); + uint64_t uniqueID() const; + bool anyRunsLCD() const; + void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; + + bool canCache() const { return fOriginalTextBlob != nullptr; } + size_t runCount() const { return fGlyphRuns.size(); } + size_t totalGlyphCount() const { + size_t glyphCount = 0; + for (const GlyphRun& run : *this) { + glyphCount += run.runSize(); + } + return glyphCount; + } + size_t maxGlyphRunSize() const { + size_t size = 0; + for (const GlyphRun& run : *this) { + size = std::max(run.runSize(), size); + } + return size; + } + + bool hasRSXForm() const { + for (const GlyphRun& run : *this) { + if (!run.scaledRotations().empty()) { return true; } + } + return false; + } + + sk_sp<SkTextBlob> makeBlob() const; + + SkPoint origin() const { return fOrigin; } + SkRect sourceBounds() const { return fSourceBounds; } + SkRect sourceBoundsWithOrigin() const { return fSourceBounds.makeOffset(fOrigin); } + const SkTextBlob* blob() const { return fOriginalTextBlob; } + GlyphRunBuilder* builder() const { return fBuilder; } + + auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } + auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } + auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); } + auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); } + auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } + auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } + auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } + +private: + // The text blob is needed to hook up the call back that the SkTextBlob destructor calls. It + // should be used for nothing else. + const SkTextBlob* fOriginalTextBlob{nullptr}; + const SkRect fSourceBounds{SkRect::MakeEmpty()}; + const SkPoint fOrigin = {0, 0}; + GlyphRunBuilder* const fBuilder; +}; + +class GlyphRunBuilder { +public: + GlyphRunList makeGlyphRunList(const GlyphRun& run, const SkPaint& paint, SkPoint origin); + const GlyphRunList& textToGlyphRunList(const SkFont& font, + const SkPaint& paint, + const void* bytes, + size_t byteLength, + SkPoint origin, + SkTextEncoding encoding = SkTextEncoding::kUTF8); + const GlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin); + std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>> + convertRSXForm(SkSpan<const SkRSXform> xforms); + + bool empty() const { return fGlyphRunListStorage.empty(); } + +private: + void initialize(const SkTextBlob& blob); + void prepareBuffers(int positionCount, int RSXFormCount); + + SkSpan<const SkGlyphID> textToGlyphIDs( + const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding); + + void makeGlyphRun( + const SkFont& font, + SkSpan<const SkGlyphID> glyphIDs, + SkSpan<const SkPoint> positions, + SkSpan<const char> text, + SkSpan<const uint32_t> clusters, + SkSpan<const SkVector> scaledRotations); + + const GlyphRunList& setGlyphRunList( + const SkTextBlob* blob, const SkRect& bounds, SkPoint origin); + + int fMaxTotalRunSize{0}; + skia_private::AutoTMalloc<SkPoint> fPositions; + int fMaxScaledRotations{0}; + skia_private::AutoTMalloc<SkVector> fScaledRotations; + + std::vector<GlyphRun> fGlyphRunListStorage; + std::optional<GlyphRunList> fGlyphRunList; // Defaults to no value; + + // Used as a temporary for preparing using utfN text. This implies that only one run of + // glyph ids will ever be needed because blobs are already glyph based. + std::vector<SkGlyphID> fScratchGlyphIDs; + +}; +} // namespace sktext + +#endif // SkGlyphRun_DEFINED |