svgtopt/gfx2d/src/GfxImage/GfxImageTransformer.cpp
changeset 0 d46562c3d99d
equal deleted inserted replaced
-1:000000000000 0:d46562c3d99d
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Graphics Extension Library source file
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "GfxImageTransformer.h"
       
    20 #include "GfxColor.h"
       
    21 
       
    22 #define RGB565toRGB888(rgb565) (0xff000000|((rgb565 << 8) & 0xf80000) | ((rgb565 << 5) & 0x00fc00) | ((rgb565 << 3) & 0x000f8))
       
    23 
       
    24 // ---------------------------------------------------------------------------
       
    25 // Constructor
       
    26 // ---------------------------------------------------------------------------
       
    27 // --------------------------------------------------------------------------
       
    28 //  TGfxImageTransformer::TGfxImageTransformer( TGfxAffineTransform* aTransform )
       
    29 // ---------------------------------------------------------------------------
       
    30  TGfxImageTransformer::TGfxImageTransformer( TGfxAffineTransform* aTransform, CVGRenderer * aRenderer )
       
    31     {
       
    32     iTransform = aTransform;
       
    33     iVgRenderer = aRenderer;
       
    34 	}
       
    35 
       
    36 
       
    37 
       
    38 
       
    39 // --------------------------------------------------------------------------
       
    40 //  void TGfxImageTransformer::ImageBlend( CFbsBitmap* aSrc,
       
    41 // ---------------------------------------------------------------------------
       
    42  void TGfxImageTransformer::ImageBlend( CFbsBitmap* aSrc,
       
    43                                           const TGfxPoint2D& aP,
       
    44 										  TInt aDstWidth,
       
    45 										  TInt aDstHeight,
       
    46                                           const TRect& aClipRect,
       
    47 										  TBool aReverse)
       
    48 {
       
    49 
       
    50     TRect srcrect( TPoint( aP.iX, aP.iY ), aSrc->SizeInPixels() );
       
    51     TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth, aDstHeight) );
       
    52 	TInt srcWidth = aSrc->SizeInPixels().iWidth;
       
    53 	TInt srcHeight = aSrc->SizeInPixels().iHeight;
       
    54 
       
    55     TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
       
    56     TRect rect (TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
       
    57 	rect.Intersection(aClipRect);	// Clipping
       
    58 
       
    59     if ( !rect.Intersects( dstrect ) )    // clip rect with dst image
       
    60         return;
       
    61 
       
    62     aSrc->LockHeap();
       
    63     rect.Intersection( dstrect );
       
    64 
       
    65 	TUint32* bufsrc32 = (TUint32*) aSrc->DataAddress();
       
    66     TUint bufLimit = aDstWidth * aDstHeight;
       
    67 
       
    68     TGfxAffineTransform inv = iTransform->CreateInverse();
       
    69 
       
    70     TInt xstart, xend, yend;
       
    71 	TGfxPoint2D horizDeriv;
       
    72 	TGfxPoint2D origin, top, right, corner, east, west, south, north;
       
    73 
       
    74 	// sort four corners into appropriate order
       
    75 	SortCoordinates(origin, top, north, south, right, east, west,
       
    76 	    corner, aP, srcWidth, srcHeight);
       
    77 
       
    78 	// compute derivitives for scanline in source.
       
    79     TPoint pinv;
       
    80     TGfxPoint2D p;
       
    81 	p.iX = 8;
       
    82 	p.iY = 0;
       
    83 	inv.Transform( &p, & p, 1 );
       
    84 	horizDeriv.iX = p.iX;
       
    85 	horizDeriv.iY = p.iY;
       
    86 	p.iX = 0;
       
    87 	p.iY = 0;
       
    88 	inv.Transform( &p, & p, 1 );
       
    89 	horizDeriv.iX -= p.iX;
       
    90 	horizDeriv.iY -= p.iY;
       
    91 	horizDeriv.iX = horizDeriv.iX >> 3;
       
    92 	horizDeriv.iY = horizDeriv.iY >> 3;
       
    93 
       
    94     yend = rect.iBr.iY;
       
    95     TInt bufLength = rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
       
    96 	TInt tempBufLength = bufLength;
       
    97 
       
    98     TInt x, y;
       
    99     TInt sx, sy;
       
   100     TUint32 pixel;
       
   101     TInt offset;
       
   102     VGint stride = CFbsBitmap::ScanLineLength( aDstWidth, aSrc->DisplayMode() );
       
   103     for ( y = rect.iTl.iY; y <= yend; y++ )
       
   104         {
       
   105         p.iY = y;
       
   106 		// compute scanline starting position
       
   107 		ComputeXPositions((TFloatFixPt)y, rect, north, west, east, south, xstart, xend);
       
   108 
       
   109 		p.iX = xstart;
       
   110 		// transform that starting position to the source image
       
   111 		inv.Transform( &p, & p, 1 );
       
   112 		bufLength += xstart - rect.iTl.iX;
       
   113 
       
   114 	#ifdef SVG_FLOAT_BUILD
       
   115 	p.iY -= TFloatFixPt( .5f );
       
   116 	#else
       
   117 	p.iY -= TFloatFixPt(0x8000, ETrue);
       
   118 	#endif
       
   119 		for ( x = xstart; x <= xend; x++ )
       
   120 			{
       
   121 			//increment the location of the position by one horizontal location
       
   122 			pinv.iX = p.iX;
       
   123 			pinv.iY = p.iY;
       
   124 
       
   125 			if ( srcrect.Contains( pinv ) )
       
   126 				{
       
   127 				pinv.iX -= ( TInt32 ) aP.iX;
       
   128 				pinv.iY -= ( TInt32 ) aP.iY;
       
   129                 // find out cooresponding x & y in OpenVG
       
   130                 offset = bufLength;
       
   131                 sy = aDstHeight - (offset / aDstWidth);
       
   132                 sx = offset % aDstWidth;
       
   133                 if (aReverse)
       
   134                     {
       
   135                     iVgRenderer->vgReadPixels((void *)&pixel, stride, VG_sRGBA_8888_PRE, sx, sy, 1, 1);
       
   136     				*(bufsrc32 + ( TInt32 ) pinv.iX + (srcWidth)*( TInt32 ) (pinv.iY)) =
       
   137     				    (pixel >> 8) | (pixel << 24) ;
       
   138     				}
       
   139     			else
       
   140     			    {
       
   141     			    pixel = *(bufsrc32 + ( TInt32 ) pinv.iX + (srcWidth)*( TInt32 ) (pinv.iY));
       
   142     			    pixel = (pixel << 8) | (pixel >> 24);
       
   143     			    iVgRenderer->vgWritePixels((void *)&pixel, stride, VG_sRGBA_8888_PRE, sx, sy, 1, 1);
       
   144     			    }
       
   145 				}
       
   146 			p.iX += horizDeriv.iX;
       
   147 			p.iY += horizDeriv.iY;
       
   148 			bufLength++;
       
   149 			}
       
   150 		tempBufLength += aDstWidth;
       
   151 		bufLength = tempBufLength;
       
   152 		if (tempBufLength + aDstWidth >= bufLimit)
       
   153             {
       
   154             aSrc->UnlockHeap();
       
   155             return;
       
   156             }
       
   157         }
       
   158     aSrc->UnlockHeap();
       
   159 
       
   160     }
       
   161 
       
   162 
       
   163 
       
   164 
       
   165 
       
   166 
       
   167 // --------------------------------------------------------------------------
       
   168 //  void TGfxImageTransformer::SortCoordinates
       
   169 // ---------------------------------------------------------------------------
       
   170 
       
   171 void TGfxImageTransformer::SortCoordinates(
       
   172     TGfxPoint2D& origin, TGfxPoint2D& top,
       
   173     TGfxPoint2D& north, TGfxPoint2D& south, TGfxPoint2D& right,
       
   174     TGfxPoint2D& east, TGfxPoint2D& west, TGfxPoint2D& corner,
       
   175     const TGfxPoint2D aP, const TInt srcWidth, const TInt srcHeight)
       
   176     {
       
   177 
       
   178 	origin.iX = aP.iX;
       
   179 	origin.iY = aP.iY;
       
   180 	corner.iX = aP.iX + (TFloatFixPt)srcWidth;
       
   181 	corner.iY = aP.iY + (TFloatFixPt)srcHeight;
       
   182 	top.iX =	aP.iX;
       
   183 	top.iY =	aP.iY + (TFloatFixPt)srcHeight;
       
   184 	right.iX =	aP.iX + (TFloatFixPt)srcWidth;
       
   185 	right.iY =	aP.iY;
       
   186 
       
   187 	// transform corners of the source rectangle.
       
   188     iTransform->Transform(&origin, &origin, 1);
       
   189     iTransform->Transform(&top, &top, 1);
       
   190     iTransform->Transform(&right, &right, 1);
       
   191 	iTransform->Transform(&corner, &corner, 1);
       
   192 
       
   193 	west = origin; east = corner; north = top; south = right;
       
   194 	if (top.iX < origin.iX)
       
   195 	    {
       
   196 	    west = top;
       
   197 	    east = right;
       
   198 	    north = corner;
       
   199 	    south = origin;
       
   200 	    }
       
   201 	else
       
   202 	    {
       
   203 	    west = origin;
       
   204 	    east = corner;
       
   205 	    north = top;
       
   206 	    south = right;
       
   207 	    }
       
   208 
       
   209 	if (corner.iX < west.iX)
       
   210 	    {
       
   211 	    west = corner;
       
   212 	    east = origin;
       
   213 	    north = right;
       
   214 	    south = top;
       
   215 	    }
       
   216 
       
   217 	if (right.iX < west.iX)
       
   218 	    {
       
   219 	    west = right;
       
   220 	    east = top;
       
   221 	    north = origin;
       
   222 	    south = corner;
       
   223 	    }
       
   224     }
       
   225 
       
   226 
       
   227 
       
   228 
       
   229 
       
   230 // --------------------------------------------------------------------------
       
   231 //  void TGfxImageTransformer::ComputeXPositions
       
   232 // ---------------------------------------------------------------------------
       
   233 
       
   234 void TGfxImageTransformer::ComputeXPositions(TFloatFixPt y, TRect rect,
       
   235     TGfxPoint2D north, TGfxPoint2D west, TGfxPoint2D east,
       
   236     TGfxPoint2D south, TInt& xstart, TInt& xend)
       
   237     {
       
   238 
       
   239 	if ( y > west.iY )
       
   240 	    {
       
   241 		if (north.iY - west.iY == (TFloatFixPt)0)
       
   242 			xstart = (TInt32) west.iX;
       
   243 		else
       
   244 			xstart = (TInt32) (west.iX + (north.iX - west.iX) *
       
   245 			    ( (y - west.iY) / (north.iY - west.iY) ));
       
   246 	    }
       
   247 	else
       
   248 	    {
       
   249 		if (west.iY - south.iY == (TFloatFixPt)0)
       
   250 			xstart = (TInt32) south.iX;
       
   251 		else
       
   252 			xstart = (TInt32) (south.iX + (west.iX - south.iX) *
       
   253 			    ( (y - south.iY) / (west.iY - south.iY) ));
       
   254 	    }
       
   255 
       
   256 	// compute scanline edges end position
       
   257 	if ( y > east.iY )
       
   258 	    {
       
   259 		if ( north.iY - east.iY == (TFloatFixPt)0 )
       
   260 			xend = (TInt32) north.iX;
       
   261 		else
       
   262 			xend = (TInt32) (east.iX + (north.iX - east.iX) *
       
   263 			    ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
       
   264 	    }
       
   265 	else
       
   266 	    {
       
   267 		if ( (east.iY - south.iY) == (TFloatFixPt)0 )
       
   268 			xend = (TInt32) east.iX;
       
   269 		else
       
   270 			xend = (TInt32) (south.iX + (east.iX - south.iX) *
       
   271 			    ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
       
   272 	    }
       
   273 
       
   274     // does span clip against edges
       
   275 	if(xstart < rect.iTl.iX)
       
   276 		xstart = rect.iTl.iX;
       
   277 
       
   278 	if(xend >= rect.iBr.iX)  // iX-1 seems to be the limit, using iX rolls over to next line
       
   279 		xend = rect.iBr.iX-1;
       
   280     }
       
   281 
       
   282 // --------------------------------------------------------------------------
       
   283 //  void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
       
   284 // ---------------------------------------------------------------------------
       
   285  void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
       
   286                                           const TGfxPoint2D& aP,
       
   287 										  TUint32* aDst,
       
   288 										  TInt aDstWidth,
       
   289 										  TInt aDstHeight,
       
   290                                           TUint8 /*aAlpha*/,
       
   291                                           TGfxColor aTransparentColor,
       
   292 										  const TRect& aClipRect,
       
   293 										  TBool aReverse
       
   294 										  )
       
   295     {
       
   296     TRect rect;
       
   297     TInt32 x, y;
       
   298 
       
   299 	TFloatFixPt currentScale = iTransform->ScalingFactor();
       
   300 		TSize bitmapSize = aSrc->SizeInPixels();
       
   301     TRect srcrect( TPoint( aP.iX, aP.iY ),
       
   302                    TSize( bitmapSize.iWidth-1, bitmapSize.iHeight-1 ) );
       
   303     TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth-1, aDstHeight-1) );
       
   304 	  TInt32 srcWidth = bitmapSize.iWidth;
       
   305 	  TInt32 srcHeight = bitmapSize.iHeight;
       
   306     TInt32 pad = (srcWidth & 1);
       
   307 
       
   308     TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
       
   309     rect.SetRect( TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
       
   310 	rect.Intersection(aClipRect);	// Clipping
       
   311 
       
   312     if ( !rect.Intersects( dstrect ) )    // clip rect with dst image
       
   313         return;
       
   314 
       
   315     aSrc->LockHeap();
       
   316     rect.Intersection( dstrect );
       
   317     TDisplayMode dispmode = aSrc->DisplayMode();
       
   318 
       
   319 	TUint16* bufsrc16 = NULL;
       
   320 	TUint32* bufsrc32 = NULL;
       
   321 	if ( dispmode ==  EColor16MU)
       
   322 	    {
       
   323 	    bufsrc32 = (TUint32*) aSrc->DataAddress();
       
   324 	    }
       
   325 	else
       
   326 	    {
       
   327 	    bufsrc16 = (TUint16*) aSrc->DataAddress();
       
   328 	    }
       
   329     TUint32* buf = aDst + rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
       
   330     TUint32* bufLimit = aDst + aDstWidth * aDstHeight;
       
   331 	TUint32 pix = 0;
       
   332         TInt dstStride = aDstWidth;
       
   333 
       
   334     TGfxAffineTransform inv = iTransform->CreateInverse();
       
   335 
       
   336     if ( aTransparentColor.GetARGB() == KGfxColorNull /* && aAlpha == 0xff */ &&
       
   337         (int)inv.TransformType() == KTransformIdentity && aReverse == EFalse)
       
   338         {
       
   339         // Fast case; no alpha or transform (cdm).
       
   340         TPoint p;
       
   341 		TInt lScrPp = (srcWidth+pad);
       
   342         for ( y = rect.iTl.iY; y <= rect.iBr.iY; y++ )
       
   343             {
       
   344             for ( x = rect.iTl.iX; x <= rect.iBr.iX; x++ )
       
   345                 {
       
   346                 p.iX = x;
       
   347                 p.iY = y;
       
   348 
       
   349                 if ( srcrect.Contains( p ) )
       
   350                     {
       
   351                     p.iX -= ( TInt32 ) aP.iX;
       
   352                     p.iY -= ( TInt32 ) aP.iY;
       
   353 					if ( dispmode ==  EColor16MU)
       
   354 					    {
       
   355     					buf[x] = (TUint32) *(bufsrc32 + ( TInt32 ) p.iX + (lScrPp)*( TInt32 ) p.iY);
       
   356     					*buf = pix;
       
   357 					    }
       
   358 					else
       
   359 					    {
       
   360     					// src:RGB565 -> dst:ARGB8888
       
   361     					pix = (TUint32) *(bufsrc16 + ( TInt32 ) p.iX + (lScrPp)*( TInt32 ) p.iY);
       
   362     					buf[x] = RGB565toRGB888(pix);
       
   363 					    }
       
   364                     }
       
   365                 }
       
   366 			buf += dstStride;
       
   367 			if (buf + dstStride >= bufLimit)
       
   368                 {
       
   369                     aSrc->UnlockHeap();
       
   370                     return;
       
   371                 }
       
   372             }
       
   373         }
       
   374     else    // Alpha blending and/or transform is required.
       
   375         {
       
   376         TPoint pinv;
       
   377         TGfxPoint2D p;
       
   378 
       
   379 		TUint32* obuf = buf;
       
   380 		TInt32 xstart, xend, yend;
       
   381 		TGfxPoint2D horizDeriv;
       
   382 		TGfxPoint2D origin, top, right, corner;
       
   383 		TGfxPoint2D east, west, south, north;
       
   384 
       
   385 		origin.iX = aP.iX;
       
   386 		origin.iY = aP.iY;
       
   387 		corner.iX = aP.iX + (TFloatFixPt)srcWidth;
       
   388 		corner.iY = aP.iY + (TFloatFixPt)srcHeight;
       
   389 		top.iX =	aP.iX;
       
   390 		top.iY =	aP.iY + (TFloatFixPt)srcHeight;
       
   391 		right.iX =	aP.iX + (TFloatFixPt)srcWidth;
       
   392 		right.iY =	aP.iY;
       
   393 
       
   394 		// transform corners of the source rectangle.
       
   395         iTransform->Transform(&origin, &origin, 1);
       
   396         iTransform->Transform(&top, &top, 1);
       
   397         iTransform->Transform(&right, &right, 1);
       
   398 		iTransform->Transform(&corner, &corner, 1);
       
   399 
       
   400 		// sort four corners into appropriate order
       
   401 		west = origin; east = corner; north = top; south = right;
       
   402 		if (top.iX < origin.iX)
       
   403 		    {
       
   404 		    west = top;
       
   405 		    east = right;
       
   406 		    north = corner;
       
   407 		    south = origin;
       
   408 		    }
       
   409 		else
       
   410 		    {
       
   411 		    west = origin;
       
   412 		    east = corner;
       
   413 		    north = top;
       
   414 		    south = right;
       
   415 		    }
       
   416 
       
   417 		if (corner.iX < west.iX)
       
   418 		    {
       
   419 		    west = corner;
       
   420 		    east = origin;
       
   421 		    north = right;
       
   422 		    south = top;
       
   423 		    }
       
   424 
       
   425 		if (right.iX < west.iX)
       
   426 		    {
       
   427 		    west = right;
       
   428 		    east = top;
       
   429 		    north = origin;
       
   430 		    south = corner;
       
   431 		    }
       
   432 
       
   433 		// compute derivitives for scanline in source.
       
   434 		p.iX = 1;
       
   435 		p.iY = 0;
       
   436 		inv.Transform( &p, & p, 1 );
       
   437 		horizDeriv.iX = p.iX;
       
   438 		horizDeriv.iY = p.iY;
       
   439 		p.iX = 0;
       
   440 		p.iY = 0;
       
   441 		inv.Transform( &p, & p, 1 );
       
   442 		horizDeriv.iX -= p.iX;
       
   443 		horizDeriv.iY -= p.iY;
       
   444 
       
   445         yend = rect.iBr.iY;
       
   446         TInt lScrPp = 0;
       
   447 		if ( dispmode ==  EColor16MU)
       
   448 		    {
       
   449 			lScrPp = srcWidth;
       
   450 		    }
       
   451 		else
       
   452 			{
       
   453 			lScrPp = srcWidth+pad;
       
   454 			}
       
   455 
       
   456 		TUint32 transparentColorRgb565 = aTransparentColor.ColorRgb565();
       
   457 
       
   458         for ( y = rect.iTl.iY; y <= yend; y++ )
       
   459             {
       
   460             p.iY = y;
       
   461 
       
   462 			// compute scanline starting position
       
   463 
       
   464 			if ( ((TFloatFixPt)y) > west.iY )
       
   465 			    {
       
   466 				if(north.iY - west.iY == (TFloatFixPt)0)
       
   467 					xstart = (TInt32) west.iX;
       
   468 				else
       
   469 					xstart = (TInt32) (west.iX + (north.iX - west.iX) * ( (((TFloatFixPt)y) - west.iY) / (north.iY - west.iY) ));
       
   470 			    }
       
   471 			else
       
   472 			    {
       
   473 				if(west.iY - south.iY == (TFloatFixPt)0)
       
   474 					xstart = (TInt32) south.iX;
       
   475 				else
       
   476 					xstart = (TInt32) (south.iX + (west.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (west.iY - south.iY) ));
       
   477 			    }
       
   478 
       
   479 			// compute scanline edges end position
       
   480 			if ( (TFloatFixPt)y > east.iY )
       
   481 			    {
       
   482 				if(north.iY - east.iY == (TFloatFixPt)0)
       
   483 					xend = (TInt32) north.iX;
       
   484 				else
       
   485 					xend = (TInt32) (east.iX + (north.iX - east.iX) * ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
       
   486 			    }
       
   487 			else
       
   488 			    {
       
   489 				if ( (east.iY - south.iY) == (TFloatFixPt)0 )
       
   490 					xend = (TInt32) east.iX;
       
   491 				else
       
   492 					xend = (TInt32) (south.iX + (east.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
       
   493 			    }
       
   494 
       
   495 		    // does span clip against edges
       
   496 			if(xstart < rect.iTl.iX)
       
   497 				xstart = rect.iTl.iX;
       
   498 
       
   499 			if(xend >= rect.iBr.iX)  // iX-1 seems to be the limit, using iX rolls over to next line
       
   500 				xend = rect.iBr.iX-1;
       
   501 
       
   502 			p.iX = xstart;
       
   503 			// transform that starting position to the source image
       
   504 			inv.Transform( &p, & p, 1 );
       
   505 			buf += xstart-rect.iTl.iX;
       
   506 
       
   507 			p.iY -= TFloatFixPt(.5f) * currentScale;
       
   508 
       
   509 			if (aTransparentColor.GetARGB() == KGfxColorNull)
       
   510 				{
       
   511 					for ( x = xstart; x <= xend; x++ )
       
   512     					{
       
   513 						//increment the location of the position by one horizontal location
       
   514 						pinv.iX = p.iX;
       
   515 						pinv.iY = p.iY;
       
   516 						if ( srcrect.Contains( pinv ) )
       
   517 						    {
       
   518 							pinv.iX -= ( TInt32 ) aP.iX;
       
   519 							pinv.iY -= ( TInt32 ) aP.iY;
       
   520         					if ( dispmode == EColor16MU )
       
   521         					    {
       
   522                                 *buf = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
       
   523         					    }
       
   524         					else
       
   525         					    {
       
   526     							// src:RGB565 -> dst:ARGB8888
       
   527     							pix = (TUint32)*(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
       
   528     							*buf = RGB565toRGB888(pix);
       
   529     						    }
       
   530 						    }
       
   531 						p.iX += horizDeriv.iX;
       
   532 						p.iY += horizDeriv.iY;
       
   533 						buf++;
       
   534 					}
       
   535 				}
       
   536 			else
       
   537 				{
       
   538 				for ( x = xstart; x <= xend; x++ )
       
   539 					{
       
   540 					//increment the location of the position by one horizontal location
       
   541 					pinv.iX = p.iX;
       
   542 					pinv.iY = p.iY;
       
   543 
       
   544 					if ( srcrect.Contains( pinv ) )
       
   545 						{
       
   546 						pinv.iX -= ( TInt32 ) aP.iX;
       
   547 						pinv.iY -= ( TInt32 ) aP.iY;
       
   548 
       
   549 						if ( aReverse ) // copy source to destination. Used for Text blending with final framebufer.
       
   550 						    { // this used for text only
       
   551         					if ( dispmode == EColor16MU )
       
   552         					    {
       
   553     							*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY)) = *buf ;
       
   554     						    }
       
   555     						else
       
   556         					    {
       
   557     							*(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY)) = *buf ;
       
   558     						    }
       
   559 						    }
       
   560 						else
       
   561 						    {
       
   562         					if ( dispmode == EColor16MU )
       
   563         					    {
       
   564     							pix = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
       
   565 						        if (pix != transparentColorRgb565)
       
   566 							        {
       
   567 							        *buf = pix;
       
   568 	                        	    }
       
   569 							    }
       
   570 							else
       
   571         					    {
       
   572     							pix = (TUint32) *(bufsrc16 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
       
   573                                 if (pix != transparentColorRgb565)
       
   574                                     {
       
   575 								    *buf = RGB565toRGB888(pix);
       
   576                                     }
       
   577 							    }
       
   578 							}
       
   579 						}
       
   580 					p.iX += horizDeriv.iX;
       
   581 					p.iY += horizDeriv.iY;
       
   582 					buf++;
       
   583 					}
       
   584 				}
       
   585 			buf = obuf+aDstWidth;
       
   586 			obuf += aDstWidth;
       
   587 			if (obuf + aDstWidth >= bufLimit)
       
   588                 {
       
   589                 aSrc->UnlockHeap();
       
   590                 return;
       
   591                 }
       
   592             }
       
   593         }
       
   594 
       
   595     aSrc->UnlockHeap();
       
   596     }
       
   597 
       
   598 // --------------------------------------------------------------------------
       
   599 //  void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
       
   600 // ---------------------------------------------------------------------------
       
   601  void TGfxImageTransformer::Draw( CFbsBitmap* aSrc,
       
   602                                           const TGfxPoint2D& aP,
       
   603                                           TUint32* aDst,
       
   604                                           TInt aDstWidth,
       
   605                                           TInt aDstHeight,
       
   606                                           const TRect& aClipRect
       
   607                                           )
       
   608     {
       
   609     TDisplayMode dispmode = aSrc->DisplayMode();
       
   610     if ( dispmode != EColor16MU )
       
   611         {
       
   612         return;
       
   613         }
       
   614 
       
   615     TRect rect;
       
   616     TInt32 x, y;
       
   617 
       
   618     TFloatFixPt currentScale = iTransform->ScalingFactor();
       
   619 
       
   620     TRect srcrect( TPoint( aP.iX, aP.iY ), aSrc->SizeInPixels() );
       
   621     TRect dstrect( TPoint( 0, 0 ), TSize(aDstWidth, aDstHeight) );
       
   622     TInt32 srcWidth = aSrc->SizeInPixels().iWidth;
       
   623     TInt32 srcHeight = aSrc->SizeInPixels().iHeight;
       
   624 
       
   625     TGfxRectangle2D rect2d = GetTransformedBound( aSrc, aP );
       
   626     rect.SetRect( TPoint( rect2d.iX, rect2d.iY ), TSize( rect2d.iWidth, rect2d.iHeight ) );
       
   627     rect.Intersection(aClipRect);   // Clipping
       
   628 
       
   629     if ( !rect.Intersects( dstrect ) )    // clip rect with dst image
       
   630         return;
       
   631 
       
   632     aSrc->LockHeap();
       
   633     rect.Intersection( dstrect );
       
   634 
       
   635     TUint32* bufsrc32 = (TUint32*) aSrc->DataAddress();
       
   636 
       
   637     TUint32* buf = aDst + rect.iTl.iX + ( rect.iTl.iY * aDstWidth );
       
   638     TUint32* bufLimit = aDst + aDstWidth * aDstHeight;
       
   639     TUint32 pix = 0;
       
   640 
       
   641     TGfxAffineTransform inv = iTransform->CreateInverse();
       
   642 
       
   643         {
       
   644         TPoint pinv;
       
   645         TGfxPoint2D p;
       
   646 
       
   647         TUint32* obuf = buf;
       
   648         TInt32 xstart, xend, yend;
       
   649         TGfxPoint2D horizDeriv;
       
   650         TGfxPoint2D origin, top, right, corner;
       
   651         TGfxPoint2D east, west, south, north;
       
   652 
       
   653         origin.iX = aP.iX;
       
   654         origin.iY = aP.iY;
       
   655         corner.iX = aP.iX + (TFloatFixPt)srcWidth;
       
   656         corner.iY = aP.iY + (TFloatFixPt)srcHeight;
       
   657         top.iX =    aP.iX;
       
   658         top.iY =    aP.iY + (TFloatFixPt)srcHeight;
       
   659         right.iX =  aP.iX + (TFloatFixPt)srcWidth;
       
   660         right.iY =  aP.iY;
       
   661 
       
   662         // transform corners of the source rectangle.
       
   663         iTransform->Transform(&origin, &origin, 1);
       
   664         iTransform->Transform(&top, &top, 1);
       
   665         iTransform->Transform(&right, &right, 1);
       
   666         iTransform->Transform(&corner, &corner, 1);
       
   667 
       
   668         // sort four corners into appropriate order
       
   669         west = origin; east = corner; north = top; south = right;
       
   670         if (top.iX < origin.iX)
       
   671             {
       
   672             west = top;
       
   673             east = right;
       
   674             north = corner;
       
   675             south = origin;
       
   676             }
       
   677         else
       
   678             {
       
   679             west = origin;
       
   680             east = corner;
       
   681             north = top;
       
   682             south = right;
       
   683             }
       
   684 
       
   685         if (corner.iX < west.iX)
       
   686             {
       
   687             west = corner;
       
   688             east = origin;
       
   689             north = right;
       
   690             south = top;
       
   691             }
       
   692 
       
   693         if (right.iX < west.iX)
       
   694             {
       
   695             west = right;
       
   696             east = top;
       
   697             north = origin;
       
   698             south = corner;
       
   699             }
       
   700 
       
   701         // compute derivitives for scanline in source.
       
   702         p.iX = 8;
       
   703         p.iY = 0;
       
   704         inv.Transform( &p, & p, 1 );
       
   705         horizDeriv.iX = p.iX;
       
   706         horizDeriv.iY = p.iY;
       
   707         p.iX = 0;
       
   708         p.iY = 0;
       
   709         inv.Transform( &p, & p, 1 );
       
   710         horizDeriv.iX -= p.iX;
       
   711         horizDeriv.iY -= p.iY;
       
   712         horizDeriv.iX = horizDeriv.iX >> 3;
       
   713         horizDeriv.iY = horizDeriv.iY >> 3;
       
   714 
       
   715         yend = rect.iBr.iY;
       
   716         TInt lScrPp = 0;
       
   717         lScrPp = srcWidth;
       
   718 
       
   719 
       
   720         for ( y = rect.iTl.iY; y <= yend; y++ )
       
   721             {
       
   722             p.iY = y;
       
   723 
       
   724             // compute scanline starting position
       
   725 
       
   726             if ( ((TFloatFixPt)y) > west.iY )
       
   727                 {
       
   728                 if(north.iY - west.iY == (TFloatFixPt)0)
       
   729                     xstart = (TInt32) west.iX;
       
   730                 else
       
   731                     xstart = (TInt32) (west.iX + (north.iX - west.iX) * ( (((TFloatFixPt)y) - west.iY) / (north.iY - west.iY) ));
       
   732                 }
       
   733             else
       
   734                 {
       
   735                 if(west.iY - south.iY == (TFloatFixPt)0)
       
   736                     xstart = (TInt32) south.iX;
       
   737                 else
       
   738                     xstart = (TInt32) (south.iX + (west.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (west.iY - south.iY) ));
       
   739                 }
       
   740 
       
   741             // compute scanline edges end position
       
   742             if ( (TFloatFixPt)y > east.iY )
       
   743                 {
       
   744                 if(north.iY - east.iY == (TFloatFixPt)0)
       
   745                     xend = (TInt32) north.iX;
       
   746                 else
       
   747                     xend = (TInt32) (east.iX + (north.iX - east.iX) * ( (((TFloatFixPt)y) - east.iY) / (north.iY - east.iY) ));
       
   748                 }
       
   749             else
       
   750                 {
       
   751                 if ( (east.iY - south.iY) == (TFloatFixPt)0 )
       
   752                     xend = (TInt32) east.iX;
       
   753                 else
       
   754                     xend = (TInt32) (south.iX + (east.iX - south.iX) * ( (((TFloatFixPt)y) - south.iY) / (east.iY - south.iY) ));
       
   755                 }
       
   756 
       
   757             // does span clip against edges
       
   758             if(xstart < rect.iTl.iX)
       
   759                 xstart = rect.iTl.iX;
       
   760 
       
   761             if(xend >= rect.iBr.iX)  // iX-1 seems to be the limit, using iX rolls over to next line
       
   762                 xend = rect.iBr.iX-1;
       
   763 
       
   764             p.iX = xstart;
       
   765             // transform that starting position to the source image
       
   766             inv.Transform( &p, & p, 1 );
       
   767             buf += xstart-rect.iTl.iX;
       
   768             // Change here
       
   769             p.iY -= TFloatFixPt(0.5f) * currentScale;
       
   770 
       
   771                 {
       
   772                     for ( x = xstart; x <= xend; x++ )
       
   773                         {
       
   774                         //increment the location of the position by one horizontal location
       
   775                         pinv.iX = p.iX;
       
   776                         pinv.iY = p.iY;
       
   777                         if ( srcrect.Contains( pinv ) )
       
   778                             {
       
   779                             pinv.iX -= ( TInt32 ) aP.iX;
       
   780                             pinv.iY -= ( TInt32 ) aP.iY;
       
   781 
       
   782                             pix = (TUint32)*(bufsrc32 + ( TInt32 ) pinv.iX + (lScrPp)*( TInt32 ) (pinv.iY));
       
   783                             TUint srcAlpha = ( pix & 0xFF000000 ) >> 24;
       
   784                             if ( srcAlpha == 0xFF )
       
   785                                 {
       
   786                                 *buf = pix;
       
   787                                 }
       
   788                             else if ( srcAlpha > 0 )
       
   789                                 {
       
   790                                 TUint destPix = *buf;
       
   791                                 TUint destAlpha = ( destPix & 0xFF000000 ) >> 24;
       
   792                                 // Blending needed: blend with background as opaque
       
   793                                 if ( destAlpha == 0xFF )
       
   794                                     {
       
   795                                     TReal32 alpha = 0.0039215686 * srcAlpha; // 0.0039.. = 1/255
       
   796                                     TReal32 inverseAlpha = 1.0f - alpha;
       
   797                                     *buf = ((((TUint)((pix     >> 16 & 0xff) * alpha) +
       
   798                                               (TUint)((destPix >> 16 & 0xff) * inverseAlpha))) << 16) | // red
       
   799                                            ((((TUint)((pix     >> 8  & 0xff) * alpha) +
       
   800                                               (TUint)((destPix >> 8  & 0xff) * inverseAlpha))) << 8 ) | // green
       
   801                                            ((((TUint)((pix           & 0xff) * alpha) +
       
   802                                               (TUint)((destPix       & 0xff) * inverseAlpha)))      ) | // blue
       
   803                                               (0xFF000000);                                             // full alpha (already blended)
       
   804                                     }
       
   805                                 // Apply alpha to each color channel of source only
       
   806                                 // Important: use original alpha
       
   807                                 else
       
   808                                     {
       
   809                                     TReal32 alpha = 0.0039215686 * srcAlpha;
       
   810                                     *buf = (srcAlpha << 24)|
       
   811                                            ((TUint)((pix >> 16 & 0xff) * alpha) << 16) |
       
   812                                            ((TUint)((pix     >> 8 & 0xff) * alpha) << 8) |
       
   813                                            ((TUint)((pix & 0xff) * alpha));
       
   814                                     }
       
   815                                 }
       
   816                             }
       
   817                         p.iX += horizDeriv.iX;
       
   818                         p.iY += horizDeriv.iY;
       
   819                         buf++;
       
   820                     }
       
   821                 }
       
   822 
       
   823             buf = obuf+aDstWidth;
       
   824             obuf += aDstWidth;
       
   825             if (obuf + aDstWidth >= bufLimit)
       
   826                 {
       
   827                 aSrc->UnlockHeap();
       
   828                 return;
       
   829                 }
       
   830             }
       
   831         }
       
   832 
       
   833     aSrc->UnlockHeap();
       
   834     }
       
   835 
       
   836 //  TGfxRectangle2D TGfxImageTransformer::GetTransformedBound( CFbsBitmap* aSrc,
       
   837 // ---------------------------------------------------------------------------
       
   838  TGfxRectangle2D TGfxImageTransformer::GetTransformedBound( CFbsBitmap* aSrc,
       
   839                                                                     const TGfxPoint2D& aOffset )
       
   840     {
       
   841     TGfxRectangle2D rect;
       
   842     TGfxPoint2D rectp[4];
       
   843 
       
   844     rectp[0].iX = aOffset.iX;
       
   845     rectp[0].iY = aOffset.iY;
       
   846     rectp[1].iX = aOffset.iX + ( TFloatFixPt ) aSrc->SizeInPixels().iWidth;
       
   847     rectp[1].iY = aOffset.iY;
       
   848     rectp[2].iX = aOffset.iX + ( TFloatFixPt ) aSrc->SizeInPixels().iWidth;
       
   849     rectp[2].iY = aOffset.iY + ( TFloatFixPt ) aSrc->SizeInPixels().iHeight;
       
   850     rectp[3].iX = aOffset.iX;
       
   851     rectp[3].iY = aOffset.iY + ( TFloatFixPt ) aSrc->SizeInPixels().iHeight;
       
   852     iTransform->Transform( rectp, rectp, 4 );
       
   853 
       
   854     TInt32 i;
       
   855     //MinX
       
   856     rect.iX = rectp[0].iX;
       
   857     rect.iY = rectp[0].iY;
       
   858     rect.iWidth = rectp[0].iX;
       
   859     rect.iHeight = rectp[0].iY;
       
   860 
       
   861     for ( i = 1; i < 4; i++ )
       
   862 	    {
       
   863         if ( rectp[i].iX < rect.iX )
       
   864             rect.iX = rectp[i].iX;
       
   865     //MinY
       
   866         if ( rectp[i].iY < rect.iY )
       
   867             rect.iY = rectp[i].iY;
       
   868     //MaxX -> width
       
   869         if ( rectp[i].iX > rect.iWidth )
       
   870             rect.iWidth = rectp[i].iX;
       
   871     //MaxY -> height
       
   872         if ( rectp[i].iY > rect.iHeight )
       
   873             rect.iHeight = rectp[i].iY;
       
   874     	}
       
   875     rect.iWidth -= rect.iX;
       
   876     rect.iHeight -= rect.iY;
       
   877 
       
   878     return rect;
       
   879     }
       
   880