compile
[kdegraphics.git] / kolourpaint / pixmapfx / kpPixmapFX.h
blob83117052fbf3184386604529ad419e2d25bb1901
2 // REFACTOR: Split this class into one for each distinct functionality category
3 // (e.g. effects, mask operations)?
5 /*
6 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
7 All rights reserved.
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #ifndef KP_PIXMAP_FX_H
33 #define KP_PIXMAP_FX_H
36 #include <qrect.h>
37 #include <qstring.h>
39 #include <klocalizedstring.h>
41 #include <kpColor.h>
44 class QBitmap;
45 class QColor;
46 class QImage;
47 class QMatrix;
48 class QPainter;
49 class QPen;
50 class QPixmap;
51 class QPoint;
52 class QPolygon;
53 class QRect;
54 class QString;
55 class QWidget;
58 class kpAbstractSelection;
62 // QPixmap (view) Manipulation.
64 // Anything that is supposed to be manipulating the document contents
65 // (i.e. kpImage), should be moved to kpPainter.
67 // kpPainter uses us for its Qt backend but we don't use kpPainter.
68 // TODO: We should not use kpColor nor kpImage for the same reason.
70 // WARNING: The given QPixmap's can have masks but not alpha channels.
71 // You must maintain this invariant (i.e. use the
72 // KP_PFX_CHECK_NO_ALPHA_CHANNEL assertion).
74 class kpPixmapFX
76 public:
77 // Call this before KApplication has been constructed.
78 static void initPre ();
80 // Call this as early as possible -- after KApplication is constructed
81 // and before any kpPixmapFX methods have been called.
83 // This may display dialogs to the user.
84 static void initPost ();
88 // Screen Depth
91 public:
92 // Called by initPre() - do not call directly.
93 static void initScreenDepthPre ();
95 // If the screen mode is paletted, it brings up a dialog warning the
96 // user that KolourPaint has not been tested under such an environment
97 // (paletted QImage's, usually created from paletted QPixmap's, need
98 // completely different code paths to truecolor QImage's; see also
99 // the warning in convertToQImage()).
101 // Called by initPost() - do not call directly.
102 static void initScreenDepthPost ();
105 // Returns whether the screen mode is paletted, rather than truecolor.
106 // If this returns true, all QPixmap's (and therefore, kpImage's) are
107 // paletted. Otherwise, they are truecolor.
108 static bool screenIsPaletted ();
110 // Returns a translated message stating that the (image) effect does
111 // not support paletted screen modes.
113 // This method is included here so that the similar messages in this
114 // method and initScreenDepthPost() can be synchronized.
116 // ASSUMPTION: screenIsPaletted()
117 static QString effectDoesNotSupportPalettedScreenMessage ();
121 // QPixmap/QImage Conversion Functions
124 public:
127 // Converts <pixmap> to a QImage and returns it.
129 // WARNING: On an 8-bit screen:
131 // QPixmap result = convertToPixmap (convertToQImage (pixmap));
133 // <result> is slightly differently colored to <pixmap>.
135 // KolourPaint needs to convert to QImage occasionally as
136 // QImage allows KolourPaint to read pixels and because the QImage
137 // paint engine gives reliable results and pixel-identical results on
138 // all platforms. The QPixmap paint engine has no such guarantee
139 // and even depends on the quality of the video driver.
141 // As a result, KolourPaint should not be used on an 8-bit screen.
143 // This bug will be fixed when KolourPaint gets a proper image library,
144 // where QPixmap -> QImage -> QPixmap transitions will be not be needed.
145 static QImage convertToQImage (const QPixmap &pixmap);
148 // Dialog info for warning about data loss with convertToPixmap().
150 // Currently (2007-08-20), instances are only created in:
152 // 1. kpDocument::getPixmapFromFile()
153 // 2. kpMainWindow::pasteWarnAboutLossInfo ()
155 // KDE3: Backport message changes (which do justice to the seriousness of
156 // the issues) to KDE 3.
158 struct WarnAboutLossInfo
160 // <moreColorsThanDisplayAndHasAlphaChannelMessage>:
162 // ki18n ("<qt><p>The (image \"example.jpg\"|image to be pasted)"
163 // " may have more colors than the current screen mode can support."
164 // " In order to display it, some color information may be removed.</p>"
166 // "<p><b>If you save this image, any color loss will become"
167 // " permanent.</b></p>"
169 // "<p>To avoid this issue, increase your screen depth to at"
170 // " least %1bpp and then restart KolourPaint.</p>"
172 // "<hr/>"
174 // "<p>It also"
176 // " contains translucency which is not fully"
177 // " supported. The translucency data will be"
178 // " approximated with a 1-bit transparency mask.</p>"
180 // "<p><b>If you save this image, this loss of translucency will"
181 // " become permanent.</b></p></qt>")
183 // <moreColorsThanDisplayMessage>:
184 // ki18n ("<qt><p>The (image \"example.jpg\"|image to be pasted)"
185 // " may have more colors than the current screen mode can support."
186 // " In order to display it, some color information may be removed.</p>"
188 // "<p><b>If you save this image, any color loss will become"
189 // " permanent.</b></p>"
191 // "<p>To avoid this issue, increase your screen depth to at"
192 // " least %1bpp and then restart KolourPaint.</p></qt>")
194 // <hasAlphaChannelMessage>:
195 // i18n ("<qt><p>The (image \"example.jpg\"|image to be pasted)"
196 // " contains translucency which is not fully"
197 // " supported. The translucency data will be"
198 // " approximated with a 1-bit transparency mask.</p>"
200 // "<p><b>If you save this image, this loss of translucency will"
201 // " become permanent.</b></p></qt>")
203 // <dontAskAgainPrefix>:
205 // Don'tAskAgain ID for dialog.
207 // <parent>:
209 // Dialog parent
211 WarnAboutLossInfo (
212 const KLocalizedString &moreColorsThanDisplayAndHasAlphaChannelMessage,
213 const KLocalizedString &moreColorsThanDisplayMessage,
214 const QString &hasAlphaChannelMessage,
215 const QString &dontAskAgainPrefix,
216 QWidget *parent)
218 m_moreColorsThanDisplayAndHasAlphaChannelMessage (
219 moreColorsThanDisplayAndHasAlphaChannelMessage),
220 m_moreColorsThanDisplayMessage (
221 moreColorsThanDisplayMessage),
222 m_hasAlphaChannelMessage (
223 hasAlphaChannelMessage),
224 m_dontAskAgainPrefix (
225 dontAskAgainPrefix),
226 m_parent (parent),
227 m_isValid (true)
231 WarnAboutLossInfo ()
232 : m_parent (0),
233 m_isValid (false)
237 ~WarnAboutLossInfo ()
242 bool isValid () const { return m_isValid; }
245 KLocalizedString m_moreColorsThanDisplayAndHasAlphaChannelMessage;
246 KLocalizedString m_moreColorsThanDisplayMessage;
247 QString m_hasAlphaChannelMessage;
248 QString m_dontAskAgainPrefix;
249 QWidget *m_parent;
250 bool m_isValid;
254 // Converts <image> to a QPixmap of the current display's depth and
255 // returns it.
257 // If the flag <pretty> is set, it will dither the image making the
258 // returned pixmap look better but if the image has few colours
259 // (less than the screen can handle), this will be at the expense of
260 // exactness of conversion.
262 // This will automatically call ensureNoAlphaChannel().
264 // Never use a foreign QPixmap that is offered to you - always get the
265 // foreign QImage and use this function to convert it to a sane QPixmap.
267 // <wali>, if specified, describes parameters for the dialog that comes
268 // up warning the user of data loss if the <image> contains translucency
269 // and/or more colors than the current display.
271 static QPixmap convertToPixmap (const QImage &image, bool pretty = false,
272 const WarnAboutLossInfo &wali = WarnAboutLossInfo ());
274 // Same as convertToPixmap() but tries as hard as possible to make the
275 // pixmap look like the original <image> - when in doubt, reads the
276 // config to see whether or not to dither (default: on).
278 // If you know for sure that <image> can be displayed losslessly on
279 // the screen, you should call convertToPixmap() with <pretty> = false
280 // instead. If you know for sure that <image> cannot be displayed
281 // losslessly, then call convertToPixmap() with <pretty> = true.
283 static QPixmap convertToPixmapAsLosslessAsPossible (const QImage &image,
284 const WarnAboutLossInfo &wali = WarnAboutLossInfo ());
287 // Sets the RGB values of the pixels where <pixmap> is transparent to
288 // <transparentColor>. This has visually no effect on the <pixmap>
289 // unless the mask is lost.
291 // TODO: As of Qt4, this does not appear to work:
293 // It certainly does not work if you convert the result to a QImage,
294 // without nuking the result's mask before the conversion. The
295 // transparent pixels in the QImage seem to have black RGB values.
296 // It looks like nuking the mask gets around this but then you lose
297 // transparency (nevertheless, this solution is usually applicable
298 // if you later restore the transparency).
300 // I'm not sure if it works if you _don't_ do a QImage conversion.
301 static QPixmap pixmapWithDefinedTransparentPixels (const QPixmap &pixmap,
302 const QColor &transparentColor);
307 // Abstract Drawing
310 public:
312 // Inside a <drawFunc> passed to kpPixmapFX::draw(), pass the <color>
313 // you intend to draw in and <drawingOnRGBLayer> (passed to your <drawFunc>),
314 // and this will spit back the appropriate QColor depending on whether you
315 // are drawing on the RGB layer or a mask.
316 static QColor draw_ToQColor (const kpColor &color, bool drawingOnRGBLayer);
318 // Exercises the drawing pattern on QPixmap's - draws on, separately, the:
320 // 1. RGB layer (if there is an opaque colour involved in the drawing i.e.
321 // <anyColorOpaque>)
322 // 2. Mask layer (if there is a transparency involved i.e.
323 // <anyColorTransparent> or the <image> has a mask to start
324 // with)
326 // Each time, it opens up a QPainter and calls <drawFunc> with:
328 // 1. A pointer to this QPainter
329 // 2. A boolean that is true if we are currently drawing on the RGB layer
330 // and false if we are drawing on the Mask layer. Often passed straight
331 // to draw_ToQColor() to convert from kpColor to QColor.
332 // 3. A pointer to the provided <data>
334 // Use of this function permits drawing on pixmaps without breaking our
335 // invariant of no alpha channels (KP_PFX_CHECK_NO_ALPHA_CHANNEL).
337 // WARNING: The current implementation does not permit <drawFunc> to access
338 // <image> (as it clears <image>'s mask before drawFunc() (but
339 // does restore the mask later)).
341 // ASSUMPTIONS:
343 // 1. <image> already satisifes the no-alpha-channel invariant
344 // (any newly-constructed QPixmap will, even though the RGB channel
345 // contains randomness).
346 // 2. <image> is not of depth 1.
348 static void draw (QPixmap *image,
349 void (*drawFunc) (QPainter * /*p*/,
350 bool /*drawingOnRGBLayer*/,
351 void * /*data*/),
352 bool anyColorOpaque, bool anyColorTransparent,
353 void *data);
355 // Same as above except that <drawFunc> is called a maximum of once
356 // for the RGB and mask layers simultaneously. Regarding the arguments
357 // this function passes to <drawFunc>, <rgbPainter> may be 0 and
358 // <maskPainter> may be 0 - but not both.
360 // <drawFunc> must return the dirty rectangle (return the full image
361 // rectangle if in doubt). This is then returned by draw() itself.
362 static QRect draw (QPixmap *image,
363 QRect (*drawFunc) (QPainter * /*rgbPainter*/, QPainter * /*maskPainter*/,
364 void * /*data*/),
365 bool anyColorOpaque, bool anyColorTransparent,
366 void *data);
370 // Get/Set Parts of Pixmap
373 public:
376 // Returns the pixel and mask data found at the <rect> in <pm>.
378 static QPixmap getPixmapAt (const QPixmap &pm, const QRect &rect);
381 // Sets the pixel and mask data at <destRect> in <*destPixmapPtr>
382 // to <srcPixmap>. Neither <destRect>'s width nor height are allowed
383 // to be bigger than <srcPixmap>'s (you can't copy more than you have).
384 // On the other hand, you can copy less than the size of <srcPixmap>
385 // - no scaling is done.
387 static void setPixmapAt (QPixmap *destPixmapPtr, const QRect &destRect,
388 const QPixmap &srcPixmap);
391 // Sets the pixel and mask data at the rectangle in <*destPixmapPtr>,
392 // with the top-left <destAt> and dimensions <srcPixmap.rect()>,
393 // to <srcPixmap>.
395 static void setPixmapAt (QPixmap *destPixmapPtr, const QPoint &destAt,
396 const QPixmap &srcPixmap);
397 static void setPixmapAt (QPixmap *destPixmapPtr, int destX, int destY,
398 const QPixmap &srcPixmap);
401 // Draws <srcPixmap> on top of <*destPixmapPtr> at <destAt>.
402 // The mask of <*destPixmapPtr> is adjusted so that all opaque
403 // pixels in <srcPixmap> will be opaque in <*destPixmapPtr>.
405 static void paintPixmapAt (QPixmap *destPixmapPtr, const QPoint &destAt,
406 const QPixmap &srcPixmap);
407 static void paintPixmapAt (QPixmap *destPixmapPtr, int destX, int destY,
408 const QPixmap &srcPixmap);
411 // Returns the colour of the pixel at <at> in <pm>.
412 // If the pixel is transparent, a value is returned such that
413 // kpTool::isColorTransparent(<return_value>) will return true.
415 static kpColor getColorAtPixel (const QPixmap &pm, const QPoint &at);
416 static kpColor getColorAtPixel (const QPixmap &pm, int x, int y);
419 // Returns the color of the pixel at <at> in <img>.
420 // If the pixel is transparent, a value is returned such that
421 // kpTool::isColorTransparent(<return_value>) will return true.
423 static kpColor getColorAtPixel (const QImage &img, const QPoint &at);
424 static kpColor getColorAtPixel (const QImage &img, int x, int y);
428 // Mask Operations
431 public:
433 // For X11: QPixmap, with XRENDER under a screen depth of 32bpp
434 // (subtlely different to 24bpp), always has an alpha channel, even
435 // if the channel is empty. This violates the KolourPaint invariant
436 // so we fix that by disabling XRENDER, killing the alpha channel.
437 // The other approach would be to change screen depth to 24bpp but
438 // such changes are not possible under X11 (XRANDR limitation).
440 // This is nasty since it reduces the quality of the whole GUI and
441 // prevents the text in text boxes from antialiasing.
443 // The proper fix -- as opposed to disabling XRENDER -- would be to either:
445 // a) Rewrite the kpImage class so that it's not tied to the screen
446 // depth (long term goal that would take months to do).
448 // OR
450 // b) Add extra code paths to support images with alpha channels
451 // (would probably require a few days of work).
453 // Called by initPre() - do not call directly.
454 static void initMaskOpsPre ();
456 // Asserts invariants.
458 // Called by initPost() - do not call directly.
459 static void initMaskOpsPost ();
461 // You should use this instead of !QPixmap::mask().isNull(), as this
462 // is faster, and instead of QPixmap::hasAlpha(), for encapsulation
463 // purposes.
464 static bool hasMask (const QPixmap &pixmap);
466 // You should use this instead of QPixmap::hasAlphaChannel(),
467 // for encapsulation purposes.
468 static bool hasAlphaChannel (const QPixmap &pixmap);
470 // Controls whether the KP_PFX_CHECK_NO_ALPHA_CHANNEL assert, if it
471 // trips, should print out an error message or crash.
473 // Called by KP_PFX_CHECK_NO_ALPHA_CHANNEL() - do not call directly.
474 // LOREFACTOR: Compile out in release mode.
475 static bool checkNoAlphaChannelInternal (const QPixmap &pixmap);
477 // Simply removing instances of this invariant check, to avoid
478 // assertion failure, is ABSOLUTELY WRONG and is merely pushing
479 // bugs elsewhere.
481 // See ensureNoAlphaChannel().
482 #define KP_PFX_CHECK_NO_ALPHA_CHANNEL(pixmap) \
483 Q_ASSERT (kpPixmapFX::checkNoAlphaChannelInternal (pixmap))
487 // Removes <*destPixmapPtr>'s Alpha Channel and attempts to convert it
488 // to a mask. KolourPaint does not support Alpha Channels - only masks.
490 // Note that this method is slow so you should avoid calling it, if
491 // possible.
493 // Generally, the only time you need to call it is when you get a QImage
494 // from a foreign source (e.g. from a file or clipboard, not originally
495 // from a QPixmap) and need to convert it to a QPixmap. You don't need
496 // to call it anywhere else since internally, all KolourPaint code is
497 // supposed to maintain the QPixmap-has-no-alpha-channel invariant.
498 // However, convertToPixmap() and convertToPixmapAsLosslessAsPossible()
499 // call this method for you anyway.
501 // It is invalid to use a QPainter directly on a QPixmap, which
502 // usually introduces an alpha channel, and then to call this method to
503 // fix it up. While this works on XRENDER, the same code path will fail
504 // without XRENDER: QPainter does not draw to the QPixmap::mask() when
505 // drawing to a QPixmap, if XRENDER is disabled. The correct way to
506 // manipulate QPixmap's is to use this class' draw*() methods or draw(),
507 // which do not introduce an alpha channel and work regardless of whether
508 // XRENDER is enabled.
510 // The no-alpha-channel invariant is checked by the
511 // KP_PFX_CHECK_NO_ALPHA_CHANNEL assertion. You must maintain this
512 // invariant for all pixmaps that you manipulate using kpPixmapFX methods
513 // or else:
515 // 1. For XRENDER screens, KolourPaint will slow down to a crawl
516 // (QPixmap::mask(), used extensively by kpPixmapFX, is very slow if
517 // an alpha channel exists) and there may be some painting artifacts.
519 // 2. For non-XRENDER screens, the invariant cannot be broken since
520 // alpha channels are not supported. However, the code path, that
521 // would have broken the invariant had XRENDER been enabled, would
522 // likely fail to draw to the pixmap mask with XRENDER disabled (see
523 // above).
525 static void ensureNoAlphaChannel (QPixmap *destPixmapPtr);
528 // Returns <pm>'s mask or a fully opaque mask (with <pm>'s dimensions)
529 // if <pm> does not have a mask.
531 static QBitmap getNonNullMask (const QPixmap &pm);
534 // Ensures that <*destPixmapPtr> is transparent at <rect>.
536 static void ensureTransparentAt (QPixmap *destPixmapPtr, const QRect &destRect);
539 // Sets the mask of <*destPixmapPtr> at the rectangle, with the
540 // top-left <destAt> and dimensions <srcMaskBitmap.rect()>,
541 // to transparent where <brushBitmap> is opaque.
543 // <brushPixmap> must be a QPixmap of depth 1 (or a QBitmap).
545 // TODO: we must drop this since 1. It is very slow 2. We later want to support alpha so this method makes little sense.
546 static KDE_DEPRECATED void paintMaskTransparentWithBrush (QPixmap *destPixmapPtr, const QPoint &destAt,
547 const QPixmap &brushBitmap);
548 static KDE_DEPRECATED void paintMaskTransparentWithBrush (QPixmap *destPixmapPtr, int destX, int destY,
549 const QPixmap &brushBitmap);
552 // Ensures that <*destPixmapPtr> is opaque at <rect>.
554 static void ensureOpaqueAt (QPixmap *destPixmapPtr, const QRect &destRect);
558 // Effects
561 public:
564 // Fills an image in the given color.
566 static void fill (QPixmap *destPixmapPtr, const kpColor &color);
567 static QPixmap fill (const QPixmap &pm, const kpColor &color);
571 // Transforms
574 public:
577 // Resizes an image to the given width and height,
578 // filling any new areas with <backgroundColor>.
580 static void resize (QPixmap *destPixmapPtr, int w, int h,
581 const kpColor &backgroundColor);
582 static QPixmap resize (const QPixmap &pm, int w, int h,
583 const kpColor &backgroundColor);
586 // Scales an image to the given width and height.
587 // If <pretty> is true, a smooth scale will be used.
589 static void scale (QPixmap *destPixmapPtr, int w, int h, bool pretty = false);
590 static QPixmap scale (const QPixmap &pm, int w, int h, bool pretty = false);
593 // The minimum difference between 2 angles (in degrees) such that they are
594 // considered different. This gives you at least enough precision to
595 // rotate an image whose width <= 10000 such that its height increases
596 // by just 1 (and similarly with height <= 10000 and width).
598 // Currently used for skew & rotate operations.
599 static const double AngleInDegreesEpsilon;
603 // Skews an image.
605 // <hangle> horizontal angle clockwise (-90 < x < 90)
606 // <vangle> vertical angle clockwise (-90 < x < 90)
607 // <backgroundColor> color to fill new areas with
608 // <targetWidth> if > 0, the desired width of the resultant pixmap
609 // <targetHeight> if > 0, the desired height of the resultant pixmap
611 // Using <targetWidth> & <targetHeight> to generate preview pixmaps is
612 // significantly more efficient than skewing and then scaling yourself.
614 static QMatrix skewMatrix (int width, int height, double hangle, double vangle);
615 static QMatrix skewMatrix (const QPixmap &pixmap, double hangle, double vangle);
617 static void skew (QPixmap *destPixmapPtr, double hangle, double vangle,
618 const kpColor &backgroundColor,
619 int targetWidth = -1, int targetHeight = -1);
620 static QPixmap skew (const QPixmap &pm, double hangle, double vangle,
621 const kpColor &backgroundColor,
622 int targetWidth = -1, int targetHeight = -1);
625 // Rotates an image.
627 // <angle> clockwise angle to rotate by
628 // <backgroundColor> color to fill new areas with
629 // <targetWidth> if > 0, the desired width of the resultant pixmap
630 // <targetHeight> if > 0, the desired height of the resultant pixmap
632 // Using <targetWidth> & <targetHeight> to generate preview pixmaps is
633 // significantly more efficient than rotating and then scaling yourself.
635 static QMatrix rotateMatrix (int width, int height, double angle);
636 static QMatrix rotateMatrix (const QPixmap &pixmap, double angle);
638 static bool isLosslessRotation (double angle);
640 static void rotate (QPixmap *destPixmapPtr, double angle,
641 const kpColor &backgroundColor,
642 int targetWidth = -1, int targetHeight = -1);
643 static QPixmap rotate (const QPixmap &pm, double angle,
644 const kpColor &backgroundColor,
645 int targetWidth = -1, int targetHeight = -1);
649 // Flips an image in the given directions.
651 static QMatrix flipMatrix (int width, int height, bool horz, bool vert);
652 static QMatrix flipMatrix (const QPixmap &pixmap, bool horz, bool vert);
654 // TODO: this kind of overloading is error prone
655 // e.g. QPixmap pixmap;
656 // kpPixmapFX::flip (pixmap, false, true);
657 // looks like it will flip vertically but does absolutely nothing!
658 // (should be &pixmap)
659 static void flip (QPixmap *destPixmapPtr, bool horz, bool vert);
660 static QPixmap flip (const QPixmap &pm, bool horz, bool vert);
661 static void flip (QImage *destImagePtr, bool horz, bool vert);
662 static QImage flip (const QImage &img, bool horz, bool vert);
666 // Drawing Shapes
669 public:
671 // Returns a pen suitable for drawing a rectangle with 90 degree
672 // corners ("MiterJoin"). This is necessary since Qt4 defaults to
673 // "BevelJoin". <qtWidth> is passed straight to QPen without modification.
674 static QPen QPainterDrawRectPen (const QColor &color, int qtWidth);
676 // Returns a pen suitable for drawing lines / polylines / polygons /
677 // curves with rounded corners. This is necessary since Qt4 defaults
678 // to square corners ("SquareCap") and "BevelJoin".
679 // <qtWidth> is passed straight to QPen without modification.
680 static QPen QPainterDrawLinePen (const QColor &color, int qtWidth);
683 // Draws a line from (x1,y1) to (x2,y2) onto <image>, with <color>
684 // and <width>. The corners are rounded and centred at those
685 // coordinates so if <width> > 1, the line is likely to extend past
686 // a rectangle with those corners.
688 // If <stippleColor> is valid, it draws a stippled line alternating
689 // between long strips of <color> and short strips of <stippleColor>.
690 static void drawPolyline (QPixmap *image,
691 const QPolygon &points,
692 const kpColor &color, int penWidth,
693 const kpColor &stippleColor = kpColor::Invalid);
694 static void drawLine (QPixmap *image,
695 int x1, int y1, int x2, int y2,
696 const kpColor &color, int penWidth,
697 const kpColor &stippleColor = kpColor::Invalid);
698 // <isFinal> = shape completed else drawing but haven't finalised.
699 // If not <isFinal>, the edge that would form the closure, if the
700 // shape were finalised now, is highlighted specially. Unfortunately,
701 // the argument is currently ignored.
703 // Odd-even fill.
704 static void drawPolygon (QPixmap *image,
705 const QPolygon &points,
706 const kpColor &fcolor, int penWidth,
707 const kpColor &bcolor = kpColor::Invalid,
708 bool isFinal = true,
709 const kpColor &fStippleColor = kpColor::Invalid);
710 // Cubic Beizer.
711 static void drawCurve (QPixmap *image,
712 const QPoint &startPoint,
713 const QPoint &controlPointP, const QPoint &controlPointQ,
714 const QPoint &endPoint,
715 const kpColor &color, int penWidth);
717 static void fillRect (QPixmap *image,
718 int x, int y, int width, int height,
719 const kpColor &color,
720 const kpColor &stippleColor = kpColor::Invalid);
722 // Draws a rectangle / rounded rectangle / ellipse with top-left at
723 // (x, y) with width <width> and height <height>. Unlike QPainter,
724 // this rectangle will really fit inside <width>x<height> and won't
725 // be one pixel higher or wider etc.
727 // <width> and <height> must be >= 0.
729 // <fcolor> must not be invalid. However, <bcolor> may be invalid
730 // to signify an unfilled rectangle / rounded rectangle /ellipse.
731 static void drawRect (QPixmap *image,
732 int x, int y, int width, int height,
733 const kpColor &fcolor, int penWidth = 1,
734 const kpColor &bcolor = kpColor::Invalid,
735 const kpColor &fStippleColor = kpColor::Invalid);
736 static void drawRoundedRect (QPixmap *image,
737 int x, int y, int width, int height,
738 const kpColor &fcolor, int penWidth = 1,
739 const kpColor &bcolor = kpColor::Invalid,
740 const kpColor &fStippleColor = kpColor::Invalid);
741 static void drawEllipse (QPixmap *image,
742 int x, int y, int width, int height,
743 const kpColor &fcolor, int penWidth = 1,
744 const kpColor &bcolor = kpColor::Invalid,
745 const kpColor &fStippleColor = kpColor::Invalid);
749 // Drawing Using Raster Operations
752 // 1. Alpha Channel Invariant
753 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
755 // The widgetDraw*() methods do not deal with pixmap data, so they safely
756 // safely disregard our pixmap invariant of not introducing an alpha
757 // channel (KP_PFX_CHECK_NO_ALPHA_CHANNEL). This permits far
758 // more straightforward implementations.
761 // 2. Raster Operation Emulation
762 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
763 // Qt4 does not actually support raster operations, unlike Qt3. So for
764 // now, these methods ignore any given colors and produce a stipple of
765 // <colorHint1> and <colorHint2>.
767 // LOTODO: For the widgetDraw*() methods (which aren't bound by the
768 // no-alpha-channel requirement), if XRENDER is currently active,
769 // we could do nice alpha effects instead of stippling.
771 // Should Qt support raster operations again, these methods should be
772 // changed to use them with the given colors. <colorHint1> and
773 // <colorHint2> would then be ignored. Note that transparent pixels that
774 // these raster operations might be drawing on -- and hence, blending with --
775 // might have uninitialized RGB values. This has to be dealt with somehow
776 // (the KolourPaint/KDE3 approach is to simply use these uninitialized
777 // values -- although it's a bit dodgy, it works well enough as you usually
778 // get a stipple of arbitrary colors).
779 // The testcase for KDE3, which might still apply is:
781 // 1. Open an image with transparent pixels
782 // 2. Press CTRL+A to look at an XOR border
783 // 3. Fill the transparent pixels with any color to initialize the
784 // RGB values
785 // 4. Fill those pixels so that they are transparent again
786 // 5. Press CTRL+A to look at an XOR border and compare with 2.
789 public:
792 // Simulated Stippled Raster XOR
795 // (used for polygonal selection border)
796 static void drawStippledXORPolygon (QPixmap *image,
797 const QPolygon &points,
798 const kpColor &fcolor1, const kpColor &fcolor2,
799 const kpColor &colorHint1, const kpColor &colorHint2,
800 bool isFinal = true);
802 // Same as drawRect() but the border consists of stippled lines of
803 // <fcolor1> and <fcolor2>, XOR'ed with the existing contents of the
804 // pixmap. Pen width is set to 1.
806 // (used for rectangular selection borders)
807 static void drawStippledXORRect (QPixmap *image,
808 int x, int y, int width, int height,
809 const kpColor &fcolor1, const kpColor &fcolor2,
810 const kpColor &colorHint1, const kpColor &colorHint2);
812 // The painter is clipped to <clipRect> if it is not empty.
813 // (used for thumbnail rectangle)
815 // WARNING: Just for this method, neither <colorHint1> nor <colorHint2>
816 // are allowed to be transparent.
817 static void widgetDrawStippledXORRect (QWidget *widget,
818 int x, int y, int width, int height,
819 const kpColor &fcolor1, const kpColor &fcolor2,
820 const kpColor &colorHint1, const kpColor &colorHint2,
821 const QRect &clipRect = QRect ());
825 // Simulated Raster XOR Filling
828 // (used for text cursor)
829 static void fillXORRect (QPixmap *image,
830 int x, int y, int width, int height,
831 const kpColor &fcolor,
832 const kpColor &colorHint1, const kpColor &colorHint2);
834 // (used for selection resize handles)
836 // WARNING: Just for this method, neither <colorHint1> nor <colorHint2>
837 // are allowed to be transparent.
838 static void widgetFillXORRect (QWidget *widget,
839 int x, int y, int width, int height,
840 const kpColor &fcolor,
841 const kpColor &colorHint1, const kpColor &colorHint2);
845 // Simulated Raster NOP
848 // (used for rectangular bounding border for non-rectangular selections
849 // and when dragging a rectangle to zoom into with the Zoom Tool)
850 static void drawNOTRect (QPixmap *image,
851 int x, int y, int width, int height,
852 const kpColor &colorHint1, const kpColor &colorHint2);
854 // (used for document resizing lines)
856 // WARNING: Just for this method, neither <colorHint1> nor <colorHint2>
857 // are allowed to be transparent.
858 static void widgetFillNOTRect (QWidget *widget,
859 int x, int y, int width, int height,
860 const kpColor &colorHint1, const kpColor &colorHint2);
864 #endif // KP_PIXMAP_FX_H