krita

kis_part_layer.cc

00001 /*
00002  *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
00003  *            (c) 2005 Bart Coppens <kde@bartcoppens.be>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  */
00019 #include "qpaintdevice.h"
00020 #include "qpixmap.h"
00021 #include "qimage.h"
00022 #include "qpainter.h"
00023 
00024 #include <klocale.h>
00025 
00026 #include "KoDocument.h"
00027 #include "KoDocumentChild.h"
00028 #include "KoFrame.h"
00029 #include "KoView.h"
00030 
00031 #include "kis_layer.h"
00032 #include "kis_types.h"
00033 #include "kis_colorspace_factory_registry.h"
00034 #include "kis_part_layer.h"
00035 #include "kis_group_layer.h"
00036 #include "kis_factory.h"
00037 #include "kis_paint_device.h"
00038 #include <kis_meta_registry.h>
00039 
00040 KisChildDoc::KisChildDoc ( KisDoc * kisDoc, const QRect & rect, KoDocument * childDoc )
00041     : KoDocumentChild( kisDoc, childDoc, rect )
00042     , m_doc(kisDoc)
00043     , m_partLayer(0)
00044 {
00045 }
00046 
00047 
00048 KisChildDoc::KisChildDoc ( KisDoc * kisDoc )
00049     : KoDocumentChild( kisDoc)
00050     , m_partLayer(0)
00051 {
00052 }
00053 
00054 KisChildDoc::~KisChildDoc ()
00055 {
00056     // XXX doesn't this get deleted by itself or by anything else? Certainly looks so
00057     // (otherwise I get a double deletion of a QObject, and krita crashes)
00058     //delete m_doc;
00059 }
00060 
00061 
00062 KisPartLayerImpl::KisPartLayerImpl(KisImageSP img, KisChildDoc * doc)
00063     : super(img, i18n("Embedded Document"), OPACITY_OPAQUE), m_doc(doc)
00064 {
00065     m_cache = new KisPaintDevice(
00066             KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""), name().latin1() );
00067     m_activated = false;
00068 }
00069 
00070 KisPartLayerImpl::~KisPartLayerImpl()
00071 {
00072 }
00073 
00074 KisLayerSP KisPartLayerImpl::clone() const {
00075     return new KisPartLayerImpl(image(), childDoc());
00076 }
00077 
00078 // Called when the layer is made active
00079 void KisPartLayerImpl::childActivated(KoDocumentChild* child)
00080 {
00081     // Clear the image, so that if we move the part while activated, no ghosts show up
00082     if (!m_activated && child == m_doc) {
00083         QRect rect = extent();
00084         m_activated = true;
00085         setDirty(rect);
00086         QPtrList<KoView> views = child->parentDocument()->views();
00087         Q_ASSERT(views.count());
00088         // XXX iterate over views
00089         connect(views.at(0), SIGNAL(activated(bool)),
00090                 this, SLOT(childDeactivated(bool)));
00091     }
00092 }
00093 
00094 // Called when another layer is made inactive
00095 void KisPartLayerImpl::childDeactivated(bool activated)
00096 {
00097     // We probably changed, notify the image that it needs to repaint where we currently updated
00098     // We use the original geometry
00099     if (m_activated && !activated /* no clue, but debugging suggests it is false here */) {
00100         QPtrList<KoView> views = m_doc->parentDocument()->views();
00101         Q_ASSERT(views.count());
00102         views.at(0)->disconnect(SIGNAL(activated(bool)));
00103         m_activated = false;
00104         setDirty(m_doc->geometry());
00105     }
00106 }
00107 
00108 void KisPartLayerImpl::setX(Q_INT32 x) {
00109     QRect rect = m_doc->geometry();
00110 
00111     // KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here,
00112     // since the part is not necesarily started at (0,0)
00113     rect.moveBy(x - this->x(), 0);
00114     m_doc->setGeometry(rect);
00115 }
00116 
00117 void KisPartLayerImpl::setY(Q_INT32 y) {
00118     QRect rect = m_doc->geometry();
00119 
00120     // KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here,
00121     // since the part is not necesarily started at (0,0)
00122     rect.moveBy(0, y - this->y());
00123     m_doc->setGeometry(rect);
00124 }
00125 
00126 void KisPartLayerImpl::paintSelection(QImage &img, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h) {
00127     uchar *j = img.bits();
00128     QRect rect = m_doc->geometry();
00129 
00130     for (int y2 = y; y2 < h + y; ++y2) {
00131         for (int x2 = x; x2 < w + x; ++x2) {
00132             if (!rect.contains(x2, y2)) {
00133                 Q_UINT8 g = (*(j + 0)  + *(j + 1 ) + *(j + 2 )) / 9;
00134                 *(j+0) = 165+g;
00135                 *(j+1) = 128+g;
00136                 *(j+2) = 128+g;
00137             }
00138             j+=4;
00139         }
00140     }
00141 
00142 }
00143 
00144 KisPaintDeviceSP KisPartLayerImpl::prepareProjection(KisPaintDeviceSP projection, const QRect& r)
00145 {
00146     if (!m_doc || !m_doc->document() || m_activated) return 0;
00147 
00148     m_cache->clear();
00149 
00150     QRect intersection(r.intersect(exactBounds()));
00151     if (intersection.isEmpty())
00152         return m_cache;
00153     // XXX: have a look at the comments and see if they still truthfully represent the code :/
00154 
00155     // We know the embedded part's size through the ChildDoc
00156     // We move it to (0,0), since that is what we will start painting from in paintEverything.
00157     QRect embedRect(intersection);
00158     embedRect.moveBy(- exactBounds().x(), - exactBounds().y());
00159     QRect paintRect(exactBounds());
00160     paintRect.moveBy(- exactBounds().x(), - exactBounds().y());
00161 
00162     QPixmap pm1(projection->convertToQImage(0 /*srgb XXX*/,
00163                                               intersection.x(), intersection.y(),
00164                                               intersection.width(), intersection.height()));
00165     QPixmap pm2(extent().width(), extent().height());
00166     copyBlt(&pm2, embedRect.x(), embedRect.y(), &pm1,
00167              0, 0, embedRect.width(), embedRect.height());
00168     QPainter painter(&pm2);
00169     painter.setClipRect(embedRect);
00170 
00171     // KWord's KWPartFrameSet::drawFrameContents has some interesting remarks concerning
00172     // the semantics of the paintEverything call.
00173     // Since a Krita Device really is displaysize/zoom agnostic, caring about zoom is not
00174     // really as important here. What we paint at the moment, is just (0,0)x(w,h)
00175     // Paint transparent, no zoom:
00176     m_doc->document()->paintEverything(painter, paintRect, true);
00177 
00178     copyBlt(&pm1, 0, 0, &pm2,
00179              embedRect.x(), embedRect.y(), embedRect.width(), embedRect.height());
00180     QImage qimg = pm1.convertToImage();
00181 
00182     //assume the part is sRGB for now, and that "" is sRGB
00183     // And we need to paint offsetted
00184     m_cache->convertFromQImage(qimg, "", intersection.left(), intersection.top());
00185 
00186     return m_cache;
00187 }
00188 
00189 QImage KisPartLayerImpl::createThumbnail(Q_INT32 w, Q_INT32 h) {
00190     QRect bounds(exactBounds());
00191     QPixmap pm(w, h);
00192     QPainter painter(&pm);
00193 
00194     painter.fillRect(0, 0, w, h, Qt::white);
00195 
00196     painter.scale(w / bounds.width(), h / bounds.height());
00197     m_doc->document()->paintEverything(painter, bounds);
00198     QImage qimg = pm.convertToImage();
00199 
00200     return qimg;
00201 }
00202 
00203 bool KisPartLayerImpl::saveToXML(QDomDocument doc, QDomElement elem)
00204 {
00205     QDomElement embeddedElement = doc.createElement("layer");
00206     embeddedElement.setAttribute("name", name());
00207 
00208     // x and y are loaded from the rect element in the embedded object tag
00209     embeddedElement.setAttribute("x", 0);
00210     embeddedElement.setAttribute("y", 0);
00211 
00212     embeddedElement.setAttribute("opacity", opacity());
00213     embeddedElement.setAttribute("compositeop", compositeOp().id().id());
00214     embeddedElement.setAttribute("visible", visible());
00215     embeddedElement.setAttribute("locked", locked());
00216     embeddedElement.setAttribute("layertype", "partlayer");
00217     elem.appendChild(embeddedElement);
00218 
00219     QDomElement objectElem = childDoc()->save(doc);
00220     embeddedElement.appendChild(objectElem);
00221 
00222     return true;
00223 }
00224 
00225 KisConnectPartLayerVisitor::KisConnectPartLayerVisitor(KisImageSP img, KisView* view, bool mode)
00226     : m_img(img), m_view(view), m_connect(mode)
00227 {
00228 }
00229 
00230 bool KisConnectPartLayerVisitor::visit(KisGroupLayer *layer) {
00231     KisLayerSP child = layer->lastChild();
00232 
00233     while (child) {
00234         child->accept(*this);
00235         child = child->prevSibling();
00236     }
00237 
00238     return true;
00239 }
00240 
00241 bool KisConnectPartLayerVisitor::visit(KisPartLayer *layer) {
00242     if (m_connect) {
00243         QObject::connect(m_view, SIGNAL(childActivated(KoDocumentChild*)),
00244                          layer, SLOT(childActivated(KoDocumentChild*)));
00245     } else {
00246         QObject::disconnect(m_view, SIGNAL(childActivated(KoDocumentChild*)), layer, 0 );
00247     }
00248 
00249     return true;
00250 }
00251 
00252 bool KisConnectPartLayerVisitor::visit(KisPaintLayer*) {
00253     return true;
00254 }
00255 
00256 bool KisConnectPartLayerVisitor::visit(KisAdjustmentLayer*) {
00257     return true;
00258 }
00259 
00260 #include "kis_part_layer.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys