|
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: CSvgtFbsRasterizer implementation. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "svgtfbsrasterizer.h" |
|
19 #include "fbsrasterizerpanics.h" |
|
20 #include "SvgtRegisteredBitmap.h" |
|
21 #include "svgtgraphicsinterface.h" |
|
22 #include <e32std.h> |
|
23 #include <nvg.h> |
|
24 #include <AknIconHeader.h> |
|
25 #include <AknIconUtils.h> |
|
26 #include <vgcontext.h> |
|
27 |
|
28 #include <bitstd.h> |
|
29 #include <bitdev.h> |
|
30 |
|
31 TBool operator==(const CFbsRasterizer::TBitmapDesc& aBitmapDesc1, |
|
32 const CFbsRasterizer::TBitmapDesc& aBitmapDesc2) |
|
33 { |
|
34 return ((&aBitmapDesc1 == &aBitmapDesc2) |
|
35 || (aBitmapDesc1.iSizeInPixels == aBitmapDesc2.iSizeInPixels |
|
36 && aBitmapDesc1.iDispMode == aBitmapDesc2.iDispMode |
|
37 && aBitmapDesc1.iDataType == aBitmapDesc2.iDataType |
|
38 && aBitmapDesc1.iData == aBitmapDesc2.iData |
|
39 && aBitmapDesc1.iDataSize == aBitmapDesc2.iDataSize)); |
|
40 } |
|
41 |
|
42 void CleanupVGImage( TAny* aObj ) |
|
43 { |
|
44 VGImage * imageToDestroy = reinterpret_cast<VGImage *>(aObj); |
|
45 if (imageToDestroy && *imageToDestroy != VG_INVALID_HANDLE) |
|
46 { |
|
47 vgDestroyImage(*imageToDestroy); |
|
48 } |
|
49 } |
|
50 |
|
51 /** Create a new rasterizer. |
|
52 @return A pointer to a newly constructed CFbsRasterizer object if successful, |
|
53 or NULL if no memory is available. |
|
54 */ |
|
55 EXPORT_C CFbsRasterizer* CSvgtFbsRasterizer::New() |
|
56 { |
|
57 CSvgtFbsRasterizer* self = new CSvgtFbsRasterizer; |
|
58 if ( self ) |
|
59 { |
|
60 self->InitializeRasterizer(); |
|
61 } |
|
62 return self; |
|
63 } |
|
64 |
|
65 /** Constructor */ |
|
66 CSvgtFbsRasterizer::CSvgtFbsRasterizer() |
|
67 :iRegisteredBmps(_FOFF(CSvgtRegisteredBitmap, iLink)), iRecentBmps(_FOFF(CSvgtRegisteredBitmap, iLink)) |
|
68 { |
|
69 RProcess currentProcess; |
|
70 TFileName exeFileName = currentProcess.FileName(); |
|
71 exeFileName.Copy(exeFileName.Mid(11)); |
|
72 exeFileName.Copy(exeFileName.Left(exeFileName.Length()-4)); |
|
73 |
|
74 if(exeFileName.Compare(_L("peninputserver"))==0) |
|
75 { |
|
76 iCacheLimit = 0x133333; |
|
77 iSpecialProcess = TRUE; |
|
78 } |
|
79 else |
|
80 { |
|
81 iCacheLimit = KMaxRecentBmpCacheSize; |
|
82 iSpecialProcess = FALSE; |
|
83 } |
|
84 } |
|
85 |
|
86 CSvgtFbsRasterizer::~CSvgtFbsRasterizer() |
|
87 { |
|
88 while (!iRegisteredBmps.IsEmpty()) |
|
89 { |
|
90 delete iRegisteredBmps.First(); |
|
91 } |
|
92 while (!iRecentBmps.IsEmpty()) |
|
93 { |
|
94 delete iRecentBmps.First(); |
|
95 } |
|
96 delete iIdle; |
|
97 |
|
98 delete iNvgEngine; |
|
99 delete iGraphicsInterface; |
|
100 if ( iMatricesUpdated ) |
|
101 { |
|
102 RestoreMatrices(); |
|
103 } |
|
104 } |
|
105 |
|
106 /** Register a bitmap with this rasterizer for rendering. In this example the extended |
|
107 bitmap data is just a buffer that is copied when BeginBitmap() is called and deleted when |
|
108 EndBitmap() is called for the same bitmap. The only display modes supported by this example |
|
109 raterizer are EColor16MU and EColor16MA |
|
110 */ |
|
111 void CSvgtFbsRasterizer::BeginBitmap(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, const TRegion* aRegionOfInterest) |
|
112 { |
|
113 TRAPD(beginErr, DoBeginBitmapL(aBitmapId, aBitmapDesc, aRegionOfInterest)); |
|
114 // If there is error in begin, the consecutive fulction calls should be invalid. |
|
115 iIsRasterizerValidState = ( beginErr == KErrNone); |
|
116 } |
|
117 |
|
118 void CSvgtFbsRasterizer::DoBeginBitmapL(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, |
|
119 const TRegion* /* aRegionOfInterest */) |
|
120 { |
|
121 // Check that the passed extended bitmap description is valid |
|
122 if ((aBitmapDesc.iSizeInPixels.iWidth <= 0) || (aBitmapDesc.iSizeInPixels.iHeight <= 0) |
|
123 || (aBitmapDesc.iDataType != KUidNvgProprietaryFormat) |
|
124 || (!aBitmapDesc.iData ) |
|
125 || (aBitmapDesc.iDataSize <= 0)) |
|
126 { |
|
127 return; |
|
128 } |
|
129 // Check if the bitmap is already registered |
|
130 CSvgtRegisteredBitmap* foundRegBmp = RegisteredBitmap(aBitmapId); |
|
131 if (!foundRegBmp) |
|
132 { |
|
133 // Not registered: check if the bitmap is in the cache of recently used bitmaps |
|
134 foundRegBmp = RecentBitmap(aBitmapId); |
|
135 if (foundRegBmp) |
|
136 { |
|
137 // Take the bitmap out of the cache and put it in the list of registered bitmaps |
|
138 foundRegBmp->iLink.Deque(); |
|
139 iTotalRecentBmpSize -= foundRegBmp->DataSize(); |
|
140 iRegisteredBmps.AddLast(*foundRegBmp); |
|
141 } |
|
142 } |
|
143 if (foundRegBmp) |
|
144 { |
|
145 // This bitmap is already registered, just increment its reference count and return |
|
146 foundRegBmp->iRefCount++; |
|
147 return; |
|
148 } |
|
149 |
|
150 CSvgtRegisteredBitmap* regBmp = new CSvgtRegisteredBitmap(aBitmapId); |
|
151 if (!regBmp) |
|
152 { |
|
153 return; |
|
154 } |
|
155 TRAPD(err, RenderL(aBitmapDesc, *regBmp)); |
|
156 if (err != KErrNone) |
|
157 { |
|
158 delete regBmp; |
|
159 return; |
|
160 } |
|
161 // Success |
|
162 iRegisteredBmps.AddLast(*regBmp); |
|
163 regBmp->iRefCount = 1; |
|
164 } |
|
165 |
|
166 /** Unregister an extended bitmap from this rasterizer. |
|
167 @see CFbsRasterizer::EndBitmap() |
|
168 @see BeginBitmap() |
|
169 */ |
|
170 void CSvgtFbsRasterizer::EndBitmap(TInt64 aBitmapId) |
|
171 { |
|
172 CSvgtRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId); |
|
173 if (regBmp) |
|
174 { |
|
175 if (--regBmp->iRefCount == 0) |
|
176 { |
|
177 // Put unregistered bitmap in the cache of recently used bitmaps if wholly pre-rendered |
|
178 // and there is an active scheduler to add the idle-time clean-up active object to |
|
179 if (CActiveScheduler::Current()) |
|
180 { |
|
181 if (!iIdle) |
|
182 { |
|
183 iIdle = CIdle::New(CActive::EPriorityIdle); |
|
184 if (!iIdle) |
|
185 { |
|
186 delete regBmp; |
|
187 return; |
|
188 } |
|
189 } |
|
190 regBmp->iLink.Deque(); |
|
191 if (regBmp->DataSize() <= iCacheLimit) |
|
192 { |
|
193 iRecentBmps.AddFirst(*regBmp); |
|
194 iTotalRecentBmpSize += regBmp->DataSize(); |
|
195 } |
|
196 // Delete the least recently used bitmaps if the maximum size of the cache is exceeded |
|
197 while (iTotalRecentBmpSize > iCacheLimit) |
|
198 { |
|
199 regBmp = iRecentBmps.Last(); |
|
200 iTotalRecentBmpSize -= regBmp->DataSize(); |
|
201 delete regBmp; |
|
202 } |
|
203 // If the cache is not empty make sure the idle-time clean-up active object is scheduled to run |
|
204 if (!iRecentBmps.IsEmpty() && !iIdle->IsActive()) |
|
205 { |
|
206 iIdle->Start(TCallBack(IdleFunction, this)); |
|
207 } |
|
208 } |
|
209 else |
|
210 { |
|
211 delete regBmp; |
|
212 } |
|
213 } |
|
214 } |
|
215 } |
|
216 |
|
217 /** Return a scanline from the passed extended bitmap given it's bitmap id. |
|
218 */ |
|
219 const TUint32* CSvgtFbsRasterizer::ScanLine(TInt64 aBitmapId, const TPoint& aPixel, TInt aLength) |
|
220 { |
|
221 CSvgtRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId); |
|
222 if (!regBmp) |
|
223 { |
|
224 return NULL; |
|
225 } |
|
226 if (!TRect(regBmp->SizeInPixels()).Contains(aPixel) |
|
227 || (aLength > (regBmp->SizeInPixels().iWidth - aPixel.iX))) |
|
228 { |
|
229 return NULL; |
|
230 } |
|
231 |
|
232 return PtrAdd(regBmp->DataAddress(), aPixel.iY * regBmp->DataStride()); |
|
233 } |
|
234 |
|
235 /** No extension interaces are available, KErrNotSupported for all aInterfaceId passed. |
|
236 @see CFbsRasterizer::GetInterface() |
|
237 */ |
|
238 TInt CSvgtFbsRasterizer::GetInterface(TUid /*aInterfaceId*/, TAny*& aInterface) |
|
239 { |
|
240 aInterface = NULL; |
|
241 return KErrExtensionNotSupported; |
|
242 } |
|
243 |
|
244 |
|
245 /** Gets a bitmap that has been registered with this rasterizer. |
|
246 |
|
247 @param aBitmapId The ID of the bitmap to check for. |
|
248 |
|
249 @return A pointer to the registered bitmap if found, NULL otherwise. |
|
250 */ |
|
251 CSvgtRegisteredBitmap* CSvgtFbsRasterizer::RegisteredBitmap(TInt64 aBitmapId) |
|
252 { |
|
253 TDblQueIter<CSvgtRegisteredBitmap> iter(iRegisteredBmps); |
|
254 while (CSvgtRegisteredBitmap* regBmp = iter++) |
|
255 { |
|
256 if (regBmp->iBitmapId == aBitmapId) |
|
257 { |
|
258 return regBmp; |
|
259 } |
|
260 } |
|
261 return NULL; |
|
262 } |
|
263 |
|
264 /** Gets a bitmap that has been recently used with this rasterizer. |
|
265 |
|
266 @param aBitmapId The ID of the bitmap to check for. |
|
267 |
|
268 @return A pointer to the recently used bitmap if found, NULL otherwise. |
|
269 */ |
|
270 CSvgtRegisteredBitmap* CSvgtFbsRasterizer::RecentBitmap(TInt64 aBitmapId) |
|
271 { |
|
272 TDblQueIter<CSvgtRegisteredBitmap> iter(iRecentBmps); |
|
273 while (CSvgtRegisteredBitmap* regBmp = iter++) |
|
274 { |
|
275 if (regBmp->iBitmapId == aBitmapId) |
|
276 { |
|
277 return regBmp; |
|
278 } |
|
279 } |
|
280 return NULL; |
|
281 } |
|
282 |
|
283 TInt CSvgtFbsRasterizer::IdleFunction(TAny* aPtr) |
|
284 { |
|
285 CSvgtFbsRasterizer* self = static_cast<CSvgtFbsRasterizer*>(aPtr); |
|
286 if(self->iSpecialProcess!=true) |
|
287 { |
|
288 |
|
289 while (!self->iRecentBmps.IsEmpty()) |
|
290 { |
|
291 delete self->iRecentBmps.First(); |
|
292 } |
|
293 self->iTotalRecentBmpSize = 0; |
|
294 } |
|
295 return 0; |
|
296 } |
|
297 |
|
298 void CSvgtFbsRasterizer::InitializeRasterizer() |
|
299 { |
|
300 } |
|
301 |
|
302 void CSvgtFbsRasterizer::RenderBitmapL(CSvgtRegisteredBitmap& aPixMap, CFbsBitmap * aMask, |
|
303 const TBitmapDesc& aBitmapDesc, TPtr8& aDataPtr8, TAknIconHeader& aIconHeader) |
|
304 { |
|
305 TSize newSize = aBitmapDesc.iSizeInPixels; |
|
306 UpdateMatrices(); |
|
307 iMatricesUpdated = ETrue; |
|
308 TBool isMargin = aIconHeader.IsMarginCorrection(); |
|
309 |
|
310 VGImage vgImage = VG_INVALID_HANDLE; |
|
311 |
|
312 if (isMargin) |
|
313 { |
|
314 vgImage = vgCreateImage((VGImageFormat) VG_sRGBA_8888_PRE , aBitmapDesc.iSizeInPixels.iWidth, |
|
315 aBitmapDesc.iSizeInPixels.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); |
|
316 if (vgImage == VG_INVALID_HANDLE) |
|
317 { |
|
318 User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); |
|
319 } |
|
320 CleanupStack::PushL( TCleanupItem( CleanupVGImage, &vgImage ) ); |
|
321 iGraphicsInterface->BindClientBuffer(vgImage); |
|
322 } |
|
323 User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); |
|
324 |
|
325 if(isMargin) |
|
326 { |
|
327 iGraphicsInterface->UnBindClientBuffer(); |
|
328 newSize = ApplyMarginL(vgImage, aBitmapDesc.iSizeInPixels); |
|
329 if(newSize!=aBitmapDesc.iSizeInPixels) |
|
330 { |
|
331 User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); |
|
332 } |
|
333 else |
|
334 { |
|
335 vgDrawImage(vgImage); |
|
336 User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); |
|
337 } |
|
338 |
|
339 CleanupStack::PopAndDestroy(); |
|
340 } |
|
341 iGraphicsInterface->CopyBitmapL(&aPixMap, aMask); |
|
342 |
|
343 TUint32 iconColor = aIconHeader.GetIconColor(); |
|
344 |
|
345 if (iconColor & 0xFFFFFF) |
|
346 { |
|
347 CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( &aPixMap ); |
|
348 CleanupStack::PushL( dev ); |
|
349 CFbsBitGc* gc = NULL; |
|
350 User::LeaveIfError( dev->CreateContext( gc ) ); |
|
351 CleanupStack::PushL( gc ); |
|
352 TRgb color(iconColor); |
|
353 gc->SetBrushColor( color ); |
|
354 gc->SetPenStyle( CGraphicsContext::ENullPen ); |
|
355 gc->SetBrushStyle( CGraphicsContext::ESolidBrush ); |
|
356 // Fill icon with the given color, mask defines the icon shape. |
|
357 TPoint origin(0, 0); |
|
358 if (newSize != aBitmapDesc.iSizeInPixels) |
|
359 { |
|
360 origin = TPoint((aBitmapDesc.iSizeInPixels.iWidth - newSize.iWidth)/2 , (aBitmapDesc.iSizeInPixels.iHeight - newSize.iHeight)/2 ); |
|
361 } |
|
362 gc->DrawRect( TRect( origin, newSize ) ); |
|
363 CleanupStack::PopAndDestroy( 2 ); // dev, gc |
|
364 } |
|
365 } |
|
366 |
|
367 void CSvgtFbsRasterizer::RenderMaskL(CSvgtRegisteredBitmap& aPixMap, CFbsBitmap * aMask, |
|
368 const TBitmapDesc& aBitmapDesc, TPtr8& aDataPtr8, TAknIconHeader& aIconHeader) |
|
369 { |
|
370 UpdateMatrices(); |
|
371 iMatricesUpdated = ETrue; |
|
372 TBool isMargin = aIconHeader.IsMarginCorrection(); |
|
373 |
|
374 VGImage vgImage = VG_INVALID_HANDLE; |
|
375 if (isMargin) |
|
376 { |
|
377 vgImage = vgCreateImage((VGImageFormat) VG_sRGBA_8888_PRE , aBitmapDesc.iSizeInPixels.iWidth, |
|
378 aBitmapDesc.iSizeInPixels.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); |
|
379 if (vgImage == VG_INVALID_HANDLE) |
|
380 { |
|
381 User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); |
|
382 } |
|
383 CleanupStack::PushL( TCleanupItem( CleanupVGImage, &vgImage ) ); |
|
384 iGraphicsInterface->BindClientBuffer(vgImage); |
|
385 } |
|
386 |
|
387 VGfloat color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; |
|
388 vgSeti(VG_SCISSORING, VG_FALSE); |
|
389 vgSetfv(VG_CLEAR_COLOR, 4, color); |
|
390 vgClear(0, 0, aBitmapDesc.iSizeInPixels.iWidth, aBitmapDesc.iSizeInPixels.iHeight); |
|
391 |
|
392 User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, aBitmapDesc.iSizeInPixels, &aPixMap, aMask)); |
|
393 if (isMargin) |
|
394 { |
|
395 iGraphicsInterface->UnBindClientBuffer(); |
|
396 TSize newSize = ApplyMarginL(vgImage, aBitmapDesc.iSizeInPixels); |
|
397 if(newSize!=aBitmapDesc.iSizeInPixels) |
|
398 { |
|
399 User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); |
|
400 } |
|
401 else |
|
402 { |
|
403 vgDrawImage(vgImage); |
|
404 User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); |
|
405 } |
|
406 CleanupStack::PopAndDestroy(); |
|
407 } |
|
408 |
|
409 TSize bitmapSize = aPixMap.SizeInPixels(); |
|
410 |
|
411 const TInt KOriginalFilterMasks = vgGeti( VG_FILTER_CHANNEL_MASK ); |
|
412 vgSeti( VG_FILTER_CHANNEL_MASK, VG_ALPHA ); |
|
413 |
|
414 const TInt KStride = CFbsBitmap::ScanLineLength(bitmapSize.iWidth, aPixMap.DisplayMode()); |
|
415 VGImageFormat format = ( aPixMap.DisplayMode() == EGray256 ) ? VG_A_8 : VG_BW_1; |
|
416 |
|
417 aPixMap.BeginDataAccess(); |
|
418 TUint * data = (TUint*)((TUint)aPixMap.DataAddress() + ( KStride * ( aPixMap.SizeInPixels().iHeight - 1 ) ) ); |
|
419 vgReadPixels( data, -KStride, format, 0, 0, bitmapSize.iWidth, bitmapSize.iHeight ); |
|
420 aPixMap.EndDataAccess(); |
|
421 |
|
422 vgSeti( VG_FILTER_CHANNEL_MASK, KOriginalFilterMasks ); |
|
423 |
|
424 } |
|
425 |
|
426 void CSvgtFbsRasterizer::RenderL( const TBitmapDesc& aBitmapDesc, CSvgtRegisteredBitmap& aBitmap ) |
|
427 { |
|
428 |
|
429 iIsRasterizerValidState = EFalse; |
|
430 |
|
431 User::LeaveIfError(aBitmap.Create(aBitmapDesc.iSizeInPixels, aBitmapDesc.iDispMode)); |
|
432 |
|
433 if (!iGraphicsInterface) |
|
434 { |
|
435 iGraphicsInterface = CSvgtGraphicsInterface::CreateImplementationL(); |
|
436 } |
|
437 |
|
438 iGraphicsInterface->InitializeL(aBitmapDesc.iSizeInPixels); |
|
439 iIsRasterizerValidState = ETrue; |
|
440 |
|
441 TPtr8 bmpDataPtr8((TUint8*)aBitmapDesc.iData, aBitmapDesc.iDataSize); |
|
442 |
|
443 if (!iNvgEngine) |
|
444 { |
|
445 iNvgEngine = CNvgEngine::NewL(); |
|
446 } |
|
447 |
|
448 iNvgEngine->SetVGImageBinder(iGraphicsInterface); |
|
449 |
|
450 TUint8 *temp = (TUint8 *)bmpDataPtr8.Ptr(); |
|
451 TPtr8 IconHeaderPtr(temp, KIconHeaderLength, KIconHeaderLength); |
|
452 |
|
453 TAknIconHeader iconheader(IconHeaderPtr); |
|
454 //skipping header bytes |
|
455 temp = temp + KIconHeaderLength; |
|
456 TPtr8 newDataPtr8(temp, (bmpDataPtr8.MaxLength() - KIconHeaderLength), (bmpDataPtr8.MaxLength() - KIconHeaderLength)); |
|
457 |
|
458 CFbsBitmap* mask = NULL; |
|
459 |
|
460 VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; |
|
461 vgSeti(VG_SCISSORING, VG_FALSE); |
|
462 vgSetfv(VG_CLEAR_COLOR, 4, color); |
|
463 vgClear(0, 0, aBitmapDesc.iSizeInPixels.iWidth, aBitmapDesc.iSizeInPixels.iHeight); |
|
464 TInt rotAngle = iconheader.GetRotation(); |
|
465 // setting the rotation angle |
|
466 iNvgEngine->Rotate(-rotAngle, aBitmapDesc.iSizeInPixels.iWidth >> 1,aBitmapDesc.iSizeInPixels.iHeight >>1); |
|
467 |
|
468 //setting preserve aspect ratio |
|
469 TNvgAlignStatusType alignTypeValue = ENvgPreserveAspectRatio_XmidYmid; |
|
470 TNvgMeetOrSliceType meetOrSliceTypeValue = ENvgMeet; |
|
471 |
|
472 switch ( iconheader.GetScaleMode() ) |
|
473 { |
|
474 case EAspectRatioPreserved: // fall through |
|
475 { |
|
476 // use default |
|
477 break; |
|
478 } |
|
479 // Ensures NVG content fully covers the area of the icon whilst preserving aspect ratio. |
|
480 case EAspectRatioPreservedSlice: |
|
481 { |
|
482 // alignTypeValue use default |
|
483 meetOrSliceTypeValue = ENvgSlice; |
|
484 break; |
|
485 } |
|
486 /* EAspectRatioPreservedAndUnusedSpaceRemoved is mapped to the same values as EAspectRatioNotPreserved |
|
487 * because we already have a frame buffer with the dimensions that preserves the aspect ratio. |
|
488 * This mapping ensures that NVG engine does not calculate aspect ratio twice and potentially resulting in precision loss.*/ |
|
489 case EAspectRatioPreservedAndUnusedSpaceRemoved: |
|
490 case EAspectRatioNotPreserved: |
|
491 { |
|
492 alignTypeValue = ENvgPreserveAspectRatio_None; |
|
493 // meetOrSliceTypeValue use default |
|
494 break; |
|
495 } |
|
496 default: |
|
497 { |
|
498 User::Leave(KErrCorrupt); |
|
499 } |
|
500 } |
|
501 iNvgEngine->SetPreserveAspectRatio(alignTypeValue, meetOrSliceTypeValue); |
|
502 |
|
503 iMatricesUpdated = EFalse; |
|
504 if (iconheader.IsMask()) |
|
505 { |
|
506 RenderMaskL(aBitmap, mask, aBitmapDesc, newDataPtr8, iconheader); |
|
507 } |
|
508 else |
|
509 { |
|
510 RenderBitmapL(aBitmap, mask, aBitmapDesc, newDataPtr8, iconheader); |
|
511 } |
|
512 |
|
513 if ( iMatricesUpdated ) |
|
514 { |
|
515 RestoreMatrices(); |
|
516 iMatricesUpdated = EFalse; |
|
517 } |
|
518 } |
|
519 |
|
520 void CSvgtFbsRasterizer::UpdateMatrices() |
|
521 { |
|
522 iUserStrokePaint = vgGetPaint(VG_STROKE_PATH); |
|
523 |
|
524 iUserFillPaint = vgGetPaint(VG_FILL_PATH); |
|
525 |
|
526 iMatrixMode = vgGeti(VG_MATRIX_MODE); |
|
527 |
|
528 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); |
|
529 |
|
530 vgGetMatrix(iPathMatrix); |
|
531 |
|
532 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); |
|
533 |
|
534 vgGetMatrix(iImageMatrix); |
|
535 |
|
536 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); |
|
537 |
|
538 vgGetMatrix(iFillPaintMatrix); |
|
539 |
|
540 vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); |
|
541 |
|
542 vgGetMatrix(iStrokePaintMatrix); |
|
543 |
|
544 vgSeti(VG_MATRIX_MODE, iMatrixMode); |
|
545 |
|
546 } |
|
547 |
|
548 void CSvgtFbsRasterizer::RestoreMatrices() |
|
549 { |
|
550 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); |
|
551 |
|
552 vgLoadMatrix(iPathMatrix); |
|
553 |
|
554 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); |
|
555 |
|
556 vgLoadMatrix(iImageMatrix); |
|
557 |
|
558 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); |
|
559 |
|
560 vgLoadMatrix(iFillPaintMatrix); |
|
561 |
|
562 vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); |
|
563 |
|
564 vgLoadMatrix(iStrokePaintMatrix); |
|
565 |
|
566 vgSeti(VG_MATRIX_MODE, iMatrixMode); |
|
567 |
|
568 vgSetPaint(iUserStrokePaint, VG_STROKE_PATH); |
|
569 |
|
570 vgSetPaint(iUserFillPaint, VG_FILL_PATH); |
|
571 } |
|
572 |
|
573 |
|
574 TSize CSvgtFbsRasterizer::ApplyMarginL(VGImage aVgImage, TSize aSize) |
|
575 { |
|
576 HBufC8* buf = HBufC8::NewL(aSize.iWidth* sizeof(TUint32)); |
|
577 TUint32* ptr = (TUint32*)(buf->Des()).Ptr(); |
|
578 |
|
579 const TInt validMargin = aSize.iHeight * 12 / 100; |
|
580 |
|
581 const TInt Ha = aSize.iHeight; |
|
582 TInt hTa = 0; |
|
583 TInt hNT = 0; |
|
584 TInt C = 0; |
|
585 TInt hNTN = Ha - 2.0 * 0.12 * Ha; |
|
586 TReal R = 1.0; |
|
587 TInt HaN = Ha; |
|
588 |
|
589 const TInt lastColumn = aSize.iHeight - 1; |
|
590 for ( TInt curRow = 0; curRow < validMargin; curRow++ ) |
|
591 { |
|
592 const TInt y = (aSize.iHeight - 1) - curRow; // h - 1 is the last line |
|
593 |
|
594 vgGetImageSubData(aVgImage, ptr, sizeof(TUint)*aSize.iWidth, VG_sRGBA_8888_PRE, 0, y, aSize.iWidth, 1); |
|
595 |
|
596 for ( TInt s = lastColumn; s >= 0; --s ) |
|
597 { |
|
598 if ( ptr[s] & 0x000000FF ) |
|
599 { |
|
600 hTa = curRow; |
|
601 hNT = Ha - 2 * hTa; |
|
602 C = 2 * hTa; |
|
603 R = ( ( (TReal)hNTN / (TReal)hNT ) > 1.0 ) ? 1 : (TReal)hNTN / (TReal)hNT; |
|
604 HaN = Ha * R - C * R + C; |
|
605 curRow = validMargin; // to exit the outer loop |
|
606 break; // to exit the inner |
|
607 } |
|
608 |
|
609 } |
|
610 } |
|
611 |
|
612 delete buf; |
|
613 |
|
614 if(aSize.iHeight > HaN) |
|
615 { |
|
616 |
|
617 VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; |
|
618 |
|
619 vgSetfv(VG_CLEAR_COLOR, 4, color); |
|
620 vgClear(0, 0, aSize.iWidth,aSize.iHeight); |
|
621 |
|
622 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); |
|
623 VGfloat Hr = (VGfloat)HaN/(aSize.iHeight); |
|
624 |
|
625 TInt WaN = aSize.iWidth*Hr; |
|
626 |
|
627 VGfloat Tx = (aSize.iHeight-HaN)/2; |
|
628 VGfloat Ty = (aSize.iWidth-WaN)/2; |
|
629 vgTranslate(Tx,Ty); |
|
630 |
|
631 return( TSize(HaN,WaN)); |
|
632 } |
|
633 return aSize; |
|
634 |
|
635 } |
|
636 |
|
637 |
|
638 |
|
639 TInt CSvgtFbsRasterizer::MapOpenVgErrorCodeToSymbian(TInt aErrorCode) |
|
640 { |
|
641 switch( aErrorCode ) |
|
642 { |
|
643 case VGI_OK: |
|
644 return KErrNone; |
|
645 |
|
646 case VGI_ERROR_OUT_OF_MEMORY: |
|
647 return KErrNoMemory; |
|
648 |
|
649 case VGI_ERROR_INVALID_ARGUMENTS: |
|
650 return KErrArgument; |
|
651 |
|
652 case VGI_ERROR_ALREADY_EXISTS: |
|
653 return KErrAlreadyExists; |
|
654 |
|
655 case VGI_ERROR_COLORSPACE_NOT_SUPPORTED: |
|
656 return KErrNotSupported; |
|
657 |
|
658 case VGI_ERROR_NOT_SUPPORTED: |
|
659 return KErrNotSupported; |
|
660 |
|
661 case VGI_ERROR_ILLEGAL_IMAGE_HANDLE: |
|
662 return KErrBadHandle; |
|
663 |
|
664 case VGI_ERROR_IMAGE_IN_USE: |
|
665 return KErrInUse; |
|
666 |
|
667 case VGI_ERROR_ILLEGAL_OPERATION: |
|
668 return KErrPermissionDenied; |
|
669 |
|
670 default: |
|
671 return KErrUnknown; |
|
672 } |
|
673 |
|
674 } |
|
675 |