File indexing completed on 2024-06-16 04:09:57

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #ifndef kpAbstractImageSelection_H
0030 #define kpAbstractImageSelection_H
0031 
0032 
0033 #include "kpImageSelectionTransparency.h"
0034 #include "layers/selections/kpAbstractSelection.h"
0035 #include "imagelib/kpImage.h"
0036 
0037 
0038 //
0039 // An abstract selection with optional image content and background
0040 // subtraction.  If there is image content, it is known as a "floating
0041 // selection" that hovers above the document.  Otherwise, it is an
0042 // image selection "border", that highlights pixels of the document, and
0043 // may later be upgraded to a floating selection by giving it an image
0044 // consisting of those pixels.
0045 //
0046 // The images passed to this class (known as "base images") should have all
0047 // pixels, outside of the border, set to transparent.  However, nothing
0048 // enforces this.  Pixels on, or inside, the border might be opaque or
0049 // transparent, depending on the content.
0050 //
0051 // The "transparent image" is the base image with background subtraction
0052 // (kpImageSelectionTransparency) applied.  This is automatically computed.
0053 //
0054 // The boundingRect() is the size of the border.  The base image must be of
0055 // exactly the same size, except that the base image is allowed to be null
0056 // (for a selection that only consists of a border).
0057 //
0058 // Instead of copying selections' images to the clipboard, we copy
0059 // selections, to preserve the border across KolourPaint instances.
0060 // Background subtraction is not copied to the clipboard so that the base
0061 // image is affected by the background subtraction of the destination
0062 // KolourPaint window.
0063 //
0064 class kpAbstractImageSelection : public kpAbstractSelection
0065 {
0066 Q_OBJECT
0067 
0068 //
0069 // Initialization
0070 //
0071 
0072 protected:
0073     // (Call these in subclass constructors)
0074     kpAbstractImageSelection (const kpImageSelectionTransparency &transparency =
0075         kpImageSelectionTransparency ());
0076 
0077     kpAbstractImageSelection (const QRect &rect,
0078         const kpImage &baseImage = kpImage (),
0079         const kpImageSelectionTransparency &transparency =
0080             kpImageSelectionTransparency ());
0081 
0082     kpAbstractImageSelection (const QRect &rect,
0083         const kpImageSelectionTransparency &transparency =
0084             kpImageSelectionTransparency ());
0085 
0086     // (Call this in subclass implementations of operator=)
0087     kpAbstractImageSelection &operator= (const kpAbstractImageSelection &rhs);
0088 
0089 public:
0090     // (Covariant return-type specialization of superclass pure virtual method)
0091     kpAbstractImageSelection *clone () const override = 0;
0092 
0093     ~kpAbstractImageSelection () override;
0094 
0095 
0096 //
0097 // Marshalling
0098 //
0099 
0100 public:
0101     // You must override this if you have extra serializable fields.
0102     // Remember to call this base implementation before your code.
0103     bool readFromStream (QDataStream &stream) override;
0104 
0105     // You must override this if you have extra serializable fields.
0106     // Remember to call this base implementation before your code.
0107     void writeToStream (QDataStream &stream) const override;
0108 
0109 
0110 //
0111 // General Queries
0112 //
0113 
0114 public:
0115     QString name () const override;
0116 
0117     // You must override this, if you have extra fields that take a
0118     // non-constant amount of space, and add the size returned by this
0119     // implementation.
0120     kpCommandSize::SizeType size () const override;
0121 
0122     // Same as virtual size() (it even calls it) but subtracts the size of the
0123     // baseImage().
0124     //
0125     // kpCommand's store the kpImage's they are working on.  These images may
0126     // be from documents or selections.  In the case of a selection, the
0127     // selection's baseImage() is identical to that image, but takes no extra
0128     // space due to kpImage's copy-on-write.  This method fixes that
0129     // double-counting of baseImage()'s size.
0130     //
0131     // The size of the internal transparency() mask is still included
0132     // (see recalculateTransparencyMask()).
0133     //
0134     // sync: kpImage copy-on-write behavior
0135     //
0136     // TODO: Check all size() implementations are correct since we've
0137     //       started removing the old kpSelection::setPixmap(QPixmap())
0138     //       (now kpAbstractImageSelection::setBaseImage(kpImage()) or
0139     //        kpAbstractImageSelection::deleteContent()) space saving hack.
0140     kpCommandSize::SizeType sizeWithoutImage () const;
0141 
0142 
0143 //
0144 // Dimensions
0145 //
0146 
0147 public:
0148     int minimumWidth () const override;
0149     int minimumHeight () const override;
0150 
0151 
0152 //
0153 // Shape Mask
0154 //
0155 // These methods do not access any class instance fields.
0156 //
0157 
0158 public:
0159     // Returns the mask corresponding to the shape of the selection.
0160     //
0161     // If <nullForRectangular> is set, the method _may_ return a null
0162     // bitmap if the selection is rectangular.
0163     //
0164     // This base implementation calls calculatePoints() and ignores
0165     // <nullForRectangular>.
0166     //
0167     // You should override this if you can implement it more efficiently or
0168     // if you can honor <nullForRectangular>.
0169     //
0170     // Note: This must be consistent with the outputs of calculatePoints() and
0171     //       shapeRegion().
0172     //
0173     // TODO: Try to get rid of this method since it's slow.
0174     virtual QBitmap shapeBitmap (bool nullForRectangular = false) const;
0175 
0176     // Returns the region corresponding to the shape of the selection
0177     // e.g. elliptical region for an elliptical selection.
0178     //
0179     // Very slow.
0180     //
0181     // Note: This must be consistent with the outputs of calculatePoints() and
0182     //       shapeRegion().
0183     //
0184     // OPT: QRegion is probably incredibly slow - cache
0185     virtual QRegion shapeRegion () const = 0;
0186 
0187     // Returns the given <image> with the pixels outside of the selection's
0188     // shape set to transparent.
0189     //
0190     // Very slow.
0191     //
0192     // ASSUMPTION: The image has the same dimensions as the selection.
0193     kpImage givenImageMaskedByShape (const kpImage &image) const;
0194 
0195 
0196 //
0197 // Content - Base Image
0198 //
0199 
0200 public:
0201     // Returns whether there's a non-null base image.
0202     bool hasContent () const override;
0203 
0204     void deleteContent () override;
0205 
0206 public:
0207     kpImage baseImage () const;
0208     void setBaseImage (const kpImage &baseImage);
0209 
0210 
0211 //
0212 // Background Subtraction
0213 //
0214 
0215 public:
0216     kpImageSelectionTransparency transparency () const;
0217 
0218     // Returns whether or not the selection changed due to setting the
0219     // transparency info.  If <checkTransparentPixmapChanged> is set,
0220     // it will try harder to return false (although the check is
0221     // expensive).
0222     bool setTransparency (const kpImageSelectionTransparency &transparency,
0223                           bool checkTransparentPixmapChanged = false);
0224 
0225 private:
0226     // Updates the selection transparency (a.k.a. background subtraction) mask
0227     // so that transparentImage() will work.
0228     //
0229     // Called when the base image or selection transparency changes.
0230     void recalculateTransparencyMaskCache ();
0231 
0232 public:
0233     // Returns baseImage() after applying kpImageSelectionTransparency
0234     kpImage transparentImage () const;
0235 
0236 
0237 //
0238 // Mutation - Effects
0239 //
0240 
0241 public:
0242     // Overwrites the base image with the selection's shape (e.g. ellipse)
0243     // filled in with <color>.  See shapeBitmap().
0244     void fill (const kpColor &color);
0245 
0246     virtual void flip (bool horiz, bool vert);
0247 
0248 
0249 //
0250 // Rendering
0251 //
0252 
0253 public:
0254     // (using transparent image)
0255     void paint (QImage *destPixmap, const QRect &docRect) const override;
0256 
0257     // (using base image)
0258     void paintWithBaseImage (QImage *destPixmap, const QRect &docRect) const;
0259 
0260 
0261 private:
0262     struct kpAbstractImageSelectionPrivate * const d;
0263 };
0264 
0265 
0266 #endif  // kpAbstractImageSelection_H