|
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 |