📄 qsvghandler.cpp
字号:
return ::toDouble(c);}static qreal toDouble(const QStringRef &str){ const QChar *c = str.constData(); return ::toDouble(c);}static QVector<qreal> parseNumbersList(const QChar *&str){ QVector<qreal> points; if (!str) return points; points.reserve(32); while (*str == QLatin1Char(' ')) ++str; while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) || *str == QLatin1Char('-') || *str == QLatin1Char('+') || *str == QLatin1Char('.')) { points.append(::toDouble(str)); while (*str == QLatin1Char(' ')) ++str; if (*str == QLatin1Char(',')) ++str; //eat the rest of space while (*str == QLatin1Char(' ')) ++str; } return points;}static QVector<qreal> parsePercentageList(const QChar *&str){ QVector<qreal> points; if (!str) return points; while (str->isSpace()) ++str; while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) || *str == QLatin1Char('-') || *str == QLatin1Char('+') || *str == QLatin1Char('.')) { points.append(::toDouble(str)); while (*str == QLatin1Char(' ')) ++str; if (*str == QLatin1Char('%')) ++str; while (*str == QLatin1Char(' ')) ++str; if (*str == QLatin1Char(',')) ++str; //eat the rest of space while (*str == QLatin1Char(' ')) ++str; } return points;}static QString idFromUrl(const QString &url){ QString::const_iterator itr = url.constBegin(); while ((*itr).isSpace()) ++itr; if ((*itr) == QLatin1Char('(')) ++itr; while ((*itr).isSpace()) ++itr; if ((*itr) == QLatin1Char('#')) ++itr; QString id; while ((*itr) != QLatin1Char(')')) { id += *itr; ++itr; } return id;}/** * returns true when successfuly set the color. false signifies * that the color should be inherited */static bool resolveColor(const QString &colorStr, QColor &color, QSvgHandler *handler){ static QHash<QString, QColor> colors; QString colorStrTr = colorStr.trimmed(); if (colors.isEmpty()) { colors.insert(QLatin1String("black"), QColor( 0, 0, 0)); colors.insert(QLatin1String("green"), QColor( 0, 128, 0)); colors.insert(QLatin1String("silver"), QColor(192, 192, 192)); colors.insert(QLatin1String("lime"), QColor( 0, 255, 0)); colors.insert(QLatin1String("gray"), QColor(128, 128, 128)); colors.insert(QLatin1String("olive"), QColor(128, 128, 0)); colors.insert(QLatin1String("white"), QColor(255, 255, 255)); colors.insert(QLatin1String("yellow"), QColor(255, 255, 0)); colors.insert(QLatin1String("maroon"), QColor(128, 0, 0)); colors.insert(QLatin1String("navy"), QColor( 0, 0, 128)); colors.insert(QLatin1String("red"), QColor(255, 0, 0)); colors.insert(QLatin1String("blue"), QColor( 0, 0, 255)); colors.insert(QLatin1String("purple"), QColor(128, 0, 128)); colors.insert(QLatin1String("teal"), QColor( 0, 128, 128)); colors.insert(QLatin1String("fuchsia"), QColor(255, 0, 255)); colors.insert(QLatin1String("aqua"), QColor( 0, 255, 255)); } if (colors.contains(colorStrTr)) { color = colors[colorStrTr]; return color.isValid(); } else if (colorStr.startsWith(QLatin1String("rgb("))) { const QChar *s = colorStr.constData() + 4; QVector<qreal> compo = parseNumbersList(s); //1 means that it failed after reaching non-parsable //character which is going to be "%" if (compo.size() == 1) { const QChar *s = colorStr.constData() + 4; compo = parsePercentageList(s); compo[0] *= 2.55; compo[1] *= 2.55; compo[2] *= 2.55; } color = QColor(int(compo[0]), int(compo[1]), int(compo[2])); return true; } else if (colorStr == QLatin1String("inherited") || colorStr == QLatin1String("inherit")) { return false; } else if (colorStr == QLatin1String("currentColor")) { color = handler->currentColor(); return true; } color = QColor(colorStrTr); return color.isValid();}static bool constructColor(const QString &colorStr, const QString &opacity, QColor &color, QSvgHandler *handler){ if (!resolveColor(colorStr, color, handler)) return false; if (!opacity.isEmpty()) { qreal op = ::toDouble(opacity); if (op <= 1) op *= 255; color.setAlpha(int(op)); } return true;}static qreal parseLength(const QString &str, QSvgHandler::LengthType &type, QSvgHandler *handler){ QString numStr = str.trimmed(); if (numStr.endsWith(QLatin1Char('%'))) { numStr.chop(1); type = QSvgHandler::PERCENT; } else if (numStr.endsWith(QLatin1String("px"))) { numStr.chop(2); type = QSvgHandler::PX; } else if (numStr.endsWith(QLatin1String("pc"))) { numStr.chop(2); type = QSvgHandler::PC; } else if (numStr.endsWith(QLatin1String("pt"))) { numStr.chop(2); type = QSvgHandler::PT; } else if (numStr.endsWith(QLatin1String("mm"))) { numStr.chop(2); type = QSvgHandler::MM; } else if (numStr.endsWith(QLatin1String("cm"))) { numStr.chop(2); type = QSvgHandler::CM; } else if (numStr.endsWith(QLatin1String("in"))) { numStr.chop(2); type = QSvgHandler::IN; } else { type = handler->defaultCoordinateSystem(); //type = QSvgHandler::OTHER; } qreal len = ::toDouble(numStr); //qDebug()<<"len is "<<len<<", from '"<<numStr << "'"; return len;}static inline qreal convertToNumber(const QString &str, QSvgHandler *handler){ QSvgHandler::LengthType type; qreal num = parseLength(str, type, handler); if (type == QSvgHandler::PERCENT) { num = num/100.0; } return num;}static bool createSvgGlyph(QSvgFont *font, const QXmlStreamAttributes &attributes){ QStringRef uncStr = attributes.value(QLatin1String("unicode")); QStringRef havStr = attributes.value(QLatin1String("horiz-adv-x")); QStringRef pathStr = attributes.value(QLatin1String("d")); QChar unicode = (uncStr.isEmpty()) ? 0 : uncStr.at(0); qreal havx = (havStr.isEmpty()) ? -1 : ::toDouble(havStr); QPainterPath path; parsePathDataFast(pathStr, path); font->addGlyph(unicode, path, havx); return true;}// this should really be called convertToDefaultCoordinateSystem// and convert when type != QSvgHandler::defaultCoordinateSystemstatic qreal convertToPixels(qreal len, bool , QSvgHandler::LengthType type){ switch (type) { case QSvgHandler::PERCENT: break; case QSvgHandler::PX: break; case QSvgHandler::PC: break; case QSvgHandler::PT: return len * 1.25; break; case QSvgHandler::MM: return len * 3.543307; break; case QSvgHandler::CM: return len * 35.43307; break; case QSvgHandler::IN: return len * 90; break; case QSvgHandler::OTHER: break; default: break; } return len;}static void parseColor(QSvgNode *, const QSvgAttributes &attributes, QSvgHandler *handler){ QString colorStr = attributes.value(QLatin1String("color")).toString(); QString opacity = attributes.value(QLatin1String("color-opacity")).toString(); QColor color; if (constructColor(colorStr, opacity, color, handler)) { handler->pushColor(color); }}static void parseBrush(QSvgNode *node, const QSvgAttributes &attributes, QSvgHandler *handler){ QString value = attributes.value(QLatin1String("fill")).toString(); QString fillRule = attributes.value(QLatin1String("fill-rule")).toString(); QString myId = someId(attributes); value = value.trimmed(); fillRule = fillRule.trimmed(); if (!value.isEmpty() || !fillRule.isEmpty()) { Qt::FillRule f = Qt::OddEvenFill; if (!fillRule.isEmpty()) { if (fillRule == QLatin1String("nonzero")) { f = Qt::WindingFill; } else { f = Qt::OddEvenFill; } } if (value.startsWith(QLatin1String("url"))) { value = value.remove(0, 3); QString id = idFromUrl(value); QSvgStructureNode *group = 0; QSvgNode *dummy = node; while (dummy && (dummy->type() != QSvgNode::DOC && dummy->type() != QSvgNode::G && dummy->type() != QSvgNode::DEFS && dummy->type() != QSvgNode::SWITCH)) { dummy = dummy->parent(); } if (dummy) group = static_cast<QSvgStructureNode*>(dummy); if (group) { QSvgStyleProperty *style = group->scopeStyle(id); if (style) node->appendStyleProperty(style, someId(attributes)); else qWarning("Couldn't resolve property: %s", qPrintable(id)); } } else if (value != QLatin1String("none")) { QString opacity = attributes.value(QLatin1String("fill-opacity")).toString(); QColor color; if (constructColor(value, opacity, color, handler)) { QSvgFillStyle *prop = new QSvgFillStyle(QBrush(color)); if (!fillRule.isEmpty()) prop->setFillRule(f); node->appendStyleProperty(prop, myId); } } else { QSvgFillStyle *prop = new QSvgFillStyle(QBrush(Qt::NoBrush)); if (!fillRule.isEmpty()) prop->setFillRule(f); node->appendStyleProperty(prop, myId); } }}static void parseQPen(QPen &pen, QSvgNode *node, const QSvgAttributes &attributes, QSvgHandler *handler){ QString value = attributes.value(QLatin1String("stroke")).toString(); QString dashArray = attributes.value(QLatin1String("stroke-dasharray")).toString(); QString dashOffset = attributes.value(QLatin1String("stroke-dashoffset")).toString(); QString linecap = attributes.value(QLatin1String("stroke-linecap")).toString(); QString linejoin = attributes.value(QLatin1String("stroke-linejoin")).toString(); QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString(); QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString(); QString width = attributes.value(QLatin1String("stroke-width")).toString(); QString myId = someId(attributes); if (!value.isEmpty() || !width.isEmpty()) { if (value != QLatin1String("none")) { if (!value.isEmpty()) { if (node && value.startsWith(QLatin1String("url"))) { value = value.remove(0, 3); QString id = idFromUrl(value); QSvgStructureNode *group = 0; QSvgNode *dummy = node; while (dummy && (dummy->type() != QSvgNode::DOC && dummy->type() != QSvgNode::G && dummy->type() != QSvgNode::DEFS && dummy->type() != QSvgNode::SWITCH)) { dummy = dummy->parent(); } if (dummy) group = static_cast<QSvgStructureNode*>(dummy); if (group) { QSvgStyleProperty *style = group->scopeStyle(id); if (style->type() == QSvgStyleProperty::GRADIENT) { QBrush b(*((QSvgGradientStyle*)style)->qgradient()); pen.setBrush(b); } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { pen.setColor( ((QSvgSolidColorStyle*)style)->qcolor()); } } else { qDebug()<<"QSvgHandler::parsePen no parent group?"; } } else { QColor color; if (constructColor(value, opacity, color, handler)) pen.setColor(color); } //since we could inherit stroke="none" //we need to reset the style of our stroke to something pen.setStyle(Qt::SolidLine); } if (!width.isEmpty()) { QSvgHandler::LengthType lt; qreal widthF = parseLength(width, lt, handler); //### fixme if (!widthF) { pen.setStyle(Qt::NoPen); return; } pen.setWidthF(widthF);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -