Rev 14710 | Rev 14721 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
13951 | fschmid | 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 | /* Code inspired by KOffice libwmf and adapted for Scribus by Jean Ghali */ |
||
9 | |||
10 | #include "scconfig.h" |
||
11 | #include "wmfimport.h" |
||
12 | |||
13 | #include <QCursor> |
||
14 | #include <QDrag> |
||
15 | #include <QBuffer> |
||
16 | #include <QDataStream> |
||
17 | #include <QFile> |
||
18 | #include <QMimeData> |
||
19 | #include <QPainterPath> |
||
20 | #include <QRegExp> |
||
21 | |||
14170 | jghali | 22 | #include "commonstrings.h" |
13951 | fschmid | 23 | #include "scribus.h" |
24 | #include "scribusXml.h" |
||
14170 | jghali | 25 | #include "fonts/scfontmetrics.h" |
13951 | fschmid | 26 | #include "fpointarray.h" |
14509 | cbradney | 27 | #include "ui/scmwmenumanager.h" |
13951 | fschmid | 28 | #include "prefsmanager.h" |
29 | #include "pageitem.h" |
||
14170 | jghali | 30 | #include "prefsfile.h" |
13951 | fschmid | 31 | #include "scmimedata.h" |
32 | #include "scraction.h" |
||
33 | #include "scribuscore.h" |
||
34 | #include "scribusdoc.h" |
||
35 | #include "selection.h" |
||
14170 | jghali | 36 | #include "ui/customfdialog.h" |
37 | #include "ui/propertiespalette.h" |
||
13951 | fschmid | 38 | #include "undomanager.h" |
39 | #include "loadsaveplugin.h" |
||
40 | #include "util.h" |
||
41 | #include "util_icon.h" |
||
42 | #include "util_math.h" |
||
43 | |||
14170 | jghali | 44 | |
13951 | fschmid | 45 | using namespace std; |
46 | |||
47 | #include "wmfstruct.h" |
||
48 | #include "wmfcmd.h" |
||
49 | #include "wmfcontext.h" |
||
50 | #include "wmfhandle.h" |
||
51 | #include "metafuncs.h" |
||
52 | |||
53 | #define WMFIMPORT_DEBUG 0 |
||
54 | #define MAX_OBJHANDLE 128 |
||
55 | |||
56 | #define ANSI_CHARSET 0 // ANSI charset (Windows-1252) |
||
57 | #define DEFAULT_CHARSET 1 |
||
58 | #define SYMBOL_CHARSET 2 |
||
59 | #define MAC_CHARSET 77 |
||
60 | #define SHIFTJIS_CHARSET 128 // Shift JIS charset (Windows-932) |
||
61 | #define HANGEUL_CHARSET 129 // Hangeul charset (Windows-949) |
||
62 | #define JOHAB_CHARSET 130 // Johab charset (Windows-1361) |
||
63 | #define GB2312_CHARSET 134 // GB2312 charset (Windows-936) |
||
64 | #define CHINESEBIG5_CHARSET 136 // Chinese Big5 charset (Windows-950) |
||
65 | #define GREEK_CHARSET 161 // Greek charset (Windows-1253) |
||
66 | #define TURKISH_CHARSET 162 // Turkish charset (Windows-1254) |
||
67 | #define VIETNAMESE_CHARSET 163 // Vietnamese charset (Windows-1258) |
||
68 | #define HEBREW_CHARSET 177 // Hebrew charset (Windows-1255) |
||
69 | #define ARABIC_CHARSET 178 // Arabic charset (Windows-1256) |
||
70 | #define BALTIC_CHARSET 186 // Baltic charset (Windows-1257) |
||
71 | #define RUSSIAN_CHARSET 204 // Cyrillic charset (Windows-1251) |
||
72 | #define THAI_CHARSET 222 // Thai charset (Windows-874) |
||
73 | #define EASTEUROPE_CHARSET 238 // Eastern european charset (Windows-1250) |
||
74 | #define OEM_CHARSET 255 |
||
75 | |||
76 | /* Symbol to unicode conversion table copied from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx |
||
77 | This code is placed under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE) */ |
||
78 | static const ushort greek_symbol_to_unicode[64] = { |
||
79 | // |
||
80 | // upper case letters: |
||
81 | // ---------------- |
||
82 | // Alpha Beta Chi Delta Epsilon Phi Gamma Eta |
||
83 | 0x0391, 0x0392, 0x03A7, 0x0394, 0x0395, 0x03A6, 0x0393, 0x0397, |
||
84 | // Iota Theta(S) Kappa Lambda Mu Nu Omicron Pi |
||
85 | 0x0399, 0x03D1, 0x039A, 0x039B, 0x039C, 0x039D, 0x039F, 0x03A0, |
||
86 | // Theta Rho Sigma Tau Upsilon Stigma Omega Xi |
||
87 | 0x0398, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03DB, 0x03A9, 0x039E, |
||
88 | // Psi Zeta Sigma Tau Upsilon ???? Omega Xi |
||
89 | 0x03A8, 0x0396, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, |
||
90 | // |
||
91 | // lower case letters: |
||
92 | // ---------------- |
||
93 | // Alpha Beta Chi Delta Epsilon Phi Gamma Eta |
||
94 | 0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x03B5, 0x03D5, 0x03B3, 0x03B7, |
||
95 | // Iota Phi (2) Kappa Lambda Mu Nu Omicron Pi |
||
96 | 0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0, |
||
97 | // Theta Rho Sigma Tau Upsilon OmegaPi Omega Xi |
||
98 | 0x03B8, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE, |
||
99 | // Psi Zeta Sigma Tau Upsilon ???? Omega Xi |
||
100 | 0x03C8, 0x03B6, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD |
||
101 | }; |
||
102 | |||
103 | /* Symbol to unicode conversion table copied from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx |
||
104 | This code is placed under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE) */ |
||
105 | static const ushort symbol_to_unicode[96] = { |
||
106 | // |
||
107 | // upper case letters: |
||
108 | // ---------------- |
||
109 | // UPSILON NUMBER LessEq Div INFINITY ??????? CLUB DIAMOND |
||
110 | 0x03D2, 0x0374, 0x2264, 0x2215, 0x221E, 0x0395, 0x2663, 0x2666, |
||
111 | // HEART SPADE <---> <--- --> RING |
||
112 | 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193, 0x2218, |
||
113 | // Theta Rho Great ???? Propor diff bullet ???? |
||
114 | 0x0398, 0x03A1, 0x2265, 0x03A4, 0x221D, 0x2202, 0x2219, 0x03A8, |
||
115 | // NonEq Ident ???? ellips div minus ????? aleph |
||
116 | 0x2260, 0x2261, 0xFFFD, 0x22EF, 0x2223, 0x2212, 0xFFFD, 0xFFFD, |
||
117 | // |
||
118 | // lower case letters: |
||
119 | // ---------------- |
||
120 | // Alpha Beta Chi Delta Epsilon Phi Gamma Eta |
||
121 | 0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x03B5, 0x03D5, 0x03B3, 0x03B7, |
||
122 | // Iota Phi (2) Kappa Lambda Mu Nu Omicron Pi |
||
123 | 0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0, |
||
124 | // Theta Rho Sigma Tau Upsilon OmegaPi Omega Xi |
||
125 | 0x03B8, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE, |
||
126 | // Psi Zeta arrow Tau Upsilon ???? Omega Xi |
||
127 | 0x03C8, 0x03B6, 0x21D4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, |
||
128 | // lower case letters: |
||
129 | // ---------------- |
||
130 | // Alpha Beta Chi Delta Sigma Phi Gamma Eta |
||
131 | 0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x2211, 0x03D5, 0x03B3, 0x03B7, |
||
132 | // Iota Phi (2) Kappa Lambda Mu Nu Omicron Pi |
||
133 | 0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0, |
||
134 | // Theta Integr Sigma Tau Upsilon OmegaPi Omega Xi |
||
135 | 0x03B8, 0x222b, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE, |
||
136 | // Psi Zeta Sigma Tau Upsilon ???? Omega Xi |
||
137 | 0x03C8, 0x03B6, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD |
||
138 | }; |
||
139 | |||
14710 | fschmid | 140 | WMFImport::WMFImport( ScribusDoc* doc, int flags ) |
13951 | fschmid | 141 | { |
142 | m_tmpSel = new Selection(this, false); |
||
14710 | fschmid | 143 | m_Doc = doc; |
13951 | fschmid | 144 | unsupported = false; |
145 | importFailed = false; |
||
146 | importCanceled = true; |
||
147 | importedColors.clear(); |
||
148 | m_docDesc = ""; |
||
149 | m_docTitle = ""; |
||
150 | interactive = (flags & LoadSavePlugin::lfInteractive); |
||
151 | |||
152 | m_Valid = false; |
||
153 | m_ObjHandleTab = NULL; |
||
154 | m_Dpi = 1440; |
||
155 | } |
||
156 | |||
157 | WMFImport::~WMFImport() |
||
158 | { |
||
159 | qDeleteAll(m_commands); |
||
160 | m_commands.clear(); |
||
161 | if ( m_tmpSel) delete m_tmpSel; |
||
162 | if ( m_ObjHandleTab ) |
||
163 | { |
||
164 | for (int i = 0; i < MAX_OBJHANDLE; ++i) |
||
165 | { |
||
166 | if (m_ObjHandleTab[i]) |
||
167 | delete m_ObjHandleTab[i]; |
||
168 | } |
||
169 | delete[] m_ObjHandleTab; |
||
170 | } |
||
171 | } |
||
172 | |||
173 | QString WMFImport::importColor(const QColor& color) |
||
174 | { |
||
175 | bool found = false; |
||
176 | int r, g, b; |
||
177 | QColor tmpColor; |
||
178 | QString retColorName; |
||
179 | ColorList::Iterator it; |
||
180 | for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it) |
||
181 | { |
||
182 | if (it.value().getColorModel() == colorModelRGB) |
||
183 | { |
||
184 | it.value().getRGB(&r, &g, &b); |
||
185 | tmpColor.setRgb(r, g, b); |
||
186 | if (color == tmpColor) |
||
187 | { |
||
188 | retColorName = it.key(); |
||
189 | found = true; |
||
190 | break; |
||
191 | } |
||
192 | } |
||
193 | } |
||
194 | if (!found) |
||
195 | { |
||
196 | ScColor tmp; |
||
197 | tmp.fromQColor(color); |
||
198 | tmp.setSpotColor(false); |
||
199 | tmp.setRegistrationColor(false); |
||
200 | m_Doc->PageColors.insert("FromWMF"+color.name(), tmp); |
||
201 | importedColors.append("FromWMF"+color.name()); |
||
202 | retColorName = "FromWMF"+color.name(); |
||
203 | } |
||
204 | return retColorName; |
||
205 | } |
||
206 | |||
207 | QColor WMFImport::colorFromParam( short* params ) |
||
208 | { |
||
209 | unsigned int colorRef; |
||
210 | int red, green, blue; |
||
211 | |||
212 | colorRef = toDWord( params ) & 0xffffff; |
||
213 | red = colorRef & 255; |
||
214 | green = ( colorRef>>8 ) & 255; |
||
215 | blue = ( colorRef>>16 ) & 255; |
||
216 | |||
217 | return QColor( red, green, blue ); |
||
218 | } |
||
219 | |||
220 | QTextCodec* WMFImport::codecFromCharset( int charset ) |
||
221 | { |
||
222 | QTextCodec* codec = NULL; |
||
223 | if (charset == DEFAULT_CHARSET || charset == OEM_CHARSET) |
||
224 | codec = QTextCodec::codecForLocale(); |
||
225 | else if (charset == ANSI_CHARSET) |
||
226 | codec = QTextCodec::codecForName("windows-1252"); |
||
227 | /*else if (charset == SYMBOL_CHARSET) |
||
228 | codec = QTextCodec::codecForLocale();// Not supported yet*/ |
||
229 | else if (charset == MAC_CHARSET) |
||
230 | codec = QTextCodec::codecForName("Apple Roman"); |
||
231 | else if (charset == SHIFTJIS_CHARSET) |
||
232 | codec = QTextCodec::codecForName("Shift-JIS"); |
||
233 | else if (charset == HANGEUL_CHARSET) |
||
234 | codec = QTextCodec::codecForName("CP949"); |
||
235 | else if (charset == GB2312_CHARSET) |
||
236 | codec = QTextCodec::codecForName("CP936"); |
||
237 | else if (charset == CHINESEBIG5_CHARSET) |
||
238 | codec = QTextCodec::codecForName("Big5"); |
||
239 | else if (charset == GREEK_CHARSET) |
||
240 | codec = QTextCodec::codecForName("windows-1253"); |
||
241 | else if (charset == TURKISH_CHARSET) |
||
242 | codec = QTextCodec::codecForName("windows-1254"); |
||
243 | else if (charset == VIETNAMESE_CHARSET) |
||
244 | codec = QTextCodec::codecForName("windows-1258"); |
||
245 | else if (charset == HEBREW_CHARSET) |
||
246 | codec = QTextCodec::codecForName("windows-1255"); |
||
247 | else if (charset == ARABIC_CHARSET) |
||
248 | codec = QTextCodec::codecForName("windows-1256"); |
||
249 | else if (charset == BALTIC_CHARSET) |
||
250 | codec = QTextCodec::codecForName("windows-1257"); |
||
251 | else if (charset == RUSSIAN_CHARSET) |
||
252 | codec = QTextCodec::codecForName("windows-1251"); |
||
253 | else if (charset == THAI_CHARSET) |
||
254 | codec = QTextCodec::codecForName("CP874"); |
||
255 | else if (charset == EASTEUROPE_CHARSET) |
||
256 | codec = QTextCodec::codecForName("windows-1250"); |
||
257 | return codec; |
||
258 | } |
||
259 | |||
260 | QString WMFImport::symbolToUnicode ( const QByteArray& chars ) |
||
261 | { |
||
262 | /*Code under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE) |
||
263 | taken from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx*/ |
||
264 | QString r; |
||
265 | const unsigned char * c = (const unsigned char *) chars.data(); |
||
266 | |||
267 | if( chars.size() == 0 ) return r; |
||
268 | |||
269 | for (int i = 0; i < chars.size(); ++i) |
||
270 | { |
||
271 | if ( 64 < c[i] && c[i] <= 64+32 ) |
||
272 | r.append( QChar(greek_symbol_to_unicode[c[i]-65]) ); |
||
273 | else if (64+32+1 <= c[i] && c[i] < 64+32+32+1) |
||
274 | r.append( QChar(greek_symbol_to_unicode[c[i]-65-32]+32) ); |
||
275 | else if (161 <= c[i] ) |
||
276 | r.append( QChar(symbol_to_unicode[c[i]-161]) ); |
||
277 | else |
||
278 | r.append( QChar(c[i]) ); |
||
279 | } |
||
280 | return r; |
||
281 | } |
||
282 | |||
283 | FPointArray WMFImport::pointsFromParam( short num, short* params ) |
||
284 | { |
||
285 | FPointArray points; |
||
286 | points.resize( num ); |
||
287 | |||
288 | for ( int i = 0; i < num; i++, params += 2 ) |
||
289 | points.setPoint( i, params[ 0 ], params[ 1 ] ); |
||
290 | |||
291 | return points; |
||
292 | } |
||
293 | |||
294 | FPointArray WMFImport::pointsToPolyline( const FPointArray& points, bool closePath ) |
||
295 | { |
||
296 | bool bFirst = true; |
||
297 | double x = 0.0, y = 0.0; |
||
298 | FPointArray polyline; |
||
299 | polyline.svgInit(); |
||
300 | for( uint i = 0; i < points.size(); ++i ) |
||
301 | { |
||
302 | FPoint point = points.point(i); |
||
303 | if( bFirst ) |
||
304 | { |
||
305 | x = point.x(); |
||
306 | y = point.y(); |
||
307 | polyline.svgMoveTo(x, y); |
||
308 | bFirst = false; |
||
309 | } |
||
310 | else |
||
311 | { |
||
312 | x = point.x(); |
||
313 | y = point.y(); |
||
314 | polyline.svgLineTo(x, y); |
||
315 | } |
||
316 | } |
||
317 | if (closePath && (points.size() > 4)) |
||
318 | polyline.svgClosePath(); |
||
319 | return polyline; |
||
320 | } |
||
321 | |||
322 | void WMFImport::pointsToAngle( double xStart, double yStart, double xEnd, double yEnd, double& angleStart, double& angleLength ) |
||
323 | { |
||
324 | double aStart = atan2( yStart, xStart ); |
||
325 | double aLength = atan2( yEnd, xEnd ) - aStart; |
||
326 | |||
327 | angleStart = (int)(aStart * 180.0 / 3.14166); |
||
328 | angleLength = (int)(aLength * 180.0 / 3.14166); |
||
329 | if ( angleLength < 0 ) angleLength = 360.0 + angleLength; |
||
330 | } |
||
331 | |||
14710 | fschmid | 332 | QImage WMFImport::readThumbnail(QString fname) |
333 | { |
||
334 | if (!loadWMF(fname)) |
||
335 | { |
||
336 | importFailed = true; |
||
337 | return QImage(); |
||
338 | } |
||
339 | QString CurDirP = QDir::currentPath(); |
||
340 | QFileInfo efp(fname); |
||
341 | QDir::setCurrent(efp.path()); |
||
342 | double scale = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05; |
||
343 | double width = m_BBox.width() * scale; |
||
344 | double height = m_BBox.height() * scale; |
||
345 | m_Doc = new ScribusDoc(); |
||
346 | m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom"); |
||
347 | m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false); |
||
348 | m_Doc->addPage(0); |
||
349 | m_Doc->setGUI(false, ScCore->primaryMainWindow(), 0); |
||
350 | m_Doc->setLoading(true); |
||
351 | m_Doc->DoDrawing = false; |
||
352 | m_Doc->scMW()->ScriptRunning = true; |
||
353 | m_Doc->PageColors.ensureBlackAndWhite(); |
||
354 | QList<PageItem*> Elements = parseWmfCommands(); |
||
355 | m_tmpSel->clear(); |
||
14720 | fschmid | 356 | QImage tmpImage = QImage(); |
14710 | fschmid | 357 | if (Elements.count() > 0) |
358 | { |
||
359 | bool isGroup = true; |
||
360 | int firstElem = -1; |
||
361 | if (Elements.at(0)->Groups.count() != 0) |
||
362 | firstElem = Elements.at(0)->Groups.top(); |
||
363 | for (int bx = 0; bx < Elements.count(); ++bx) |
||
364 | { |
||
365 | PageItem* bxi = Elements.at(bx); |
||
366 | if (bxi->Groups.count() != 0) |
||
367 | { |
||
368 | if (bxi->Groups.top() != firstElem) |
||
369 | isGroup = false; |
||
370 | } |
||
371 | else |
||
372 | isGroup = false; |
||
373 | } |
||
374 | if (!isGroup) |
||
375 | { |
||
376 | double minx = 99999.9; |
||
377 | double miny = 99999.9; |
||
378 | double maxx = -99999.9; |
||
379 | double maxy = -99999.9; |
||
380 | uint lowestItem = 999999; |
||
381 | uint highestItem = 0; |
||
382 | for (int a = 0; a < Elements.count(); ++a) |
||
383 | { |
||
384 | Elements.at(a)->Groups.push(m_Doc->GroupCounter); |
||
385 | PageItem* currItem = Elements.at(a); |
||
386 | lowestItem = qMin(lowestItem, currItem->ItemNr); |
||
387 | highestItem = qMax(highestItem, currItem->ItemNr); |
||
388 | double x1, x2, y1, y2; |
||
389 | currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2); |
||
390 | minx = qMin(minx, x1); |
||
391 | miny = qMin(miny, y1); |
||
392 | maxx = qMax(maxx, x2); |
||
393 | maxy = qMax(maxy, y2); |
||
394 | } |
||
395 | double gx = minx; |
||
396 | double gy = miny; |
||
397 | double gw = maxx - minx; |
||
398 | double gh = maxy - miny; |
||
399 | PageItem *high = m_Doc->Items->at(highestItem); |
||
400 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->itemToolPrefs.shapeFillColor, m_Doc->itemToolPrefs.shapeLineColor, true); |
||
401 | PageItem *neu = m_Doc->Items->takeAt(z); |
||
402 | m_Doc->Items->insert(lowestItem, neu); |
||
403 | neu->Groups.push(m_Doc->GroupCounter); |
||
404 | neu->setItemName( tr("Group%1").arg(neu->Groups.top())); |
||
405 | neu->AutoName = false; |
||
406 | neu->isGroupControl = true; |
||
407 | neu->groupsLastItem = high; |
||
408 | for (int a = 0; a < m_Doc->Items->count(); ++a) |
||
409 | { |
||
410 | m_Doc->Items->at(a)->ItemNr = a; |
||
411 | } |
||
412 | neu->setRedrawBounding(); |
||
413 | neu->setTextFlowMode(PageItem::TextFlowDisabled); |
||
414 | Elements.prepend(neu); |
||
415 | m_Doc->GroupCounter++; |
||
416 | } |
||
14720 | fschmid | 417 | m_Doc->DoDrawing = true; |
418 | m_Doc->m_Selection->delaySignalsOn(); |
||
419 | for (int dre=0; dre<Elements.count(); ++dre) |
||
420 | { |
||
421 | m_tmpSel->addItem(Elements.at(dre), true); |
||
422 | } |
||
423 | m_tmpSel->setGroupRect(); |
||
424 | double xs = m_tmpSel->width(); |
||
425 | double ys = m_tmpSel->height(); |
||
426 | double sc = 500.0 / qMax(xs, ys); |
||
427 | m_Doc->scaleGroup(sc, sc, true, m_tmpSel); |
||
428 | QImage tmpImage = Elements.at(0)->DrawObj_toImage(); |
||
429 | tmpImage.setText("XSize", QString("%1").arg(xs)); |
||
430 | tmpImage.setText("YSize", QString("%1").arg(ys)); |
||
431 | m_Doc->m_Selection->delaySignalsOff(); |
||
432 | m_Doc->setLoading(false); |
||
14710 | fschmid | 433 | } |
434 | m_Doc->scMW()->ScriptRunning = false; |
||
435 | delete m_Doc; |
||
436 | QDir::setCurrent(CurDirP); |
||
437 | return tmpImage; |
||
438 | } |
||
439 | |||
13951 | fschmid | 440 | bool WMFImport::import(QString fname, const TransactionSettings& trSettings, int flags) |
441 | { |
||
442 | if (!loadWMF(fname)) |
||
443 | { |
||
444 | importFailed = true; |
||
445 | return false; |
||
446 | } |
||
447 | QString CurDirP = QDir::currentPath(); |
||
448 | QFileInfo efp(fname); |
||
449 | QDir::setCurrent(efp.path()); |
||
450 | bool success = importWMF(trSettings, flags); |
||
451 | QDir::setCurrent(CurDirP); |
||
452 | return success; |
||
453 | } |
||
454 | |||
455 | bool WMFImport::loadWMF( const QString &fileName ) |
||
456 | { |
||
457 | QFile file( fileName ); |
||
458 | |||
459 | if ( !file.exists() ) |
||
460 | { |
||
461 | cerr << "File " << QFile::encodeName(fileName).data() << " does not exist" << endl; |
||
462 | return false; |
||
463 | } |
||
464 | |||
465 | if ( !file.open( QIODevice::ReadOnly ) ) |
||
466 | { |
||
467 | cerr << "Cannot open file " << QFile::encodeName(fileName).data() << endl; |
||
468 | return false; |
||
469 | } |
||
470 | |||
471 | QByteArray ba = file.readAll(); |
||
472 | file.close(); |
||
473 | |||
474 | QBuffer buffer( &ba ); |
||
475 | buffer.open( QIODevice::ReadOnly ); |
||
476 | return loadWMF( buffer ); |
||
477 | } |
||
478 | |||
479 | bool WMFImport::loadWMF( QBuffer &buffer ) |
||
480 | { |
||
481 | QDataStream st; |
||
482 | WmfEnhMetaHeader eheader; |
||
483 | WmfMetaHeader header; |
||
484 | WmfPlaceableHeader pheader; |
||
485 | WORD16 checksum; |
||
486 | int filePos, idx, i; |
||
487 | WmfCmd *cmd; |
||
488 | WORD32 rdSize; |
||
489 | WORD16 rdFunc; |
||
490 | |||
491 | header.mtSize = 0; |
||
492 | header.mtHeaderSize = 0; |
||
493 | header.mtNoParameters = 0; |
||
494 | |||
495 | qDeleteAll(m_commands); |
||
496 | m_commands.clear(); |
||
497 | |||
498 | st.setDevice( &buffer ); |
||
499 | st.setByteOrder( QDataStream::LittleEndian ); // Great, I love Qt ! |
||
500 | |||
501 | //----- Read placeable metafile header |
||
502 | st >> pheader.key; |
||
503 | m_IsPlaceable = (pheader.key == (WORD32) APMHEADER_KEY); |
||
504 | if ( m_IsPlaceable ) |
||
505 | { |
||
506 | st >> pheader.hmf; |
||
507 | st >> pheader.bbox.left; |
||
508 | st >> pheader.bbox.top; |
||
509 | st >> pheader.bbox.right; |
||
510 | st >> pheader.bbox.bottom; |
||
511 | st >> pheader.inch; |
||
512 | st >> pheader.reserved; |
||
513 | st >> pheader.checksum; |
||
514 | checksum = calcCheckSum( &pheader ); |
||
515 | if ( pheader.checksum!=checksum ) m_IsPlaceable = false; |
||
516 | |||
517 | m_Dpi = pheader.inch; |
||
518 | m_BBox.setLeft( pheader.bbox.left ); |
||
519 | m_BBox.setTop( pheader.bbox.top ); |
||
520 | m_BBox.setRight( pheader.bbox.right ); |
||
521 | m_BBox.setBottom( pheader.bbox.bottom ); |
||
522 | m_HeaderBoundingBox = m_BBox; |
||
523 | if ( WMFIMPORT_DEBUG ) |
||
524 | { |
||
525 | cerr << endl << "-------------------------------------------------" << endl; |
||
526 | cerr << "WMF Placeable Header ( " << static_cast<int>(sizeof( pheader ) ) << "):" << endl; |
||
527 | cerr << " bbox=( " << m_BBox.left() << "; " << m_BBox.top() << "; " << m_BBox.width() << "; " << m_BBox.height() << ")" << endl; |
||
528 | cerr << " inch=" << pheader.inch << endl; |
||
529 | cerr << " checksum=" << pheader.checksum << "( " << (pheader.checksum==checksum?"ok":"wrong") << " )" << endl; |
||
530 | } |
||
531 | } |
||
532 | else buffer.seek( 0 ); |
||
533 | |||
534 | //----- Read as enhanced metafile header |
||
535 | filePos = buffer.pos(); |
||
536 | st >> eheader.iType; |
||
537 | st >> eheader.nSize; |
||
538 | st >> eheader.rclBounds.left; |
||
539 | st >> eheader.rclBounds.top; |
||
540 | st >> eheader.rclBounds.right; |
||
541 | st >> eheader.rclBounds.bottom; |
||
542 | st >> eheader.rclFrame.left; |
||
543 | st >> eheader.rclFrame.top; |
||
544 | st >> eheader.rclFrame.right; |
||
545 | st >> eheader.rclFrame.bottom; |
||
546 | st >> eheader.dSignature; |
||
547 | m_IsEnhanced = ( eheader.dSignature==ENHMETA_SIGNATURE ); |
||
548 | if ( m_IsEnhanced ) // is it really enhanced ? |
||
549 | { |
||
550 | st >> eheader.nVersion; |
||
551 | st >> eheader.nBytes; |
||
552 | st >> eheader.nRecords; |
||
553 | st >> eheader.nHandles; |
||
554 | st >> eheader.sReserved; |
||
555 | st >> eheader.nDescription; |
||
556 | st >> eheader.offDescription; |
||
557 | st >> eheader.nPalEntries; |
||
558 | st >> eheader.szlDevice.width; |
||
559 | st >> eheader.szlDevice.height; |
||
560 | st >> eheader.szlMillimeters.width; |
||
561 | st >> eheader.szlMillimeters.height; |
||
562 | |||
563 | if ( WMFIMPORT_DEBUG ) |
||
564 | { |
||
565 | cerr << endl << "-------------------------------------------------" << endl; |
||
566 | cerr << "WMF Extended Header:" << endl; |
||
567 | cerr << " iType=" << eheader.iType << endl; |
||
568 | cerr << " nSize=" << eheader.nSize << endl; |
||
569 | cerr << " rclBounds=( " << eheader.rclBounds.left << "; " << eheader.rclBounds.top << "; " |
||
570 | << eheader.rclBounds.right << "; " << eheader.rclBounds.bottom << ")" << endl; |
||
571 | cerr << " rclFrame=( " << eheader.rclFrame.left << "; " << eheader.rclFrame.top << "; " |
||
572 | << eheader.rclFrame.right << "; " << eheader.rclFrame.bottom << ")" << endl; |
||
573 | cerr << " nBytes=" << eheader.nBytes << endl; |
||
574 | cerr << "\nNOT YET IMPLEMENTED, SORRY." << endl; |
||
575 | } |
||
576 | } |
||
577 | else // no, not enhanced |
||
578 | { |
||
579 | //----- Read as standard metafile header |
||
580 | buffer.seek( filePos ); |
||
581 | st >> header.mtType; |
||
582 | st >> header.mtHeaderSize; |
||
583 | st >> header.mtVersion; |
||
584 | st >> header.mtSize; |
||
585 | st >> header.mtNoObjects; |
||
586 | st >> header.mtMaxRecord; |
||
587 | st >> header.mtNoParameters; |
||
588 | if ( WMFIMPORT_DEBUG ) { |
||
589 | cerr << "WMF Header: " << "mtSize=" << header.mtSize << endl; |
||
590 | } |
||
591 | } |
||
592 | |||
593 | //----- Test header validity |
||
594 | m_Valid = ((header.mtHeaderSize == 9) && (header.mtNoParameters == 0)) || m_IsEnhanced || m_IsPlaceable; |
||
595 | if ( m_Valid ) |
||
596 | { |
||
597 | //----- Read Metafile Records |
||
598 | rdFunc = -1; |
||
599 | while ( !st.atEnd() && (rdFunc != 0) ) |
||
600 | { |
||
601 | st >> rdSize; |
||
602 | st >> rdFunc; |
||
603 | idx = findFunc( rdFunc ); |
||
604 | rdSize -= 3; |
||
605 | |||
606 | cmd = new WmfCmd; |
||
607 | m_commands.append(cmd); |
||
608 | |||
609 | cmd->funcIndex = idx; |
||
610 | cmd->numParam = rdSize; |
||
611 | cmd->params = new WORD16[ rdSize ]; |
||
612 | |||
613 | for ( i=0; i<rdSize && !st.atEnd(); i++ ) |
||
614 | st >> cmd->params[ i ]; |
||
615 | |||
616 | |||
617 | if ( rdFunc == 0x020B && !m_IsPlaceable) { // SETWINDOWORG: dimensions |
||
618 | m_BBox.setLeft( qMin((int) cmd->params[ 1 ], m_BBox.left()) ); |
||
619 | m_BBox.setTop ( qMin((int) cmd->params[ 0 ], m_BBox.top()) ); |
||
620 | } |
||
621 | if ( rdFunc == 0x020C && !m_IsPlaceable ) { // SETWINDOWEXT: dimensions |
||
622 | m_BBox.setWidth ( qMax((int) cmd->params[ 1 ], m_BBox.width()) ); |
||
623 | m_BBox.setHeight( qMax((int) cmd->params[ 0 ], m_BBox.height())); |
||
624 | } |
||
625 | |||
626 | if ( i<rdSize ) |
||
627 | { |
||
628 | cerr << "WMF : file truncated !" << endl; |
||
629 | return false; |
||
630 | } |
||
631 | } |
||
632 | //----- Test records validities |
||
633 | m_Valid = (rdFunc == 0) && (m_BBox.width() != 0) && (m_BBox.height() != 0); |
||
634 | if ( !m_Valid ) { |
||
635 | cerr << "WMF : incorrect file format !" << endl; |
||
636 | } |
||
637 | } |
||
638 | else { |
||
639 | cerr << "WMF Header : incorrect header !" << endl; |
||
640 | } |
||
641 | |||
642 | buffer.close(); |
||
643 | return m_Valid; |
||
644 | } |
||
645 | |||
646 | bool WMFImport::importWMF(const TransactionSettings& trSettings, int flags) |
||
647 | { |
||
648 | bool ret = false; |
||
649 | //double scale = (m_Dpi > 288) ? 288.0 / m_Dpi : 1.0; |
||
650 | double scale = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05; |
||
651 | double width = m_BBox.width() * scale; |
||
652 | double height = m_BBox.height() * scale; |
||
653 | if (!interactive || (flags & LoadSavePlugin::lfInsertPage)) |
||
654 | { |
||
655 | m_Doc->setPage(fabs(width), fabs(height), 0, 0, 0, 0, 0, 0, false, false); |
||
656 | m_Doc->addPage(0); |
||
657 | m_Doc->view()->addPage(0); |
||
658 | } |
||
659 | else |
||
660 | { |
||
661 | if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc)) |
||
662 | { |
||
663 | m_Doc=ScCore->primaryMainWindow()->doFileNew(fabs(width), fabs(height), 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true); |
||
664 | ScCore->primaryMainWindow()->HaveNewDoc(); |
||
665 | ret = true; |
||
666 | } |
||
667 | } |
||
668 | if ((ret) || (!interactive)) |
||
669 | { |
||
670 | if (width > height) |
||
671 | m_Doc->PageOri = 1; |
||
672 | else |
||
673 | m_Doc->PageOri = 0; |
||
674 | m_Doc->m_pageSize = "Custom"; |
||
675 | } |
||
676 | FPoint minSize = m_Doc->minCanvasCoordinate; |
||
677 | FPoint maxSize = m_Doc->maxCanvasCoordinate; |
||
678 | FPoint cOrigin = m_Doc->view()->canvasOrigin(); |
||
679 | m_Doc->view()->Deselect(); |
||
680 | m_Doc->setLoading(true); |
||
681 | m_Doc->DoDrawing = false; |
||
682 | m_Doc->view()->updatesOn(false); |
||
683 | m_Doc->scMW()->ScriptRunning = true; |
||
684 | qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); |
||
13996 | cbradney | 685 | //gc->Family = m_Doc->toolSettings.textFont; |
13951 | fschmid | 686 | m_Doc->PageColors.ensureBlackAndWhite(); |
687 | //m_gc.push( gc ); |
||
688 | QList<PageItem*> Elements = parseWmfCommands(); |
||
689 | if (flags & LoadSavePlugin::lfCreateDoc) |
||
690 | { |
||
691 | m_Doc->documentInfo.setTitle(m_docTitle); |
||
692 | m_Doc->documentInfo.setComments(m_docDesc); |
||
693 | } |
||
694 | m_tmpSel->clear(); |
||
695 | if (Elements.count() == 0) |
||
696 | { |
||
697 | importFailed = true; |
||
698 | if (importedColors.count() != 0) |
||
699 | { |
||
700 | for (int cd = 0; cd < importedColors.count(); cd++) |
||
701 | { |
||
702 | m_Doc->PageColors.remove(importedColors[cd]); |
||
703 | } |
||
704 | } |
||
705 | } |
||
706 | if (Elements.count() > 1) |
||
707 | { |
||
708 | bool isGroup = true; |
||
709 | int firstElem = -1; |
||
710 | if (Elements.at(0)->Groups.count() != 0) |
||
711 | firstElem = Elements.at(0)->Groups.top(); |
||
712 | for (int bx = 0; bx < Elements.count(); ++bx) |
||
713 | { |
||
714 | PageItem* bxi = Elements.at(bx); |
||
715 | if (bxi->Groups.count() != 0) |
||
716 | { |
||
717 | if (bxi->Groups.top() != firstElem) |
||
718 | isGroup = false; |
||
719 | } |
||
720 | else |
||
721 | isGroup = false; |
||
722 | } |
||
723 | if (!isGroup) |
||
724 | { |
||
725 | double minx = 99999.9; |
||
726 | double miny = 99999.9; |
||
727 | double maxx = -99999.9; |
||
728 | double maxy = -99999.9; |
||
729 | uint lowestItem = 999999; |
||
730 | uint highestItem = 0; |
||
731 | for (int a = 0; a < Elements.count(); ++a) |
||
732 | { |
||
733 | Elements.at(a)->Groups.push(m_Doc->GroupCounter); |
||
734 | PageItem* currItem = Elements.at(a); |
||
735 | lowestItem = qMin(lowestItem, currItem->ItemNr); |
||
736 | highestItem = qMax(highestItem, currItem->ItemNr); |
||
737 | double x1, x2, y1, y2; |
||
738 | currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2); |
||
739 | minx = qMin(minx, x1); |
||
740 | miny = qMin(miny, y1); |
||
741 | maxx = qMax(maxx, x2); |
||
742 | maxy = qMax(maxy, y2); |
||
743 | } |
||
744 | double gx = minx; |
||
745 | double gy = miny; |
||
746 | double gw = maxx - minx; |
||
747 | double gh = maxy - miny; |
||
748 | PageItem *high = m_Doc->Items->at(highestItem); |
||
14014 | cbradney | 749 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->itemToolPrefs.shapeFillColor, m_Doc->itemToolPrefs.shapeLineColor, true); |
13951 | fschmid | 750 | PageItem *neu = m_Doc->Items->takeAt(z); |
751 | m_Doc->Items->insert(lowestItem, neu); |
||
752 | neu->Groups.push(m_Doc->GroupCounter); |
||
753 | neu->setItemName( tr("Group%1").arg(neu->Groups.top())); |
||
754 | neu->AutoName = false; |
||
755 | neu->isGroupControl = true; |
||
756 | neu->groupsLastItem = high; |
||
757 | for (int a = 0; a < m_Doc->Items->count(); ++a) |
||
758 | { |
||
759 | m_Doc->Items->at(a)->ItemNr = a; |
||
760 | } |
||
761 | neu->setRedrawBounding(); |
||
762 | neu->setTextFlowMode(PageItem::TextFlowDisabled); |
||
763 | Elements.prepend(neu); |
||
764 | m_Doc->GroupCounter++; |
||
765 | } |
||
766 | } |
||
767 | m_Doc->DoDrawing = true; |
||
768 | m_Doc->scMW()->ScriptRunning = false; |
||
769 | if (interactive) |
||
770 | m_Doc->setLoading(false); |
||
771 | qApp->setOverrideCursor(QCursor(Qt::ArrowCursor)); |
||
772 | if ((Elements.count() > 0) && (!ret) && (interactive)) |
||
773 | { |
||
774 | if (flags & LoadSavePlugin::lfScripted) |
||
775 | { |
||
776 | bool loadF = m_Doc->isLoading(); |
||
777 | m_Doc->setLoading(false); |
||
778 | m_Doc->changed(); |
||
779 | m_Doc->setLoading(loadF); |
||
780 | m_Doc->m_Selection->delaySignalsOn(); |
||
781 | for (int dre=0; dre<Elements.count(); ++dre) |
||
782 | { |
||
783 | m_Doc->m_Selection->addItem(Elements.at(dre), true); |
||
784 | } |
||
785 | m_Doc->m_Selection->delaySignalsOff(); |
||
786 | m_Doc->m_Selection->setGroupRect(); |
||
787 | m_Doc->view()->updatesOn(true); |
||
788 | importCanceled = false; |
||
789 | } |
||
790 | else |
||
791 | { |
||
792 | m_Doc->DragP = true; |
||
793 | m_Doc->DraggedElem = 0; |
||
794 | m_Doc->DragElements.clear(); |
||
795 | m_Doc->m_Selection->delaySignalsOn(); |
||
796 | for (int dre=0; dre<Elements.count(); ++dre) |
||
797 | { |
||
798 | m_Doc->DragElements.append(Elements.at(dre)->ItemNr); |
||
799 | m_tmpSel->addItem(Elements.at(dre), true); |
||
800 | } |
||
801 | ScriXmlDoc *ss = new ScriXmlDoc(); |
||
802 | m_tmpSel->setGroupRect(); |
||
803 | ScElemMimeData* md = new ScElemMimeData(); |
||
804 | md->setScribusElem(ss->WriteElem(m_Doc, m_Doc->view(), m_tmpSel)); |
||
805 | delete ss; |
||
806 | /*#ifndef QT_MAC*/ |
||
807 | // see #2526 |
||
808 | m_Doc->itemSelection_DeleteItem(m_tmpSel); |
||
809 | /*#endif*/ |
||
810 | m_Doc->view()->updatesOn(true); |
||
811 | m_Doc->m_Selection->delaySignalsOff(); |
||
812 | // We must copy the TransationSettings object as it is owned |
||
813 | // by handleObjectImport method afterwards |
||
814 | TransactionSettings* transacSettings = new TransactionSettings(trSettings); |
||
815 | m_Doc->view()->handleObjectImport(md, transacSettings); |
||
816 | m_Doc->DragP = false; |
||
817 | m_Doc->DraggedElem = 0; |
||
818 | m_Doc->DragElements.clear(); |
||
819 | } |
||
820 | } |
||
821 | else |
||
822 | { |
||
823 | bool loadF = m_Doc->isLoading(); |
||
824 | m_Doc->setLoading(false); |
||
825 | m_Doc->changed(); |
||
826 | m_Doc->reformPages(); |
||
827 | m_Doc->view()->updatesOn(true); |
||
828 | m_Doc->setLoading(loadF); |
||
829 | } |
||
830 | return true; |
||
831 | } |
||
832 | |||
833 | QList<PageItem*> WMFImport::parseWmfCommands(void) |
||
834 | { |
||
835 | int idx, i; |
||
836 | const WmfCmd* cmd; |
||
837 | QList<PageItem*> elements; |
||
838 | |||
839 | m_context.reset(); |
||
840 | |||
841 | if ( !m_Valid ) return elements; |
||
842 | |||
843 | if ( m_ObjHandleTab ) delete[] m_ObjHandleTab; |
||
844 | m_ObjHandleTab = new WmfObjHandle* [ MAX_OBJHANDLE ]; |
||
845 | for ( i = MAX_OBJHANDLE-1; i >= 0; i-- ) |
||
846 | m_ObjHandleTab[ i ] = NULL; |
||
847 | |||
848 | if ( WMFIMPORT_DEBUG ) { |
||
849 | cerr << "Bounding box : " << m_BBox.left() << " " << m_BBox.top() << " " << m_BBox.right() << " " << m_BBox.bottom() << endl; |
||
850 | } |
||
851 | |||
852 | double scale = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05; |
||
853 | m_context.setViewportOrg( 0, 0 ); |
||
854 | m_context.setViewportExt( m_BBox.width() * scale, m_BBox.height() * scale ); |
||
855 | m_context.setWindowOrg( m_BBox.left(), m_BBox.bottom() ); |
||
856 | m_context.setWindowExt( m_BBox.width(), m_BBox.height() ); |
||
857 | |||
858 | for (int index = 0; index < m_commands.count(); ++index) |
||
859 | { |
||
860 | cmd = m_commands.at(index); |
||
861 | idx = cmd->funcIndex; |
||
862 | ( this->*metaFuncTab[ idx ].method )( elements, cmd->numParam, cmd->params ); |
||
863 | |||
864 | if ( WMFIMPORT_DEBUG ) { |
||
865 | QString str = "", param; |
||
866 | if ( metaFuncTab[ idx ].name == NULL ) { |
||
867 | str += "UNKNOWN "; |
||
868 | } |
||
869 | if ( metaFuncTab[ idx ].method == &WMFImport::noop ) { |
||
870 | str += "UNIMPLEMENTED "; |
||
871 | } |
||
872 | str += metaFuncTab[ idx ].name; |
||
873 | str += " : "; |
||
874 | |||
875 | for ( i=0 ; i < cmd->numParam ; i++ ) { |
||
876 | param.setNum( cmd->params[ i ] ); |
||
877 | str += param; |
||
878 | str += " "; |
||
879 | } |
||
880 | cerr << str.toAscii().data() << endl; |
||
881 | } |
||
882 | } |
||
883 | return elements; |
||
884 | } |
||
885 | |||
886 | void WMFImport::finishCmdParsing( PageItem* item ) |
||
887 | { |
||
888 | QTransform gcm = m_context.worldMatrix(); |
||
889 | double coeff1 = sqrt(gcm.m11() * gcm.m11() + gcm.m12() * gcm.m12()); |
||
890 | double coeff2 = sqrt(gcm.m21() * gcm.m21() + gcm.m22() * gcm.m22()); |
||
891 | if( item->asImageFrame() ) |
||
892 | { |
||
893 | item->moveBy(gcm.dx(), gcm.dy()); |
||
894 | item->setWidthHeight(item->width() * gcm.m11(), item->height() * gcm.m22()); |
||
895 | item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25)); |
||
896 | if (item->PictureIsAvailable) |
||
897 | item->setImageXYScale(item->width() / item->pixm.width(), item->height() / item->pixm.height()); |
||
898 | } |
||
899 | else if( item->asTextFrame() ) |
||
900 | { |
||
901 | item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25)); |
||
902 | } |
||
903 | else |
||
904 | { |
||
905 | item->ClipEdited = true; |
||
906 | item->FrameType = 3; |
||
907 | item->PoLine.map(gcm); |
||
908 | item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25)); |
||
909 | FPoint wh = getMaxClipF(&item->PoLine); |
||
910 | item->setWidthHeight(wh.x(), wh.y()); |
||
911 | m_Doc->AdjustItemSize(item); |
||
912 | } |
||
913 | item->setRedrawBounding(); |
||
914 | item->OwnPage = m_Doc->OnPage(item); |
||
915 | item->PLineEnd = m_context.pen().capStyle(); |
||
916 | item->PLineJoin = m_context.pen().joinStyle(); |
||
917 | item->setTextFlowMode(PageItem::TextFlowDisabled); |
||
918 | //item->DashOffset = gc->dashOffset; |
||
919 | //item->DashValues = gc->dashArray; |
||
920 | } |
||
921 | |||
922 | void WMFImport::setWindowOrg( QList<PageItem*>& /*items*/, long, short* params ) |
||
923 | { |
||
924 | m_context.setWindowOrg( params[ 1 ], params[ 0 ] ); |
||
925 | } |
||
926 | |||
927 | void WMFImport::setWindowExt( QList<PageItem*>& /*items*/, long, short* params ) |
||
928 | { |
||
929 | m_context.setWindowExt( params[ 1 ], params[ 0 ] ); |
||
930 | } |
||
931 | |||
932 | void WMFImport::lineTo( QList<PageItem*>& items, long, short* params ) |
||
933 | { |
||
934 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
935 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
936 | QPoint currentPos = m_context.position(); |
||
937 | bool doStroke = (m_context.pen().style() != Qt::NoPen); |
||
938 | if (doStroke) |
||
939 | { |
||
940 | double x1 = currentPos.x(); |
||
941 | double y1 = currentPos.y(); |
||
942 | double x2 = params[1]; |
||
943 | double y2 = params[0]; |
||
944 | double lineWidth = m_context.pen().width(); |
||
945 | QString lineColor = importColor(m_context.pen().color()); |
||
946 | int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, CommonStrings::None, lineColor, true); |
||
947 | PageItem* ite = m_Doc->Items->at(z); |
||
948 | ite->PoLine.resize(4); |
||
949 | ite->PoLine.setPoint(0, FPoint(x1, y1)); |
||
950 | ite->PoLine.setPoint(1, FPoint(x1, y1)); |
||
951 | ite->PoLine.setPoint(2, FPoint(x2, y2)); |
||
952 | ite->PoLine.setPoint(3, FPoint(x2, y2)); |
||
953 | finishCmdParsing(ite); |
||
954 | items.append(ite); |
||
955 | } |
||
956 | m_context.setPosition( QPoint(params[1], params[0]) ); |
||
957 | } |
||
958 | |||
959 | void WMFImport::moveTo( QList<PageItem*>& /*items*/, long, short* params ) |
||
960 | { |
||
961 | m_context.setPosition( QPoint(params[1], params[0]) ); |
||
962 | } |
||
963 | |||
964 | void WMFImport::ellipse( QList<PageItem*>& items, long, short* params ) |
||
965 | { |
||
966 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
967 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
968 | double rx = (params[ 1 ] - params[ 3 ]) / 2.0; |
||
969 | double ry = (params[ 0 ] - params[ 2 ]) / 2.0; |
||
970 | double px = (params[ 1 ] + params[ 3 ]) / 2.0 - rx; |
||
971 | double py = (params[ 0 ] + params[ 2 ]) / 2.0 - ry; |
||
972 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
973 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
974 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
975 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
976 | double lineWidth = m_context.pen().width(); |
||
977 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, lineWidth, fillColor, strokeColor, true); |
||
978 | PageItem* ite = m_Doc->Items->at(z); |
||
979 | QTransform mm(1.0, 0.0, 0.0, 1.0, px, py); |
||
980 | ite->PoLine.map(mm); |
||
981 | finishCmdParsing(ite); |
||
982 | items.append(ite); |
||
983 | } |
||
984 | |||
985 | void WMFImport::polygon( QList<PageItem*>& items, long, short* params ) |
||
986 | { |
||
987 | //cerr << "WMFImport::polygon unimplemented" << endl; |
||
988 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
989 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
990 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
991 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
992 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
993 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
994 | double lineWidth = m_context.pen().width(); |
||
995 | if (doStroke && lineWidth <= 0.0 ) |
||
996 | lineWidth = 1.0; |
||
997 | FPointArray paramPoints = pointsFromParam( params[0], ¶ms[1] ); |
||
998 | FPointArray points = pointsToPolyline( paramPoints, true ); |
||
999 | if( paramPoints.size() > 0 ) |
||
1000 | { |
||
1001 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true); |
||
1002 | PageItem* ite = m_Doc->Items->at(z); |
||
1003 | ite->PoLine = points; |
||
1004 | ite->fillRule = !m_context.windingFill(); |
||
1005 | finishCmdParsing(ite); |
||
1006 | items.append(ite); |
||
1007 | } |
||
1008 | } |
||
1009 | |||
1010 | void WMFImport::polyPolygon( QList<PageItem*>& items, long num, short* params ) |
||
1011 | { |
||
1012 | int numPolys = params[0]; |
||
1013 | int pointIndex = params[0] + 1; |
||
1014 | for (int i = 0; i < numPolys; ++i) |
||
1015 | { |
||
1016 | short numPoints = params[i + 1]; |
||
1017 | short* paramArray = new short[1 + 2 * numPoints]; |
||
1018 | paramArray[0] = numPoints; |
||
1019 | memcpy(¶mArray[1], ¶ms[pointIndex], 2 * numPoints * sizeof(short)); |
||
1020 | polygon(items, num, paramArray); |
||
1021 | delete[] paramArray; |
||
1022 | pointIndex += (2 * numPoints); |
||
1023 | } |
||
1024 | } |
||
1025 | |||
1026 | void WMFImport::polyline( QList<PageItem*>& items, long, short* params ) |
||
1027 | { |
||
1028 | //cerr << "WMFImport::polyline unimplemented" << endl; |
||
1029 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1030 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1031 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1032 | QString fillColor = CommonStrings::None; |
||
1033 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1034 | double lineWidth = m_context.pen().width(); |
||
1035 | if (doStroke && lineWidth <= 0.0 ) |
||
1036 | lineWidth = 1.0; |
||
1037 | FPointArray paramPoints = pointsFromParam( params[0], ¶ms[1] ); |
||
1038 | FPointArray points = pointsToPolyline( paramPoints, false ); |
||
1039 | if( paramPoints.size() > 0 ) |
||
1040 | { |
||
1041 | int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true); |
||
1042 | PageItem* ite = m_Doc->Items->at(z); |
||
1043 | ite->PoLine = points; |
||
1044 | finishCmdParsing(ite); |
||
1045 | items.append(ite); |
||
1046 | } |
||
1047 | } |
||
1048 | |||
1049 | void WMFImport::rectangle( QList<PageItem*>& items, long, short* params ) |
||
1050 | { |
||
1051 | //cerr << "WMFImport::rectangle unimplemented" << endl; |
||
1052 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1053 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1054 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
1055 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1056 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
1057 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1058 | double lineWidth = m_context.pen().width(); |
||
1059 | if (doStroke && lineWidth <= 0.0 ) |
||
1060 | lineWidth = 1.0; |
||
1061 | double x = ((params[3] - params[1]) > 0) ? params[1] : params[3]; |
||
1062 | double y = ((params[2] - params[0]) > 0) ? params[0] : params[2]; |
||
1063 | double width = fabs((double) params[3] - params[1]); |
||
1064 | double height = fabs((double) params[2] - params[0]); |
||
1065 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, lineWidth, fillColor, strokeColor, true); |
||
1066 | PageItem* ite = m_Doc->Items->at(z); |
||
1067 | QTransform mm(1.0, 0.0, 0.0, 1.0, x, y); |
||
1068 | ite->PoLine.map(mm); |
||
1069 | finishCmdParsing(ite); |
||
1070 | items.append(ite); |
||
1071 | } |
||
1072 | |||
1073 | void WMFImport::roundRect( QList<PageItem*>& items, long, short* params ) |
||
1074 | { |
||
1075 | //cerr << "WMFImport::roundRect unimplemented" << endl; |
||
1076 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1077 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1078 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
1079 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1080 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
1081 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1082 | double lineWidth = m_context.pen().width(); |
||
1083 | if (doStroke && lineWidth <= 0.0 ) |
||
1084 | lineWidth = 1.0; |
||
1085 | double x = ((params[5] - params[3]) > 0) ? params[3] : params[5]; |
||
1086 | double y = ((params[4] - params[2]) > 0) ? params[2] : params[4]; |
||
1087 | double width = fabs((double) params[5] - params[3]); |
||
1088 | double height = fabs((double) params[4] - params[2]); |
||
1089 | double rx = params[1] / 2.0; |
||
1090 | double ry = params[0] / 2.0; |
||
1091 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, lineWidth, fillColor, strokeColor, true); |
||
1092 | PageItem* ite = m_Doc->Items->at(z); |
||
1093 | if ((rx != 0.0) || (ry != 0.0)) |
||
1094 | { |
||
1095 | ite->setCornerRadius(qMax(rx, ry)); |
||
1096 | ite->SetFrameRound(); |
||
1097 | m_Doc->setRedrawBounding(ite); |
||
1098 | } |
||
1099 | QTransform mm(1.0, 0.0, 0.0, 1.0, x, y); |
||
1100 | ite->PoLine.map(mm); |
||
1101 | finishCmdParsing(ite); |
||
1102 | items.append(ite); |
||
1103 | } |
||
1104 | |||
1105 | void WMFImport::arc( QList<PageItem*>& items, long, short* params ) |
||
1106 | { |
||
1107 | FPointArray pointArray; |
||
1108 | QPainterPath painterPath; |
||
1109 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1110 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1111 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1112 | QString fillColor = CommonStrings::None; |
||
1113 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1114 | double lineWidth = m_context.pen().width(); |
||
1115 | if (doStroke && lineWidth <= 0.0 ) |
||
1116 | lineWidth = 1.0; |
||
1117 | double angleStart, angleLength; |
||
1118 | double x = ((params[7] - params[5]) > 0) ? params[5] : params[7]; |
||
1119 | double y = ((params[6] - params[4]) > 0) ? params[4] : params[6]; |
||
1120 | double xCenter = (params[5] + params[7]) / 2.0; |
||
1121 | double yCenter = (params[4] + params[6]) / 2.0; |
||
1122 | double xWidth = fabs((double) params[5] - params[7]); |
||
1123 | double yHeight = fabs((double) params[4] - params[6]); |
||
1124 | pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength); |
||
1125 | painterPath.arcMoveTo(x, y, xWidth, yHeight, angleStart); |
||
1126 | painterPath.arcTo(x, y, xWidth, yHeight, angleStart, angleLength); |
||
1127 | pointArray.fromQPainterPath(painterPath); |
||
1128 | if( pointArray.size() > 0 ) |
||
1129 | { |
||
1130 | int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true); |
||
1131 | PageItem* ite = m_Doc->Items->at(z); |
||
1132 | ite->PoLine = pointArray; |
||
1133 | finishCmdParsing(ite); |
||
1134 | items.append(ite); |
||
1135 | } |
||
1136 | } |
||
1137 | |||
1138 | void WMFImport::chord( QList<PageItem*>& items, long, short* params ) |
||
1139 | { |
||
1140 | QPointF firstPoint; |
||
1141 | FPointArray pointArray; |
||
1142 | QPainterPath painterPath; |
||
1143 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1144 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1145 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
1146 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1147 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
1148 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1149 | double lineWidth = m_context.pen().width(); |
||
1150 | if (doStroke && lineWidth <= 0.0 ) |
||
1151 | lineWidth = 1.0; |
||
1152 | double angleStart, angleLength; |
||
1153 | double x = ((params[7] - params[5]) > 0) ? params[5] : params[7]; |
||
1154 | double y = ((params[6] - params[4]) > 0) ? params[4] : params[6]; |
||
1155 | double xCenter = (params[5] + params[7]) / 2.0; |
||
1156 | double yCenter = (params[4] + params[6]) / 2.0; |
||
1157 | double xWidth = fabs((double) params[5] - params[7]); |
||
1158 | double yHeight = fabs((double) params[4] - params[6]); |
||
1159 | pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength); |
||
1160 | painterPath.arcMoveTo(x, y, xWidth, yHeight, angleStart); |
||
1161 | firstPoint = painterPath.currentPosition(); |
||
1162 | painterPath.arcTo (x, y, xWidth, yHeight, angleStart, angleLength); |
||
1163 | painterPath.lineTo(firstPoint); |
||
1164 | pointArray.fromQPainterPath(painterPath); |
||
1165 | if( pointArray.size() > 0 ) |
||
1166 | { |
||
1167 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true); |
||
1168 | PageItem* ite = m_Doc->Items->at(z); |
||
1169 | ite->PoLine = pointArray; |
||
1170 | finishCmdParsing(ite); |
||
1171 | items.append(ite); |
||
1172 | } |
||
1173 | } |
||
1174 | |||
1175 | void WMFImport::pie( QList<PageItem*>& items, long, short* params ) |
||
1176 | { |
||
1177 | QPointF firstPoint; |
||
1178 | FPointArray pointArray; |
||
1179 | QPainterPath painterPath; |
||
1180 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1181 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1182 | bool doFill = m_context.brush().style() != Qt::NoBrush; |
||
1183 | bool doStroke = m_context.pen().style() != Qt::NoPen; |
||
1184 | QString fillColor = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None; |
||
1185 | QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None; |
||
1186 | double lineWidth = m_context.pen().width(); |
||
1187 | if (doStroke && lineWidth <= 0.0 ) |
||
1188 | lineWidth = 1.0; |
||
1189 | double angleStart, angleLength; |
||
1190 | double x = ((params[7] - params[5]) > 0) ? params[5] : params[7]; |
||
1191 | double y = ((params[6] - params[4]) > 0) ? params[4] : params[6]; |
||
1192 | double xCenter = (params[5] + params[7]) / 2.0; |
||
1193 | double yCenter = (params[4] + params[6]) / 2.0; |
||
1194 | double xWidth = fabs((double) params[5] - params[7]); |
||
1195 | double yHeight = fabs((double) params[4] - params[6]); |
||
1196 | pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength); |
||
1197 | painterPath.arcMoveTo(x,y, xWidth, yHeight, angleStart); |
||
1198 | firstPoint = painterPath.currentPosition(); |
||
1199 | painterPath.arcTo (x, y, xWidth, yHeight, angleStart, angleLength); |
||
1200 | painterPath.lineTo(xCenter, yCenter); |
||
1201 | painterPath.lineTo(firstPoint); |
||
1202 | pointArray.fromQPainterPath(painterPath); |
||
1203 | if( pointArray.size() > 0 ) |
||
1204 | { |
||
1205 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true); |
||
1206 | PageItem* ite = m_Doc->Items->at(z); |
||
1207 | ite->PoLine = pointArray; |
||
1208 | finishCmdParsing(ite); |
||
1209 | items.append(ite); |
||
1210 | } |
||
1211 | } |
||
1212 | |||
1213 | void WMFImport::setPolyFillMode( QList<PageItem*>& /*items*/, long, short* params ) |
||
1214 | { |
||
1215 | m_context.setWindingFill( params[0] ); |
||
1216 | } |
||
1217 | |||
1218 | void WMFImport::setBkColor( QList<PageItem*>& /*items*/, long, short* params ) |
||
1219 | { |
||
1220 | m_context.setBackgroundColor( colorFromParam( params ) ); |
||
1221 | } |
||
1222 | |||
1223 | void WMFImport::setBkMode( QList<PageItem*>& /*items*/, long, short* params ) |
||
1224 | { |
||
1225 | if ( params[ 0 ]==1 ) |
||
1226 | m_context.setBackgroundMode( Qt::TransparentMode ); |
||
1227 | else |
||
1228 | m_context.setBackgroundMode( Qt::OpaqueMode ); |
||
1229 | } |
||
1230 | |||
1231 | void WMFImport::saveDC( QList<PageItem*>& /*items*/, long, short* ) |
||
1232 | { |
||
1233 | m_context.save(); |
||
1234 | } |
||
1235 | |||
1236 | void WMFImport::restoreDC( QList<PageItem*>& /*items*/, long, short *params ) |
||
1237 | { |
||
1238 | for ( int i=0; i > params[ 0 ] ; i-- ) |
||
1239 | m_context.restore(); |
||
1240 | } |
||
1241 | |||
1242 | void WMFImport::intersectClipRect( QList<PageItem*>& /*items*/, long, short* /*params*/ ) |
||
1243 | { |
||
1244 | cerr << "WMFImport::intersectClipRect unimplemented" << endl; |
||
1245 | } |
||
1246 | |||
1247 | void WMFImport::excludeClipRect( QList<PageItem*>& /*items*/, long, short* /*params*/ ) |
||
1248 | { |
||
1249 | cerr << "WMFImport::excludeClipRect unimplemented" << endl; |
||
1250 | } |
||
1251 | |||
1252 | void WMFImport::setTextColor( QList<PageItem*>& /*items*/, long, short* params ) |
||
1253 | { |
||
1254 | m_context.setTextColor( colorFromParam(params) ); |
||
1255 | } |
||
1256 | |||
1257 | void WMFImport::setTextAlign( QList<PageItem*>& /*items*/, long, short* params ) |
||
1258 | { |
||
1259 | m_context.setTextAlign(params[ 0 ]); |
||
1260 | } |
||
1261 | |||
1262 | void WMFImport::textOut( QList<PageItem*>& items, long num, short* params ) |
||
1263 | { |
||
1264 | short *copyParm = new short[num + 1]; |
||
1265 | |||
1266 | // re-order parameters |
||
1267 | int idxOffset = (params[0] / 2) + 1 + (params[0] & 1); |
||
1268 | copyParm[0] = params[idxOffset]; |
||
1269 | copyParm[1] = params[idxOffset + 1]; |
||
1270 | copyParm[2] = params[0]; |
||
1271 | copyParm[3] = 0; |
||
1272 | memcpy( ©Parm[4], ¶ms[1], params[0] ); |
||
1273 | |||
1274 | extTextOut(items, num + 1, copyParm ); |
||
1275 | delete [] copyParm; |
||
1276 | } |
||
1277 | |||
1278 | void WMFImport::extTextOut( QList<PageItem*>& items, long num, short* params ) |
||
1279 | { |
||
1280 | QString textString; |
||
1281 | double BaseX = m_Doc->currentPage()->xOffset(); |
||
1282 | double BaseY = m_Doc->currentPage()->yOffset(); |
||
1283 | |||
1284 | if (params[3] & 0x0010) // ETO_GLYPH_INDEX |
||
1285 | { |
||
1286 | cerr << "WMFImport::extTextOut: ETO_GLYPH_INDEX option not supported " << endl; |
||
1287 | unsupported = true; |
||
1288 | return; |
||
1289 | } |
||
1290 | |||
1291 | // ETO_CLIPPED flag add 4 parameters |
||
1292 | char* ptStr = (params[3] & 0x0004) ? ((char*)¶ms[8]) : ((char*)¶ms[4]); |
||
1293 | QByteArray textArray( ptStr, params[2] ); |
||
1294 | |||
1295 | QTextCodec* codec = codecFromCharset( m_context.textCharSet() ); |
||
1296 | if (codec) |
||
1297 | textString = codec->toUnicode(textArray); |
||
1298 | else if ( m_context.textCharSet() == SYMBOL_CHARSET ) |
||
1299 | textString = symbolToUnicode(textArray); |
||
1300 | else |
||
1301 | textString = QString::fromLocal8Bit(textArray.data()); |
||
1302 | |||
1303 | QFontMetrics fm( m_context.font() ); |
||
1304 | int width = fm.width(textString) + fm.descent(); // because fm.width(text) isn't rigth with Italic text |
||
1305 | /*int height = fm.height(); |
||
1306 | int ascent = fm.ascent();*/ |
||
1307 | |||
1308 | double startX = params[1], startY = params[0]; |
||
1309 | int textAlign = m_context.textAlign(); |
||
1310 | double textRotation = m_context.textRotation(); |
||
1311 | if ( textAlign & 0x01 ) { // (left, top) position = current logical position |
||
1312 | QPoint pos = m_context.position(); |
||
1313 | startX = pos.x(); |
||
1314 | startY = pos.y(); |
||
1315 | } |
||
1316 | |||
1317 | m_context.save(); |
||
1318 | // A bit hacky but should be sufficient to have text not flipped |
||
1319 | // top down in some wmfs (see cell.wmf sample from libwmf) |
||
1320 | if ( m_context.worldMatrix().m22() < 0.0) |
||
1321 | { |
||
1322 | m_context.translate(startX, startY); |
||
1323 | m_context.scale (1.0, -1.0); |
||
1324 | m_context.translate( -startX, -startY); |
||
1325 | } |
||
1326 | if ( textRotation != 0.0) { |
||
1327 | m_context.translate(startX, startY); |
||
1328 | m_context.rotate ( textRotation ); |
||
1329 | m_context.translate( -startX, -startY); |
||
1330 | } |
||
1331 | |||
1332 | if ( (textAlign & 0x04) && (textAlign & 0x02) ) // TA_CENTER 0x06 |
||
1333 | startX -= (width / 2); |
||
1334 | else if ( textAlign & 0x02 ) // TA_RIGHT 0x02 |
||
1335 | startX -= width; |
||
1336 | if ( textAlign == 0 ) // TA_TOP |
||
1337 | startY += fm.ascent(); |
||
1338 | |||
1339 | bool eto_empty = (params[3] == 0); |
||
1340 | bool eto_clipped_set = (params[3] & 0x0004); |
||
1341 | bool eto_pdy_set = (params[3] & 0x2000); |
||
1342 | |||
1343 | int idxOffset = (params[ 2 ] / 2) + 4 + (params[ 2 ] & 1) + (eto_clipped_set ? 4 : 0); |
||
1344 | int minParams = eto_pdy_set ? (idxOffset + 2 * (params[2] - 1)) : (idxOffset + params[2]); |
||
1345 | bool useCharInterdistances = (num >= minParams) && (eto_empty || eto_pdy_set); |
||
1346 | if ((params[2] > 1) && useCharInterdistances) |
||
1347 | { |
||
1348 | double xpos = startX; |
||
1349 | double ypos = startY; |
||
1350 | double lineWidth = 0.0; |
||
1351 | FPointArray textPath; |
||
1352 | QString textColor = importColor( m_context.textColor() ); |
||
1353 | for (int index = 0; (index < params[2] && index < textString.length()); ++index) |
||
1354 | { |
||
1355 | QPainterPath painterPath; |
||
1356 | if (index > 0 && eto_pdy_set) |
||
1357 | { |
||
1358 | xpos += params[idxOffset + index * 2 - 1]; |
||
1359 | ypos += params[idxOffset + index * 2]; |
||
1360 | } |
||
1361 | else if (index > 0) |
||
1362 | xpos += params[idxOffset + index - 1]; |
||
1363 | painterPath.addText(xpos, ypos, m_context.font(), textString.at(index)); |
||
1364 | textPath.fromQPainterPath(painterPath); |
||
1365 | if (textPath.size() > 0) |
||
1366 | { |
||
1367 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, textColor, CommonStrings::None, true); |
||
1368 | PageItem* ite = m_Doc->Items->at(z); |
||
1369 | ite->PoLine = textPath; |
||
1370 | finishCmdParsing(ite); |
||
1371 | items.append(ite); |
||
1372 | } |
||
1373 | } |
||
1374 | } |
||
1375 | else |
||
1376 | { |
||
1377 | FPointArray textPath; |
||
1378 | QString textColor = importColor( m_context.textColor() ); |
||
1379 | QPainterPath painterPath; |
||
1380 | painterPath.addText( startX, startY, m_context.font(), textString ); |
||
1381 | textPath.fromQPainterPath(painterPath); |
||
1382 | if (textPath.size() > 0) |
||
1383 | { |
||
1384 | double lineWidth = 0.0; |
||
1385 | int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, textColor, CommonStrings::None, true); |
||
1386 | PageItem* ite = m_Doc->Items->at(z); |
||
1387 | ite->PoLine = textPath; |
||
1388 | finishCmdParsing(ite); |
||
1389 | items.append(ite); |
||
1390 | } |
||
1391 | } |
||
1392 | m_context.restore(); |
||
1393 | } |
||
1394 | |||
1395 | void WMFImport::selectObject( QList<PageItem*>& /*items*/, long, short* params ) |
||
1396 | { |
||
1397 | int idx = params[ 0 ]; |
||
1398 | if ( idx >= 0 && idx < MAX_OBJHANDLE && m_ObjHandleTab[ idx ] ) |
||
1399 | m_ObjHandleTab[ idx ]->apply( m_context ); |
||
1400 | } |
||
1401 | |||
1402 | void WMFImport::deleteObject( QList<PageItem*>& /*items*/, long, short* params ) |
||
1403 | { |
||
1404 | deleteHandle( params[ 0 ] ); |
||
1405 | } |
||
1406 | |||
1407 | void WMFImport::createEmptyObject( QList<PageItem*>& /*items*/, long, short* ) |
||
1408 | { |
||
1409 | // allocation of an empty object (to keep object counting in sync) |
||
1410 | WmfObjPenHandle* handle = new WmfObjPenHandle(); |
||
1411 | addHandle( handle ); |
||
1412 | cerr << "WMFImport: unimplemented createObject " << endl; |
||
1413 | } |
||
1414 | |||
1415 | void WMFImport::createBrushIndirect( QList<PageItem*>& /*items*/, long, short* params ) |
||
1416 | { |
||
1417 | static Qt::BrushStyle hatchedStyleTab[] = |
||
1418 | { |
||
1419 | Qt::HorPattern, |
||
1420 | Qt::FDiagPattern, |
||
1421 | Qt::BDiagPattern, |
||
1422 | Qt::CrossPattern, |
||
1423 | Qt::DiagCrossPattern |
||
1424 | }; |
||
1425 | static Qt::BrushStyle styleTab[] = |
||
1426 | { Qt::SolidPattern, |
||
1427 | Qt::NoBrush, |
||
1428 | Qt::FDiagPattern, /* hatched */ |
||
1429 | Qt::Dense4Pattern, /* should be custom bitmap pattern */ |
||
1430 | Qt::HorPattern, /* should be BS_INDEXED (?) */ |
||
1431 | Qt::VerPattern, /* should be device-independent bitmap */ |
||
1432 | Qt::Dense6Pattern, /* should be device-independent packed-bitmap */ |
||
1433 | Qt::Dense2Pattern, /* should be BS_PATTERN8x8 */ |
||
1434 | Qt::Dense3Pattern /* should be device-independent BS_DIBPATTERN8x8 */ |
||
1435 | }; |
||
1436 | Qt::BrushStyle style; |
||
1437 | short arg; |
||
1438 | WmfObjBrushHandle* handle = new WmfObjBrushHandle(); |
||
1439 | addHandle( handle ); |
||
1440 | |||
1441 | arg = params[0]; |
||
1442 | if ( arg == 2 ) |
||
1443 | { |
||
1444 | arg = params[3]; |
||
1445 | if ( arg >= 0 && arg < 5 ) |
||
1446 | style = hatchedStyleTab[ arg ]; |
||
1447 | else |
||
1448 | { |
||
1449 | cerr << "WMFImport::createBrushIndirect: invalid hatched brush " << arg << endl; |
||
1450 | style = Qt::SolidPattern; |
||
1451 | } |
||
1452 | } |
||
1453 | else if ( arg >= 0 && arg < 9 ) |
||
1454 | style = styleTab[arg]; |
||
1455 | else |
||
1456 | { |
||
1457 | cerr << "WMFImport::createBrushIndirect: invalid brush " << arg << endl; |
||
1458 | style = Qt::SolidPattern; |
||
1459 | } |
||
1460 | handle->brush.setStyle( style ); |
||
1461 | handle->brush.setColor( colorFromParam( params+1 ) ); |
||
1462 | } |
||
1463 | |||
1464 | void WMFImport::createPenIndirect( QList<PageItem*>& /*items*/, long, short* params ) |
||
1465 | { |
||
1466 | static Qt::PenStyle styleTab[] = { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine, |
||
1467 | Qt::NoPen, Qt::SolidLine }; |
||
1468 | Qt::PenStyle style; |
||
1469 | WmfObjPenHandle* handle = new WmfObjPenHandle(); |
||
1470 | addHandle( handle ); |
||
1471 | |||
1472 | if ( params[0] >= 0 && params[0] < 6 ) |
||
1473 | style = styleTab[ params[0] ]; |
||
1474 | else |
||
1475 | { |
||
1476 | cerr << "WMFImport::createPenIndirect: invalid pen " << params[ 0 ] << endl; |
||
1477 | style = Qt::SolidLine; |
||
1478 | } |
||
1479 | |||
1480 | handle->pen.setStyle( style ); |
||
1481 | handle->pen.setWidth( params[1] ); |
||
1482 | handle->pen.setColor( colorFromParam( params+3 ) ); |
||
1483 | handle->pen.setCapStyle( Qt::RoundCap ); |
||
1484 | } |
||
1485 | |||
1486 | void WMFImport::createFontIndirect( QList<PageItem*>& /*items*/, long , short* params) |
||
1487 | { |
||
1488 | WmfObjFontHandle* handle = new WmfObjFontHandle(); |
||
1489 | addHandle( handle ); |
||
1490 | |||
1491 | QString family( (const char*)¶ms[ 9 ] ); |
||
1492 | |||
1493 | handle->rotation = -params[ 2 ] / 10; // text rotation (in 1/10 degree) |
||
1494 | handle->font.setFamily( family ); |
||
1495 | handle->font.setStyleStrategy( QFont::PreferOutline ); |
||
1496 | handle->font.setFixedPitch( ((params[ 8 ] & 0x01) == 0) ); |
||
1497 | // TODO: investigation why some test case need -2. (size of font in logical point) |
||
1498 | int fontSize = (params[0] != 0) ? (qAbs(params[0]) - 2) : 12; |
||
1499 | handle->font.setPixelSize( fontSize ); |
||
1500 | handle->font.setWeight( (params[ 4 ] >> 3) ); |
||
1501 | handle->font.setItalic( (params[ 5 ] & 0x01) ); |
||
1502 | handle->font.setUnderline( (params[ 5 ] & 0x100) ); |
||
1503 | handle->font.setStrikeOut( (params[ 6 ] & 0x01) ); |
||
1504 | handle->charset = (params[ 6 ] & 0xFF00) >> 8; |
||
1505 | } |
||
1506 | |||
1507 | void WMFImport::noop( QList<PageItem*>& /*items*/, long, short* ) |
||
1508 | { |
||
1509 | } |
||
1510 | |||
1511 | void WMFImport::end( QList<PageItem*>& /*items*/, long, short* ) |
||
1512 | { |
||
1513 | //cerr << "WMFImport::end unimplemented" << endl; |
||
1514 | } |
||
1515 | |||
1516 | void WMFImport::addHandle( WmfObjHandle* handle ) |
||
1517 | { |
||
1518 | int idx; |
||
1519 | |||
1520 | for ( idx =0; idx < MAX_OBJHANDLE ; idx++ ) |
||
1521 | if ( m_ObjHandleTab[ idx ] == NULL ) break; |
||
1522 | |||
1523 | if ( idx < MAX_OBJHANDLE ) |
||
1524 | m_ObjHandleTab[ idx ] = handle; |
||
1525 | else |
||
1526 | cerr << "WMFImport error: handle table full !" << endl; |
||
1527 | } |
||
1528 | |||
1529 | void WMFImport::deleteHandle( int idx ) |
||
1530 | { |
||
1531 | if ( idx >= 0 && idx < MAX_OBJHANDLE && m_ObjHandleTab[ idx ] ) |
||
1532 | { |
||
1533 | delete m_ObjHandleTab[ idx ]; |
||
1534 | m_ObjHandleTab[ idx ] = NULL; |
||
1535 | } |
||
1536 | } |
||
1537 | |||
1538 | unsigned short WMFImport::calcCheckSum( WmfPlaceableHeader* apmfh ) |
||
1539 | { |
||
1540 | WORD16* lpWord; |
||
1541 | WORD16 wResult, i; |
||
1542 | |||
1543 | // Start with the first word |
||
1544 | wResult = *( lpWord = ( WORD16* )( apmfh ) ); |
||
1545 | // XOR in each of the other 9 words |
||
1546 | for( i=1; i<=9; i++ ) |
||
1547 | { |
||
1548 | wResult ^= lpWord[ i ]; |
||
1549 | } |
||
1550 | return wResult; |
||
1551 | } |
||
1552 | |||
1553 | int WMFImport::findFunc( unsigned short aFunc ) const |
||
1554 | { |
||
1555 | int i = 0; |
||
1556 | |||
1557 | for ( i=0; metaFuncTab[ i ].name; i++ ) |
||
1558 | if ( metaFuncTab[ i ].func == aFunc ) return i; |
||
1559 | |||
1560 | // here : unknown function |
||
1561 | return i; |
||
1562 | } |
||
1563 | |||
1564 | unsigned int WMFImport::toDWord( short* params ) |
||
1565 | { |
||
1566 | unsigned int l; |
||
1567 | #if !defined( WORDS_BIGENDIAN ) |
||
1568 | l = *( unsigned int* )( params ); |
||
1569 | #else |
||
1570 | char *bytes; |
||
1571 | char swap[ 4 ]; |
||
1572 | bytes = ( char* )params; |
||
1573 | swap[ 0 ] = bytes[ 2 ]; |
||
1574 | swap[ 1 ] = bytes[ 3 ]; |
||
1575 | swap[ 2 ] = bytes[ 0 ]; |
||
1576 | swap[ 3 ] = bytes[ 1 ]; |
||
1577 | l = *( unsigned int* )( swap ); |
||
1578 | #endif |
||
1579 | return l; |
||
1580 | } |