|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "BMDRAW.H" |
|
17 #include "BitDrawInterfaceId.h" |
|
18 |
|
19 //The method prepares RGB value writting, calculating physical aX, aY, aWidth and aHeight. |
|
20 //The calculated coordinates are used by methods wich do not use methods in BmDraw8Scaling.cpp |
|
21 //file - WriteRgbMultiXOR(), WriteRgbMultiAND(), WriteRgbMultiOR(). |
|
22 //If the scaling is "off" then it is very simple - draw physical pixels. But if the scaling is |
|
23 //"on" then a rectanngle is being drawn instead of a pixel. And rectangle coordinates are |
|
24 //calculated depending on the device' orientation. |
|
25 //aX, aY - logical coordinates. |
|
26 //aWidth, aHeight - output parameters, they will be initialized in the method's body, |
|
27 //if aDrawMode is not CGraphicsContext::EPenmode. If aDrawMode is CGraphicsContext::EPenmode, |
|
28 //then aWidth will be set with iScalingSettings.iFactorX and aheight - with |
|
29 //iScalingSettings.iFactorY. |
|
30 void CDrawBitmap::PreWriteRgb(TInt& aWidth, |
|
31 TInt& aHeight, |
|
32 TInt& aX, |
|
33 TInt& aY, |
|
34 CGraphicsContext::TDrawMode aDrawMode) |
|
35 { |
|
36 DeOrientate(aX, aY);//aX and aY - physical coordinates |
|
37 |
|
38 __ASSERT_DEBUG(aX >= 0 && aX < iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds)); |
|
39 __ASSERT_DEBUG(aY >= 0 && aY < iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds)); |
|
40 |
|
41 //If scaling is ON, instead of drawing single point, rectangle with size [FactorX, FactorY] |
|
42 //is drawn. Rectangle's width and height might be swapped, depending on the orientation. |
|
43 aWidth = iScalingSettings.iFactorX; |
|
44 aHeight = iScalingSettings.iFactorY; |
|
45 |
|
46 if(iScalingOff) |
|
47 { |
|
48 return; |
|
49 } |
|
50 |
|
51 //Do this additional deorientation only for not EPenmode modes and when scaling is ON! |
|
52 //EPenmode uses WriteRgb(aX,aY,aColor), which does not need any changes in |
|
53 //coordinates! |
|
54 if(!(aDrawMode & CGraphicsContext::EPenmode)) |
|
55 { |
|
56 //aX, aY - physical coordinates |
|
57 //aWidth, aWidth - output parameters |
|
58 //When scaling is ON, instead of drawing single point, rectangle is drawn |
|
59 //and top-left coordinates, width and height has to be calculated. |
|
60 register TInt scalingFactorX = aWidth; |
|
61 register TInt scalingFactorY = aHeight; |
|
62 __ASSERT_DEBUG(scalingFactorX > 0, User::Invariant()); |
|
63 __ASSERT_DEBUG(scalingFactorY > 0, User::Invariant()); |
|
64 register CFbsDrawDevice::TOrientation orientation = iOrientation; |
|
65 |
|
66 switch(orientation) |
|
67 { |
|
68 case EOrientationRotated90: |
|
69 case EOrientationRotated270: |
|
70 { |
|
71 if(orientation == EOrientationRotated90) |
|
72 { |
|
73 aX -= (scalingFactorX - 1); |
|
74 } |
|
75 if(orientation == EOrientationRotated270) |
|
76 { |
|
77 aY -= (scalingFactorY - 1); |
|
78 } |
|
79 break; |
|
80 } |
|
81 case EOrientationRotated180 : |
|
82 { |
|
83 aX -= (scalingFactorX - 1); |
|
84 aY -= (scalingFactorY - 1); |
|
85 break; |
|
86 } |
|
87 default: |
|
88 break; |
|
89 } |
|
90 //If the calculated coordinates are negative, set them to 0. |
|
91 if(aX < 0) |
|
92 { |
|
93 aX = 0; |
|
94 } |
|
95 if(aY < 0) |
|
96 { |
|
97 aY = 0; |
|
98 } |
|
99 } |
|
100 } |
|
101 |
|
102 //Writes RGB value at the specified physical screen coordinates. |
|
103 //When scaling is ON - rectangle [aWidth, aHeight] is drawn instead of single point. |
|
104 //Depending on the orientation aWidth and aHeight might be swapped. |
|
105 //aX, aY - physical coordinates |
|
106 //aWidth, aHeight - physical |
|
107 void CDrawBitmap::WriteRgb(TInt& aWidth, TInt& aHeight, |
|
108 TInt& aX, TInt& aY, TRgb aColor, |
|
109 CGraphicsContext::TDrawMode aDrawMode) |
|
110 { |
|
111 MapColorToUserDisplayMode(aColor); |
|
112 if(iShadowMode) |
|
113 { |
|
114 Shadow(aColor); |
|
115 } |
|
116 if(aDrawMode&CGraphicsContext::EInvertPen) |
|
117 { |
|
118 aColor=~aColor; |
|
119 } |
|
120 if(aDrawMode&CGraphicsContext::EPenmode) |
|
121 { |
|
122 WriteRgb(aX,aY,aColor); |
|
123 return; |
|
124 } |
|
125 __ASSERT_DEBUG(aWidth > 0, User::Invariant()); |
|
126 __ASSERT_DEBUG(aHeight > 0, User::Invariant()); |
|
127 if(aDrawMode&CGraphicsContext::EWriteAlpha) |
|
128 { |
|
129 // WriteRgbMulti is the only available api that writes alpha |
|
130 WriteRgbMulti(aX,aY,aWidth,aHeight,aColor); |
|
131 return; |
|
132 } |
|
133 if(aDrawMode&CGraphicsContext::EInvertScreen) |
|
134 { |
|
135 WriteRgbMultiXOR(aX, aY, aWidth, aHeight, KRgbWhite); |
|
136 } |
|
137 if(aDrawMode&CGraphicsContext::EXor) |
|
138 { |
|
139 WriteRgbMultiXOR(aX, aY, aWidth, aHeight, aColor); |
|
140 } |
|
141 else if(aDrawMode&CGraphicsContext::EAnd) |
|
142 { |
|
143 WriteRgbMultiAND(aX, aY, aWidth, aHeight, aColor); |
|
144 } |
|
145 else if(aDrawMode&CGraphicsContext::EOr) |
|
146 { |
|
147 WriteRgbMultiOR(aX, aY, aWidth, aHeight, aColor); |
|
148 } |
|
149 } |
|
150 |
|
151 /** |
|
152 Implementation for CFbsDrawDevice::GetDrawRect(). |
|
153 Gets logical coordinates of the drawing rectangle. |
|
154 If the device is not scaled and with zero origin, logocal coordinates of |
|
155 the drawing rectangle are the same as its physical coordinates. |
|
156 If the device is rotated, drawing rectangle width and height are swapped. |
|
157 Always prefer GetDrawRect() to SizeInPixels() call. SizeInPixels() will return |
|
158 drawing rectangle width and height. But if the device is scaled or with nonzero origin, |
|
159 GetDrawRect() will take into account and the top-left corner of the drawing rectangle too, |
|
160 which may not be [0, 0]. |
|
161 @param aRect Upon return aRect contains drawing rectangle logical coordinates. |
|
162 */ |
|
163 void CDrawBitmap::GetDrawRect(TRect& aDrawRect) const |
|
164 { |
|
165 aDrawRect = iDrawRect; |
|
166 if (iOrientation & 1) |
|
167 {//90 or 270 degrees |
|
168 if (iOrigin.iX!=iOrigin.iY || iScalingSettings.iFactorX!=iScalingSettings.iFactorY) |
|
169 { //When the scales are different between the dimensions the origin needs to recalculating |
|
170 aDrawRect.iTl.iX=Origin(iOrigin.iX,iScalingSettings.iFactorY); |
|
171 aDrawRect.iTl.iY=Origin(iOrigin.iY,iScalingSettings.iFactorX); |
|
172 } |
|
173 aDrawRect.SetWidth(iDrawRect.Height()); |
|
174 aDrawRect.SetHeight(iDrawRect.Width()); |
|
175 } |
|
176 } |
|
177 |
|
178 /** |
|
179 Implementation for MScalingSettings::Set(). |
|
180 Sets scaling factor by which the drawing device should scale the drawing images. |
|
181 If you want to un-scale the device, call Set() with |
|
182 factorX = 1, factorY = 1, divisorX = 1, divisorY = 1. |
|
183 @param aFactorX Scaling factor for the X-axis of the screen device. |
|
184 @param aFactorY Scaling factor for the y-axis of the screen device. |
|
185 @param aDivisorX Not used. Should be set to 1. |
|
186 @param aDivisorY Not used. Should be set to 1. |
|
187 @return KErrNone success. |
|
188 */ |
|
189 TInt CDrawBitmap::Set(TInt aFactorX, TInt aFactorY, TInt aDivisorX, TInt aDivisorY) |
|
190 { |
|
191 __ASSERT_DEBUG(aDivisorX == 1 && aDivisorY == 1, User::Invariant()); |
|
192 __ASSERT_DEBUG(aFactorX > 0 && aFactorY > 0, User::Invariant()); |
|
193 |
|
194 iScalingSettings.iFactorX = aFactorX; |
|
195 iScalingSettings.iFactorY = aFactorY; |
|
196 iScalingSettings.iDivisorX = aDivisorX; |
|
197 iScalingSettings.iDivisorY = aDivisorY; |
|
198 |
|
199 iScalingOff = aFactorX == 1 && aFactorY == 1 && aDivisorX == 1 && aDivisorY == 1; |
|
200 |
|
201 InitLogicalCoordinates(); |
|
202 |
|
203 return KErrNone; |
|
204 } |
|
205 |
|
206 /** |
|
207 Implementation for MScalingSettings::Get(). |
|
208 Retrieves X-axis and Y-axis scaling factors. |
|
209 @param aFactorX Upon return contains X-axis scaling factor. |
|
210 @param aFactorY Upon return contains Y-axis scaling factor. |
|
211 @param aDivisorX Upon return contains the decimal fraction of X-axis scaling factor. |
|
212 @param aDivisorY Upon return contains the decimal fraction of Y-axis scaling factor. |
|
213 */ |
|
214 void CDrawBitmap::Get(TInt& aFactorX, TInt& aFactorY, TInt& aDivisorX, TInt& aDivisorY) |
|
215 { |
|
216 aFactorX = iScalingSettings.iFactorX; |
|
217 aFactorY = iScalingSettings.iFactorY; |
|
218 aDivisorX = iScalingSettings.iDivisorX; |
|
219 aDivisorY = iScalingSettings.iDivisorY; |
|
220 } |
|
221 |
|
222 /** |
|
223 Implementation for MScalingSettings::IsScalingOff(). |
|
224 Notifies the caller whether the drawing device is scaled or not. |
|
225 @return ETrue Drawing device is not scaled, EFalse - it is scaled. |
|
226 */ |
|
227 TBool CDrawBitmap::IsScalingOff() |
|
228 { |
|
229 return iScalingOff; |
|
230 } |
|
231 |
|
232 /** |
|
233 Implementation for MDrawDeviceOrigin::Set(). |
|
234 Sets drawing device origin. |
|
235 If you want to the default origin, call Set() with Origin (0,0). |
|
236 @param aOrigin Specifies physical coordinates of the new scaling origin |
|
237 of the drawing device. The drawing device maps the logical point [0,0] to |
|
238 the "aOrigin" physical point . |
|
239 @return KErrNone success. |
|
240 */ |
|
241 TInt CDrawBitmap::Set(const TPoint& aOrigin) |
|
242 { |
|
243 __ASSERT_DEBUG(aOrigin.iX >= 0 && aOrigin.iY >= 0, User::Invariant()); |
|
244 __ASSERT_DEBUG(aOrigin.iX < iSize.iWidth && aOrigin.iY < iSize.iHeight, User::Invariant()); |
|
245 |
|
246 iOrigin = aOrigin; |
|
247 |
|
248 iOriginIsZero = iOrigin.iX == 0 && iOrigin.iY == 0; |
|
249 |
|
250 InitLogicalCoordinates(); |
|
251 |
|
252 return KErrNone; |
|
253 } |
|
254 |
|
255 /** |
|
256 Implementation for MDrawDeviceOrigin::Get(). |
|
257 Retrieves origin point. |
|
258 @param aOrigin Upon return contains scaling origin point. |
|
259 */ |
|
260 void CDrawBitmap::Get(TPoint& aOrigin) |
|
261 { |
|
262 aOrigin = iOrigin; |
|
263 } |
|
264 |
|
265 //Initializes iDrawRect data member, which contains logical coordinates of |
|
266 //the drawing(screen) rectangle. |
|
267 //The method does not use iOrientation data member. |
|
268 void CDrawBitmap::InitLogicalCoordinates() |
|
269 { |
|
270 register TInt orgX = iOrigin.iX; |
|
271 register TInt orgY = iOrigin.iY; |
|
272 register TInt fX = iScalingSettings.iFactorX; |
|
273 register TInt fY = iScalingSettings.iFactorY; |
|
274 |
|
275 iDrawRect.iTl.iX = Origin(orgX, fX); |
|
276 iDrawRect.iTl.iY = Origin(orgY, fY); |
|
277 iDrawRect.iBr.iX = OtherSide(orgX, iSize.iWidth, fX); |
|
278 iDrawRect.iBr.iY = OtherSide(orgY, iSize.iHeight, fY); |
|
279 if (orgX!=orgY) |
|
280 { //The number of addressable pixels in the physical dimensions |
|
281 //Sometimes needs to be one less when rotationed by 90 or 270 |
|
282 //If so set it one less all the time as the value is not recalculated |
|
283 if (fX>1) |
|
284 { //Calculated the physical left and right of screen when rotation by 90 or 270 |
|
285 //Use this width if it is smaller |
|
286 TInt left = Origin(orgY, fX); |
|
287 TInt right = OtherSide(orgY, iSize.iWidth, fX); |
|
288 iDrawRect.iBr.iX = Min(iDrawRect.iBr.iX, iDrawRect.iTl.iX+(right-left)); |
|
289 } |
|
290 if (fY>1) |
|
291 { //Calculated the physical top and bottom of screen when rotation by 90 or 270 |
|
292 //Use this height if it is smaller |
|
293 TInt top = Origin(orgX, fY); |
|
294 TInt bottom = OtherSide(orgX, iSize.iHeight, fY); |
|
295 iDrawRect.iBr.iY = Min(iDrawRect.iBr.iY, iDrawRect.iTl.iY+(bottom-top)); |
|
296 } |
|
297 } |
|
298 } |
|
299 |
|
300 /** |
|
301 Notifies the caller whether the drawing device can be scaled or not. |
|
302 @return ETrue Drawing device can be scaled, EFalse - it can't be scaled. |
|
303 */ |
|
304 TBool CDrawBitmap::CanBeScaled() const |
|
305 { |
|
306 //The function will return true for all display modes |
|
307 return ETrue; |
|
308 } |
|
309 |
|
310 /** |
|
311 Notifies the caller whether the drawing device origin can be moved from (0, 0) point or not. |
|
312 @return ETrue Drawing device origin can be moved, EFalse - it can't be moved. |
|
313 */ |
|
314 TBool CDrawBitmap::CanOriginBeMoved() const |
|
315 { |
|
316 //The function will return true for all display modes |
|
317 return ETrue; |
|
318 } |
|
319 |
|
320 //This method calculates pixel increment value and row increment value depending |
|
321 //on the orientation. The device might be scaled. The result is returned in |
|
322 //aPixelInc and aRowInc parameters. |
|
323 void CDrawBitmap::SetPixelInc(TInt& aPixelInc, TInt& aRowInc) const |
|
324 { |
|
325 register TInt scalingFactorX = iScalingSettings.iFactorX; |
|
326 register TInt scalingFactorY = iScalingSettings.iFactorY; |
|
327 switch(iOrientation) |
|
328 { |
|
329 case EOrientationNormal: |
|
330 { |
|
331 aPixelInc = scalingFactorX; |
|
332 aRowInc = iLongWidth * scalingFactorY; |
|
333 break; |
|
334 } |
|
335 case EOrientationRotated90: |
|
336 { |
|
337 aPixelInc = iLongWidth * scalingFactorY; |
|
338 aRowInc = -scalingFactorX; |
|
339 break; |
|
340 } |
|
341 case EOrientationRotated180: |
|
342 { |
|
343 aPixelInc = -scalingFactorX; |
|
344 aRowInc = -iLongWidth * scalingFactorY; |
|
345 break; |
|
346 } |
|
347 default: // EOrientationRotated270 |
|
348 { |
|
349 aPixelInc = -iLongWidth * scalingFactorY; |
|
350 aRowInc = scalingFactorX; |
|
351 break; |
|
352 } |
|
353 } |
|
354 } |
|
355 |
|
356 //Calculates "Y" increment value and assigns it to aY parameter. |
|
357 //The device might be scaled and rotated. |
|
358 //It is used by WriteBinary(), WriteBinaryOp(), ... methods and only there. |
|
359 //The method is very specific for the methods mentioned above - |
|
360 //if the device is scaled and rotated 0 or 180 degrees, Y-axis coordinate has to |
|
361 //be incremented not by 1, but by iScalingSettings.iFactorY. Because of the integer divison |
|
362 //when transforming logical to physical coordinates, incremented Y-axis coordinates may |
|
363 //go negative or greater than drawing rectangle height. Then it has to be adjusted to 0 |
|
364 //or rectangle height. |
|
365 void CDrawBitmap::IncScaledY(TInt& aY, TInt aYOrg) const |
|
366 { |
|
367 const TOrientation orientation = iOrientation; |
|
368 const TInt fY = iScalingSettings.iFactorY; |
|
369 switch(orientation) |
|
370 { |
|
371 case EOrientationNormal: |
|
372 { |
|
373 aY += fY; |
|
374 const TInt height = iSize.iHeight - 1; |
|
375 if(aY > height) |
|
376 { |
|
377 aY = height; |
|
378 } |
|
379 break; |
|
380 } |
|
381 case EOrientationRotated180: |
|
382 { |
|
383 aY -= fY; |
|
384 if(aY < 0) |
|
385 { |
|
386 aY = 0; |
|
387 } |
|
388 break; |
|
389 } |
|
390 default: |
|
391 { |
|
392 aY = aYOrg; |
|
393 } |
|
394 } |
|
395 } |
|
396 |
|
397 //Calculates "Y" increment value and assigns it to aY parameter. |
|
398 //The device might be scaled and rotated. |
|
399 //It is used by WriteBinary(), WriteBinaryOp(), WriteLine...() methods and only there. |
|
400 //The method is very specific for the methods mentioned above - |
|
401 //if the device is scaled and rotated 90 or 270 degrees, Y-axis coordinate has to |
|
402 //be incremented not by 1, but by iScalingSettings.iFactorX. Because of the integer divison |
|
403 //when transforming logical to physical coordinates, incremented Y-axis coordinates may |
|
404 //go negative or greater than drawing rectangle height. Then it has to be adjusted to 0 |
|
405 //or rectangle height. |
|
406 void CDrawBitmap::IncScaledY(TInt& aY) const |
|
407 { |
|
408 const TOrientation orientation = iOrientation; |
|
409 const TInt fX = iScalingSettings.iFactorY; |
|
410 if(orientation == EOrientationRotated90) |
|
411 { |
|
412 aY += fX; |
|
413 const TInt height = iSize.iHeight - 1; |
|
414 if(aY > height) |
|
415 { |
|
416 aY = height; |
|
417 } |
|
418 } |
|
419 else if(orientation == EOrientationRotated270) |
|
420 { |
|
421 aY -= fX; |
|
422 if(aY < 0) |
|
423 { |
|
424 aY = 0; |
|
425 } |
|
426 } |
|
427 } |
|
428 |
|
429 //Increment without scaling |
|
430 TInt CDrawBitmap::PixelAddressIncrement() const |
|
431 { |
|
432 switch (iOrientation) |
|
433 { |
|
434 case EOrientationNormal: |
|
435 return 1; |
|
436 case EOrientationRotated90: |
|
437 return iLongWidth; |
|
438 case EOrientationRotated180: |
|
439 return -1; |
|
440 case EOrientationRotated270: |
|
441 return -iLongWidth; |
|
442 default: |
|
443 break; |
|
444 } |
|
445 return KInvalidValue; |
|
446 } |
|
447 |
|
448 //Pixel increment with scaling. |
|
449 //It is used by CDrawEightBppBitmapCommon::SetPixels, |
|
450 //CDrawEightBppBitmapCommon::XORPixels, CDrawEightBppBitmapCommon::ANDPixels, |
|
451 //CDrawEightBppBitmapCommon::ORPixels methods |
|
452 TInt CDrawBitmap::LogicalPixelAddressIncrement() const |
|
453 { |
|
454 register TInt scalingFactorX = iScalingSettings.iFactorX; |
|
455 register TInt scalingFactorY = iScalingSettings.iFactorY; |
|
456 switch (iOrientation) |
|
457 { |
|
458 case EOrientationNormal: |
|
459 return scalingFactorX; |
|
460 case EOrientationRotated90: |
|
461 return iLongWidth * scalingFactorY; |
|
462 case EOrientationRotated180: |
|
463 return -scalingFactorX; |
|
464 case EOrientationRotated270: |
|
465 return -iLongWidth * scalingFactorY; |
|
466 default: |
|
467 break; |
|
468 } |
|
469 return KInvalidValue; |
|
470 } |
|
471 |
|
472 inline TInt CDrawBitmap::Origin(TInt aPhysOrg, TInt aScale) const |
|
473 { |
|
474 return -(aPhysOrg/aScale + (aPhysOrg%aScale ? 1:0)); |
|
475 } |
|
476 |
|
477 inline TInt CDrawBitmap::OtherSide(TInt aPhysOrg, TInt aPhysSize, TInt aScale) const |
|
478 { |
|
479 return (aPhysSize-1-aPhysOrg) / aScale + 1; |
|
480 } |