Blame src/lib/MWAWPictMac.cxx

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: