1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <test/mtfxmldump.hxx>
11 #include <test/xmltesttools.hxx>
12 #include <test/xmlwriter.hxx>
14 #include <vcl/metaact.hxx>
15 #include <rtl/string.hxx>
16 #include <rtl/strbuf.hxx>
18 #include <boost/scoped_ptr.hpp>
23 OUString
flagToString(PushFlags nFlag
)
25 if (nFlag
& PushFlags::LINECOLOR
)
26 return OUString("PushLineColor");
27 else if (nFlag
& PushFlags::FILLCOLOR
)
28 return OUString("PushFillColor");
29 else if (nFlag
& PushFlags::FONT
)
30 return OUString("PushFont");
31 else if (nFlag
& PushFlags::TEXTCOLOR
)
32 return OUString("PushTextColor");
33 else if (nFlag
& PushFlags::MAPMODE
)
34 return OUString("PushMapMode");
35 else if (nFlag
& PushFlags::CLIPREGION
)
36 return OUString("PushClipRegion");
37 else if (nFlag
& PushFlags::RASTEROP
)
38 return OUString("PushRasterOp");
39 else if (nFlag
& PushFlags::TEXTFILLCOLOR
)
40 return OUString("PushTextFillColor");
41 else if (nFlag
& PushFlags::TEXTALIGN
)
42 return OUString("PushTextAlign");
43 else if (nFlag
& PushFlags::REFPOINT
)
44 return OUString("PushRefPoint");
45 else if (nFlag
& PushFlags::TEXTLINECOLOR
)
46 return OUString("PushTextLineColor");
47 else if (nFlag
& PushFlags::TEXTLAYOUTMODE
)
48 return OUString("PushTextLayoutMode");
49 else if (nFlag
& PushFlags::TEXTLANGUAGE
)
50 return OUString("PushTextLanguage");
51 else if (nFlag
& PushFlags::OVERLINECOLOR
)
52 return OUString("PushOverlineColor");
57 OUString
collectPushFlags(PushFlags nFlags
)
59 if ((nFlags
& PushFlags::ALL
) == nFlags
)
60 return OUString("PushAll");
61 else if ((nFlags
& PUSH_ALLFONT
) == nFlags
)
62 return OUString("PushAllFont");
63 else if ((nFlags
& PUSH_ALLTEXT
) == nFlags
)
64 return OUString("PushAllText");
68 for (sal_uInt16 nFlag
= 1; nFlag
> 0; nFlag
<<= 1)
70 OUString sFlag
= flagToString(static_cast<PushFlags
>(nFlag
));
73 if (!sFlags
.isEmpty())
77 sFlags
+= flagToString(static_cast<PushFlags
>(nFlag
));
84 OUString
convertRopToString(RasterOp eRop
)
88 case ROP_OVERPAINT
: return OUString("overpaint");
89 case ROP_XOR
: return OUString("xor");
90 case ROP_0
: return OUString("0");
91 case ROP_1
: return OUString("1");
92 case ROP_INVERT
: return OUString("invert");
97 OUString
convertTextAlignToString(TextAlign eAlign
)
101 case ALIGN_BASELINE
: return OUString("baseline");
102 case ALIGN_BOTTOM
: return OUString("bottom");
103 case ALIGN_TOP
: return OUString("top");
104 case TextAlign_FORCE_EQUAL_SIZE
: return OUString("equalsize");
109 OUString
convertColorToString(Color aColor
)
111 OUString aRGBString
= aColor
.AsRGBHexString();
112 return "#" + aRGBString
;
115 OUString
convertLineStyleToString(LineStyle eAlign
)
119 case LINE_NONE
: return OUString("none");
120 case LINE_SOLID
: return OUString("solid");
121 case LINE_DASH
: return OUString("dash");
122 case LineStyle_FORCE_EQUAL_SIZE
: return OUString("equalsize");
127 OUString
convertFontWeigthToString(FontWeight eFontWeight
)
129 enum FontWeight
{ WEIGHT_DONTKNOW
, WEIGHT_THIN
, WEIGHT_ULTRALIGHT
,
130 WEIGHT_LIGHT
, WEIGHT_SEMILIGHT
, WEIGHT_NORMAL
,
131 WEIGHT_MEDIUM
, WEIGHT_SEMIBOLD
, WEIGHT_BOLD
,
132 WEIGHT_ULTRABOLD
, WEIGHT_BLACK
, FontWeight_FORCE_EQUAL_SIZE
=SAL_MAX_ENUM
};
135 case WEIGHT_DONTKNOW
: return OUString("unknown");
136 case WEIGHT_THIN
: return OUString("thin");
137 case WEIGHT_ULTRALIGHT
: return OUString("ultralight");
138 case WEIGHT_LIGHT
: return OUString("light");
139 case WEIGHT_SEMILIGHT
: return OUString("semilight");
140 case WEIGHT_NORMAL
: return OUString("normal");
141 case WEIGHT_MEDIUM
: return OUString("medium");
142 case WEIGHT_SEMIBOLD
: return OUString("semibold");
143 case WEIGHT_BOLD
: return OUString("bold");
144 case WEIGHT_ULTRABOLD
: return OUString("ultrabold");
145 case WEIGHT_BLACK
: return OUString("black");
146 case FontWeight_FORCE_EQUAL_SIZE
: return OUString("equalsize");
151 OString
convertLineStyleToString(const MetaActionType nActionType
)
155 case MetaActionType::NONE
: return "null";
156 case MetaActionType::PIXEL
: return "pixel";
157 case MetaActionType::POINT
: return "point";
158 case MetaActionType::LINE
: return "line";
159 case MetaActionType::RECT
: return "rect";
160 case MetaActionType::ROUNDRECT
: return "roundrect";
161 case MetaActionType::ELLIPSE
: return "ellipse";
162 case MetaActionType::ARC
: return "arc";
163 case MetaActionType::PIE
: return "pie";
164 case MetaActionType::CHORD
: return "chord";
165 case MetaActionType::POLYLINE
: return "polyline";
166 case MetaActionType::POLYGON
: return "polygon";
167 case MetaActionType::POLYPOLYGON
: return "polypolygon";
168 case MetaActionType::TEXT
: return "text";
169 case MetaActionType::TEXTARRAY
: return "textarray";
170 case MetaActionType::STRETCHTEXT
: return "stretchtext";
171 case MetaActionType::TEXTRECT
: return "textrect";
172 case MetaActionType::TEXTLINE
: return "textline";
173 case MetaActionType::BMP
: return "bmp";
174 case MetaActionType::BMPSCALE
: return "bmpscale";
175 case MetaActionType::BMPSCALEPART
: return "bmpscalepart";
176 case MetaActionType::BMPEX
: return "bmpex";
177 case MetaActionType::BMPEXSCALE
: return "bmpexscale";
178 case MetaActionType::BMPEXSCALEPART
: return "bmpexscalepart";
179 case MetaActionType::MASK
: return "mask";
180 case MetaActionType::MASKSCALE
: return "maskscale";
181 case MetaActionType::MASKSCALEPART
: return "maskscalepart";
182 case MetaActionType::GRADIENT
: return "gradient";
183 case MetaActionType::GRADIENTEX
: return "gradientex";
184 case MetaActionType::HATCH
: return "hatch";
185 case MetaActionType::WALLPAPER
: return "wallpaper";
186 case MetaActionType::CLIPREGION
: return "clipregion";
187 case MetaActionType::ISECTRECTCLIPREGION
: return "sectrectclipregion";
188 case MetaActionType::ISECTREGIONCLIPREGION
: return "sectregionclipregion";
189 case MetaActionType::MOVECLIPREGION
: return "moveclipregion";
190 case MetaActionType::LINECOLOR
: return "linecolor";
191 case MetaActionType::FILLCOLOR
: return "fillcolor";
192 case MetaActionType::TEXTCOLOR
: return "textcolor";
193 case MetaActionType::TEXTFILLCOLOR
: return "textfillcolor";
194 case MetaActionType::TEXTLINECOLOR
: return "textlinecolor";
195 case MetaActionType::OVERLINECOLOR
: return "overlinecolor";
196 case MetaActionType::TEXTALIGN
: return "textalign";
197 case MetaActionType::MAPMODE
: return "mapmode";
198 case MetaActionType::FONT
: return "font";
199 case MetaActionType::PUSH
: return "push";
200 case MetaActionType::POP
: return "pop";
201 case MetaActionType::RASTEROP
: return "rasterop";
202 case MetaActionType::Transparent
: return "transparent";
203 case MetaActionType::FLOATTRANSPARENT
: return "floattransparent";
204 case MetaActionType::EPS
: return "eps";
205 case MetaActionType::REFPOINT
: return "refpoint";
206 case MetaActionType::COMMENT
: return "comment";
207 case MetaActionType::LAYOUTMODE
: return "layoutmode";
208 case MetaActionType::TEXTLANGUAGE
: return "textlanguage";
213 } // anonymous namespace
215 MetafileXmlDump::MetafileXmlDump()
217 maFilter
.fill(false);
220 MetafileXmlDump::~MetafileXmlDump()
223 void MetafileXmlDump::filterActionType(const MetaActionType nActionType
, bool bShouldFilter
)
225 maFilter
[nActionType
] = bShouldFilter
;
228 void MetafileXmlDump::filterAllActionTypes()
233 xmlDocPtr
MetafileXmlDump::dumpAndParse(const GDIMetaFile
& rMetaFile
, const OUString
& rTempStreamName
)
235 boost::scoped_ptr
<SvStream
> pStream
;
237 if (rTempStreamName
.isEmpty())
238 pStream
.reset(new SvMemoryStream());
240 pStream
.reset(new SvFileStream(rTempStreamName
, STREAM_STD_READWRITE
| StreamMode::TRUNC
));
242 XmlWriter
aWriter(pStream
.get());
243 aWriter
.startDocument();
244 aWriter
.startElement("metafile");
246 writeXml(rMetaFile
, aWriter
);
248 aWriter
.endElement();
249 aWriter
.endDocument();
251 pStream
->Seek(STREAM_SEEK_TO_BEGIN
);
253 xmlDocPtr pDoc
= XmlTestTools::parseXmlStream(pStream
.get());
258 void MetafileXmlDump::writeXml(const GDIMetaFile
& rMetaFile
, XmlWriter
& rWriter
)
260 for(size_t nAction
= 0; nAction
< rMetaFile
.GetActionSize(); ++nAction
)
262 MetaAction
* pAction
= rMetaFile
.GetAction(nAction
);
263 const MetaActionType nActionType
= pAction
->GetType();
264 if (maFilter
[nActionType
])
267 OString sCurrentElementTag
= convertLineStyleToString(nActionType
);
271 case MetaActionType::LINE
:
273 MetaLineAction
* pMetaLineAction
= static_cast<MetaLineAction
*>(pAction
);
274 rWriter
.startElement(sCurrentElementTag
);
276 rWriter
.attribute("startx", pMetaLineAction
->GetStartPoint().X());
277 rWriter
.attribute("starty", pMetaLineAction
->GetStartPoint().Y());
278 rWriter
.attribute("endx", pMetaLineAction
->GetEndPoint().X());
279 rWriter
.attribute("endy", pMetaLineAction
->GetEndPoint().Y());
281 LineInfo aLineInfo
= pMetaLineAction
->GetLineInfo();
282 rWriter
.attribute("style", convertLineStyleToString(aLineInfo
.GetStyle()));
283 rWriter
.attribute("width", aLineInfo
.GetWidth());
284 rWriter
.attribute("dashlen", aLineInfo
.GetDashLen());
285 rWriter
.attribute("dotlen", aLineInfo
.GetDotLen());
286 rWriter
.attribute("distance", aLineInfo
.GetDistance());
288 rWriter
.endElement();
292 case MetaActionType::PUSH
:
294 MetaPushAction
* pMetaPushAction
= static_cast<MetaPushAction
*>(pAction
);
295 rWriter
.startElement(sCurrentElementTag
);
297 rWriter
.attribute("flags", collectPushFlags(pMetaPushAction
->GetFlags()));
301 case MetaActionType::POP
:
303 rWriter
.endElement();
307 case MetaActionType::RASTEROP
:
309 MetaRasterOpAction
* pMetaRasterOpAction
= static_cast<MetaRasterOpAction
*>(pAction
);
310 rWriter
.startElement(sCurrentElementTag
);
312 if (pMetaRasterOpAction
->GetRasterOp() != ROP_OVERPAINT
)
314 rWriter
.attribute("operation", convertRopToString(pMetaRasterOpAction
->GetRasterOp()));
316 rWriter
.endElement();
320 case MetaActionType::TEXTLINECOLOR
:
322 MetaTextLineColorAction
* pMetaTextLineColorAction
= static_cast<MetaTextLineColorAction
*>(pAction
);
323 rWriter
.startElement(sCurrentElementTag
);
325 rWriter
.attribute("color", convertColorToString(pMetaTextLineColorAction
->GetColor()));
326 rWriter
.endElement();
330 case MetaActionType::TEXTFILLCOLOR
:
332 MetaTextFillColorAction
* pMetaTextFillColorAction
= static_cast<MetaTextFillColorAction
*>(pAction
);
333 rWriter
.startElement(sCurrentElementTag
);
335 rWriter
.attribute("color", convertColorToString(pMetaTextFillColorAction
->GetColor()));
337 if (pMetaTextFillColorAction
->IsSetting())
338 rWriter
.attribute("setting", OUString("true"));
340 rWriter
.endElement();
344 case MetaActionType::FONT
:
346 MetaFontAction
* pMetaFontAction
= static_cast<MetaFontAction
*>(pAction
);
347 rWriter
.startElement(sCurrentElementTag
);
349 vcl::Font aFont
= pMetaFontAction
->GetFont();
351 rWriter
.attribute("color", convertColorToString(aFont
.GetColor()));
352 rWriter
.attribute("fillcolor", convertColorToString(aFont
.GetFillColor()));
353 rWriter
.attribute("name", aFont
.GetName());
354 rWriter
.attribute("stylename", aFont
.GetStyleName());
355 rWriter
.attribute("width", aFont
.GetSize().Width());
356 rWriter
.attribute("height", aFont
.GetSize().Height());
357 rWriter
.attribute("orientation", aFont
.GetOrientation());
358 rWriter
.attribute("weight", convertFontWeigthToString(aFont
.GetWeight()));
360 rWriter
.endElement();
364 case MetaActionType::TEXTALIGN
:
366 MetaTextAlignAction
* pMetaTextAlignAction
= static_cast<MetaTextAlignAction
*>(pAction
);
367 rWriter
.startElement(sCurrentElementTag
);
368 OUString sAlign
= convertTextAlignToString(pMetaTextAlignAction
->GetTextAlign());
369 if (!sAlign
.isEmpty())
370 rWriter
.attribute("align", sAlign
);
371 rWriter
.endElement();
375 case MetaActionType::TEXTCOLOR
:
377 MetaTextColorAction
* pMetaTextColorAction
= static_cast<MetaTextColorAction
*>(pAction
);
378 rWriter
.startElement(sCurrentElementTag
);
380 rWriter
.attribute("color", convertColorToString(pMetaTextColorAction
->GetColor()));
381 rWriter
.endElement();
385 case MetaActionType::TEXTARRAY
:
387 MetaTextArrayAction
* pMetaTextArrayAction
= static_cast<MetaTextArrayAction
*>(pAction
);
388 rWriter
.startElement(sCurrentElementTag
);
390 sal_Int32 aIndex
= pMetaTextArrayAction
->GetIndex();
391 sal_Int32 aLength
= pMetaTextArrayAction
->GetLen();
393 rWriter
.attribute("x", pMetaTextArrayAction
->GetPoint().X());
394 rWriter
.attribute("y", pMetaTextArrayAction
->GetPoint().Y());
395 rWriter
.attribute("index", aIndex
);
396 rWriter
.attribute("length", aLength
);
398 rWriter
.startElement("dxarray");
399 OUString sDxLengthString
;
400 for (sal_Int32 i
= 0; i
< aLength
; ++i
)
402 sDxLengthString
+= OUString::number(pMetaTextArrayAction
->GetDXArray()[aIndex
+i
]);
403 sDxLengthString
+= " ";
405 rWriter
.content(sDxLengthString
);
406 rWriter
.endElement();
408 rWriter
.startElement("text");
409 rWriter
.content(pMetaTextArrayAction
->GetText());
410 rWriter
.endElement();
412 rWriter
.endElement();
416 case MetaActionType::LINECOLOR
:
418 MetaLineColorAction
* pMetaLineColorAction
= static_cast<MetaLineColorAction
*>(pAction
);
419 rWriter
.startElement(sCurrentElementTag
);
421 rWriter
.attribute("color", convertColorToString(pMetaLineColorAction
->GetColor()));
422 rWriter
.endElement();
426 case MetaActionType::FILLCOLOR
:
428 MetaFillColorAction
* pMetaFillColorAction
= static_cast<MetaFillColorAction
*>(pAction
);
429 rWriter
.startElement(sCurrentElementTag
);
431 rWriter
.attribute("color", convertColorToString(pMetaFillColorAction
->GetColor()));
432 rWriter
.endElement();
436 case MetaActionType::CLIPREGION
:
438 const MetaClipRegionAction
* pA
= static_cast< const MetaClipRegionAction
* >(pAction
);
439 rWriter
.startElement(sCurrentElementTag
);
441 // FIXME for now we dump only the bounding box; this is
442 // enough for the tests we have, but may need extending to
443 // dumping the real polypolygon in the future
444 Rectangle aRectangle
= pA
->GetRegion().GetBoundRect();
445 rWriter
.attribute("top", aRectangle
.Top());
446 rWriter
.attribute("left", aRectangle
.Left());
447 rWriter
.attribute("bottom", aRectangle
.Bottom());
448 rWriter
.attribute("right", aRectangle
.Right());
450 rWriter
.endElement();
454 case MetaActionType::ISECTRECTCLIPREGION
:
456 MetaISectRectClipRegionAction
* pMetaISectRectClipRegionAction
= static_cast<MetaISectRectClipRegionAction
*>(pAction
);
457 rWriter
.startElement(sCurrentElementTag
);
459 Rectangle aRectangle
= pMetaISectRectClipRegionAction
->GetRect();
460 rWriter
.attribute("top", aRectangle
.Top());
461 rWriter
.attribute("left", aRectangle
.Left());
462 rWriter
.attribute("bottom", aRectangle
.Bottom());
463 rWriter
.attribute("right", aRectangle
.Right());
465 rWriter
.endElement();
469 case MetaActionType::POLYLINE
:
471 MetaPolyLineAction
* pMetaPolyLineAction
= static_cast<MetaPolyLineAction
*>(pAction
);
472 rWriter
.startElement(sCurrentElementTag
);
474 Polygon aPolygon
= pMetaPolyLineAction
->GetPolygon();
475 for (sal_uInt16 i
= 0; i
< aPolygon
.GetSize(); i
++)
477 rWriter
.startElement("point");
478 rWriter
.attribute("x", aPolygon
[i
].X());
479 rWriter
.attribute("y", aPolygon
[i
].Y());
480 rWriter
.endElement();
483 LineInfo aLineInfo
= pMetaPolyLineAction
->GetLineInfo();
484 rWriter
.attribute("style", convertLineStyleToString(aLineInfo
.GetStyle()));
485 rWriter
.attribute("width", aLineInfo
.GetWidth());
486 rWriter
.attribute("dashlen", aLineInfo
.GetDashLen());
487 rWriter
.attribute("dotlen", aLineInfo
.GetDotLen());
488 rWriter
.attribute("distance", aLineInfo
.GetDistance());
490 rWriter
.endElement();
494 case MetaActionType::POLYGON
:
496 MetaPolygonAction
* pMetaPolygonAction
= static_cast<MetaPolygonAction
*>(pAction
);
497 rWriter
.startElement(sCurrentElementTag
);
499 Polygon aPolygon
= pMetaPolygonAction
->GetPolygon();
500 for (sal_uInt16 i
= 0; i
< aPolygon
.GetSize(); i
++)
502 rWriter
.startElement("point");
503 rWriter
.attribute("x", aPolygon
[i
].X());
504 rWriter
.attribute("y", aPolygon
[i
].Y());
505 rWriter
.endElement();
508 rWriter
.endElement();
512 case MetaActionType::COMMENT
:
514 MetaCommentAction
* pMetaCommentAction
= static_cast<MetaCommentAction
*>(pAction
);
515 rWriter
.startElement(sCurrentElementTag
);
517 if (pMetaCommentAction
->GetDataSize() > 0)
519 rWriter
.attribute("datasize", pMetaCommentAction
->GetDataSize());
521 if (!pMetaCommentAction
->GetComment().isEmpty())
523 rWriter
.startElement("comment");
524 rWriter
.content(pMetaCommentAction
->GetComment());
525 rWriter
.endElement();
528 rWriter
.endElement();
534 rWriter
.element(sCurrentElementTag
);
541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */