예제 #1
0
void RMemoryStorage::clear() {
    RStorage::clear();

    maxLineweight = RLineweight::Weight000;
    inTransaction = false;
    boundingBoxChanged = true;
    boundingBox[0][0] = RBox();
    boundingBox[0][1] = RBox();
    boundingBox[1][0] = RBox();
    boundingBox[1][1] = RBox();
    objectMap.clear();
    objectHandleMap.clear();
    entityMap.clear();
    blockEntityMap.clear();
    blockMap.clear();
    layerMap.clear();
    linetypeMap.clear();
    transactionMap.clear();
    documentVariables.clear();
    variables.clear();
    variableCaseMap.clear();
    if (!documentVariables.isNull()) {
        documentVariables->clear();
    }
    //linetypeScale = 1.0;
    setLastTransactionId(-1);
}
예제 #2
0
파일: RArc.cpp 프로젝트: Alpha-Kand/qcad
RBox RArc::getBoundingBox() const {
    RVector minV;
    RVector maxV;
    double minX = qMin(getStartPoint().x, getEndPoint().x);
    double minY = qMin(getStartPoint().y, getEndPoint().y);
    double maxX = qMax(getStartPoint().x, getEndPoint().x);
    double maxY = qMax(getStartPoint().y, getEndPoint().y);

    if (getStartPoint().getDistanceTo(getEndPoint()) < 1.0e-6 && getRadius()
            > 1.0e5) {
        minV = RVector(minX, minY);
        maxV = RVector(maxX, maxY);
        return RBox(minV, maxV);
    }

    double a1 = RMath::getNormalizedAngle(!isReversed() ? startAngle : endAngle);
    double a2 = RMath::getNormalizedAngle(!isReversed() ? endAngle : startAngle);

    // check for left limit:
    if ((a1<M_PI && a2>M_PI) ||
            (a1>a2-1.0e-12 && a2>M_PI) ||
            (a1>a2-1.0e-12 && a1<M_PI) ) {

        minX = qMin(center.x - radius, minX);
    }

    // check for right limit:
    if (a1 > a2-1.0e-12) {
        maxX = qMax(center.x + radius, maxX);
    }

    // check for bottom limit:
    if ((a1<(M_PI_2*3) && a2>(M_PI_2*3)) ||
            (a1>a2-1.0e-12    && a2>(M_PI_2*3)) ||
            (a1>a2-1.0e-12    && a1<(M_PI_2*3)) ) {

        minY = qMin(center.y - radius, minY);
    }

    // check for top limit:
    if ((a1<M_PI_2 && a2>M_PI_2) ||
            (a1>a2-1.0e-12   && a2>M_PI_2) ||
            (a1>a2-1.0e-12   && a1<M_PI_2) ) {

        maxY = qMax(center.y + radius, maxY);
    }

    minV = RVector(minX, minY);
    maxV = RVector(maxX, maxY);

    return RBox(minV, maxV);
}
예제 #3
0
void RSpline::updateInternal() const {
    if (!dirty || updateInProgress) {
        return;
    }

    dirty = false;
    updateInProgress = true;

    if (degree<1) {
        invalidate();
        qWarning() << "RSpline::updateInternal: invalid degree: " << degree;
        updateInProgress = false;
        return;
    }

    exploded.clear();

    // if fit points are known, update from fit points, otherwise from
    // control points:
    // TODO: use fitpoints from DXF/DWG file if possible (fit points might not correspond to control points):
    if (fitPoints.size()==0) {
        updateFromControlPoints();
    }
    else {
        updateFromFitPoints();
    }

    //updateBoundingBox();
    boundingBox = RBox();
    //getExploded();

    updateInProgress = false;
}
예제 #4
0
RBox RSpline::getBoundingBox() const {
    if (!isValid()) {
        return RBox();
    }

    if (!boundingBox.isValid()) {
        updateBoundingBox();
    }

    return boundingBox;

    //ON_3dPoint onmin;
    //ON_3dPoint onmax;
    //curve.GetBoundingBox(onmin, onmax);

//    double min[3];
//    double max[3];
//    curve.GetBBox(min, max);

    //ON_BoundingBox bb;
    //curve.GetTightBoundingBox(bb);

    //return RBox(RVector(bb.Min().x, bb.Min().y), RVector(bb.Max().x, bb.Max().y));
    //return RBox(RVector(min[0], min[1]), RVector(max[0], max[1]));
}
예제 #5
0
파일: REllipse.cpp 프로젝트: Jackieee/qcad
RBox REllipse::getBoundingBox() const {
    double radius1 = getMajorRadius();
    double radius2 = getMinorRadius();
    double angle = getAngle();
    double a1 = ((!isReversed()) ? startParam : endParam);
    double a2 = ((!isReversed()) ? endParam : startParam);
    RVector startPoint = getStartPoint();
    RVector endPoint = getEndPoint();

    double minX = qMin(startPoint.x, endPoint.x);
    double minY = qMin(startPoint.y, endPoint.y);
    double maxX = qMax(startPoint.x, endPoint.x);
    double maxY = qMax(startPoint.y, endPoint.y);

    // kind of a brute force. TODO: exact calculation
    RVector vp;
    double a = a1;
    do {
        vp.set(center.x + radius1 * cos(a),
               center.y + radius2 * sin(a));
        vp.rotate(angle, center);

        minX = qMin(minX, vp.x);
        minY = qMin(minY, vp.y);
        maxX = qMax(maxX, vp.x);
        maxY = qMax(maxY, vp.y);

        a += 0.03;
    } while (RMath::isAngleBetween(a, a1, a2, false) && a<4*M_PI);

    return RBox(RVector(minX,minY), RVector(maxX,maxY));
}
예제 #6
0
void RSpline::updateInternal() const {
    if (!dirty || updateInProgress) {
        return;
    }

    dirty = false;
    updateInProgress = true;

    if (degree<2 || degree>3) {
        invalidate();
        qWarning() << "RSpline::updateInternal: invalid degree: " << degree;
        updateInProgress = false;
        return;
    }

    exploded.clear();

    // if fit points are known, update from fit points, otherwise from
    // control points:
    if (fitPoints.size()==0) {
        updateFromControlPoints();
    }
    else {
        updateFromFitPoints();
    }

    //updateBoundingBox();
    boundingBox = RBox();
    getExploded();

    updateInProgress = false;
}
예제 #7
0
void RDimensionData::update() const {
    dirty = true;
    textData.update();
    boundingBox = RBox();
    if (!autoUpdatesBlocked) {
        //qDebug() << "clear dim block name";
        dimBlockName = "";
    }
}
예제 #8
0
void RSpatialIndexSimple::addToIndex(
    int id, int pos,
    double x1, double y1, double z1,
    double x2, double y2, double z2) {

    Q_ASSERT(si[id].size()==pos);
    si[id].insert(pos, RBox(RVector(x1,y1,z1), RVector(x2,y2,z2)));
    //si.insert(id, RBox(RVector(x1,y1,z1), RVector(x2,y2,z2)));
}
예제 #9
0
RBox RGraphicsView::getBox() const {
    QList<RVector> corners = mapCornersFromView();

    return RBox(
        RVector::getMinimum(
            RVector::getMinimum(corners[0], corners[1]),
            RVector::getMinimum(corners[2], corners[3])
        ),
        RVector::getMaximum(
            RVector::getMaximum(corners[0], corners[1]),
            RVector::getMaximum(corners[2], corners[3])
        )
    );
}
예제 #10
0
RBox RTextBasedData::getBoundingBox(bool ignoreEmpty) const {
    if (!boundingBox.isValid() || dirty) {
        getPainterPaths(gotDraft);
    }

//    if (!ignoreEmpty && boundingBox.getWidth()<RS::PointTolerance && boundingBox.getHeight()<RS::PointTolerance) {
//        RDebug::printBacktrace();
//    }

    if (ignoreEmpty && boundingBox.getWidth()<RS::PointTolerance && boundingBox.getHeight()<RS::PointTolerance) {
        return RBox();
    }

    return boundingBox;
}
예제 #11
0
/**
 * Maps the given \c box (e.g. a 3d bounding box) to a 2d box
 * in view coordinates (pixels).
 */
