LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/mspub/src/lib - MSPUBCollector.cpp (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 770 0.0 %
Date: 2012-12-17 Functions: 0 79 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* libmspub
       3             :  * Version: MPL 1.1 / GPLv2+ / LGPLv2+
       4             :  *
       5             :  * The contents of this file are subject to the Mozilla Public License Version
       6             :  * 1.1 (the "License"); you may not use this file except in compliance with
       7             :  * the License or as specified alternatively below. You may obtain a copy of
       8             :  * the License at http://www.mozilla.org/MPL/
       9             :  *
      10             :  * Software distributed under the License is distributed on an "AS IS" basis,
      11             :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12             :  * for the specific language governing rights and limitations under the
      13             :  * License.
      14             :  *
      15             :  * Major Contributor(s):
      16             :  * Copyright (C) 2012 Brennan Vincent <brennanv@email.arizona.edu>
      17             :  * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
      18             :  *
      19             :  *
      20             :  * All Rights Reserved.
      21             :  *
      22             :  * For minor contributions see the git repository.
      23             :  *
      24             :  * Alternatively, the contents of this file may be used under the terms of
      25             :  * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
      26             :  * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
      27             :  * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
      28             :  * instead of those above.
      29             :  */
      30             : 
      31             : #include <math.h>
      32             : #include "MSPUBCollector.h"
      33             : #include "libmspub_utils.h"
      34             : #include "MSPUBConstants.h"
      35             : #include "MSPUBTypes.h"
      36             : #include "PolygonUtils.h"
      37             : #include "Coordinate.h"
      38             : #pragma GCC diagnostic ignored "-Wpragmas"
      39             : #pragma GCC diagnostic ignored "-Wuninitialized"
      40             : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
      41             : 
      42           0 : WPXBinaryData &libmspub::MSPUBCollector::addEOTFont(const WPXString &name)
      43             : {
      44           0 :   m_embeddedFonts.push_back(EmbeddedFontInfo(name));
      45           0 :   return m_embeddedFonts.back().m_blob;
      46             : }
      47             : 
      48           0 : void libmspub::MSPUBCollector::setShapePictureRecolor(unsigned seqNum,
      49             :     const ColorReference &recolor)
      50             : {
      51           0 :   m_shapeInfosBySeqNum[seqNum].m_pictureRecolor = recolor;
      52           0 : }
      53             : 
      54           0 : void libmspub::MSPUBCollector::setShapeBeginArrow(unsigned seqNum,
      55             :     const Arrow &arrow)
      56             : {
      57           0 :   m_shapeInfosBySeqNum[seqNum].m_beginArrow = arrow;
      58           0 : }
      59             : 
      60           0 : void libmspub::MSPUBCollector::setShapeVerticalTextAlign(unsigned seqNum,
      61             :     VerticalAlign va)
      62             : {
      63           0 :   m_shapeInfosBySeqNum[seqNum].m_verticalAlign = va;
      64           0 : }
      65             : 
      66           0 : void libmspub::MSPUBCollector::setShapeEndArrow(unsigned seqNum,
      67             :     const Arrow &arrow)
      68             : {
      69           0 :   m_shapeInfosBySeqNum[seqNum].m_endArrow = arrow;
      70           0 : }
      71             : 
      72           0 : void libmspub::MSPUBCollector::setShapeTableInfo(unsigned seqNum,
      73             :     const TableInfo &ti)
      74             : {
      75           0 :   m_shapeInfosBySeqNum[seqNum].m_tableInfo = ti;
      76           0 : }
      77             : 
      78           0 : void libmspub::MSPUBCollector::setShapeNumColumns(unsigned seqNum,
      79             :     unsigned numColumns)
      80             : {
      81           0 :   m_shapeInfosBySeqNum[seqNum].m_numColumns = numColumns;
      82           0 : }
      83             : 
      84           0 : void libmspub::MSPUBCollector::setShapeColumnSpacing(unsigned seqNum,
      85             :     unsigned spacing)
      86             : {
      87           0 :   m_shapeInfosBySeqNum[seqNum].m_columnSpacing = spacing;
      88           0 : }
      89             : 
      90           0 : void libmspub::MSPUBCollector::setShapeStretchBorderArt(unsigned seqNum)
      91             : {
      92           0 :   m_shapeInfosBySeqNum[seqNum].m_stretchBorderArt = true;
      93           0 : }
      94             : 
      95           0 : void libmspub::MSPUBCollector::setRectCoordProps(Coordinate coord, WPXPropertyList *props) const
      96             : {
      97           0 :   int xs = coord.m_xs, ys = coord.m_ys, xe = coord.m_xe, ye = coord.m_ye;
      98           0 :   double x_center = m_width / 2;
      99           0 :   double y_center = m_height / 2;
     100           0 :   props->insert("svg:x", x_center + (double)xs / EMUS_IN_INCH);
     101           0 :   props->insert("svg:y", y_center + (double)ys / EMUS_IN_INCH);
     102           0 :   props->insert("svg:width", (double)(xe - xs) / EMUS_IN_INCH);
     103           0 :   props->insert("svg:height", (double)(ye - ys) / EMUS_IN_INCH);
     104           0 : }
     105             : 
     106           0 : libmspub::Coordinate getFudgedCoordinates(libmspub::Coordinate coord, const std::vector<libmspub::Line> &lines, bool makeBigger, libmspub::BorderPosition borderPosition)
     107             : {
     108           0 :   libmspub::Coordinate fudged = coord;
     109           0 :   unsigned topFudge = 0;
     110           0 :   unsigned rightFudge = 0;
     111           0 :   unsigned bottomFudge = 0;
     112           0 :   unsigned leftFudge = 0;
     113           0 :   switch (borderPosition)
     114             :   {
     115             :   case libmspub::HALF_INSIDE_SHAPE:
     116           0 :     topFudge = (!lines.empty()) ? lines[0].m_widthInEmu / 2 : 0;
     117           0 :     rightFudge = (lines.size() > 1) ? lines[1].m_widthInEmu / 2 : 0;
     118           0 :     bottomFudge = (lines.size() > 2) ? lines[2].m_widthInEmu / 2 : 0;
     119           0 :     leftFudge = (lines.size() > 3) ? lines[3].m_widthInEmu / 2 : 0;
     120           0 :     break;
     121             :   case libmspub::OUTSIDE_SHAPE:
     122           0 :     topFudge = (!lines.empty()) ? lines[0].m_widthInEmu : 0;
     123           0 :     rightFudge = (lines.size() > 1) ? lines[1].m_widthInEmu : 0;
     124           0 :     bottomFudge = (lines.size() > 2) ? lines[2].m_widthInEmu : 0;
     125           0 :     leftFudge = (lines.size() > 3) ? lines[3].m_widthInEmu : 0;
     126           0 :     break;
     127             :   case libmspub::INSIDE_SHAPE:
     128             :   default:
     129           0 :     break;
     130             :   }
     131           0 :   if (makeBigger)
     132             :   {
     133           0 :     fudged.m_xs -= leftFudge;
     134           0 :     fudged.m_xe += rightFudge;
     135           0 :     fudged.m_ys -= topFudge;
     136           0 :     fudged.m_ye += bottomFudge;
     137             :   }
     138             :   else
     139             :   {
     140           0 :     fudged.m_xs += leftFudge;
     141           0 :     fudged.m_xe -= rightFudge;
     142           0 :     fudged.m_ys += topFudge;
     143           0 :     fudged.m_ye -= bottomFudge;
     144             :   }
     145           0 :   return fudged;
     146             : }
     147             : 
     148           0 : void libmspub::MSPUBCollector::setNextPage(unsigned pageSeqNum)
     149             : {
     150           0 :   m_pageSeqNumsOrdered.push_back(pageSeqNum);
     151           0 : }
     152             : 
     153             : #ifndef M_PI
     154             : #define M_PI 3.14159265358979323846
     155             : #endif
     156             : 
     157           0 : libmspub::MSPUBCollector::MSPUBCollector(libwpg::WPGPaintInterface *painter) :
     158             :   m_painter(painter), m_contentChunkReferences(), m_width(0), m_height(0),
     159             :   m_widthSet(false), m_heightSet(false),
     160             :   m_numPages(0), m_textStringsById(), m_pagesBySeqNum(),
     161             :   m_images(), m_borderImages(),
     162             :   m_textColors(), m_fonts(),
     163             :   m_defaultCharStyles(), m_defaultParaStyles(), m_shapeTypesBySeqNum(),
     164             :   m_paletteColors(), m_shapeSeqNumsOrdered(),
     165             :   m_pageSeqNumsByShapeSeqNum(), m_bgShapeSeqNumsByPageSeqNum(),
     166             :   m_skipIfNotBgSeqNums(),
     167             :   m_currentShapeGroup(NULL), m_topLevelShapes(),
     168             :   m_groupsBySeqNum(), m_embeddedFonts(),
     169             :   m_shapeInfosBySeqNum(), m_masterPages(),
     170             :   m_shapesWithCoordinatesRotated90(),
     171             :   m_masterPagesByPageSeqNum(),
     172             :   m_encoding(), m_tableCellTextEndsVector(), m_stringOffsetsByTextId(),
     173           0 :   m_calculationValuesSeen(), m_pageSeqNumsOrdered()
     174             : {
     175           0 : }
     176             : 
     177           0 : void libmspub::MSPUBCollector::setTextStringOffset(
     178             :   unsigned textId, unsigned offset)
     179             : {
     180           0 :   m_stringOffsetsByTextId[textId] = offset;
     181           0 : }
     182             : 
     183           0 : void libmspub::MSPUBCollector::setNextTableCellTextEnds(
     184             :   const std::vector<unsigned> &ends)
     185             : {
     186           0 :   m_tableCellTextEndsVector.push_back(ends);
     187           0 : }
     188             : 
     189           0 : void libmspub::MSPUBCollector::setEncoding(Encoding encoding)
     190             : {
     191           0 :   m_encoding = encoding;
     192           0 : }
     193             : 
     194           0 : void libmspub::MSPUBCollector::setShapeShadow(unsigned seqNum, const Shadow &shadow)
     195             : {
     196           0 :   m_shapeInfosBySeqNum[seqNum].m_shadow = shadow;
     197           0 : }
     198             : 
     199           0 : void libmspub::noop(const CustomShape *)
     200             : {
     201           0 : }
     202             : 
     203           0 : void libmspub::MSPUBCollector::setShapeCoordinatesRotated90(unsigned seqNum)
     204             : {
     205           0 :   m_shapesWithCoordinatesRotated90.insert(seqNum);
     206           0 : }
     207             : 
     208           0 : void libmspub::MSPUBCollector::setShapeBorderImageId(unsigned seqNum, unsigned id)
     209             : {
     210           0 :   m_shapeInfosBySeqNum[seqNum].m_borderImgIndex = id;
     211           0 : }
     212             : 
     213           0 : void libmspub::MSPUBCollector::setShapeCustomPath(unsigned seqNum,
     214             :     const DynamicCustomShape &shape)
     215             : {
     216           0 :   m_shapeInfosBySeqNum[seqNum].m_customShape = shape;
     217           0 : }
     218             : 
     219           0 : void libmspub::MSPUBCollector::beginGroup()
     220             : {
     221           0 :   ShapeGroupElement *tmp = new ShapeGroupElement(m_currentShapeGroup);
     222           0 :   if (!m_currentShapeGroup)
     223             :   {
     224           0 :     m_topLevelShapes.push_back(tmp);
     225             :   }
     226           0 :   m_currentShapeGroup = tmp;
     227           0 : }
     228             : 
     229           0 : bool libmspub::MSPUBCollector::endGroup()
     230             : {
     231           0 :   if (!m_currentShapeGroup)
     232             :   {
     233           0 :     return false;
     234             :   }
     235           0 :   m_currentShapeGroup = m_currentShapeGroup->getParent();
     236           0 :   return true;
     237             : }
     238             : 
     239           0 : void libmspub::MSPUBCollector::addShapeLine(unsigned seqNum, Line line)
     240             : {
     241           0 :   m_shapeInfosBySeqNum[seqNum].m_lines.push_back(line);
     242           0 : }
     243             : 
     244           0 : void libmspub::MSPUBCollector::setShapeBorderPosition(unsigned seqNum, BorderPosition pos)
     245             : {
     246           0 :   m_shapeInfosBySeqNum[seqNum].m_borderPosition = pos;
     247           0 : }
     248             : 
     249           0 : bool libmspub::MSPUBCollector::hasPage(unsigned seqNum) const
     250             : {
     251           0 :   return m_pagesBySeqNum.find(seqNum) != m_pagesBySeqNum.end();
     252             : }
     253             : 
     254           0 : void libmspub::MSPUBCollector::setShapeMargins(unsigned seqNum, unsigned left, unsigned top, unsigned right, unsigned bottom)
     255             : {
     256           0 :   m_shapeInfosBySeqNum[seqNum].m_margins = Margins(left, top, right, bottom);
     257           0 : }
     258             : 
     259           0 : void libmspub::MSPUBCollector::setPageBgShape(unsigned pageSeqNum, unsigned seqNum)
     260             : {
     261           0 :   m_bgShapeSeqNumsByPageSeqNum[pageSeqNum] = seqNum;
     262           0 : }
     263             : 
     264           0 : bool libmspub::MSPUBCollector::setCurrentGroupSeqNum(unsigned seqNum)
     265             : {
     266           0 :   if (!m_currentShapeGroup)
     267             :   {
     268           0 :     return false;
     269             :   }
     270           0 :   m_currentShapeGroup->setSeqNum(seqNum);
     271           0 :   m_groupsBySeqNum.insert(std::pair<unsigned, ShapeGroupElement *>(seqNum, m_currentShapeGroup));
     272           0 :   return true;
     273             : }
     274             : 
     275           0 : void libmspub::MSPUBCollector::setShapeOrder(unsigned seqNum)
     276             : {
     277           0 :   ShapeGroupElement *tmp = new ShapeGroupElement(m_currentShapeGroup, seqNum);
     278           0 :   if (!m_currentShapeGroup)
     279             :   {
     280           0 :     m_topLevelShapes.push_back(tmp);
     281             :   }
     282           0 : }
     283             : 
     284           0 : void libmspub::MSPUBCollector::addPaletteColor(Color c)
     285             : {
     286           0 :   m_paletteColors.push_back(c);
     287           0 : }
     288             : 
     289           0 : void no_op()
     290             : {
     291           0 : }
     292             : 
     293           0 : void endShapeGroup(libwpg::WPGPaintInterface *painter)
     294             : {
     295           0 :   painter->endLayer();
     296           0 : }
     297             : 
     298           0 : std::vector<int> libmspub::MSPUBCollector::getShapeAdjustValues(const ShapeInfo &info) const
     299             : {
     300           0 :   std::vector<int> ret;
     301           0 :   boost::shared_ptr<const CustomShape> ptr_shape = info.getCustomShape();
     302           0 :   if (ptr_shape)
     303             :   {
     304           0 :     for (unsigned i = 0; i < ptr_shape->m_numDefaultAdjustValues; ++i)
     305             :     {
     306           0 :       ret.push_back(ptr_shape->mp_defaultAdjustValues[i]);
     307             :     }
     308             :   }
     309           0 :   for (std::map<unsigned, int>::const_iterator i = info.m_adjustValuesByIndex.begin();
     310           0 :        i != info.m_adjustValuesByIndex.end(); ++i)
     311             :   {
     312           0 :     unsigned index = i->first;
     313           0 :     int adjustVal = i->second;
     314           0 :     for (unsigned j = info.m_adjustValues.size(); j <= index; ++j)
     315             :     {
     316           0 :       ret.push_back(0);
     317             :     }
     318           0 :     ret[index] = adjustVal;
     319             :   }
     320           0 :   return ret;
     321             : }
     322             : 
     323           0 : boost::optional<std::vector<libmspub::TextParagraph> > libmspub::MSPUBCollector::getShapeText(const ShapeInfo &info) const
     324             : {
     325           0 :   if (info.m_textId.is_initialized())
     326             :   {
     327           0 :     unsigned stringId = info.m_textId.get();
     328           0 :     const std::vector<TextParagraph> *ptr_str = getIfExists_const(m_textStringsById, stringId);
     329           0 :     if (ptr_str)
     330             :     {
     331           0 :       return *ptr_str;
     332             :     }
     333             :   }
     334           0 :   return boost::optional<std::vector<TextParagraph> >();
     335             : }
     336             : 
     337           0 : void libmspub::MSPUBCollector::setupShapeStructures(ShapeGroupElement &elt)
     338             : {
     339           0 :   ShapeInfo *ptr_info = getIfExists(m_shapeInfosBySeqNum, elt.getSeqNum());
     340           0 :   if (ptr_info)
     341             :   {
     342           0 :     if (ptr_info->m_imgIndex.is_initialized())
     343             :     {
     344           0 :       unsigned index = ptr_info->m_imgIndex.get();
     345           0 :       if (index - 1 < m_images.size())
     346             :       {
     347           0 :         ptr_info->m_fill = boost::shared_ptr<const Fill>(new ImgFill(index, this, false));
     348             :       }
     349             :     }
     350           0 :     elt.setShapeInfo(*ptr_info);
     351           0 :     std::pair<bool, bool> flips = ptr_info->m_flips.get_value_or(std::pair<bool, bool>(false, false));
     352           0 :     VectorTransformation2D flipsTransform = VectorTransformation2D::fromFlips(flips.second, flips.first);
     353           0 :     double rotation = ptr_info->m_rotation.get_value_or(0);
     354           0 :     rotation = doubleModulo(rotation, 360);
     355           0 :     bool rotBackwards = flips.first ^ flips.second;
     356           0 :     VectorTransformation2D rot = VectorTransformation2D::fromCounterRadians((rotBackwards ? -rotation : rotation) * M_PI / 180);
     357           0 :     elt.setTransform(rot * flipsTransform);
     358             :   }
     359           0 : }
     360             : 
     361             : 
     362           0 : boost::function<void(void)> libmspub::MSPUBCollector::paintShape(const ShapeInfo &info, const Coordinate &/* relativeTo*/, const VectorTransformation2D &foldedTransform, bool isGroup, const VectorTransformation2D &thisTransform) const
     363             : {
     364           0 :   std::vector<int> adjustValues = getShapeAdjustValues(info);
     365           0 :   if (isGroup)
     366             :   {
     367           0 :     m_painter->startLayer(WPXPropertyList());
     368           0 :     return boost::bind(&endShapeGroup, m_painter);
     369             :   }
     370           0 :   WPXPropertyList graphicsProps;
     371           0 :   WPXPropertyListVector graphicsPropsVector;
     372           0 :   if (info.m_fill)
     373             :   {
     374           0 :     graphicsPropsVector = info.m_fill->getProperties(&graphicsProps);
     375             :   }
     376           0 :   bool hasStroke = false;
     377           0 :   bool hasBorderArt = false;
     378           0 :   boost::optional<unsigned> maybeBorderImg = info.m_borderImgIndex;
     379           0 :   if (maybeBorderImg.is_initialized() && !info.m_lines.empty())
     380             :   {
     381           0 :     hasStroke = true;
     382           0 :     hasBorderArt = true;
     383             :   }
     384             :   else
     385             :   {
     386           0 :     for (unsigned i = 0; i < info.m_lines.size(); ++i)
     387             :     {
     388           0 :       hasStroke = hasStroke || info.m_lines[i].m_lineExists;
     389           0 :       if (hasStroke)
     390             :       {
     391           0 :         break;
     392             :       }
     393             :     }
     394             :   }
     395           0 :   WPXString fill = graphicsProps["draw:fill"] ? graphicsProps["draw:fill"]->getStr() : "none";
     396           0 :   bool hasFill = fill != "none";
     397           0 :   boost::optional<std::vector<TextParagraph> > maybeText = getShapeText(info);
     398           0 :   bool hasText = maybeText.is_initialized();
     399             :   bool makeLayer = hasBorderArt ||
     400           0 :                    (hasStroke && hasFill) || (hasStroke && hasText) || (hasFill && hasText);
     401           0 :   if (makeLayer)
     402             :   {
     403           0 :     m_painter->startLayer(WPXPropertyList());
     404             :   }
     405           0 :   graphicsProps.insert("draw:stroke", "none");
     406           0 :   const Coordinate &coord = info.m_coordinates.get_value_or(Coordinate());
     407             :   BorderPosition borderPosition =
     408           0 :     hasBorderArt ? INSIDE_SHAPE : info.m_borderPosition.get_value_or(HALF_INSIDE_SHAPE);
     409           0 :   ShapeType type = info.m_type.get_value_or(RECTANGLE);
     410           0 :   if (hasFill)
     411             :   {
     412             :     double x, y, height, width;
     413           0 :     x = coord.getXIn(m_width);
     414           0 :     y = coord.getYIn(m_height);
     415           0 :     height = coord.getHeightIn();
     416           0 :     width = coord.getWidthIn();
     417           0 :     if (hasBorderArt)
     418             :     {
     419             :       double borderImgWidth =
     420           0 :         static_cast<double>(info.m_lines[0].m_widthInEmu) / EMUS_IN_INCH;
     421           0 :       if (height > 2 * borderImgWidth && width >= 2 * borderImgWidth)
     422             :       {
     423           0 :         x += borderImgWidth;
     424           0 :         y += borderImgWidth;
     425           0 :         height -= 2 * borderImgWidth;
     426           0 :         width -= 2 * borderImgWidth;
     427             :       }
     428             :     }
     429           0 :     if (info.m_pictureRecolor.is_initialized())
     430             :     {
     431           0 :       Color obc = info.m_pictureRecolor.get().getFinalColor(m_paletteColors);
     432           0 :       graphicsProps.insert("draw:color-mode", "greyscale");
     433             :       graphicsProps.insert("draw:red",
     434           0 :                            static_cast<double>(obc.r) / 255.0, WPX_PERCENT);
     435             :       graphicsProps.insert("draw:blue",
     436           0 :                            static_cast<double>(obc.b) / 255.0, WPX_PERCENT);
     437             :       graphicsProps.insert("draw:green",
     438           0 :                            static_cast<double>(obc.g) / 255.0, WPX_PERCENT);
     439             :     }
     440           0 :     bool shadowPropsInserted = false;
     441           0 :     if (info.m_shadow.is_initialized())
     442             :     {
     443           0 :       const Shadow &s = info.m_shadow.get();
     444           0 :       if (!needsEmulation(s))
     445             :       {
     446           0 :         shadowPropsInserted = true;
     447           0 :         graphicsProps.insert("draw:shadow", "visible");
     448             :         graphicsProps.insert("draw:shadow-offset-x",
     449           0 :                              static_cast<double>(s.m_offsetXInEmu) / EMUS_IN_INCH);
     450             :         graphicsProps.insert("draw:shadow-offset-y",
     451           0 :                              static_cast<double>(s.m_offsetYInEmu) / EMUS_IN_INCH);
     452             :         graphicsProps.insert("draw:shadow-color",
     453           0 :                              getColorString(s.m_color.getFinalColor(m_paletteColors)));
     454             :         graphicsProps.insert("draw:shadow-opacity",
     455           0 :                              s.m_opacity, WPX_PERCENT);
     456             :       }
     457             :       // TODO: Emulate shadows that don't conform
     458             :       // to LibreOffice's range of possible shadows.
     459             :     }
     460           0 :     m_painter->setStyle(graphicsProps, graphicsPropsVector);
     461             : 
     462             :     writeCustomShape(type, graphicsProps, m_painter, x, y, height, width,
     463             :                      true, foldedTransform,
     464           0 :                      std::vector<Line>(), boost::bind(&libmspub::MSPUBCollector::getCalculationValue, this, info, _1, false, adjustValues), m_paletteColors, info.getCustomShape());
     465           0 :     if (info.m_pictureRecolor.is_initialized())
     466             :     {
     467           0 :       graphicsProps.remove("draw:color-mode");
     468           0 :       graphicsProps.remove("draw:red");
     469           0 :       graphicsProps.remove("draw:blue");
     470           0 :       graphicsProps.remove("draw:green");
     471             :     }
     472           0 :     if (shadowPropsInserted)
     473             :     {
     474           0 :       graphicsProps.remove("draw:shadow");
     475           0 :       graphicsProps.remove("draw:shadow-offset-x");
     476           0 :       graphicsProps.remove("draw:shadow-offset-y");
     477           0 :       graphicsProps.remove("draw:shadow-color");
     478           0 :       graphicsProps.remove("draw:shadow-opacity");
     479             :     }
     480             :   }
     481           0 :   const std::vector<Line> &lines = info.m_lines;
     482           0 :   if (hasStroke)
     483             :   {
     484           0 :     if (hasBorderArt)
     485             :     {
     486           0 :       bool stretch = info.m_stretchBorderArt;
     487           0 :       double x = coord.getXIn(m_width);
     488           0 :       double y = coord.getYIn(m_height);
     489           0 :       double height = coord.getHeightIn();
     490           0 :       double width = coord.getWidthIn();
     491             :       double borderImgWidth =
     492           0 :         static_cast<double>(info.m_lines[0].m_widthInEmu) / EMUS_IN_INCH;
     493           0 :       unsigned numImagesHoriz = static_cast<unsigned>(width / borderImgWidth);
     494           0 :       unsigned numImagesVert = static_cast<unsigned>(height / borderImgWidth);
     495           0 :       double borderVertTotalPadding = height - numImagesVert * borderImgWidth;
     496           0 :       double borderHorizTotalPadding = width - numImagesHoriz * borderImgWidth;
     497           0 :       if (numImagesHoriz >= 2 && numImagesVert >= 2)
     498             :       {
     499             :         unsigned numStretchedImagesVert = static_cast<unsigned>(
     500           0 :                                             0.5 + (height - 2 * borderImgWidth) / borderImgWidth);
     501             :         unsigned numStretchedImagesHoriz = static_cast<unsigned>(
     502           0 :                                              0.5 + (width - 2 * borderImgWidth) / borderImgWidth);
     503             :         double stretchedImgHeight = stretch ?
     504             :                                     (height - 2 * borderImgWidth) / numStretchedImagesVert :
     505           0 :                                     borderImgWidth;
     506             :         double stretchedImgWidth = stretch ?
     507             :                                    (width - 2 * borderImgWidth) / numStretchedImagesHoriz :
     508           0 :                                    borderImgWidth;
     509           0 :         if (stretch)
     510             :         {
     511           0 :           numImagesVert = 2 + numStretchedImagesVert;
     512           0 :           numImagesHoriz = 2 + numStretchedImagesHoriz;
     513             :         }
     514           0 :         double borderVertPadding = borderVertTotalPadding / (numImagesVert - 1);
     515           0 :         double borderHorizPadding = borderHorizTotalPadding / (numImagesHoriz - 1);
     516           0 :         const BorderArtInfo &ba = m_borderImages[maybeBorderImg.get()];
     517           0 :         if (!ba.m_offsets.empty())
     518             :         {
     519           0 :           WPXPropertyList baProps;
     520           0 :           baProps.insert("draw:stroke", "none");
     521           0 :           baProps.insert("draw:fill", "solid");
     522           0 :           baProps.insert("draw:fill-color", "#ffffff");
     523           0 :           m_painter->setStyle(baProps, WPXPropertyListVector());
     524           0 :           WPXPropertyList topRectProps;
     525           0 :           topRectProps.insert("svg:x", x);
     526           0 :           topRectProps.insert("svg:y", y);
     527           0 :           topRectProps.insert("svg:height", borderImgWidth);
     528           0 :           topRectProps.insert("svg:width", width);
     529           0 :           m_painter->drawRectangle(topRectProps);
     530           0 :           WPXPropertyList rightRectProps;
     531           0 :           rightRectProps.insert("svg:x", x + width - borderImgWidth);
     532           0 :           rightRectProps.insert("svg:y", y);
     533           0 :           rightRectProps.insert("svg:height", height);
     534           0 :           rightRectProps.insert("svg:width", borderImgWidth);
     535           0 :           m_painter->drawRectangle(rightRectProps);
     536           0 :           WPXPropertyList botRectProps;
     537           0 :           botRectProps.insert("svg:x", x);
     538           0 :           botRectProps.insert("svg:y", y + height - borderImgWidth);
     539           0 :           botRectProps.insert("svg:height", borderImgWidth);
     540           0 :           botRectProps.insert("svg:width", width);
     541           0 :           m_painter->drawRectangle(botRectProps);
     542           0 :           WPXPropertyList leftRectProps;
     543           0 :           leftRectProps.insert("svg:x", x);
     544           0 :           leftRectProps.insert("svg:y", y);
     545           0 :           leftRectProps.insert("svg:height", height);
     546           0 :           leftRectProps.insert("svg:width", borderImgWidth);
     547           0 :           m_painter->drawRectangle(leftRectProps);
     548           0 :           std::vector<unsigned>::const_iterator iOffset = ba.m_offsets.begin();
     549           0 :           boost::optional<Color> oneBitColor;
     550           0 :           if (info.m_lineBackColor.is_initialized())
     551             :           {
     552           0 :             oneBitColor = info.m_lineBackColor.get().getFinalColor(m_paletteColors);
     553             :           }
     554             :           // top left
     555             :           unsigned iOrdOff = find(ba.m_offsetsOrdered.begin(),
     556           0 :                                   ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     557           0 :           if (iOrdOff < ba.m_images.size())
     558             :           {
     559           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     560             :             writeImage(x, y, borderImgWidth, borderImgWidth,
     561           0 :                        bi.m_type, bi.m_imgBlob, oneBitColor);
     562             :           }
     563           0 :           if (iOffset + 1 != ba.m_offsets.end())
     564             :           {
     565           0 :             ++iOffset;
     566             :           }
     567             :           // top
     568             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     569           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     570           0 :           if (iOrdOff < ba.m_images.size())
     571             :           {
     572           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     573           0 :             for (unsigned iTop = 1; iTop < numImagesHoriz - 1; ++iTop)
     574             :             {
     575             :               double imgX = stretch ?
     576             :                             x + borderImgWidth + (iTop - 1) * stretchedImgWidth :
     577           0 :                             x + iTop * (borderImgWidth + borderHorizPadding);
     578             :               writeImage(imgX, y,
     579             :                          borderImgWidth, stretchedImgWidth,
     580           0 :                          bi.m_type, bi.m_imgBlob, oneBitColor);
     581             :             }
     582             :           }
     583           0 :           if (iOffset + 1 != ba.m_offsets.end())
     584             :           {
     585           0 :             ++iOffset;
     586             :           }
     587             :           // top right
     588             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     589           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     590           0 :           if (iOrdOff < ba.m_images.size())
     591             :           {
     592           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     593             :             writeImage(x + width - borderImgWidth, y,
     594             :                        borderImgWidth, borderImgWidth,
     595           0 :                        bi.m_type, bi.m_imgBlob, oneBitColor);
     596             :           }
     597           0 :           if (iOffset + 1 != ba.m_offsets.end())
     598             :           {
     599           0 :             ++iOffset;
     600             :           }
     601             :           // right
     602             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     603           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     604           0 :           if (iOrdOff < ba.m_images.size())
     605             :           {
     606           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     607           0 :             for (unsigned iRight = 1; iRight < numImagesVert - 1; ++iRight)
     608             :             {
     609             :               double imgY = stretch ?
     610             :                             y + borderImgWidth + (iRight - 1) * stretchedImgHeight :
     611           0 :                             y + iRight * (borderImgWidth + borderVertPadding);
     612             :               writeImage(x + width - borderImgWidth,
     613             :                          imgY,
     614             :                          stretchedImgHeight, borderImgWidth,
     615           0 :                          bi.m_type, bi.m_imgBlob, oneBitColor);
     616             :             }
     617             :           }
     618           0 :           if (iOffset + 1 != ba.m_offsets.end())
     619             :           {
     620           0 :             ++iOffset;
     621             :           }
     622             :           // bottom right
     623             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     624           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     625           0 :           if (iOrdOff < ba.m_images.size())
     626             :           {
     627           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     628             :             writeImage(x + width - borderImgWidth,
     629             :                        y + height - borderImgWidth,
     630             :                        borderImgWidth, borderImgWidth,
     631           0 :                        bi.m_type, bi.m_imgBlob, oneBitColor);
     632             :           }
     633           0 :           if (iOffset + 1 != ba.m_offsets.end())
     634             :           {
     635           0 :             ++iOffset;
     636             :           }
     637             :           // bottom
     638             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     639           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     640           0 :           if (iOrdOff < ba.m_images.size())
     641             :           {
     642           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     643           0 :             for (unsigned iBot = 1; iBot < numImagesHoriz - 1; ++iBot)
     644             :             {
     645             :               double imgX = stretch ?
     646             :                             x + width - borderImgWidth - iBot * stretchedImgWidth :
     647           0 :                             x + width - borderImgWidth - iBot * (borderImgWidth + borderHorizPadding);
     648             :               writeImage(
     649             :                 imgX, y + height - borderImgWidth,
     650             :                 borderImgWidth, stretchedImgWidth,
     651           0 :                 bi.m_type, bi.m_imgBlob, oneBitColor);
     652             :             }
     653             :           }
     654           0 :           if (iOffset + 1 != ba.m_offsets.end())
     655             :           {
     656           0 :             ++iOffset;
     657             :           }
     658             :           // bottom left
     659             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     660           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     661           0 :           if (iOrdOff < ba.m_images.size())
     662             :           {
     663           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     664             :             writeImage(x, y + height - borderImgWidth,
     665             :                        borderImgWidth, borderImgWidth,
     666           0 :                        bi.m_type, bi.m_imgBlob, oneBitColor);
     667             :           }
     668           0 :           if (iOffset + 1 != ba.m_offsets.end())
     669             :           {
     670           0 :             ++iOffset;
     671             :           }
     672             :           // left
     673             :           iOrdOff = find(ba.m_offsetsOrdered.begin(),
     674           0 :                          ba.m_offsetsOrdered.end(), *iOffset) - ba.m_offsetsOrdered.begin();
     675           0 :           if (iOrdOff < ba.m_images.size())
     676             :           {
     677           0 :             const BorderImgInfo &bi = ba.m_images[iOrdOff];
     678           0 :             for (unsigned iLeft = 1; iLeft < numImagesVert - 1; ++iLeft)
     679             :             {
     680             :               double imgY = stretch ?
     681             :                             y + height - borderImgWidth - iLeft * stretchedImgHeight :
     682             :                             y + height - borderImgWidth -
     683           0 :                             iLeft * (borderImgWidth + borderVertPadding);
     684             :               writeImage(x, imgY, stretchedImgHeight, borderImgWidth,
     685           0 :                          bi.m_type, bi.m_imgBlob, oneBitColor);
     686             :             }
     687           0 :           }
     688             :         }
     689             :       }
     690             :     }
     691             :     else
     692             :     {
     693           0 :       Coordinate strokeCoord = isShapeTypeRectangle(type) ?
     694           0 :                                getFudgedCoordinates(coord, lines, true, borderPosition) : coord;
     695             :       double x, y, height, width;
     696           0 :       x = strokeCoord.getXIn(m_width);
     697           0 :       y = strokeCoord.getYIn(m_height);
     698           0 :       height = strokeCoord.getHeightIn();
     699           0 :       width = strokeCoord.getWidthIn();
     700           0 :       graphicsProps.insert("draw:fill", "none");
     701           0 :       if (info.m_dash.is_initialized() && !info.m_dash.get().m_dots.empty())
     702             :       {
     703           0 :         const Dash &dash = info.m_dash.get();
     704           0 :         graphicsProps.insert("draw:stroke", "dash");
     705           0 :         graphicsProps.insert("draw:distance", dash.m_distance, WPX_INCH);
     706           0 :         switch (dash.m_dotStyle)
     707             :         {
     708             :         case ROUND_DOT:
     709           0 :           graphicsProps.insert("svg:stroke-linecap", "round");
     710           0 :           break;
     711             :         case RECT_DOT:
     712           0 :           graphicsProps.insert("svg:stroke-linecap", "rect");
     713           0 :           break;
     714             :         default:
     715           0 :           break;
     716             :         }
     717           0 :         for (unsigned i = 0; i < dash.m_dots.size(); ++i)
     718             :         {
     719           0 :           WPXString dots;
     720           0 :           dots.sprintf("draw:dots%d", i + 1);
     721           0 :           graphicsProps.insert(dots.cstr(), static_cast<int>(dash.m_dots[i].m_count));
     722           0 :           if (dash.m_dots[i].m_length.is_initialized())
     723             :           {
     724           0 :             WPXString length;
     725           0 :             length.sprintf("draw:dots%d-length", i + 1);
     726           0 :             graphicsProps.insert(length.cstr(), dash.m_dots[i].m_length.get(), WPX_INCH);
     727             :           }
     728           0 :         }
     729             :       }
     730             :       else
     731             :       {
     732           0 :         graphicsProps.insert("draw:stroke", "solid");
     733             :       }
     734           0 :       m_painter->setStyle(graphicsProps, graphicsPropsVector);
     735             :       writeCustomShape(type, graphicsProps, m_painter, x, y, height, width,
     736             :                        false, foldedTransform, lines,
     737             :                        boost::bind(
     738             :                          &libmspub::MSPUBCollector::getCalculationValue, this, info, _1, false, adjustValues
     739             :                        ),
     740           0 :                        m_paletteColors, info.getCustomShape());
     741             :     }
     742             :   }
     743           0 :   if (hasText)
     744             :   {
     745           0 :     const std::vector<TextParagraph> &text = maybeText.get();
     746           0 :     graphicsProps.insert("draw:fill", "none");
     747           0 :     Coordinate textCoord = isShapeTypeRectangle(type) ?
     748           0 :                            getFudgedCoordinates(coord, lines, false, borderPosition) : coord;
     749           0 :     m_painter->setStyle(graphicsProps, graphicsPropsVector);
     750           0 :     WPXPropertyList props;
     751           0 :     setRectCoordProps(textCoord, &props);
     752           0 :     double textRotation = thisTransform.getRotation();
     753           0 :     if (textRotation != 0)
     754             :     {
     755           0 :       props.insert("libwpg:rotate", textRotation * 180 / M_PI);
     756             :     }
     757           0 :     Margins margins = info.m_margins.get_value_or(Margins());
     758           0 :     props.insert("fo:padding-left", (double)margins.m_left / EMUS_IN_INCH);
     759           0 :     props.insert("fo:padding-top", (double)margins.m_top / EMUS_IN_INCH);
     760           0 :     props.insert("fo:padding-right", (double)margins.m_right / EMUS_IN_INCH);
     761           0 :     props.insert("fo:padding-bottom", (double)margins.m_bottom / EMUS_IN_INCH);
     762           0 :     if(info.m_verticalAlign.is_initialized())
     763             :     {
     764           0 :       switch (info.m_verticalAlign.get())
     765             :       {
     766             :       default:
     767             :       case TOP:
     768           0 :         props.insert("draw:textarea-vertical-align", "top");
     769           0 :         break;
     770             :       case MIDDLE:
     771           0 :         props.insert("draw:textarea-vertical-align", "middle");
     772           0 :         break;
     773             :       case BOTTOM:
     774           0 :         props.insert("draw:textarea-vertical-align", "bottom");
     775           0 :         break;
     776             :       }
     777             :     }
     778           0 :     m_painter->startTextObject(props, WPXPropertyListVector());
     779           0 :     for (unsigned i_lines = 0; i_lines < text.size(); ++i_lines)
     780             :     {
     781           0 :       WPXPropertyList paraProps = getParaStyleProps(text[i_lines].style, text[i_lines].style.m_defaultCharStyleIndex);
     782           0 :       m_painter->startTextLine(paraProps);
     783           0 :       for (unsigned i_spans = 0; i_spans < text[i_lines].spans.size(); ++i_spans)
     784             :       {
     785           0 :         WPXString textString;
     786           0 :         appendCharacters(textString, text[i_lines].spans[i_spans].chars,
     787           0 :                          m_encoding.get_value_or(UTF_16));
     788           0 :         WPXPropertyList charProps = getCharStyleProps(text[i_lines].spans[i_spans].style, text[i_lines].style.m_defaultCharStyleIndex);
     789           0 :         m_painter->startTextSpan(charProps);
     790           0 :         m_painter->insertText(textString);
     791           0 :         m_painter->endTextSpan();
     792           0 :       }
     793           0 :       m_painter->endTextLine();
     794           0 :     }
     795           0 :     m_painter->endTextObject();
     796             :   }
     797           0 :   if (makeLayer)
     798             :   {
     799           0 :     m_painter->endLayer();
     800             :   }
     801           0 :   return &no_op;
     802             : }
     803             : 
     804           0 : void libmspub::MSPUBCollector::setShapeLineBackColor(unsigned shapeSeqNum,
     805             :     ColorReference backColor)
     806             : {
     807           0 :   m_shapeInfosBySeqNum[shapeSeqNum].m_lineBackColor = backColor;
     808           0 : }
     809             : 
     810           0 : void libmspub::MSPUBCollector::writeImage(double x, double y,
     811             :     double height, double width, ImgType type, const WPXBinaryData &blob,
     812             :     boost::optional<Color> oneBitColor) const
     813             : {
     814           0 :   WPXPropertyList props;
     815           0 :   if (oneBitColor.is_initialized())
     816             :   {
     817           0 :     Color obc = oneBitColor.get();
     818           0 :     props.insert("draw:color-mode", "greyscale");
     819           0 :     props.insert("draw:red", static_cast<double>(obc.r) / 255.0, WPX_PERCENT);
     820           0 :     props.insert("draw:blue", static_cast<double>(obc.b) / 255.0, WPX_PERCENT);
     821           0 :     props.insert("draw:green", static_cast<double>(obc.g) / 255.0, WPX_PERCENT);
     822             :   }
     823           0 :   props.insert("svg:x", x);
     824           0 :   props.insert("svg:y", y);
     825           0 :   props.insert("svg:width", width);
     826           0 :   props.insert("svg:height", height);
     827           0 :   props.insert("libwpg:mime-type", mimeByImgType(type));
     828           0 :   m_painter->drawGraphicObject(props, blob);
     829           0 : }
     830             : 
     831           0 : double libmspub::MSPUBCollector::getSpecialValue(const ShapeInfo &info, const CustomShape &shape, int arg, const std::vector<int> &adjustValues) const
     832             : {
     833           0 :   if (PROP_ADJUST_VAL_FIRST <= arg && PROP_ADJUST_VAL_LAST >= arg)
     834             :   {
     835           0 :     unsigned adjustIndex = arg - PROP_ADJUST_VAL_FIRST;
     836           0 :     if (adjustIndex < adjustValues.size())
     837             :     {
     838           0 :       if ((shape.m_adjustShiftMask >> adjustIndex) & 0x1)
     839             :       {
     840           0 :         return adjustValues[adjustIndex] >> 16;
     841             :       }
     842           0 :       return adjustValues[adjustIndex];
     843             :     }
     844           0 :     return 0;
     845             :   }
     846           0 :   if (arg == ASPECT_RATIO)
     847             :   {
     848           0 :     const Coordinate &coord = info.m_coordinates.get_value_or(Coordinate());
     849           0 :     return (double)coord.getWidthIn() / coord.getHeightIn();
     850             :   }
     851           0 :   if (arg & OTHER_CALC_VAL)
     852             :   {
     853           0 :     return getCalculationValue(info, arg & 0xff, true, adjustValues);
     854             :   }
     855           0 :   switch (arg)
     856             :   {
     857             :   case PROP_GEO_LEFT:
     858           0 :     return 0;
     859             :   case PROP_GEO_TOP:
     860           0 :     return 0;
     861             :   case PROP_GEO_RIGHT:
     862           0 :     return shape.m_coordWidth;
     863             :   case PROP_GEO_BOTTOM:
     864           0 :     return shape.m_coordHeight;
     865             :   default:
     866           0 :     break;
     867             :   }
     868           0 :   return 0;
     869             : }
     870             : 
     871           0 : double libmspub::MSPUBCollector::getCalculationValue(const ShapeInfo &info, unsigned index, bool recursiveEntry, const std::vector<int> &adjustValues) const
     872             : {
     873           0 :   boost::shared_ptr<const CustomShape> p_shape = info.getCustomShape();
     874           0 :   if (! p_shape)
     875             :   {
     876           0 :     return 0;
     877             :   }
     878           0 :   const CustomShape &shape = *p_shape;
     879           0 :   if (index >= shape.m_numCalculations)
     880             :   {
     881           0 :     return 0;
     882             :   }
     883           0 :   if (! recursiveEntry)
     884             :   {
     885           0 :     m_calculationValuesSeen.clear();
     886           0 :     m_calculationValuesSeen.resize(shape.m_numCalculations);
     887             :   }
     888           0 :   if (m_calculationValuesSeen[index])
     889             :   {
     890             :     //recursion detected. The simplest way to avoid infinite recursion, at the "cost"
     891             :     // of making custom shape parsing not Turing-complete ;), is to ban recursion entirely.
     892           0 :     return 0;
     893             :   }
     894           0 :   m_calculationValuesSeen[index] = true;
     895             : 
     896           0 :   const Calculation &c = shape.mp_calculations[index];
     897           0 :   bool oneSpecial = (c.m_flags & 0x2000) != 0;
     898           0 :   bool twoSpecial = (c.m_flags & 0x4000) != 0;
     899           0 :   bool threeSpecial = (c.m_flags & 0x8000) != 0;
     900             : 
     901           0 :   double valOne = oneSpecial ? getSpecialValue(info, shape, c.m_argOne, adjustValues) : c.m_argOne;
     902           0 :   double valTwo = twoSpecial ? getSpecialValue(info, shape, c.m_argTwo, adjustValues) : c.m_argTwo;
     903           0 :   double valThree = threeSpecial ? getSpecialValue(info, shape, c.m_argThree, adjustValues) : c.m_argThree;
     904           0 :   m_calculationValuesSeen[index] = false;
     905           0 :   switch (c.m_flags & 0xFF)
     906             :   {
     907             :   case 0:
     908             :   case 14:
     909           0 :     return valOne + valTwo - valThree;
     910             :   case 1:
     911           0 :     return valOne * valTwo / (valThree == 0 ? 1 : valThree);
     912             :   case 2:
     913           0 :     return (valOne + valTwo) / 2;
     914             :   case 3:
     915           0 :     return fabs(valOne);
     916             :   case 4:
     917           0 :     return std::min(valOne, valTwo);
     918             :   case 5:
     919           0 :     return std::max(valOne, valTwo);
     920             :   case 6:
     921           0 :     return valOne ? valTwo : valThree;
     922             :   case 7:
     923           0 :     return sqrt(valOne * valTwo * valThree);
     924             :   case 8:
     925           0 :     return atan2(valTwo, valOne) / (M_PI / 180);
     926             :   case 9:
     927           0 :     return valOne * sin(valTwo * (M_PI / 180) );
     928             :   case 10:
     929           0 :     return valOne * cos(valTwo * (M_PI / 180) );
     930             :   case 11:
     931           0 :     return valOne * cos(atan2(valThree, valTwo));
     932             :   case 12:
     933           0 :     return valOne * sin(atan2(valThree, valTwo));
     934             :   case 13:
     935           0 :     return sqrt(valOne);
     936             :   case 15:
     937           0 :     return valThree * sqrt(1 - (valOne / valTwo) * (valOne / valTwo));
     938             :   case 16:
     939           0 :     return valOne * tan(valTwo);
     940             :   case 0x80:
     941           0 :     return sqrt(valThree * valThree - valOne * valOne);
     942             :   case 0x81:
     943           0 :     return (cos(valThree * (M_PI / 180)) * (valOne - 10800) + sin(valThree * (M_PI / 180)) * (valTwo - 10800)) + 10800;
     944             :   case 0x82:
     945           0 :     return -(sin(valThree * (M_PI / 180)) * (valOne - 10800) - cos(valThree * (M_PI / 180)) * (valTwo - 10800)) + 10800;
     946             :   default:
     947           0 :     return 0;
     948           0 :   }
     949             : }
     950             : 
     951           0 : libmspub::MSPUBCollector::~MSPUBCollector()
     952             : {
     953           0 : }
     954             : 
     955           0 : void libmspub::MSPUBCollector::setShapeRotation(unsigned seqNum, double rotation)
     956             : {
     957           0 :   m_shapeInfosBySeqNum[seqNum].m_rotation = rotation;
     958           0 : }
     959             : 
     960           0 : void libmspub::MSPUBCollector::setShapeFlip(unsigned seqNum, bool flipVertical, bool flipHorizontal)
     961             : {
     962           0 :   m_shapeInfosBySeqNum[seqNum].m_flips = std::pair<bool, bool>(flipVertical, flipHorizontal);
     963           0 : }
     964             : 
     965           0 : void libmspub::MSPUBCollector::setShapeType(unsigned seqNum, ShapeType type)
     966             : {
     967           0 :   m_shapeInfosBySeqNum[seqNum].m_type = type;
     968           0 : }
     969             : 
     970           0 : void libmspub::MSPUBCollector::setAdjustValue(unsigned seqNum, unsigned index, int adjust)
     971             : {
     972           0 :   m_shapeInfosBySeqNum[seqNum].m_adjustValuesByIndex[index] = adjust;
     973           0 : }
     974             : 
     975           0 : void libmspub::MSPUBCollector::addDefaultCharacterStyle(const CharacterStyle &st)
     976             : {
     977           0 :   m_defaultCharStyles.push_back(st);
     978           0 : }
     979             : 
     980           0 : void libmspub::MSPUBCollector::addDefaultParagraphStyle(const ParagraphStyle &st)
     981             : {
     982           0 :   m_defaultParaStyles.push_back(st);
     983           0 : }
     984             : 
     985           0 : bool libmspub::MSPUBCollector::addPage(unsigned seqNum)
     986             : {
     987           0 :   if (! (m_widthSet && m_heightSet) )
     988             :   {
     989           0 :     return false;
     990             :   }
     991             :   MSPUB_DEBUG_MSG(("Adding page of seqnum 0x%x\n", seqNum));
     992           0 :   m_pagesBySeqNum[seqNum] = PageInfo();
     993           0 :   return true;
     994             : }
     995             : 
     996           0 : void libmspub::MSPUBCollector::addTextShape(unsigned stringId, unsigned seqNum)
     997             : {
     998           0 :   m_shapeInfosBySeqNum[seqNum].m_textId = stringId;
     999           0 : }
    1000             : 
    1001           0 : void libmspub::MSPUBCollector::setShapeImgIndex(unsigned seqNum, unsigned index)
    1002             : {
    1003             :   MSPUB_DEBUG_MSG(("Setting image index of shape with seqnum 0x%x to 0x%x\n", seqNum, index));
    1004           0 :   m_shapeInfosBySeqNum[seqNum].m_imgIndex = index;
    1005           0 : }
    1006             : 
    1007           0 : void libmspub::MSPUBCollector::setShapeDash(unsigned seqNum, const Dash &dash)
    1008             : {
    1009           0 :   m_shapeInfosBySeqNum[seqNum].m_dash = dash;
    1010           0 : }
    1011             : 
    1012           0 : void libmspub::MSPUBCollector::setShapeFill(unsigned seqNum, boost::shared_ptr<Fill> fill, bool skipIfNotBg)
    1013             : {
    1014           0 :   m_shapeInfosBySeqNum[seqNum].m_fill = fill;
    1015           0 :   if (skipIfNotBg)
    1016             :   {
    1017           0 :     m_skipIfNotBgSeqNums.insert(seqNum);
    1018             :   }
    1019           0 : }
    1020             : 
    1021           0 : void libmspub::MSPUBCollector::setShapeCoordinatesInEmu(unsigned seqNum, int xs, int ys, int xe, int ye)
    1022             : {
    1023           0 :   m_shapeInfosBySeqNum[seqNum].m_coordinates = Coordinate(xs, ys, xe, ye);
    1024           0 : }
    1025             : 
    1026           0 : void libmspub::MSPUBCollector::addFont(std::vector<unsigned char> name)
    1027             : {
    1028           0 :   m_fonts.push_back(name);
    1029           0 : }
    1030             : 
    1031           0 : WPXPropertyList libmspub::MSPUBCollector::getParaStyleProps(const ParagraphStyle &style, boost::optional<unsigned> defaultParaStyleIndex) const
    1032             : {
    1033           0 :   ParagraphStyle _nothing;
    1034           0 :   const ParagraphStyle &defaultStyle = defaultParaStyleIndex.is_initialized() && defaultParaStyleIndex.get() < m_defaultParaStyles.size() ? m_defaultParaStyles[defaultParaStyleIndex.get()] : _nothing;
    1035           0 :   WPXPropertyList ret;
    1036             :   Alignment align = style.m_align.get_value_or(
    1037           0 :                       defaultStyle.m_align.get_value_or(LEFT));
    1038           0 :   switch (align)
    1039             :   {
    1040             :   case RIGHT:
    1041           0 :     ret.insert("fo:text-align", "right");
    1042           0 :     break;
    1043             :   case CENTER:
    1044           0 :     ret.insert("fo:text-align", "center");
    1045           0 :     break;
    1046             :   case JUSTIFY:
    1047           0 :     ret.insert("fo:text-align", "justify");
    1048           0 :     break;
    1049             :   case LEFT:
    1050             :   default:
    1051           0 :     ret.insert("fo:text-align", "left");
    1052           0 :     break;
    1053             :   }
    1054             :   LineSpacingInfo info = style.m_lineSpacing.get_value_or(
    1055           0 :                            defaultStyle.m_lineSpacing.get_value_or(LineSpacingInfo()));
    1056           0 :   LineSpacingType lineSpacingType = info.m_type;
    1057           0 :   double lineSpacing = info.m_amount;
    1058           0 :   if (!(lineSpacingType == LINE_SPACING_SP && lineSpacing == 1))
    1059             :   {
    1060           0 :     if (lineSpacingType == LINE_SPACING_SP)
    1061             :     {
    1062           0 :       ret.insert("fo:line-height", lineSpacing, WPX_PERCENT);
    1063             :     }
    1064           0 :     else if (lineSpacingType == LINE_SPACING_PT)
    1065             :     {
    1066           0 :       ret.insert("fo:line-height", lineSpacing, WPX_POINT);
    1067             :     }
    1068             :   }
    1069             :   unsigned spaceAfterEmu = style.m_spaceAfterEmu.get_value_or(
    1070           0 :                              defaultStyle.m_spaceAfterEmu.get_value_or(0));
    1071             :   unsigned spaceBeforeEmu = style.m_spaceBeforeEmu.get_value_or(
    1072           0 :                               defaultStyle.m_spaceBeforeEmu.get_value_or(0));
    1073             :   unsigned firstLineIndentEmu = style.m_firstLineIndentEmu.get_value_or(
    1074           0 :                                   defaultStyle.m_firstLineIndentEmu.get_value_or(0));
    1075             :   unsigned leftIndentEmu = style.m_leftIndentEmu.get_value_or(
    1076           0 :                              defaultStyle.m_leftIndentEmu.get_value_or(0));
    1077             :   unsigned rightIndentEmu = style.m_rightIndentEmu.get_value_or(
    1078           0 :                               defaultStyle.m_rightIndentEmu.get_value_or(0));
    1079           0 :   if (spaceAfterEmu != 0)
    1080             :   {
    1081           0 :     ret.insert("fo:margin-bottom", (double)spaceAfterEmu / EMUS_IN_INCH);
    1082             :   }
    1083           0 :   if (spaceBeforeEmu != 0)
    1084             :   {
    1085           0 :     ret.insert("fo:margin-top", (double)spaceBeforeEmu / EMUS_IN_INCH);
    1086             :   }
    1087           0 :   if (firstLineIndentEmu != 0)
    1088             :   {
    1089           0 :     ret.insert("fo:text-indent", (double)firstLineIndentEmu / EMUS_IN_INCH);
    1090             :   }
    1091           0 :   if (leftIndentEmu != 0)
    1092             :   {
    1093           0 :     ret.insert("fo:margin-left", (double)leftIndentEmu / EMUS_IN_INCH);
    1094             :   }
    1095           0 :   if (rightIndentEmu != 0)
    1096             :   {
    1097           0 :     ret.insert("fo:margin-right", (double)rightIndentEmu / EMUS_IN_INCH);
    1098             :   }
    1099           0 :   return ret;
    1100             : }
    1101             : 
    1102           0 : WPXPropertyList libmspub::MSPUBCollector::getCharStyleProps(const CharacterStyle &style, boost::optional<unsigned> defaultCharStyleIndex) const
    1103             : {
    1104           0 :   CharacterStyle _nothing = CharacterStyle(false, false, false);
    1105           0 :   const CharacterStyle &defaultCharStyle = defaultCharStyleIndex.is_initialized() && defaultCharStyleIndex.get() < m_defaultCharStyles.size() ? m_defaultCharStyles[defaultCharStyleIndex.get()] : _nothing;
    1106           0 :   WPXPropertyList ret;
    1107           0 :   if (style.italic ^ defaultCharStyle.italic)
    1108             :   {
    1109           0 :     ret.insert("fo:font-style", "italic");
    1110             :   }
    1111           0 :   if (style.bold ^ defaultCharStyle.bold)
    1112             :   {
    1113           0 :     ret.insert("fo:font-weight", "bold");
    1114             :   }
    1115           0 :   if (style.underline ^ defaultCharStyle.underline)
    1116             :   {
    1117           0 :     ret.insert("style:text-underline-type", "single");
    1118             :   }
    1119           0 :   if (style.textSizeInPt.is_initialized())
    1120             :   {
    1121           0 :     ret.insert("fo:font-size", style.textSizeInPt.get() / POINTS_IN_INCH);
    1122             :   }
    1123           0 :   else if (defaultCharStyle.textSizeInPt.is_initialized())
    1124             :   {
    1125           0 :     ret.insert("fo:font-size", defaultCharStyle.textSizeInPt.get()
    1126           0 :                / POINTS_IN_INCH);
    1127             :   }
    1128           0 :   if (style.colorIndex >= 0 && (size_t)style.colorIndex < m_textColors.size())
    1129             :   {
    1130           0 :     ret.insert("fo:color", getColorString(m_textColors[style.colorIndex].getFinalColor(m_paletteColors)));
    1131             :   }
    1132           0 :   else if (defaultCharStyle.colorIndex >= 0 && (size_t)defaultCharStyle.colorIndex < m_textColors.size())
    1133             :   {
    1134           0 :     ret.insert("fo:color", getColorString(m_textColors[defaultCharStyle.colorIndex].getFinalColor(m_paletteColors)));
    1135             :   }
    1136             :   else
    1137             :   {
    1138           0 :     ret.insert("fo:color", getColorString(Color(0, 0, 0)));  // default color is black
    1139             :   }
    1140           0 :   if (style.fontIndex.is_initialized() &&
    1141           0 :       style.fontIndex.get() < m_fonts.size())
    1142             :   {
    1143           0 :     WPXString str;
    1144           0 :     appendCharacters(str, m_fonts[style.fontIndex.get()],
    1145           0 :                      m_encoding.get_value_or(UTF_16));
    1146           0 :     ret.insert("style:font-name", str);
    1147             :   }
    1148           0 :   else if (defaultCharStyle.fontIndex.is_initialized() &&
    1149           0 :            defaultCharStyle.fontIndex.get() < m_fonts.size())
    1150             :   {
    1151           0 :     WPXString str;
    1152           0 :     appendCharacters(str, m_fonts[defaultCharStyle.fontIndex.get()],
    1153           0 :                      m_encoding.get_value_or(UTF_16));
    1154           0 :     ret.insert("style:font-name", str);
    1155             :   }
    1156           0 :   else if (!m_fonts.empty())
    1157             :   {
    1158           0 :     WPXString str;
    1159           0 :     appendCharacters(str, m_fonts[0],
    1160           0 :                      m_encoding.get_value_or(UTF_16));
    1161           0 :     ret.insert("style:font-name", str);
    1162             :   }
    1163           0 :   switch (style.superSubType)
    1164             :   {
    1165             :   case SUPERSCRIPT:
    1166           0 :     ret.insert("style:text-position", "50% 67%");
    1167           0 :     break;
    1168             :   case SUBSCRIPT:
    1169           0 :     ret.insert("style:text-position", "-50% 67%");
    1170           0 :     break;
    1171             :   default:
    1172           0 :     break;
    1173             :   }
    1174           0 :   return ret;
    1175             : }
    1176             : 
    1177           0 : WPXString libmspub::MSPUBCollector::getColorString(const Color &color)
    1178             : {
    1179           0 :   WPXString ret;
    1180           0 :   ret.sprintf("#%.2x%.2x%.2x",(unsigned char)color.r, (unsigned char)color.g, (unsigned char)color.b);
    1181             :   MSPUB_DEBUG_MSG(("String for r: 0x%x, g: 0x%x, b: 0x%x is %s\n", color.r, color.g, color.b, ret.cstr()));
    1182           0 :   return ret;
    1183             : }
    1184             : 
    1185           0 : void libmspub::MSPUBCollector::addBlackToPaletteIfNecessary()
    1186             : {
    1187           0 :   if (m_paletteColors.size() < 8)
    1188             :   {
    1189           0 :     m_paletteColors.insert(m_paletteColors.begin(), Color());
    1190             :   }
    1191           0 : }
    1192             : 
    1193           0 : void libmspub::MSPUBCollector::assignShapesToPages()
    1194             : {
    1195           0 :   for (unsigned i = 0; i < m_topLevelShapes.size(); ++i)
    1196             :   {
    1197           0 :     unsigned *ptr_pageSeqNum = getIfExists(m_pageSeqNumsByShapeSeqNum, m_topLevelShapes[i].getSeqNum());
    1198           0 :     m_topLevelShapes[i].setup(boost::bind(&libmspub::MSPUBCollector::setupShapeStructures, this, _1));
    1199           0 :     if (ptr_pageSeqNum)
    1200             :     {
    1201           0 :       PageInfo *ptr_page = getIfExists(m_pagesBySeqNum, *ptr_pageSeqNum);
    1202           0 :       if (ptr_page)
    1203             :       {
    1204           0 :         ptr_page->m_shapeGroupsOrdered.push_back(&m_topLevelShapes[i]);
    1205             :       }
    1206             :     }
    1207             :   }
    1208           0 : }
    1209             : 
    1210           0 : boost::optional<unsigned> libmspub::MSPUBCollector::getMasterPageSeqNum(unsigned pageSeqNum) const
    1211             : {
    1212           0 :   boost::optional<unsigned> toReturn;
    1213           0 :   const unsigned *ptr_masterSeqNum = getIfExists_const(m_masterPagesByPageSeqNum, pageSeqNum);
    1214           0 :   if (ptr_masterSeqNum && m_masterPages.find(*ptr_masterSeqNum) != m_masterPages.end())
    1215             :   {
    1216           0 :     return *ptr_masterSeqNum;
    1217             :   }
    1218           0 :   return toReturn;
    1219             : }
    1220             : 
    1221           0 : void libmspub::MSPUBCollector::writePage(unsigned pageSeqNum) const
    1222             : {
    1223           0 :   const PageInfo &pageInfo = m_pagesBySeqNum.find(pageSeqNum)->second;
    1224           0 :   WPXPropertyList pageProps;
    1225           0 :   if (m_widthSet)
    1226             :   {
    1227           0 :     pageProps.insert("svg:width", m_width);
    1228             :   }
    1229           0 :   if (m_heightSet)
    1230             :   {
    1231           0 :     pageProps.insert("svg:height", m_height);
    1232             :   }
    1233           0 :   const std::vector<ShapeGroupElement *> &shapeGroupsOrdered = pageInfo.m_shapeGroupsOrdered;
    1234           0 :   if (!shapeGroupsOrdered.empty())
    1235             :   {
    1236           0 :     m_painter->startGraphics(pageProps);
    1237           0 :     boost::optional<unsigned> masterSeqNum = getMasterPageSeqNum(pageSeqNum);
    1238           0 :     bool hasMaster = masterSeqNum.is_initialized();
    1239           0 :     if (hasMaster)
    1240             :     {
    1241           0 :       writePageBackground(masterSeqNum.get());
    1242             :     }
    1243           0 :     writePageBackground(pageSeqNum);
    1244           0 :     if (hasMaster)
    1245             :     {
    1246           0 :       writePageShapes(masterSeqNum.get());
    1247             :     }
    1248           0 :     writePageShapes(pageSeqNum);
    1249           0 :     m_painter->endGraphics();
    1250           0 :   }
    1251           0 : }
    1252             : 
    1253           0 : void libmspub::MSPUBCollector::writePageShapes(unsigned pageSeqNum) const
    1254             : {
    1255           0 :   const PageInfo &pageInfo = m_pagesBySeqNum.find(pageSeqNum)->second;
    1256           0 :   const std::vector<ShapeGroupElement *> &shapeGroupsOrdered = pageInfo.m_shapeGroupsOrdered;
    1257           0 :   for (unsigned i = 0; i < shapeGroupsOrdered.size(); ++i)
    1258             :   {
    1259           0 :     ShapeGroupElement *shapeGroup = shapeGroupsOrdered[i];
    1260           0 :     shapeGroup->visit(boost::bind(&libmspub::MSPUBCollector::paintShape, this, _1, _2, _3, _4, _5));
    1261             :   }
    1262           0 : }
    1263             : 
    1264           0 : void libmspub::MSPUBCollector::writePageBackground(unsigned pageSeqNum) const
    1265             : {
    1266           0 :   const unsigned *ptr_fillSeqNum = getIfExists_const(m_bgShapeSeqNumsByPageSeqNum, pageSeqNum);
    1267           0 :   if (ptr_fillSeqNum)
    1268             :   {
    1269           0 :     boost::shared_ptr<const Fill> ptr_fill;
    1270           0 :     const ShapeInfo *ptr_info = getIfExists_const(m_shapeInfosBySeqNum, *ptr_fillSeqNum);
    1271           0 :     if (ptr_info)
    1272             :     {
    1273           0 :       ptr_fill = ptr_info->m_fill;
    1274             :     }
    1275           0 :     if (ptr_fill)
    1276             :     {
    1277           0 :       ShapeInfo bg;
    1278           0 :       bg.m_type = RECTANGLE;
    1279           0 :       Coordinate wholePage(-m_width/2 * EMUS_IN_INCH, -m_height/2 * EMUS_IN_INCH, m_width/2 * EMUS_IN_INCH, m_height/2 * EMUS_IN_INCH);
    1280           0 :       bg.m_coordinates = wholePage;
    1281           0 :       bg.m_pageSeqNum = pageSeqNum;
    1282           0 :       bg.m_fill = ptr_fill;
    1283           0 :       paintShape(bg, Coordinate(), VectorTransformation2D(), false, VectorTransformation2D());
    1284           0 :     }
    1285             :   }
    1286           0 : }
    1287             : 
    1288           0 : bool libmspub::MSPUBCollector::pageIsMaster(unsigned pageSeqNum) const
    1289             : {
    1290           0 :   return m_masterPages.find(pageSeqNum) != m_masterPages.end();
    1291             : }
    1292             : 
    1293           0 : bool libmspub::MSPUBCollector::go()
    1294             : {
    1295           0 :   addBlackToPaletteIfNecessary();
    1296           0 :   assignShapesToPages();
    1297           0 :   if (m_pageSeqNumsOrdered.empty())
    1298             :   {
    1299           0 :     for (std::map<unsigned, PageInfo>::const_iterator i = m_pagesBySeqNum.begin();
    1300           0 :          i != m_pagesBySeqNum.end(); ++i)
    1301             :     {
    1302           0 :       if (!pageIsMaster(i->first))
    1303             :       {
    1304           0 :         writePage(i->first);
    1305             :       }
    1306             :     }
    1307             :   }
    1308             :   else
    1309             :   {
    1310           0 :     for (unsigned i = 0; i < m_pageSeqNumsOrdered.size(); ++i)
    1311             :     {
    1312             :       std::map<unsigned, PageInfo>::const_iterator iter =
    1313           0 :         m_pagesBySeqNum.find(m_pageSeqNumsOrdered[i]);
    1314           0 :       if (iter != m_pagesBySeqNum.end() && !pageIsMaster(iter->first))
    1315             :       {
    1316           0 :         writePage(iter->first);
    1317             :       }
    1318             :     }
    1319             :   }
    1320           0 :   return true;
    1321             : }
    1322             : 
    1323             : 
    1324           0 : bool libmspub::MSPUBCollector::addTextString(const std::vector<TextParagraph> &str, unsigned id)
    1325             : {
    1326             :   MSPUB_DEBUG_MSG(("addTextString, id: 0x%x\n", id));
    1327           0 :   m_textStringsById[id] = str;
    1328           0 :   return true; //FIXME: Warn if the string already existed in the map.
    1329             : }
    1330             : 
    1331           0 : void libmspub::MSPUBCollector::setWidthInEmu(unsigned long widthInEmu)
    1332             : {
    1333             :   //FIXME: Warn if this is called twice
    1334           0 :   m_width = ((double)widthInEmu) / EMUS_IN_INCH;
    1335           0 :   m_widthSet = true;
    1336           0 : }
    1337             : 
    1338           0 : void libmspub::MSPUBCollector::setHeightInEmu(unsigned long heightInEmu)
    1339             : {
    1340             :   //FIXME: Warn if this is called twice
    1341           0 :   m_height = ((double)heightInEmu) / EMUS_IN_INCH;
    1342           0 :   m_heightSet = true;
    1343           0 : }
    1344             : 
    1345           0 : bool libmspub::MSPUBCollector::addImage(unsigned index, ImgType type, WPXBinaryData img)
    1346             : {
    1347             :   MSPUB_DEBUG_MSG(("Image at index %d and of type 0x%x added.\n", index, type));
    1348           0 :   while (m_images.size() < index)
    1349             :   {
    1350           0 :     m_images.push_back(std::pair<ImgType, WPXBinaryData>(UNKNOWN, WPXBinaryData()));
    1351             :   }
    1352           0 :   m_images[index - 1] = std::pair<ImgType, WPXBinaryData>(type, img);
    1353           0 :   return true;
    1354             : }
    1355             : 
    1356           0 : WPXBinaryData *libmspub::MSPUBCollector::addBorderImage(ImgType type,
    1357             :     unsigned borderArtIndex)
    1358             : {
    1359           0 :   while (borderArtIndex >= m_borderImages.size())
    1360             :   {
    1361           0 :     m_borderImages.push_back(BorderArtInfo());
    1362             :   }
    1363           0 :   m_borderImages[borderArtIndex].m_images.push_back(BorderImgInfo(type));
    1364           0 :   return &(m_borderImages[borderArtIndex].m_images.back().m_imgBlob);
    1365             : }
    1366             : 
    1367           0 : void libmspub::MSPUBCollector::setBorderImageOffset(unsigned index, unsigned offset)
    1368             : {
    1369           0 :   while (index >= m_borderImages.size())
    1370             :   {
    1371           0 :     m_borderImages.push_back(BorderArtInfo());
    1372             :   }
    1373           0 :   BorderArtInfo &bai = m_borderImages[index];
    1374           0 :   bai.m_offsets.push_back(offset);
    1375           0 :   bool added = false;
    1376           0 :   for (std::vector<unsigned>::iterator i = bai.m_offsetsOrdered.begin();
    1377           0 :        i != bai.m_offsetsOrdered.end(); ++i)
    1378             :   {
    1379           0 :     if (*i >= offset)
    1380             :     {
    1381           0 :       bai.m_offsetsOrdered.insert(i, offset);
    1382           0 :       added = true;
    1383           0 :       break;
    1384             :     }
    1385             :   }
    1386           0 :   if (!added)
    1387             :   {
    1388           0 :     bai.m_offsetsOrdered.push_back(offset);
    1389             :   }
    1390           0 : }
    1391             : 
    1392           0 : void libmspub::MSPUBCollector::setShapePage(unsigned seqNum, unsigned pageSeqNum)
    1393             : {
    1394           0 :   m_shapeInfosBySeqNum[seqNum].m_pageSeqNum = pageSeqNum;
    1395           0 :   m_pageSeqNumsByShapeSeqNum[seqNum] = pageSeqNum;
    1396           0 : }
    1397             : 
    1398           0 : void libmspub::MSPUBCollector::addTextColor(ColorReference c)
    1399             : {
    1400           0 :   m_textColors.push_back(c);
    1401           0 : }
    1402             : 
    1403           0 : void libmspub::MSPUBCollector::designateMasterPage(unsigned seqNum)
    1404             : {
    1405           0 :   m_masterPages.insert(seqNum);
    1406           0 : }
    1407             : 
    1408           0 : void libmspub::MSPUBCollector::setMasterPage(unsigned seqNum, unsigned masterPageSeqNum)
    1409             : {
    1410           0 :   m_masterPagesByPageSeqNum[seqNum] = masterPageSeqNum;
    1411           0 : }
    1412             : 
    1413             : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */

Generated by: LCOV version 1.10