OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "xfa/src/fde/fde_geobject.h" | |
8 | |
9 #include "xfa/src/fde/fde_object.h" | |
10 | |
11 IFDE_Path* IFDE_Path::Create() { | |
12 return new CFDE_Path; | |
13 } | |
14 FX_BOOL CFDE_Path::StartFigure() { | |
15 return CloseFigure(); | |
16 } | |
17 FX_BOOL CFDE_Path::CloseFigure() { | |
18 FX_PATHPOINT* pPoint = GetLastPoint(); | |
19 if (pPoint) { | |
20 pPoint->m_Flag |= FXPT_CLOSEFIGURE; | |
21 } | |
22 return TRUE; | |
23 } | |
24 FX_PATHPOINT* CFDE_Path::GetLastPoint(int32_t iCount) const { | |
25 if (iCount < 1) { | |
26 return NULL; | |
27 } | |
28 int32_t iPoints = m_Path.GetPointCount(); | |
29 if (iCount > iPoints) { | |
30 return NULL; | |
31 } | |
32 return m_Path.GetPoints() + iPoints - iCount; | |
33 } | |
34 FX_BOOL CFDE_Path::FigureClosed() const { | |
35 FX_PATHPOINT* pPoint = GetLastPoint(); | |
36 return pPoint ? (pPoint->m_Flag & FXPT_CLOSEFIGURE) : TRUE; | |
37 } | |
38 FX_PATHPOINT* CFDE_Path::AddPoints(int32_t iCount) { | |
39 if (iCount < 1) { | |
40 return NULL; | |
41 } | |
42 int32_t iPoints = m_Path.GetPointCount(); | |
43 m_Path.AddPointCount(iCount); | |
44 return m_Path.GetPoints() + iPoints; | |
45 } | |
46 void CFDE_Path::MoveTo(FX_FLOAT fx, FX_FLOAT fy) { | |
47 FX_PATHPOINT* pPoint = AddPoints(1); | |
48 pPoint->m_PointX = fx; | |
49 pPoint->m_PointY = fy; | |
50 pPoint->m_Flag = FXPT_MOVETO; | |
51 } | |
52 void CFDE_Path::LineTo(FX_FLOAT fx, FX_FLOAT fy) { | |
53 FX_PATHPOINT* pPoint = AddPoints(1); | |
54 pPoint->m_PointX = fx; | |
55 pPoint->m_PointY = fy; | |
56 pPoint->m_Flag = FXPT_LINETO; | |
57 } | |
58 void CFDE_Path::BezierTo(const CFX_PointF& p1, | |
59 const CFX_PointF& p2, | |
60 const CFX_PointF& p3) { | |
61 FX_PATHPOINT* p = AddPoints(3); | |
62 p[0].m_PointX = p1.x; | |
63 p[0].m_PointY = p1.y; | |
64 p[0].m_Flag = FXPT_BEZIERTO; | |
65 p[1].m_PointX = p2.x; | |
66 p[1].m_PointY = p2.y; | |
67 p[1].m_Flag = FXPT_BEZIERTO; | |
68 p[2].m_PointX = p3.x; | |
69 p[2].m_PointY = p3.y; | |
70 p[2].m_Flag = FXPT_BEZIERTO; | |
71 } | |
72 void CFDE_Path::ArcTo(FX_BOOL bStart, | |
73 const CFX_RectF& rect, | |
74 FX_FLOAT startAngle, | |
75 FX_FLOAT endAngle) { | |
76 FX_FLOAT rx = rect.width / 2; | |
77 FX_FLOAT ry = rect.height / 2; | |
78 FX_FLOAT cx = rect.left + rx; | |
79 FX_FLOAT cy = rect.top + ry; | |
80 FX_FLOAT alpha = | |
81 FXSYS_atan2(rx * FXSYS_sin(startAngle), ry * FXSYS_cos(startAngle)); | |
82 FX_FLOAT beta = | |
83 FXSYS_atan2(rx * FXSYS_sin(endAngle), ry * FXSYS_cos(endAngle)); | |
84 if (FXSYS_fabs(beta - alpha) > FX_PI) { | |
85 if (beta > alpha) { | |
86 beta -= 2 * FX_PI; | |
87 } else { | |
88 alpha -= 2 * FX_PI; | |
89 } | |
90 } | |
91 FX_FLOAT half_delta = (beta - alpha) / 2; | |
92 FX_FLOAT bcp = 4.0f / 3 * (1 - FXSYS_cos(half_delta)) / FXSYS_sin(half_delta); | |
93 FX_FLOAT sin_alpha = FXSYS_sin(alpha); | |
94 FX_FLOAT sin_beta = FXSYS_sin(beta); | |
95 FX_FLOAT cos_alpha = FXSYS_cos(alpha); | |
96 FX_FLOAT cos_beta = FXSYS_cos(beta); | |
97 if (bStart) | |
98 MoveTo(CFX_PointF(cx + rx * cos_alpha, cy + ry * sin_alpha)); | |
99 | |
100 BezierTo(CFX_PointF(cx + rx * (cos_alpha - bcp * sin_alpha), | |
101 cy + ry * (sin_alpha + bcp * cos_alpha)), | |
102 CFX_PointF(cx + rx * (cos_beta + bcp * sin_beta), | |
103 cy + ry * (sin_beta - bcp * cos_beta)), | |
104 CFX_PointF(cx + rx * cos_beta, cy + ry * sin_beta)); | |
105 } | |
106 | |
107 void CFDE_Path::AddBezier(const CFX_PointsF& points) { | |
108 if (points.GetSize() != 4) { | |
109 return; | |
110 } | |
111 const CFX_PointF* p = points.GetData(); | |
112 MoveTo(p[0]); | |
113 BezierTo(p[1], p[2], p[3]); | |
114 } | |
115 void CFDE_Path::AddBeziers(const CFX_PointsF& points) { | |
116 int32_t iCount = points.GetSize(); | |
117 if (iCount < 4) { | |
118 return; | |
119 } | |
120 const CFX_PointF* p = points.GetData(); | |
121 const CFX_PointF* pEnd = p + iCount; | |
122 MoveTo(p[0]); | |
123 for (++p; p <= pEnd - 3; p += 3) { | |
124 BezierTo(p[0], p[1], p[2]); | |
125 } | |
126 } | |
127 void CFDE_Path::GetCurveTangents(const CFX_PointsF& points, | |
128 CFX_PointsF& tangents, | |
129 FX_BOOL bClosed, | |
130 FX_FLOAT fTension) const { | |
131 int32_t iCount = points.GetSize(); | |
132 tangents.SetSize(iCount); | |
133 if (iCount < 3) { | |
134 return; | |
135 } | |
136 FX_FLOAT fCoefficient = fTension / 3.0f; | |
137 const CFX_PointF* pPoints = points.GetData(); | |
138 CFX_PointF* pTangents = tangents.GetData(); | |
139 for (int32_t i = 0; i < iCount; ++i) { | |
140 int32_t r = i + 1; | |
141 int32_t s = i - 1; | |
142 if (r >= iCount) { | |
143 r = bClosed ? (r - iCount) : (iCount - 1); | |
144 } | |
145 if (s < 0) { | |
146 s = bClosed ? (s + iCount) : 0; | |
147 } | |
148 pTangents[i].x += (fCoefficient * (pPoints[r].x - pPoints[s].x)); | |
149 pTangents[i].y += (fCoefficient * (pPoints[r].y - pPoints[s].y)); | |
150 } | |
151 } | |
152 void CFDE_Path::AddCurve(const CFX_PointsF& points, | |
153 FX_BOOL bClosed, | |
154 FX_FLOAT fTension) { | |
155 int32_t iLast = points.GetUpperBound(); | |
156 if (iLast < 1) { | |
157 return; | |
158 } | |
159 CFX_PointsF tangents; | |
160 GetCurveTangents(points, tangents, bClosed, fTension); | |
161 const CFX_PointF* pPoints = points.GetData(); | |
162 CFX_PointF* pTangents = tangents.GetData(); | |
163 MoveTo(pPoints[0]); | |
164 for (int32_t i = 0; i < iLast; ++i) { | |
165 BezierTo(CFX_PointF(pPoints[i].x + pTangents[i].x, | |
166 pPoints[i].y + pTangents[i].y), | |
167 CFX_PointF(pPoints[i + 1].x - pTangents[i + 1].x, | |
168 pPoints[i + 1].y - pTangents[i + 1].y), | |
169 CFX_PointF(pPoints[i + 1].x, pPoints[i + 1].y)); | |
170 } | |
171 if (bClosed) { | |
172 BezierTo(CFX_PointF(pPoints[iLast].x + pTangents[iLast].x, | |
173 pPoints[iLast].y + pTangents[iLast].y), | |
174 CFX_PointF(pPoints[0].x - pTangents[0].x, | |
175 pPoints[0].y - pTangents[0].y), | |
176 CFX_PointF(pPoints[0].x, pPoints[0].y)); | |
177 CloseFigure(); | |
178 } | |
179 } | |
180 void CFDE_Path::AddEllipse(const CFX_RectF& rect) { | |
181 FX_FLOAT fStartAngle = 0; | |
182 FX_FLOAT fEndAngle = FX_PI / 2; | |
183 for (int32_t i = 0; i < 4; ++i) { | |
184 ArcTo(i == 0, rect, fStartAngle, fEndAngle); | |
185 fStartAngle += FX_PI / 2; | |
186 fEndAngle += FX_PI / 2; | |
187 } | |
188 CloseFigure(); | |
189 } | |
190 void CFDE_Path::AddLine(const CFX_PointF& pt1, const CFX_PointF& pt2) { | |
191 FX_PATHPOINT* pLast = GetLastPoint(); | |
192 if (pLast == NULL || FXSYS_fabs(pLast->m_PointX - pt1.x) > 0.001 || | |
193 FXSYS_fabs(pLast->m_PointY - pt1.y) > 0.001) { | |
194 MoveTo(pt1); | |
195 } | |
196 LineTo(pt2); | |
197 } | |
198 void CFDE_Path::AddPath(const IFDE_Path* pSrc, FX_BOOL bConnect) { | |
199 CFDE_Path* pPath = (CFDE_Path*)pSrc; | |
200 if (pPath == NULL) { | |
201 return; | |
202 } | |
203 int32_t iCount = pPath->m_Path.GetPointCount(); | |
204 if (iCount < 1) { | |
205 return; | |
206 } | |
207 if (bConnect) { | |
208 LineTo(pPath->m_Path.GetPointX(0), pPath->m_Path.GetPointY(0)); | |
209 } | |
210 m_Path.Append(&pPath->m_Path, NULL); | |
211 } | |
212 void CFDE_Path::AddPolygon(const CFX_PointsF& points) { | |
213 int32_t iCount = points.GetSize(); | |
214 if (iCount < 2) { | |
215 return; | |
216 } | |
217 AddLines(points); | |
218 const CFX_PointF* p = points.GetData(); | |
219 if (FXSYS_fabs(p[0].x - p[iCount - 1].x) < 0.01f || | |
220 FXSYS_fabs(p[0].y - p[iCount - 1].y) < 0.01f) { | |
221 LineTo(p[0]); | |
222 } | |
223 CloseFigure(); | |
224 } | |
225 void CFDE_Path::AddLines(const CFX_PointsF& points) { | |
226 int32_t iCount = points.GetSize(); | |
227 if (iCount < 2) { | |
228 return; | |
229 } | |
230 const CFX_PointF* p = points.GetData(); | |
231 const CFX_PointF* pEnd = p + iCount; | |
232 MoveTo(p[0]); | |
233 for (++p; p < pEnd; ++p) { | |
234 LineTo(*p); | |
235 } | |
236 } | |
237 void CFDE_Path::AddRectangle(const CFX_RectF& rect) { | |
238 MoveTo(rect.TopLeft()); | |
239 LineTo(rect.TopRight()); | |
240 LineTo(rect.BottomRight()); | |
241 LineTo(rect.BottomLeft()); | |
242 CloseFigure(); | |
243 } | |
244 void CFDE_Path::GetBBox(CFX_RectF& bbox) const { | |
245 CFX_FloatRect rect = m_Path.GetBoundingBox(); | |
246 bbox.Set(rect.left, rect.top, rect.Width(), rect.Height()); | |
247 bbox.Normalize(); | |
248 } | |
249 void CFDE_Path::GetBBox(CFX_RectF& bbox, | |
250 FX_FLOAT fLineWidth, | |
251 FX_FLOAT fMiterLimit) const { | |
252 CFX_FloatRect rect = m_Path.GetBoundingBox(fLineWidth, fMiterLimit); | |
253 bbox.Set(rect.left, rect.top, rect.Width(), rect.Height()); | |
254 bbox.Normalize(); | |
255 } | |
OLD | NEW |