summaryrefslogtreecommitdiffstats
path: root/chalk/core/kis_paint_device.h
blob: 6c8d7331a160526f0da7b6e3803ee58322b4ee15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
/*
 *  copyright (c) 2002 patrick julien <freak@codepimps.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., 675 mass ave, cambridge, ma 02139, usa.
 */
#ifndef KIS_PAINT_DEVICE_IMPL_H_
#define KIS_PAINT_DEVICE_IMPL_H_

#include <tqcolor.h>
#include <tqobject.h>
#include <tqpixmap.h>
#include <tqptrlist.h>
#include <tqrect.h>
#include <tqvaluelist.h>
#include <tqstring.h>

#include "kis_types.h"
#include "kdebug.h"
#include "kis_global.h"
#include "kis_image.h"
#include "kis_colorspace.h"
#include "kis_canvas_controller.h"
#include "kis_color.h"
#include <koffice_export.h>

class DCOPObject;

class TQImage;
class TQSize;
class TQPoint;
class TQWMatrix;
class TQTimer;

class KNamedCommand;

class KoStore;

class KisExifInfo;
class KisHLineIteratorPixel;
class KisImage;
class KisRectIteratorPixel;
class KisVLineIteratorPixel;
class KisRandomAccessorPixel;
class KisRandomSubAccessorPixel;
class KisUndoAdapter;
class KisFilter;
class KisDataManager;
typedef KSharedPtr<KisDataManager> KisDataManagerSP;

class KisMemento;
typedef KSharedPtr<KisMemento> KisMementoSP;


/**
 * A paint device contains the actual pixel data and offers methods
 * to read and write pixels. A paint device has an integer x,y position
 * (i.e., are not positioned on the image with sub-pixel accuracy).
 * A KisPaintDevice doesn't have any fixed size, the size change dynamicaly
 * when pixels are accessed by an iterator.
 */
