|
rpm-build |
9243a4 |
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
* This file is part of the libmspub project.
|
|
rpm-build |
9243a4 |
*
|
|
rpm-build |
9243a4 |
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
rpm-build |
9243a4 |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
rpm-build |
9243a4 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
#include "MSPUBParser2k.h"
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
#include <algorithm>
|
|
rpm-build |
9243a4 |
#include <utility>
|
|
rpm-build |
9243a4 |
#include <memory>
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
#include <librevenge-stream/librevenge-stream.h>
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
#include "ColorReference.h"
|
|
rpm-build |
9243a4 |
#include "Fill.h"
|
|
rpm-build |
9243a4 |
#include "Line.h"
|
|
rpm-build |
9243a4 |
#include "MSPUBCollector.h"
|
|
rpm-build |
9243a4 |
#include "ShapeType.h"
|
|
rpm-build |
9243a4 |
#include "libmspub_utils.h"
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
namespace libmspub
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
namespace
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
class ChunkNestingGuard
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
public:
|
|
rpm-build |
9243a4 |
ChunkNestingGuard(std::deque<unsigned> &chunks, const unsigned seqNum)
|
|
rpm-build |
9243a4 |
: m_chunks(chunks)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_chunks.push_front(seqNum);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
~ChunkNestingGuard()
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_chunks.pop_front();
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
private:
|
|
rpm-build |
9243a4 |
std::deque<unsigned> &m_chunks;
|
|
rpm-build |
9243a4 |
};
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
MSPUBParser2k::MSPUBParser2k(librevenge::RVNGInputStream *input, MSPUBCollector *collector)
|
|
rpm-build |
9243a4 |
: MSPUBParser(input, collector),
|
|
rpm-build |
9243a4 |
m_imageDataChunkIndices(),
|
|
rpm-build |
9243a4 |
m_quillColorEntries(),
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById(),
|
|
rpm-build |
9243a4 |
m_chunksBeingRead()
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getColorIndexByQuillEntry(unsigned entry)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
unsigned translation = translate2kColorReference(entry);
|
|
rpm-build |
9243a4 |
std::vector<unsigned>::const_iterator i_entry = std::find(m_quillColorEntries.begin(), m_quillColorEntries.end(), translation);
|
|
rpm-build |
9243a4 |
if (i_entry == m_quillColorEntries.end())
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_quillColorEntries.push_back(translation);
|
|
rpm-build |
9243a4 |
m_collector->addTextColor(ColorReference(translation));
|
|
rpm-build |
9243a4 |
return m_quillColorEntries.size() - 1;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
return i_entry - m_quillColorEntries.begin();
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
MSPUBParser2k::~MSPUBParser2k()
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
// Takes a line width specifier in Pub2k format and translates it into quarter points
|
|
rpm-build |
9243a4 |
unsigned short translateLineWidth(unsigned char lineWidth)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (lineWidth == 0x81)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (lineWidth > 0x81)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return ((lineWidth - 0x81) / 3) * 4 + ((lineWidth - 0x81) % 3) + 1;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return lineWidth * 4;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
Color MSPUBParser2k::getColorBy2kHex(unsigned hex)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
switch ((hex >> 24) & 0xFF)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0x80:
|
|
rpm-build |
9243a4 |
case 0x00:
|
|
rpm-build |
9243a4 |
return getColorBy2kIndex(hex & 0xFF);
|
|
rpm-build |
9243a4 |
case 0x90:
|
|
rpm-build |
9243a4 |
case 0x20:
|
|
rpm-build |
9243a4 |
return Color(hex & 0xFF, (hex >> 8) & 0xFF, (hex >> 16) & 0xFF);
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
return Color();
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
Color MSPUBParser2k::getColorBy2kIndex(unsigned char index)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
switch (index)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0x00:
|
|
rpm-build |
9243a4 |
return Color(0, 0, 0);
|
|
rpm-build |
9243a4 |
case 0x01:
|
|
rpm-build |
9243a4 |
return Color(0xff, 0xff, 0xff);
|
|
rpm-build |
9243a4 |
case 0x02:
|
|
rpm-build |
9243a4 |
return Color(0xff, 0, 0);
|
|
rpm-build |
9243a4 |
case 0x03:
|
|
rpm-build |
9243a4 |
return Color(0, 0xff, 0);
|
|
rpm-build |
9243a4 |
case 0x04:
|
|
rpm-build |
9243a4 |
return Color(0, 0, 0xff);
|
|
rpm-build |
9243a4 |
case 0x05:
|
|
rpm-build |
9243a4 |
return Color(0xff, 0xff, 0);
|
|
rpm-build |
9243a4 |
case 0x06:
|
|
rpm-build |
9243a4 |
return Color(0, 0xff, 0xff);
|
|
rpm-build |
9243a4 |
case 0x07:
|
|
rpm-build |
9243a4 |
return Color(0xff, 0, 0xff);
|
|
rpm-build |
9243a4 |
case 0x08:
|
|
rpm-build |
9243a4 |
return Color(128, 128, 128);
|
|
rpm-build |
9243a4 |
case 0x09:
|
|
rpm-build |
9243a4 |
return Color(192, 192, 192);
|
|
rpm-build |
9243a4 |
case 0x0A:
|
|
rpm-build |
9243a4 |
return Color(128, 0, 0);
|
|
rpm-build |
9243a4 |
case 0x0B:
|
|
rpm-build |
9243a4 |
return Color(0, 128, 0);
|
|
rpm-build |
9243a4 |
case 0x0C:
|
|
rpm-build |
9243a4 |
return Color(0, 0, 128);
|
|
rpm-build |
9243a4 |
case 0x0D:
|
|
rpm-build |
9243a4 |
return Color(128, 128, 0);
|
|
rpm-build |
9243a4 |
case 0x0E:
|
|
rpm-build |
9243a4 |
return Color(0, 128, 128);
|
|
rpm-build |
9243a4 |
case 0x0F:
|
|
rpm-build |
9243a4 |
return Color(128, 0, 128);
|
|
rpm-build |
9243a4 |
case 0x10:
|
|
rpm-build |
9243a4 |
return Color(255, 153, 51);
|
|
rpm-build |
9243a4 |
case 0x11:
|
|
rpm-build |
9243a4 |
return Color(51, 0, 51);
|
|
rpm-build |
9243a4 |
case 0x12:
|
|
rpm-build |
9243a4 |
return Color(0, 0, 153);
|
|
rpm-build |
9243a4 |
case 0x13:
|
|
rpm-build |
9243a4 |
return Color(0, 153, 0);
|
|
rpm-build |
9243a4 |
case 0x14:
|
|
rpm-build |
9243a4 |
return Color(153, 153, 0);
|
|
rpm-build |
9243a4 |
case 0x15:
|
|
rpm-build |
9243a4 |
return Color(204, 102, 0);
|
|
rpm-build |
9243a4 |
case 0x16:
|
|
rpm-build |
9243a4 |
return Color(153, 0, 0);
|
|
rpm-build |
9243a4 |
case 0x17:
|
|
rpm-build |
9243a4 |
return Color(204, 153, 204);
|
|
rpm-build |
9243a4 |
case 0x18:
|
|
rpm-build |
9243a4 |
return Color(102, 102, 255);
|
|
rpm-build |
9243a4 |
case 0x19:
|
|
rpm-build |
9243a4 |
return Color(102, 255, 102);
|
|
rpm-build |
9243a4 |
case 0x1A:
|
|
rpm-build |
9243a4 |
return Color(255, 255, 153);
|
|
rpm-build |
9243a4 |
case 0x1B:
|
|
rpm-build |
9243a4 |
return Color(255, 204, 153);
|
|
rpm-build |
9243a4 |
case 0x1C:
|
|
rpm-build |
9243a4 |
return Color(255, 102, 102);
|
|
rpm-build |
9243a4 |
case 0x1D:
|
|
rpm-build |
9243a4 |
return Color(255, 153, 0);
|
|
rpm-build |
9243a4 |
case 0x1E:
|
|
rpm-build |
9243a4 |
return Color(0, 102, 255);
|
|
rpm-build |
9243a4 |
case 0x1F:
|
|
rpm-build |
9243a4 |
return Color(255, 204, 0);
|
|
rpm-build |
9243a4 |
case 0x20:
|
|
rpm-build |
9243a4 |
return Color(153, 0, 51);
|
|
rpm-build |
9243a4 |
case 0x21:
|
|
rpm-build |
9243a4 |
return Color(102, 51, 0);
|
|
rpm-build |
9243a4 |
case 0x22:
|
|
rpm-build |
9243a4 |
return Color(66, 66, 66);
|
|
rpm-build |
9243a4 |
case 0x23:
|
|
rpm-build |
9243a4 |
return Color(255, 153, 102);
|
|
rpm-build |
9243a4 |
case 0x24:
|
|
rpm-build |
9243a4 |
return Color(153, 51, 0);
|
|
rpm-build |
9243a4 |
case 0x25:
|
|
rpm-build |
9243a4 |
return Color(255, 102, 0);
|
|
rpm-build |
9243a4 |
case 0x26:
|
|
rpm-build |
9243a4 |
return Color(51, 51, 0);
|
|
rpm-build |
9243a4 |
case 0x27:
|
|
rpm-build |
9243a4 |
return Color(153, 204, 0);
|
|
rpm-build |
9243a4 |
case 0x28:
|
|
rpm-build |
9243a4 |
return Color(255, 255, 153);
|
|
rpm-build |
9243a4 |
case 0x29:
|
|
rpm-build |
9243a4 |
return Color(0, 51, 0);
|
|
rpm-build |
9243a4 |
case 0x2A:
|
|
rpm-build |
9243a4 |
return Color(51, 153, 102);
|
|
rpm-build |
9243a4 |
case 0x2B:
|
|
rpm-build |
9243a4 |
return Color(204, 255, 204);
|
|
rpm-build |
9243a4 |
case 0x2C:
|
|
rpm-build |
9243a4 |
return Color(0, 51, 102);
|
|
rpm-build |
9243a4 |
case 0x2D:
|
|
rpm-build |
9243a4 |
return Color(51, 204, 204);
|
|
rpm-build |
9243a4 |
case 0x2E:
|
|
rpm-build |
9243a4 |
return Color(204, 255, 255);
|
|
rpm-build |
9243a4 |
case 0x2F:
|
|
rpm-build |
9243a4 |
return Color(51, 102, 255);
|
|
rpm-build |
9243a4 |
case 0x30:
|
|
rpm-build |
9243a4 |
return Color(0, 204, 255);
|
|
rpm-build |
9243a4 |
case 0x31:
|
|
rpm-build |
9243a4 |
return Color(153, 204, 255);
|
|
rpm-build |
9243a4 |
case 0x32:
|
|
rpm-build |
9243a4 |
return Color(51, 51, 153);
|
|
rpm-build |
9243a4 |
case 0x33:
|
|
rpm-build |
9243a4 |
return Color(102, 102, 153);
|
|
rpm-build |
9243a4 |
case 0x34:
|
|
rpm-build |
9243a4 |
return Color(153, 51, 102);
|
|
rpm-build |
9243a4 |
case 0x35:
|
|
rpm-build |
9243a4 |
return Color(204, 153, 255);
|
|
rpm-build |
9243a4 |
case 0x36:
|
|
rpm-build |
9243a4 |
return Color(51, 51, 51);
|
|
rpm-build |
9243a4 |
case 0x37:
|
|
rpm-build |
9243a4 |
return Color(150, 150, 150);
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
return Color();
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
// takes a color reference in 2k format and translates it into 2k2 format that collector understands.
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::translate2kColorReference(unsigned ref2k)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
switch ((ref2k >> 24) & 0xFF)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0xC0: //index into user palette
|
|
rpm-build |
9243a4 |
case 0xE0:
|
|
rpm-build |
9243a4 |
return (ref2k & 0xFF) | (0x08 << 24);
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
Color c = getColorBy2kHex(ref2k);
|
|
rpm-build |
9243a4 |
return (c.r) | (c.g << 8) | (c.b << 16);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
//FIXME: Valek found different values; what does this depend on?
|
|
rpm-build |
9243a4 |
ShapeType MSPUBParser2k::getShapeType(unsigned char shapeSpecifier)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
switch (shapeSpecifier)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0x1:
|
|
rpm-build |
9243a4 |
return RIGHT_TRIANGLE;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x2:
|
|
rpm-build |
9243a4 |
return GENERAL_TRIANGLE;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x3:
|
|
rpm-build |
9243a4 |
return UP_ARROW;
|
|
rpm-build |
9243a4 |
case 0x4:
|
|
rpm-build |
9243a4 |
return STAR;
|
|
rpm-build |
9243a4 |
case 0x5:
|
|
rpm-build |
9243a4 |
return HEART;
|
|
rpm-build |
9243a4 |
case 0x6:
|
|
rpm-build |
9243a4 |
return ISOCELES_TRIANGLE;
|
|
rpm-build |
9243a4 |
case 0x7:
|
|
rpm-build |
9243a4 |
return PARALLELOGRAM;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x8:
|
|
rpm-build |
9243a4 |
return TILTED_TRAPEZOID;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x9:
|
|
rpm-build |
9243a4 |
return UP_DOWN_ARROW;
|
|
rpm-build |
9243a4 |
case 0xA:
|
|
rpm-build |
9243a4 |
return SEAL_16;
|
|
rpm-build |
9243a4 |
case 0xB:
|
|
rpm-build |
9243a4 |
return WAVE;
|
|
rpm-build |
9243a4 |
case 0xC:
|
|
rpm-build |
9243a4 |
return DIAMOND;
|
|
rpm-build |
9243a4 |
case 0xD:
|
|
rpm-build |
9243a4 |
return TRAPEZOID;
|
|
rpm-build |
9243a4 |
case 0xE:
|
|
rpm-build |
9243a4 |
return CHEVRON;
|
|
rpm-build |
9243a4 |
case 0xF:
|
|
rpm-build |
9243a4 |
return BENT_ARROW;
|
|
rpm-build |
9243a4 |
case 0x10:
|
|
rpm-build |
9243a4 |
return SEAL_24;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x11:
|
|
rpm-build |
9243a4 |
return PIE;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x12:
|
|
rpm-build |
9243a4 |
return PENTAGON;
|
|
rpm-build |
9243a4 |
case 0x13:
|
|
rpm-build |
9243a4 |
return HOME_PLATE;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x14:
|
|
rpm-build |
9243a4 |
return NOTCHED_TRIANGLE;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x15:
|
|
rpm-build |
9243a4 |
return U_TURN_ARROW;
|
|
rpm-build |
9243a4 |
case 0x16:
|
|
rpm-build |
9243a4 |
return IRREGULAR_SEAL_1;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x17:
|
|
rpm-build |
9243a4 |
return CHORD;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x18:
|
|
rpm-build |
9243a4 |
return HEXAGON;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x19:
|
|
rpm-build |
9243a4 |
return NOTCHED_RECTANGLE;
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x1A:
|
|
rpm-build |
9243a4 |
return W_SHAPE; //This is a bizarre shape; the number of vertices depends on one of the adjust values.
|
|
rpm-build |
9243a4 |
//We need to refactor our escher shape drawing routines before we can handle it.
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x1B:
|
|
rpm-build |
9243a4 |
return ROUND_RECT_CALLOUT_2K; //This is not quite the same as the round rect. found in 2k2 and above.
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x1C:
|
|
rpm-build |
9243a4 |
return IRREGULAR_SEAL_2;
|
|
rpm-build |
9243a4 |
case 0x1D:
|
|
rpm-build |
9243a4 |
return BLOCK_ARC;
|
|
rpm-build |
9243a4 |
case 0x1E:
|
|
rpm-build |
9243a4 |
return OCTAGON;
|
|
rpm-build |
9243a4 |
case 0x1F:
|
|
rpm-build |
9243a4 |
return PLUS;
|
|
rpm-build |
9243a4 |
case 0x20:
|
|
rpm-build |
9243a4 |
return CUBE;
|
|
rpm-build |
9243a4 |
/*
|
|
rpm-build |
9243a4 |
case 0x21:
|
|
rpm-build |
9243a4 |
return OVAL_CALLOUT_2K; //Not sure yet if this is the same as the 2k2 one.
|
|
rpm-build |
9243a4 |
*/
|
|
rpm-build |
9243a4 |
case 0x22:
|
|
rpm-build |
9243a4 |
return LIGHTNING_BOLT;
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
return UNKNOWN_SHAPE;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseContentsTextIfNecessary(librevenge::RVNGInputStream *)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
bool MSPUBParser2k::parseContents(librevenge::RVNGInputStream *input)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
parseContentsTextIfNecessary(input);
|
|
rpm-build |
9243a4 |
input->seek(0x16, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned trailerOffset = readU32(input);
|
|
rpm-build |
9243a4 |
input->seek(trailerOffset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned numBlocks = readU16(input);
|
|
rpm-build |
9243a4 |
unsigned chunkOffset = 0;
|
|
rpm-build |
9243a4 |
for (unsigned i = 0; i < numBlocks; ++i)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(input->tell() + 2, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned short id = readU16(input);
|
|
rpm-build |
9243a4 |
unsigned short parent = readU16(input);
|
|
rpm-build |
9243a4 |
chunkOffset = readU32(input);
|
|
rpm-build |
9243a4 |
if (m_contentChunks.size() > 0)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_contentChunks.back().end = chunkOffset;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
unsigned offset = input->tell();
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned short typeMarker = readU16(input);
|
|
rpm-build |
9243a4 |
input->seek(offset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
switch (typeMarker)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0x0014:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found page chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(PAGE, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_pageChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x0015:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found document chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(DOCUMENT, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_documentChunkIndex = unsigned(m_contentChunks.size() - 1);
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x0002:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found image_2k chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(IMAGE_2K, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_shapeChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x0021:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found image_2k_data chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(IMAGE_2K_DATA, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_imageDataChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x0000:
|
|
rpm-build |
9243a4 |
case 0x0004:
|
|
rpm-build |
9243a4 |
case 0x0005:
|
|
rpm-build |
9243a4 |
case 0x0006:
|
|
rpm-build |
9243a4 |
case 0x0007:
|
|
rpm-build |
9243a4 |
case 0x0008:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found shape chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(SHAPE, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_shapeChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x0047:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found palette chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(PALETTE, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_paletteChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
case 0x000F:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found group chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(GROUP, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_shapeChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Found unknown chunk of id 0x%x and parent 0x%x\n", id, parent));
|
|
rpm-build |
9243a4 |
m_contentChunks.push_back(ContentChunkReference(UNKNOWN_CHUNK, chunkOffset, 0, id, parent));
|
|
rpm-build |
9243a4 |
m_unknownChunkIndices.push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
m_chunkChildIndicesById[parent].push_back(unsigned(m_contentChunks.size() - 1));
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (m_contentChunks.size() > 0)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_contentChunks.back().end = chunkOffset;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
if (!parseDocument(input))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("No document chunk found.\n"));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
for (unsigned int paletteChunkIndex : m_paletteChunkIndices)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
const ContentChunkReference &chunk = m_contentChunks.at(paletteChunkIndex);
|
|
rpm-build |
9243a4 |
input->seek(chunk.offset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
input->seek(0xA0, librevenge::RVNG_SEEK_CUR);
|
|
rpm-build |
9243a4 |
for (unsigned j = 0; j < 8; ++j)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
unsigned hex = readU32(input);
|
|
rpm-build |
9243a4 |
Color color = getColorBy2kHex(hex);
|
|
rpm-build |
9243a4 |
m_collector->addPaletteColor(color);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
for (unsigned int imageDataChunkIndex : m_imageDataChunkIndices)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
const ContentChunkReference &chunk = m_contentChunks.at(imageDataChunkIndex);
|
|
rpm-build |
9243a4 |
input->seek(chunk.offset + 4, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned toRead = readU32(input);
|
|
rpm-build |
9243a4 |
librevenge::RVNGBinaryData img;
|
|
rpm-build |
9243a4 |
while (toRead > 0 && stillReading(input, (unsigned long)-1))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
unsigned long howManyRead = 0;
|
|
rpm-build |
9243a4 |
const unsigned char *buf = input->read(toRead, howManyRead);
|
|
rpm-build |
9243a4 |
img.append(buf, howManyRead);
|
|
rpm-build |
9243a4 |
toRead -= howManyRead;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
m_collector->addImage(++m_lastAddedImage, WMF, img);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
for (unsigned int shapeChunkIndex : m_shapeChunkIndices)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
parse2kShapeChunk(m_contentChunks.at(shapeChunkIndex), input);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
return true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
bool MSPUBParser2k::parseDocument(librevenge::RVNGInputStream *input)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (bool(m_documentChunkIndex))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(m_contentChunks[m_documentChunkIndex.get()].offset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
input->seek(0x14, librevenge::RVNG_SEEK_CUR);
|
|
rpm-build |
9243a4 |
unsigned width = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned height = readU32(input);
|
|
rpm-build |
9243a4 |
m_collector->setWidthInEmu(width);
|
|
rpm-build |
9243a4 |
m_collector->setHeightInEmu(height);
|
|
rpm-build |
9243a4 |
return true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeRotation(librevenge::RVNGInputStream *input, bool isGroup, bool isLine,
|
|
rpm-build |
9243a4 |
unsigned seqNum, unsigned chunkOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + 4, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
// shape transforms are NOT compounded with group transforms. They are equal to what they would be
|
|
rpm-build |
9243a4 |
// if the shape were not part of a group at all. This is different from how MSPUBCollector handles rotations;
|
|
rpm-build |
9243a4 |
// we work around the issue by simply not setting the rotation of any group, thereby letting it default to zero.
|
|
rpm-build |
9243a4 |
//
|
|
rpm-build |
9243a4 |
// Furthermore, line rotations are redundant and need to be treated as zero.
|
|
rpm-build |
9243a4 |
unsigned short counterRotationInDegreeTenths = readU16(input);
|
|
rpm-build |
9243a4 |
if (!isGroup && !isLine)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeRotation(seqNum, 360. - double(counterRotationInDegreeTenths) / 10);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
bool MSPUBParser2k::parse2kShapeChunk(const ContentChunkReference &chunk, librevenge::RVNGInputStream *input,
|
|
rpm-build |
9243a4 |
boost::optional<unsigned> pageSeqNum, bool topLevelCall)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (find(m_chunksBeingRead.begin(), m_chunksBeingRead.end(), chunk.seqNum) != m_chunksBeingRead.end())
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("chunk %u is nested in itself", chunk.seqNum));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
const ChunkNestingGuard guard(m_chunksBeingRead, chunk.seqNum);
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned page = pageSeqNum.get_value_or(chunk.parentSeqNum);
|
|
rpm-build |
9243a4 |
input->seek(chunk.offset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
if (topLevelCall)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
// ignore non top level shapes
|
|
rpm-build |
9243a4 |
int i_page = -1;
|
|
rpm-build |
9243a4 |
for (unsigned int pageIndex : m_pageChunkIndices)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (m_contentChunks.at(pageIndex).seqNum == chunk.parentSeqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
i_page = pageIndex;
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (i_page == -1)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (getPageTypeBySeqNum(m_contentChunks[i_page].seqNum) != NORMAL)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
// if the parent of this is a page and hasn't yet been added, then add it.
|
|
rpm-build |
9243a4 |
if (!m_collector->hasPage(chunk.parentSeqNum))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->addPage(chunk.parentSeqNum);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
m_collector->setShapePage(chunk.seqNum, page);
|
|
rpm-build |
9243a4 |
m_collector->setShapeBorderPosition(chunk.seqNum, INSIDE_SHAPE); // This appears to be the only possibility for MSPUB2k
|
|
rpm-build |
9243a4 |
bool isImage = false;
|
|
rpm-build |
9243a4 |
bool isRectangle = false;
|
|
rpm-build |
9243a4 |
bool isGroup = false;
|
|
rpm-build |
9243a4 |
bool isLine = false;
|
|
rpm-build |
9243a4 |
unsigned flagsOffset(0); // ? why was this changed from boost::optional ?
|
|
rpm-build |
9243a4 |
parseShapeType(input, chunk.seqNum, chunk.offset, isGroup, isLine, isImage, isRectangle, flagsOffset);
|
|
rpm-build |
9243a4 |
parseShapeRotation(input, isGroup, isLine, chunk.seqNum, chunk.offset);
|
|
rpm-build |
9243a4 |
parseShapeCoordinates(input, chunk.seqNum, chunk.offset);
|
|
rpm-build |
9243a4 |
parseShapeFlips(input, flagsOffset, chunk.seqNum, chunk.offset);
|
|
rpm-build |
9243a4 |
if (isGroup)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return parseGroup(input, chunk.seqNum, page);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (isImage)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
assignShapeImgIndex(chunk.seqNum);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
parseShapeFill(input, chunk.seqNum, chunk.offset);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
parseShapeLine(input, isRectangle, chunk.offset, chunk.seqNum);
|
|
rpm-build |
9243a4 |
m_collector->setShapeOrder(chunk.seqNum);
|
|
rpm-build |
9243a4 |
return true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getShapeFillTypeOffset() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x2A;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getShapeFillColorOffset() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x22;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeFill(librevenge::RVNGInputStream *input, unsigned seqNum, unsigned chunkOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + getShapeFillTypeOffset(), librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned char fillType = readU8(input);
|
|
rpm-build |
9243a4 |
if (fillType == 2) // other types are gradients and patterns which are not implemented yet. 0 is no fill.
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + getShapeFillColorOffset(), librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned fillColorReference = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned translatedFillColorReference = translate2kColorReference(fillColorReference);
|
|
rpm-build |
9243a4 |
m_collector->setShapeFill(seqNum, std::shared_ptr<Fill>(new SolidFill(ColorReference(translatedFillColorReference), 1, m_collector)), false);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
bool MSPUBParser2k::parseGroup(librevenge::RVNGInputStream *input, unsigned seqNum, unsigned page)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
bool retVal = true;
|
|
rpm-build |
9243a4 |
m_collector->beginGroup();
|
|
rpm-build |
9243a4 |
m_collector->setCurrentGroupSeqNum(seqNum);
|
|
rpm-build |
9243a4 |
const std::map<unsigned, std::vector<unsigned> >::const_iterator it = m_chunkChildIndicesById.find(seqNum);
|
|
rpm-build |
9243a4 |
if (it != m_chunkChildIndicesById.end())
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
const std::vector<unsigned> &chunkChildIndices = it->second;
|
|
rpm-build |
9243a4 |
for (unsigned int chunkChildIndex : chunkChildIndices)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
const ContentChunkReference &childChunk = m_contentChunks.at(chunkChildIndex);
|
|
rpm-build |
9243a4 |
if (childChunk.type == SHAPE || childChunk.type == GROUP)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
retVal = retVal && parse2kShapeChunk(childChunk, input, page, false);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
m_collector->endGroup();
|
|
rpm-build |
9243a4 |
return retVal;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::assignShapeImgIndex(unsigned seqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
int i_dataIndex = -1;
|
|
rpm-build |
9243a4 |
for (unsigned j = 0; j < m_imageDataChunkIndices.size(); ++j)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (m_contentChunks.at(m_imageDataChunkIndices[j]).parentSeqNum == seqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
i_dataIndex = j;
|
|
rpm-build |
9243a4 |
break;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (i_dataIndex >= 0)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeImgIndex(seqNum, i_dataIndex + 1);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeCoordinates(librevenge::RVNGInputStream *input, unsigned seqNum,
|
|
rpm-build |
9243a4 |
unsigned chunkOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + 6, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
int xs = translateCoordinateIfNecessary(readS32(input));
|
|
rpm-build |
9243a4 |
int ys = translateCoordinateIfNecessary(readS32(input));
|
|
rpm-build |
9243a4 |
int xe = translateCoordinateIfNecessary(readS32(input));
|
|
rpm-build |
9243a4 |
int ye = translateCoordinateIfNecessary(readS32(input));
|
|
rpm-build |
9243a4 |
m_collector->setShapeCoordinatesInEmu(seqNum, xs, ys, xe, ye);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
int MSPUBParser2k::translateCoordinateIfNecessary(int coordinate) const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return coordinate;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeFlips(librevenge::RVNGInputStream *input, unsigned flagsOffset, unsigned seqNum,
|
|
rpm-build |
9243a4 |
unsigned chunkOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
if (flagsOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + flagsOffset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned char flags = readU8(input);
|
|
rpm-build |
9243a4 |
bool flipV = flags & 0x1;
|
|
rpm-build |
9243a4 |
bool flipH = flags & (0x2 | 0x10); // FIXME: this is a guess
|
|
rpm-build |
9243a4 |
m_collector->setShapeFlip(seqNum, flipV, flipH);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeType(librevenge::RVNGInputStream *input,
|
|
rpm-build |
9243a4 |
unsigned seqNum, unsigned chunkOffset,
|
|
rpm-build |
9243a4 |
bool &isGroup, bool &isLine, bool &isImage, bool &isRectangle,
|
|
rpm-build |
9243a4 |
unsigned &flagsOffset)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned short typeMarker = readU16(input);
|
|
rpm-build |
9243a4 |
if (typeMarker == 0x000f)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
isGroup = true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == 0x0004)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
isLine = true;
|
|
rpm-build |
9243a4 |
flagsOffset = 0x41;
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, LINE);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == 0x0002)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
isImage = true;
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, RECTANGLE);
|
|
rpm-build |
9243a4 |
isRectangle = true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == 0x0005)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, RECTANGLE);
|
|
rpm-build |
9243a4 |
isRectangle = true;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == 0x0006)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + 0x31, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
ShapeType shapeType = getShapeType(readU8(input));
|
|
rpm-build |
9243a4 |
flagsOffset = 0x33;
|
|
rpm-build |
9243a4 |
if (shapeType != UNKNOWN_SHAPE)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, shapeType);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == 0x0007)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, ELLIPSE);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
else if (typeMarker == getTextMarker())
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
m_collector->setShapeType(seqNum, RECTANGLE);
|
|
rpm-build |
9243a4 |
isRectangle = true;
|
|
rpm-build |
9243a4 |
input->seek(chunkOffset + getTextIdOffset(), librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned txtId = readU16(input);
|
|
rpm-build |
9243a4 |
m_collector->addTextShape(txtId, seqNum);
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getTextIdOffset() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x58;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned short MSPUBParser2k::getTextMarker() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x0008;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getFirstLineOffset() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x2C;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
unsigned MSPUBParser2k::getSecondLineOffset() const
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
return 0x35;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
void MSPUBParser2k::parseShapeLine(librevenge::RVNGInputStream *input, bool isRectangle, unsigned offset,
|
|
rpm-build |
9243a4 |
unsigned seqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(offset + getFirstLineOffset(), librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned short leftLineWidth = readU8(input);
|
|
rpm-build |
9243a4 |
bool leftLineExists = leftLineWidth != 0;
|
|
rpm-build |
9243a4 |
unsigned leftColorReference = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned translatedLeftColorReference = translate2kColorReference(leftColorReference);
|
|
rpm-build |
9243a4 |
if (isRectangle)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
input->seek(offset + getSecondLineOffset(), librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
9243a4 |
unsigned char topLineWidth = readU8(input);
|
|
rpm-build |
9243a4 |
bool topLineExists = topLineWidth != 0;
|
|
rpm-build |
9243a4 |
unsigned topColorReference = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned translatedTopColorReference = translate2kColorReference(topColorReference);
|
|
rpm-build |
9243a4 |
m_collector->addShapeLine(seqNum, Line(ColorReference(translatedTopColorReference),
|
|
rpm-build |
9243a4 |
translateLineWidth(topLineWidth) * EMUS_IN_INCH / (4 * POINTS_IN_INCH), topLineExists));
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
input->seek(1, librevenge::RVNG_SEEK_CUR);
|
|
rpm-build |
9243a4 |
unsigned char rightLineWidth = readU8(input);
|
|
rpm-build |
9243a4 |
bool rightLineExists = rightLineWidth != 0;
|
|
rpm-build |
9243a4 |
unsigned rightColorReference = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned translatedRightColorReference = translate2kColorReference(rightColorReference);
|
|
rpm-build |
9243a4 |
m_collector->addShapeLine(seqNum, Line(ColorReference(translatedRightColorReference),
|
|
rpm-build |
9243a4 |
translateLineWidth(rightLineWidth) * EMUS_IN_INCH / (4 * POINTS_IN_INCH), rightLineExists));
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
input->seek(1, librevenge::RVNG_SEEK_CUR);
|
|
rpm-build |
9243a4 |
unsigned char bottomLineWidth = readU8(input);
|
|
rpm-build |
9243a4 |
bool bottomLineExists = bottomLineWidth != 0;
|
|
rpm-build |
9243a4 |
unsigned bottomColorReference = readU32(input);
|
|
rpm-build |
9243a4 |
unsigned translatedBottomColorReference = translate2kColorReference(bottomColorReference);
|
|
rpm-build |
9243a4 |
m_collector->addShapeLine(seqNum, Line(ColorReference(translatedBottomColorReference),
|
|
rpm-build |
9243a4 |
translateLineWidth(bottomLineWidth) * EMUS_IN_INCH / (4 * POINTS_IN_INCH), bottomLineExists));
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
m_collector->addShapeLine(seqNum, Line(ColorReference(translatedLeftColorReference),
|
|
rpm-build |
9243a4 |
translateLineWidth(leftLineWidth) * EMUS_IN_INCH / (4 * POINTS_IN_INCH), leftLineExists));
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
bool MSPUBParser2k::parse()
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
std::unique_ptr<librevenge::RVNGInputStream> contents(m_input->getSubStreamByName("Contents"));
|
|
rpm-build |
9243a4 |
if (!contents)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Couldn't get contents stream.\n"));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (!parseContents(contents.get()))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Couldn't parse contents stream.\n"));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
std::unique_ptr<librevenge::RVNGInputStream> quill(m_input->getSubStreamByName("Quill/QuillSub/CONTENTS"));
|
|
rpm-build |
9243a4 |
if (!quill)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Couldn't get quill stream.\n"));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
if (!parseQuill(quill.get()))
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
MSPUB_DEBUG_MSG(("Couldn't parse quill stream.\n"));
|
|
rpm-build |
9243a4 |
return false;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
return m_collector->go();
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
PageType MSPUBParser2k::getPageTypeBySeqNum(unsigned seqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
switch (seqNum)
|
|
rpm-build |
9243a4 |
{
|
|
rpm-build |
9243a4 |
case 0x116:
|
|
rpm-build |
9243a4 |
case 0x108:
|
|
rpm-build |
9243a4 |
case 0x10B:
|
|
rpm-build |
9243a4 |
case 0x10D:
|
|
rpm-build |
9243a4 |
case 0x119:
|
|
rpm-build |
9243a4 |
return DUMMY_PAGE;
|
|
rpm-build |
9243a4 |
case 0x109:
|
|
rpm-build |
9243a4 |
return MASTER;
|
|
rpm-build |
9243a4 |
default:
|
|
rpm-build |
9243a4 |
return NORMAL;
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
}
|
|
rpm-build |
9243a4 |
|
|
rpm-build |
9243a4 |
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|