|
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: Implements a brush that is able to draw images. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "uiacceltk/HuiImageBrush.h" // Class definition |
|
21 #include "uiacceltk/HuiDrawing.h" |
|
22 #include "uiacceltk/HuiVisual.h" |
|
23 #include "uiacceltk/HuiUtil.h" |
|
24 |
|
25 |
|
26 EXPORT_C CHuiImageBrush* |
|
27 CHuiImageBrush::NewL(const THuiImage & aImage) |
|
28 { |
|
29 CHuiImageBrush* self = NewLC(aImage); |
|
30 CleanupStack::Pop(); |
|
31 return self; |
|
32 } |
|
33 |
|
34 |
|
35 EXPORT_C CHuiImageBrush* CHuiImageBrush::NewLC(const THuiImage & aImage) |
|
36 { |
|
37 CHuiImageBrush* self = new (ELeave) CHuiImageBrush(aImage); |
|
38 CleanupStack::PushL(self); |
|
39 return self; |
|
40 } |
|
41 |
|
42 |
|
43 CHuiImageBrush::CHuiImageBrush(const THuiImage & aImage) |
|
44 : iImage(aImage), |
|
45 iScaleMode(CHuiImageVisual::EScaleFit), |
|
46 iLeftBorderWidth(0), |
|
47 iRightBorderWidth(0), |
|
48 iTopBorderWidth(0), |
|
49 iBottomBorderWidth(0) |
|
50 |
|
51 { |
|
52 SetClipToVisual(EFalse); |
|
53 iScale.Set(1.f); |
|
54 iImageOffset.iX.Set(0.f); |
|
55 iImageOffset.iY.Set(0.f); |
|
56 } |
|
57 |
|
58 EXPORT_C CHuiImageBrush::~CHuiImageBrush() |
|
59 { |
|
60 } |
|
61 |
|
62 EXPORT_C void CHuiImageBrush::SetScaleMode( |
|
63 CHuiImageVisual::TScaleMode aScaleMode) |
|
64 { |
|
65 iScaleMode = aScaleMode; |
|
66 SetChanged(); |
|
67 } |
|
68 |
|
69 EXPORT_C void CHuiImageBrush::SetImage(const THuiImage& aImage) |
|
70 { |
|
71 iImage = aImage; |
|
72 SetChanged(); |
|
73 } |
|
74 |
|
75 EXPORT_C const THuiImage& CHuiImageBrush::Image() const |
|
76 { |
|
77 return iImage; |
|
78 } |
|
79 |
|
80 |
|
81 EXPORT_C void CHuiImageBrush::SetBorders(TInt aLeftBorderPixels, |
|
82 TInt aRightBorderPixels, |
|
83 TInt aTopBorderPixels, |
|
84 TInt aBottomBorderPixels) |
|
85 { |
|
86 iLeftBorderWidth = aLeftBorderPixels; |
|
87 iRightBorderWidth = aRightBorderPixels; |
|
88 iTopBorderWidth = aTopBorderPixels; |
|
89 iBottomBorderWidth = aBottomBorderPixels; |
|
90 SetChanged(); |
|
91 } |
|
92 |
|
93 EXPORT_C TBool CHuiImageBrush::BorderDrawingEnabled() const |
|
94 { |
|
95 return ((iLeftBorderWidth!=0) || (iRightBorderWidth!=0) |
|
96 || (iTopBorderWidth!=0) || (iBottomBorderWidth!=0)); |
|
97 } |
|
98 |
|
99 EXPORT_C TBool CHuiImageBrush::CenterDrawingEnabled() const |
|
100 { |
|
101 if(!iImage.HasTexture()) |
|
102 { |
|
103 return EFalse; |
|
104 } |
|
105 // determine if there are center pixels available inside borders |
|
106 // if not, we can't draw the center.. |
|
107 TSize imageSize = iImage.Texture().Size(); |
|
108 if(((imageSize.iWidth - iLeftBorderWidth) - iRightBorderWidth <= 0) |
|
109 || ((imageSize.iHeight - iTopBorderWidth) - iBottomBorderWidth <= 0)) |
|
110 { |
|
111 return EFalse; |
|
112 } |
|
113 |
|
114 return ETrue; |
|
115 } |
|
116 |
|
117 EXPORT_C void CHuiImageBrush::ExpandVisualRect(TRect& aRect) const |
|
118 { |
|
119 if ( CenterDrawingEnabled() ) |
|
120 { |
|
121 THuiRealRect contentArea(aRect); |
|
122 |
|
123 // Get the scaled size |
|
124 THuiRealSize imageSize( iImage.Texture().Size() ); |
|
125 if ( iScaleMode == CHuiImageVisual::EScaleFit ) |
|
126 { |
|
127 imageSize = contentArea.Size() * iScale.Now(); |
|
128 } |
|
129 else |
|
130 { |
|
131 TReal32 scale = HuiUtil::CalculateScaleFactorFromScaleMode( |
|
132 contentArea.Size(), |
|
133 iImage.Texture().Size(), |
|
134 iScaleMode, |
|
135 iScale.Now() ); |
|
136 imageSize = imageSize * scale; |
|
137 } |
|
138 |
|
139 THuiRealPoint mid = contentArea.Center(); |
|
140 |
|
141 // Move mid point based on the offset |
|
142 TReal32 xOffset = 0; |
|
143 TReal32 yOffset = 0; |
|
144 |
|
145 xOffset = contentArea.Width() * iImageOffset.iX.Now(); |
|
146 yOffset = contentArea.Height() * iImageOffset.iY.Now(); |
|
147 |
|
148 mid += THuiRealPoint( xOffset, yOffset ); |
|
149 |
|
150 // expand the dirty area rect if needed |
|
151 aRect.iTl.iX = Min( aRect.iTl.iX, mid.iX-imageSize.iWidth/2.f ); |
|
152 aRect.iTl.iY = Min( aRect.iTl.iY, mid.iY-imageSize.iHeight/2.f ); |
|
153 aRect.iBr.iX = Max( aRect.iBr.iX, mid.iX+imageSize.iWidth/2.f ); |
|
154 aRect.iBr.iY = Max( aRect.iBr.iY, mid.iY+imageSize.iHeight/2.f ); |
|
155 } |
|
156 |
|
157 if(BorderDrawingEnabled()) |
|
158 { |
|
159 // expand the area of the content to include the border: |
|
160 aRect.Grow((Max(iLeftBorderWidth, 0) + Max(iRightBorderWidth, 0)) / 2, |
|
161 (Max(iTopBorderWidth, 0) + Max(iBottomBorderWidth, 0)) / 2); |
|
162 // move the area to justify the border width differencies |
|
163 aRect.Move((Max(iRightBorderWidth, 0)-Max(iLeftBorderWidth, 0)) / 2, |
|
164 (Max(iTopBorderWidth, 0)-Max(iBottomBorderWidth, 0)) / 2); |
|
165 } |
|
166 } |
|
167 |
|
168 TBool CHuiImageBrush::Changed() const |
|
169 { |
|
170 if ( CHuiBrush::Changed() ) |
|
171 { |
|
172 return ETrue; |
|
173 } |
|
174 return iImageOffset.Changed() || iScale.Changed() || iImage.Changed(); |
|
175 } |
|
176 |
|
177 void CHuiImageBrush::ClearChanged() |
|
178 { |
|
179 CHuiBrush::ClearChanged(); |
|
180 iImageOffset.ClearChanged(); |
|
181 iScale.ClearChanged(); |
|
182 iImage.ClearChanged(); |
|
183 } |
|
184 |
|
185 EXPORT_C void CHuiImageBrush::Draw(CHuiGc& aGc, const MHuiBrushGuide& aGuide) const |
|
186 { |
|
187 |
|
188 TBool borderDrawing = BorderDrawingEnabled(); |
|
189 TBool centerDrawing = CenterDrawingEnabled(); |
|
190 |
|
191 TReal32 opacity = aGuide.BrushOpacity() * iOpacity.Now(); |
|
192 aGc.SetPenColor(KRgbWhite); |
|
193 aGc.SetPenAlpha(TInt(opacity * 255.f)); |
|
194 |
|
195 if(centerDrawing) |
|
196 { |
|
197 THuiRealRect contentArea = aGuide.BrushRect(); |
|
198 |
|
199 aGc.Enable(CHuiGc::EFeatureBlending); |
|
200 |
|
201 if(borderDrawing) |
|
202 { |
|
203 // contract the content area if the borders |
|
204 // have been defined to be inside |
|
205 if(iLeftBorderWidth < 0) |
|
206 { |
|
207 contentArea.iTl.iX -= iLeftBorderWidth; |
|
208 } |
|
209 if(iRightBorderWidth < 0) |
|
210 { |
|
211 contentArea.iBr.iX += iRightBorderWidth; |
|
212 } |
|
213 if(iTopBorderWidth < 0) |
|
214 { |
|
215 contentArea.iTl.iY -= iTopBorderWidth; |
|
216 } |
|
217 if(iBottomBorderWidth < 0) |
|
218 { |
|
219 contentArea.iBr.iY += iBottomBorderWidth; |
|
220 } |
|
221 |
|
222 // Read in the original texture coordinates (NOTE: not affected |
|
223 // by any renderer-specific texcoord manipulations, like the Gles POT trick). |
|
224 TSize imageSize(iImage.Texture().Size()); |
|
225 THuiRealPoint tl = iImage.TopLeft(), br = iImage.BottomRight(); |
|
226 TReal32 widthU = br.iX - tl.iX; |
|
227 TReal32 heightV = br.iY - tl.iY; |
|
228 |
|
229 // Remove borders by adjusting texture coordinates. |
|
230 // But don't divide by 0 |
|
231 if ( imageSize.iWidth != 0 && imageSize.iHeight != 0 ) |
|
232 { |
|
233 tl.iX += ((TReal32)Abs(iLeftBorderWidth) / (TReal32)imageSize.iWidth) * widthU; |
|
234 br.iX -= ((TReal32)Abs(iRightBorderWidth) / (TReal32)imageSize.iWidth) * widthU; |
|
235 tl.iY += ((TReal32)Abs(iTopBorderWidth) / (TReal32)imageSize.iHeight) * heightV; |
|
236 br.iY -= ((TReal32)Abs(iBottomBorderWidth) / (TReal32)imageSize.iHeight) * heightV; |
|
237 } |
|
238 |
|
239 // Create temporary Image with adjusted texcoords |
|
240 THuiImage imageBordersRemoved; |
|
241 imageBordersRemoved.SetTexture(iImage.TextureIf()); |
|
242 imageBordersRemoved.SetTexCoords(tl.iX, tl.iY, br.iX, br.iY); |
|
243 |
|
244 // Draw the image without the borders. |
|
245 aGc.DrawStretchImage(CHuiGc::EStretchFull, |
|
246 imageBordersRemoved, |
|
247 contentArea); |
|
248 } |
|
249 else |
|
250 { |
|
251 |
|
252 TReal32 scale = HuiUtil::CalculateScaleFactorFromScaleMode( |
|
253 contentArea.Size(), |
|
254 iImage.Texture().Size(), |
|
255 iScaleMode, |
|
256 iScale.Now() ); |
|
257 |
|
258 // Determine offset. |
|
259 TReal32 xOffset = 0; |
|
260 TReal32 yOffset = 0; |
|
261 |
|
262 xOffset = aGuide.BrushRect().Width() * iImageOffset.iX.Now(); |
|
263 yOffset = aGuide.BrushRect().Height() * iImageOffset.iY.Now(); |
|
264 |
|
265 |
|
266 // Do scaling |
|
267 TBool doTranslate = !HuiUtil::RealCompare( scale, 1.f ) || !HuiUtil::RealCompare(xOffset,0.f) || !HuiUtil::RealCompare(yOffset,0.f); |
|
268 if( doTranslate ) |
|
269 { |
|
270 /** @todo GC must provide some support for transformations. */ |
|
271 aGc.Push(EHuiGcMatrixModel); |
|
272 |
|
273 // Rotate around the midpoint of the visual. |
|
274 THuiRealPoint mid = contentArea.Center(); |
|
275 |
|
276 aGc.Translate(EHuiGcMatrixModel, mid.iX + xOffset, mid.iY + yOffset, 0.f); |
|
277 if( !HuiUtil::RealCompare( scale, 1.f ) ) |
|
278 { |
|
279 aGc.Scale(EHuiGcMatrixModel, scale, scale, 1.f); |
|
280 } |
|
281 aGc.Translate(EHuiGcMatrixModel, -mid.iX, -mid.iY, 0.f); |
|
282 } |
|
283 |
|
284 // Use the appropriate alignment in the graphics context. |
|
285 if(iScaleMode == CHuiImageVisual::EScaleFit) |
|
286 { |
|
287 aGc.SetAlign(EHuiAlignHLeft, EHuiAlignVTop); |
|
288 } |
|
289 else |
|
290 { |
|
291 aGc.SetAlign(EHuiAlignHCenter, EHuiAlignVCenter); |
|
292 } |
|
293 |
|
294 // draw the image |
|
295 if(iScaleMode == CHuiImageVisual::EScaleFit) |
|
296 { |
|
297 aGc.DrawImage(iImage, contentArea.iTl, contentArea.Size()); |
|
298 } |
|
299 else |
|
300 { |
|
301 aGc.DrawImage(iImage, contentArea); |
|
302 } |
|
303 |
|
304 // Restore original transformation. |
|
305 if( doTranslate ) |
|
306 { |
|
307 aGc.Pop(EHuiGcMatrixModel); |
|
308 } |
|
309 |
|
310 } |
|
311 |
|
312 } |
|
313 |
|
314 if(borderDrawing) |
|
315 { |
|
316 THuiRealRect contentArea = aGuide.BrushRect(); |
|
317 |
|
318 // expand the area of the content to include the border: |
|
319 contentArea.Grow((Max(iLeftBorderWidth, 0) + Max(iRightBorderWidth, 0)) / 2, |
|
320 (Max(iTopBorderWidth, 0) + Max(iBottomBorderWidth, 0)) / 2); |
|
321 // move the area to justify the border width differencies |
|
322 contentArea.Move((Max(iRightBorderWidth, 0)-Max(iLeftBorderWidth, 0)) / 2, |
|
323 (Max(iTopBorderWidth, 0)-Max(iBottomBorderWidth, 0)) / 2); |
|
324 |
|
325 aGc.DrawBorders(contentArea.Round(), |
|
326 Abs(iLeftBorderWidth), |
|
327 Abs(iRightBorderWidth), |
|
328 Abs(iTopBorderWidth), |
|
329 Abs(iBottomBorderWidth), |
|
330 CHuiGc::EBorderFixedCorners, |
|
331 &iImage); |
|
332 } |
|
333 |
|
334 } |