summaryrefslogtreecommitdiffstats
path: root/krita/core/kis_pattern.cc
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /krita/core/kis_pattern.cc
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krita/core/kis_pattern.cc')
-rw-r--r--krita/core/kis_pattern.cc335
1 files changed, 335 insertions, 0 deletions
diff --git a/krita/core/kis_pattern.cc b/krita/core/kis_pattern.cc
new file mode 100644
index 00000000..db6ae0a1
--- /dev/null
+++ b/krita/core/kis_pattern.cc
@@ -0,0 +1,335 @@
+/*
+ * kis_pattern.cc - part of Krayon
+ *
+ * Copyright (c) 2000 Matthias Elter <elter@kde.org>
+ * 2001 John Califf
+ * 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "kis_pattern.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <qpoint.h>
+#include <qsize.h>
+#include <qimage.h>
+#include <qvaluevector.h>
+#include <qmap.h>
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "kis_color.h"
+#include "kis_layer.h"
+#include "kis_paint_device.h"
+
+namespace {
+ struct GimpPatternHeader {
+ Q_UINT32 header_size; /* header_size = sizeof (PatternHeader) + brush name */
+ Q_UINT32 version; /* pattern file version # */
+ Q_UINT32 width; /* width of pattern */
+ Q_UINT32 height; /* height of pattern */
+ Q_UINT32 bytes; /* depth of pattern in bytes : 1, 2, 3 or 4*/
+ Q_UINT32 magic_number; /* GIMP brush magic number */
+ };
+
+ // Yes! This is _NOT_ what my pat.txt file says. It's really not 'GIMP', but 'GPAT'
+ Q_UINT32 const GimpPatternMagic = (('G' << 24) + ('P' << 16) + ('A' << 8) + ('T' << 0));
+}
+
+KisPattern::KisPattern(const QString& file) : super(file), m_hasFile(true)
+{
+}
+
+KisPattern::KisPattern(KisPaintDevice* image, int x, int y, int w, int h)
+ : super(""), m_hasFile(false)
+{
+ // Forcefully convert to RGBA8
+ // XXX profile and exposure?
+ setImage(image->convertToQImage(0, x, y, w, h));
+ setName(image->name());
+}
+
+KisPattern::~KisPattern()
+{
+}
+
+bool KisPattern::load()
+{
+ if (!m_hasFile)
+ return true;
+
+ QFile file(filename());
+ file.open(IO_ReadOnly);
+ QByteArray data = file.readAll();
+ if (!data.isEmpty()) {
+ Q_INT32 startPos = m_data.size();
+
+ m_data.resize(m_data.size() + data.count());
+ memcpy(&m_data[startPos], data.data(), data.count());
+ }
+ file.close();
+ return init();
+}
+
+bool KisPattern::save()
+{
+ QFile file(filename());
+ file.open(IO_WriteOnly | IO_Truncate);
+
+ QTextStream stream(&file);
+ // Header: header_size (24+name length),version,width,height,colourdepth of brush,magic,name
+ // depth: 1 = greyscale, 2 = greyscale + A, 3 = RGB, 4 = RGBA
+ // magic = "GPAT", as a single uint32, the docs are wrong here!
+ // name is UTF-8 (\0-terminated! The docs say nothing about this!)
+ // _All_ data in network order, it seems! (not mentioned in gimp-2.2.8/devel-docs/pat.txt!!)
+ // We only save RGBA at the moment
+ // Version is 1 for now...
+
+ GimpPatternHeader ph;
+ QCString utf8Name = name().utf8();
+ char const* name = utf8Name.data();
+ int nameLength = qstrlen(name);
+
+ ph.header_size = htonl(sizeof(GimpPatternHeader) + nameLength + 1); // trailing 0
+ ph.version = htonl(1);
+ ph.width = htonl(width());
+ ph.height = htonl(height());
+ ph.bytes = htonl(4);
+ ph.magic_number = htonl(GimpPatternMagic);
+
+ QByteArray bytes;
+ bytes.setRawData(reinterpret_cast<char*>(&ph), sizeof(GimpPatternHeader));
+ int wrote = file.writeBlock(bytes);
+ bytes.resetRawData(reinterpret_cast<char*>(&ph), sizeof(GimpPatternHeader));
+
+ if (wrote == -1)
+ return false;
+
+ wrote = file.writeBlock(name, nameLength + 1); // Trailing 0 apparantly!
+ if (wrote == -1)
+ return false;
+
+ int k = 0;
+ bytes.resize(width() * height() * 4);
+ for (Q_INT32 y = 0; y < height(); y++) {
+ for (Q_INT32 x = 0; x < width(); x++) {
+ // RGBA only
+ QRgb pixel = m_img.pixel(x,y);
+ bytes[k++] = static_cast<char>(qRed(pixel));
+ bytes[k++] = static_cast<char>(qGreen(pixel));
+ bytes[k++] = static_cast<char>(qBlue(pixel));
+ bytes[k++] = static_cast<char>(qAlpha(pixel));
+ }
+ }
+
+ wrote = file.writeBlock(bytes);
+ if (wrote == -1)
+ return false;
+
+ file.close();
+
+ return true;
+}
+
+QImage KisPattern::img()
+{
+ return m_img;
+}
+
+bool KisPattern::init()
+{
+ // load Gimp patterns
+ GimpPatternHeader bh;
+ Q_INT32 k;
+ QValueVector<char> name;
+
+ if (sizeof(GimpPatternHeader) > m_data.size()) {
+ return false;
+ }
+
+ memcpy(&bh, &m_data[0], sizeof(GimpPatternHeader));
+ bh.header_size = ntohl(bh.header_size);
+ bh.version = ntohl(bh.version);
+ bh.width = ntohl(bh.width);
+ bh.height = ntohl(bh.height);
+ bh.bytes = ntohl(bh.bytes);
+ bh.magic_number = ntohl(bh.magic_number);
+
+ if (bh.header_size > m_data.size() || bh.header_size == 0) {
+ return false;
+ }
+
+ name.resize(bh.header_size - sizeof(GimpPatternHeader));
+ memcpy(&name[0], &m_data[sizeof(GimpPatternHeader)], name.size());
+
+ if (name[name.size() - 1]) {
+ return false;
+ }
+
+ setName(i18n(&name[0]));
+
+ if (bh.width == 0 || bh.height == 0 || !m_img.create(bh.width, bh.height, 32)) {
+ return false;
+ }
+
+ k = bh.header_size;
+
+ if (bh.bytes == 1) {
+ // Grayscale
+ Q_INT32 val;
+
+ for (Q_UINT32 y = 0; y < bh.height; y++) {
+ for (Q_UINT32 x = 0; x < bh.width; x++, k++) {
+ if (static_cast<Q_UINT32>(k) > m_data.size()) {
+ kdDebug(DBG_AREA_FILE) << "failed in gray\n";
+ return false;
+ }
+
+ val = m_data[k];
+ m_img.setPixel(x, y, qRgb(val, val, val));
+ m_img.setAlphaBuffer(false);
+ }
+ }
+ } else if (bh.bytes == 2) {
+ // Grayscale + A
+ Q_INT32 val;
+ Q_INT32 alpha;
+ for (Q_UINT32 y = 0; y < bh.height; y++) {
+ for (Q_UINT32 x = 0; x < bh.width; x++, k++) {
+ if (static_cast<Q_UINT32>(k + 2) > m_data.size()) {
+ kdDebug(DBG_AREA_FILE) << "failed in grayA\n";
+ return false;
+ }
+
+ val = m_data[k];
+ alpha = m_data[k++];
+ m_img.setPixel(x, y, qRgba(val, val, val, alpha));
+ m_img.setAlphaBuffer(true);
+ }
+ }
+ } else if (bh.bytes == 3) {
+ // RGB without alpha
+ for (Q_UINT32 y = 0; y < bh.height; y++) {
+ for (Q_UINT32 x = 0; x < bh.width; x++) {
+ if (static_cast<Q_UINT32>(k + 3) > m_data.size()) {
+ kdDebug(DBG_AREA_FILE) << "failed in RGB\n";
+ return false;
+ }
+
+ m_img.setPixel(x, y, qRgb(m_data[k],
+ m_data[k + 1],
+ m_data[k + 2]));
+ k += 3;
+ m_img.setAlphaBuffer(false);
+ }
+ }
+ } else if (bh.bytes == 4) {
+ // Has alpha
+ for (Q_UINT32 y = 0; y < bh.height; y++) {
+ for (Q_UINT32 x = 0; x < bh.width; x++) {
+ if (static_cast<Q_UINT32>(k + 4) > m_data.size()) {
+ kdDebug(DBG_AREA_FILE) << "failed in RGBA\n";
+ return false;
+ }
+
+ m_img.setPixel(x, y, qRgba(m_data[k],
+ m_data[k + 1],
+ m_data[k + 2],
+ m_data[k + 3]));
+ k += 4;
+ m_img.setAlphaBuffer(true);
+ }
+ }
+ } else {
+ return false;
+ }
+
+ if (m_img.isNull()) {
+ return false;
+ }
+
+ setWidth(m_img.width());
+ setHeight(m_img.height());
+
+ setValid(true);
+
+ return true;
+}
+
+KisPaintDeviceSP KisPattern::image(KisColorSpace * colorSpace) {
+ // Check if there's already a pattern prepared for this colorspace
+ QMap<QString, KisPaintDeviceSP>::const_iterator it = m_colorspaces.find(colorSpace->id().id());
+ if (it != m_colorspaces.end())
+ return (*it);
+
+ // If not, create one
+ KisPaintDeviceSP layer = new KisPaintDevice(colorSpace, "pattern");
+
+ Q_CHECK_PTR(layer);
+
+ layer->convertFromQImage(m_img,"");
+
+ m_colorspaces[colorSpace->id().id()] = layer;
+ return layer;
+}
+
+Q_INT32 KisPattern::width() const
+{
+ return m_width;
+}
+
+void KisPattern::setWidth(Q_INT32 w)
+{
+ m_width = w;
+}
+
+Q_INT32 KisPattern::height() const
+{
+ return m_height;
+}
+
+void KisPattern::setHeight(Q_INT32 h)
+{
+ m_height = h;
+}
+
+void KisPattern::setImage(const QImage& img)
+{
+ m_hasFile = false;
+ m_img = img;
+ m_img.detach();
+
+ setWidth(img.width());
+ setHeight(img.height());
+
+ setValid(true);
+}
+
+KisPattern* KisPattern::clone() const
+{
+ KisPattern* pattern = new KisPattern("");
+ pattern->setImage(m_img);
+ pattern->setName(name());
+ return pattern;
+}
+
+#include "kis_pattern.moc"