View Issue Details

IDProjectCategoryView StatusLast Update
0032137LazarusLCLpublic2020-04-17 19:20
ReporterValdas Jankūnas Assigned ToZeljan Rikalo  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Platformlinux 4.10.0-26-genericOSKubuntu 17.04 
Product Version1.9 (SVN) 
Summary0032137: Broken CopyRect when stretching
DescriptionTry attached example:
 - part (one pixel width column) of TImage.Picture.Bitmap.Canvas is copied to entire TPainTbox;
 - part (one pixel width column) of TShape.Canvas is copied to entire TPaintBox;
 - in all copy operations CopyRect is used.

Results (see attached screenshots):
 - from TImage: entire image is copied and offseted by SourceRect.Left (Qt result slightly differ from Gtk2);
 - from TShape: in Gtk2 is OK, in Qt no result is produced.

I think that in both cases column of pixels from source must be stretched over destination.
Additional InformationFPC v 3.0.0
TagsNo tags attached.
Fixed in Revision62870
LazTarget-
WidgetsetGTK 2, QT
Attached Files

Activities

Valdas Jankūnas

2017-07-11 14:48

reporter  

test_project.zip (67,544 bytes)

Valdas Jankūnas

2017-07-11 14:48

reporter  

result_qt.png (13,005 bytes)   
result_qt.png (13,005 bytes)   

Valdas Jankūnas

2017-07-11 14:48

reporter  

result_gtk2.png (13,370 bytes)   
result_gtk2.png (13,370 bytes)   

Valdas Jankūnas

2017-07-11 15:12

reporter   ~0101663

It works without problems in Qt and Gtk2 if I SourceRect and DestinatioRect are same.

Valdas Jankūnas

2017-07-12 21:51

reporter   ~0101676

Last edited: 2017-07-13 13:48

View 4 revisions

Additional info:
  FPC v 3.0.0
  KDE uses Qt v 5.7.1

In system "libqt4pas" v2.5-18 is installed.

Not sure which Qt version test application uses. How to get that info?

Valdas Jankūnas

2017-07-13 13:48

reporter  

result_win.png (5,102 bytes)   
result_win.png (5,102 bytes)   

Valdas Jankūnas

2017-07-13 13:49

reporter   ~0101690

In Windows 7 (in virtualbox) it looks OK (see attached pic).

Zeljan Rikalo

2020-04-01 17:04

developer  

issue32137.diff (6,467 bytes)   
Index: lcl/interfaces/qt/qtwinapi.inc
===================================================================
--- lcl/interfaces/qt/qtwinapi.inc	(revision 62844)
+++ lcl/interfaces/qt/qtwinapi.inc	(working copy)
@@ -6817,7 +6817,7 @@
   DstQDC: TQtDeviceContext absolute DestDC;
   SrcRect, DstRect, MaskRect: TRect;
   Image, TmpImage, QMask, TmpMask: QImageH;
-  TmpPixmap: QPixmapH;
+  TmpPixmap, TmpPixmap2: QPixmapH;
   SrcMatrix: QTransformH;
   dx, dy: integer;
   OldRop: Integer;
@@ -6840,17 +6840,59 @@
   Result := False;
 
   SrcMatrix := QPainter_transform(SrcQDC.Widget);
+
+  if (Rop = SRCCOPY) and (SrcQDC.vImage <> nil) and (SrcQDC.vImage.Handle <> nil) then
+  begin
+    //issue #32137
+    TmpImage := QImage_Create();
+    Dx := round(QTransform_dx(QPainter_transform(SrcQDC.Widget)));
+    Dy := round(QTransform_dy(QPainter_transform(SrcQDC.Widget)));
+    QImage_copy(SrcQDC.vImage.Handle, TmpImage, XSrc + Dx, YSrc + Dy, SrcWidth, SrcHeight);
+    TmpPixmap := QPixmap_create();
+    QPixmap_fromImage(TmpPixmap, TmpImage);
+
+    if (Width <> SrcWidth) or (Height <> SrcHeight) then
+    begin
+      TmpPixmap2 := QPixmap_create();
+      QPixmap_copy(TmpPixmap, TmpPixmap2, 0, 0, Width, Height);
+      QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap2);
+      QPixmap_destroy(TmpPixmap2);
+    end else
+      QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap);
+    QImage_destroy(TmpImage);
+    QPixmap_destroy(TmpPixmap);
+    exit;
+  end else
   if SrcQDC.vImage = nil then
   begin
     if SrcQDC.Parent <> nil then
     begin
