diff --git a/Boxer.xcodeproj/project.pbxproj b/Boxer.xcodeproj/project.pbxproj index 2f4a287cc..0ee4eb246 100644 --- a/Boxer.xcodeproj/project.pbxproj +++ b/Boxer.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -47,6 +47,8 @@ 5514503A24BE8DE60002CE28 /* envelope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5514503824BE8DE50002CE28 /* envelope.cpp */; }; 5514503D24BE8FB90002CE28 /* program_autotype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5514503B24BE8FB90002CE28 /* program_autotype.cpp */; }; 5514503E24BE8FB90002CE28 /* program_autotype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5514503B24BE8FB90002CE28 /* program_autotype.cpp */; }; + 55215F452AD22FD8007C7C68 /* MT32LCDDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55215F442AD22FD8007C7C68 /* MT32LCDDisplay.swift */; }; + 55215F462AD22FD8007C7C68 /* MT32LCDDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55215F442AD22FD8007C7C68 /* MT32LCDDisplay.swift */; }; 55220E3824CFFF8C00A6736A /* BXShaderParametersWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 058BC52324C27B790078C244 /* BXShaderParametersWindowController.m */; }; 55220E3924CFFF8C00A6736A /* BXShadersModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 058BC51F24C27B770078C244 /* BXShadersModel.swift */; }; 55220E3A24CFFF8C00A6736A /* BXShadersModel+OpenEmu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 058BC52124C27B780078C244 /* BXShadersModel+OpenEmu.swift */; }; @@ -425,7 +427,6 @@ 9F2D30AF15B8233800FAE848 /* BXCoalfaceAudio.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9F34BE3E142B700100A69FAF /* BXCoalfaceAudio.mm */; }; 9F2D30B015B8233800FAE848 /* BXEmulator+BXAudio.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9F34BE5E142B851700A69FAF /* BXEmulator+BXAudio.mm */; }; 9F2D30B115B8233800FAE848 /* BXBaseAppController+BXSupportFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F34BE61142B917100A69FAF /* BXBaseAppController+BXSupportFiles.m */; }; - 9F2D30B215B8233800FAE848 /* BXMT32LCDDisplay.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBEC4EF142CE8300016964A /* BXMT32LCDDisplay.m */; }; 9F2D30B315B8233800FAE848 /* BXMIDISynth.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F902C23142E183500843B01 /* BXMIDISynth.m */; }; 9F2D30B415B8233800FAE848 /* BXEmulatedMT32.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9F902C26142E198100843B01 /* BXEmulatedMT32.mm */; }; 9F2D30B515B8233800FAE848 /* BXExternalMIDIDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F902C29142E199100843B01 /* BXExternalMIDIDevice.m */; }; @@ -763,7 +764,6 @@ 9FBC3C780F56E0D7001811F2 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FBC3C760F56E0D7001811F2 /* AudioUnit.framework */; }; 9FBC3C790F56E0D7001811F2 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FBC3C770F56E0D7001811F2 /* CoreMIDI.framework */; }; 9FBD321710E5144C00031CB6 /* Brand.png in Resources */ = {isa = PBXBuildFile; fileRef = 9FBD321610E5144C00031CB6 /* Brand.png */; }; - 9FBEC4F0142CE8300016964A /* BXMT32LCDDisplay.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBEC4EF142CE8300016964A /* BXMT32LCDDisplay.m */; }; 9FBF66AF11F35ADD00DAAB9A /* ADBSingleFileTransfer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FBF66AE11F35ADD00DAAB9A /* ADBSingleFileTransfer.m */; }; 9FC1620E119E9AD700705EA5 /* BXCursorFadeAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FC1620D119E9AD700705EA5 /* BXCursorFadeAnimation.m */; }; 9FC2F84013D60FBD00BD4F6B /* BXDualActionControllerProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FC2F83F13D60FBD00BD4F6B /* BXDualActionControllerProfile.m */; }; @@ -1092,6 +1092,7 @@ 5514503B24BE8FB90002CE28 /* program_autotype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = program_autotype.cpp; sourceTree = ""; }; 5514503C24BE8FB90002CE28 /* program_autotype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = program_autotype.h; sourceTree = ""; }; 551B793625593573006C57CE /* URL+ADBFilesystemHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ADBFilesystemHelpers.swift"; sourceTree = ""; }; + 55215F442AD22FD8007C7C68 /* MT32LCDDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MT32LCDDisplay.swift; sourceTree = ""; }; 5529311E252AF0DA0069EB35 /* soft_limiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = soft_limiter.h; sourceTree = ""; }; 55419B67255A2F1400A779B2 /* URL+ADBQuickLookHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ADBQuickLookHelpers.swift"; sourceTree = ""; }; 55419B73255A7FFA00A779B2 /* URL+ADBAliasHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ADBAliasHelpers.swift"; sourceTree = ""; }; @@ -1898,8 +1899,6 @@ 9FBC3C770F56E0D7001811F2 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; 9FBC3CB10F56E32C001811F2 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = ""; }; 9FBD321610E5144C00031CB6 /* Brand.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Brand.png; sourceTree = ""; }; - 9FBEC4EE142CE8300016964A /* BXMT32LCDDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BXMT32LCDDisplay.h; sourceTree = ""; }; - 9FBEC4EF142CE8300016964A /* BXMT32LCDDisplay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BXMT32LCDDisplay.m; sourceTree = ""; }; 9FBF66AD11F35ADD00DAAB9A /* ADBSingleFileTransfer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADBSingleFileTransfer.h; sourceTree = ""; }; 9FBF66AE11F35ADD00DAAB9A /* ADBSingleFileTransfer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADBSingleFileTransfer.m; sourceTree = ""; usesTabs = 1; }; 9FBF66FC11F376B900DAAB9A /* ADBOperationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADBOperationDelegate.h; sourceTree = ""; }; @@ -2910,8 +2909,7 @@ 9F57684815DA27A300B50500 /* BXHUDSpinningProgressIndicator.m */, 9F60B0DA13AA418300F06BB1 /* BXCollectionItemView.h */, 9F60B0DB13AA418300F06BB1 /* BXCollectionItemView.m */, - 9FBEC4EE142CE8300016964A /* BXMT32LCDDisplay.h */, - 9FBEC4EF142CE8300016964A /* BXMT32LCDDisplay.m */, + 55215F442AD22FD8007C7C68 /* MT32LCDDisplay.swift */, 9FC1620C119E9AD700705EA5 /* BXCursorFadeAnimation.h */, 9FC1620D119E9AD700705EA5 /* BXCursorFadeAnimation.m */, ); @@ -4305,6 +4303,7 @@ 9F0F2B9512AD3C8500CD7078 /* ADBFileTransferSet.m in Sources */, 9F444FCC12AEA28700A2D405 /* ADBOperationSet.m in Sources */, 9F444FFF12AEBE5200A2D405 /* BXDriveBundleImport.m in Sources */, + 55215F452AD22FD8007C7C68 /* MT32LCDDisplay.swift in Sources */, 9F44500212AEC0FC00A2D405 /* BXSimpleDriveImport.m in Sources */, 5514502224BE81E00002CE28 /* ppscale.c in Sources */, 9F2120F813015653002AB1B7 /* BXShelfArt.m in Sources */, @@ -4363,7 +4362,6 @@ 9F34BE40142B700100A69FAF /* BXCoalfaceAudio.mm in Sources */, 9F34BE5F142B851800A69FAF /* BXEmulator+BXAudio.mm in Sources */, 9F34BE62142B917100A69FAF /* BXBaseAppController+BXSupportFiles.m in Sources */, - 9FBEC4F0142CE8300016964A /* BXMT32LCDDisplay.m in Sources */, 9F902C24142E183500843B01 /* BXMIDISynth.m in Sources */, 55DB150427EDA2C70024AE9E /* program_boot.cpp in Sources */, 9F902C27142E198100843B01 /* BXEmulatedMT32.mm in Sources */, @@ -4589,6 +4587,7 @@ 9F2D2FA415B8233800FAE848 /* BXCloseAlert.m in Sources */, 9F2D2FA515B8233800FAE848 /* NSAlert+BXAlert.m in Sources */, 9F2D2FA615B8233800FAE848 /* BXHelpMenuController.m in Sources */, + 55215F462AD22FD8007C7C68 /* MT32LCDDisplay.swift in Sources */, 9F2D2FA715B8233800FAE848 /* NSWorkspace+ADBMountedVolumes.m in Sources */, 9F2D2FA815B8233800FAE848 /* BXGamebox.m in Sources */, 9F2D2FA915B8233800FAE848 /* BXEmulator+BXDOSFileSystem.mm in Sources */, @@ -4823,7 +4822,6 @@ 9F2D30AF15B8233800FAE848 /* BXCoalfaceAudio.mm in Sources */, 9F2D30B015B8233800FAE848 /* BXEmulator+BXAudio.mm in Sources */, 9F2D30B115B8233800FAE848 /* BXBaseAppController+BXSupportFiles.m in Sources */, - 9F2D30B215B8233800FAE848 /* BXMT32LCDDisplay.m in Sources */, 9F2D30B315B8233800FAE848 /* BXMIDISynth.m in Sources */, 9F2D30B415B8233800FAE848 /* BXEmulatedMT32.mm in Sources */, 5557480C208FA8040045E635 /* sn76496.cpp in Sources */, diff --git a/Boxer/BXMT32LCDDisplay.h b/Boxer/BXMT32LCDDisplay.h deleted file mode 100644 index bbdf90a45..000000000 --- a/Boxer/BXMT32LCDDisplay.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright (c) 2013 Alun Bestor and contributors. All rights reserved. - This source file is released under the GNU General Public License 2.0. A full copy of this license - can be found in this XCode project at Resources/English.lproj/BoxerHelp/pages/legalese.html, or read - online at [http://www.gnu.org/licenses/gpl-2.0.txt]. - */ - - -#import - -/// BXMT32LCDDisplay imitates, as the name suggests, the LCD display on a Roland MT-32 Sound Module. -/// It is used for displaying messages sent by the games to the emulated MT-32. (Many Sierra games -/// would send cheeky messages to it on startup.) -/// -/// This field can only display ASCII characters, as that was all the MT-32's display could handle. -/// Non-ASCII characters will be drawn as empty space. -@interface BXMT32LCDDisplay : NSTextField - -/// The image containing glyph data for the pixel font. -- (NSImage *) pixelFont; - -/// The mask image to use for the LCD pixel grid. -/// This will be drawn in for 20 character places. -- (NSImage *) pixelGrid; - -/// The background color of the field. -- (NSColor *) screenColor; - -/// The background color of the LCD pixel grid. -- (NSColor *) gridColor; - -/// The colour of lit LCD pixels upon the grid. -- (NSColor *) pixelColor; - -/// The inner shadow of the screen. -- (NSShadow *) innerShadow; - -/// The lighting effects applied on top of the screen. -- (NSGradient *) screenLighting; - -@end diff --git a/Boxer/BXMT32LCDDisplay.m b/Boxer/BXMT32LCDDisplay.m deleted file mode 100644 index a914343c5..000000000 --- a/Boxer/BXMT32LCDDisplay.m +++ /dev/null @@ -1,181 +0,0 @@ -/* - Copyright (c) 2013 Alun Bestor and contributors. All rights reserved. - This source file is released under the GNU General Public License 2.0. A full copy of this license - can be found in this XCode project at Resources/English.lproj/BoxerHelp/pages/legalese.html, or read - online at [http://www.gnu.org/licenses/gpl-2.0.txt]. - */ - -#import "BXMT32LCDDisplay.h" -#import "NSShadow+ADBShadowExtensions.h" -#import "NSImage+ADBImageEffects.h" -#import "NSBezierPath+MCAdditions.h" -#import "ADBGeometry.h" - - -@implementation BXMT32LCDDisplay - -- (NSImage *) pixelFont -{ - return [NSImage imageNamed: @"MT32ScreenDisplay/MT32LCDFontTemplate"]; -} - -- (NSImage *) pixelGrid -{ - return [NSImage imageNamed: @"MT32ScreenDisplay/MT32LCDGridTemplate"]; -} - -- (NSColor *) screenColor -{ - return [NSColor colorNamed: @"MT32ScreenDisplay/screenColor"]; -} - -- (NSColor *) frameColor -{ - return [NSColor colorNamed: @"MT32ScreenDisplay/frameColor"]; -} - -- (NSColor *) gridColor -{ - return [NSColor colorNamed: @"MT32ScreenDisplay/gridColor"]; -} - -- (NSColor *) pixelColor -{ - return [NSColor colorNamed: @"MT32ScreenDisplay/pixelColor"]; -} - -- (NSShadow *) innerShadow -{ - return [NSShadow shadowWithBlurRadius: 10.0 - offset: NSMakeSize(0, -2.0) - color: [NSColor colorNamed: @"MT32ScreenDisplay/innerShadowColor"]]; -} - -- (NSGradient *) screenLighting -{ - NSGradient *lighting = [[NSGradient alloc] initWithColorsAndLocations: - [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.10], 0.0, - [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.07], 0.5, - [NSColor clearColor], 0.55, - nil]; - return lighting; -} - -- (void) drawRect: (NSRect)dirtyRect -{ - NSString *charsToDisplay = [[self stringValue] stringByPaddingToLength: 20 - withString: @" " - startingAtIndex: 0]; - - NSImage *fontTemplate = [self pixelFont]; - NSImage *gridTemplate = [self pixelGrid]; - - NSShadow *screenShadow = [self innerShadow]; - NSColor *screenColor = [self screenColor]; - - NSBezierPath *screenPath = [NSBezierPath bezierPathWithRoundedRect: [self bounds] - xRadius: 4.0f - yRadius: 4.0f]; - - - //First, draw the screen itself - [NSGraphicsContext saveGraphicsState]; - [screenColor set]; - [screenPath fill]; - [NSGraphicsContext restoreGraphicsState]; - - NSColor *gridColor = [self gridColor]; - NSColor *glyphColor = [self pixelColor]; - - - - NSSize characterSize = [gridTemplate size]; - NSUInteger characterSpacing = 3; - - NSSize glyphSize = NSMakeSize(5, 9); - unichar firstGlyph = '!'; - - NSRect gridRect = NSMakeRect(0, 0, - (characterSize.width + characterSpacing) * 19 + characterSize.width, - characterSize.height); - - gridRect = centerInRect(gridRect, [self bounds]); - gridRect.origin = integralPoint(gridRect.origin); - - - NSRect fontTemplateRect = NSMakeRect(0, 0, [fontTemplate size].width, [fontTemplate size].height); - NSRect gridTemplateRect = NSMakeRect(0, 0, [gridTemplate size].width, [gridTemplate size].height); - - NSRect characterRect = NSMakeRect(gridRect.origin.x, - gridRect.origin.y, - characterSize.width, - characterSize.height); - - NSImage *grid = [gridTemplate imageFilledWithColor: gridColor - atSize: characterSize]; - - NSUInteger i; - - for (i = 0; i < 20; i++) - { - //First, draw the background grid for this character - [grid drawInRect: characterRect - fromRect: NSZeroRect - operation: NSCompositingOperationSourceOver - fraction: 1.0f - respectFlipped: YES - hints: nil]; - - //Next, draw the glyph to show in this grid, if it's within - //the range of our drawable characters - unichar c = [charsToDisplay characterAtIndex: i]; - NSInteger glyphOffset = c - firstGlyph; - - //The place in the font image to grab the glyph from - NSRect glyphRect = NSMakeRect(glyphOffset * glyphSize.width, 0, - glyphSize.width, glyphSize.height); - - //Only bother drawing the character if it's represented in our glyph image. - if (NSContainsRect(fontTemplateRect, glyphRect)) - { - NSImage *maskedGlyph = [gridTemplate copy]; - - //First, use the grid to mask the glyph - [maskedGlyph lockFocus]; - //Disable interpolation to ensure crisp scaling when we redraw the glyph. - [[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationNone]; - [fontTemplate drawInRect: gridTemplateRect - fromRect: glyphRect - operation: NSCompositingOperationDestinationIn - fraction: 1.0f - respectFlipped: YES - hints: nil]; - [maskedGlyph unlockFocus]; - - //Then, draw the masked glyph into the itself - NSImage *tintedGlyph = [maskedGlyph imageFilledWithColor: glyphColor - atSize: NSZeroSize]; - - [tintedGlyph drawInRect: characterRect - fromRect: NSZeroRect - operation: NSCompositingOperationSourceOver - fraction: 1.0f - respectFlipped: YES - hints: nil]; - } - - characterRect.origin.x += characterSize.width + characterSpacing; - } - - - //Finally, draw the shadowing and lighting effects and the frame - [[NSGraphicsContext currentContext] saveGraphicsState]; - [screenPath fillWithInnerShadow: screenShadow]; - [[self frameColor] setStroke]; - [screenPath setLineWidth: 2.0f]; - [screenPath strokeInside]; - [[self screenLighting] drawInBezierPath: screenPath angle: 80.0f]; - [[NSGraphicsContext currentContext] restoreGraphicsState]; -} - -@end diff --git a/Boxer/Boxer-Bridging-Header.h b/Boxer/Boxer-Bridging-Header.h index e372b960d..81c8bef1f 100644 --- a/Boxer/Boxer-Bridging-Header.h +++ b/Boxer/Boxer-Bridging-Header.h @@ -6,3 +6,7 @@ #import "BXFileTypes.h" #import "NSError+ADBErrorHelpers.h" #import "RegexKitLite.h" //FIXME: we shouldn't introduce dependencies on 3rd-party libraries. +#import "NSShadow+ADBShadowExtensions.h" +#import "NSImage+ADBImageEffects.h" +#import "NSBezierPath+MCAdditions.h" +#import "ADBGeometry.h" diff --git a/Boxer/MT32LCDDisplay.swift b/Boxer/MT32LCDDisplay.swift new file mode 100644 index 000000000..6d57e21ec --- /dev/null +++ b/Boxer/MT32LCDDisplay.swift @@ -0,0 +1,137 @@ +// +// MT32LCDDisplay.swift +// Boxer +// +// Created by C.W. Betts on 10/7/23. +// Copyright © 2023 Alun Bestor and contributors. All rights reserved. +// + +import Cocoa + +/// BXMT32LCDDisplay imitates, as the name suggests, the LCD display on a Roland MT-32 Sound Module. +/// It is used for displaying messages sent by the games to the emulated MT-32. (Many Sierra games +/// would send cheeky messages to it on startup.) +/// +/// This field can only display ASCII characters, as that was all the MT-32's display could handle. +/// Non-ASCII characters will be drawn as empty space. +class MT32LCDDisplay : NSTextField { + /// The image containing glyph data for the pixel font. + private var pixelFont: NSImage { + return NSImage(resource: ImageResource.MT32ScreenDisplay.mt32LCDFontTemplate) + } + + /// The mask image to use for the LCD pixel grid. + /// This will be drawn in for 20 character places. + private var pixelGrid: NSImage { + return NSImage(resource: ImageResource.MT32ScreenDisplay.mt32LCDGridTemplate) + } + + /// The background color of the field. + private var screenColor: NSColor { + return NSColor(resource: ColorResource.MT32ScreenDisplay.screen) + } + + private var frameColor: NSColor { + return NSColor(resource: ColorResource.MT32ScreenDisplay.frame) + } + + /// The background color of the LCD pixel grid. + private var gridColor: NSColor { + return NSColor(resource: ColorResource.MT32ScreenDisplay.grid) + } + + /// The colour of lit LCD pixels upon the grid. + private var pixelColor: NSColor { + return NSColor(resource: ColorResource.MT32ScreenDisplay.pixel) + } + + /// The inner shadow of the screen. + private var innerShadow: NSShadow { + return NSShadow(blurRadius: 10, offset: NSSize(width: 0, height: -2.0), color: NSColor(resource: ColorResource.MT32ScreenDisplay.innerShadow)) + } + + /// The lighting effects applied on top of the screen. + private var screenLighting: NSGradient { + return NSGradient(colorsAndLocations: (NSColor(calibratedWhite: 1.0, alpha: 0.10), 0.0), (NSColor(calibratedWhite: 1.0, alpha: 0.07), 0.5), (NSColor.clear, 0.55))! + } + + override func draw(_ dirtyRect: NSRect) { + let charsToDisplay = stringValue.padding(toLength: 20, withPad: " ", startingAt: 0) + + let fontTemplate = pixelFont + let gridTemplate = pixelGrid + + let screenShadow = innerShadow + let screenColor = self.screenColor + + let screenPath = NSBezierPath(roundedRect: bounds, xRadius: 4, yRadius: 4) + + //First, draw the screen itself + NSGraphicsContext.saveGraphicsState() + screenColor.set() + screenPath.fill() + NSGraphicsContext.restoreGraphicsState() + + let gridColor = self.gridColor + let glyphColor = self.pixelColor + + let characterSize = gridTemplate.size + let characterSpacing = 3 + + let glyphSize = NSSize(width: 5, height: 9) + let firstGlyph: Character = "!" + + var gridRect = NSRect(origin: .zero, size: CGSize(width: (characterSize.width + CGFloat(characterSpacing)) * 19 + characterSize.width, height: characterSize.height)) + + gridRect = centerInRect(gridRect, bounds) + gridRect.origin = integralPoint(gridRect.origin) + + let fontTemplateRect = NSRect(origin: .zero, size: fontTemplate.size) + let gridTemplateRect = NSRect(origin: .zero, size: gridTemplate.size) + + var characterRect = NSRect(origin: gridRect.origin, size: characterSize) + + let grid = gridTemplate.imageFilled(with: gridColor, at: characterSize) + + for c in charsToDisplay { + //First, draw the background grid for this character + grid.draw(in: characterRect, from: .zero, operation: .sourceOver, fraction: 1, respectFlipped: true, hints: nil) + + //Next, draw the glyph to show in this grid, if it's within + //the range of our drawable characters + let glyphOffset = Int(c.asciiValue ?? 0) - Int(firstGlyph.asciiValue!) + + //The place in the font image to grab the glyph from + let glyphRect = NSRect(x: CGFloat(glyphOffset) * glyphSize.width, y: 0, + width: glyphSize.width, height: glyphSize.height) + + //Only bother drawing the character if it's represented in our glyph image. + if NSContainsRect(fontTemplateRect, glyphRect) { + let maskedGlyph = gridTemplate.copy() as! NSImage + + //First, use the grid to mask the glyph + maskedGlyph.lockFocus() + //Disable interpolation to ensure crisp scaling when we redraw the glyph. + NSGraphicsContext.current?.imageInterpolation = .none + fontTemplate.draw(in: gridTemplateRect, from: glyphRect, operation: .destinationIn, fraction: 1, respectFlipped: true, hints: nil) + maskedGlyph.unlockFocus() + + //Then, draw the masked glyph into the itself + let tintedGlyph = maskedGlyph.imageFilled(with: glyphColor, at: .zero) + + tintedGlyph.draw(in: characterRect, from: .zero, operation: .sourceOver, fraction: 1, respectFlipped: true, hints: nil) + } + + characterRect.origin.x += characterSize.width + CGFloat(characterSpacing) + } + + //Finally, draw the shadowing and lighting effects and the frame + NSGraphicsContext.current?.saveGraphicsState() + screenPath.fill(withInnerShadow: screenShadow) + frameColor.setStroke() + screenPath.lineWidth = 2 + screenPath.strokeInside() + screenLighting.draw(in: screenPath, angle: 80) + NSGraphicsContext.current?.restoreGraphicsState() + } +} diff --git a/Resources/Base.lproj/Bezel.xib b/Resources/Base.lproj/Bezel.xib index 9d57c3daf..ce414df12 100644 --- a/Resources/Base.lproj/Bezel.xib +++ b/Resources/Base.lproj/Bezel.xib @@ -1,8 +1,8 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -53,7 +53,7 @@ Cmd+click to access the menu bar. - + @@ -85,7 +85,7 @@ Cmd+click to access the menu bar. - + @@ -107,7 +107,7 @@ Cmd+click to access the menu bar. - + @@ -116,7 +116,7 @@ Cmd+click to access the menu bar. - + @@ -136,7 +136,7 @@ Cmd+click to access the menu bar. - + @@ -150,7 +150,7 @@ Cmd+click to access the menu bar. - + @@ -165,7 +165,7 @@ Cmd+click to access the menu bar. - + @@ -179,7 +179,7 @@ Cmd+click to access the menu bar. - + @@ -194,7 +194,7 @@ Cmd+click to access the menu bar. - + @@ -205,7 +205,7 @@ to joystick input. - + @@ -246,7 +246,7 @@ joystick control within the game. - + @@ -255,7 +255,7 @@ joystick control within the game. - + @@ -285,7 +285,7 @@ joystick control within the game. - + @@ -295,12 +295,13 @@ joystick control within the game. + - + @@ -309,7 +310,7 @@ joystick control within the game. - + @@ -326,7 +327,7 @@ in Boxer’s Audio preferences. - + @@ -346,7 +347,7 @@ in Boxer’s Audio preferences. - + @@ -366,7 +367,7 @@ in Boxer’s Audio preferences. - + @@ -386,7 +387,7 @@ in Boxer’s Audio preferences. - + @@ -447,7 +448,7 @@ in Boxer’s Audio preferences. - + @@ -468,8 +469,8 @@ in Boxer’s Audio preferences. - - + + diff --git a/Resources/cs.lproj/Bezel.xib b/Resources/cs.lproj/Bezel.xib index 09589a88c..2addf257c 100644 --- a/Resources/cs.lproj/Bezel.xib +++ b/Resources/cs.lproj/Bezel.xib @@ -1,8 +1,8 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -54,7 +54,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -86,7 +86,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -108,7 +108,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -117,7 +117,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -137,7 +137,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -151,7 +151,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -166,7 +166,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -180,7 +180,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -196,7 +196,7 @@ Kombinací Cmd+kliknutí získáte přístup k řádku nabídek. - + @@ -207,7 +207,7 @@ ovládání joystickem. - + @@ -248,7 +248,7 @@ joystickem zapnout přímo ve hře. - + @@ -257,7 +257,7 @@ joystickem zapnout přímo ve hře. - + @@ -287,7 +287,7 @@ joystickem zapnout přímo ve hře. - + @@ -297,12 +297,13 @@ joystickem zapnout přímo ve hře. + - + @@ -311,7 +312,7 @@ joystickem zapnout přímo ve hře. - + @@ -328,7 +329,7 @@ v nastavení zvuku Boxeru. - + @@ -349,7 +350,7 @@ v nastavení zvuku Boxeru. - + @@ -369,7 +370,7 @@ v nastavení zvuku Boxeru. - + @@ -390,7 +391,7 @@ v nastavení zvuku Boxeru. - + @@ -451,7 +452,7 @@ v nastavení zvuku Boxeru. - + @@ -473,8 +474,8 @@ v nastavení zvuku Boxeru. - - + + diff --git a/Standalone/Boxer Standalone-Bridging-Header.h b/Standalone/Boxer Standalone-Bridging-Header.h index e372b960d..81c8bef1f 100644 --- a/Standalone/Boxer Standalone-Bridging-Header.h +++ b/Standalone/Boxer Standalone-Bridging-Header.h @@ -6,3 +6,7 @@ #import "BXFileTypes.h" #import "NSError+ADBErrorHelpers.h" #import "RegexKitLite.h" //FIXME: we shouldn't introduce dependencies on 3rd-party libraries. +#import "NSShadow+ADBShadowExtensions.h" +#import "NSImage+ADBImageEffects.h" +#import "NSBezierPath+MCAdditions.h" +#import "ADBGeometry.h"