/*
 * Copyright (c) 2004 Nokia. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of Nokia nor the names of its contributors may be
 * used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "KWQPixmap.h"
#include "KWQAssertions.h"

#include "WebCoreImageRendererFactory.h"
#include "WebCoreImageRenderer.h"


void initGdkRectangleFromSize(GdkRectangle * rect, const QSize & size) {
    ASSERT(rect);
    rect->x = rect->y = 0;
    rect->width = size.width();
    rect->height = size.height();
}

void initGdkRectangle(GdkRectangle * rect, const int w, const int h) {
    ASSERT(rect);
    rect->x = rect->y = 0;
    rect->width = w;
    rect->height = h;
}

class QPixmapPrivate
{
public:
    GdkPixmap *pixmap;
    GdkPixmap *alpha_bitmap;
    GdkPixbuf *buf;
    QPixmapPrivate();
};


QPixmapPrivate::QPixmapPrivate()
    : pixmap(0),alpha_bitmap(0),buf(0)
{
}


QPixmap *KWQLoadPixmap(const char *name)
{
    QPixmap *p = new QPixmap(WebCoreImageRendererFactory::sharedFactory()->imageRendererWithName(name));

    return p;
}

bool canRenderImageType(const QString &type)
{
    return WebCoreImageRendererFactory::sharedFactory()->supports(type.latin1());
}

QPixmap::QPixmap ()
{
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRenderer();
    needCopyOnWrite = false;
}

QPixmap::QPixmap(WebCoreImageRenderer* r)
{
    ASSERT(r);
    imageRenderer = r;
    needCopyOnWrite = false;
}

QPixmap::QPixmap(const QString& MIME)
{
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithMIMEType(MIME.latin1());
    MIMEType = MIME;
    needCopyOnWrite = false;
}

QPixmap::QPixmap(const QSize &sz)
{
    GdkRectangle rect;
    initGdkRectangleFromSize(&rect, sz);
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithSize(&rect);
    needCopyOnWrite = false;
}

QPixmap::QPixmap(const QByteArray &bytes)
{
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithBytes(bytes.data(), bytes.size());
    needCopyOnWrite = false;
}

QPixmap::QPixmap(const QByteArray &bytes, const QString &MIME)
{
    MIMEType = MIME;
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithBytes(bytes.data(), bytes.size(), MIMEType.latin1());
}

QPixmap::QPixmap(int w, int h)
{
    GdkRectangle rect;
    initGdkRectangle(&rect, w, h);
    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithSize(&rect);
    needCopyOnWrite = false;
}

QPixmap::QPixmap(const QPixmap &copyFrom) : QPaintDevice(copyFrom)
{
    imageRenderer = copyFrom.imageRenderer;
    if (imageRenderer) { 
	imageRenderer->retain();
	copyFrom.needCopyOnWrite = true;
	needCopyOnWrite = true;
    }

    MIMEType = copyFrom.MIMEType;

}

QPixmap::~QPixmap()
{
    if (imageRenderer) imageRenderer->release();
}

bool QPixmap::receivedData(const QByteArray &bytes, bool isComplete)
{
    if (!imageRenderer) {
	if (isComplete) {
	    imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithBytes(bytes.data(), bytes.size(), MIMEType.latin1());
	    return imageRenderer->isNull();
	}

	imageRenderer = WebCoreImageRendererFactory::sharedFactory()->imageRendererWithMIMEType(MIMEType.utf8());
    }

    return imageRenderer->incrementalLoadWithBytes(bytes.data(), bytes.size(), isComplete);
}

bool QPixmap::mask() const
{
    return false;
}

bool QPixmap::isNull() const
{
    return !imageRenderer || imageRenderer->isNull();
}


QSize QPixmap::size () const
{
    if (!imageRenderer) return QSize(0, 0);
    GdkRectangle rect;
    imageRenderer->size(&rect);
    return QSize(&rect);
    
}

QRect QPixmap::rect () const
{
    return QRect(QPoint(0,0), size());
}

int QPixmap::width () const
{
    return size().width();
}

int QPixmap::height () const
{
    return size().height();
}

void QPixmap::resize(const QSize &sz)
{
    if (needCopyOnWrite) {
        WebCoreImageRenderer* newImageRenderer = imageRenderer->copy();
	newImageRenderer->retain();
	imageRenderer->release();
        imageRenderer = newImageRenderer;
        needCopyOnWrite = false;
    }

    GdkRectangle newSize;
    initGdkRectangleFromSize(&newSize, sz);
    imageRenderer->resize(&newSize);
}

void QPixmap::resize(int w, int h)
{
    resize(QSize(w,h));
}

QPixmap QPixmap::xForm(const QWMatrix &m) const {
    // This function is only called when an image needs to be scaled.
    // We can depend on render_image.cpp to call resize AFTER
    // creating a copy of the image to be scaled. So, this
    // implementation simply returns a copy of the image. Note,
    // this assumption depends on the implementation of
    // RenderImage::printObject.
    return *this;
}

QPixmap & QPixmap::operator=(const QPixmap &assignFrom)
{    
    WebCoreImageRenderer* oldImageRenderer = imageRenderer;
    imageRenderer = assignFrom.imageRenderer;
    if (imageRenderer) {
	imageRenderer->retain();
	assignFrom.needCopyOnWrite = true;
	needCopyOnWrite = true;
    }
    if (oldImageRenderer) oldImageRenderer->release();

    MIMEType = assignFrom.MIMEType;
    return *this;
}

void QPixmap::increaseUseCount() const
{
    if (imageRenderer) imageRenderer->increaseUseCount();
}

void QPixmap::decreaseUseCount() const
{
    if (imageRenderer)  imageRenderer->decreaseUseCount();
}

void QPixmap::stopAnimations()
{
    if (imageRenderer) imageRenderer->stopAnimation();
}

void QPixmap::flushRasterCache()
{
    if (imageRenderer) imageRenderer->flushRasterCache();
}
