/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* This file is part of the libpagemaker 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/.
*/
#include "OutputShape.h"
#include <math.h>
#include "geometry.h"
#include "libpagemaker_utils.h"
std::shared_ptr<libpagemaker::OutputShape> libpagemaker::newOutputShape(
const std::shared_ptr<const PMDLineSet> &ptrToLineSet, const InchPoint &translate)
{
if (ptrToLineSet->shapeType() == SHAPE_TYPE_TEXTBOX)
{
std::shared_ptr<libpagemaker::OutputShape> ptrToOutputShape(
new OutputShape(ptrToLineSet->getIsClosed(), ptrToLineSet->shapeType(), ptrToLineSet->getRotation(), ptrToLineSet->getSkew(), ptrToLineSet->getText(), ptrToLineSet->getCharProperties(), ptrToLineSet->getParaProperties()));
PMDShapePoint bboxTopLeft = ptrToLineSet->getBboxTopLeft();
PMDShapePoint bboxBotRight = ptrToLineSet->getBboxBotRight();
ptrToOutputShape->setBoundingBox(InchPoint((bboxTopLeft.m_x.toInches() + translate.m_x),(bboxTopLeft.m_y.toInches() + translate.m_y)), InchPoint((bboxBotRight.m_x.toInches() + translate.m_x),(bboxBotRight.m_y.toInches() + translate.m_y)));
double pmdRotation = ptrToLineSet->getRotation();
double pmdSkew = ptrToLineSet->getSkew();
if (pmdRotation == 0 && pmdSkew == 0)
{
double x = bboxTopLeft.m_x.toInches() + translate.m_x;
double y = bboxTopLeft.m_y.toInches() + translate.m_y;
ptrToOutputShape->addPoint(InchPoint(x, y));
double width = fabs(bboxBotRight.m_x.toInches() - bboxTopLeft.m_x.toInches());
double height = fabs(bboxBotRight.m_y.toInches() - bboxTopLeft.m_y.toInches());
ptrToOutputShape->setDimensions(width, height);
}
else
{
PMDShapePoint pmdXformTopLeft = ptrToLineSet->getXformTopLeft();
PMDShapePoint pmdXformBotRight = ptrToLineSet->getXformBotRight();
double width = fabs(pmdXformBotRight.m_x.toInches() - pmdXformTopLeft.m_x.toInches());
double height = fabs(pmdXformBotRight.m_y.toInches() - pmdXformTopLeft.m_y.toInches());
ptrToOutputShape->setDimensions(width, height);
PMDShapePoint pmdRotatingPoint = ptrToLineSet->getRotatingPoint();
double x = pmdRotatingPoint.m_x.toInches() + translate.m_x;
double y = pmdRotatingPoint.m_y.toInches() + translate.m_y;
x += (width*cos(pmdRotation)-height*sin(pmdRotation)-width)/2.0;
y += (width*sin(pmdRotation)+height*cos(pmdRotation)-height)/2.0;
ptrToOutputShape->addPoint(InchPoint(x, y));
}
return ptrToOutputShape;
}
else if (ptrToLineSet->shapeType() == SHAPE_TYPE_BITMAP)
{
std::shared_ptr<libpagemaker::OutputShape> ptrToOutputShape(
new OutputShape(ptrToLineSet->getIsClosed(), ptrToLineSet->shapeType(), ptrToLineSet->getRotation(), ptrToLineSet->getSkew(), ptrToLineSet->getBitmap()));
PMDShapePoint bboxTopLeft = ptrToLineSet->getBboxTopLeft();
PMDShapePoint bboxBotRight = ptrToLineSet->getBboxBotRight();
ptrToOutputShape->setBoundingBox(InchPoint((bboxTopLeft.m_x.toInches() + translate.m_x),(bboxTopLeft.m_y.toInches() + translate.m_y)), InchPoint((bboxBotRight.m_x.toInches() + translate.m_x),(bboxBotRight.m_y.toInches() + translate.m_y)));
std::vector<PMDShapePoint> pmdPoints = ptrToLineSet->getPoints();
double pmdRotation = ptrToLineSet->getRotation();
double pmdSkew = ptrToLineSet->getSkew();
if (pmdRotation == 0 && pmdSkew == 0)
{
double x = bboxTopLeft.m_x.toInches() + translate.m_x;
double y = bboxTopLeft.m_y.toInches() + translate.m_y;
ptrToOutputShape->addPoint(InchPoint(x, y));
double width = fabs(bboxBotRight.m_x.toInches() - bboxTopLeft.m_x.toInches());
double height = fabs(bboxBotRight.m_y.toInches() - bboxTopLeft.m_y.toInches());
ptrToOutputShape->setDimensions(width, height);
}
else
{
PMDShapePoint pmdXformTopLeft = ptrToLineSet->getXformTopLeft();
PMDShapePoint pmdXformBotRight = ptrToLineSet->getXformBotRight();
double width = fabs(pmdXformBotRight.m_x.toInches() - pmdXformTopLeft.m_x.toInches());
double height = fabs(pmdXformBotRight.m_y.toInches() - pmdXformTopLeft.m_y.toInches());
ptrToOutputShape->setDimensions(width, height);
PMDShapePoint pmdRotatingPoint = ptrToLineSet->getRotatingPoint();
double x = pmdRotatingPoint.m_x.toInches() + translate.m_x;
double y = pmdRotatingPoint.m_y.toInches() + translate.m_y;
x += (width*cos(pmdRotation)-height*sin(pmdRotation)-width)/2.0;
y += (width*sin(pmdRotation)+height*cos(pmdRotation)-height)/2.0;
ptrToOutputShape->addPoint(InchPoint(x, y));
}
return ptrToOutputShape;
}
else
{
std::shared_ptr<libpagemaker::OutputShape> ptrToOutputShape(
new OutputShape(ptrToLineSet->getIsClosed(), ptrToLineSet->shapeType(), ptrToLineSet->getRotation(), ptrToLineSet->getSkew(), ptrToLineSet->getFillProperties(), ptrToLineSet->getStrokeProperties()));
PMDShapePoint bboxTopLeft = ptrToLineSet->getBboxTopLeft();
PMDShapePoint bboxBotRight = ptrToLineSet->getBboxBotRight();
ptrToOutputShape->setBoundingBox(InchPoint((bboxTopLeft.m_x.toInches() + translate.m_x),(bboxTopLeft.m_y.toInches() + translate.m_y)), InchPoint((bboxBotRight.m_x.toInches() + translate.m_x),(bboxBotRight.m_y.toInches() + translate.m_y)));
if (ptrToLineSet->shapeType() == SHAPE_TYPE_LINE || ptrToLineSet->shapeType() == SHAPE_TYPE_POLY || ptrToLineSet->shapeType() == SHAPE_TYPE_RECT)
{
std::vector<PMDShapePoint> pmdPoints = ptrToLineSet->getPoints();
double pmdRotation = ptrToLineSet->getRotation();
double pmdSkew = ptrToLineSet->getSkew();
if (pmdRotation == 0 && pmdSkew == 0)
{
for (auto &pmdPoint : pmdPoints)
{
double x = pmdPoint.m_x.toInches() + translate.m_x;
double y = pmdPoint.m_y.toInches() + translate.m_y;
ptrToOutputShape->addPoint(InchPoint(x, y));
}
}
else
{
PMDShapePoint pmdXformTopLeft = ptrToLineSet->getXformTopLeft();
PMDShapePoint pmdXformBotRight = ptrToLineSet->getXformBotRight();
double width = fabs(pmdXformBotRight.m_x.toInches() - pmdXformTopLeft.m_x.toInches());
double height = fabs(pmdXformBotRight.m_y.toInches() - pmdXformTopLeft.m_y.toInches());
if (ptrToLineSet->shapeType() == SHAPE_TYPE_RECT)
{
PMDShapePoint pmdRotatingPoint = ptrToLineSet->getRotatingPoint();
double x1 = pmdRotatingPoint.m_x.toInches() + translate.m_x;
double y1 = pmdRotatingPoint.m_y.toInches() + translate.m_y;
double x2 = x1 + width*cos(pmdRotation);
double y2 = y1 + width*sin(pmdRotation);
double x4 = x1 - height*sin(pmdRotation);
double y4 = y1 + height*cos(pmdRotation);
double x3 = x4 + width*cos(pmdRotation);
double y3 = y4 + width*sin(pmdRotation);
x3 += height*cos(pmdRotation)*sin(pmdSkew)/cos(pmdSkew);
y3 += height*sin(pmdRotation)*sin(pmdSkew)/cos(pmdSkew);
x4 += height*cos(pmdRotation)*sin(pmdSkew)/cos(pmdSkew);
y4 += height*sin(pmdRotation)*sin(pmdSkew)/cos(pmdSkew);
ptrToOutputShape->addPoint(InchPoint(x1, y1));
ptrToOutputShape->addPoint(InchPoint(x2, y2));
ptrToOutputShape->addPoint(InchPoint(x3, y3));
ptrToOutputShape->addPoint(InchPoint(x4, y4));
}
else
{
double tx = (bboxBotRight.m_x.toInches() + bboxTopLeft.m_x.toInches())/2 + translate.m_x;
double ty = (bboxBotRight.m_y.toInches() + bboxTopLeft.m_y.toInches())/2 + translate.m_y;
for (auto &pmdPoint : pmdPoints)
{
double temp = pmdPoint.m_x.toInches() + tan(pmdSkew)*pmdPoint.m_y.toInches();
double x = temp*cos(pmdRotation) - pmdPoint.m_y.toInches()*sin(pmdRotation) + tx;
double y = temp*sin(pmdRotation) + pmdPoint.m_y.toInches()*cos(pmdRotation) + ty;
ptrToOutputShape->addPoint(InchPoint(x, y));
}
}
}
return ptrToOutputShape;
}
else
{
std::vector<PMDShapePoint> pmdPoints = ptrToLineSet->getPoints();
double pmdRotation = ptrToLineSet->getRotation();
double pmdSkew = ptrToLineSet->getSkew();
double cx = (pmdPoints[0].m_x.toInches() + pmdPoints[1].m_x.toInches())/2 + translate.m_x;
double cy = (pmdPoints[0].m_y.toInches() + pmdPoints[1].m_y.toInches())/2 + translate.m_y;
double rx = 0;
double ry = 0;
if (pmdRotation == 0 && pmdSkew == 0)
{
rx = fabs(pmdPoints[1].m_x.toInches() - pmdPoints[0].m_x.toInches())/2;
ry = fabs(pmdPoints[1].m_y.toInches() - pmdPoints[0].m_y.toInches())/2;
}
else
{
PMDShapePoint pmdXformTopLeft = ptrToLineSet->getXformTopLeft();
PMDShapePoint pmdXformBotRight = ptrToLineSet->getXformBotRight();
double width = fabs(pmdXformBotRight.m_x.toInches() - pmdXformTopLeft.m_x.toInches());
double height = fabs(pmdXformBotRight.m_y.toInches() - pmdXformTopLeft.m_y.toInches());
rx = width/2;
ry = height/2;
}
ptrToOutputShape->addPoint(InchPoint(cx, cy));
ptrToOutputShape->addPoint(InchPoint(rx, ry));
return ptrToOutputShape;
}
}
}
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */