1/*
2 * Copyright 2015 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 GrAtlasTextContext_DEFINED
9#define GrAtlasTextContext_DEFINED
10
11#include "GrAtlasTextBlob.h"
12#include "GrDistanceFieldAdjustTable.h"
13#include "GrGeometryProcessor.h"
14#include "GrTextUtils.h"
15#include "SkTextBlobRunIterator.h"
16
17#if GR_TEST_UTILS
18#include "GrDrawOpTest.h"
19#endif
20
21class GrDrawOp;
22class GrTextBlobCache;
23class SkGlyph;
24
25/*
26 * Renders text using some kind of an atlas, ie BitmapText or DistanceField text
27 */
28class GrAtlasTextContext {
29public:
30    struct Options {
31        /**
32         * Below this size (in device space) distance field text will not be used. Negative means
33         * use a default value.
34         */
35        SkScalar fMinDistanceFieldFontSize = -1.f;
36        /**
37         * Above this size (in device space) distance field text will not be used and glyphs will
38         * be rendered from outline as individual paths. Negative means use a default value.
39         */
40        SkScalar fMaxDistanceFieldFontSize = -1.f;
41        /** Forces all distance field vertices to use 3 components, not just when in perspective. */
42        bool fDistanceFieldVerticesAlwaysHaveW = false;
43    };
44
45    static std::unique_ptr<GrAtlasTextContext> Make(const Options& options);
46
47    void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
48                  const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
49                  size_t byteLength, SkScalar x, SkScalar y, const SkIRect& regionClipBounds);
50    void drawPosText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
51                     const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
52                     size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
53                     const SkPoint& offset, const SkIRect& regionClipBounds);
54    void drawTextBlob(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
55                      const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
56                      SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds);
57
58private:
59    GrAtlasTextContext(const Options& options);
60
61    class FallbackTextHelper {
62    public:
63        FallbackTextHelper(const SkMatrix& viewMatrix,
64                           const SkPaint& pathPaint,
65                           const GrGlyphCache* glyphCache,
66                           SkScalar textRatio)
67            : fViewMatrix(viewMatrix)
68            , fTextSize(pathPaint.getTextSize())
69            , fMaxTextSize(glyphCache->getGlyphSizeLimit())
70            , fTextRatio(textRatio)
71            , fScaledFallbackTextSize(fMaxTextSize)
72            , fUseScaledFallback(false) {
73            fMaxScale = viewMatrix.getMaxScale();
74        }
75
76        void appendText(const SkGlyph& glyph, int count, const char* text, SkPoint glyphPos);
77        void drawText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
78                      const GrTextUtils::Paint&, SkScalerContextFlags);
79
80    private:
81        SkTDArray<char> fFallbackTxt;
82        SkTDArray<SkPoint> fFallbackPos;
83
84        const SkMatrix& fViewMatrix;
85        SkScalar fTextSize;
86        SkScalar fMaxTextSize;
87        SkScalar fTextRatio;
88        SkScalar fScaledFallbackTextSize;
89        SkScalar fMaxScale;
90        bool fUseScaledFallback;
91    };
92
93    // sets up the descriptor on the blob and returns a detached cache.  Client must attach
94    static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
95    // Determines if we need to use fake gamma (and contrast boost):
96    static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&);
97    void regenerateTextBlob(GrAtlasTextBlob* bmp,
98                            GrGlyphCache*,
99                            const GrShaderCaps&,
100                            const GrTextUtils::Paint&,
101                            SkScalerContextFlags scalerContextFlags,
102                            const SkMatrix& viewMatrix,
103                            const SkSurfaceProps&,
104                            const SkTextBlob* blob, SkScalar x, SkScalar y,
105                            SkDrawFilter* drawFilter) const;
106
107    static bool HasLCD(const SkTextBlob*);
108
109    sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrGlyphCache*,
110                                            const GrShaderCaps&,
111                                            const GrTextUtils::Paint&,
112                                            SkScalerContextFlags scalerContextFlags,
113                                            const SkMatrix& viewMatrix,
114                                            const SkSurfaceProps&,
115                                            const char text[], size_t byteLength,
116                                            SkScalar x, SkScalar y) const;
117
118    sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
119                                               const GrShaderCaps&,
120                                               const GrTextUtils::Paint&,
121                                               SkScalerContextFlags scalerContextFlags,
122                                               const SkMatrix& viewMatrix,
123                                               const SkSurfaceProps&,
124                                               const char text[], size_t byteLength,
125                                               const SkScalar pos[],
126                                               int scalarsPerPosition,
127                                               const SkPoint& offset) const;
128
129    // Functions for appending BMP text to GrAtlasTextBlob
130    static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
131                            const SkSurfaceProps&, const GrTextUtils::Paint& paint,
132                            SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
133                            const char text[], size_t byteLength, SkScalar x, SkScalar y);
134
135    static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
136                               const SkSurfaceProps&, const GrTextUtils::Paint& paint,
137                               SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
138                               const char text[], size_t byteLength, const SkScalar pos[],
139                               int scalarsPerPosition, const SkPoint& offset);
140
141    static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
142                                   const SkSurfaceProps&, const GrTextUtils::Paint& paint,
143                                   SkScalerContextFlags scalerContextFlags,
144                                   const SkMatrix& viewMatrix, const char text[],
145                                   size_t byteLength, SkScalar x, SkScalar y);
146
147    static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
148                                      const SkSurfaceProps&, const GrTextUtils::Paint& paint,
149                                      SkScalerContextFlags scalerContextFlags,
150                                      const SkMatrix& viewMatrix,
151                                      const char text[], size_t byteLength,
152                                      const SkScalar pos[], int scalarsPerPosition,
153                                      const SkPoint& offset);
154
155    // functions for appending distance field text
156    bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix,
157                                 const SkSurfaceProps& props, const GrShaderCaps& caps) const;
158
159    void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
160                    const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags,
161                    const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x,
162                    SkScalar y) const;
163
164    void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*,
165                       const SkSurfaceProps&, const GrTextUtils::Paint& paint,
166                       SkScalerContextFlags scalerContextFlags,
167                       const SkMatrix& viewMatrix, const char text[],
168                       size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
169                       const SkPoint& offset) const;
170
171    void initDistanceFieldPaint(GrAtlasTextBlob* blob,
172                                SkPaint* skPaint,
173                                SkScalar* textRatio,
174                                const SkMatrix& viewMatrix) const;
175
176    static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
177                               sk_sp<GrTextStrike>*, const SkGlyph&, SkScalar sx, SkScalar sy,
178                               GrColor color, SkGlyphCache*, SkScalar textRatio);
179
180    static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
181                              sk_sp<GrTextStrike>*, const SkGlyph&, SkScalar sx, SkScalar sy,
182                              GrColor color, SkGlyphCache* cache, SkScalar textRatio);
183
184    const GrDistanceFieldAdjustTable* dfAdjustTable() const { return fDistanceAdjustTable.get(); }
185
186    sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
187
188    SkScalar fMinDistanceFieldFontSize;
189    SkScalar fMaxDistanceFieldFontSize;
190    bool fDistanceFieldVerticesAlwaysHaveW;
191
192#if GR_TEST_UTILS
193    static const SkScalerContextFlags kTextBlobOpScalerContextFlags =
194            SkScalerContextFlags::kFakeGammaAndBoostContrast;
195    GR_DRAW_OP_TEST_FRIEND(GrAtlasTextOp);
196#endif
197};
198
199#endif
200