#include "feature.h"
#include <QDebug>
#include "./symbol.h"
#include "./util.h"
#include "./font.h"


class PcbCamFeaturePrivate
{
    Q_DECLARE_PUBLIC(PcbCamFeature)
public:
    explicit PcbCamFeaturePrivate() { }
    virtual ~PcbCamFeaturePrivate() {}

    PcbCam::FeatureType type {PcbCam::PadFeature};
    PcbCam::Polarity polarity {PcbCam::Positive};
    QVariantMap attrMap;
    int index {0};
    int decode {0};
    PcbCamSymbol *symbol {nullptr};
    bool selected {false};


    mutable QPainterPath shape;

protected:
    PcbCamFeature *q_ptr {nullptr};
};

PcbCamFeature::PcbCamFeature()
    : d_ptr(new PcbCamFeaturePrivate)
{
    d_ptr->q_ptr = this;
}


PcbCamFeature::~PcbCamFeature()
{

}

PcbCam::FeatureType PcbCamFeature::type() const
{
    Q_D(const PcbCamFeature);
    return d->type;
}

PcbCam::Polarity PcbCamFeature::polarity() const
{
    Q_D(const PcbCamFeature);
    return d->polarity;
}

void PcbCamFeature::setPolarity(PcbCam::Polarity iPolarity)
{
    Q_D(PcbCamFeature);
    d->polarity = iPolarity;
}

int PcbCamFeature::index() const
{
    Q_D(const PcbCamFeature);
    return d->index;
}

void PcbCamFeature::setIndex(int iIndex)
{
    Q_D(PcbCamFeature);
    d->index = iIndex;
}


int PcbCamFeature::dcode() const
{
    Q_D(const PcbCamFeature);
    return d->decode;
}

void PcbCamFeature::setDcode(int iDcode)
{
    Q_D(PcbCamFeature);
    d->decode = iDcode;
}

void PcbCamFeature::setSymbol(PcbCamSymbol *iSymbol)
{
    Q_D(PcbCamFeature);
    d->symbol = iSymbol;
    d->shape = QPainterPath();
}

PcbCamSymbol *PcbCamFeature::symbol() const
{
    Q_D(const PcbCamFeature);
    return d->symbol;
}

QVariantMap PcbCamFeature::attr() const
{
    Q_D(const PcbCamFeature);
    return d->attrMap;
}

QVariant PcbCamFeature::attr(const QString &iName) const
{
    Q_D(const PcbCamFeature);
    return d->attrMap.value(iName.toLower());
}

bool PcbCamFeature::hasAttr(const QString &iName) const
{
    Q_D(const PcbCamFeature);
    return d->attrMap.contains(iName.toLower());
}

void PcbCamFeature::setAttr(const QString &iName, const QVariant &iValue)
{
    Q_D(PcbCamFeature);
    d->attrMap.insert(iName.toLower(), iValue);
}

void PcbCamFeature::setAttr(const QVariantMap &iAttrMap)
{
    Q_D(PcbCamFeature);
    d->attrMap = iAttrMap;
}

void PcbCamFeature::removeAttr(const QString &iName)
{
    Q_D(PcbCamFeature);
    d->attrMap.remove(iName.toLower());
}

void PcbCamFeature::clearAttr()
{
    Q_D(PcbCamFeature);
    d->attrMap.clear();
}

void PcbCamFeature::setSelected(bool iSel)
{
    Q_D(PcbCamFeature);
    d->selected = iSel;
}

bool PcbCamFeature::isSelected() const
{
    Q_D(const PcbCamFeature);
    return d->selected;
}

PcbCamFeature::PcbCamFeature(PcbCamFeaturePrivate &dd)
    : d_ptr(&dd)
{
    d_ptr->q_ptr = this;
}

/*******************************************LINE*********************************************/

class PcbCamFeatureLinePrivate : public PcbCamFeaturePrivate
{
    Q_DECLARE_PUBLIC(PcbCamFeatureLine)
public:
    PcbCamFeatureLinePrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeatureLinePrivate() { }

    QLineF line ;

};

