| 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 |