1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicsdeviceinterface/screendriver/sbit/BmDrawScaling.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,480 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "BMDRAW.H"
1.20 +#include "BitDrawInterfaceId.h"
1.21 +
1.22 +//The method prepares RGB value writting, calculating physical aX, aY, aWidth and aHeight.
1.23 +//The calculated coordinates are used by methods wich do not use methods in BmDraw8Scaling.cpp
1.24 +//file - WriteRgbMultiXOR(), WriteRgbMultiAND(), WriteRgbMultiOR().
1.25 +//If the scaling is "off" then it is very simple - draw physical pixels. But if the scaling is
1.26 +//"on" then a rectanngle is being drawn instead of a pixel. And rectangle coordinates are
1.27 +//calculated depending on the device' orientation.
1.28 +//aX, aY - logical coordinates.
1.29 +//aWidth, aHeight - output parameters, they will be initialized in the method's body,
1.30 +//if aDrawMode is not CGraphicsContext::EPenmode. If aDrawMode is CGraphicsContext::EPenmode,
1.31 +//then aWidth will be set with iScalingSettings.iFactorX and aheight - with
1.32 +//iScalingSettings.iFactorY.
1.33 +void CDrawBitmap::PreWriteRgb(TInt& aWidth,
1.34 + TInt& aHeight,
1.35 + TInt& aX,
1.36 + TInt& aY,
1.37 + CGraphicsContext::TDrawMode aDrawMode)
1.38 + {
1.39 + DeOrientate(aX, aY);//aX and aY - physical coordinates
1.40 +
1.41 + __ASSERT_DEBUG(aX >= 0 && aX < iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
1.42 + __ASSERT_DEBUG(aY >= 0 && aY < iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
1.43 +
1.44 + //If scaling is ON, instead of drawing single point, rectangle with size [FactorX, FactorY]
1.45 + //is drawn. Rectangle's width and height might be swapped, depending on the orientation.
1.46 + aWidth = iScalingSettings.iFactorX;
1.47 + aHeight = iScalingSettings.iFactorY;
1.48 +
1.49 + if(iScalingOff)
1.50 + {
1.51 + return;
1.52 + }
1.53 +
1.54 + //Do this additional deorientation only for not EPenmode modes and when scaling is ON!
1.55 + //EPenmode uses WriteRgb(aX,aY,aColor), which does not need any changes in
1.56 + //coordinates!
1.57 + if(!(aDrawMode & CGraphicsContext::EPenmode))
1.58 + {
1.59 + //aX, aY - physical coordinates
1.60 + //aWidth, aWidth - output parameters
1.61 + //When scaling is ON, instead of drawing single point, rectangle is drawn
1.62 + //and top-left coordinates, width and height has to be calculated.
1.63 + register TInt scalingFactorX = aWidth;
1.64 + register TInt scalingFactorY = aHeight;
1.65 + __ASSERT_DEBUG(scalingFactorX > 0, User::Invariant());
1.66 + __ASSERT_DEBUG(scalingFactorY > 0, User::Invariant());
1.67 + register CFbsDrawDevice::TOrientation orientation = iOrientation;
1.68 +
1.69 + switch(orientation)
1.70 + {
1.71 + case EOrientationRotated90:
1.72 + case EOrientationRotated270:
1.73 + {
1.74 + if(orientation == EOrientationRotated90)
1.75 + {
1.76 + aX -= (scalingFactorX - 1);
1.77 + }
1.78 + if(orientation == EOrientationRotated270)
1.79 + {
1.80 + aY -= (scalingFactorY - 1);
1.81 + }
1.82 + break;
1.83 + }
1.84 + case EOrientationRotated180 :
1.85 + {
1.86 + aX -= (scalingFactorX - 1);
1.87 + aY -= (scalingFactorY - 1);
1.88 + break;
1.89 + }
1.90 + default:
1.91 + break;
1.92 + }
1.93 + //If the calculated coordinates are negative, set them to 0.
1.94 + if(aX < 0)
1.95 + {
1.96 + aX = 0;
1.97 + }
1.98 + if(aY < 0)
1.99 + {
1.100 + aY = 0;
1.101 + }
1.102 + }
1.103 + }
1.104 +
1.105 +//Writes RGB value at the specified physical screen coordinates.
1.106 +//When scaling is ON - rectangle [aWidth, aHeight] is drawn instead of single point.
1.107 +//Depending on the orientation aWidth and aHeight might be swapped.
1.108 +//aX, aY - physical coordinates
1.109 +//aWidth, aHeight - physical
1.110 +void CDrawBitmap::WriteRgb(TInt& aWidth, TInt& aHeight,
1.111 + TInt& aX, TInt& aY, TRgb aColor,
1.112 + CGraphicsContext::TDrawMode aDrawMode)
1.113 + {
1.114 + MapColorToUserDisplayMode(aColor);
1.115 + if(iShadowMode)
1.116 + {
1.117 + Shadow(aColor);
1.118 + }
1.119 + if(aDrawMode&CGraphicsContext::EInvertPen)
1.120 + {
1.121 + aColor=~aColor;
1.122 + }
1.123 + if(aDrawMode&CGraphicsContext::EPenmode)
1.124 + {
1.125 + WriteRgb(aX,aY,aColor);
1.126 + return;
1.127 + }
1.128 + __ASSERT_DEBUG(aWidth > 0, User::Invariant());
1.129 + __ASSERT_DEBUG(aHeight > 0, User::Invariant());
1.130 + if(aDrawMode&CGraphicsContext::EWriteAlpha)
1.131 + {
1.132 + // WriteRgbMulti is the only available api that writes alpha
1.133 + WriteRgbMulti(aX,aY,aWidth,aHeight,aColor);
1.134 + return;
1.135 + }
1.136 + if(aDrawMode&CGraphicsContext::EInvertScreen)
1.137 + {
1.138 + WriteRgbMultiXOR(aX, aY, aWidth, aHeight, KRgbWhite);
1.139 + }
1.140 + if(aDrawMode&CGraphicsContext::EXor)
1.141 + {
1.142 + WriteRgbMultiXOR(aX, aY, aWidth, aHeight, aColor);
1.143 + }
1.144 + else if(aDrawMode&CGraphicsContext::EAnd)
1.145 + {
1.146 + WriteRgbMultiAND(aX, aY, aWidth, aHeight, aColor);
1.147 + }
1.148 + else if(aDrawMode&CGraphicsContext::EOr)
1.149 + {
1.150 + WriteRgbMultiOR(aX, aY, aWidth, aHeight, aColor);
1.151 + }
1.152 + }
1.153 +
1.154 +/**
1.155 +Implementation for CFbsDrawDevice::GetDrawRect().
1.156 +Gets logical coordinates of the drawing rectangle.
1.157 +If the device is not scaled and with zero origin, logocal coordinates of
1.158 +the drawing rectangle are the same as its physical coordinates.
1.159 +If the device is rotated, drawing rectangle width and height are swapped.
1.160 +Always prefer GetDrawRect() to SizeInPixels() call. SizeInPixels() will return
1.161 +drawing rectangle width and height. But if the device is scaled or with nonzero origin,
1.162 +GetDrawRect() will take into account and the top-left corner of the drawing rectangle too,
1.163 +which may not be [0, 0].
1.164 +@param aRect Upon return aRect contains drawing rectangle logical coordinates.
1.165 +*/
1.166 +void CDrawBitmap::GetDrawRect(TRect& aDrawRect) const
1.167 + {
1.168 + aDrawRect = iDrawRect;
1.169 + if (iOrientation & 1)
1.170 + {//90 or 270 degrees
1.171 + if (iOrigin.iX!=iOrigin.iY || iScalingSettings.iFactorX!=iScalingSettings.iFactorY)
1.172 + { //When the scales are different between the dimensions the origin needs to recalculating
1.173 + aDrawRect.iTl.iX=Origin(iOrigin.iX,iScalingSettings.iFactorY);
1.174 + aDrawRect.iTl.iY=Origin(iOrigin.iY,iScalingSettings.iFactorX);
1.175 + }
1.176 + aDrawRect.SetWidth(iDrawRect.Height());
1.177 + aDrawRect.SetHeight(iDrawRect.Width());
1.178 + }
1.179 + }
1.180 +
1.181 +/**
1.182 +Implementation for MScalingSettings::Set().
1.183 +Sets scaling factor by which the drawing device should scale the drawing images.
1.184 +If you want to un-scale the device, call Set() with
1.185 +factorX = 1, factorY = 1, divisorX = 1, divisorY = 1.
1.186 +@param aFactorX Scaling factor for the X-axis of the screen device.
1.187 +@param aFactorY Scaling factor for the y-axis of the screen device.
1.188 +@param aDivisorX Not used. Should be set to 1.
1.189 +@param aDivisorY Not used. Should be set to 1.
1.190 +@return KErrNone success.
1.191 +*/
1.192 +TInt CDrawBitmap::Set(TInt aFactorX, TInt aFactorY, TInt aDivisorX, TInt aDivisorY)
1.193 + {
1.194 + __ASSERT_DEBUG(aDivisorX == 1 && aDivisorY == 1, User::Invariant());
1.195 + __ASSERT_DEBUG(aFactorX > 0 && aFactorY > 0, User::Invariant());
1.196 +
1.197 + iScalingSettings.iFactorX = aFactorX;
1.198 + iScalingSettings.iFactorY = aFactorY;
1.199 + iScalingSettings.iDivisorX = aDivisorX;
1.200 + iScalingSettings.iDivisorY = aDivisorY;
1.201 +
1.202 + iScalingOff = aFactorX == 1 && aFactorY == 1 && aDivisorX == 1 && aDivisorY == 1;
1.203 +
1.204 + InitLogicalCoordinates();
1.205 +
1.206 + return KErrNone;
1.207 + }
1.208 +
1.209 +/**
1.210 +Implementation for MScalingSettings::Get().
1.211 +Retrieves X-axis and Y-axis scaling factors.
1.212 +@param aFactorX Upon return contains X-axis scaling factor.
1.213 +@param aFactorY Upon return contains Y-axis scaling factor.
1.214 +@param aDivisorX Upon return contains the decimal fraction of X-axis scaling factor.
1.215 +@param aDivisorY Upon return contains the decimal fraction of Y-axis scaling factor.
1.216 +*/
1.217 +void CDrawBitmap::Get(TInt& aFactorX, TInt& aFactorY, TInt& aDivisorX, TInt& aDivisorY)
1.218 + {
1.219 + aFactorX = iScalingSettings.iFactorX;
1.220 + aFactorY = iScalingSettings.iFactorY;
1.221 + aDivisorX = iScalingSettings.iDivisorX;
1.222 + aDivisorY = iScalingSettings.iDivisorY;
1.223 + }
1.224 +
1.225 +/**
1.226 +Implementation for MScalingSettings::IsScalingOff().
1.227 +Notifies the caller whether the drawing device is scaled or not.
1.228 +@return ETrue Drawing device is not scaled, EFalse - it is scaled.
1.229 +*/
1.230 +TBool CDrawBitmap::IsScalingOff()
1.231 + {
1.232 + return iScalingOff;
1.233 + }
1.234 +
1.235 +/**
1.236 +Implementation for MDrawDeviceOrigin::Set().
1.237 +Sets drawing device origin.
1.238 +If you want to the default origin, call Set() with Origin (0,0).
1.239 +@param aOrigin Specifies physical coordinates of the new scaling origin
1.240 +of the drawing device. The drawing device maps the logical point [0,0] to
1.241 +the "aOrigin" physical point .
1.242 +@return KErrNone success.
1.243 +*/
1.244 +TInt CDrawBitmap::Set(const TPoint& aOrigin)
1.245 + {
1.246 + __ASSERT_DEBUG(aOrigin.iX >= 0 && aOrigin.iY >= 0, User::Invariant());
1.247 + __ASSERT_DEBUG(aOrigin.iX < iSize.iWidth && aOrigin.iY < iSize.iHeight, User::Invariant());
1.248 +
1.249 + iOrigin = aOrigin;
1.250 +
1.251 + iOriginIsZero = iOrigin.iX == 0 && iOrigin.iY == 0;
1.252 +
1.253 + InitLogicalCoordinates();
1.254 +
1.255 + return KErrNone;
1.256 + }
1.257 +
1.258 +/**
1.259 +Implementation for MDrawDeviceOrigin::Get().
1.260 +Retrieves origin point.
1.261 +@param aOrigin Upon return contains scaling origin point.
1.262 +*/
1.263 +void CDrawBitmap::Get(TPoint& aOrigin)
1.264 + {
1.265 + aOrigin = iOrigin;
1.266 + }
1.267 +
1.268 +//Initializes iDrawRect data member, which contains logical coordinates of
1.269 +//the drawing(screen) rectangle.
1.270 +//The method does not use iOrientation data member.
1.271 +void CDrawBitmap::InitLogicalCoordinates()
1.272 + {
1.273 + register TInt orgX = iOrigin.iX;
1.274 + register TInt orgY = iOrigin.iY;
1.275 + register TInt fX = iScalingSettings.iFactorX;
1.276 + register TInt fY = iScalingSettings.iFactorY;
1.277 +
1.278 + iDrawRect.iTl.iX = Origin(orgX, fX);
1.279 + iDrawRect.iTl.iY = Origin(orgY, fY);
1.280 + iDrawRect.iBr.iX = OtherSide(orgX, iSize.iWidth, fX);
1.281 + iDrawRect.iBr.iY = OtherSide(orgY, iSize.iHeight, fY);
1.282 + if (orgX!=orgY)
1.283 + { //The number of addressable pixels in the physical dimensions
1.284 + //Sometimes needs to be one less when rotationed by 90 or 270
1.285 + //If so set it one less all the time as the value is not recalculated
1.286 + if (fX>1)
1.287 + { //Calculated the physical left and right of screen when rotation by 90 or 270
1.288 + //Use this width if it is smaller
1.289 + TInt left = Origin(orgY, fX);
1.290 + TInt right = OtherSide(orgY, iSize.iWidth, fX);
1.291 + iDrawRect.iBr.iX = Min(iDrawRect.iBr.iX, iDrawRect.iTl.iX+(right-left));
1.292 + }
1.293 + if (fY>1)
1.294 + { //Calculated the physical top and bottom of screen when rotation by 90 or 270
1.295 + //Use this height if it is smaller
1.296 + TInt top = Origin(orgX, fY);
1.297 + TInt bottom = OtherSide(orgX, iSize.iHeight, fY);
1.298 + iDrawRect.iBr.iY = Min(iDrawRect.iBr.iY, iDrawRect.iTl.iY+(bottom-top));
1.299 + }
1.300 + }
1.301 + }
1.302 +
1.303 +/**
1.304 +Notifies the caller whether the drawing device can be scaled or not.
1.305 +@return ETrue Drawing device can be scaled, EFalse - it can't be scaled.
1.306 +*/
1.307 +TBool CDrawBitmap::CanBeScaled() const
1.308 + {
1.309 + //The function will return true for all display modes
1.310 + return ETrue;
1.311 + }
1.312 +
1.313 +/**
1.314 +Notifies the caller whether the drawing device origin can be moved from (0, 0) point or not.
1.315 +@return ETrue Drawing device origin can be moved, EFalse - it can't be moved.
1.316 +*/
1.317 +TBool CDrawBitmap::CanOriginBeMoved() const
1.318 + {
1.319 + //The function will return true for all display modes
1.320 + return ETrue;
1.321 + }
1.322 +
1.323 +//This method calculates pixel increment value and row increment value depending
1.324 +//on the orientation. The device might be scaled. The result is returned in
1.325 +//aPixelInc and aRowInc parameters.
1.326 +void CDrawBitmap::SetPixelInc(TInt& aPixelInc, TInt& aRowInc) const
1.327 + {
1.328 + register TInt scalingFactorX = iScalingSettings.iFactorX;
1.329 + register TInt scalingFactorY = iScalingSettings.iFactorY;
1.330 + switch(iOrientation)
1.331 + {
1.332 + case EOrientationNormal:
1.333 + {
1.334 + aPixelInc = scalingFactorX;
1.335 + aRowInc = iLongWidth * scalingFactorY;
1.336 + break;
1.337 + }
1.338 + case EOrientationRotated90:
1.339 + {
1.340 + aPixelInc = iLongWidth * scalingFactorY;
1.341 + aRowInc = -scalingFactorX;
1.342 + break;
1.343 + }
1.344 + case EOrientationRotated180:
1.345 + {
1.346 + aPixelInc = -scalingFactorX;
1.347 + aRowInc = -iLongWidth * scalingFactorY;
1.348 + break;
1.349 + }
1.350 + default: // EOrientationRotated270
1.351 + {
1.352 + aPixelInc = -iLongWidth * scalingFactorY;
1.353 + aRowInc = scalingFactorX;
1.354 + break;
1.355 + }
1.356 + }
1.357 + }
1.358 +
1.359 +//Calculates "Y" increment value and assigns it to aY parameter.
1.360 +//The device might be scaled and rotated.
1.361 +//It is used by WriteBinary(), WriteBinaryOp(), ... methods and only there.
1.362 +//The method is very specific for the methods mentioned above -
1.363 +//if the device is scaled and rotated 0 or 180 degrees, Y-axis coordinate has to
1.364 +//be incremented not by 1, but by iScalingSettings.iFactorY. Because of the integer divison
1.365 +//when transforming logical to physical coordinates, incremented Y-axis coordinates may
1.366 +//go negative or greater than drawing rectangle height. Then it has to be adjusted to 0
1.367 +//or rectangle height.
1.368 +void CDrawBitmap::IncScaledY(TInt& aY, TInt aYOrg) const
1.369 + {
1.370 + const TOrientation orientation = iOrientation;
1.371 + const TInt fY = iScalingSettings.iFactorY;
1.372 + switch(orientation)
1.373 + {
1.374 + case EOrientationNormal:
1.375 + {
1.376 + aY += fY;
1.377 + const TInt height = iSize.iHeight - 1;
1.378 + if(aY > height)
1.379 + {
1.380 + aY = height;
1.381 + }
1.382 + break;
1.383 + }
1.384 + case EOrientationRotated180:
1.385 + {
1.386 + aY -= fY;
1.387 + if(aY < 0)
1.388 + {
1.389 + aY = 0;
1.390 + }
1.391 + break;
1.392 + }
1.393 + default:
1.394 + {
1.395 + aY = aYOrg;
1.396 + }
1.397 + }
1.398 + }
1.399 +
1.400 +//Calculates "Y" increment value and assigns it to aY parameter.
1.401 +//The device might be scaled and rotated.
1.402 +//It is used by WriteBinary(), WriteBinaryOp(), WriteLine...() methods and only there.
1.403 +//The method is very specific for the methods mentioned above -
1.404 +//if the device is scaled and rotated 90 or 270 degrees, Y-axis coordinate has to
1.405 +//be incremented not by 1, but by iScalingSettings.iFactorX. Because of the integer divison
1.406 +//when transforming logical to physical coordinates, incremented Y-axis coordinates may
1.407 +//go negative or greater than drawing rectangle height. Then it has to be adjusted to 0
1.408 +//or rectangle height.
1.409 +void CDrawBitmap::IncScaledY(TInt& aY) const
1.410 + {
1.411 + const TOrientation orientation = iOrientation;
1.412 + const TInt fX = iScalingSettings.iFactorY;
1.413 + if(orientation == EOrientationRotated90)
1.414 + {
1.415 + aY += fX;
1.416 + const TInt height = iSize.iHeight - 1;
1.417 + if(aY > height)
1.418 + {
1.419 + aY = height;
1.420 + }
1.421 + }
1.422 + else if(orientation == EOrientationRotated270)
1.423 + {
1.424 + aY -= fX;
1.425 + if(aY < 0)
1.426 + {
1.427 + aY = 0;
1.428 + }
1.429 + }
1.430 + }
1.431 +
1.432 +//Increment without scaling
1.433 +TInt CDrawBitmap::PixelAddressIncrement() const
1.434 + {
1.435 + switch (iOrientation)
1.436 + {
1.437 + case EOrientationNormal:
1.438 + return 1;
1.439 + case EOrientationRotated90:
1.440 + return iLongWidth;
1.441 + case EOrientationRotated180:
1.442 + return -1;
1.443 + case EOrientationRotated270:
1.444 + return -iLongWidth;
1.445 + default:
1.446 + break;
1.447 + }
1.448 + return KInvalidValue;
1.449 + }
1.450 +
1.451 +//Pixel increment with scaling.
1.452 +//It is used by CDrawEightBppBitmapCommon::SetPixels,
1.453 +//CDrawEightBppBitmapCommon::XORPixels, CDrawEightBppBitmapCommon::ANDPixels,
1.454 +//CDrawEightBppBitmapCommon::ORPixels methods
1.455 +TInt CDrawBitmap::LogicalPixelAddressIncrement() const
1.456 + {
1.457 + register TInt scalingFactorX = iScalingSettings.iFactorX;
1.458 + register TInt scalingFactorY = iScalingSettings.iFactorY;
1.459 + switch (iOrientation)
1.460 + {
1.461 + case EOrientationNormal:
1.462 + return scalingFactorX;
1.463 + case EOrientationRotated90:
1.464 + return iLongWidth * scalingFactorY;
1.465 + case EOrientationRotated180:
1.466 + return -scalingFactorX;
1.467 + case EOrientationRotated270:
1.468 + return -iLongWidth * scalingFactorY;
1.469 + default:
1.470 + break;
1.471 + }
1.472 + return KInvalidValue;
1.473 + }
1.474 +
1.475 +inline TInt CDrawBitmap::Origin(TInt aPhysOrg, TInt aScale) const
1.476 + {
1.477 + return -(aPhysOrg/aScale + (aPhysOrg%aScale ? 1:0));
1.478 + }
1.479 +
1.480 +inline TInt CDrawBitmap::OtherSide(TInt aPhysOrg, TInt aPhysSize, TInt aScale) const
1.481 + {
1.482 + return (aPhysSize-1-aPhysOrg) / aScale + 1;
1.483 + }