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 "core/include/fxcrt/fx_system.h" | |
8 #include "core/include/fxge/fx_ge.h" | |
9 #include "third_party/base/numerics/safe_math.h" | |
10 | |
11 CFX_ClipRgn::CFX_ClipRgn(int width, int height) { | |
12 m_Type = RectI; | |
13 m_Box.left = m_Box.top = 0; | |
14 m_Box.right = width; | |
15 m_Box.bottom = height; | |
16 } | |
17 CFX_ClipRgn::CFX_ClipRgn(const FX_RECT& rect) { | |
18 m_Type = RectI; | |
19 m_Box = rect; | |
20 } | |
21 CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { | |
22 m_Type = src.m_Type; | |
23 m_Box = src.m_Box; | |
24 m_Mask = src.m_Mask; | |
25 } | |
26 CFX_ClipRgn::~CFX_ClipRgn() {} | |
27 void CFX_ClipRgn::Reset(const FX_RECT& rect) { | |
28 m_Type = RectI; | |
29 m_Box = rect; | |
30 m_Mask.SetNull(); | |
31 } | |
32 void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { | |
33 if (m_Type == RectI) { | |
34 m_Box.Intersect(rect); | |
35 return; | |
36 } | |
37 if (m_Type == MaskF) { | |
38 IntersectMaskRect(rect, m_Box, m_Mask); | |
39 return; | |
40 } | |
41 } | |
42 void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, | |
43 FX_RECT mask_rect, | |
44 CFX_DIBitmapRef Mask) { | |
45 const CFX_DIBitmap* mask_dib = Mask; | |
46 m_Type = MaskF; | |
47 m_Box = rect; | |
48 m_Box.Intersect(mask_rect); | |
49 if (m_Box.IsEmpty()) { | |
50 m_Type = RectI; | |
51 return; | |
52 } | |
53 if (m_Box == mask_rect) { | |
54 m_Mask = Mask; | |
55 return; | |
56 } | |
57 CFX_DIBitmap* new_dib = m_Mask.New(); | |
58 if (!new_dib) { | |
59 return; | |
60 } | |
61 new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); | |
62 for (int row = m_Box.top; row < m_Box.bottom; row++) { | |
63 uint8_t* dest_scan = | |
64 new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); | |
65 uint8_t* src_scan = | |
66 mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top); | |
67 for (int col = m_Box.left; col < m_Box.right; col++) { | |
68 dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; | |
69 } | |
70 } | |
71 } | |
72 void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) { | |
73 const CFX_DIBitmap* mask_dib = Mask; | |
74 ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask); | |
75 FX_RECT mask_box(left, top, left + mask_dib->GetWidth(), | |
76 top + mask_dib->GetHeight()); | |
77 if (m_Type == RectI) { | |
78 IntersectMaskRect(m_Box, mask_box, Mask); | |
79 return; | |
80 } | |
81 if (m_Type == MaskF) { | |
82 FX_RECT new_box = m_Box; | |
83 new_box.Intersect(mask_box); | |
84 if (new_box.IsEmpty()) { | |
85 m_Type = RectI; | |
86 m_Mask.SetNull(); | |
87 m_Box = new_box; | |
88 return; | |
89 } | |
90 CFX_DIBitmapRef new_mask; | |
91 CFX_DIBitmap* new_dib = new_mask.New(); | |
92 if (!new_dib) { | |
93 return; | |
94 } | |
95 new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); | |
96 const CFX_DIBitmap* old_dib = m_Mask; | |
97 for (int row = new_box.top; row < new_box.bottom; row++) { | |
98 uint8_t* old_scan = | |
99 old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); | |
100 uint8_t* mask_scan = | |
101 mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); | |
102 uint8_t* new_scan = | |
103 new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); | |
104 for (int col = new_box.left; col < new_box.right; col++) { | |
105 new_scan[col - new_box.left] = | |
106 old_scan[col - m_Box.left] * mask_scan[col - left] / 255; | |
107 } | |
108 } | |
109 m_Box = new_box; | |
110 m_Mask = new_mask; | |
111 return; | |
112 } | |
113 ASSERT(FALSE); | |
114 } | |
115 CFX_PathData::CFX_PathData() { | |
116 m_PointCount = m_AllocCount = 0; | |
117 m_pPoints = NULL; | |
118 } | |
119 CFX_PathData::~CFX_PathData() { | |
120 FX_Free(m_pPoints); | |
121 } | |
122 void CFX_PathData::SetPointCount(int nPoints) { | |
123 m_PointCount = nPoints; | |
124 if (m_AllocCount < nPoints) { | |
125 FX_Free(m_pPoints); | |
126 m_pPoints = FX_Alloc(FX_PATHPOINT, nPoints); | |
127 m_AllocCount = nPoints; | |
128 } | |
129 } | |
130 void CFX_PathData::AllocPointCount(int nPoints) { | |
131 if (m_AllocCount < nPoints) { | |
132 FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints); | |
133 if (m_PointCount) { | |
134 FXSYS_memcpy(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT)); | |
135 } | |
136 FX_Free(m_pPoints); | |
137 m_pPoints = pNewBuf; | |
138 m_AllocCount = nPoints; | |
139 } | |
140 } | |
141 CFX_PathData::CFX_PathData(const CFX_PathData& src) { | |
142 m_PointCount = m_AllocCount = src.m_PointCount; | |
143 m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount); | |
144 FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); | |
145 } | |
146 void CFX_PathData::TrimPoints(int nPoints) { | |
147 if (m_PointCount <= nPoints) { | |
148 return; | |
149 } | |
150 SetPointCount(nPoints); | |
151 } | |
152 void CFX_PathData::AddPointCount(int addPoints) { | |
153 pdfium::base::CheckedNumeric<int> safe_new_count = m_PointCount; | |
154 safe_new_count += addPoints; | |
155 int new_count = safe_new_count.ValueOrDie(); | |
156 AllocPointCount(new_count); | |
157 m_PointCount = new_count; | |
158 } | |
159 void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix) { | |
160 int old_count = m_PointCount; | |
161 AddPointCount(pSrc->m_PointCount); | |
162 FXSYS_memcpy(m_pPoints + old_count, pSrc->m_pPoints, | |
163 pSrc->m_PointCount * sizeof(FX_PATHPOINT)); | |
164 if (pMatrix) { | |
165 for (int i = 0; i < pSrc->m_PointCount; i++) { | |
166 pMatrix->Transform(m_pPoints[old_count + i].m_PointX, | |
167 m_pPoints[old_count + i].m_PointY); | |
168 } | |
169 } | |
170 } | |
171 void CFX_PathData::SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag) { | |
172 ASSERT(index < m_PointCount); | |
173 m_pPoints[index].m_PointX = x; | |
174 m_pPoints[index].m_PointY = y; | |
175 m_pPoints[index].m_Flag = flag; | |
176 } | |
177 void CFX_PathData::AppendRect(FX_FLOAT left, | |
178 FX_FLOAT bottom, | |
179 FX_FLOAT right, | |
180 FX_FLOAT top) { | |
181 int old_count = m_PointCount; | |
182 AddPointCount(5); | |
183 FX_PATHPOINT* pPoints = m_pPoints + old_count; | |
184 pPoints[0].m_PointX = pPoints[1].m_PointX = pPoints[4].m_PointX = left; | |
185 pPoints[2].m_PointX = pPoints[3].m_PointX = right; | |
186 pPoints[0].m_PointY = pPoints[3].m_PointY = pPoints[4].m_PointY = bottom; | |
187 pPoints[1].m_PointY = pPoints[2].m_PointY = top; | |
188 pPoints[0].m_Flag = FXPT_MOVETO; | |
189 pPoints[1].m_Flag = pPoints[2].m_Flag = pPoints[3].m_Flag = FXPT_LINETO; | |
190 pPoints[4].m_Flag = FXPT_LINETO | FXPT_CLOSEFIGURE; | |
191 } | |
192 CFX_FloatRect CFX_PathData::GetBoundingBox() const { | |
193 CFX_FloatRect rect; | |
194 if (m_PointCount) { | |
195 rect.InitRect(m_pPoints[0].m_PointX, m_pPoints[0].m_PointY); | |
196 for (int i = 1; i < m_PointCount; i++) { | |
197 rect.UpdateRect(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); | |
198 } | |
199 } | |
200 return rect; | |
201 } | |
202 static void _UpdateLineEndPoints(CFX_FloatRect& rect, | |
203 FX_FLOAT start_x, | |
204 FX_FLOAT start_y, | |
205 FX_FLOAT end_x, | |
206 FX_FLOAT end_y, | |
207 FX_FLOAT hw) { | |
208 if (start_x == end_x) { | |
209 if (start_y == end_y) { | |
210 rect.UpdateRect(end_x + hw, end_y + hw); | |
211 rect.UpdateRect(end_x - hw, end_y - hw); | |
212 return; | |
213 } | |
214 FX_FLOAT point_y; | |
215 if (end_y < start_y) { | |
216 point_y = end_y - hw; | |
217 } else { | |
218 point_y = end_y + hw; | |
219 } | |
220 rect.UpdateRect(end_x + hw, point_y); | |
221 rect.UpdateRect(end_x - hw, point_y); | |
222 return; | |
223 } | |
224 if (start_y == end_y) { | |
225 FX_FLOAT point_x; | |
226 if (end_x < start_x) { | |
227 point_x = end_x - hw; | |
228 } else { | |
229 point_x = end_x + hw; | |
230 } | |
231 rect.UpdateRect(point_x, end_y + hw); | |
232 rect.UpdateRect(point_x, end_y - hw); | |
233 return; | |
234 } | |
235 FX_FLOAT dx = end_x - start_x; | |
236 FX_FLOAT dy = end_y - start_y; | |
237 FX_FLOAT ll = FXSYS_sqrt2(dx, dy); | |
238 FX_FLOAT mx = end_x + hw * dx / ll; | |
239 FX_FLOAT my = end_y + hw * dy / ll; | |
240 FX_FLOAT dx1 = hw * dy / ll; | |
241 FX_FLOAT dy1 = hw * dx / ll; | |
242 rect.UpdateRect(mx - dx1, my + dy1); | |
243 rect.UpdateRect(mx + dx1, my - dy1); | |
244 } | |
245 static void _UpdateLineJoinPoints(CFX_FloatRect& rect, | |
246 FX_FLOAT start_x, | |
247 FX_FLOAT start_y, | |
248 FX_FLOAT middle_x, | |
249 FX_FLOAT middle_y, | |
250 FX_FLOAT end_x, | |
251 FX_FLOAT end_y, | |
252 FX_FLOAT half_width, | |
253 FX_FLOAT miter_limit) { | |
254 FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0, | |
255 start_dc = 0, end_len = 0, end_dc = 0; | |
256 FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20; | |
257 FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20; | |
258 if (bStartVert && bEndVert) { | |
259 int start_dir = middle_y > start_y ? 1 : -1; | |
260 FX_FLOAT point_y = middle_y + half_width * start_dir; | |
261 rect.UpdateRect(middle_x + half_width, point_y); | |
262 rect.UpdateRect(middle_x - half_width, point_y); | |
263 return; | |
264 } | |
265 if (!bStartVert) { | |
266 start_k = (middle_y - start_y) / (middle_x - start_x); | |
267 start_c = middle_y - (start_k * middle_x); | |
268 start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y); | |
269 start_dc = | |
270 (FX_FLOAT)FXSYS_fabs(half_width * start_len / (start_x - middle_x)); | |
271 } | |
272 if (!bEndVert) { | |
273 end_k = (end_y - middle_y) / (end_x - middle_x); | |
274 end_c = middle_y - (end_k * middle_x); | |
275 end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y); | |
276 end_dc = (FX_FLOAT)FXSYS_fabs(half_width * end_len / (end_x - middle_x)); | |
277 } | |
278 if (bStartVert) { | |
279 FX_FLOAT outside_x = start_x; | |
280 if (end_x < start_x) { | |
281 outside_x += half_width; | |
282 } else { | |
283 outside_x -= half_width; | |
284 } | |
285 FX_FLOAT outside_y; | |
286 if (start_y < (end_k * start_x) + end_c) { | |
287 outside_y = (end_k * outside_x) + end_c + end_dc; | |
288 } else { | |
289 outside_y = (end_k * outside_x) + end_c - end_dc; | |
290 } | |
291 rect.UpdateRect(outside_x, outside_y); | |
292 return; | |
293 } | |
294 if (bEndVert) { | |
295 FX_FLOAT outside_x = end_x; | |
296 if (start_x < end_x) { | |
297 outside_x += half_width; | |
298 } else { | |
299 outside_x -= half_width; | |
300 } | |
301 FX_FLOAT outside_y; | |
302 if (end_y < (start_k * end_x) + start_c) { | |
303 outside_y = (start_k * outside_x) + start_c + start_dc; | |
304 } else { | |
305 outside_y = (start_k * outside_x) + start_c - start_dc; | |
306 } | |
307 rect.UpdateRect(outside_x, outside_y); | |
308 return; | |
309 } | |
310 if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) { | |
311 int start_dir = middle_x > start_x ? 1 : -1; | |
312 int end_dir = end_x > middle_x ? 1 : -1; | |
313 if (start_dir == end_dir) { | |
314 _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width); | |
315 } else { | |
316 _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y, | |
317 half_width); | |
318 } | |
319 return; | |
320 } | |
321 FX_FLOAT start_outside_c = start_c; | |
322 if (end_y < (start_k * end_x) + start_c) { | |
323 start_outside_c += start_dc; | |
324 } else { | |
325 start_outside_c -= start_dc; | |
326 } | |
327 FX_FLOAT end_outside_c = end_c; | |
328 if (start_y < (end_k * start_x) + end_c) { | |
329 end_outside_c += end_dc; | |
330 } else { | |
331 end_outside_c -= end_dc; | |
332 } | |
333 FX_FLOAT join_x = (end_outside_c - start_outside_c) / (start_k - end_k); | |
334 FX_FLOAT join_y = (start_k * join_x) + start_outside_c; | |
335 rect.UpdateRect(join_x, join_y); | |
336 } | |
337 CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width, | |
338 FX_FLOAT miter_limit) const { | |
339 CFX_FloatRect rect(100000 * 1.0f, 100000 * 1.0f, -100000 * 1.0f, | |
340 -100000 * 1.0f); | |
341 int iPoint = 0; | |
342 FX_FLOAT half_width = line_width; | |
343 int iStartPoint, iEndPoint, iMiddlePoint; | |
344 FX_BOOL bJoin; | |
345 while (iPoint < m_PointCount) { | |
346 if (m_pPoints[iPoint].m_Flag == FXPT_MOVETO) { | |
347 iStartPoint = iPoint + 1; | |
348 iEndPoint = iPoint; | |
349 bJoin = FALSE; | |
350 } else { | |
351 if (m_pPoints[iPoint].m_Flag == FXPT_BEZIERTO) { | |
352 rect.UpdateRect(m_pPoints[iPoint].m_PointX, m_pPoints[iPoint].m_PointY); | |
353 rect.UpdateRect(m_pPoints[iPoint + 1].m_PointX, | |
354 m_pPoints[iPoint + 1].m_PointY); | |
355 iPoint += 2; | |
356 } | |
357 if (iPoint == m_PointCount - 1 || | |
358 m_pPoints[iPoint + 1].m_Flag == FXPT_MOVETO) { | |
359 iStartPoint = iPoint - 1; | |
360 iEndPoint = iPoint; | |
361 bJoin = FALSE; | |
362 } else { | |
363 iStartPoint = iPoint - 1; | |
364 iMiddlePoint = iPoint; | |
365 iEndPoint = iPoint + 1; | |
366 bJoin = TRUE; | |
367 } | |
368 } | |
369 FX_FLOAT start_x = m_pPoints[iStartPoint].m_PointX; | |
370 FX_FLOAT start_y = m_pPoints[iStartPoint].m_PointY; | |
371 FX_FLOAT end_x = m_pPoints[iEndPoint].m_PointX; | |
372 FX_FLOAT end_y = m_pPoints[iEndPoint].m_PointY; | |
373 if (bJoin) { | |
374 FX_FLOAT middle_x = m_pPoints[iMiddlePoint].m_PointX; | |
375 FX_FLOAT middle_y = m_pPoints[iMiddlePoint].m_PointY; | |
376 _UpdateLineJoinPoints(rect, start_x, start_y, middle_x, middle_y, end_x, | |
377 end_y, half_width, miter_limit); | |
378 } else { | |
379 _UpdateLineEndPoints(rect, start_x, start_y, end_x, end_y, half_width); | |
380 } | |
381 iPoint++; | |
382 } | |
383 return rect; | |
384 } | |
385 void CFX_PathData::Transform(const CFX_Matrix* pMatrix) { | |
386 if (!pMatrix) { | |
387 return; | |
388 } | |
389 for (int i = 0; i < m_PointCount; i++) { | |
390 pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); | |
391 } | |
392 } | |
393 FX_BOOL CFX_PathData::GetZeroAreaPath(CFX_PathData& NewPath, | |
394 CFX_Matrix* pMatrix, | |
395 FX_BOOL& bThin, | |
396 FX_BOOL bAdjust) const { | |
397 if (m_PointCount < 3) { | |
398 return FALSE; | |
399 } | |
400 if (m_PointCount == 3 && (m_pPoints[0].m_Flag & FXPT_TYPE) == FXPT_MOVETO && | |
401 (m_pPoints[1].m_Flag & FXPT_TYPE) == FXPT_LINETO && | |
402 (m_pPoints[2].m_Flag & FXPT_TYPE) == FXPT_LINETO && | |
403 m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && | |
404 m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) { | |
405 NewPath.AddPointCount(2); | |
406 if (bAdjust) { | |
407 if (pMatrix) { | |
408 FX_FLOAT x = m_pPoints[0].m_PointX, y = m_pPoints[0].m_PointY; | |
409 pMatrix->TransformPoint(x, y); | |
410 x = (int)x + 0.5f; | |
411 y = (int)y + 0.5f; | |
412 NewPath.SetPoint(0, x, y, FXPT_MOVETO); | |
413 x = m_pPoints[1].m_PointX, y = m_pPoints[1].m_PointY; | |
414 pMatrix->TransformPoint(x, y); | |
415 x = (int)x + 0.5f; | |
416 y = (int)y + 0.5f; | |
417 NewPath.SetPoint(1, x, y, FXPT_LINETO); | |
418 pMatrix->SetIdentity(); | |
419 } else { | |
420 FX_FLOAT x = (int)m_pPoints[0].m_PointX + 0.5f, | |
421 y = (int)m_pPoints[0].m_PointY + 0.5f; | |
422 NewPath.SetPoint(0, x, y, FXPT_MOVETO); | |
423 x = (int)m_pPoints[1].m_PointX + 0.5f, | |
424 y = (int)m_pPoints[1].m_PointY + 0.5f; | |
425 NewPath.SetPoint(1, x, y, FXPT_LINETO); | |
426 } | |
427 } else { | |
428 NewPath.SetPoint(0, m_pPoints[0].m_PointX, m_pPoints[0].m_PointY, | |
429 FXPT_MOVETO); | |
430 NewPath.SetPoint(1, m_pPoints[1].m_PointX, m_pPoints[1].m_PointY, | |
431 FXPT_LINETO); | |
432 } | |
433 if (m_pPoints[0].m_PointX != m_pPoints[1].m_PointX && | |
434 m_pPoints[0].m_PointY != m_pPoints[1].m_PointY) { | |
435 bThin = TRUE; | |
436 } | |
437 return TRUE; | |
438 } | |
439 if (((m_PointCount > 3) && (m_PointCount % 2))) { | |
440 int mid = m_PointCount / 2; | |
441 FX_BOOL bZeroArea = FALSE; | |
442 CFX_PathData t_path; | |
443 for (int i = 0; i < mid; i++) { | |
444 if (!(m_pPoints[mid - i - 1].m_PointX == | |
445 m_pPoints[mid + i + 1].m_PointX && | |
446 m_pPoints[mid - i - 1].m_PointY == | |
447 m_pPoints[mid + i + 1].m_PointY && | |
448 ((m_pPoints[mid - i - 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && | |
449 (m_pPoints[mid + i + 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO))) { | |
450 bZeroArea = TRUE; | |
451 break; | |
452 } | |
453 int new_count = t_path.GetPointCount(); | |
454 t_path.AddPointCount(2); | |
455 t_path.SetPoint(new_count, m_pPoints[mid - i].m_PointX, | |
456 m_pPoints[mid - i].m_PointY, FXPT_MOVETO); | |
457 t_path.SetPoint(new_count + 1, m_pPoints[mid - i - 1].m_PointX, | |
458 m_pPoints[mid - i - 1].m_PointY, FXPT_LINETO); | |
459 } | |
460 if (!bZeroArea) { | |
461 NewPath.Append(&t_path, NULL); | |
462 bThin = TRUE; | |
463 return TRUE; | |
464 } | |
465 } | |
466 int stratPoint = 0; | |
467 int next = 0, i; | |
468 for (i = 0; i < m_PointCount; i++) { | |
469 int point_type = m_pPoints[i].m_Flag & FXPT_TYPE; | |
470 if (point_type == FXPT_MOVETO) { | |
471 stratPoint = i; | |
472 } else if (point_type == FXPT_LINETO) { | |
473 next = (i + 1 - stratPoint) % (m_PointCount - stratPoint) + stratPoint; | |
474 if ((m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && | |
475 (m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_MOVETO) { | |
476 if ((m_pPoints[i - 1].m_PointX == m_pPoints[i].m_PointX && | |
477 m_pPoints[i].m_PointX == m_pPoints[next].m_PointX) && | |
478 ((m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) * | |
479 (m_pPoints[i].m_PointY - m_pPoints[next].m_PointY) > | |
480 0)) { | |
481 int pre = i; | |
482 if (FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) < | |
483 FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[next].m_PointY)) { | |
484 pre--; | |
485 next--; | |
486 } | |
487 int new_count = NewPath.GetPointCount(); | |
488 NewPath.AddPointCount(2); | |
489 NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, | |
490 m_pPoints[pre].m_PointY, FXPT_MOVETO); | |
491 NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, | |
492 m_pPoints[next].m_PointY, FXPT_LINETO); | |
493 } else if ((m_pPoints[i - 1].m_PointY == m_pPoints[i].m_PointY && | |
494 m_pPoints[i].m_PointY == m_pPoints[next].m_PointY) && | |
495 ((m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) * | |
496 (m_pPoints[i].m_PointX - m_pPoints[next].m_PointX) > | |
497 0)) { | |
498 int pre = i; | |
499 if (FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) < | |
500 FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[next].m_PointX)) { | |
501 pre--; | |
502 next--; | |
503 } | |
504 int new_count = NewPath.GetPointCount(); | |
505 NewPath.AddPointCount(2); | |
506 NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, | |
507 m_pPoints[pre].m_PointY, FXPT_MOVETO); | |
508 NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, | |
509 m_pPoints[next].m_PointY, FXPT_LINETO); | |
510 } else if ((m_pPoints[i - 1].m_Flag & FXPT_TYPE) == FXPT_MOVETO && | |
511 (m_pPoints[next].m_Flag & FXPT_TYPE) == FXPT_LINETO && | |
512 m_pPoints[i - 1].m_PointX == m_pPoints[next].m_PointX && | |
513 m_pPoints[i - 1].m_PointY == m_pPoints[next].m_PointY && | |
514 m_pPoints[next].m_Flag & FXPT_CLOSEFIGURE) { | |
515 int new_count = NewPath.GetPointCount(); | |
516 NewPath.AddPointCount(2); | |
517 NewPath.SetPoint(new_count, m_pPoints[i - 1].m_PointX, | |
518 m_pPoints[i - 1].m_PointY, FXPT_MOVETO); | |
519 NewPath.SetPoint(new_count + 1, m_pPoints[i].m_PointX, | |
520 m_pPoints[i].m_PointY, FXPT_LINETO); | |
521 bThin = TRUE; | |
522 } | |
523 } | |
524 } else if (point_type == FXPT_BEZIERTO) { | |
525 i += 2; | |
526 continue; | |
527 } | |
528 } | |
529 if (m_PointCount > 3 && NewPath.GetPointCount()) { | |
530 bThin = TRUE; | |
531 } | |
532 if (NewPath.GetPointCount() == 0) { | |
533 return FALSE; | |
534 } | |
535 return TRUE; | |
536 } | |
537 FX_BOOL CFX_PathData::IsRect() const { | |
538 if (m_PointCount != 5 && m_PointCount != 4) { | |
539 return FALSE; | |
540 } | |
541 if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || | |
542 m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || | |
543 (m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && | |
544 m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) || | |
545 (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && | |
546 m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { | |
547 return FALSE; | |
548 } | |
549 if (m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && | |
550 m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { | |
551 return FALSE; | |
552 } | |
553 for (int i = 1; i < 4; i++) { | |
554 if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { | |
555 return FALSE; | |
556 } | |
557 if (m_pPoints[i].m_PointX != m_pPoints[i - 1].m_PointX && | |
558 m_pPoints[i].m_PointY != m_pPoints[i - 1].m_PointY) { | |
559 return FALSE; | |
560 } | |
561 } | |
562 return m_PointCount == 5 || (m_pPoints[3].m_Flag & FXPT_CLOSEFIGURE); | |
563 } | |
564 FX_BOOL CFX_PathData::IsRect(const CFX_Matrix* pMatrix, | |
565 CFX_FloatRect* pRect) const { | |
566 if (!pMatrix) { | |
567 if (!IsRect()) { | |
568 return FALSE; | |
569 } | |
570 if (pRect) { | |
571 pRect->left = m_pPoints[0].m_PointX; | |
572 pRect->right = m_pPoints[2].m_PointX; | |
573 pRect->bottom = m_pPoints[0].m_PointY; | |
574 pRect->top = m_pPoints[2].m_PointY; | |
575 pRect->Normalize(); | |
576 } | |
577 return TRUE; | |
578 } | |
579 if (m_PointCount != 5 && m_PointCount != 4) { | |
580 return FALSE; | |
581 } | |
582 if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || | |
583 m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || | |
584 (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && | |
585 m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { | |
586 return FALSE; | |
587 } | |
588 if (m_PointCount == 4 && m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && | |
589 m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { | |
590 return FALSE; | |
591 } | |
592 FX_FLOAT x[5], y[5]; | |
593 for (int i = 0; i < m_PointCount; i++) { | |
594 pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, x[i], | |
595 y[i]); | |
596 if (i) { | |
597 if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { | |
598 return FALSE; | |
599 } | |
600 if (x[i] != x[i - 1] && y[i] != y[i - 1]) { | |
601 return FALSE; | |
602 } | |
603 } | |
604 } | |
605 if (pRect) { | |
606 pRect->left = x[0]; | |
607 pRect->right = x[2]; | |
608 pRect->bottom = y[0]; | |
609 pRect->top = y[2]; | |
610 pRect->Normalize(); | |
611 } | |
612 return TRUE; | |
613 } | |
614 void CFX_PathData::Copy(const CFX_PathData& src) { | |
615 SetPointCount(src.m_PointCount); | |
616 FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); | |
617 } | |
618 CFX_GraphStateData::CFX_GraphStateData() { | |
619 m_LineCap = LineCapButt; | |
620 m_DashCount = 0; | |
621 m_DashArray = NULL; | |
622 m_DashPhase = 0; | |
623 m_LineJoin = LineJoinMiter; | |
624 m_MiterLimit = 10 * 1.0f; | |
625 m_LineWidth = 1.0f; | |
626 } | |
627 CFX_GraphStateData::CFX_GraphStateData(const CFX_GraphStateData& src) { | |
628 m_DashArray = NULL; | |
629 Copy(src); | |
630 } | |
631 void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) { | |
632 m_LineCap = src.m_LineCap; | |
633 m_DashCount = src.m_DashCount; | |
634 FX_Free(m_DashArray); | |
635 m_DashArray = NULL; | |
636 m_DashPhase = src.m_DashPhase; | |
637 m_LineJoin = src.m_LineJoin; | |
638 m_MiterLimit = src.m_MiterLimit; | |
639 m_LineWidth = src.m_LineWidth; | |
640 if (m_DashCount) { | |
641 m_DashArray = FX_Alloc(FX_FLOAT, m_DashCount); | |
642 FXSYS_memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(FX_FLOAT)); | |
643 } | |
644 } | |
645 CFX_GraphStateData::~CFX_GraphStateData() { | |
646 FX_Free(m_DashArray); | |
647 } | |
648 void CFX_GraphStateData::SetDashCount(int count) { | |
649 FX_Free(m_DashArray); | |
650 m_DashArray = NULL; | |
651 m_DashCount = count; | |
652 if (count == 0) { | |
653 return; | |
654 } | |
655 m_DashArray = FX_Alloc(FX_FLOAT, count); | |
656 } | |
OLD | NEW |