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/fxgraphics/fx_path_generator.h" | |
8 | |
9 #include "xfa/src/fxgraphics/pre.h" | |
10 | |
11 CFX_PathGenerator::CFX_PathGenerator() { | |
12 m_pPathData = NULL; | |
13 } | |
14 void CFX_PathGenerator::Create() { | |
15 m_pPathData = new CFX_PathData; | |
16 } | |
17 CFX_PathGenerator::~CFX_PathGenerator() { | |
18 if (m_pPathData) { | |
19 delete m_pPathData; | |
20 m_pPathData = NULL; | |
21 } | |
22 } | |
23 void CFX_PathGenerator::AddPathData(CFX_PathData* pPathData) { | |
24 if (pPathData && pPathData->GetPointCount() > 0) { | |
25 int nCount = pPathData->GetPointCount(); | |
26 FX_PATHPOINT* pPoints = pPathData->GetPoints(); | |
27 AddPathData(pPoints, nCount); | |
28 } | |
29 } | |
30 void CFX_PathGenerator::AddPathData(FX_PATHPOINT* pPoints, int nCount) { | |
31 if (pPoints && nCount > 0) { | |
32 int nOldCount = m_pPathData->GetPointCount(); | |
33 m_pPathData->AddPointCount(nCount); | |
34 FX_PATHPOINT* pDstPoints = m_pPathData->GetPoints(); | |
35 FXSYS_memcpy(pDstPoints + nOldCount, pPoints, | |
36 sizeof(FX_PATHPOINT) * nCount); | |
37 } | |
38 } | |
39 void CFX_PathGenerator::MoveTo(FX_FLOAT x, FX_FLOAT y) { | |
40 m_pPathData->AddPointCount(1); | |
41 m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_MOVETO); | |
42 } | |
43 void CFX_PathGenerator::LineTo(FX_FLOAT x, FX_FLOAT y) { | |
44 m_pPathData->AddPointCount(1); | |
45 m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_LINETO); | |
46 } | |
47 void CFX_PathGenerator::BezierTo(FX_FLOAT ctrl_x1, | |
48 FX_FLOAT ctrl_y1, | |
49 FX_FLOAT ctrl_x2, | |
50 FX_FLOAT ctrl_y2, | |
51 FX_FLOAT to_x, | |
52 FX_FLOAT to_y) { | |
53 int old_count = m_pPathData->GetPointCount(); | |
54 m_pPathData->AddPointCount(3); | |
55 m_pPathData->SetPoint(old_count, ctrl_x1, ctrl_y1, FXPT_BEZIERTO); | |
56 m_pPathData->SetPoint(old_count + 1, ctrl_x2, ctrl_y2, FXPT_BEZIERTO); | |
57 m_pPathData->SetPoint(old_count + 2, to_x, to_y, FXPT_BEZIERTO); | |
58 } | |
59 void CFX_PathGenerator::Close() { | |
60 if (m_pPathData->GetPointCount() > 0) { | |
61 int index = m_pPathData->GetPointCount() - 1; | |
62 FX_PATHPOINT* pPoints = m_pPathData->GetPoints(); | |
63 pPoints[index].m_Flag |= FXPT_CLOSEFIGURE; | |
64 } | |
65 } | |
66 void CFX_PathGenerator::AddLine(FX_FLOAT x1, | |
67 FX_FLOAT y1, | |
68 FX_FLOAT x2, | |
69 FX_FLOAT y2) { | |
70 int old_count = m_pPathData->GetPointCount(); | |
71 m_pPathData->AddPointCount(2); | |
72 m_pPathData->SetPoint(old_count, x1, y1, FXPT_MOVETO); | |
73 m_pPathData->SetPoint(old_count + 1, x2, y2, FXPT_LINETO); | |
74 } | |
75 void CFX_PathGenerator::AddBezier(FX_FLOAT start_x, | |
76 FX_FLOAT start_y, | |
77 FX_FLOAT ctrl_x1, | |
78 FX_FLOAT ctrl_y1, | |
79 FX_FLOAT ctrl_x2, | |
80 FX_FLOAT ctrl_y2, | |
81 FX_FLOAT end_x, | |
82 FX_FLOAT end_y) { | |
83 int old_count = m_pPathData->GetPointCount(); | |
84 m_pPathData->AddPointCount(4); | |
85 m_pPathData->SetPoint(old_count, start_x, start_y, FXPT_MOVETO); | |
86 m_pPathData->SetPoint(old_count + 1, ctrl_x1, ctrl_y1, FXPT_BEZIERTO); | |
87 m_pPathData->SetPoint(old_count + 2, ctrl_x2, ctrl_y2, FXPT_BEZIERTO); | |
88 m_pPathData->SetPoint(old_count + 3, end_x, end_y, FXPT_BEZIERTO); | |
89 } | |
90 void CFX_PathGenerator::AddRectangle(FX_FLOAT x1, | |
91 FX_FLOAT y1, | |
92 FX_FLOAT x2, | |
93 FX_FLOAT y2) { | |
94 m_pPathData->AppendRect(x1, y1, x2, y2); | |
95 } | |
96 void CFX_PathGenerator::AddEllipse(FX_FLOAT x, | |
97 FX_FLOAT y, | |
98 FX_FLOAT width, | |
99 FX_FLOAT height) { | |
100 AddArc(x, y, width, height, 0, FX_PI * 2); | |
101 } | |
102 void CFX_PathGenerator::ArcTo(FX_FLOAT x, | |
103 FX_FLOAT y, | |
104 FX_FLOAT width, | |
105 FX_FLOAT height, | |
106 FX_FLOAT start_angle, | |
107 FX_FLOAT sweep_angle) { | |
108 FX_FLOAT x0 = FXSYS_cos(sweep_angle / 2); | |
109 FX_FLOAT y0 = FXSYS_sin(sweep_angle / 2); | |
110 FX_FLOAT tx = ((1.0f - x0) * 4) / (3 * 1.0f); | |
111 FX_FLOAT ty = y0 - ((tx * x0) / y0); | |
112 FX_FLOAT px[3], py[3]; | |
113 px[0] = x0 + tx; | |
114 py[0] = -ty; | |
115 px[1] = x0 + tx; | |
116 py[1] = ty; | |
117 FX_FLOAT sn = FXSYS_sin(start_angle + sweep_angle / 2); | |
118 FX_FLOAT cs = FXSYS_cos(start_angle + sweep_angle / 2); | |
119 int old_count = m_pPathData->GetPointCount(); | |
120 m_pPathData->AddPointCount(3); | |
121 FX_FLOAT bezier_x, bezier_y; | |
122 bezier_x = x + (width * ((px[0] * cs) - (py[0] * sn))); | |
123 bezier_y = y + (height * ((px[0] * sn) + (py[0] * cs))); | |
124 m_pPathData->SetPoint(old_count, bezier_x, bezier_y, FXPT_BEZIERTO); | |
125 bezier_x = x + (width * ((px[1] * cs) - (py[1] * sn))); | |
126 bezier_y = y + (height * ((px[1] * sn) + (py[1] * cs))); | |
127 m_pPathData->SetPoint(old_count + 1, bezier_x, bezier_y, FXPT_BEZIERTO); | |
128 bezier_x = x + (width * FXSYS_cos(start_angle + sweep_angle)); | |
129 bezier_y = y + (height * FXSYS_sin(start_angle + sweep_angle)); | |
130 m_pPathData->SetPoint(old_count + 2, bezier_x, bezier_y, FXPT_BEZIERTO); | |
131 } | |
132 void CFX_PathGenerator::AddArc(FX_FLOAT x, | |
133 FX_FLOAT y, | |
134 FX_FLOAT width, | |
135 FX_FLOAT height, | |
136 FX_FLOAT start_angle, | |
137 FX_FLOAT sweep_angle) { | |
138 if (sweep_angle == 0) { | |
139 return; | |
140 } | |
141 | |
142 const FX_FLOAT bezier_arc_angle_epsilon = 0.01f; | |
143 while (start_angle > FX_PI * 2) { | |
144 start_angle -= FX_PI * 2; | |
145 } | |
146 while (start_angle < 0) { | |
147 start_angle += FX_PI * 2; | |
148 } | |
149 if (sweep_angle >= FX_PI * 2) { | |
150 sweep_angle = FX_PI * 2; | |
151 } | |
152 if (sweep_angle <= -FX_PI * 2) { | |
153 sweep_angle = -FX_PI * 2; | |
154 } | |
155 m_pPathData->AddPointCount(1); | |
156 m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, | |
157 x + (width * FXSYS_cos(start_angle)), | |
158 y + (height * FXSYS_sin(start_angle)), FXPT_MOVETO); | |
159 FX_FLOAT total_sweep = 0, local_sweep = 0, prev_sweep = 0; | |
160 FX_BOOL done = FALSE; | |
161 do { | |
162 if (sweep_angle < 0) { | |
163 prev_sweep = total_sweep; | |
164 local_sweep = -FX_PI / 2; | |
165 total_sweep -= FX_PI / 2; | |
166 if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { | |
167 local_sweep = sweep_angle - prev_sweep; | |
168 done = TRUE; | |
169 } | |
170 } else { | |
171 prev_sweep = total_sweep; | |
172 local_sweep = FX_PI / 2; | |
173 total_sweep += FX_PI / 2; | |
174 if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { | |
175 local_sweep = sweep_angle - prev_sweep; | |
176 done = TRUE; | |
177 } | |
178 } | |
179 ArcTo(x, y, width, height, start_angle, local_sweep); | |
180 start_angle += local_sweep; | |
181 } while (!done); | |
182 } | |
183 void CFX_PathGenerator::AddPie(FX_FLOAT x, | |
184 FX_FLOAT y, | |
185 FX_FLOAT width, | |
186 FX_FLOAT height, | |
187 FX_FLOAT start_angle, | |
188 FX_FLOAT sweep_angle) { | |
189 if (sweep_angle == 0) { | |
190 int old_count = m_pPathData->GetPointCount(); | |
191 m_pPathData->AddPointCount(2); | |
192 m_pPathData->SetPoint(old_count, x, y, FXPT_MOVETO); | |
193 m_pPathData->SetPoint(old_count + 1, x + (width * FXSYS_cos(start_angle)), | |
194 y + (height * FXSYS_sin(start_angle)), FXPT_LINETO); | |
195 return; | |
196 } | |
197 AddArc(x, y, width, height, start_angle, sweep_angle); | |
198 m_pPathData->AddPointCount(1); | |
199 m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, | |
200 FXPT_LINETO | FXPT_CLOSEFIGURE); | |
201 } | |
OLD | NEW |