RBox RGraphicsView::mapToView(const RBox& box) const {
    QList<RVector> boxCorners = box.getCorners();

    RVector minView(RMAXDOUBLE, RMAXDOUBLE, RMAXDOUBLE);
    RVector maxView(RMINDOUBLE, RMINDOUBLE, RMINDOUBLE);
    RVector corner;

    for (int i=0; i<8; i++) {
        corner = mapToView(boxCorners[i]);
        minView = RVector::getMinimum(corner, minView);
        maxView = RVector::getMaximum(corner, maxView);
    }

    return RBox(minView, maxView);
}
예제 #12
0
RBox RPolyline::getBoundingBox() const {
    RBox ret;

    if (countVertices()==1) {
        ret = RBox(vertices.at(0), vertices.at(0));
    }

    QList<QSharedPointer<RShape> > sub = getExploded();
    QList<QSharedPointer<RShape> >::iterator it;
    for (it=sub.begin(); it!=sub.end(); ++it) {
        RBox bb = (*it)->getBoundingBox();
        ret.growToInclude(bb);
    }

    return ret;
}
예제 #13
0
/**
 * \return The one shape that is part of this entity which is the
 *      closest to the given position.
 */
QSharedPointer<RShape> REntityData::getClosestShape(const RVector& pos, double range) const {
    QSharedPointer<RShape> ret;

    QList<QSharedPointer<RShape> > shapes;
    if (RMath::isNaN(range)) {
        shapes = getShapes();
    }
    else {
        shapes = getShapes(RBox(pos, range));
    }

    // entity not based on shape:
    if (shapes.size()==0) {
        return ret;
    }

    // entity based on one or more shapes, find closest:
    double minDistance = RMAXDOUBLE;
    QList<QSharedPointer<RShape> >::const_iterator it;
    for (it=shapes.constBegin(); it!=shapes.constEnd(); ++it) {
        QSharedPointer<RShape> shape = (*it);

        // explode shape if possible:
        QList<QSharedPointer<RShape> > subShapes;
        QSharedPointer<RExplodable> explodable = shape.dynamicCast<RExplodable>();
        // 20110916: interpolated shapes are not exploded at this point (e.g.
        // for perpendicular snap to spline inside block):
        if (explodable.isNull() || shape->isInterpolated()) {
            subShapes.append(QSharedPointer<RShape>(shape->clone()));
        }
        else {
            subShapes = explodable->getExploded();
        }

        QList<QSharedPointer<RShape> >::iterator it2;
        for (it2=subShapes.begin(); it2!=subShapes.end(); ++it2) {
            QSharedPointer<RShape> shape2 = (*it2);
            double distance = shape2->getDistanceTo(pos);
            if (distance<minDistance) {
                minDistance = distance;
                ret = shape2;
            }
        }
    }

    return ret;
}
예제 #14
0
RBox RMemoryStorage::getBoundingBox(bool includeHiddenLayer) {
    if (!boundingBoxChanged) {
        return boundingBox;
    }

    RBlock::Id currentBlockId = getCurrentBlockId();
    boundingBox = RBox();
    maxLineweight = RLineweight::Weight000;
    QHash<RObject::Id, QSharedPointer<REntity> >::iterator it;
    for (it = entityMap.begin(); it != entityMap.end(); ++it) {
        QSharedPointer<REntity> e = *it;
        if (e.isNull() || e->isUndone()) {
            continue;
        }

        if (includeHiddenLayer) {
            QSharedPointer<RLayer> layer = queryLayerDirect(e->getLayerId());
            if (layer.isNull() || layer->isFrozen()) {
                continue;
            }
        }

        if (e->getBlockId() == currentBlockId) {
            boundingBox.growToInclude(e->getBoundingBox());
        }

        // resolve line width ByLayer:
        //QSharedPointer<RLayer> layer =
        //        queryLayerDirect(e->getLayerId());

        // don't resolve block references, if line weight is ByBlock,
        // the maxLinewidth will be adjusted when the block reference
        // is encountered:
        QStack<RBlockReferenceEntity*> blockRefStack;

        RLineweight::Lineweight lw =
                e->getLineweight(true, blockRefStack);
        if (!boundingBox.isValid()) {
            maxLineweight = lw;
        } else {
            maxLineweight = qMax(lw, maxLineweight);
        }
    }

    boundingBoxChanged = false;
    return boundingBox;
}
예제 #15
0
/**
 * \return Closest point to \c point on this entity. Used for snap to
 *        points on entity.
 */