PcbCamFeatureLine::PcbCamFeatureLine()
    : PcbCamFeature(*new PcbCamFeatureLinePrivate)
{
    Q_D(PcbCamFeatureLine);
    d->type = PcbCam::LineFeature;
}

PcbCamFeatureLine::~PcbCamFeatureLine()
{

}

void PcbCamFeatureLine::setLine(const QLineF &iLine)
{
    Q_D(PcbCamFeatureLine);
    d->line = iLine;
    d->shape = QPainterPath();
}

QLineF PcbCamFeatureLine::line() const
{
    Q_D(const PcbCamFeatureLine);
    return d->line;
}

QPainterPath PcbCamFeatureLine::shape() const
{
    Q_D(const PcbCamFeatureLine);
    if (d->shape.isEmpty()) {
        //当起点和终点在一起的线，PainterPathStroker不会创建对象，会造成图像丢失，因此需做特殊处理；
        if (d->line.length() < 0.00000001) {
            QPainterPath path = symbol()->shape();
            d->shape =  PcbCamUtil::matrix(d->line.p1(), PcbCam::Orient_N_0).map(path);
        }
        else {
            QPainterPathStroker stroker(PcbCamUtil::sym2pen(symbol()));
            d->shape = stroker.createStroke(PcbCamUtil::line2path(d->line));
        }
    }
    return d->shape;
}

QRectF PcbCamFeatureLine::boundingRect() const
{
    return shape().controlPointRect();
}



/*******************************************PAD*********************************************/

class PcbCamFeaturePadPrivate : public PcbCamFeaturePrivate
{
    Q_DECLARE_PUBLIC(PcbCamFeaturePad)
public:
    PcbCamFeaturePadPrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeaturePadPrivate() { }

    QPointF pos {0.0, 0.0};
    PcbCam::Orient orient {PcbCam::Orient_N_0};
};

PcbCamFeaturePad::PcbCamFeaturePad()
    : PcbCamFeature(*new PcbCamFeaturePadPrivate)
{
    Q_D(PcbCamFeaturePad);
    d->type = PcbCam::PadFeature;
}

PcbCamFeaturePad::~PcbCamFeaturePad()
{

}

QPointF PcbCamFeaturePad::pos() const
{
    Q_D(const PcbCamFeaturePad);
    return d->pos;
}

void PcbCamFeaturePad::setPos(const QPointF &iPos)
{
    Q_D(PcbCamFeaturePad);
    d->pos = iPos;
}

PcbCam::Orient PcbCamFeaturePad::orient() const
{
    Q_D(const PcbCamFeaturePad);
    return d->orient;
}

void PcbCamFeaturePad::setOrient(PcbCam::Orient iOrient)
{
    Q_D(PcbCamFeaturePad);
    d->orient = iOrient;
}

QPainterPath PcbCamFeaturePad::shape() const
{
    Q_D(const PcbCamFeaturePad);
    QPainterPath path = symbol()->shape();
    return PcbCamUtil::matrix(d->pos, d->orient).map(path);
}

QRectF PcbCamFeaturePad::boundingRect() const
{
    Q_D(const PcbCamFeaturePad);
    //return shape().controlPointRect();
    return PcbCamUtil::matrix(d->pos, d->orient).mapRect(symbol()->boundingRect());
}


/*******************************************ARC*********************************************/

class PcbCamFeatureArcPrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeatureArcPrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeatureArcPrivate() { }

    QPointF ps;
    QPointF pe;
    QPointF pc;
    bool cw {false};
};

PcbCamFeatureArc::PcbCamFeatureArc()
    : PcbCamFeature(*new PcbCamFeatureArcPrivate)
{
    Q_D(PcbCamFeatureArc);
    d->type = PcbCam::ArcFeature;
}

PcbCamFeatureArc::~PcbCamFeatureArc()
{

}

void PcbCamFeatureArc::setData(const QPointF &iPs, const QPointF &iPe, const QPointF &iPc, bool iCw)
{
    Q_D(PcbCamFeatureArc);
    d->ps = iPs;
    d->pe = iPe;
    d->pc = iPc;
    d->cw = iCw;
    d->shape = QPainterPath();
}

