コード例 #1
0
void DocumentCanvas::zoom(double factor, bool relativezoom, double userCenterX, double userCenterY, unsigned int deviceX, unsigned int deviceY) {
    LcPainter &painter = cachedPainter(VIEWER_DOCUMENT);
    if ((_zoomMax <= painter.scale() && factor > 1.) || (_zoomMin >= painter.scale() && factor < 1.)) {
        return;
    }

    if (relativezoom) {
        factor = factor * painter.scale();
    }

    // Calculate reference device offset at device location
    painter.save();
    double refX = deviceX;
    double refY = deviceY;
    painter.reset_transformations();
    painter.scale(factor);
    painter.device_to_user(&refX, &refY);
    painter.restore();

    // Set translation
    for (auto i = _cachedPainters.begin(); i != _cachedPainters.end(); i++) {
        LcPainter *p = i->second;
        p->reset_transformations();
        p->scale(factor);
        p->translate(refX - userCenterX,-refY + userCenterY);
    }
}
コード例 #2
0
ファイル: lcvspline.cpp プロジェクト: LibreCAD/LibreCAD_3
void LCVSpline::draw(LcPainter &painter, const LcDrawOptions &options, const lc::geo::Area &rect) const {

    auto bezlist = _spline->beziers();

    for(const auto &bezier: bezlist) {
        auto bez = bezier->getCP();

        painter.move_to(bez[0].x(), bez[0].y());

        if(bez.size()==4) {
            painter.curve_to(bez[1].x(), bez[1].y(), bez[2].x(), bez[2].y(), bez[3].x(), bez[3].y());
        } else if (bez.size()==3) {
            painter.quadratic_curve_to(bez[1].x(), bez[1].y(), bez[2].x(), bez[2].y());
        } else if(bez.size()==2) {
            painter.line_to(bez[1].x(), bez[1].y());
        }
    }
    painter.stroke();
}
コード例 #3
0
LcPainter& DocumentCanvas::cachedPainter(PainterCacheType cacheType) {

    double s = 1.;
    double x = 0.;
    double y = 0.;

    if (_cachedPainters.size() != 0) {
        LcPainter* p = _cachedPainters.begin()->second;
        s = p->scale();
        p->getTranslate(&x, &y);
    }

    if (_cachedPainters.count(cacheType) == 0) {
        _cachedPainters[cacheType] = _createPainterFunctor(_deviceWidth, _deviceHeight);
        _cachedPainters[cacheType]->scale(s);
        _cachedPainters[cacheType]->translate(x, y);
    }

    return *_cachedPainters[cacheType];
}
コード例 #4
0
void DocumentCanvas::newDeviceSize(unsigned int width, unsigned int height) {
    if (_deviceWidth!=width && _deviceHeight!=height) {
        _deviceWidth = width;
        _deviceHeight = height;

        double s = 1.;
        double x = 0.;
        double y = 0.;

        if (_cachedPainters.size() != 0) {
            LcPainter* p = _cachedPainters.begin()->second;
            s = p->scale();
            p->getTranslate(&x, &y);
        }

        for (auto i = _cachedPainters.begin(); i != _cachedPainters.end(); i++) {
            _deletePainterFunctor(i->second);
            _cachedPainters[i->first] = _createPainterFunctor(_deviceWidth, _deviceHeight);
            _cachedPainters[i->first]->scale(s);
            _cachedPainters[i->first]->translate(x, y);
        }
    }
}
コード例 #5
0
void DocumentCanvas::pan(double move_x, double move_y) {

    double pan_x=0.;
    double pan_y=0.;

    if (_cachedPainters.size() != 0) {
        LcPainter* p = _cachedPainters.begin()->second;
        p->getTranslate(&pan_x, &pan_y);
    }

    /* FIXME 100.0 should be dynamically calculated, depends on the drawing speed */
    if (std::abs(pan_x-move_x) > 100.0 || std::abs(pan_y - move_y) > 100.0 || pan_x == 0.0 || pan_y == 0.0) {
        pan_x = move_x;
        pan_y = move_y;
    }

    for (auto i = _cachedPainters.begin(); i != _cachedPainters.end(); i++) {
        LcPainter* p = i->second;
        p->translate(move_x - pan_x, move_y - pan_y);
    }

    pan_x = move_x;
    pan_y = move_y;
}
コード例 #6
0
ファイル: lcdimradial.cpp プロジェクト: Solvoj/LibreCAD_3
/**
* Draw a DimRadial
* TODO: 1) Draw correct leader
*       2) Change text position such that it's correctly placed under the text. I am not 100% sure how this is done from DXF
*       It could be that Attachmentpoint is simply incorrect?!?!?! or that the DXF importer is incorrect?
*
*/
void LCDimRadial::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const {
    bool modified = false;

    // Decide to show the explecit value or the measured value
    double radiusCircle = this->definitionPoint().distanceTo(this->definitionPoint2());
    const lc::geo::Coordinate& mousePos = middleOfText();
    const bool mouseIsInside = mousePos.distanceTo(definitionPoint()) < radiusCircle;
    // FIXME this should not be fixed
    const double capSize = 2.;
    
    std::string value = lc::StringHelper::dim_value(explicitValue(), options.radialFormat(), radiusCircle);
    
    /* get text size  */
    painter.save();
    painter.font_size(options.dimTextHeight());
    TextExtends te = painter.text_extends(value.c_str());
    painter.restore();
    
    // Draw line
    EndCaps endCaps;
    auto tLinePos = !mouseIsInside
      ? mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), te.width + capSize)
      : mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), -te.width - capSize);

    auto tMText = !mouseIsInside
      ? mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), te.width / 2 + capSize / 2)
      : mousePos.move(mousePos - lc::geo::Coordinate(definitionPoint().x(), mousePos.y()), -te.width / 2 - capSize / 2);
      
    painter.move_to(definitionPoint2().x(), definitionPoint2().y());
    painter.line_to(mousePos.x(), mousePos.y());
    painter.line_to(tLinePos.x(), mousePos.y());
    painter.stroke();
    endCaps.render(painter, EndCaps::CLOSEDARROW, mousePos.x(), mousePos.y(), definitionPoint2().x(), definitionPoint2().y(), capSize) ;

    this->drawText(value, textAngle(), lc::TextConst::AttachmentPoint::Top_center, tMText, painter, options, rect);

    if (modified) {
        painter.restore();
    }

}
コード例 #7
0
/**
* Draw a DimDiametric
* TODO: draw correct leader and verification if we draw this correctly compared to other CAD drawings
*/
void LCDimDiametric::draw(LcPainter &painter, const LcDrawOptions &options, const lc::geo::Area &rect) const {
    // Decide to show the explecit value or the measured value
    auto diameterCircle = _dimDiametric->definitionPoint().distanceTo(_dimDiametric->definitionPoint2());
    auto circle_middle_p0 = _dimDiametric->definitionPoint2().mid(_dimDiametric->definitionPoint());
    // FIXME this should not be fixed
    const double capSize = 2.;

    auto value = lc::tools::StringHelper::dim_value(
            _dimDiametric->explicitValue(),
            options.diametricFormat(),
            diameterCircle
    );

    /* get text size  */
    painter.save();
    painter.font_size(options.dimTextHeight(), false);
    TextExtends te = painter.text_extends(value.c_str());
    painter.restore();

    EndCaps endCaps;
    const bool textisInside = _dimDiametric->middleOfText().distanceTo(circle_middle_p0) < diameterCircle / 2.;
    const bool textFitsInside = diameterCircle > te.width;
    // Draw inside if the text really fit's and if it was initially setup inside
    // No sure if this follow's DXF spec??
    if (textisInside && textFitsInside) {
        painter.move_to(_dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y());
        painter.line_to(_dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y());
        painter.stroke();

        endCaps.render(
                painter,
                EndCaps::CLOSEDARROW,
                _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(),
                _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(),
                capSize
        );
        endCaps.render(
                painter,
                EndCaps::CLOSEDARROW,
                _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(),
                _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(),
                capSize
        );

        this->drawText(
                value,
                _dimDiametric->textAngle(),
                lc::TextConst::AttachmentPoint::Top_center,
                _dimDiametric->middleOfText(),
                painter,
                options,
                rect
        );

    }
    else {
        // When we draw text outside, we move the arrows around (facing inwards) and we draw a small leader where we place the text on
        // here we ignore _dimDiametric->middleOfText() and I am not sure if that's suppose to work like that (RVT)
        auto center = _dimDiametric->definitionPoint().mid(_dimDiametric->definitionPoint2());
        auto p1 = _dimDiametric->definitionPoint().moveTo(center, -capSize * 1.5);
        auto p2 = _dimDiametric->definitionPoint2().moveTo(center, -capSize * 1.5);

        // take largest X value of both _dimDiametric->definition points (on the right) and draw text there
        if (p1.x() > p2.x()) {
            painter.move_to(p1.x() + capSize, p1.y());
            painter.line_to(p1.x(), p1.y());
            painter.line_to(p2.x(), p2.y());
            painter.stroke();
            this->drawText(
                    value,
                    _dimDiametric->textAngle(),
                    lc::TextConst::AttachmentPoint::Top_left,
                    lc::geo::Coordinate(p1.x(), p1.y()),
                    painter,
                    options,
                    rect
            );
        } else {
            painter.move_to(p2.x() + capSize, p2.y());
            painter.line_to(p2.x(), p2.y());
            painter.line_to(p1.x(), p1.y());
            painter.stroke();
            this->drawText(
                    value,
                    _dimDiametric->textAngle(),
                    lc::TextConst::AttachmentPoint::Top_right,
                    lc::geo::Coordinate(p2.x(), p2.y()),
                    painter,
                    options,
                    rect
            );
        }

        endCaps.render(
                painter,
                EndCaps::CLOSEDARROW,
                p1.x(), p1.y(),
                _dimDiametric->definitionPoint().x(), _dimDiametric->definitionPoint().y(),
                capSize
        );
        endCaps.render(
                painter,
                EndCaps::CLOSEDARROW,
                p2.x(), p2.y(),
                _dimDiametric->definitionPoint2().x(), _dimDiametric->definitionPoint2().y(),
                capSize
        );
    }
}
コード例 #8
0
ファイル: lcvtext.cpp プロジェクト: Solvoj/LibreCAD_3
/**
* TODO items for text:
* 1) Test multi-line text rendering
* 2) Accept color codes during text rendering in the form of \Cx (x is the index color)
* 3) Font selection
* For testing there is a lua script
*
* We can increase performance if we pre-calculate some values and cache them so that we
* don't have to keep calling text_extends and do some of the calculations
* also we shouldn't draw text smaller then XX pixels when rendered on screen.
*/
void LCVText::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const {
    bool modified = false;
    painter.font_size(height());
    painter.select_font_face("stick3.ttf");

    TextExtends te = painter.text_extends(text_value().c_str());
    double alignX = 0.0;
    double alignY = 0.0;

    //    double alignX, alignY;
    // The idea of height() * .2 is just a average basline offset. Don't this value to seriously,
    // we could get it from font exists but that sounds over exaggerating for the moment.
    switch (valign()) {
        case lc::TextConst::VAMiddle:
            alignX += 0.0;
            alignY += -height() / 2. + (height() * .2);
            break;

        case lc::TextConst::VABottom:
            alignX += 0.0;
            alignY += -height() + (height() * .2);
            break;

        case lc::TextConst::VABaseline:
            alignX += 0.0;
            alignY += 0.0;
            break;

        case lc::TextConst::VATop:
            alignX += 0.0;
            alignY += 0.0 + (height() * .2);
            break;

        default:
            break;
    }

    // Horizontal Align:
    switch (halign()) {
        case lc::TextConst::HALeft:
            alignX += - te.width;
            alignY += 0.;
            break;

        case lc::TextConst::HACenter:
            alignX += - te.width / 2.0;
            alignY += 0.;
            break;

        case lc::TextConst::HAMiddle:
            alignX += - te.width / 2.0;
            alignY += 0.;
            break;

        case lc::TextConst::HARight:
            alignX += 0.;
            alignY += 0.;
            break;

        default:
            break;
    }

    painter.save();
    painter.translate(insertion_point().x(), -insertion_point().y());
    painter.rotate(-angle());
    painter.translate(alignX, -alignY);
    painter.move_to(0., 0.);
    painter.text(text_value().c_str());
    painter.stroke();
    painter.restore();

    if (modified) {
        painter.restore();
    }

}
コード例 #9
0
void DocumentCanvas::transY(int y) {
    for (auto i = _cachedPainters.begin(); i != _cachedPainters.end(); i++) {
        LcPainter* p = i->second;
        p->translate(0, y);
    }
}