summaryrefslogtreecommitdiff
path: root/src/lib/SW602Printer.cpp
blob: 142155b2fe9d2629ed04f3762fe78c7467ebbd51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libsw602 project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "SW602Printer.h"

#include <iostream>

#include "SW602Types.h"
#include "libsw602_utils.h"

namespace libsw602
{
//------------------------------------------------------------
//
// The printer information
// see http://www.mactech.com/articles/mactech/Vol.01/01.09/AllAboutPrinting/index.html
//
//------------------------------------------------------------


//
// PrinterRect : a rectangle
//
bool PrinterRect::read(librevenge::RVNGInputStream &input, SW602Vec2i const &res)
{
  for (int st = 0; st < 2; st++)
  {
    int y = int(readU16(input));
    y = int(float(y)*72./float(res.y()));
    int x = int(readU16(input));
    x = int(float(x)*72./float(res.x()));
    m_pos[st].set(x,y);
  }

  if (input.isEnd()) return false;

  if (m_pos[0].x() > m_pos[1].x() || m_pos[0].y() > m_pos[1].y())
    return false;
  return true;
}

//! Internal: structure used to keep a rectangle with its resolution
struct PrinterRectResolution
{
  PrinterRectResolution() : m_rect(), m_resolution(), m_iDev(-1) {}
  //! page dimension
  PrinterRect page() const
  {
    return m_rect;
  }
  //! resolution
  SW602Vec2i const &resolution() const
  {
    return m_resolution;
  }

  //! operator <<
  friend std::ostream &operator<< (std::ostream &o, PrinterRectResolution const &r)
  {
    o << r.m_rect << ":" << r.m_resolution;
    return o;
  }
  //! reads the data from file
  bool read(librevenge::RVNGInputStream &input)
  {
    m_iDev = int(readU16(input));
    int y = int(readU16(input));
    int x = int(readU16(input));
    if (x <= 0 || y <= 0) return false;
    m_resolution.set(x,y);
    return m_rect.read(input, m_resolution);
  }

protected:
  //! returns the main rectangle
  PrinterRect m_rect;
  //! returns the resolution
  SW602Vec2i m_resolution;
  //! a field which is reserved
  int m_iDev;
};

//! Internal: structure used to keep the printer style information
struct PrinterStyle
{
  /** operator<<

  \note print nothing*/
  friend std::ostream &operator<< (std::ostream &o, PrinterStyle const &)
  {
    return o;
  }
  //! reads data from file
  bool read(librevenge::RVNGInputStream &input)
  {
    m_wDev = (int) readU16(input);
    m_pageWidth = (int) readU16(input);
    m_pageHeight = (int) readU16(input);
    if (m_pageWidth < 0 || m_pageHeight < 0) return false;
    m_port = (int) readU8(input);
    m_feed = (int) readU8(input);
    if (input.isEnd()) return false;
    return true;
  }

protected:
  int m_wDev /** used internally */;
  int m_feed /** paper type: cut, fanfold, mechcut or other */;
  int m_pageHeight /** paper height */, m_pageWidth /** paper width*/, m_port /** printer or modem port */;
};

//! Internal: structure used to keep a printer job
struct PrinterJob
{
  //! operator<<
  friend std::ostream &operator<< (std::ostream &o, PrinterJob const &r)
  {
    o << "fP=" << r.m_firstPage << ", lP=" << r.m_lastPage << ", copies=" << r.m_copies;
    if (r.m_fileVol || r.m_fileVers) o << ", fVol=" << r.m_fileVol << ", fVers=" << r.m_fileVers;
    return o;
  }
  //! read data from file
  bool read(librevenge::RVNGInputStream &input)
  {
    m_firstPage = (int) readU16(input);
    m_lastPage = (int) readU16(input);
    m_copies = (int) readU16(input);
    m_jobDocLoop = (int) readU8(input);
    m_fromUser = (int) readU8(input);
    // skip pIdleProc
    if (input.seek(4, librevenge::RVNG_SEEK_CUR) != 0 || input.isEnd()) return false;
    // skip pFileName
    if (input.seek(4, librevenge::RVNG_SEEK_CUR) != 0 || input.isEnd()) return false;
    m_fileVol = (int) readU16(input);
    m_fileVers = (int) readU8(input);
    return true;
  }

protected:
  int m_firstPage /** first page*/, m_lastPage/** last page*/, m_copies /** number of copies */;
  int m_jobDocLoop/** printing method: draft or defered */;
  int m_fileVol /** volume reference number*/ , m_fileVers /** version of spool file */;
  //! reserved
  int m_fromUser;
};

//
// PrinterInfo storage class
//
struct PrinterInfoData
{
  PrinterInfoData(): m_info(), m_paper(), m_feed(), m_info2(), m_job(), m_version(-1) {}

  //! printer information
  PrinterRectResolution m_info;
  //! paper
  PrinterRect m_paper;
  //! printer style
  PrinterStyle m_feed;
  //! printer information
  PrinterRectResolution m_info2;
  //! jobs
  PrinterJob m_job;
  //! reserved
  int m_version;
};

//
// PrinterInfo : ie. apple TPrint
//
PrinterInfo::PrinterInfo() : m_data(new PrinterInfoData) {}
PrinterInfo::~PrinterInfo()
{
}

PrinterRect PrinterInfo::page() const
{
  return m_data->m_info.page();
}
PrinterRect PrinterInfo::paper() const
{
  return m_data->m_paper;
}

//! operator<< for a PrinterInfo
std::ostream &operator<< (std::ostream &o, PrinterInfo const &r)
{
  o << "page = " << r.m_data->m_info << ", paper = " << r.m_data->m_paper
    << ", infoPt: " << r.m_data->m_info2 << ", jobs: [" << r.m_data->m_job << "]";
  return o;
}

bool PrinterInfo::read(librevenge::RVNGInputStream &input)
{
  m_data->m_version = (int) readU16(input);
  if (!m_data->m_info.read(input)) return false;
  if (!m_data->m_paper.read(input, m_data->m_info.resolution())) return false;
  if (!m_data->m_feed.read(input)) return false;
  long pos = input.tell();
  if (!m_data->m_info2.read(input))
  {
    // can be left unfilled, so as we do not use the result, ...
    input.seek(pos+14, librevenge::RVNG_SEEK_SET);
    if (input.tell() != pos+14) return false;
  }
  // skip unknown structure prXInfo
  if (input.seek(16, librevenge::RVNG_SEEK_CUR) != 0 || input.isEnd()) return false;

  if (!m_data->m_job.read(input)) return false;
  readU8(input);

  // skip printX 19 short + 2 align
  pos = input.tell();
  if (input.seek(19*2,librevenge::RVNG_SEEK_CUR) != 0 || input.tell()!=pos+19*2) return false;
  return true;
}
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */