summaryrefslogtreecommitdiff
path: root/src/lib/SW602GraphicShape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/SW602GraphicShape.cpp')
-rw-r--r--src/lib/SW602GraphicShape.cpp648
1 files changed, 648 insertions, 0 deletions
diff --git a/src/lib/SW602GraphicShape.cpp b/src/lib/SW602GraphicShape.cpp
new file mode 100644
index 0000000..0dee0b1
--- /dev/null
+++ b/src/lib/SW602GraphicShape.cpp
@@ -0,0 +1,648 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * This file is part of the libsw602 project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* This header contains code specific to a pict mac file
+ */
+
+#include "SW602GraphicShape.h"
+
+#include <string.h>
+
+#include <cmath>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <librevenge/librevenge.h>
+
+#include "SW602GraphicEncoder.h"
+#include "SW602GraphicStyle.h"
+#include "SW602Types.h"
+
+namespace libsw602
+{
+
+////////////////////////////////////////////////////////////
+// SW602GraphicShape::PathData
+////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &o, SW602GraphicShape::PathData const &path)
+{
+ o << path.m_type;
+ switch (path.m_type)
+ {
+ case 'H':
+ o << ":" << path.m_x[0];
+ break;
+ case 'V':
+ o << ":" << path.m_x[1];
+ break;
+ case 'M':
+ case 'L':
+ case 'T':
+ o << ":" << path.m_x;
+ break;
+ case 'Q':
+ case 'S':
+ o << ":" << path.m_x << ":" << path.m_x1;
+ break;
+ case 'C':
+ o << ":" << path.m_x << ":" << path.m_x1 << ":" << path.m_x2;
+ break;
+ case 'A':
+ o << ":" << path.m_x << ":r=" << path.m_r;
+ if (path.m_largeAngle) o << ":largeAngle";
+ if (path.m_sweep) o << ":sweep";
+ if (path.m_rotate<0 || path.m_rotate>0) o << ":rot=" << path.m_rotate;
+ case 'Z':
+ break;
+ default:
+ o << "###";
+ }
+ return o;
+}
+
+void SW602GraphicShape::PathData::translate(SW602Vec2f const &decal)
+{
+ if (m_type=='Z')
+ return;
+ m_x += decal;
+ if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T' || m_type=='A')
+ return;
+ m_x1 += decal;
+ if (m_type=='Q' || m_type=='S')
+ return;
+ m_x2 += decal;
+}
+
+void SW602GraphicShape::PathData::scale(SW602Vec2f const &scaling)
+{
+ if (m_type=='Z')
+ return;
+ m_x = SW602Vec2f(m_x[0]*scaling[0], m_x[1]*scaling[1]);
+ if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T' || m_type=='A')
+ return;
+ m_x1 = SW602Vec2f(m_x1[0]*scaling[0], m_x1[1]*scaling[1]);
+ if (m_type=='Q' || m_type=='S')
+ return;
+ m_x2 = SW602Vec2f(m_x2[0]*scaling[0], m_x2[1]*scaling[1]);
+}
+
+void SW602GraphicShape::PathData::rotate(float angle, SW602Vec2f const &decal)
+{
+ if (m_type=='Z')
+ return;
+ float angl=angle*float(M_PI/180.);
+ m_x = SW602Vec2f(std::cos(angl)*m_x[0]-std::sin(angl)*m_x[1],
+ std::sin(angl)*m_x[0]+std::cos(angl)*m_x[1])+decal;
+ if (m_type=='A')
+ {
+ m_rotate += angle;
+ return;
+ }
+ if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T')
+ return;
+ m_x1 = SW602Vec2f(std::cos(angl)*m_x1[0]-std::sin(angl)*m_x1[1],
+ std::sin(angl)*m_x1[0]+std::cos(angl)*m_x1[1])+decal;
+ if (m_type=='Q' || m_type=='S')
+ return;
+ m_x2 = SW602Vec2f(std::cos(angl)*m_x2[0]-std::sin(angl)*m_x2[1],
+ std::sin(angl)*m_x2[0]+std::cos(angl)*m_x2[1])+decal;
+}
+
+bool SW602GraphicShape::PathData::get(librevenge::RVNGPropertyList &list, SW602Vec2f const &orig) const
+{
+ list.clear();
+ std::string type("");
+ type += m_type;
+ list.insert("librevenge:path-action", type.c_str());
+ if (m_type=='Z')
+ return true;
+ if (m_type=='H')
+ {
+ list.insert("svg:x",m_x[0]-orig[0], librevenge::RVNG_POINT);
+ return true;
+ }
+ if (m_type=='V')
+ {
+ list.insert("svg:y",m_x[1]-orig[1], librevenge::RVNG_POINT);
+ return true;
+ }
+ list.insert("svg:x",m_x[0]-orig[0], librevenge::RVNG_POINT);
+ list.insert("svg:y",m_x[1]-orig[1], librevenge::RVNG_POINT);
+ if (m_type=='M' || m_type=='L' || m_type=='T')
+ return true;
+ if (m_type=='A')
+ {
+ list.insert("svg:rx",m_r[0], librevenge::RVNG_POINT);
+ list.insert("svg:ry",m_r[1], librevenge::RVNG_POINT);
+ list.insert("librevenge:large-arc", m_largeAngle);
+ list.insert("librevenge:sweep", m_sweep);
+ list.insert("librevenge:rotate", m_rotate, librevenge::RVNG_GENERIC);
+ return true;
+ }
+ list.insert("svg:x1",m_x1[0]-orig[0], librevenge::RVNG_POINT);
+ list.insert("svg:y1",m_x1[1]-orig[1], librevenge::RVNG_POINT);
+ if (m_type=='Q' || m_type=='S')
+ return true;
+ list.insert("svg:x2",m_x2[0]-orig[0], librevenge::RVNG_POINT);
+ list.insert("svg:y2",m_x2[1]-orig[1], librevenge::RVNG_POINT);
+ if (m_type=='C')
+ return true;
+ SW602_DEBUG_MSG(("SW602GraphicShape::PathData::get: unknown command %c\n", m_type));
+ list.clear();
+ return false;
+}
+
+int SW602GraphicShape::PathData::cmp(SW602GraphicShape::PathData const &a) const
+{
+ if (m_type < a.m_type) return 1;
+ if (m_type > a.m_type) return 1;
+ int diff = m_x.cmp(a.m_x);
+ if (diff) return diff;
+ diff = m_x1.cmp(a.m_x1);
+ if (diff) return diff;
+ diff = m_x2.cmp(a.m_x2);
+ if (diff) return diff;
+ diff = m_r.cmp(a.m_r);
+ if (diff) return diff;
+ if (m_rotate < a.m_rotate) return 1;
+ if (m_rotate > a.m_rotate) return -1;
+ if (m_largeAngle != a.m_largeAngle)
+ return m_largeAngle ? 1 : -1;
+ if (m_sweep != a.m_sweep)
+ return m_sweep ? 1 : -1;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////
+// SW602GraphicShape
+////////////////////////////////////////////////////////////
+SW602GraphicShape SW602GraphicShape::line(SW602Vec2f const &orig, SW602Vec2f const &dest)
+{
+ SW602GraphicShape res;
+ res.m_type = SW602GraphicShape::Line;
+ res.m_vertices.resize(2);
+ res.m_vertices[0]=orig;
+ res.m_vertices[1]=dest;
+ SW602Vec2f minPt(orig), maxPt(orig);
+ for (int c=0; c<2; ++c)
+ {
+ if (orig[c] < dest[c])
+ maxPt[c]=dest[c];
+ else
+ minPt[c]=dest[c];
+ }
+ res.m_bdBox=SW602Box2f(minPt,maxPt);
+ return res;
+}
+
+SW602GraphicShape SW602GraphicShape::measure(SW602Vec2f const &orig, SW602Vec2f const &dest)
+{
+ SW602GraphicShape res=line(orig,dest);
+ res.m_type= SW602GraphicShape::Measure;
+ return res;
+}
+
+std::ostream &operator<<(std::ostream &o, SW602GraphicShape const &sh)
+{
+ o << "box=" << sh.m_bdBox << ",";
+ switch (sh.m_type)
+ {
+ case SW602GraphicShape::Line:
+ o << "line,";
+ if (sh.m_vertices.size()!=2)
+ o << "###pts,";
+ else
+ o << "pts=" << sh.m_vertices[0] << "<->" << sh.m_vertices[1] << ",";
+ break;
+ case SW602GraphicShape::Measure:
+ o << "measure,";
+ if (sh.m_vertices.size()!=2)
+ o << "###pts,";
+ else
+ o << "pts=" << sh.m_vertices[0] << "<->" << sh.m_vertices[1] << ",";
+ break;
+ case SW602GraphicShape::Rectangle:
+ o << "rect,";
+ if (sh.m_formBox!=sh.m_bdBox)
+ o << "box[rect]=" << sh.m_formBox << ",";
+ if (sh.m_cornerWidth!=SW602Vec2f(0,0))
+ o << "corners=" << sh.m_cornerWidth << ",";
+ break;
+ case SW602GraphicShape::Circle:
+ o << "circle,";
+ break;
+ case SW602GraphicShape::Arc:
+ case SW602GraphicShape::Pie:
+ o << (sh.m_type == SW602GraphicShape::Arc ? "arc," : "pie,");
+ o << "box[ellipse]=" << sh.m_formBox << ",";
+ o << "angle=" << sh.m_arcAngles << ",";
+ break;
+ case SW602GraphicShape::Polygon:
+ o << "polygons,pts=[";
+ for (size_t pt=0; pt < sh.m_vertices.size(); ++pt)
+ o << sh.m_vertices[pt] << ",";
+ o << "],";
+ break;
+ case SW602GraphicShape::Path:
+ o << "path,pts=[";
+ for (size_t pt=0; pt < sh.m_path.size(); ++pt)
+ o << sh.m_path[pt] << ",";
+ o << "],";
+ break;
+ case SW602GraphicShape::ShapeUnknown:
+ default:
+ o << "###unknown[shape],";
+ break;
+ }
+ o << sh.m_extra;
+ return o;
+}
+
+int SW602GraphicShape::cmp(SW602GraphicShape const &a) const
+{
+ if (m_type < a.m_type) return 1;
+ if (m_type > a.m_type) return -1;
+ int diff = m_bdBox.cmp(a.m_bdBox);
+ if (diff) return diff;
+ diff = m_formBox.cmp(a.m_formBox);
+ if (diff) return diff;
+ diff = m_cornerWidth.cmp(a.m_cornerWidth);
+ if (diff) return diff;
+ diff = m_arcAngles.cmp(a.m_arcAngles);
+ if (diff) return diff;
+ if (m_vertices.size()<a.m_vertices.size()) return -1;
+ if (m_vertices.size()>a.m_vertices.size()) return -1;
+ for (size_t pt=0; pt < m_vertices.size(); ++pt)
+ {
+ diff = m_vertices[pt].cmp(a.m_vertices[pt]);
+ if (diff) return diff;
+ }
+ if (m_path.size()<a.m_path.size()) return -1;
+ if (m_path.size()>a.m_path.size()) return -1;
+ for (size_t pt=0; pt < m_path.size(); ++pt)
+ {
+ diff = m_path[pt].cmp(a.m_path[pt]);
+ if (diff) return diff;
+ }
+ return 0;
+}
+
+SW602Box2f SW602GraphicShape::getBdBox(SW602GraphicStyle const &style, bool moveToO) const
+{
+ SW602Box2f bdBox=m_bdBox;
+ if (moveToO)
+ bdBox=SW602Box2f(SW602Vec2f(0,0),m_bdBox.size());
+ if (style.hasLine())
+ bdBox.extend(style.m_lineWidth/2.f);
+ if (m_type==Line)
+ {
+ // fixme: add 4pt for each arrows
+ int numArrows=(style.m_arrows[0].isEmpty() ? 0 : 1)+(style.m_arrows[1].isEmpty() ? 0 : 1);
+ if (numArrows) bdBox.extend(float(2*numArrows));
+ }
+ return bdBox;
+}
+
+void SW602GraphicShape::translate(SW602Vec2f const &decal)
+{
+ if (decal==SW602Vec2f(0,0))
+ return;
+ m_bdBox=SW602Box2f(m_bdBox.min()+decal, m_bdBox.max()+decal);
+ m_formBox=SW602Box2f(m_formBox.min()+decal, m_formBox.max()+decal);
+ for (size_t pt=0; pt<m_vertices.size(); ++pt)
+ m_vertices[pt]+=decal;
+ for (size_t pt=0; pt<m_path.size(); ++pt)
+ m_path[pt].translate(decal);
+}
+
+void SW602GraphicShape::scale(SW602Vec2f const &scaling)
+{
+ // checkme: does not work for symetry if shape is an arc...
+ m_bdBox=SW602Box2f(SW602Vec2f(scaling[0]*m_bdBox.min()[0],scaling[1]*m_bdBox.min()[1]),
+ SW602Vec2f(scaling[0]*m_bdBox.max()[0],scaling[1]*m_bdBox.max()[1]));
+ m_formBox=SW602Box2f(SW602Vec2f(scaling[0]*m_formBox.min()[0],scaling[1]*m_formBox.min()[1]),
+ SW602Vec2f(scaling[0]*m_formBox.max()[0],scaling[1]*m_formBox.max()[1]));
+ for (size_t pt=0; pt<m_vertices.size(); ++pt)
+ m_vertices[pt]=SW602Vec2f(scaling[0]*m_vertices[pt][0],
+ scaling[1]*m_vertices[pt][1]);
+ for (size_t pt=0; pt<m_path.size(); ++pt)
+ m_path[pt].scale(scaling);
+}
+
+SW602GraphicShape SW602GraphicShape::rotate(float angle, SW602Vec2f const &center) const
+{
+ while (angle >= 360) angle -= 360;
+ while (angle <= -360) angle += 360;
+ if (angle >= -1e-3 && angle <= 1e-3) return *this;
+ float angl=angle*float(M_PI/180.);
+ SW602Vec2f decal=center-SW602Vec2f(std::cos(angl)*center[0]-std::sin(angl)*center[1],
+ std::sin(angl)*center[0]+std::cos(angl)*center[1]);
+ SW602Box2f fBox;
+ for (int i=0; i < 4; ++i)
+ {
+ SW602Vec2f pt=SW602Vec2f(m_bdBox[i%2][0],m_bdBox[i/2][1]);
+ pt = SW602Vec2f(std::cos(angl)*pt[0]-std::sin(angl)*pt[1],
+ std::sin(angl)*pt[0]+std::cos(angl)*pt[1])+decal;
+ if (i==0) fBox=SW602Box2f(pt,pt);
+ else fBox=fBox.getUnion(SW602Box2f(pt,pt));
+ }
+ SW602GraphicShape res = path(fBox);
+ res.m_path=getPath();
+ for (size_t p=0; p < res.m_path.size(); p++)
+ res.m_path[p].rotate(angle, decal);
+ return res;
+}
+
+bool SW602GraphicShape::addPathTo(SW602Vec2f const &orig, librevenge::RVNGPropertyListVector &vect) const
+{
+ SW602Vec2f decal=orig-m_bdBox[0];
+ std::vector<SW602GraphicShape::PathData> fPath=getPath();
+ size_t n=fPath.size();
+ if (!n)
+ {
+ SW602_DEBUG_MSG(("SW602GraphicShape::addPathTo: can not find the path\n"));
+ return false;
+ }
+ librevenge::RVNGPropertyList list;
+ for (size_t c=0; c < n; ++c)
+ {
+ list.clear();
+ if (fPath[c].get(list, -1.0f*decal))
+ vect.append(list);
+ }
+ if (fPath[n-1].m_type != 'Z')
+ {
+ // odg need a closed path to draw surface, so ...
+ list.clear();
+ list.insert("librevenge:path-action", "Z");
+ vect.append(list);
+ }
+ return true;
+}
+
+SW602GraphicShape::Command SW602GraphicShape::addTo(SW602Vec2f const &orig, bool asSurface, librevenge::RVNGPropertyList &propList) const
+{
+ SW602Vec2f pt;
+ librevenge::RVNGPropertyList list;
+ librevenge::RVNGPropertyListVector vect;
+ SW602Vec2f decal=orig-m_bdBox[0];
+ switch (m_type)
+ {
+ case Line:
+ case Measure:
+ if (m_vertices.size()!=2) break;
+ if (m_type==Measure)
+ propList.insert("draw:show-unit", true);
+ pt=m_vertices[0]+decal;
+ list.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+ pt=m_vertices[1]+decal;
+ list.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+ propList.insert("svg:points", vect);
+ return C_Polyline;
+ case Rectangle:
+ if (m_cornerWidth[0] > 0 && m_cornerWidth[1] > 0)
+ {
+ propList.insert("svg:rx",double(m_cornerWidth[0]), librevenge::RVNG_POINT);
+ propList.insert("svg:ry",double(m_cornerWidth[1]), librevenge::RVNG_POINT);
+ }
+ pt=m_formBox[0]+decal;
+ propList.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ propList.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ pt=m_formBox.size();
+ propList.insert("svg:width",pt.x(), librevenge::RVNG_POINT);
+ propList.insert("svg:height",pt.y(), librevenge::RVNG_POINT);
+ return C_Rectangle;
+ case Circle:
+ pt=0.5*(m_formBox[0]+m_formBox[1])+decal;
+ propList.insert("svg:cx",pt.x(), librevenge::RVNG_POINT);
+ propList.insert("svg:cy",pt.y(), librevenge::RVNG_POINT);
+ pt=0.5*(m_formBox[1]-m_formBox[0]);
+ propList.insert("svg:rx",pt.x(), librevenge::RVNG_POINT);
+ propList.insert("svg:ry",pt.y(), librevenge::RVNG_POINT);
+ return C_Ellipse;
+ case Arc:
+ case Pie:
+ {
+ SW602Vec2f center=0.5*(m_formBox[0]+m_formBox[1])+decal;
+ SW602Vec2f rad=0.5*(m_formBox[1]-m_formBox[0]);
+ float angl0=m_arcAngles[0];
+ float angl1=m_arcAngles[1];
+ if (rad[1]<0)
+ {
+ static bool first=true;
+ if (first)
+ {
+ SW602_DEBUG_MSG(("SW602GraphicShape::addTo: oops radiusY for arc is negative, inverse it\n"));
+ first=false;
+ }
+ rad[1]=-rad[1];
+ }
+ while (angl1<angl0)
+ angl1+=360.f;
+ while (angl1>angl0+360.f)
+ angl1-=360.f;
+ if (angl1-angl0>=180.f && angl1-angl0<=180.f)
+ angl1+=0.01f;
+ float angl=angl0*float(M_PI/180.);
+ bool addCenter=m_type==Pie && asSurface;
+ if (addCenter)
+ {
+ pt=center;
+ list.insert("librevenge:path-action", "M");
+ list.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+ }
+ list.clear();
+ pt=center+SW602Vec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
+ list.insert("librevenge:path-action", addCenter ? "L" : "M");
+ list.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+
+ list.clear();
+ angl=angl1*float(M_PI/180.);
+ pt=center+SW602Vec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
+ list.insert("librevenge:path-action", "A");
+ list.insert("librevenge:large-arc", !(angl1-angl0<180.f));
+ list.insert("librevenge:sweep", false);
+ list.insert("svg:rx",rad.x(), librevenge::RVNG_POINT);
+ list.insert("svg:ry",rad.y(), librevenge::RVNG_POINT);
+ list.insert("svg:x",pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y",pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+ if (asSurface)
+ {
+ list.clear();
+ list.insert("librevenge:path-action", "Z");
+ vect.append(list);
+ }
+
+ propList.insert("svg:d", vect);
+ return C_Path;
+ }
+ case Polygon:
+ {
+ size_t n=m_vertices.size();
+ if (n<2) break;
+ for (size_t i = 0; i < n; ++i)
+ {
+ list.clear();
+ pt=m_vertices[i]+decal;
+ list.insert("svg:x", pt.x(), librevenge::RVNG_POINT);
+ list.insert("svg:y", pt.y(), librevenge::RVNG_POINT);
+ vect.append(list);
+ }
+ propList.insert("svg:points", vect);
+ return asSurface ? C_Polygon : C_Polyline;
+ }
+ case Path:
+ {
+ size_t n=m_path.size();
+ if (!n) break;
+ for (size_t c=0; c < n; ++c)
+ {
+ list.clear();
+ if (m_path[c].get(list, -1.0f*decal))
+ vect.append(list);
+ }
+ if (asSurface && m_path[n-1].m_type != 'Z')
+ {
+ // odg need a closed path to draw surface, so ...
+ list.clear();
+ list.insert("librevenge:path-action", "Z");
+ vect.append(list);
+ }
+ propList.insert("svg:d", vect);
+ return C_Path;
+ }
+ case ShapeUnknown:
+ default:
+ break;
+ }
+ SW602_DEBUG_MSG(("SW602GraphicShape::addTo: can not send a shape with type=%d\n", int(m_type)));
+ return C_Bad;
+}
+
+std::vector<SW602GraphicShape::PathData> SW602GraphicShape::getPath() const
+{
+ std::vector<SW602GraphicShape::PathData> res;
+ switch (m_type)
+ {
+ case Measure:
+ SW602_DEBUG_MSG(("SW602GraphicShape::getPath: called on a measure, transform it in line\n"));
+ // fall through expected
+ case Line:
+ case Polygon:
+ {
+ size_t n=m_vertices.size();
+ if (n<2) break;
+ res.push_back(PathData('M',m_vertices[0]));
+ for (size_t i = 1; i < n; ++i)
+ res.push_back(PathData('L', m_vertices[i]));
+ break;
+ }
+ case Rectangle:
+ if (m_cornerWidth[0] > 0 && m_cornerWidth[1] > 0)
+ {
+ SW602Box2f box=m_formBox;
+ SW602Vec2f c=m_cornerWidth;
+ res.push_back(PathData('M',SW602Vec2f(box[1][0]-c[0],box[0][1])));
+ PathData data('A',SW602Vec2f(box[1][0],box[0][1]+c[1]));
+ data.m_r=c;
+ data.m_sweep=true;
+ res.push_back(data);
+ res.push_back(PathData('L',SW602Vec2f(box[1][0],box[1][1]-c[1])));
+ data.m_x=SW602Vec2f(box[1][0]-c[0],box[1][1]);
+ res.push_back(data);
+ res.push_back(PathData('L',SW602Vec2f(box[0][0]+c[0],box[1][1])));
+ data.m_x=SW602Vec2f(box[0][0],box[1][1]-c[1]);
+ res.push_back(data);
+ res.push_back(PathData('L',SW602Vec2f(box[0][0],box[0][1]+c[1])));
+ data.m_x=SW602Vec2f(box[0][0]+c[0],box[0][1]);
+ res.push_back(data);
+ res.push_back(PathData('Z'));
+ break;
+ }
+ res.push_back(PathData('M',m_formBox[0]));
+ res.push_back(PathData('L',SW602Vec2f(m_formBox[0][0],m_formBox[1][1])));
+ res.push_back(PathData('L',m_formBox[1]));
+ res.push_back(PathData('L',SW602Vec2f(m_formBox[1][0],m_formBox[0][1])));
+ res.push_back(PathData('Z'));
+ break;
+ case Circle:
+ {
+ SW602Vec2f pt0 = SW602Vec2f(m_formBox[0][0],0.5f*(m_formBox[0][1]+m_formBox[1][1]));
+ SW602Vec2f pt1 = SW602Vec2f(m_formBox[1][0],pt0[1]);
+ res.push_back(PathData('M',pt0));
+ PathData data('A',pt1);
+ data.m_r=0.5*(m_formBox[1]-m_formBox[0]);
+ data.m_largeAngle=true;
+ res.push_back(data);
+ data.m_x=pt0;
+ res.push_back(data);
+ break;
+ }
+ case Arc:
+ case Pie:
+ {
+ SW602Vec2f center=0.5*(m_formBox[0]+m_formBox[1]);
+ SW602Vec2f rad=0.5*(m_formBox[1]-m_formBox[0]);
+ float angl0=m_arcAngles[0];
+ float angl1=m_arcAngles[1];
+ if (rad[1]<0)
+ {
+ static bool first=true;
+ if (first)
+ {
+ SW602_DEBUG_MSG(("SW602GraphicShape::getPath: oops radiusY for arc is negative, inverse it\n"));
+ first=false;
+ }
+ rad[1]=-rad[1];
+ }
+ while (angl1<angl0)
+ angl1+=360.f;
+ while (angl1>angl0+360.f)
+ angl1-=360.f;
+ if (angl1-angl0>=180.f && angl1-angl0<=180.f)
+ angl1+=0.01f;
+ float angl=angl0*float(M_PI/180.);
+ bool addCenter=m_type==Pie;
+ if (addCenter)
+ res.push_back(PathData('M', center));
+ SW602Vec2f pt=center+SW602Vec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
+ res.push_back(PathData(addCenter ? 'L' : 'M', pt));
+ angl=angl1*float(M_PI/180.);
+ pt=center+SW602Vec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
+ PathData data('A',pt);
+ data.m_largeAngle=(angl1-angl0>=180.f);
+ data.m_r=rad;
+ res.push_back(data);
+ break;
+ }
+ case Path:
+ return m_path;
+ case ShapeUnknown:
+ default:
+ SW602_DEBUG_MSG(("SW602GraphicShape::getPath: unexpected type\n"));
+ break;
+ }
+ return res;
+}
+
+}
+
+/* vim:set shiftwidth=2 softtabstop=2 expandtab: */