View Issue Details

IDProjectCategoryView StatusLast Update
0025336LazarusLCLpublic2013-11-23 17:21
ReporteraccSoneAssigned ToPaul Ishenin 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformdarwin x86_64OSOSXOS Version10.6.8
Product Version1.3 (SVN)Product Build 
Target VersionFixed in Version1.4 
Summary0025336: BitBlt in cocoa behaves differnt than with the win32 and carbon widgetset
DescriptionCocoa does stretching in SRCCOPY rop, carbon and win32 not
Steps To ReproduceTry following code. compile it under carbon and cocoa. See the different stretchings and origin positions

procedure TForm1.FormPaint(Sender: TObject);
var bmBuff:TBitMap;
begin

bmBuff:=TBitMap.Create;

bmBuff.Width:=100;
bmBuff.Height:=100;

bmBuff.Canvas.Brush.Color := clgreen;
bmBuff.Canvas.FillRect(types.rect(0,0,width,height));
bmBuff.Canvas.Brush.Color := clred;
bmBuff.Canvas.FillRect(types.rect(10,25,50,75));
bmBuff.Canvas.Brush.Color := clyellow;
bmBuff.Canvas.FillRect(types.rect(10,75,50,95));


BitBlt(Canvas.Handle,10,10,350,450,bmBuff.Canvas.Handle,10,24,SRCCOPY);

end;
Additional InformationFind attached the fix at least for SRCCOPY rop. Other modes still might work different.
TagsNo tags attached.
Fixed in Revision43468
LazTarget-
WidgetsetCocoa
Attached Files
  • fix_0025336.patch (1,202 bytes)
    Index: /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas
    ===================================================================
    --- /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 43457)
    +++ /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas	(working copy)
    @@ -1772,6 +1772,7 @@
       Msk: TCocoaBitmap; XMsk, YMsk: Integer; Rop: DWORD): Boolean;
     var
       Bmp: TCocoaBitmap;
    +  w,h:Integer;
     begin
       Result := False;
     
    @@ -1783,9 +1784,17 @@
     //  if Assigned(MskImage) then
     //    CGContextClipToMask(LayerContext, ImgRect, MskImage);
     
    +  w:=Width;
    +  h:=Height;
    +  if Rop=SRCCOPY then
    +     begin
    +     w:=SrcWidth;    // this ensures win32 and carbon compatibility of the SCRCOPY mode
    +     h:=SrcHeight;
    +     end;
    +
       Result := DrawImageRep(
    -    GetNSRect(X, Y, Width, Height),
    -    GetNSRect(XSrc, YSrc, SrcWidth, SrcHeight), Bmp.ImageRep);
    +    GetNSRect(X, Y, w, h),
    +    GetNSRect(XSrc, -YSrc, SrcWidth, SrcHeight), Bmp.ImageRep);    // have to transform  YSrc because cocoa painting is different from win32 / carbon
     end;
     
     {------------------------------------------------------------------------------
    
    fix_0025336.patch (1,202 bytes)
  • fix_0025336_add.patch (844 bytes)
    Index: /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc
    ===================================================================
    --- /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc	(revision 43444)
    +++ /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc	(working copy)
    @@ -60,9 +60,14 @@
     
     function TCocoaWidgetSet.BitBlt(DestDC: HDC; X, Y, Width, Height: Integer;
       SrcDC: HDC; XSrc, YSrc: Integer; Rop: DWORD): Boolean;
    +var  Bmp: TCocoaBitmap;
     begin
    +  Bmp := TCocoaBitmapContext(SrcDC).Bitmap;
    +  if not Assigned(Bmp) then
    +    Exit;
    +
       Result := StretchMaskBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc,
    -    Width, Height, 0, 0, 0, Rop);
    +    Bmp.width, Bmp.Height, 0, 0, 0, Rop);
     end;
     
    
     
     {------------------------------- SYNC OBJECTS ---------------------------------}
    
    fix_0025336_add.patch (844 bytes)

Activities

accSone

2013-11-20 14:14

developer  

