Example #1
0
/**
 * Updates the Inserts (letters) of this text. Called when the
 * text or it's data, position, alignment, .. changes.
 * This method also updates the usedTextWidth / usedTextHeight property.
 */
void RS_Text::update() {

    RS_DEBUG->print("RS_Text::update");

    clear();

    if (isUndone()) {
        return;
    }

    usedTextWidth = 0.0;
    usedTextHeight = 0.0;

    RS_Font* font = RS_FONTLIST->requestFont(data.style);

    if (font==NULL) {
        return;
    }

    RS_Vector letterPos = RS_Vector(0.0, -9.0);
    RS_Vector letterSpace = RS_Vector(font->getLetterSpacing(), 0.0);
    RS_Vector space = RS_Vector(font->getWordSpacing(), 0.0);

    // First every text line is created with
    //   alignement: top left
    //   angle: 0
    //   height: 9.0
    // Rotation, scaling and centering is done later

    // For every letter:
    for (int i=0; i<(int)data.text.length(); ++i) {
        // Space:
        if (data.text.at(i).unicode() == 0x20) {
            letterPos+=space;
        } else {
            // One Letter:
            QString letterText = QString(data.text.at(i));
            if (font->findLetter(letterText) == NULL) {
                RS_DEBUG->print("RS_Text::update: missing font for letter( %s ), replaced it with QChar(0xfffd)",qPrintable(letterText));
                letterText = QChar(0xfffd);
            }
            RS_DEBUG->print("RS_Text::update: insert a "
                            "letter at pos: %f/%f", letterPos.x, letterPos.y);

            RS_InsertData d(letterText,
                            letterPos,
                            RS_Vector(1.0, 1.0),
                            0.0,
                            1,1, RS_Vector(0.0,0.0),
                            font->getLetterList(), RS2::NoUpdate);

            RS_Insert* letter = new RS_Insert(this, d);
            RS_Vector letterWidth;
            letter->setPen(RS_Pen(RS2::FlagInvalid));
            letter->setLayer(NULL);
            letter->update();
            letter->forcedCalculateBorders();

            letterWidth = RS_Vector(letter->getMax().x-letterPos.x, 0.0);
            if (letterWidth.x < 0)
                letterWidth.x = -letterSpace.x;

//            oneLine->addEntity(letter);
            addEntity(letter);

            // next letter position:
            letterPos += letterWidth;
            letterPos += letterSpace;
        }
    }

    if( ! RS_EntityContainer::autoUpdateBorders) {
        //only update borders when needed
        forcedCalculateBorders();
    }
    RS_Vector textSize = getSize();

    RS_DEBUG->print("RS_Text::updateAddLine: width 2: %f", textSize.x);

    // Vertical Align:
    double vSize = 9.0;
    //HAAligned, HAFit, HAMiddle require VABaseline
    if (data.halign == RS_TextData::HAAligned
            || data.halign == RS_TextData::HAFit
            || data.halign == RS_TextData::HAMiddle) {
        data.valign = RS_TextData::VABaseline;
    }
    RS_Vector offset(0.0, 0.0);
    switch (data.valign) {
    case RS_TextData::VAMiddle:
        offset.move(RS_Vector(0.0, vSize/2.0));
        break;

    case RS_TextData::VABottom:
        offset.move(RS_Vector(0.0, vSize+3));
        break;

    case RS_TextData::VABaseline:
        offset.move(RS_Vector(0.0, vSize));
        break;

    default:
        break;
    }

    // Horizontal Align:
    switch (data.halign) {
    case RS_TextData::HAMiddle:{
        offset.move(RS_Vector(-textSize.x/2.0, -(vSize + textSize.y/2.0 + getMin().y) ));
        break;}
    case RS_TextData::HACenter:
        RS_DEBUG->print("RS_Text::updateAddLine: move by: %f", -textSize.x/2.0);
        offset.move(RS_Vector(-textSize.x/2.0, 0.0));
        break;
    case RS_TextData::HARight:
        offset.move(RS_Vector(-textSize.x, 0.0));
        break;

    default:
        break;
    }

    if (data.halign!=RS_TextData::HAAligned && data.halign!=RS_TextData::HAFit){
        data.secondPoint = RS_Vector(offset.x, offset.y - vSize);
    }
    RS_EntityContainer::move(offset);


    // Scale:
    if (data.halign==RS_TextData::HAAligned){
        double dist = data.insertionPoint.distanceTo(data.secondPoint)/textSize.x;
        data.height = vSize*dist;
        RS_EntityContainer::scale(RS_Vector(0.0,0.0),
                        RS_Vector(dist, dist));
    } else if (data.halign==RS_TextData::HAFit){
        double dist = data.insertionPoint.distanceTo(data.secondPoint)/textSize.x;
        RS_EntityContainer::scale(RS_Vector(0.0,0.0),
                        RS_Vector(dist, data.height/9.0));
    } else {
        RS_EntityContainer::scale(RS_Vector(0.0,0.0),
                        RS_Vector(data.height*data.widthRel/9.0, data.height/9.0));
        data.secondPoint.scale(RS_Vector(0.0,0.0),
                               RS_Vector(data.height*data.widthRel/9.0, data.height/9.0));
    }

    forcedCalculateBorders();

    // Update actual text size (before rotating, after scaling!):
    usedTextWidth = getSize().x;
    usedTextHeight = data.height;

    // Rotate:
    if (data.halign==RS_TextData::HAAligned || data.halign==RS_TextData::HAFit){
        double angle = data.insertionPoint.angleTo(data.secondPoint);
        data.angle = angle;
    } else {
        data.secondPoint.rotate(RS_Vector(0.0,0.0), data.angle);
        data.secondPoint.move(data.insertionPoint);
    }
    RS_EntityContainer::rotate(RS_Vector(0.0,0.0), data.angle);

    // Move to insertion point:
    RS_EntityContainer::move(data.insertionPoint);

    forcedCalculateBorders();

    RS_DEBUG->print("RS_Text::update: OK");
}
Example #2
0
/**
 * Updates the Inserts (letters) of this text. Called when the
 * text or it's data, position, alignment, .. changes.
 * This method also updates the usedTextWidth / usedTextHeight property.
 */
