Diffstat (limited to 'noncore/graphics/drawpad/drawpadcanvas.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/graphics/drawpad/drawpadcanvas.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/noncore/graphics/drawpad/drawpadcanvas.cpp b/noncore/graphics/drawpad/drawpadcanvas.cpp new file mode 100644 index 0000000..f02f478 --- a/dev/null +++ b/noncore/graphics/drawpad/drawpadcanvas.cpp | |||
@@ -0,0 +1,339 @@ | |||
1 | /*************************************************************************** | ||
2 | * * | ||
3 | * DrawPad - a drawing program for Opie Environment * | ||
4 | * * | ||
5 | * (C) 2002 by S. Prud'homme <prudhomme@laposte.net> * | ||
6 | * * | ||
7 | * This program is free software; you can redistribute it and/or modify * | ||
8 | * it under the terms of the GNU General Public License as published by * | ||
9 | * the Free Software Foundation; either version 2 of the License, or * | ||
10 | * (at your option) any later version. * | ||
11 | * * | ||
12 | ***************************************************************************/ | ||
13 | |||
14 | #include "drawpadcanvas.h" | ||
15 | |||
16 | #include "drawmode.h" | ||
17 | #include "drawpad.h" | ||
18 | |||
19 | #include <qbuffer.h> | ||
20 | #include <qimage.h> | ||
21 | #include <qpainter.h> | ||
22 | #include <qpixmap.h> | ||
23 | #include <qtextcodec.h> | ||
24 | #include <qtextstream.h> | ||
25 | #include <qxml.h> | ||
26 | |||
27 | #include <zlib.h> | ||
28 | |||
29 | class DrawPadCanvasXmlHandler: public QXmlDefaultHandler | ||
30 | { | ||
31 | public: | ||
32 | DrawPadCanvasXmlHandler(); | ||
33 | ~DrawPadCanvasXmlHandler(); | ||
34 | |||
35 | QList<QPixmap> pixmaps(); | ||
36 | |||
37 | bool startElement(const QString& namespaceURI, const QString& localName, | ||
38 | const QString& qName, const QXmlAttributes& atts); | ||
39 | bool endElement(const QString& namespaceURI, const QString& localName, | ||
40 | const QString& qName); | ||
41 | bool characters(const QString& ch); | ||
42 | |||
43 | private: | ||
44 | enum State { | ||
45 | Unknown, | ||
46 | InData | ||
47 | }; | ||
48 | |||
49 | State m_state; | ||
50 | ulong m_dataLenght; | ||
51 | QList<QPixmap> m_pixmaps; | ||
52 | }; | ||
53 | |||
54 | DrawPadCanvasXmlHandler::DrawPadCanvasXmlHandler() | ||
55 | { | ||
56 | m_state = Unknown; | ||
57 | } | ||
58 | |||
59 | DrawPadCanvasXmlHandler::~DrawPadCanvasXmlHandler() | ||
60 | { | ||
61 | } | ||
62 | |||
63 | QList<QPixmap> DrawPadCanvasXmlHandler::pixmaps() | ||
64 | { | ||
65 | return m_pixmaps; | ||
66 | } | ||
67 | |||
68 | bool DrawPadCanvasXmlHandler::startElement(const QString& namespaceURI, const QString& localName, | ||
69 | const QString& qName, const QXmlAttributes& atts) | ||
70 | { | ||
71 | Q_CONST_UNUSED(namespaceURI) | ||
72 | Q_CONST_UNUSED(localName) | ||
73 | |||
74 | if (qName.compare("data") == 0) { | ||
75 | m_state = InData; | ||
76 | m_dataLenght = atts.value("length").toULong(); | ||
77 | } | ||
78 | |||
79 | return true; | ||
80 | } | ||
81 | |||
82 | bool DrawPadCanvasXmlHandler::endElement(const QString& namespaceURI, const QString& localName, | ||
83 | const QString& qName) | ||
84 | { | ||
85 | Q_CONST_UNUSED(namespaceURI) | ||
86 | Q_CONST_UNUSED(localName) | ||
87 | |||
88 | if (qName.compare("data") == 0) { | ||
89 | m_state = Unknown; | ||
90 | } | ||
91 | |||
92 | return true; | ||
93 | } | ||
94 | |||
95 | bool DrawPadCanvasXmlHandler::characters(const QString& ch) | ||
96 | { | ||
97 | if (m_state == InData) { | ||
98 | QByteArray byteArray(ch.length() / 2); | ||
99 | |||
100 | for (int i = 0; i < (int)ch.length() / 2; i++) { | ||
101 | char h = ch[2 * i].latin1(); | ||
102 | char l = ch[2 * i + 1].latin1(); | ||
103 | uchar r = 0; | ||
104 | |||
105 | if (h <= '9') { | ||
106 | r += h - '0'; | ||
107 | } else { | ||
108 | r += h - 'a' + 10; | ||
109 | } | ||
110 | |||
111 | r = r << 4; | ||
112 | |||
113 | if (l <= '9') { | ||
114 | r += l - '0'; | ||
115 | } else { | ||
116 | r += l - 'a' + 10; | ||
117 | } | ||
118 | |||
119 | byteArray[i] = r; | ||
120 | } | ||
121 | |||
122 | if (m_dataLenght < ch.length() * 5) { | ||
123 | m_dataLenght = ch.length() * 5; | ||
124 | } | ||
125 | |||
126 | QByteArray byteArrayUnzipped(m_dataLenght); | ||
127 | ::uncompress((uchar*)byteArrayUnzipped.data(), &m_dataLenght, (uchar*)byteArray.data(), byteArray.size()); | ||
128 | |||
129 | QImage image; | ||
130 | image.loadFromData((const uchar*)byteArrayUnzipped.data(), m_dataLenght, "XPM"); | ||
131 | |||
132 | QPixmap* pixmap = new QPixmap(image.width(), image.height()); | ||
133 | pixmap->convertFromImage(image); | ||
134 | m_pixmaps.append(pixmap); | ||
135 | } | ||
136 | |||
137 | return true; | ||
138 | } | ||
139 | |||
140 | DrawPadCanvas::DrawPadCanvas(DrawPad* drawPad, QWidget* parent, const char* name, WFlags f) | ||
141 | : QWidget(parent, name, f) | ||
142 | { | ||
143 | setBackgroundMode(QWidget::PaletteBase); | ||
144 | |||
145 | m_pDrawPad = drawPad; | ||
146 | m_buffers.setAutoDelete(true); | ||
147 | m_buffers.append(new QPixmap(width(), height())); | ||
148 | m_buffers.current()->fill(Qt::white); | ||
149 | } | ||
150 | |||
151 | DrawPadCanvas::~DrawPadCanvas() | ||
152 | { | ||
153 | } | ||
154 | |||
155 | void DrawPadCanvas::load(QIODevice* ioDevice) | ||
156 | { | ||
157 | QTextStream textStream(ioDevice); | ||
158 | textStream.setCodec(QTextCodec::codecForName("UTF-8")); | ||
159 | |||
160 | QXmlInputSource xmlInputSource(textStream); | ||
161 | QXmlSimpleReader xmlSimpleReader; | ||
162 | DrawPadCanvasXmlHandler drawPadCanvasXmlHandler; | ||
163 | |||
164 | xmlSimpleReader.setContentHandler(&drawPadCanvasXmlHandler); | ||
165 | xmlSimpleReader.parse(xmlInputSource); | ||
166 | |||
167 | m_buffers = drawPadCanvasXmlHandler.pixmaps(); | ||
168 | |||
169 | if (m_buffers.isEmpty()) { | ||
170 | m_buffers.append(new QPixmap(width(), height())); | ||
171 | m_buffers.current()->fill(Qt::white); | ||
172 | } | ||
173 | |||
174 | repaint(); | ||
175 | } | ||
176 | |||
177 | void DrawPadCanvas::save(QIODevice* ioDevice) | ||
178 | { | ||
179 | QTextStream textStream(ioDevice); | ||
180 | textStream.setCodec(QTextCodec::codecForName("UTF-8")); | ||
181 | |||
182 | textStream << "<drawpad>" << endl; | ||
183 | textStream << " <images>" << endl; | ||
184 | |||
185 | QListIterator<QPixmap> bufferIterator(m_buffers); | ||
186 | |||
187 | for (bufferIterator.toFirst(); bufferIterator.current() != 0; ++bufferIterator) { | ||
188 | textStream << " <image>" << endl; | ||
189 | |||
190 | QImage image = bufferIterator.current()->convertToImage(); | ||
191 | QByteArray byteArray; | ||
192 | QBuffer buffer(byteArray); | ||
193 | QImageIO imageIO(&buffer, "XPM"); | ||
194 | |||
195 | buffer.open(IO_WriteOnly); | ||
196 | imageIO.setImage(image); | ||
197 | imageIO.write(); | ||
198 | buffer.close(); | ||
199 | |||
200 | ulong size = byteArray.size() * 2; | ||
201 | QByteArray byteArrayZipped(size); | ||
202 | ::compress((uchar*)byteArrayZipped.data(), &size, (uchar*)byteArray.data(), byteArray.size()); | ||
203 | |||
204 | textStream << " <data length=\"" << byteArray.size() << "\">"; | ||
205 | |||
206 | static const char hexchars[] = "0123456789abcdef"; | ||
207 | |||
208 | for (int i = 0; i < (int)size; i++ ) { | ||
209 | uchar s = (uchar)byteArrayZipped[i]; | ||
210 | textStream << hexchars[s >> 4]; | ||
211 | textStream << hexchars[s & 0x0f]; | ||
212 | } | ||
213 | |||
214 | textStream << "</data>" << endl; | ||
215 | textStream << " </image>" << endl; | ||
216 | } | ||
217 | |||
218 | textStream << " </images>" << endl; | ||
219 | textStream << "</drawpad>"; | ||
220 | } | ||
221 | |||
222 | QPixmap* DrawPadCanvas::currentPage() | ||
223 | { | ||
224 | return m_buffers.current(); | ||
225 | } | ||
226 | |||
227 | void DrawPadCanvas::clearAll() | ||
228 | { | ||
229 | m_buffers.clear(); | ||
230 | |||
231 | m_buffers.append(new QPixmap(width(), height())); | ||
232 | m_buffers.current()->fill(Qt::white); | ||
233 | |||
234 | repaint(); | ||
235 | } | ||
236 | |||
237 | void DrawPadCanvas::newPage() | ||
238 | { | ||
239 | m_buffers.insert(m_buffers.at() + 1, new QPixmap(width(), height())); | ||
240 | m_buffers.current()->fill(Qt::white); | ||
241 | repaint(); | ||
242 | } | ||
243 | |||
244 | void DrawPadCanvas::clearPage() | ||
245 | { | ||
246 | m_buffers.current()->fill(Qt::white); | ||
247 | repaint(); | ||
248 | } | ||
249 | |||
250 | void DrawPadCanvas::deletePage() | ||
251 | { | ||
252 | m_buffers.remove(m_buffers.current()); | ||
253 | |||
254 | if (m_buffers.isEmpty()) { | ||
255 | m_buffers.append(new QPixmap(width(), height())); | ||
256 | m_buffers.current()->fill(Qt::white); | ||
257 | } | ||
258 | |||
259 | repaint(); | ||
260 | } | ||
261 | |||
262 | bool DrawPadCanvas::goPreviousPageEnabled() | ||
263 | { | ||
264 | return (m_buffers.current() != m_buffers.getFirst()); | ||
265 | } | ||
266 | |||
267 | bool DrawPadCanvas::goNextPageEnabled() | ||
268 | { | ||
269 | return (m_buffers.current() != m_buffers.getLast()); | ||
270 | } | ||
271 | |||
272 | void DrawPadCanvas::goFirstPage() | ||
273 | { | ||
274 | m_buffers.first(); | ||
275 | repaint(); | ||
276 | } | ||
277 | |||
278 | void DrawPadCanvas::goPreviousPage() | ||
279 | { | ||
280 | m_buffers.prev(); | ||
281 | repaint(); | ||
282 | } | ||
283 | |||
284 | void DrawPadCanvas::goNextPage() | ||
285 | { | ||
286 | m_buffers.next(); | ||
287 | repaint(); | ||
288 | } | ||
289 | |||
290 | void DrawPadCanvas::goLastPage() | ||
291 | { | ||
292 | m_buffers.last(); | ||
293 | repaint(); | ||
294 | } | ||
295 | |||
296 | void DrawPadCanvas::mousePressEvent(QMouseEvent* e) | ||
297 | { | ||
298 | m_pDrawPad->drawMode()->mousePressEvent(e); | ||
299 | } | ||
300 | |||
301 | void DrawPadCanvas::mouseReleaseEvent(QMouseEvent* e) | ||
302 | { | ||
303 | m_pDrawPad->drawMode()->mouseReleaseEvent(e); | ||
304 | } | ||
305 | |||
306 | void DrawPadCanvas::mouseMoveEvent(QMouseEvent* e) | ||
307 | { | ||
308 | m_pDrawPad->drawMode()->mouseMoveEvent(e); | ||
309 | } | ||
310 | |||
311 | void DrawPadCanvas::resizeEvent(QResizeEvent* e) | ||
312 | { | ||
313 | QWidget::resizeEvent(e); | ||
314 | |||
315 | QListIterator<QPixmap> bufferIterator(m_buffers); | ||
316 | |||
317 | for (bufferIterator.toFirst(); bufferIterator.current() != 0; ++bufferIterator) { | ||
318 | int w = width() > bufferIterator.current()->width() ? width() : bufferIterator.current()->width(); | ||
319 | int h = height() > bufferIterator.current()->height() ? height() : bufferIterator.current()->height(); | ||
320 | |||
321 | QPixmap tmpPixmap(*(bufferIterator.current())); | ||
322 | bufferIterator.current()->resize(w, h); | ||
323 | bufferIterator.current()->fill(Qt::white); | ||
324 | |||
325 | bitBlt(bufferIterator.current(), 0, 0, &tmpPixmap, 0, 0, tmpPixmap.width(), tmpPixmap.height()); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | void DrawPadCanvas::paintEvent(QPaintEvent* e) | ||
330 | { | ||
331 | QWidget::paintEvent(e); | ||
332 | |||
333 | QArray<QRect> rects = e->region().rects(); | ||
334 | |||
335 | for (uint i = 0; i < rects.count(); i++) { | ||
336 | QRect r = rects[i]; | ||
337 | bitBlt(this, r.x(), r.y(), m_buffers.current(), r.x(), r.y(), r.width(), r.height()); | ||
338 | } | ||
339 | } | ||