javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/imagebase.cpp
changeset 80 d6dafc5d983f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/imagebase.cpp	Fri Oct 15 12:29:39 2010 +0300
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Nokia Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "imagebase.h"
+#include "gfxlog.h"
+
+namespace Java { namespace GFX {
+
+ImageBase::ImageBase() : mAlpha(-1), mHasMask(false)
+    {
+    }
+
+ImageBase::~ImageBase()
+    {
+    }
+
+void ImageBase::doGetRgb(QImage& image, int* aRgbdata, int aOffset, int aScanlength, 
+                         int aX, int aY, int aWidth, int aHeight)
+    {
+    GFX_LOG_FUNC_CALL();
+
+    if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
+        {
+        image = image.copy(aX, aY, aWidth, aHeight);
+        if(image.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
+            }
+        }
+
+    // If image is not 32bpp we need to convert it
+    if(image.format() != QImage::Format_RGB32 &&
+       image.format() != QImage::Format_ARGB32)
+        {
+        image = image.convertToFormat(QImage::Format_ARGB32);
+        if(image.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "format convertion to 32bpp failed");
+            }
+        }
+
+    // Temporary storage for pixels
+    QRgb* pixel = NULL;
+
+    // dataArray index, start from offset
+    int targetIndex = aOffset;
+    // Iterate through lines
+    for(int b = 0; b < aHeight; ++b)
+        {
+        // Obtain pointer to start of current line (y)
+        const unsigned char* lineStart = image.scanLine(b);
+        // Iterate through pixels on each line
+        for (int a = 0; a < aWidth; ++a)
+            {
+            // Set the current pixel, relative to line start
+            pixel = ((QRgb*)lineStart) + a;
+            // Move target pointer to the next slot
+            targetIndex = aOffset + a + (b * aScanlength);
+            // Shift pixels to correct places, needed for 32-bit format
+            // as the bits order in memory may vary between systems
+            aRgbdata[targetIndex] =  ((qAlpha(*pixel) & 0xff) << 24) |
+                                     ((qRed(*pixel)   & 0xff) << 16) |
+                                     ((qGreen(*pixel) & 0xff) << 8 ) |
+                                     ((qBlue(*pixel)  & 0xff));
+            }
+        }
+    }
+
+void ImageBase::doGetRgb(QImage& image, char* aRgbdata, char* aTransparencyMask,int aOffset, 
+                         int aScanlength, int aX, int aY, int aWidth, int aHeight, int aFormat)
+    {
+    GFX_LOG_FUNC_CALL();
+
+    if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
+        {
+        image = image.copy(aX, aY, aWidth, aHeight);
+        if(image.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
+            }
+        }
+
+    if(aScanlength < 0)
+        {
+         image = image.mirrored(false, true);
+         if(image.isNull())
+             {
+             throw GfxException(EGfxErrorNoMemory, "Mirroring failed");
+             }
+        }
+
+    // If image is not monochrome we need to convert it
+    if(image.format() != QImage::Format_Mono)
+    {
+        image = image.convertToFormat(QImage::Format_Mono);
+        if(image.isNull())
+        {
+            throw GfxException(EGfxErrorNoMemory, "Format conversion to 8bpp failed");
+        }
+    }
+
+    // dataArray index, start from offset
+    int targetIndex = aOffset;
+
+    const unsigned char* imageStart = image.bits();
+    QImage mask = image.alphaChannel();
+    const unsigned char* maskStart = mask.bits();
+
+    // Find the number of full bytes
+    int fullBytes = aWidth/8;
+    int bpl = image.bytesPerLine();
+
+    if(bpl == fullBytes)
+        {
+        memcpy(aRgbdata+targetIndex, imageStart, bpl*aHeight);
+        memcpy(aTransparencyMask+targetIndex, maskStart, bpl*aHeight);
+        }
+    else
+        {
+        memcpy(aRgbdata+targetIndex, imageStart, fullBytes*aHeight + aHeight);
+        memcpy(aTransparencyMask+targetIndex, maskStart, fullBytes*aHeight + aHeight);
+        }
+    }
+
+void ImageBase::doGetRgb(QImage& image, short* aRgbdata, int aOffset, int aScanlength, 
+                         int aX, int aY, int aWidth, int aHeight, int aFormat)
+    {
+    GFX_LOG_FUNC_CALL();
+
+    // Match format to QT
+    int format;
+    switch (aFormat) {
+        case EFormatRGB555:
+            format = QImage::Format_RGB555;
+            break;
+        case EFormatRGB16:
+            format = QImage::Format_RGB16;
+            break;
+         case EFormatRGB444:
+            format = QImage::Format_RGB444;
+            break;
+         case EFormatARGB4444Premultiplied:
+            format = QImage::Format_ARGB4444_Premultiplied;
+            break;
+         default:
+            format = QImage::Format_RGB16;
+    }
+
+    if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
+        {
+        image = image.copy(aX, aY, aWidth, aHeight);
+        if(image.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
+            }
+        }
+
+    // If image is not format we need, convert it
+    if(image.format() != format)
+        {
+        image = image.convertToFormat((QImage::Format)format);
+        if(image.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "format convertion to 16bpp failed");
+            }
+        }
+
+    // Temporary storage for pixels
+    short* pixel = NULL;
+    // dataArray index, start from offset
+    int targetIndex = aOffset;
+
+    // Iterate through lines
+    for(int b=0; b < aHeight; b++)
+        {
+        // Obtain pointer to start of current line (y)
+        const unsigned char* lineStart = image.scanLine(b);
+        // Iterate through pixels on each line
+        for(int a=0; a < aWidth; a++)
+            {
+            // Set the current pixel, relative to line start
+            pixel = ((short*)lineStart) + a;
+            // Move target pointer to the next slot
+            targetIndex = aOffset + a + (b * aScanlength);
+            aRgbdata[targetIndex] =  *pixel;
+            }
+        }
+    }
+
+QTransform ImageBase::generateTransformMatrix(TTransform aTransform)
+    {
+    GFX_LOG_FUNC_CALL();
+
+    // In case there's both mirror and rotate is requested, the angle of rotation
+    // must be negative since when the transform is applied the z-axis is processed
+    // before y-axis, while the spec mandates reverse order. So by having negative  
+    // degrees for rotation along z-axis here, gives correct output.
+    QTransform transform;
+    switch(aTransform) 
+        {
+        case ETransNone:
+            // No transform or mirror
+            break;
+        case ETransRot90:
+            transform.rotate(90, Qt::ZAxis);
+            break;
+        case ETransRot180:
+            transform.rotate(180, Qt::ZAxis);
+            break;
+        case ETransRot270:
+            transform.rotate(270, Qt::ZAxis);
+            break;
+        case ETransMirror:
+            transform.rotate(180,Qt::YAxis);
+            break;
+        case ETransMirrorRot90:
+            transform.rotate(180, Qt::YAxis);
+            transform.rotate(-90, Qt::ZAxis);
+            break;
+        case ETransMirrorRot180:
+            transform.rotate(180, Qt::YAxis);
+            transform.rotate(-180, Qt::ZAxis);
+            break;
+        case ETransMirrorRot270:
+            transform.rotate(180, Qt::YAxis);
+            transform.rotate(-270, Qt::ZAxis);
+            break;
+        default:
+            Q_ASSERT_X(false, "Graphics", "Transform type not recognized");
+        }
+    return transform;
+    }
+
+int ImageBase::getAlpha() 
+    {
+    return mAlpha;
+    }
+
+bool ImageBase::hasMask()
+    {
+    return mHasMask;
+    }
+
+QImage ImageBase::imageDataToQImage(ImageDataWrapper* aData)
+    {
+    if(aData->getDepth() != 32)
+        {
+        // Java side always converts the ImageData to 32 bit before passing it
+        // to native side, bail out if we get something else
+        throw GfxException(EGfxErrorNoMemory, "Only 32 bit ImageData is supported in Image creation");
+        }
+
+    int bpp = 4; // bit depth = 32, 4 bytes per pixel
+    int size = aData->getWidth()*aData->getHeight()*bpp;
+    char* pixelData = aData->getData(ImageDataWrapper::EPixelData);
+
+    for(int index = 0; index < size; index += bpp)
+        {
+        int pixel = *(reinterpret_cast<int*>(pixelData+index));
+
+        pixelData[index]   = (uchar)(pixel >> 24) & 0xFF;
+        pixelData[index+1] = (uchar)(pixel >> 16) & 0xFF;
+        pixelData[index+2] = (uchar)(pixel >> 8) & 0xFF;
+        pixelData[index+3] = 0xFF; // Set alpha to opaque here, alpha channel data will be handled later
+        }
+
+    QImage image(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EPixelData)),
+                                              aData->getWidth(),
+                                              aData->getHeight(),
+                                              aData->getBytesPerLine(),
+                                              QImage::Format_ARGB32);
+    if(image.isNull())
+        {
+        throw GfxException(EGfxErrorNoMemory, "Image creation failed");
+        }
+
+    // Set indexed palette (if one is set)
+    if(!aData->isDirect())
+        {
+        image.setColorTable(*aData->getPaletteData()->getIndexedPalette());
+        }
+
+    mHasMask = false;
+    mAlpha = aData->getAlpha();
+
+    if(aData->getData(ImageDataWrapper::EMaskData))
+        {
+        QImage mask(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EMaskData)),
+                                             aData->getWidth(),
+                                             aData->getHeight(),
+                                             QImage::Format_Mono);
+        if(mask.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
+            }
+        image.setAlphaChannel(mask);
+        mHasMask = true;
+        }
+    else if(mAlpha != -1)
+        {
+        // Global alpha is set, overrides alpha channel data
+        QImage alpha(aData->getWidth(), aData->getHeight(), QImage::Format_Indexed8);
+        if(alpha.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
+            }
+
+        alpha.fill(aData->getAlpha());
+        image.setAlphaChannel(alpha);
+        }
+    else if(aData->getData(ImageDataWrapper::EAlphaData))
+        {
+        // Alpha channel data is set
+        const int w = aData->getWidth();
+        QImage alpha(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EAlphaData)),
+                                              w,
+                                              aData->getHeight(),
+                                              w,
+                                              QImage::Format_Indexed8);
+        QVector<QRgb> colors(255);
+        for(int i=0; i<255; i++)
+            {
+            colors[i] = qRgb(i, i, i);
+            }
+        alpha.setColorTable(colors);
+        colors.clear();
+
+        if(alpha.isNull())
+            {
+            throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
+            }
+        image.setAlphaChannel(alpha);
+        }
+    return image;
+    }
+
+
+QImage::Format ImageBase::mapInternalFormatToQt(TImageFormat internalImageFormat)
+    {
+    switch (internalImageFormat) 
+        {
+        case EFormatARGB32:
+            return QImage::Format_ARGB32;
+        case EFormatRGB32:
+            return QImage::Format_RGB32;
+        case EFormatARGB32Premultiplied:
+            return QImage::Format_ARGB32_Premultiplied;
+         case EFormatRGB16:
+            return QImage::Format_RGB16;
+         case EFormatRGB555:
+            return QImage::Format_RGB555;
+         case EFormatRGB444:
+            return QImage::Format_RGB444;
+         case EFormatARGB4444Premultiplied:
+            return QImage::Format_ARGB4444_Premultiplied;
+         case EFormatMONO:
+            return QImage::Format_Mono;
+         default:
+            return QImage::Format_Invalid;
+        }
+    }
+
+TImageFormat ImageBase::mapQtFormatToInternal(QImage::Format qtImageFormat)
+    {
+    switch (qtImageFormat) 
+        {
+        case QImage::Format_ARGB32:
+            return EFormatARGB32;
+        case QImage::Format_RGB32:
+            return EFormatRGB32;
+        case QImage::Format_ARGB32_Premultiplied:
+            return EFormatARGB32Premultiplied;
+         case QImage::Format_RGB16:
+            return EFormatRGB16;
+         case QImage::Format_RGB555:
+            return EFormatRGB555;
+         case QImage::Format_RGB444:
+            return EFormatRGB444;
+         case QImage::Format_ARGB4444_Premultiplied:
+            return EFormatARGB4444Premultiplied;
+         case QImage::Format_Mono:
+            return EFormatMONO;
+         default:
+            return EFormatNone;
+        }
+    }
+
+} // namespace GFX
+} // namespace Java