| Index: experimental/tools/coreGraphicsPdf2png.cpp | 
| diff --git a/experimental/tools/coreGraphicsPdf2png.cpp b/experimental/tools/coreGraphicsPdf2png.cpp | 
| index a8459326162428c5886330badd422193b2dc626e..c747a269ae0f868da865b11170e77496f373a1a6 100644 | 
| --- a/experimental/tools/coreGraphicsPdf2png.cpp | 
| +++ b/experimental/tools/coreGraphicsPdf2png.cpp | 
| @@ -5,56 +5,72 @@ | 
| * found in the LICENSE file. | 
| */ | 
|  | 
| -#include <stdio.h> | 
| - | 
| -#include "SkBitmap.h" | 
| -#include "SkCGUtils.h" | 
| -#include "SkForceLinking.h" | 
| -#include "SkImageEncoder.h" | 
| -#include "SkStream.h" | 
| - | 
| -__SK_FORCE_IMAGE_DECODER_LINKING; | 
| - | 
| -class StdOutWStream : public SkWStream { | 
| -public: | 
| -    StdOutWStream() : fBytesWritten(0) {} | 
| -    bool write(const void* buffer, size_t size) final { | 
| -        fBytesWritten += size; | 
| -        return size == fwrite(buffer, 1, size, stdout); | 
| -    } | 
| -    size_t bytesWritten() const final { return fBytesWritten; } | 
| +//  c++ --std=c++11 coreGraphicsPdf2png.cpp -o coreGraphicsPdf2png  -framework ApplicationServices | 
|  | 
| -private: | 
| -    size_t fBytesWritten; | 
| -}; | 
| +#include <cstdio> | 
| +#include <memory> | 
|  | 
| -static SkStreamAsset* open_for_reading(const char* path) { | 
| -    if (!path || !path[0] || 0 == strcmp(path, "-")) { | 
| -        return new SkFILEStream(stdin, SkFILEStream::kCallerRetains_Ownership); | 
| -    } | 
| -    return SkStream::NewFromFile(path); | 
| -} | 
| +#include <ApplicationServices/ApplicationServices.h> | 
|  | 
| -static SkWStream* open_for_writing(const char* path) { | 
| -    if (!path || !path[0] || 0 == strcmp(path, "-")) { | 
| -        return new StdOutWStream; | 
| -    } | 
| -    return new SkFILEWStream(path); | 
| -} | 
| +#define ASSERT(x)                                \ | 
| +    do {                                         \ | 
| +        if (!(x)) {                              \ | 
| +            fprintf(stderr, "ERROR: " __FILE__   \ | 
| +                    ":%d (%s)\n", __LINE__, #x); \ | 
| +            return 1;                            \ | 
| +        }                                        \ | 
| +    } while (false)                              \ | 
|  | 
| -static bool to_png(SkWStream* o, const SkBitmap& bm) { | 
| -    return SkImageEncoder::EncodeStream(o, bm, SkImageEncoder::kPNG_Type, 100); | 
| -} | 
| +const int PAGE = 1; | 
|  | 
| -// Note: I could implement this using only MacOS|CG API calls, but | 
| -// since most of this is already done in Skia, here it is. | 
| int main(int argc, char** argv) { | 
| -    SkBitmap bm; | 
| -    SkAutoTDelete<SkStream> in(open_for_reading(argc > 1 ? argv[1] : NULL)); | 
| -    SkAutoTDelete<SkWStream> out(open_for_writing(argc > 2 ? argv[2] : NULL)); | 
| -    if (SkPDFDocumentToBitmap(in.release(), &bm) && to_png(out, bm)) { | 
| -        return 0; | 
| -    } else { | 
| +    if (argc <= 1 || !*(argv[1]) || 0 == strcmp(argv[1], "-")) { | 
| +        fprintf(stderr, "usage:\n\t%s INPUT_PDF_FILE_PATH [OUTPUT_PNG_PATH]\n", argv[0]); | 
| return 1; | 
| } | 
| +    const char* output = argc > 2 ? argv[2] : nullptr; | 
| +    CGDataProviderRef data = CGDataProviderCreateWithFilename(argv[1]); | 
| +    ASSERT(data); | 
| +    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data); | 
| +    CGDataProviderRelease(data); | 
| +    ASSERT(pdf); | 
| +    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, PAGE); | 
| +    ASSERT(page); | 
| +    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); | 
| +    int w = (int)CGRectGetWidth(bounds); | 
| +    int h = (int)CGRectGetHeight(bounds); | 
| +    CGBitmapInfo info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast; | 
| +    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); | 
| +    ASSERT(cs); | 
| +    std::unique_ptr<uint32_t[]> bitmap(new uint32_t[w * h]); | 
| +    memset(bitmap.get(), 0xFF, 4 * w * h); | 
| +    CGContextRef ctx = CGBitmapContextCreate(bitmap.get(), w, h, 8, w * 4, cs, info); | 
| +    ASSERT(ctx); | 
| +    CGContextDrawPDFPage(ctx, page); | 
| +    CGPDFDocumentRelease(pdf); | 
| +    CGImageRef image = CGBitmapContextCreateImage(ctx); | 
| +    ASSERT(image); | 
| +    CGDataConsumerCallbacks procs; | 
| +    procs.putBytes = [](void* f, const void* buf, size_t s) { | 
| +        return fwrite(buf, 1, s, (FILE*)f); | 
| +    }; | 
| +    procs.releaseConsumer = [](void* info) { fclose((FILE*)info); }; | 
| +    FILE* ofile = (!output || !output[0] || 0 == strcmp(output, "-")) | 
| +        ? stdout : fopen(output, "wb"); | 
| +    ASSERT(ofile); | 
| +    CGDataConsumerRef consumer = CGDataConsumerCreate(ofile, &procs); | 
| +    ASSERT(consumer); | 
| +    CGImageDestinationRef dst = | 
| +        CGImageDestinationCreateWithDataConsumer(consumer, kUTTypePNG, 1, nullptr); | 
| +    CFRelease(consumer); | 
| +    ASSERT(dst); | 
| +    CGImageDestinationAddImage(dst, image, nullptr); | 
| +    ASSERT(CGImageDestinationFinalize(dst)); | 
| +    CFRelease(dst); | 
| +    CGImageRelease(image); | 
| +    CGColorSpaceRelease(cs); | 
| +    CGContextRelease(ctx); | 
| +    return 0; | 
| } | 
| + | 
| + | 
|  |