javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/gfxutils.cpp
author hgs
Fri, 15 Oct 2010 12:29:39 +0300
changeset 80 d6dafc5d983f
parent 21 2a9601315dfc
permissions -rw-r--r--
v2.2.19_1

/*******************************************************************************
 * Copyright (c) 2008 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 <QDebug>
#include <QFont>
#include <QFontMetrics>
#include <QSharedDataPointer>
#include <QRect>
#include <QImage>
#include "gfxutils.h"
#include "graphicscontextimpl.h"

namespace Java { namespace GFX {

//
// CollisionDetection
//

#define HANDLE_TO_POINTER(type, variable, handle) type variable = reinterpret_cast<type>( handle )

bool gfxUtils::detectCollision(Image* aImage1, int aTransform1, int aP1x, int aP1y, int aR1x1, int aR1y1, int aR1x2, int aR1y2,
                               Image* aImage2, int aTransform2, int aP2x, int aP2y, int aR2x1, int aR2y1, int aR2x2, int aR2y2)
{
    int transform1 = getCgTransformValue(aTransform1);
    int transform2 = getCgTransformValue(aTransform2);

    // Calculate the intersection of collisionRectangles:
    QRect rect1(aP1x, aP1y, aR1x2 - aR1x1, aR1y2 - aR1y1);
    QRect rect2(aP2x, aP2y, aR2x2 - aR2x1, aR2y2 - aR2y1);

    if (aTransform1 & EReflectDiag)
    {
        int tmp = rect1.width();
        rect1.setWidth(rect1.height());
        rect1.setHeight(tmp);
    }
    if (aTransform2 & EReflectDiag)
    {
        int tmp = rect2.width();
        rect2.setWidth(rect2.height());
        rect2.setHeight(tmp);
    }

    QRect rect3 = rect1.intersected(rect2);

    QImage qimage1;

    if(transform1 == ETransRot90)
    {
        GraphicsContextImpl gc;
        // create a copy of the image and transform it, i.e. don't modify the original
        qimage1 = gc.doTransform(aImage1->toImage(), transform1);
    }
    else
    {
        qimage1 = aImage1->toImage();
    }
    int totalWidth1 = qimage1.width();

    QImage qimage2;

    if(transform2 == ETransRot90)
    {
        GraphicsContextImpl gc;
        // create a copy of the image and transform it, i.e. don't modify the original
        qimage2 = gc.doTransform(aImage2->toImage(), transform2);
    }
    else
    {
        qimage2 = aImage2->toImage();
    }
    int totalWidth2 = qimage2.width();	
        
    const unsigned char* data1 = qimage1.bits();
    const unsigned char* data2 = qimage2.bits();

    // Save intersection to collisionRectangles:
    aR1x1 += rect3.x() - aP1x;
    aR1y1 += rect3.y() - aP1y;
    aR1x2 = aR1x1 + rect3.width();
    aR1y2 = aR1y1 + rect3.height();
    aR2x1 += rect3.x() - aP2x;
    aR2y1 += rect3.y() - aP2y;
    aR2x2 = aR2x1 + rect3.width();
    aR2y2 = aR2y1 + rect3.height();

    // These rectangles defines areas to be checked.
    QRect image1Rect(aR1x1, aR1y1, aR1x2 - aR1x1, aR1y2 - aR1y1);
    QRect image2Rect(aR2x1, aR2y1, aR2x2 - aR2x1, aR2y2 - aR2y1);

    // Following variables define how much we need to increase or
    // decrease x and y in every loop round:
    int rect1XInc = 0;
    int rect1YInc = 0;
    int rect2XInc = 0;
    int rect2YInc = 0;

    // These defines how much we need to increment/decrement x and y
    // when moving to next line:
    int rect1XLineInc = 0;
    int rect1YLineInc = 0;
    int rect2XLineInc = 0;
    int rect2YLineInc = 0;

    // These variables contains the coordinates of the pixel we are
    // checking:
    int rect1X = 0;
    int rect1Y = 0;
    int rect2X = 0;
    int rect2Y = 0;

    // Tells where to start:
    int rect1XStart = 0;
    int rect1YStart = 0;
    int rect2XStart = 0;
    int rect2YStart = 0;

    // Position of last pixel.
    int rect1XEnd = 0;
    int rect1YEnd = 0;
    int rect2XEnd = 0;
    int rect2YEnd = 0;

    switch(transform1) 
    {
        case ETransNone:
            rect1XInc = 1;
            rect1YInc = 0;
            rect1XLineInc = 0;
            rect1YLineInc = 1;
            rect1XStart = image1Rect.x();
            rect1YStart = image1Rect.y();
            rect1XEnd = image1Rect.x() + image1Rect.width() - 1;
            rect1YEnd = image1Rect.y() + image1Rect.height() - 1;
            break;
        case ETransRot90:
            rect1XInc = 0;
            rect1YInc = 1;
            rect1XLineInc = -1;
            rect1YLineInc = 0;
            rect1XStart = image1Rect.x() + image1Rect.width() -1;
            rect1YStart = image1Rect.y();
            rect1XEnd = image1Rect.x();
            rect1YEnd = image1Rect.y() + image1Rect.height() - 1;
            break;
        case ETransRot180:
            rect1XInc = -1;
            rect1YInc = 0;
            rect1XLineInc = 0;
            rect1YLineInc = -1;
            rect1XStart = image1Rect.x() + image1Rect.width() -1;
            rect1YStart = image1Rect.y() + image1Rect.height() - 1;
            rect1XEnd = image1Rect.x();
            rect1YEnd = image1Rect.y();
            break;
        case ETransRot270:
            rect1XInc = 0;
            rect1YInc = -1;
            rect1XLineInc = 1;
            rect1YLineInc = 0;
            rect1XStart = image1Rect.x();
            rect1YStart = image1Rect.y() + image1Rect.height() - 1;
            rect1XEnd = image1Rect.x() + image1Rect.height() - 1;
            rect1YEnd = image1Rect.y();
            break;
        case ETransMirror:
            rect1XInc = -1;
            rect1YInc = 0;
            rect1XLineInc = 0;
            rect1YLineInc = 1;
            rect1XStart = image1Rect.x() + image1Rect.width() - 1;
            rect1YStart = image1Rect.y();
            rect1XEnd = image1Rect.x();
            rect1YEnd = image1Rect.y() + image1Rect.height() - 1;
            break;
        case ETransMirrorRot90:
            rect1XInc = 0;
            rect1YInc = -1;
            rect1XLineInc = -1;
            rect1YLineInc = 0;
            rect1XStart = image1Rect.x() + image1Rect.width() -1;
            rect1YStart = image1Rect.y() + image1Rect.height() - 1;
            rect1XEnd = image1Rect.x();
            rect1YEnd = image1Rect.y();
            break;
        case ETransMirrorRot180:
            rect1XInc = 1;
            rect1YInc = 0;
            rect1XLineInc = 0;
            rect1YLineInc = -1;
            rect1XStart = image1Rect.x();
            rect1YStart = image1Rect.y() + image1Rect.height() - 1;
            rect1XEnd = image1Rect.x() + image1Rect.width() - 1;
            rect1YEnd = image1Rect.y();
            break;
        case ETransMirrorRot270:
            rect1XInc = 0;
            rect1YInc = 1;
            rect1XLineInc = 1;
            rect1YLineInc = 0;
            rect1XStart = image1Rect.x();
            rect1YStart = image1Rect.y();
            rect1XEnd = image1Rect.x() + image1Rect.height() - 1;
            rect1YEnd = image1Rect.y() + image1Rect.width() - 1;
            break;
        default:
            break;
    }

    switch(transform2) 
    {
        case ETransNone:
            rect2XInc = 1;
            rect2YInc = 0;
            rect2XLineInc = 0;
            rect2YLineInc = 1;
            rect2XStart = image2Rect.x();
            rect2YStart = image2Rect.y();
            rect2XEnd = image2Rect.x() + image2Rect.width() - 1;
            rect2YEnd = image2Rect.y() + image2Rect.height() - 1;
            break;
        case ETransRot90:
            rect2XInc = 0;
            rect2YInc = 1;
            rect2XLineInc = -1;
            rect2YLineInc = 0;
            rect2XStart = image2Rect.x() + image2Rect.width() -1;
            rect2YStart = image2Rect.y();
            rect2XEnd = image2Rect.x();
            rect2YEnd = image2Rect.y() + image2Rect.height() - 1;
            break;
        case ETransRot180:
            rect2XInc = -1;
            rect2YInc = 0;
            rect2XLineInc = 0;
            rect2YLineInc = -1;
            rect2XStart = image2Rect.x() + image2Rect.width() -1;
            rect2YStart = image2Rect.y() + image2Rect.height() - 1;
            rect2XEnd = image2Rect.x();
            rect2YEnd = image2Rect.y();
            break;
        case ETransRot270:
            rect2XInc = 0;
            rect2YInc = -1;
            rect2XLineInc = 1;
            rect2YLineInc = 0;
            rect2XStart = image2Rect.x();
            rect2YStart = image2Rect.y() + image2Rect.height() - 1;
            rect2XEnd = image2Rect.x() + image2Rect.height() - 1;
            rect2YEnd = image2Rect.y();
            break;
        case ETransMirror:
            rect2XInc = -1;
            rect2YInc = 0;
            rect2XLineInc = 0;
            rect2YLineInc = 1;
            rect2XStart = image2Rect.x() + image2Rect.width() - 1;
            rect2YStart = image2Rect.y();
            rect2XEnd = image2Rect.x();
            rect2YEnd = image2Rect.y() + image2Rect.height() - 1;
            break;
        case ETransMirrorRot90:
            rect2XInc = 0;
            rect2YInc = -1;
            rect2XLineInc = -1;
            rect2YLineInc = 0;
            rect2XStart = image2Rect.x() + image2Rect.width() -1;
            rect2YStart = image2Rect.y() + image2Rect.height() - 1;
            rect2XEnd = image2Rect.x();
            rect2YEnd = image2Rect.y();
            break;
        case ETransMirrorRot180:
            rect2XInc = 1;
            rect2YInc = 0;
            rect2XLineInc = 0;
            rect2YLineInc = -1;
            rect2XStart = image2Rect.x();
            rect2YStart = image2Rect.y() + image2Rect.height() - 1;
            rect2XEnd = image2Rect.x() + image2Rect.width() - 1;
            rect2YEnd = image2Rect.y();
            break;
        case ETransMirrorRot270:
            rect2XInc = 0;
            rect2YInc = 1;
            rect2XLineInc = 1;
            rect2YLineInc = 0;
            rect2XStart = image2Rect.x();
            rect2YStart = image2Rect.y();
            rect2XEnd = image2Rect.x() + image2Rect.height() - 1;
            rect2YEnd = image2Rect.y() + image2Rect.width() - 1;
            break;
        default:
            break;
    }


    rect1X = rect1XStart;
    rect1Y = rect1YStart;
    rect2X = rect2XStart;
    rect2Y = rect2YStart;

    // Go through the intersection area pixel by pixel.
    // Following code assumes that format is 32-bit RGBA or 32-bit RGB.
    while(true) 
    {
        // Check is there hit:
        if(data1[rect1Y * totalWidth1 * 4 + rect1X * 4 + 3])
        {
            if(data2[rect2Y * totalWidth2 * 4 + rect2X * 4 + 3]) 
            {
                return true;
            }
        }

        if((rect1X == rect1XEnd) && (rect1Y == rect1YEnd))
        {
            // Done, no hit:
            return false;
        }

        // Move to next line if in the end:
        if(rect1XLineInc == 0)
        {
            if(rect1X == rect1XEnd)
            {
                rect1X = rect1XStart - rect1XInc;
                rect1Y += rect1YLineInc;
            }
        }
        else
        {
            if(rect1Y == rect1YEnd)
            {
                rect1Y = rect1YStart - rect1YInc;
                rect1X += rect1XLineInc;
            }
        }

        if(rect2XLineInc == 0)
        {
            if(rect2X == rect2XEnd)
            {
                rect2X = rect2XStart - rect2XInc;
                rect2Y += rect2YLineInc;
            }
        }
        else
        {
            if(rect2Y == rect2YEnd)
            {
                rect2Y = rect2YStart - rect2YInc;
                rect2X += rect2XLineInc;
            }
        }

        // Move to next pixel:
        rect1X += rect1XInc;
        rect1Y += rect1YInc;
        rect2X += rect2XInc;
        rect2Y += rect2YInc;
    }
}

    /**
     *  Maps transform constants to Common Graphics.
     */
	int gfxUtils::getCgTransformValue(int aTransform)
    {
        int retVal = ETransNone;
        switch(aTransform)
        {
            case ETransNoneType:
                retVal = ETransNone;
                break;
            case ETransRot90Type:
                retVal = ETransRot90;
                break;
            case ETransRot180Type:
                retVal = ETransRot180;
                break;
            case ETransRot270Type:
                retVal = ETransRot270;
                break;
            case ETransMirrorType:
                retVal = ETransMirror;
                break;
            case ETransMirrorRot90Type:
                retVal = ETransMirrorRot90;
                break;
            case ETransMirrorRot180Type:
                retVal = ETransMirrorRot180;
                break;
            case ETransMirrorRot270Type:
                retVal = ETransMirrorRot270;
                break;
            default:
                break;
        }
        return retVal;
    }
} // namespace GFX
} // namespace Java