Coverage Report

Created: 2024-05-20 07:14

/src/skia/tools/ToolUtils.h
Line
Count
Source (jump to first uncovered line)
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 ToolUtils_DEFINED
9
#define ToolUtils_DEFINED
10
11
#include "include/core/SkColor.h"
12
#include "include/core/SkFontArguments.h"
13
#include "include/core/SkFontParameters.h"
14
#include "include/core/SkFontStyle.h"
15
#include "include/core/SkPixmap.h"
16
#include "include/core/SkPoint.h"
17
#include "include/core/SkRect.h"
18
#include "include/core/SkRefCnt.h"
19
#include "include/core/SkScalar.h"
20
#include "include/core/SkSpan.h"
21
#include "include/core/SkString.h"
22
#include "include/core/SkSurface.h"
23
#include "include/core/SkTypeface.h"  // IWYU pragma: keep
24
#include "include/core/SkTypes.h"
25
#include "include/private/base/SkDebug.h"
26
#include "include/private/base/SkTArray.h"
27
#include "include/private/base/SkTDArray.h"
28
#include "src/base/SkRandom.h"
29
#include "src/base/SkTInternalLList.h"
30
31
#include <cstddef>
32
#include <cstdint>
33
#include <memory>
34
#include <vector>
35
#include <functional>
36
37
class SkBitmap;
38
class SkCanvas;
39
class SkFont;
40
class SkImage;
41
class SkMatrix;
42
class SkMetaData;
43
class SkPaint;
44
class SkPath;
45
class SkShader;
46
class SkSurfaceProps;
47
class SkTextBlobBuilder;
48
enum SkAlphaType : int;
49
enum SkColorType : int;
50
enum class SkTextEncoding;
51
enum class SkTileMode;
52
struct SkImageInfo;
53
54
namespace ToolUtils {
55
56
const char* alphatype_name (SkAlphaType);
57
const char* colortype_name (SkColorType);
58
const char* colortype_depth(SkColorType);  // like colortype_name, but channel order agnostic
59
const char* tilemode_name(SkTileMode);
60
61
/**
62
 * Map opaque colors from 8888 to 565.
63
 */
64
SkColor color_to_565(SkColor color);
65
66
void get_text_path(const SkFont&,
67
                   const void* text,
68
                   size_t      length,
69
                   SkTextEncoding,
70
                   SkPath*,
71
                   const SkPoint* positions = nullptr);
72
73
/**
74
 *  Returns true iff all of the pixels between the two images are identical.
75
 *
76
 *  If the configs differ, return false.
77
 */
78
bool equal_pixels(const SkPixmap&, const SkPixmap&);
79
bool equal_pixels(const SkBitmap&, const SkBitmap&);
80
bool equal_pixels(const SkImage* a, const SkImage* b);
81
82
/** Returns a newly created CheckerboardShader. */
83
sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size);
84
85
/** Draw a checkerboard pattern in the current canvas, restricted to
86
    the current clip, using SkBlendMode::kSrc. */
87
void draw_checkerboard(SkCanvas* canvas, SkColor color1, SkColor color2, int checkSize);
88
89
/** Make it easier to create a bitmap-based checkerboard */
90
SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize);
91
92
sk_sp<SkImage> create_checkerboard_image(int w, int h, SkColor c1, SkColor c2, int checkSize);
93
94
/** A default checkerboard. */
95
0
inline void draw_checkerboard(SkCanvas* canvas) {
96
0
    ToolUtils::draw_checkerboard(canvas, 0xFF999999, 0xFF666666, 8);
97
0
}
98
99
class HilbertGenerator {
100
public:
101
    HilbertGenerator(float desiredSize, float desiredLineWidth, int desiredDepth);
102
103
    // Draw a Hilbert curve into the canvas w/ a gradient along its length
104
    void draw(SkCanvas* canvas);
105
106
private:
107
    void turn90(bool turnLeft);
108
    void line(SkCanvas* canvas);
109
    void recursiveDraw(SkCanvas* canvas, int curDepth, bool turnLeft);
110
    SkColor4f getColor(float curLen);
111
112
    const float fDesiredSize;
113
    const int fDesiredDepth;
114
    const float fSegmentLength;            // length of a line segment
115
    const float fDesiredLineWidth;
116
117
    SkRect fActualBounds;
118
119
    // The "turtle" state
120
    SkPoint fCurPos;
121
    int fCurDir;
122
123
    const float fExpectedLen;
124
    float fCurLen;
125
};
126
127
/** Create pixmaps to initialize a 32x32 image w/ or w/o mipmaps.
128
 *  Returns the number of levels (either 1 or 6). The mipmap levels will be colored as
129
 *  specified in 'colors'
130
 */
