Blame src/lib/MWAWGraphicShape.cxx

rpm-build 6f7582
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
rpm-build 6f7582
rpm-build 6f7582
/* libmwaw
rpm-build 6f7582
* Version: MPL 2.0 / LGPLv2+
rpm-build 6f7582
*
rpm-build 6f7582
* The contents of this file are subject to the Mozilla Public License Version
rpm-build 6f7582
* 2.0 (the "License"); you may not use this file except in compliance with
rpm-build 6f7582
* the License or as specified alternatively below. You may obtain a copy of
rpm-build 6f7582
* the License at http://www.mozilla.org/MPL/
rpm-build 6f7582
*
rpm-build 6f7582
* Software distributed under the License is distributed on an "AS IS" basis,
rpm-build 6f7582
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
rpm-build 6f7582
* for the specific language governing rights and limitations under the
rpm-build 6f7582
* License.
rpm-build 6f7582
*
rpm-build 6f7582
* Major Contributor(s):
rpm-build 6f7582
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
rpm-build 6f7582
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
rpm-build 6f7582
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
rpm-build 6f7582
* Copyright (C) 2006, 2007 Andrew Ziem
rpm-build 6f7582
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
rpm-build 6f7582
*
rpm-build 6f7582
*
rpm-build 6f7582
* All Rights Reserved.
rpm-build 6f7582
*
rpm-build 6f7582
* For minor contributions see the git repository.
rpm-build 6f7582
*
rpm-build 6f7582
* Alternatively, the contents of this file may be used under the terms of
rpm-build 6f7582
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
rpm-build 6f7582
* in which case the provisions of the LGPLv2+ are applicable
rpm-build 6f7582
* instead of those above.
rpm-build 6f7582
*/
rpm-build 6f7582
rpm-build 6f7582
/* This header contains code specific to a pict mac file
rpm-build 6f7582
 */
rpm-build 6f7582
#include <string.h>
rpm-build 6f7582
rpm-build 6f7582
#include <algorithm>
rpm-build 6f7582
#include <cmath>
rpm-build 6f7582
#include <cstring>
rpm-build 6f7582
#include <iomanip>
rpm-build 6f7582
#include <iostream>
rpm-build 6f7582
#include <sstream>
rpm-build 6f7582
#include <string>
rpm-build 6f7582
#include <utility>
rpm-build 6f7582
rpm-build 6f7582
#include <librevenge/librevenge.h>
rpm-build 6f7582
rpm-build 6f7582
#include "libmwaw_internal.hxx"
rpm-build 6f7582
rpm-build 6f7582
#include "MWAWGraphicEncoder.hxx"
rpm-build 6f7582
#include "MWAWGraphicStyle.hxx"
rpm-build 6f7582
rpm-build 6f7582
#include "MWAWGraphicShape.hxx"
rpm-build 6f7582
rpm-build 6f7582
////////////////////////////////////////////////////////////
rpm-build 6f7582
// MWAWGraphicShape::PathData
rpm-build 6f7582
////////////////////////////////////////////////////////////
rpm-build 6f7582
std::ostream &operator<<(std::ostream &o, MWAWGraphicShape::PathData const &path)
rpm-build 6f7582
{
rpm-build 6f7582
  o << path.m_type;
rpm-build 6f7582
  switch (path.m_type) {
rpm-build 6f7582
  case 'H':
rpm-build 6f7582
    o << ":" << path.m_x[0];
rpm-build 6f7582
    break;
rpm-build 6f7582
  case 'V':
rpm-build 6f7582
    o << ":" << path.m_x[1];
rpm-build 6f7582
    break;
rpm-build 6f7582
  case 'M':
rpm-build 6f7582
  case 'L':
rpm-build 6f7582
  case 'T':
rpm-build 6f7582
    o << ":" << path.m_x;
rpm-build 6f7582
    break;
rpm-build 6f7582
  case 'Q':
rpm-build 6f7582
  case 'S':
rpm-build 6f7582
    o << ":" << path.m_x << ":" << path.m_x1;
rpm-build 6f7582
    break;
rpm-build 6f7582
  case 'C':
rpm-build 6f7582
    o << ":" << path.m_x << ":" << path.m_x1 << ":" << path.m_x2;
rpm-build 6f7582
    break;
rpm-build 6f7582
  case 'A':
rpm-build 6f7582
    o << ":" << path.m_x << ":r=" << path.m_r;
rpm-build 6f7582
    if (path.m_largeAngle) o << ":largeAngle";
rpm-build 6f7582
    if (path.m_sweep) o << ":sweep";
rpm-build 6f7582
    if (path.m_rotate<0 || path.m_rotate>0) o << ":rot=" << path.m_rotate;
rpm-build 6f7582
  case 'Z':
rpm-build 6f7582
    break;
rpm-build 6f7582
  default:
rpm-build 6f7582
    o << "###";
rpm-build 6f7582
  }
rpm-build 6f7582
  return o;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::PathData::translate(MWAWVec2f const &decal)
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type=='Z')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x += decal;
rpm-build 6f7582
  if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T' || m_type=='A')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x1 += decal;
rpm-build 6f7582
  if (m_type=='Q' || m_type=='S')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x2 += decal;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::PathData::scale(MWAWVec2f const &scaling)
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type=='Z')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x = MWAWVec2f(m_x[0]*scaling[0], m_x[1]*scaling[1]);
rpm-build 6f7582
  if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T' || m_type=='A')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x1 = MWAWVec2f(m_x1[0]*scaling[0], m_x1[1]*scaling[1]);
rpm-build 6f7582
  if (m_type=='Q' || m_type=='S')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x2 = MWAWVec2f(m_x2[0]*scaling[0], m_x2[1]*scaling[1]);
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::PathData::rotate(float angle, MWAWVec2f const &decal)
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type=='Z')
rpm-build 6f7582
    return;
