|
28 | 28 | return button;
|
29 | 29 | }
|
30 | 30 |
|
31 |
| -static CGFloat calculateBrightness(NSColor *color) { |
32 |
| - if (color.colorSpace.colorSpaceModel == NSColorSpaceModelRGB) { |
33 |
| - // Calculate brightness according to a formula from |
34 |
| - // the W3C that gives brightness as the eye perceives it. Then lighten |
35 |
| - // or darken the default colors based on whether brightness is greater |
36 |
| - // than 50% to achieve good visual contrast. |
37 |
| - // www.w3.org/WAI/ER/WD-AERT/#color-contrast |
38 |
| - CGFloat r, g, b; |
39 |
| - [color getRed:&r green:&g blue:&b alpha:NULL]; |
40 |
| - return r * 0.299 + g * 0.114 + b * 0.587; |
41 |
| - } else if (color.colorSpace.colorSpaceModel == NSColorSpaceModelGray) { |
42 |
| - return color.whiteComponent; |
43 |
| - } |
44 |
| - return 1; |
45 |
| -} |
46 |
| - |
47 | 31 | @implementation MMTabline
|
48 | 32 | {
|
49 | 33 | NSView *_tabsContainer;
|
@@ -299,7 +283,11 @@ - (NSColor *)tablineStrokeColor
|
299 | 283 |
|
300 | 284 | // High-contrast modes. Should stroke to make it easier to read.
|
301 | 285 | NSColor *bgColor = self.tablineBgColor;
|
302 |
| - CGFloat brightness = calculateBrightness(bgColor); |
| 286 | + CGFloat brightness = 1; |
| 287 | + if (bgColor.colorSpace.colorSpaceModel == NSColorSpaceModelRGB) |
| 288 | + brightness = bgColor.brightnessComponent; |
| 289 | + else if (bgColor.colorSpace.colorSpaceModel == NSColorSpaceModelGray) |
| 290 | + brightness = bgColor.whiteComponent; |
303 | 291 | if (brightness > 0.5)
|
304 | 292 | return NSColor.blackColor;
|
305 | 293 | else
|
@@ -565,29 +553,63 @@ - (void)setAutoColorsSelBg:(NSColor *)back fg:(NSColor *)fore;
|
565 | 553 | {
|
566 | 554 | // Set the colors for the tabline based on the default background and
|
567 | 555 | // foreground colors.
|
568 |
| - const CGFloat brightness = calculateBrightness(back); |
569 | 556 |
|
| 557 | + // Calculate CIE Lab color. This is used for deriving other colors that are |
| 558 | + // brighter / darker versions of the background color. Using Lab gives better |
| 559 | + // results than simpy blending non-linearized RGB values. |
| 560 | + // Note: We don't use CGColorSpaceCreateWithName(kCGColorSpaceGenericLab) |
| 561 | + // because the API is only available on macOS 10.13+. |
| 562 | + const CGFloat whitePoint[3] = {0.95947,1,1.08883}; // D65 white point |
| 563 | + const CGFloat blackPoint[3] = {0,0,0}; |
| 564 | + const CGFloat ranges[4] = {-127, 127, -127, 127}; |
| 565 | + CGColorSpaceRef labRef = CGColorSpaceCreateLab(whitePoint, blackPoint, ranges); |
| 566 | + NSColorSpace *lab = [[NSColorSpace alloc] initWithCGColorSpace:labRef]; |
| 567 | + NSColor *backLab = [back colorUsingColorSpace:lab]; |
| 568 | + CGColorSpaceRelease(labRef); |
| 569 | + if (backLab.numberOfComponents > 4) |
| 570 | + backLab = nil; // don't know how this could happen, but just to be safe |
| 571 | + |
| 572 | + CGFloat backComponents[4] = { 1, 0, 0, 1 }; // L*/a*/b*/alpha. L* is perceptual lightness from 0-100. |
| 573 | + [backLab getComponents:backComponents]; |
| 574 | + CGFloat newComponents[4]; |
| 575 | + memcpy(newComponents, backComponents, sizeof(newComponents)); |
| 576 | + |
| 577 | + // Contrast (different in lightness) for fill bg and tab bg colors relative to the background color |
| 578 | + // Note that this is not perceptively accurate to just add a fixed offset to the L* value but it's |
| 579 | + // good enough for our purpose. |
| 580 | + const CGFloat fillContrastDark = 17.0; |
| 581 | + const CGFloat bgContrastDark = fillContrastDark * 0.71; |
| 582 | + const CGFloat fillContrastLight = -19.0; |
| 583 | + const CGFloat bgContrastLight = fillContrastLight * 0.70; |
| 584 | + |
| 585 | + const CGFloat fillContrast = backComponents[0] >= 40 ? fillContrastLight : fillContrastDark; |
| 586 | + const CGFloat bgContrast = backComponents[0] >= 40 ? bgContrastLight : bgContrastDark; |
| 587 | + |
| 588 | + // Assign the colors |
570 | 589 | _tablineSelBgColor = back;
|
571 | 590 |
|
572 |
| - _tablineSelFgColor = (brightness > 0.5) |
573 |
| - ? [fore blendedColorWithFraction:0.6 ofColor:NSColor.blackColor] |
574 |
| - : [fore blendedColorWithFraction:0.6 ofColor:NSColor.whiteColor]; |
| 591 | + _tablineSelFgColor = [fore blendedColorWithFraction:0.6 |
| 592 | + ofColor:(backComponents[0] >= 50 ? NSColor.blackColor : NSColor.whiteColor)]; |
575 | 593 | _addTabButton.fgColor = _tablineSelFgColor;
|
576 | 594 | _backwardScrollButton.fgColor = _tablineSelFgColor;
|
577 | 595 | _forwardScrollButton.fgColor = _tablineSelFgColor;
|
578 | 596 |
|
579 |
| - _tablineBgColor = (brightness > 0.5) |
580 |
| - ? [back blendedColorWithFraction:0.16 ofColor:NSColor.blackColor] |
581 |
| - : [back blendedColorWithFraction:0.13 ofColor:NSColor.whiteColor]; |
| 597 | + newComponents[0] = backComponents[0] + bgContrast; |
| 598 | + _tablineBgColor = [[NSColor colorWithColorSpace:lab |
| 599 | + components:newComponents |
| 600 | + count:4] |
| 601 | + colorUsingColorSpace:NSColorSpace.sRGBColorSpace]; |
582 | 602 |
|
583 | 603 | _tablineFgColor = [_tablineSelFgColor blendedColorWithFraction:0.5 ofColor:_tablineBgColor];
|
584 | 604 |
|
585 | 605 | _tablineUnfocusedFgColor = [_tablineFgColor blendedColorWithFraction:0.4 ofColor:_tablineBgColor];
|
586 | 606 | _tablineUnfocusedSelFgColor = [_tablineSelFgColor blendedColorWithFraction:0.38 ofColor:_tablineSelBgColor];
|
587 | 607 |
|
588 |
| - _tablineFillBgColor = (brightness > 0.5) |
589 |
| - ? [back blendedColorWithFraction:0.25 ofColor:NSColor.blackColor] |
590 |
| - : [back blendedColorWithFraction:0.18 ofColor:NSColor.whiteColor]; |
| 608 | + newComponents[0] = backComponents[0] + fillContrast; |
| 609 | + _tablineFillBgColor = [[NSColor colorWithColorSpace:lab |
| 610 | + components:newComponents |
| 611 | + count:4] |
| 612 | + colorUsingColorSpace:NSColorSpace.sRGBColorSpace]; |
591 | 613 |
|
592 | 614 | [self updateTabStates];
|
593 | 615 | self.needsDisplay = YES;
|
|
0 commit comments