• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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