RVector REntityData::getClosestPointOnEntity(const RVector& point,
    double range, bool limited) const {

    Q_UNUSED(range)

    RVector ret = RVector::invalid;
    double minDist = RMAXDOUBLE;
    QList<QSharedPointer<RShape> > shapes = getShapes(RBox(), true);
    for (int i=0; i<shapes.size(); i++) {
        RVector r = shapes.at(i)->getClosestPointOnShape(point, limited);
        double dist = r.getDistanceTo(point);
        if (!ret.isValid() || dist<minDist) {
            ret = r;
            minDist = dist;
        }
    }
    return ret;
}
예제 #16
0
void RMemoryStorage::clear() {
    RStorage::clear();

    maxLineweight = RLineweight::Weight000;
    inTransaction = false;
    boundingBoxChanged = true;
    boundingBox = RBox();
    objectMap.clear();
    entityMap.clear();
    blockEntityMap.clear();
    blockMap.clear();
    layerMap.clear();
    transactionMap.clear();
    variables.clear();
    variableCaseMap.clear();
    knownVariables.clear();
    linetypeScale = 1.0;
    setLastTransactionId(-1);
}
예제 #17
0
RBox RMemoryStorage::getBoundingBox(bool ignoreHiddenLayers, bool ignoreEmpty) const {
    if (!boundingBoxChanged) {
        return boundingBox[ignoreHiddenLayers][ignoreEmpty];
    }

    RBlock::Id currentBlockId = getCurrentBlockId();
    boundingBox[0][0] = RBox();
    boundingBox[0][1] = RBox();
    boundingBox[1][0] = RBox();
    boundingBox[1][1] = RBox();
    maxLineweight = RLineweight::Weight000;

    QHash<RObject::Id, QSharedPointer<REntity> >::const_iterator it;
    for (it = entityMap.constBegin(); it != entityMap.constEnd(); ++it) {
        QSharedPointer<REntity> e = *it;
        if (e.isNull() || e->isUndone()) {
            continue;
        }

        //if (ignoreHiddenLayers) {
        bool layerHidden = false;
            QSharedPointer<RLayer> layer = queryLayerDirect(e->getLayerId());
            if (layer.isNull() || layer->isFrozen()) {
                layerHidden = true;
            }
        //}

        if (e->getBlockId() == currentBlockId) {
            //bb.growToInclude(e->getBoundingBox(ignoreEmpty));

            RBox bb = e->getBoundingBox(false);
            RBox bbIgnoreEmpty = e->getBoundingBox(true);

            if (!bb.isSane()) {
                continue;
            }

            boundingBox[0][0].growToInclude(bb);
            boundingBox[0][1].growToInclude(bbIgnoreEmpty);
            if (!layerHidden) {
                boundingBox[1][0].growToInclude(bb);
                boundingBox[1][1].growToInclude(bbIgnoreEmpty);
            }
        }

        // don't resolve block references, if line weight is ByBlock,
        // the maxLinewidth will be adjusted when the block reference
        // is encountered:
        QStack<REntity*> blockRefStack;

        RLineweight::Lineweight lw = e->getLineweight(true, blockRefStack);
        maxLineweight = qMax(lw, maxLineweight);
    }

    boundingBoxChanged = false;

//    qDebug() << "\n\nbb: " << boundingBox[0][0];
//    qDebug() << "bb ignoreEmpty: " << boundingBox[0][1];
//    qDebug() << "bb ignoreHiddenLayers: " << boundingBox[1][0];
//    qDebug() << "bb ignoreHiddenLayers, ignoreEmpty: " << boundingBox[1][1];

    return boundingBox[ignoreHiddenLayers][ignoreEmpty];
}
예제 #18
0
RBox RViewportData::getBoundingBox(bool ignoreEmpty) const {
    Q_UNUSED(ignoreEmpty)

    RVector v(width/2, height/2);
    return RBox(center - v, center + v);
}
예제 #19
0
/**
 * Renders the text data into painter paths.
 */
void RTextRenderer::renderSimple() {
    boundingBox = RBox();
    painterPaths.clear();
    richText = "";

    RVector pos = textData.getAlignmentPoint();
    QString text = textData.getEscapedText();
    double textHeight = textData.getTextHeight();
    RS::VAlign verticalAlignment = textData.getVAlign();
    RS::HAlign horizontalAlignment = textData.getHAlign();
    QString fontName = textData.getFontName();
    bool bold = textData.isBold();
    bool italic = textData.isItalic();
    double angle = textData.getAngle();

    // degree:
    text.replace(QRegExp(RTextRenderer::rxDegree), RTextRenderer::chDegree);
    // plus minus:
    text.replace(QRegExp(RTextRenderer::rxPlusMinus), RTextRenderer::chPlusMinus);
    // diameter:
    text.replace(QRegExp(RTextRenderer::rxDiameter), RTextRenderer::chDiameter);

    bool leadingSpaces = false;
    bool trailingSpaces = false;

    if (!text.isEmpty()) {
        if (text.at(0).isSpace()) {
            leadingSpaces = true;
        }
        if (text.at(text.length()-1).isSpace()) {
            trailingSpaces = true;
        }
    }

    // implicit top level format block:
    QTextCharFormat f;
    f.setForeground(QBrush(QColor()));
    currentFormat.push(f);
    QTextLayout::FormatRange fr;
    fr.start = 0;
    fr.length = text.length();
    fr.format = currentFormat.top();
    QList<QTextLayout::FormatRange> formats;
    formats.append(fr);
    blockHeight.push(textHeight);
    blockFont.push(fontName);
    blockBold.push(bold);
    blockItalic.push(italic);
    useCadFont.push(RFontList::isCadFont(blockFont.top()));
    openTags.push(QStringList());

    double horizontalAdvance = 0.0;
    double horizontalAdvanceNoSpacing = 0.0;
    double ascent = 0.0;
    double descent = 0.0;

    // get painter paths for text at height 1.0:
    painterPaths = getPainterPathsForBlock(
                text, formats,
                horizontalAdvance,
                horizontalAdvanceNoSpacing,
                ascent, descent);

    width = horizontalAdvanceNoSpacing * textHeight;

    // transform to scale text from 1.0 to current text height:
    QTransform sizeTransform;
    sizeTransform.scale(textHeight, textHeight);

    // transform paths of text:
    boundingBox = RBox();
    for (int i=0; i<painterPaths.size(); ++i) {
        painterPaths[i].transform(sizeTransform);
        boundingBox.growToInclude(painterPaths[i].getBoundingBox());
    }

    // feature size of a text is its height
    // determines if text is displayed or only bounding box
    double featureSize = boundingBox.getHeight();

    QPen pen;
    for (int i=0; i<painterPaths.size(); ++i) {
        if (i==0) {
            pen = painterPaths[i].getPen();
            if (pen.style()==Qt::NoPen) {
                pen = QPen(painterPaths[i].getBrush().color());
            }
        }
        painterPaths[i].setFeatureSize(featureSize);
    }

    RPainterPath bbPath;
    bbPath.addBox(boundingBox);
    bbPath.setFeatureSize(-featureSize);
    bbPath.setPen(pen);
    painterPaths.append(bbPath);

    //height = boundingBox.getHeight();

    double topLine = textHeight;
    double baseLine = 0.0;
    double bottomLine = descent * textHeight;

    // at this point, the text is at 0/0 with the base line of the
    // first text line at y==0

    double xOffset = 0.0;
    double yOffset = 0.0;

    switch (verticalAlignment) {
    case RS::VAlignTop:
        yOffset = -topLine;
        break;
    case RS::VAlignMiddle:
        yOffset = -textHeight/2.0;
        break;
    case RS::VAlignBase:
        yOffset = -baseLine;
        break;
    case RS::VAlignBottom:
        yOffset = -bottomLine;
        break;
    }

    switch (horizontalAlignment) {
    default:
    case RS::HAlignAlign:
    case RS::HAlignFit:
    case RS::HAlignLeft:
        if (!leadingSpaces) {
            // move completely to the left (left border is 0.0):
            xOffset = -boundingBox.getMinimum().x;
        }
        else {
            xOffset = 0.0;
        }
        break;
    case RS::HAlignMid:
    case RS::HAlignCenter:
        if (!leadingSpaces && !trailingSpaces) {
            xOffset =  -(boundingBox.getMinimum().x +
                          boundingBox.getMaximum().x)/2.0;
        }
        else {
            xOffset = -horizontalAdvance/2.0*textHeight;
        }
        break;
    case RS::HAlignRight:
        if (!trailingSpaces) {
            xOffset = -boundingBox.getMaximum().x;
        }
        else {
            xOffset = -horizontalAdvance*textHeight;
        }
        break;
    }

    height = boundingBox.getHeight();

    QTransform globalTransform;
    globalTransform.translate(pos.x, pos.y);
    globalTransform.rotate(RMath::rad2deg(angle));
    globalTransform.translate(xOffset, yOffset);

    // apply global transform for position, angle and vertical alignment:
    boundingBox = RBox();
    for (int i=0; i<painterPaths.size(); ++i) {
        painterPaths[i].transform(globalTransform);
        boundingBox.growToInclude(painterPaths[i].getBoundingBox());
    }
}
예제 #20
0
/**
 * Updates the grid information, in particular the grid spacing and
 * grid region to the current view port.
 */