rpm-build 6f7582
  float angl=angle*float(M_PI/180.);
rpm-build 6f7582
  m_x = MWAWVec2f(std::cos(angl)*m_x[0]-std::sin(angl)*m_x[1],
rpm-build 6f7582
                  std::sin(angl)*m_x[0]+std::cos(angl)*m_x[1])+decal;
rpm-build 6f7582
  if (m_type=='A') {
rpm-build 6f7582
    m_rotate += angle;
rpm-build 6f7582
    return;
rpm-build 6f7582
  }
rpm-build 6f7582
  if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x1 = MWAWVec2f(std::cos(angl)*m_x1[0]-std::sin(angl)*m_x1[1],
rpm-build 6f7582
                   std::sin(angl)*m_x1[0]+std::cos(angl)*m_x1[1])+decal;
rpm-build 6f7582
  if (m_type=='Q' || m_type=='S')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x2 = MWAWVec2f(std::cos(angl)*m_x2[0]-std::sin(angl)*m_x2[1],
rpm-build 6f7582
                   std::sin(angl)*m_x2[0]+std::cos(angl)*m_x2[1])+decal;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::PathData::transform(MWAWTransformation const &matrix, float rotation)
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type=='Z')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x = matrix*m_x;
rpm-build 6f7582
  if (m_type=='A') {
rpm-build 6f7582
    m_rotate += rotation;
rpm-build 6f7582
    return;
rpm-build 6f7582
  }
rpm-build 6f7582
  if (m_type=='H' || m_type=='V' || m_type=='M' || m_type=='L' || m_type=='T')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x1 = matrix*m_x1;
