Home | History | Annotate | Download | only in fiddle
      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