Skip to content

Commit f0b1f08

Browse files
committed
Fix font config sync issue
1 parent 230d3e4 commit f0b1f08

File tree

7 files changed

+86
-68
lines changed

7 files changed

+86
-68
lines changed

Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.resolved

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
3+
func withLock<T>(_ lock: NSLock, _ perform: () throws -> T) rethrows -> T {
4+
lock.lock()
5+
defer { lock.unlock() }
6+
return try perform()
7+
}

Sources/SwiftAssRenderer/FontConfig/FontConfig.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ protocol FontConfigType {
1919
public struct FontConfig: FontConfigType {
2020
private static let fontsCacheDirName = "fonts-cache"
2121
private static let fontsConfFileName = "fonts.conf"
22+
private static let lock = NSLock()
2223

2324
private let fileManager: FileManagerType
2425
private let moduleBundle: BundleType
@@ -28,6 +29,7 @@ public struct FontConfig: FontConfigType {
2829
private let defaultFontName: String?
2930
private let defaultFontFamily: String?
3031
private let fontProvider: FontProvider
32+
private let fontsCacheSubDirName: String
3133

3234
/// - Parameters:
3335
/// - fontsPath: URL path to fonts directory. Can be read-only.
@@ -48,6 +50,7 @@ public struct FontConfig: FontConfigType {
4850
fontProvider: FontProvider = .fontConfig
4951
) {
5052
self.init(
53+
uuid: UUID.init,
5154
fileManager: FileManager.default,
5255
moduleBundle: Bundle.module,
5356
libraryWrapper: LibraryWrapper.self,
@@ -60,6 +63,7 @@ public struct FontConfig: FontConfigType {
6063
}
6164

6265
init(
66+
uuid: @escaping () -> UUID,
6367
fileManager: FileManagerType,
6468
moduleBundle: BundleType,
6569
libraryWrapper: LibraryWrapperType.Type,
@@ -77,12 +81,15 @@ public struct FontConfig: FontConfigType {
7781
self.defaultFontName = defaultFontName
7882
self.defaultFontFamily = defaultFontFamily
7983
self.fontProvider = fontProvider
84+
self.fontsCacheSubDirName = uuid().uuidString
8085
}
8186

8287
func configure(library: OpaquePointer, renderer: OpaquePointer) throws {
83-
try makeFontsCacheDirectory()
84-
try writeFontConfFile()
85-
configureLibrary(library, renderer: renderer)
88+
try withLock(FontConfig.lock) {
89+
try makeFontsCacheDirectory()
90+
try writeFontConfFile()
91+
configureLibrary(library, renderer: renderer)
92+
}
8693
}
8794

8895
// MARK: - Private
@@ -92,7 +99,9 @@ public struct FontConfig: FontConfigType {
9299
}
93100

94101
private var cachePath: URL {
95-
(fontsCachePath ?? fileManager.cachesDirectory).appendingPathComponent(FontConfig.fontsCacheDirName)
102+
(fontsCachePath ?? fileManager.cachesDirectory)
103+
.appendingPathComponent(fontsCacheSubDirName)
104+
.appendingPathComponent(FontConfig.fontsCacheDirName)
96105
}
97106

98107
private func makeFontsCacheDirectory() throws {

Sources/SwiftAssRenderer/Wrapper/LibraryWrapper.swift

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,36 +45,38 @@ protocol LibraryWrapperType {
4545
}
4646

4747
enum LibraryWrapper: LibraryWrapperType {
48+
private static let lock = NSLock()
49+
4850
static var libraryLogger: (Int, String) -> Void = { _, message in
4951
print("[swift-ass] \(message)")
5052
}
5153

5254
static func libraryInit() -> OpaquePointer? {
53-
withLock {
55+
withLock(lock) {
5456
ass_library_init()
5557
}
5658
}
5759

5860
static func libraryDone(_ library: OpaquePointer) {
59-
withLock {
61+
withLock(lock) {
6062
ass_library_done(library)
6163
}
6264
}
6365

6466
static func rendererInit(_ library: OpaquePointer) -> OpaquePointer? {
65-
withLock {
67+
withLock(lock) {
6668
ass_renderer_init(library)
6769
}
6870
}
6971

7072
static func rendererDone(_ renderer: OpaquePointer) {
71-
withLock {
73+
withLock(lock) {
7274
ass_renderer_done(renderer)
7375
}
7476
}
7577

7678
static func setLogCallback(_ library: OpaquePointer) {
77-
withLock {
79+
withLock(lock) {
7880
ass_set_message_cb(library, { messageLevel, messageString, messageArgs, _ in
7981
guard let messageString else { return }
8082
let message = String(cString: messageString)
@@ -89,13 +91,13 @@ enum LibraryWrapper: LibraryWrapperType {
8991
}
9092

9193
static func setRendererSize(_ renderer: OpaquePointer, size: CGSize) {
92-
withLock {
94+
withLock(lock) {
9395
ass_set_frame_size(renderer, Int32(size.width), Int32(size.height))
9496
}
9597
}
9698

9799
static func setExtractFonts(_ library: OpaquePointer, extract: Bool) {
98-
withLock {
100+
withLock(lock) {
99101
ass_set_extract_fonts(library, extract ? 1 : 0)
100102
}
101103
}
@@ -107,7 +109,7 @@ enum LibraryWrapper: LibraryWrapperType {
107109
defaultFont: String? = nil,
108110
defaultFamily: String? = nil
109111
) {
110-
withLock {
112+
withLock(lock) {
111113
let defaultFont = defaultFont.flatMap { $0.cString(using: .utf8) }
112114
let defaultFamily = defaultFamily.flatMap { $0.cString(using: .utf8) }
113115
let fontConfig = configPath.flatMap { $0.cString(using: .utf8) }
@@ -117,7 +119,7 @@ enum LibraryWrapper: LibraryWrapperType {
117119
}
118120

119121
static func readTrack(_ library: OpaquePointer, content: String) -> ASS_Track? {
120-
withLock {
122+
withLock(lock) {
121123
guard var buffer = content.cString(using: .utf8) else { return nil }
122124
return ass_read_memory(library, &buffer, buffer.count, nil).pointee
123125
}
@@ -128,22 +130,12 @@ enum LibraryWrapper: LibraryWrapperType {
128130
track: inout ASS_Track,
129131
at offset: TimeInterval
130132
) -> LibraryRenderResult? {
131-
withLock {
133+
withLock(lock) {
132134
var changed: Int32 = 0
133135
let millisecond = Int64(offset * 1000)
134136
guard let frame = ass_render_frame(renderer, &track, millisecond, &changed) else { return nil }
135137

136138
return LibraryRenderResult(image: frame.pointee, changed: changed != 0)
137139
}
138140
}
139-
140-
// MARK: - Private
141-
142-
private static let lock = NSLock()
143-
144-
private static func withLock<T>(_ perform: () -> T) -> T {
145-
lock.lock()
146-
defer { lock.unlock() }
147-
return perform()
148-
}
149141
}

SwiftAssRenderer.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/FontConfig/FontConfigTests.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ final class FontConfigTests: XCTestCase {
77
private var mockFileManager: MockFileManager!
88
private var mockBundle: MockBundle!
99
private var mockLibraryWrapper: MockLibraryWrapper.Type!
10+
private var mockUUID: UUID!
1011

1112
private var cachesDirectory: URL {
1213
if #available(iOS 16.0, tvOS 16.0, visionOS 1.0, macOS 13.0, *) {
@@ -40,6 +41,7 @@ final class FontConfigTests: XCTestCase {
4041
mockFileManager = MockFileManager()
4142
mockBundle = MockBundle()
4243
mockLibraryWrapper = MockLibraryWrapper.self
44+
mockUUID = UUID()
4345
}
4446

4547
func createConfig(
@@ -50,6 +52,7 @@ final class FontConfigTests: XCTestCase {
5052
fontProvider: FontProvider = .fontConfig
5153
) -> FontConfig {
5254
FontConfig(
55+
uuid: { self.mockUUID },
5356
fileManager: mockFileManager,
5457
moduleBundle: mockBundle,
5558
libraryWrapper: mockLibraryWrapper,
@@ -73,7 +76,9 @@ final class FontConfigTests: XCTestCase {
7376
try config.configure(library: library, renderer: renderer)
7477

7578
// THEN
76-
let expectedURL = defaultFontsCachePath.appendingPathComponent("fonts-cache")
79+
let expectedURL = defaultFontsCachePath
80+
.appendingPathComponent(mockUUID.uuidString)
81+
.appendingPathComponent("fonts-cache")
7782
XCTAssert(mockFileManager.createDirectoryFunc.wasCalled(with: expectedURL))
7883
}
7984

@@ -102,7 +107,9 @@ final class FontConfigTests: XCTestCase {
102107
try config.configure(library: library, renderer: renderer)
103108

104109
// THEN
105-
let expectedURL = fontsCachePath.appendingPathComponent("fonts-cache")
110+
let expectedURL = fontsCachePath
111+
.appendingPathComponent(mockUUID.uuidString)
112+
.appendingPathComponent("fonts-cache")
106113
XCTAssert(mockFileManager.createDirectoryFunc.wasCalled(with: expectedURL))
107114
}
108115

@@ -119,7 +126,10 @@ final class FontConfigTests: XCTestCase {
119126
// THEN
120127
let createFileArgument = try XCTUnwrap(mockFileManager.createItemFunc.argument)
121128
let expectedDir = fontsPath.path
122-
let expectedCacheDir = fontsCachePath.appendingPathComponent("fonts-cache").path
129+
let expectedCacheDir = fontsCachePath
130+
.appendingPathComponent(mockUUID.uuidString)
131+
.appendingPathComponent("fonts-cache")
132+
.path
123133
let expectedConfFile = cachesDirectory.appendingPathComponent("fonts.conf")
124134
let expectedContents = """
125135
<?xml version="1.0"?>

0 commit comments

Comments
 (0)