|
rpm-build |
6f7582 |
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/* libmwaw
|
|
rpm-build |
6f7582 |
* Version: MPL 2.0 / LGPLv2+
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* The contents of this file are subject to the Mozilla Public License Version
|
|
rpm-build |
6f7582 |
* 2.0 (the "License"); you may not use this file except in compliance with
|
|
rpm-build |
6f7582 |
* the License or as specified alternatively below. You may obtain a copy of
|
|
rpm-build |
6f7582 |
* the License at http://www.mozilla.org/MPL/
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
rpm-build |
6f7582 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
rpm-build |
6f7582 |
* for the specific language governing rights and limitations under the
|
|
rpm-build |
6f7582 |
* License.
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* Major Contributor(s):
|
|
rpm-build |
6f7582 |
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
|
|
rpm-build |
6f7582 |
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
|
|
rpm-build |
6f7582 |
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
|
|
rpm-build |
6f7582 |
* Copyright (C) 2006, 2007 Andrew Ziem
|
|
rpm-build |
6f7582 |
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* All Rights Reserved.
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* For minor contributions see the git repository.
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* Alternatively, the contents of this file may be used under the terms of
|
|
rpm-build |
6f7582 |
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
|
|
rpm-build |
6f7582 |
* in which case the provisions of the LGPLv2+ are applicable
|
|
rpm-build |
6f7582 |
* instead of those above.
|
|
rpm-build |
6f7582 |
*/
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/* This header contains code specific to a pict mac file
|
|
rpm-build |
6f7582 |
*/
|
|
rpm-build |
6f7582 |
#include <cstring>
|
|
rpm-build |
6f7582 |
#include <map>
|
|
rpm-build |
6f7582 |
#include <sstream>
|
|
rpm-build |
6f7582 |
#include <string>
|
|
rpm-build |
6f7582 |
#include <vector>
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
#include <librevenge/librevenge.h>
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
#include "libmwaw_internal.hxx"
|
|
rpm-build |
6f7582 |
#include "MWAWDebug.hxx"
|
|
rpm-build |
6f7582 |
#include "MWAWInputStream.hxx"
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
#include "MWAWPictMac.hxx"
|
|
rpm-build |
6f7582 |
#include "MWAWPictBitmap.hxx"
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
// and then to save the read bitmap/pixmap
|
|
rpm-build |
6f7582 |
#define DEBUG_BITMAP 0
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
MWAWPictMac::~MWAWPictMac()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
MWAWPictMac::ReadResult MWAWPictMac::checkOrGet
|
|
rpm-build |
6f7582 |
(MWAWInputStreamPtr input, int size, MWAWBox2f &box, MWAWPictData **result)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
if (result) *result=nullptr;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
int version, subvers;
|
|
rpm-build |
6f7582 |
// we can not read the data, ...
|
|
rpm-build |
6f7582 |
long actualPos = input->tell();
|
|
rpm-build |
6f7582 |
input->seek(actualPos,librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
if (size < 0xd)
|
|
rpm-build |
6f7582 |
return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
auto readSize = int(input->readULong(2));
|
|
rpm-build |
6f7582 |
long dim[4];
|
|
rpm-build |
6f7582 |
for (auto &d : dim) d = input->readLong(2);
|
|
rpm-build |
6f7582 |
long lastFlag = input->readLong(2);
|
|
rpm-build |
6f7582 |
bool empty = false;
|
|
rpm-build |
6f7582 |
switch (lastFlag) {
|
|
rpm-build |
6f7582 |
case 0x1101: {
|
|
rpm-build |
6f7582 |
if (readSize != size && readSize+1 != size)
|
|
rpm-build |
6f7582 |
return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
version = subvers = 1;
|
|
rpm-build |
6f7582 |
empty = (size == 0xd);
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
case 0x0011: {
|
|
rpm-build |
6f7582 |
if (size < 40) return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
if (input->readULong(2) != 0x2ff) return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
if (input->readULong(2) != 0xC00) return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
subvers = -int(input->readLong(2));
|
|
rpm-build |
6f7582 |
if (subvers == 1) empty = (size == 42);
|
|
rpm-build |
6f7582 |
else if (subvers == 2) empty = (size == 40);
|
|
rpm-build |
6f7582 |
else if (subvers >= -6 && subvers < 6) {
|
|
rpm-build |
6f7582 |
// find also 0 and -1 and -4 here...
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("MWAWPictMac::checkOrGet: unknown subversion: %d\n", subvers));
|
|
rpm-build |
6f7582 |
empty = (size == 0xd);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
else return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
version = 2;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (empty) {
|
|
rpm-build |
6f7582 |
input->seek(actualPos+size-1,librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
if (input->readULong(1) != 0xff) return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
box.set(MWAWVec2f(float(dim[1]),float(dim[0])), MWAWVec2f(float(dim[3]),float(dim[2])));
|
|
rpm-build |
6f7582 |
if (!empty && (box.size().x() < 0 || box.size().y() < 0)) return MWAW_R_BAD;
|
|
rpm-build |
6f7582 |
if (box.size().x() <= 0 || box.size().y() <= 0) empty = true;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (empty) return MWAW_R_OK_EMPTY;
|
|
rpm-build |
6f7582 |
if (!result) return MWAW_R_OK;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
auto *res = new MWAWPictMac(box);
|
|
rpm-build |
6f7582 |
res->m_version = version;
|
|
rpm-build |
6f7582 |
res->m_subVersion = subvers;
|
|
rpm-build |
6f7582 |
*result = res;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
// let caller read the data
|
|
rpm-build |
6f7582 |
return MWAW_R_OK;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
/** Internal and low level: generic tools about Mac Pict1.0 picture
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* This regroups some functions to parse them and to convert them in Pict2.0 picture
|
|
rpm-build |
6f7582 |
*/
|
|
rpm-build |
6f7582 |
namespace libmwaw_applepict1
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
/** Internal and low level: the different types of arguments.
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* By default, data are signed, excepted if we add U to indicate that they are unsigned,
|
|
rpm-build |
6f7582 |
* - WP_PATTERN: 8x8bits which defined a 8x8 picture (black or white)
|
|
rpm-build |
6f7582 |
* - WP_COLOR: 3 bits which defined r,g,b (checkme)
|
|
rpm-build |
6f7582 |
* - for BITMAP, R indicates Region bitmap while P indicates Packed bitmap
|
|
rpm-build |
6f7582 |
*/
|
|
rpm-build |
6f7582 |
enum DataType {
|
|
rpm-build |
6f7582 |
WP_NONE, WP_BYTE, WP_UBYTE, WP_INT, WP_UINT, WP_UFIXED,
|
|
rpm-build |
6f7582 |
WP_COLOR, WP_PATTERN, WP_POINT, WP_POINTBYTE, WP_POINTUBYTE, WP_POLY, WP_RECT, WP_REGION, WP_TEXT, WP_LTEXT,
|
|
rpm-build |
6f7582 |
WP_BITMAP, WP_RBITMAP, WP_PBITMAP, WP_RPBITMAP, WP_UNKNOWN
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** Internal and low level: class used to read/store a picture region
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* A region is formed by bounding box followed by an array of bits
|
|
rpm-build |
6f7582 |
* which indicate which defines a mask */
|
|
rpm-build |
6f7582 |
class Region
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
public:
|
|
rpm-build |
6f7582 |
Region()
|
|
rpm-build |
6f7582 |
: m_box()
|
|
rpm-build |
6f7582 |
, m_points()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! operator << for a Region
|
|
rpm-build |
6f7582 |
friend std::ostream &operator<< (std::ostream &o, Region const &f)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
o << "reg=" << f.m_box;
|
|
rpm-build |
6f7582 |
if (f.m_points.size()==0) return o;
|
|
rpm-build |
6f7582 |
o << ", [";
|
|
rpm-build |
6f7582 |
for (size_t c = 0; c < f.m_points.size(); c++) {
|
|
rpm-build |
6f7582 |
if (c) o << ",";
|
|
rpm-build |
6f7582 |
o << f.m_points[c];
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
o << "]";
|
|
rpm-build |
6f7582 |
return o;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! tries to read the data
|
|
rpm-build |
6f7582 |
bool read(MWAWInputStream &input)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
// the region size
|
|
rpm-build |
6f7582 |
auto sz = static_cast<int>(input.readULong(2));
|
|
rpm-build |
6f7582 |
if ((sz%2) != 0 || sz<10 || !input.checkPosition(actualPos+sz)) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Region: read odd size: %d\n", sz));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
sz /= 2;
|
|
rpm-build |
6f7582 |
int dim[4];
|
|
rpm-build |
6f7582 |
for (auto &d : dim) d = static_cast<int>(input.readLong(2));
|
|
rpm-build |
6f7582 |
m_box.set(MWAWVec2i(dim[1], dim[0]), MWAWVec2i(dim[3], dim[2]));
|
|
rpm-build |
6f7582 |
sz -= 5;
|
|
rpm-build |
6f7582 |
m_points.resize(0);
|
|
rpm-build |
6f7582 |
if (sz == 0) return true;
|
|
rpm-build |
6f7582 |
// une liste de point dans la box: x1, y1, .. yn 0x7fff, x2, ... 0x7fff
|
|
rpm-build |
6f7582 |
while (sz > 0) {
|
|
rpm-build |
6f7582 |
auto y = static_cast<int>(input.readLong(2));
|
|
rpm-build |
6f7582 |
sz--;
|
|
rpm-build |
6f7582 |
if (y == 0x7fff) break;
|
|
rpm-build |
6f7582 |
if (y < m_box[0].y() || y > m_box[1].y()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Region: found eroneous y value: %d\n", y));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
bool endF = false;
|
|
rpm-build |
6f7582 |
while (sz > 0) {
|
|
rpm-build |
6f7582 |
auto x = static_cast<int>(input.readLong(2));
|
|
rpm-build |
6f7582 |
sz--;
|
|
rpm-build |
6f7582 |
if (x == 0x7fff) {
|
|
rpm-build |
6f7582 |
endF = true;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (x < m_box[0].x() || x > m_box[1].x()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Region: found eroneous x value %d\n", x));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
m_points.push_back(MWAWVec2i(x,y));
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (!endF) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Region: does not find end of file...\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (sz) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Region: find some remaining data ...\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
protected:
|
|
rpm-build |
6f7582 |
//! the bounding box
|
|
rpm-build |
6f7582 |
MWAWBox2i m_box;
|
|
rpm-build |
6f7582 |
//! the set of points which defines the mask
|
|
rpm-build |
6f7582 |
std::vector<MWAWVec2i> m_points;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! Internal and low level: a class used to read pack/unpack black-white bitmap
|
|
rpm-build |
6f7582 |
struct Bitmap {
|
|
rpm-build |
6f7582 |
Bitmap()
|
|
rpm-build |
6f7582 |
: m_rowBytes()
|
|
rpm-build |
6f7582 |
, m_rect()
|
|
rpm-build |
6f7582 |
, m_src()
|
|
rpm-build |
6f7582 |
, m_dst()
|
|
rpm-build |
6f7582 |
, m_region()
|
|
rpm-build |
6f7582 |
, m_bitmap()
|
|
rpm-build |
6f7582 |
, m_mode(0)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! tries to read a bitmap
|
|
rpm-build |
6f7582 |
bool read(MWAWInputStream &input, bool packed, bool hasRegion)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
m_rowBytes = static_cast<int>(input.readULong(2));
|
|
rpm-build |
6f7582 |
m_rowBytes &= 0x3FFF;
|
|
rpm-build |
6f7582 |
if (m_rowBytes < 0 || (!packed && m_rowBytes > 8)) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: find odd rowBytes %d... \n", m_rowBytes));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
// read the rectangle: bound
|
|
rpm-build |
6f7582 |
// ------ end of bitmap ----------
|
|
rpm-build |
6f7582 |
// and the two general rectangle src, dst
|
|
rpm-build |
6f7582 |
for (int c = 0; c < 3; c++) {
|
|
rpm-build |
6f7582 |
int dim[4];
|
|
rpm-build |
6f7582 |
for (auto &d : dim) d = static_cast<int>(input.readLong(2));
|
|
rpm-build |
6f7582 |
MWAWBox2i box(MWAWVec2i(dim[1],dim[0]), MWAWVec2i(dim[3],dim[2]));
|
|
rpm-build |
6f7582 |
if (box.size().x() <= 0 || box.size().y() <= 0) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: find odd rectangle %d... \n", c));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (c == 0) m_rect=box;
|
|
rpm-build |
6f7582 |
else if (c==1) m_src = box;
|
|
rpm-build |
6f7582 |
else m_dst = box;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (!packed && m_rowBytes*8 < m_rect.size().x()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: row bytes seems to short: %d/%d... \n", m_rowBytes*8, m_rect.size().y()));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
m_mode = static_cast<int>(input.readLong(2)); // mode: I find 0,1 and 3
|
|
rpm-build |
6f7582 |
if (m_mode < 0 || m_mode > 64) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: unknown mode: %d \n", m_mode));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (hasRegion) { // CHECKME...
|
|
rpm-build |
6f7582 |
std::shared_ptr<Region>rgn(new Region);
|
|
rpm-build |
6f7582 |
if (!rgn->read(input)) return false;
|
|
rpm-build |
6f7582 |
m_region = rgn;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (!readBitmapData(input, packed)) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (input.isEnd()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: EOF \n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! operator<< for Bitmap
|
|
rpm-build |
6f7582 |
friend std::ostream &operator<< (std::ostream &o, Bitmap const &f)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
o << "rDim=" << f.m_rowBytes << ", " << f.m_rect << ", " << f.m_src << ", " << f.m_dst;
|
|
rpm-build |
6f7582 |
if (f.m_region.get()) o << ", " << *f.m_region;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (f.m_mode >= 0 && f.m_mode < 16) {
|
|
rpm-build |
6f7582 |
static char const *mode0[] = { // 0-15
|
|
rpm-build |
6f7582 |
"srcCopy", "srcOr", "srcXOr", "srcBic",
|
|
rpm-build |
6f7582 |
"notSrcCopy", "notSrcOr", "notSrcXOr", "notSrcBic",
|
|
rpm-build |
6f7582 |
"patCopy", "patOr", "patXOr", "patBic",
|
|
rpm-build |
6f7582 |
"notPatCopy", "notPatOr", "notPatXOr", "notPatBic"
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
o << ", " << mode0[f.m_mode] << ", [...]";
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
else if (f.m_mode >= 32 && f.m_mode < 40) {
|
|
rpm-build |
6f7582 |
static char const *mode1[] = { // 32-39
|
|
rpm-build |
6f7582 |
"blend", "addPin", "addOver", "subPin",
|
|
rpm-build |
6f7582 |
"transparent", "addMax", "subOver", "addMin"
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
o << ", " << mode1[f.m_mode-32] << ", [...]";
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
else if (f.m_mode == 49) o << ", grayishTextOr, [...]";
|
|
rpm-build |
6f7582 |
else if (f.m_mode == 50) o << ", hilitetransfermode, [...]";
|
|
rpm-build |
6f7582 |
else if (f.m_mode == 64) o << ", ditherCopy, [...]";
|
|
rpm-build |
6f7582 |
else
|
|
rpm-build |
6f7582 |
o << ", ###mod=" << f.m_mode << ", [...]";
|
|
rpm-build |
6f7582 |
#if DEBUG_BITMAP
|
|
rpm-build |
6f7582 |
f.saveBitmap();
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
return o;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! saves the bitmap in file (debugging function)
|
|
rpm-build |
6f7582 |
bool saveBitmap() const
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
if (m_rowBytes <= 0) return false;
|
|
rpm-build |
6f7582 |
int nRows = int(m_bitmap.size())/m_rowBytes;
|
|
rpm-build |
6f7582 |
MWAWPictBitmapBW bitmap(MWAWVec2i(m_rect.size().x(),nRows));
|
|
rpm-build |
6f7582 |
if (!bitmap.valid()) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
for (int i = 0; i < nRows; i++)
|
|
rpm-build |
6f7582 |
bitmap.setRowPacked(i, &m_bitmap[size_t(i*m_rowBytes)], &m_bitmap[0] + m_bitmap.size());
|
|
rpm-build |
6f7582 |
MWAWEmbeddedObject picture;
|
|
rpm-build |
6f7582 |
if (!bitmap.getBinary(picture) || picture.m_dataList.empty()) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
static int ppmNumber = 0;
|
|
rpm-build |
6f7582 |
std::stringstream f;
|
|
rpm-build |
6f7582 |
f << "PictBitmap" << ppmNumber++ << ".pbm";
|
|
rpm-build |
6f7582 |
return libmwaw::Debug::dumpFile(picture.m_dataList[0], f.str().c_str());
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! creates the bitmap from the packdata
|
|
rpm-build |
6f7582 |
bool unpackedData(unsigned char const *pData, int sz)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
int rPos = 0;
|
|
rpm-build |
6f7582 |
size_t wPos = m_bitmap.size(), wNPos = wPos+size_t(m_rowBytes);
|
|
rpm-build |
6f7582 |
m_bitmap.resize(size_t(wNPos));
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
while (rPos < sz) {
|
|
rpm-build |
6f7582 |
if (rPos+2 > sz) return false;
|
|
rpm-build |
6f7582 |
auto n = static_cast<signed char>(pData[rPos++]);
|
|
rpm-build |
6f7582 |
if (n < 0) {
|
|
rpm-build |
6f7582 |
int nCount = 1-n;
|
|
rpm-build |
6f7582 |
if (wPos+size_t(nCount) > wNPos) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
unsigned char val = pData[rPos++];
|
|
rpm-build |
6f7582 |
for (int i = 0; i < nCount; i++)
|
|
rpm-build |
6f7582 |
m_bitmap[wPos++] = val;
|
|
rpm-build |
6f7582 |
continue;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
int nCount = 1+n;
|
|
rpm-build |
6f7582 |
if (rPos+nCount > sz || wPos+size_t(nCount) > wNPos) return false;
|
|
rpm-build |
6f7582 |
for (int i = 0; i < nCount; i++)
|
|
rpm-build |
6f7582 |
m_bitmap[wPos++] = pData[rPos++];
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return (wPos == wNPos);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! parses the bitmap data zone
|
|
rpm-build |
6f7582 |
bool readBitmapData(MWAWInputStream &input, bool packed)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
int numRows = m_rect.size().y(), szRowSize=1;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (packed) {
|
|
rpm-build |
6f7582 |
// CHECKME: the limit(1/2 bytes) is probably 251: the value for a Pict2.0
|
|
rpm-build |
6f7582 |
// from collected data files, we have 246 < limit < 254
|
|
rpm-build |
6f7582 |
if (m_rowBytes > 250) szRowSize = 2;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
else
|
|
rpm-build |
6f7582 |
m_bitmap.resize(size_t(numRows*m_rowBytes));
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
size_t pos=0;
|
|
rpm-build |
6f7582 |
for (int i = 0; i < numRows; i++) {
|
|
rpm-build |
6f7582 |
if (input.isEnd()) break;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (!packed) {
|
|
rpm-build |
6f7582 |
unsigned long numR = 0;
|
|
rpm-build |
6f7582 |
unsigned char const *data = input.read(size_t(m_rowBytes), numR);
|
|
rpm-build |
6f7582 |
if (!data || int(numR) != m_rowBytes) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: can not read line %d/%d (%d chars)\n", i, numRows, m_rowBytes));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
for (int j = 0; j < m_rowBytes; j++)
|
|
rpm-build |
6f7582 |
m_bitmap[pos++]=data[j];
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
else {
|
|
rpm-build |
6f7582 |
auto numB = static_cast<int>(input.readULong(szRowSize));
|
|
rpm-build |
6f7582 |
if (numB < 0 || numB > 2*m_rowBytes) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: odd numB:%d in row: %d/%d\n", numB, i, numRows));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
unsigned long numR = 0;
|
|
rpm-build |
6f7582 |
unsigned char const *data = input.read(size_t(numB), numR);
|
|
rpm-build |
6f7582 |
if (!data || int(numR) != numB) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: can not read line %d/%d (%d chars)\n", i, numRows, numB));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (!unpackedData(data,numB)) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Bitmap: can not unpacked line:%d\n", i));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! the num of bytes used to store a row
|
|
rpm-build |
6f7582 |
int m_rowBytes;
|
|
rpm-build |
6f7582 |
MWAWBox2i m_rect /** the bitmap rectangle */, m_src/** the initial dimension */, /** another final dimension */ m_dst ;
|
|
rpm-build |
6f7582 |
//! the region
|
|
rpm-build |
6f7582 |
std::shared_ptr<Region> m_region;
|
|
rpm-build |
6f7582 |
//! the bitmap
|
|
rpm-build |
6f7582 |
std::vector<unsigned char> m_bitmap;
|
|
rpm-build |
6f7582 |
//! the encoding mode ?
|
|
rpm-build |
6f7582 |
int m_mode;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! Internal and low level: a class used to read and store all possible value
|
|
rpm-build |
6f7582 |
struct Value {
|
|
rpm-build |
6f7582 |
Value()
|
|
rpm-build |
6f7582 |
: m_type()
|
|
rpm-build |
6f7582 |
, m_int(0)
|
|
rpm-build |
6f7582 |
, m_rgb(MWAWColor::white())
|
|
rpm-build |
6f7582 |
, m_text("")
|
|
rpm-build |
6f7582 |
, m_point()
|
|
rpm-build |
6f7582 |
, m_box()
|
|
rpm-build |
6f7582 |
, m_listPoint()
|
|
rpm-build |
6f7582 |
, m_region()
|
|
rpm-build |
6f7582 |
, m_bitmap()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
for (auto &p : m_pat) p=0;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
virtual ~Value();
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** the stored type of the data
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* This can only be WP_INT, WP_COLOR, WP_PATTERN, WP_POINT, WP_POLY, WP_RECT, WP_REGION, WP_TEXT, WP_BITMAP */
|
|
rpm-build |
6f7582 |
DataType m_type;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! operator<< for Value
|
|
rpm-build |
6f7582 |
friend std::ostream &operator<< (std::ostream &o, Value const &f)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
switch (f.m_type) {
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
o << f.m_int;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
o << "col=(" << f.m_rgb << ")";
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
o << "pat=(" << std::hex;
|
|
rpm-build |
6f7582 |
for (int c= 0; c < 8; c++) {
|
|
rpm-build |
6f7582 |
if (c) o << ",";
|
|
rpm-build |
6f7582 |
o << f.m_pat[c];
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
o << ")" << std::dec;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
o << f.m_point;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
o << f.m_box;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
if (f.m_region.get()) {
|
|
rpm-build |
6f7582 |
o << *f.m_region;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Value: I do not find my region... \n"));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
o << "[reg=" << f.m_box << ":";
|
|
rpm-build |
6f7582 |
for (size_t c = 0; c < f.m_listPoint.size(); c++) {
|
|
rpm-build |
6f7582 |
if (c) o << ",";
|
|
rpm-build |
6f7582 |
o << f.m_listPoint[c];
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
o << "]";
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
o << "\"" << f.m_text << "\"";
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
if (f.m_bitmap.get()) {
|
|
rpm-build |
6f7582 |
o << *f.m_bitmap;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Value: I do not find my bitmap... \n"));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:Value: does not know how to print my values... \n"));
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return o;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! the int value when type=WP_INT
|
|
rpm-build |
6f7582 |
int m_int;
|
|
rpm-build |
6f7582 |
//! the color when type=WP_COLOR
|
|
rpm-build |
6f7582 |
MWAWColor m_rgb;
|
|
rpm-build |
6f7582 |
//! the pattern when type=WP_PATTERN
|
|
rpm-build |
6f7582 |
int m_pat[8];
|
|
rpm-build |
6f7582 |
//! the text when type=WP_TEXT
|
|
rpm-build |
6f7582 |
std::string m_text;
|
|
rpm-build |
6f7582 |
//! the point when type=WP_POINT
|
|
rpm-build |
6f7582 |
MWAWVec2i m_point;
|
|
rpm-build |
6f7582 |
//! the rectangle when type=WP_RECT
|
|
rpm-build |
6f7582 |
MWAWBox2i m_box;
|
|
rpm-build |
6f7582 |
//! the list of points which defined the polygon when type=WP_POLY
|
|
rpm-build |
6f7582 |
std::vector<MWAWVec2i> m_listPoint;
|
|
rpm-build |
6f7582 |
//! the region when type=WP_REGION
|
|
rpm-build |
6f7582 |
std::shared_ptr<Region> m_region;
|
|
rpm-build |
6f7582 |
//! the bitmap when type=WP_BITMAP
|
|
rpm-build |
6f7582 |
std::shared_ptr<Bitmap> m_bitmap;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
Value::~Value()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! Internal and low level: a class to define each opcode and their arguments and read their data
|
|
rpm-build |
6f7582 |
struct OpCode {
|
|
rpm-build |
6f7582 |
/** constructor
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* \param id is the code of the opcode in the file
|
|
rpm-build |
6f7582 |
* \param nm is the short name of the opcode
|
|
rpm-build |
6f7582 |
* \param type1 type of the first component
|
|
rpm-build |
6f7582 |
* \param type2 type of the second component (if it exists)
|
|
rpm-build |
6f7582 |
* \param type3 type of the third component (if it exists)
|
|
rpm-build |
6f7582 |
* \param type4 type of the fourst component (if it exists)
|
|
rpm-build |
6f7582 |
* \param type5 type of the fifth component (if it exists)
|
|
rpm-build |
6f7582 |
*/
|
|
rpm-build |
6f7582 |
OpCode(int id, char const *nm, DataType type1=WP_NONE, DataType type2=WP_NONE, DataType type3=WP_NONE, DataType type4=WP_NONE, DataType type5=WP_NONE)
|
|
rpm-build |
6f7582 |
: m_id(id)
|
|
rpm-build |
6f7582 |
, m_name(nm)
|
|
rpm-build |
6f7582 |
, m_types()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
if (type1==WP_NONE) return;
|
|
rpm-build |
6f7582 |
else m_types.push_back(type1);
|
|
rpm-build |
6f7582 |
if (type2==WP_NONE) return;
|
|
rpm-build |
6f7582 |
else m_types.push_back(type2);
|
|
rpm-build |
6f7582 |
if (type3==WP_NONE) return;
|
|
rpm-build |
6f7582 |
else m_types.push_back(type3);
|
|
rpm-build |
6f7582 |
if (type4==WP_NONE) return;
|
|
rpm-build |
6f7582 |
else m_types.push_back(type4);
|
|
rpm-build |
6f7582 |
if (type5==WP_NONE) return;
|
|
rpm-build |
6f7582 |
else m_types.push_back(type5);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
virtual ~OpCode();
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** tries to read the data in the file
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* If the read is succefull, fills listValue with the read argument */
|
|
rpm-build |
6f7582 |
bool readData(MWAWInputStream &input, std::vector<Value> &listValue) const
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
size_t numTypes = m_types.size();
|
|
rpm-build |
6f7582 |
listValue.resize(numTypes);
|
|
rpm-build |
6f7582 |
Value newVal;
|
|
rpm-build |
6f7582 |
for (size_t i = 0; i < numTypes; i++) {
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
if (readValue(input, m_types[i], newVal)) {
|
|
rpm-build |
6f7582 |
listValue[i] = newVal;
|
|
rpm-build |
6f7582 |
continue;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
input.seek(actualPos, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! computes the size of the data
|
|
rpm-build |
6f7582 |
bool computeSize(MWAWInputStream &input, int &sz) const
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
long actPos = input.tell();
|
|
rpm-build |
6f7582 |
sz = 0;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
for (auto type : m_types) {
|
|
rpm-build |
6f7582 |
input.seek(actPos+sz, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
int newSz = getSize(input, type);
|
|
rpm-build |
6f7582 |
if (newSz < 0) return false;
|
|
rpm-build |
6f7582 |
sz += newSz;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
input.seek(actPos, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** read a rectangles field
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
\note can be used to read the first dimensions of a picture */
|
|
rpm-build |
6f7582 |
static bool readRect(MWAWInputStream &input, DataType type, MWAWBox2i &res)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
DataType valType;
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
valType = WP_POINT;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readRect is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
MWAWVec2i v[2];
|
|
rpm-build |
6f7582 |
for (auto &val : v) {
|
|
rpm-build |
6f7582 |
if (!readPoint(input, valType, val)) return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
res.set(v[0], v[1]);
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! the opCode
|
|
rpm-build |
6f7582 |
int m_id;
|
|
rpm-build |
6f7582 |
//! the opCode name
|
|
rpm-build |
6f7582 |
std::string m_name;
|
|
rpm-build |
6f7582 |
//! the different argument types
|
|
rpm-build |
6f7582 |
std::vector<DataType> m_types;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
protected:
|
|
rpm-build |
6f7582 |
/** returns the size of the next argument of type \a type.
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* \note This function can update the next reading position in the input, if it uses the input to compute the size of this argument */
|
|
rpm-build |
6f7582 |
static int getSize(MWAWInputStream &input, DataType type)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
return 1;
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
return 2;
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
return 4;
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
return 8;
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
return static_cast<int>(input.readULong(2));
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
return 1+static_cast<int>(input.readULong(1));
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
return 2+static_cast<int>(input.readULong(2));
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP: {
|
|
rpm-build |
6f7582 |
// can not guess, so we read the bitmap...
|
|
rpm-build |
6f7582 |
long actPos = input.tell();
|
|
rpm-build |
6f7582 |
bool packed = type==WP_PBITMAP || type == WP_RPBITMAP;
|
|
rpm-build |
6f7582 |
bool hasRgn = type ==WP_RBITMAP || type == WP_RPBITMAP;
|
|
rpm-build |
6f7582 |
std::shared_ptr<Bitmap> btmap(new Bitmap);
|
|
rpm-build |
6f7582 |
if (!btmap->read(input, packed, hasRgn)) return -1;
|
|
rpm-build |
6f7582 |
return int(input.tell()-actPos);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return -1;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! reads a argument of type \a type, if successfull updates \a val.
|
|
rpm-build |
6f7582 |
static bool readValue(MWAWInputStream &input, DataType type, Value &val)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
val.m_type = WP_INT;
|
|
rpm-build |
6f7582 |
return readInt(input, type, val.m_int);
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
val.m_type = WP_COLOR;
|
|
rpm-build |
6f7582 |
return readColor(input, type, val.m_rgb);
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
val.m_type = WP_PATTERN;
|
|
rpm-build |
6f7582 |
return readPattern(input, type, val.m_pat);
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
val.m_type = WP_POINT;
|
|
rpm-build |
6f7582 |
return readPoint(input, type, val.m_point);
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
val.m_type = WP_POLY;
|
|
rpm-build |
6f7582 |
return readPoly(input, type, val.m_box, val.m_listPoint);
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
val.m_type = WP_RECT;
|
|
rpm-build |
6f7582 |
return readRect(input, type, val.m_box);
|
|
rpm-build |
6f7582 |
case WP_REGION: {
|
|
rpm-build |
6f7582 |
std::shared_ptr<Region> rgn(new Region);
|
|
rpm-build |
6f7582 |
if (!rgn->read(input)) return false;
|
|
rpm-build |
6f7582 |
val.m_type = WP_REGION;
|
|
rpm-build |
6f7582 |
val.m_region = rgn;
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
val.m_type = WP_TEXT;
|
|
rpm-build |
6f7582 |
return readText(input, type, val.m_text);
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP: {
|
|
rpm-build |
6f7582 |
bool packed = type==WP_PBITMAP || type == WP_RPBITMAP;
|
|
rpm-build |
6f7582 |
bool hasRgn = type ==WP_RBITMAP || type == WP_RPBITMAP;
|
|
rpm-build |
6f7582 |
std::shared_ptr<Bitmap> btmap(new Bitmap);
|
|
rpm-build |
6f7582 |
if (!btmap->read(input, packed, hasRgn)) return false;
|
|
rpm-build |
6f7582 |
val.m_type = WP_BITMAP;
|
|
rpm-build |
6f7582 |
val.m_bitmap = btmap;
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:readValue: find unknown type... \n"));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:readValue: does not know how to read type %d... \n", type));
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! low level: reads a integer ( bytes or 2 bytes, signed or unsigned)
|
|
rpm-build |
6f7582 |
static bool readInt(MWAWInputStream &input, DataType type, int &res)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
int sz = 0;
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
res = 0;
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
res = static_cast<int>(input.readLong((sz=1)));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
res = static_cast<int>(input.readULong((sz=1)));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
res = static_cast<int>(input.readLong((sz=2)));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
res = static_cast<int>(input.readULong((sz=2)));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
res = static_cast<int>(input.readULong((sz=4)));
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readInt is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
if (actualPos+sz != input.tell()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readInt find end of file...\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
/** low level: reads a color argument
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* \note check if this is not an indexed color */
|
|
rpm-build |
6f7582 |
static bool readColor(MWAWInputStream &input, DataType type, MWAWColor &col)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
if (type != WP_COLOR) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readColor is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
auto val = long(input.readULong(4));
|
|
rpm-build |
6f7582 |
switch (val) {
|
|
rpm-build |
6f7582 |
case 30:
|
|
rpm-build |
6f7582 |
col = MWAWColor::white();
|
|
rpm-build |
6f7582 |
break; // white
|
|
rpm-build |
6f7582 |
case 33:
|
|
rpm-build |
6f7582 |
col = MWAWColor::black();
|
|
rpm-build |
6f7582 |
break; // black
|
|
rpm-build |
6f7582 |
case 69:
|
|
rpm-build |
6f7582 |
col = MWAWColor(255,255,0);
|
|
rpm-build |
6f7582 |
break; // yellow
|
|
rpm-build |
6f7582 |
case 137:
|
|
rpm-build |
6f7582 |
col = MWAWColor(255,0,255);
|
|
rpm-build |
6f7582 |
break; // magenta
|
|
rpm-build |
6f7582 |
case 205:
|
|
rpm-build |
6f7582 |
col = MWAWColor(255,0,0);
|
|
rpm-build |
6f7582 |
break; // red
|
|
rpm-build |
6f7582 |
case 273:
|
|
rpm-build |
6f7582 |
col = MWAWColor(0,255,255);
|
|
rpm-build |
6f7582 |
break; // cyan
|
|
rpm-build |
6f7582 |
case 341:
|
|
rpm-build |
6f7582 |
col = MWAWColor(0,255,0);
|
|
rpm-build |
6f7582 |
break; // green
|
|
rpm-build |
6f7582 |
case 409:
|
|
rpm-build |
6f7582 |
col = MWAWColor(0,0,255);
|
|
rpm-build |
6f7582 |
break; // blue
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: unknown color %ld\n", val));
|
|
rpm-build |
6f7582 |
col = MWAWColor(128,128,128);
|
|
rpm-build |
6f7582 |
break; // gray
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (actualPos+4 != input.tell()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readColor find end of file...\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! low level: reads a pattern argument
|
|
rpm-build |
6f7582 |
static bool readPattern(MWAWInputStream &input, DataType type, int (&pat)[8])
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
if (type != WP_PATTERN) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPattern is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
for (auto &p : pat) p=static_cast<int>(input.readULong(1));
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (actualPos+8 != input.tell()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPattern find end of file...\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! low level: reads a point argument
|
|
rpm-build |
6f7582 |
static bool readPoint(MWAWInputStream &input, DataType type, MWAWVec2i &res)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
DataType valType;
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
valType = WP_INT;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
valType = WP_BYTE;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
valType = WP_UBYTE;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPoint is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
int v[2];
|
|
rpm-build |
6f7582 |
for (auto &val : v) {
|
|
rpm-build |
6f7582 |
if (!readInt(input, valType, val)) return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
res.set(v[0], v[1]);
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! low level: reads a polygon argument
|
|
rpm-build |
6f7582 |
static bool readPoly(MWAWInputStream &input, DataType type, MWAWBox2i &box, std::vector<MWAWVec2i> &res)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
DataType boxType, valType;
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
valType = WP_POINT;
|
|
rpm-build |
6f7582 |
boxType = WP_RECT;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPoly is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
int sz;
|
|
rpm-build |
6f7582 |
if (!readInt(input, WP_UINT, sz)) return false;
|
|
rpm-build |
6f7582 |
if ((sz%2) != 0) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPoly odd size: %d\n", sz));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
sz /= 2;
|
|
rpm-build |
6f7582 |
if (sz < 5) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPoly size is too short: %d\n", sz*2));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (!readRect(input, boxType, box)) return false;
|
|
rpm-build |
6f7582 |
int numPt = sz-5;
|
|
rpm-build |
6f7582 |
if ((numPt%2) != 0) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readPoly odd point number: %d\n", numPt));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
numPt /= 2;
|
|
rpm-build |
6f7582 |
res.resize(size_t(numPt));
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
MWAWVec2i pt;
|
|
rpm-build |
6f7582 |
for (auto &p : res) {
|
|
rpm-build |
6f7582 |
if (!readPoint(input, valType, pt)) return false;
|
|
rpm-build |
6f7582 |
p = pt;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
//! low level: reads a string argument
|
|
rpm-build |
6f7582 |
static bool readText(MWAWInputStream &input, DataType type, std::string &res)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
int sz = 0;
|
|
rpm-build |
6f7582 |
switch (type) {
|
|
rpm-build |
6f7582 |
case WP_TEXT:
|
|
rpm-build |
6f7582 |
// CHECKME:in at least one file: DHText, sz=5 but the text contains only
|
|
rpm-build |
6f7582 |
// one char
|
|
rpm-build |
6f7582 |
if (!readInt(input, WP_UBYTE, sz)) return false;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_LTEXT:
|
|
rpm-build |
6f7582 |
if (!readInt(input, WP_INT, sz) || sz < 0) return false;
|
|
rpm-build |
6f7582 |
break;
|
|
rpm-build |
6f7582 |
case WP_NONE:
|
|
rpm-build |
6f7582 |
case WP_BYTE:
|
|
rpm-build |
6f7582 |
case WP_UBYTE:
|
|
rpm-build |
6f7582 |
case WP_INT:
|
|
rpm-build |
6f7582 |
case WP_UINT:
|
|
rpm-build |
6f7582 |
case WP_UFIXED:
|
|
rpm-build |
6f7582 |
case WP_COLOR:
|
|
rpm-build |
6f7582 |
case WP_PATTERN:
|
|
rpm-build |
6f7582 |
case WP_POINT:
|
|
rpm-build |
6f7582 |
case WP_POINTBYTE:
|
|
rpm-build |
6f7582 |
case WP_POINTUBYTE:
|
|
rpm-build |
6f7582 |
case WP_POLY:
|
|
rpm-build |
6f7582 |
case WP_RECT:
|
|
rpm-build |
6f7582 |
case WP_REGION:
|
|
rpm-build |
6f7582 |
case WP_BITMAP:
|
|
rpm-build |
6f7582 |
case WP_RBITMAP:
|
|
rpm-build |
6f7582 |
case WP_PBITMAP:
|
|
rpm-build |
6f7582 |
case WP_RPBITMAP:
|
|
rpm-build |
6f7582 |
case WP_UNKNOWN:
|
|
rpm-build |
6f7582 |
#if !defined(__clang__)
|
|
rpm-build |
6f7582 |
default:
|
|
rpm-build |
6f7582 |
#endif
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readText is called with %d\n", type));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
long actualPos = input.tell();
|
|
rpm-build |
6f7582 |
res = "";
|
|
rpm-build |
6f7582 |
if (!input.checkPosition(actualPos+sz)) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:OpCode: readText: find EOF\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
for (int i = 0; i < sz; i++) {
|
|
rpm-build |
6f7582 |
auto c = char(input.readULong(1));
|
|
rpm-build |
6f7582 |
res += c;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode::~OpCode()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** internal and low level: map opcode id -> OpCode */
|
|
rpm-build |
6f7582 |
class PictParser
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
public:
|
|
rpm-build |
6f7582 |
//! the constructor
|
|
rpm-build |
6f7582 |
PictParser()
|
|
rpm-build |
6f7582 |
: m_mapIdOp()
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
/* list of known opcodes
|
|
rpm-build |
6f7582 |
*
|
|
rpm-build |
6f7582 |
* \note codes 0x2c, 0x2e, 0xa5 are not standard opcodes, but I find them in some pictures */
|
|
rpm-build |
6f7582 |
OpCode const listCodes[] = {
|
|
rpm-build |
6f7582 |
OpCode(0,"NOP"), OpCode(1,"ClipRgn",WP_REGION), OpCode(2,"BkPat",WP_PATTERN),
|
|
rpm-build |
6f7582 |
OpCode(3,"TxFont",WP_INT), OpCode(4,"TxFace",WP_UBYTE), OpCode(5,"TxMode",WP_INT), OpCode(6,"SpExtra",WP_UFIXED),
|
|
rpm-build |
6f7582 |
OpCode(7,"PnSize",WP_POINT), OpCode(8,"PnMode",WP_INT), OpCode(9,"PnPat",WP_PATTERN),
|
|
rpm-build |
6f7582 |
OpCode(0xa,"FillPat",WP_PATTERN), OpCode(0xb,"OvSize",WP_POINT), OpCode(0xc,"Origin",WP_POINT),
|
|
rpm-build |
6f7582 |
OpCode(0xd,"TxSize",WP_INT), OpCode(0xe,"FgColor",WP_COLOR), OpCode(0xf,"BkColor",WP_COLOR),
|
|
rpm-build |
6f7582 |
OpCode(0x10,"TxRatio",WP_POINT,WP_POINT), OpCode(0x11,"picVersion",WP_UBYTE),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x20,"Line",WP_POINT,WP_POINT),OpCode(0x21,"LineFrom",WP_POINT),
|
|
rpm-build |
6f7582 |
OpCode(0x22,"ShortLine",WP_POINT, WP_POINTBYTE), OpCode(0x23,"ShortLineFrom", WP_POINTBYTE),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x28,"LongText",WP_POINT,WP_TEXT), OpCode(0x29,"DHText",WP_UBYTE,WP_TEXT), OpCode(0x2a,"DVText",WP_UBYTE,WP_TEXT),
|
|
rpm-build |
6f7582 |
OpCode(0x2b,"DHDVText",WP_POINTUBYTE,WP_TEXT),
|
|
rpm-build |
6f7582 |
// not really a Pict1. code, but it can appear in some pict
|
|
rpm-build |
6f7582 |
OpCode(0x2c,"FontName",WP_INT,WP_INT,WP_TEXT),
|
|
rpm-build |
6f7582 |
// can we find 0x2d ?
|
|
rpm-build |
6f7582 |
// Fixme: add 0x2e: not really a Pict1. code, but it can appear in some pict
|
|
rpm-build |
6f7582 |
OpCode(0x2e,"GlyphState?", WP_INT, WP_INT, WP_INT),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x30,"frameRect",WP_RECT), OpCode(0x31,"paintRect",WP_RECT), OpCode(0x32,"eraseRect",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x33,"invertRect",WP_RECT), OpCode(0x34,"fillRect",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x38,"frameSameRect"), OpCode(0x39,"paintSameRect"), OpCode(0x3a,"eraseSameRect"),
|
|
rpm-build |
6f7582 |
OpCode(0x3b,"invertSameRect"), OpCode(0x3c,"fillSameRect"),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x40,"frameRRect",WP_RECT), OpCode(0x41,"paintRRect",WP_RECT), OpCode(0x42,"eraseRRect",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x43,"invertRRect",WP_RECT), OpCode(0x44,"fillRRect",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x48,"frameSameRRect"), OpCode(0x49,"paintSameRRect"), OpCode(0x4a,"eraseSameRRect"),
|
|
rpm-build |
6f7582 |
OpCode(0x4b,"invertSameRRect"), OpCode(0x4c,"fillSameRRect"),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x50,"frameOval",WP_RECT), OpCode(0x51,"paintOval",WP_RECT), OpCode(0x52,"eraseOval",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x53,"invertOval",WP_RECT), OpCode(0x54,"fillOval",WP_RECT),
|
|
rpm-build |
6f7582 |
OpCode(0x58,"frameSameOval"), OpCode(0x59,"paintSameOval"), OpCode(0x5a,"eraseSameOval"),
|
|
rpm-build |
6f7582 |
OpCode(0x5b,"invertSameOval"), OpCode(0x5c,"fillSameOval"),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x60,"frameArc",WP_RECT,WP_INT,WP_INT), OpCode(0x61,"paintArc",WP_RECT,WP_INT,WP_INT), OpCode(0x62,"eraseArc",WP_RECT,WP_INT,WP_INT),
|
|
rpm-build |
6f7582 |
OpCode(0x63,"invertArc",WP_RECT,WP_INT,WP_INT), OpCode(0x64,"fillArc",WP_RECT,WP_INT,WP_INT),
|
|
rpm-build |
6f7582 |
OpCode(0x68,"frameSameArc",WP_INT,WP_INT), OpCode(0x69,"paintSameArc",WP_INT,WP_INT), OpCode(0x6a,"eraseSameArc",WP_INT,WP_INT),
|
|
rpm-build |
6f7582 |
OpCode(0x6b,"invertSameArc",WP_INT,WP_INT), OpCode(0x6c,"fillSameArc",WP_INT,WP_INT),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x70,"framePoly",WP_POLY), OpCode(0x71,"paintPoly",WP_POLY), OpCode(0x72,"erasePoly",WP_POLY),
|
|
rpm-build |
6f7582 |
OpCode(0x73,"invertPoly",WP_POLY), OpCode(0x74,"fillPoly",WP_POLY),
|
|
rpm-build |
6f7582 |
// reserved: but not implemented
|
|
rpm-build |
6f7582 |
OpCode(0x78,"frameSamePoly"), OpCode(0x79,"paintSamePoly"), OpCode(0x7a,"eraseSamePoly"),
|
|
rpm-build |
6f7582 |
OpCode(0x7b,"invertSamePoly"), OpCode(0x7c,"fillSamePoly"),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x80,"frameRgn",WP_REGION), OpCode(0x81,"paintRgn",WP_REGION), OpCode(0x82,"eraseRgn",WP_REGION),
|
|
rpm-build |
6f7582 |
OpCode(0x83,"invertRgn",WP_REGION), OpCode(0x84,"fillRgn",WP_REGION),
|
|
rpm-build |
6f7582 |
// reserved: but not implemented
|
|
rpm-build |
6f7582 |
OpCode(0x88,"frameSameRgn"), OpCode(0x89,"paintSameRgn"), OpCode(0x8a,"eraseSameRgn"),
|
|
rpm-build |
6f7582 |
OpCode(0x8b,"invertSameRgn"), OpCode(0x8c,"fillSameRgn"),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
// fixme: bitmap to implement
|
|
rpm-build |
6f7582 |
OpCode(0x90,"BitsRect", WP_BITMAP),
|
|
rpm-build |
6f7582 |
OpCode(0x91,"BitsRgn", WP_RBITMAP),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0x98,"PackBitsRect", WP_PBITMAP),
|
|
rpm-build |
6f7582 |
OpCode(0x99,"PackBitsRgn", WP_RPBITMAP),
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode(0xa0,"ShortComment", WP_INT),
|
|
rpm-build |
6f7582 |
OpCode(0xa1,"LongComment", WP_INT, WP_LTEXT),
|
|
rpm-build |
6f7582 |
// not really a Pict1. code, but it can appear in some pict
|
|
rpm-build |
6f7582 |
OpCode(0xa5,"LongComment????", WP_INT, WP_LTEXT),
|
|
rpm-build |
6f7582 |
OpCode(0xff,"EndOfPicture")
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
for (auto const &opCode : listCodes)
|
|
rpm-build |
6f7582 |
m_mapIdOp.insert(std::map<int,OpCode>::value_type(opCode.m_id,opCode));
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** internal and low level: tries to convert a Pict1.0 picture stored in \a orig in a Pict2.0 picture */
|
|
rpm-build |
6f7582 |
bool convertToPict2(librevenge::RVNGBinaryData const &orig, librevenge::RVNGBinaryData &result);
|
|
rpm-build |
6f7582 |
protected:
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
//! the map
|
|
rpm-build |
6f7582 |
std::map<int,OpCode> m_mapIdOp;
|
|
rpm-build |
6f7582 |
};
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
/** internal and low level: tries to convert a Pict1.0 picture stored in \a orig in a Pict2.0 picture */
|
|
rpm-build |
6f7582 |
bool PictParser::convertToPict2(librevenge::RVNGBinaryData const &orig, librevenge::RVNGBinaryData &result)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
# ifdef ADD_DATA_SHORT
|
|
rpm-build |
6f7582 |
# undef ADD_DATA_SHORT
|
|
rpm-build |
6f7582 |
# endif
|
|
rpm-build |
6f7582 |
# define ADD_DATA_SHORT(resPtr,val) do { \
|
|
rpm-build |
6f7582 |
*(resPtr++) = static_cast<unsigned char>((val & 0xFF00) >> 8); \
|
|
rpm-build |
6f7582 |
*(resPtr++) = static_cast<unsigned char> (val & 0xFF); } while(0)
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
auto pictSize = long(orig.size());
|
|
rpm-build |
6f7582 |
if (pictSize < 10) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
std::unique_ptr<unsigned char[]> res{new unsigned char [size_t(2*pictSize+50)]};
|
|
rpm-build |
6f7582 |
unsigned char *resPtr = res.get();
|
|
rpm-build |
6f7582 |
const unsigned char *resEnd = res.get() + 2*pictSize+50;
|
|
rpm-build |
6f7582 |
if (!res) return false;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
MWAWInputStreamPtr input=MWAWInputStream::get(orig, false);
|
|
rpm-build |
6f7582 |
if (!input) {
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
input->seek(0, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
auto sz = static_cast<int>(input->readULong(2));
|
|
rpm-build |
6f7582 |
if (pictSize != sz && pictSize != sz+1) {
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,0); // size, we must fill it latter
|
|
rpm-build |
6f7582 |
long dim[4];
|
|
rpm-build |
6f7582 |
for (auto &d : dim) { // read the rectangle
|
|
rpm-build |
6f7582 |
d = input->readLong(2);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,d);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (input->readLong(2) != 0x1101) {
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,0x11);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,0x2FF);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,0xC00); // HeaderOp
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr, -1);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr, -1);
|
|
rpm-build |
6f7582 |
for (int i = 0; i < 4; i++) {
|
|
rpm-build |
6f7582 |
int depl = (i%2) ? -1 : 1;
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,dim[i+depl]);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr,0);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr, 0);
|
|
rpm-build |
6f7582 |
ADD_DATA_SHORT(resPtr, 0);
|
|
rpm-build |
6f7582 |
# undef ADD_DATA_SHORT
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
bool findEnd = false;
|
|
rpm-build |
6f7582 |
while (!findEnd && !input->isEnd()) {
|
|
rpm-build |
6f7582 |
long actPos = input->tell();
|
|
rpm-build |
6f7582 |
auto code = static_cast<int>(input->readULong(1));
|
|
rpm-build |
6f7582 |
auto it = m_mapIdOp.find(code);
|
|
rpm-build |
6f7582 |
if (it == m_mapIdOp.end()) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:convertToPict2 can not find opCode 0x%x\n", static_cast<unsigned int>(code)));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
OpCode const &opCode = it->second;
|
|
rpm-build |
6f7582 |
sz = 0;
|
|
rpm-build |
6f7582 |
if (!opCode.computeSize(*input, sz)) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:convertToPict2 can not compute size for opCode 0x%x\n", static_cast<unsigned int>(code)));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
bool skip = (code == 0x2e) || (code == 0xa5); // normally unemplemented, so..
|
|
rpm-build |
6f7582 |
findEnd = code == 0xff;
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
if (!skip) {
|
|
rpm-build |
6f7582 |
if (resEnd-resPtr < 2+sz+sz%2) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:convertToPict2 output buffer overflow\n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
*(resPtr++) = 0;
|
|
rpm-build |
6f7582 |
*(resPtr++) = static_cast<unsigned char>(code);
|
|
rpm-build |
6f7582 |
input->seek(actPos+1, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
for (int i = 0; i < sz; i++)
|
|
rpm-build |
6f7582 |
*(resPtr++) = static_cast<unsigned char>(input->readULong(1));
|
|
rpm-build |
6f7582 |
if ((sz%2)==1) *(resPtr++) = 0;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
input->seek(actPos+1+sz, librevenge::RVNG_SEEK_SET);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
bool endOk = false;
|
|
rpm-build |
6f7582 |
if (findEnd) {
|
|
rpm-build |
6f7582 |
if (input->isEnd()) endOk = true;
|
|
rpm-build |
6f7582 |
else { // allows a final caracter for alignment
|
|
rpm-build |
6f7582 |
input->seek(1, librevenge::RVNG_SEEK_CUR);
|
|
rpm-build |
6f7582 |
endOk = input->isEnd();
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
if (!endOk) {
|
|
rpm-build |
6f7582 |
MWAW_DEBUG_MSG(("Pict1:convertToPict2 find EOF or EndOfPict prematurely \n"));
|
|
rpm-build |
6f7582 |
return false;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
long newSize = resPtr - res.get();
|
|
rpm-build |
6f7582 |
res[0] = static_cast<unsigned char>((newSize & 0xFF00) >> 8);
|
|
rpm-build |
6f7582 |
res[1] = static_cast<unsigned char>(newSize & 0xFF);
|
|
rpm-build |
6f7582 |
result.clear();
|
|
rpm-build |
6f7582 |
result.append(res.get(), static_cast<unsigned long>(newSize));
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
return true;
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
|
|
rpm-build |
6f7582 |
bool MWAWPictMac::convertPict1To2(librevenge::RVNGBinaryData const &orig, librevenge::RVNGBinaryData &result)
|
|
rpm-build |
6f7582 |
{
|
|
rpm-build |
6f7582 |
libmwaw_applepict1::PictParser parser;
|
|
rpm-build |
6f7582 |
return parser.convertToPict2(orig, result);
|
|
rpm-build |
6f7582 |
}
|
|
rpm-build |
6f7582 |
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
|