fix_0025336.patch (1,202 bytes)
Index: /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas
===================================================================
--- /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 43457)
+++ /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoagdiobjects.pas	(working copy)
@@ -1772,6 +1772,7 @@
   Msk: TCocoaBitmap; XMsk, YMsk: Integer; Rop: DWORD): Boolean;
 var
   Bmp: TCocoaBitmap;
+  w,h:Integer;
 begin
   Result := False;
 
@@ -1783,9 +1784,17 @@
 //  if Assigned(MskImage) then
 //    CGContextClipToMask(LayerContext, ImgRect, MskImage);
 
+  w:=Width;
+  h:=Height;
+  if Rop=SRCCOPY then
+     begin
+     w:=SrcWidth;    // this ensures win32 and carbon compatibility of the SCRCOPY mode
+     h:=SrcHeight;
+     end;
+
   Result := DrawImageRep(
-    GetNSRect(X, Y, Width, Height),
-    GetNSRect(XSrc, YSrc, SrcWidth, SrcHeight), Bmp.ImageRep);
+    GetNSRect(X, Y, w, h),
+    GetNSRect(XSrc, -YSrc, SrcWidth, SrcHeight), Bmp.ImageRep);    // have to transform  YSrc because cocoa painting is different from win32 / carbon
 end;
 
 {------------------------------------------------------------------------------
fix_0025336.patch (1,202 bytes)

accSone

2013-11-20 14:16

developer   ~0071418

I can assume that this fix might solve a lot of cocoa strange painting bugs...

Paul Ishenin

2013-11-20 15:49

manager   ~0071425

Actually, DrawImageRep() method cares about Y mirroring. Need to check this again.

accSone

2013-11-20 15:53

developer  

fix_0025336_add.patch (844 bytes)
Index: /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc
===================================================================
--- /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc	(revision 43444)
+++ /Developer/lazarus_trunc/lcl/interfaces/cocoa/cocoawinapi.inc	(working copy)
@@ -60,9 +60,14 @@
 
 function TCocoaWidgetSet.BitBlt(DestDC: HDC; X, Y, Width, Height: Integer;
   SrcDC: HDC; XSrc, YSrc: Integer; Rop: DWORD): Boolean;
+var  Bmp: TCocoaBitmap;
 begin
+  Bmp := TCocoaBitmapContext(SrcDC).Bitmap;
+  if not Assigned(Bmp) then
+    Exit;
+
   Result := StretchMaskBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc,
-    Width, Height, 0, 0, 0, Rop);
+    Bmp.width, Bmp.Height, 0, 0, 0, Rop);
 end;
 

 
 {------------------------------- SYNC OBJECTS ---------------------------------}
fix_0025336_add.patch (844 bytes)

accSone

2013-11-20 15:53

developer   ~0071426

Last edited: 2013-11-20 16:04

View 4 revisions

Yes, but in the wrong direction of the y source origin ...

carbon behaves like this with LCLType.SRCCOPY (Attention there is another const SRCCOPY with another value in Quicktime):


- BitBlt doesn't Stretch, so width= Image.width and height=Image.height
- X,Y are painting destinations (works fine due to the flipped context)
- XSrc left Offset into the image(works fine)
- YSrc top Offset into the image (Coca does it in the wrong direction)

Paul Ishenin

2013-11-21 01:04

manager   ~0071457

And what if you want to draw just a piece of source bitmap? With your changes it is not possible anymore :)

You go into a wrong direction. There is no need to change Width and Height in the first patch - they are already set by cocoa BitBlt() implementation.

Paul Ishenin

2013-11-21 01:23

manager   ~0071458

Please look at the commited changes. I made an implementation based on your changes but it differs.

Please close if you think it works ok.

accSone

2013-11-22 10:24

developer   ~0071482

Last edited: 2013-11-22 10:31

View 3 revisions

No with your changes SRCCOPY rop doen't behave like in carbon/win32 with

height < image.height or/and width < image.width

This is a somehow legacy behavior in the special SRCCOPY mode, because it doesn't stretch independed from the arguments.