QPointF PcbCamFeatureArc::ps() const
{
    Q_D(const PcbCamFeatureArc);
    return d->ps;
}

QPointF PcbCamFeatureArc::pe() const
{
    Q_D(const PcbCamFeatureArc);
    return d->pe;
}

QPointF PcbCamFeatureArc::pc() const
{
    Q_D(const PcbCamFeatureArc);
    return d->pc;
}

bool PcbCamFeatureArc::cw() const
{
    Q_D(const PcbCamFeatureArc);
    return d->cw;
}

QPainterPath PcbCamFeatureArc::shape() const
{
    Q_D(const PcbCamFeatureArc);
    if (d->shape.isEmpty()) {
        QPainterPathStroker stroker(PcbCamUtil::sym2pen(symbol()));
        d->shape = stroker.createStroke(PcbCamUtil::arc2path(d->ps, d->pe, d->pc, d->cw));
    }
    return d->shape;
}

QRectF PcbCamFeatureArc::boundingRect() const
{
    return shape().controlPointRect();
}


/*******************************************TEXT*********************************************/

class PcbCamFeatureTextPrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeatureTextPrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeatureTextPrivate() {
        clearFeatures();
    }

    QPointF pos;
    PcbCamFont *font {nullptr};
    PcbCam::Orient orient {PcbCam::Orient_N_0};
    QSizeF size;
    qreal widthFactor {1.0};
    QString text;
    int version {1};
    QString dynamicText;

    QList<PcbCamFeature *> features;
    QMap<QString, PcbCamSymbol*> lineSymbolsMap;

    void clearFeatures()
    {
        for (auto k : lineSymbolsMap.keys()) {
            PcbCamSymbol *sym = lineSymbolsMap.value(k, nullptr);
            if (sym != nullptr) {
                delete sym;
                sym = nullptr;
            }
        }
        lineSymbolsMap.clear();

        for (PcbCamFeature *f : features) {
            delete f;
            f = nullptr;
        }

        features.clear();
    }

    void genFeatures()
    {
        clearFeatures();

        //找出原点：ODB++手册上说是所有Char的左下角不原点，但经测试发现在genesis里是以“M"字母的左下角为原点
        QList<PcbCamFontCharLine> mlines = this->font->charLines(QChar('M'));
        QPainterPath mpath;
        for (const PcbCamFontCharLine &l : mlines) {
            QPainterPathStroker stroker;
            QTransform mat((this->size.width()-this->widthFactor*l.width())/(this->font->sizeX()), 0, 0, (this->size.height()-this->widthFactor*l.width())/this->font->sizeY(), 0, 0);
            stroker.setCapStyle(l.shape() == PcbCamFontCharLine::LineShape_S  ? Qt::SquareCap : Qt::RoundCap);
            stroker.setWidth(l.width() * this->widthFactor);
            QPainterPath path;
            path.moveTo(l.line().p1());
            path.lineTo(l.line().p2());
            path = mat.map(path);
            mpath.addPath(stroker.createStroke(path));
        }
        QPointF origin = mpath.boundingRect().topLeft();

        QString tmptext = this->dynamicText;
        for (int i = 0; i < tmptext.length(); ++i) {
            QList<PcbCamFontCharLine> lines = this->font->charLines(tmptext.at(i));
            for (const PcbCamFontCharLine &line : lines) {
                QTransform mat((this->size.width()-this->widthFactor*line.width())/(this->font->sizeX()), 0, 0, (this->size.height()-this->widthFactor*line.width())/this->font->sizeY(), 0, 0);
                double symsize =  line.width() * this->widthFactor * 1000;
                QString symname = QString( line.shape() == PcbCamFontCharLine::LineShape_S ? "s%1" : "r%1").arg(symsize, 0, 'f', 6);
                if (!lineSymbolsMap.contains(symname)) {
                    if (line.shape() == PcbCamFontCharLine::LineShape_S) {
                        lineSymbolsMap.insert(symname, new PcbCamSymbolS(symname));
                    }
                    else {
                        lineSymbolsMap.insert(symname, new PcbCamSymbolR(symname));
                    }
                }
                PcbCamFeatureLine *f = new PcbCamFeatureLine();
                f->setPolarity(line.polarity());
                f->setLine(mat.map(line.line()).translated(i*this->size.width() -origin.x(), -origin.y()));
                f->setSymbol(lineSymbolsMap[symname]);
                features.append(f);
            }
        }
    }

};

