You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/chalk/ui/kis_part_layer.cc

261 lines
8.4 KiB

/*
* 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 repaint where we currently updated
// We use the original geometry
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->geometry());
}
}
void KisPartLayerImpl::setX(TQ_INT32 x) {
TQRect rect = m_doc->geometry();
// 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->geometry();
// 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->geometry();
for (int y2 = y; y2 < h + y; ++y2) {
for (int x2 = x; x2 < w + x; ++x2) {
if (!rect.contains(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"