128 self.__image = QImage(32, 32, QImage.Format_ARGB32) |
128 self.__image = QImage(32, 32, QImage.Format_ARGB32) |
129 self.__image.fill(qRgba(0, 0, 0, 0)) |
129 self.__image.fill(qRgba(0, 0, 0, 0)) |
130 self.__markImage = QImage(self.__image) |
130 self.__markImage = QImage(self.__image) |
131 self.__markImage.fill(self.NoMarkColor.rgba()) |
131 self.__markImage.fill(self.NoMarkColor.rgba()) |
132 |
132 |
|
133 self.__compositingMode = QPainter.CompositionMode_SourceOver |
|
134 ## self.__compositingMode = QPainter.CompositionMode_Source |
|
135 self.__lastPos = (-1, -1) |
|
136 |
133 self.__gridEnabled = True |
137 self.__gridEnabled = True |
134 self.__selectionAvailable = False |
138 self.__selectionAvailable = False |
135 |
139 |
136 self.__initCursors() |
140 self.__initCursors() |
137 self.__initUndoTexts() |
141 self.__initUndoTexts() |
243 |
247 |
244 @return current drawing color (QColor) |
248 @return current drawing color (QColor) |
245 """ |
249 """ |
246 return QColor(self.__curColor) |
250 return QColor(self.__curColor) |
247 |
251 |
|
252 def setCompositingMode(self, mode): |
|
253 """ |
|
254 Public method to set the compositing mode. |
|
255 |
|
256 @param mode compositing mode to set (QPainter.CompositionMode) |
|
257 """ |
|
258 self.__compositingMode = mode |
|
259 |
|
260 def compositingMode(self): |
|
261 """ |
|
262 Public method to get the compositing mode. |
|
263 |
|
264 @return compositing mode (QPainter.CompositionMode) |
|
265 """ |
|
266 return self.__compositingMode |
|
267 |
248 def setTool(self, tool): |
268 def setTool(self, tool): |
249 """ |
269 """ |
250 Public method to set the current drawing tool. |
270 Public method to set the current drawing tool. |
251 |
271 |
252 @param tool drawing tool to be used |
272 @param tool drawing tool to be used |
253 (IconEditorGrid.Pencil ... IconEditorGrid.CircleSelection) |
273 (IconEditorGrid.Pencil ... IconEditorGrid.CircleSelection) |
254 """ |
274 """ |
255 self.__curTool = tool |
275 self.__curTool = tool |
|
276 self.__lastPos = (-1, -1) |
256 |
277 |
257 if self.__curTool in [self.RectangleSelection, self.CircleSelection]: |
278 if self.__curTool in [self.RectangleSelection, self.CircleSelection]: |
258 self.__selecting = True |
279 self.__selecting = True |
259 else: |
280 else: |
260 self.__selecting = False |
281 self.__selecting = False |
520 @param pos position of the pixel in the widget (QPoint) |
541 @param pos position of the pixel in the widget (QPoint) |
521 @param opaque flag indicating a set operation (boolean) |
542 @param opaque flag indicating a set operation (boolean) |
522 """ |
543 """ |
523 i, j = self.__imageCoordinates(pos) |
544 i, j = self.__imageCoordinates(pos) |
524 |
545 |
525 if self.__image.rect().contains(i, j): |
546 if self.__image.rect().contains(i, j) and (i, j) != self.__lastPos: |
526 if opaque: |
547 if opaque: |
527 self.__image.setPixel(i, j, self.penColor().rgba()) |
548 painter = QPainter(self.__image) |
|
549 painter.setPen(self.penColor()) |
|
550 painter.setCompositionMode(self.__compositingMode) |
|
551 painter.drawPoint(i, j) |
|
552 ## if opaque: |
|
553 ## self.__image.setPixel(i, j, self.penColor().rgba()) |
528 else: |
554 else: |
529 self.__image.setPixel(i, j, qRgba(0, 0, 0, 0)) |
555 self.__image.setPixel(i, j, qRgba(0, 0, 0, 0)) |
530 |
556 self.__lastPos = (i, j) |
531 self.update(self.__pixelRect(i, j)) |
557 |
|
558 self.update(self.__pixelRect(i, j)) |
532 |
559 |
533 def __imageCoordinates(self, pos): |
560 def __imageCoordinates(self, pos): |
534 """ |
561 """ |
535 Private method to convert from widget to image coordinates. |
562 Private method to convert from widget to image coordinates. |
536 |
563 |
594 start = QPoint(*self.__imageCoordinates(self.__startPos)) |
621 start = QPoint(*self.__imageCoordinates(self.__startPos)) |
595 end = QPoint(*self.__imageCoordinates(pos)) |
622 end = QPoint(*self.__imageCoordinates(pos)) |
596 |
623 |
597 painter = QPainter(img) |
624 painter = QPainter(img) |
598 painter.setPen(drawColor) |
625 painter.setPen(drawColor) |
599 painter.setCompositionMode(QPainter.CompositionMode_Source) |
626 painter.setCompositionMode(self.__compositingMode) |
600 |
627 |
601 if self.__curTool == self.Line: |
628 if self.__curTool == self.Line: |
602 painter.drawLine(start, end) |
629 painter.drawLine(start, end) |
603 |
630 |
604 elif self.__curTool in [self.Rectangle, self.FilledRectangle, |
631 elif self.__curTool in [self.Rectangle, self.FilledRectangle, |
845 self.__isPasting = True |
872 self.__isPasting = True |
846 self.__clipboardSize = img.size() |
873 self.__clipboardSize = img.size() |
847 else: |
874 else: |
848 cmd = IconEditCommand(self, self.trUtf8("Paste Clipboard"), self.__image) |
875 cmd = IconEditCommand(self, self.trUtf8("Paste Clipboard"), self.__image) |
849 self.__markImage.fill(self.NoMarkColor.rgba()) |
876 self.__markImage.fill(self.NoMarkColor.rgba()) |
850 for sx in range(self.__pasteRect.width() + 1): |
877 painter = QPainter(self.__image) |
851 for sy in range(self.__pasteRect.height() + 1): |
878 painter.setPen(self.penColor()) |
852 dx = self.__pasteRect.x() + sx |
879 painter.setCompositionMode(self.__compositingMode) |
853 dy = self.__pasteRect.y() + sy |
880 painter.drawImage(self.__pasteRect.x(), self.__pasteRect.y(), img, 0, 0, |
854 if True: # TODO: insert code to test for compositing |
881 self.__pasteRect.width() + 1, self.__pasteRect.height() + 1) |
855 # Porter-Duff Over composition |
|
856 colorS = img.pixel(sx, sy) |
|
857 colorD = self.__image.pixel(dx, dy) |
|
858 |
|
859 alphaS = qAlpha(colorS) / 255.0 |
|
860 alphaD = qAlpha(colorD) / 255.0 |
|
861 |
|
862 r = qRed(colorS) * alphaS + \ |
|
863 (1 - alphaS) * qRed(colorD) * alphaD |
|
864 g = qGreen(colorS) * alphaS + \ |
|
865 (1 - alphaS) * qGreen(colorD) * alphaD |
|
866 b = qBlue(colorS) * alphaS + \ |
|
867 (1 - alphaS) * qBlue(colorD) * alphaD |
|
868 a = alphaS + \ |
|
869 (1 - alphaS) * alphaD |
|
870 |
|
871 # Remove multiplication by alpha |
|
872 if a > 0: |
|
873 r /= a |
|
874 g /= a |
|
875 b /= a |
|
876 else: |
|
877 r = 0 |
|
878 g = 0 |
|
879 b = 0 |
|
880 |
|
881 ir = int(r + 0.5) |
|
882 if ir < 0: |
|
883 ir = 0 |
|
884 elif ir > 255: |
|
885 ir = 255 |
|
886 |
|
887 ig = int(g + 0.5) |
|
888 if ig < 0: |
|
889 ig = 0 |
|
890 elif ig > 255: |
|
891 ig = 255 |
|
892 |
|
893 ib = int(b + 0.5) |
|
894 if ib < 0: |
|
895 ib = 0 |
|
896 elif ib > 255: |
|
897 ib = 255 |
|
898 |
|
899 ia = int(a * 255 + 0.5) |
|
900 if ia < 0: |
|
901 ia = 0 |
|
902 elif ia > 255: |
|
903 ia = 255 |
|
904 |
|
905 self.__image.setPixel(dx, dy, qRgba(ir, ig, ib, ia)) |
|
906 else: |
|
907 self.__image.setPixel(dx, dy, img.pixel(sx, sy)) |
|
908 |
882 |
909 self.__undoStack.push(cmd) |
883 self.__undoStack.push(cmd) |
910 cmd.setAfterImage(self.__image) |
884 cmd.setAfterImage(self.__image) |
911 |
885 |
912 self.__updateImageRect(self.__pasteRect.topLeft(), |
886 self.__updateImageRect(self.__pasteRect.topLeft(), |