|
1 /* |
|
2 * Copyright (c) 2004-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: Poly line class. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "AknsAlPolyLine.h" |
|
20 |
|
21 // ----------------------------------------------------------------------------- |
|
22 // C++ constructor. |
|
23 // ----------------------------------------------------------------------------- |
|
24 // |
|
25 CAknsAlPolyLine::CAknsAlPolyLine() |
|
26 { |
|
27 } |
|
28 |
|
29 // ----------------------------------------------------------------------------- |
|
30 // Destructor. |
|
31 // ----------------------------------------------------------------------------- |
|
32 // |
|
33 CAknsAlPolyLine::~CAknsAlPolyLine() |
|
34 { |
|
35 delete [] iSegmentLengths; |
|
36 iSegmentLengths = NULL; |
|
37 } |
|
38 |
|
39 // ----------------------------------------------------------------------------- |
|
40 // Symbian 1st phase constructor. |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 CAknsAlPolyLine* CAknsAlPolyLine::NewL() |
|
44 { // static |
|
45 CAknsAlPolyLine* self=new(ELeave) CAknsAlPolyLine(); |
|
46 return self; |
|
47 } |
|
48 |
|
49 // ----------------------------------------------------------------------------- |
|
50 // Gets poly point. |
|
51 // ----------------------------------------------------------------------------- |
|
52 // |
|
53 TPoint CAknsAlPolyLine::GetPolyPoint( const TUint32 aPosition ) |
|
54 { |
|
55 // aPosition is 32 bit integer representing range 0...1 |
|
56 #if (defined(__SERIES60_26__) || defined(__SERIES60_27__) || defined(__SERIES60_28__)) |
|
57 TInt64 aa; |
|
58 aa.Set(0,aPosition); |
|
59 TInt64 bb; |
|
60 bb.Set(0,iSegmentLengths[iPointCount-2]); |
|
61 TInt64 pos64 = aa*bb; |
|
62 TUint32 pos = (TUint32)pos64.High(); // same as pos64 >> 32 |
|
63 #else // 3.0 or newer |
|
64 TUint64 pos64 = TUint64(aPosition) * TUint64(iSegmentLengths[iPointCount-2]); |
|
65 TUint32 pos = pos64 >> 32; |
|
66 #endif |
|
67 // because of possible rounding errors, first check for last pixel |
|
68 if (pos >= iSegmentLengths[iPointCount-2]) |
|
69 { |
|
70 return TPoint(iPoints[iPointCount-1].iX, |
|
71 iPoints[iPointCount-1].iY); |
|
72 } |
|
73 |
|
74 // find the segment, where pos is pointing |
|
75 TInt i = 0; // first index |
|
76 TInt j = iPointCount-2; // last index |
|
77 TInt k; |
|
78 while ( i < j ) |
|
79 { |
|
80 k = (i + j)/2; |
|
81 if ( pos < iSegmentLengths[k] ) |
|
82 { |
|
83 j = k; |
|
84 } |
|
85 else |
|
86 { |
|
87 i = k + 1; |
|
88 } |
|
89 } |
|
90 // i = j = wanted index |
|
91 |
|
92 TUint32 segLength; // real segment length (not cumulative) |
|
93 if (i > 0) |
|
94 { |
|
95 pos -= iSegmentLengths[i-1]; // position between 0...segment length |
|
96 segLength = iSegmentLengths[i]-iSegmentLengths[i-1]; |
|
97 } |
|
98 else |
|
99 { |
|
100 segLength = iSegmentLengths[0]; // we are in first segment |
|
101 } |
|
102 |
|
103 TUint32 deltaX, deltaY; |
|
104 // must handle negative values differently |
|
105 TBool xnegative = EFalse; |
|
106 TBool ynegative = EFalse; |
|
107 |
|
108 if ( (iPoints[i+1].iX - iPoints[i].iX) < 0) |
|
109 { |
|
110 deltaX = iPoints[i].iX - iPoints[i+1].iX; // max 16 bits |
|
111 xnegative = ETrue; |
|
112 } |
|
113 else |
|
114 { |
|
115 deltaX = iPoints[i+1].iX - iPoints[i].iX; // max 16 bits |
|
116 } |
|
117 |
|
118 if ( (iPoints[i+1].iY - iPoints[i].iY) < 0) |
|
119 { |
|
120 deltaY = iPoints[i].iY - iPoints[i+1].iY; // max 16 bits |
|
121 ynegative = ETrue; |
|
122 } |
|
123 else |
|
124 { |
|
125 deltaY = iPoints[i+1].iY - iPoints[i].iY; // max 16 bits |
|
126 } |
|
127 |
|
128 TUint32 deltaXpos = ((pos * deltaX) / segLength); |
|
129 TUint32 deltaYpos = ((pos * deltaY) / segLength); |
|
130 |
|
131 if (xnegative) |
|
132 { |
|
133 deltaXpos = iPoints[i].iX - deltaXpos; |
|
134 } |
|
135 else |
|
136 { |
|
137 deltaXpos = iPoints[i].iX + deltaXpos; |
|
138 } |
|
139 |
|
140 if (ynegative) |
|
141 { |
|
142 deltaYpos = iPoints[i].iY - deltaYpos; |
|
143 } |
|
144 else |
|
145 { |
|
146 deltaYpos = iPoints[i].iY + deltaYpos; |
|
147 } |
|
148 |
|
149 return CalculateScaledPoint(TPoint(deltaXpos,deltaYpos)); |
|
150 } |
|
151 |
|
152 // ----------------------------------------------------------------------------- |
|
153 // Calculates lengths. |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 void CAknsAlPolyLine::CalculateLengthsL() |
|
157 { |
|
158 // won't get here if not at least 2 points are already set |
|
159 delete [] iSegmentLengths; |
|
160 iSegmentLengths = NULL; |
|
161 |
|
162 iSegmentLengths = new (ELeave) TUint32[iPointCount-1]; |
|
163 |
|
164 TInt32 diffX, diffY; |
|
165 |
|
166 TUint32 length = 0; // for holding the cumulative length |
|
167 |
|
168 for (TInt i = 0; i < (iPointCount-1); i++) |
|
169 { |
|
170 // Points have their x and y coordinates in form 0.16 (e.g. only decimal |
|
171 // part is set), so there won't be overflow when multiplying. But after |
|
172 // multiply the results can't be added together without a possibility |
|
173 // for overflow. That's why the coordinates are first divided by 2. |
|
174 diffX = (iPoints[i+1].iX - iPoints[i].iX) >> 1; // result can be negative! |
|
175 diffY = (iPoints[i+1].iY - iPoints[i].iY) >> 1; // result can be negative! |
|
176 |
|
177 // this is not the actual length, but length/2 |
|
178 // length might overflow if the poly has over 60000 segments... |
|
179 length += Sqrt( diffX*diffX + diffY*diffY ); |
|
180 iSegmentLengths[i] = length; |
|
181 } |
|
182 } |
|
183 |
|
184 // End of file |