-      with SrcQDC.getDeviceSize do
-        TmpPixmap := QPixmap_create(x, y);
       AWidgetID := QWidget_winId(SrcQDC.Parent);
-      QPixmap_grabWindow(TmpPixmap, AWidgetID, 0, 0);
-      Image := QImage_create();
-      QPixmap_toImage(TmpPixmap, Image);
-      QPixmap_destroy(TmpPixmap);
+      if Rop = SRCCOPY then //issue #32137
+      begin
+        TmpPixmap := QPixmap_create();
+        Dx := round(QTransform_dx(QPainter_transform(SrcQDC.Widget)));
+        Dy := round(QTransform_dy(QPainter_transform(SrcQDC.Widget)));
+        QPixmap_grabWindow(TmpPixmap, AWidgetID, XSrc + Dx,  YSrc + Dy, SrcWidth, SrcHeight);
+        if (Width <> SrcWidth) or (Height <> SrcHeight) then
+        begin
+          TmpPixmap2 := QPixmap_create();
+          QPixmap_copy(TmpPixmap, TmpPixmap2, 0, 0, Width, Height);
+          QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap2);
+          QPixmap_destroy(TmpPixmap2);
+        end else
+          QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap);
+        QPixmap_destroy(TmpPixmap);
+        exit;
+      end else
+      begin
+        with SrcQDC.getDeviceSize do
+          TmpPixmap := QPixmap_create(x, y);
+        QPixmap_grabWindow(TmpPixmap, AWidgetID, 0, 0);
+        Image := QImage_create();
+        QPixmap_toImage(TmpPixmap, Image);
+        QPixmap_destroy(TmpPixmap);
+      end;
     end
     else
       Exit;
Index: lcl/interfaces/qt5/qtwinapi.inc
===================================================================
--- lcl/interfaces/qt5/qtwinapi.inc	(revision 62844)
+++ lcl/interfaces/qt5/qtwinapi.inc	(working copy)
@@ -6760,7 +6760,7 @@
   DstQDC: TQtDeviceContext absolute DestDC;
   SrcRect, DstRect, MaskRect: TRect;
   Image, TmpImage, QMask, TmpMask: QImageH;
-  TmpPixmap: QPixmapH;
+  TmpPixmap, TmpPixmap2: QPixmapH;
   SrcMatrix: QTransformH;
   dx, dy: integer;
   OldRop: Integer;
@@ -6785,13 +6785,33 @@
   Result := False;
 
   SrcMatrix := QPainter_transform(SrcQDC.Widget);
+
+  if (Rop = SRCCOPY) and (SrcQDC.vImage <> nil) and (SrcQDC.vImage.Handle <> nil) then
+  begin
+    //issue #32137
+    TmpImage := QImage_Create();
+    Dx := round(QTransform_dx(QPainter_transform(SrcQDC.Widget)));
+    Dy := round(QTransform_dy(QPainter_transform(SrcQDC.Widget)));
+    // DebugLn(Format('StretchMaskBlt: ImageCopy W %d H %d SW %d SH %d  dx %d dy %d',[Width, Height, SrcWidth, SrcHeight, Dx, Dy]));
+    QImage_copy(SrcQDC.vImage.Handle, TmpImage, XSrc + Dx, YSrc + Dy, SrcWidth, SrcHeight);
+    TmpPixmap := QPixmap_create();
+    QPixmap_fromImage(TmpPixmap, TmpImage);
+    if (Width <> SrcWidth) or (Height <> SrcHeight) then
+    begin
+      TmpPixmap2 := QPixmap_create();
+      QPixmap_copy(TmpPixmap, TmpPixmap2, 0, 0, Width, Height);
+      QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap2);
+      QPixmap_destroy(TmpPixmap2);
+    end else
+      QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap);
+    QImage_destroy(TmpImage);
+    QPixmap_destroy(TmpPixmap);
+    exit;
+  end else
   if SrcQDC.vImage = nil then
   begin
     if SrcQDC.Parent <> nil then
     begin
