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