|
1 /* |
|
2 * Copyright (c) 2006-2007 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: Abstract base class for format converters. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "TMIDFormatConverter.h" |
|
22 #include "TMIDGray1.h" |
|
23 #include <fbs.h> |
|
24 |
|
25 namespace |
|
26 { |
|
27 const TInt KAnchorHCenter = 1; |
|
28 const TInt KAnchorVCenter = 2; |
|
29 const TInt KAnchorRight = 8; |
|
30 const TInt KAnchorBottom = 32; |
|
31 const TInt KScanLengthOffset = 31; |
|
32 const TInt KScanLengthDivider = 32; |
|
33 } |
|
34 |
|
35 TMIDFormatConverter::TMIDFormatConverter() |
|
36 { |
|
37 iTransformer = TMIDTransformer(); |
|
38 iBitmapRect = TRect(); |
|
39 iOffset = 0; |
|
40 iScanlength = 0; |
|
41 iAlphaBitmap = NULL; |
|
42 iAlphaMode = ENone; |
|
43 iTransparency = ETrue; |
|
44 } |
|
45 |
|
46 void TMIDFormatConverter::InitializeL(const TMIDBitmapParameters& aParameters) |
|
47 { |
|
48 iOffset = aParameters.iOffset; |
|
49 iScanlength = aParameters.iScanLength; |
|
50 iAlphaBitmap = aParameters.iAlpha; |
|
51 iAlphaMode = aParameters.iAlphaMode; |
|
52 iTransparency = aParameters.iTransparency; |
|
53 |
|
54 switch (iAlphaMode) |
|
55 { |
|
56 case EGray2: |
|
57 { |
|
58 iAlphaScanLength = ((aParameters.iWidth + KScanLengthOffset) / |
|
59 KScanLengthDivider); |
|
60 |
|
61 break; |
|
62 } |
|
63 default: |
|
64 { |
|
65 if (iAlphaBitmap) |
|
66 { |
|
67 iAlphaScanLength = aParameters.iBitmap->ScanLineLength( |
|
68 aParameters.iWidth, iAlphaMode); |
|
69 } |
|
70 } |
|
71 } |
|
72 |
|
73 TInt lastPixel = iScanlength * (aParameters.iHeight - 1) + |
|
74 aParameters.iWidth - 1 + iOffset; |
|
75 |
|
76 // checking that bitmap is big enough |
|
77 if (iOffset < 0 || |
|
78 !CheckSize(aParameters.iPixelsSize, lastPixel)) |
|
79 { |
|
80 // out of bounds |
|
81 User::Leave(KErrArrayIndexOutOfBoundsException); |
|
82 } |
|
83 |
|
84 // checking alpha size |
|
85 if (iAlphaBitmap) |
|
86 { |
|
87 if (((iAlphaMode == EGray256) && |
|
88 (aParameters.iAlphaSize < |
|
89 (aParameters.iHeight * aParameters.iWidth + iOffset))) || |
|
90 ((iAlphaMode == EGray2) && |
|
91 (aParameters.iAlphaSize < |
|
92 (aParameters.iHeight * (aParameters.iWidth >> KMIDShift3Bits) |
|
93 + iOffset))) || |
|
94 ((iAlphaMode != EGray256) && (iAlphaMode != EGray2) && |
|
95 (!CheckSize(aParameters.iAlphaSize, lastPixel)))) |
|
96 { |
|
97 // out of bounds |
|
98 User::Leave(KErrArrayIndexOutOfBoundsException); |
|
99 } |
|
100 } |
|
101 |
|
102 |
|
103 iBitmapRect = TRect(aParameters.iX, aParameters.iY, |
|
104 aParameters.iX + aParameters.iWidth, |
|
105 aParameters.iY + aParameters.iHeight); |
|
106 |
|
107 // initializing transformer, this will only rotate |
|
108 iTransformer.Transform(iBitmapRect, aParameters.iManipulation); |
|
109 |
|
110 // calculating new position from anchor point |
|
111 if (aParameters.iAnchor != 0) |
|
112 { |
|
113 if (aParameters.iAnchor & KAnchorRight) |
|
114 { |
|
115 iBitmapRect.Move(-iBitmapRect.Width(), 0); |
|
116 } |
|
117 if (aParameters.iAnchor & KAnchorBottom) |
|
118 { |
|
119 iBitmapRect.Move(0, -iBitmapRect.Height()); |
|
120 } |
|
121 if (aParameters.iAnchor & KAnchorHCenter) |
|
122 { |
|
123 iBitmapRect.Move(-(iBitmapRect.Width() >> 1), 0); |
|
124 } |
|
125 if (aParameters.iAnchor & KAnchorVCenter) |
|
126 { |
|
127 iBitmapRect.Move(0, -(iBitmapRect.Height() >> 1)); |
|
128 } |
|
129 } |
|
130 |
|
131 |
|
132 // second phase of initialization, this will do actual initalization of directions |
|
133 // for both flip and rotate. Movement value is for changing starting position if out |
|
134 // of clipping rect. |
|
135 TPoint move(0, 0); |
|
136 if (iBitmapRect.iTl.iX < aParameters.iClipRect.iTl.iX) |
|
137 { |
|
138 move.iX = aParameters.iClipRect.iTl.iX - iBitmapRect.iTl.iX; |
|
139 } |
|
140 if (iBitmapRect.iTl.iY < aParameters.iClipRect.iTl.iY) |
|
141 { |
|
142 move.iY = aParameters.iClipRect.iTl.iY - iBitmapRect.iTl.iY; |
|
143 } |
|
144 |
|
145 // This will rotate and flip bitmap, returns error code if manipulation is |
|
146 // invalid |
|
147 User::LeaveIfError(iTransformer.Transform(move)); |
|
148 |
|
149 // calculating possible new size after clipping |
|
150 iBitmapRect.Intersection(aParameters.iClipRect); |
|
151 if (iBitmapRect.IsEmpty()) |
|
152 { |
|
153 // we are not in clipping rect, cancelling the drawing |
|
154 return; |
|
155 } |
|
156 |
|
157 // iTransformers moves are two dimensional moves with following combinations |
|
158 // x-move y-move |
|
159 // (1, 0) (0, 1) Default (no rotations or flips) |
|
160 // (1, 0) (0,-1) |
|
161 // (-1,0) (0, 1) |
|
162 // (-1,0) (0,-1) |
|
163 // (0, 1) (1, 0) |
|
164 // (0, 1) (-1,0) |
|
165 // (0,-1) (1, 0) |
|
166 // (0,-1) (-1,0) |
|
167 |
|
168 // So precalculating moves |
|
169 |
|
170 // going right or left when advancing y |
|
171 // x(y) y(x) |
|
172 //(1) (1) -scan * (height - 1) + 1 |
|
173 //(1) (-1) -scan * (height - 1) - 1 |
|
174 //(-1) (1) scan * (height - 1) + 1 |
|
175 //(-1) (-1) scan * (height - 1) - 1 |
|
176 if (iTransformer.iYMove.iX != 0) |
|
177 { |
|
178 iTransformer.iYMove.iX += (-(iTransformer.iXMove.iY) * iScanlength) * |
|
179 (iBitmapRect.Width() - 1); |
|
180 } |
|
181 |
|
182 // going up or down when advancing x |
|
183 iTransformer.iXMove.iY *= iScanlength; |
|
184 |
|
185 // going up or down (default) when advancing y |
|
186 // x y |
|
187 //(1) (1) scan - width + 1 |
|
188 //(-1) (1) scan + width - 1 |
|
189 //(1) (-1) -scan - width + 1 |
|
190 //(-1) (-1) -scan + width - 1 |
|
191 iTransformer.iYMove.iY = iTransformer.iYMove.iY * iScanlength - |
|
192 (iTransformer.iXMove.iX * iBitmapRect.Width()) + iTransformer.iXMove.iX; |
|
193 |
|
194 // combine x & y to one value |
|
195 iTransformer.iXMove.iX += iTransformer.iXMove.iY; |
|
196 iTransformer.iYMove.iX += iTransformer.iYMove.iY; |
|
197 } |
|
198 |
|
199 |
|
200 void TMIDFormatConverter::GetPixelWithAlpha(TMIDInternalARGB& aResult) const |
|
201 { |
|
202 GetPixel(aResult); |
|
203 switch (iAlphaMode) |
|
204 { |
|
205 case(EGray256): |
|
206 { |
|
207 TInt line = iOffset / iScanlength; |
|
208 TInt column = iOffset % iScanlength; |
|
209 aResult.iA = |
|
210 ((TUint8*)iAlphaBitmap)[ line * iAlphaScanLength + column ]; // CSI: 2 Wrong index means implementation error # |
|
211 break; |
|
212 } |
|
213 case(EGray2): |
|
214 { |
|
215 TInt line = iOffset / iScanlength; |
|
216 TInt column = iOffset % iScanlength; |
|
217 TInt word = line * iAlphaScanLength + (column >> KMIDShift5Bits); |
|
218 aResult.iA = (((((TUint32*)iAlphaBitmap)[ word ] >> // CSI: 2 Wrong index means implementation error # |
|
219 (column % KScanLengthDivider)) & 1) * KAlphaFullOpaque); |
|
220 |
|
221 break; |
|
222 } |
|
223 default: |
|
224 { |
|
225 aResult.iA = GetAlpha(); |
|
226 } |
|
227 } |
|
228 } |
|
229 |
|
230 void TMIDFormatConverter::PlotPixelWithAlpha(const TMIDInternalARGB& aInternal) |
|
231 { |
|
232 PlotPixel(aInternal); |
|
233 |
|
234 // modifying alpha channel |
|
235 if (iAlphaBitmap) |
|
236 { |
|
237 switch (iAlphaMode) |
|
238 { |
|
239 case(EGray256): |
|
240 { |
|
241 TInt line = iOffset / iScanlength; |
|
242 TInt column = iOffset % iScanlength; |
|
243 ((TUint8*)iAlphaBitmap)[ line * iAlphaScanLength + column ] = // CSI: 2 Wrong index means implementation error # |
|
244 aInternal.iA; |
|
245 break; |
|
246 } |
|
247 case(EGray2): |
|
248 { |
|
249 TInt line = iOffset / iScanlength; |
|
250 TInt column = iOffset % iScanlength; |
|
251 TInt word = line * iAlphaScanLength + (column >> KMIDShift5Bits); |
|
252 if ((aInternal.iR + aInternal.iG + aInternal.iB) < |
|
253 KWhiteBlackSumRGBMidValue) |
|
254 { |
|
255 iAlphaBitmap[ word ] = (TUint32)(iAlphaBitmap[ word ] | // CSI: 2 Wrong offset means implementation error # |
|
256 KBits32[ column % KScanLengthDivider ]); // CSI: 2 Wrong index means implementation error # |
|
257 } |
|
258 else |
|
259 { |
|
260 iAlphaBitmap[ word ] = (TUint32)(iAlphaBitmap[ word ] & // CSI: 2 Wrong offset means implementation error # |
|
261 ~KBits32[ column % KScanLengthDivider ]); // CSI: 2 Wrong index means implementation error # |
|
262 } |
|
263 } |
|
264 default: |
|
265 { |
|
266 // otherwise we have same format as normal bitmap |
|
267 // getting real bitmap from converter |
|
268 TUint32* tempBitmap = Bitmap(); |
|
269 SetBitmap(iAlphaBitmap); |
|
270 |
|
271 // It must be either white or black |
|
272 TMIDInternalARGB alphaIn; |
|
273 if (aInternal.iA == KAlphaFullOpaque) |
|
274 { |
|
275 alphaIn = KOpaque; |
|
276 } |
|
277 PlotPixel(alphaIn); |
|
278 |
|
279 // reverting to original bitmap |
|
280 SetBitmap(tempBitmap); |
|
281 } |
|
282 } |
|
283 } |
|
284 } |
|
285 |
|
286 TBool TMIDFormatConverter::IsAlpha() |
|
287 { |
|
288 |
|
289 if (iAlphaBitmap) |
|
290 { |
|
291 return ETrue; |
|
292 } |
|
293 return EFalse; |
|
294 } |