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