/*
 * MACDRV image functions
 *
 * Copyright 2013 Ken Thomases for CodeWeavers Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include "macdrv.h"
#include "winuser.h"

WINE_DEFAULT_DEBUG_CHANNEL(image);

#include "pshpack1.h"

typedef struct
{
    BYTE bWidth;
    BYTE bHeight;
    BYTE bColorCount;
    BYTE bReserved;
    WORD wPlanes;
    WORD wBitCount;
    DWORD dwBytesInRes;
    WORD nID;
} GRPICONDIRENTRY;

typedef struct
{
    WORD idReserved;
    WORD idType;
    WORD idCount;
    GRPICONDIRENTRY idEntries[1];
} GRPICONDIR;

#include "poppack.h"


/***********************************************************************
 *              create_cgimage_from_icon_bitmaps
 */
CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP hbmColor,
                                            unsigned char *color_bits, int color_size, HBITMAP hbmMask,
                                            unsigned char *mask_bits, int mask_size, int width,
                                            int height, int istep)
{
    int i;
    BOOL has_alpha = FALSE;
    DWORD *ptr;
    CGBitmapInfo alpha_format;
    CGColorSpaceRef colorspace;
    CFDataRef data;
    CGDataProviderRef provider;
    CGImageRef cgimage;

    /* draw the cursor frame to a temporary buffer then create a CGImage from that */
    memset(color_bits, 0x00, color_size);
    SelectObject(hdc, hbmColor);
    if (!DrawIconEx(hdc, 0, 0, icon, width, height, istep, NULL, DI_NORMAL))
    {
        WARN("Could not draw frame %d (walk past end of frames).\n", istep);
        return NULL;
    }

    /* check if the cursor frame was drawn with an alpha channel */
    for (i = 0, ptr = (DWORD*)color_bits; i < width * height; i++, ptr++)
        if ((has_alpha = (*ptr & 0xff000000) != 0)) break;

    if (has_alpha)
        alpha_format = kCGImageAlphaFirst;
    else
        alpha_format = kCGImageAlphaNoneSkipFirst;

    colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    if (!colorspace)
    {
        WARN("failed to create colorspace\n");
        return NULL;
    }

    data = CFDataCreate(NULL, (UInt8*)color_bits, color_size);
    if (!data)
    {
        WARN("failed to create data\n");
        CGColorSpaceRelease(colorspace);
        return NULL;
    }

    provider = CGDataProviderCreateWithCFData(data);
    CFRelease(data);
    if (!provider)
    {
        WARN("failed to create data provider\n");
        CGColorSpaceRelease(colorspace);
        return NULL;
    }

    cgimage = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
                            alpha_format | kCGBitmapByteOrder32Little,
                            provider, NULL, FALSE, kCGRenderingIntentDefault);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorspace);
    if (!cgimage)
    {
        WARN("failed to create image\n");
        return NULL;
    }

    /* if no alpha channel was drawn then generate it from the mask */
    if (!has_alpha)
    {
        unsigned int width_bytes = (width + 31) / 32 * 4;
        CGImageRef cgmask, temp;

        /* draw the cursor mask to a temporary buffer */
        memset(mask_bits, 0xFF, mask_size);
        SelectObject(hdc, hbmMask);
        if (!DrawIconEx(hdc, 0, 0, icon, width, height, istep, NULL, DI_MASK))
        {
            WARN("Failed to draw frame mask %d.\n", istep);
            CGImageRelease(cgimage);
            return NULL;
        }

        data = CFDataCreate(NULL, (UInt8*)mask_bits, mask_size);
        if (!data)
        {
            WARN("failed to create data\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        provider = CGDataProviderCreateWithCFData(data);
        CFRelease(data);
        if (!provider)
        {
            WARN("failed to create data provider\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        cgmask = CGImageMaskCreate(width, height, 1, 1, width_bytes, provider, NULL, FALSE);
        CGDataProviderRelease(provider);
        if (!cgmask)
        {
            WARN("failed to create mask\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        temp = CGImageCreateWithMask(cgimage, cgmask);
        CGImageRelease(cgmask);
        CGImageRelease(cgimage);
        if (!temp)
        {
            WARN("failed to create masked image\n");
            return NULL;
        }
        cgimage = temp;
    }

    return cgimage;
}


/***********************************************************************
 *              create_cgimage_from_icon
 *
 * Create a CGImage from a Windows icon.
 */
CGImageRef create_cgimage_from_icon(HANDLE icon, int width, int height)
{
    CGImageRef ret = NULL;
    HDC hdc;
    char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
    BITMAPINFO *bitmapinfo = (BITMAPINFO*)buffer;
    unsigned char *color_bits, *mask_bits;
    HBITMAP hbmColor = 0, hbmMask = 0;
    int color_size, mask_size;

    TRACE("icon %p width %d height %d\n", icon, width, height);

    if (!width && !height)
    {
        ICONINFO info;
        BITMAP bm;

        if (!GetIconInfo(icon, &info))
            return NULL;

        GetObjectW(info.hbmMask, sizeof(bm), &bm);
        if (!info.hbmColor) bm.bmHeight = max(1, bm.bmHeight / 2);
        width = bm.bmWidth;
        height = bm.bmHeight;
        TRACE("new width %d height %d\n", width, height);

        DeleteObject(info.hbmColor);
        DeleteObject(info.hbmMask);
    }

    hdc = CreateCompatibleDC(0);

    bitmapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapinfo->bmiHeader.biWidth = width;
    bitmapinfo->bmiHeader.biHeight = -height;
    bitmapinfo->bmiHeader.biPlanes = 1;
    bitmapinfo->bmiHeader.biCompression = BI_RGB;
    bitmapinfo->bmiHeader.biXPelsPerMeter = 0;
    bitmapinfo->bmiHeader.biYPelsPerMeter = 0;
    bitmapinfo->bmiHeader.biClrUsed = 0;
    bitmapinfo->bmiHeader.biClrImportant = 0;
    bitmapinfo->bmiHeader.biBitCount = 32;
    color_size = width * height * 4;
    bitmapinfo->bmiHeader.biSizeImage = color_size;
    hbmColor = CreateDIBSection(hdc, bitmapinfo, DIB_RGB_COLORS, (VOID **) &color_bits, NULL, 0);
    if (!hbmColor)
    {
        WARN("failed to create DIB section for cursor color data\n");
        goto cleanup;
    }

    bitmapinfo->bmiHeader.biBitCount = 1;
    bitmapinfo->bmiColors[0].rgbRed      = 0;
    bitmapinfo->bmiColors[0].rgbGreen    = 0;
    bitmapinfo->bmiColors[0].rgbBlue     = 0;
    bitmapinfo->bmiColors[0].rgbReserved = 0;
    bitmapinfo->bmiColors[1].rgbRed      = 0xff;
    bitmapinfo->bmiColors[1].rgbGreen    = 0xff;
    bitmapinfo->bmiColors[1].rgbBlue     = 0xff;
    bitmapinfo->bmiColors[1].rgbReserved = 0;
    mask_size = ((width + 31) / 32 * 4) * height;
    bitmapinfo->bmiHeader.biSizeImage = mask_size;
    hbmMask = CreateDIBSection(hdc, bitmapinfo, DIB_RGB_COLORS, (VOID **) &mask_bits, NULL, 0);
    if (!hbmMask)
    {
        WARN("failed to create DIB section for cursor mask data\n");
        goto cleanup;
    }

    ret = create_cgimage_from_icon_bitmaps(hdc, icon, hbmColor, color_bits, color_size, hbmMask,
                                           mask_bits, mask_size, width, height, 0);

cleanup:
    if (hbmColor) DeleteObject(hbmColor);
    if (hbmMask) DeleteObject(hbmMask);
    DeleteDC(hdc);
    return ret;
}


/***********************************************************************
 *              get_first_resource
 *
 * Helper for create_app_icon_images().  Enum proc for EnumResourceNamesW()
 * which just gets the handle for the first resource and stops further
 * enumeration.
 */
static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR name, LONG_PTR lparam)
{
    HRSRC *res_info = (HRSRC*)lparam;

    *res_info = FindResourceW(module, name, (LPCWSTR)RT_GROUP_ICON);
    return FALSE;
}


/***********************************************************************
 *              create_app_icon_images
 */
CFArrayRef create_app_icon_images(void)
{
    HRSRC res_info;
    HGLOBAL res_data;
    GRPICONDIR *icon_dir;
    CFMutableArrayRef images = NULL;
    int i;

    TRACE("()\n");

    res_info = NULL;
    EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info);
    if (!res_info)
    {
        WARN("found no RT_GROUP_ICON resource\n");
        return NULL;
    }

    if (!(res_data = LoadResource(NULL, res_info)))
    {
        WARN("failed to load RT_GROUP_ICON resource\n");
        return NULL;
    }

    if (!(icon_dir = LockResource(res_data)))
    {
        WARN("failed to lock RT_GROUP_ICON resource\n");
        goto cleanup;
    }

    images = CFArrayCreateMutable(NULL, icon_dir->idCount, &kCFTypeArrayCallBacks);
    if (!images)
    {
        WARN("failed to create images array\n");
        goto cleanup;
    }

    for (i = 0; i < icon_dir->idCount; i++)
    {
        int width = icon_dir->idEntries[i].bWidth;
        int height = icon_dir->idEntries[i].bHeight;
        BOOL found_better_bpp = FALSE;
        int j;
        LPCWSTR name;
        HGLOBAL icon_res_data;
        BYTE *icon_bits;

        if (!width) width = 256;
        if (!height) height = 256;

        /* If there's another icon at the same size but with better
           color depth, skip this one.  We end up making CGImages that
           are all 32 bits per pixel, so Cocoa doesn't get the original
           color depth info to pick the best representation itself. */
        for (j = 0; j < icon_dir->idCount; j++)
        {
            int jwidth = icon_dir->idEntries[j].bWidth;
            int jheight = icon_dir->idEntries[j].bHeight;

            if (!jwidth) jwidth = 256;
            if (!jheight) jheight = 256;

            if (j != i && jwidth == width && jheight == height &&
                icon_dir->idEntries[j].wBitCount > icon_dir->idEntries[i].wBitCount)
            {
                found_better_bpp = TRUE;
                break;
            }
        }

        if (found_better_bpp) continue;

        name = MAKEINTRESOURCEW(icon_dir->idEntries[i].nID);
        res_info = FindResourceW(NULL, name, (LPCWSTR)RT_ICON);
        if (!res_info)
        {
            WARN("failed to find RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
            continue;
        }

        icon_res_data = LoadResource(NULL, res_info);
        if (!icon_res_data)
        {
            WARN("failed to load icon %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
            continue;
        }

        icon_bits = LockResource(icon_res_data);
        if (icon_bits)
        {
            static const BYTE png_magic[] = { 0x89, 0x50, 0x4e, 0x47 };
            CGImageRef cgimage = NULL;

            if (!memcmp(icon_bits, png_magic, sizeof(png_magic)))
            {
                CFDataRef data = CFDataCreate(NULL, (UInt8*)icon_bits, icon_dir->idEntries[i].dwBytesInRes);
                if (data)
                {
                    CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
                    CFRelease(data);
                    if (provider)
                    {
                        cgimage = CGImageCreateWithPNGDataProvider(provider, NULL, FALSE,
                                                                   kCGRenderingIntentDefault);
                        CGDataProviderRelease(provider);
                    }
                }
            }

            if (!cgimage)
            {
                HICON icon;
                icon = CreateIconFromResourceEx(icon_bits, icon_dir->idEntries[i].dwBytesInRes,
                                                TRUE, 0x00030000, width, height, 0);
                if (icon)
                {
                    cgimage = create_cgimage_from_icon(icon, width, height);
                    DestroyIcon(icon);
                }
                else
                    WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID);
            }

            if (cgimage)
            {
                CFArrayAppendValue(images, cgimage);
                CGImageRelease(cgimage);
            }
        }
        else
            WARN("failed to lock RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);

        FreeResource(icon_res_data);
    }

cleanup:
    if (images && !CFArrayGetCount(images))
    {
        CFRelease(images);
        images = NULL;
    }
    FreeResource(res_data);

    return images;
}
