C++程序  |  156行  |  4.91 KB

/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <stdio.h>

#include <GL/osmesa.h>

#include "fiddle_main.h"

// Globals externed in fiddle_main.h
SkBitmap source;
SkImage* image(nullptr);

static void encode_to_base64(const void* data, size_t size, FILE* out) {
    const uint8_t* input = reinterpret_cast<const uint8_t*>(data);
    const uint8_t* end = &input[size];
    static const char codes[] =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz0123456789+/";
    while (input != end) {
        uint8_t b = (*input & 0xFC) >> 2;
        fputc(codes[b], out);
        b = (*input & 0x03) << 4;
        ++input;
        if (input == end) {
            fputc(codes[b], out);
            fputs("==", out);
            return;
        }
        b |= (*input & 0xF0) >> 4;
        fputc(codes[b], out);
        b = (*input & 0x0F) << 2;
        ++input;
        if (input == end) {
            fputc(codes[b], out);
            fputc('=', out);
            return;
        }
        b |= (*input & 0xC0) >> 6;
        fputc(codes[b], out);
        b = *input & 0x3F;
        fputc(codes[b], out);
        ++input;
    }
}

static void dump_output(SkData* data, const char* name, bool last = true) {
    if (data) {
        printf("\t\"%s\": \"", name);
        encode_to_base64(data->data(), data->size(), stdout);
        fputs(last ? "\"\n" : "\",\n", stdout);
    }
}

static SkData* encode_snapshot(SkSurface* surface) {
    SkAutoTUnref<SkImage> img(surface->newImageSnapshot());
    return img ? img->encode() : nullptr;
}

static OSMesaContext create_osmesa_context() {
    OSMesaContext osMesaContext =
        OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, nullptr);
    if (osMesaContext != nullptr) {
        static uint32_t buffer[16 * 16];
        OSMesaMakeCurrent(osMesaContext, &buffer, GL_UNSIGNED_BYTE, 16, 16);
    }
    return osMesaContext;
}

static GrContext* create_mesa_grcontext() {
    SkAutoTUnref<const GrGLInterface> mesa(GrGLCreateMesaInterface());
    intptr_t backend = reinterpret_cast<intptr_t>(mesa.get());
    return backend ? GrContext::Create(kOpenGL_GrBackend, backend) : nullptr;
}


int main() {
    const DrawOptions options = GetDrawOptions();
    fprintf(stderr, "%s\n", options.source);
    if (options.source) {
        SkAutoTUnref<SkData> data(SkData::NewFromFileName(options.source));
        if (!data) {
            perror(options.source);
            return 1;
        } else {
            image = SkImage::NewFromEncoded(data);
            if (!image) {
                perror("Unable to decode the source image.");
                return 1;
            }
            SkAssertResult(image->asLegacyBitmap(
                                   &source, SkImage::kRO_LegacyBitmapMode));
        }
    }
    SkAutoTUnref<SkData> rasterData, gpuData, pdfData, skpData;
    if (options.raster) {
        SkAutoTUnref<SkSurface> rasterSurface(
                SkSurface::NewRaster(SkImageInfo::MakeN32Premul(options.size)));
        draw(rasterSurface->getCanvas());
        rasterData.reset(encode_snapshot(rasterSurface));
    }
    if (options.gpu) {
        OSMesaContext osMesaContext = create_osmesa_context();
        SkAutoTUnref<GrContext> grContext(create_mesa_grcontext());
        if (!grContext) {
            fputs("Unable to get Mesa GrContext.\n", stderr);
        } else {
            SkAutoTUnref<SkSurface> surface(
                    SkSurface::NewRenderTarget(
                            grContext,
                            SkBudgeted::kNo,
                            SkImageInfo::MakeN32Premul(options.size)));
            if (!surface) {
                fputs("Unable to get render surface.\n", stderr);
                exit(1);
            }
            draw(surface->getCanvas());
            gpuData.reset(encode_snapshot(surface));
        }
        if (osMesaContext) {
            OSMesaDestroyContext(osMesaContext);
        }
    }
    if (options.pdf) {
        SkDynamicMemoryWStream pdfStream;
        SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdfStream));
        draw(document->beginPage(options.size.width(), options.size.height()));
        document->close();
        pdfData.reset(pdfStream.copyToData());
    }
    if (options.skp) {
        SkSize size;
        size = options.size;
        SkPictureRecorder recorder;
        draw(recorder.beginRecording(size.width(), size.height()));
        SkAutoTUnref<SkPicture> picture(recorder.endRecordingAsPicture());
        SkDynamicMemoryWStream skpStream;
        picture->serialize(&skpStream);
        skpData.reset(skpStream.copyToData());
    }

    printf("{\n");
    dump_output(rasterData, "Raster", !gpuData && !pdfData && !skpData);
    dump_output(gpuData, "Gpu", !pdfData && !skpData);
    dump_output(pdfData, "Pdf", !skpData);
    dump_output(skpData, "Skp");
    printf("}\n");

    SkSafeSetNull(image);
    return 0;
}