|
1 /* |
|
2 * Copyright (c) 2006-2008 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: OpenVG class for canvas graphics context |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <e32math.h> |
|
19 |
|
20 #include "huivg10canvasgc.h" |
|
21 #include "huicanvasgc.h" |
|
22 #include "HuiVg10Gc.h" |
|
23 #include "uiacceltk/HuiCanvasVisual.h" |
|
24 #include "uiacceltk/HuiSkin.h" |
|
25 #include "uiacceltk/HuiS60Skin.h" |
|
26 #include <uiacceltk/huidisplaybackgrounditem.h> |
|
27 #include "HuiRenderSurface.h" |
|
28 #include "uiacceltk/HuiDisplay.h" |
|
29 #include "uiacceltk/HuiEnv.h" |
|
30 #include "uiacceltk/HuiUtil.h" |
|
31 #ifndef __SERIES60_30__ |
|
32 #include "HuiTargetBitmap.h" |
|
33 #endif |
|
34 |
|
35 #include <AknsRendererWrapper.h> |
|
36 #include <AknsDrawUtils.h> |
|
37 #include <coecntrl.h> |
|
38 #include "huiskinbackroundlayout.h" |
|
39 #include "huivg10canvasrenderbuffer.h" |
|
40 #include "HuiFxVg10.h" |
|
41 |
|
42 CHuiVg10CanvasGc::CHuiVg10CanvasGc() |
|
43 { |
|
44 } |
|
45 |
|
46 CHuiVg10CanvasGc::~CHuiVg10CanvasGc() |
|
47 { |
|
48 } |
|
49 |
|
50 void CHuiVg10CanvasGc::DoDrawPolygon(RArray<THuiRealPoint>& aPoints) |
|
51 { |
|
52 if(iPolygonDrawMode == EHuiNoFill) |
|
53 { |
|
54 CHuiCanvasGc::DoDrawPolygon(aPoints); |
|
55 } |
|
56 else |
|
57 { |
|
58 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
59 vg10Gc->SetFillRule( iPolygonDrawMode ); |
|
60 vg10Gc->SetPaintPattern(iPolygonFillTexture, iPolygonFillTextureOrigin); |
|
61 vg10Gc->DrawPolygon(aPoints); |
|
62 vg10Gc->SetPaintPattern(NULL, iPolygonFillTextureOrigin); |
|
63 } |
|
64 } |
|
65 |
|
66 void CHuiVg10CanvasGc::DoDrawArc(const THuiRealRect& aDestinationRect, |
|
67 const THuiRealPoint& aStart, const THuiRealPoint& aEnd) |
|
68 { |
|
69 DoDrawPieAndArc( aDestinationRect, aStart, aEnd, EFalse); |
|
70 } |
|
71 |
|
72 void CHuiVg10CanvasGc::DoDrawPie(const THuiRealRect& aDestinationRect, |
|
73 const THuiRealPoint& aStart, const THuiRealPoint& aEnd) |
|
74 { |
|
75 DoDrawPieAndArc( aDestinationRect, aStart, aEnd, ETrue); |
|
76 } |
|
77 |
|
78 |
|
79 void CHuiVg10CanvasGc::DoDrawPieAndArc(const THuiRealRect& aDestinationRect, |
|
80 const THuiRealPoint& aStart, const THuiRealPoint& aEnd, TBool aIsPie) |
|
81 { |
|
82 THuiRealRect destinationRect = aDestinationRect; |
|
83 destinationRect.Shrink(0.5f, 0.5f); |
|
84 THuiRealPoint center = destinationRect.Center(); |
|
85 |
|
86 // Ok, explaining this is not going to be easy. So, please pay attention! |
|
87 // |
|
88 // Symbian Window Gc DrawArc() method always draws an arc anti-clockwise, from start angle |
|
89 // to end angle. As y-axis in Window GC point downwards, the angle grows towards *negative* |
|
90 // direction, if we go anti-clockwise. To be able to make calculations later we have to make |
|
91 // sure both the start and end angles are negative. |
|
92 // |
|
93 TReal startAngle = 0; |
|
94 Math::ATan(startAngle, aStart.iY - center.iY, aStart.iX - center.iX); |
|
95 startAngle = (startAngle*180)/KPi; |
|
96 // make sure this is negative angle |
|
97 if (startAngle > - 0.000001) |
|
98 { |
|
99 startAngle -= 360.0; |
|
100 } |
|
101 |
|
102 TReal endAngle = 0; |
|
103 Math::ATan(endAngle, aEnd.iY - center.iY, aEnd.iX - center.iX); |
|
104 endAngle = (endAngle*180)/KPi; |
|
105 // make sure this is negative angle |
|
106 if (endAngle > - 0.000001) |
|
107 { |
|
108 endAngle -= 360.0; |
|
109 } |
|
110 |
|
111 // Make a full circle if the end and start angles are equal |
|
112 if ( Abs(endAngle-startAngle) < 0.000001) |
|
113 { |
|
114 endAngle -= 360.0; |
|
115 } |
|
116 |
|
117 // Organize angles so that we go from start to end angle anti-clockwise, i.e. towards negative direction |
|
118 if ( endAngle > startAngle ) |
|
119 { |
|
120 endAngle -= 360; |
|
121 } |
|
122 |
|
123 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
124 vg10Gc->SetPaintPattern(iPolygonFillTexture, iPolygonFillTextureOrigin); |
|
125 vg10Gc->DrawArc(aDestinationRect.Round(), iPolygonDrawMode, iPenWidth, startAngle, endAngle, aIsPie); |
|
126 vg10Gc->SetPaintPattern(NULL, iPolygonFillTextureOrigin); |
|
127 } |
|
128 |
|
129 void CHuiVg10CanvasGc::DoDrawRoundRect(const THuiRealRect& aDestinationRect, const THuiRealSize& aSize) |
|
130 { |
|
131 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
132 vg10Gc->SetPaintPattern(iPolygonFillTexture, iPolygonFillTextureOrigin); |
|
133 vg10Gc->DrawRoundRect(aDestinationRect.Round(), aSize, iPolygonDrawMode, iPenWidth); |
|
134 vg10Gc->SetPaintPattern(NULL, iPolygonFillTextureOrigin); |
|
135 } |
|
136 |
|
137 void CHuiVg10CanvasGc::ClearWithSkinBackground(const THuiRealRect& /*aRect*/) |
|
138 { |
|
139 if (!iGc) |
|
140 { |
|
141 return; |
|
142 } |
|
143 |
|
144 // Acquire background texture |
|
145 const CHuiTexture* backgroundTexture = NULL; |
|
146 TInt err = CHuiStatic::Env().Skin().GetTexture(EHuiSkinBackgroundTexture, backgroundTexture); |
|
147 ASSERT(backgroundTexture!=NULL); |
|
148 __ASSERT_ALWAYS(err == KErrNone, User::Invariant()); |
|
149 |
|
150 // Apply background texture |
|
151 THuiImage background(*backgroundTexture); |
|
152 |
|
153 TPoint screenOrigin(0, 0); |
|
154 CHuiStatic::CurrentRenderSurface()->GetScreenOrigin(screenOrigin); |
|
155 // The origin is used to offset the background in the display's |
|
156 // rendering surface, so that the background's origin is in the |
|
157 // top left screen corner. |
|
158 screenOrigin.iX = -screenOrigin.iX; |
|
159 screenOrigin.iY = -screenOrigin.iY; |
|
160 |
|
161 iGc->SetPenColor(KRgbWhite); |
|
162 iGc->SetPenAlpha(255); |
|
163 iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop); |
|
164 iGc->Disable(CHuiGc::EFeatureBlending); |
|
165 iGc->Disable(CHuiGc::EFeatureClipping); |
|
166 iGc->DrawImage(background, screenOrigin, background.Texture().Size()); |
|
167 iGc->Enable(CHuiGc::EFeatureBlending); |
|
168 iGc->Enable(CHuiGc::EFeatureClipping); |
|
169 } |
|
170 |
|
171 void CHuiVg10CanvasGc::ClearWithBackgroundItems(const THuiRealRect& /*aRect*/, const RArray<THuiDisplayBackgroundItem>& aItems) |
|
172 { |
|
173 if (!iGc) |
|
174 return; |
|
175 |
|
176 THuiDisplayBackgroundItem item; |
|
177 CHuiS60Skin* s60skin = static_cast<CHuiS60Skin*>(&CHuiStatic::Env().Skin()); |
|
178 CHuiTexture* backgroundTexture = NULL; |
|
179 |
|
180 for (TInt index = 0; index < aItems.Count(); index++) |
|
181 { |
|
182 item = aItems[index]; |
|
183 switch (item.ClearMode()) |
|
184 { |
|
185 case CHuiDisplay::EClearNone: |
|
186 // do nothing... |
|
187 break; |
|
188 case CHuiDisplay::EClearWithColor: |
|
189 iGc->SetPenColor(item.Color()); |
|
190 iGc->SetPenAlpha(TInt(item.Color().Alpha() * 255)); |
|
191 iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop); |
|
192 iGc->Disable(CHuiGc::EFeatureBlending); |
|
193 iGc->Enable(CHuiGc::EFeatureClipping); |
|
194 iGc->PushClip(); |
|
195 iGc->Clip(item.Rect()); // takes transformations into account |
|
196 iGc->Clear(); |
|
197 iGc->PopClip(); |
|
198 break; |
|
199 case CHuiDisplay::EClearWithSkinBackground: |
|
200 TRect skinRect; |
|
201 TRect dummy; |
|
202 GetRectForItem(item.SkinBackground(), dummy, skinRect); |
|
203 backgroundTexture = s60skin->BackgroundTexture(item.SkinBackground()); |
|
204 if (backgroundTexture) |
|
205 { |
|
206 THuiImage background(*backgroundTexture); |
|
207 |
|
208 TPoint screenOrigin(0, 0); |
|
209 CHuiStatic::CurrentRenderSurface()->GetScreenOrigin(screenOrigin); |
|
210 screenOrigin.iX = -screenOrigin.iX; |
|
211 screenOrigin.iY = -screenOrigin.iY; |
|
212 screenOrigin+=skinRect.iTl; |
|
213 iGc->SetPenColor(KRgbWhite); |
|
214 iGc->SetPenAlpha(255); |
|
215 iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop); |
|
216 iGc->Disable(CHuiGc::EFeatureBlending); |
|
217 iGc->Enable(CHuiGc::EFeatureClipping); |
|
218 skinRect.Intersection(item.Rect()); |
|
219 iGc->PushClip(); |
|
220 iGc->Clip(skinRect); // takes transformations into account |
|
221 iGc->DrawImage(background, screenOrigin, background.Texture().Size()); |
|
222 iGc->PopClip(); |
|
223 } |
|
224 break; |
|
225 } |
|
226 } |
|
227 } |
|
228 |
|
229 TInt CHuiVg10CanvasGc::MaxNumberOfClipRects() const |
|
230 { |
|
231 // We could ask this number from OpenVg, but spec says that at least 32 must be supported |
|
232 return 32; |
|
233 } |
|
234 |
|
235 CHuiCanvasRenderBuffer* CHuiVg10CanvasGc::CreateRenderBufferL(const TSize& /*aSize*/) |
|
236 { |
|
237 CHuiVg10CanvasRenderBuffer* buffer = new (ELeave) CHuiVg10CanvasRenderBuffer; |
|
238 return buffer; |
|
239 } |
|
240 |
|
241 void CHuiVg10CanvasGc::DoDrawRenderBuffer(const CHuiCanvasRenderBuffer& aImage, const THuiRealPoint& aDestinationPoint) |
|
242 { |
|
243 const CHuiVg10CanvasRenderBuffer* vg10RenderBuffer = (const CHuiVg10CanvasRenderBuffer*) &aImage; |
|
244 |
|
245 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
246 if (vg10RenderBuffer->Image()) |
|
247 { |
|
248 vg10Gc->UpdateColor(); |
|
249 iGc->Push(EHuiGcMatrixModel); |
|
250 vgTranslate(aDestinationPoint.iX, aDestinationPoint.iY); |
|
251 vgDrawImage(vg10RenderBuffer->Image()); |
|
252 iGc->Pop(EHuiGcMatrixModel); |
|
253 } |
|
254 } |
|
255 |
|
256 void CHuiVg10CanvasGc::DoClearRenderBuffer( CHuiCanvasRenderBuffer& aImage, const TRect & aRect ) |
|
257 { |
|
258 HUIFX_VG_INVARIANT(); |
|
259 const CHuiVg10CanvasRenderBuffer* vg10RenderBuffer = (const CHuiVg10CanvasRenderBuffer*) &aImage; |
|
260 |
|
261 const TInt COLOR_COMPONENTS = 4; |
|
262 VGfloat savedColor[COLOR_COMPONENTS]; |
|
263 vgGetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, savedColor); |
|
264 |
|
265 VGfloat color[COLOR_COMPONENTS] = |
|
266 { |
|
267 0.0f, 0.0f, 0.0f, 0.0f |
|
268 }; |
|
269 vgSetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, color); |
|
270 vgClearImage(vg10RenderBuffer->Image(), aRect.iTl.iX, aRect.iTl.iY, aRect.Size().iWidth, aRect.Size().iHeight); |
|
271 vgSetfv(VG_CLEAR_COLOR, COLOR_COMPONENTS, savedColor); |
|
272 HUIFX_VG_INVARIANT(); |
|
273 } |
|
274 |
|
275 |
|
276 void CHuiVg10CanvasGc::RestoreFlaggedState() const |
|
277 { |
|
278 if (iGc) |
|
279 { |
|
280 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
281 vg10Gc->RestoreFlaggedState(); |
|
282 } |
|
283 } |
|
284 |
|
285 void CHuiVg10CanvasGc::DoDrawRects(RArray<THuiRealRect>& aRects) |
|
286 { |
|
287 if(iPolygonDrawMode == EHuiNoFill) |
|
288 { |
|
289 CHuiCanvasGc::DoDrawRects(aRects); |
|
290 } |
|
291 else |
|
292 { |
|
293 for(TInt i=0; i<aRects.Count(); i++) |
|
294 { |
|
295 TRect roundedRect = aRects[i].Round(); |
|
296 if (roundedRect.Height() > 0 && roundedRect.Width() > 0) |
|
297 { |
|
298 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
299 vg10Gc->SetPaintPattern(iPolygonFillTexture, iPolygonFillTextureOrigin); |
|
300 iGc->DrawRect(roundedRect); |
|
301 vg10Gc->SetPaintPattern(NULL, iPolygonFillTextureOrigin); |
|
302 } |
|
303 } |
|
304 } |
|
305 } |
|
306 |
|
307 void CHuiVg10CanvasGc::DrawEllipse(const THuiRealRect& aDestinationRect) |
|
308 { |
|
309 if (!iGc) |
|
310 { |
|
311 return; |
|
312 } |
|
313 |
|
314 Setup(); |
|
315 |
|
316 EnableDelayedClippingIfNeeded(aDestinationRect); |
|
317 |
|
318 while (ClipNext()) |
|
319 { |
|
320 DoDrawEllipse( aDestinationRect ); |
|
321 } |
|
322 |
|
323 DisableDelayedClippingIfNeeded(); |
|
324 |
|
325 Cleanup(); |
|
326 } |
|
327 |
|
328 void CHuiVg10CanvasGc::DoDrawEllipse(const THuiRealRect& aDestinationRect) |
|
329 { |
|
330 CHuiVg10Gc* vg10Gc = (CHuiVg10Gc *)iGc; |
|
331 vg10Gc->SetPaintPattern(iPolygonFillTexture, iPolygonFillTextureOrigin); |
|
332 vg10Gc->DrawEllipse(aDestinationRect.Round(), iPolygonDrawMode, iPenWidth); |
|
333 vg10Gc->SetPaintPattern(NULL, iPolygonFillTextureOrigin); |
|
334 } |