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 #include <cstdio> 9 #include <cstdlib> 10 #include <sstream> 11 #include <string> 12 13 #include "SkCommandLineFlags.h" 14 15 #include "fiddle_main.h" 16 17 DEFINE_double(duration, 1.0, "The total duration, in seconds, of the animation we are drawing."); 18 DEFINE_double(frame, 1.0, "A double value in [0, 1] that specifies the point in animation to draw."); 19 20 // Globals externed in fiddle_main.h 21 SkBitmap source; 22 sk_sp<SkImage> image; 23 double duration; // The total duration of the animation in seconds. 24 double frame; // A value in [0, 1] of where we are in the animation. 25 26 // Global used by the local impl of SkDebugf. 27 std::ostringstream gTextOutput; 28 29 // Global to record the GL driver info via create_grcontext(). 30 std::ostringstream gGLDriverInfo; 31 32 void SkDebugf(const char * fmt, ...) { 33 va_list args; 34 va_start(args, fmt); 35 char formatbuffer[1024]; 36 int n = vsnprintf(formatbuffer, sizeof(formatbuffer), fmt, args); 37 va_end(args); 38 if (n>=0 && n<=int(sizeof(formatbuffer))) { 39 gTextOutput.write(formatbuffer, n); 40 } 41 } 42 43 static void encode_to_base64(const void* data, size_t size, FILE* out) { 44 const uint8_t* input = reinterpret_cast<const uint8_t*>(data); 45 const uint8_t* end = &input[size]; 46 static const char codes[] = 47 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 48 "abcdefghijklmnopqrstuvwxyz0123456789+/"; 49 while (input != end) { 50 uint8_t b = (*input & 0xFC) >> 2; 51 fputc(codes[b], out); 52 b = (*input & 0x03) << 4; 53 ++input; 54 if (input == end) { 55 fputc(codes[b], out); 56 fputs("==", out); 57 return; 58 } 59 b |= (*input & 0xF0) >> 4; 60 fputc(codes[b], out); 61 b = (*input & 0x0F) << 2; 62 ++input; 63 if (input == end) { 64 fputc(codes[b], out); 65 fputc('=', out); 66 return; 67 } 68 b |= (*input & 0xC0) >> 6; 69 fputc(codes[b], out); 70 b = *input & 0x3F; 71 fputc(codes[b], out); 72 ++input; 73 } 74 } 75 76 77 static void dump_output(const void* data, size_t size, 78 const char* name, bool last = true) { 79 printf("\t\"%s\": \"", name); 80 encode_to_base64(data, size, stdout); 81 fputs(last ? "\"\n" : "\",\n", stdout); 82 } 83 84 static void dump_output(const sk_sp<SkData>& data, 85 const char* name, bool last = true) { 86 if (data) { 87 dump_output(data->data(), data->size(), name, last); 88 } 89 } 90 91 static sk_sp<SkData> encode_snapshot(const sk_sp<SkSurface>& surface) { 92 sk_sp<SkImage> img(surface->makeImageSnapshot()); 93 return img ? img->encodeToData() : nullptr; 94 } 95 96 static SkCanvas* prepare_canvas(SkCanvas * canvas) { 97 canvas->clear(SK_ColorWHITE); 98 return canvas; 99 } 100 101 int main(int argc, char** argv) { 102 SkCommandLineFlags::Parse(argc, argv); 103 duration = FLAGS_duration; 104 frame = FLAGS_frame; 105 DrawOptions options = GetDrawOptions(); 106 // If textOnly then only do one type of image, otherwise the text 107 // output is duplicated for each type. 108 if (options.textOnly) { 109 options.raster = true; 110 options.gpu = false; 111 options.pdf = false; 112 options.skp = false; 113 } 114 if (options.source) { 115 sk_sp<SkData> data(SkData::MakeFromFileName(options.source)); 116 if (!data) { 117 perror(options.source); 118 return 1; 119 } else { 120 image = SkImage::MakeFromEncoded(std::move(data)); 121 if (!image) { 122 perror("Unable to decode the source image."); 123 return 1; 124 } 125 SkAssertResult(image->asLegacyBitmap( 126 &source, SkImage::kRO_LegacyBitmapMode)); 127 } 128 } 129 sk_sp<SkData> rasterData, gpuData, pdfData, skpData; 130 SkColorType colorType = kN32_SkColorType; 131 sk_sp<SkColorSpace> colorSpace = nullptr; 132 if (options.f16) { 133 SkASSERT(options.srgb); 134 colorType = kRGBA_F16_SkColorType; 135 colorSpace = SkColorSpace::MakeSRGBLinear(); 136 } else if (options.srgb) { 137 colorSpace = SkColorSpace::MakeSRGB(); 138 } 139 SkImageInfo info = SkImageInfo::Make(options.size.width(), options.size.height(), colorType, 140 kPremul_SkAlphaType, colorSpace); 141 if (options.raster) { 142 auto rasterSurface = SkSurface::MakeRaster(info); 143 srand(0); 144 draw(prepare_canvas(rasterSurface->getCanvas())); 145 rasterData = encode_snapshot(rasterSurface); 146 } 147 if (options.gpu) { 148 auto grContext = create_grcontext(gGLDriverInfo); 149 if (!grContext) { 150 fputs("Unable to get GrContext.\n", stderr); 151 } else { 152 auto surface = SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kNo, info); 153 if (!surface) { 154 fputs("Unable to get render surface.\n", stderr); 155 exit(1); 156 } 157 srand(0); 158 draw(prepare_canvas(surface->getCanvas())); 159 gpuData = encode_snapshot(surface); 160 } 161 } 162 if (options.pdf) { 163 SkDynamicMemoryWStream pdfStream; 164 sk_sp<SkDocument> document(SkDocument::MakePDF(&pdfStream)); 165 if (document) { 166 srand(0); 167 draw(prepare_canvas(document->beginPage(options.size.width(), options.size.height()))); 168 document->close(); 169 pdfData = pdfStream.detachAsData(); 170 } 171 } 172 if (options.skp) { 173 SkSize size; 174 size = options.size; 175 SkPictureRecorder recorder; 176 srand(0); 177 draw(prepare_canvas(recorder.beginRecording(size.width(), size.height()))); 178 auto picture = recorder.finishRecordingAsPicture(); 179 SkDynamicMemoryWStream skpStream; 180 picture->serialize(&skpStream); 181 skpData = skpStream.detachAsData(); 182 } 183 184 printf("{\n"); 185 if (!options.textOnly) { 186 dump_output(rasterData, "Raster", false); 187 dump_output(gpuData, "Gpu", false); 188 dump_output(pdfData, "Pdf", false); 189 dump_output(skpData, "Skp", false); 190 } else { 191 std::string textoutput = gTextOutput.str(); 192 dump_output(textoutput.c_str(), textoutput.length(), "Text", false); 193 } 194 std::string glinfo = gGLDriverInfo.str(); 195 dump_output(glinfo.c_str(), glinfo.length(), "GLInfo", true); 196 printf("}\n"); 197 198 return 0; 199 } 200