131
int make_pixmaps(SkColorType,
132
                 SkAlphaType,
133
                 bool withMips,
134
                 const SkColor4f colors[6],
135
                 SkPixmap pixmaps[6],
136
                 std::unique_ptr<char[]>* mem);
137
138
// If the canvas doesn't make a surface (e.g. recording), make a raster surface
139
sk_sp<SkSurface> makeSurface(SkCanvas*, const SkImageInfo&, const SkSurfaceProps* = nullptr);
140
141
// A helper for inserting a drawtext call into a SkTextBlobBuilder
142
void add_to_text_blob_w_len(SkTextBlobBuilder*,
143
                            const char* text,
144
                            size_t      len,
145
                            SkTextEncoding,
146
                            const SkFont&,
147
                            SkScalar x,
148
                            SkScalar y);
149
150
void add_to_text_blob(SkTextBlobBuilder*, const char* text, const SkFont&, SkScalar x, SkScalar y);
151
152
// Constructs a star by walking a 'numPts'-sided regular polygon with even/odd fill:
153
//
154
//   moveTo(pts[0]);
155
//   lineTo(pts[step % numPts]);
156
//   ...
157
//   lineTo(pts[(step * (N - 1)) % numPts]);
158
//
159
// numPts=5, step=2 will produce a classic five-point star.
160
//
161
// numPts and step must be co-prime.
162
SkPath make_star(const SkRect& bounds, int numPts = 5, int step = 2);
163
164
void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst);
165
166
void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst);
167
168
void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);
169
170
// A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
171
class TopoTestNode : public SkRefCnt {
172
public:
173
0
    TopoTestNode(int id) : fID(id) {}
174
175
0
    void dependsOn(TopoTestNode* src) { *fDependencies.append() = src; }
176
0
    void targets(uint32_t target) { *fTargets.append() = target; }
177
178
0
    int  id() const { return fID; }
179
0
    void reset() {
180
0
        fOutputPos = 0;
181
0
        fTempMark = false;
182
0
        fWasOutput = false;
183
0
    }
184
185
0
    uint32_t outputPos() const {
186
0
        SkASSERT(fWasOutput);
187
0
        return fOutputPos;
188
0
    }
189
190
    // check that the topological sort is valid for this node
191
0
    bool check() {
192
0
        if (!fWasOutput) {
193
0
            return false;
194
0
        }
195
0
196
0
        for (int i = 0; i < fDependencies.size(); ++i) {
197
0
            if (!fDependencies[i]->fWasOutput) {
198
0
                return false;
199
0
            }
200
0
            // This node should've been output after all the nodes on which it depends
201
0
            if (fOutputPos < fDependencies[i]->outputPos()) {
202
0
                return false;
203
0
            }
204
0
        }
205
0
206
0
        return true;
207
0
    }
208
209
    // The following 7 methods are needed by the topological sort
210
0
    static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; }
211
0
    static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; }
212
0
    static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; }
213
0
    static void Output(TopoTestNode* node, uint32_t outputPos) {
214
0
        SkASSERT(!node->fWasOutput);
215
0
        node->fOutputPos = outputPos;
216
0
        node->fWasOutput = true;
217
0
    }
218
0
    static bool          WasOutput(TopoTestNode* node) { return node->fWasOutput; }
219
0
    static uint32_t      GetIndex(TopoTestNode* node) { return node->outputPos(); }
220
0
    static int           NumDependencies(TopoTestNode* node) { return node->fDependencies.size(); }
221
0
    static TopoTestNode* Dependency(TopoTestNode* node, int index) {
222
0
        return node->fDependencies[index];
223
0
    }
224
0
    static int           NumTargets(TopoTestNode* node) { return node->fTargets.size(); }
225
0
    static uint32_t      GetTarget(TopoTestNode* node, int i) { return node->fTargets[i]; }
226
0
    static uint32_t      GetID(TopoTestNode* node) { return node->id(); }
227
228
    // Helper functions for TopoSortBench & TopoSortTest
