View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0036565 | Patches | Widgetset | public | 2020-01-12 18:39 | 2020-01-13 11:19 |
Reporter | Yuriy Sydorov | Assigned To | Dmitry Boyarintsev | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Product Version | 2.1 (SVN) | ||||
Summary | 0036565: Cocoa: Fixes for pattern brush to be Windows widgetset and Delphi compatible. | ||||
Description | Attached patch resolves the following: - Properly draw custom monochrome brush patterns. The current brush color is used to paint the pattern's background, the current text color is used to paint the pattern's foreground. - Fixed pattern alignment. | ||||
Steps To Reproduce | Attached the patch, a demo project, screenshots of the demo project to demonstrate the same brush drawing after the patch on Mac and Windows. | ||||
Tags | No tags attached. | ||||
Fixed in Revision | 62539 | ||||
LazTarget | - | ||||
Widgetset | Cocoa | ||||
Attached Files |
|
|
pattern_brush.diff (6,059 bytes)
Index: lcl/interfaces/cocoa/cocoagdiobjects.pas =================================================================== --- lcl/interfaces/cocoa/cocoagdiobjects.pas (revision 62502) +++ lcl/interfaces/cocoa/cocoagdiobjects.pas (working copy) @@ -119,16 +119,20 @@ property ColorRef: TColorRef read GetColorRef; end; + TCocoaPatternColorMode = (cpmBitmap, cpmBrushColor, cpmContextColor); + { TCocoaBrush } TCocoaBrush = class(TCocoaColorObject) strict private FCGPattern: CGPatternRef; - FColored: Boolean; + FPatternColorMode: TCocoaPatternColorMode; FBitmap: TCocoaBitmap; FColor: NSColor; + FFgColor: TColorRef; private FImage: CGImageRef; + procedure DrawPattern(c: CGContextRef); strict protected procedure Clear; @@ -3090,11 +3094,8 @@ procedure DrawBitmapPattern(info: UnivPtr; c: CGContextRef); MWPascal; var ABrush: TCocoaBrush absolute info; - AImage: CGImageRef; begin - AImage := ABrush.FImage; - CGContextDrawImage(c, GetCGRect(0, 0, CGImageGetWidth(AImage), CGImageGetHeight(AImage)), - AImage); + ABrush.DrawPattern(c); end; procedure TCocoaBrush.SetHatchStyle(AHatch: PtrInt); @@ -3122,11 +3123,11 @@ CGDataProvider := CGDataProviderCreateWithData(nil, @HATCH_DATA[AHatch], 8, nil); FImage := CGImageMaskCreate(8, 8, 1, 1, 1, CGDataProvider, nil, 0); CGDataProviderRelease(CGDataProvider); - FColored := False; + FPatternColorMode := cpmBrushColor; if FCGPattern <> nil then CGPatternRelease(FCGPattern); FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, 8, 8), CGAffineTransformIdentity, 8.0, 8.0, kCGPatternTilingConstantSpacing, - Ord(FColored), ACallBacks); + 0, ACallBacks); end; end; @@ -3134,6 +3135,7 @@ var AWidth, AHeight: Integer; ACallBacks: CGPatternCallbacks; + CGDataProvider: CGDataProviderRef; begin AWidth := ABitmap.Width; AHeight := ABitmap.Height; @@ -3142,12 +3144,25 @@ if (FBitmap <> nil) then FBitmap.Release; FBitmap := TCocoaBitmap.Create(ABitmap); if FImage <> nil then CGImageRelease(FImage); - FImage := CGImageCreateCopy(MacOSAll.CGImageRef( FBitmap.imageRep.CGImageForProposedRect_context_hints(nil, nil, nil))); - FColored := True; + if FBitmap.BitmapType = cbtMono then + begin + with FBitmap do + begin + CGDataProvider := CGDataProviderCreateWithData(nil, Data, DataSize, nil); + FImage := CGImageMaskCreate(Width, Height, BitsPerSample, BitsPerPixel, BytesPerRow, CGDataProvider, nil, 0); + CGDataProviderRelease(CGDataProvider); + end; + FPatternColorMode := cpmContextColor; + end + else + begin + FImage := CGImageCreateCopy(MacOSAll.CGImageRef( FBitmap.imageRep.CGImageForProposedRect_context_hints(nil, nil, nil))); + FPatternColorMode := cpmBitmap; + end; if FCGPattern <> nil then CGPatternRelease(FCGPattern); FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, AWidth, AHeight), CGAffineTransformIdentity, CGFloat(AWidth), CGFloat(AHeight), kCGPatternTilingConstantSpacing, - Ord(FColored), ACallBacks); + Ord(FPatternColorMode = cpmBitmap), ACallBacks); end; procedure TCocoaBrush.SetImage(AImage: NSImage); @@ -3159,7 +3174,7 @@ ACallBacks.drawPattern := @DrawBitmapPattern; if FImage <> nil then CGImageRelease(FImage); FImage := CGImageCreateCopy(MacOSAll.CGImageRef( AImage.CGImageForProposedRect_context_hints(nil, nil, nil))); - FColored := True; + FPatternColorMode := cpmBitmap; Rect.origin.x := 0; Rect.origin.y := 0; Rect.size := CGSize(AImage.size); @@ -3166,7 +3181,7 @@ if FCGPattern <> nil then CGPatternRelease(FCGPattern); FCGPattern := CGPatternCreate(Self, Rect, CGAffineTransformIdentity, Rect.size.width, Rect.size.height, kCGPatternTilingConstantSpacing, - Ord(FColored), ACallBacks); + 1, ACallBacks); end; procedure TCocoaBrush.SetColor(AColor: NSColor); @@ -3274,6 +3289,22 @@ end; end; +procedure TCocoaBrush.DrawPattern(c: CGContextRef); +var + R: CGRect; + sR, sG, sB: single; +begin + R:=CGRectMake(0, 0, CGImageGetWidth(FImage), CGImageGetHeight(FImage)); + if FPatternColorMode = cpmContextColor then + begin + CGContextSetRGBFillColor(c, Red/255, Green/255, Blue/255, 1); + CGContextFillRect(c, R); + ColorToRGBFloat(FFgColor, sR, sG, sB); + CGContextSetRGBFillColor(c, sR, sG, sB, 1); + end; + CGContextDrawImage(c, R, FImage); +end; + procedure TCocoaBrush.Clear; begin if FColor <> nil then @@ -3313,6 +3344,9 @@ AROP2: Integer; APatternSpace: CGColorSpaceRef; BaseSpace: CGColorSpaceRef; + sR, sG, sB: single; + sz: CGSize; + offset: TPoint; begin if ADC = nil then Exit; @@ -3333,13 +3367,39 @@ if Assigned(FCGPattern) then begin - if not FColored then - BaseSpace := CGColorSpaceCreateDeviceRGB - else + // Set proper pattern alignment + offset:=ADC.GetLogicalOffset; + with CGPointApplyAffineTransform(CGPointMake(0,0), CGContextGetCTM(ADC.CGContext)) do begin - BaseSpace := nil; - RGBA[0] := 1.0; + sz.width:=x - offset.X; + sz.height:=y + offset.Y; + sz.width:=Round(sz.width) mod CGImageGetWidth(FImage); + sz.height:=Round(sz.height) mod CGImageGetHeight(FImage); end; + CGContextSetPatternPhase(ADC.CGContext, sz); + + case FPatternColorMode of + cpmBitmap: + begin + BaseSpace := nil; + RGBA[0] := 1.0; + end; + cpmBrushColor: + begin + BaseSpace := CGColorSpaceCreateDeviceRGB; + end; + cpmContextColor: + begin + BaseSpace := CGColorSpaceCreateDeviceRGB; + SetColor(ADC.BkColor, True); + FFgColor:=ColorToRGB(ADC.TextColor); + ColorToRGBFloat(FFgColor, sR, sG, sB); + RGBA[0]:=sR; + RGBA[1]:=sG; + RGBA[2]:=sB; + RGBA[3]:=1.0; + end; + end; APatternSpace := CGColorSpaceCreatePattern(BaseSpace); CGContextSetFillColorSpace(ADC.CGContext, APatternSpace); CGColorSpaceRelease(APatternSpace); |
|
thanks for the patch, applied. please test and close if ok |
|
As a side note, I don't do Cocoa Widget but Windows has a function "SetBrushOrgEx" which offsets the Brush pattern so if you want to keep with that note in mind a little research if the widget set supports this feature and if it does then maybe the code should also test the Offset ? Its possible all of this al already taken care of in the under layer but I don't see that here. |
|
please update the sample to test the offset. I don't recall any code that would support it. |
|
Thanks for applying the patch. There is no cross-platform support for SetBrushOrgEx in LCL. Also there is no TCanvas API to change brush alignment. By default brush patterns must be aligned to the top-left corner of the device context. Now the Cocoa widgetset handles brush patterns properly. |
Date Modified | Username | Field | Change |
---|---|---|---|
2020-01-12 18:39 | Yuriy Sydorov | New Issue | |
2020-01-12 18:39 | Yuriy Sydorov | File Added: pattern_brush.diff | |
2020-01-12 18:39 | Yuriy Sydorov | File Added: screen-mac.png | |
2020-01-12 18:39 | Yuriy Sydorov | File Added: screen-win.png | |
2020-01-12 18:39 | Yuriy Sydorov | File Added: demo.zip | |
2020-01-12 21:21 | Dmitry Boyarintsev | Assigned To | => Dmitry Boyarintsev |
2020-01-12 21:21 | Dmitry Boyarintsev | Status | new => resolved |
2020-01-12 21:21 | Dmitry Boyarintsev | Resolution | open => fixed |
2020-01-12 21:21 | Dmitry Boyarintsev | Fixed in Revision | => 62539 |
2020-01-12 21:21 | Dmitry Boyarintsev | LazTarget | => - |
2020-01-12 21:21 | Dmitry Boyarintsev | Widgetset | Cocoa => Cocoa |
2020-01-12 21:21 | Dmitry Boyarintsev | Note Added: 0120375 | |
2020-01-13 02:58 | jamie philbrook | Note Added: 0120390 | |
2020-01-13 04:30 | Dmitry Boyarintsev | Note Added: 0120392 | |
2020-01-13 11:18 | Yuriy Sydorov | Note Added: 0120396 | |
2020-01-13 11:19 | Yuriy Sydorov | Status | resolved => closed |