/trunk/Scribus/AUTHORS |
---|
71,6 → 71,20 |
Giovanni Mugnai musical777@gmail.com |
Refactoring text layout code and the new boxes model, Oman House of Open Source |
Technology team: |
Anood Almuharbi anood.almuharbi@gmail.com |
Asma ALbahanta as.bahanta@gmail.com |
Dawood Albadi daawood.albadi@gmail.com |
Ibrahim Alrashdi ibrahimalrashdi745@gmail.com |
Ibtisam Nasser ibtisammabsali@gmail.com |
Khaled Hosny khaledhosny@eglug.org |
Noseeba noseeba1@gmail.com |
Shamsa Hamed shamsahamed59@gmail.com |
Sheikha sheikha443@gmail.com |
Official Documentation: |
Peter Linnell plinnell@scribus.net |
/trunk/Scribus/scribus/canvas.cpp |
---|
2061,6 → 2061,7 |
void Canvas::DrawPageIndicatorSub(ScPainter *p, ScPage *page) |
{ |
p->save(); |
int fm = p->fillMode(); |
p->setAntialiasing(false); |
p->translate(page->xOffset(), page->yOffset()); |
double lineWidth = 1.0 / m_viewMode.scale; |
2072,6 → 2073,7 |
p->setPen(PrefsManager::instance()->appPrefs.displayPrefs.pageBorderColor, 1 / m_viewMode.scale, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
p->drawRect(0, 0, pageWidth, pageHeight); |
p->setAntialiasing(true); |
p->setFillMode(fm); |
p->restore(); |
} |
/trunk/Scribus/scribus/canvasmode.cpp |
---|
1016,141 → 1016,21 |
void CanvasMode::commonDrawTextCursor(QPainter* p, PageItem_TextFrame* textframe, const QPointF& offset) |
{ |
double dx, dy, dy1; |
QLineF cursor; |
QPen cPen ( Qt::black, 0.9 , Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin ); |
// normalize Current Position |
textframe->itemText.normalizeCursorPosition(); |
int textCursorPos ( textframe->itemText.cursorPosition() ); |
cursor = textframe->textLayout.positionToPoint(textCursorPos); |
if ( textframe->lastInFrame() >= textframe->itemText.length() |
|| textframe->itemText.length() == 0 ) |
{ |
dx = textframe->textToFrameDistLeft(); |
dy = textframe->textToFrameDistTop(); |
dy1 = textframe->textToFrameDistTop() + (textframe->itemText.defaultStyle().charStyle().fontSize() / 10.0); |
cPen.setColor(ScColorEngine::getRGBColor(m_doc->PageColors[textframe->itemText.charStyle(textCursorPos).fillColor()], m_doc)); |
cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.defaultStyle().charStyle().fillColor() ], m_doc ) ); |
} |
else if ( textCursorPos > textframe->lastInFrame() ) |
{ |
// Happens often when typing directly into frame. |
// And the cursor curses nothing, vertigo. |
textCursorPos = qMax(0, textframe->lastInFrame()); |
QChar textCursorChar = textframe->itemText.text(textCursorPos); |
if (textCursorChar == SpecialChars::PARSEP || textCursorChar == SpecialChars::LINEBREAK) |
{ |
// The cursor must be moved to the beginning of the next line |
FRect bbox = textframe->textLayout.boundingBox ( textCursorPos ); |
double lineSpacing(textframe->itemText.paragraphStyle(textCursorPos).lineSpacing()); |
// take care if cursor is not in first column |
int curCol(1); |
double ccPos(textframe->textLayout.boundingBox ( textCursorPos ).x()); |
double leftOffset(textframe->textToFrameDistLeft()); |
for(int ci(1); ci <= textframe->columns(); ++ci) |
{ |
double cLeft(((ci-1) * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset); |
double cRight((ci * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset); |
if((cLeft <= ccPos) && (ccPos <= cRight)) |
{ |
curCol = ci; |
break; |
} |
} |
dx = (textframe->columnWidth() * (curCol - 1)) + (textframe->columnGap() * (curCol - 1)) + leftOffset; |
dy = bbox.y(); |
if ( bbox.height() <= 2 ) |
dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0; |
else |
dy1 = bbox.y() + bbox.height(); |
dy += lineSpacing; |
dy1 += lineSpacing; |
} |
else if (textCursorChar == SpecialChars::COLBREAK) |
{ |
// A bit tricky :) |
// We want to position the cursor at the beginning of the next column, if any. |
// At first we need to know in which column the cursor is. |
int curCol(1); |
double ccPos(textframe->textLayout.boundingBox ( textCursorPos ).x()); |
double leftOffset(textframe->textToFrameDistLeft()); |
for(int ci(1); ci <= textframe->columns(); ++ci) |
{ |
double cLeft(((ci-1) * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset); |
double cRight((ci * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset); |
if((cLeft <= ccPos) && (ccPos <= cRight)) |
{ |
curCol = ci; |
break; |
} |
} |
if(textframe->columns() > curCol) |
{ |
dx = (textframe->columnWidth() * curCol) + (textframe->columnGap() * curCol) + leftOffset; |
dy = textframe->textToFrameDistTop(); |
dy1 = textframe->textToFrameDistTop() + textframe->textLayout.boundingBox ( textCursorPos ).height(); |
} |
else // there is no column after the current column |
{ |
FRect bbox = textframe->textLayout.boundingBox ( textCursorPos ); |
dx = bbox.x(); |
dy = bbox.y(); |
dx += textframe->itemText.getGlyphs(textCursorPos)->wide(); |
if ( bbox.height() <= 2 ) |
dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0; |
else |
dy1 = bbox.y() + bbox.height(); |
} |
} |
else |
{ |
FRect bbox = textframe->textLayout.boundingBox ( textCursorPos ); |
dx = bbox.x(); |
dy = bbox.y(); |
dx += textframe->itemText.getGlyphs(textCursorPos)->wide(); |
if ( bbox.height() <= 2 ) |
dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0; |
else |
dy1 = bbox.y() + bbox.height(); |
} |
cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.charStyle ( textCursorPos ).fillColor() ], m_doc ) ); |
} |
else |
{ |
FRect bbox = textframe->textLayout.boundingBox ( textCursorPos ); |
dx = bbox.x(); |
dy = bbox.y(); |
if ( bbox.height() <= 2 ) |
dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0; |
else |
dy1 = bbox.y() + bbox.height(); |
cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.charStyle ( textCursorPos ).fillColor() ], m_doc ) ); |
} |
//handle Right to Left writing |
if (textframe->imageFlippedH()) |
dx = textframe->width() - dx; |
if (textframe->imageFlippedV()) |
{ |
dy = textframe->height() - dy; |
dy1 = textframe->height() - dy1; |
} |
p->save(); |
p->setTransform(textframe->getTransform(), true); |
p->setPen ( cPen ); |
p->setRenderHint ( QPainter::Antialiasing, true ); |
// avoid displaying the cursor on the frameborder |
dx = qMax ( ( cPen.widthF() / 2.0 ), dx ); |
dy = qMin ( qMax ( dy,0.0 ) , textframe->height() ); |
dy1 = qMin ( qMax ( dy1,0.0 ), textframe->height() ); |
p->drawLine ( QLineF ( dx,dy,dx,dy1 ).translated(offset) ); |
p->drawLine(cursor.translated(offset)); |
p->restore(); |
} |
/trunk/Scribus/scribus/pageitem.cpp |
---|
2549,7 → 2549,7 |
/** |
layout glyphs translates the chars into a number of glyphs, applying the Charstyle |
'style'. The following fields are set in layout: glyph, more, scaleH, scaleV, xoffset, yoffset, xadvance. |
'style'. The following fields are set in layout: glyph, scaleH, scaleV, xoffset, yoffset, xadvance. |
If the DropCap-bit in style.effects is set and yadvance is > 0, scaleH/V, x/yoffset and xadvance |
are modified to scale the glyphs to this height. |
Otherwise yadvance is set to the max ascender of all generated glyphs. |
2557,9 → 2557,9 |
sets xadvance to the advance width without kerning. If more than one glyph |
is generated, kerning is included in all but the last xadvance. |
*/ |
double PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags, GlyphLayout& layout) |
GlyphLayout PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags) |
{ |
double retval = 0.0; |
GlyphLayout gl; |
const ScFace font = style.font(); |
double asce = font.ascent(style.fontSize() / 10.0); |
int chst = style.effects() & ScStyle_UserStyles; |
2578,36 → 2578,34 |
} |
else */ |
{ |
layout.glyph = font.char2CMap(chars[0].unicode()); |
gl.glyph = font.char2CMap(chars[0].unicode()); |
} |
double tracking = 0.0; |
if ( (flags & ScLayout_StartOfLine) == 0) |
tracking = style.fontSize() * style.tracking() / 10000.0; |
layout.xoffset = tracking; |
layout.yoffset = 0; |
gl.xoffset = tracking; |
gl.yoffset = 0; |
if (chst != ScStyle_Default) |
{ |
if (chst & ScStyle_Superscript) |
{ |
retval -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0; |
layout.yoffset -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0; |
layout.scaleV = layout.scaleH = qMax(m_Doc->typographicPrefs().scalingSuperScript / 100.0, 10.0 / style.fontSize()); |
gl.yoffset -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0; |
gl.scaleV = gl.scaleH = qMax(m_Doc->typographicPrefs().scalingSuperScript / 100.0, 10.0 / style.fontSize()); |
} |
else if (chst & ScStyle_Subscript) |
{ |
retval += asce * m_Doc->typographicPrefs().valueSubScript / 100.0; |
layout.yoffset += asce * m_Doc->typographicPrefs().valueSubScript / 100.0; |
layout.scaleV = layout.scaleH = qMax(m_Doc->typographicPrefs().scalingSubScript / 100.0, 10.0 / style.fontSize()); |
gl.yoffset += asce * m_Doc->typographicPrefs().valueSubScript / 100.0; |
gl.scaleV = gl.scaleH = qMax(m_Doc->typographicPrefs().scalingSubScript / 100.0, 10.0 / style.fontSize()); |
} |
else { |
layout.scaleV = layout.scaleH = 1.0; |
gl.scaleV = gl.scaleH = 1.0; |
} |
layout.scaleH *= style.scaleH() / 1000.0; |
layout.scaleV *= style.scaleV() / 1000.0; |
gl.scaleH *= style.scaleH() / 1000.0; |
gl.scaleV *= style.scaleV() / 1000.0; |
if (chst & ScStyle_AllCaps) |
{ |
layout.glyph = font.char2CMap(chars[0].toUpper().unicode()); |
gl.glyph = font.char2CMap(chars[0].toUpper().unicode()); |
} |
if (chst & ScStyle_SmallCaps) |
{ |
2615,15 → 2613,15 |
QChar uc = chars[0].toUpper(); |
if (uc != chars[0]) |
{ |
layout.glyph = font.char2CMap(chars[0].toUpper().unicode()); |
layout.scaleV *= smallcapsScale; |
layout.scaleH *= smallcapsScale; |
gl.glyph = font.char2CMap(chars[0].toUpper().unicode()); |
gl.scaleV *= smallcapsScale; |
gl.scaleH *= smallcapsScale; |
} |
} |
} |
else { |
layout.scaleH = style.scaleH() / 1000.0; |
layout.scaleV = style.scaleV() / 1000.0; |
gl.scaleH = style.scaleH() / 1000.0; |
gl.scaleV = style.scaleV() / 1000.0; |
} |
/* if (layout.glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode())) { |
2642,313 → 2640,15 |
} |
else */ |
{ |
layout.xadvance = font.glyphWidth(layout.glyph, style.fontSize() / 10) * layout.scaleH; |
layout.yadvance = font.glyphBBox(layout.glyph, style.fontSize() / 10).ascent * layout.scaleV; |
gl.xadvance = font.glyphWidth(gl.glyph, style.fontSize() / 10); |
gl.yadvance = font.glyphBBox(gl.glyph, style.fontSize() / 10).ascent; |
} |
if (layout.xadvance > 0) |
layout.xadvance += tracking; |
if (gl.xadvance > 0) |
gl.xadvance += tracking; |
if (chars.length() > 1) { |
layout.grow(); |
layoutGlyphs(style, chars.mid(1), ScLayout_None, *layout.more); |
layout.xadvance += font.glyphKerning(layout.glyph, layout.more->glyph, style.fontSize() / 10) * layout.scaleH; |
if (layout.more->yadvance > layout.yadvance) |
layout.yadvance = layout.more->yadvance; |
} |
else { |
layout.shrink(); |
} |
return retval; |
return gl; |
} |
void PageItem::drawGlyphs(ScPainter *p, const CharStyle& style, LayoutFlags flags, GlyphLayout& glyphs) |
{ |
uint glyph = glyphs.glyph; |
const ScFace font = style.font(); |
if ((m_Doc->guidesPrefs().showControls) && |
(glyph == font.char2CMap(QChar(' ')) || glyph >= ScFace::CONTROL_GLYPHS)) |
{ |
bool stroke = false; |
if (glyph >= ScFace::CONTROL_GLYPHS) |
glyph -= ScFace::CONTROL_GLYPHS; |
else |
glyph = 32; |
QTransform chma, chma4, chma5; |
FPointArray points; |
if (glyph == SpecialChars::TAB.unicode()) |
{ |
points = m_Doc->symTab.copy(); |
chma4.translate(glyphs.xoffset + glyphs.xadvance - ((style.fontSize() / 10.0) * glyphs.scaleH * 0.7), glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV * 0.5)); |
} |
else if (glyph == SpecialChars::COLBREAK.unicode()) |
{ |
points = m_Doc->symNewCol.copy(); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.6)); |
} |
else if (glyph == SpecialChars::FRAMEBREAK.unicode()) |
{ |
points = m_Doc->symNewFrame.copy(); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.6)); |
} |
else if (glyph == SpecialChars::PARSEP.unicode()) |
{ |
points = m_Doc->symReturn.copy(); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.8)); |
} |
else if (glyph == SpecialChars::LINEBREAK.unicode()) |
{ |
points = m_Doc->symNewLine.copy(); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.4)); |
} |
else if (glyph == SpecialChars::NBSPACE.unicode() || |
glyph == 32) |
{ |
stroke = (glyph == 32); |
points = m_Doc->symNonBreak.copy(); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.4)); |
} |
else if (glyph == SpecialChars::NBHYPHEN.unicode()) |
{ |
points = font.glyphOutline(font.char2CMap(QChar('-')), style.fontSize() / 100); |
chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV)); |
} |
else if (glyph == SpecialChars::SHYPHEN.unicode()) |
{ |
points.resize(0); |
points.addQuadPoint(0, -10, 0, -10, 0, -6, 0, -6); |
stroke = true; |
} |
else if (glyph == SpecialChars::OBJECT.unicode()) |
{ |
//for showing marks entries as control chars |
points.resize(0); |
points.addQuadPoint(0, -8, 1, -8, 0, -6, 1, -6); |
stroke = true; |
} |
else // ??? |
{ |
points.resize(0); |
points.addQuadPoint(0, -10, 0, -10, 0, -9, 0, -9); |
points.addQuadPoint(0, -9, 0, -9, 1, -9, 1, -9); |
points.addQuadPoint(1, -9, 1, -9, 1, -10, 1, -10); |
points.addQuadPoint(1, -10, 1, -10, 0, -10, 0, -10); |
} |
chma.scale(glyphs.scaleH * style.fontSize() / 100.0, glyphs.scaleV * style.fontSize() / 100.0); |
points.map(chma * chma4); |
p->setupPolygon(&points, true); |
QColor oldBrush = p->brush(); |
p->setBrush( (flags & ScLayout_SuppressSpace) ? Qt::green |
: PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor); |
if (stroke) |
{ |
QColor tmp = p->pen(); |
p->setPen(p->brush(), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
p->setLineWidth(style.fontSize() * glyphs.scaleV / 200.0); |
p->strokePath(); |
p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
else |
{ |
p->setFillMode(1); |
p->fillPath(); |
} |
p->setBrush(oldBrush); |
if (glyphs.more) |
{ |
p->translate(glyphs.xadvance, 0); |
drawGlyphs(p, style, ScLayout_None, *glyphs.more); |
} |
return; |
} |
else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) || |
glyph == (ScFace::CONTROL_GLYPHS + 32)) |
glyph = font.char2CMap(QChar(' ')); |
else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) |
glyph = font.char2CMap(QChar('-')); |
if (glyph >= ScFace::CONTROL_GLYPHS || (style.effects() & ScLayout_SuppressSpace)) { |
// qDebug("drawGlyphs: skipping %d", glyph); |
// all those are empty |
if (glyphs.more) |
{ |
p->translate(glyphs.xadvance, 0); |
drawGlyphs(p, style, ScLayout_None, *glyphs.more); |
} |
return; |
} |
// if (font.canRender(QChar(glyph))) |
{ |
FPointArray gly = font.glyphOutline(glyph); |
// Do underlining first so you can get typographically correct |
// underlines when drawing a white outline |
if (((style.effects() & ScStyle_Underline) || ((style.effects() & ScStyle_UnderlineWords) && glyph != font.char2CMap(QChar(' ')))) && (style.strokeColor() != CommonStrings::None)) |
{ |
double st, lw; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
st = (style.underlineOffset() / 1000.0) * (font.descent(style.fontSize() / 10.0)); |
else |
st = font.underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
lw = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = font.underlinePos(style.fontSize() / 10.0); |
lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0); |
QColor tmpC = p->pen(); |
int oldStrokeMode = p->strokeMode(); |
p->setPen(p->brush()); |
p->setLineWidth(lw); |
p->setStrokeMode(1); |
if (style.effects() & ScStyle_Subscript) |
p->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st)); |
else |
p->drawLine(FPoint(glyphs.xoffset, -st), FPoint(glyphs.xoffset + glyphs.xadvance, -st)); |
p->setStrokeMode(oldStrokeMode); |
p->setPen(tmpC); |
} |
if (gly.size() > 3) |
{ |
if (glyph == 0) |
{ |
// qDebug() << QString("glyph 0: (%1,%2) * %3 %4 + %5").arg(glyphs.xoffset).arg(glyphs.yoffset).arg(glyphs.scaleH).arg(glyphs.scaleV).arg(glyphs.xadvance)); |
} |
p->save(); |
p->translate(glyphs.xoffset, glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV)); |
if (m_isReversed) |
{ |
p->scale(-1, 1); |
p->translate(-glyphs.xadvance, 0); |
} |
if (style.baselineOffset() != 0) |
p->translate(0, -(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0)); |
double glxSc = glyphs.scaleH * style.fontSize() / 100.00; |
double glySc = glyphs.scaleV * style.fontSize() / 100.0; |
p->scale(glxSc, glySc); |
// p->setFillMode(1); |
bool fr = p->fillRule(); |
p->setFillRule(false); |
// double a = gly.point(0).x(); |
// double b = gly.point(0).y(); |
// double c = gly.point(3).x(); |
// double d = gly.point(3).y(); |
// qDebug() << QString("drawglyphs: %1 (%2,%3) (%4,%5) scaled %6,%7 trans %8,%9") |
// .arg(gly.size()).arg(a).arg(b).arg(c).arg(d) |
// .arg(p->worldMatrix().m11()).arg(p->worldMatrix().m22()).arg(p->worldMatrix().dx()).arg(p->worldMatrix().dy()); |
p->setupPolygon(&gly, true); |
if (m_Doc->layerOutline(LayerID)) |
{ |
p->save(); |
p->setPen(m_Doc->layerMarker(LayerID), 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
p->setFillMode(ScPainter::None); |
p->setBrushOpacity(1.0); |
p->setPenOpacity(1.0); |
p->strokePath(); |
p->restore(); |
p->setFillRule(fr); |
p->restore(); |
if (glyphs.more) |
{ |
p->translate(glyphs.xadvance, 0); |
drawGlyphs(p, style, ScLayout_None, *glyphs.more); |
} |
return; |
} |
if (glyph == 0) |
{ |
p->setPen(PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
p->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() * 2 / 10000.0); |
p->strokePath(); |
} |
else if ((font.isStroked()) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0)) |
{ |
QColor tmp = p->brush(); |
p->setStrokeMode(1); |
p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
p->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0); |
p->strokePath(); |
} |
else |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
p->save(); |
p->translate((style.fontSize() * glyphs.scaleH * style.shadowXOffset() / 10000.0) / glxSc, -(style.fontSize() * glyphs.scaleV * style.shadowYOffset() / 10000.0) / glySc); |
QColor tmp = p->brush(); |
p->setBrush(p->pen()); |
p->setupPolygon(&gly, true); |
p->fillPath(); |
p->setBrush(tmp); |
p->restore(); |
p->setupPolygon(&gly, true); |
} |
if (style.fillColor() != CommonStrings::None) |
p->fillPath(); |
if ((style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0)) |
{ |
p->setStrokeMode(1); |
p->setLineWidth((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) / glySc); |
p->strokePath(); |
} |
} |
p->setFillRule(fr); |
p->restore(); |
} |
else { |
// qDebug() << "drawGlyphs: empty glyph" << glyph; |
} |
if ((style.effects() & ScStyle_Strikethrough) && (style.strokeColor() != CommonStrings::None)) |
{ |
double st, lw; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
st = (style.strikethruOffset() / 1000.0) * (font.ascent(style.fontSize() / 10.0)); |
else |
st = font.strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
lw = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = font.strikeoutPos(style.fontSize() / 10.0); |
lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0); |
int oldStrokeMode = p->strokeMode(); |
p->setPen(p->brush()); |
p->setLineWidth(lw); |
p->setStrokeMode(1); |
p->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st)); |
p->setStrokeMode(oldStrokeMode); |
} |
} |
/* else |
{ |
p->setLineWidth(1); |
p->setPen(red); |
p->setBrush(red); |
p->setFillMode(1); |
p->drawRect(glyphs.xoffset, glyphs.yoffset - (style.fontSize() / 10.0) * glyphs.scaleV , (style.fontSize() / 10.0) * glyphs.scaleH, (style.fontSize() / 10.0) * glyphs.scaleV); |
} |
*/ |
if (glyphs.more) |
{ |
p->translate(glyphs.xadvance, 0); |
drawGlyphs(p, style, ScLayout_None, *glyphs.more); |
} |
} |
void PageItem::DrawPolyL(QPainter *p, QPolygon pts) |
{ |
if (Segments.count() != 0) |
/trunk/Scribus/scribus/pageitem.h |
---|
415,9 → 415,8 |
/// Return current text properties (current char + paragraph properties) |
void currentTextProps(ParagraphStyle& parStyle) const; |
// deprecated: |
double layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags, GlyphLayout& layout); |
GlyphLayout layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags); |
void SetQColor(QColor *tmp, QString farbe, double shad); |
void drawGlyphs(ScPainter *p, const CharStyle& style, LayoutFlags flags, GlyphLayout& glyphs ); |
void DrawPolyL(QPainter *p, QPolygon pts); |
QString ExpandToken(uint base); |
const FPointArray shape() const { return PoLine; } |
/trunk/Scribus/scribus/pageitem_pathtext.cpp |
---|
46,6 → 46,9 |
#include "undostate.h" |
#include "util.h" |
#include "util_math.h" |
#include "text/boxes.h" |
#include "text/textlayoutpainter.h" |
#include "text/screenpainter.h" |
using namespace std; |
79,18 → 82,8 |
double dx; |
FPoint point = FPoint(0, 0); |
FPoint tangent = FPoint(0, 0); |
QColor tmp; |
CurX = m_textDistanceMargins.left(); |
QString cachedStroke = ""; |
QString cachedFill = ""; |
double cachedFillShade = -1; |
double cachedStrokeShade = -1; |
QString actStroke = ""; |
QString actFill = ""; |
double actFillShade = -1; |
double actStrokeShade = -1; |
QColor cachedFillQ; |
QColor cachedStrokeQ; |
if (!m_Doc->layerOutline(LayerID)) |
{ |
if (PoShow) |
202,7 → 195,6 |
double wordExtra = 0; |
for (a = firstChar; a < itemRenderText.length(); ++a) |
{ |
GlyphLayout* glyphs = itemRenderText.getGlyphs(a); |
chstr = itemRenderText.text(a, 1); |
if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT |
|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK) |
211,13 → 203,11 |
spaceCount++; |
if (a < itemRenderText.length()-1) |
chstr += itemRenderText.text(a+1, 1); |
glyphs->yadvance = 0; |
layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs); |
glyphs->shrink(); |
GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a)); |
if (itemRenderText.hasObject(a)) |
totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH; |
totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH; |
else |
totalTextLen += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0; |
totalTextLen += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0; |
} |
for (int segs = 0; segs < PoLine.size()-3; segs += 4) |
{ |
252,10 → 242,10 |
QList<QPainterPath> pathList = decomposePath(guidePath); |
QPainterPath currPath = pathList[0]; |
int currPathIndex = 0; |
PathLineBox* linebox = new PathLineBox(); |
for (a = firstChar; a < itemRenderText.length(); ++a) |
{ |
CurY = 0; |
GlyphLayout* glyphs = itemRenderText.getGlyphs(a); |
PathData* pdata = & (textLayout.point(a)); |
chstr = itemRenderText.text(a,1); |
if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT |
263,15 → 253,16 |
continue; |
if (a < itemRenderText.length()-1) |
chstr += itemRenderText.text(a+1, 1); |
glyphs->yadvance = 0; |
layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs); |
glyphs->shrink(); // HACK |
GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a)); |
GlyphRun run(&itemRenderText.charStyle(a), itemRenderText.flags(a), a, a, itemRenderText.object(a)); |
run.glyphs().append(glyphs); |
if (itemRenderText.hasObject(a)) |
dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH / 2.0; |
dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH / 2.0; |
else |
dx = glyphs->wide() / 2.0; |
dx = glyphs.xadvance / 2.0; |
CurX += dx; |
double currPerc = currPath.percentAtLength(CurX); |
if (currPerc >= 0.9999999) |
{ |
293,7 → 284,7 |
QPointF currPoint = currPath.pointAtPercent(currPerc); |
tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0)); |
point = FPoint(currPoint.x(), currPoint.y()); |
glyphs->xoffset = 0; |
glyphs.xoffset = 0; |
pdata->PtransX = point.x(); |
pdata->PtransY = point.y(); |
pdata->PRot = currAngle * M_PI / 180.0; |
315,63 → 306,56 |
else |
trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() ); |
} |
QTransform sca = p->worldMatrix(); |
trafo *= sca; |
p->save(); |
QTransform savWM = p->worldMatrix(); |
p->setWorldMatrix(trafo); |
if (!m_Doc->RePos) |
const CharStyle& cStyle(run.style()); |
double scaleV = cStyle.scaleV() / 1000.0; |
double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0); |
double ascent = cStyle.font().ascent(cStyle.fontSize()/10.00) * scaleV + offset; |
double descent = cStyle.font().descent(cStyle.fontSize()/10.00) * scaleV - offset; |
linebox->setAscent(ascent); |
linebox->setDescent(descent); |
Box* box; |
if (itemRenderText.hasObject(a)) |
{ |
actFill = itemRenderText.charStyle(a).fillColor(); |
actFillShade = itemRenderText.charStyle(a).fillShade(); |
if (actFill != CommonStrings::None) |
{ |
p->setFillMode(ScPainter::Solid); |
if ((cachedFillShade != actFillShade) || (cachedFill != actFill)) |
{ |
SetQColor(&tmp, actFill, actFillShade); |
p->setBrush(tmp); |
cachedFillQ = tmp; |
cachedFill = actFill; |
cachedFillShade = actFillShade; |
} |
else |
p->setBrush(cachedFillQ); |
} |
else |
p->setFillMode(ScPainter::None); |
actStroke = itemRenderText.charStyle(a).strokeColor(); |
actStrokeShade = itemRenderText.charStyle(a).strokeShade(); |
if (actStroke != CommonStrings::None) |
{ |
if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke)) |
{ |
SetQColor(&tmp, actStroke, actStrokeShade); |
p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
cachedStrokeQ = tmp; |
cachedStroke = actStroke; |
cachedStrokeShade = actStrokeShade; |
} |
else |
p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
p->translate(0.0, BaseOffs); |
if (itemRenderText.hasObject(a)) |
DrawObj_Embedded(p, cullingArea, itemRenderText.charStyle(a), itemRenderText.object(a)); |
else |
drawGlyphs(p, itemRenderText.charStyle(a), itemRenderText.flags(a), *glyphs); |
box = new ObjectBox(run); |
box->setAscent(run.object()->height() - run.object()->lineWidth()); |
box->setDescent(0); |
} |
p->setWorldMatrix(savWM); |
p->restore(); |
else |
{ |
box = new GlyphBox(run); |
box->setAscent(linebox->ascent()); |
box->setDescent(linebox->descent()); |
} |
box->setMatrix(trafo); |
linebox->addBox(box); |
MaxChars = a+1; |
CurX -= dx; |
if (itemRenderText.hasObject(a)) |
CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH + extraOffset; |
CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH + extraOffset; |
else if (chstr[0] == SpecialChars::BLANK) |
CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset; |
CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset; |
else |
CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset; |
CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset; |
} |
textLayout.addColumn(0, 0); |
textLayout.appendLine(linebox); |
if (!m_Doc->RePos) |
{ |
int fm = p->fillMode(); |
p->setFillMode(1); |
p->save(); |
ScreenPainter painter(p, this); |
textLayout.render(&painter); |
p->setFillMode(fm); |
p->restore(); |
} |
} |
bool PageItem_PathText::createInfoGroup(QFrame *infoGroup, QGridLayout *infoGroupLayout) |
/trunk/Scribus/scribus/pageitem_textframe.cpp |
---|
55,6 → 55,8 |
#include "scribusview.h" |
#include "scribusstructs.h" |
#include "selection.h" |
#include "text/boxes.h" |
#include "text/screenpainter.h" |
#include "ui/guidemanager.h" |
#include "ui/marksmanager.h" |
#include "undomanager.h" |
346,7 → 348,7 |
stream << "scaleV" << "\t"; |
stream << "\n"; |
for (int zc = line.firstItem; zc < line.lastItem; ++zc) |
for (int zc = line.firstChar; zc < line.lastChar; ++zc) |
{ |
const ScText* item = itemText.item(zc); |
388,46 → 390,6 |
} |
*/ |
/** |
Clones the tab fill char as often as necssary after all distances are known |
*/ |
static void fillInTabLeaders(StoryText & itemText, LineSpec & curLine) |
{ |
// fill in tab leaders |
double xPos = curLine.x; |
for (int ti= curLine.firstItem; ti <= curLine.lastItem; ++ti) |
{ |
GlyphLayout* glyphs = itemText.getGlyphs(ti); |
if (itemText.text(ti) == SpecialChars::TAB) |
{ |
GlyphLayout * tglyph = glyphs->more; |
if (!tglyph) |
continue; |
const CharStyle & charStyle(itemText.charStyle(ti)); |
double wt = charStyle.font().glyphWidth(tglyph->glyph, charStyle.fontSize() * tglyph->scaleV / 10.0); |
double len = glyphs->xadvance; |
int count = static_cast<int>(len / wt); |
double sPos = -len; |
tglyph->xoffset = sPos; |
// qDebug() << QString("tab leaders: %1 %2 width=%3 count=%4").arg(sPos).arg(curLine.y).arg(wt).arg(count); |
for (int cx = 1; cx < count; ++cx) |
{ |
// clone fillchar |
tglyph->grow(); |
*(tglyph->more) = *tglyph; |
tglyph->more->more = NULL; |
tglyph = tglyph->more; |
tglyph->xoffset = sPos + wt * cx; |
} |
} |
xPos += glyphs->wide(); |
} |
} |
enum TabStatus { |
TabNONE = 0, |
TabLEFT = TabNONE, |
442,19 → 404,36 |
fields which describe what type of tab is currently active |
*/ |
struct TabControl { |
bool active; |
int status; |
int charIndex; |
double xPos; |
QChar fillChar; |
bool active; |
int status; |
double xPos; |
QChar fillChar; |
GlyphLayout* tabGlyph; |
}; |
struct LineSpec |
{ |
qreal x; |
qreal y; |
qreal width; |
qreal ascent; |
qreal descent; |
qreal colLeft; |
int firstRun; |
int lastRun; |
qreal naturalWidth; |
bool isFirstLine; |
qreal height; |
}; |
/** |
fields which describe how the current line is placed into the frame |
*/ |
*/ |
struct LineControl { |
LineSpec line; |
int itemsInLine; |
QList<GlyphRun>& glyphRuns; |
bool isEmpty; |
int hyphenCount; |
double colWidth; |
double colGap; |
472,8 → 451,8 |
double leftIndent; |
double rightMargin; |
double mustLineEnd; |
int restartIndex; //index of char where line computing should be restarted |
int restartRowIndex; //index of char where row of text is started |
int restartIndex; //index of glyph run where line computing should be restarted |
int restartRowIndex; //index of glyph run where row of text is started |
double restartX; //starting X position of line if must be restarted |
double rowDesc; |
487,38 → 466,36 |
double maxShrink; |
double maxStretch; |
ScribusDoc *doc; |
/// remember frame dimensions and offsets |
void init(double w, double h, const MarginStruct& extra, double lCorr) |
LineControl(double w, double h, const MarginStruct& extra, double lCorr, ScribusDoc* d, QList<GlyphRun>& runs, double colwidth, double colgap) |
: glyphRuns(runs) |
, hasDropCap(false) |
, doc(d) |
{ |
insets = extra; |
lineCorr = lCorr; |
frameWidth = w; |
frameHeight = h; |
hasDropCap = false; |
} |
/// start at column 0 |
void initColumns(double width, double gap) |
{ |
column = 0; |
colWidth = width; |
colGap = gap; |
colWidth = colwidth; |
colGap = colgap; |
hyphenCount = 0; |
} |
/// move position to next column |
void nextColumn(double asce = 0.0) |
void nextColumn(TextLayout &textLayout) |
{ |
startOfCol = true; |
colLeft = (colWidth + colGap) * column + insets.left() + lineCorr; |
textLayout.addColumn(colLeft, colWidth); |
//now colRight is REAL column right edge |
colRight = colLeft + colWidth; |
if (legacy) |
colRight += lineCorr; |
xPos = colLeft; |
yPos = asce + insets.top() + lineCorr; |
line.colLeft = colLeft; |
yPos = insets.top() + lineCorr; |
} |
bool isEndOfCol(double morespace = 0) |
529,19 → 506,18 |
/** |
init fields for a new line at current position |
*/ |
void startLine(int first) |
void startLine(int firstRun) |
{ |
itemsInLine = 0; |
isEmpty = true; |
line.x = xPos; |
line.y = yPos; |
line.firstItem = first; |
line.lastItem = 0; |
line.firstRun = firstRun; |
line.lastRun = 0; |
line.ascent = 0.0; |
line.descent = 0.0; |
line.width = 0.0; |
line.naturalWidth = 0.0; |
line.colLeft = colLeft; |
line.isFirstLine = false; |
breakIndex = -1; |
breakXPos = 0.0; |
maxShrink = 0.0; |
586,18 → 562,17 |
breakXPos = pos; |
breakIndex = index; |
} |
/// called when a mandatory break is found |
void breakLine(const StoryText& itemText, const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy, int last) |
void breakLine(const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy, int last) |
{ |
breakIndex = last; |
breakXPos = line.x; |
for (int j = line.firstItem; j <= last; ++j) |
if ( !itemText.hasFlag(j, ScLayout_SuppressSpace) ) |
breakXPos += itemText.getGlyphs(j)->wide(); |
for (int i = line.firstRun; i <= breakIndex; i++) |
breakXPos += glyphRuns.at(i).width(); |
// #8194, #8717 : update line ascent and descent with sensible values |
// so that endOfLine() returns correct result |
updateHeightMetrics(itemText); |
updateHeightMetrics(); |
// #9060 : update line offset too |
// updateLineOffset(itemText, style, offsetPolicy); |
} |
605,7 → 580,7 |
/// use the last remembered break to set line width and itemrange |
void finishLine(double endX) |
{ |
line.lastItem = breakIndex; |
line.lastRun = breakIndex; |
line.naturalWidth = breakXPos - line.x; |
line.width = endX - line.x; |
maxShrink = maxStretch = 0; |
620,7 → 595,7 |
startLine(restartRowIndex); |
addLeftIndent = true; |
afterOverflow = false; |
return restartRowIndex -1; |
return restartRowIndex - 1; |
} |
int restartLine(bool recalcY, bool add) |
630,7 → 605,7 |
xPos = restartX; |
startLine(restartIndex); |
afterOverflow = false; |
return restartIndex -1; |
return restartIndex - 1; |
} |
bool isEndOfLine(double moreSpace = 0) |
732,147 → 707,29 |
return qMin(EndX2, maxX); |
} |
double getLineAscent(const StoryText& itemText) |
void updateHeightMetrics() |
{ |
double result = 0; |
QChar firstChar = itemText.text (line.firstItem); |
if ((firstChar == SpecialChars::PAGENUMBER) || (firstChar == SpecialChars::PAGECOUNT)) |
firstChar = '8'; |
PageItem *obj = itemText.object (line.firstItem); |
const CharStyle& fcStyle(itemText.charStyle(line.firstItem)); |
if ((firstChar == SpecialChars::PARSEP) || (firstChar == SpecialChars::LINEBREAK)) |
result = fcStyle.font().ascent(fcStyle.fontSize() / 10.0); |
else if (obj) |
result = qMax(result, (obj->height() + obj->lineWidth()) * (fcStyle.scaleV() / 1000.0)); |
else |
result = fcStyle.font().realCharAscent(firstChar, fcStyle.fontSize() / 10.0); |
for (int zc = 0; zc < itemsInLine; ++zc) |
{ |
QChar ch = itemText.text(line.firstItem + zc); |
if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT)) |
ch = '8'; // should have highest ascender even in oldstyle |
const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc)); |
if ((ch == SpecialChars::TAB) || (ch == QChar(10)) |
|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace())) |
continue; |
double asce; |
PageItem *obj = itemText.object (line.firstItem + zc); |
if (obj) |
asce = obj->height() + obj->lineWidth() * (cStyle.scaleV() / 1000.0); |
else |
asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0); |
// qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result); |
result = qMax(result, asce); |
} |
return result; |
line.ascent = line.descent = 0; |
// Can happen when inserting a new line at end of text, WTF! |
if (line.firstRun >= glyphRuns.length()) |
return; |
const CharStyle& cStyle(glyphRuns.at(line.firstRun).style()); |
double scaleV = cStyle.scaleV() / 1000.0; |
double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0); |
line.ascent = cStyle.font().ascent(cStyle.fontSize()/10.00) * scaleV + offset; |
line.descent = cStyle.font().descent(cStyle.fontSize()/10.00) * scaleV - offset; |
} |
double getLineDescent(const StoryText& itemText) |
{ |
double result = 0; |
QChar firstChar = itemText.text(line.firstItem); |
if ((firstChar == SpecialChars::PAGENUMBER) || (firstChar == SpecialChars::PAGECOUNT)) |
firstChar = '8'; |
const CharStyle& fcStyle(itemText.charStyle(line.firstItem)); |
if ((firstChar == SpecialChars::PARSEP) || (firstChar == SpecialChars::LINEBREAK)) |
result = fcStyle.font().descent(fcStyle.fontSize() / 10.0); |
else if (itemText.object(line.firstItem)) |
result = 0.0; |
else |
result = fcStyle.font().realCharDescent(firstChar, fcStyle.fontSize() / 10.0); |
for (int zc = 0; zc < itemsInLine; ++zc) |
{ |
QChar ch = itemText.text(line.firstItem + zc); |
if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT)) |
ch = '8'; // should have highest ascender even in oldstyle |
const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc)); |
if ((ch == SpecialChars::TAB) || (ch == QChar(10)) |
|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace())) |
continue; |
double desc; |
if (itemText.object(line.firstItem + zc)) |
desc = 0.0; |
else |
desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0); |
// qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result); |
result = qMax(result, desc); |
} |
return result; |
} |
double getLineHeight(const StoryText& itemText) |
{ |
double result = 0; |
const CharStyle& firstStyle(itemText.charStyle(line.firstItem)); |
PageItem *obj = itemText.object (line.firstItem); |
if (obj) |
result = qMax(result, (obj->height() + obj->lineWidth()) * (firstStyle.scaleV() / 1000.0)); |
else |
result = firstStyle.font().height(firstStyle.fontSize() / 10.0); |
for (int zc = 0; zc < itemsInLine; ++zc) |
{ |
QChar ch = itemText.text(line.firstItem+zc); |
if ((ch == SpecialChars::TAB) || (ch == QChar(10)) |
|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace())) |
continue; |
const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc)); |
PageItem *obj = itemText.object (line.firstItem + zc); |
double asce; |
if (obj) |
asce = (obj->height() + obj->lineWidth()) * (cStyle.scaleV() / 1000.0); |
else |
asce = cStyle.font().height (cStyle.fontSize() / 10.0); |
// qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result); |
result = qMax(result, asce); |
} |
return result; |
} |
void updateHeightMetrics(const StoryText& itemText) |
{ |
double asce, desc, hei; |
line.ascent = 0; |
line.descent = 0; |
line.height = 0; |
for (int zc = 0; zc < itemsInLine; ++zc) |
{ |
QChar ch = itemText.text(line.firstItem+zc); |
if ((ch == SpecialChars::TAB) || (ch == QChar(10)) |
|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace())) |
continue; |
const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc)); |
double scaleV = cStyle.scaleV() / 1000.0; |
double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0); |
if (itemText.object(line.firstItem+zc) != 0) |
{ |
asce = (itemText.object(line.firstItem+zc)->height() + itemText.object(line.firstItem+zc)->lineWidth()) * scaleV + offset; |
desc = 0.0; |
hei = asce; |
} |
else //if ((itemText.flags(current.line.firstItem+zc) & ScLayout_DropCap) == 0) |
{ |
asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0) * scaleV + offset; |
desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0) * scaleV - offset; |
hei = cStyle.font().height(cStyle.fontSize() / 10.0) * scaleV; |
} |
// qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result); |
line.ascent = qMax(line.ascent, asce); |
line.descent = qMax(line.descent, desc); |
line.height = qMax(line.height, hei); |
} |
} |
// yPos should not be changed when all line is already calculated - at new y position there can be overflow!!! |
// edit: can't happen as it should only move upwards, and this is covered by the calculations done. |
//void updateLineOffset(const StoryText& itemText, const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy) |
//{ |
// if (itemsInLine <= 0) |
// if (charsInLine <= 0) |
// return; |
// if ((!hasDropCap) && (startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing)) |
// { |
// //FIXME: use glyphs, not chars |
// double firstasce = itemText.charStyle(line.firstItem).font().ascent(itemText.charStyle(line.firstItem).fontSize() / 10.0); |
// double firstasce = itemText.charStyle(line.firstChar).font().ascent(itemText.charStyle(line.firstChar).fontSize() / 10.0); |
// double adj (0.0); |
// double currasce (this->getLineAscent(itemText)); |
// if (offsetPolicy == FLOPRealGlyphHeight) |
893,11 → 750,11 |
// } |
// else if ((!startOfCol) && (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)) |
// { |
// QChar ch = itemText.text(line.firstItem); |
// QChar ch = itemText.text(line.firstChar); |
// double firstasce = style.lineSpacing(); |
// double currasce = getLineHeight(itemText); |
// double adj = firstasce - currasce; |
// qDebug() << QString("move2 line %1.. down by %2").arg(current.line.firstItem).arg(-adj); |
// qDebug() << QString("move2 line %1.. down by %2").arg(current.line.firstChar).arg(-adj); |
// line.ascent = currasce; |
// line.y -= adj; |
// yPos -= adj; |
904,6 → 761,40 |
// } |
//} |
LineBox* createLineBox() |
{ |
LineBox* result = new LineBox(); |
result->moveTo(line.x - colLeft, line.y); |
result->setWidth(line.width); |
result->setAscent(line.ascent); |
result->setDescent(line.descent); |
for (int i = line.firstRun; i <= line.lastRun; ++i) |
{ |
addBox(result, glyphRuns.at(i)); |
} |
return result; |
} |
void addBox(LineBox *lineBox, const GlyphRun& run) |
{ |
Box* result; |
if (run.object()) |
{ |
result = new ObjectBox(run); |
result->setAscent(run.object()->height() - run.object()->lineWidth()); |
result->setDescent(0); |
} |
else |
{ |
result = new GlyphBox(run); |
result->setAscent(lineBox->ascent()); |
result->setDescent(lineBox->descent()); |
} |
lineBox->addBox(result); |
} |
private: |
double frameWidth; |
double frameHeight; |
911,6 → 802,34 |
double lineCorr; |
}; |
/** |
Clones the tab fill char as often as necssary after all distances are known |
*/ |
static void fillInTabLeaders(LineControl & current) |
{ |
// fill in tab leaders |
for(int i = current.line.firstRun; i <= current.line.lastRun; i++) |
{ |
GlyphRun& glyphRun = current.glyphRuns[i]; |
CharStyle charStyle(glyphRun.style()); |
if (glyphRun.hasFlag(ScLayout_TabLeaders)) |
{ |
GlyphLayout tglyph = glyphRun.glyphs().last(); |
double width = glyphRun.width(); |
double wt = charStyle.font().glyphWidth(tglyph.glyph, charStyle.fontSize() * tglyph.scaleV / 10.0); |
int count = static_cast<int>(width / wt); |
glyphRun.glyphs().clear(); |
for(int cx = 0; cx < count; ++cx) |
{ |
GlyphLayout more = tglyph; |
more.xadvance = width / count; |
glyphRun.glyphs().append(more); |
} |
} |
} |
} |
static bool checkCJK(QChar ch) { |
unsigned int code = ch.unicode(); |
if ( (0x2E80 < code && code < 0x2EFF) || // CJK Radicals Supplement |
957,10 → 876,6 |
return true; |
} |
static bool implicitSpace(QChar f, QChar s) { |
return checkCJK(f) && checkCJK(s); |
} |
static bool implicitBreak(QChar f, QChar s) { |
if (checkCJK(f) && checkCJK(s)) { |
return allowedCJKBreakAfter(f) && allowedCJKBreakBefore(s); |
969,7 → 884,7 |
} |
/// called when line length is known and line is to be justified |
static void justifyLine(StoryText& itemText, LineSpec& line) |
static void justifyLine(const ParagraphStyle& style, LineControl& curr) |
{ |
double glyphNatural = 0; |
979,24 → 894,21 |
int spaceInsertion = 0; |
double imSpace = -1; |
const ParagraphStyle& style(itemText.paragraphStyle(line.firstItem)); |
// measure natural widths for glyphs and spaces |
for (int sof = line.firstItem; sof <= line.lastItem; ++sof) |
for (int i = curr.line.firstRun; i <= curr.line.lastRun; ++i) |
{ |
GlyphLayout* glyph = itemText.getGlyphs(sof); |
QChar ch = itemText.text(sof); |
if (!SpecialChars::isExpandingSpace(ch)) |
GlyphRun glyphrun = curr.glyphRuns[i]; |
if (!glyphrun.hasFlag(ScLayout_ExpandingSpace)) |
{ |
glyphNatural += glyph->wide(); |
glyphNatural += glyphrun.width(); |
} |
else if ( !itemText.hasFlag(sof, ScLayout_SuppressSpace) ) |
else if ( !glyphrun.hasFlag(ScLayout_SuppressSpace) ) |
{ |
spaceNatural += glyph->wide(); |
if (imSpace < 0.0 || imSpace > glyph->wide()) |
imSpace = glyph->wide(); |
spaceNatural += glyphrun.width(); |
if (imSpace < 0.0 || imSpace > glyphrun.width()) |
imSpace = glyphrun.width(); |
} |
if (sof != line.firstItem && implicitSpace(itemText.text(sof - 1), ch)) { |
if (i != curr.line.firstRun && glyphrun.hasFlag(ScLayout_ImplicitSpace)) |
{ |
spaceInsertion += 1; |
} |
} |
1005,16 → 917,16 |
// decision: prio 1: stretch glyph; prio 2: insert spaces; prio 3: stretch spaces |
if (line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0) |
if (curr.line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0) |
{ |
glyphExtension = style.minGlyphExtension() - 1; |
spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1; |
spaceExtension = (curr.line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1; |
imSpace = 0; |
} |
else if (line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0) |
else if (curr.line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0) |
{ |
spaceExtension = 0; |
glyphExtension = (line.width - spaceNatural) / glyphNatural - 1; |
glyphExtension = (curr.line.width - spaceNatural) / glyphNatural - 1; |
imSpace = 0; |
} |
else |
1021,7 → 933,7 |
{ |
glyphExtension = style.maxGlyphExtension() - 1; |
if (spaceInsertion) { |
double remaining = line.width - glyphNatural * (1 + glyphExtension) - spaceNatural; |
double remaining = curr.line.width - glyphNatural * (1 + glyphExtension) - spaceNatural; |
if (imSpace > 0) { |
if (remaining / spaceInsertion < imSpace) { |
imSpace = remaining / spaceInsertion; |
1036,7 → 948,7 |
} |
} else { |
if (spaceNatural > 0) |
spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1; |
spaceExtension = (curr.line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1; |
else |
spaceExtension = 0; |
} |
1051,47 → 963,51 |
.arg(style.minWordTracking()).arg(style.minGlyphExtension()); |
*/ |
int startItem = line.firstItem; |
if (itemText.hasFlag(startItem, ScLayout_DropCap)) |
int startItem = curr.line.firstRun; |
if (curr.glyphRuns[startItem].hasFlag(ScLayout_DropCap)) |
startItem++; |
// distribute whitespace on spaces and glyphs |
for (int yof = startItem; yof <= line.lastItem; ++yof) |
for (int i = startItem; i <= curr.line.lastRun; ++i) |
{ |
GlyphLayout* glyph = itemText.getGlyphs(yof); |
QChar ch = itemText.text(yof); |
double wide = glyph->wide(); |
if (!SpecialChars::isExpandingSpace(ch)) |
GlyphRun& glyphrun = curr.glyphRuns[i]; |
if (i != curr.line.firstRun && glyphrun.hasFlag(ScLayout_ImplicitSpace)) |
{ |
glyph->last()->xadvance += wide * glyphExtension; |
while (glyph) |
GlyphRun& lastRun = curr.glyphRuns[i-1]; |
lastRun.glyphs().last().xadvance += imSpace; |
} |
double wide = glyphrun.width(); |
if (!glyphrun.hasFlag(ScLayout_ExpandingSpace)) |
{ |
for (int j = 0; j < glyphrun.glyphs().count(); ++j) |
{ |
glyph->xoffset *= glyphScale; |
glyph->scaleH *= glyphScale; |
glyph = glyph->more; |
GlyphLayout& glyph = glyphrun.glyphs()[j]; |
glyph.xadvance += wide * glyphExtension; |
glyph.xoffset *= glyphScale; |
glyph.scaleH *= glyphScale; |
} |
} |
else if (!itemText.hasFlag(yof, ScLayout_SuppressSpace)) |
else if (!glyphrun.hasFlag(ScLayout_SuppressSpace)) |
{ |
glyph->last()->xadvance += wide * spaceExtension; |
GlyphLayout& glyph = glyphrun.glyphs().last(); |
glyph.xadvance += wide * spaceExtension; |
} |
if (yof != line.firstItem && implicitSpace(itemText.text(yof - 1), ch)) { |
itemText.getGlyphs(yof - 1)->last()->xadvance += imSpace; |
} |
} |
} |
/// called when linelength is known and line is not justified |
static void indentLine(StoryText& itemText, LineSpec& line, double leftIndent) |
static void indentLine(const ParagraphStyle& style, LineControl& curr, double leftIndent) |
{ |
if (line.naturalWidth > line.width) |
if (curr.line.naturalWidth > curr.line.width) |
{ |
justifyLine(itemText, line); |
justifyLine(style, curr); |
} |
if (leftIndent > 0) |
{ |
line.x += leftIndent; |
line.width -= leftIndent; |
curr.line.x += leftIndent; |
curr.line.width -= leftIndent; |
} |
} |
1099,8 → 1015,8 |
///// calculate how much the first char should stick out to the left |
//static double opticalLeftMargin(const StoryText& itemText, const LineSpec& line) |
//{ |
// int b = line.firstItem; |
// while (b < line.lastItem && (itemText.flags(b)) & ScLayout_SuppressSpace)) |
// int b = line.firstChar; |
// while (b < line.lastChar && (itemText.flags(b) & ScLayout_SuppressSpace)) |
// ++b; |
// |
// double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0); |
1135,19 → 1051,20 |
//} |
/// calculate how much the last char should stick out to the right |
static double opticalRightMargin(const StoryText& itemText, const LineSpec& line) |
static double opticalRightMargin(const StoryText& itemText, const QList<GlyphRun> runs, const LineSpec& line) |
{ |
int b = line.lastItem; |
while (b > line.firstItem && |
(SpecialChars::isBreakingSpace(itemText.text(b)) || SpecialChars::isBreak(itemText.text(b))) |
int b = line.lastRun; |
while (b > line.firstRun && |
(SpecialChars::isBreakingSpace(itemText.text(runs[b].firstChar())) || |
SpecialChars::isBreak(itemText.text(runs[b].firstChar()))) |
) |
--b; |
if (b >= line.firstItem) |
if (b >= line.firstRun) |
{ |
const CharStyle& chStyle(itemText.charStyle(b)); |
const CharStyle& chStyle(runs[b].style()); |
double chs = chStyle.fontSize() * (chStyle.scaleH() / 1000.0); |
QChar chr = itemText.hasFlag(b, ScLayout_SoftHyphenVisible) ? |
QChar('-') : itemText.text(b); |
QChar chr = runs[b].hasFlag(ScLayout_SoftHyphenVisible) ? |
QChar('-') : itemText.text(runs[b].firstChar()); |
double rightCorr = chStyle.font().realCharWidth(chr, chs / 10.0); |
if (QString("-,.`´'~").indexOf(chr) >= 0 |
|| chr == QChar(0x2018) |
1309,6 → 1226,154 |
} |
} |
QList<GlyphRun> PageItem_TextFrame::shapeText() |
{ |
// maps expanded characters to itemText tokens. |
QMap<int, int> textMap; |
QString text; |
for (int i = firstInFrame(); i < itemText.length(); ++i) |
{ |
Mark* mark = itemText.mark(i); |
if (itemText.hasMark(i)) |
{ |
mark->OwnPage = OwnPage; |
//itemPtr and itemName set to this frame only if mark type is different than MARK2ItemType |
if (!mark->isType(MARK2ItemType)) |
{ |
mark->setItemPtr(this); |
mark->setItemName(itemName()); |
} |
//anchors and indexes has no visible inserts in text |
if (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType)) |
continue; |
//set note marker charstyle |
if (mark->isNoteType()) |
{ |
TextNote* note = mark->getNotePtr(); |
if (note == NULL) |
continue; |
mark->setItemPtr(this); |
NotesStyle* nStyle = note->notesStyle(); |
Q_ASSERT(nStyle != NULL); |
QString chsName = nStyle->marksChStyle(); |
CharStyle currStyle(itemText.charStyle(i)); |
if (!chsName.isEmpty()) |
{ |
CharStyle marksStyle(m_Doc->charStyle(chsName)); |
if (!currStyle.equiv(marksStyle)) |
{ |
currStyle.setParent(chsName); |
itemText.applyCharStyle(i, 1, currStyle); |
} |
} |
StyleFlag s(itemText.charStyle(i).effects()); |
if (mark->isType(MARKNoteMasterType)) |
{ |
if (nStyle->isSuperscriptInMaster()) |
s |= ScStyle_Superscript; |
else |
s &= ~ScStyle_Superscript; |
} |
else |
{ |
if (nStyle->isSuperscriptInNote()) |
s |= ScStyle_Superscript; |
else |
s &= ~ScStyle_Superscript; |
} |
if (s != itemText.charStyle(i).effects()) |
{ |
CharStyle haveSuperscript; |
haveSuperscript.setFeatures(s.featureList()); |
itemText.applyCharStyle(i, 1, haveSuperscript); |
} |
} |
} |
bool bullet = false; |
if (i == 0 || itemText.text(i - 1) == SpecialChars::PARSEP) |
{ |
ParagraphStyle style = itemText.paragraphStyle(i); |
if (style.hasBullet() || style.hasNum()) |
{ |
bullet = true; |
if (mark == NULL || !mark->isType(MARKBullNumType)) |
{ |
itemText.insertMark(new BulNumMark(), i); |
i--; |
continue; |
} |
if (style.hasBullet()) |
mark->setString(style.bulletStr()); |
else if (style.hasNum() && mark->getString().isEmpty()) |
{ |
mark->setString("?"); |
m_Doc->flag_Renumber = true; |
} |
} |
} |
if (!bullet && mark && mark->isType(MARKBullNumType)) |
{ |
itemText.removeChars(i, 1); |
i--; |
continue; |
} |
QString str = ExpandToken(i); |
if (str.isEmpty()) |
str = SpecialChars::ZWNBSPACE; |
for (int j = 0; j < str.length(); j++) |
textMap.insert(text.length() + j, i); |
text.append(str); |
} |
QList<GlyphRun> glyphRuns; |
glyphRuns.reserve(text.length()); |
for (int i = 0; i < text.length(); i++) |
{ |
const QChar ch(text.at(i)); |
int a = textMap.value(i); |
GlyphRun run(&itemText.charStyle(a), itemText.flags(a), a, a, itemText.object(a)); |
if (SpecialChars::isExpandingSpace(ch)) |
run.setFlag(ScLayout_ExpandingSpace); |
GlyphLayout gl = layoutGlyphs(run.style(), QString(ch), itemText.flags(a)); |
if (!glyphRuns.isEmpty()) |
{ |
GlyphLayout& last = glyphRuns.last().glyphs().last(); |
last.xadvance += run.style().font().glyphKerning(last.glyph, gl.glyph, run.style().fontSize() / 10) * last.scaleH; |
} |
//show control characters for marks |
if (itemText.hasMark(a)) |
{ |
GlyphLayout control; |
control.glyph = SpecialChars::OBJECT.unicode() + ScFace::CONTROL_GLYPHS; |
run.glyphs().append(control); |
} |
if (SpecialChars::isExpandingSpace(ch)) |
gl.xadvance *= run.style().wordTracking(); |
if (itemText.hasObject(a)) |
gl.xadvance = itemText.object(a)->width() + itemText.object(a)->lineWidth(); |
run.glyphs().append(gl); |
glyphRuns.append(run); |
} |
return glyphRuns; |
} |
void PageItem_TextFrame::layout() |
{ |
// qDebug()<<"==Layout==" << itemName() ; |
1342,10 → 1407,7 |
QPoint pt1, pt2; |
QRect pt; |
double chs, chsd = 0; |
double EndX, OFs, wide, kernVal; |
QString chstr; |
QChar currentCh; |
GlyphLayout* glyphs; |
double EndX, OFs; |
ParagraphStyle style; |
int opticalMargins = ParagraphStyle::OM_None; |
1356,7 → 1418,7 |
TabControl tabs; |
tabs.active = false; // RTab |
tabs.status = TabNONE; // TabCode |
tabs.charIndex = -1; // StartRT |
tabs.tabGlyph = 0; // was int charIndex ~ StartRT |
tabs.xPos = 0; // RTabX |
QList<ParagraphStyle::TabRecord> tTabValues; |
1378,14 → 1440,6 |
if (lineColor() != CommonStrings::None) |
lineCorr = m_lineWidth / 2.0; |
// TODO: refactor this into PageItem |
MarginStruct savedTextDistanceMargins(m_textDistanceMargins); |
LineControl current; |
current.init(m_width, m_height, m_textDistanceMargins, lineCorr); |
current.initColumns(columnWidth(), ColGap); |
current.hyphenCount = 0; |
//hold Y position of last computed line of text (with glyphs descent) |
//for moving next line if glyphs are higher than that |
double lastLineY = 0; |
1456,7 → 1510,11 |
m_availableRegion = matrix.map(m_availableRegion); |
} |
current.nextColumn(); |
QList<GlyphRun> glyphRuns = shapeText(); |
LineControl current(m_width, m_height, m_textDistanceMargins, lineCorr, m_Doc, glyphRuns, columnWidth(), ColGap); |
current.nextColumn(textLayout); |
lastLineY = m_textDistanceMargins.top(); |
//automatic line spacing factor (calculated once) |
1486,13 → 1544,13 |
desc = -itemText.defaultStyle().charStyle().font().descent(itemText.defaultStyle().charStyle().fontSize() / 10.0); |
current.yPos = itemText.defaultStyle().lineSpacing() + m_textDistanceMargins.top() + lineCorr - desc; |
} |
current.startLine(firstInFrame()); |
current.startLine(0); |
outs = false; |
OFs = 0; |
MaxChars = 0; |
double realEnd = 0; |
current.restartIndex = current.restartRowIndex = firstInFrame(); |
current.restartIndex = current.restartRowIndex = 0; |
current.afterOverflow = false; |
current.addLine = false; |
current.recalculateY = true; |
1513,81 → 1571,35 |
int regionMinY = 0, regionMaxY= 0; |
double autoLeftIndent = 0.0; |
for (int i = 0; i < glyphRuns.length(); ++i) |
{ |
if (glyphRuns[i].glyphs().isEmpty()) |
continue; |
for (int a = firstInFrame(); a < itLen; ++a) |
{ |
currentCh = itemText.text(a); |
glyphs = itemText.getGlyphs(a); |
int a = glyphRuns[i].firstChar(); |
bool HasObject = itemText.hasObject(a); |
PageItem* currentObject = HasObject? itemText.object(a): NULL; |
PageItem* currentObject = itemText.object(a); |
bool HasMark = itemText.hasMark(a); |
Mark* mark = itemText.mark(a); |
if (itemText.charStyle(a).effects() & ScStyle_UnderlineWords) |
{ |
CharStyle tmp(itemText.charStyle(a)); |
StyleFlag effects = tmp.effects(); |
if (!itemText.text(a).isSpace()) |
effects |= ScStyle_Underline; |
effects &= ~ScStyle_UnderlineWords; |
tmp.setFeatures(effects.featureList()); |
itemText.applyCharStyle(a, 1, tmp); |
} |
if (HasMark) |
{ |
//show control characters for marks |
glyphs->glyph = SpecialChars::OBJECT.unicode() + ScFace::CONTROL_GLYPHS; |
mark->OwnPage = OwnPage; |
//itemPtr and itemName set to this frame only if mark type is different than MARK2ItemType |
if (!mark->isType(MARK2ItemType)) |
{ |
mark->setItemPtr(this); |
mark->setItemName(itemName()); |
} |
//anchors and indexes has no visible inserts in text |
if (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType)) |
{ |
glyphs->shrink(); |
continue; |
} |
Mark* mark = itemText.mark(a); |
//store mark pointer and position in text |
if (mark->isType(MARKNoteMasterType)) |
noteMarksPosMap.insert(a, mark); |
//set note marker charstyle |
if (mark->isNoteType()) |
{ |
TextNote* note = mark->getNotePtr(); |
if (note == NULL) |
continue; |
mark->setItemPtr(this); |
NotesStyle* nStyle = note->notesStyle(); |
Q_ASSERT(nStyle != NULL); |
QString chsName = nStyle->marksChStyle(); |
CharStyle currStyle(itemText.charStyle(a)); |
if (!chsName.isEmpty()) |
{ |
CharStyle marksStyle(m_Doc->charStyle(chsName)); |
if (!currStyle.equiv(marksStyle)) |
{ |
currStyle.setParent(chsName); |
itemText.applyCharStyle(a, 1, currStyle); |
} |
} |
} |
StyleFlag s(itemText.charStyle(a).effects()); |
if (mark->isType(MARKNoteMasterType)) |
{ |
if (nStyle->isSuperscriptInMaster()) |
s |= ScStyle_Superscript; |
else |
s &= ~ScStyle_Superscript; |
} |
else |
{ |
if (nStyle->isSuperscriptInNote()) |
s |= ScStyle_Superscript; |
else |
s &= ~ScStyle_Superscript; |
} |
if (s != itemText.charStyle(a).effects()) |
{ |
CharStyle haveSuperscript; |
haveSuperscript.setFeatures(s.featureList()); |
itemText.applyCharStyle(a, 1, haveSuperscript); |
} |
} |
} |
BulNumMode = false; |
if (a==0 || itemText.text(a-1) == SpecialChars::PARSEP) |
{ |
1596,37 → 1608,13 |
if (style.hasBullet() || style.hasNum()) |
{ |
BulNumMode = true; |
if (mark == NULL || !mark->isType(MARKBullNumType)) |
{ |
BulNumMark* bnMark = new BulNumMark(); |
itemText.insertMark(bnMark,a); |
a--; |
itLen = itemText.length(); |
continue; |
} |
if (style.hasBullet()) |
mark->setString(style.bulletStr()); |
else if (style.hasNum()) |
{ |
if (mark->getString().isEmpty()) |
{ |
mark->setString("?"); |
m_Doc->flag_Renumber = true; |
} |
} |
} |
} |
if (!BulNumMode && mark && mark->isType(MARKBullNumType)) |
{ |
itemText.removeChars(a,1); |
a--; |
itLen = itemText.length(); |
continue; |
} |
if (current.itemsInLine == 0) |
if (current.isEmpty) |
opticalMargins = style.opticalMargins(); |
//-->#13490 |
if (isNoteFrame() && !mark) |
if (isNoteFrame() && !HasMark) |
{ |
StyleFlag s(itemText.charStyle(a).effects()); |
s &= ~ScStyle_Superscript; |
1636,12 → 1624,8 |
} |
//--<#13490 |
CharStyle charStyle = ((itemText.text(a) != SpecialChars::PARSEP) ? itemText.charStyle(a) : style.charStyle()); |
chstr = ExpandToken(a); |
int chstrLen = chstr.length(); |
if (chstr.isEmpty()) |
chstr = SpecialChars::ZWNBSPACE; |
curStat = SpecialChars::getCJKAttr(currentCh); |
curStat = SpecialChars::getCJKAttr(itemText.text(a)); |
//set style for paragraph effects |
if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP) |
{ |
1678,7 → 1662,7 |
{ |
if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP) |
{ |
if (currentCh != SpecialChars::PARSEP) |
if (itemText.text(a) != SpecialChars::PARSEP) |
{ |
DropCmode = style.hasDropCap(); |
if (DropCmode) |
1692,20 → 1676,20 |
const ScFace font = charStyle.font(); |
itemText.clearFlag(a, ScLayout_DropCap); |
itemText.clearFlag(a, ScLayout_SoftHyphenVisible); |
glyphRuns[i].clearFlag(ScLayout_DropCap); |
glyphRuns[i].clearFlag(ScLayout_SoftHyphenVisible); |
// No space at begin of line, |
if (legacy) |
{ |
// unless at begin of par (eeks) |
if ( (current.itemsInLine == 0) && (SpecialChars::isBreakingSpace(currentCh)) |
if ( (current.isEmpty) && (SpecialChars::isBreakingSpace(itemText.text(a))) |
&& (a > 0 && ! SpecialChars::isBreak(itemText.text(a-1))) |
&& ! (a > 0 && SpecialChars::isBreakingSpace(itemText.text(a-1)) |
&& (!itemText.hasFlag(a-1, ScLayout_SuppressSpace)))) |
&& (!glyphRuns[i - 1].hasFlag(ScLayout_SuppressSpace)))) |
{ |
itemText.setFlag(a, ScLayout_SuppressSpace); |
glyphs->xadvance = 0; |
glyphRuns[i].setFlag(ScLayout_SuppressSpace); |
glyphRuns[i].glyphs().first().xadvance = 0; |
continue; |
} |
else |
1713,16 → 1697,16 |
} |
else // from 134 on use NBSPACE for this effect |
{ |
if ( current.itemsInLine == 0 && (SpecialChars::isBreakingSpace(currentCh) || currentCh.isSpace())) |
if ( current.isEmpty && (SpecialChars::isBreakingSpace(itemText.text(a)) || itemText.text(a).isSpace())) |
{ |
itemText.setFlag(a, ScLayout_SuppressSpace); |
glyphs->xadvance = 0; |
glyphRuns[i].setFlag(ScLayout_SuppressSpace); |
glyphRuns[i].glyphs()[0].xadvance = 0; |
continue; |
} |
else |
itemText.clearFlag(a, ScLayout_SuppressSpace); |
} |
if (current.itemsInLine == 0) |
if (current.isEmpty) |
{ |
if (style.rightMargin() == 0) |
{ |
1745,7 → 1729,7 |
if (!current.afterOverflow && current.recalculateY && !current.startOfCol) |
current.yPos += style.gapBefore(); |
DropCapDrop = 0; |
if (chstr[0] != SpecialChars::PARSEP) |
if (itemText.text(a) != SpecialChars::PARSEP) |
DropCmode = style.hasDropCap(); |
else |
DropCmode = false; |
1770,10 → 1754,10 |
//text height, width, ascent and descent should be calculated for whole text provided by ScText in current position |
//and that may be more than one char (variable text for example) |
double realCharHeight = 0.0, realCharAscent = 0.0; |
for (int i = 0; i < chstrLen; ++i) |
{ |
realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], 1)); |
realCharAscent = qMax(realCharAscent, font.realCharAscent(chstr[i], 1)); |
foreach (GlyphLayout gl, glyphRuns[i].glyphs()) { |
GlyphMetrics gm = font.glyphBBox(gl.glyph); |
realCharHeight = qMax(realCharHeight, gm.ascent + gm.descent); |
realCharAscent = qMax(realCharAscent, gm.ascent); |
} |
double fontAscent = font.ascent(style.charStyle().fontSize() / 10.0); |
if (realCharHeight == 0.0) |
1782,8 → 1766,8 |
realCharAscent = fontAscent; |
chsd = (10 * ((DropCapDrop + fontAscent) / realCharHeight)); |
chs = (10 * ((DropCapDrop + fontAscent) / realCharAscent)); |
itemText.setFlag(a, ScLayout_DropCap); |
glyphs->yoffset -= DropCapDrop; |
glyphRuns[i].setFlag(ScLayout_DropCap); |
glyphRuns[i].glyphs().first().yoffset += DropCapDrop; |
if (HasObject) |
{ |
chs = qRound((currentObject->height() + currentObject->lineWidth()) * 10); |
1797,113 → 1781,92 |
else |
chs = charStyle.fontSize(); |
} |
// set StartOfLine (and find tracking?) |
if (current.itemsInLine == 0) |
// set StartOfLine |
if (current.isEmpty) |
{ |
itemText.setFlag(a, ScLayout_StartOfLine); |
kernVal = 0; |
glyphRuns[i].setFlag(ScLayout_StartOfLine); |
} |
else |
{ |
kernVal = 0; // chs * charStyle.tracking() / 10000.0; |
itemText.clearFlag(a, ScLayout_StartOfLine); |
glyphRuns[i].clearFlag(ScLayout_StartOfLine); |
} |
glyphs->yadvance = 0; |
layoutGlyphs(charStyle, chstr, itemText.flags(a), *glyphs); |
// glyphs->yadvance = 0; |
// find out width, ascent and descent of char |
if (HasObject) |
GlyphLayout& firstGlyph = glyphRuns[i].glyphs().first(); |
GlyphLayout& lastGlyph = glyphRuns[i].glyphs().last(); |
// apply cjk kerning |
//TODO: cjk spacing and kerning should be done in layoutGlyphs! |
if (i + 1 < glyphRuns.length()) |
{ |
wide = currentObject->width() + currentObject->lineWidth(); |
glyphs->xadvance = wide * glyphs->scaleH; |
} |
else |
{ |
wide = glyphs->wide(); |
// apply kerning |
if (a+1 < itemText.length()) |
{ |
uint glyph2 = font.char2CMap(itemText.text(a+1)); |
double kern = font.glyphKerning(glyphs->last()->glyph, glyph2, chs / 10.0) * glyphs->scaleH; |
wide += kern; |
glyphs->last()->xadvance += kern; |
// change xadvance, xoffset according to JIS X4051 |
int nextStat = SpecialChars::getCJKAttr(itemText.text(a+1)); |
int prevStat; |
if (curStat != 0) |
{ // current char is CJK |
if (nextStat == 0 && !SpecialChars::isBreakingSpace(itemText.text(a+1))){ |
switch(curStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_KANJI: |
case SpecialChars::CJK_KANA: |
case SpecialChars::CJK_NOTOP: |
kern = charStyle.fontSize() / 10 / 4; |
wide += kern; |
glyphs->last()->xadvance += kern; |
} |
} else { // next char is CJK, too |
switch(curStat & SpecialChars::CJK_CHAR_MASK){ |
GlyphRun nextRun = glyphRuns[i + 1]; |
// change xadvance, xoffset according to JIS X4051 |
int nextStat = SpecialChars::getCJKAttr(itemText.text(nextRun.firstChar())); |
if (curStat != 0) |
{ // current char is CJK |
if (nextStat == 0 && !SpecialChars::isBreakingSpace(itemText.text(nextRun.firstChar()))){ |
switch(curStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_KANJI: |
case SpecialChars::CJK_KANA: |
case SpecialChars::CJK_NOTOP: |
lastGlyph.xadvance += charStyle.fontSize() / 10 / 4; |
} |
} else { // next char is CJK, too |
switch(curStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_END: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_BEGIN: |
case SpecialChars::CJK_FENCE_END: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_BEGIN: |
case SpecialChars::CJK_FENCE_END: |
case SpecialChars::CJK_COMMA: |
case SpecialChars::CJK_PERIOD: |
case SpecialChars::CJK_MIDPOINT: |
kern = -charStyle.fontSize() / 10 / 2; |
wide += kern; |
glyphs->last()->xadvance += kern; |
} |
break; |
case SpecialChars::CJK_COMMA: |
case SpecialChars::CJK_PERIOD: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_BEGIN: |
case SpecialChars::CJK_FENCE_END: |
kern = -charStyle.fontSize() / 10 / 2; |
wide += kern; |
glyphs->last()->xadvance += kern; |
} |
break; |
case SpecialChars::CJK_MIDPOINT: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_BEGIN: |
kern = -charStyle.fontSize() / 10 / 2; |
wide += kern; |
glyphs->last()->xadvance += kern; |
} |
break; |
lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2; |
} |
break; |
case SpecialChars::CJK_COMMA: |
case SpecialChars::CJK_PERIOD: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_FENCE_BEGIN: |
if (a == current.line.firstItem){ // first char of the line |
prevStat = SpecialChars::CJK_FENCE_BEGIN; |
} else { |
prevStat = SpecialChars::getCJKAttr(itemText.text(a-1)) & SpecialChars::CJK_CHAR_MASK; |
} |
if (prevStat == SpecialChars::CJK_FENCE_BEGIN){ |
kern = -charStyle.fontSize() / 10 / 2; |
wide += kern; |
glyphs->last()->xadvance += kern; |
glyphs->last()->xoffset += kern; |
} |
break; |
case SpecialChars::CJK_FENCE_END: |
lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2;; |
} |
} |
} else { // current char is not CJK |
if (nextStat != 0 && !SpecialChars::isBreakingSpace(currentCh)){ |
break; |
case SpecialChars::CJK_MIDPOINT: |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_KANJI: |
case SpecialChars::CJK_KANA: |
case SpecialChars::CJK_NOTOP: |
// use the size of the current char instead of the next one |
kern = charStyle.fontSize() / 10 / 4; |
wide += kern; |
glyphs->last()->xadvance += kern; |
case SpecialChars::CJK_FENCE_BEGIN: |
lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2; |
} |
break; |
case SpecialChars::CJK_FENCE_BEGIN: |
int prevStat = 0; |
if (i == current.line.firstRun){ // first char of the line |
prevStat = SpecialChars::CJK_FENCE_BEGIN; |
} else if (i != 0) { |
prevStat = SpecialChars::getCJKAttr(itemText.text(glyphRuns[i - 1].lastChar())) & SpecialChars::CJK_CHAR_MASK; |
} |
if (prevStat == SpecialChars::CJK_FENCE_BEGIN){ |
lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2; |
lastGlyph.xoffset -= charStyle.fontSize() / 10 / 2; |
} |
break; |
} |
} |
} else { // current char is not CJK |
if (nextStat != 0 && !SpecialChars::isBreakingSpace(itemText.text(glyphRuns[i].lastChar()))){ |
switch(nextStat & SpecialChars::CJK_CHAR_MASK){ |
case SpecialChars::CJK_KANJI: |
case SpecialChars::CJK_KANA: |
case SpecialChars::CJK_NOTOP: |
// use the size of the current char instead of the next one |
lastGlyph.xadvance += charStyle.fontSize() / 10 / 4; |
} |
} |
} |
} |
// find out width, ascent and descent of char |
double wide = glyphRuns[i].width(); |
if (DropCmode) |
{ |
// drop caps are wider... |
1912,22 → 1875,23 |
double itemHeight = currentObject->height() + currentObject->lineWidth(); |
if (itemHeight == 0) |
itemHeight = font.height(style.charStyle().fontSize() / 10.0); |
wide = currentObject->width() + currentObject->lineWidth(); |
asce = currentObject->height() + currentObject->lineWidth(); |
realAsce = calculateLineSpacing (style, this) * DropLines; |
glyphs->scaleH /= glyphs->scaleV; |
glyphs->scaleV = (realAsce / itemHeight); |
glyphs->scaleH *= glyphs->scaleV; |
firstGlyph.scaleH /= firstGlyph.scaleV; |
firstGlyph.scaleV = (realAsce / itemHeight); |
firstGlyph.scaleH *= firstGlyph.scaleV; |
} |
else |
{ |
double realCharHeight = 0.0; |
wide = 0.0; realAsce = 0.0; |
for (int i = 0; i < chstrLen; ++i) |
{ |
realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], charStyle.fontSize() / 10.0)); |
realAsce = qMax(realAsce, font.realCharHeight(chstr[i], chsd / 10.0)); |
wide += font.realCharWidth(chstr[i], chsd / 10.0); |
foreach (GlyphLayout gl, glyphRuns[i].glyphs()) { |
GlyphMetrics gm; |
gm = font.glyphBBox(gl.glyph, charStyle.fontSize() / 10.0); |
realCharHeight = qMax(realCharHeight, gm.ascent + gm.descent); |
gm = font.glyphBBox(gl.glyph, chsd / 10.0); |
realAsce = qMax(realAsce, gm.ascent + gm.descent); |
wide += gm.width; |
} |
wide = (wide* scaleH) + (1 - scaleH); |
realAsce = realAsce * scaleV + offset; |
1935,37 → 1899,33 |
realCharHeight = font.height(style.charStyle().fontSize() / 10.0); |
asce = font.ascent(hlcsize10); |
// qDebug() QString("dropcaps pre: chsd=%1 realCharHeight = %2 chstr=%3").arg(chsd).arg(asce).arg(chstr2[0]); |
glyphs->scaleH /= glyphs->scaleV; |
glyphs->scaleV = (realAsce / realCharHeight); |
glyphs->scaleH *= glyphs->scaleV; |
glyphs->xoffset -= 0.5; //drop caps are always to far from column left edge |
firstGlyph.scaleH /= firstGlyph.scaleV; |
firstGlyph.scaleV = (realAsce / realCharHeight); |
firstGlyph.scaleH *= firstGlyph.scaleV; |
firstGlyph.xoffset -= 0.5; //drop caps are always to far from column left edge |
} |
glyphs->xadvance = wide; |
firstGlyph.xadvance = wide / firstGlyph.scaleH; |
desc = realDesc = 0; |
} |
else // !DropCMode |
{ |
if (SpecialChars::isExpandingSpace(currentCh)) |
{ |
double wordtracking = charStyle.wordTracking(); |
glyphs->xadvance *= wordtracking; |
wide *= wordtracking; |
} |
// find ascent / descent |
if (HasObject) |
desc = realDesc = 0; |
else |
{ |
for (int i = 0; i < chstrLen; ++i) |
if (itemText.text(a) != SpecialChars::OBJECT) |
{ |
if (chstr[i] == SpecialChars::OBJECT) |
continue; |
realDesc = qMax(realDesc, font.realCharDescent(chstr[i], hlcsize10)); |
realAsce = font.realCharAscent(chstr[i], hlcsize10); |
foreach (GlyphLayout gl, glyphRuns[i].glyphs()) { |
GlyphMetrics gm = font.glyphBBox(gl.glyph, hlcsize10); |
realDesc = qMax(realDesc, gm.descent); |
realAsce = gm.ascent; |
} |
} |
realDesc = realDesc * scaleV - offset; |
desc = -font.descent(hlcsize10); |
current.rememberShrinkStretch(currentCh, wide, style); |
current.rememberShrinkStretch(itemText.text(a), wide, style); |
} |
if (HasObject) |
{ |
1979,8 → 1939,8 |
realAsce = asce * scaleV + offset; |
else |
{ |
for (int i = 0; i < chstrLen; ++i) |
realAsce = qMax(realAsce, font.realCharAscent(chstr[i], hlcsize10) * scaleV + offset); |
foreach (GlyphLayout gl, glyphRuns[i].glyphs()) |
realAsce = qMax(realAsce, font.glyphBBox(gl.glyph, hlcsize10).ascent * scaleV + offset); |
} |
} |
} |
1987,7 → 1947,7 |
// if (BulNumMode) |
// hl->glyph.last()->xadvance += style.parEffectOffset(); |
//check for Y position at beginning of line |
if (current.itemsInLine == 0 && !current.afterOverflow) |
if (current.isEmpty && !current.afterOverflow) |
{ |
if (current.recalculateY) |
{ |
1996,7 → 1956,7 |
{ |
lastLineY = qMax(lastLineY, m_textDistanceMargins.top() + lineCorr); |
//fix for proper rendering first empty line (only with PARSEP) |
if (chstr[0] == SpecialChars::PARSEP) |
if (itemText.text(a) == SpecialChars::PARSEP) |
current.yPos += style.lineSpacing(); |
if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing || FlopBaseline) |
{ |
2101,7 → 2061,7 |
regionMaxY = static_cast<int>(floor(current.yPos + desc)); |
} |
if (current.itemsInLine == 0 && !current.afterOverflow) |
if (current.isEmpty && !current.afterOverflow) |
{ |
//start a new line |
goNoRoom = false; |
2219,12 → 2179,12 |
} |
if (newColumn) |
{ |
current.nextColumn(); |
current.nextColumn(textLayout); |
current.mustLineEnd = current.colRight; |
current.restartX = current.xPos; |
lastLineY = current.yPos; |
current.rowDesc = 0; |
a--; |
i--; |
current.recalculateY = true; |
current.addLeftIndent = true; |
continue; |
2231,13 → 2191,15 |
} |
current.line.x = current.restartX = current.xPos; |
current.line.y = current.yPos; |
if (glyphRuns[current.line.firstRun].hasFlag(ScLayout_DropCap)) |
current.line.y -= DropCapDrop; |
} |
//check if line must start at new Y position due to current glyph height or previous line descent |
if (!SpecialChars::isBreak(currentCh, true) |
&& !SpecialChars::isBreakingSpace(currentCh) |
&& !SpecialChars::isExpandingSpace(currentCh) |
&& currentCh != SpecialChars::TAB) |
if (!SpecialChars::isBreak(itemText.text(a), true) |
&& !SpecialChars::isBreakingSpace(itemText.text(a)) |
&& !SpecialChars::isExpandingSpace(itemText.text(a)) |
&& itemText.text(a) != SpecialChars::TAB) |
{ |
double diff = 0; |
if (current.startOfCol || DropCmode) |
2247,7 → 2209,7 |
if (HasObject) |
diff = (currentObject->height() + currentObject->lineWidth()) * scaleV + offset - (current.yPos - lastLineY); |
else |
diff = font.realCharAscent(QChar('l'), hlcsize10) * scaleV + offset - (current.yPos - lastLineY); |
diff = font.capHeight(hlcsize10) * scaleV + offset - (current.yPos - lastLineY); |
} |
else |
{ |
2290,7 → 2252,7 |
maxDY = 0; |
} |
} |
a = current.restartRow(false); |
i = current.restartRow(false); |
continue; |
} |
} |
2297,7 → 2259,7 |
// right tab stuff |
if (tabs.active) |
{ |
if (((currentCh == '.') && (tabs.status == TabPOINT)) || ((currentCh == ',') && (tabs.status == TabCOMMA)) || (currentCh == SpecialChars::TAB)) |
if (((itemText.text(a) == '.') && (tabs.status == TabPOINT)) || ((itemText.text(a) == ',') && (tabs.status == TabCOMMA)) || (itemText.text(a) == SpecialChars::TAB)) |
{ |
tabs.active = false; |
tabs.status = TabNONE; |
2304,7 → 2266,7 |
} |
} |
// tab positioning |
if (currentCh == SpecialChars::TAB) |
if (itemText.text(a) == SpecialChars::TAB) |
{ |
wide = 1; |
if (tabs.active) |
2342,23 → 2304,19 |
} |
// remember fill char |
if (!tabs.fillChar.isNull()) { |
glyphs->growWithTabLayout(); |
TabLayout * tglyph = dynamic_cast<TabLayout*>(glyphs->more); |
if (tglyph) |
{ |
tglyph->fillChar = tabs.fillChar; |
tglyph->glyph = font.char2CMap(tabs.fillChar); |
tglyph->yoffset = glyphs->yoffset; |
tglyph->scaleV = tglyph->scaleH = chs / charStyle.fontSize(); |
tglyph->xadvance = 0; |
} |
if (!tabs.fillChar.isNull()) |
{ |
glyphRuns[i].setFlag(ScLayout_TabLeaders); |
GlyphLayout tglyph; |
tglyph.glyph = font.char2CMap(tabs.fillChar); |
tglyph.yoffset = firstGlyph.yoffset; |
tglyph.scaleV = tglyph.scaleH = chs / charStyle.fontSize(); |
tglyph.xadvance = 0; |
glyphRuns[i].glyphs().append(tglyph); |
} |
} |
current.xPos -= (legacy ? 1.0 : 0.0); |
glyphs->xadvance = current.xPos + wide + kernVal - tabs.xPos; |
// wide = current.xPos - RTabX; |
tabs.charIndex = a; |
firstGlyph.xadvance = current.xPos + wide - tabs.xPos; |
tabs.tabGlyph = &firstGlyph; |
} |
} |
2366,9 → 2324,9 |
if (DropCmode) |
{ |
double yoffset = 0.0; |
for (int i = 0; i < chstrLen; ++i) |
yoffset = qMax(yoffset, font.realCharHeight(chstr[i], chsd / 10.0) - font.realCharAscent(chstr[i], chsd / 10.0)); |
glyphs->yoffset -= yoffset; |
foreach (GlyphLayout gl, glyphRuns[i].glyphs()) |
yoffset = qMax(yoffset, font.glyphBBox(gl.glyph, chsd / 10.0).descent); |
firstGlyph.yoffset -= yoffset; |
} |
// remember x pos |
double breakPos = current.xPos; |
2375,11 → 2333,11 |
if (!tabs.active) // normal case |
{ |
current.xPos += wide+kernVal; |
current.xPos += wide; |
} |
else if (tabs.active && tabs.status == TabCENTER) // center tab |
{ |
current.xPos += (wide+kernVal) / 2; |
current.xPos += wide / 2; |
current.xPos = qMax(current.xPos, current.colLeft); |
} |
else // other tabs.active |
2387,17 → 2345,17 |
current.xPos = qMax(current.xPos, current.colLeft); |
} |
// remember possible break |
if ( (SpecialChars::isBreakingSpace(currentCh) || currentCh == SpecialChars::TAB)) |
if ( (SpecialChars::isBreakingSpace(itemText.text(a)) || itemText.text(a) == SpecialChars::TAB)) |
{ |
if ( a == firstInFrame() || !SpecialChars::isBreakingSpace(itemText.text(a-1)) ) |
{ |
current.rememberBreak(a, breakPos, style.rightMargin()); |
current.rememberBreak(i, breakPos, style.rightMargin()); |
} |
} |
if (HasObject) |
current.rememberBreak(a, breakPos, style.rightMargin()); |
current.rememberBreak(i, breakPos, style.rightMargin()); |
// CJK break |
if (a > current.line.firstItem) |
if (i > current.line.firstRun) |
{ // not the first char |
if ((lastStat == 0) && (curStat == 0)) |
{ // both non-CJK |
2406,7 → 2364,7 |
// non-CJK char does not have CJK_NOBREAK_AFTER/CJK_NOBREAK_BEFORE |
if ((lastStat & SpecialChars::CJK_NOBREAK_AFTER) == 0 && |
(curStat & SpecialChars::CJK_NOBREAK_BEFORE) == 0){ |
current.rememberBreak(a-1, breakPos, style.rightMargin()); |
current.rememberBreak(i-1, breakPos, style.rightMargin()); |
} |
} |
2423,17 → 2381,18 |
double overflowWidth = 0.0; |
double hyphWidth = 0.0; |
bool inOverflow = false; |
if (itemText.hasFlag(a,ScLayout_HyphenationPossible) || currentCh == SpecialChars::SHYPHEN) |
if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN) |
hyphWidth = font.charWidth('-', hlcsize10) * (charStyle.scaleH() / 1000.0); |
if ((current.isEndOfLine(style.rightMargin() + hyphWidth)) || current.isEndOfCol(realDesc) || SpecialChars::isBreak(currentCh, Cols > 1) || (current.xPos - current.maxShrink + hyphWidth) >= current.mustLineEnd) |
if ((current.isEndOfLine(style.rightMargin() + hyphWidth)) || current.isEndOfCol(realDesc) || SpecialChars::isBreak(itemText.text(a), Cols > 1) || (current.xPos - current.maxShrink + hyphWidth) >= current.mustLineEnd) |
{ |
//end of row reached - right column, end of column, break char or line must end |
if (current.itemsInLine == 0 && !current.afterOverflow && !SpecialChars::isBreak(currentCh, Cols > 1)) |
if (current.isEmpty && !current.afterOverflow && !SpecialChars::isBreak(itemText.text(a), Cols > 1)) |
{ |
//no glyphs in line, so start new row |
if (SpecialChars::isBreak(currentCh, Cols > 1)) |
current.restartRowIndex = a +1; |
a = current.restartRow(true); |
if (SpecialChars::isBreak(itemText.text(a), Cols > 1)) |
current.restartRowIndex = i + 1; |
i = current.restartRow(true); |
inOverflow = false; |
outs = false; |
continue; |
2442,13 → 2401,14 |
if (current.breakIndex < 0) |
{ |
//force break |
if (!SpecialChars::isBreak(currentCh, Cols > 1)) |
if (!SpecialChars::isBreak(itemText.text(a), Cols > 1)) |
{ |
//force line end at previouse glyph |
a--; |
i--; |
a = glyphRuns[i].firstChar(); |
current.mustLineEnd = current.line.x; |
} |
current.breakLine(itemText, style, firstLineOffset(),a); |
current.breakLine(style, firstLineOffset(), i); |
} |
if (!current.addLine && !current.lastInRowLine && current.afterOverflow) |
{ |
2457,7 → 2417,7 |
//if we have some text here - insert text WITHOUT right margin |
//if there is no place for text - insert text WITH right margin and end line |
current.lastInRowLine = false; |
if (current.line.firstItem == current.restartIndex) |
if (current.line.firstRun == current.restartIndex) |
current.lastInRowLine = true; |
if (current.hasDropCap && DropLinesCount == 0 && current.restartIndex == current.restartRowIndex) |
{ |
2465,12 → 2425,13 |
maxDX = 0; |
current.yPos = maxDY; |
} |
a = current.restartLine(false,true); |
i = current.restartLine(false,true); |
outs = false; |
inOverflow = false; |
continue; |
} |
outs = true; |
current.addLine = true; |
current.lastInRowLine = true; |
current.rightMargin = style.rightMargin(); |
2480,7 → 2441,7 |
else |
{ |
int charStart, charEnd; |
if (current.itemsInLine == 0) |
if (current.isEmpty) |
{ |
charStart = static_cast<int>(floor(current.line.x)); |
charEnd = static_cast<int>(ceil(current.xPos)); |
2491,10 → 2452,10 |
charEnd = static_cast<int>(ceil(current.xPos - current.maxShrink)); |
} |
if (legacy && |
(((currentCh == '-' || itemText.hasFlag(a, ScLayout_HyphenationPossible)) && (current.hyphenCount < m_Doc->hyphConsecutiveLines() || m_Doc->hyphConsecutiveLines() == 0)) |
|| currentCh == SpecialChars::SHYPHEN)) |
(((itemText.text(a) == '-' || glyphRuns[i].hasFlag(ScLayout_HyphenationPossible)) && (current.hyphenCount < m_Doc->hyphConsecutiveLines() || m_Doc->hyphConsecutiveLines() == 0)) |
|| itemText.text(a) == SpecialChars::SHYPHEN)) |
{ |
if (itemText.hasFlag(a, ScLayout_HyphenationPossible) || currentCh == SpecialChars::SHYPHEN) |
if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN) |
{ |
pt1 = QPoint(charStart, regionMinY); |
pt2 = QPoint(static_cast<int>(charEnd + hyphWidth), regionMaxY -1); |
2505,7 → 2466,7 |
pt2 = QPoint(charEnd, regionMaxY -1); |
} |
} |
else if (!legacy && SpecialChars::isBreakingSpace(currentCh)) |
else if (!legacy && SpecialChars::isBreakingSpace(itemText.text(a))) |
{ |
pt1 = QPoint(static_cast<int>(qMax(floor(breakPos - current.maxShrink - (style.minGlyphExtension() * wide)),0.0)), regionMinY); |
pt2 = QPoint(charEnd, regionMaxY -1); |
2536,11 → 2497,11 |
} |
if (outs) |
{ |
if (current.itemsInLine == 0) |
if (current.isEmpty) |
{ |
current.line.x = current.xPos = realEnd; |
a--; |
current.startLine(a+1); |
i--; |
current.startLine(i+1); |
if (!current.wasFirstInRow) |
current.addLeftIndent = true; |
if (current.hasDropCap && DropLinesCount == 0 && !current.afterOverflow) |
2554,8 → 2515,9 |
} |
if (current.breakIndex < 0) |
{ |
a--; |
current.breakLine(itemText, style, firstLineOffset(), a); |
i--; |
a = glyphRuns[i].firstChar(); |
current.breakLine(style, firstLineOffset(), i); |
} |
//check if after overflow text can be placed |
overflowWidth = realEnd - (current.xPos - current.maxShrink); |
2577,7 → 2539,7 |
current.lastInRowLine = true; |
current.mustLineEnd = current.line.x; |
} |
else if (current.line.firstItem == current.restartIndex) |
else if (current.line.firstRun == current.restartIndex) |
current.lastInRowLine = true; |
} |
else |
2587,7 → 2549,7 |
current.hasDropCap = false; |
maxDX = 0; |
} |
a = current.restartLine(false, true); |
i = current.restartLine(false, true); |
inOverflow = false; |
outs = false; |
continue; |
2604,13 → 2566,13 |
} |
// hyphenation |
if ((itemText.hasFlag(a, ScLayout_HyphenationPossible) |
|| currentCh == '-' |
|| currentCh == SpecialChars::SHYPHEN) |
&& (!outs) && !itemText.text(a-1).isSpace() ) |
if ((glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) |
|| itemText.text(a) == '-' |
|| itemText.text(a) == SpecialChars::SHYPHEN) |
&& (!outs) && !itemText.text(glyphRuns[i - 1].lastChar()).isSpace() ) |
{ |
breakPos = current.xPos; |
if (currentCh != '-') |
if (itemText.text(a) != '-') |
{ |
breakPos += hyphWidth; |
} |
2622,22 → 2584,22 |
if (legacy || (breakPos - rightHang < current.colRight - style.rightMargin())) |
{ |
if ((current.hyphenCount < m_Doc->hyphConsecutiveLines()) || (m_Doc->hyphConsecutiveLines() == 0) || currentCh == SpecialChars::SHYPHEN) |
if ((current.hyphenCount < m_Doc->hyphConsecutiveLines()) || (m_Doc->hyphConsecutiveLines() == 0) || itemText.text(a) == SpecialChars::SHYPHEN) |
{ |
current.rememberBreak(a, breakPos, style.rightMargin() + hyphWidth); |
current.rememberBreak(i, breakPos, style.rightMargin() + hyphWidth); |
} |
} |
} |
if ((currentCh == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1)) |
if ((itemText.text(a) == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1)) |
goNoRoom = true; |
if ((currentCh == SpecialChars::COLBREAK) && (Cols > 1)) |
if ((itemText.text(a) == SpecialChars::COLBREAK) && (Cols > 1)) |
goNextColumn = true; |
if (a != firstInFrame() && implicitBreak(itemText.text(a - 1), itemText.text(a))) |
current.rememberBreak(a - 1, breakPos); |
current.rememberBreak(i -1, breakPos); |
++current.itemsInLine; |
current.isEmpty = (i - current.line.firstRun + 1) == 0; |
if (tabs.active) |
{ |
2645,10 → 2607,10 |
if (tabs.status == TabCENTER) |
cen = 2; |
double newTabAdvance = itemText.getGlyphs(tabs.charIndex)->xadvance - (wide+kernVal) / cen; |
double newTabAdvance = tabs.tabGlyph->xadvance - wide / cen; |
if (newTabAdvance >= 0) { |
itemText.getGlyphs(tabs.charIndex)->xadvance = newTabAdvance; |
tabs.tabGlyph->xadvance = newTabAdvance; |
} |
else { |
tabs.active = false; |
2658,7 → 2620,7 |
if ((DropCmode || BulNumMode) && !outs) |
{ |
current.xPos += style.parEffectOffset(); |
glyphs->last()->xadvance += style.parEffectOffset(); |
lastGlyph.xadvance += style.parEffectOffset(); |
if (DropCmode) |
{ |
DropCmode = false; |
2678,10 → 2640,10 |
{ |
tabs.active = false; |
tabs.status = TabNONE; |
if (SpecialChars::isBreak(currentCh, Cols > 1)) |
if (SpecialChars::isBreak(itemText.text(a), Cols > 1)) |
{ |
// find end of line |
current.breakLine(itemText, style, firstLineOffset(), a); |
current.breakLine(style, firstLineOffset(), i); |
EndX = current.endOfLine(m_availableRegion, style.rightMargin(), regionMinY, regionMaxY); |
current.finishLine(EndX); |
//addLine = true; |
2688,7 → 2650,7 |
assert(current.addLine); |
//current.startOfCol = false; |
//addLeftIndent = true; |
if (currentCh == SpecialChars::PARSEP) |
if (itemText.text(a) == SpecialChars::PARSEP) |
{ |
maxDX = 0; |
if (current.hasDropCap) |
2702,7 → 2664,7 |
// if (style.alignment() != 0) |
{ |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.width += opticalRightMargin(itemText, current.line); |
current.line.width += opticalRightMargin(itemText, glyphRuns, current.line); |
OFs = 0; |
if (style.alignment() == ParagraphStyle::Rightaligned) |
2714,22 → 2676,22 |
if (style.alignment() == ParagraphStyle::Extended |
|| (style.alignment() == ParagraphStyle::Justified |
&& (currentCh == SpecialChars::LINEBREAK || |
currentCh == SpecialChars::FRAMEBREAK || |
currentCh == SpecialChars::COLBREAK) |
&& !itemText.text(current.line.lastItem - 1).isSpace())) |
&& (itemText.text(a) == SpecialChars::LINEBREAK || |
itemText.text(a) == SpecialChars::FRAMEBREAK || |
itemText.text(a) == SpecialChars::COLBREAK) |
&& !itemText.text(glyphRuns[current.line.lastRun - 1].lastChar()).isSpace())) |
{ |
justifyLine(itemText, current.line); |
justifyLine(style, current); |
} |
else |
{ |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.naturalWidth += opticalRightMargin(itemText, current.line); |
current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line); |
double optiWidth = current.colRight - style.rightMargin() - style.lineSpacing()/2.0 - current.line.x; |
if (current.line.naturalWidth > optiWidth) |
current.line.width = qMax(current.line.width - current.maxShrink, optiWidth); |
// simple offset |
indentLine(itemText, current.line, OFs); |
indentLine(style, current, OFs); |
} |
current.xPos = current.colRight; |
} |
2737,11 → 2699,14 |
else // outs -- last char went outside the columns (or into flow-around shape) |
{ |
if (current.breakIndex >= 0) |
a = current.breakIndex; |
assert( a >= 0 ); |
assert( a < itemText.length() ); |
glyphs = itemText.getGlyphs(a); |
current.itemsInLine = a - current.line.firstItem + 1; |
{ |
i = current.breakIndex; |
a = glyphRuns[i].firstChar(); |
} |
assert( i >= 0 ); |
assert( i < glyphRuns.length() ); |
//glyphs = itemText.getGlyphs(a); |
current.isEmpty = (i - current.line.firstRun + 1) == 0; |
if (current.addLine) |
{ |
// go back to last break position |
2752,11 → 2717,11 |
style.setLineSpacing(m_Doc->guidesPrefs().valueBaselineGrid); |
if (itemText.text(a) == ' ') { |
itemText.setFlag(a, ScLayout_SuppressSpace); |
glyphs->xadvance = 0; |
glyphRuns[i].setFlag(ScLayout_SuppressSpace); |
glyphRuns[i].glyphs()[0].xadvance = 0; |
} |
current.updateHeightMetrics(itemText); |
current.updateHeightMetrics(); |
//current.updateLineOffset(itemText, style, firstLineOffset()); |
//current.xPos = current.breakXPos; |
EndX = current.endOfLine(m_availableRegion, current.rightMargin, regionMinY, regionMaxY); |
2763,29 → 2728,33 |
current.finishLine(EndX); |
hyphWidth = 0.0; |
if (itemText.hasFlag(a, ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN) |
if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN) |
{ |
// insert hyphen |
if (current.lastInRowLine) |
//increase hyphen count only for hyphens a the end of text row, omit hyphens before overflow |
current.hyphenCount++; |
itemText.setFlag(a, ScLayout_SoftHyphenVisible); |
glyphs->grow(); |
glyphs->more->glyph = font.char2CMap(QChar('-')); |
glyphs->more->xadvance = font.charWidth('-', itemText.charStyle(a).fontSize() / 10.0) * scaleH; //FIX ME - hyphen is not rendered with proper width - check yhis with large glyphs horizontal scaling eg. 20% |
hyphWidth = glyphs->more->xadvance; |
glyphRuns[i].setFlag(ScLayout_SoftHyphenVisible); |
GlyphLayout hyphen; |
hyphen.glyph = font.char2CMap(QChar('-')); |
hyphen.xadvance = font.glyphBBox(hyphen.glyph, itemText.charStyle(a).fontSize() / 10.0).width; |
hyphWidth = hyphen.xadvance * scaleH; |
glyphRuns[i].glyphs().append(hyphen); |
} |
else |
{ |
if (itemText.text(a) != '-') |
current.hyphenCount = 0; |
itemText.clearFlag(a, ScLayout_SoftHyphenVisible); |
glyphs->shrink(); |
if (glyphRuns[i].hasFlag(ScLayout_SoftHyphenVisible)) |
{ |
glyphRuns[i].clearFlag(ScLayout_SoftHyphenVisible); |
glyphRuns[i].glyphs().removeLast(); |
} |
} |
// Justification |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.width += opticalRightMargin(itemText, current.line); |
current.line.width += opticalRightMargin(itemText, glyphRuns, current.line); |
// #12565: Right alignment of hyphens |
// The additional character width has already been taken into account |
// above via the line break position, so it's not necessary to increase |
2805,12 → 2774,12 |
OFs = (current.line.width - current.line.naturalWidth) / 2; |
if ((style.alignment() == ParagraphStyle::Justified) || (style.alignment() == ParagraphStyle::Extended)) |
justifyLine(itemText, current.line); |
justifyLine(style, current); |
else |
{ |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.naturalWidth += opticalRightMargin(itemText, current.line); |
indentLine(itemText, current.line, OFs); |
current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line); |
indentLine(style, current, OFs); |
} |
current.xPos = current.line.x + current.line.width; |
} |
2833,10 → 2802,10 |
if (current.isEndOfCol(desc)) |
{ |
//check if really line extends bottom margin |
current.updateHeightMetrics(itemText); |
current.updateHeightMetrics(); |
if (current.isEndOfCol(current.line.descent)) |
{ |
if (current.itemsInLine == 0 || current.column+1 == Cols) |
if (current.isEmpty || current.column+1 == Cols) |
{ |
goNoRoom = true; |
MaxChars = a + 1; |
2849,22 → 2818,23 |
} |
else |
setMaxY(maxYDesc); |
if (current.line.firstItem <= current.line.lastItem && current.itemsInLine > 0) |
if (current.line.firstRun <= current.line.lastRun && !current.isEmpty) |
{ |
if (current.addLine && current.breakIndex >= 0) |
{ |
if (itemText.charStyle(current.line.firstItem).effects() & ScLayout_DropCap) |
if (glyphRuns[current.line.firstRun].style().effects() & ScLayout_DropCap) |
{ |
// put line back to top |
current.line.y -= DropCapDrop; |
itemText.getGlyphs(current.line.firstItem)->yoffset += DropCapDrop; |
glyphRuns[current.line.firstRun].glyphs().first().yoffset += DropCapDrop; |
} |
fillInTabLeaders(itemText, current.line); |
fillInTabLeaders(current); |
//if right margin is set we temporally save line, not append it |
textLayout.appendLine(current.line); |
textLayout.appendLine(current.createLineBox()); |
setMaxY(maxYDesc); |
current.restartIndex = current.line.lastItem +1; |
a = current.restartIndex -1; |
current.restartIndex = current.line.lastRun + 1; |
i = current.line.lastRun; |
a = glyphRuns[i].firstChar(); |
current.rowDesc = qMax(current.rowDesc,current.yPos + current.line.descent); |
if (!current.lastInRowLine) |
{ |
2879,7 → 2849,7 |
else if (!inOverflow && !current.afterOverflow && current.lastInRowLine) |
{ |
current.yPos++; |
a = current.restartLine(true, true); |
i = current.restartLine(true, true); |
inOverflow = false; |
outs = false; |
current.mustLineEnd = current.colRight; |
2930,7 → 2900,8 |
outs = false; |
current.addLine = false; |
current.lastInRowLine = false; |
current.startLine(a+1); |
// WTF does i+1 mean here, what if i is the last run we have! |
current.startLine(i+1); |
if (goNoRoom) |
{ |
goNoRoom = false; |
2945,7 → 2916,7 |
{ |
if (firstLineOffset() == FLOPRealGlyphHeight) |
asce = 0; |
current.nextColumn(); |
current.nextColumn(textLayout); |
current.mustLineEnd = current.colRight; |
current.addLeftIndent = true; |
lastLineY = m_textDistanceMargins.top(); |
2961,23 → 2932,23 |
} |
} |
} |
if (a == itemText.length() -1) |
if (i == glyphRuns.length() - 1) |
{ |
if (!current.afterOverflow || current.addLine) |
{ |
current.addLine = true; |
current.lastInRowLine = true; |
current.breakLine(itemText, style, firstLineOffset(),a); |
current.breakLine(style, firstLineOffset(), i); |
} |
if (current.afterOverflow && !current.addLine) |
{ |
if (current.restartIndex < current.line.firstItem) |
if (current.restartIndex < current.line.firstRun) |
{ |
a = current.restartLine(false,true); |
i = current.restartLine(false,true); |
continue; |
} |
else |
current.breakLine(itemText, style, firstLineOffset(),a); |
current.breakLine(style, firstLineOffset(), i); |
} |
} |
} |
2988,10 → 2959,11 |
} |
// end of itemText |
// now place the last line |
if (current.itemsInLine > 0 ) |
if (!current.isEmpty) |
{ |
int a = itemText.length()-1; |
current.breakLine(itemText, style, firstLineOffset(), a); |
int i = glyphRuns.length() - 1; |
current.breakLine(style, firstLineOffset(), i); |
if (current.startOfCol) |
{ |
3029,7 → 3001,7 |
current.finishLine(EndX); |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.width += opticalRightMargin(itemText, current.line); |
current.line.width += opticalRightMargin(itemText, glyphRuns, current.line); |
OFs = 0; |
if (style.alignment() == ParagraphStyle::Rightaligned) |
3043,27 → 3015,27 |
&& (itemText.text(a) == SpecialChars::LINEBREAK || |
itemText.text(a) == SpecialChars::FRAMEBREAK || |
itemText.text(a) == SpecialChars::COLBREAK) |
&& !itemText.text(current.line.firstItem + current.itemsInLine-1).isSpace())) |
&& !itemText.text(a).isSpace())) |
{ |
justifyLine(itemText, current.line); |
justifyLine(style, current); |
} |
else |
{ |
if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) |
current.line.naturalWidth += opticalRightMargin(itemText, current.line); |
indentLine(itemText, current.line, OFs); |
current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line); |
indentLine(style, current, OFs); |
} |
if ( itemText.charStyle(current.line.firstItem).effects() & ScLayout_DropCap ) |
if (glyphRuns[current.line.firstRun].style().effects() & ScLayout_DropCap) |
{ |
// put line back to top |
current.line.y -= DropCapDrop; |
itemText.getGlyphs(current.line.firstItem)->yoffset += DropCapDrop; |
glyphRuns[current.line.firstRun].glyphs().first().yoffset += DropCapDrop; |
} |
fillInTabLeaders(itemText, current.line); |
fillInTabLeaders(current); |
current.startOfCol = false; |
goNextColumn = false; |
textLayout.appendLine(current.line); |
textLayout.appendLine(current.createLineBox()); |
setMaxY(maxYDesc); |
current.startOfCol = false; |
3077,20 → 3049,12 |
MaxChars = itemText.length(); |
if ((verticalAlign > 0) && (NextBox == NULL)) |
{ |
int vertAlign = verticalAlign; |
double topDist = m_textDistanceMargins.top(); |
double hAdjust = 0; |
if (verticalAlign == 1) |
hAdjust = (height() - (m_textDistanceMargins.bottom() + lineCorr) - maxY) / 2.0; |
else if (verticalAlign == 2) |
hAdjust = (height() - (m_textDistanceMargins.bottom() + lineCorr) - maxY); |
double hAdjust = height() - textLayout.box()->naturalHeight(); |
if (hAdjust > 0) |
{ |
m_textDistanceMargins.setTop(topDist + hAdjust); |
verticalAlign = 0; |
layout(); |
m_textDistanceMargins.setTop(topDist); |
verticalAlign = vertAlign; |
if (verticalAlign == 1) |
hAdjust /= 2; |
textLayout.box()->moveBy(0, hAdjust); |
} |
} |
invalid = false; |
3220,20 → 3184,6 |
if (m_Doc->RePos) |
return; |
QTransform pf2; |
QPoint pt1, pt2; |
double wide; |
QString cachedStroke = ""; |
QString cachedFill = ""; |
double cachedFillShade = -1; |
double cachedStrokeShade = -1; |
QString actStroke = ""; |
QString actFill = ""; |
double actFillShade = -1; |
double actStrokeShade = -1; |
QColor cachedFillQ; |
QColor cachedStrokeQ; |
// QValueList<ParagraphStyle::TabRecord> tTabValues; |
double desc, asce; |
// tTabValues.clear(); |
p->save(); //SA1 |
3696,326 → 3646,16 |
} |
assert( firstInFrame() >= 0 ); |
assert( lastInFrame() < itemText.length() ); |
LineSpec ls; |
uint llp = 0; |
while (llp < textLayout.lines()) |
{ |
ls = textLayout.line(llp++); |
const ParagraphStyle& LineStyle = itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
QColor tmp; |
SetQColor(&tmp, LineStyle.backgroundColor(), LineStyle.backgroundShade()); |
double y0 = ls.y; |
double y2 = ls.y; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < textLayout.lines()) |
{ |
ls = textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < textLayout.lines()) |
{ |
if ((textLayout.line(llp + 1).lastItem - textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + textLayout.line(llp + 1).ascent); |
llp++; |
} |
p->save(); |
p->setupPolygon(&PoLine); |
p->setClipPath(); |
p->setAntialiasing(false); |
p->setFillMode(1); |
p->setStrokeMode(0); |
p->setBrush(tmp); |
p->drawRect(lMarg + adjX, y0 - ascent, columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
p->setAntialiasing(true); |
p->restore(); |
} |
} |
for (uint ll=0; ll < textLayout.lines(); ++ll) |
{ |
ls = textLayout.line(ll); |
double CurX = ls.x; |
// Draw text selection rectangles |
QRectF selectedFrame; |
QList<QRectF> sFList; |
bool previousWasObject(false); |
double selX = ls.x; |
GlyphLayout* glyphs = 0; |
int last = qMin(ls.lastItem, itemText.length() - 1); |
for (int as = ls.firstItem; as <= last; ++as) |
{ |
bool selecteds = itemText.selected(as); |
glyphs = itemText.getGlyphs(as); |
bool HasObject = itemText.hasObject(as); |
Mark* mark = itemText.mark(as); |
if (mark != NULL && (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType))) |
continue; |
if (selecteds) |
{ |
const CharStyle& charStyleS(itemText.charStyle(as)); |
if (((as > ls.firstItem) && (charStyleS != itemText.charStyle(as-1))) |
|| ((!selectedFrame.isNull()) && HasObject) |
|| previousWasObject) |
{ |
sFList << selectedFrame; |
selectedFrame = QRectF(); |
previousWasObject = false; |
} |
if ((m_isSelected || (NextBox != 0 || BackBox != 0)) |
&& (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable)) |
{ |
double xcoZli = selX + glyphs->xoffset; |
// ugly hack to make selection correct, as xoffset is used to |
// remove left-half of CJK lparen , which is blank. |
if (glyphs->xoffset) |
{ |
int attr = SpecialChars::getCJKAttr(itemText.text(as)) & SpecialChars::CJK_CHAR_MASK; |
if (attr == SpecialChars::CJK_FENCE_BEGIN) |
{ |
xcoZli -= glyphs->xoffset; |
} |
} |
const ScFace font = charStyleS.font(); |
double fontSize = charStyleS.fontSize() / 10.0; |
desc = - font.descent(fontSize); |
asce = font.ascent(fontSize); |
wide = glyphs->wide(); |
QRectF scr; |
if (HasObject) |
{ |
PageItem* obj = itemText.object(as); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scr = QRectF(xcoZli, ls.y - hh, ww , hh); |
previousWasObject = true; |
} |
else |
scr = QRectF(xcoZli, ls.y + glyphs->yoffset - asce * glyphs->scaleV, wide , (asce+desc) * (glyphs->scaleV)); |
selectedFrame |= scr; |
} |
} |
// Unneeded now that glyph xadvance is set appropriately for inline objects by layout() - JG |
/*if ((hls->ch == SpecialChars::OBJECT) && (hls->embedded.hasItem())) |
selX += (hls->embedded.getItem()->gWidth + hls->embedded.getItem()->lineWidth()) * hls->glyph.scaleH; |
else*/ |
selX += glyphs->wide(); |
} |
if (!selectedFrame.isNull()) |
sFList << selectedFrame; |
p->save();//SA3 |
p->setFillMode(1); |
p->setBrush(qApp->palette().color(QPalette::Active, QPalette::Highlight)); |
p->setLineWidth(0); |
// TODO - I dunno why but scpainter does not accept |
// to actually set the pen to 0? As a wa, |
// we set its color same as brush: "Ã malin, malin et demi!". |
p->setPen(qApp->palette().color(QPalette::Active, QPalette::Highlight)); |
for(int sfc(0);sfc < sFList.count();++sfc) |
p->drawRect(sFList[sfc].x(), sFList[sfc].y(), sFList[sfc].width(), sFList[sfc].height()); |
p->restore();//RE3 |
// End of selection |
QColor tmp; |
double CurXB = ls.x; |
QRectF scrG; |
QString oldBack; |
double oldShade = 100; |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
glyphs = itemText.getGlyphs(a); |
const CharStyle& charStyle(itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
SetQColor(&tmp, charStyle.backColor(), charStyle.backShade()); |
const ParagraphStyle& LineStyle = itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = doc()->guidesPrefs().valueBaselineGrid; |
else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = LineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (LineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= LineStyle.dropCapLines(); |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= LineStyle.lineSpacing(); |
else if (firstLineOffset() == FLOPRealGlyphHeight || firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= LineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scr; |
if (itemText.hasObject(a)) |
{ |
PageItem* obj = itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scr = QRectF(CurXB, ls.y - hh, ww , hh); |
} |
else |
scr = QRectF(CurXB, y1, glyphs->wide(), hl); |
if ((oldBack.isEmpty()) || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scrG |= scr; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
p->save(); |
p->setFillMode(1); |
p->setStrokeMode(0); |
SetQColor(&tmp, oldBack, oldShade); |
p->setBrush(tmp); |
p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
p->restore(); |
scrG = scr; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
} |
else |
{ |
oldBack.clear(); |
oldShade = 100; |
if (!scrG.isNull()) |
{ |
p->save(); |
p->setFillMode(1); |
p->setStrokeMode(0); |
p->setBrush(tmp); |
p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
p->restore(); |
} |
scrG = QRectF(); |
} |
CurXB += glyphs->wide(); |
} |
if (!scrG.isNull()) |
{ |
p->save(); |
p->setFillMode(1); |
p->setStrokeMode(0); |
p->setBrush(tmp); |
p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
p->restore(); |
} |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
glyphs = itemText.getGlyphs(a); |
const CharStyle& charStyle(itemText.charStyle(a)); |
bool selected = itemText.selected(a); |
actFill = charStyle.fillColor(); |
actFillShade = charStyle.fillShade(); |
if (actFill != CommonStrings::None) |
{ |
p->setFillMode(ScPainter::Solid); |
if ((cachedFillShade != actFillShade) || (cachedFill != actFill)) |
{ |
SetQColor(&tmp, actFill, actFillShade); |
p->setBrush(tmp); |
cachedFillQ = tmp; |
cachedFill = actFill; |
cachedFillShade = actFillShade; |
} |
else |
p->setBrush(cachedFillQ); |
} |
else |
p->setFillMode(ScPainter::None); |
const ScFace font = charStyle.font(); |
double fontSize = charStyle.fontSize() / 10.0; |
desc = - font.descent(fontSize); |
asce = font.ascent(fontSize); |
if (((selected && m_isSelected) || ((NextBox != 0 || BackBox != 0) && selected)) && (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable)) |
{ |
// set text color to highlight if its selected |
p->setBrush(qApp->palette().color(QPalette::Active, QPalette::HighlightedText)); |
} |
actStroke = charStyle.strokeColor(); |
actStrokeShade = charStyle.strokeShade(); |
if (actStroke != CommonStrings::None) |
{ |
if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke)) |
{ |
SetQColor(&tmp, actStroke, actStrokeShade); |
p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
cachedStrokeQ = tmp; |
cachedStroke = actStroke; |
cachedStrokeShade = actStrokeShade; |
} |
else |
p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
// paint glyphs |
QRectF scrGl; |
if (itemText.hasObject(a)) |
{ |
PageItem* obj = itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scrGl = QRectF(CurX, ls.y + glyphs->yoffset, ww , -hh).normalized(); |
previousWasObject = true; |
} |
else |
scrGl = QRectF(CurX + glyphs->xoffset, ls.y + glyphs->yoffset - asce * glyphs->scaleV, glyphs->xadvance+1 , (asce+desc) * (glyphs->scaleV)); |
if (isEmbedded || cullingArea.intersects(pf2.mapRect(scrGl))) |
{ |
p->save();//SA4 |
p->translate(CurX, ls.y); |
if (itemText.hasObject(a)) |
DrawObj_Embedded(p, cullingArea, charStyle, itemText.object(a)); |
else |
{ |
//control chars for marks |
if (m_Doc->guidesPrefs().showControls && itemText.hasMark(a) && (glyphs->glyph != SpecialChars::OBJECT)) |
{ |
GlyphLayout markGlyph; |
layoutGlyphs(charStyle, SpecialChars::OBJECT, ScLayout_None, markGlyph); |
drawGlyphs(p, charStyle, ScLayout_None, markGlyph); |
} |
drawGlyphs(p, charStyle, itemText.flags(a), *glyphs); |
} |
p->restore();//RE4 |
} |
// Unneeded now that glyph xadvance is set appropriately for inline objects by layout() - JG |
/*if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem())) |
CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH; |
else*/ |
CurX += glyphs->wide(); |
} |
} |
// else { |
// // qDebug("skipping textframe: len=%d", itemText.count()); |
// } |
// pf2.end(); |
int fm = p->fillMode(); |
int sm = p->strokeMode(); |
p->setFillMode(1); |
p->setStrokeMode(1); |
ScreenPainter painter(p, this); |
textLayout.renderBackground(&painter); |
textLayout.render(&painter, this); |
p->setFillMode(fm); |
p->setStrokeMode(sm); |
} |
m_textDistanceMargins=savedTextDistanceMargins; |
p->restore();//RE1 |
4489,7 → 4129,7 |
ExpandSel(1, oldPos); |
} |
else |
if ((textLayout.lines() > 0) && (oldPos >= textLayout.line(textLayout.lines()-1).firstItem) && (itemText.cursorPosition() >= lastInFrame()) && (NextBox != 0)) |
if ((textLayout.lines() > 0) && (oldPos >= textLayout.line(textLayout.lines()-1)->firstChar()) && (itemText.cursorPosition() >= lastInFrame()) && (NextBox != 0)) |
{ |
if (NextBox->frameDisplays(itemText.cursorPosition())) |
{ |
4540,7 → 4180,7 |
ExpandSel(-1, oldPos); |
} |
else |
if ((textLayout.lines() > 0) && (oldPos <= textLayout.line(0).lastItem) && (itemText.cursorPosition() == firstInFrame()) && (BackBox != 0)) |
if ((textLayout.lines() > 0) && (oldPos <= textLayout.line(0)->lastChar()) && (itemText.cursorPosition() == firstInFrame()) && (BackBox != 0)) |
{ |
view->Deselect(true); |
// TODO position at the right place in previous frame |
6254,59 → 5894,34 |
void PageItem_TextFrame::setTextFrameHeight() |
{ |
//ugly hack increasing min frame`s haeight against strange glyph painting if it is too close of bottom |
double hackValue = 0.5; |
if (textLayout.lines() <= 0) |
return; |
const LineSpec& firstLine = textLayout.line(0); |
const LineSpec& lastLine = textLayout.line(textLayout.lines() -1); |
double y1 = firstLine.y /*- firstLine.ascent*/; |
double y2 = lastLine.y + lastLine.descent; |
const ParagraphStyle& firstLineStyle = itemText.paragraphStyle(firstLine.firstItem); |
if (firstLineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= firstLineStyle.lineSpacing(); |
else if (firstLineOffset() == FLOPRealGlyphHeight || firstLineOffset() == FLOPFontAscent) |
y1 -= firstLine.ascent; |
else |
y1 -= firstLineStyle.lineSpacing(); |
double newHeight = ceil(y2) + m_textDistanceMargins.bottom() + hackValue; |
if (NextBox == 0) // Vertical alignment is not used inside a text chain |
{ |
if (verticalAlign == 1) |
newHeight -= floor(y1); |
else if (verticalAlign == 2) |
newHeight = m_height - floor(y1); |
} |
textLayout.box()->moveTo(textLayout.box()->x(), 0); |
double newHeight = textLayout.box()->naturalHeight(); |
UndoTransaction undoTransaction; |
if (UndoManager::undoEnabled() && (verticalAlign != 0)) |
{ |
QString unitSuffix = unitGetStrFromIndex(m_Doc->unitIndex()); |
int unitPrecision = unitGetPrecisionFromIndex(m_Doc->unitIndex()); |
double unitRatio = m_Doc->unitRatio(); |
QString owString = QString::number(oldWidth * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString ohString = QString::number(oldHeight * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString nwString = QString::number(m_width * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString nhString = QString::number(m_height * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString tooltip = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString); |
undoTransaction = undoManager->beginTransaction(Um::Selection, Um::ITextFrame, Um::Resize, tooltip, Um::IResize); |
} |
UndoTransaction undoTransaction; |
if (UndoManager::undoEnabled()) |
{ |
QString unitSuffix = unitGetStrFromIndex(m_Doc->unitIndex()); |
int unitPrecision = unitGetPrecisionFromIndex(m_Doc->unitIndex()); |
double unitRatio = m_Doc->unitRatio(); |
QString owString = QString::number(oldWidth * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString ohString = QString::number(oldHeight * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString nwString = QString::number(m_width * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString nhString = QString::number(m_height * unitRatio, 'f', unitPrecision) + " " + unitSuffix; |
QString tooltip = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString); |
undoTransaction = undoManager->beginTransaction(Um::Selection, Um::ITextFrame, Um::Resize, tooltip, Um::IResize); |
} |
if (verticalAlign != 0) |
{ |
double newX = m_xPos + floor(y1) * cos(-m_rotation * M_PI / 180 - M_PI / 2); |
double newY = m_yPos - floor(y1) * sin(-m_rotation * M_PI / 180 - M_PI / 2); |
setXYPos(newX, newY); |
setHeight(newHeight); |
if (undoTransaction) |
undoTransaction.commit(); |
} |
setHeight(newHeight); |
if (undoTransaction) |
undoTransaction.commit(); |
updateClip(); |
invalid = true; |
m_Doc->changed(); |
/trunk/Scribus/scribus/pageitem_textframe.h |
---|
159,6 → 159,9 |
public: |
void setTextFrameHeight(); |
private: |
QList<GlyphRun> shapeText(); |
}; |
#endif |
/trunk/Scribus/scribus/pdflib_core.cpp |
---|
71,6 → 71,7 |
#include "sccolor.h" |
#include "sccolorengine.h" |
#include "scfonts.h" |
#include "text/textlayoutpainter.h" |
#include "fonts/cff.h" |
#include "fonts/sfnt.h" |
#include "scpage.h" |
87,6 → 88,7 |
#include "util_formats.h" |
#include "util_math.h" |
#include "util_ghostscript.h" |
#include "text/boxes.h" |
#ifdef HAVE_OSG |
#include "third_party/prc/exportPRC.h" |
103,7 → 105,377 |
#undef GetObject |
#endif |
static inline QByteArray FToStr(double c) |
{ |
double v = c; |
if (fabs(c) < 0.0000001) |
v = 0.0; |
return QByteArray::number(v, 'f', 5); |
} |
class PdfPainter: public TextLayoutPainter |
{ |
QByteArray m_glyphBuffer; |
QByteArray m_pathBuffer; |
PageItem* m_item; |
QMap<QString, PdfFont> m_UsedFontsP; |
PDFLibCore *m_pdf; |
uint m_PNr; |
const ScPage* m_page; |
QByteArray transformToStr(QTransform tr) |
{ |
return FToStr(tr.m11()) + " " + FToStr(-tr.m12()) + " " + FToStr(-tr.m21()) + " " + FToStr(tr.m22()) + " " + FToStr(tr.dx()) + " " + FToStr(-tr.dy()); |
} |
public: |
PdfPainter(PageItem *ite, PDFLibCore *pdf, uint num, const ScPage* pag) : |
m_glyphBuffer(), |
m_pathBuffer(), |
m_item(ite), |
m_pdf(pdf), |
m_PNr(num), |
m_page(pag) |
{} |
~PdfPainter() {} |
void drawGlyph(const GlyphLayout gl) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
PdfFont pdfFont = m_pdf->UsedFontsP[font().replacementName()]; |
QByteArray StrokeColor; |
QByteArray FillColor; |
QTransform transform = matrix(); |
if (strokeColor().color != CommonStrings::None) |
StrokeColor = m_pdf->putColor(strokeColor().color, strokeColor().shade, false); |
if (fillColor().color != CommonStrings::None) |
FillColor = m_pdf->putColor(fillColor().color, fillColor().shade, true); |
if (pdfFont.method == Use_XForm) |
{ |
if (!FillColor.isEmpty()) |
m_pathBuffer += FillColor; |
m_pathBuffer += "q\n"; |
m_glyphBuffer += FToStr(fontSize()) + " 0 0 " + FToStr(fontSize()) + " " + FToStr(x()) + " " + FToStr(y()) + " cm\n"; |
if (gl.scaleV != 1.0) |
m_pathBuffer += "1 0 0 1 0 " + FToStr(((fontSize() - fontSize() * gl.scaleV) / fontSize()) * -1) + " cm\n"; |
transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1)); |
m_glyphBuffer += transformToStr(transform) + " cm\n"; |
if (!FillColor.isEmpty()) |
m_pathBuffer += pdfFont.name + Pdf::toPdf(gl.glyph) + " Do\n"; |
m_pathBuffer += "Q\n"; |
} |
else |
{ |
uint gid = gl.glyph; |
uint fontNr = 65535; |
switch (pdfFont.encoding) |
{ |
case Encode_256: |
gid = pdfFont.glyphmap[gid]; |
fontNr = gid / 256; |
gid = gid % 256; |
break; |
case Encode_224: |
fontNr = gid / 224; |
gid = gid % 224 + 32; |
break; |
case Encode_Subset: |
gid = pdfFont.glyphmap[gid]; |
break; |
case Encode_IdentityH: |
break; |
} |
if (fontNr == 65535) |
m_glyphBuffer += pdfFont.name + " " + FToStr(fontSize()) + " Tf\n"; |
else |
m_glyphBuffer += pdfFont.name + "S" + Pdf::toPdf(fontNr) + " " + FToStr(fontSize()) + " Tf\n"; |
if (!StrokeColor.isEmpty()) |
m_glyphBuffer += StrokeColor; |
if (!FillColor.isEmpty()) |
m_glyphBuffer += FillColor; |
m_glyphBuffer += "0 Tr\n"; |
transform.translate(x(), y()); |
transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1)); |
m_glyphBuffer += transformToStr(transform) + " Tm\n"; |
if (pdfFont.method != Use_Type3 || !FillColor.isEmpty()) |
{ |
switch (pdfFont.encoding) |
{ |
case Encode_224: |
case Encode_256: |
m_glyphBuffer += Pdf::toHexString8(gid) + " Tj\n"; |
break; |
case Encode_IdentityH: |
default: |
m_glyphBuffer += Pdf::toHexString16(gid) + " Tj\n"; |
break; |
} |
} |
} |
} |
void drawGlyphOutline(const GlyphLayout gl, bool fill) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
PdfFont pdfFont = m_pdf->UsedFontsP[font().replacementName()]; |
QByteArray StrokeColor; |
QByteArray FillColor; |
QTransform transform = matrix(); |
if (strokeColor().color != CommonStrings::None) |
StrokeColor = m_pdf->putColor(strokeColor().color, strokeColor().shade, false); |
if (fill && fillColor().color != CommonStrings::None) |
FillColor = m_pdf->putColor(fillColor().color, fillColor().shade, true); |
if (pdfFont.method == Use_XForm) |
{ |
if (!StrokeColor.isEmpty()) |
{ |
m_pathBuffer += FToStr(strokeWidth()) + " w\n[] 0 d\n0 J\n0 j\n"; |
m_pathBuffer += StrokeColor; |
} |
if (!FillColor.isEmpty()) |
m_pathBuffer += FillColor; |
m_pathBuffer += "q\n"; |
m_glyphBuffer += FToStr(fontSize()) + " 0 0 " + FToStr(fontSize()) + " " + FToStr(x()) + " " + FToStr(y()) + " cm\n"; |
if (gl.scaleV != 1.0) |
m_pathBuffer += "1 0 0 1 0 " + FToStr(((fontSize() - fontSize() * (gl.scaleV)) / fontSize()) * -1) + " cm\n"; |
transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1)); |
m_pathBuffer += transformToStr(transform) + " cm\n"; |
if (!FillColor.isEmpty()) |
m_pathBuffer += pdfFont.name + Pdf::toPdf(gl.glyph) + " Do\n"; |
FPointArray outline = font().glyphOutline(gl.glyph); |
QTransform mat; |
mat.scale(0.1, 0.1); |
outline.map(mat); |
bool nPath = true; |
FPoint np; |
if (outline.size() > 3) |
{ |
for (int poi = 0; poi < outline.size() - 3; poi += 4) |
{ |
if (outline.isMarker(poi)) |
{ |
m_pathBuffer += "h\n"; |
nPath = true; |
continue; |
} |
if (nPath) |
{ |
np = outline.point(poi); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " m\n"; |
nPath = false; |
} |
np = outline.point(poi + 1); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " "; |
np = outline.point(poi + 3); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " "; |
np = outline.point(poi + 2); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " c\n"; |
} |
} |
m_pathBuffer += "h s\n"; |
m_pathBuffer += "Q\n"; |
} |
else |
{ |
if (!StrokeColor.isEmpty()) |
m_pathBuffer += StrokeColor; |
uint gid = gl.glyph; |
uint fontNr = 65535; |
switch (pdfFont.encoding) |
{ |
case Encode_256: |
gid = pdfFont.glyphmap[gid]; |
fontNr = gid / 256; |
gid = gid % 256; |
break; |
case Encode_224: |
fontNr = gid / 224; |
gid = gid % 224 + 32; |
break; |
case Encode_Subset: |
gid = pdfFont.glyphmap[gid]; |
break; |
case Encode_IdentityH: |
break; |
} |
if (fontNr == 65535) |
m_glyphBuffer += pdfFont.name + " " + FToStr(fontSize()) + " Tf\n"; |
else |
m_glyphBuffer += pdfFont.name + "S" + Pdf::toPdf(fontNr) + " " + FToStr(fontSize()) + " Tf\n"; |
if (!StrokeColor.isEmpty()) |
m_glyphBuffer += StrokeColor; |
if (!FillColor.isEmpty()) |
m_glyphBuffer += FillColor; |
if (pdfFont.method == Use_Type3 && !StrokeColor.isEmpty()) |
{ |
m_pathBuffer += "q\n"; |
m_pathBuffer += FToStr(strokeWidth()) + " w\n[] 0 d\n0 J\n0 j\n"; |
transform.scale(fontSize(), fontSize()); |
transform.translate(x(), y()); |
if (gl.scaleV != 1.0) |
transform.translate(0, ((fontSize() - fontSize() * gl.scaleV) / fontSize()) * -1); |
transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1)); |
m_pathBuffer += transformToStr(transform) + " cm\n"; |
/* paint outline */ |
FPointArray outline = font().glyphOutline(gl.glyph); |
QTransform mat; |
mat.scale(0.1, 0.1); |
outline.map(mat); |
bool nPath = true; |
FPoint np; |
if (outline.size() > 3) |
{ |
for (int poi = 0; poi < outline.size() - 3; poi += 4) |
{ |
if (outline.isMarker(poi)) |
{ |
m_pathBuffer += "h\n"; |
nPath = true; |
continue; |
} |
if (nPath) |
{ |
np = outline.point(poi); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " m\n"; |
nPath = false; |
} |
np = outline.point(poi + 1); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " "; |
np = outline.point(poi + 3); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " "; |
np = outline.point(poi + 2); |
m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " c\n"; |
} |
} |
m_pathBuffer += "h s\n"; |
m_pathBuffer += "Q\n"; |
} |
else |
{ |
m_glyphBuffer += FToStr(strokeWidth()) + " w "; |
if (fill) |
m_glyphBuffer += "2 Tr\n"; |
else |
m_glyphBuffer += "1 Tr\n"; |
} |
transform.translate(x(), y()); |
transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1)); |
m_glyphBuffer += transformToStr(transform) + " Tm\n"; |
if (pdfFont.method != Use_Type3 || !FillColor.isEmpty()) |
{ |
switch (pdfFont.encoding) |
{ |
case Encode_224: |
case Encode_256: |
m_glyphBuffer += Pdf::toHexString8(gid) + " Tj\n"; |
break; |
case Encode_IdentityH: |
default: |
m_glyphBuffer += Pdf::toHexString16(gid) + " Tj\n"; |
break; |
} |
} |
} |
} |
void drawLine(QPointF start, QPointF end) |
{ |
QTransform transform = matrix(); |
transform.translate(x(), y()); |
m_pathBuffer += "q\n"; |
m_pathBuffer += transformToStr(transform) + " cm\n"; |
m_pathBuffer += m_pdf->putColor(strokeColor().color, strokeColor().shade, false); |
m_pathBuffer += FToStr(strokeWidth())+" w\n"; |
m_pathBuffer += FToStr(start.x()) + " " + FToStr(-start.y()) + " m\n"; |
m_pathBuffer += FToStr(end.x()) + " " + FToStr(-end.y()) + " l\n"; |
m_pathBuffer += "S\n"; |
m_pathBuffer += "Q\n"; |
} |
QByteArray getBuffer() |
{ |
return "BT\n" + m_glyphBuffer + "ET\n" + m_pathBuffer; |
} |
void drawRect(QRectF rect) |
{ |
QTransform transform = matrix(); |
// transform.translate(x(), y()); |
double rectX = x() + rect.x(); |
double rectY = -y() - rect.y(); |
m_glyphBuffer += "q\n"; |
m_glyphBuffer += transformToStr(transform) + " cm\n"; |
m_glyphBuffer += "n\n"; |
m_glyphBuffer += m_pdf->putColor(fillColor().color, fillColor().shade, true); |
m_glyphBuffer += m_pdf->putColor(strokeColor().color, strokeColor().shade, false); |
m_glyphBuffer += FToStr(rectX) + " " + FToStr(rectY) + " m\n"; |
m_glyphBuffer += FToStr(rectX + rect.width()) + " " + FToStr(rectY) + " l\n"; |
m_glyphBuffer += FToStr(rectX + rect.width()) + " " + FToStr(rectY - rect.height()) + " l\n"; |
m_glyphBuffer += FToStr(rectX) + " " + FToStr(rectY - rect.height()) + " l\n"; |
m_glyphBuffer += "h\nf\n"; |
m_glyphBuffer += "Q\n"; |
} |
void drawObject(PageItem* embedded) |
{ |
m_glyphBuffer += "ET\n"+m_pathBuffer; |
m_pathBuffer = ""; |
m_pathBuffer += "q\n"; |
m_pathBuffer += FToStr(scaleH()) + " 0 0 " + FToStr(scaleV()) + " " + FToStr(x()) + " " + FToStr(-y()) + " cm\n"; |
QByteArray output; |
if (!m_pdf->PDF_ProcessItem(output, embedded, m_page, m_PNr, true)) |
return; |
m_pathBuffer += output; |
m_pathBuffer += "Q\n"; |
m_glyphBuffer += m_pathBuffer+"\n"; |
m_pathBuffer = ""; |
m_glyphBuffer += "BT\n"; |
} |
}; |
PDFLibCore::PDFLibCore(ScribusDoc & docu) |
: QObject(&docu), |
doc(docu), |
170,13 → 542,6 |
delete progressDialog; |
} |
static inline QByteArray FToStr(double c) |
{ |
double v = c; |
if (fabs(c) < 0.0000001) |
v = 0.0; |
return QByteArray::number(v, 'f', 5); |
}; |
bool PDFLibCore::PDF_IsPDFX() |
{ |
5380,855 → 5745,12 |
// Return a PDF substring representing a PageItem's text |
QByteArray PDFLibCore::setTextSt(PageItem *ite, uint PNr, const ScPage* pag) |
{ |
int tabCc = 0; |
int savedOwnPage = ite->OwnPage; |
double tabDist = ite->textToFrameDistLeft(); |
QByteArray tmp(""), tmp2(""); |
QList<ParagraphStyle::TabRecord> tTabValues; |
ite->OwnPage = PNr; |
ite->layout(); |
ite->OwnPage = savedOwnPage; |
if (ite->lineColor() != CommonStrings::None) |
tabDist += ite->lineWidth() / 2.0; |
// Loop over each character (!) in the pageItem... |
if (ite->itemType() == PageItem::TextFrame) |
{ |
PathData straightPath; |
straightPath.PtransX = 0; |
straightPath.PtransY = 0; |
straightPath.PRot = 0; |
straightPath.PDx = 0; |
tmp += "BT\n"; |
uint llp = 0; |
while (llp < ite->textLayout.lines()) |
{ |
LineSpec ls = ite->textLayout.line(llp++); |
const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
double y0 = ls.y; |
double y2 = ls.y; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < ite->textLayout.lines()) |
{ |
ls = ite->textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (ite->itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (ite->itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < ite->textLayout.lines()) |
{ |
if ((ite->textLayout.line(llp + 1).lastItem - ite->textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < ite->textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent); |
llp++; |
} |
QRectF scr(lMarg + adjX, y0 - ascent, ite->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
tmp += "q\n"; |
tmp += "n\n"; |
tmp += SetPathAndClip(ite); |
tmp += putColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), true); |
tmp += FToStr(scr.x()) +" "+FToStr(-scr.y())+" m\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += "h\nf\n"; |
tmp += "Q\n"; |
} |
} |
for (uint ll=0; ll < ite->textLayout.lines(); ++ll) |
{ |
LineSpec ls = ite->textLayout.line(ll); |
tabDist = ls.x; |
double CurX = ls.x; |
double CurXB = ls.x; |
int last = qMin(ls.lastItem, ite->itemText.length() - 1); |
QRectF scr; |
QString oldBack = ""; |
double oldShade = 100; |
QByteArray colorB = ""; |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
const GlyphLayout* glyphs(ite->itemText.getGlyphs(a)); |
const CharStyle& charStyle(ite->itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
colorB = putColor(charStyle.backColor(), charStyle.backShade(), true); |
// This code is for rendering character background color. |
const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = doc.guidesPrefs().valueBaselineGrid; |
else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = LineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (ite->textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (LineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= LineStyle.dropCapLines(); |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= LineStyle.lineSpacing(); |
else if (ite->firstLineOffset() == FLOPRealGlyphHeight || ite->firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= LineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scrG; |
if (ite->itemText.hasObject(a)) |
{ |
PageItem* obj = ite->itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scrG = QRectF(CurXB, ls.y - hh, ww , hh); |
} |
else |
scrG = QRectF(CurXB, y1, glyphs->wide(), hl); |
if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scr |= scrG; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
tmp += "q\n"; |
tmp += "n\n"; |
tmp += putColor(oldBack, oldShade, true); |
tmp += FToStr(scr.x()) +" "+FToStr(-scr.y())+" m\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += "h\nf\n"; |
tmp += "Q\n"; |
scr = scrG; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
} |
else |
{ |
if (!scr.isNull()) |
{ |
tmp += "q\n"; |
tmp += colorB; |
tmp += FToStr(scr.x()) +" "+FToStr(-scr.y())+" m\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += "h\nf\n"; |
tmp += "Q\n"; |
} |
oldBack = ""; |
oldShade = 100; |
scr = QRectF(); |
} |
CurXB += glyphs->wide(); |
} |
if (!scr.isNull()) |
{ |
tmp += "q\n"; |
tmp += colorB; |
tmp += FToStr(scr.x()) +" "+FToStr(-scr.y())+" m\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n"; |
tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n"; |
tmp += "h\nf\n"; |
tmp += "Q\n"; |
} |
for (int d = ls.firstItem; d <= ls.lastItem; ++d) |
{ |
GlyphLayout* glyphs = ite->itemText.getGlyphs(d); |
PathData* pdata = &straightPath; |
const QChar ch = ite->itemText.text(d); |
const CharStyle& chstyle(ite->itemText.charStyle(d)); |
const ParagraphStyle& pstyle(ite->itemText.paragraphStyle(d)); |
if (SpecialChars::isBreak(ch, true) || (ch == QChar(10))) |
continue; |
if (ite->itemText.hasFlag(d, ScLayout_SuppressSpace)) |
continue; |
tTabValues = pstyle.tabValues(); |
if (ite->itemText.hasFlag(d, ScLayout_StartOfLine)) |
tabCc = 0; |
if ((ch == SpecialChars::TAB) && (tTabValues.count() != 0)) |
{ |
QChar tabFillChar; |
const TabLayout* tabLayout = dynamic_cast<const TabLayout*>(glyphs->more); |
if (tabLayout) |
tabFillChar = tabLayout->fillChar; |
if (!tabFillChar.isNull()) |
{ |
GlyphLayout gl2; |
CharStyle cl2(chstyle); |
const GlyphLayout * const gl = glyphs->more; |
double scale = gl ? gl->scaleV : 1.0; |
double wt = chstyle.font().charWidth(tabFillChar, chstyle.fontSize() * scale / 10.0); |
double len = glyphs->xadvance; |
int coun = static_cast<int>(len / wt); |
// #6728 : update code according to fillInTabLeaders() and PageItem::layout() - JG |
double sPos = 0.0 /*CurX - len + chstyle.fontSize() / 10.0 * 0.7 + 1*/; |
//hl2.ch = tTabValues[tabCc].tabFillChar; |
cl2.setTracking(0); |
cl2.setScaleH(1000); |
cl2.setScaleV(1000); |
gl2.glyph = chstyle.font().char2CMap(tabFillChar); |
gl2.yoffset = glyphs->yoffset; |
for (int cx = 0; cx < coun; ++cx) |
{ |
gl2.xoffset = sPos + wt * cx; |
if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None)) |
{ |
GlyphLayout gl3; |
CharStyle cl3(cl2); |
//<< HACK to fix Bug #8446 |
cl3.setEffects(cl3.effects() & (~(ScStyle_Outline))); |
//>> |
gl3.glyph = gl2.glyph; |
cl3.setFillColor(cl2.strokeColor()); |
cl3.setFillShade(cl2.strokeShade()); |
gl3.yoffset = gl2.yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0); |
gl3.xoffset = gl2.xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0); |
setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl3, &gl3, pdata, pstyle, pag); |
} |
setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag); |
} |
} |
tabCc++; |
} |
if (ch == SpecialChars::TAB) |
{ |
CurX += glyphs->wide(); |
continue; |
} |
if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None)) |
{ |
GlyphLayout gl2(*glyphs); |
gl2.glyph = glyphs->glyph; |
const GlyphLayout *gl1 = glyphs; |
GlyphLayout* glx = &gl2; |
while (gl1->more) |
{ |
glx->more = new GlyphLayout(*gl1->more); |
glx->more->yoffset -= (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0); |
glx->more->xoffset += (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0); |
glx->more->more = NULL; |
gl1 = gl1->more; |
glx = glx->more; |
} |
CharStyle cl2(chstyle); |
//<< HACK to fix Bug #8446 |
cl2.setEffects(cl2.effects() & (~(ScStyle_Outline))); |
//>> |
cl2.setFillColor(chstyle.strokeColor()); |
cl2.setFillShade(chstyle.strokeShade()); |
gl2.xadvance = glyphs->xadvance; |
gl2.yadvance = glyphs->yadvance; |
gl2.yoffset = glyphs->yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0); |
gl2.xoffset = glyphs->xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0); |
gl2.scaleH = glyphs->scaleH; |
gl2.scaleV = glyphs->scaleV; |
setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag); |
gl2.shrink(); |
} |
setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, chstyle, glyphs, pdata, pstyle, pag); |
// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG |
/*if (hl->ch == SpecialChars::OBJECT) |
{ |
InlineFrame& embedded(const_cast<InlineFrame&>(hl->embedded)); |
CurX += (embedded.getItem()->gWidth + embedded.getItem()->lineWidth()) * hl->glyph.scaleH; |
} |
else*/ |
CurX += glyphs->wide(); |
tabDist = CurX; |
} |
} |
} |
else |
{ |
ite->OwnPage = PNr; |
ite->asPathText()->layout(); |
ite->OwnPage = savedOwnPage; |
double CurX = 0; |
for (int d = 0; d < ite->maxCharsInFrame(); ++d) |
{ |
GlyphLayout* glyphs = ite->asPathText()->itemRenderText.getGlyphs(d); |
PathData* pdata = &ite->textLayout.point(d); |
const QChar ch = ite->asPathText()->itemRenderText.text(d); |
const CharStyle& chstyle(ite->asPathText()->itemRenderText.charStyle(d)); |
const ParagraphStyle& pstyle(ite->asPathText()->itemRenderText.paragraphStyle(d)); |
if (SpecialChars::isBreak(ch, true) || (ch == QChar(10))) |
continue; |
if (ite->asPathText()->itemRenderText.hasFlag(d, ScLayout_SuppressSpace)) |
continue; |
tTabValues = pstyle.tabValues(); |
if (ite->asPathText()->itemRenderText.hasFlag(d, ScLayout_StartOfLine)) |
tabCc = 0; |
if ((ch == SpecialChars::TAB) && (tTabValues.count() != 0)) |
{ |
if ((tabCc < tTabValues.count()) && (!tTabValues[tabCc].tabFillChar.isNull())) |
{ |
GlyphLayout gl2; |
CharStyle cl2(chstyle); |
double wt = chstyle.font().charWidth(tTabValues[tabCc].tabFillChar, chstyle.fontSize()); |
int coun = static_cast<int>((CurX+ glyphs->xoffset - tabDist) / wt); |
// #6728 : update code according to fillInTabLeaders() and PageItem::layout() - JG |
double sPos = 0.0 /* CurX+hl->glyph.xoffset - (CurX+hl->glyph.xoffset - tabDist) + 1 */; |
gl2.glyph = chstyle.font().char2CMap(tTabValues[tabCc].tabFillChar); |
cl2.setTracking(0); |
cl2.setScaleH(1000); |
cl2.setScaleV(1000); |
gl2.yoffset = glyphs->yoffset; |
for (int cx = 0; cx < coun; ++cx) |
{ |
glyphs->xoffset = sPos + wt * cx; |
if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None)) |
{ |
GlyphLayout gl3; |
CharStyle cl3(cl2); |
//<< HACK to fix Bug #8446 |
cl3.setEffects(cl3.effects() & (~(ScStyle_Outline))); |
//>> |
gl3.glyph = gl2.glyph; |
cl3.setFillColor(cl2.strokeColor()); |
cl3.setFillShade(cl2.strokeShade()); |
gl3.yoffset = gl2.yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0); |
gl3.xoffset = gl2.xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0); |
setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl3, &gl3, pdata, pstyle, pag); |
} |
setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag); |
} |
tabCc++; |
} |
else |
{ |
tabCc++; |
} |
} |
if (ch == SpecialChars::TAB) |
{ |
CurX += glyphs->wide(); |
continue; |
} |
if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None)) |
{ |
GlyphLayout gl2; |
gl2.glyph = glyphs->glyph; |
CharStyle cl2(chstyle); |
//<< HACK to fix Bug #8446 |
cl2.setEffects(cl2.effects() & (~(ScStyle_Outline))); |
//>> |
cl2.setFillColor(chstyle.strokeColor()); |
cl2.setFillShade(chstyle.strokeShade()); |
gl2.yoffset = glyphs->yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0); |
gl2.xoffset = glyphs->xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0); |
gl2.scaleH = glyphs->scaleH; |
gl2.scaleV = glyphs->scaleV; |
setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag); |
} |
setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, chstyle, glyphs, pdata, pstyle, pag); |
CurX += glyphs->wide(); |
tabDist = CurX; |
} |
} |
if (ite->itemType() == PageItem::TextFrame) |
tmp += "ET\n"+tmp2; |
return tmp; |
PdfPainter p(ite, this, PNr, pag); |
ite->textLayout.renderBackground(&p); |
ite->textLayout.render(&p); |
return p.getBuffer(); |
} |
bool PDFLibCore::setTextCh(PageItem *ite, uint PNr, double x, double y, uint d, QByteArray &tmp, QByteArray &tmp2, const CharStyle& style, GlyphLayout *glyphs, PathData* pdata, const ParagraphStyle& pstyle, const ScPage* pag) |
{ |
QByteArray output; |
QByteArray FillColor = ""; |
QByteArray StrokeColor = ""; |
if (ite->asPathText()) |
{ |
tmp += "q\n"; |
QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) ); |
QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx, 0 ); |
if (ite->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (ite->textPathType == 0) |
trafo *= QTransform( tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata->PtransX, -pdata->PtransY ); |
else if (ite->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, pdata->PtransX, -pdata->PtransY ); |
else if (ite->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata->PtransX, -pdata->PtransY ); // ID's Skew mode |
else |
trafo *= QTransform( a, 6 * b, 0, -1, pdata->PtransX, -pdata->PtransY ); |
} |
tmp += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n"; |
if (ite->BaseOffs != 0) |
tmp += "1 0 0 1 0 "+ FToStr( -ite->BaseOffs)+" cm\n"; |
if (glyphs->xoffset != 0.0 || glyphs->yoffset != 0.0) |
tmp += "1 0 0 1 " + FToStr( glyphs->xoffset)+ " " + FToStr( -glyphs->yoffset)+" cm\n"; |
if (ite->itemText.text(d) != SpecialChars::OBJECT) |
tmp += "BT\n"; |
} |
QChar chstr = ite->itemText.text(d); |
double tsz = style.fontSize(); |
/* if (hl->effects() & ScStyle_DropCap) |
{ |
if (pstyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
tsz = qRound(10 * ((doc.typographicSettings.valueBaseGrid * (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (hl->font().realCharHeight(chstr, 10)))); |
else |
{ |
if (pstyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
tsz = qRound(10 * ((pstyle.lineSpacing() * (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (hl->font().realCharHeight(chstr, 10)))); |
else |
{ |
double currasce = hl->font().height(pstyle.charStyle().fontSize()); |
tsz = qRound(10 * ((currasce * (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / hl->font().realCharHeight(chstr, 10))); |
} |
} |
} |
*/ |
if (ite->itemText.hasObject(d)) |
{ |
if (!ite->asPathText()) |
{ |
tmp += "ET\n"+tmp2; |
tmp2 = ""; |
} |
PageItem* embedded = ite->itemText.object(d); |
tmp2 += "q\n"; |
if (ite->asPathText()) |
tmp2 += FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr((embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->gHeight * (style.baselineOffset() / 1000.0))+" cm\n"; |
else |
{ |
if (d == 0 || ite->itemText.text(d-1) == SpecialChars::PARSEP) |
{ |
if ((style.baselineOffset() != 0) && (!pstyle.hasDropCap())) |
tmp2 += FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x + glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->height() * (style.baselineOffset() / 1000.0))+" cm\n"; |
else |
tmp2 += FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))+" cm\n"; |
} |
else |
{ |
if (style.baselineOffset() != 0) |
tmp2 += FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->height() * (style.baselineOffset() / 1000.0))+" cm\n"; |
else |
tmp2 += FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))+" cm\n"; |
} |
} |
if (!PDF_ProcessItem(output, embedded, pag, PNr, true)) |
return false; |
tmp2 +=output; |
tmp2 += "Q\n"; |
tmp += tmp2+"\n"; |
tmp2 = ""; |
if (ite->asPathText()) |
tmp += "Q\n"; |
else |
tmp += "BT\n"; |
return true; |
} |
PdfFont pdfFont = UsedFontsP[style.font().replacementName()]; |
uint glyph = glyphs->glyph; |
if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) || |
glyph == (ScFace::CONTROL_GLYPHS + 32)) |
{ |
glyph = style.font().char2CMap(QChar(' ')); |
chstr = ' '; |
} |
else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) |
{ |
glyph = style.font().char2CMap(QChar('-')); |
chstr = '-'; |
} |
if (glyph < ScFace::CONTROL_GLYPHS) |
{ |
if (style.strokeColor() != CommonStrings::None) |
{ |
StrokeColor = ""; |
StrokeColor += putColor(style.strokeColor(), style.strokeShade(), false); |
} |
if (style.fillColor() != CommonStrings::None) |
{ |
FillColor = ""; |
FillColor += putColor(style.fillColor(), style.fillShade(), true); |
} |
if (((style.effects() & ScStyle_Underline) && (chstr != SpecialChars::PARSEP)) || ((style.effects() & ScStyle_UnderlineWords) && (!chstr.isSpace()))) |
{ |
// double Ulen = style.font().charWidth(chstr, style.fontSize()) * (hl->glyph.scaleH); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
tmp2 += putColor(style.fillColor(), style.fillShade(), false); |
tmp2 += FToStr(Uwid)+" w\n"; |
if (ite->itemType() == PageItem::PathText) |
{ |
if (style.effects() & ScStyle_Subscript) |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n"; |
} |
else |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y+ glyphs->yoffset+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+ glyphs->yoffset+Upos)+" l\n"; |
} |
} |
else |
{ |
if (style.effects() & ScStyle_Subscript) |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y- glyphs->yoffset+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y- glyphs->yoffset+Upos)+" l\n"; |
} |
else |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n"; |
} |
} |
tmp2 += "S\n"; |
} |
if (pdfFont.method == Use_XForm) |
{ |
if (glyph != style.font().char2CMap(QChar(' '))) |
{ |
if ((style.strokeColor() != CommonStrings::None) && (style.effects() & ScStyle_Outline)) |
{ |
tmp2 += FToStr((tsz * style.outlineWidth() / 1000.0) / tsz)+" w\n[] 0 d\n0 J\n0 j\n"; |
tmp2 += StrokeColor; |
} |
if (style.fillColor() != CommonStrings::None) |
tmp2 += FillColor; |
tmp2 += "q\n"; |
// #see 8257 : transform is already computed at beginning of the function |
/*if (ite->itemType() == PageItem::PathText) |
{ |
QPointF tangt = QPointF( cos(hl->PRot), sin(hl->PRot) ); |
QTransform trafo = QTransform( 1, 0, 0, -1, -hl->PDx, 0 ); |
if (ite->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (ite->textPathType == 0) |
trafo *= QTransform(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), hl->PtransX, -hl->PtransY); |
else if (ite->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, hl->PtransX, -hl->PtransY ); |
tmp2 += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n"; |
}*/ |
if (!ite->asPathText()) |
{ |
if (ite->reversed()) |
{ |
double wid = style.font().charWidth(chstr, style.fontSize()) * (glyphs->scaleH); |
tmp2 += "1 0 0 1 "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n"; |
tmp2 += "-1 0 0 1 0 0 cm\n"; |
tmp2 += "1 0 0 1 "+FToStr(-wid)+" 0 cm\n"; |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 0 cm\n"; |
} |
else |
{ |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n"; |
} |
} |
else |
{ |
// if (ite->BaseOffs != 0) |
// tmp2 += "1 0 0 1 0 "+FToStr( -ite->BaseOffs)+" cm\n"; |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 "+FToStr(tsz / 10.0)+" cm\n"; |
} |
if (glyphs->scaleV != 1.0) |
tmp2 += "1 0 0 1 0 "+FToStr( (((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV)) / (tsz / 10.0)) * -1)+" cm\n"; |
tmp2 += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 cm\n"; |
if (style.fillColor() != CommonStrings::None) |
tmp2 += pdfFont.name + Pdf::toPdf(glyph)+" Do\n"; |
if (style.effects() & ScStyle_Outline) |
{ |
FPointArray gly = style.font().glyphOutline(glyph); |
QTransform mat; |
mat.scale(0.1, 0.1); |
gly.map(mat); |
bool nPath = true; |
FPoint np; |
if (gly.size() > 3) |
{ |
for (int poi=0; poi<gly.size()-3; poi += 4) |
{ |
if (gly.isMarker(poi)) |
{ |
tmp2 += "h\n"; |
nPath = true; |
continue; |
} |
if (nPath) |
{ |
np = gly.point(poi); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" m\n"; |
nPath = false; |
} |
np = gly.point(poi+1); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" "; |
np = gly.point(poi+3); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" "; |
np = gly.point(poi+2); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" c\n"; |
} |
} |
tmp2 += "h s\n"; |
} |
tmp2 += "Q\n"; |
} |
} |
else |
{ |
if (style.strokeColor() != CommonStrings::None) |
{ |
if ((style.effects() & ScStyle_Underline) || (style.effects() & ScStyle_Strikethrough) || (style.effects() & ScStyle_Outline)) |
tmp2 += StrokeColor; |
} |
if (style.fillColor() != CommonStrings::None) |
{ |
if ((style.effects() & ScStyle_Underline) || (style.effects() & ScStyle_Strikethrough)) |
tmp2 += FillColor; |
} |
if (glyph != style.font().char2CMap(QChar(' '))) |
{ |
uint gid = glyphs->glyph; |
uint fontNr = 65535; |
switch (pdfFont.encoding) |
{ |
case Encode_256: |
gid = pdfFont.glyphmap[gid]; |
fontNr = gid / 256; |
gid = gid % 256; |
break; |
case Encode_224: |
fontNr = gid / 224; |
gid = gid % 224 + 32; |
break; |
case Encode_Subset: |
gid = pdfFont.glyphmap[gid]; |
break; |
case Encode_IdentityH: |
break; |
} |
if (fontNr == 65535) |
tmp+= pdfFont.name + " " + FToStr(tsz / 10.0)+" Tf\n"; |
else |
tmp += pdfFont.name+"S"+Pdf::toPdf(fontNr) + " "+FToStr(tsz / 10.0)+" Tf\n"; |
if (style.strokeColor() != CommonStrings::None) |
tmp += StrokeColor; |
if (style.fillColor() != CommonStrings::None) |
tmp += FillColor; |
if (pdfFont.method == Use_Type3 && (style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None)) |
{ |
tmp2 += "q\n"; |
tmp2 += FToStr((tsz * style.outlineWidth() / 1000.0) / tsz)+" w\n[] 0 d\n0 J\n0 j\n"; |
// #see 8257 : transform is already computed at beginning of the function |
/*if (ite->itemType() == PageItem::PathText) |
{ |
QPointF tangt = QPointF( cos(hl->PRot), sin(hl->PRot) ); |
QTransform trafo = QTransform( 1, 0, 0, -1, -hl->PDx, 0 ); |
if (ite->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (ite->textPathType == 0) |
trafo *= QTransform(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), hl->PtransX, -hl->PtransY); |
else if (ite->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, hl->PtransX, -hl->PtransY ); |
tmp2 += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n"; |
}*/ |
if (!ite->asPathText()) |
{ |
if (ite->reversed()) |
{ |
double wid = style.font().charWidth(chstr, style.fontSize()) * (glyphs->scaleH); |
tmp2 += "1 0 0 1 "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n"; |
tmp2 += "-1 0 0 1 0 0 cm\n"; |
tmp2 += "1 0 0 1 "+FToStr(-wid)+" 0 cm\n"; |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 0 cm\n"; |
} |
else |
{ |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n"; |
} |
} |
else |
{ |
tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 "+FToStr(tsz / 10.0)+" cm\n"; |
} |
if (glyphs->scaleV != 1.0) |
tmp2 += "1 0 0 1 0 "+FToStr( (((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV)) / (tsz / 10.0)) * -1)+" cm\n"; |
tmp2 += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 cm\n"; |
/* paint outline */ |
FPointArray gly = style.font().glyphOutline(glyph); |
QTransform mat; |
mat.scale(0.1, 0.1); |
gly.map(mat); |
bool nPath = true; |
FPoint np; |
if (gly.size() > 3) |
{ |
for (int poi=0; poi<gly.size()-3; poi += 4) |
{ |
if (gly.isMarker(poi)) |
{ |
tmp2 += "h\n"; |
nPath = true; |
continue; |
} |
if (nPath) |
{ |
np = gly.point(poi); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" m\n"; |
nPath = false; |
} |
np = gly.point(poi+1); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" "; |
np = gly.point(poi+3); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" "; |
np = gly.point(poi+2); |
tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" c\n"; |
} |
} |
tmp2 += "h s\n"; |
tmp2 += "Q\n"; |
} |
else |
{ |
if (style.effects() & ScStyle_Outline) |
tmp += FToStr(tsz * style.outlineWidth() / 10000.0) + (style.fillColor() != CommonStrings::None ? " w 2 Tr\n" : " w 1 Tr\n"); |
else |
tmp += "0 Tr\n"; |
} |
if (!ite->asPathText()) |
{ |
if (ite->reversed()) |
{ |
double wtr = glyphs->xadvance; |
tmp += FToStr(-qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1)) +" "+FToStr(x+ glyphs->xoffset+wtr)+" "+FToStr(-y- glyphs->yoffset+(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0))+" Tm\n"; |
} |
else |
tmp += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr(-y- glyphs->yoffset+(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0))+" Tm\n"; |
} |
else |
{ |
tmp += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 Tm\n"; |
} |
if (pdfFont.method != Use_Type3 || style.fillColor() != CommonStrings::None) |
{ |
switch (pdfFont.encoding) |
{ |
case Encode_224: |
case Encode_256: |
tmp += Pdf::toHexString8(gid) + " Tj\n"; |
break; |
case Encode_IdentityH: |
default: |
tmp += Pdf::toHexString16(gid) + " Tj\n"; |
break; |
} |
} |
} |
} |
if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP)) |
{ |
// double Ulen = style.font().charWidth(chstr, style.fontSize()) * (hl->glyph.scaleH); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
tmp2 += putColor(style.fillColor(), style.fillShade(), false); |
tmp2 += FToStr(Uwid)+" w\n"; |
if (ite->itemType() == PageItem::PathText) |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n"; |
} |
else |
{ |
tmp2 += FToStr(x+ glyphs->xoffset) +" "+FToStr(-y- glyphs->yoffset+Upos)+" m\n"; |
tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y- glyphs->yoffset+Upos)+" l\n"; |
} |
tmp2 += "S\n"; |
} |
if (ite->asPathText()) |
{ |
tmp += "ET\n"+tmp2+"Q\n"; |
tmp2 = ""; |
} |
} |
if (glyphs->more) { |
// // ugly hack until setTextCh interface is changed |
// ScText hl2(*hl); |
// hl2.glyph = *(hl->glyph.more); |
if (!setTextCh(ite, PNr, x + glyphs->xadvance, y, d, tmp, tmp2, style, glyphs->more, pdata, pstyle, pag)) |
return false; |
// // don't let hl2's destructor delete these! |
// hl2.glyph.more = 0; |
} |
return true; |
} |
QByteArray PDFLibCore::SetColor(const QString& farbe, double Shade) |
{ |
const ScColor& col = doc.PageColors[farbe]; |
/trunk/Scribus/scribus/pdflib_core.h |
---|
43,6 → 43,8 |
#include "pdfwriter.h" |
class PdfPainter; |
/** |
* PDFLibCore provides Scribus's implementation of PDF export functionality. |
* |
59,6 → 61,8 |
{ |
Q_OBJECT |
friend class PdfPainter; |
public: |
explicit PDFLibCore(ScribusDoc & docu); |
~PDFLibCore(); |
171,7 → 175,6 |
QByteArray Write_FormXObject(QByteArray &data, PageItem *controlItem = 0); |
QByteArray Write_TransparencyGroup(double trans, int blend, QByteArray &data, PageItem *controlItem = 0); |
QByteArray setTextSt(PageItem *ite, uint PNr, const ScPage* pag); |
bool setTextCh(PageItem *ite, uint PNr, double x, double y, uint d, QByteArray &tmp, QByteArray &tmp2, const CharStyle& cstyle, GlyphLayout *glyphs, PathData* pdata, const ParagraphStyle& pstyle, const ScPage* pag); |
void getBleeds(const ScPage* page, double &left, double &right); |
void getBleeds(const ScPage* page, double &left, double &right, double &bottom, double& top); |
/trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp |
---|
55,6 → 55,9 |
#include "sccolorengine.h" |
#include "util_formats.h" |
#include "util_math.h" |
#include "text/textlayout.h" |
#include "text/textlayoutpainter.h" |
#include "text/boxes.h" |
int svgexplugin_getPluginAPIVersion() |
{ |
368,11 → 371,9 |
ob = processImageItem(Item, trans, fill, stroke); |
break; |
case PageItem::TextFrame: |
case PageItem::PathText: |
ob = processTextItem(Item, trans, fill, stroke); |
break; |
case PageItem::PathText: |
ob = processPathTextItem(Item, trans, stroke); |
break; |
case PageItem::Symbol: |
ob = processSymbolItem(Item, trans); |
break; |
1144,6 → 1145,97 |
return ob; |
} |
class SvgPainter: public TextLayoutPainter |
{ |
QDomElement m_elem; |
SVGExPlug *m_svg; |
QString m_trans; |
public: |
SvgPainter(QString trans, SVGExPlug *svg, QDomElement &elem) |
: m_elem(elem) |
, m_svg(svg) |
, m_trans(trans) |
{} |
void drawGlyph(const GlyphLayout gl) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
QTransform transform = matrix(); |
transform.translate(x(), y() - (fontSize() * gl.scaleV)); |
transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0); |
QDomElement glyph = m_svg->docu.createElement("use"); |
glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font())); |
glyph.setAttribute("transform", m_svg->MatrixToStr(transform)); |
QString fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";"; |
QString stroke = "stroke:none;"; |
glyph.setAttribute("style", fill + stroke); |
m_elem.appendChild(glyph); |
} |
void drawGlyphOutline(const GlyphLayout gl, bool hasFill) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
QTransform transform = matrix(); |
transform.translate(x(), y() - (fontSize() * gl.scaleV)); |
transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0); |
QDomElement glyph = m_svg->docu.createElement("use"); |
glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font())); |
glyph.setAttribute("transform", m_svg->MatrixToStr(transform)); |
QString fill = "fill:none;"; |
if (hasFill) |
fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";"; |
QString stroke ="stroke:" + m_svg->SetColor(strokeColor().color, strokeColor().shade) + ";"; |
stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";"; |
glyph.setAttribute("style", fill + stroke); |
m_elem.appendChild(glyph); |
} |
void drawLine(QPointF start, QPointF end) |
{ |
QTransform transform = matrix(); |
transform.translate(x(), y()); |
QDomElement path = m_svg-> docu.createElement("path"); |
path.setAttribute("d", QString("M %1 %2 L%3 %4").arg(start.x()).arg(start.y()).arg(end.x()).arg(end.y())); |
QString stroke = "stroke:none;"; |
if (fillColor().color != CommonStrings::None) |
{ |
stroke = "stroke:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";"; |
stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";"; |
} |
path.setAttribute("style", "fill:none;" + stroke); |
path.setAttribute("transform", m_svg->MatrixToStr(transform)); |
m_elem.appendChild(path); |
} |
void drawRect(QRectF rect) |
{ |
QTransform transform = matrix(); |
transform.translate(x(), y()); |
QString paS = QString("M %1 %2 ").arg(rect.x()).arg(rect.y()); |
paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y()); |
paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y() + rect.height()); |
paS += QString("L %1 %2 ").arg(rect.x()).arg(rect.y() + rect.height()); |
paS += "Z"; |
QDomElement path = m_svg-> docu.createElement("path"); |
path.setAttribute("d", paS); |
path.setAttribute("transform", m_svg->MatrixToStr(transform)); |
path.setAttribute("style", "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";" + "stroke:none;"); |
m_elem.appendChild(path); |
} |
void drawObject(PageItem* item) |
{ |
QDomElement layerGroup = m_svg->processInlineItem(item, m_trans, scaleH(), scaleV()); |
m_elem.appendChild(layerGroup); |
} |
}; |
QDomElement SVGExPlug::processTextItem(PageItem *Item, QString trans, QString fill, QString stroke) |
{ |
QDomElement ob; |
1168,14 → 1260,6 |
} |
} |
bool bFound = false; |
for (uint ll=0; ll < Item->textLayout.lines(); ++ll) |
{ |
if (Item->itemText.paragraphStyle(Item->textLayout.line(ll).firstItem).backgroundColor() != CommonStrings::None) |
{ |
bFound = true; |
break; |
} |
} |
if (bFound) |
{ |
QDomElement cl; |
1188,634 → 1272,14 |
if (!ob2.isNull()) |
ob.setAttribute("clip-path", "url(#" + ob2.attribute("id") + ")"); |
} |
double x, y, wide; |
QString chstr; |
uint llp = 0; |
while (llp < Item->textLayout.lines()) |
{ |
LineSpec ls = Item->textLayout.line(llp++); |
const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
double y0 = ls.y; |
double y2 = 0; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < Item->textLayout.lines()) |
{ |
ls = Item->textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (Item->itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (Item->itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < Item->textLayout.lines()) |
{ |
if ((Item->textLayout.line(llp + 1).lastItem - Item->textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < Item->textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent); |
llp++; |
} |
QRectF scr(lMarg + adjX, y0 - ascent, Item->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height()); |
paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height()); |
paS += "Z"; |
QDomElement glyS = docu.createElement("path"); |
glyS.setAttribute("d", paS); |
glyS.setAttribute("style", "fill:"+SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade())+";" + "stroke:none;"); |
ob.appendChild(glyS); |
} |
} |
for (uint ll=0; ll < Item->textLayout.lines(); ++ll) |
{ |
LineSpec ls = Item->textLayout.line(ll); |
double CurX = ls.x; |
double CurXB = ls.x; |
int last = qMin(ls.lastItem, Item->itemText.length() - 1); |
QRectF scr; |
QString oldBack = ""; |
double oldShade = 100; |
QString colorB = ""; |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
const GlyphLayout* glyphs(Item->itemText.getGlyphs(a)); |
const CharStyle& charStyle(Item->itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
// This code is for rendering character background color. |
colorB = SetColor(charStyle.backColor(), charStyle.backShade()); |
const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = m_Doc->guidesPrefs().valueBaselineGrid; |
else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = LineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (Item->textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (LineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= LineStyle.dropCapLines(); |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= LineStyle.lineSpacing(); |
else if (Item->firstLineOffset() == FLOPRealGlyphHeight || Item->firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= LineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scrG; |
if (Item->itemText.hasObject(a)) |
{ |
PageItem* obj = Item->itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scrG = QRectF(CurXB, ls.y - hh, ww , hh); |
} |
else |
scrG = QRectF(CurXB, y1, glyphs->wide(), hl); |
if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scr |= scrG; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height()); |
paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height()); |
paS += "Z"; |
QDomElement glyS = docu.createElement("path"); |
glyS.setAttribute("d", paS); |
glyS.setAttribute("style", "fill:"+SetColor(oldBack, oldShade)+";" + "stroke:none;"); |
ob.appendChild(glyS); |
scr = scrG; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
// end background code |
} |
else |
{ |
if (!scr.isNull()) |
{ |
QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height()); |
paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height()); |
paS += "Z"; |
QDomElement glyS = docu.createElement("path"); |
glyS.setAttribute("d", paS); |
glyS.setAttribute("style", "fill:"+colorB+";" + "stroke:none;"); |
ob.appendChild(glyS); |
} |
oldBack = ""; |
oldShade = 100; |
scr = QRectF(); |
} |
CurXB += glyphs->wide(); |
} |
if (!scr.isNull()) |
{ |
QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y()); |
paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height()); |
paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height()); |
paS += "Z"; |
QDomElement glyS = docu.createElement("path"); |
glyS.setAttribute("d", paS); |
glyS.setAttribute("style", "fill:"+colorB+";" + "stroke:none;"); |
ob.appendChild(glyS); |
} |
for (int a = ls.firstItem; a <= ls.lastItem; ++a) |
{ |
x = 0.0; |
y = 0.0; |
//ScText * hl = Item->itemText.item_p(a); |
const CharStyle& charStyle(Item->itemText.charStyle(a)); |
const GlyphLayout* glyphs = Item->itemText.getGlyphs(a); |
PageItem* embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL; |
LayoutFlags flags = Item->itemText.flags(a); |
chstr = Item->itemText.text(a,1); |
if ((chstr == QChar(13)) || (chstr == QChar(29))) |
{ |
if (chstr == QChar(29)) |
CurX += glyphs->wide(); |
continue; |
} |
if (chstr == QChar(30)) |
{ |
chstr = Item->ExpandToken(a); |
if (chstr == QChar(32)) |
{ |
CurX += glyphs->wide(); |
continue; |
} |
} |
double chs = charStyle.fontSize(); |
if (charStyle.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstr = chstr.toUpper(); |
} |
} |
else if (charStyle.effects() & ScStyle_AllCaps) |
chstr = chstr.toUpper(); |
uint chr = chstr[0].unicode(); |
QTransform chma, chma2, chma3, chma4, chma6; |
QTransform trafo = QTransform( 1, 0, 0, 1, CurX, ls.y ); |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(-Item->xPos(), -Item->yPos()); |
trafo *= sca; |
} |
chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0); |
if (Item->reversed()) |
{ |
if (a < Item->itemText.length()-1) |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), Item->itemText.text(a+1)); |
else |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize()); |
chma3.scale(-1, 1); |
chma3.translate(-wide, 0); |
} |
chma4.translate(0, Item->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV); |
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript | ScLayout_DropCap)) |
chma6.translate(0, glyphs->yoffset); |
if (charStyle.baselineOffset() != 0) |
chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0)); |
QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo; |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(Item->xPos(), Item->yPos()); |
finalMat *= sca; |
} |
if (embItem != NULL) |
{ |
ob.appendChild(processInlineItem(CurX + glyphs->xoffset, ls.y + glyphs->yoffset, finalMat, embItem, charStyle, false, trans)); |
CurX += (embItem->width() + embItem->lineWidth()) * glyphs->scaleH; |
} |
else |
{ |
QString glName; |
if (chstr > QChar(32)) |
glName = handleGlyph(chr, charStyle); |
if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None) && (chstr > QChar(32))) |
{ |
QTransform sha = finalMat; |
QTransform shad; |
shad.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0); |
sha *= shad; |
QDomElement ob2 = docu.createElement("use"); |
ob2.setAttribute("xlink:href", "#" + glName); |
ob2.setAttribute("transform", MatrixToStr(sha)); |
ob2.setAttribute("style", "fill:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";" + "stroke:none;"); |
ob.appendChild(ob2); |
} |
if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr[0])) |
|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstr[0].isSpace() && !SpecialChars::isBreak(chstr[0]))) |
{ |
x = CurX; |
y = ls.y; |
double Ulen = glyphs->xadvance; |
double Upos, lw, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1)) |
{ |
if (charStyle.underlineOffset() != -1) |
Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
if (charStyle.underlineWidth() != -1) |
lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
QDomElement ob6 = docu.createElement("path"); |
if (charStyle.effects() & ScStyle_Subscript) |
ob6.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y + glyphs->yoffset - Upos).arg(x + glyphs->xoffset+Ulen).arg(y + glyphs->yoffset - Upos)); |
else |
ob6.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y - Upos).arg(x + glyphs->xoffset+Ulen).arg(y - Upos)); |
QString sT = "stroke:none;"; |
if (charStyle.fillColor() != CommonStrings::None) |
{ |
sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
sT += " stroke-width:"+FToStr(lw)+";"; |
} |
ob6.setAttribute("style", "fill:none;" + sT); |
ob.appendChild(ob6); |
} |
if (chstr > QChar(32)) |
{ |
QDomElement ob3 = docu.createElement("use"); |
ob3.setAttribute("xlink:href", "#" + glName); |
ob3.setAttribute("transform", MatrixToStr(finalMat)); |
QString fT = "fill:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
QString sT = "stroke:none;"; |
if (charStyle.effects() & ScStyle_Outline) |
{ |
sT = "stroke:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";"; |
sT += " stroke-width:"+FToStr(chs * charStyle.outlineWidth() / 10000.0)+";"; |
} |
ob3.setAttribute("style", fT + sT); |
ob.appendChild(ob3); |
} |
if (charStyle.effects() & ScStyle_Strikethrough) |
{ |
x = CurX; |
y = ls.y; |
double Ulen = glyphs->xadvance; |
double Upos, lw, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1)) |
{ |
if (charStyle.strikethruOffset() != -1) |
Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
if (charStyle.strikethruWidth() != -1) |
lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0); |
QDomElement ob7 = docu.createElement("path"); |
ob7.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y + glyphs->yoffset - Upos).arg(x + glyphs->xoffset+Ulen).arg(y + glyphs->yoffset - Upos)); |
QString sT = "stroke:none;"; |
if (charStyle.fillColor() != CommonStrings::None) |
{ |
sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
sT += " stroke-width:"+FToStr(lw)+";"; |
} |
ob7.setAttribute("style", "fill:none;" + sT); |
ob.appendChild(ob7); |
} |
CurX += glyphs->wide(); |
} |
} |
} |
if (Item->NamedLStyle.isEmpty()) |
{ |
QDomElement ob4 = docu.createElement("path"); |
ob4.setAttribute("d", SetClipPath(&Item->PoLine, true)); |
ob4.setAttribute("style", "fill:none; "+stroke); |
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath)) |
ob4.appendChild(processSymbolStroke(Item, trans)); |
ob.appendChild(ob4); |
} |
else |
{ |
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle]; |
for (int it = ml.size()-1; it > -1; it--) |
{ |
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0)) |
{ |
QDomElement ob5 = docu.createElement("path"); |
ob5.setAttribute("d", SetClipPath(&Item->PoLine, true)); |
ob5.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item)); |
ob.appendChild(ob5); |
} |
} |
} |
SvgPainter p(trans, this, ob); |
Item->textLayout.renderBackground(&p); |
Item->textLayout.render(&p); |
return ob; |
} |
QDomElement SVGExPlug::processPathTextItem(PageItem *Item, QString trans, QString stroke) |
QDomElement SVGExPlug::processInlineItem(PageItem* embItem, QString trans, double scaleH, double scaleV) |
{ |
QDomElement ob; |
ob = docu.createElement("g"); |
ob.setAttribute("transform", trans); |
if (Item->PoShow) |
{ |
if (Item->NamedLStyle.isEmpty()) |
{ |
QDomElement ob4 = docu.createElement("path"); |
ob4.setAttribute("d", SetClipPath(&Item->PoLine, false)); |
ob4.setAttribute("style", "fill:none; "+stroke); |
ob.appendChild(ob4); |
} |
else |
{ |
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle]; |
for (int it = ml.size()-1; it > -1; it--) |
{ |
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0)) |
{ |
QDomElement ob5 = docu.createElement("path"); |
ob5.setAttribute("d", SetClipPath(&Item->PoLine, false)); |
ob5.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item)); |
ob.appendChild(ob5); |
} |
} |
} |
} |
double wide; |
QString chstr; |
for (int a = 0; a < Item->asPathText()->itemRenderText.length(); ++a) |
{ |
//ScText *hl = Item->asPathText()->itemRenderText.item_p(a); |
const CharStyle& charStyle(Item->asPathText()->itemRenderText.charStyle(a)); |
const GlyphLayout* glyphs = Item->asPathText()->itemRenderText.getGlyphs(a); |
const PathData* pdata = &(Item->textLayout.point(a)); |
PageItem* embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL; |
LayoutFlags flags = Item->itemText.flags(a); |
chstr = Item->asPathText()->itemRenderText.text(a,1); |
if ((chstr == QChar(13)) || (chstr == QChar(29))) |
continue; |
if (chstr == QChar(30)) |
{ |
chstr = Item->ExpandToken(a); |
if (chstr == QChar(32)) |
continue; |
} |
double chs = charStyle.fontSize(); |
if (charStyle.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstr = chstr.toUpper(); |
} |
} |
else if (charStyle.effects() & ScStyle_AllCaps) |
chstr = chstr.toUpper(); |
uint chr = chstr[0].unicode(); |
QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) ); |
QTransform chma, chma2, chma3, chma4, chma6; |
QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx, 0 ); |
if (Item->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (Item->textPathType == 0) |
trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata->PtransX, pdata->PtransY ); |
else if (Item->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, pdata->PtransX, pdata->PtransY ); |
else if (Item->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata->PtransX, pdata->PtransY ); // ID's Skew mode |
else |
trafo *= QTransform( a, 6 * b, 0, -1, pdata->PtransX, pdata->PtransY ); |
} |
if (embItem != NULL) |
{ |
QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo; |
ob.appendChild(processInlineItem(0, 0, finalMat, embItem, charStyle, true, trans)); |
} |
else |
{ |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(-Item->xPos(), -Item->yPos()); |
trafo *= sca; |
} |
chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0); |
if (Item->reversed()) |
{ |
if (a < Item->itemText.length()-1) |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), Item->itemText.text(a+1)); |
else |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize()); |
chma3.scale(-1, 1); |
chma3.translate(-wide, 0); |
} |
chma4.translate(0, Item->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV); |
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript | ScLayout_DropCap)) |
chma6.translate(0, glyphs->yoffset); |
if (charStyle.baselineOffset() != 0) |
chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0)); |
QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo; |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(Item->xPos(), Item->yPos()); |
finalMat *= sca; |
} |
if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr[0])) |
|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstr[0].isSpace() && !SpecialChars::isBreak(chstr[0]))) |
{ |
QTransform stro = chma2 * chma3 * chma6 * trafo; |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(Item->xPos(), Item->yPos()); |
stro *= sca; |
} |
double Ulen = glyphs->xadvance; |
double Upos, Uwid, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1)) |
{ |
if (charStyle.underlineOffset() != -1) |
Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
if (charStyle.underlineWidth() != -1) |
Uwid = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
QDomElement ob8 = docu.createElement("path"); |
ob8.setAttribute("transform", MatrixToStr(stro)); |
if (charStyle.effects() & ScStyle_Subscript) |
ob8.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-Upos).arg(glyphs->xoffset+Ulen).arg(-Upos)); |
else |
ob8.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-(Upos + glyphs->yoffset)).arg(glyphs->xoffset+Ulen).arg(-(Upos + glyphs->yoffset))); |
QString sT = "stroke:none;"; |
if (charStyle.fillColor() != CommonStrings::None) |
{ |
sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
sT += " stroke-width:"+FToStr(Uwid)+";"; |
} |
ob8.setAttribute("style", "fill:none;" + sT); |
ob.appendChild(ob8); |
} |
if (chstr > QChar(32)) |
{ |
QString glName = handleGlyph(chr, charStyle); |
if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None)) |
{ |
QTransform sha = finalMat; |
QTransform shad; |
shad.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0); |
sha *= shad; |
QDomElement ob2 = docu.createElement("use"); |
ob2.setAttribute("xlink:href", "#" + glName); |
ob2.setAttribute("transform", MatrixToStr(sha)); |
ob2.setAttribute("style", "fill:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";" + "stroke:none;"); |
ob.appendChild(ob2); |
} |
QDomElement ob1 = docu.createElement("use"); |
ob1.setAttribute("xlink:href", "#" + glName); |
ob1.setAttribute("transform", MatrixToStr(finalMat)); |
QString fT = "fill:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
QString sT = "stroke:none;"; |
if (charStyle.effects() & ScStyle_Outline) |
{ |
sT = "stroke:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";"; |
sT += " stroke-width:"+FToStr(chs * charStyle.outlineWidth() / 10000.0)+";"; |
} |
ob1.setAttribute("style", fT + sT); |
ob.appendChild(ob1); |
} |
if (charStyle.effects() & ScStyle_Strikethrough) |
{ |
QTransform stro = chma2 * chma3 * chma6 * trafo; |
if (Item->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(Item->xPos(), Item->yPos()); |
stro *= sca; |
} |
double Ulen = glyphs->xadvance; |
double Upos, Uwid, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1)) |
{ |
if (charStyle.strikethruOffset() != -1) |
Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
if (charStyle.strikethruWidth() != -1) |
Uwid = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
QDomElement ob7 = docu.createElement("path"); |
ob7.setAttribute("transform", MatrixToStr(stro)); |
ob7.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-Upos).arg(glyphs->xoffset+Ulen).arg(-Upos)); |
QString sT = "stroke:none;"; |
if (charStyle.fillColor() != CommonStrings::None) |
{ |
sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";"; |
sT += " stroke-width:"+FToStr(Uwid)+";"; |
} |
ob7.setAttribute("style", "fill:none;" + sT); |
ob.appendChild(ob7); |
} |
} |
} |
return ob; |
} |
QDomElement SVGExPlug::processInlineItem(double xpos, double ypos, QTransform &finalMat, PageItem* embItem, const CharStyle & charStyle, bool pathT, QString trans) |
{ |
QList<PageItem*> emG; |
if (embItem->isGroup()) |
emG = embItem->getItemList(); |
1823,8 → 1287,6 |
emG.append(embItem); |
QDomElement layerGroup = docu.createElement("g"); |
if (pathT) |
layerGroup.setAttribute("transform", MatrixToStr(finalMat)); |
for (int em = 0; em < emG.count(); ++em) |
{ |
PageItem* embedded = emG.at(em); |
1853,11 → 1315,9 |
obE = processImageItem(embedded, trans, fill, stroke); |
break; |
case PageItem::TextFrame: |
case PageItem::PathText: |
obE = processTextItem(embedded, trans, fill, stroke); |
break; |
case PageItem::PathText: |
obE = processPathTextItem(embedded, trans, stroke); |
break; |
case PageItem::Symbol: |
obE = processSymbolItem(embedded, trans); |
break; |
1865,13 → 1325,10 |
break; |
} |
QTransform mm; |
mm.translate(xpos + embedded->gXpos * (charStyle.scaleH() / 1000.0), (ypos - (embedded->gHeight * (charStyle.scaleV() / 1000.0)) + embedded->gYpos * (charStyle.scaleV() / 1000.0))); |
if (charStyle.baselineOffset() != 0) |
mm.translate(0, embedded->gHeight * (charStyle.baselineOffset() / 1000.0)); |
if (charStyle.scaleH() != 1000) |
mm.scale(charStyle.scaleH() / 1000.0, 1); |
if (charStyle.scaleV() != 1000) |
mm.scale(1, charStyle.scaleV() / 1000.0); |
if (scaleH != 1.0) |
mm.scale(scaleH, 1); |
if (scaleV != 1.0) |
mm.scale(1, scaleV); |
mm.rotate(embedded->rotation()); |
obE.setAttribute("transform", MatrixToStr(mm)); |
layerGroup.appendChild(obE); |
1879,15 → 1336,12 |
return layerGroup; |
} |
QString SVGExPlug::handleGlyph(uint chr, const CharStyle& cStyle) |
QString SVGExPlug::handleGlyph(uint gid, const ScFace font) |
{ |
if (chr == 32) |
return "SPACE"; |
QString glName = QString("Gl%1%2").arg(cStyle.font().psName().simplified().replace(QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )).arg(chr); |
QString glName = QString("Gl%1%2").arg(font.psName().simplified().replace(QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )).arg(gid); |
if (glyphNames.contains(glName)) |
return glName; |
uint gl = cStyle.font().char2CMap(chr); |
FPointArray pts = cStyle.font().glyphOutline(gl); |
FPointArray pts = font.glyphOutline(gid); |
QDomElement ob = docu.createElement("path"); |
ob.setAttribute("d", SetClipPath(&pts, true)); |
ob.setAttribute("id", glName); |
/trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h |
---|
58,7 → 58,8 |
class SVGExPlug : public QObject |
{ |
Q_OBJECT |
Q_OBJECT |
friend class SvgPainter; |
public: |
/*! |
90,9 → 91,8 |
QDomElement processLineItem(PageItem *Item, QString trans, QString stroke); |
QDomElement processImageItem(PageItem *Item, QString trans, QString fill, QString stroke); |
QDomElement processTextItem(PageItem *Item, QString trans, QString fill, QString stroke); |
QDomElement processPathTextItem(PageItem *Item, QString trans, QString stroke); |
QDomElement processInlineItem(double xpos, double ypos, QTransform &finalMat, PageItem* embItem, const CharStyle& cStyle, bool pathT, QString trans); |
QString handleGlyph(uint chr, const CharStyle& cStyle); |
QDomElement processInlineItem(PageItem* embItem, QString trans, double scaleH, double scaleV); |
QString handleGlyph(uint gid, const ScFace font); |
QDomElement processArrows(PageItem *Item, QDomElement line, QString trans); |
QString handleMask(PageItem *Item, double xOffset, double yOffset); |
QString getFillStyle(PageItem *Item); |
/trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp |
---|
51,6 → 51,7 |
#include "scribusview.h" |
#include "sctextstruct.h" |
#include "tableutils.h" |
#include "text/textlayoutpainter.h" |
#include "util.h" |
#include "ui/customfdialog.h" |
#include "ui/guidemanager.h" |
59,6 → 60,7 |
#include "util_formats.h" |
#include "util_math.h" |
#include "third_party/zip/scribus_zip.h" |
#include "text/boxes.h" |
int xpsexplugin_getPluginAPIVersion() |
{ |
435,6 → 437,7 |
else |
processImageItem(xOffset, yOffset, Item, parentElem, rel_root); |
break; |
case PageItem::PathText: |
case PageItem::TextFrame: |
if (checkForFallback(Item)) |
handleImageFallBack(Item, parentElem, rel_root); |
441,12 → 444,6 |
else |
processTextItem(xOffset, yOffset, Item, parentElem, rel_root); |
break; |
case PageItem::PathText: |
if (checkForFallback(Item)) |
handleImageFallBack(Item, parentElem, rel_root); |
else |
processPathTextItem(xOffset, yOffset, Item, parentElem, rel_root); |
break; |
case PageItem::Table: |
if (checkForFallback(Item)) |
handleImageFallBack(Item, parentElem, rel_root); |
804,6 → 801,121 |
return; |
} |
class XPSPainter: public TextLayoutPainter |
{ |
PageItem *m_item; |
QDomElement m_group; |
XPSExPlug *m_xps; |
QMap<QString, QString> &m_fontMap; |
QDomElement &m_relRoot; |
public: |
XPSPainter(PageItem *item, QDomElement &group, XPSExPlug *xps, QMap<QString, QString> &XPSfontMap, QDomElement &rel_root): |
m_item(item), |
m_group(group), |
m_xps(xps), |
m_fontMap(XPSfontMap), |
m_relRoot(rel_root) |
{ } |
void drawGlyph(const GlyphLayout gl) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
if (!m_fontMap.contains(font().replacementName())) |
m_fontMap.insert(font().replacementName(), m_xps->embedFont(font(), m_relRoot)); |
QTransform transform = matrix(); |
QDomElement glyph = m_xps->p_docu.createElement("Glyphs"); |
double size = fontSize() * qMax(gl.scaleV, gl.scaleH) * m_xps->conversionFactor; |
glyph.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor)); |
glyph.setAttribute("BidiLevel", "0"); |
glyph.setAttribute("StyleSimulations", "None"); |
glyph.setAttribute("FontRenderingEmSize", m_xps->FToStr(size)); |
glyph.setAttribute("FontUri", m_fontMap[font().replacementName()]); |
glyph.setAttribute("Fill", m_xps->SetColor(fillColor().color,fillColor().shade, 0)); |
glyph.setAttribute("OriginX", m_xps->FToStr(x() * m_xps->conversionFactor)); |
glyph.setAttribute("OriginY", m_xps->FToStr(y() * m_xps->conversionFactor)); |
glyph.setAttribute("Indices", QString::number(gl.glyph)); |
m_group.appendChild(glyph); |
} |
void drawGlyphOutline(const GlyphLayout gl, bool fill) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
FPointArray outline = font().glyphOutline(gl.glyph); |
if (outline.size() >= 4) |
{ |
QTransform transform = matrix(); |
transform.scale((fontSize() * gl.scaleH) / 10.0, (fontSize() * gl.scaleV) / 10.0); |
outline.map(transform); |
outline.translate(0, -fontSize() * gl.scaleV); |
outline.translate(x(), y()); |
outline.scale(m_xps->conversionFactor, m_xps->conversionFactor); |
QString pathData = m_xps->SetClipPath(&outline, true); |
QDomElement glyph = m_xps->p_docu.createElement("Path"); |
glyph.setAttribute("Data", pathData); |
if (!fill) |
glyph.setAttribute("Fill", m_xps->SetColor("None", fillColor().shade, 0)); |
else |
glyph.setAttribute("Fill", m_xps->SetColor(fillColor().color, fillColor().shade, 0)); |
glyph.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor)); |
glyph.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0)); |
m_group.appendChild(glyph); |
} |
} |
void drawLine(QPointF start, QPointF end) |
{ |
QTransform transform = matrix(); |
QDomElement path = m_xps->p_docu.createElement("Path"); |
path.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor)); |
path.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((x() + start.x()) * m_xps->conversionFactor).arg((y() + end.y()) * m_xps->conversionFactor).arg((x() + start.x() + end.x()) * m_xps->conversionFactor).arg((y() + end.y()) * m_xps->conversionFactor)); |
path.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0)); |
path.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor)); |
m_group.appendChild(path); |
} |
void drawRect(QRectF rect) |
{ |
QTransform transform = matrix(); |
double rx = (x() + rect.x()) * m_xps->conversionFactor; |
double ry = (y() + rect.y()) * m_xps->conversionFactor; |
double rw = rx + rect.width() * m_xps->conversionFactor; |
double rh = ry + rect.height() * m_xps->conversionFactor; |
QString paS = QString("M%1,%2 ").arg(rx).arg(ry); |
paS += QString("L%1,%2 ").arg(rw).arg(ry); |
paS += QString("L%1,%2 ").arg(rw).arg(rh); |
paS += QString("L%1,%2 ").arg(rx).arg(rh); |
paS += "Z"; |
QDomElement path = m_xps->p_docu.createElement("Path"); |
path.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor)); |
path.setAttribute("Data", paS); |
path.setAttribute("Fill", m_xps->SetColor(fillColor().color, fillColor().shade, 0)); |
path.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor)); |
path.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0)); |
m_group.appendChild(path); |
} |
void drawObject(PageItem* item) |
{ |
QDomElement canvas = m_xps->p_docu.createElement("Canvas"); |
QTransform matrix = QTransform(); |
matrix.translate(x() * m_xps->conversionFactor, (y() - (item->height() * (scaleV() / 1000.0))) * m_xps->conversionFactor); |
if (scaleH() != 1.0) |
matrix.scale(scaleH(), 1); |
if (scaleV() != 1.0) |
matrix.scale(1, scaleV()); |
canvas.setAttribute("RenderTransform", m_xps->MatrixToStr(matrix)); |
m_xps->writeItemOnPage(item->gXpos, item->gYpos, item, canvas, m_relRoot); |
m_group.appendChild(canvas); |
} |
}; |
void XPSExPlug::processTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root) |
{ |
if (Item->isAnnotation()) |
879,758 → 991,13 |
grp.appendChild(ob); |
} |
} |
bool bFound = false; |
for (uint ll=0; ll < Item->textLayout.lines(); ++ll) |
{ |
if (Item->itemText.paragraphStyle(Item->textLayout.line(ll).firstItem).backgroundColor() != CommonStrings::None) |
{ |
bFound = true; |
break; |
} |
} |
if (bFound) |
{ |
FPointArray path = Item->PoLine.copy(); |
path.scale(conversionFactor, conversionFactor); |
SetClipAttr(grp, &path, Item->fillRule); |
} |
uint llp = 0; |
while (llp < Item->textLayout.lines()) |
{ |
LineSpec ls = Item->textLayout.line(llp++); |
const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
double y0 = ls.y; |
double y2 = ls.y; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < Item->textLayout.lines()) |
{ |
ls = Item->textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (Item->itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (Item->itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < Item->textLayout.lines()) |
{ |
if ((Item->textLayout.line(llp + 1).lastItem - Item->textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < Item->textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent); |
llp++; |
} |
QRectF scr(lMarg + adjX, y0 - ascent, Item->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += "Z"; |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), 0)); |
grp.appendChild(glyS); |
} |
} |
for (uint ll=0; ll < Item->textLayout.lines(); ++ll) |
{ |
LineSpec ls = Item->textLayout.line(ll); |
QList<txtRunItem> current_run; |
QList<QList<txtRunItem> > textRuns; |
QList<txtRunItem> specialText; |
double CurX = ls.x; |
double CurXB = ls.x; |
int last = qMin(ls.lastItem, Item->itemText.length() - 1); |
QRectF scr; |
QString oldBack = ""; |
double oldShade = 100; |
QString colorB = ""; |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
const GlyphLayout* glyphs(Item->itemText.getGlyphs(a)); |
const CharStyle& charStyle(Item->itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
// This code is for rendering character background color. |
colorB = SetColor(charStyle.backColor(), charStyle.backShade(), 0); |
const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = m_Doc->guidesPrefs().valueBaselineGrid; |
else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = LineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (Item->textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (LineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= LineStyle.dropCapLines(); |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= LineStyle.lineSpacing(); |
else if (Item->firstLineOffset() == FLOPRealGlyphHeight || Item->firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= LineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scrG; |
if (Item->itemText.hasObject(a)) |
{ |
PageItem* obj = Item->itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scrG = QRectF(CurXB, ls.y - hh, ww , hh); |
} |
else |
scrG = QRectF(CurXB, y1, glyphs->wide(), hl); |
if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scr |= scrG; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += "Z"; |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", SetColor(oldBack, oldShade, 0)); |
grp.appendChild(glyS); |
scr = scrG; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
} |
else |
{ |
if (!scr.isNull()) |
{ |
QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += "Z"; |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", colorB); |
grp.appendChild(glyS); |
} |
oldBack = ""; |
oldShade = 100; |
scr = QRectF(); |
} |
CurXB += glyphs->wide(); |
} |
if (!scr.isNull()) |
{ |
QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor); |
paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor); |
paS += "Z"; |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", colorB); |
grp.appendChild(glyS); |
} |
for (int a = ls.firstItem; a <= ls.lastItem; ++a) |
{ |
//ScText *hl = Item->itemText.item_p(a); |
QChar chr = Item->itemText.text(a); |
CharStyle charStyle = Item->itemText.charStyle(a); |
GlyphLayout* glyphs = Item->itemText.getGlyphs(a); |
LayoutFlags flags = Item->itemText.flags(a); |
const ScFace* font = &charStyle.font(); |
txtRunItem txItem; |
txItem.chr = chr; |
txItem.glyphs = glyphs; |
txItem.style = charStyle; |
txItem.index = a; |
txItem.CurX = CurX; |
txItem.embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL; |
if (!((font->type() == ScFace::TTF) || (font->type() == ScFace::OTF))) |
{ |
specialText.append(txItem); |
textRuns.append(current_run); |
current_run.clear(); |
CurX += txItem.glyphs->wide(); |
continue; |
} |
if (SpecialChars::isBreak(chr, true) || (chr == QChar(10))) |
{ |
continue; |
} |
if (flags & ScLayout_SuppressSpace) |
{ |
continue; |
} |
if ((chr == SpecialChars::OLD_NBSPACE) || (chr == SpecialChars::OBJECT) || (charStyle.effects() & ScStyle_UserStyles)) |
{ |
specialText.append(txItem); |
textRuns.append(current_run); |
current_run.clear(); |
CurX += txItem.glyphs->wide(); |
continue; |
} |
QString guidFont; |
if (!xps_fontMap.contains(font->replacementName())) |
{ |
guidFont = embedFont(font, rel_root); |
xps_fontMap.insert(font->replacementName(), guidFont); |
} |
else |
guidFont = xps_fontMap[font->replacementName()]; |
if (current_run.isEmpty()) |
current_run.append(txItem); |
else |
{ |
txtRunItem txItemL = current_run.last(); |
double chl = (txItemL.style.fontSize() / 10.0) * qMax(txItemL.glyphs->scaleV, txItemL.glyphs->scaleH) * conversionFactor; |
const ScFace* fontL = &txItemL.style.font(); |
QString guidFontL = xps_fontMap[fontL->replacementName()]; |
StyleFlag old_sty = txItemL.style.effects(); |
int old_shade = txItemL.style.fillShade(); |
QString old_fill = txItemL.style.fillColor(); |
double chs = (charStyle.fontSize() / 10.0) * qMax(glyphs->scaleV, glyphs->scaleH) * conversionFactor; |
if ((chs != chl) || (guidFont != guidFontL) || (charStyle.effects() != old_sty) || (charStyle.fillColor() != old_fill) || (charStyle.fillShade() != old_shade)) |
{ |
textRuns.append(current_run); |
current_run.clear(); |
} |
current_run.append(txItem); |
} |
CurX += txItem.glyphs->wide(); |
} |
textRuns.append(current_run); |
for (int txr = 0; txr < textRuns.count(); txr++) |
{ |
QString uniString = ""; |
QString indString = ""; |
current_run = textRuns[txr]; |
if (current_run.isEmpty()) |
continue; |
double StartX = current_run[0].CurX; |
CurX = current_run[0].CurX; |
double chs = (current_run[0].style.fontSize() / 10.0) * qMax(current_run[0].glyphs->scaleV, current_run[0].glyphs->scaleH) * conversionFactor; |
for (int cr = 0; cr < current_run.count(); cr++) |
{ |
txtRunItem txItem = current_run[cr]; |
if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT)) |
{ |
QString exString = Item->ExpandToken(txItem.index); |
for (int ex = 0; ex < exString.count(); ex++) |
{ |
indString += ";"; |
} |
uniString += exString; |
} |
else if ((SpecialChars::isBreakingSpace(txItem.chr)) || (SpecialChars::isExpandingSpace(txItem.chr)) || (txItem.chr.isSpace())) |
{ |
indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100); |
uniString += " "; |
} |
else |
{ |
uniString += txItem.chr; |
if ((txItem.glyphs->xoffset != 0) || (txItem.glyphs->yoffset != 0)) |
indString += QString(",%1,%2,%3;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100).arg((txItem.glyphs->xoffset * conversionFactor) / chs * 100).arg((-txItem.glyphs->yoffset * conversionFactor) / chs * 100); |
else |
indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100); |
} |
CurX += txItem.glyphs->wide(); |
} |
if (!indString.isEmpty()) |
indString.chop(1); |
QDomElement gly = p_docu.createElement("Glyphs"); |
gly.setAttribute("BidiLevel", "0"); |
gly.setAttribute("StyleSimulations", "None"); |
gly.setAttribute("FontRenderingEmSize", FToStr(chs)); |
const ScFace* fontL = ¤t_run[0].style.font(); |
gly.setAttribute("FontUri", xps_fontMap[fontL->replacementName()]); |
gly.setAttribute("Fill", SetColor(current_run[0].style.fillColor(), current_run[0].style.fillShade(), 0)); |
gly.setAttribute("UnicodeString", uniString); |
if (current_run.count() == 1) |
{ |
gly.setAttribute("OriginX", FToStr((StartX + current_run[0].glyphs->xoffset) * conversionFactor)); |
gly.setAttribute("OriginY", FToStr((ls.y + current_run[0].glyphs->yoffset) * conversionFactor)); |
} |
else |
{ |
gly.setAttribute("OriginX", FToStr(StartX * conversionFactor)); |
gly.setAttribute("OriginY", FToStr(ls.y * conversionFactor)); |
gly.setAttribute("Indices", indString); |
} |
grp.appendChild(gly); |
} |
for (int cr = 0; cr < specialText.count(); cr++) |
{ |
txtRunItem txItem = specialText[cr]; |
CurX = txItem.CurX; |
if (txItem.chr == SpecialChars::OBJECT) |
{ |
if (txItem.embItem != NULL) |
{ |
QDomElement obO = p_docu.createElement("Canvas"); |
QTransform mm; |
mm.translate(CurX * conversionFactor, (ls.y - (txItem.embItem->height() * (txItem.style.scaleV() / 1000.0))) * conversionFactor); |
if (txItem.style.baselineOffset() != 0) |
mm.translate(0, (txItem.style.baselineOffset() / 1000.0) * conversionFactor); |
if (txItem.style.scaleH() != 1000) |
mm.scale(txItem.style.scaleH() / 1000.0, 1); |
if (txItem.style.scaleV() != 1000) |
mm.scale(1, txItem.style.scaleV() / 1000.0); |
obO.setAttribute("RenderTransform", MatrixToStr(mm)); |
QList<PageItem*> emG; |
if (txItem.embItem->isGroup()) |
emG = txItem.embItem->getItemList(); |
else |
emG.append(txItem.embItem); |
for (int em = 0; em < emG.count(); ++em) |
{ |
PageItem* embed = emG.at(em); |
writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root); |
} |
grp.appendChild(obO); |
} |
continue; |
} |
QString chstr = txItem.chr; |
if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT)) |
chstr = Item->ExpandToken(txItem.index); |
double chs = txItem.style.fontSize(); |
if (txItem.style.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
chs = qMax(static_cast<int>(txItem.style.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstr = chstr.toUpper(); |
} |
} |
else if (txItem.style.effects() & ScStyle_AllCaps) |
chstr = chstr.toUpper(); |
for (int cx = 0; cx < chstr.count(); cx++) |
{ |
FPointArray pts; |
QChar chstrex = chstr[cx]; |
uint chr = chstrex.unicode(); |
QTransform chma; |
uint gl = txItem.style.font().char2CMap(chr); |
if (!chstrex.isSpace()) |
{ |
pts = txItem.style.font().glyphOutline(gl); |
if (pts.size() < 4) |
continue; |
chma = QTransform(); |
chma.scale(txItem.glyphs->scaleH * txItem.style.fontSize() / 100.00, txItem.glyphs->scaleV * txItem.style.fontSize() / 100.0); |
pts.map(chma); |
if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript)) |
pts.translate(0, -(chs / 10.0 * txItem.glyphs->scaleV)); |
else |
pts.translate(0, -(chs / 10.0)); |
pts.translate(CurX, ls.y); |
// Fix for drop caps ??? |
if (ls.isFirstLine && Item->itemText.paragraphStyle(ls.firstItem).hasDropCap() && (txItem.index == ls.firstItem)) |
pts.translate(0, -ls.ascent); |
if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript)) |
pts.translate(0, txItem.glyphs->yoffset); |
if ((txItem.style.effects() & ScStyle_Shadowed) && (txItem.style.strokeColor() != CommonStrings::None)) |
{ |
FPointArray ptsS = pts.copy(); |
ptsS.translate(txItem.style.fontSize() * txItem.style.shadowXOffset() / 10000.0, -txItem.style.fontSize() * txItem.style.shadowYOffset() / 10000.0); |
ptsS.scale(conversionFactor, conversionFactor); |
QString paS = SetClipPath(&ptsS, true); |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0)); |
grp.appendChild(glyS); |
} |
pts.scale(conversionFactor, conversionFactor); |
QString pa = SetClipPath(&pts, true); |
QDomElement gly = p_docu.createElement("Path"); |
gly.setAttribute("Data", pa); |
gly.setAttribute("Fill", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0)); |
if (txItem.style.effects() & ScStyle_Outline) |
{ |
gly.setAttribute("StrokeThickness", FToStr((chs * txItem.style.outlineWidth() / 10000.0) * conversionFactor)); |
gly.setAttribute("Stroke", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0)); |
} |
grp.appendChild(gly); |
} |
if ((txItem.style.effects() & ScStyle_Underline) || ((txItem.style.effects() & ScStyle_UnderlineWords) && chstr.toUInt() != txItem.style.font().char2CMap(QChar(' ')))) |
{ |
double st, lw; |
if ((txItem.style.underlineOffset() != -1) || (txItem.style.underlineWidth() != -1)) |
{ |
if (txItem.style.underlineOffset() != -1) |
st = (txItem.style.underlineOffset() / 1000.0) * (txItem.style.font().descent(txItem.style.fontSize() / 10.0)); |
else |
st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0); |
if (txItem.style.underlineWidth() != -1) |
lw = (txItem.style.underlineWidth() / 1000.0) * (txItem.style.fontSize() / 10.0); |
else |
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0); |
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0); |
} |
if (txItem.style.baselineOffset() != 0) |
st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0); |
QDomElement gly = p_docu.createElement("Path"); |
if (txItem.style.effects() & ScStyle_Subscript) |
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor)); |
else |
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor)); |
gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0)); |
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor)); |
grp.appendChild(gly); |
} |
if (txItem.style.effects() & ScStyle_Strikethrough) |
{ |
double st, lw; |
if ((txItem.style.strikethruOffset() != -1) || (txItem.style.strikethruWidth() != -1)) |
{ |
if (txItem.style.strikethruOffset() != -1) |
st = (txItem.style.strikethruOffset() / 1000.0) * (txItem.style.font().ascent(txItem.style.fontSize() / 10.0)); |
else |
st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0); |
if (txItem.style.strikethruWidth() != -1) |
lw = (txItem.style.strikethruWidth() / 1000.0) * (txItem.style.fontSize() / 10.0); |
else |
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0); |
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0); |
} |
if (txItem.style.baselineOffset() != 0) |
st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0); |
QDomElement gly = p_docu.createElement("Path"); |
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor)); |
gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0)); |
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor)); |
grp.appendChild(gly); |
} |
} |
} |
} |
parentElem.appendChild(grp); |
if ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty()) |
{ |
if (Item->NamedLStyle.isEmpty()) |
{ |
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath)) |
{ |
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root); |
} |
else |
{ |
QDomElement ob3 = p_docu.createElement("Path"); |
ob3.setAttribute("Data", pa); |
getStrokeStyle(Item, ob3, rel_root, xOffset, yOffset); |
ob3.setAttribute("RenderTransform", MatrixToStr(mpl)); |
parentElem.appendChild(ob3); |
} |
} |
else |
{ |
QDomElement grp2 = p_docu.createElement("Canvas"); |
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle]; |
for (int it = ml.size()-1; it > -1; it--) |
{ |
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0)) |
{ |
QDomElement ob3 = p_docu.createElement("Path"); |
ob3.setAttribute("Data", pa); |
GetMultiStroke(&ml[it], ob3); |
grp2.appendChild(ob3); |
} |
} |
if (Item->lineTransparency() != 0) |
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency())); |
grp2.setAttribute("RenderTransform", MatrixToStr(mpl)); |
parentElem.appendChild(grp2); |
} |
} |
XPSPainter p(Item, grp, this, xps_fontMap, rel_root); |
Item->textLayout.renderBackground(&p); |
Item->textLayout.render(&p); |
} |
void XPSExPlug::processPathTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root) |
{ |
QDomElement grp = p_docu.createElement("Canvas"); |
QTransform mpx; |
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor); |
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV()) |
{ |
mpx.rotate(Item->rotation()); |
if (Item->imageFlippedH()) |
{ |
mpx.translate(Item->width() * conversionFactor, 0); |
mpx.scale(-1, 1); |
} |
if (Item->imageFlippedV()) |
{ |
mpx.translate(0, Item->height() * conversionFactor); |
mpx.scale(1, -1); |
} |
} |
grp.setAttribute("RenderTransform", MatrixToStr(mpx)); |
if ((Item->PoShow) && (Item->lineColor() != CommonStrings::None)) |
{ |
QDomElement ob = p_docu.createElement("Path"); |
FPointArray path = Item->PoLine.copy(); |
path.scale(conversionFactor, conversionFactor); |
QString pa = SetClipPath(&path, false); |
ob.setAttribute("Data", pa); |
if (Item->NamedLStyle.isEmpty()) |
{ |
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath)) |
{ |
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root); |
} |
else |
{ |
getStrokeStyle(Item, ob, rel_root, xOffset, yOffset); |
grp.appendChild(ob); |
} |
} |
else |
{ |
QDomElement grp2 = p_docu.createElement("Canvas"); |
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle]; |
for (int it = ml.size()-1; it > -1; it--) |
{ |
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0)) |
{ |
QDomElement ob3 = p_docu.createElement("Path"); |
ob3.setAttribute("Data", pa); |
GetMultiStroke(&ml[it], ob3); |
grp2.appendChild(ob3); |
} |
} |
if (Item->lineTransparency() != 0) |
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency())); |
grp.appendChild(grp2); |
} |
} |
QString chstr; |
for (int a = 0; a < Item->asPathText()->itemRenderText.length(); ++a) |
{ |
//ScText *hl = Item->asPathText()->itemRenderText.item_p(a); |
const CharStyle& charStyle(Item->asPathText()->itemRenderText.charStyle(a)); |
const PathData* pdata = &(Item->asPathText()->textLayout.point(a)); |
const GlyphLayout* glyphs = Item->asPathText()->itemRenderText.getGlyphs(a); |
PageItem* embItem = Item->asPathText()->itemRenderText.hasObject(a)? |
Item->asPathText()->itemRenderText.object(a) : NULL; |
chstr = Item->asPathText()->itemRenderText.text(a,1); |
if ((chstr == QChar(13)) || (chstr == QChar(29))) |
continue; |
if (chstr == QChar(30)) |
{ |
chstr = Item->ExpandToken(a); |
if (chstr == QChar(32)) |
continue; |
} |
double chs = charStyle.fontSize(); |
if (charStyle.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstr = chstr.toUpper(); |
} |
} |
else if (charStyle.effects() & ScStyle_AllCaps) |
chstr = chstr.toUpper(); |
uint chr = chstr[0].unicode(); |
QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) ); |
QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx * conversionFactor, 0 ); |
if (Item->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (Item->textPathType == 0) |
trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); |
else if (Item->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); |
else if (Item->textPathType == 2) |
{ |
double a = 1; |
if (tangt.x() < 0) |
a = -1; |
if (fabs(tangt.x()) > 0.1) |
trafo *= QTransform( a, (tangt.y() / tangt.x()) * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); // ID's Skew mode |
else |
trafo *= QTransform( a, 4 * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); |
} |
if (charStyle.baselineOffset() != 0) |
trafo.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0)); |
trafo.translate(0, Item->BaseOffs); |
QTransform finalMat = trafo; |
if (chr == SpecialChars::OBJECT) |
{ |
if (embItem != NULL) |
{ |
QDomElement obO = p_docu.createElement("Canvas"); |
QTransform mm = finalMat; |
mm.translate(0, (-(embItem->height() * (charStyle.scaleV() / 1000.0))) * conversionFactor); |
if (charStyle.scaleH() != 1000) |
mm.scale(charStyle.scaleH() / 1000.0, 1); |
if (charStyle.scaleV() != 1000) |
mm.scale(1, charStyle.scaleV() / 1000.0); |
obO.setAttribute("RenderTransform", MatrixToStr(mm)); |
QList<PageItem*> emG; |
if (embItem->isGroup()) |
emG = embItem->getItemList(); |
else |
emG.append(embItem); |
for (int em = 0; em < emG.count(); ++em) |
{ |
PageItem* embed = emG.at(em); |
writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root); |
} |
grp.appendChild(obO); |
} |
continue; |
} |
finalMat.scale(conversionFactor, conversionFactor); |
FPointArray pts; |
QTransform chma; |
uint gl = charStyle.font().char2CMap(chr); |
pts = charStyle.font().glyphOutline(gl); |
if (pts.size() < 4) |
continue; |
chma = QTransform(); |
chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0); |
pts.map(chma); |
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript)) |
pts.translate(0, -(chs / 10.0 * glyphs->scaleV)); |
else |
pts.translate(0, -(chs / 10.0)); |
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript)) |
pts.translate(0, glyphs->yoffset); |
if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None)) |
{ |
FPointArray ptsS = pts.copy(); |
ptsS.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0); |
ptsS.map(finalMat); |
QString paS = SetClipPath(&ptsS, true); |
QDomElement glyS = p_docu.createElement("Path"); |
glyS.setAttribute("Data", paS); |
glyS.setAttribute("Fill", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0)); |
grp.appendChild(glyS); |
} |
pts.map(finalMat); |
QString pa = SetClipPath(&pts, true); |
QDomElement gly = p_docu.createElement("Path"); |
gly.setAttribute("Data", pa); |
gly.setAttribute("Fill", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0)); |
if (charStyle.effects() & ScStyle_Outline) |
{ |
gly.setAttribute("StrokeThickness", FToStr((chs * charStyle.outlineWidth() / 10000.0) * conversionFactor)); |
gly.setAttribute("Stroke", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0)); |
} |
grp.appendChild(gly); |
if ((charStyle.effects() & ScStyle_Underline) || ((charStyle.effects() & ScStyle_UnderlineWords) && chstr.toUInt() != charStyle.font().char2CMap(QChar(' ')))) |
{ |
double st, lw; |
if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1)) |
{ |
if (charStyle.underlineOffset() != -1) |
st = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0)); |
else |
st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
if (charStyle.underlineWidth() != -1) |
lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0); |
FPointArray ptsS; |
ptsS.svgInit(); |
if (charStyle.effects() & ScStyle_Subscript) |
{ |
ptsS.svgMoveTo(glyphs->xoffset, glyphs->yoffset - st); |
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, glyphs->yoffset - st); |
} |
else |
{ |
ptsS.svgMoveTo(glyphs->xoffset, -st); |
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st); |
} |
ptsS.map(finalMat); |
QString paS = SetClipPath(&ptsS, true); |
QDomElement gly = p_docu.createElement("Path"); |
gly.setAttribute("Data", paS); |
gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0)); |
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor)); |
grp.appendChild(gly); |
} |
if (charStyle.effects() & ScStyle_Strikethrough) |
{ |
double st, lw; |
if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1)) |
{ |
if (charStyle.strikethruOffset() != -1) |
st = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0)); |
else |
st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
if (charStyle.strikethruWidth() != -1) |
lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0); |
FPointArray ptsS; |
ptsS.svgInit(); |
ptsS.svgMoveTo(glyphs->xoffset, -st); |
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st); |
ptsS.map(finalMat); |
QString paS = SetClipPath(&ptsS, true); |
QDomElement gly = p_docu.createElement("Path"); |
gly.setAttribute("Data", paS); |
gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0)); |
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor)); |
grp.appendChild(gly); |
} |
} |
parentElem.appendChild(grp); |
return; |
} |
void XPSExPlug::processSymbolItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root) |
{ |
QDomElement ob = p_docu.createElement("Canvas"); |
2274,10 → 1641,10 |
} |
} |
QString XPSExPlug::embedFont(const ScFace *font, QDomElement &rel_root) |
QString XPSExPlug::embedFont(const ScFace font, QDomElement &rel_root) |
{ |
QByteArray fontData; |
loadRawText(font->fontFilePath(), fontData); |
loadRawText(font.fontFilePath(), fontData); |
QUuid id = QUuid::createUuid(); |
QString guidString = id.toString(); |
guidString = guidString.toUpper(); |
3084,6 → 2451,12 |
return cc.setNum(c); |
} |
QString XPSExPlug::MatrixToStr(QTransform &mat, double factor) |
{ |
QString cc("%1, %2, %3, %4, %5, %6"); |
return cc.arg(mat.m11()).arg(mat.m12()).arg(mat.m21()).arg(mat.m22()).arg(mat.dx() * factor).arg(mat.dy() * factor); |
} |
QString XPSExPlug::MatrixToStr(QTransform &mat) |
{ |
QString cc("%1, %2, %3, %4, %5, %6"); |
/trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h |
---|
58,8 → 58,9 |
class XPSExPlug : public QObject |
{ |
Q_OBJECT |
Q_OBJECT |
friend class XPSPainter; |
public: |
/*! |
\author Franz Schmid |
81,7 → 82,6 |
void processLineItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processImageItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processPathTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processSymbolItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processTableItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void paintBorder(const TableBorder &border, const QPointF &start, const QPointF &end, const QPointF &startOffsetFactors, const QPointF &endOffsetFactors, QDomElement &ob); |
89,7 → 89,7 |
void processSymbolStroke(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void processArrows(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root); |
void drawArrow(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, FPointArray &arrow); |
QString embedFont(const ScFace *font, QDomElement &rel_root); |
QString embedFont(const ScFace font, QDomElement &rel_root); |
void GetMultiStroke(struct SingleLine *sl, QDomElement &parentElem); |
void getStrokeStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool forArrow = false); |
void getFillStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool withTransparency = true); |
104,6 → 104,7 |
QString FToStr(double c); |
QString IToStr(int c); |
QString MatrixToStr(QTransform &mat); |
QString MatrixToStr(QTransform &mat, double factor); |
int hex2int(char hex); |
bool checkForFallback(PageItem *Item); |
ScribusDoc* m_Doc; |
/trunk/Scribus/scribus/pslib.cpp |
---|
55,13 → 55,158 |
#include "scstreamfilter_ascii85.h" |
#include "scstreamfilter_flate.h" |
#include "tableutils.h" |
#include "text/textlayoutpainter.h" |
#include "ui/multiprogressdialog.h" |
#include "util.h" |
#include "util_formats.h" |
#include "util_math.h" |
#include "text/boxes.h" |
using namespace TableUtils; |
class PSPainter:public TextLayoutPainter |
{ |
ScribusDoc* m_Doc; |
uint m_argh; |
ScPage* m_page; |
bool m_sep; |
bool m_farb; |
bool m_master; |
PSLib* m_ps; |
void applyTransform() |
{ |
if (matrix() != QTransform()) |
{ |
m_ps->PutStream(m_ps->MatrixToStr(1.0, 0.0, 0.0, -1.0, x(), 0.0) + "\n"); |
m_ps->PutStream(m_ps->MatrixToStr(matrix().m11(), -matrix().m12(), matrix().m21(), -matrix().m22(), matrix().dx(), -matrix().dy()) + "\n"); |
m_ps->PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
} |
} |
public: |
PSPainter(ScribusDoc* Doc, uint argh, ScPage* page, bool sep, bool farb, bool master, PSLib* ps): |
m_Doc(Doc), |
m_argh(argh), |
m_page(page), |
m_sep(sep), |
m_farb(farb), |
m_master(master), |
m_ps(ps) |
{} |
void drawGlyph(const GlyphLayout gl); |
void drawGlyphOutline(const GlyphLayout gl, bool fill); |
void drawLine(QPointF start, QPointF end); |
void drawRect(QRectF rect); |
void drawObject(PageItem* item); |
}; |
void PSPainter::drawGlyph(const GlyphLayout gl) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
m_ps->PS_save(); |
applyTransform(); |
m_ps->PS_translate(x(), -(y() - fontSize())); |
if (gl.scaleH != 1.0) |
m_ps->PS_scale(gl.scaleH, 1); |
if (gl.scaleV != 1.0) |
{ |
m_ps->PS_translate(0, -(fontSize() - fontSize() * gl.scaleV)); |
m_ps->PS_scale(1, gl.scaleV); |
} |
if (fillColor().color != CommonStrings::None) |
m_ps->putColorNoDraw(fillColor().color, fillColor().shade); |
m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false); |
m_ps->PS_restore(); |
} |
void PSPainter::drawGlyphOutline(const GlyphLayout gl, bool fill) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
int h, s, v, k; |
QVector<double> dum; |
dum.clear(); |
m_ps->PS_save(); |
applyTransform(); |
if (strokeColor().color != CommonStrings::None) |
{ |
m_ps->PS_setlinewidth(strokeWidth()); |
m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin); |
m_ps->PS_setdash(Qt::SolidLine, 0, dum); |
m_ps->PS_translate(x(), -(y() - fontSize())); |
FPointArray gly = font().glyphOutline(gl.glyph); |
QTransform chma; |
chma.scale((fontSize() * gl.scaleH) / 10.0, (fontSize() * gl.scaleV) / 10.0); |
gly.map(chma); |
m_ps->PS_translate(0, -(fontSize() - fontSize() * gl.scaleV)); |
m_ps->SetColor(strokeColor().color, strokeColor().shade, &h, &s, &v, &k); |
m_ps->PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
m_ps->SetClipPath(&gly, true); |
m_ps->PS_closepath(); |
m_ps->putColor(strokeColor().color, strokeColor().shade, false); |
if (gl.scaleH != 1.0 || gl.scaleV != 1.0) |
m_ps->PS_scale(gl.scaleH, gl.scaleV); |
if (fill) |
m_ps->putColorNoDraw(fillColor().color, fillColor().shade); |
m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false); |
} |
m_ps->PS_restore(); |
} |
void PSPainter::drawRect(QRectF rect) |
{ |
int h, s, v, k; |
m_ps->PS_save(); |
applyTransform(); |
m_ps->PS_moveto(x() + rect.x(), -y() - rect.y()); |
m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y()); |
m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y() - rect.height()); |
m_ps->PS_lineto(x() + rect.x(), -y() - rect.y() - rect.height()); |
m_ps->PS_closepath(); |
m_ps->SetColor(fillColor().color, fillColor().shade, &h, &s, &v, &k); |
m_ps->PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
m_ps->putColor(fillColor().color, fillColor().shade, true); |
m_ps->PS_restore(); |
} |
void PSPainter::drawLine(QPointF start, QPointF end) |
{ |
int h, s, v, k ; |
QVector<double> dum; |
dum.clear(); |
m_ps->PS_save(); |
applyTransform(); |
if (fillColor().color != CommonStrings::None) |
{ |
m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin); |
m_ps->PS_setdash(Qt::SolidLine, 0, dum); |
m_ps->SetColor(fillColor().color,fillColor().shade, &h, &s, &v, &k); |
m_ps->PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
m_ps->PS_setlinewidth(strokeWidth()); |
m_ps->PS_moveto(x() + start.x(), -y() - start.y()); |
m_ps->PS_lineto(x() + end.x(), -y() - end.y()); |
m_ps->putColor(fillColor().color, fillColor().shade, false); |
m_ps->PS_restore(); |
} |
void PSPainter::drawObject(PageItem* item) |
{ |
m_ps->PS_save(); |
m_ps->PS_translate(x(), -y()); |
applyTransform(); |
if (scaleH() != 1 || scaleV() != 1) |
m_ps->PS_scale(scaleH(), scaleV()); |
m_ps->ProcessItem(m_Doc, m_page, item, m_argh, m_sep, m_farb, m_master, true); |
m_ps->PS_restore(); |
} |
PSLib::PSLib(PrintOptions &options, bool psart, SCFonts &AllFonts, QMap<QString, QMap<uint, FPointArray> > DocFonts, ColorList DocColors, bool pdf, bool spot) |
{ |
Options = options; |
555,7 → 700,7 |
PutStream("%%Page: " + IToStr(Seiten) + " " + IToStr(Seiten) + "\n"); |
PutStream("%%PageOrientation: "); |
// when creating EPS files determine the orientation from the bounding box |
if (!psExport) |
if (!psExport) |
{ |
if ((pg->width() - Ma->left() - Ma->right()) <= (pg->height() - Ma->bottom() - Ma->top())) |
PutStream("Portrait\n"); |
1665,14 → 1810,8 |
bool PSLib::ProcessItem(ScribusDoc* Doc, ScPage* a, PageItem* c, uint PNr, bool sep, bool farb, bool master, bool embedded, bool useTemplate) |
{ |
double tsz; |
int h, s, v, k; |
int d; |
int savedOwnPage; |
//ScText *hl; |
QVector<double> dum; |
QChar chstr; |
QString tmps; |
if (c->printEnabled()) |
{ |
fillRule = true; |
2156,401 → 2295,7 |
PS_restore(); |
} |
} |
savedOwnPage = c->OwnPage; |
c->OwnPage = PNr-1; |
c->asPathText()->layout(); |
c->OwnPage = savedOwnPage; |
for (d = 0; d < c->maxCharsInFrame(); ++d) |
{ |
// hl = c->asPathText()->itemRenderText.item_p(d); |
chstr = c->asPathText()->itemRenderText.text(d); |
if ((chstr == QChar(13)) || (chstr == QChar(30)) || (chstr == QChar(9)) || (chstr == QChar(28))) |
continue; |
const CharStyle & style(c->asPathText()->itemRenderText.charStyle(d)); |
const PathData& pdata(c->textLayout.point(d)); |
const GlyphLayout* glyphs(c->asPathText()->itemRenderText.getGlyphs(d)); |
PageItem* embItem = c->asPathText()->itemRenderText.hasObject(d)? |
c->asPathText()->itemRenderText.object(d) : NULL; |
QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) ); |
tsz = style.fontSize(); |
if (chstr == QChar(29)) |
chstr = ' '; |
if (chstr == QChar(0xA0)) |
chstr = ' '; |
if (style.effects() & ScStyle_AllCaps) |
{ |
if (chstr.toUpper() != chstr) |
chstr = chstr.toUpper(); |
} |
if (style.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
tsz = style.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100; |
chstr = chstr.toUpper(); |
} |
} |
if (style.effects() & ScStyle_Superscript) |
tsz = style.fontSize() * Doc->typographicPrefs().scalingSuperScript / 100; |
if (style.effects() & ScStyle_Subscript) |
tsz = style.fontSize() * Doc->typographicPrefs().scalingSubScript / 100; |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
if (embItem != NULL) |
{ |
PS_save(); |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (c->textPathFlipped) |
{ |
PutStream("[1 0 0 -1 0 0]\n"); |
PutStream("[0 0 0 0 0 0] concatmatrix\n"); //??????? |
} |
if (c->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x()< 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
// PS_translate(0, (tsz / 10.0)); |
if (c->BaseOffs != 0) |
PS_translate(0, -c->BaseOffs); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
QList<PageItem*> emG; |
if (embItem->isGroup()) |
emG = embItem->getItemList(); |
else |
emG.append(embItem); |
for (int em = 0; em < emG.count(); ++em) |
{ |
PageItem* embedded = emG.at(em); |
PS_save(); |
PS_translate(embedded->gXpos * (style.scaleH() / 1000.0), ((embedded->gHeight * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))); |
if (style.baselineOffset() != 0) |
PS_translate(0, embedded->gHeight * (style.baselineOffset() / 1000.0)); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
if (style.scaleV() != 1000) |
PS_scale(1, style.scaleV() / 1000.0); |
ProcessItem(Doc, a, embedded, PNr, sep, farb, master, true); |
PS_restore(); |
} |
PS_restore(); |
continue; |
} |
/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */ |
if (FontSubsetMap.contains(style.font().scName())) |
{ |
// uint chr = chstr.unicode(); |
uint chr = style.font().char2CMap(chstr); |
if (style.font().canRender(chstr)) |
{ |
PS_save(); |
if (style.fillColor() != CommonStrings::None) |
{ |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (c->textPathFlipped) |
{ |
PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n"); |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\n"); |
} |
if (c->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
PS_translate(0, (tsz / 10.0)); |
if (c->BaseOffs != 0) |
PS_translate(0, -c->BaseOffs); |
if (glyphs->xoffset !=0 || glyphs->yoffset != 0) |
PS_translate(glyphs->xoffset, -glyphs->yoffset); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13))) |
|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr))) |
{ |
PS_save(); |
PS_translate(0, -(tsz / 10.0)); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
if (style.effects() & ScStyle_Subscript) |
{ |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
} |
else |
{ |
PS_moveto(glyphs->xoffset , glyphs->yoffset+Upos); |
PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos); |
} |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
if (chstr != ' ') |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
PS_save(); |
PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0); |
putColorNoDraw(style.strokeColor(), style.strokeShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false); |
PS_restore(); |
} |
putColorNoDraw(style.fillColor(), style.fillShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false); |
if ((style.effects() & ScStyle_Outline)) |
{ |
if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0)) |
{ |
PS_save(); |
PS_setlinewidth(tsz * style.outlineWidth() / 10000.0); |
putColorNoDraw(style.strokeColor(), style.strokeShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, true); |
PS_restore(); |
} |
} |
} |
if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP)) |
{ |
PS_save(); |
PS_translate(0, -(tsz / 10.0)); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
} |
PS_restore(); |
} |
} |
else |
{ |
uint glyph = glyphs->glyph; |
PS_selectfont(style.font().replacementName(), tsz / 10.0); |
PS_save(); |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (c->textPathFlipped) |
{ |
PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n"); |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\n"); |
} |
if (c->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (c->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
if (c->BaseOffs != 0) |
PS_translate(0, -c->BaseOffs); |
if (glyphs->xoffset !=0 || glyphs->yoffset != 0) |
PS_translate(glyphs->xoffset, -glyphs->yoffset); |
if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13))) |
|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr))) |
{ |
PS_save(); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
if (style.effects() & ScStyle_Subscript) |
{ |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
} |
else |
{ |
PS_moveto(glyphs->xoffset , glyphs->yoffset+Upos); |
PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos); |
} |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
if (chstr != ' ') |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
PS_save(); |
PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0); |
PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.strokeColor(), style.strokeShade()); |
PS_restore(); |
} |
PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.fillColor(), style.fillShade()); |
if ((style.effects() & ScStyle_Outline)) |
{ |
if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0)) |
{ |
uint gl = style.font().char2CMap(chstr); |
FPointArray gly = style.font().glyphOutline(gl); |
QTransform chma; |
chma.scale(tsz / 100.0, tsz / 100.0); |
gly.map(chma); |
PS_save(); |
PS_setlinewidth(tsz * style.outlineWidth() / 10000.0); |
PS_translate(0, tsz / 10.0); |
SetColor(style.strokeColor(), style.strokeShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
SetClipPath(&gly); |
PS_closepath(); |
putColor(style.strokeColor(), style.strokeShade(), false); |
PS_restore(); |
} |
} |
} |
if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP)) |
{ |
PS_save(); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
PS_restore(); |
} |
} |
setTextSt(Doc, c, PNr-1, a, sep, farb, master); |
break; |
case PageItem::Symbol: |
if (m_Doc->docPatterns.contains(c->pattern())) |
3221,10 → 2966,6 |
} |
else if (ite->asPathText()) |
{ |
double tsz; |
int d; |
//ScText *hl; |
QChar chstr; |
PS_save(); |
PS_translate(ite->xPos() - mPage->xOffset(), mPage->height() - (ite->yPos() - mPage->yOffset())); |
if (ite->PoShow) |
3270,400 → 3011,7 |
PS_restore(); |
} |
} |
int savedOwnPage = ite->OwnPage; |
ite->OwnPage = PNr; |
ite->asPathText()->layout(); |
ite->OwnPage = savedOwnPage; |
for (d = 0; d < ite->maxCharsInFrame(); ++d) |
{ |
//hl = ite->asPathText()->itemRenderText.item_p(d); |
chstr = ite->asPathText()->itemRenderText.text(d); |
const CharStyle & style(ite->asPathText()->itemRenderText.charStyle(d)); |
if ((chstr == QChar(13)) || (chstr == QChar(30)) || (chstr == QChar(9)) || (chstr == QChar(28))) |
continue; |
const PathData& pdata(ite->textLayout.point(d)); |
const GlyphLayout* glyphs(ite->asPathText()->itemRenderText.getGlyphs(d)); |
PageItem* embItem = ite->asPathText()->itemRenderText.hasObject(d)? |
ite->asPathText()->itemRenderText.object(d) : NULL; |
QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) ); |
tsz = style.fontSize(); |
if (chstr == QChar(29)) |
chstr = ' '; |
if (chstr == QChar(0xA0)) |
chstr = ' '; |
if (style.effects() & ScStyle_AllCaps) |
{ |
if (chstr.toUpper() != chstr) |
chstr = chstr.toUpper(); |
} |
if (style.effects() & ScStyle_SmallCaps) |
{ |
if (chstr.toUpper() != chstr) |
{ |
tsz = style.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100; |
chstr = chstr.toUpper(); |
} |
} |
if (style.effects() & ScStyle_Superscript) |
tsz = style.fontSize() * Doc->typographicPrefs().scalingSuperScript / 100; |
if (style.effects() & ScStyle_Subscript) |
tsz = style.fontSize() * Doc->typographicPrefs().scalingSubScript / 100; |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
if (embItem != NULL) |
{ |
PS_save(); |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (ite->textPathFlipped) |
{ |
PutStream("[1 0 0 -1 0 0]\n"); |
PutStream("[0 0 0 0 0 0] concatmatrix\n"); //??????? |
} |
if (ite->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x()< 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
// PS_translate(0, (tsz / 10.0)); |
if (ite->BaseOffs != 0) |
PS_translate(0, -ite->BaseOffs); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
QList<PageItem*> emG; |
if (embItem->isGroup()) |
emG = embItem->getItemList(); |
else |
emG.append(embItem); |
for (int em = 0; em < emG.count(); ++em) |
{ |
PageItem* embedded = emG.at(em); |
PS_save(); |
PS_translate(embedded->gXpos * (style.scaleH() / 1000.0), ((embedded->gHeight * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))); |
if (style.baselineOffset() != 0) |
PS_translate(0, embedded->gHeight * (style.baselineOffset() / 1000.0)); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
if (style.scaleV() != 1000) |
PS_scale(1, style.scaleV() / 1000.0); |
ProcessItem(Doc, mPage, embedded, PNr, sep, farb, true, true); |
PS_restore(); |
} |
PS_restore(); |
continue; |
} |
/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */ |
if (FontSubsetMap.contains(style.font().scName())) |
{ |
// uint chr = chstr.unicode(); |
uint chr = style.font().char2CMap(chstr); |
if (style.font().canRender(chstr)) |
{ |
PS_save(); |
if (style.fillColor() != CommonStrings::None) |
{ |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (ite->textPathFlipped) |
{ |
PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n"); |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\n"); |
} |
if (ite->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
PS_translate(0, (tsz / 10.0)); |
if (ite->BaseOffs != 0) |
PS_translate(0, -ite->BaseOffs); |
if (glyphs->xoffset !=0 || glyphs->yoffset != 0) |
PS_translate(glyphs->xoffset, -glyphs->yoffset); |
if (style.scaleH() != 1000) |
PS_scale(style.scaleH() / 1000.0, 1); |
if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13))) |
|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr))) |
{ |
PS_save(); |
PS_translate(0, -(tsz / 10.0)); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
if (style.effects() & ScStyle_Subscript) |
{ |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
} |
else |
{ |
PS_moveto(glyphs->xoffset , glyphs->yoffset+Upos); |
PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos); |
} |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
if (chstr != ' ') |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
PS_save(); |
PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0); |
putColorNoDraw(style.strokeColor(), style.strokeShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false); |
PS_restore(); |
} |
putColorNoDraw(style.fillColor(), style.fillShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false); |
if ((style.effects() & ScStyle_Outline)) |
{ |
if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0)) |
{ |
PS_save(); |
PS_setlinewidth(tsz * style.outlineWidth() / 10000.0); |
putColorNoDraw(style.strokeColor(), style.strokeShade()); |
PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, true); |
PS_restore(); |
} |
} |
} |
if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP)) |
{ |
PS_save(); |
PS_translate(0, -(tsz / 10.0)); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
} |
PS_restore(); |
} |
} |
else |
{ |
uint glyph = glyphs->glyph; |
PS_selectfont(style.font().replacementName(), tsz / 10.0); |
PS_save(); |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n"); |
if (ite->textPathFlipped) |
{ |
PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n"); |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\n"); |
} |
if (ite->textPathType == 0) |
PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 1) |
PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else if (ite->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
else |
PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n"); |
} |
PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n"); |
if (ite->BaseOffs != 0) |
PS_translate(0, -ite->BaseOffs); |
if (glyphs->xoffset !=0 || glyphs->yoffset != 0) |
PS_translate(glyphs->xoffset, -glyphs->yoffset); |
if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13))) |
|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr))) |
{ |
PS_save(); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().underlinePos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
if (style.effects() & ScStyle_Subscript) |
{ |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
} |
else |
{ |
PS_moveto(glyphs->xoffset , glyphs->yoffset+Upos); |
PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos); |
} |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
if (chstr != ' ') |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
PS_save(); |
PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0); |
PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.strokeColor(), style.strokeShade()); |
PS_restore(); |
} |
PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.fillColor(), style.fillShade()); |
if ((style.effects() & ScStyle_Outline)) |
{ |
if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0)) |
{ |
uint gl = style.font().char2CMap(chstr); |
FPointArray gly = style.font().glyphOutline(gl); |
QTransform chma; |
chma.scale(tsz / 100.0, tsz / 100.0); |
gly.map(chma); |
PS_save(); |
PS_setlinewidth(tsz * style.outlineWidth() / 10000.0); |
PS_translate(0, tsz / 10.0); |
SetColor(style.strokeColor(), style.strokeShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
SetClipPath(&gly); |
PS_closepath(); |
putColor(style.strokeColor(), style.strokeShade(), false); |
PS_restore(); |
} |
} |
} |
if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP)) |
{ |
PS_save(); |
double Ulen = glyphs->xadvance; |
double Upos, Uwid; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = style.font().strikeoutPos(style.fontSize() / 10.0); |
Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0); |
if (style.fillColor() != CommonStrings::None) |
if (style.fillColor() != CommonStrings::None) |
{ |
SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(Uwid); |
PS_moveto(glyphs->xoffset , Upos); |
PS_lineto(glyphs->xoffset+Ulen, Upos); |
putColor(style.fillColor(), style.fillShade(), false); |
PS_restore(); |
} |
PS_restore(); |
} |
} |
setTextSt(Doc, ite, PNr, mPage, sep, farb, true); |
PS_restore(); |
} |
if (!success) |
5056,573 → 4404,11 |
*/ |
void PSLib::setTextSt(ScribusDoc* Doc, PageItem* ite, uint argh, ScPage* pg, bool sep, bool farb, bool master) |
{ |
// qDebug() << QString("pslib setTextSt: ownPage=%1 pageNr=%2 OnMasterPage=%3;").arg(ite->OwnPage).arg(pg->pageNr()).arg(ite->OnMasterPage); |
int tabCc = 0; |
int savedOwnPage = ite->OwnPage; |
double tabDist = ite->textToFrameDistLeft(); |
QList<ParagraphStyle::TabRecord> tTabValues; |
ite->OwnPage = argh; |
ite->layout(); |
ite->OwnPage = savedOwnPage; |
if (ite->lineColor() != CommonStrings::None) |
tabDist += ite->lineWidth() / 2.0; |
uint llp = 0; |
while (llp < ite->textLayout.lines()) |
{ |
LineSpec ls = ite->textLayout.line(llp++); |
const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
double y0 = ls.y; |
double y2 = ls.y; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < ite->textLayout.lines()) |
{ |
ls = ite->textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (ite->itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (ite->itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < ite->textLayout.lines()) |
{ |
if ((ite->textLayout.line(llp + 1).lastItem - ite->textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < ite->textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent); |
llp++; |
} |
QRectF scr(lMarg + adjX, y0 - ascent, ite->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
PS_save(); |
SetPathAndClip(ite->PoLine, true); |
int h, s, v, k; |
SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), &h, &s, &v, &k); |
PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
PS_moveto(scr.x(), -scr.y()); |
PS_lineto(scr.x() + scr.width(), -scr.y()); |
PS_lineto(scr.x() + scr.width(), -scr.y() - scr.height()); |
PS_lineto(scr.x(), -scr.y() - scr.height()); |
PS_closepath(); |
putColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), true); |
PS_restore(); |
} |
} |
for (uint ll=0; ll < ite->textLayout.lines(); ++ll) |
{ |
LineSpec ls = ite->textLayout.line(ll); |
tabDist = ls.x; |
double CurX = ls.x; |
double CurXB = ls.x; |
QRectF scrG; |
QString oldBack = ""; |
double oldShade = 100; |
int last = qMin(ls.lastItem, ite->itemText.length() - 1); |
for (int a = ls.firstItem; a <= last; ++a) |
{ |
const GlyphLayout* glyphs(ite->itemText.getGlyphs(a)); |
const CharStyle& charStyle(ite->itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
// This code is for rendering character background color. |
int h, s, v, k; |
SetColor(charStyle.backColor(), charStyle.backShade(), &h, &s, &v, &k); |
PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = Doc->guidesPrefs().valueBaselineGrid; |
else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = LineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (ite->textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (LineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= LineStyle.dropCapLines(); |
if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= LineStyle.lineSpacing(); |
else if (ite->firstLineOffset() == FLOPRealGlyphHeight || ite->firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= LineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scr; |
if (ite->itemText.hasObject(a)) |
{ |
PageItem* obj = ite->itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scr = QRectF(CurXB, ls.y - hh, ww , hh); |
} |
else |
scr = QRectF(CurXB, y1, glyphs->wide(), hl); |
if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scrG |= scr; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
PS_save(); |
PS_moveto(scrG.x(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height()); |
PS_lineto(scrG.x(), -scrG.y() - scrG.height()); |
PS_closepath(); |
SetColor(oldBack, oldShade, &h, &s, &v, &k); |
PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
putColor(oldBack, oldShade, true); |
PS_restore(); |
scrG = scr; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
} |
else |
{ |
if (!scrG.isNull()) |
{ |
PS_save(); |
PS_moveto(scrG.x(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height()); |
PS_lineto(scrG.x(), -scrG.y() - scrG.height()); |
PS_closepath(); |
putColor(oldBack, oldShade, true); |
PS_restore(); |
} |
oldBack = ""; |
oldShade = 100; |
scrG = QRectF(); |
} |
CurXB += glyphs->wide(); |
} |
if (!scrG.isNull()) |
{ |
PS_save(); |
PS_moveto(scrG.x(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y()); |
PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height()); |
PS_lineto(scrG.x(), -scrG.y() - scrG.height()); |
PS_closepath(); |
putColor(oldBack, oldShade, true); |
PS_restore(); |
} |
for (int d = ls.firstItem; d <= ls.lastItem; ++d) |
{ |
//ScText *hl = ite->itemText.item_p(d); |
QChar chr = ite->itemText.text(d); |
const CharStyle & cstyle(ite->itemText.charStyle(d)); |
const ParagraphStyle& pstyle(ite->itemText.paragraphStyle(d)); |
const GlyphLayout* glyphs(ite->itemText.getGlyphs(d)); |
LayoutFlags flags = ite->itemText.flags(d); |
// if ((hl->ch == QChar(13)) || (hl->ch == QChar(10)) || (hl->ch == QChar(28)) || (hl->ch == QChar(27)) || (hl->ch == QChar(26))) |
// continue; |
if (flags & ScLayout_SuppressSpace) |
continue; |
tTabValues = pstyle.tabValues(); |
if (flags & ScLayout_StartOfLine) |
tabCc = 0; |
if ((chr == SpecialChars::TAB) && (tTabValues.count() != 0)) |
{ |
QChar tabFillChar; |
const TabLayout* tabLayout = dynamic_cast<const TabLayout*>(glyphs->more); |
if (tabLayout) |
tabFillChar = tabLayout->fillChar; |
if (!tabFillChar.isNull()) |
{ |
//ScText hl2; |
//static_cast<CharStyle&>(hl2) = static_cast<const CharStyle&>(*hl); |
const GlyphLayout * const gl = glyphs->more; |
double scale = gl ? gl->scaleV : 1.0; |
double wt = cstyle.font().charWidth(tabFillChar, cstyle.fontSize() * scale / 10.0); |
double len = glyphs->xadvance; |
int coun = static_cast<int>(len / wt); |
// JG - #6728 : update code according to fillInTabLeaders() and PageItem::layout() |
double sPos = 0.0 /*CurX - len + cstyle.fontSize() / 10.0 * 0.7 + 1*/; |
//hl2.ch = tabFillChar; |
//hl2.setTracking(0); |
//hl2.setScaleH(1000); |
//hl2.setScaleV(1000); |
//hl2.glyph.glyph = cstyle.font().char2CMap(tabFillChar); |
//hl2.glyph.yoffset = glyphs->yoffset; |
GlyphLayout gl2 = *gl; |
gl2.glyph = cstyle.font().char2CMap(tabFillChar); |
gl2.yoffset = glyphs->yoffset; |
CharStyle shadow(cstyle); |
shadow.setFillColor(cstyle.strokeColor()); |
for (int cx = 0; cx < coun; ++cx) |
{ |
gl2.xoffset = sPos + wt * cx; |
if ((cstyle.effects() & ScStyle_Shadowed) && (cstyle.strokeColor() != CommonStrings::None)) |
{ |
//ScText hl3; |
//static_cast<CharStyle&>(hl3) = static_cast<const CharStyle&>(hl2); |
//hl3.ch = hl2.ch; |
//hl3.glyph.glyph = hl2.glyph.glyph; |
//hl3.setFillColor(hl2.strokeColor()); |
//hl3.glyph.yoffset = hl2.glyph.yoffset - (hl2.fontSize() * hl2.shadowYOffset() / 10000.0); |
//hl3.glyph.xoffset = hl2.glyph.xoffset + (hl2.fontSize() * hl2.shadowXOffset() / 10000.0); |
GlyphLayout gl3 = gl2; |
gl3.yoffset = gl2.yoffset - (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0); |
gl3.xoffset = gl2.xoffset + (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0); |
setTextCh(Doc, ite, CurX, ls.y, argh, d, tabFillChar, &gl3, shadow, pstyle, pg, sep, farb, master); |
} |
setTextCh(Doc, ite, CurX, ls.y, argh, d, tabFillChar, &gl2, cstyle, pstyle, pg, sep, farb, master); |
} |
} |
tabCc++; |
} |
if (chr == SpecialChars::TAB) { |
CurX += glyphs->wide(); |
continue; |
} |
if ((cstyle.effects() & ScStyle_Shadowed) && (cstyle.strokeColor() != CommonStrings::None)) |
{ |
const GlyphLayout *gl1 = glyphs; |
GlyphLayout* gl2 = new GlyphLayout(*gl1); |
GlyphLayout* gl3 = gl2; |
while (gl1->more) |
{ |
gl2->more = new GlyphLayout(*gl1->more); |
gl2->more->yoffset -= (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0); |
gl2->more->xoffset += (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0); |
gl2->more->more = NULL; |
gl1 = gl1->more; |
gl2 = gl2->more; |
} |
CharStyle shadowed(cstyle); |
shadowed.setFillColor(cstyle.strokeColor()); |
shadowed.setFillShade(cstyle.strokeShade()); |
gl2->xadvance = glyphs->xadvance; |
gl2->yadvance = glyphs->yadvance; |
gl2->yoffset = glyphs->yoffset - (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0); |
gl2->xoffset = glyphs->xoffset + (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0); |
gl2->scaleH = glyphs->scaleH; |
gl2->scaleV = glyphs->scaleV; |
setTextCh(Doc, ite, CurX, ls.y, argh, d, chr, gl2, shadowed, pstyle, pg, sep, farb, master); |
while (gl3->more) { |
GlyphLayout* more = gl3->more; |
gl3->more = gl3->more->more; |
delete more; |
} |
delete gl3; |
} |
setTextCh(Doc, ite, CurX, ls.y, argh, d, chr, glyphs, cstyle, pstyle, pg, sep, farb, master); |
// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG |
/*if (hl->ch == SpecialChars::OBJECT) |
{ |
InlineFrame& embedded(const_cast<InlineFrame&>(hl->embedded)); |
CurX += (embedded.getItem()->gWidth + embedded.getItem()->lineWidth()) * glyphs->scaleH; |
} |
else*/ |
CurX += glyphs->wide(); |
tabDist = CurX; |
} |
} |
PSPainter p(Doc, argh, pg, sep, farb, master, this); |
ite->textLayout.renderBackground(&p); |
ite->textLayout.render(&p); |
} |
void PSLib::setTextCh(ScribusDoc* Doc, PageItem* ite, double x, double y, uint argh, uint doh, QChar chstr, const GlyphLayout* glyphs, const CharStyle& cstyle, const ParagraphStyle& pstyle, ScPage* pg, bool sep, bool farb, bool master) |
{ |
//QChar chstr = hl->ch; |
//const CharStyle & cstyle(*hl); |
//const GlyphLayout* glyphs(&(hl->glyph)); |
uint glyph = glyphs->glyph; |
int h, s, v, k; |
double tsz; |
double wideR = 0.0; |
QVector<double> dum; |
dum.clear(); |
tsz = cstyle.fontSize(); |
/* if (cstyle.effects() & ScStyle_DropCap) |
{ |
// QString chstr; // dummy, FIXME: replace by glyph |
if (pstyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
tsz = qRound(10 * ((Doc->typographicSettings.valueBaseGrid * (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (cstyle.font().realCharHeight(chstr, 10)))); |
else |
{ |
if (pstyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
tsz = qRound(10 * ((pstyle.lineSpacing() * (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (cstyle.font().realCharHeight(chstr, 10)))); |
else |
{ |
double currasce = cstyle.font().height(pstyle.charStyle().fontSize()); |
tsz = qRound(10 * ((currasce * (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / cstyle.font().realCharHeight(chstr, 10))); |
} |
} |
} |
*/ |
if (ite->itemText.hasObject(doh-1)) |
{ |
PageItem* embedded = ite->itemText.object(doh-1); |
PS_save(); |
PS_translate(x + glyphs->xoffset + embedded->gXpos * (cstyle.scaleH() / 1000.0), (y + glyphs->yoffset - (embedded->gHeight * (cstyle.scaleV() / 1000.0)) + embedded->gYpos * (cstyle.scaleV() / 1000.0)) * -1); |
if (doh == 0 || ite->itemText.text(doh-1) == SpecialChars::PARSEP) |
{ |
if ((cstyle.baselineOffset() != 0) && (!pstyle.hasDropCap())) |
PS_translate(0, embedded->gHeight * (cstyle.baselineOffset() / 1000.0)); |
} |
else |
{ |
if (cstyle.baselineOffset() != 0) |
PS_translate(0, embedded->gHeight * (cstyle.baselineOffset() / 1000.0)); |
} |
if (cstyle.scaleH() != 1000) |
PS_scale(cstyle.scaleH() / 1000.0, 1); |
if (cstyle.scaleV() != 1000) |
PS_scale(1, cstyle.scaleV() / 1000.0); |
ProcessItem(Doc, pg, embedded, argh, sep, farb, master, true); |
PS_restore(); |
return; |
} |
if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) || |
glyph == (ScFace::CONTROL_GLYPHS + 32)) |
{ |
glyph = cstyle.font().char2CMap(QChar(' ')); |
chstr = ' '; |
} |
else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) |
{ |
glyph = cstyle.font().char2CMap(QChar('-')); |
chstr = '-'; |
} |
if (glyph < ScFace::CONTROL_GLYPHS) |
{ |
if (((cstyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13))) |
|| ((cstyle.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr))) |
{ |
// double Ulen = cstyle.font().glyphWidth(glyph, cstyle.fontSize()) * glyphs->scaleH; |
double Ulen = glyphs->xadvance; |
double Upos, lw; |
if ((cstyle.underlineOffset() != -1) || (cstyle.underlineWidth() != -1)) |
{ |
if (cstyle.underlineOffset() != -1) |
Upos = (cstyle.underlineOffset() / 1000.0) * (cstyle.font().descent(cstyle.fontSize() / 10.0)); |
else |
Upos = cstyle.font().underlinePos(cstyle.fontSize() / 10.0); |
if (cstyle.underlineWidth() != -1) |
lw = (cstyle.underlineWidth() / 1000.0) * (cstyle.fontSize() / 10.0); |
else |
lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = cstyle.font().underlinePos(cstyle.fontSize() / 10.0); |
lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0); |
} |
if (cstyle.baselineOffset() != 0) |
Upos += (cstyle.fontSize() / 10.0) * glyphs->scaleV * (cstyle.baselineOffset() / 1000.0); |
if (cstyle.fillColor() != CommonStrings::None) |
{ |
PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin); |
PS_setdash(Qt::SolidLine, 0, dum); |
SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(lw); |
if (cstyle.effects() & ScStyle_Subscript) |
{ |
PS_moveto(x + glyphs->xoffset , -y - glyphs->yoffset+Upos); |
PS_lineto(x + glyphs->xoffset+Ulen, -y - glyphs->yoffset+Upos); |
} |
else |
{ |
PS_moveto(x + glyphs->xoffset , -y + Upos); |
PS_lineto(x + glyphs->xoffset+Ulen, -y + Upos); |
} |
putColor(cstyle.fillColor(), cstyle.fillShade(), false); |
} |
/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */ |
if (FontSubsetMap.contains(cstyle.font().scName())) |
{ |
if (glyph != 0 && glyph != cstyle.font().char2CMap(QChar(' ')) && (!SpecialChars::isBreak(chstr))) |
{ |
PS_save(); |
if (ite->reversed()) |
{ |
PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (tsz / 10.0)) * -1); |
PS_scale(-1, 1); |
PS_translate(-glyphs->xadvance, 0); |
} |
else |
PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (cstyle.fontSize() / 10.0)) * -1); |
if (cstyle.baselineOffset() != 0) |
PS_translate(0, (cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0)); |
if (glyphs->scaleH != 1.0) |
PS_scale(glyphs->scaleH, 1); |
if (glyphs->scaleV != 1.0) |
{ |
PS_translate(0, -((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV))); |
PS_scale(1, glyphs->scaleV); |
} |
if (cstyle.fillColor() != CommonStrings::None) |
{ |
putColorNoDraw(cstyle.fillColor(), cstyle.fillShade()); |
PS_showSub(glyph, FontSubsetMap[cstyle.font().scName()], tsz / 10.0, false); |
} |
PS_restore(); |
} |
} |
else if (glyph != 0) |
{ |
PS_selectfont(cstyle.font().replacementName(), tsz / 10.0); |
PS_save(); |
PS_translate(x + glyphs->xoffset, -y - glyphs->yoffset); |
if (ite->reversed()) |
{ |
PS_scale(-1, 1); |
PS_translate(glyphs->xadvance, 0); |
} |
if (cstyle.baselineOffset() != 0) |
PS_translate(0, (cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0)); |
if (glyphs->scaleH != 1.0 || glyphs->scaleV != 1.0) |
PS_scale(glyphs->scaleH, glyphs->scaleV); |
if (cstyle.fillColor() != CommonStrings::None) |
{ |
PS_show_xyG(cstyle.font().replacementName(), glyph, 0, 0, cstyle.fillColor(), cstyle.fillShade()); |
} |
PS_restore(); |
} |
if ((cstyle.effects() & ScStyle_Outline) || glyph == 0)//&& (chstr != QChar(13))) |
{ |
// if (cstyle.font().canRender(chstr)) |
{ |
FPointArray gly = cstyle.font().glyphOutline(glyph); |
QTransform chma, chma2, chma3; |
chma.scale(tsz / 100.0, tsz / 100.0); |
chma2.scale(glyphs->scaleH, glyphs->scaleV); |
if (cstyle.baselineOffset() != 0) |
chma3.translate(0, -(cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0)); |
gly.map(chma * chma2 * chma3); |
if (ite->reversed()) |
{ |
chma = QTransform(); |
chma.scale(-1, 1); |
chma.translate(wideR, 0); |
gly.map(chma); |
} |
if ((cstyle.strokeColor() != CommonStrings::None) && ((tsz * cstyle.outlineWidth() / 10000.0) != 0)) |
{ |
PS_save(); |
PS_setlinewidth(tsz * cstyle.outlineWidth() / 10000.0); |
PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin); |
PS_setdash(Qt::SolidLine, 0, dum); |
PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (tsz / 10.0)) * -1); |
PS_translate(0, -((tsz / 10.0) - (tsz / 10.0) * glyphs->scaleV)); |
SetColor(cstyle.strokeColor(), cstyle.strokeShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
SetClipPath(&gly); |
PS_closepath(); |
putColor(cstyle.strokeColor(), cstyle.strokeShade(), false); |
PS_restore(); |
} |
} |
} |
if ((cstyle.effects() & ScStyle_Strikethrough))//&& (chstr != QChar(13))) |
{ |
// double Ulen = cstyle.font().glyphWidth(glyph, cstyle.fontSize()) * glyphs->scaleH; |
double Ulen = glyphs->xadvance; |
double Upos, lw; |
if ((cstyle.strikethruOffset() != -1) || (cstyle.strikethruWidth() != -1)) |
{ |
if (cstyle.strikethruOffset() != -1) |
Upos = (cstyle.strikethruOffset() / 1000.0) * (cstyle.font().ascent(cstyle.fontSize() / 10.0)); |
else |
Upos = cstyle.font().strikeoutPos(cstyle.fontSize() / 10.0); |
if (cstyle.strikethruWidth() != -1) |
lw = (cstyle.strikethruWidth() / 1000.0) * (cstyle.fontSize() / 10.0); |
else |
lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = cstyle.font().strikeoutPos(cstyle.fontSize() / 10.0); |
lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0); |
} |
if (cstyle.baselineOffset() != 0) |
Upos += (cstyle.fontSize() / 10.0) * glyphs->scaleV * (cstyle.baselineOffset() / 1000.0); |
if (cstyle.fillColor() != CommonStrings::None) |
{ |
PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin); |
PS_setdash(Qt::SolidLine, 0, dum); |
SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
} |
PS_setlinewidth(lw); |
PS_moveto(x + glyphs->xoffset , -y-glyphs->yoffset+Upos); |
PS_lineto(x + glyphs->xoffset+Ulen, -y-glyphs->yoffset+Upos); |
putColor(cstyle.fillColor(), cstyle.fillShade(), false); |
} |
} |
if (glyphs->more) { |
//// ugly hack until setTextCh interface is changed |
//ScText hl2(*hl); |
//hl2.glyph = *glyphs->more; |
setTextCh(Doc, ite, x + glyphs->xadvance, y, argh, doh, chstr, glyphs->more, cstyle, pstyle, pg, sep, farb, master); |
//// don't let hl2's destructor delete these! |
//hl2.glyph.more = 0; |
} |
/* if (cstyle.effects() & ScStyle_SoftHyphenVisible) |
{ |
int chs = cstyle.fontSize(); |
// double wide = cstyle.font().charWidth(chstr, chs) * (cstyle.scaleH() / 1000.0); |
// chstr = '-'; |
// if (cstyle.font().canRender(chstr)) |
{ |
FPointArray gly = cstyle.font().glyphOutline(glyph); |
QTransform chma; |
chma.scale(tsz / 100.0, tsz / 100.0); |
gly.map(chma); |
chma = QTransform(); |
chma.scale(glyphs->scaleH, glyphs->scaleV); |
gly.map(chma); |
if (cstyle.fillColor() != CommonStrings::None) |
{ |
PS_save(); |
PS_newpath(); |
PS_translate(x + glyphs->xoffset + glyphs->xadvance, (y + glyphs->yoffset - (tsz / 10.0)) * -1); |
SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k); |
PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0); |
SetClipPath(&gly); |
PS_closepath(); |
putColor(cstyle.fillColor(), cstyle.fillShade(), true); |
PS_restore(); |
} |
} |
}*/ |
} |
void PSLib::putColor(const QString& colorName, double shade, bool fill) |
{ |
ScColor& color(colorsToUse[colorName]); |
/trunk/Scribus/scribus/pslib.h |
---|
45,6 → 45,7 |
class MultiProgressDialog; |
class ScImage; |
class ScLayer; |
class PSPainter; |
/** |
*@author Franz Schmid |
54,6 → 55,9 |
class SCRIBUS_API PSLib : public QObject |
{ |
Q_OBJECT |
friend class PSPainter; |
public: |
typedef enum |
140,7 → 144,6 |
virtual void SetColor(const QString& color, double shade, int *h, int *s, int *v, int *k); |
virtual void SetColor(const ScColor& color, double shade, int *h, int *s, int *v, int *k); |
virtual void setTextSt(ScribusDoc* Doc, PageItem* ite, uint a, ScPage* pg, bool sep, bool farb, bool master); |
virtual void setTextCh(ScribusDoc* Doc, PageItem* ite, double x, double y, uint a, uint d, QChar chstr, const GlyphLayout* glyphs, const CharStyle& cstyle, const ParagraphStyle& pstyle, ScPage* pg, bool sep, bool farb, bool master); |
bool psExport; |
private: |
/trunk/Scribus/scribus/scpageoutput.cpp |
---|
10,7 → 10,7 |
#include <QPointF> |
#include <QRectF> |
#include <QStack> |
#include <pageitem_textframe.h> |
#include "cmsettings.h" |
#include "collapsedtablepainterex.h" |
#include "commonstrings.h" |
31,11 → 31,13 |
#include "scimage.h" |
#include "scpage.h" |
#include "scpattern.h" |
#include "text/textlayoutpainter.h" |
#include "scribusdoc.h" |
#include "util.h" |
#include "util_formats.h" |
#include "util_math.h" |
#include "text/boxes.h" |
MarksOptions::MarksOptions(void) |
506,167 → 508,6 |
painter->restore(); |
} |
void ScPageOutput::drawGlyphs(PageItem* item, ScPainterExBase *painter, const CharStyle& style, GlyphLayout& glyphs, QRect clip) |
{ |
uint glyph = glyphs.glyph; |
if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode())) // NBSPACE |
glyph = style.font().char2CMap(QChar(' ')); |
else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) // NBHYPHEN |
glyph = style.font().char2CMap(QChar('-')); |
if (glyph >= ScFace::CONTROL_GLYPHS) |
{ |
if (glyphs.more) |
{ |
painter->translate(glyphs.xadvance, 0); |
drawGlyphs(item, painter, style, *glyphs.more, clip); |
} |
return; |
} |
//if (style.font().canRender(QChar(glyph))) |
{ |
QTransform chma, chma2, chma3, chma4, chma5, chma6; |
chma.scale(glyphs.scaleH * style.fontSize() / 100.00, glyphs.scaleV * style.fontSize() / 100.0); |
FPointArray gly = style.font().glyphOutline(glyph); |
// Do underlining first so you can get typographically correct |
// underlines when drawing a white outline |
if ((style.effects() & ScStyle_Underline) || ((style.effects() & ScStyle_UnderlineWords) && (glyph != style.font().char2CMap(QChar(' '))))) |
{ |
double st, lw; |
if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1)) |
{ |
if (style.underlineOffset() != -1) |
st = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0)); |
else |
st = style.font().underlinePos(style.fontSize() / 10.0); |
if (style.underlineWidth() != -1) |
lw = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = style.font().underlinePos(style.fontSize() / 10.0); |
lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0); |
ScColorShade tmpPen = painter->pen(); |
int tmpStrokeMode = painter->strokeMode(); |
painter->setPen(painter->brush()); |
painter->setLineWidth(lw); |
painter->setStrokeMode(1); |
if (style.effects() & ScStyle_Subscript) |
painter->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st)); |
else |
painter->drawLine(FPoint(glyphs.xoffset, -st), FPoint(glyphs.xoffset + glyphs.xadvance, -st)); |
painter->setStrokeMode(tmpStrokeMode); |
painter->setPen(tmpPen); |
} |
if (gly.size() > 3) |
{ |
painter->save(); |
painter->translate(glyphs.xoffset, glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV)); |
if (item->reversed()) |
{ |
painter->scale(-1, 1); |
painter->translate(-glyphs.xadvance, 0); |
} |
if (style.baselineOffset() != 0) |
painter->translate(0, -(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0)); |
double glxSc = glyphs.scaleH * style.fontSize() / 100.00; |
double glySc = glyphs.scaleV * style.fontSize() / 100.0; |
painter->scale(glxSc, glySc); |
painter->setFillMode(ScPainterExBase::Solid); |
bool fr = painter->fillRule(); |
painter->setFillRule(false); |
painter->setupPolygon(&gly, true); |
if (glyph == 0) |
{ |
ScColorShade tmp(PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor, 100); |
painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
painter->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() * 2 / 10000.0); |
painter->strokePath(); |
} |
else if ((style.font().isStroked()) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0)) |
{ |
ScColorShade tmp = painter->brush(); |
painter->setStrokeMode(1); |
painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
painter->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0); |
painter->strokePath(); |
} |
else |
{ |
if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None)) |
{ |
painter->save(); |
painter->translate((style.fontSize() * glyphs.scaleH * style.shadowXOffset() / 10000.0) / glxSc, -(style.fontSize() * glyphs.scaleV * style.shadowYOffset() / 10000.0) / glySc); |
ScColorShade tmp = painter->brush(); |
painter->setBrush(painter->pen()); |
painter->setupPolygon(&gly, true); |
fillPath(item, painter, clip); |
painter->setBrush(tmp); |
painter->restore(); |
painter->setupPolygon(&gly, true); |
} |
if (style.fillColor() != CommonStrings::None) |
fillPath(item, painter, clip); |
if ((style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0)) |
{ |
painter->setStrokeMode(1); |
painter->setLineWidth((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) / glySc); |
painter->strokePath(); |
} |
} |
painter->setFillRule(fr); |
painter->restore(); |
} |
if (style.effects() & ScStyle_Strikethrough) |
{ |
double st, lw; |
if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1)) |
{ |
if (style.strikethruOffset() != -1) |
st = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0)); |
else |
st = style.font().strikeoutPos(style.fontSize() / 10.0); |
if (style.strikethruWidth() != -1) |
lw = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0); |
else |
lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
else |
{ |
st = style.font().strikeoutPos(style.fontSize() / 10.0); |
lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0); |
} |
if (style.baselineOffset() != 0) |
st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0); |
int tmpStrokeMode = painter->strokeMode(); |
painter->setPen(painter->brush()); |
painter->setLineWidth(lw); |
painter->setStrokeMode(1); |
painter->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st)); |
painter->setStrokeMode(tmpStrokeMode); |
} |
} |
/*else |
{ |
painter->setLineWidth(1); |
painter->setPen(ScColorShade(Qt::red, 100)); |
painter->setBrush(ScColorShade(Qt::red, 100)); |
painter->setFillMode(1); |
painter->drawRect(glyphs.xoffset, glyphs.yoffset - (style.fontSize() / 10.0) * glyphs.scaleV , (style.fontSize() / 10.0) * glyphs.scaleH, (style.fontSize() / 10.0) * glyphs.scaleV); |
}*/ |
if (glyphs.more) |
{ |
painter->translate(glyphs.xadvance, 0); |
drawGlyphs(item, painter, style, *glyphs.more, clip); |
} |
} |
void ScPageOutput::drawItem_Embedded( PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded) |
{ |
if (!cembedded) |
1080,185 → 921,185 |
} |
} |
void ScPageOutput::drawItem_PathText( PageItem_PathText* item, ScPainterExBase* painter, QRect clip ) |
class ScpageoutputPainter: public TextLayoutPainter |
{ |
QString chstr; |
//ScText *hl; |
FPoint point = FPoint(0, 0); |
FPoint tangent = FPoint(0, 0); |
double CurX = item->textToFrameDistLeft(); // item->CurX = item->textToFrameDistLeft() |
QString actFill, actStroke; |
double actFillShade, actStrokeShade, dx; |
StoryText& itemText = item->itemText; |
if (item->pathTextShowFrame()) |
private: |
PageItem* m_item; |
ScPainterExBase* m_painter; |
ScPageOutput* m_scpage; |
void setupState() |
{ |
painter->setupPolygon(&item->PoLine, false); |
if (item->NamedLStyle.isEmpty()) |
m_painter->setLineWidth(strokeWidth()); |
ScColorShade fill(m_item->doc()->PageColors[fillColor().color], qRound(fillColor().shade)); |
m_painter->setBrush(fill); |
ScColorShade stroke(m_item->doc()->PageColors[strokeColor().color], qRound(strokeColor().shade)); |
m_painter->setPen(stroke); |
if (matrix() != QTransform()) |
{ |
if (item->lineColor() != CommonStrings::None) |
painter->strokePath(); |
m_painter->setWorldMatrix(matrix() * m_painter->worldMatrix()); |
} |
else |
{ |
multiLine ml = m_doc->MLineStyles[item->NamedLStyle]; |
for (int it = ml.size() - 1; it > -1; it--) |
{ |
const SingleLine& sl = ml[it]; |
if ((sl.Color != CommonStrings::None) && (sl.Width != 0)) |
{ |
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade); |
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash), |
static_cast<Qt::PenCapStyle>(sl.LineEnd), |
static_cast<Qt::PenJoinStyle>(sl.LineJoin)); |
painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0)); |
} |
} |
} |
} |
double totalTextLen = 0.0; |
double totalCurveLen = 0.0; |
double extraOffset = 0.0; |
if (itemText.length() != 0) |
public: |
ScpageoutputPainter(PageItem* item, ScPainterExBase* painter, ScPageOutput* scpage) |
: m_item(item) |
, m_painter(painter) |
, m_scpage(scpage) |
{} |
void translate(double xp, double yp) |
{ |
CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0; |
totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0; |
TextLayoutPainter::translate(xp, yp); |
m_painter->translate(xp, yp); |
} |
for (int a = 0; a < itemText.length(); ++a) |
void save() |
{ |
GlyphLayout* glyphs = itemText.getGlyphs(a); |
chstr =itemText.text(a,1); |
if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT |
|| chstr[0] == SpecialChars::TAB || chstr == SpecialChars::LINEBREAK) |
continue; |
if (a < itemText.length()-1) |
chstr += itemText.text(a+1, 1); |
glyphs->yadvance = 0; |
item->layoutGlyphs(itemText.charStyle(a), chstr, itemText.flags(a), *glyphs); |
glyphs->shrink(); |
if (item->itemText.hasObject(a)) |
totalTextLen += (item->itemText.object(a)->width() + item->itemText.object(a)->lineWidth()) * glyphs->scaleH; |
else |
totalTextLen += glyphs->wide()+itemText.charStyle(a).fontSize() * itemText.charStyle(a).tracking() / 10000.0; |
TextLayoutPainter::save(); |
m_painter->save(); |
} |
for (int segs = 0; segs < item->PoLine.size()-3; segs += 4) |
void restore() |
{ |
totalCurveLen += item->PoLine.lenPathSeg(segs); |
TextLayoutPainter::restore(); |
m_painter->restore(); |
} |
if ((itemText.defaultStyle().alignment() != 0) && (totalCurveLen >= totalTextLen + item->textToFrameDistLeft())) |
void setScale(double h, double v) |
{ |
if (itemText.defaultStyle().alignment() == 2) |
{ |
CurX = totalCurveLen - totalTextLen; |
CurX -= item->textToFrameDistLeft(); |
} |
if (itemText.defaultStyle().alignment() == 1) |
CurX = (totalCurveLen - totalTextLen) / 2.0; |
if ((itemText.defaultStyle().alignment() == 3) || (itemText.defaultStyle().alignment() == 4)) |
extraOffset = (totalCurveLen - item->textToFrameDistLeft() - totalTextLen) / static_cast<double>(itemText.length()); |
TextLayoutPainter::setScale(h, v); |
m_painter->scale(h, v); |
} |
QPainterPath guidePath = item->PoLine.toQPainterPath(false); |
QList<QPainterPath> pathList = decomposePath(guidePath); |
QPainterPath currPath = pathList[0]; |
int currPathIndex = 0; |
for (int a = item->firstInFrame(); a < itemText.length(); ++a) |
void drawGlyph(const GlyphLayout gl) |
{ |
GlyphLayout* glyphs = itemText.getGlyphs(a); |
PathData* pdata = &(item->textLayout.point(a)); |
chstr = itemText.text(a,1); |
if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT |
|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK) |
continue; |
if (a < itemText.length()-1) |
chstr += itemText.text(a+1, 1); |
glyphs->yadvance = 0; |
item->layoutGlyphs(itemText.charStyle(a), chstr, itemText.flags(a), *glyphs); |
glyphs->shrink(); // HACK |
// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG |
/*if (hl->hasObject()) |
dx = (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH / 2.0; |
else*/ |
dx = glyphs->wide() / 2.0; |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
CurX += dx; |
m_painter->save(); |
bool fr = m_painter->fillRule(); |
int fm = m_painter->fillMode(); |
double currPerc = currPath.percentAtLength(CurX); |
if (currPerc >= 0.9999999) |
{ |
currPathIndex++; |
if (currPathIndex == pathList.count()) |
break; |
currPath = pathList[currPathIndex]; |
CurX = dx; |
currPerc = currPath.percentAtLength(CurX); |
} |
double currAngle = currPath.angleAtPercent(currPerc); |
if (currAngle <= 180.0) |
currAngle *= -1.0; |
else |
currAngle = 360.0 - currAngle; |
QPointF currPoint = currPath.pointAtPercent(currPerc); |
tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0)); |
point = FPoint(currPoint.x(), currPoint.y()); |
m_painter->setFillRule(false); |
m_painter->setFillMode(1); |
//hl = itemText.item_p(a); |
glyphs->xoffset = 0; |
pdata->PtransX = point.x(); |
pdata->PtransY = point.y(); |
pdata->PRot = currAngle * M_PI / 180.0; |
pdata->PDx = dx; |
QTransform trafo = QTransform( 1, 0, 0, -1, -dx, 0 ); |
if (item->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (item->textPathType == 0) |
trafo *= QTransform( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode |
else if (item->textPathType == 1) |
trafo *= QTransform( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode |
else if (item->textPathType == 2) |
setupState(); |
m_painter->translate(0, -(fontSize() * gl.scaleV)); |
FPointArray outline = font().glyphOutline(gl.glyph); |
double scaleH = gl.scaleH * fontSize() / 10.0; |
double scaleV = gl.scaleV * fontSize() / 10.0; |
m_painter->scale(scaleH, scaleV); |
m_painter->setupPolygon(&outline, true); |
if (outline.size() > 3) |
m_painter->fillPath(); |
m_painter->setFillMode(fm); |
m_painter->setFillRule(fr); |
m_painter->restore(); |
} |
void drawGlyphOutline(const GlyphLayout gl, bool fill) |
{ |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
m_painter->save(); |
bool fr = m_painter->fillRule(); |
m_painter->setFillRule(false); |
setupState(); |
m_painter->translate(0, -(fontSize() * gl.scaleV)); |
FPointArray outline = font().glyphOutline(gl.glyph); |
double scaleH = gl.scaleH * fontSize() / 10.0; |
double scaleV = gl.scaleV * fontSize() / 10.0; |
m_painter->scale(scaleH, scaleV); |
m_painter->setupPolygon(&outline, true); |
if (outline.size() > 3) |
{ |
double a = 1; |
if (tangent.x() < 0) |
a = -1; |
if (fabs(tangent.x()) > 0.1) |
trafo *= QTransform( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode |
else |
trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() ); |
m_painter->setLineWidth(strokeWidth()); |
m_painter->strokePath(); |
} |
QTransform sca = painter->worldMatrix(); |
trafo *= sca; |
painter->save(); |
QTransform savWM = painter->worldMatrix(); |
painter->setWorldMatrix(trafo); |
actFill = itemText.charStyle(a).fillColor(); |
actFillShade = itemText.charStyle(a).fillShade(); |
if (actFill != CommonStrings::None) |
m_painter->setFillRule(fr); |
m_painter->restore(); |
if (fill) |
drawGlyph(gl); |
} |
void drawLine(QPointF start, QPointF end) |
{ |
m_painter->save(); |
setupState(); |
m_painter->drawLine(start, end); |
m_painter->restore(); |
} |
void drawRect(QRectF rect) |
{ |
m_painter->save(); |
setupState(); |
m_painter->setFillMode(1); |
m_painter->setStrokeMode(1); |
m_painter->drawRect(rect.x(), rect.y(), rect.width(), rect.height()); |
m_painter->restore(); |
} |
void drawObject(PageItem* embedded) |
{ |
QRect cullingArea; |
if (!embedded) |
return; |
if (!m_item->m_Doc->DoDrawing) |
return; |
m_painter->save(); |
double pws = embedded->m_lineWidth; |
embedded->Dirty = m_item->Dirty; |
embedded->invalid = true; |
m_scpage->drawItem_Pre(embedded, m_painter); |
switch(embedded->itemType()) |
{ |
ScColorShade tmp(m_doc->PageColors[actFill], qRound(actFillShade)); |
painter->setBrush(tmp); |
case PageItem::ImageFrame: |
case PageItem::TextFrame: |
case PageItem::LatexFrame: |
case PageItem::OSGFrame: |
case PageItem::Polygon: |
case PageItem::PathText: |
case PageItem::Symbol: |
case PageItem::Group: |
case PageItem::RegularPolygon: |
case PageItem::Arc: |
case PageItem::Table: |
m_scpage->drawItem(embedded, m_painter, cullingArea); |
break; |
case PageItem::Line: |
case PageItem::PolyLine: |
case PageItem::Spiral: |
embedded->m_lineWidth = pws * qMin(scaleH(), scaleV()); |
m_scpage->drawItem(embedded, m_painter, cullingArea); |
break; |
default: |
break; |
} |
actStroke = itemText.charStyle(a).strokeColor(); |
actStrokeShade = itemText.charStyle(a).strokeShade(); |
if (actStroke != CommonStrings::None) |
{ |
ScColorShade tmp(m_doc->PageColors[actStroke], qRound(actStrokeShade)); |
painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
painter->translate(0.0, item->pathTextBaseOffset()); |
if (itemText.hasObject(a)) |
drawItem_Embedded(itemText.object(a), painter, clip, itemText.charStyle(a), itemText.object(a)); |
else |
drawGlyphs(item, painter, itemText.charStyle(a), *glyphs, clip); |
painter->setWorldMatrix(savWM); |
painter->restore(); |
CurX -= dx; |
if (itemText.hasObject(a)) |
CurX += (itemText.object(a)->width() + itemText.object(a)->lineWidth()) * glyphs->scaleH; |
else |
CurX += glyphs->wide()+itemText.charStyle(a).fontSize() * itemText.charStyle(a).tracking() / 10000.0 + extraOffset; |
embedded->m_lineWidth = pws * qMin(scaleH(), scaleV()); |
m_scpage->drawItem_Post(embedded, m_painter); |
embedded->m_lineWidth = pws; |
m_painter->restore(); |
} |
}; |
void ScPageOutput::drawItem_PathText( PageItem_PathText* item, ScPainterExBase* painter, QRect clip ) |
{ |
ScpageoutputPainter p(item, painter, this); |
item->textLayout.renderBackground(&p); |
item->textLayout.render(&p); |
} |
void ScPageOutput::drawItem_Polygon ( PageItem_Polygon* item , ScPainterExBase* painter, QRect clip ) |
1610,251 → 1451,9 |
void ScPageOutput::drawItem_TextFrame( PageItem_TextFrame* item, ScPainterExBase* painter, QRect cullingArea ) |
{ |
QTransform wm; |
QPoint pt1, pt2; |
FPoint ColBound; |
QRegion cm; |
int a; |
double desc, asce; |
painter->save(); |
if (!item->isEmbedded) |
wm.translate(item->xPos(), item->yPos()); |
wm.rotate(item->rotation()); |
if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0)) |
{ |
painter->setupPolygon(&item->PoLine); |
fillPath(item, painter, cullingArea); |
} |
if ((item->isAnnotation()) && (item->annotation().Type() == Annotation::Button) && (!item->Pfile.isEmpty()) && (item->imageIsAvailable) && (item->imageVisible()) && (item->annotation().UseIcons())) |
{ |
painter->save(); |
painter->setupPolygon(&item->PoLine); |
painter->setClipPath(); |
painter->scale(item->imageXScale(), item->imageYScale()); |
painter->translate(static_cast<int>(item->imageXOffset() * item->imageXScale()), static_cast<int>(item->imageYOffset() * item->imageYScale())); |
if (!item->pixm.qImage().isNull()) |
painter->drawImage(&item->pixm, ScPainterExBase::rgbImages); |
painter->restore(); |
} |
if ((item->itemText.length() != 0)) |
{ |
if (item->imageFlippedH()) |
{ |
painter->translate(item->width(), 0); |
painter->scale(-1, 1); |
wm.translate(item->width(), 0); |
wm.scale(-1, 1); |
} |
if (item->imageFlippedV()) |
{ |
painter->translate(0, item->height()); |
painter->scale(1, -1); |
wm.translate(0, item->height()); |
wm.scale(1, -1); |
} |
uint llp = 0; |
LineSpec ls; |
while (llp < item->textLayout.lines()) |
{ |
ls = item->textLayout.line(llp++); |
const ParagraphStyle& LineStyle = item->itemText.paragraphStyle(ls.firstItem); |
if (LineStyle.backgroundColor() != CommonStrings::None) |
{ |
ScColorShade colorShade; |
colorShade.color = m_doc->PageColors[LineStyle.backgroundColor()]; |
colorShade.shade = LineStyle.backgroundShade(); |
double y0 = ls.y; |
double y2 = ls.y; |
double ascent = ls.ascent; |
double descent = ls.descent; |
double rMarg = LineStyle.rightMargin(); |
double lMarg = ls.colLeft; |
double adjX = 0; |
if (LineStyle.firstIndent() <= 0) |
adjX += LineStyle.leftMargin() + LineStyle.firstIndent(); |
while (llp < item->textLayout.lines()) |
{ |
ls = item->textLayout.line(llp); |
if ((ls.colLeft > lMarg) || (item->itemText.paragraphStyle(ls.firstItem) != LineStyle)) |
{ |
if (y2 == 0) |
y2 = y0; |
break; |
} |
if (item->itemText.text(ls.lastItem) == SpecialChars::PARSEP) |
{ |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < item->textLayout.lines()) |
{ |
if ((item->textLayout.line(llp + 1).lastItem - item->textLayout.line(llp + 1).firstItem) > 0) |
descent += LineStyle.lineSpacing() - (ls.descent + item->textLayout.line(llp + 1).ascent); |
} |
llp++; |
break; |
} |
y2 = ls.y; |
descent = ls.descent; |
if ((llp + 1) < item->textLayout.lines()) |
descent += LineStyle.lineSpacing() - (ls.descent + item->textLayout.line(llp + 1).ascent); |
llp++; |
} |
painter->save(); |
painter->setupPolygon(&item->PoLine); |
painter->setClipPath(); |
painter->setFillMode(1); |
painter->setStrokeMode(0); |
painter->setBrush(colorShade); |
painter->drawRect(lMarg + adjX, y0 - ascent, item->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent); |
painter->restore(); |
} |
} |
for (uint ll=0; ll < item->textLayout.lines(); ++ll) |
{ |
const LineSpec& ls = item->textLayout.line(ll); |
double CurX = ls.x; |
// Draw text background |
ScColorShade tmpShade; |
double curXB = ls.x; |
QRectF scrG; |
QString oldBack; |
double oldShade = 100; |
for (a = ls.firstItem; a <= ls.lastItem; ++a) |
{ |
GlyphLayout* glyphs = item->itemText.getGlyphs(a); |
const CharStyle& charStyle(item->itemText.charStyle(a)); |
if (charStyle.backColor() != CommonStrings::None) |
{ |
tmpShade.color = m_doc->PageColors[charStyle.backColor()]; |
tmpShade.shade = charStyle.backShade(); |
const ParagraphStyle& lineStyle = item->itemText.paragraphStyle(ls.firstItem); |
double y1 = ls.y; |
double hl = ls.height; |
if (lineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
hl = m_doc->guidesPrefs().valueBaselineGrid; |
else if (lineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing) |
hl = lineStyle.lineSpacing(); |
if (ls.isFirstLine) |
{ |
if (item->textLayout.lines() == 1) |
hl = ls.ascent + ls.descent; |
if (lineStyle.hasDropCap() && (a == ls.firstItem)) |
hl *= lineStyle.dropCapLines(); |
if (lineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing) |
y1 -= lineStyle.lineSpacing(); |
else if (item->firstLineOffset() == FLOPRealGlyphHeight || item->firstLineOffset() == FLOPFontAscent) |
y1 -= ls.ascent; |
else |
y1 -= lineStyle.lineSpacing(); |
} |
else |
y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0; |
QRectF scr; |
if (item->itemText.hasObject(a)) |
{ |
PageItem* obj = item->itemText.object(a); |
double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH; |
double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV; |
scr = QRectF(curXB, ls.y - hh, ww , hh); |
} |
else |
scr = QRectF(curXB, y1, glyphs->wide(), hl); |
if ((oldBack.isEmpty()) || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade()))) |
scrG |= scr; |
else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade())) |
{ |
tmpShade.color = m_doc->PageColors[oldBack]; |
tmpShade.shade = oldShade; |
painter->save(); |
painter->setFillMode(1); |
painter->setStrokeMode(0); |
painter->setBrush(tmpShade); |
painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
painter->restore(); |
scrG = scr; |
} |
oldBack = charStyle.backColor(); |
oldShade = charStyle.backShade(); |
} |
else |
{ |
oldBack.clear(); |
oldShade = 100; |
if (!scrG.isNull()) |
{ |
painter->save(); |
painter->setFillMode(1); |
painter->setStrokeMode(0); |
painter->setBrush(tmpShade); |
painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
painter->restore(); |
} |
scrG = QRectF(); |
} |
curXB += glyphs->wide(); |
} |
if (!scrG.isNull()) |
{ |
painter->save(); |
painter->setFillMode(1); |
painter->setStrokeMode(0); |
painter->setBrush(tmpShade); |
painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height()); |
painter->restore(); |
} |
// Draw text |
for (a = ls.firstItem; a <= ls.lastItem; ++a) |
{ |
GlyphLayout* glyphs = item->itemText.getGlyphs(a); |
const CharStyle& charStyle = item->itemText.charStyle(a); |
if (charStyle.fillColor() != CommonStrings::None) |
{ |
ScColorShade tmp(m_doc->PageColors[charStyle.fillColor()], (int) charStyle.fillShade()); |
painter->setBrush(tmp); |
} |
if (charStyle.strokeColor() != CommonStrings::None) |
{ |
ScColorShade tmp(m_doc->PageColors[charStyle.strokeColor()], (int) charStyle.strokeShade()); |
painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
//if (!m_doc->RePos) |
{ |
//double xcoZli = CurX + glyphs->xoffset; |
desc = - charStyle.font().descent(charStyle.fontSize() / 10.0); |
asce = charStyle.font().ascent(charStyle.fontSize() / 10.0); |
if (charStyle.strokeColor() != CommonStrings::None) |
{ |
ScColorShade tmp(m_doc->PageColors[charStyle.strokeColor()], (int) charStyle.strokeShade()); |
painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); |
} |
if (item->isEmbedded || cullingArea.intersects(wm.mapRect(QRect(qRound(CurX + glyphs->xoffset),qRound(ls.y + glyphs->yoffset-asce), qRound(glyphs->xadvance+1), qRound(asce+desc))))) |
{ |
painter->save(); |
painter->translate(CurX, ls.y); |
if (item->itemText.hasObject(a)) |
drawItem_Embedded(item, painter, cullingArea, charStyle, item->itemText.object(a)); |
else |
drawGlyphs(item, painter, charStyle, *glyphs, cullingArea); |
painter->restore(); |
} |
// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG |
/*if (hl->hasObject()) |
CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()); |
else*/ |
CurX += glyphs->wide(); |
} |
} |
} |
} |
painter->restore(); |
ScpageoutputPainter p(item, painter, this); |
item->textLayout.renderBackground(&p); |
item->textLayout.render(&p); |
} |
void ScPageOutput::drawArrow(ScPainterExBase* painter, PageItem* item, QTransform &arrowTrans, int arrowIndex) |
/trunk/Scribus/scribus/scpageoutput.h |
---|
53,6 → 53,8 |
class SCRIBUS_API ScPageOutput |
{ |
friend class ScpageoutputPainter; |
public: |
ScPageOutput(ScribusDoc* doc, bool reloadImages = false, int resolution = 72, bool useProfiles = false); |
virtual ~ScPageOutput() { } |
82,7 → 84,6 |
virtual void drawItem_Pre( PageItem* item, ScPainterExBase* painter ); |
virtual void drawItem_Post( PageItem* item, ScPainterExBase* painter ); |
virtual void drawGlyphs(PageItem* item, ScPainterExBase *painter, const CharStyle& style, GlyphLayout& glyphs, QRect clip); |
virtual void drawItem_Embedded( PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded); |
virtual void drawPattern(PageItem* item, ScPainterExBase* painter, QRect clip); |
virtual void drawStrokePattern(PageItem* item, ScPainterExBase* painter, const QPainterPath& path); |
/trunk/Scribus/scribus/scpainter.cpp |
---|
181,6 → 181,11 |
m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) ); |
} |
cairo_t *ScPainter::context() |
{ |
return m_cr; |
} |
const QTransform ScPainter::worldMatrix() |
{ |
cairo_matrix_t matrix; |
424,6 → 429,11 |
return m_fill; |
} |
double ScPainter::brushOpacity() |
{ |
return m_fill_trans; |
} |
void ScPainter::setPen( const QColor &c ) |
{ |
m_stroke = c; |
495,6 → 505,11 |
m_zoomFactor = m_zoomStack.pop(); |
} |
int ScPainter::blendModeFill() |
{ |
return m_blendModeFill; |
} |
void ScPainter::setRasterOp(int blendMode) |
{ |
if (blendMode == 0) |
1932,6 → 1947,7 |
void ScPainter::drawText(QRectF area, QString text, bool filled, int align) |
{ |
// FIXME HOST: This uses Cairo "Toy text API" which does not support complex text layout. |
cairo_text_extents_t extents; |
cairo_font_extents_t extentsF; |
double x; |
/trunk/Scribus/scribus/scpainter.h |
---|
19,6 → 19,7 |
#include <QPointF> |
#include "scribusapi.h" |
#include "scconfig.h" |
#include "sctextstruct.h" |
#include "fpoint.h" |
#include "fpointarray.h" |
#include "vgradient.h" |
43,6 → 44,7 |
virtual void end(); |
void clear(); |
virtual void clear( const QColor & ); |
virtual cairo_t* context(); |
// matrix manipulation |
virtual void setWorldMatrix( const QTransform & ); |
66,6 → 68,7 |
virtual bool fillRule() { return m_fillRule; } |
virtual void setFillMode( int fill ); |
virtual int fillMode() { return m_fillMode; } |
virtual int maskMode() { return m_maskMode; } |
virtual void setStrokeMode( int stroke ); |
virtual int strokeMode() { return m_strokeMode; } |
virtual void setGradient( VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew); |
109,6 → 112,7 |
// pen + brush |
virtual QColor pen(); |
virtual QColor brush(); |
virtual double brushOpacity(); |
virtual void setPen( const QColor & ); |
virtual void setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo ); |
virtual void setPenOpacity( double op ); |
123,6 → 127,7 |
// stack management |
virtual void save(); |
virtual void restore(); |
virtual int blendModeFill(); |
virtual void setRasterOp( int blendMode ); |
/trunk/Scribus/scribus/scribusdoc.cpp |
---|
42,6 → 42,7 |
#include "actionmanager.h" |
#include "appmodes.h" |
#include "text/boxes.h" |
#include "canvas.h" |
#include "colorblind.h" |
#include "commonstrings.h" |
95,6 → 96,7 |
#include "selection.h" |
#include "serializer.h" |
#include "tableborder.h" |
#include "text/textlayoutpainter.h" |
#include "ui/hruler.h" |
#include "ui/layers.h" |
#include "ui/mark2item.h" |
4497,181 → 4499,45 |
} |
} |
void ScribusDoc::checkItemForFonts(PageItem *it, QMap<QString, QMap<uint, FPointArray> > & Really, uint lc) |
// a special painter that does not actually paint anything, |
// but collects the glyphs used in the frame. |
class UsedGlyphsPainter: public TextLayoutPainter |
{ |
if (!it->isTextFrame() && !it->isPathText()) |
return; |
public: |
UsedGlyphsPainter(QMap<QString, QMap<uint, FPointArray> > & Really) |
: m_really(Really) |
{} |
FPointArray gly; |
QChar chstr; |
int start = it->isTextFrame() ? it->firstInFrame() : 0; |
int stop = it->isTextFrame() ? it->lastInFrame() + 1 : it->itemText.length(); |
for (int e = start; e < stop; ++e) |
void drawGlyph(const GlyphLayout gl) |
{ |
const ScFace* font = &it->itemText.charStyle(e).font(); |
if (it->itemText.hasMark(e)) |
{ |
QString mrkStr = it->itemText.mark(e)->getString(); |
for (int i=0;i<mrkStr.length(); ++i) |
{ |
if (font->canRender(mrkStr[i].unicode())) |
{ |
uint gl = font->char2CMap(mrkStr[i]); |
FPointArray gly(font->glyphOutline(gl)); |
if (!font->replacementName().isEmpty()) |
Really[font->replacementName()].insert(gl, gly); |
} |
} |
} |
if (! Really.contains(font->replacementName()) ) |
{ |
if (!font->replacementName().isEmpty()) |
Really.insert(font->replacementName(), QMap<uint, FPointArray>()); |
} |
uint chr = it->itemText.text(e).unicode(); |
if ((chr == 13) || (chr == 32) || ((chr >= 26) && (chr <= 29))) |
continue; |
if (chr == 9) |
{ |
for (int t1 = 0; t1 < it->itemText.paragraphStyle(e).tabValues().count(); t1++) |
{ |
if (it->itemText.paragraphStyle(e).tabValues()[t1].tabFillChar.isNull()) |
continue; |
chstr = it->itemText.paragraphStyle(e).tabValues()[t1].tabFillChar; |
if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps)) |
{ |
if (chstr.toUpper() != chstr) |
chstr = chstr.toUpper(); |
} |
chr = chstr.unicode(); |
uint gl = font->char2CMap(chstr); |
gly = font->glyphOutline(gl); |
if (!font->replacementName().isEmpty()) |
Really[font->replacementName()].insert(gl, gly); |
} |
for (int t1 = 0; t1 < it->itemText.defaultStyle().tabValues().count(); t1++) |
{ |
if (it->itemText.defaultStyle().tabValues()[t1].tabFillChar.isNull()) |
continue; |
chstr = it->itemText.defaultStyle().tabValues()[t1].tabFillChar; |
if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps)) |
{ |
if (chstr.toUpper() != chstr) |
chstr = chstr.toUpper(); |
} |
chr = chstr.unicode(); |
uint gl = font->char2CMap(chstr); |
gly = font->glyphOutline(gl); |
if (!font->replacementName().isEmpty()) |
Really[font->replacementName()].insert(gl, gly); |
} |
continue; |
} |
if ((chr == 30) || (chr == 23)) |
{ |
//Our page number collection string |
QString pageNumberText(QString::null); |
if (chr == 30) |
{//ch == SpecialChars::PAGENUMBER |
if (e > 0 && it->itemText.text(e-1) == SpecialChars::PAGENUMBER) |
pageNumberText=SpecialChars::ZWNBSPACE; |
else if (lc!=0) //If not on a master page just get the page number for the page and the text |
{ |
pageNumberText = QString("%1").arg(getSectionPageNumberForPageIndex(it->OwnPage), |
getSectionPageNumberWidthForPageIndex(it->OwnPage), |
getSectionPageNumberFillCharForPageIndex(it->OwnPage)); |
} |
else |
{ |
//Else, for a page number in a text frame on a master page we must scan |
//all pages to see which ones use this page and get their page numbers. |
//We only add each character of the pages' page number text if its nothing |
//already in the pageNumberText variable. No need to add glyphs twice. |
QString newText; |
uint docPageCount=DocPages.count(); |
for (uint a = 0; a < docPageCount; ++a) |
{ |
if (DocPages.at(a)->MPageNam == it->OnMasterPage) |
{ |
newText = QString("%1").arg(getSectionPageNumberForPageIndex(a), |
getSectionPageNumberWidthForPageIndex(a), |
getSectionPageNumberFillCharForPageIndex(a)); |
for (int nti=0;nti<newText.length();++nti) |
if (pageNumberText.indexOf(newText[nti])==-1) |
pageNumberText+=newText[nti]; |
} |
} |
} |
} |
else |
{//ch == SpecialChars::PAGECOUNT |
if (lc!=0) |
{ |
int key = getSectionKeyForPageIndex(it->OwnPage); |
if (key == -1) |
pageNumberText = ""; |
else |
pageNumberText = QString("%1").arg(getStringFromSequence(m_docPrefsData.docSectionMap[key].type, m_docPrefsData.docSectionMap[key].toindex - m_docPrefsData.docSectionMap[key].fromindex + 1)); |
} |
else |
{ |
QString newText; |
uint docPageCount=DocPages.count(); |
for (uint a = 0; a < docPageCount; ++a) |
{ |
if (DocPages.at(a)->MPageNam == it->OnMasterPage) |
{ |
int key = getSectionKeyForPageIndex(a); |
if (key == -1) |
newText = ""; |
else |
newText = QString("%1").arg(getStringFromSequence(m_docPrefsData.docSectionMap[key].type, m_docPrefsData.docSectionMap[key].toindex - m_docPrefsData.docSectionMap[key].fromindex + 1)); |
for (int nti=0;nti<newText.length();++nti) |
if (pageNumberText.indexOf(newText[nti])==-1) |
pageNumberText+=newText[nti]; |
} |
} |
} |
} |
//Now scan and add any glyphs used in page numbers |
for (int pnti=0;pnti<pageNumberText.length(); ++pnti) |
{ |
uint chr = pageNumberText[pnti].unicode(); |
if (font->canRender(chr)) |
{ |
uint gl = font->char2CMap(pageNumberText[pnti]); |
FPointArray gly(font->glyphOutline(gl)); |
if (!font->replacementName().isEmpty()) |
Really[font->replacementName()].insert(gl, gly); |
} |
} |
continue; |
} |
if (gl.glyph >= ScFace::CONTROL_GLYPHS) |
return; |
if (it->itemText.hasFlag(e, ScLayout_SoftHyphenVisible)) |
if (!font().replacementName().isEmpty()) |
{ |
uint gl = it->itemText.charStyle(e).font().char2CMap(QChar('-')); |
FPointArray gly(it->itemText.charStyle(e).font().glyphOutline(gl)); |
if (!it->itemText.charStyle(e).font().replacementName().isEmpty()) |
Really[it->itemText.charStyle(e).font().replacementName()].insert(gl, gly); |
FPointArray outline(font().glyphOutline(gl.glyph)); |
m_really[font().replacementName()].insert(gl.glyph, outline); |
} |
if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps)) |
{ |
chstr = it->itemText.text(e); |
if (chstr.toUpper() != chstr) |
chstr = chstr.toUpper(); |
chr = chstr.unicode(); |
} |
if (it->itemText.charStyle(e).font().canRender(chr)) |
{ |
uint gl = it->itemText.charStyle(e).font().char2CMap(chr); |
gly = it->itemText.charStyle(e).font().glyphOutline(gl); |
if (!it->itemText.charStyle(e).font().replacementName().isEmpty()) |
Really[it->itemText.charStyle(e).font().replacementName()].insert(gl, gly); |
} |
} |
void drawGlyphOutline(const GlyphLayout gl, bool) { drawGlyph(gl); } |
// we don't need this one |
void drawLine(QPointF, QPointF) {} |
void drawRect(QRectF) {} |
void drawObject(PageItem*) {} |
private: |
QMap<QString, QMap<uint, FPointArray> > & m_really; |
}; |
void ScribusDoc::checkItemForFonts(PageItem *it, QMap<QString, QMap<uint, FPointArray> > & Really, uint lc) |
{ |
if (!it->isTextFrame() && !it->isPathText()) |
return; |
UsedGlyphsPainter p(Really); |
it->textLayout.render(&p); |
} |
/trunk/Scribus/scribus/scribusview.cpp |
---|
80,6 → 80,7 |
#include "hyphenator.h" |
#include "iconmanager.h" |
#include "loadsaveplugin.h" |
#include "text/textlayoutpainter.h" |
#include "pageitem.h" |
#include "pageitem_group.h" |
#include "pageitem_imageframe.h" |
1651,8 → 1652,14 |
point.setX(textFrame->width() - point.x()); |
if (textFrame->imageFlippedV()) |
point.setY(textFrame->height() - point.y()); |
textFrame->itemText.setCursorPosition(textFrame->itemText.length() == 0 ? 0 : |
textFrame->textLayout.screenToPosition(point)); |
if (textFrame->itemText.length() == 0) |
textFrame->itemText.setCursorPosition(0); |
else |
{ |
int result = textFrame->textLayout.pointToPosition(point.toQPointF()); |
if (result >= 0) |
textFrame->itemText.setCursorPosition(result); |
} |
if (textFrame->itemText.length() > 0) |
{ |
2998,6 → 3005,91 |
} |
} |
// FIXME: the following code is untested, but it should give an idea for |
// anyone who wants to fix and knows how to test it. |
class TextToPathPainter: public TextLayoutPainter |
{ |
ScribusView* m_view; |
PageItem* m_item; |
QList<PageItem*> m_group; |
int m_counter; |
public: |
TextToPathPainter(ScribusView* view, PageItem* item) |
: m_view(view) |
, m_item(item) |
, m_counter(0) |
{} |
void drawGlyph(const GlyphLayout gl) |
{ |
FPointArray outline = font().glyphOutline(gl.glyph); |
if (outline.size() < 4) |
return; |
QTransform transform = matrix(); |
transform.scale(x(), y()); |
outline.map(transform); |
uint z = m_view->Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, m_item->xPos(), m_item->yPos(), m_item->width(), m_item->height(), m_item->lineWidth(), m_item->lineColor(), m_item->fillColor()); |
PageItem* item = m_view->Doc->Items->at(z); |
m_view->undoManager->setUndoEnabled(false); |
item->setTextFlowMode(m_item->textFlowMode()); |
item->setSizeLocked(m_item->sizeLocked()); |
item->setLocked(m_item->locked()); |
item->NamedLStyle = m_item->NamedLStyle; |
item->setItemName(m_item->itemName() + "+U" + QString::number(m_counter++)); |
item->PoLine = outline.copy(); |
if (!m_item->asPathText()) |
item->setRotation(m_item->rotation()); |
item->setFillColor(fillColor().color); |
item->setFillShade(fillColor().shade); |
item->setLineWidth(strokeWidth()); |
m_view->Doc->adjustItemSize(item); |
item->ContourLine = item->PoLine.copy(); |
item->ClipEdited = true; |
item->FrameType = 3; |
item->OldB2 = item->width(); |
item->OldH2 = item->height(); |
m_view->Doc->setRedrawBounding(item); |
m_view->undoManager->setUndoEnabled(true); |
m_group.append(m_view->Doc->Items->takeAt(z)); |
} |
void drawGlyphOutline(const GlyphLayout gl, bool fill) |
{ |
drawGlyph(gl); |
} |
void drawLine(QPointF start, QPointF end) |
{ |
QTransform transform = matrix(); |
transform.translate(x(), y()); |
uint z = m_view->Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, m_item->xPos(), m_item->yPos(), m_item->width(), m_item->height(), m_item->lineWidth(), m_item->lineColor(), m_item->fillColor()); |
PageItem* item = m_view->Doc->Items->at(z); |
m_view->undoManager->setUndoEnabled(false); |
item->setTextFlowMode(m_item->textFlowMode()); |
item->setSizeLocked(m_item->sizeLocked()); |
item->setLocked(m_item->locked()); |
item->NamedLStyle = m_item->NamedLStyle; |
item->setItemName(m_item->itemName() + "+U" + QString::number(m_counter++)); |
item->PoLine.resize(0); |
item->PoLine.addQuadPoint(FPoint(start), FPoint(start), FPoint(end), FPoint(end)); |
item->PoLine.map(transform); |
item->setLineColor(fillColor().color); |
item->setLineShade(fillColor().shade); |
item->setLineWidth(strokeWidth()); |
m_view->Doc->adjustItemSize(item); |
item->ContourLine = item->PoLine.copy(); |
item->ClipEdited = true; |
item->FrameType = 3; |
item->OldB2 = item->width(); |
item->OldH2 = item->height(); |
m_view->Doc->setRedrawBounding(item); |
m_view->undoManager->setUndoEnabled(true); |
m_group.append(m_view->Doc->Items->takeAt(z)); |
} |
void drawRect(QRectF rect) {} |
void drawObject(PageItem* item) {} |
}; |
void ScribusView::TextToPath() |
{ |
if (Doc->appMode == modeEditClip) |
3048,642 → 3140,9 |
++offset; |
continue; |
} |
// newGroupedItems.clear(); |
FPointArray pts; |
double x=0.0, y=0.0, wide=0.0; |
QString chstr, ccounter; |
QChar chstrex; |
PageItem* bb; |
if (currItem->asPathText()) |
{ |
for (int a = 0; a < currItem->asPathText()->itemRenderText.length(); ++a) |
{ |
pts.resize(0); |
x = 0.0; |
y = 0.0; |
//ScText * hl = currItem->asPathText()->itemRenderText.item_p(a); |
const CharStyle& charStyle(currItem->asPathText()->itemRenderText.charStyle(a)); |
const PathData& pdata(currItem->textLayout.point(a)); |
const GlyphLayout* glyphs = currItem->asPathText()->itemRenderText.getGlyphs(a); |
LayoutFlags flags = currItem->asPathText()->itemRenderText.flags(a); |
chstr = currItem->asPathText()->itemRenderText.text(a,1); |
if ((chstr == SpecialChars::PARSEP) || (chstr == SpecialChars::OLD_NBSPACE)) |
continue; |
if (chstr == SpecialChars::OBJECT) |
{ |
continue; |
} |
if (chstr == SpecialChars::PAGENUMBER) |
chstr = currItem->ExpandToken(a); |
double chs = charStyle.fontSize(); |
if (charStyle.effects() & ScStyle_SmallCaps) |
{ |
if (chstr[0].toUpper() != chstr[0]) |
{ |
chs = qMax(static_cast<int>(charStyle.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstr = chstr[0].toUpper(); |
} |
} |
else if (charStyle.effects() & ScStyle_AllCaps) |
chstr = chstr[0].toUpper(); |
// double csi = static_cast<double>(chs) / 100.0; |
uint chr = chstr[0].unicode(); |
QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) ); |
QTransform chma, chma2, chma3, chma4, chma6; |
QTransform trafo = QTransform( 1, 0, 0, -1, -pdata.PDx, 0 ); |
if (currItem->textPathFlipped) |
trafo *= QTransform(1, 0, 0, -1, 0, 0); |
if (currItem->textPathType == 0) |
trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata.PtransX, pdata.PtransY ); |
else if (currItem->textPathType == 1) |
trafo *= QTransform(1, 0, 0, -1, pdata.PtransX, pdata.PtransY ); |
else if (currItem->textPathType == 2) |
{ |
double a = 1; |
double b = -1; |
if (tangt.x() < 0) |
{ |
a = -1; |
b = 1; |
} |
if (fabs(tangt.x()) > 0.1) |
trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata.PtransX, pdata.PtransY ); // ID's Skew mode |
else |
trafo *= QTransform( a, 6 * b, 0, -1, pdata.PtransX, pdata.PtransY ); |
} |
//trafo *= QTransform( hl->PtransX, hl->PtransY, hl->PtransY, -hl->PtransX, glyphs->xoffset, glyphs->yoffset); |
if (currItem->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(-currItem->xPos(), -currItem->yPos()); |
sca.rotate(currItem->rotation()); |
trafo *= sca; |
} |
chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0); |
if (currItem->reversed()) |
{ |
if (a < currItem->asPathText()->itemRenderText.length()-1) |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->asPathText()->itemRenderText.text(a+1)); |
else |
wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize()); |
chma3.scale(-1, 1); |
chma3.translate(-wide, 0); |
} |
chma4.translate(0, currItem->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV); |
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript)) |
chma6.translate(0, glyphs->yoffset); |
if (charStyle.baselineOffset() != 0) |
chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0)); |
uint gl = charStyle.font().char2CMap(chr); |
QTransform finalMat = QTransform(chma * chma2 * chma3 * chma4 * chma6 * trafo); |
if (currItem->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(currItem->xPos(), currItem->yPos()); |
pts.map(sca); |
} |
QChar chstc = chstr[0]; |
if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstc)) |
|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstc.isSpace() && !SpecialChars::isBreak(chstc))) |
{ |
QTransform stro = QTransform(chma2 * chma3 * chma6 * trafo); |
if (currItem->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(currItem->xPos(), currItem->yPos()); |
stro *= sca; |
} |
double Ulen = glyphs->xadvance; |
double Upos, Uwid, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1)) |
{ |
if (charStyle.underlineOffset() != -1) |
Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
if (charStyle.underlineWidth() != -1) |
Uwid = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0); |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor()); |
bb = Doc->Items->at(z); |
undoManager->setUndoEnabled(false); |
bb->setTextFlowMode(currItem->textFlowMode()); |
bb->setSizeLocked(currItem->sizeLocked()); |
bb->setLocked(currItem->locked()); |
bb->NamedLStyle = currItem->NamedLStyle; |
bb->setItemName(currItem->itemName()+"+U"+ccounter.setNum(a)); |
FPoint start, stop; |
if (charStyle.effects() & ScStyle_Subscript) |
{ |
start = FPoint(glyphs->xoffset-kern, -Upos); |
stop = FPoint(glyphs->xoffset+Ulen, -Upos); |
} |
else |
{ |
start = FPoint(glyphs->xoffset-kern, -(Upos + glyphs->yoffset)); |
stop = FPoint(glyphs->xoffset+Ulen, -(Upos + glyphs->yoffset)); |
} |
bb->PoLine.resize(0); |
bb->PoLine.addQuadPoint(start, start, stop, stop); |
bb->PoLine.map(stro); |
bb->setLineColor(charStyle.fillColor()); |
bb->setLineShade(charStyle.fillShade()); |
bb->setLineWidth(Uwid); |
Doc->adjustItemSize(bb); |
bb->ContourLine = bb->PoLine.copy(); |
bb->ClipEdited = true; |
bb->FrameType = 3; |
bb->OldB2 = bb->width(); |
bb->OldH2 = bb->height(); |
Doc->setRedrawBounding(bb); |
undoManager->setUndoEnabled(true); |
newGroupedItems.append(Doc->Items->takeAt(z)); |
} |
if ((chstr.length() > 0) && (!chstr.at(0).isSpace())) |
{ |
pts = charStyle.font().glyphOutline(gl); |
if (pts.size() < 4) |
continue; |
if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None)) |
{ |
double glxTr = charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0; |
double glyTr = -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0; |
uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor()); |
bb = Doc->Items->at(z); |
undoManager->setUndoEnabled(false); |
bb->setTextFlowMode(currItem->textFlowMode()); |
bb->setSizeLocked(currItem->sizeLocked()); |
bb->setLocked(currItem->locked()); |
bb->NamedLStyle = currItem->NamedLStyle; |
bb->setItemName(currItem->itemName()+"+Sh"+ccounter.setNum(a)); |
bb->PoLine = pts.copy(); |
QTransform shmap; |
shmap.translate(glxTr, glyTr); |
bb->PoLine.map(finalMat * shmap); |
bb->setFillColor(charStyle.strokeColor()); |
bb->setFillShade(charStyle.strokeShade()); |
if (currItem->asPathText()->itemRenderText.charStyle(a).effects() & ScStyle_Outline) |
{ |
bb->setLineColor(charStyle.strokeColor()); |
bb->setLineShade(charStyle.strokeShade()); |
} |
else |
{ |
bb->setLineColor(CommonStrings::None); |
bb->setLineShade(100); |
} |
bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0); |
Doc->adjustItemSize(bb); |
bb->ContourLine = bb->PoLine.copy(); |
bb->ClipEdited = true; |
bb->FrameType = 3; |
bb->OldB2 = bb->width(); |
bb->OldH2 = bb->height(); |
Doc->setRedrawBounding(bb); |
undoManager->setUndoEnabled(true); |
newGroupedItems.append(Doc->Items->takeAt(z)); |
} |
pts.map(finalMat); |
uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor()); |
bb = Doc->Items->at(z); |
//bb->setTextFlowsAroundFrame(currItem->textFlowsAroundFrame()); |
//bb->setTextFlowUsesBoundingBox(currItem->textFlowUsesBoundingBox()); |
undoManager->setUndoEnabled(false); |
bb->setTextFlowMode(currItem->textFlowMode()); |
bb->setSizeLocked(currItem->sizeLocked()); |
bb->setLocked(currItem->locked()); |
bb->NamedLStyle = currItem->NamedLStyle; |
bb->setItemName(currItem->itemName()+"+"+ccounter.setNum(a)); |
bb->PoLine = pts.copy(); |
if (!currItem->asPathText()) |
bb->setRotation(currItem->rotation()); |
bb->setFillColor(charStyle.fillColor()); |
bb->setFillShade(charStyle.fillShade()); |
if (currItem->asPathText()->itemRenderText.charStyle(a).effects() & ScStyle_Outline) |
{ |
bb->setLineColor(charStyle.strokeColor()); |
bb->setLineShade(charStyle.strokeShade()); |
} |
else |
{ |
bb->setLineColor(CommonStrings::None); |
bb->setLineShade(100); |
} |
bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0); |
Doc->adjustItemSize(bb); |
bb->ContourLine = bb->PoLine.copy(); |
bb->ClipEdited = true; |
bb->FrameType = 3; |
bb->OldB2 = bb->width(); |
bb->OldH2 = bb->height(); |
Doc->setRedrawBounding(bb); |
undoManager->setUndoEnabled(true); |
newGroupedItems.append(Doc->Items->takeAt(z)); |
} |
if (charStyle.effects() & ScStyle_Strikethrough) |
{ |
QTransform stro = QTransform(chma2 * chma3 * chma6 * trafo); |
if (currItem->rotation() != 0) |
{ |
QTransform sca; |
sca.translate(currItem->xPos(), currItem->yPos()); |
stro *= sca; |
} |
double Ulen = glyphs->xadvance; |
double Upos, Uwid, kern; |
if (flags & ScLayout_StartOfLine) |
kern = 0; |
else |
kern = charStyle.fontSize() * charStyle.tracking() / 10000.0; |
if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1)) |
{ |
if (charStyle.strikethruOffset() != -1) |
Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0)); |
else |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
if (charStyle.strikethruWidth() != -1) |
Uwid = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0); |
else |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
else |
{ |
Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0); |
Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0); |
} |
if (charStyle.baselineOffset() != 0) |
Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor()); |
bb = Doc->Items->at(z); |
undoManager->setUndoEnabled(false); |
bb->setTextFlowMode(currItem->textFlowMode()); |
bb->setSizeLocked(currItem->sizeLocked()); |
bb->setLocked(currItem->locked()); |
bb->NamedLStyle = currItem->NamedLStyle; |
bb->setItemName(currItem->itemName()+"+S"+ccounter.setNum(a)); |
FPoint start = FPoint(glyphs->xoffset-kern, -Upos); |
FPoint stop = FPoint(glyphs->xoffset+Ulen, -Upos); |
bb->PoLine.resize(0); |
bb->PoLine.addQuadPoint(start, start, stop, stop); |
bb->PoLine.map(stro); |
bb->setLineColor(charStyle.fillColor()); |
bb->setLineShade(charStyle.fillShade()); |
bb->setLineWidth(Uwid); |
Doc->adjustItemSize(bb); |
bb->ContourLine = bb->PoLine.copy(); |
bb->ClipEdited = true; |
bb->FrameType = 3; |
bb->OldB2 = bb->width(); |
bb->OldH2 = bb->height(); |
Doc->setRedrawBounding(bb); |
bb->setItemName(currItem->itemName()+"+S"+ccounter.setNum(a)); |
undoManager->setUndoEnabled(true); |
newGroupedItems.append(Doc->Items->takeAt(z)); |
} |
} |
} |
else |
{ |
for (uint ll=0; ll < currItem->textLayout.lines(); ++ll) |
{ |
LineSpec ls = currItem->textLayout.line(ll); |
double CurX = ls.x; |
for (int a = ls.firstItem; a <= ls.lastItem; ++a) |
{ |
pts.resize(0); |
x = 0.0; |
y = 0.0; |
GlyphLayout* glyphs = currItem->itemText.getGlyphs(a); |
const CharStyle& charStyle(currItem->itemText.charStyle(a)); |
chstr = currItem->itemText.text(a,1); |
if ((chstr == SpecialChars::PARSEP) || (chstr == SpecialChars::OLD_NBSPACE)) |
{ |
if (chstr == SpecialChars::OLD_NBSPACE) |
CurX += glyphs->wide(); |
continue; |
} |
if (chstr == SpecialChars::OBJECT) |
{ |
if (currItem->itemText.hasObject(a)) |
{ |
ScriXmlDoc ss; |
Selection tempSelection(this, false); |
tempSelection.addItem(currItem->itemText.object(a), true); |
QString dataS = ss.WriteElem(Doc, &tempSelection); |
emit LoadElem(dataS, currItem->xPos(), currItem->yPos(), false, true, Doc, this); |
bb = Doc->Items->last(); |
int z = Doc->Items->indexOf(bb); |
bb->setTextFlowMode(currItem->textFlowMode()); |
bb->setSizeLocked(currItem->sizeLocked()); |
bb->setLocked(currItem->locked()); |
bb->setItemName(currItem->itemName()+"+"+ccounter.setNum(a)); |
bb->setRotation(currItem->rotation()); |
double textX = CurX + glyphs->xoffset; |
double textY = ls.y - bb->height(); |
if (charStyle.baselineOffset() != 0) |
textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0); |
if (currItem->imageFlippedH()) |
textX = currItem->width() - textX - wide; |
if (currItem->imageFlippedV()) |
textY = currItem->height() - textY + y - (bb->height() - y); |
FPoint npo(textX, textY, 0.0, 0.0, currItem->rotation(), 1.0, 1.0); |
bb->setXYPos(currItem->xPos() + npo.x(), currItem->yPos() + npo.y(), false); |
Doc->setRedrawBounding(bb); |
newGroupedItems.append(Doc->Items->takeAt(z)); |
} |
CurX += glyphs->wide(); |
continue; |
} |
if (chstr == SpecialChars::PAGENUMBER) |
chstr = currItem->ExpandToken(a); |
for (int cx = 0; cx < chstr.count(); cx++) |
{ |
chstrex = chstr[cx]; |
double chs = charStyle.fontSize(); |
if (currItem->itemText.charStyle(a).effects() & ScStyle_SmallCaps) |
{ |
if (chstrex.toUpper() != chstrex) |
{ |
chs = qMax(static_cast<int>(chs * Doc->typographicPrefs().valueSmallCaps / 100), 1); |
chstrex = chstrex.toUpper(); |
} |
} |
else if (currItem->itemText.charStyle(a).effects() & ScStyle_AllCaps) |
chstrex = chstrex.toUpper(); |
double csi = static_cast<double>(chs) / 100.0; |
uint chr = chstrex.unicode(); |
QTransform chma, chma6; |
uint gl = charStyle.font().char2CMap(chr); |
FPoint origin = char |