void ROrthoGrid::update(bool force) {
    if (!force && viewBox==view.getBox()) {
        return;
    }

    viewBox = view.getBox();
    int viewportNumber = view.getViewportNumber();

    RDocument* doc = view.getDocument();
    if (doc == NULL) {
        qWarning() << "ROrthoGrid::update: document is NULL";
        return;
    }

    RGraphicsScene* scene = view.getScene();
    if (scene==NULL) {
        qWarning() << "ROrthoGrid::update: scene is NULL";
        return;
    }

    RS::ProjectionRenderingHint hint =  scene->getProjectionRenderingHint();

    // for 3d views, we have no convenient way to calculate the grid dimensions:
    if (hint == RS::RenderThreeD) {
        gridBox = RBox(RVector(-1000, -1000), RVector(1000, 1000));
        spacing = RVector(10.0, 10.0);
        return;
    }

    QString key;

    key = QString("Grid/IsometricGrid0%1").arg(viewportNumber);
    isometric = doc->getVariable(key, false, true).toBool();

    RS::Unit unit = doc->getUnit();
    RS::LinearFormat linearFormat = doc->getLinearFormat();

    // default values for missing configurations and 'auto' settings:
    minSpacing.valid = true;
    minMetaSpacing.valid = true;
    if (isFractionalFormat(linearFormat) && !RUnit::isMetric(unit)) {
        //minSpacing.x = minSpacing.y = RNANDOUBLE;
        //minMetaSpacing.x = minMetaSpacing.y = RNANDOUBLE;
        minSpacing.x = minSpacing.y = RUnit::convert(1.0, RS::Inch, unit) / 1024;
        minMetaSpacing.x = minMetaSpacing.y = RUnit::convert(1.0, RS::Inch, unit) / 1024;
    }
    else {
        minSpacing.x = minSpacing.y = 1.0e-6;
        minMetaSpacing.x = minMetaSpacing.y = RNANDOUBLE;
        //minSpacing.x = minSpacing.y = RNANDOUBLE;
        //minMetaSpacing.x = minMetaSpacing.y = 1.0e-6;
    }

    key = QString("Grid/GridSpacingX0%1").arg(viewportNumber);
    QVariant strSx = doc->getVariable(key, QVariant(), true);
    key = QString("Grid/GridSpacingY0%1").arg(viewportNumber);
    QVariant strSy = doc->getVariable(key, QVariant(), true);

    spacing.valid = true;

    bool autoX = !strSx.isValid() || strSx.toString()=="auto";
    bool autoY = !strSy.isValid() || strSy.toString()=="auto";

    // grid spacing x:
    if (!autoX) {
        // fixed:
        double d = RMath::eval(strSx.toString());
        if (!RMath::hasError() && d>RS::PointTolerance) {
            minSpacing.x = spacing.x = d;
        }
    }

    // grid spacing y:
    if (!autoY) {
        double d = RMath::eval(strSy.toString());
        if (!RMath::hasError() && d>RS::PointTolerance) {
            minSpacing.y = spacing.y = d;
        }
    }




    // meta grid:
    key = QString("Grid/MetaGridSpacingX0%1").arg(viewportNumber);
    QVariant strMsx = doc->getVariable(key, QVariant(), true);
    key = QString("Grid/MetaGridSpacingY0%1").arg(viewportNumber);
    QVariant strMsy = doc->getVariable(key, QVariant(), true);

    metaSpacing.valid = true;

    bool metaAutoX = !strMsx.isValid() || strMsx.toString()=="auto";
    bool metaAutoY = !strMsy.isValid() || strMsy.toString()=="auto";

    // meta grid spacing x:
    if (!metaAutoX) {
        // fixed:
        double d = RMath::eval(strMsx.toString());
        if (d>RS::PointTolerance) {
            minMetaSpacing.x = metaSpacing.x = d;
        }
    }

    // meta grid spacing y:
    if (!metaAutoY) {
        // fixed:
        double d = RMath::eval(strMsy.toString());
        if (d>RS::PointTolerance) {
            minMetaSpacing.y = metaSpacing.y = d;
        }
    }

    // auto scale grid:
    QList<RVector> s = getIdealSpacing(minPixelSpacing, minSpacing, minMetaSpacing);
    if (RSettings::getAutoScaleGrid()) {
        autoSpacing = spacing = s.at(0);
    }
    if (RSettings::getAutoScaleMetaGrid()) {
        autoMetaSpacing = metaSpacing = s.at(1);
    }

    // switch grid off below given pixel limit:
    if (view.mapDistanceToView(spacing.x) < minPixelSpacing) {
        spacing = RVector::invalid;
    }
    if (view.mapDistanceToView(metaSpacing.x) < minPixelSpacing) {
        metaSpacing = RVector::invalid;
    }
    if (view.mapDistanceToView(spacing.y) < minPixelSpacing) {
        spacing = RVector::invalid;
    }
    if (view.mapDistanceToView(metaSpacing.y) < minPixelSpacing) {
        metaSpacing = RVector::invalid;
    }

//    qDebug() << "spacing: " << spacing;
//    qDebug() << "minSpacing: " << minSpacing;
//    qDebug() << "metaSpacing: " << metaSpacing;

//    if (scaleGrid) {
//        QList<RVector> s = ROrthoGrid::getIdealSpacing(view, minPixelSpacing, minSpacing);
//        spacing = s.at(0);
//        metaSpacing = s.at(1);
//    } else {
//        spacing = minSpacing;
//    }
    
    RVector minGridPoint;
    RVector maxGridPoint;

    spacing.z = 1;

    if (isometric) {
        spacing.x = spacing.y * 2.0 * sin(M_PI/3.0);
        metaSpacing.x = metaSpacing.y * 2.0 * sin(M_PI/3.0);

        spacing = spacing / 2;
        //metaSpacing = metaSpacing / 2;
    }

    minGridPoint = viewBox.getCorner1();
    minGridPoint = minGridPoint.getDividedComponents(spacing).getFloor();
    minGridPoint = minGridPoint.getMultipliedComponents(spacing);

    maxGridPoint = viewBox.getCorner2();
    maxGridPoint = maxGridPoint.getDividedComponents(spacing).getCeil();
    maxGridPoint = maxGridPoint.getMultipliedComponents(spacing);

    minGridPoint.z = viewBox.getCorner1().z;
    maxGridPoint.z = viewBox.getCorner2().z;
    
    gridBox = RBox(minGridPoint, maxGridPoint);

    minGridPoint = viewBox.getCorner1();
    minGridPoint = minGridPoint.getDividedComponents(metaSpacing).getFloor();
    minGridPoint = minGridPoint.getMultipliedComponents(metaSpacing);

    maxGridPoint = viewBox.getCorner2();
    maxGridPoint = maxGridPoint.getDividedComponents(metaSpacing).getCeil();
    maxGridPoint = maxGridPoint.getMultipliedComponents(metaSpacing);

    minGridPoint.z = viewBox.getCorner1().z;
    maxGridPoint.z = viewBox.getCorner2().z;
    
    metaGridBox = RBox(minGridPoint, maxGridPoint);

    if (isometric) {
        QString i1 = RUnit::getLabel(spacing.x / cos(M_PI/6), *doc, true, true);
        QString i2 = RUnit::getLabel(metaSpacing.x / cos(M_PI/6) / 2, *doc, true, true);
        infoText = QString("%1 < %2").arg(i1).arg(i2);
    }
    else {
        QString i1 = RUnit::getLabel(spacing.x, *doc, true, true);
        QString i2 = RUnit::getLabel(metaSpacing.x, *doc, true, true);
        infoText = QString("%1 < %2").arg(i1).arg(i2);
    }
}
예제 #21
0
void RDimensionData::update() const {
    dirty = true;
    textData.update();
    boundingBox = RBox();
}
예제 #22
0
/**
 * Renders the text data into painter paths.
 */