PcbCamFeatureText::PcbCamFeatureText()
    : PcbCamFeature(*new PcbCamFeatureTextPrivate)
{
    Q_D(PcbCamFeatureText);
    d->type = PcbCam::TextFeature;
}


PcbCamFeatureText::~PcbCamFeatureText()
{

}

void PcbCamFeatureText::setData(const QPointF &iPos, PcbCamFont *iFont, PcbCam::Orient iOrient, const QSizeF &iSize, qreal iWithFactor, const QString &iText, int iVersion)
{
    Q_D(PcbCamFeatureText);
    d->pos = iPos;
    d->font = iFont;
    d->orient = iOrient;
    d->size = iSize;
    d->widthFactor = iWithFactor;
    d->text = iText;
    d->version = iVersion;
    d->dynamicText = iText;
    d->shape = QPainterPath();
    d->genFeatures();
}

QPointF PcbCamFeatureText::pos() const
{
    Q_D(const PcbCamFeatureText);
    return d->pos;
}

PcbCamFont *PcbCamFeatureText::font() const
{
    Q_D(const PcbCamFeatureText);
    return d->font;
}

PcbCam::Orient PcbCamFeatureText::orient() const
{
    Q_D(const PcbCamFeatureText);
    return d->orient;
}

QSizeF PcbCamFeatureText::size() const
{
    Q_D(const PcbCamFeatureText);
    return d->size;
}

qreal PcbCamFeatureText::widthFactor() const
{
    Q_D(const PcbCamFeatureText);
    return d->widthFactor;
}

QString PcbCamFeatureText::text() const
{
    Q_D(const PcbCamFeatureText);
    return d->text;
}

int PcbCamFeatureText::version() const
{
    Q_D(const PcbCamFeatureText);
    return d->version;
}

QString PcbCamFeatureText::dynamicText() const
{
    Q_D(const PcbCamFeatureText);
    return d->dynamicText;
}

void PcbCamFeatureText::setDynamicText(const QString &iText)
{
    Q_D(PcbCamFeatureText);
    d->dynamicText = iText;
    d->shape = QPainterPath();
    d->genFeatures();
}

QList<PcbCamFeature*> PcbCamFeatureText::features() const
{
    Q_D(const PcbCamFeatureText);
    return d->features;
}

QPainterPath PcbCamFeatureText::shape() const
{
    Q_D(const PcbCamFeatureText);
    if (d->shape.isEmpty() && d->font != nullptr) {
       for (const PcbCamFeature *feat : d->features) {
           d->shape.addPath(feat->shape());
       }
    }
    return PcbCamUtil::matrix(d->pos, d->orient).map(d->shape);
}

QRectF PcbCamFeatureText::boundingRect() const
{
    return shape().boundingRect();
}

/*******************************************BARCODE*********************************************/

class PcbCamFeatureBarcodePrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeatureBarcodePrivate() : PcbCamFeaturePrivate(){ }
    ~PcbCamFeatureBarcodePrivate() { }

    QPointF pos;
    QString barcode;
    QString font {"standard"};
    PcbCam::Orient orient {PcbCam::Orient_N_0};
    QSizeF size;
    bool fullAscii {false};
    bool checkSum {false};
    bool background {false};
    bool additionStr {false};
    PcbCam::BarcodeTextPos additionStrPos {PcbCam::BarcodeTextPos_Top};
    QString text;

};

PcbCamFeatureBarcode::PcbCamFeatureBarcode()
    : PcbCamFeature(*new PcbCamFeatureBarcodePrivate)
{
    Q_D(PcbCamFeatureBarcode);
    d->type = PcbCam::BarcodeFeature;
}

PcbCamFeatureBarcode::~PcbCamFeatureBarcode()
{

}

QPointF PcbCamFeatureBarcode::pos() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->pos;
}

