#pragma execution_character_set( "utf-8" ) #ifndef CCSSVGTOPDF_H #define CCSSVGTOPDF_H #include #include #include #include #include #include #include //#include //#include #if QT_VERSION == QT_VERSION_CHECK(5, 15, 2) #include #include #endif // #if QT_VERSION == QT_VERSION_CHECK(5, 15, 4) #include #include #endif // #if QT_VERSION == QT_VERSION_CHECK(5, 12, 0) #include #include #endif // #if QT_VERSION == QT_VERSION_CHECK(5, 15, 0) #include #include #endif #if QT_VERSION == QT_VERSION_CHECK(6, 3, 2) #include #include #include #endif class ReportSVGRender { public: void Render(QString strPath, QPainter* pPainter,QRectF bounds,int iOption = 0) { //std::string str = (strPath).toLocal8Bit(); std::string str = (strPath).toStdString(); const char* ch = str.c_str(); FILE* pf = fopen(ch, "rb+"); if (pf == nullptr) return; QFile file; file.open(pf, QIODevice::ReadOnly, QFileDevice::AutoCloseHandle); QByteArray data = file.readAll(); if (iOption == 1) { QSvgRenderer* pRenderer = new QSvgRenderer(data); pRenderer->render(pPainter, bounds); file.close(); fclose(pf); delete pRenderer; } else { QXmlStreamReader xml(data); QSvgTinyDocument* doc = QSvgTinyDocument::load(data); QSvgExtraStates states; WriteText(pPainter, doc, states, bounds, &xml); file.close(); fclose(pf); delete doc; } } bool xmlToNode(QXmlStreamReader* xml, QSvgNode::Type type) { while (!xml->atEnd()) { switch (xml->readNext()) { case QXmlStreamReader::StartElement: { QString localName = xml->name().toString(); if ((type == QSvgNode::G && localName == "g") || (type == QSvgNode::TEXT && localName == "text")) { return true; } } default: break; } } return false; } void WriteNodeText(QPainter* pPainter, QSvgStructureNode* parentNode, QSvgExtraStates& states, QXmlStreamReader* xml) { QList nodeList = parentNode->renderers(); QList::iterator itr = nodeList.begin(); //QList parentNode->applyStyle(pPainter, states); while (itr != nodeList.end()) { QSvgNode* node = *itr; if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) { if (node->type() == QSvgNode::TEXT) { QSvgText* textNode = static_cast(node); textNode->applyStyle(pPainter, states); qreal oldOpacity = pPainter->opacity(); pPainter->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 / pPainter->font().pointSizeF(); Qt::Alignment alignment = states.textAnchor; QTransform oldTransform = pPainter->worldTransform(); pPainter->scale(1 / scale, 1 / scale); QFont font = pPainter->font(); font.setPixelSize(font.pointSizeF() * scale); pPainter->setFont(font); xmlToNode(xml, QSvgNode::TEXT); QXmlStreamAttributes attributes = xml->attributes(); //const QStringRef x = attributes.value(QLatin1String("x")); //const QStringRef y = attributes.value(QLatin1String("y")); const QStringView x = attributes.value(QLatin1String("x")); const QStringView y = attributes.value(QLatin1String("y")); #if QT_VERSION == QT_VERSION_CHECK(5, 12, 0) qreal nx = x.toString().toDouble() * scale; qreal ny = y.toString().toDouble() * scale; #else qreal nx = x.toDouble() * scale; qreal ny = y.toDouble() * scale; #endif // QString text = xmlText(xml); pPainter->drawText(QPointF(nx, ny), text); pPainter->setWorldTransform(oldTransform, false); pPainter->setOpacity(oldOpacity); textNode->revertStyle(pPainter, states); } else if (node->type() == QSvgNode::G) { QSvgStructureNode* nodeG = static_cast(node); xmlToNode(xml, QSvgNode::G); WriteNodeText(pPainter, nodeG, states, xml); } else { node->draw(pPainter, states); } } ++itr; } parentNode->revertStyle(pPainter, states); } void WriteText(QPainter* pPainter, QSvgTinyDocument* doc, QSvgExtraStates& states, QRectF& bounds, QXmlStreamReader* xml) { QRectF source = doc->viewBox(); //QMatrix matrixSrc = pPainter->matrix(); QTransform curTransform = pPainter->transform(); if (source != bounds && !source.isNull()) { QTransform transform; transform.scale(bounds.width() / source.width(), bounds.height() / source.height()); QRectF c2 = transform.mapRect(source); pPainter->translate(bounds.x() - c2.x(), bounds.y() - c2.y()); pPainter->scale(bounds.width() / source.width(), bounds.height() / source.height()); } WriteNodeText(pPainter, doc, states, xml); pPainter->setTransform(curTransform); //pPainter->setMatrix(matrixSrc); } void WriteText(QPainter* pPainter, QSvgTinyDocument* doc, QSvgExtraStates& states, QXmlStreamReader* xml) { WriteNodeText(pPainter, doc, states, xml); } QString xmlText(QXmlStreamReader* xml) { while (!xml->atEnd()) { switch (xml->readNext()) { case QXmlStreamReader::Characters: return xml->text().toString(); break; default: break; } } return ""; } }; #endif