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/SkData.h"
13 #include "include/core/SkEncodedImageFormat.h"
14 #include "include/core/SkFont.h"
15 #include "include/core/SkFontStyle.h"
16 #include "include/core/SkFontTypes.h"
17 #include "include/core/SkImageEncoder.h"
18 #include "include/core/SkImageInfo.h"
19 #include "include/core/SkPixmap.h"
20 #include "include/core/SkRect.h"
21 #include "include/core/SkRefCnt.h"
22 #include "include/core/SkScalar.h"
23 #include "include/core/SkStream.h"
24 #include "include/core/SkSurface.h"
25 #include "include/core/SkTypeface.h"
26 #include "include/core/SkTypes.h"
27 #include "include/private/SkTArray.h"
28 #include "include/private/SkTDArray.h"
29 #include "include/utils/SkRandom.h"
30
31 class SkBitmap;
32 class SkCanvas;
33 class SkFontStyle;
34 class SkImage;
35 class SkPath;
36 class SkPixmap;
37 class SkRRect;
38 class SkShader;
39 class SkSurface;
40 class SkSurfaceProps;
41 class SkTextBlobBuilder;
42 class SkTypeface;
43
44 namespace ToolUtils {
45
46 const char* alphatype_name (SkAlphaType);
47 const char* colortype_name (SkColorType);
48 const char* colortype_depth(SkColorType); // like colortype_name, but channel order agnostic
49 const char* tilemode_name(SkTileMode);
50
51 /**
52 * Map opaque colors from 8888 to 565.
53 */
54 SkColor color_to_565(SkColor color);
55
56 /* Return a color emoji typeface with planets to scale if available. */
57 sk_sp<SkTypeface> planet_typeface();
58
59 /** Return a color emoji typeface if available. */
60 sk_sp<SkTypeface> emoji_typeface();
61
62 /** Sample text for the emoji_typeface font. */
63 const char* emoji_sample_text();
64
65 /**
66 * Returns a platform-independent text renderer.
67 */
68 sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style);
69
create_portable_typeface()70 static inline sk_sp<SkTypeface> create_portable_typeface() {
71 return create_portable_typeface(nullptr, SkFontStyle());
72 }
73
74 /**
75 * Turn on portable (--nonativeFonts) or GDI font rendering (--gdi).
76 */
77 void SetDefaultFontMgr();
78
79
80 void get_text_path(const SkFont&,
81 const void* text,
82 size_t length,
83 SkTextEncoding,
84 SkPath*,
85 const SkPoint* positions = nullptr);
86
87 /**
88 * Returns true iff all of the pixels between the two images are identical.
89 *
90 * If the configs differ, return false.
91 */
92 bool equal_pixels(const SkPixmap&, const SkPixmap&);
93 bool equal_pixels(const SkBitmap&, const SkBitmap&);
94 bool equal_pixels(const SkImage* a, const SkImage* b);
95
96 /** Returns a newly created CheckerboardShader. */
97 sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size);
98
99 /** Draw a checkerboard pattern in the current canvas, restricted to
100 the current clip, using SkXfermode::kSrc_Mode. */
101 void draw_checkerboard(SkCanvas* canvas, SkColor color1, SkColor color2, int checkSize);
102
103 /** Make it easier to create a bitmap-based checkerboard */
104 SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize);
105
106 /** A default checkerboard. */
draw_checkerboard(SkCanvas * canvas)107 inline void draw_checkerboard(SkCanvas* canvas) {
108 ToolUtils::draw_checkerboard(canvas, 0xFF999999, 0xFF666666, 8);
109 }
110
111 SkBitmap create_string_bitmap(int w, int h, SkColor c, int x, int y, int textSize, const char* str);
112
113 // If the canvas does't make a surface (e.g. recording), make a raster surface
114 sk_sp<SkSurface> makeSurface(SkCanvas*, const SkImageInfo&, const SkSurfaceProps* = nullptr);
115
116 // A helper for inserting a drawtext call into a SkTextBlobBuilder
117 void add_to_text_blob_w_len(SkTextBlobBuilder*,
118 const char* text,
119 size_t len,
120 SkTextEncoding,
121 const SkFont&,
122 SkScalar x,
123 SkScalar y);
124
125 void add_to_text_blob(SkTextBlobBuilder*, const char* text, const SkFont&, SkScalar x, SkScalar y);
126
127 // Constructs a star by walking a 'numPts'-sided regular polygon with even/odd fill:
128 //
129 // moveTo(pts[0]);
130 // lineTo(pts[step % numPts]);
131 // ...
132 // lineTo(pts[(step * (N - 1)) % numPts]);
133 //
134 // numPts=5, step=2 will produce a classic five-point star.
135 //
136 // numPts and step must be co-prime.
137 SkPath make_star(const SkRect& bounds, int numPts = 5, int step = 2);
138
139 void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst);
140
141 void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst);
142
143 void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);
144
145 void make_big_path(SkPath& path);
146
147 // A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
148 class TopoTestNode : public SkRefCnt {
149 public:
TopoTestNode(int id)150 TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) {}
151
dependsOn(TopoTestNode * src)152 void dependsOn(TopoTestNode* src) { *fDependencies.append() = src; }
153
id()154 int id() const { return fID; }
reset()155 void reset() { fOutputPos = -1; }
156
outputPos()157 int outputPos() const { return fOutputPos; }
158
159 // check that the topological sort is valid for this node
check()160 bool check() {
161 if (-1 == fOutputPos) {
162 return false;
163 }
164
165 for (int i = 0; i < fDependencies.count(); ++i) {
166 if (-1 == fDependencies[i]->outputPos()) {
167 return false;
168 }
169 // This node should've been output after all the nodes on which it depends
170 if (fOutputPos < fDependencies[i]->outputPos()) {
171 return false;
172 }
173 }
174
175 return true;
176 }
177
178 // The following 7 methods are needed by the topological sort
SetTempMark(TopoTestNode * node)179 static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; }
ResetTempMark(TopoTestNode * node)180 static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; }
IsTempMarked(TopoTestNode * node)181 static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; }
Output(TopoTestNode * node,int outputPos)182 static void Output(TopoTestNode* node, int outputPos) {
183 SkASSERT(-1 != outputPos);
184 node->fOutputPos = outputPos;
185 }
WasOutput(TopoTestNode * node)186 static bool WasOutput(TopoTestNode* node) { return (-1 != node->fOutputPos); }
NumDependencies(TopoTestNode * node)187 static int NumDependencies(TopoTestNode* node) { return node->fDependencies.count(); }
Dependency(TopoTestNode * node,int index)188 static TopoTestNode* Dependency(TopoTestNode* node, int index) {
189 return node->fDependencies[index];
190 }
191
192 // Helper functions for TopoSortBench & TopoSortTest
AllocNodes(SkTArray<sk_sp<ToolUtils::TopoTestNode>> * graph,int num)193 static void AllocNodes(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph, int num) {
194 graph->reserve(num);
195
196 for (int i = 0; i < num; ++i) {
197 graph->push_back(sk_sp<TopoTestNode>(new TopoTestNode(i)));
198 }
199 }
200
201 #ifdef SK_DEBUG
Print(const SkTArray<TopoTestNode * > & graph)202 static void Print(const SkTArray<TopoTestNode*>& graph) {
203 for (int i = 0; i < graph.count(); ++i) {
204 SkDebugf("%d, ", graph[i]->id());
205 }
206 SkDebugf("\n");
207 }
208 #endif
209
210 // randomize the array
Shuffle(SkTArray<sk_sp<TopoTestNode>> * graph,SkRandom * rand)211 static void Shuffle(SkTArray<sk_sp<TopoTestNode>>* graph, SkRandom* rand) {
212 for (int i = graph->count() - 1; i > 0; --i) {
213 int swap = rand->nextU() % (i + 1);
214
215 (*graph)[i].swap((*graph)[swap]);
216 }
217 }
218
219 private:
220 int fID;
221 int fOutputPos;
222 bool fTempMark;
223
224 SkTDArray<TopoTestNode*> fDependencies;
225 };
226
227 template <typename T>
EncodeImageToFile(const char * path,const T & src,SkEncodedImageFormat f,int q)228 inline bool EncodeImageToFile(const char* path, const T& src, SkEncodedImageFormat f, int q) {
229 SkFILEWStream file(path);
230 return file.isValid() && SkEncodeImage(&file, src, f, q);
231 }
232
233 bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
234 void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
235
236 class PixelIter {
237 public:
238 PixelIter();
PixelIter(SkSurface * surf)239 PixelIter(SkSurface* surf) {
240 SkPixmap pm;
241 if (!surf->peekPixels(&pm)) {
242 pm.reset();
243 }
244 this->reset(pm);
245 }
246
reset(const SkPixmap & pm)247 void reset(const SkPixmap& pm) {
248 fPM = pm;
249 fLoc = {-1, 0};
250 }
251
252 void* next(SkIPoint* loc = nullptr) {
253 if (!fPM.addr()) {
254 return nullptr;
255 }
256 fLoc.fX += 1;
257 if (fLoc.fX >= fPM.width()) {
258 fLoc.fX = 0;
259 if (++fLoc.fY >= fPM.height()) {
260 this->setDone();
261 return nullptr;
262 }
263 }
264 if (loc) {
265 *loc = fLoc;
266 }
267 return fPM.writable_addr(fLoc.fX, fLoc.fY);
268 }
269
setDone()270 void setDone() { fPM.reset(); }
271
272 private:
273 SkPixmap fPM;
274 SkIPoint fLoc;
275 };
276
277 } // namespace ToolUtils
278
279 #endif // ToolUtils_DEFINED
280