void RS_MText::update() {

    RS_DEBUG->print("RS_Text::update");

    clear();

    if (isUndone()) {
        return;
    }

    usedTextWidth = 0.0;
    usedTextHeight = 0.0;

    RS_Font* font = RS_FONTLIST->requestFont(data.style);

    if (font==NULL) {
        return;
    }

    RS_Vector letterPos = RS_Vector(0.0, -9.0);
    RS_Vector letterSpace = RS_Vector(font->getLetterSpacing(), 0.0);
    RS_Vector space = RS_Vector(font->getWordSpacing(), 0.0);
    int lineCounter = 0;

    // Every single text line gets stored in this entity container
    //  so we can move the whole line around easely:
    RS_EntityContainer* oneLine = new RS_EntityContainer(this);

    // First every text line is created with
    //   alignement: top left
    //   angle: 0
    //   height: 9.0
    // Rotation, scaling and centering is done later

    // For every letter:
    for (int i=0; i<(int)data.text.length(); ++i) {
        bool handled = false;
        switch (data.text.at(i).unicode()) {
        case 0x0A:
            // line feed:
            updateAddLine(oneLine, lineCounter++);
            oneLine = new RS_EntityContainer(this);
            letterPos = RS_Vector(0.0, -9.0);
            break;

        case 0x20:
            // Space:
            letterPos+=space;
            break;

        case 0x5C: {
                // code (e.g. \S, \P, ..)
                i++;
                int ch = data.text.at(i).unicode();
                switch (ch) {
                case 'P':
                    updateAddLine(oneLine, lineCounter++);
                    oneLine = new RS_EntityContainer(this);
                    letterPos = RS_Vector(0.0, -9.0);
                    handled = true;
                    break;
                    case 'f':
                    case 'F':
                    //font change
                    // \f{symbol} changes font to symbol
                    // \f{} sets font to standard
                {
                    i++;
                    if(data.text.at(i).unicode()!='{') {
                        i--;
                        continue;
                    }
                    int j=data.text.indexOf('}',i);
                    if(j>i){
                        //
                        QString fontName;
                        if(j==i+1)
                            fontName="standard";
                        else
                            fontName=data.text.mid(i+1,j-i-1);
                        RS_Font* fontNew = RS_FONTLIST->requestFont(
                                    fontName
                                    );
                        if(fontNew != NULL) {
                            font=fontNew;
                        }
                        if(font==NULL) font = RS_FONTLIST->requestFont("standard");
                        i=j;
                    }
                }
                        continue;

                case 'S': {
                        QString up;
                        QString dw;
                        //letterPos += letterSpace;

                        // get upper string:
                        i++;
                        while (data.text.at(i).unicode()!='^' &&
                                                       //data.text.at(i).unicode()!='/' &&
                                                       data.text.at(i).unicode()!='\\' &&
                                                       //data.text.at(i).unicode()!='#' &&
                                i<(int)data.text.length()) {
                            up += data.text.at(i);
                            i++;
                        }

                        i++;

                                                if (data.text.at(i-1).unicode()=='^' &&
                                                     data.text.at(i).unicode()==' ') {
                                                        i++;
                                                }

                        // get lower string:
                        while (data.text.at(i).unicode()!=';' &&
                                i<(int)data.text.length()) {
                            dw += data.text.at(i);
                            i++;
                        }

                        // add texts:
                        RS_MText* upper =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos + RS_Vector(0.0,9.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, up, data.style,
                                            0.0, RS2::Update));
                                            upper->setLayer(NULL);
                        upper->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(upper);

                        RS_MText* lower =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos+RS_Vector(0.0,4.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, dw, data.style,
                                            0.0, RS2::Update));
                                            lower->setLayer(NULL);
                        lower->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(lower);

                        // move cursor:
                        upper->calculateBorders();
                        lower->calculateBorders();

                        double w1 = upper->getSize().x;
                        double w2 = lower->getSize().x;

                        if (w1>w2) {
                            letterPos += RS_Vector(w1, 0.0);
                        } else {
                            letterPos += RS_Vector(w2, 0.0);
                        }
                        letterPos += letterSpace;
                    }
                    handled = true;
                    break;

                default:
                    i--;
                    break;
                }
            }
            //if char is not handled continue in default: statement
            if (handled)
                break;

        default: {
                // One Letter:
                QString letterText = QString(data.text.at(i));
                if (font->findLetter(letterText) == NULL) {
                    RS_DEBUG->print("RS_Text::update: missing font for letter( %s ), replaced it with QChar(0xfffd)",qPrintable(letterText));
                    letterText = QChar(0xfffd);
                }
//                if (font->findLetter(QString(data.text.at(i))) != NULL) {

                                        RS_DEBUG->print("RS_Text::update: insert a "
                                          "letter at pos: %f/%f", letterPos.x, letterPos.y);

                    RS_InsertData d(letterText,
                                    letterPos,
                                    RS_Vector(1.0, 1.0),
                                    0.0,
                                    1,1, RS_Vector(0.0,0.0),
                                    font->getLetterList(), RS2::NoUpdate);

                    RS_Insert* letter = new RS_Insert(this, d);
                    RS_Vector letterWidth;
                    letter->setPen(RS_Pen(RS2::FlagInvalid));
                    letter->setLayer(NULL);
                    letter->update();
                    letter->forcedCalculateBorders();

                                        // until 2.0.4.5:
                    //letterWidth = RS_Vector(letter->getSize().x, 0.0);
                                        // from 2.0.4.6:
                    letterWidth = RS_Vector(letter->getMax().x-letterPos.x, 0.0);
                    if (letterWidth.x < 0)
                        letterWidth.x = -letterSpace.x;

                    oneLine->addEntity(letter);

                    // next letter position:
                    letterPos += letterWidth;
                    letterPos += letterSpace;
//                }
            }
            break;
        }
    }

    double tt = updateAddLine(oneLine, lineCounter);
    if (data.valign == RS_MTextData::VABottom) {
        RS_Vector ot = RS_Vector(0.0,-tt).rotate(data.angle);
        RS_EntityContainer::move(ot);
    }

    usedTextHeight -= data.height*data.lineSpacingFactor*5.0/3.0
                      - data.height;
    forcedCalculateBorders();

    RS_DEBUG->print("RS_Text::update: OK");
}