class KRITACORE_EXPORT KisPaintDevice
    : public TQObject
    , public KShared
{

        Q_OBJECT
  TQ_OBJECT

public:

    /**
     * Create a new paint device with the specified colorspace.
     *
     * @param colorSpace the colorspace of this paint device
     * @param name for debugging purposes
     */
    KisPaintDevice(KisColorSpace * colorSpace, const char * name = 0);

    /**
     * Create a new paint device with the specified colorspace. The
     * parentLayer will be notified of changes to this paint device.
     *
     * @param parentLayer the layer that contains this paint device.
     * @param colorSpace the colorspace of this paint device
     * @param name for debugging purposes
     */
    KisPaintDevice(KisLayer *parentLayer, KisColorSpace * colorSpace, const char * name = 0);

    KisPaintDevice(const KisPaintDevice& rhs);
    virtual ~KisPaintDevice();
    virtual DCOPObject *dcopObject();

    void lock(bool lock) { m_lock = lock; }

public:

    /**
     * Write the pixels of this paint device into the specified file store.
     */
    virtual bool write(KoStore *store);

    /**
     * Fill this paint device with the pixels from the specified file store.
     */
    virtual bool read(KoStore *store);

public:

    /**
     * Moves the device to these new coordinates (so no incremental move or so)
     */
    virtual void move(TQ_INT32 x, TQ_INT32 y);

    /**
     * Convenience method for the above
     */
    virtual void move(const TQPoint& pt);

    /**
     * Move the paint device to the specified location and make it possible to
     * undo the move.
     */
    virtual KNamedCommand * moveCommand(TQ_INT32 x, TQ_INT32 y);

    /**
     * Returns true of x,y is within the extent of this paint device
     */
    bool tqcontains(TQ_INT32 x, TQ_INT32 y) const;

    /**
     * Convenience method for the above
     */
    bool tqcontains(const TQPoint& pt) const;

    /**
     * Retrieve the bounds of the paint device. The size is not exact,
     * but may be larger if the underlying datamanager works that way.
     * For instance, the tiled datamanager keeps the extent to the nearest
     * multiple of 64.
     */
    virtual void extent(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const;
    virtual TQRect extent() const;

    /**
     * XXX: This should be a temporay hack, awaiting a proper fix.
     *
     * Indicates whether the extent really represents the extent. For example,
     * the KisBackground checkerboard pattern is generated by filling the
     * default tile but it will return an empty extent.
     */
    bool extentIsValid() const;

    /// Convience method for the above
    void setExtentIsValid(bool isValid);

    /**
     * Get the exact bounds of this paint device. This may be very slow,
     * especially on larger paint devices because it does a linear scanline search.
     */
    virtual void exactBounds(TQ_INT32 &x, TQ_INT32 &y, TQ_INT32 &w, TQ_INT32 &h) const;
    virtual TQRect exactBounds() const;
    virtual TQRect exactBoundsOldMethod() const;
    virtual TQRect exactBoundsImprovedOldMethod() const;

    /**
     * Cut the paint device down to the specified rect
     */
    void crop(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h);

    /// Convience method for the above
    void crop(TQRect r);

    /**
     * Complete erase the current paint device. Its size will become 0.
     */
    virtual void clear();

    /**
     * Fill the given rectangle with the given pixel.
     */
    void fill(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h, const TQ_UINT8 *fillPixel);

    /**
     * Read the bytes representing the rectangle described by x, y, w, h into
     * data. If data is not big enough, Chalk will gladly overwrite the rest
     * of your precious memory.
     *
     * Since this is a copy, you need to make sure you have enough memory.
     *
     * Reading from areas not previously initialized will read the default
     * pixel value into data but not initialize that region.
     */
    virtual void readBytes(TQ_UINT8 * data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h);

    /**
     * Copy the bytes in data into the rect specified by x, y, w, h. If the
     * data is too small or uninitialized, Chalk will happily read parts of
     * memory you never wanted to be read.
     *
     * If the data is written to areas of the paint device not previously initialized,
     * the paint device will grow.
     */
    virtual void writeBytes(const TQ_UINT8 * data, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h);

    /**
     * Get the number of contiguous columns starting at x, valid for all values
     * of y between minY and maxY.
     */
    TQ_INT32 numContiguousColumns(TQ_INT32 x, TQ_INT32 minY, TQ_INT32 maxY);

    /**
     * Get the number of contiguous rows starting at y, valid for all values
     * of x between minX and maxX.
     */
    TQ_INT32 numContiguousRows(TQ_INT32 y, TQ_INT32 minX, TQ_INT32 maxX);

    /**
     * Get the row stride at pixel (x, y). This is the number of bytes to add to a
     * pointer to pixel (x, y) to access (x, y + 1).
     */
    TQ_INT32 rowStride(TQ_INT32 x, TQ_INT32 y);

    /**
     * Get a read-only pointer to pixel (x, y).
     */
    KDE_DEPRECATED const TQ_UINT8* pixel(TQ_INT32 x, TQ_INT32 y);

    /**
     * Get a read-write pointer to pixel (x, y).
     */
    KDE_DEPRECATED TQ_UINT8* writablePixel(TQ_INT32 x, TQ_INT32 y);

    /**
     *   Converts the paint device to a different colorspace
     */
    virtual void convertTo(KisColorSpace * dstColorSpace, TQ_INT32 renderingIntent = INTENT_PERCEPTUAL);

    /**
     * Changes the profile of the colorspace of this paint device to the given
     * profile. If the given profile is 0, nothing happens.
     */
    virtual void setProfile(KisProfile * profile);
    
    /**
     * Fill this paint device with the data from img; starting at (offsetX, offsetY)
     * @param srcProfileName name of the RGB profile to interpret the img as. "" is interpreted as sRGB
     */
    virtual void convertFromTQImage(const TQImage& img, const TQString &srcProfileName, TQ_INT32 offsetX = 0, TQ_INT32 offsetY = 0);

    /**
     * Create an RGBA TQImage from a rectangle in the paint device.
     *
     * @param x Left coordinate of the rectangle
     * @param y Top coordinate of the rectangle
     * @param w Width of the rectangle in pixels
     * @param h Height of the rectangle in pixels
     * @param dstProfile RGB profile to use in conversion. May be 0, in which
     * case it's up to the colour strategy to choose a profile (most
     * like sRGB).
     * @param exposure The exposure setting used to render a preview of a high dynamic range image.
     */
    virtual TQImage convertToTQImage(KisProfile *  dstProfile, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h, float exposure = 0.0f);

    /**
     * Create an RGBA TQImage from a rectangle in the paint device. The rectangle is defined by the tqparent image's bounds.
     *
     * @param dstProfile RGB profile to use in conversion. May be 0, in which
     * case it's up to the colour strategy to choose a profile (most
     * like sRGB).
     * @param exposure The exposure setting used to render a preview of a high dynamic range image.
     */
    virtual TQImage convertToTQImage(KisProfile *  dstProfile, float exposure = 0.0f);

    /**
     * Creates a paint device thumbnail of the paint device, retaining the aspect ratio.
     * The width and height of the returned device won't exceed \p maxw and \p maxw, but they may be smaller.
     */

    KisPaintDeviceSP createThumbnailDevice(TQ_INT32 w, TQ_INT32 h);
            
    /**
     * Creates a thumbnail of the paint device, retaining the aspect ratio.
     * The width and height of the returned TQImage won't exceed \p maxw and \p maxw, but they may be smaller.
     * The colors are not corrected for display!
     */
    virtual TQImage createThumbnail(TQ_INT32 maxw, TQ_INT32 maxh);


    /**
     * Fill c and opacity with the values found at x and y.
     *
     * The color values will be transformed from the profile of
     * this paint device to the display profile.
     *
     * @return true if the operation was succesful.
     */
    bool pixel(TQ_INT32 x, TQ_INT32 y, TQColor *c, TQ_UINT8 *opacity);


    /**
     * Fill kc with the values found at x and y. This method differs
     * from the above in using KisColor, which can be of any colorspace
     *
     * The color values will be transformed from the profile of
     * this paint device to the display profile.
     *
     * @return true if the operation was succesful.
     */
    bool pixel(TQ_INT32 x, TQ_INT32 y, KisColor * kc);

    /**
     * Return the KisColor of the pixel at x,y.
     */
    KisColor colorAt(TQ_INT32 x, TQ_INT32 y);

    /**
     * Set the specified pixel to the specified color. Note that this
     * bypasses KisPainter. the PaintDevice is here used as an equivalent
     * to TQImage, not TQPixmap. This means that this is not undoable; also,
     * there is no compositing with an existing value at this location.
     *
     * The color values will be transformed from the display profile to
     * the paint device profile.
     *
     * Note that this will use 8-bit values and may cause a significant
     * degradation when used on 16-bit or hdr quality images.
     *
     * @return true if the operation was succesful
     *
     */
    bool setPixel(TQ_INT32 x, TQ_INT32 y, const TQColor& c, TQ_UINT8 opacity);

    bool setPixel(TQ_INT32 x, TQ_INT32 y, const KisColor& kc);

    KisColorSpace * colorSpace() const;

    KisDataManagerSP dataManager() const;

    /**
     * Replace the pixel data, color strategy, and profile.
     */
    void setData(KisDataManagerSP data, KisColorSpace * colorSpace);

    /**
     * The X offset of the paint device
     */
    TQ_INT32 getX() const;

    /**
     * The Y offset of the paint device
     */
    TQ_INT32 getY() const;

    /**
     * Return the X offset of the paint device
     */
    void setX(TQ_INT32 x);

    /**
     * Return the Y offset of the paint device
     */
    void setY(TQ_INT32 y);


    /**
     * Return the number of bytes a pixel takes.
     */
    virtual TQ_INT32 pixelSize() const;

    /**
     * Return the number of channels a pixel takes
     */
    virtual TQ_INT32 nChannels() const;

    /**
     * Return the image that contains this paint device, or 0 if it is not
     * part of an image. This is the same as calling parentLayer()->image().
     */
    KisImage *image() const;

    /**
     * Returns the KisLayer that contains this paint device, or 0 if this is not
     * part of a layer.
     */
    KisLayer *parentLayer() const;

    /**
     * Set the KisLayer that contains this paint device, or 0 if this is not
     * part of a layer.
     */
    void setParentLayer(KisLayer *parentLayer);

    /**
     * Add the specified rect top the tqparent layer (if present)
     */
    virtual void setDirty(const TQRect & rc);

    /**
     * Set the tqparent layer completely dirty, if this paint device has one.
     */
    virtual void setDirty();
    
    
    /**
     * Mirror the device along the X axis
     */
    void mirrorX();
    /**
     * Mirror the device along the Y axis
     */
    void mirrorY();

    KisMementoSP getMemento();
    void rollback(KisMementoSP memento);
    void rollforward(KisMementoSP memento);

    /**
     * This function return an iterator which points to the first pixel of an rectangle
     */
    KisRectIteratorPixel createRectIterator(TQ_INT32 left, TQ_INT32 top, TQ_INT32 w, TQ_INT32 h, bool writable);

    /**
     * This function return an iterator which points to the first pixel of a horizontal line
     */
    KisHLineIteratorPixel createHLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, bool writable);

    /**
     * This function return an iterator which points to the first pixel of a vertical line
     */
    KisVLineIteratorPixel createVLineIterator(TQ_INT32 x, TQ_INT32 y, TQ_INT32 h, bool writable);

    /**
     * This function creates a random accessor which allow to randomly access any pixels on
     * the paint device.
     * <b>Note:</b> random access is way slower than iterators, allways use iterators whenever
     * you can
     */
    KisRandomAccessorPixel createRandomAccessor(TQ_INT32 x, TQ_INT32 y, bool writable);
    
    /**
     * This function create a random accessor which can easily access to sub pixel values.
     */
    KisRandomSubAccessorPixel createRandomSubAccessor();
    
    /** Get the current selection or create one if this paintdevice hasn't got a selection yet. */
    KisSelectionSP selection();

    /** Adds the specified selection to the currently active selection for this paintdevice */
    void addSelection(KisSelectionSP selection);

    /** Subtracts the specified selection from the currently active selection for this paindevice */
    void subtractSelection(KisSelectionSP selection);

    /** Whether there is a valid selection for this paintdevice. */
    bool hasSelection();

   /** Whether the previous selection was deselected. */
    bool selectionDeselected();

    /** Deselect the selection for this paintdevice. */
    void deselect();

    /** Reinstates the old selection */
    void reselect();
        
    /** Clear the selected pixels from the paint device */
    void clearSelection();

    /**
     * Apply a tqmask to the image data, i.e. multiply each pixel's opacity by its
     * selectedness in the tqmask.
     */
    void applySelectionMask(KisSelectionSP tqmask);

    /**
     * Sets the selection of this paint device to the new selection,
     * returns the old selection, if there was an old selection,
     * otherwise 0
     */
    KisSelectionSP setSelection(KisSelectionSP selection);

    /**
     * Notify the owning image that the current selection has changed.
     */
    void emitSelectionChanged();

    /**
     * Notify the owning image that the current selection has changed.
     *
     * @param r the area for which the selection has changed
     */
    void emitSelectionChanged(const TQRect& r);

    
    KisUndoAdapter *undoAdapter() const;

    /**
     * Return the exifInfo associated with this layer. If no exif infos are
     * available, the function will create it.
     */
    KisExifInfo* exifInfo();
    /**
     * This function return true if the layer has exif info associated with it.
     */
    bool hasExifInfo() { return m_exifInfo != 0; }
signals:
    void positionChanged(KisPaintDeviceSP device);
    void ioProgress(TQ_INT8 percentage);
    void profileChanged(KisProfile *  profile);

private slots:

    void runBackgroundFilters();
    
private:
    KisPaintDevice& operator=(const KisPaintDevice&);

protected:
    KisDataManagerSP m_datamanager;
    
private:
    /* The KisLayer that contains this paint device, or 0 if this is not 
     * part of a layer.
     */
    KisLayer *m_parentLayer;

    bool m_extentIsValid;

    TQ_INT32 m_x;
    TQ_INT32 m_y;
    KisColorSpace * m_colorSpace;
    // Cached for quick access
    TQ_INT32 m_pixelSize;
    TQ_INT32 m_nChannels;

    // Whether the selection is active
    bool m_hasSelection;
    bool m_selectionDeselected;
    
    // Contains the actual selection. For now, there can be only
    // one selection per layer. XXX: is this a limitation?
    KisSelectionSP m_selection;
    
    DCOPObject * m_dcop;

    KisExifInfo* m_exifInfo;

    TQValueList<KisFilter*> m_longRunningFilters;
    TQTimer * m_longRunningFilterTimer;

    bool m_lock;
};

inline TQ_INT32 KisPaintDevice::pixelSize() const
{
    Q_ASSERT(m_pixelSize > 0);
    return m_pixelSize;
}

inline TQ_INT32 KisPaintDevice::nChannels() const
{
    Q_ASSERT(m_nChannels > 0);
    return m_nChannels;
;
}

inline KisColorSpace * KisPaintDevice::colorSpace() const
{
    Q_ASSERT(m_colorSpace != 0);
        return m_colorSpace;
}


inline TQ_INT32 KisPaintDevice::getX() const
{
    return m_x;
}

inline TQ_INT32 KisPaintDevice::getY() const
{
    return m_y;
}

#endif // KIS_PAINT_DEVICE_IMPL_H_