229
0
    static void AllocNodes(skia_private::TArray<sk_sp<ToolUtils::TopoTestNode>>* graph, int num) {
230
0
        graph->reserve_exact(graph->size() + num);
231
0
232
0
        for (int i = 0; i < num; ++i) {
233
0
            graph->push_back(sk_sp<TopoTestNode>(new TopoTestNode(i)));
234
0
        }
235
0
    }
236
237
#ifdef SK_DEBUG
238
0
    static void Print(const skia_private::TArray<TopoTestNode*>& graph) {
239
0
        for (int i = 0; i < graph.size(); ++i) {
240
0
            SkDebugf("%d, ", graph[i]->id());
241
0
        }
242
0
        SkDebugf("\n");
243
0
    }
244
#endif
245
246
    // randomize the array
247
0
    static void Shuffle(SkSpan<sk_sp<TopoTestNode>> graph, SkRandom* rand) {
248
0
        for (size_t i = graph.size() - 1; i > 0; --i) {
249
0
            int swap = rand->nextU() % (i + 1);
250
0
251
0
            graph[i].swap(graph[swap]);
252
0
        }
253
0
    }
254
255
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(TopoTestNode);
256
257
private:
258
    int      fID;
259
    uint32_t fOutputPos = 0;
260
    bool     fTempMark = false;
261
    bool     fWasOutput = false;
262
263
    SkTDArray<TopoTestNode*> fDependencies;
264
    SkTDArray<uint32_t>      fTargets;
265
};
266
267
bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
268
void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
269
270
class PixelIter {
271
public:
272
    PixelIter();
273
0
    PixelIter(SkSurface* surf) {
274
0
        SkPixmap pm;
275
0
        if (!surf->peekPixels(&pm)) {
276
0
            pm.reset();
277
0
        }
278
0
        this->reset(pm);
279
0
    }
280
281
0
    void reset(const SkPixmap& pm) {
282
0
        fPM  = pm;
283
0
        fLoc = {-1, 0};
284
0
    }
285
286
0
    void* next(SkIPoint* loc = nullptr) {
287
0
        if (!fPM.addr()) {
288
0
            return nullptr;
289
0
        }
290
0
        fLoc.fX += 1;
291
0
        if (fLoc.fX >= fPM.width()) {
292
0
            fLoc.fX = 0;
293
0
            if (++fLoc.fY >= fPM.height()) {
294
0
                this->setDone();
295
0
                return nullptr;
296
0
            }
297
0
        }
298
0
        if (loc) {
299
0
            *loc = fLoc;
300
0
        }
301
0
        return fPM.writable_addr(fLoc.fX, fLoc.fY);
302
0
    }
303
304
0
    void setDone() { fPM.reset(); }
305
306
private:
307
    SkPixmap fPM;
308
    SkIPoint fLoc;
309
};
310
311
using PathSniffCallback = void(const SkMatrix&, const SkPath&, const SkPaint&);
312
313
// Calls the provided PathSniffCallback for each path in the given file.
314
// Supported file formats .skp. (See SvgPathExtractor for .svg)
315
void ExtractPathsFromSKP(const char filepath[], std::function<PathSniffCallback>);
316
317
// Initialised with a font, this class can be called to setup GM UI with sliders for font
318
// variations, and returns a set of variation coordinates that matches what the sliders in the UI
319
// are set to. Useful for testing variable font properties, see colrv1.cpp.
320
class VariationSliders {
321
public:
322
0
    VariationSliders() {}
323
324
    VariationSliders(SkTypeface*,
325
                     SkFontArguments::VariationPosition variationPosition = {nullptr, 0});
326
327
    bool writeControls(SkMetaData* controls);
328
329
    /* Scans controls for information about the variation axes that the user may have configured.
330
     * Optionally pass in a boolean to receive information on whether the axes were updated. */
331
    void readControls(const SkMetaData& controls, bool* changed = nullptr);
332
333
    SkSpan<const SkFontArguments::VariationPosition::Coordinate> getCoordinates();
334
335
    static SkString tagToString(SkFourByteTag tag);
336
337
private:
338
    struct AxisSlider {
339
        SkScalar current;
340
        SkFontParameters::Variation::Axis axis;
341
        SkString name;
342
    };
343
344
    std::vector<AxisSlider> fAxisSliders;
345
    std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoords;
346
    static constexpr size_t kAxisVarsSize = 3;
347
};
348
349
}  // namespace ToolUtils
350
351
#endif  // ToolUtils_DEFINED