⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q3paintengine_svg.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        {"ellipse",  EllipseElement },        {"g",        GroupElement   },        {"image",    ImageElement   },        {"line",     LineElement    },        {"polyline", PolylineElement},        {"polygon",  PolygonElement },        {"path",     PathElement    },        {"rect",     RectElement    },        {"svg",      SvgElement     },        {"text",     TextElement    },        {"tspan",    TSpanElement   },        {"title",    TitleElement   },        {0,          InvalidElement }    };    // initialize only once    if (!qSvgTypeMap) {        qSvgTypeMap = new QSvgTypeMap;        const ElementTable *t = etab;        while (t->name) {            qSvgTypeMap->insert(QLatin1String(t->name), t->type);            t++;        }    }    // initial state    Q3SVGPaintEngineState st;    st.textx = st.texty = 0;    st.textalign = Qt::AlignLeft;    d->stack.append(st);    d->curr = &d->stack.last();    // 'play' all elements recursively starting with 'svg' as root    bool b = d->play(svg, pt);    d->stack.removeFirst();    return b;}bool Q3SVGPaintEnginePrivate::play(const QDomNode &node, QPainter *pt){    saveAttributes(pt);    ElementType t = (*qSvgTypeMap)[node.nodeName()];    if (t == LineElement && pt->pen().style() == Qt::NoPen) {        QPen p = pt->pen();        p.setStyle(Qt::SolidLine);        pt->setPen(p);    }    QDomNamedNodeMap attr = node.attributes();    if (attr.contains(QLatin1String("style")))        setStyle(attr.namedItem(QLatin1String("style")).nodeValue(), pt);    // ### might have to exclude more elements from transform    if (t != SvgElement && attr.contains(QLatin1String("transform")))        setTransform(attr.namedItem(QLatin1String("transform")).nodeValue(), pt);    uint i = attr.length();    if (i > 0) {        QPen pen = pt->pen();        QFont font = pt->font();        while (i--) {            QDomNode n = attr.item(i);            QString a = n.nodeName();            QString val = n.nodeValue().toLower().trimmed();            setStyleProperty(a, val, &pen, &font, &curr->textalign, pt);        }        pt->setPen(pen);        pt->setFont(font);    }    double x1, y1, x2, y2, rx, ry, w, h;    double cx1, cy1, crx, cry;    switch (t) {    case CommentElement:        // ignore        break;    case RectElement:        rx = ry = 0;        x1 = lenToDouble(attr, QLatin1String("x"));        y1 = lenToDouble(attr, QLatin1String("y"));        w = lenToDouble(attr, QLatin1String("width"));        h = lenToDouble(attr, QLatin1String("height"));        if (w == 0 || h == 0) // prevent div by zero below            break;        x2 = attr.contains(QLatin1String("rx")); // tiny abuse of x2 and y2        y2 = attr.contains(QLatin1String("ry"));        if (x2)            rx = lenToDouble(attr, QLatin1String("rx"));        if (y2)            ry = lenToDouble(attr, QLatin1String("ry"));        if (x2 && !y2)            ry = rx;        else if (!x2 && y2)            rx = ry;        rx = 200.0*rx / w;        ry = 200.0*ry / h;        pt->drawRoundRect(QRectF(x1, y1, w, h), int(rx), int(ry));        break;    case CircleElement:        cx1 = lenToDouble(attr, QLatin1String("cx")) + 0.5;        cy1 = lenToDouble(attr, QLatin1String("cy")) + 0.5;        crx = lenToDouble(attr, QLatin1String("r"));        pt->drawEllipse(QRectF(cx1-crx, cy1-crx, 2*crx, 2*crx));        break;    case EllipseElement:        cx1 = lenToDouble(attr, QLatin1String("cx")) + 0.5;        cy1 = lenToDouble(attr, QLatin1String("cy")) + 0.5;        crx = lenToDouble(attr, QLatin1String("rx"));        cry = lenToDouble(attr, QLatin1String("ry"));        pt->drawEllipse(QRectF(cx1-crx, cy1-cry, 2*crx, 2*cry));        break;    case LineElement:        {            x1 = lenToDouble(attr, QLatin1String("x1"));            x2 = lenToDouble(attr, QLatin1String("x2"));            y1 = lenToDouble(attr, QLatin1String("y1"));            y2 = lenToDouble(attr, QLatin1String("y2"));            QPen p = pt->pen();            w = p.width();            p.setWidth((unsigned int)(w * (qAbs(pt->worldMatrix().m11()) + qAbs(pt->worldMatrix().m22())) / 2));            pt->setPen(p);            pt->drawLine(QLineF(x1, y1, x2, y2));            p.setWidthF(w);            pt->setPen(p);        }        break;    case PolylineElement:    case PolygonElement:        {            QString pts = attr.namedItem(QLatin1String("points")).nodeValue();            pts = pts.simplified();            QStringList sl = pts.split(QRegExp(QString::fromLatin1("[,\\s]")),                                               QString::SkipEmptyParts);            QPolygonF ptarr((uint) sl.count() / 2);            for (int i = 0; i < (int) sl.count() / 2; i++) {                double dx = sl[2*i].toDouble();                double dy = sl[2*i+1].toDouble();                ptarr[i] = QPointF(dx, dy);            }            if (t == PolylineElement) {                if (pt->brush().style() != Qt::NoBrush) {                    QPen pn = pt->pen();                    pt->setPen(Qt::NoPen);                    pt->drawPolygon(ptarr);                    pt->setPen(pn);                }                pt->drawPolyline(ptarr); // ### closes when filled. bug ?            } else {                pt->drawPolygon(ptarr);            }        }        break;    case SvgElement:    case GroupElement:    case AnchorElement:        {            QDomNode child = node.firstChild();            while (!child.isNull()) {                play(child, pt);                child = child.nextSibling();            }        }        break;    case PathElement:        drawPath(attr.namedItem(QLatin1String("d")).nodeValue(), pt);        break;    case TSpanElement:    case TextElement:        {            if (attr.contains(QLatin1String("x")))                 curr->textx = lenToDouble(attr, QLatin1String("x"));            if (attr.contains(QLatin1String("y")))                 curr->texty = lenToDouble(attr, QLatin1String("y"));            if (t == TSpanElement) {                curr->textx += lenToDouble(attr, QLatin1String("dx"));                curr->texty += lenToDouble(attr, QLatin1String("dy"));            }            // backup old colors            QPen pn = pt->pen();            QColor pcolor = pn.color();            QColor bcolor = pt->brush().color();            QDomNode c = node.firstChild();            while (!c.isNull()) {                if (c.isText()) {                    // we have pen and brush reversed for text drawing                    pn.setColor(bcolor);                    pt->setPen(pn);                    QString text = c.toText().nodeValue();                    text = text.simplified(); // ### 'preserve'                    w = pt->fontMetrics().width(text);                    if (curr->textalign == Qt::AlignHCenter)                        curr->textx -= w / 2;                    else if (curr->textalign == Qt::AlignRight)                        curr->textx -= w;                    pt->drawText(QPointF(curr->textx, curr->texty), text);                    // restore pen                    pn.setColor(pcolor);                    pt->setPen(pn);                    curr->textx += w;                } else if (c.isElement() && c.toElement().tagName() == QLatin1String("tspan")) {                    play(c, pt);                }                c = c.nextSibling();            }            if (t == TSpanElement) {                // move current text position in parent text element                StateList::Iterator it = --(--stack.end());                (*it).textx = curr->textx;                (*it).texty = curr->texty;            }        }        break;    case ImageElement:        {            x1 = lenToDouble(attr, QLatin1String("x"));            y1 = lenToDouble(attr, QLatin1String("y"));            w = lenToDouble(attr, QLatin1String("width"));            h = lenToDouble(attr, QLatin1String("height"));            QString href = attr.namedItem(QLatin1String("xlink:href")).nodeValue();            // ### catch references to embedded .svg files            QPixmap pix;            if (!pix.load(href)){                qWarning("Q3SVGPaintEngine::play: Couldn't load image %s",href.latin1());                break;            }            pt->drawPixmap(QRectF(x1, y1, w, h), pix, QRectF());        }        break;    case DescElement:    case TitleElement:        // ignored for now        break;    case ClipElement:        {            restoreAttributes(pt); // To ensure the clip rect is saved, we need to restore now            QDomNode child = node.firstChild();            QDomNamedNodeMap childAttr = child.attributes();            if (child.nodeName() == QLatin1String("rect")) {                QRect r;                r.setX(lenToInt(childAttr, QLatin1String("x")));                r.setY(lenToInt(childAttr, QLatin1String("y")));                r.setWidth(lenToInt(childAttr, QLatin1String("width")));                r.setHeight(lenToInt(childAttr, QLatin1String("height")));                pt->setClipRect(r);            } else if (child.nodeName() == QLatin1String("ellipse")) {                QRect r;                int x = lenToInt(childAttr, QLatin1String("cx"));                int y = lenToInt(childAttr, QLatin1String("cy"));                int width = lenToInt(childAttr, QLatin1String("rx"));                int height = lenToInt(childAttr, QLatin1String("ry"));                r.setX(x - width);                r.setY(y - height);                r.setWidth(width * 2);                r.setHeight(height * 2);                QRegion rgn(r, QRegion::Ellipse);                pt->setClipRegion(rgn);            }            break;        }    case InvalidElement:        qWarning("Q3SVGPaintEngine::play: unknown element type %s", node.nodeName().latin1());        break;    }    if (t != ClipElement)        restoreAttributes(pt);    return true;}/*!    \internal    Parse a <length> datatype consisting of a number followed by an    optional unit specifier. Can be used for type <coordinate> as    well. For relative units the value of \a horiz will determine    whether the horizontal or vertical dimension will be used.*/double Q3SVGPaintEnginePrivate::parseLen(const QString &str, bool *ok, bool horiz) const{    QRegExp reg(QString::fromLatin1("([+-]?\\d*\\.*\\d*[Ee]?[+-]?\\d*)(em|ex|px|%|pt|pc|cm|mm|in|)$"));    if (reg.indexIn(str) == -1) {        qWarning("Q3SVGPaintEngine::parseLen: couldn't parse %s", str.latin1());        if (ok)            *ok = false;        return 0.0;    }    double dbl = reg.cap(1).toDouble();    QString u = reg.cap(2);    if (!u.isEmpty() && u != QLatin1String("px")) {        if (u == QLatin1String("em")) {            QFontInfo fi(cfont);            dbl *= fi.pixelSize();        } else if (u == QLatin1String("ex")) {            QFontInfo fi(cfont);            dbl *= 0.5 * fi.pixelSize();        } else if (u == QLatin1String("%"))            dbl *= (horiz ? wwidth : wheight)/100.0;        else if (u == QLatin1String("cm"))            dbl *= dev->logicalDpiX() / 2.54;        else if (u == QLatin1String("mm"))            dbl *= dev->logicalDpiX() / 25.4;        else if (u == QLatin1String("in"))            dbl *= dev->logicalDpiX();        else if (u == QLatin1String("pt"))            dbl *= dev->logicalDpiX() / 72.0;        else if (u == QLatin1String("pc"))            dbl *= dev->logicalDpiX() / 6.0;        else            qWarning("Q3SVGPaintEngine::parseLen: Unknown unit %s", u.latin1());    }    if (ok)        *ok = true;    return dbl;}/*!    \internal    Returns the length specified in attribute \a attr in \a map. If    the specified attribute doesn't exist or can't be parsed \a def is    returned.*/int Q3SVGPaintEnginePrivate::lenToInt(const QDomNamedNodeMap &map, const QString &attr, int def) const{    if (map.contains(attr)) {        bool ok;        double dbl = parseLen(map.namedItem(attr).nodeValue(), &ok);        if (ok)            return qRound(dbl);    }    return def;}double Q3SVGPaintEnginePrivate::lenToDouble(const QDomNamedNodeMap &map, const QString &attr,                                    int def) const{    if (map.contains(attr)) {        bool ok;        double x = parseLen(map.namedItem(attr).nodeValue(), &ok);        if (ok) return x;    }    return static_cast<double>(def);}void Q3SVGPaintEnginePrivate::setTransform(const QString &tr, QPainter *pt){    QString t = tr.simplified();    QRegExp reg(QString::fromLatin1("\\s*([\\w]+)\\s*\\(([^\\(]*)\\)"));    int index = 0;    while ((index = reg.indexIn(t, index)) >= 0) {        QString command = reg.cap(1);        QString params = reg.cap(2);        QStringList plist = params.split(QRegExp(QString::fromLatin1("[,\\s]")),                                         QString::SkipEmptyParts);        if (command == QLatin1String("translate")) {            double tx = 0, ty = 0;            tx = plist[0].toDouble();            if (plist.count() >= 2)                ty = plist[1].toDouble();            pt->translate(tx, ty);        } else if (command == QLatin1String("rotate")) {            pt->rotate(plist[0].toDouble());        } else if (command == QLatin1String("scale")) {            double sx, sy;            sx = sy = plist[0].toDouble();            if (plist.count() >= 2)                sy = plist[1].toDouble();            pt->scale(sx, sy);        } else if (command == QLatin1String("matrix") && plist.count() >= 6) {            double m[6];            for (int i = 0; i < 6; i++)                m[i] = plist[i].toDouble();            QMatrix wm(m[0], m[1], m[2], m[3], m[4], m[5]);            pt->setWorldMatrix(wm, true);        } else if (command == QLatin1String("skewX")) {            pt->shear(0.0, tan(plist[0].toDouble() * deg2rad));        } else if (command == QLatin1String("skewY")) {            pt->shear(tan(plist[0].toDouble() * deg2rad), 0.0);        }        // move on to next command

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -