
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkCGUtils.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"

static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
    delete bitmap;
}

static bool getBitmapInfo(const SkBitmap& bm,
                          size_t* bitsPerComponent,
                          CGBitmapInfo* info,
                          bool* upscaleTo32) {
    if (upscaleTo32) {
        *upscaleTo32 = false;
    }

    switch (bm.colorType()) {
        case kRGB_565_SkColorType:
#if 0
            // doesn't see quite right. Are they thinking 1555?
            *bitsPerComponent = 5;
            *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone;
            break;
#endif
            if (upscaleTo32) {
                *upscaleTo32 = true;
            }
            // fall through
        case kPMColor_SkColorType:
            *bitsPerComponent = 8;
#if SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
            *info = kCGBitmapByteOrder32Big;
            if (bm.isOpaque()) {
                *info |= kCGImageAlphaNoneSkipLast;
            } else {
                *info |= kCGImageAlphaPremultipliedLast;
            }
#elif SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
            // Matches the CGBitmapInfo that Apple recommends for best
            // performance, used by google chrome.
            *info = kCGBitmapByteOrder32Little;
            if (bm.isOpaque()) {
                *info |= kCGImageAlphaNoneSkipFirst;
            } else {
                *info |= kCGImageAlphaPremultipliedFirst;
            }
#else
            // ...add more formats as required...
#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
This will probably not work.
            // Legacy behavior. Perhaps turn this into an error at some
            // point.
            *info = kCGBitmapByteOrder32Big;
            if (bm.isOpaque()) {
                *info |= kCGImageAlphaNoneSkipLast;
            } else {
                *info |= kCGImageAlphaPremultipliedLast;
            }
#endif
            break;
        case kARGB_4444_SkColorType:
            *bitsPerComponent = 4;
            *info = kCGBitmapByteOrder16Little;
            if (bm.isOpaque()) {
                *info |= kCGImageAlphaNoneSkipLast;
            } else {
                *info |= kCGImageAlphaPremultipliedLast;
            }
            break;
        default:
            return false;
    }
    return true;
}

static SkBitmap* prepareForImageRef(const SkBitmap& bm,
                                    size_t* bitsPerComponent,
                                    CGBitmapInfo* info) {
    bool upscaleTo32;
    if (!getBitmapInfo(bm, bitsPerComponent, info, &upscaleTo32)) {
        return NULL;
    }

    SkBitmap* copy;
    if (upscaleTo32) {
        copy = new SkBitmap;
        // here we make a ceep copy of the pixels, since CG won't take our
        // 565 directly
        bm.copyTo(copy, kPMColor_SkColorType);
    } else {
        copy = new SkBitmap(bm);
    }
    return copy;
}

CGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
                                            CGColorSpaceRef colorSpace) {
    size_t bitsPerComponent SK_INIT_TO_AVOID_WARNING;
    CGBitmapInfo info       SK_INIT_TO_AVOID_WARNING;

    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
    if (NULL == bitmap) {
        return NULL;
    }

    const int w = bitmap->width();
    const int h = bitmap->height();
    const size_t s = bitmap->getSize();

    // our provider "owns" the bitmap*, and will take care of deleting it
    // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
    // proc, which will in turn unlock the pixels
    bitmap->lockPixels();
    CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
                                                             SkBitmap_ReleaseInfo);

    bool releaseColorSpace = false;
    if (NULL == colorSpace) {
        colorSpace = CGColorSpaceCreateDeviceRGB();
        releaseColorSpace = true;
    }

    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
                                   bitmap->bytesPerPixel() * 8,
                                   bitmap->rowBytes(), colorSpace, info, dataRef,
                                   NULL, false, kCGRenderingIntentDefault);

    if (releaseColorSpace) {
        CGColorSpaceRelease(colorSpace);
    }
    CGDataProviderRelease(dataRef);
    return ref;
}

void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
    CGImageRef img = SkCreateCGImageRef(bm);

    if (img) {
        CGRect r = CGRectMake(0, 0, bm.width(), bm.height());

        CGContextSaveGState(cg);
        CGContextTranslateCTM(cg, x, r.size.height + y);
        CGContextScaleCTM(cg, 1, -1);

        CGContextDrawImage(cg, r, img);

        CGContextRestoreGState(cg);

        CGImageRelease(img);
    }
}

///////////////////////////////////////////////////////////////////////////////

#include "SkStream.h"

class SkAutoPDFRelease {
public:
    SkAutoPDFRelease(CGPDFDocumentRef doc) : fDoc(doc) {}
    ~SkAutoPDFRelease() {
        if (fDoc) {
            CGPDFDocumentRelease(fDoc);
        }
    }
private:
    CGPDFDocumentRef fDoc;
};
#define SkAutoPDFRelease(...) SK_REQUIRE_LOCAL_VAR(SkAutoPDFRelease)

static void CGDataProviderReleaseData_FromMalloc(void*, const void* data,
                                                 size_t size) {
    sk_free((void*)data);
}

bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
    size_t size = stream->getLength();
    void* ptr = sk_malloc_throw(size);
    stream->read(ptr, size);
    CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size,
                                          CGDataProviderReleaseData_FromMalloc);
    if (NULL == data) {
        return false;
    }

    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
    CGDataProviderRelease(data);
    if (NULL == pdf) {
        return false;
    }
    SkAutoPDFRelease releaseMe(pdf);

    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
    if (NULL == page) {
        return false;
    }

    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);

    int w = (int)CGRectGetWidth(bounds);
    int h = (int)CGRectGetHeight(bounds);

    SkBitmap bitmap;
    if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
        return false;
    }
    bitmap.eraseColor(SK_ColorWHITE);

    size_t bitsPerComponent;
    CGBitmapInfo info;
    getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL);

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h,
                                             bitsPerComponent, bitmap.rowBytes(),
                                             cs, info);
    CGColorSpaceRelease(cs);

    if (ctx) {
        CGContextDrawPDFPage(ctx, page);
        CGContextRelease(ctx);
    }

    output->swap(bitmap);
    return true;
}
