aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/text/GrStencilAndCoverTextContext.h
blob: 1ba113b59bbcfc812c013257f5ca4fc356f06563 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrStencilAndCoverTextContext_DEFINED
#define GrStencilAndCoverTextContext_DEFINED

#include "GrRenderTargetContext.h"
#include "GrStyle.h"
#include "SkDrawFilter.h"
#include "SkOpts.h"
#include "SkTextBlob.h"
#include "SkTHash.h"
#include "SkTInternalLList.h"
#include "SkTLList.h"
#include "batches/GrDrawPathBatch.h"

class GrAtlasTextContext;
class GrTextStrike;
class GrPath;
class SkSurfaceProps;

/*
 * This class implements text rendering using stencil and cover path rendering
 * (by the means of GrOpList::drawPath).
 */
class GrStencilAndCoverTextContext {
public:
    static GrStencilAndCoverTextContext* Create(GrAtlasTextContext* fallbackTextContext);

    void drawText(GrContext*, GrRenderTargetContext* rtc,
                  const GrClip&,  const GrPaint&, const SkPaint&,
                  const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
                  size_t byteLength, SkScalar x,
                  SkScalar y, const SkIRect& clipBounds);
    void drawPosText(GrContext*, GrRenderTargetContext*,
                     const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix, const SkSurfaceProps&,
                     const char text[], size_t byteLength,
                     const SkScalar pos[], int scalarsPerPosition,
                     const SkPoint& offset, const SkIRect& clipBounds);
    void drawTextBlob(GrContext*, GrRenderTargetContext*, const GrClip&, const SkPaint&,
                      const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
                      SkScalar x, SkScalar y,
                      SkDrawFilter*, const SkIRect& clipBounds);

    virtual ~GrStencilAndCoverTextContext();

private:
    GrStencilAndCoverTextContext(GrAtlasTextContext* fallbackTextContext);

    bool canDraw(const SkPaint& skPaint, const SkMatrix&) {
        return this->internalCanDraw(skPaint);
    }

    bool internalCanDraw(const SkPaint&);

    void uncachedDrawTextBlob(GrContext*, GrRenderTargetContext* rtc,
                              const GrClip& clip, const SkPaint& skPaint,
                              const SkMatrix& viewMatrix,
                              const SkSurfaceProps&,
                              const SkTextBlob* blob,
                              SkScalar x, SkScalar y,
                              SkDrawFilter* drawFilter,
                              const SkIRect& clipBounds);

    class FallbackBlobBuilder;

    class TextRun {
    public:
        TextRun(const SkPaint& fontAndStroke);
        ~TextRun();

        void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y);

        void setPosText(const char text[], size_t byteLength, const SkScalar pos[],
                        int scalarsPerPosition, const SkPoint& offset);

        void draw(GrContext*, GrRenderTargetContext*, const GrPaint&, const GrClip&,
                  const SkMatrix&, const SkSurfaceProps&,
                  SkScalar x, SkScalar y, const SkIRect& clipBounds,
                  GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const;

        void releaseGlyphCache() const;

        size_t computeSizeInCache() const;

        GrAA isAntiAlias() const { return fFont.isAntiAlias() ? GrAA::kYes : GrAA::kNo; }

    private:
        typedef GrDrawPathRangeBatch::InstanceData InstanceData;

        SkGlyphCache* getGlyphCache() const;
        GrPathRange* createGlyphs(GrContext*) const;
        void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*);

        GrStyle                         fStyle;
        SkPaint                         fFont;
        SkScalar                        fTextRatio;
        float                           fTextInverseRatio;
        bool                            fUsingRawGlyphPaths;
        GrUniqueKey                     fGlyphPathsKey;
        int                             fTotalGlyphCount;
        sk_sp<InstanceData>             fInstanceData;
        int                             fFallbackGlyphCount;
        sk_sp<SkTextBlob>               fFallbackTextBlob;
        mutable SkGlyphCache*           fDetachedGlyphCache;
        mutable GrGpuResource::UniqueID fLastDrawnGlyphsID;
    };

    // Text blobs/caches.

    class TextBlob : public SkTLList<TextRun, 1> {
    public:
        typedef SkTArray<uint32_t, true> Key;

        static const Key& GetKey(const TextBlob* blob) { return blob->key(); }

        static uint32_t Hash(const Key& key) {
            SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map.
            return SkOpts::hash(key.begin(), sizeof(uint32_t) * key.count());
        }

        TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint)
            : fKey(&blobId, 1) { this->init(skBlob, skPaint); }

        TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint)
            : fKey(key) {
            // 1-length keys are unterstood to be the blob id and must use the other constructor.
            SkASSERT(fKey.count() > 1);
            this->init(skBlob, skPaint);
        }

        const Key& key() const { return fKey; }

        size_t cpuMemorySize() const { return fCpuMemorySize; }

    private:
        void init(const SkTextBlob*, const SkPaint&);

        const SkSTArray<1, uint32_t, true>   fKey;
        size_t                               fCpuMemorySize;

        SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
    };

    const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&);
    void purgeToFit(const TextBlob&);

    GrAtlasTextContext*                                       fFallbackTextContext;
    SkTHashMap<uint32_t, TextBlob*>                           fBlobIdCache;
    SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob>   fBlobKeyCache;
    SkTInternalLList<TextBlob>                                fLRUList;
    size_t                                                    fCacheSize;
};

#endif