rpm-build 6f7582
  if (m_type=='Q' || m_type=='S')
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_x2 = matrix*m_x2;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
bool MWAWGraphicShape::PathData::get(librevenge::RVNGPropertyList &list, MWAWVec2f const &orig) const
rpm-build 6f7582
{
rpm-build 6f7582
  list.clear();
rpm-build 6f7582
  std::string type("");
rpm-build 6f7582
  type += m_type;
rpm-build 6f7582
  list.insert("librevenge:path-action", type.c_str());
rpm-build 6f7582
  if (m_type=='Z')
rpm-build 6f7582
    return true;
rpm-build 6f7582
  if (m_type=='H') {
rpm-build 6f7582
    list.insert("svg:x",double(m_x[0]-orig[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
    return true;
rpm-build 6f7582
  }
rpm-build 6f7582
  if (m_type=='V') {
rpm-build 6f7582
    list.insert("svg:y",double(m_x[1]-orig[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
    return true;
rpm-build 6f7582
  }
rpm-build 6f7582
  list.insert("svg:x",double(m_x[0]-orig[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
  list.insert("svg:y",double(m_x[1]-orig[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
  if (m_type=='M' || m_type=='L' || m_type=='T')
rpm-build 6f7582
    return true;
rpm-build 6f7582
  if (m_type=='A') {
rpm-build 6f7582
    list.insert("svg:rx",double(m_r[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:ry",double(m_r[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("librevenge:large-arc", m_largeAngle);
rpm-build 6f7582
    list.insert("librevenge:sweep", m_sweep);
rpm-build 6f7582
    list.insert("librevenge:rotate", double(m_rotate), librevenge::RVNG_GENERIC);
rpm-build 6f7582
    return true;
rpm-build 6f7582
  }
rpm-build 6f7582
  list.insert("svg:x1",double(m_x1[0]-orig[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
  list.insert("svg:y1",double(m_x1[1]-orig[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
  if (m_type=='Q' || m_type=='S')
rpm-build 6f7582
    return true;
rpm-build 6f7582
  list.insert("svg:x2",double(m_x2[0]-orig[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
  list.insert("svg:y2",double(m_x2[1]-orig[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
  if (m_type=='C')
rpm-build 6f7582
    return true;
rpm-build 6f7582
  MWAW_DEBUG_MSG(("MWAWGraphicShape::PathData::get: unknown command %c\n", m_type));
rpm-build 6f7582
  list.clear();
rpm-build 6f7582
  return false;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
int MWAWGraphicShape::PathData::cmp(MWAWGraphicShape::PathData const &a) const
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type < a.m_type) return 1;
rpm-build 6f7582
  if (m_type > a.m_type) return 1;
rpm-build 6f7582
  int diff = m_x.cmp(a.m_x);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  diff = m_x1.cmp(a.m_x1);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  diff = m_x2.cmp(a.m_x2);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  diff = m_r.cmp(a.m_r);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  if (m_rotate < a.m_rotate) return 1;
rpm-build 6f7582
  if (m_rotate > a.m_rotate) return -1;
rpm-build 6f7582
  if (m_largeAngle != a.m_largeAngle)
rpm-build 6f7582
    return m_largeAngle ? 1 : -1;
rpm-build 6f7582
  if (m_sweep != a.m_sweep)
rpm-build 6f7582
    return m_sweep ? 1 : -1;
rpm-build 6f7582
  return 0;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
////////////////////////////////////////////////////////////
rpm-build 6f7582
// MWAWGraphicShape
rpm-build 6f7582
////////////////////////////////////////////////////////////
rpm-build 6f7582
MWAWGraphicShape::~MWAWGraphicShape()
rpm-build 6f7582
{
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWGraphicShape MWAWGraphicShape::line(MWAWVec2f const &orig, MWAWVec2f const &dest)
rpm-build 6f7582
{
rpm-build 6f7582
  MWAWGraphicShape res;
rpm-build 6f7582
  res.m_type = MWAWGraphicShape::Line;
rpm-build 6f7582
  res.m_vertices.resize(2);
rpm-build 6f7582
  res.m_vertices[0]=orig;
rpm-build 6f7582
  res.m_vertices[1]=dest;
rpm-build 6f7582
  MWAWVec2f minPt(orig), maxPt(orig);
rpm-build 6f7582
  for (int c=0; c<2; ++c) {
rpm-build 6f7582
    if (orig[c] < dest[c])
rpm-build 6f7582
      maxPt[c]=dest[c];
rpm-build 6f7582
    else
rpm-build 6f7582
      minPt[c]=dest[c];
rpm-build 6f7582
  }
rpm-build 6f7582
  res.m_bdBox=MWAWBox2f(minPt,maxPt);
rpm-build 6f7582
  return res;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWGraphicShape MWAWGraphicShape::measure(MWAWVec2f const &orig, MWAWVec2f const &dest)
rpm-build 6f7582
{
rpm-build 6f7582
  MWAWGraphicShape res=line(orig,dest);
rpm-build 6f7582
  res.m_type= MWAWGraphicShape::Measure;
rpm-build 6f7582
  return res;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
std::ostream &operator<<(std::ostream &o, MWAWGraphicShape const &sh)
rpm-build 6f7582
{
rpm-build 6f7582
  o << "box=" << sh.m_bdBox << ",";
rpm-build 6f7582
  switch (sh.m_type) {
rpm-build 6f7582
  case MWAWGraphicShape::Line:
rpm-build 6f7582
    o << "line,";
rpm-build 6f7582
    if (sh.m_vertices.size()!=2)
rpm-build 6f7582
      o << "###pts,";
rpm-build 6f7582
    else
rpm-build 6f7582
      o << "pts=" << sh.m_vertices[0] << "<->" << sh.m_vertices[1] << ",";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Measure:
rpm-build 6f7582
    o << "measure,";
rpm-build 6f7582
    if (sh.m_vertices.size()!=2)
rpm-build 6f7582
      o << "###pts,";
rpm-build 6f7582
    else
rpm-build 6f7582
      o << "pts=" << sh.m_vertices[0] << "<->" << sh.m_vertices[1] << ",";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Rectangle:
rpm-build 6f7582
    o << "rect,";
rpm-build 6f7582
    if (sh.m_formBox!=sh.m_bdBox)
rpm-build 6f7582
      o << "box[rect]=" << sh.m_formBox << ",";
rpm-build 6f7582
    if (sh.m_cornerWidth!=MWAWVec2f(0,0))
rpm-build 6f7582
      o << "corners=" << sh.m_cornerWidth << ",";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Circle:
rpm-build 6f7582
    o << "circle,";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Arc:
rpm-build 6f7582
  case MWAWGraphicShape::Pie:
rpm-build 6f7582
    o << (sh.m_type == MWAWGraphicShape::Arc ? "arc," : "pie,");
rpm-build 6f7582
    o << "box[ellipse]=" << sh.m_formBox << ",";
rpm-build 6f7582
    o << "angle=" << sh.m_arcAngles << ",";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Polygon:
rpm-build 6f7582
  case MWAWGraphicShape::Polyline:
rpm-build 6f7582
    if (sh.m_type==MWAWGraphicShape::Polygon)
rpm-build 6f7582
      o << "polygon,pts=[";
rpm-build 6f7582
    else
rpm-build 6f7582
      o << "polyline,pts=[";
rpm-build 6f7582
    for (auto const &pt : sh.m_vertices)
rpm-build 6f7582
      o << pt << ",";
rpm-build 6f7582
    o << "],";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::Path:
rpm-build 6f7582
    o << "path,pts=[";
rpm-build 6f7582
    for (auto const &pt : sh.m_path)
rpm-build 6f7582
      o << pt << ",";
rpm-build 6f7582
    o << "],";
rpm-build 6f7582
    break;
rpm-build 6f7582
  case MWAWGraphicShape::ShapeUnknown:
rpm-build 6f7582
#if !defined(__clang__)
rpm-build 6f7582
  default:
rpm-build 6f7582
#endif
rpm-build 6f7582
    o << "###unknown[shape],";
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  o << sh.m_extra;
rpm-build 6f7582
  return o;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
int MWAWGraphicShape::cmp(MWAWGraphicShape const &a) const
rpm-build 6f7582
{
rpm-build 6f7582
  if (m_type < a.m_type) return 1;
rpm-build 6f7582
  if (m_type > a.m_type) return -1;
rpm-build 6f7582
  if (m_bdBox < a.m_bdBox) return 1;
rpm-build 6f7582
  if (m_bdBox > a.m_bdBox) return -1;
rpm-build 6f7582
  if (m_formBox < a.m_formBox) return 1;
rpm-build 6f7582
  if (m_formBox > a.m_formBox) return -1;
rpm-build 6f7582
  int diff = m_cornerWidth.cmp(a.m_cornerWidth);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  diff = m_arcAngles.cmp(a.m_arcAngles);
rpm-build 6f7582
  if (diff) return diff;
rpm-build 6f7582
  if (m_vertices.size()
rpm-build 6f7582
  if (m_vertices.size()>a.m_vertices.size()) return -1;
rpm-build 6f7582
  for (size_t pt=0; pt < m_vertices.size(); ++pt) {
rpm-build 6f7582
    diff = m_vertices[pt].cmp(a.m_vertices[pt]);
rpm-build 6f7582
    if (diff) return diff;
rpm-build 6f7582
  }
rpm-build 6f7582
  if (m_path.size()
rpm-build 6f7582
  if (m_path.size()>a.m_path.size()) return -1;
rpm-build 6f7582
  for (size_t pt=0; pt < m_path.size(); ++pt) {
rpm-build 6f7582
    diff = m_path[pt].cmp(a.m_path[pt]);
rpm-build 6f7582
    if (diff) return diff;
rpm-build 6f7582
  }
rpm-build 6f7582
  return 0;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWBox2f MWAWGraphicShape::getBdBox(MWAWGraphicStyle const &style, bool moveToO) const
rpm-build 6f7582
{
rpm-build 6f7582
  MWAWBox2f bdBox=m_bdBox;
rpm-build 6f7582
  if (moveToO)
rpm-build 6f7582
    bdBox=MWAWBox2f(MWAWVec2f(0,0),m_bdBox.size());
rpm-build 6f7582
  if (style.hasLine())
rpm-build 6f7582
    bdBox.extend(style.m_lineWidth/2.f);
rpm-build 6f7582
  if (m_type==Line) {
rpm-build 6f7582
    // fixme: add 4pt for each arrows
rpm-build 6f7582
    int numArrows=(style.m_arrows[0].isEmpty() ? 0 : 1)+(style.m_arrows[1].isEmpty() ? 0 : 1);
rpm-build 6f7582
    if (numArrows) bdBox.extend(float(2*numArrows));
rpm-build 6f7582
  }
rpm-build 6f7582
  return bdBox;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::translate(MWAWVec2f const &decal)
rpm-build 6f7582
{
rpm-build 6f7582
  if (decal==MWAWVec2f(0,0))
rpm-build 6f7582
    return;
rpm-build 6f7582
  m_bdBox=MWAWBox2f(m_bdBox.min()+decal, m_bdBox.max()+decal);
rpm-build 6f7582
  m_formBox=MWAWBox2f(m_formBox.min()+decal, m_formBox.max()+decal);
rpm-build 6f7582
  for (auto &pt : m_vertices)
rpm-build 6f7582
    pt+=decal;
rpm-build 6f7582
  for (auto &pt : m_path)
rpm-build 6f7582
    pt.translate(decal);
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
void MWAWGraphicShape::scale(MWAWVec2f const &scaling)
rpm-build 6f7582
{
rpm-build 6f7582
  // checkme: does not work for symetry if shape is an arc...
rpm-build 6f7582
  m_bdBox=MWAWBox2f(MWAWVec2f(scaling[0]*m_bdBox.min()[0],scaling[1]*m_bdBox.min()[1]),
rpm-build 6f7582
                    MWAWVec2f(scaling[0]*m_bdBox.max()[0],scaling[1]*m_bdBox.max()[1]));
rpm-build 6f7582
  m_formBox=MWAWBox2f(MWAWVec2f(scaling[0]*m_formBox.min()[0],scaling[1]*m_formBox.min()[1]),
rpm-build 6f7582
                      MWAWVec2f(scaling[0]*m_formBox.max()[0],scaling[1]*m_formBox.max()[1]));
rpm-build 6f7582
  for (auto &pt : m_vertices)
rpm-build 6f7582
    pt=MWAWVec2f(scaling[0]*pt[0], scaling[1]*pt[1]);
rpm-build 6f7582
  for (auto &pt : m_path)
rpm-build 6f7582
    pt.scale(scaling);
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWGraphicShape MWAWGraphicShape::rotate(float angle, MWAWVec2f const &center) const
rpm-build 6f7582
{
rpm-build 6f7582
  while (angle >= 360) angle -= 360;
rpm-build 6f7582
  while (angle <= -360) angle += 360;
rpm-build 6f7582
  if (angle >= -1.e-3f && angle <= 1.e-3f) return *this;
rpm-build 6f7582
  float angl=angle*float(M_PI/180.);
rpm-build 6f7582
  MWAWVec2f decal=center-MWAWVec2f(std::cos(angl)*center[0]-std::sin(angl)*center[1],
rpm-build 6f7582
                                   std::sin(angl)*center[0]+std::cos(angl)*center[1]);
rpm-build 6f7582
  MWAWBox2f fBox;
rpm-build 6f7582
  for (int i=0; i < 4; ++i) {
rpm-build 6f7582
    MWAWVec2f pt=MWAWVec2f(m_bdBox[i%2][0],m_bdBox[i/2][1]);
rpm-build 6f7582
    pt = MWAWVec2f(std::cos(angl)*pt[0]-std::sin(angl)*pt[1],
rpm-build 6f7582
                   std::sin(angl)*pt[0]+std::cos(angl)*pt[1])+decal;
rpm-build 6f7582
    if (i==0) fBox=MWAWBox2f(pt,pt);
rpm-build 6f7582
    else fBox=fBox.getUnion(MWAWBox2f(pt,pt));
rpm-build 6f7582
  }
rpm-build 6f7582
  MWAWGraphicShape res = path(fBox);
rpm-build 6f7582
  res.m_path=getPath(false);
rpm-build 6f7582
  for (auto &pt : res.m_path)
rpm-build 6f7582
    pt.rotate(angle, decal);
rpm-build 6f7582
  return res;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWGraphicShape MWAWGraphicShape::transform(MWAWTransformation const &matrix) const
rpm-build 6f7582
{
rpm-build 6f7582
  if (matrix.isIdentity()) return *this;
rpm-build 6f7582
  if (matrix[0][1]<=0 && matrix[0][1]>=0 && matrix[1][0]<=0 && matrix[1][0]>=0) {
rpm-build 6f7582
    MWAWGraphicShape res=*this;
rpm-build 6f7582
    if (matrix[0][0]<1 || matrix[0][0]>1 || matrix[1][1]<1 || matrix[1][1]>1)
rpm-build 6f7582
      res.scale(MWAWVec2f(matrix[0][0], matrix[1][1]));
rpm-build 6f7582
    res.translate(MWAWVec2f(matrix[0][2],matrix[1][2]));
rpm-build 6f7582
    return res;
rpm-build 6f7582
  }
rpm-build 6f7582
rpm-build 6f7582
  MWAWBox2f fBox;
rpm-build 6f7582
  for (int i=0; i < 4; ++i) {
rpm-build 6f7582
    MWAWVec2f pt = matrix*MWAWVec2f(m_bdBox[i%2][0],m_bdBox[i/2][1]);
rpm-build 6f7582
    if (i==0) fBox=MWAWBox2f(pt,pt);
rpm-build 6f7582
    else fBox=fBox.getUnion(MWAWBox2f(pt,pt));
rpm-build 6f7582
  }
rpm-build 6f7582
  MWAWGraphicShape res = path(fBox);
rpm-build 6f7582
  res.m_path=getPath(true);
rpm-build 6f7582
rpm-build 6f7582
  MWAWTransformation transf;
rpm-build 6f7582
  float rotation=0;
rpm-build 6f7582
  MWAWVec2f shearing;
rpm-build 6f7582
  if (!matrix.decompose(rotation,shearing,transf,fBox.center()))
rpm-build 6f7582
    rotation=0;
rpm-build 6f7582
  for (auto &pt : res.m_path)
rpm-build 6f7582
    pt.transform(matrix, rotation);
rpm-build 6f7582
  return res;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
bool MWAWGraphicShape::addPathTo(MWAWVec2f const &orig, librevenge::RVNGPropertyListVector &vect) const
rpm-build 6f7582
{
rpm-build 6f7582
  MWAWVec2f decal=orig-m_bdBox[0];
rpm-build 6f7582
  std::vector<MWAWGraphicShape::PathData> fPath=getPath(false);
rpm-build 6f7582
  size_t n=fPath.size();
rpm-build 6f7582
  if (!n) {
rpm-build 6f7582
    MWAW_DEBUG_MSG(("MWAWGraphicShape::addPathTo: can not find the path\n"));
rpm-build 6f7582
    return false;
rpm-build 6f7582
  }
rpm-build 6f7582
  librevenge::RVNGPropertyList list;
rpm-build 6f7582
  for (auto const &pt : fPath) {
rpm-build 6f7582
    list.clear();
rpm-build 6f7582
    if (pt.get(list, -1.0f*decal))
rpm-build 6f7582
      vect.append(list);
rpm-build 6f7582
  }
rpm-build 6f7582
  if (fPath[n-1].m_type != 'Z') {
rpm-build 6f7582
    // odg need a closed path to draw surface, so ...
rpm-build 6f7582
    list.clear();
rpm-build 6f7582
    list.insert("librevenge:path-action", "Z");
rpm-build 6f7582
    vect.append(list);
rpm-build 6f7582
  }
rpm-build 6f7582
  return true;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
MWAWGraphicShape::Command MWAWGraphicShape::addTo(MWAWVec2f const &orig, bool asSurface, librevenge::RVNGPropertyList &propList) const
rpm-build 6f7582
{
rpm-build 6f7582
  MWAWVec2f pt;
rpm-build 6f7582
  librevenge::RVNGPropertyList list;
rpm-build 6f7582
  librevenge::RVNGPropertyListVector vect;
rpm-build 6f7582
  MWAWVec2f decal=orig-m_bdBox[0];
rpm-build 6f7582
  switch (m_type) {
rpm-build 6f7582
  case Line:
rpm-build 6f7582
  case Measure:
rpm-build 6f7582
    if (m_vertices.size()!=2) break;
rpm-build 6f7582
    if (m_type==Measure)
rpm-build 6f7582
      propList.insert("draw:show-unit", true);
rpm-build 6f7582
    pt=m_vertices[0]+decal;
rpm-build 6f7582
    list.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    vect.append(list);
rpm-build 6f7582
    pt=m_vertices[1]+decal;
rpm-build 6f7582
    list.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    vect.append(list);
rpm-build 6f7582
    propList.insert("svg:points", vect);
rpm-build 6f7582
    return C_Polyline;
rpm-build 6f7582
  case Rectangle:
rpm-build 6f7582
    if (m_cornerWidth[0] > 0 && m_cornerWidth[1] > 0) {
rpm-build 6f7582
      propList.insert("svg:rx",double(m_cornerWidth[0]), librevenge::RVNG_POINT);
rpm-build 6f7582
      propList.insert("svg:ry",double(m_cornerWidth[1]), librevenge::RVNG_POINT);
rpm-build 6f7582
    }
rpm-build 6f7582
    pt=m_formBox[0]+decal;
rpm-build 6f7582
    propList.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    propList.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    pt=m_formBox.size();
rpm-build 6f7582
    propList.insert("svg:width",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    propList.insert("svg:height",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    return C_Rectangle;
rpm-build 6f7582
  case Circle:
rpm-build 6f7582
    pt=0.5f*(m_formBox[0]+m_formBox[1])+decal;
rpm-build 6f7582
    propList.insert("svg:cx",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    propList.insert("svg:cy",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    pt=0.5f*(m_formBox[1]-m_formBox[0]);
rpm-build 6f7582
    propList.insert("svg:rx",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    propList.insert("svg:ry",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    return C_Ellipse;
rpm-build 6f7582
  case Arc:
rpm-build 6f7582
  case Pie: {
rpm-build 6f7582
    MWAWVec2f center=0.5f*(m_formBox[0]+m_formBox[1])+decal;
rpm-build 6f7582
    MWAWVec2f rad=0.5f*(m_formBox[1]-m_formBox[0]);
rpm-build 6f7582
    float angl0=m_arcAngles[0];
rpm-build 6f7582
    float angl1=m_arcAngles[1];
rpm-build 6f7582
    if (rad[1]<0) {
rpm-build 6f7582
      static bool first=true;
rpm-build 6f7582
      if (first) {
rpm-build 6f7582
        MWAW_DEBUG_MSG(("MWAWGraphicShape::addTo: oops radiusY for arc is negative, inverse it\n"));
rpm-build 6f7582
        first=false;
rpm-build 6f7582
      }
rpm-build 6f7582
      rad[1]=-rad[1];
rpm-build 6f7582
    }
rpm-build 6f7582
    while (angl1
rpm-build 6f7582
      angl1+=360.f;
rpm-build 6f7582
    while (angl1>angl0+360.f)
rpm-build 6f7582
      angl1-=360.f;
rpm-build 6f7582
    if (angl1-angl0>=180.f && angl1-angl0<=180.f)
rpm-build 6f7582
      angl1+=0.01f;
rpm-build 6f7582
    float angl=angl0*float(M_PI/180.);
rpm-build 6f7582
    bool addCenter=m_type==Pie && asSurface;
rpm-build 6f7582
    if (addCenter) {
rpm-build 6f7582
      pt=center;
rpm-build 6f7582
      list.insert("librevenge:path-action", "M");
rpm-build 6f7582
      list.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
      list.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
      vect.append(list);
rpm-build 6f7582
    }
rpm-build 6f7582
    list.clear();
rpm-build 6f7582
    pt=center+MWAWVec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
rpm-build 6f7582
    list.insert("librevenge:path-action", addCenter ? "L" : "M");
rpm-build 6f7582
    list.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    vect.append(list);
rpm-build 6f7582
rpm-build 6f7582
    list.clear();
rpm-build 6f7582
    angl=angl1*float(M_PI/180.);
rpm-build 6f7582
    pt=center+MWAWVec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
rpm-build 6f7582
    list.insert("librevenge:path-action", "A");
rpm-build 6f7582
    list.insert("librevenge:large-arc", !(angl1-angl0<180.f));
rpm-build 6f7582
    list.insert("librevenge:sweep", false);
rpm-build 6f7582
    list.insert("svg:rx",double(rad.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:ry",double(rad.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:x",double(pt.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
    list.insert("svg:y",double(pt.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
    vect.append(list);
rpm-build 6f7582
    if (asSurface) {
rpm-build 6f7582
      list.clear();
rpm-build 6f7582
      list.insert("librevenge:path-action", "Z");
rpm-build 6f7582
      vect.append(list);
rpm-build 6f7582
    }
rpm-build 6f7582
rpm-build 6f7582
    propList.insert("svg:d", vect);
rpm-build 6f7582
    return C_Path;
rpm-build 6f7582
  }
rpm-build 6f7582
  case Polygon:
rpm-build 6f7582
  case Polyline: {
rpm-build 6f7582
    size_t n=m_vertices.size();
rpm-build 6f7582
    if (n<2) break;
rpm-build 6f7582
    for (auto point : m_vertices) {
rpm-build 6f7582
      list.clear();
rpm-build 6f7582
      point += decal;
rpm-build 6f7582
      list.insert("svg:x", double(point.x()), librevenge::RVNG_POINT);
rpm-build 6f7582
      list.insert("svg:y", double(point.y()), librevenge::RVNG_POINT);
rpm-build 6f7582
      vect.append(list);
rpm-build 6f7582
    }
rpm-build 6f7582
    propList.insert("svg:points", vect);
rpm-build 6f7582
    return (asSurface && m_type==Polygon) ? C_Polygon : C_Polyline;
rpm-build 6f7582
  }
rpm-build 6f7582
  case Path: {
rpm-build 6f7582
    size_t n=m_path.size();
rpm-build 6f7582
    if (!n) break;
rpm-build 6f7582
    for (auto const &point : m_path) {
rpm-build 6f7582
      list.clear();
rpm-build 6f7582
      if (point.get(list, -1.0f*decal))
rpm-build 6f7582
        vect.append(list);
rpm-build 6f7582
    }
rpm-build 6f7582
    if (asSurface && m_path[n-1].m_type != 'Z') {
rpm-build 6f7582
      // odg need a closed path to draw surface, so ...
rpm-build 6f7582
      list.clear();
rpm-build 6f7582
      list.insert("librevenge:path-action", "Z");
rpm-build 6f7582
      vect.append(list);
rpm-build 6f7582
    }
rpm-build 6f7582
    propList.insert("svg:d", vect);
rpm-build 6f7582
    return C_Path;
rpm-build 6f7582
  }
rpm-build 6f7582
  case ShapeUnknown:
rpm-build 6f7582
#if !defined(__clang__)
rpm-build 6f7582
  default:
rpm-build 6f7582
#endif
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  MWAW_DEBUG_MSG(("MWAWGraphicShape::addTo: can not send a shape with type=%d\n", int(m_type)));
rpm-build 6f7582
  return C_Bad;
rpm-build 6f7582
}
rpm-build 6f7582
rpm-build 6f7582
std::vector<MWAWGraphicShape::PathData> MWAWGraphicShape::getPath(bool forTransformation) const
rpm-build 6f7582
{
rpm-build 6f7582
  std::vector<MWAWGraphicShape::PathData> res;
rpm-build 6f7582
  float const delta=0.55228f;
rpm-build 6f7582
  switch (m_type) {
rpm-build 6f7582
  case Measure:
rpm-build 6f7582
    MWAW_DEBUG_MSG(("MWAWGraphicShape::getPath: called on a measure, transform it in line\n"));
rpm-build 6f7582
    MWAW_FALLTHROUGH;
rpm-build 6f7582
  case Line:
rpm-build 6f7582
  case Polygon:
rpm-build 6f7582
  case Polyline: {
rpm-build 6f7582
    size_t n=m_vertices.size();
rpm-build 6f7582
    if (n<2) break;
rpm-build 6f7582
    res.push_back(PathData('M',m_vertices[0]));
rpm-build 6f7582
    for (size_t i = 1; i < n; ++i)
rpm-build 6f7582
      res.push_back(PathData('L', m_vertices[i]));
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  case Rectangle:
rpm-build 6f7582
    if (m_cornerWidth[0] > 0 && m_cornerWidth[1] > 0) {
rpm-build 6f7582
      MWAWBox2f box=m_formBox;
rpm-build 6f7582
      if (box.min()[0]>box.max()[0]) std::swap(box.min()[0],box.max()[0]);
rpm-build 6f7582
      if (box.min()[1]>box.max()[1]) std::swap(box.min()[1],box.max()[1]);
rpm-build 6f7582
      MWAWVec2f c=m_cornerWidth;
rpm-build 6f7582
      if (2*c[0]>box.size()[0]) c[0]=0.5f*box.size()[0];
rpm-build 6f7582
      if (2*c[1]>box.size()[1]) c[1]=0.5f*box.size()[1];
rpm-build 6f7582
      if (forTransformation) {
rpm-build 6f7582
        MWAWVec2f pt0(box[1][0]-c[0],box[0][1]);
rpm-build 6f7582
        res.push_back(PathData('M',pt0));
rpm-build 6f7582
        MWAWVec2f pt1(box[1][0],box[0][1]+c[1]);
rpm-build 6f7582
        res.push_back(PathData('C',pt1,pt0+MWAWVec2f(delta*c[0],0),pt1-MWAWVec2f(0,delta*c[1])));
rpm-build 6f7582
        pt0=MWAWVec2f(box[1][0],box[1][1]-c[1]);
rpm-build 6f7582
        res.push_back(PathData('L',pt0));
rpm-build 6f7582
        pt1=MWAWVec2f(box[1][0]-c[0],box[1][1]);
rpm-build 6f7582
        res.push_back(PathData('C',pt1,pt0+MWAWVec2f(0,delta*c[1]),pt1+MWAWVec2f(delta*c[0],0)));
rpm-build 6f7582
        pt0=MWAWVec2f(box[0][0]+c[0],box[1][1]);
rpm-build 6f7582
        res.push_back(PathData('L',pt0));
rpm-build 6f7582
        pt1=MWAWVec2f(box[0][0],box[1][1]-c[1]);
rpm-build 6f7582
        res.push_back(PathData('C',pt1,pt0-MWAWVec2f(delta*c[0],0),pt1+MWAWVec2f(0,delta*c[1])));
rpm-build 6f7582
        pt0=MWAWVec2f(box[0][0],box[0][1]+c[1]);
rpm-build 6f7582
        res.push_back(PathData('L',pt0));
rpm-build 6f7582
        pt1=MWAWVec2f(box[0][0]+c[0],box[0][1]);
rpm-build 6f7582
        res.push_back(PathData('C',pt1,pt0-MWAWVec2f(0,delta*c[1]),pt1-MWAWVec2f(delta*c[0],0)));
rpm-build 6f7582
      }
rpm-build 6f7582
      else {
rpm-build 6f7582
        res.push_back(PathData('M',MWAWVec2f(box[1][0]-c[0],box[0][1])));
rpm-build 6f7582
        PathData data('A',MWAWVec2f(box[1][0],box[0][1]+c[1]));
rpm-build 6f7582
        data.m_r=c;
rpm-build 6f7582
        data.m_sweep=true;
rpm-build 6f7582
        res.push_back(data);
rpm-build 6f7582
        res.push_back(PathData('L',MWAWVec2f(box[1][0],box[1][1]-c[1])));
rpm-build 6f7582
        data.m_x=MWAWVec2f(box[1][0]-c[0],box[1][1]);
rpm-build 6f7582
        res.push_back(data);
rpm-build 6f7582
        res.push_back(PathData('L',MWAWVec2f(box[0][0]+c[0],box[1][1])));
rpm-build 6f7582
        data.m_x=MWAWVec2f(box[0][0],box[1][1]-c[1]);
rpm-build 6f7582
        res.push_back(data);
rpm-build 6f7582
        res.push_back(PathData('L',MWAWVec2f(box[0][0],box[0][1]+c[1])));
rpm-build 6f7582
        data.m_x=MWAWVec2f(box[0][0]+c[0],box[0][1]);
rpm-build 6f7582
        res.push_back(data);
rpm-build 6f7582
      }
rpm-build 6f7582
      res.push_back(PathData('Z'));
rpm-build 6f7582
      break;
rpm-build 6f7582
    }
rpm-build 6f7582
    res.push_back(PathData('M',m_formBox[0]));
rpm-build 6f7582
    res.push_back(PathData('L',MWAWVec2f(m_formBox[0][0],m_formBox[1][1])));
rpm-build 6f7582
    res.push_back(PathData('L',m_formBox[1]));
rpm-build 6f7582
    res.push_back(PathData('L',MWAWVec2f(m_formBox[1][0],m_formBox[0][1])));
rpm-build 6f7582
    res.push_back(PathData('Z'));
rpm-build 6f7582
    break;
rpm-build 6f7582
  case Circle: {
rpm-build 6f7582
    if (forTransformation) {
rpm-build 6f7582
      MWAWVec2f center=m_formBox.center();
rpm-build 6f7582
      MWAWVec2f dir=0.5f*delta*(m_formBox[1]-m_formBox[0]);
rpm-build 6f7582
      MWAWVec2f pt0(m_formBox[0][0],center[1]);
rpm-build 6f7582
      res.push_back(PathData('M',pt0));
rpm-build 6f7582
      MWAWVec2f pt1(center[0],m_formBox[0][1]);
rpm-build 6f7582
      res.push_back(PathData('C',pt1, pt0-MWAWVec2f(0,dir[1]), pt1-MWAWVec2f(dir[0],0)));
rpm-build 6f7582
      pt0=MWAWVec2f(m_formBox[1][0],center[1]);
rpm-build 6f7582
      res.push_back(PathData('C',pt0, pt1+MWAWVec2f(dir[0],0), pt0-MWAWVec2f(0,dir[1])));
rpm-build 6f7582
      pt1=MWAWVec2f(center[0],m_formBox[1][1]);
rpm-build 6f7582
      res.push_back(PathData('C',pt1, pt0+MWAWVec2f(0,dir[1]), pt1+MWAWVec2f(dir[0],0)));
rpm-build 6f7582
      pt0=MWAWVec2f(m_formBox[0][0],center[1]);
rpm-build 6f7582
      res.push_back(PathData('C',pt0, pt1-MWAWVec2f(dir[0],0), pt0+MWAWVec2f(0,dir[1])));
rpm-build 6f7582
      res.push_back(PathData('Z'));
rpm-build 6f7582
    }
rpm-build 6f7582
    else {
rpm-build 6f7582
      MWAWVec2f pt0 = MWAWVec2f(m_formBox[0][0],0.5f*(m_formBox[0][1]+m_formBox[1][1]));
rpm-build 6f7582
      MWAWVec2f pt1 = MWAWVec2f(m_formBox[1][0],pt0[1]);
rpm-build 6f7582
      res.push_back(PathData('M',pt0));
rpm-build 6f7582
      PathData data('A',pt1);
rpm-build 6f7582
      data.m_r=0.5f*(m_formBox[1]-m_formBox[0]);
rpm-build 6f7582
      data.m_largeAngle=true;
rpm-build 6f7582
      res.push_back(data);
rpm-build 6f7582
      data.m_x=pt0;
rpm-build 6f7582
      res.push_back(data);
rpm-build 6f7582
    }
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  case Arc:
rpm-build 6f7582
  case Pie: {
rpm-build 6f7582
    MWAWVec2f center=0.5f*(m_formBox[0]+m_formBox[1]);
rpm-build 6f7582
    MWAWVec2f rad=0.5f*(m_formBox[1]-m_formBox[0]);
rpm-build 6f7582
    float angl0=m_arcAngles[0];
rpm-build 6f7582
    float angl1=m_arcAngles[1];
rpm-build 6f7582
    if (rad[1]<0) {
rpm-build 6f7582
      static bool first=true;
rpm-build 6f7582
      if (first) {
rpm-build 6f7582
        MWAW_DEBUG_MSG(("MWAWGraphicShape::getPath: oops radiusY for arc is negative, inverse it\n"));
rpm-build 6f7582
        first=false;
rpm-build 6f7582
      }
rpm-build 6f7582
      rad[1]=-rad[1];
rpm-build 6f7582
    }
rpm-build 6f7582
    while (angl1
rpm-build 6f7582
      angl1+=360.f;
rpm-build 6f7582
    while (angl1>angl0+360.f)
rpm-build 6f7582
      angl1-=360.f;
rpm-build 6f7582
    if (angl1-angl0>=180.f && angl1-angl0<=180.f)
rpm-build 6f7582
      angl1+=0.01f;
rpm-build 6f7582
    float angl=angl0*float(M_PI/180.);
rpm-build 6f7582
    bool addCenter=m_type==Pie;
rpm-build 6f7582
    if (addCenter)
rpm-build 6f7582
      res.push_back(PathData('M', center));
rpm-build 6f7582
    MWAWVec2f pt=center+MWAWVec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
rpm-build 6f7582
    res.push_back(PathData(addCenter ? 'L' : 'M', pt));
rpm-build 6f7582
    if (!forTransformation) {
rpm-build 6f7582
      angl=angl1*float(M_PI/180.);
rpm-build 6f7582
      pt=center+MWAWVec2f(std::cos(angl)*rad[0],-std::sin(angl)*rad[1]);
rpm-build 6f7582
      PathData data('A',pt);
rpm-build 6f7582
      data.m_largeAngle=(angl1-angl0>=180.f);
rpm-build 6f7582
      data.m_r=rad;
rpm-build 6f7582
      res.push_back(data);
rpm-build 6f7582
    }
rpm-build 6f7582
    else {
rpm-build 6f7582
      int N=int(angl1-angl0)/90;
rpm-build 6f7582
      float dAngle=float(angl1-angl0)/float(N+1);
rpm-build 6f7582
      for (int i=0; i<=N; ++i) {
rpm-build 6f7582
        float newAngl= i==N ? angl1 : angl0+float(i+1)*dAngle;
rpm-build 6f7582
        newAngl*=float(M_PI/180.);
rpm-build 6f7582
        MWAWVec2f newPt=center+MWAWVec2f(std::cos(angl1)*rad[0],-std::sin(angl1)*rad[1]);
rpm-build 6f7582
        MWAWVec2f dir(-std::sin(angl)*rad[0],-std::cos(angl)*rad[1]);
rpm-build 6f7582
        MWAWVec2f newDir(-std::sin(newAngl)*rad[0],-std::cos(newAngl)*rad[1]);
rpm-build 6f7582
        float deltaDir=4/3.f*std::tan((newAngl-angl)/4);
rpm-build 6f7582
        res.push_back(PathData('C',newPt,pt+deltaDir*dir,newPt-deltaDir*newDir));
rpm-build 6f7582
        pt=newPt;
rpm-build 6f7582
        angl=newAngl;
rpm-build 6f7582
      }
rpm-build 6f7582
      if (m_type==Pie) res.push_back(PathData('Z'));
rpm-build 6f7582
    }
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  case Path:
rpm-build 6f7582
    return m_path;
rpm-build 6f7582
  case ShapeUnknown:
rpm-build 6f7582
#if !defined(__clang__)
rpm-build 6f7582
  default:
rpm-build 6f7582
#endif
rpm-build 6f7582
    MWAW_DEBUG_MSG(("MWAWGraphicShape::getPath: unexpected type\n"));
rpm-build 6f7582
    break;
rpm-build 6f7582
  }
rpm-build 6f7582
  return res;
rpm-build 6f7582
}
rpm-build 6f7582
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
rpm-build 6f7582