void PcbCamFeatureBarcode::setPos(const QPointF &iPos)
{
    Q_D(PcbCamFeatureBarcode);
    d->pos = iPos;
}

QString PcbCamFeatureBarcode::barcode() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->barcode;
}

void PcbCamFeatureBarcode::setBarcode(const QString &iBarcode)
{
    Q_D(PcbCamFeatureBarcode);
    d->barcode = iBarcode;
}

QString PcbCamFeatureBarcode::font() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->font;
}

void PcbCamFeatureBarcode::setFont(const QString &iFont)
{
    Q_D(PcbCamFeatureBarcode);
    d->font = iFont;
}

PcbCam::Orient PcbCamFeatureBarcode::orient() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->orient;
}

void PcbCamFeatureBarcode::setOrient(PcbCam::Orient iOrient)
{
    Q_D(PcbCamFeatureBarcode);
    d->orient = iOrient;
}

QSizeF PcbCamFeatureBarcode::size() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->size;
}

void PcbCamFeatureBarcode::setSize(const QSizeF &iSize)
{
    Q_D(PcbCamFeatureBarcode);
    d->size = iSize;
}

bool PcbCamFeatureBarcode::fullAscii() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->fullAscii;
}

void PcbCamFeatureBarcode::setFullAscii(bool iBol)
{
    Q_D(PcbCamFeatureBarcode);
    d->fullAscii = iBol;
}

bool PcbCamFeatureBarcode::checkSum() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->checkSum;
}

void PcbCamFeatureBarcode::setCheckSum(bool iBol)
{
    Q_D(PcbCamFeatureBarcode);
    d->checkSum = iBol;
}

bool PcbCamFeatureBarcode::background() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->background;
}

void PcbCamFeatureBarcode::setBackground(bool iBol)
{
    Q_D(PcbCamFeatureBarcode);
    d->background = iBol;
}

bool PcbCamFeatureBarcode::additionStr() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->additionStr;
}

void PcbCamFeatureBarcode::setAdditionStr(bool iBol)
{
    Q_D(PcbCamFeatureBarcode);
    d->additionStr = iBol;
}

PcbCam::BarcodeTextPos PcbCamFeatureBarcode::additiontStrPos() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->additionStrPos;
}

void PcbCamFeatureBarcode::setAdditionStrPos(PcbCam::BarcodeTextPos iTorB)
{
    Q_D(PcbCamFeatureBarcode);
    d->additionStrPos = iTorB;
}

QString PcbCamFeatureBarcode::text() const
{
    Q_D(const PcbCamFeatureBarcode);
    return d->text;
}

void PcbCamFeatureBarcode::setText(const QString &iText)
{
    Q_D(PcbCamFeatureBarcode);
    d->text = iText;
}

QPainterPath PcbCamFeatureBarcode::shape() const
{
    Q_D(const PcbCamFeatureBarcode);
    if (d->shape.isEmpty()) {
        QPainterPath path;
        path.addRect(d->pos.x(), d->pos.y(), d->size.width(), d->size.height());
        d->shape = path;
    }
    return d->shape;
}

QRectF PcbCamFeatureBarcode::boundingRect() const
{
    return shape().boundingRect();
}



/*******************************************SURFACE*********************************************/

class PcbCamFeatureSurfacePrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeatureSurfacePrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeatureSurfacePrivate() { }

    QPainterPath path;

};

PcbCamFeatureSurface::PcbCamFeatureSurface()
    : PcbCamFeature(*new PcbCamFeatureSurfacePrivate)
{
    Q_D(PcbCamFeatureSurface);
    d->type = PcbCam::SurfaceFeature;
}

PcbCamFeatureSurface::~PcbCamFeatureSurface()
{

}

QPainterPath PcbCamFeatureSurface::path() const
{
    Q_D(const PcbCamFeatureSurface);
    return d->path;
}

void PcbCamFeatureSurface::setPath(const QPainterPath &iPath)
{
    Q_D(PcbCamFeatureSurface);
    d->path = iPath;
}

QPainterPath PcbCamFeatureSurface::shape() const
{
    Q_D(const PcbCamFeatureSurface);
    return d->path;
}

