|
|
|
/*
|
|
|
|
* Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
|
|
|
|
* (c) 2005 Bart Coppens <kde@bartcoppens.be>
|
|
|
|
*
|
|
|
|
* 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 "tqpaintdevice.h"
|
|
|
|
#include "tqpixmap.h"
|
|
|
|
#include "tqimage.h"
|
|
|
|
#include "tqpainter.h"
|
|
|
|
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include "KoDocument.h"
|
|
|
|
#include "KoDocumentChild.h"
|
|
|
|
#include "KoFrame.h"
|
|
|
|
#include "KoView.h"
|
|
|
|
|
|
|
|
#include "kis_layer.h"
|
|
|
|
#include "kis_types.h"
|
|
|
|
#include "kis_colorspace_factory_registry.h"
|
|
|
|
#include "kis_part_layer.h"
|
|
|
|
#include "kis_group_layer.h"
|
|
|
|
#include "kis_factory.h"
|
|
|
|
#include "kis_paint_device.h"
|
|
|
|
#include <kis_meta_registry.h>
|
|
|
|
|
|
|
|
KisChildDoc::KisChildDoc ( KisDoc * kisDoc, const TQRect & rect, KoDocument * childDoc )
|
|
|
|
: KoDocumentChild( kisDoc, childDoc, rect )
|
|
|
|
, m_doc(kisDoc)
|
|
|
|
, m_partLayer(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KisChildDoc::KisChildDoc ( KisDoc * kisDoc )
|
|
|
|
: KoDocumentChild( kisDoc)
|
|
|
|
, m_partLayer(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KisChildDoc::~KisChildDoc ()
|
|
|
|
{
|
|
|
|
// XXX doesn't this get deleted by itself or by anything else? Certainly looks so
|
|
|
|
// (otherwise I get a double deletion of a TQObject, and chalk crashes)
|
|
|
|
//delete m_doc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KisPartLayerImpl::KisPartLayerImpl(KisImageSP img, KisChildDoc * doc)
|
|
|
|
: super(img, i18n("Embedded Document"), OPACITY_OPAQUE), m_doc(doc)
|
|
|
|
{
|
|
|
|
m_cache = new KisPaintDevice(
|
|
|
|
KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""), name().latin1() );
|
|
|
|
m_activated = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KisPartLayerImpl::~KisPartLayerImpl()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KisLayerSP KisPartLayerImpl::clone() const {
|
|
|
|
return new KisPartLayerImpl(image(), childDoc());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called when the layer is made active
|
|
|
|
void KisPartLayerImpl::childActivated(KoDocumentChild* child)
|
|
|
|
{
|
|
|
|
// Clear the image, so that if we move the part while activated, no ghosts show up
|
|
|
|
if (!m_activated && child == m_doc) {
|
|
|
|
TQRect rect = extent();
|
|
|
|
m_activated = true;
|
|
|
|
setDirty(rect);
|
|
|
|
TQPtrList<KoView> views = child->parentDocument()->views();
|
|
|
|
Q_ASSERT(views.count());
|
|
|
|
// XXX iterate over views
|
|
|
|
connect(views.at(0), TQT_SIGNAL(activated(bool)),
|
|
|
|
this, TQT_SLOT(childDeactivated(bool)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called when another layer is made inactive
|
|
|
|
void KisPartLayerImpl::childDeactivated(bool activated)
|
|
|
|
{
|
|
|
|
// We probably changed, notify the image that it needs to tqrepaint where we currently updated
|
|
|
|
// We use the original tqgeometry
|
|
|
|
if (m_activated && !activated /* no clue, but debugging suggests it is false here */) {
|
|
|
|
TQPtrList<KoView> views = m_doc->parentDocument()->views();
|
|
|
|
Q_ASSERT(views.count());
|
|
|
|
views.at(0)->disconnect(TQT_SIGNAL(activated(bool)));
|
|
|
|
m_activated = false;
|
|
|
|
setDirty(m_doc->tqgeometry());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KisPartLayerImpl::setX(TQ_INT32 x) {
|
|
|
|
TQRect rect = m_doc->tqgeometry();
|
|
|
|
|
|
|
|
// KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here,
|
|
|
|
// since the part is not necesarily started at (0,0)
|
|
|
|
rect.moveBy(x - this->x(), 0);
|
|
|
|
m_doc->setGeometry(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KisPartLayerImpl::setY(TQ_INT32 y) {
|
|
|
|
TQRect rect = m_doc->tqgeometry();
|
|
|
|
|
|
|
|
// KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here,
|
|
|
|
// since the part is not necesarily started at (0,0)
|
|
|
|
rect.moveBy(0, y - this->y());
|
|
|
|
m_doc->setGeometry(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KisPartLayerImpl::paintSelection(TQImage &img, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h) {
|
|
|
|
uchar *j = img.bits();
|
|
|
|
TQRect rect = m_doc->tqgeometry();
|
|
|
|
|
|
|
|
for (int y2 = y; y2 < h + y; ++y2) {
|
|
|
|
for (int x2 = x; x2 < w + x; ++x2) {
|
|
|
|
if (!rect.tqcontains(x2, y2)) {
|
|
|
|
TQ_UINT8 g = (*(j + 0) + *(j + 1 ) + *(j + 2 )) / 9;
|
|
|
|
*(j+0) = 165+g;
|
|
|
|
*(j+1) = 128+g;
|
|
|
|
*(j+2) = 128+g;
|
|
|
|
}
|
|
|
|
j+=4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
KisPaintDeviceSP KisPartLayerImpl::prepareProjection(KisPaintDeviceSP projection, const TQRect& r)
|
|
|
|
{
|
|
|
|
if (!m_doc || !m_doc->document() || m_activated) return 0;
|
|
|
|
|
|
|
|
m_cache->clear();
|
|
|
|
|
|
|
|
TQRect intersection(r.intersect(exactBounds()));
|
|
|
|
if (intersection.isEmpty())
|
|
|
|
return m_cache;
|
|
|
|
// XXX: have a look at the comments and see if they still truthfully represent the code :/
|
|
|
|
|
|
|
|
// We know the embedded part's size through the ChildDoc
|
|
|
|
// We move it to (0,0), since that is what we will start painting from in paintEverything.
|
|
|
|
TQRect embedRect(intersection);
|
|
|
|
embedRect.moveBy(- exactBounds().x(), - exactBounds().y());
|
|
|
|
TQRect paintRect(exactBounds());
|
|
|
|
paintRect.moveBy(- exactBounds().x(), - exactBounds().y());
|
|
|
|
|
|
|
|
TQPixmap pm1(projection->convertToTQImage(0 /*srgb XXX*/,
|
|
|
|
intersection.x(), intersection.y(),
|
|
|
|
intersection.width(), intersection.height()));
|
|
|
|
TQPixmap pm2(extent().width(), extent().height());
|
|
|
|
copyBlt(&pm2, embedRect.x(), embedRect.y(), &pm1,
|
|
|
|
0, 0, embedRect.width(), embedRect.height());
|
|
|
|
TQPainter painter(&pm2);
|
|
|
|
painter.setClipRect(embedRect);
|
|
|
|
|
|
|
|
// KWord's KWPartFrameSet::drawFrameContents has some interesting remarks concerning
|
|
|
|
// the semantics of the paintEverything call.
|
|
|
|
// Since a Chalk Device really is displaysize/zoom agnostic, caring about zoom is not
|
|
|
|
// really as important here. What we paint at the moment, is just (0,0)x(w,h)
|
|
|
|
// Paint transparent, no zoom:
|
|
|
|
m_doc->document()->paintEverything(painter, paintRect, true);
|
|
|
|
|
|
|
|
copyBlt(&pm1, 0, 0, &pm2,
|
|
|
|
embedRect.x(), embedRect.y(), embedRect.width(), embedRect.height());
|
|
|
|
TQImage qimg = pm1.convertToImage();
|
|
|
|
|
|
|
|
//assume the part is sRGB for now, and that "" is sRGB
|
|
|
|
// And we need to paint offsetted
|
|
|
|
m_cache->convertFromTQImage(qimg, "", intersection.left(), intersection.top());
|
|
|
|
|
|
|
|
return m_cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQImage KisPartLayerImpl::createThumbnail(TQ_INT32 w, TQ_INT32 h) {
|
|
|
|
TQRect bounds(exactBounds());
|
|
|
|
TQPixmap pm(w, h);
|
|
|
|
TQPainter painter(&pm);
|
|
|
|
|
|
|
|
painter.fillRect(0, 0, w, h, TQt::white);
|
|
|
|
|
|
|
|
painter.scale(w / bounds.width(), h / bounds.height());
|
|
|
|
m_doc->document()->paintEverything(painter, bounds);
|
|
|
|
TQImage qimg = pm.convertToImage();
|
|
|
|
|
|
|
|
return qimg;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KisPartLayerImpl::saveToXML(TQDomDocument doc, TQDomElement elem)
|
|
|
|
{
|
|
|
|
TQDomElement embeddedElement = doc.createElement("layer");
|
|
|
|
embeddedElement.setAttribute("name", name());
|
|
|
|
|
|
|
|
// x and y are loaded from the rect element in the embedded object tag
|
|
|
|
embeddedElement.setAttribute("x", 0);
|
|
|
|
embeddedElement.setAttribute("y", 0);
|
|
|
|
|
|
|
|
embeddedElement.setAttribute("opacity", opacity());
|
|
|
|
embeddedElement.setAttribute("compositeop", compositeOp().id().id());
|
|
|
|
embeddedElement.setAttribute("visible", visible());
|
|
|
|
embeddedElement.setAttribute("locked", locked());
|
|
|
|
embeddedElement.setAttribute("layertype", "partlayer");
|
|
|
|
elem.appendChild(embeddedElement);
|
|
|
|
|
|
|
|
TQDomElement objectElem = childDoc()->save(doc);
|
|
|
|
embeddedElement.appendChild(objectElem);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
KisConnectPartLayerVisitor::KisConnectPartLayerVisitor(KisImageSP img, KisView* view, bool mode)
|
|
|
|
: m_img(img), m_view(view), m_connect(mode)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KisConnectPartLayerVisitor::visit(KisGroupLayer *layer) {
|
|
|
|
KisLayerSP child = layer->lastChild();
|
|
|
|
|
|
|
|
while (child) {
|
|
|
|
child->accept(*this);
|
|
|
|
child = child->prevSibling();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KisConnectPartLayerVisitor::visit(KisPartLayer *layer) {
|
|
|
|
if (m_connect) {
|
|
|
|
TQObject::connect(m_view, TQT_SIGNAL(childActivated(KoDocumentChild*)),
|
|
|
|
layer, TQT_SLOT(childActivated(KoDocumentChild*)));
|
|
|
|
} else {
|
|
|
|
TQObject::disconnect(m_view, TQT_SIGNAL(childActivated(KoDocumentChild*)), layer, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KisConnectPartLayerVisitor::visit(KisPaintLayer*) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KisConnectPartLayerVisitor::visit(KisAdjustmentLayer*) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kis_part_layer.moc"
|