1/*
2 * Copyright 2014 Google Inc.
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 GrStencilAndCoverTextContext_DEFINED
9#define GrStencilAndCoverTextContext_DEFINED
10
11#include "GrDrawTarget.h"
12#include "GrStrokeInfo.h"
13#include "SkDrawFilter.h"
14#include "SkTextBlob.h"
15#include "SkTHash.h"
16#include "SkTInternalLList.h"
17#include "SkTLList.h"
18#include "batches/GrDrawPathBatch.h"
19
20class GrAtlasTextContext;
21class GrTextStrike;
22class GrPath;
23class SkSurfaceProps;
24
25/*
26 * This class implements text rendering using stencil and cover path rendering
27 * (by the means of GrDrawTarget::drawPath).
28 */
29class GrStencilAndCoverTextContext {
30public:
31    static GrStencilAndCoverTextContext* Create();
32
33    void drawText(GrContext*, GrDrawContext* dc,
34                  const GrClip&,  const GrPaint&, const SkPaint&,
35                  const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
36                  size_t byteLength, SkScalar x,
37                  SkScalar y, const SkIRect& clipBounds);
38    void drawPosText(GrContext*, GrDrawContext*,
39                     const GrClip&, const GrPaint&, const SkPaint&,
40                     const SkMatrix& viewMatrix, const SkSurfaceProps&,
41                     const char text[], size_t byteLength,
42                     const SkScalar pos[], int scalarsPerPosition,
43                     const SkPoint& offset, const SkIRect& clipBounds);
44    void drawTextBlob(GrContext*, GrDrawContext*, const GrClip&, const SkPaint&,
45                      const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
46                      SkScalar x, SkScalar y,
47                      SkDrawFilter*, const SkIRect& clipBounds);
48
49    virtual ~GrStencilAndCoverTextContext();
50
51private:
52    GrStencilAndCoverTextContext();
53
54    bool canDraw(const SkPaint& skPaint, const SkMatrix&) {
55        return this->internalCanDraw(skPaint);
56    }
57
58    bool internalCanDraw(const SkPaint&);
59
60    void uncachedDrawTextBlob(GrContext*, GrDrawContext* dc,
61                              const GrClip& clip, const SkPaint& skPaint,
62                              const SkMatrix& viewMatrix,
63                              const SkSurfaceProps&,
64                              const SkTextBlob* blob,
65                              SkScalar x, SkScalar y,
66                              SkDrawFilter* drawFilter,
67                              const SkIRect& clipBounds);
68
69    class FallbackBlobBuilder;
70
71    class TextRun {
72    public:
73        TextRun(const SkPaint& fontAndStroke);
74        ~TextRun();
75
76        void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y);
77
78        void setPosText(const char text[], size_t byteLength, const SkScalar pos[],
79                        int scalarsPerPosition, const SkPoint& offset);
80
81        void draw(GrContext*, GrDrawContext*, GrPipelineBuilder*, GrColor, const SkMatrix&,
82                  const SkSurfaceProps&,
83                  SkScalar x, SkScalar y, const SkIRect& clipBounds,
84                  GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const;
85
86        void releaseGlyphCache() const;
87
88        size_t computeSizeInCache() const;
89
90    private:
91        typedef GrDrawPathRangeBatch::InstanceData InstanceData;
92
93        SkGlyphCache* getGlyphCache() const;
94        GrPathRange* createGlyphs(GrContext*) const;
95        void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*);
96
97        GrStrokeInfo                     fStroke;
98        SkPaint                          fFont;
99        SkScalar                         fTextRatio;
100        float                            fTextInverseRatio;
101        bool                             fUsingRawGlyphPaths;
102        GrUniqueKey                      fGlyphPathsKey;
103        int                              fTotalGlyphCount;
104        SkAutoTUnref<InstanceData>       fInstanceData;
105        int                              fFallbackGlyphCount;
106        SkAutoTUnref<const SkTextBlob>   fFallbackTextBlob;
107        mutable SkGlyphCache*            fDetachedGlyphCache;
108        mutable uint32_t                 fLastDrawnGlyphsID;
109    };
110
111    // Text blobs/caches.
112
113    class TextBlob : public SkTLList<TextRun, 1> {
114    public:
115        typedef SkTArray<uint32_t, true> Key;
116
117        static const Key& GetKey(const TextBlob* blob) { return blob->key(); }
118
119        static uint32_t Hash(const Key& key) {
120            SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map.
121            return SkChecksum::Murmur3(key.begin(), sizeof(uint32_t) * key.count());
122        }
123
124        TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint)
125            : fKey(&blobId, 1) { this->init(skBlob, skPaint); }
126
127        TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint)
128            : fKey(key) {
129            // 1-length keys are unterstood to be the blob id and must use the other constructor.
130            SkASSERT(fKey.count() > 1);
131            this->init(skBlob, skPaint);
132        }
133
134        const Key& key() const { return fKey; }
135
136        size_t cpuMemorySize() const { return fCpuMemorySize; }
137
138    private:
139        void init(const SkTextBlob*, const SkPaint&);
140
141        const SkSTArray<1, uint32_t, true>   fKey;
142        size_t                               fCpuMemorySize;
143
144        SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
145    };
146
147    const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&);
148    void purgeToFit(const TextBlob&);
149
150    GrAtlasTextContext*                                       fFallbackTextContext;
151    SkTHashMap<uint32_t, TextBlob*>                           fBlobIdCache;
152    SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob>   fBlobKeyCache;
153    SkTInternalLList<TextBlob>                                fLRUList;
154    size_t                                                    fCacheSize;
155};
156
157#endif
158