Home | History | Annotate | Download | only in core
      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 SkGlyphRun_DEFINED
      9 #define SkGlyphRun_DEFINED
     10 
     11 #include <functional>
     12 #include <vector>
     13 
     14 #include "SkFont.h"
     15 #include "SkPaint.h"
     16 #include "SkPoint.h"
     17 #include "SkSpan.h"
     18 #include "SkTemplates.h"
     19 #include "SkTypes.h"
     20 
     21 class SkBaseDevice;
     22 class SkGlyph;
     23 class SkTextBlob;
     24 
     25 class SkGlyphRun {
     26 public:
     27     SkGlyphRun() = default;
     28     SkGlyphRun(const SkFont& font,
     29                SkSpan<const SkPoint> positions,
     30                SkSpan<const SkGlyphID> glyphIDs,
     31                SkSpan<const char> text,
     32                SkSpan<const uint32_t> clusters);
     33     SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
     34 
     35     void filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions);
     36 
     37     size_t runSize() const { return fGlyphIDs.size(); }
     38     SkSpan<const SkPoint> positions() const { return fPositions.toConst(); }
     39     SkSpan<const SkGlyphID> glyphsIDs() const { return fGlyphIDs; }
     40     const SkFont& font() const { return fFont; }
     41     SkSpan<const uint32_t> clusters() const { return fClusters; }
     42     SkSpan<const char> text() const { return fText; }
     43 
     44 private:
     45     // Positions of each glyph.
     46     const SkSpan<const SkPoint> fPositions;
     47     // This is temporary while converting from the old per glyph code to the bulk code.
     48     const SkSpan<const SkGlyphID> fGlyphIDs;
     49     // Original text from SkTextBlob if present. Will be empty of not present.
     50     const SkSpan<const char> fText;
     51     // Original clusters from SkTextBlob if present. Will be empty if not present.
     52     const SkSpan<const uint32_t>   fClusters;
     53     // Paint for this run modified to have glyph encoding and left alignment.
     54     SkFont fFont;
     55 };
     56 
     57 class SkGlyphRunList {
     58     const SkPaint* fOriginalPaint{nullptr};  // This should be deleted soon.
     59     // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
     60     // should be used for nothing else
     61     const SkTextBlob*  fOriginalTextBlob{nullptr};
     62     SkPoint fOrigin = {0, 0};
     63     SkSpan<const SkGlyphRun> fGlyphRuns;
     64 
     65 public:
     66     SkGlyphRunList();
     67     // Blob maybe null.
     68     SkGlyphRunList(
     69             const SkPaint& paint,
     70             const SkTextBlob* blob,
     71             SkPoint origin,
     72             SkSpan<const SkGlyphRun> glyphRunList);
     73 
     74     SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint);
     75 
     76     uint64_t uniqueID() const;
     77     bool anyRunsLCD() const;
     78     bool anyRunsSubpixelPositioned() const;
     79     void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
     80 
     81     bool canCache() const { return fOriginalTextBlob != nullptr; }
     82     size_t runCount() const { return fGlyphRuns.size(); }
     83     size_t totalGlyphCount() const {
     84         size_t glyphCount = 0;
     85         for(const auto& run : fGlyphRuns) {
     86             glyphCount += run.runSize();
     87         }
     88         return glyphCount;
     89     }
     90     bool allFontsFinite() const;
     91 
     92     SkPoint origin() const { return fOrigin; }
     93     const SkPaint& paint() const { return *fOriginalPaint; }
     94     const SkTextBlob* blob() const { return fOriginalTextBlob; }
     95 
     96     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();  }
     97     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();    }
     98     auto begin() const -> decltype(fGlyphRuns.cbegin())        { return fGlyphRuns.cbegin(); }
     99     auto end()   const -> decltype(fGlyphRuns.cend())          { return fGlyphRuns.cend();   }
    100     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();   }
    101     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();  }
    102     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];     }
    103 };
    104 
    105 class SkGlyphIDSet {
    106 public:
    107     SkSpan<const SkGlyphID> uniquifyGlyphIDs(
    108             uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs,
    109             SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices);
    110 private:
    111     size_t fUniverseToUniqueSize{0};
    112     SkAutoTMalloc<uint16_t> fUniverseToUnique;
    113 };
    114 
    115 class SkGlyphRunBuilder {
    116 public:
    117     void drawTextUTF8(
    118         const SkPaint& paint, const SkFont&, const void* bytes, size_t byteLength, SkPoint origin);
    119     void drawGlyphsWithPositions(
    120             const SkPaint&, const SkFont&, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos);
    121     void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkBaseDevice*);
    122 
    123     const SkGlyphRunList& useGlyphRunList();
    124 
    125     bool empty() const { return fGlyphRunListStorage.size() == 0; }
    126 
    127     static void DispatchBlob(SkGlyphRunBuilder* builder, const SkPaint& paint,
    128                              const SkTextBlob& blob, SkPoint origin, SkBaseDevice* device);
    129 
    130 private:
    131     void initialize(size_t totalRunSize);
    132     SkSpan<const SkGlyphID> textToGlyphIDs(
    133             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
    134 
    135     void makeGlyphRun(
    136             const SkFont& font,
    137             SkSpan<const SkGlyphID> glyphIDs,
    138             SkSpan<const SkPoint> positions,
    139             SkSpan<const char> text,
    140             SkSpan<const uint32_t> clusters);
    141 
    142     void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin);
    143 
    144     void simplifyDrawText(
    145             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
    146             SkPoint origin, SkPoint* positions,
    147             SkSpan<const char> text = SkSpan<const char>{},
    148             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
    149     void simplifyDrawPosTextH(
    150             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
    151             const SkScalar* xpos, SkScalar constY, SkPoint* positions,
    152             SkSpan<const char> text = SkSpan<const char>{},
    153             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
    154     void simplifyDrawPosText(
    155             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
    156             const SkPoint* pos,
    157             SkSpan<const char> text = SkSpan<const char>{},
    158             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
    159 
    160     size_t fMaxTotalRunSize{0};
    161     SkAutoTMalloc<SkPoint> fPositions;
    162 
    163     std::vector<SkGlyphRun> fGlyphRunListStorage;
    164     SkGlyphRunList fGlyphRunList;
    165 
    166     // Used as a temporary for preparing using utfN text. This implies that only one run of
    167     // glyph ids will ever be needed because blobs are already glyph based.
    168     std::vector<SkGlyphID> fScratchGlyphIDs;
    169 
    170     // Used as temporary storage for calculating positions for drawText.
    171     std::vector<SkPoint> fScratchAdvances;
    172 
    173     // Used for collecting the set of unique glyphs.
    174     SkGlyphIDSet fGlyphIDSet;
    175     SkAutoTMalloc<SkGlyphID> fUniqueGlyphIDs;
    176     SkAutoTMalloc<uint16_t> fUniqueGlyphIDIndices;
    177 };
    178 
    179 #endif  // SkGlyphRun_DEFINED
    180