• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkDebugf(const char * fmt,...)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 
encode_to_base64(const void * data,size_t size,FILE * out)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 
dump_output(const void * data,size_t size,const char * name,bool last=true)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 
dump_output(const sk_sp<SkData> & data,const char * name,bool last=true)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 
encode_snapshot(const sk_sp<SkSurface> & surface)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 
prepare_canvas(SkCanvas * canvas)96 static SkCanvas* prepare_canvas(SkCanvas * canvas) {
97     canvas->clear(SK_ColorWHITE);
98     return canvas;
99 }
100 
main(int argc,char ** argv)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