diff --git a/lcl/interfaces/cocoa/cocoagdiobjects.pas b/lcl/interfaces/cocoa/cocoagdiobjects.pas index e463c2afea..41f9032e78 100644 --- a/lcl/interfaces/cocoa/cocoagdiobjects.pas +++ b/lcl/interfaces/cocoa/cocoagdiobjects.pas @@ -1038,10 +1038,23 @@ begin end; procedure TCocoaContext.SetBkColor(AValue: TColor); +var + SysBrush: TCocoaBrush; + Color: NSColor; begin - AValue := TColor(ColorToRGB(AValue)); - FBkColor := AValue; - FBkBrush.SetColor(AValue, BkMode = OPAQUE); + if IsSysColor(AValue) then + begin + SysBrush := TCocoaBrush(CocoaWidgetSet.GetSysColorBrush(SysColorToSysColorIndex(AValue))); + Color := TCocoaBrush(SysBrush).Color; + FBkColor := NSColorToColorRef(Color); + FBkBrush.Color := Color; + FBkBrush.Solid := BkMode = OPAQUE; + end + else + begin + FBkColor := AValue; + FBkBrush.SetColor(AValue, BkMode = OPAQUE); + end; end; procedure TCocoaContext.SetBkMode(AValue: Integer); diff --git a/lcl/interfaces/cocoa/cocoautils.pas b/lcl/interfaces/cocoa/cocoautils.pas index d7d1071938..b41362dd61 100644 --- a/lcl/interfaces/cocoa/cocoautils.pas +++ b/lcl/interfaces/cocoa/cocoautils.pas @@ -59,7 +59,10 @@ function GetNSControlValue(c: NSControl): String; inline; procedure ColorToRGBFloat(cl: TColorRef; var r,g,b: Single); inline; function RGBToColorFloat(r,g,b: Single): TColorRef; inline; +// extract ColorRef from NSColor in RGB colorspace function NSColorToRGB(const Color: NSColor): TColorRef; inline; +// extract ColorRef from any NSColor +function NSColorToColorRef(const Color: NSColor): TColorRef; function ColorToNSColor(const Color: TColorRef): NSColor; inline; implementation @@ -85,6 +88,66 @@ begin Result := RGBToColorFloat(redComponent, greenComponent, blueComponent); end; +function NSColorToColorRef(const Color: NSColor): TColorRef; + +function AverageColor(Color1, Color2: TColorRef): TColorRef; inline; + begin + if Color1 = Color2 then + Result := Color1 + else + Result := + (((Color1 and $FF) + (Color2 and $FF)) shr 1) and $FF or + (((((Color1 shr 8) and $FF) + ((Color2 shr 8) and $FF)) shr 1) and $FF) shl 8 or + (((((Color1 shr 16) and $FF) + ((Color2 shr 16) and $FF)) shr 1) and $FF) shl 16; + end; + +var + LocalPool: NSAutoReleasePool; + RGBColor, PatternColor: NSColor; + ImageRep: NSImageRep; + x, y: Integer; +begin + LocalPool := NSAutoReleasePool.alloc.init; + RGBColor := Color.colorUsingColorSpaceName(NSCalibratedRGBColorSpace); + // if color is a pattern it can't be converted as is to a solid color value + if RGBColor = nil then + begin + PatternColor := Color.colorUsingColorSpaceName(NSPatternColorSpace); + if PatternColor = nil then + Result := 0 + else + begin + // compute an average color of the top left 2x2 rectangle + ImageRep := PatternColor.patternImage.bestRepresentationForRect_context_hints(RectToNSRect(Types.Rect(0, 0, 1, 1)), nil, nil); + if (ImageRep = nil) or not ImageRep.isKindOfClass(NSBitmapImageRep) then + Result := 0 + else + begin + for y := 0 to ImageRep.pixelsHigh - 1 do + for x := 0 to ImageRep.pixelsWide - 1 do + begin + RGBColor := NSBitmapImageRep(ImageRep).colorAtX_y(x, y).colorUsingColorSpaceName(NSCalibratedRGBColorSpace); + if Assigned(RGBColor) then + begin + if (x = 0) and (y = 0) then + Result := NSColorToRGB(RGBColor) + else + Result := AverageColor(Result, NSColorToRGB(RGBColor)) + end + else + begin + Result := 0; + break; + end + end; + end; + end; + end + else + Result := NSColorToRGB(RGBColor); + LocalPool.release; +end; + function ColorToNSColor(const Color: TColorRef): NSColor; inline; begin Result := NSColor.colorWithCalibratedRed_green_blue_alpha( diff --git a/lcl/interfaces/cocoa/cocoawinapi.inc b/lcl/interfaces/cocoa/cocoawinapi.inc index 901235e9d9..c0d5fb18b0 100644 --- a/lcl/interfaces/cocoa/cocoawinapi.inc +++ b/lcl/interfaces/cocoa/cocoawinapi.inc @@ -1047,23 +1047,8 @@ begin end; function TCocoaWidgetSet.GetSysColor(nIndex: Integer): DWORD; - - function AverageColor(Color1, Color2: TColorRef): TColorRef; inline; - begin - if Color1 = Color2 then - Result := Color1 - else - Result := - (((Color1 and $FF) + (Color2 and $FF)) shr 1) and $FF or - (((((Color1 shr 8) and $FF) + ((Color2 shr 8) and $FF)) shr 1) and $FF) shl 8 or - (((((Color1 shr 16) and $FF) + ((Color2 shr 16) and $FF)) shr 1) and $FF) shl 16; - end; - var - LocalPool: NSAutoReleasePool; - Color, RGBColor, PatternColor: NSColor; - ImageRep: NSImageRep; - x, y: Integer; + Color: NSColor; SysBrush: HBrush; begin // 1. get the system brush - it has a NSColor reference @@ -1077,47 +1062,7 @@ begin Color := TCocoaBrush(SysBrush).Color; if Assigned(Color) then - begin - LocalPool := NSAutoReleasePool.alloc.init; - RGBColor := Color.colorUsingColorSpaceName(NSCalibratedRGBColorSpace); - // if color is a pattern it can't be converted as is to a solid color value - if RGBColor = nil then - begin - PatternColor := Color.colorUsingColorSpaceName(NSPatternColorSpace); - if PatternColor = nil then - Result := 0 - else - begin - // compute an average color of the top left 2x2 rectangle - ImageRep := PatternColor.patternImage.bestRepresentationForRect_context_hints(RectToNSRect(Types.Rect(0, 0, 1, 1)), nil, nil); - if (ImageRep = nil) or not ImageRep.isKindOfClass(NSBitmapImageRep) then - Result := 0 - else - begin - for y := 0 to ImageRep.pixelsHigh - 1 do - for x := 0 to ImageRep.pixelsWide - 1 do - begin - RGBColor := NSBitmapImageRep(ImageRep).colorAtX_y(x, y).colorUsingColorSpaceName(NSCalibratedRGBColorSpace); - if Assigned(RGBColor) then - begin - if (x = 0) and (y = 0) then - Result := NSColorToRGB(RGBColor) - else - Result := AverageColor(Result, NSColorToRGB(RGBColor)) - end - else - begin - Result := 0; - break; - end - end; - end; - end; - end - else - Result := NSColorToRGB(RGBColor); - LocalPool.release; - end + Result := NSColorToColorRef(Color) else Result := 0; end;