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