void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds) { if (m_time.isNull()) { m_time.start(); } if (m_viewBox.isNull()) { QMatrix matx = QMatrix(); m_viewBox = transformedBounds(matx); } p->save(); //sets default style on the painter //### not the most optimal way adjustWindowBounds(p, bounds, m_viewBox); p->setPen(Qt::NoPen); p->setBrush(Qt::black); p->setRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::SmoothPixmapTransform); QList<QSvgNode*>::iterator itr = m_renderers.begin(); applyStyle(p); while (itr != m_renderers.end()) { QSvgNode *node = *itr; if (node->isVisible()) node->draw(p); ++itr; } revertStyle(p); p->restore(); }
void QSvgPath::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); m_path.setFillRule(states.fillRule); QT_SVG_DRAW_SHAPE(p->drawPath(m_path)); revertStyle(p, states); }
QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const { applyStyle(p, states); QRectF rect = bounds(p, states); revertStyle(p, states); return rect; }
void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds) { if (m_time.isNull()) { m_time.start(); } if (displayMode() == QSvgNode::NoneMode) return; p->save(); //sets default style on the painter //### not the most optimal way mapSourceToTarget(p, bounds); QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); pen.setMiterLimit(4); p->setPen(pen); p->setBrush(Qt::black); p->setRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::SmoothPixmapTransform); QList<QSvgNode*>::iterator itr = m_renderers.begin(); applyStyle(p, m_states); while (itr != m_renderers.end()) { QSvgNode *node = *itr; if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) node->draw(p, m_states); ++itr; } revertStyle(p, m_states); p->restore(); }
void QSvgRect::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); if (m_rx || m_ry) { QT_SVG_DRAW_SHAPE(p->drawRoundedRect(m_rect, m_rx, m_ry, Qt::RelativeSize)); } else { QT_SVG_DRAW_SHAPE(p->drawRect(m_rect)); } revertStyle(p, states); }
void QSvgLine::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); p->drawLine(m_line); p->setOpacity(oldOpacity); } revertStyle(p, states); }
void QSvgPolyline::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); if (p->brush().style() != Qt::NoBrush) { QPen save = p->pen(); p->setPen(QPen(Qt::NoPen)); p->drawPolygon(m_poly); p->setPen(save); } p->drawPolyline(m_poly); revertStyle(p, states); }
void QSvgG::draw(QPainter *p, QSvgExtraStates &states) { QList<QSvgNode*>::iterator itr = m_renderers.begin(); applyStyle(p, states); while (itr != m_renderers.end()) { QSvgNode *node = *itr; if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) node->draw(p, states); ++itr; } revertStyle(p, states); }
void QSvgUse::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); if (!m_start.isNull()) { p->translate(m_start); } m_link->draw(p, states); if (!m_start.isNull()) { p->translate(-m_start); } revertStyle(p, states); }
void QSvgPolyline::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); qreal oldOpacity = p->opacity(); if (p->brush().style() != Qt::NoBrush) { QPen save = p->pen(); p->setPen(QPen(Qt::NoPen)); p->setOpacity(oldOpacity * states.fillOpacity); p->drawPolygon(m_poly, states.fillRule); p->setPen(save); } if (p->pen().widthF() != 0) { p->setOpacity(oldOpacity * states.strokeOpacity); p->drawPolyline(m_poly); } p->setOpacity(oldOpacity); revertStyle(p, states); }
void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); revertStyle(p, states); }
void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.fillOpacity); // Force the font to have a size of 100 pixels to avoid truncation problems // when the font is very small. qreal scale = 100.0 / p->font().pointSizeF(); Qt::Alignment alignment = states.textAnchor; QTransform oldTransform = p->worldTransform(); p->scale(1 / scale, 1 / scale); qreal y = 0; bool initial = true; qreal px = m_coord.x() * scale; qreal py = m_coord.y() * scale; QSizeF scaledSize = m_size * scale; if (m_type == TEXTAREA) { if (alignment == Qt::AlignHCenter) px += scaledSize.width() / 2; else if (alignment == Qt::AlignRight) px += scaledSize.width(); } QRectF bounds; if (m_size.height() != 0) bounds = QRectF(0, py, 1, scaledSize.height()); // x and width are not used. bool appendSpace = false; QVector<QString> paragraphs; QStack<QTextCharFormat> formats; QVector<QList<QTextLayout::FormatRange> > formatRanges; paragraphs.push_back(QString()); formatRanges.push_back(QList<QTextLayout::FormatRange>()); for (int i = 0; i < m_tspans.size(); ++i) { if (m_tspans[i] == LINEBREAK) { if (m_type == TEXTAREA) { if (paragraphs.back().isEmpty()) { QFont font = p->font(); font.setPixelSize(font.pointSizeF() * scale); QTextLayout::FormatRange range; range.start = 0; range.length = 1; range.format.setFont(font); formatRanges.back().append(range); paragraphs.back().append(QLatin1Char(' '));; } appendSpace = false; paragraphs.push_back(QString()); formatRanges.push_back(QList<QTextLayout::FormatRange>()); } } else { WhitespaceMode mode = m_tspans[i]->whitespaceMode(); m_tspans[i]->applyStyle(p, states); QFont font = p->font(); font.setPixelSize(font.pointSizeF() * scale); QString newText(m_tspans[i]->text()); newText.replace(QLatin1Char('\t'), QLatin1Char(' ')); newText.replace(QLatin1Char('\n'), QLatin1Char(' ')); bool prependSpace = !appendSpace && !m_tspans[i]->isTspan() && (mode == Default) && !paragraphs.back().isEmpty() && newText.startsWith(QLatin1Char(' ')); if (appendSpace || prependSpace) paragraphs.back().append(QLatin1Char(' ')); bool appendSpaceNext = (!m_tspans[i]->isTspan() && (mode == Default) && newText.endsWith(QLatin1Char(' '))); if (mode == Default) { newText = newText.simplified(); if (newText.isEmpty()) appendSpaceNext = false; } QTextLayout::FormatRange range; range.start = paragraphs.back().length(); range.length = newText.length(); range.format.setFont(font); range.format.setTextOutline(p->pen()); range.format.setForeground(p->brush()); if (appendSpace) { Q_ASSERT(!formatRanges.back().isEmpty()); ++formatRanges.back().back().length; } else if (prependSpace) { --range.start; ++range.length; } formatRanges.back().append(range); appendSpace = appendSpaceNext; paragraphs.back() += newText; m_tspans[i]->revertStyle(p, states); } } if (states.svgFont) { // SVG fonts not fully supported... QString text = paragraphs.front(); for (int i = 1; i < paragraphs.size(); ++i) { text.append(QLatin1Char('\n')); text.append(paragraphs[i]); } states.svgFont->draw(p, m_coord * scale, text, p->font().pointSizeF() * scale, states.textAnchor); } else { for (int i = 0; i < paragraphs.size(); ++i) { QTextLayout tl(paragraphs[i]); QTextOption op = tl.textOption(); op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); tl.setTextOption(op); tl.setAdditionalFormats(formatRanges[i]); tl.beginLayout(); forever { QTextLine line = tl.createLine(); if (!line.isValid()) break; if (m_size.width() != 0) line.setLineWidth(scaledSize.width()); } tl.endLayout(); bool endOfBoundsReached = false; for (int i = 0; i < tl.lineCount(); ++i) { QTextLine line = tl.lineAt(i); qreal x = 0; if (alignment == Qt::AlignHCenter) x -= 0.5 * line.naturalTextWidth(); else if (alignment == Qt::AlignRight) x -= line.naturalTextWidth(); if (initial && m_type == TEXT) y -= line.ascent(); initial = false; line.setPosition(QPointF(x, y)); // Check if the current line fits into the bounding rectangle. if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width()) || (m_size.height() != 0 && y + line.height() > scaledSize.height())) { // I need to set the bounds height to 'y-epsilon' to avoid drawing the current // line. Since the font is scaled to 100 units, 1 should be a safe epsilon. bounds.setHeight(y - 1); endOfBoundsReached = true; break; } y += 1.1 * line.height(); } tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds); if (endOfBoundsReached) break; } } p->setWorldTransform(oldTransform, false); p->setOpacity(oldOpacity); revertStyle(p, states); }
void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); p->drawPath(cubic); revertStyle(p, states); }
void QSvgPolygon::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, states.fillRule)); revertStyle(p, states); }
void QSvgLine::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); p->drawLine(m_bounds); revertStyle(p, states); }
void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>( styleProperty(QSvgStyleProperty::FONT)); if (fontStyle && fontStyle->svgFont()) { // SVG fonts not fully supported... QString text = m_paragraphs.front(); for (int i = 1; i < m_paragraphs.size(); ++i) { text.append(QLatin1Char('\n')); text.append(m_paragraphs[i]); } fontStyle->svgFont()->draw(p, m_coord, text, fontStyle->pointSize(), m_textAlignment); revertStyle(p, states); return; } // Scale the font to its correct size. QTransform oldTransform = p->worldTransform(); p->scale(1 / m_scale, 1 / m_scale); qreal y = 0; bool initial = true; qreal px = m_coord.x() * m_scale; qreal py = m_coord.y() * m_scale; QSizeF scaledSize = m_size * m_scale; if (m_type == TEXTAREA) { if (m_textAlignment == Qt::AlignHCenter) px += scaledSize.width() / 2; else if (m_textAlignment == Qt::AlignRight) px += scaledSize.width(); } QRectF bounds; if (m_size.height() != 0) bounds = QRectF(0, 0, 1, scaledSize.height()); for (int i = 0; i < m_paragraphs.size(); ++i) { QTextLayout tl(m_paragraphs[i]); QTextOption op = tl.textOption(); op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); tl.setTextOption(op); tl.setAdditionalFormats(m_formatRanges[i]); tl.beginLayout(); forever { QTextLine line = tl.createLine(); if (!line.isValid()) break; if (m_size.width() != 0) line.setLineWidth(scaledSize.width()); } tl.endLayout(); bool endOfBoundsReached = false; for (int i = 0; i < tl.lineCount(); ++i) { QTextLine line = tl.lineAt(i); qreal x = 0; if (m_textAlignment == Qt::AlignHCenter) x -= line.naturalTextWidth() / 2; else if (m_textAlignment == Qt::AlignRight) x -= line.naturalTextWidth(); if (initial && m_type == TEXT) y -= line.ascent(); initial = false; line.setPosition(QPointF(x, y)); if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width()) || (m_size.height() != 0 && y + line.height() > scaledSize.height())) { bounds.setHeight(y); endOfBoundsReached = true; break; } y += 1.1 * line.height(); } tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds); if (endOfBoundsReached) break; } p->setWorldTransform(oldTransform, false); revertStyle(p, states); }
void QSvgVideo::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); revertStyle(p, states); }
void QSvgImage::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); p->drawImage(m_bounds, m_image); revertStyle(p, states); }
void QSvgSwitch::draw(QPainter *p, QSvgExtraStates &states) { QList<QSvgNode*>::iterator itr = m_renderers.begin(); applyStyle(p, states); while (itr != m_renderers.end()) { QSvgNode *node = *itr; if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) { const QStringList &features = node->requiredFeatures(); const QStringList &extensions = node->requiredExtensions(); const QStringList &languages = node->requiredLanguages(); const QStringList &formats = node->requiredFormats(); const QStringList &fonts = node->requiredFonts(); bool okToRender = true; if (!features.isEmpty()) { QStringList::const_iterator sitr = features.constBegin(); for (; sitr != features.constEnd(); ++sitr) { if (!isSupportedSvgFeature(*sitr)) { okToRender = false; break; } } } if (okToRender && !extensions.isEmpty()) { QStringList::const_iterator sitr = extensions.constBegin(); for (; sitr != extensions.constEnd(); ++sitr) { if (!isSupportedSvgExtension(*sitr)) { okToRender = false; break; } } } if (okToRender && !languages.isEmpty()) { QStringList::const_iterator sitr = languages.constBegin(); okToRender = false; for (; sitr != languages.constEnd(); ++sitr) { if ((*sitr).startsWith(m_systemLanguagePrefix)) { okToRender = true; break; } } } if (okToRender && !formats.isEmpty()) { okToRender = false; } if (okToRender && !fonts.isEmpty()) { okToRender = false; } if (okToRender) { node->draw(p, states); break; } } ++itr; } revertStyle(p, states); }