-      with SrcQDC.getDeviceSize do
-        TmpPixmap := QPixmap_create(x, y);
-
       AWidgetID := QWidget_winId(SrcQDC.Parent);
       AWindow := QWidget_windowHandle(SrcQDC.Parent);
       if AWindow <> nil then
@@ -6799,10 +6819,32 @@
       else
         AScreen := QGuiApplication_primaryScreen();
 
-      QScreen_grabWindow(AScreen, TmpPixmap, AWidgetID, 0, 0);
-      Image := QImage_create();
-      QPixmap_toImage(TmpPixmap, Image);
-      QPixmap_destroy(TmpPixmap);
+      if Rop = SRCCOPY then
+      begin
+        // DebugLn(Format('StretchMaskBlt: DeviceCopy W %d H %d SW %d SH %d',[Width, Height, SrcWidth, SrcHeight]));
+        TmpPixmap := QPixmap_create();
+        Dx := round(QTransform_dx(QPainter_transform(SrcQDC.Widget)));
+        Dy := round(QTransform_dy(QPainter_transform(SrcQDC.Widget)));
+        QScreen_grabWindow(AScreen, TmpPixmap, AWidgetID, XSrc + Dx,  YSrc + Dy, SrcWidth, SrcHeight);
+        if (Width <> SrcWidth) or (Height <> SrcHeight) then
+        begin
+          TmpPixmap2 := QPixmap_create();
+          QPixmap_copy(TmpPixmap, TmpPixmap2, 0, 0, Width, Height);
+          QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap2);
+          QPixmap_destroy(TmpPixmap2);
+        end else
+          QPainter_drawPixmap(DstQDC.Widget, X, Y, Width, Height, TmpPixmap);
+        QPixmap_destroy(TmpPixmap);
+        exit;
+      end else
+      begin
+        with SrcQDC.getDeviceSize do
+          TmpPixmap := QPixmap_create(x, y);
+        QScreen_grabWindow(AScreen, TmpPixmap, AWidgetID, 0, 0);
+        Image := QImage_create();
+        QPixmap_toImage(TmpPixmap, Image);
+        QPixmap_destroy(TmpPixmap);
+      end;
     end
     else
       Exit;
issue32137.diff (6,467 bytes)   

Zeljan Rikalo

2020-04-01 17:05

developer   ~0121832

Please test with attached patch (lazarus trunk). I need more examples to test if this approach is ok (eg image scaling etc).
Note that this is just another approach for SRCCOPY, tested only under linux atm.

Zeljan Rikalo

2020-04-03 10:57

developer   ~0121858

Qt/Qt5 is fixed with r62870

Issue History

Date Modified Username Field Change
2017-07-11 14:48 Valdas Jankūnas New Issue
2017-07-11 14:48 Valdas Jankūnas File Added: test_project.zip
2017-07-11 14:48 Valdas Jankūnas File Added: result_qt.png
2017-07-11 14:48 Valdas Jankūnas File Added: result_gtk2.png
2017-07-11 15:12 Valdas Jankūnas Note Added: 0101663
2017-07-12 21:51 Valdas Jankūnas Note Added: 0101676
2017-07-12 21:53 Valdas Jankūnas Note Edited: 0101676 View Revisions
2017-07-12 21:53 Valdas Jankūnas Note Edited: 0101676 View Revisions
2017-07-13 13:48 Valdas Jankūnas Note Edited: 0101676 View Revisions
2017-07-13 13:48 Valdas Jankūnas File Added: result_win.png
2017-07-13 13:49 Valdas Jankūnas Note Added: 0101690
2017-07-13 17:36 Zeljan Rikalo Assigned To => Zeljan Rikalo
2017-07-13 17:36 Zeljan Rikalo Status new => assigned
2020-04-01 17:04 Zeljan Rikalo File Added: issue32137.diff
2020-04-01 17:05 Zeljan Rikalo Status assigned => feedback
2020-04-01 17:05 Zeljan Rikalo LazTarget => -
2020-04-01 17:05 Zeljan Rikalo Note Added: 0121832
2020-04-03 10:57 Zeljan Rikalo Status feedback => resolved
2020-04-03 10:57 Zeljan Rikalo Resolution open => fixed
2020-04-03 10:57 Zeljan Rikalo Fixed in Revision => 62870
2020-04-03 10:57 Zeljan Rikalo Widgetset GTK 2, QT => GTK 2, QT
2020-04-03 10:57 Zeljan Rikalo Note Added: 0121858