1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 scribusXml.cpp the document xml library for scribus
9 -------------------
10 begin : Sam Jul 14 10:00:00 CEST 2001
11 copyright : (C) 2001 by Christian T�p
12 email : christian.toepp@mr-ct@gmx.de
13 ***************************************************************************/
14
15 #include "scribusXml.h"
16
17 #include <QApplication>
18 #include <QByteArray>
19 #include <QBuffer>
20 #include <QCursor>
21 #include <QDir>
22 #include <QFile>
23 #include <QRegExp>
24 #include <QTextCodec>
25 #include <QTextStream>
26 #include <QXmlStreamReader>
27 #include <QDebug>
28
29 #include <cstdlib>
30
31 #include "commonstrings.h"
32 #include "pageitem.h"
33 #include "pageitem_latexframe.h"
34 #ifdef HAVE_OSG
35 #include "pageitem_osgframe.h"
36 #endif
37 #include "prefsmanager.h"
38 #include "scclocale.h"
39 #include "scmimedata.h"
40 #include "scpage.h"
41 #include "scpaths.h"
42 #include "scribusdoc.h"
43 #include "selection.h"
44 #include "units.h"
45
46 #include <iostream>
47
48 #include "scconfig.h"
49
50 #include "util.h"
51 #include "util_text.h"
52 #include "util_math.h"
53 #include "util_color.h"
54 #include "sclimits.h"
55 #include "scpattern.h"
56 #include "sctextstream.h"
57 #include "scxmlstreamwriter.h"
58 #include "scpainter.h"
59 #include "fileloader.h"
60 #include "loadsaveplugin.h"
61 #include "plugins/formatidlist.h"
62
63 using namespace std;
64
ScriXmlDoc()65 ScriXmlDoc::ScriXmlDoc()
66 {
67 }
68
readElemHeader(const QString & file,bool isFile,double * x,double * y,double * w,double * h)69 bool ScriXmlDoc::readElemHeader(const QString& file, bool isFile, double *x, double *y, double *w, double *h)
70 {
71 QString ff = "";
72 if (isFile)
73 {
74 QByteArray f;
75 if (!loadRawText(file, f))
76 return false;
77 if (f.left(16) == "<SCRIBUSELEMUTF8")
78 ff = QString::fromUtf8(f.data());
79 else
80 ff = f;
81 }
82 else
83 ff = file;
84
85 bool succeed = false;
86 QStringRef tName;
87 QXmlStreamReader sReader(ff);
88 QXmlStreamReader::TokenType tType;
89 while (!sReader.atEnd() && !sReader.hasError())
90 {
91 tType = sReader.readNext();
92 if (tType == QXmlStreamReader::StartElement)
93 {
94 tName = sReader.name();
95 if ((tName == "SCRIBUSELEM") || (tName == "SCRIBUSELEMUTF8"))
96 {
97 QXmlStreamAttributes attrs = sReader.attributes();;
98 QString attx = attrs.value("XP").toString();
99 QString atty = attrs.value("YP").toString();
100 QString attw = attrs.value("W").toString();
101 QString atth = attrs.value("H").toString();
102 *x = (attx.isEmpty()) ? 0.0 : ScCLocale::toDoubleC(attx);
103 *y = (atty.isEmpty()) ? 0.0 : ScCLocale::toDoubleC(atty);
104 *w = (attw.isEmpty()) ? 0.0 : ScCLocale::toDoubleC(attw);
105 *h = (atth.isEmpty()) ? 0.0 : ScCLocale::toDoubleC(atth);
106 succeed = true;
107 }
108 }
109 }
110 return (succeed && !sReader.hasError());
111 }
112
readElem(const QString & fileNameOrData,ScribusDoc * doc,double xPos,double yPos,bool isDataFromFile,bool loc)113 bool ScriXmlDoc::readElem(const QString& fileNameOrData, ScribusDoc *doc, double xPos, double yPos, bool isDataFromFile, bool loc)
114 {
115 // Do not suppose the existence of layer with id = 0
116 // return readElemToLayer(fileName, avail, doc, Xp, Yp, Fi, loc, FontSub, view, 0);
117 return readElemToLayer(fileNameOrData, doc, xPos, yPos, isDataFromFile, loc, doc->activeLayer());
118 }
119
readElemToLayer(const QString & fileNameOrData,ScribusDoc * doc,double xPos,double yPos,bool isDataFromFile,bool loc,int toLayer)120 bool ScriXmlDoc::readElemToLayer(const QString& fileNameOrData, ScribusDoc *doc, double xPos, double yPos, bool isDataFromFile, bool loc, int toLayer)
121 {
122 QString elementData;
123 QString fileDir = ScPaths::applicationDataDir();
124 if (isDataFromFile)
125 {
126 QByteArray f;
127 if (!loadRawText(fileNameOrData, f))
128 return false;
129 if (f.left(16) == "<SCRIBUSELEMUTF8")
130 elementData = QString::fromUtf8(f.data());
131 else
132 elementData = f;
133 fileDir = QFileInfo(fileNameOrData).absolutePath();
134 }
135 else
136 {
137 elementData = fileNameOrData;
138 }
139 // In case elementData contains some old broken scribus xml
140 elementData.replace(QChar(5), SpecialChars::PARSEP);
141 elementData.replace(QChar(4), SpecialChars::TAB);
142 elementData.replace(QChar(0), QChar(32));
143 elementData.replace("", SpecialChars::PARSEP);
144 elementData.replace("", SpecialChars::TAB);
145 const FileFormat *fmt = LoadSavePlugin::getFormatById(FORMATID_SLA150IMPORT);
146 if (fmt)
147 {
148 fmt->setupTargets(doc, nullptr, doc->scMW(), nullptr, &(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts));
149 fmt->loadElements(elementData, fileDir, toLayer, xPos, yPos, loc);
150 return true;
151 }
152 return false;
153 }
154
writeElem(ScribusDoc * doc,Selection * selection)155 QString ScriXmlDoc::writeElem(ScribusDoc *doc, Selection* selection)
156 {
157 if (selection->count()==0)
158 return "";
159 double xp, yp, wp, hp;
160 PageItem *item;
161 QString documentStr = "";
162 item = selection->itemAt(0);
163
164 auto items = getItemsFromSelection(doc, selection);
165
166 double selectionWidth = 0;
167 double selectionHeight = 0;
168 if (selection->isMultipleSelection())
169 {
170 double gx, gy, gw, gh;
171 selection->getGroupRect(&gx, &gy, &gw, &gh);
172 xp = gx;
173 yp = gy;
174 wp = gw;
175 hp = gh;
176 selection->getVisualGroupRect(&gx, &gy, &selectionWidth, &selectionHeight);
177 }
178 else
179 {
180 double minx = std::numeric_limits<double>::max();
181 double miny = std::numeric_limits<double>::max();
182 double maxx = -std::numeric_limits<double>::max();
183 double maxy = -std::numeric_limits<double>::max();
184 double x1, x2, y1, y2;
185 item->getVisualBoundingRect(&x1, &y1, &x2, &y2);
186 xp = qMin(minx, x1);
187 yp = qMin(miny, y1);
188 selectionWidth = wp = qMax(maxx, x2) - xp;
189 selectionHeight = hp = qMax(maxy, y2) - yp;
190 }
191 double scaleI = 50.0 / qMax(selectionWidth, selectionHeight);
192 QImage retImg = QImage(50, 50, QImage::Format_ARGB32_Premultiplied);
193 retImg.fill( qRgba(0, 0, 0, 0) );
194 ScPainter *painter = new ScPainter(&retImg, retImg.width(), retImg.height(), 1, 0);
195 painter->setZoomFactor(scaleI);
196 for (int em = 0; em < items.count(); ++em)
197 {
198 PageItem* embedded = items.at(em);
199 painter->save();
200 painter->translate(-xp, -yp);
201 embedded->invalid = true;
202 embedded->DrawObj(painter, QRectF());
203 painter->restore();
204 }
205 int pg = doc->OnPage(xp + wp / 2.0, yp + hp / 2.0);
206 if (pg > -1)
207 {
208 xp = xp - doc->getXOffsetForPage(pg);
209 yp = yp - doc->getYOffsetForPage(pg);
210 }
211 delete painter;
212 QBuffer buffer;
213 buffer.open(QIODevice::WriteOnly);
214 retImg.save(&buffer, "PNG");
215 QByteArray ba = buffer.buffer().toBase64();
216 buffer.close();
217 const FileFormat *fmt = LoadSavePlugin::getFormatById(FORMATID_SLA150EXPORT);
218 if (fmt)
219 {
220 fmt->setupTargets(doc, nullptr, doc->scMW(), nullptr, &(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts));
221 documentStr = fmt->saveElements(xp, yp, wp, hp, selection, ba);
222 }
223 return documentStr;
224 }
225
writeToMimeData(ScribusDoc * doc,Selection * selection)226 ScElemMimeData* ScriXmlDoc::writeToMimeData(ScribusDoc *doc, Selection *selection)
227 {
228 ScElemMimeData* md = new ScElemMimeData();
229 md->setScribusElem(writeElem(doc, selection));
230 return md;
231 }
232
getItemsFromSelection(ScribusDoc * doc,Selection * selection)233 QList<PageItem*> ScriXmlDoc::getItemsFromSelection(ScribusDoc *doc, Selection* selection)
234 {
235 QMap<int, PageItem*> items;
236
237 const QList<PageItem*> selectedItems = selection->items();
238 for (auto item : selectedItems)
239 items.insert(doc->Items->indexOf(item), item);
240 return items.values();
241 }