QRectF PcbCamFeatureSurface::boundingRect() const
{
    Q_D(const PcbCamFeatureSurface);
    return d->path.controlPointRect();
}


/*******************************************PATH*********************************************/

class PcbCamFeaturePathPrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeaturePathPrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeaturePathPrivate() { }

    QPainterPath path;
    int width {1};

};

PcbCamFeaturePath::PcbCamFeaturePath()
    : PcbCamFeature(*new PcbCamFeaturePathPrivate)
{
    Q_D(PcbCamFeaturePath);
    d->type = PcbCam::PathFeature;
}

PcbCamFeaturePath::~PcbCamFeaturePath()
{

}

QPainterPath PcbCamFeaturePath::path() const
{
    Q_D(const PcbCamFeaturePath);
    return d->path;
}

void PcbCamFeaturePath::setPath(const QPainterPath &iPath)
{
    Q_D(PcbCamFeaturePath);
    d->path = iPath;
}

int PcbCamFeaturePath::width() const
{
    Q_D(const PcbCamFeaturePath);
    return d->width;
}

void PcbCamFeaturePath::setWidth(int iWidth)
{
    Q_D(PcbCamFeaturePath);
    d->width = iWidth;
}

QPainterPath PcbCamFeaturePath::shape() const
{
    Q_D(const PcbCamFeaturePath);
    return d->path;
}

QRectF PcbCamFeaturePath::boundingRect() const
{
    Q_D(const PcbCamFeaturePath);
    return d->path.controlPointRect();
}


/*******************************************COMPONENT*********************************************/

class PcbCamFeatureComponentPrivate : public PcbCamFeaturePrivate
{
public:
    PcbCamFeatureComponentPrivate() : PcbCamFeaturePrivate() { }
    ~PcbCamFeatureComponentPrivate() { }

    QPointF pos;
    double rotation {0.0};
    bool mirror {false};
    QString compName;
    QString partName;

};

PcbCamFeatureComponent::PcbCamFeatureComponent()
    : PcbCamFeature(*new PcbCamFeatureComponentPrivate)
{
    Q_D(PcbCamFeatureComponent);
    d->type = PcbCam::ComponentFeature;
}

PcbCamFeatureComponent::~PcbCamFeatureComponent()
{

}

void PcbCamFeatureComponent::setData(const QPointF &iPos, double iRotation, bool iMirror, const QString &iCompName, const QString &iPartName)
{
    Q_D(PcbCamFeatureComponent);
    d->pos = iPos;
    d->rotation = iRotation;
    d->mirror = iMirror;
    d->compName = iCompName;
    d->partName = iPartName;
}

QPointF PcbCamFeatureComponent::pos() const
{
    Q_D(const PcbCamFeatureComponent);
    return d->pos;
}

double PcbCamFeatureComponent::rotation() const
{
    Q_D(const PcbCamFeatureComponent);
    return d->rotation;
}

bool PcbCamFeatureComponent::mirror() const
{
    Q_D(const PcbCamFeatureComponent);
    return d->mirror;
}

QString PcbCamFeatureComponent::compName() const
{
    Q_D(const PcbCamFeatureComponent);
    return d->compName;
}

QString PcbCamFeatureComponent::partName() const
{
    Q_D(const PcbCamFeatureComponent);
    return d->partName;
}

QPainterPath PcbCamFeatureComponent::shape() const
{
    Q_D(const PcbCamFeatureComponent);
    QPainterPath path;
    if (d->shape.isEmpty()) {
        auto sym = static_cast<PcbCamSymbolUser *>(d->symbol);
        if (sym != nullptr) {
            auto symfeats = sym->features();
            if (!symfeats.isEmpty()) {
                path = symfeats.at(0)->shape();
            }
        }
    }

    return PcbCamUtil::matrix(d->pos, QPointF(0, 0), d->rotation, d->mirror).map(path);
}

QRectF PcbCamFeatureComponent::boundingRect() const
{
    Q_D(const PcbCamFeatureComponent);
    //return shape().controlPointRect();
    return PcbCamUtil::matrix(d->pos, QPointF(0, 0), d->rotation, d->mirror).mapRect(symbol()->boundingRect());
}