Adding the following after your Min check, will solve it :

 // Width and Height should not be greater than bitmap width
  Width := Min(Width, Bmp.Width);
  Height := Min(Height, Bmp.Height);

+ if Rop=SRCCOPY then
+ begin
+ Width := Bmp.Width;
+ Height := Bmp.Height;
+ end;

To verify:

Compile the following in Carbon and Cocoa and see the difference without my addition

procedure TForm1.FormPaint(Sender: TObject);
var bmBuff:TBitMap;
begin

bmBuff:=TBitMap.Create;

bmBuff.Width:=100;
bmBuff.Height:=100;

bmBuff.Canvas.Brush.Color := clgreen;
bmBuff.Canvas.FillRect(types.rect(0,0,width,height));
bmBuff.Canvas.Brush.Color := clred;
bmBuff.Canvas.FillRect(types.rect(10,25,50,75));
bmBuff.Canvas.Brush.Color := clyellow;
bmBuff.Canvas.FillRect(types.rect(10,75,50,95));


BitBlt(Canvas.Handle,10,10,50,50,bmBuff.Canvas.Handle,10,24,SRCCOPY);

end;

accSone

2013-11-22 10:34

developer   ~0071484

Last edited: 2013-11-22 10:53

View 6 revisions

You're right: I just observed - there is an additional behavior: In carbon/win32 it paints only part of the image but *not* stretched! That could mean that we have to somehow compensate the stretching in SRCOPY rop mode or do it with my approach above and mask the output somehow. At least my projects working with my addition because they didn't used partly painting. For me it would be ok for now to add my addition and a todo remark...

Paul Ishenin

2013-11-23 10:44

manager   ~0071510

Please test with r43474

accSone

2013-11-23 17:21

developer   ~0071518

Works! You're a champ!

Issue History

Date Modified Username Field Change
2013-11-20 14:13 accSone New Issue
2013-11-20 14:14 accSone File Added: fix_0025336.patch
2013-11-20 14:16 accSone Note Added: 0071418
2013-11-20 14:25 Paul Ishenin Assigned To => Paul Ishenin
2013-11-20 14:25 Paul Ishenin Status new => assigned
2013-11-20 15:49 Paul Ishenin Note Added: 0071425
2013-11-20 15:53 accSone File Added: fix_0025336_add.patch
2013-11-20 15:53 accSone Note Added: 0071426
2013-11-20 15:54 accSone Note Edited: 0071426 View Revisions
2013-11-20 16:04 accSone Note Edited: 0071426 View Revisions
2013-11-20 16:04 accSone Note Edited: 0071426 View Revisions
2013-11-21 01:04 Paul Ishenin Note Added: 0071457
2013-11-21 01:23 Paul Ishenin Fixed in Revision => 43468
2013-11-21 01:23 Paul Ishenin LazTarget => -
2013-11-21 01:23 Paul Ishenin Note Added: 0071458
2013-11-21 01:23 Paul Ishenin Status assigned => resolved
2013-11-21 01:23 Paul Ishenin Fixed in Version => 1.4
2013-11-21 01:23 Paul Ishenin Resolution open => fixed
2013-11-22 10:24 accSone Note Added: 0071482
2013-11-22 10:24 accSone Note Edited: 0071482 View Revisions
2013-11-22 10:31 accSone Note Edited: 0071482 View Revisions
2013-11-22 10:34 accSone Note Added: 0071484
2013-11-22 10:49 accSone Note Edited: 0071484 View Revisions
2013-11-22 10:50 accSone Note Edited: 0071484 View Revisions
2013-11-22 10:52 accSone Note Edited: 0071484 View Revisions
2013-11-22 10:52 accSone Note Edited: 0071484 View Revisions
2013-11-22 10:53 accSone Note Edited: 0071484 View Revisions
2013-11-23 10:44 Paul Ishenin Note Added: 0071510
2013-11-23 17:21 accSone Note Added: 0071518
2013-11-23 17:21 accSone Status resolved => closed