void RTextRenderer::render() {
    boundingBox = RBox();
    painterPaths.clear();
    richText = "";

    QString text = textData.getEscapedText();
    //RVector position = textData.getPosition();
    RVector position = textData.getAlignmentPoint();
    double textHeight = textData.getTextHeight();
    RS::VAlign verticalAlignment = textData.getVAlign();
    RS::HAlign horizontalAlignment = textData.getHAlign();
    double lineSpacingFactor = textData.getLineSpacingFactor();
    QString fontName = textData.getFontName();
    bool bold = textData.isBold();
    bool italic = textData.isItalic();
    double angle = textData.getAngle();
    //RColor color = textData.getColor(true);

    // split up text where separation is required due to line feed,
    // or any type of height change (\P, \H[0-9]*.?[0-9]+;, \S*/*;)

    // split up text at every formatting change:
    QRegExp regExpAll(rxAll);
    QStringList literals = text.split(regExpAll);

    // collect formatting change information for every literal:
    QStringList formattings;
    int pos = 0;
    while ((pos = regExpAll.indexIn(text, pos)) != -1) {
        formattings << regExpAll.cap(1);
        pos += regExpAll.matchedLength();
    }

    // x position in real units:
    double xCursor = 0.0;
    // y position for next text line:
    double yCursor = 0.0;
    // painter paths for current text line:
    QList<RPainterPath> linePaths;
    // max ascent of current text line:
    double maxAscent = 0.0;
    // max descent of current line:
    double minDescent = 0.0;
    // max descent of _previous_ line:
    double minDescentPrevious = 0.0;
    // true for the first block of the current line:
    bool firstBlockInLine = true;
    // current line has leading spaces:
    bool leadingSpaces = false;
    // current line has trailing spaces:
    bool trailingSpaces = false;
    // text has leading empty lines:
    bool leadingEmptyLines = false;
    // text has trailing empty lines:
    bool trailingEmptyLines = false;
    int lineCounter = 0;
    QString textBlock;
    QList<QTextLayout::FormatRange> formats;

    bool blockChangedHeightOrFont = false;

    // implicit top level format block:
    QTextCharFormat f;
    f.setForeground(QBrush(QColor()));
    currentFormat.push(f);
    QTextLayout::FormatRange fr;
    fr.start = 0;
    fr.length = 0;
    fr.format = currentFormat.top();
    formats.append(fr);
    blockHeight.push(textHeight);
    blockFont.push(fontName);
    blockBold.push(bold);
    blockItalic.push(italic);
    useCadFont.push(RFontList::isCadFont(fontName));
    openTags.push(QStringList());

    width = 0.0;
    height = 0.0;

    // iterate through all text blocks:
    for (int i=0; i<literals.size(); ++i) {

        // the literal text, e.g. "ABC":
        QString literal = literals.at(i);

        // the formatting _after_ the text, e.g. "\C1;"
        QString formatting;
        if (i<formattings.size()) {
            formatting = formattings.at(i);
        }

//        qDebug() << "block: " << i;
//        qDebug() << "  literal: " << literal;
//        qDebug() << "  literal length: " << literal.length();
//        qDebug() << "  formatting: " << formatting;
//        qDebug() << "  font: " << blockFont.top();
//        qDebug() << "  height: " << blockHeight.top();
//        qDebug() << "  cad font: " << useCadFont.top();
//        qDebug() << "  xCursor: " << xCursor;

        // handle literal:
        textBlock.append(literal);

        if (firstBlockInLine) {
            if (!literal.isEmpty()) {
                if (literal.at(0).isSpace()) {
                    leadingSpaces = true;
                }
            }
            else {
                if (formatting=="\\~") {
                    leadingSpaces = true;
                }
            }
            firstBlockInLine = false;
        }

        bool lineFeed = false;
        bool paragraphFeed = false;
        bool heightChange = false;
        bool stackedText = false;
        bool fontChange = false;
        bool colorChange = false;
        bool blockEnd = false;

        // detect formatting that ends the current text block:
        if (!formatting.isEmpty()) {
            fontChange = QRegExp(rxFontChangeTtf).exactMatch(formatting) ||
                QRegExp(rxFontChangeCad).exactMatch(formatting);
            colorChange = QRegExp(rxColorChangeCustom).exactMatch(formatting) ||
                QRegExp(rxColorChangeIndex).exactMatch(formatting);
            heightChange = QRegExp(rxHeightChange).exactMatch(formatting);
            stackedText = QRegExp(rxStackedText).exactMatch(formatting);
            lineFeed = QRegExp(rxLineFeed).exactMatch(formatting);
            paragraphFeed = QRegExp(rxParagraphFeed).exactMatch(formatting);
            blockEnd = QRegExp(rxEndBlock).exactMatch(formatting);
        }

        bool start = (i==0);
        bool end = (i==literals.size()-1);

        // first line is empty:
        if (textBlock.trimmed().isEmpty() && (lineFeed || paragraphFeed || end)) {
            if (start) {
                leadingEmptyLines = true;
            }
            else if (end) {
                trailingEmptyLines = true;
            }
        }

        // reached a new text block that needs to be rendered separately
        // due to line feed, height change, font change, ...:
        if (target==RichText ||
            lineFeed || paragraphFeed || heightChange || stackedText ||
            fontChange || colorChange || end
            || (blockEnd && blockChangedHeightOrFont)) {

            // render block _before_ format change that requires new block:
            if (textBlock!="") {
                // fix format lengths to match up. each format stops where
                // the next one starts. formatting that is carried over is set
                // again for the new format.
                for (int i=0; i<formats.size(); i++) {
                    int nextStart;
                    if (i<formats.size()-1) {
                        nextStart = formats[i+1].start;
                    }
                    else {
                        nextStart = textBlock.length();
                    }
                    formats[i].length = nextStart - formats[i].start;
                }

                if (target==RichText) {
                    richText += getRichTextForBlock(
                                   textBlock, formats);
                }

                if (target==PainterPaths) {
                    double horizontalAdvance = 0.0;
                    double horizontalAdvanceNoSpacing = 0.0;
                    double ascent = 0.0;
                    double descent = 0.0;
                    QList<RPainterPath> paths;

                    // get painter paths for current text block at height 1.0:
                    paths = getPainterPathsForBlock(
                                textBlock, formats,
                                horizontalAdvance,
                                horizontalAdvanceNoSpacing,
                                ascent, descent);

                    // transform to scale text from 1.0 to current text height:
                    QTransform sizeTransform;
                    sizeTransform.scale(blockHeight.top(), blockHeight.top());

                    // transform for current block due to xCursor position:
                    QTransform blockTransform;
                    blockTransform.translate(xCursor, 0);

                    // combine transforms for current text block:
                    QTransform allTransforms = sizeTransform;
                    allTransforms *= blockTransform;

                    maxAscent = qMax(maxAscent, ascent * blockHeight.top());
                    minDescent = qMin(minDescent, descent * blockHeight.top());

                    // transform paths of current block and append to paths
                    // of current text line:
                    for (int i=0; i<paths.size(); ++i) {
                        RPainterPath p = paths.at(i);
                        p.transform(allTransforms);
                        linePaths.append(p);
                    }

                    xCursor += horizontalAdvance * blockHeight.top();
                }
            }

            // empty text, might be line feed, we need ascent, descent anyway:
            else if (lineFeed || paragraphFeed || end) {
                if (target==PainterPaths) {
                    double horizontalAdvance = 0.0;
                    double horizontalAdvanceNoSpacing = 0.0;
                    double ascent = 0.0;
                    double descent = 0.0;

                    // get painter paths for current text block at height 1.0:
                    getPainterPathsForBlock(
                                "A", QList<QTextLayout::FormatRange>(),
                                horizontalAdvance,
                                horizontalAdvanceNoSpacing,
                                ascent, descent);

                    maxAscent = qMax(maxAscent, ascent * blockHeight.top());
                    minDescent = qMin(minDescent, descent * blockHeight.top());
                }
            }

            // handle stacked text:
            if (stackedText) {
                QRegExp reg;
                reg.setPattern(rxStackedText);
                reg.exactMatch(formatting);

                if (target==PainterPaths) {
                    double horizontalAdvance[2];
                    horizontalAdvance[0] = 0.0;
                    horizontalAdvance[1] = 0.0;
                    double horizontalAdvanceNoSpacing[2];
                    horizontalAdvanceNoSpacing[0] = 0.0;
                    horizontalAdvanceNoSpacing[1] = 0.0;
                    double heightFactor = 0.4;

                    // s==0: superscript, s==1: subscript:
                    for (int s=0; s<=1; ++s) {
                        QString script = reg.cap(s+1);

                        QList<RPainterPath> paths;

                        double ascent = 0.0;
                        double descent = 0.0;

                        QList<QTextLayout::FormatRange> localFormats;

                        QTextLayout::FormatRange fr;
                        fr.start = 0;
                        fr.length = script.length();
                        fr.format = currentFormat.top();
                        localFormats.append(fr);

                        // get painter paths for superscript at height 1.0:
                        paths = getPainterPathsForBlock(
                                    script, localFormats,
                                    horizontalAdvance[s],
                                    horizontalAdvanceNoSpacing[s],
                                    ascent, descent);

                        if (s==0) {
                            maxAscent = qMax(maxAscent, ascent * blockHeight.top() * heightFactor + blockHeight.top()*(1.0-heightFactor));
                        }
                        else {
                            minDescent = qMin(minDescent, descent * blockHeight.top() * heightFactor);
                        }

                        // transform to scale text from 1.0 to current text height * 0.4:
                        QTransform sizeTransform;
                        sizeTransform.scale(blockHeight.top()*heightFactor, blockHeight.top()*heightFactor);

                        // move top text more to the right for italic texts:
                        double xOffset = 0.0;
                        if (s==0 && blockItalic.top()==true) {
                            double y = blockHeight.top()*(1.0-heightFactor);
                            // assume italic means roughly 12 degrees:
                            xOffset = tan(RMath::deg2rad(12)) * y;
                        }

                        // transform for current block due to xCursor position
                        // and top or bottom text position:
                        QTransform blockTransform;
                        blockTransform.translate(xCursor + xOffset,
                                                 s==0 ? blockHeight.top()*(1.0-heightFactor) : 0.0);

                        horizontalAdvance[s] += xOffset / (blockHeight.top() * heightFactor);

                        // combine transforms for current text block:
                        QTransform allTransforms = sizeTransform;
                        allTransforms *= blockTransform;

                        // transform paths of current block and append to paths
                        // of current text line:
                        for (int i=0; i<paths.size(); ++i) {
                            RPainterPath p = paths.at(i);
                            p.transform(allTransforms);
                            linePaths.append(p);
                        }
                    }

                    xCursor += qMax(horizontalAdvance[0], horizontalAdvance[1]) * blockHeight.top() * heightFactor;
                }

                if (target==RichText) {
                    QString super = reg.cap(1);
                    QString sub = reg.cap(2);
                    if (!super.isEmpty()) {
                        richText += QString("<span style=\"vertical-align:super;\">%1</span>").arg(super);
                    }
                    if (!sub.isEmpty()) {
                        richText += QString("<span style=\"vertical-align:sub;\">%1</span>").arg(sub);
                    }
                }
            }

            // prepare for next text block:
            if (lineFeed || paragraphFeed || end) {
                if (!textBlock.isEmpty()) {
                    if (textBlock.at(textBlock.length()-1).isSpace()) {
                        trailingSpaces = true;
                    }
                }
//                else {
//                    if (formatting=="\\~") {
//                        trailingSpaces = true;
//                    }
//                }
            }

            textBlock = "";
            formats.clear();
            QTextLayout::FormatRange fr;
            fr.start = 0;
            fr.length = 0;
            fr.format = currentFormat.top();
            formats.append(fr);

            // handle text line.
            // add all painter paths of the current line to result set of
            // painter paths. apply line feed transformations.
            if (lineFeed || paragraphFeed || end) {
//                qDebug() << "lineFeed: adding text line:";
//                qDebug() << "  maxAscent: " << maxAscent;
//                qDebug() << "  minDescent: " << minDescent;
//                qDebug() << "  minDescentPrevious: " << minDescentPrevious;
//                qDebug() << "got line feed or end";
//                qDebug() << "  trailingSpaces: " << trailingSpaces;

                if (target==RichText) {
                    if (lineFeed || paragraphFeed) {
                        richText += "<br/>";
                    }
                }

                if (lineCounter!=0) {
                    yCursor += (minDescentPrevious - maxAscent) * lineSpacingFactor;
                }

                // calculate line bounding box for alignment without spaces at borders:
                RBox lineBoundingBox;
                for (int i=0; i<linePaths.size(); ++i) {
                    RPainterPath p = linePaths.at(i);
                    lineBoundingBox.growToInclude(p.getBoundingBox());
                }

                double featureSize = lineBoundingBox.getHeight();

                QTransform lineTransform;

                switch (horizontalAlignment) {
                case RS::HAlignAlign:
                case RS::HAlignFit:
                case RS::HAlignLeft:
                    if (!leadingSpaces) {
                        // move completely to the left (left border is 0.0):
                        lineTransform.translate(
                                    -lineBoundingBox.getMinimum().x,
                                    yCursor);
                    }
                    else {
                        lineTransform.translate(0, yCursor);
                    }
                    break;
                case RS::HAlignMid:
                case RS::HAlignCenter:
                    if (!leadingSpaces && !trailingSpaces) {
                        lineTransform.translate(
                                    -(lineBoundingBox.getMinimum().x +
                                      lineBoundingBox.getMaximum().x)/2.0,
                                    yCursor);
                    }
                    else {
                        lineTransform.translate(-xCursor/2.0, yCursor);
                    }
                    break;
                case RS::HAlignRight:
                    if (!trailingSpaces) {
                        lineTransform.translate(-lineBoundingBox.getMaximum().x, yCursor);
                    }
                    else {
                        lineTransform.translate(-xCursor, yCursor);
                    }
                    break;
                }

                width = qMax(width, lineBoundingBox.getMaximum().x - qMin(0.0, lineBoundingBox.getMinimum().x));

                // add current text line to result set:
                QPen pen;
                for (int i=0; i<linePaths.size(); ++i) {
                    RPainterPath p = linePaths[i];
                    if (i==0) {
                        pen = p.getPen();
                        if (pen.style()==Qt::NoPen) {
                           pen = QPen(p.getBrush().color());
                        }
                    }
                    p.transform(lineTransform);
                    p.setFeatureSize(featureSize);
                    painterPaths.append(p);
                    boundingBox.growToInclude(p.getBoundingBox());
                }

                RPainterPath bbPath;
                bbPath.addBox(lineBoundingBox);
                bbPath.transform(lineTransform);
                bbPath.setFeatureSize(-featureSize);
                bbPath.setPen(pen);
                painterPaths.append(bbPath);

                lineCounter++;
                xCursor = 0.0;
                maxAscent = 0.0;
                minDescentPrevious = minDescent;
                minDescent = 0.0;
                linePaths.clear();
                firstBlockInLine = true;
                leadingSpaces = false;
                trailingSpaces = false;
            }
        }

        // handle formatting after text block, that applies either
        // to the next text block(s) or the rest of the current text block:
        if (formatting.isEmpty()) {
            continue;
        }

        QRegExp reg;

        // unicode:
        reg.setPattern(rxUnicode);
        if (reg.exactMatch(formatting)) {
            textBlock += QChar(reg.cap(1).toInt(0, 16));
            continue;
        }

        // curly braket open:
        reg.setPattern(rxCurlyOpen);
        if (reg.exactMatch(formatting)) {
            textBlock += "{";
            continue;
        }

        // curly braket close:
        reg.setPattern(rxCurlyClose);
        if (reg.exactMatch(formatting)) {
            textBlock += "}";
            continue;
        }

        // degree:
        reg.setPattern(rxDegree);
        if (reg.exactMatch(formatting)) {
            textBlock += chDegree;
            continue;
        }

        // plus/minus:
        reg.setPattern(rxPlusMinus);
        if (reg.exactMatch(formatting)) {
            textBlock += chPlusMinus;
            continue;
        }

        // diameter:
        reg.setPattern(rxDiameter);
        if (reg.exactMatch(formatting)) {
            textBlock += chDiameter;
            continue;
        }

        // backslash:
        reg.setPattern(rxBackslash);
        if (reg.exactMatch(formatting)) {
            textBlock += "\\";
            continue;
        }

        // non-breaking space:
        reg.setPattern(rxNonBreakingSpace);
        if (reg.exactMatch(formatting)) {
            if (target==PainterPaths) {
                textBlock += QChar(Qt::Key_nobreakspace);
            }
            if (target==RichText) {
                textBlock += "&nbsp;";
            }
            continue;
        }

        // font change (TTF):
        reg.setPattern(rxFontChangeTtf);
        if (reg.exactMatch(formatting)) {
            blockFont.top() = reg.cap(1);
            blockBold.top() = (reg.cap(2).toInt()!=0);
            blockItalic.top() = (reg.cap(3).toInt()!=0);
            useCadFont.top() = false;
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-family:%1;").arg(blockFont.top());
                style += QString("font-weight:%1;").arg(blockBold.top() ? "bold" : "normal");
                style += QString("font-style:%1;").arg(blockItalic.top() ? "italic" : "normal");
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // font change (CAD):
        reg.setPattern(rxFontChangeCad);
        if (reg.exactMatch(formatting)) {
            blockFont.top() = reg.cap(1);
            useCadFont.top() = true;
            if (xCursor>RS::PointTolerance) {
                RFont* f = RFontList::get(blockFont.top());
                if (f!=NULL && f->isValid()) {
                    xCursor += f->getLetterSpacing() / 9.0;
                }
            }
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-family:%1;").arg(blockFont.top());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // height change:
        reg.setPattern(rxHeightChange);
        if (reg.exactMatch(formatting)) {
            bool factor = reg.cap(2)=="x";

            if (factor) {
                blockHeight.top() *= reg.cap(1).toDouble();
            }
            else {
                blockHeight.top() = reg.cap(1).toDouble();
            }
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-size:%1pt;").arg(blockHeight.top() * fontHeightFactor);
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        QTextLayout::FormatRange fr;
        fr.start = textBlock.length();
        fr.length = 0;

        // start format block:
        reg.setPattern(rxBeginBlock);
        if (reg.exactMatch(formatting)) {
            currentFormat.push(currentFormat.top());
            blockFont.push(blockFont.top());
            blockBold.push(blockBold.top());
            blockItalic.push(blockItalic.top());
            blockHeight.push(blockHeight.top());
            useCadFont.push(useCadFont.top());
            if (target==RichText) {
                openTags.push(QStringList());
            }
            blockChangedHeightOrFont = false;
            continue;
        }

        // end format block:
        reg.setPattern(rxEndBlock);
        if (reg.exactMatch(formatting)) {
            currentFormat.pop();
            fr.format = currentFormat.top();
            formats.append(fr);
            blockFont.pop();
            blockBold.pop();
            blockItalic.pop();
            blockHeight.pop();
            useCadFont.pop();
            blockChangedHeightOrFont = false;

            if (target==RichText) {
                // close all tags that were opened in this block:
                for (int i=openTags.top().size()-1; i>=0; --i) {
                    QString tag = openTags.top().at(i);
                    richText += QString("</%1>").arg(tag);
                }
                openTags.pop();
            }

            continue;
        }

        // color change (indexed):
        reg.setPattern(rxColorChangeIndex);
        if (reg.exactMatch(formatting)) {
            RColor blockColor = RColor::createFromCadIndex(reg.cap(1));
            if (blockColor.isByLayer()) {
                currentFormat.top().setForeground(RColor::CompatByLayer);
            } else if (blockColor.isByBlock()) {
                currentFormat.top().setForeground(RColor::CompatByBlock);
            }
            else {
                currentFormat.top().setForeground(blockColor);
            }
            fr.format = currentFormat.top();
            formats.append(fr);

            if (target==RichText) {
                QString style;
                style += QString("color:%1;").arg(blockColor.name());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // color change (custom):
        reg.setPattern(rxColorChangeCustom);
        if (reg.exactMatch(formatting)) {
            RColor blockColor = RColor::createFromCadCustom(reg.cap(1));
            currentFormat.top().setForeground(blockColor);
            fr.format = currentFormat.top();
            formats.append(fr);

            if (target==RichText) {
                QString style;
                style += QString("color:%1;").arg(blockColor.name());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }
    }

    if (target==PainterPaths) {
        // at this point, the text is at 0/0 with the base line of the
        // first text line at y==0

        // vertical alignment:
        double topLine = qMax(textHeight, boundingBox.getMaximum().y);
        double bottomLine = qMin(0.0, boundingBox.getMinimum().y);

        QTransform globalTransform;
        globalTransform.translate(position.x, position.y);
        globalTransform.rotate(RMath::rad2deg(angle));
        switch (verticalAlignment) {
        case RS::VAlignTop:
            //if (!leadingEmptyLines) {
                globalTransform.translate(0.0, -topLine);
            //}
            break;
        case RS::VAlignMiddle:
            if (leadingEmptyLines || trailingEmptyLines) {
                globalTransform.translate(0.0, -(yCursor+textHeight)/2.0);
            }
            else {
                globalTransform.translate(0.0, -(bottomLine + topLine) / 2.0);
            }
            break;
        case RS::VAlignBottom:
        case RS::VAlignBase:
            if (trailingEmptyLines) {
                globalTransform.translate(0.0, -yCursor);
            }
            else {
                globalTransform.translate(0.0, -bottomLine);
            }
            break;
        }

        height = boundingBox.getHeight();

        // apply global transform for position, angle and vertical alignment:
        boundingBox = RBox();
        for (int i=0; i<painterPaths.size(); ++i) {
            painterPaths[i].transform(globalTransform);
            boundingBox.growToInclude(painterPaths[i].getBoundingBox());
        }
    }

    if (target==RichText) {
        // close all tags that were opened:
        for (int i=openTags.top().size()-1; i>=0; --i) {
            QString tag = openTags.top().at(i);
            richText += QString("</%1>").arg(tag);
        }
    }
}
예제 #23
0
RBox RTriangle::getBoundingBox() const {
    return RBox(RVector::getMinimum(RVector::getMinimum(corner[0], corner[1]),
            corner[2]), RVector::getMaximum(RVector::getMaximum(corner[0],
            corner[1]), corner[2]));
}
예제 #24
0
파일: RSpline.cpp 프로젝트: Jackieee/qcad
void RSpline::update() const {
    dirty = true;
    boundingBox = RBox();
    exploded.clear();
}
예제 #25
0
파일: RPoint.cpp 프로젝트: eric3361229/qcad
RBox RPoint::getBoundingBox() const {
    return RBox(position, position);
}
예제 #26
0
파일: RLine.cpp 프로젝트: ljx0305/qcad
RBox RLine::getBoundingBox() const {
    return RBox(RVector::getMinimum(startPoint, endPoint), RVector::getMaximum(
            startPoint, endPoint));
}
예제 #27
0
파일: RCircle.cpp 프로젝트: fallenwind/qcad
RBox RCircle::getBoundingBox() const {
    return RBox(center - RVector(radius, radius), center + RVector(radius,
            radius));
}
예제 #28
0
파일: RXLine.cpp 프로젝트: Alpha-Kand/qcad
RBox RXLine::getBoundingBox() const {
    return RBox(
        RVector::getMinimum(basePoint, getSecondPoint()),
        RVector::getMaximum(basePoint, getSecondPoint())
    );
}