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 "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