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