--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/gfx2d/src/GfxImage/GfxImageTransformer.cpp Thu Jan 07 16:19:02 2010 +0200
@@ -0,0 +1,880 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Graphics Extension Library source file
+*
+*/
+
+
+#include "GfxImageTransformer.h"
+#include "GfxColor.h"
+
+#define RGB565toRGB888(rgb565) (0xff000000|((rgb565 << 8) & 0xf80000) | ((rgb565 << 5) & 0x00fc00) | ((rgb565 << 3) & 0x000f8))
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// TGfxImageTransformer::TGfxImageTransformer( TGfxAffineTransform* aTransform )
+// ---------------------------------------------------------------------------
+ TGfxImageTransformer::TGfxImageTransformer( TGfxAffineTransform* aTransform, CVGRenderer * aRenderer )
+ {
+ iTransform = aTransform;
+ iVgRenderer = aRenderer;
+ }
+
+
+
+
+// --------------------------------------------------------------------------
+// void TGfxImageTransformer::ImageBlend( CFbsBitmap* aSrc,
+// ---------------------------------------------------------------------------
+ void TGfxImageTransformer::ImageBlend( CFbsBitmap* aSrc,
+ const TGfxPoint2D& aP,
+ TInt aDstWidth,
+ TInt aDstHeight,
+ const TRect& aClipRect,
+ TBool aReverse)
+{
+
+ TRect srcrect( TPoint( aP.iX, aP.iY ), aSrc->SizeInPixels() );
+ TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth, aDstHeight) );
+ TInt srcWidth = aSrc->SizeInPixels().iWidth;
+ TInt srcHeight = aSrc->SizeInPixels().iHeight;
+
+ TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
+ TRect rect (TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
+ rect.Intersection(aClipRect); // Clipping
+
+ if ( !rect.Intersects( dstrect ) ) // clip rect with dst image
+ return;
+
+ aSrc->LockHeap();
+ rect.Intersection( dstrect );
+
+ TUint32* bufsrc32 = (TUint32*) aSrc->DataAddress();
+ TUint bufLimit = aDstWidth * aDstHeight;
+
+ TGfxAffineTransform inv = iTransform->CreateInverse();
+
+ TInt xstart, xend, yend;
+ TGfxPoint2D horizDeriv;
+ TGfxPoint2D origin, top, right, corner, east, west, south, north;
+
+ // sort four corners into appropriate order
+ SortCoordinates(origin, top, north, south, right, east, west,
+ corner, aP, srcWidth, srcHeight);
+
+ // compute derivitives for scanline in source.
+ TPoint pinv;
+ TGfxPoint2D p;
+ p.iX = 8;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX = p.iX;
+ horizDeriv.iY = p.iY;
+ p.iX = 0;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX -= p.iX;
+ horizDeriv.iY -= p.iY;
+ horizDeriv.iX = horizDeriv.iX >> 3;
+ horizDeriv.iY = horizDeriv.iY >> 3;
+
+ yend = rect.iBr.iY;
+ TInt bufLength = rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
+ TInt tempBufLength = bufLength;
+
+ TInt x, y;
+ TInt sx, sy;
+ TUint32 pixel;
+ TInt offset;
+ VGint stride = CFbsBitmap::ScanLineLength( aDstWidth, aSrc->DisplayMode() );
+ for ( y = rect.iTl.iY; y <= yend; y++ )
+ {
+ p.iY = y;
+ // compute scanline starting position
+ ComputeXPositions((TFloatFixPt)y, rect, north, west, east, south, xstart, xend);
+
+ p.iX = xstart;
+ // transform that starting position to the source image
+ inv.Transform( &p, & p, 1 );
+ bufLength += xstart - rect.iTl.iX;
+
+ #ifdef SVG_FLOAT_BUILD
+ p.iY -= TFloatFixPt( .5f );
+ #else
+ p.iY -= TFloatFixPt(0x8000, ETrue);
+ #endif
+ for ( x = xstart; x <= xend; x++ )
+ {
+ //increment the location of the position by one horizontal location
+ pinv.iX = p.iX;
+ pinv.iY = p.iY;
+
+ if ( srcrect.Contains( pinv ) )
+ {
+ pinv.iX -= ( TInt32 ) aP.iX;
+ pinv.iY -= ( TInt32 ) aP.iY;
+ // find out cooresponding x & y in OpenVG
+ offset = bufLength;
+ sy = aDstHeight - (offset / aDstWidth);
+ sx = offset % aDstWidth;
+ if (aReverse)
+ {
+ iVgRenderer->vgReadPixels((void *)&pixel, stride, VG_sRGBA_8888_PRE, sx, sy, 1, 1);
+ *(bufsrc32 + ( TInt32 ) pinv.iX + (srcWidth)*( TInt32 ) (pinv.iY)) =
+ (pixel >> 8) | (pixel << 24) ;
+ }
+ else
+ {
+ pixel = *(bufsrc32 + ( TInt32 ) pinv.iX + (srcWidth)*( TInt32 ) (pinv.iY));
+ pixel = (pixel << 8) | (pixel >> 24);
+ iVgRenderer->vgWritePixels((void *)&pixel, stride, VG_sRGBA_8888_PRE, sx, sy, 1, 1);
+ }
+ }
+ p.iX += horizDeriv.iX;
+ p.iY += horizDeriv.iY;
+ bufLength++;
+ }
+ tempBufLength += aDstWidth;
+ bufLength = tempBufLength;
+ if (tempBufLength + aDstWidth >= bufLimit)
+ {
+ aSrc->UnlockHeap();
+ return;
+ }
+ }
+ aSrc->UnlockHeap();
+
+ }
+
+
+
+
+
+
+// --------------------------------------------------------------------------
+// void TGfxImageTransformer::SortCoordinates
+// ---------------------------------------------------------------------------
+
+void TGfxImageTransformer::SortCoordinates(
+ TGfxPoint2D& origin, TGfxPoint2D& top,
+ TGfxPoint2D& north, TGfxPoint2D& south, TGfxPoint2D& right,
+ TGfxPoint2D& east, TGfxPoint2D& west, TGfxPoint2D& corner,
+ const TGfxPoint2D aP, const TInt srcWidth, const TInt srcHeight)
+ {
+
+ origin.iX = aP.iX;
+ origin.iY = aP.iY;
+ corner.iX = aP.iX + (TFloatFixPt)srcWidth;
+ corner.iY = aP.iY + (TFloatFixPt)srcHeight;
+ top.iX = aP.iX;
+ top.iY = aP.iY + (TFloatFixPt)srcHeight;
+ right.iX = aP.iX + (TFloatFixPt)srcWidth;
+ right.iY = aP.iY;
+
+ // transform corners of the source rectangle.
+ iTransform->Transform(&origin, &origin, 1);
+ iTransform->Transform(&top, &top, 1);
+ iTransform->Transform(&right, &right, 1);
+ iTransform->Transform(&corner, &corner, 1);
+
+ west = origin; east = corner; north = top; south = right;
+ if (top.iX < origin.iX)
+ {
+ west = top;
+ east = right;
+ north = corner;
+ south = origin;
+ }
+ else
+ {
+ west = origin;
+ east = corner;
+ north = top;
+ south = right;
+ }
+
+ if (corner.iX < west.iX)
+ {
+ west = corner;
+ east = origin;
+ north = right;
+ south = top;
+ }
+
+ if (right.iX < west.iX)
+ {
+ west = right;
+ east = top;
+ north = origin;
+ south = corner;
+ }
+ }
+
+
+
+
+
+// --------------------------------------------------------------------------
+// void TGfxImageTransformer::ComputeXPositions
+// ---------------------------------------------------------------------------
+
+void TGfxImageTransformer::ComputeXPositions(TFloatFixPt y, TRect rect,
+ TGfxPoint2D north, TGfxPoint2D west, TGfxPoint2D east,
+ TGfxPoint2D south, TInt& xstart, TInt& xend)
+ {
+
+ if ( y > west.iY )
+ {
+ if (north.iY - west.iY == (TFloatFixPt)0)
+ xstart = (TInt32) west.iX;
+ else
+ xstart = (TInt32) (west.iX + (north.iX - west.iX) *
+ ( (y - west.iY) / (north.iY - west.iY) ));
+ }
+ else
+ {
+ if (west.iY - south.iY == (TFloatFixPt)0)
+ xstart = (TInt32) south.iX;
+ else
+ xstart = (TInt32) (south.iX + (west.iX - south.iX) *
+ ( (y - south.iY) / (west.iY - south.iY) ));
+ }
+
+ // compute scanline edges end position
+ if ( y > east.iY )
+ {
+ if ( north.iY - east.iY == (TFloatFixPt)0 )
+ xend = (TInt32) north.iX;
+ else
+ xend = (TInt32) (east.iX + (north.iX - east.iX) *
+ ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
+ }
+ else
+ {
+ if ( (east.iY - south.iY) == (TFloatFixPt)0 )
+ xend = (TInt32) east.iX;
+ else
+ xend = (TInt32) (south.iX + (east.iX - south.iX) *
+ ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
+ }
+
+ // does span clip against edges
+ if(xstart < rect.iTl.iX)
+ xstart = rect.iTl.iX;
+
+ if(xend >= rect.iBr.iX) // iX-1 seems to be the limit, using iX rolls over to next line
+ xend = rect.iBr.iX-1;
+ }
+
+// --------------------------------------------------------------------------
+// void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
+// ---------------------------------------------------------------------------
+ void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
+ const TGfxPoint2D& aP,
+ TUint32* aDst,
+ TInt aDstWidth,
+ TInt aDstHeight,
+ TUint8 /*aAlpha*/,
+ TGfxColor aTransparentColor,
+ const TRect& aClipRect,
+ TBool aReverse
+ )
+ {
+ TRect rect;
+ TInt32 x, y;
+
+ TFloatFixPt currentScale = iTransform->ScalingFactor();
+ TSize bitmapSize = aSrc->SizeInPixels();
+ TRect srcrect( TPoint( aP.iX, aP.iY ),
+ TSize( bitmapSize.iWidth-1, bitmapSize.iHeight-1 ) );
+ TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth-1, aDstHeight-1) );
+ TInt32 srcWidth = bitmapSize.iWidth;
+ TInt32 srcHeight = bitmapSize.iHeight;
+ TInt32 pad = (srcWidth & 1);
+
+ TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
+ rect.SetRect( TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
+ rect.Intersection(aClipRect); // Clipping
+
+ if ( !rect.Intersects( dstrect ) ) // clip rect with dst image
+ return;
+
+ aSrc->LockHeap();
+ rect.Intersection( dstrect );
+ TDisplayMode dispmode = aSrc->DisplayMode();
+
+ TUint16* bufsrc16 = NULL;
+ TUint32* bufsrc32 = NULL;
+ if ( dispmode == EColor16MU)
+ {
+ bufsrc32 = (TUint32*) aSrc->DataAddress();
+ }
+ else
+ {
+ bufsrc16 = (TUint16*) aSrc->DataAddress();
+ }
+ TUint32* buf = aDst + rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
+ TUint32* bufLimit = aDst + aDstWidth * aDstHeight;
+ TUint32 pix = 0;
+ TInt dstStride = aDstWidth;
+
+ TGfxAffineTransform inv = iTransform->CreateInverse();
+
+ if ( aTransparentColor.GetARGB() == KGfxColorNull /* && aAlpha == 0xff */ &&
+ (int)inv.TransformType() == KTransformIdentity && aReverse == EFalse)
+ {
+ // Fast case; no alpha or transform (cdm).
+ TPoint p;
+ TInt lScrPp = (srcWidth+pad);
+ for ( y = rect.iTl.iY; y <= rect.iBr.iY; y++ )
+ {
+ for ( x = rect.iTl.iX; x <= rect.iBr.iX; x++ )
+ {
+ p.iX = x;
+ p.iY = y;
+
+ if ( srcrect.Contains( p ) )
+ {
+ p.iX -= ( TInt32 ) aP.iX;
+ p.iY -= ( TInt32 ) aP.iY;
+ if ( dispmode == EColor16MU)
+ {
+ buf[x] = (TUint32) *(bufsrc32 + ( TInt32 ) p.iX + (lScrPp)*( TInt32 ) p.iY);
+ *buf = pix;
+ }
+ else
+ {
+ // src:RGB565 -> dst:ARGB8888
+ pix = (TUint32) *(bufsrc16 + ( TInt32 ) p.iX + (lScrPp)*( TInt32 ) p.iY);
+ buf[x] = RGB565toRGB888(pix);
+ }
+ }
+ }
+ buf += dstStride;
+ if (buf + dstStride >= bufLimit)
+ {
+ aSrc->UnlockHeap();
+ return;
+ }
+ }
+ }
+ else // Alpha blending and/or transform is required.
+ {
+ TPoint pinv;
+ TGfxPoint2D p;
+
+ TUint32* obuf = buf;
+ TInt32 xstart, xend, yend;
+ TGfxPoint2D horizDeriv;
+ TGfxPoint2D origin, top, right, corner;
+ TGfxPoint2D east, west, south, north;
+
+ origin.iX = aP.iX;
+ origin.iY = aP.iY;
+ corner.iX = aP.iX + (TFloatFixPt)srcWidth;
+ corner.iY = aP.iY + (TFloatFixPt)srcHeight;
+ top.iX = aP.iX;
+ top.iY = aP.iY + (TFloatFixPt)srcHeight;
+ right.iX = aP.iX + (TFloatFixPt)srcWidth;
+ right.iY = aP.iY;
+
+ // transform corners of the source rectangle.
+ iTransform->Transform(&origin, &origin, 1);
+ iTransform->Transform(&top, &top, 1);
+ iTransform->Transform(&right, &right, 1);
+ iTransform->Transform(&corner, &corner, 1);
+
+ // sort four corners into appropriate order
+ west = origin; east = corner; north = top; south = right;
+ if (top.iX < origin.iX)
+ {
+ west = top;
+ east = right;
+ north = corner;
+ south = origin;
+ }
+ else
+ {
+ west = origin;
+ east = corner;
+ north = top;
+ south = right;
+ }
+
+ if (corner.iX < west.iX)
+ {
+ west = corner;
+ east = origin;
+ north = right;
+ south = top;
+ }
+
+ if (right.iX < west.iX)
+ {
+ west = right;
+ east = top;
+ north = origin;
+ south = corner;
+ }
+
+ // compute derivitives for scanline in source.
+ p.iX = 1;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX = p.iX;
+ horizDeriv.iY = p.iY;
+ p.iX = 0;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX -= p.iX;
+ horizDeriv.iY -= p.iY;
+
+ yend = rect.iBr.iY;
+ TInt lScrPp = 0;
+ if ( dispmode == EColor16MU)
+ {
+ lScrPp = srcWidth;
+ }
+ else
+ {
+ lScrPp = srcWidth+pad;
+ }
+
+ TUint32 transparentColorRgb565 = aTransparentColor.ColorRgb565();
+
+ for ( y = rect.iTl.iY; y <= yend; y++ )
+ {
+ p.iY = y;
+
+ // compute scanline starting position
+
+ if ( ((TFloatFixPt)y) > west.iY )
+ {
+ if(north.iY - west.iY == (TFloatFixPt)0)
+ xstart = (TInt32) west.iX;
+ else
+ xstart = (TInt32) (west.iX + (north.iX - west.iX) * ( (((TFloatFixPt)y) - west.iY) / (north.iY - west.iY) ));
+ }
+ else
+ {
+ if(west.iY - south.iY == (TFloatFixPt)0)
+ xstart = (TInt32) south.iX;
+ else
+ xstart = (TInt32) (south.iX + (west.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (west.iY - south.iY) ));
+ }
+
+ // compute scanline edges end position
+ if ( (TFloatFixPt)y > east.iY )
+ {
+ if(north.iY - east.iY == (TFloatFixPt)0)
+ xend = (TInt32) north.iX;
+ else
+ xend = (TInt32) (east.iX + (north.iX - east.iX) * ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
+ }
+ else
+ {
+ if ( (east.iY - south.iY) == (TFloatFixPt)0 )
+ xend = (TInt32) east.iX;
+ else
+ xend = (TInt32) (south.iX + (east.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
+ }
+
+ // does span clip against edges
+ if(xstart < rect.iTl.iX)
+ xstart = rect.iTl.iX;
+
+ if(xend >= rect.iBr.iX) // iX-1 seems to be the limit, using iX rolls over to next line
+ xend = rect.iBr.iX-1;
+
+ p.iX = xstart;
+ // transform that starting position to the source image
+ inv.Transform( &p, & p, 1 );
+ buf += xstart-rect.iTl.iX;
+
+ p.iY -= TFloatFixPt(.5f) * currentScale;
+
+ if (aTransparentColor.GetARGB() == KGfxColorNull)
+ {
+ for ( x = xstart; x <= xend; x++ )
+ {
+ //increment the location of the position by one horizontal location
+ pinv.iX = p.iX;
+ pinv.iY = p.iY;
+ if ( srcrect.Contains( pinv ) )
+ {
+ pinv.iX -= ( TInt32 ) aP.iX;
+ pinv.iY -= ( TInt32 ) aP.iY;
+ if ( dispmode == EColor16MU )
+ {
+ *buf = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
+ }
+ else
+ {
+ // src:RGB565 -> dst:ARGB8888
+ pix = (TUint32)*(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
+ *buf = RGB565toRGB888(pix);
+ }
+ }
+ p.iX += horizDeriv.iX;
+ p.iY += horizDeriv.iY;
+ buf++;
+ }
+ }
+ else
+ {
+ for ( x = xstart; x <= xend; x++ )
+ {
+ //increment the location of the position by one horizontal location
+ pinv.iX = p.iX;
+ pinv.iY = p.iY;
+
+ if ( srcrect.Contains( pinv ) )
+ {
+ pinv.iX -= ( TInt32 ) aP.iX;
+ pinv.iY -= ( TInt32 ) aP.iY;
+
+ if ( aReverse ) // copy source to destination. Used for Text blending with final framebufer.
+ { // this used for text only
+ if ( dispmode == EColor16MU )
+ {
+ *(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY)) = *buf ;
+ }
+ else
+ {
+ *(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY)) = *buf ;
+ }
+ }
+ else
+ {
+ if ( dispmode == EColor16MU )
+ {
+ pix = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
+ if (pix != transparentColorRgb565)
+ {
+ *buf = pix;
+ }
+ }
+ else
+ {
+ pix = (TUint32) *(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
+ if (pix != transparentColorRgb565)
+ {
+ *buf = RGB565toRGB888(pix);
+ }
+ }
+ }
+ }
+ p.iX += horizDeriv.iX;
+ p.iY += horizDeriv.iY;
+ buf++;
+ }
+ }
+ buf = obuf+aDstWidth;
+ obuf += aDstWidth;
+ if (obuf + aDstWidth >= bufLimit)
+ {
+ aSrc->UnlockHeap();
+ return;
+ }
+ }
+ }
+
+ aSrc->UnlockHeap();
+ }
+
+// --------------------------------------------------------------------------
+// void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
+// ---------------------------------------------------------------------------
+ void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
+ const TGfxPoint2D& aP,
+ TUint32* aDst,
+ TInt aDstWidth,
+ TInt aDstHeight,
+ const TRect& aClipRect
+ )
+ {
+ TDisplayMode dispmode = aSrc->DisplayMode();
+ if ( dispmode != EColor16MU )
+ {
+ return;
+ }
+
+ TRect rect;
+ TInt32 x, y;
+
+ TFloatFixPt currentScale = iTransform->ScalingFactor();
+
+ TRect srcrect( TPoint( aP.iX, aP.iY ), aSrc->SizeInPixels() );
+ TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth, aDstHeight) );
+ TInt32 srcWidth = aSrc->SizeInPixels().iWidth;
+ TInt32 srcHeight = aSrc->SizeInPixels().iHeight;
+
+ TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
+ rect.SetRect( TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
+ rect.Intersection(aClipRect); // Clipping
+
+ if ( !rect.Intersects( dstrect ) ) // clip rect with dst image
+ return;
+
+ aSrc->LockHeap();
+ rect.Intersection( dstrect );
+
+ TUint32* bufsrc32 = (TUint32*) aSrc->DataAddress();
+
+ TUint32* buf = aDst + rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
+ TUint32* bufLimit = aDst + aDstWidth * aDstHeight;
+ TUint32 pix = 0;
+
+ TGfxAffineTransform inv = iTransform->CreateInverse();
+
+ {
+ TPoint pinv;
+ TGfxPoint2D p;
+
+ TUint32* obuf = buf;
+ TInt32 xstart, xend, yend;
+ TGfxPoint2D horizDeriv;
+ TGfxPoint2D origin, top, right, corner;
+ TGfxPoint2D east, west, south, north;
+
+ origin.iX = aP.iX;
+ origin.iY = aP.iY;
+ corner.iX = aP.iX + (TFloatFixPt)srcWidth;
+ corner.iY = aP.iY + (TFloatFixPt)srcHeight;
+ top.iX = aP.iX;
+ top.iY = aP.iY + (TFloatFixPt)srcHeight;
+ right.iX = aP.iX + (TFloatFixPt)srcWidth;
+ right.iY = aP.iY;
+
+ // transform corners of the source rectangle.
+ iTransform->Transform(&origin, &origin, 1);
+ iTransform->Transform(&top, &top, 1);
+ iTransform->Transform(&right, &right, 1);
+ iTransform->Transform(&corner, &corner, 1);
+
+ // sort four corners into appropriate order
+ west = origin; east = corner; north = top; south = right;
+ if (top.iX < origin.iX)
+ {
+ west = top;
+ east = right;
+ north = corner;
+ south = origin;
+ }
+ else
+ {
+ west = origin;
+ east = corner;
+ north = top;
+ south = right;
+ }
+
+ if (corner.iX < west.iX)
+ {
+ west = corner;
+ east = origin;
+ north = right;
+ south = top;
+ }
+
+ if (right.iX < west.iX)
+ {
+ west = right;
+ east = top;
+ north = origin;
+ south = corner;
+ }
+
+ // compute derivitives for scanline in source.
+ p.iX = 8;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX = p.iX;
+ horizDeriv.iY = p.iY;
+ p.iX = 0;
+ p.iY = 0;
+ inv.Transform( &p, & p, 1 );
+ horizDeriv.iX -= p.iX;
+ horizDeriv.iY -= p.iY;
+ horizDeriv.iX = horizDeriv.iX >> 3;
+ horizDeriv.iY = horizDeriv.iY >> 3;
+
+ yend = rect.iBr.iY;
+ TInt lScrPp = 0;
+ lScrPp = srcWidth;
+
+
+ for ( y = rect.iTl.iY; y <= yend; y++ )
+ {
+ p.iY = y;
+
+ // compute scanline starting position
+
+ if ( ((TFloatFixPt)y) > west.iY )
+ {
+ if(north.iY - west.iY == (TFloatFixPt)0)
+ xstart = (TInt32) west.iX;
+ else
+ xstart = (TInt32) (west.iX + (north.iX - west.iX) * ( (((TFloatFixPt)y) - west.iY) / (north.iY - west.iY) ));
+ }
+ else
+ {
+ if(west.iY - south.iY == (TFloatFixPt)0)
+ xstart = (TInt32) south.iX;
+ else
+ xstart = (TInt32) (south.iX + (west.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (west.iY - south.iY) ));
+ }
+
+ // compute scanline edges end position
+ if ( (TFloatFixPt)y > east.iY )
+ {
+ if(north.iY - east.iY == (TFloatFixPt)0)
+ xend = (TInt32) north.iX;
+ else
+ xend = (TInt32) (east.iX + (north.iX - east.iX) * ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
+ }
+ else
+ {
+ if ( (east.iY - south.iY) == (TFloatFixPt)0 )
+ xend = (TInt32) east.iX;
+ else
+ xend = (TInt32) (south.iX + (east.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
+ }
+
+ // does span clip against edges
+ if(xstart < rect.iTl.iX)
+ xstart = rect.iTl.iX;
+
+ if(xend >= rect.iBr.iX) // iX-1 seems to be the limit, using iX rolls over to next line
+ xend = rect.iBr.iX-1;
+
+ p.iX = xstart;
+ // transform that starting position to the source image
+ inv.Transform( &p, & p, 1 );
+ buf += xstart-rect.iTl.iX;
+ // Change here
+ p.iY -= TFloatFixPt(0.5f) * currentScale;
+
+ {
+ for ( x = xstart; x <= xend; x++ )
+ {
+ //increment the location of the position by one horizontal location
+ pinv.iX = p.iX;
+ pinv.iY = p.iY;
+ if ( srcrect.Contains( pinv ) )
+ {
+ pinv.iX -= ( TInt32 ) aP.iX;
+ pinv.iY -= ( TInt32 ) aP.iY;
+
+ pix = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
+ TUint srcAlpha = ( pix & 0xFF000000 ) >> 24;
+ if ( srcAlpha == 0xFF )
+ {
+ *buf = pix;
+ }
+ else if ( srcAlpha > 0 )
+ {
+ TUint destPix = *buf;
+ TUint destAlpha = ( destPix & 0xFF000000 ) >> 24;
+ // Blending needed: blend with background as opaque
+ if ( destAlpha == 0xFF )
+ {
+ TReal32 alpha = 0.0039215686 * srcAlpha; // 0.0039.. = 1/255
+ TReal32 inverseAlpha = 1.0f - alpha;
+ *buf = ((((TUint)((pix >> 16 & 0xff) * alpha) +
+ (TUint)((destPix >> 16 & 0xff) * inverseAlpha))) << 16) | // red
+ ((((TUint)((pix >> 8 & 0xff) * alpha) +
+ (TUint)((destPix >> 8 & 0xff) * inverseAlpha))) << 8 ) | // green
+ ((((TUint)((pix & 0xff) * alpha) +
+ (TUint)((destPix & 0xff) * inverseAlpha))) ) | // blue
+ (0xFF000000); // full alpha (already blended)
+ }
+ // Apply alpha to each color channel of source only
+ // Important: use original alpha
+ else
+ {
+ TReal32 alpha = 0.0039215686 * srcAlpha;
+ *buf = (srcAlpha << 24)|
+ ((TUint)((pix >> 16 & 0xff) * alpha) << 16) |
+ ((TUint)((pix >> 8 & 0xff) * alpha) << 8) |
+ ((TUint)((pix & 0xff) * alpha));
+ }
+ }
+ }
+ p.iX += horizDeriv.iX;
+ p.iY += horizDeriv.iY;
+ buf++;
+ }
+ }
+
+ buf = obuf+aDstWidth;
+ obuf += aDstWidth;
+ if (obuf + aDstWidth >= bufLimit)
+ {
+ aSrc->UnlockHeap();
+ return;
+ }
+ }
+ }
+
+ aSrc->UnlockHeap();
+ }
+
+// TGfxRectangle2D TGfxImageTransformer::GetTransformedBound( CFbsBitmap* aSrc,
+// ---------------------------------------------------------------------------
+ TGfxRectangle2D TGfxImageTransformer::GetTransformedBound( CFbsBitmap* aSrc,
+ const TGfxPoint2D& aOffset )
+ {
+ TGfxRectangle2D rect;
+ TGfxPoint2D rectp[4];
+
+ rectp[0].iX = aOffset.iX;
+ rectp[0].iY = aOffset.iY;
+ rectp[1].iX = aOffset.iX + ( TFloatFixPt ) aSrc->SizeInPixels().iWidth;
+ rectp[1].iY = aOffset.iY;
+ rectp[2].iX = aOffset.iX + ( TFloatFixPt ) aSrc->SizeInPixels().iWidth;
+ rectp[2].iY = aOffset.iY + ( TFloatFixPt ) aSrc->SizeInPixels().iHeight;
+ rectp[3].iX = aOffset.iX;
+ rectp[3].iY = aOffset.iY + ( TFloatFixPt ) aSrc->SizeInPixels().iHeight;
+ iTransform->Transform( rectp, rectp, 4 );
+
+ TInt32 i;
+ //MinX
+ rect.iX = rectp[0].iX;
+ rect.iY = rectp[0].iY;
+ rect.iWidth = rectp[0].iX;
+ rect.iHeight = rectp[0].iY;
+
+ for ( i = 1; i < 4; i++ )
+ {
+ if ( rectp[i].iX < rect.iX )
+ rect.iX = rectp[i].iX;
+ //MinY
+ if ( rectp[i].iY < rect.iY )
+ rect.iY = rectp[i].iY;
+ //MaxX -> width
+ if ( rectp[i].iX > rect.iWidth )
+ rect.iWidth = rectp[i].iX;
+ //MaxY -> height
+ if ( rectp[i].iY > rect.iHeight )
+ rect.iHeight = rectp[i].iY;
+ }
+ rect.iWidth -= rect.iX;
+ rect.iHeight -= rect.iY;
+
+ return rect;
+ }
+