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

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
2-
"originHash" : "aa6ce7645f111c948bf66866b845dc1214110ab4ebc22a570bdd5299ae84c4ad",
2+
"originHash" : "8df6a389d2eadcdfd6b4dc4afe96c3817645a0d6f61318ef7a84060338bea551",
33
"pins" : [
44
{
55
"identity" : "combine-schedulers",
66
"kind" : "remoteSourceControl",
77
"location" : "https://github.com/pointfreeco/combine-schedulers",
88
"state" : {
9-
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
10-
"version" : "1.0.0"
9+
"revision" : "487a4d151e795a5e076a7e7aedcd13c2ebff6c31",
10+
"version" : "1.0.1"
1111
}
1212
},
1313
{
@@ -29,21 +29,21 @@
2929
}
3030
},
3131
{
32-
"identity" : "swift-libass",
32+
"identity" : "swift-issue-reporting",
3333
"kind" : "remoteSourceControl",
34-
"location" : "https://github.com/mihai8804858/swift-libass",
34+
"location" : "https://github.com/pointfreeco/swift-issue-reporting",
3535
"state" : {
36-
"revision" : "a097db001228834c57ffb8c5245f3bccc8df8124",
37-
"version" : "1.3.1"
36+
"revision" : "c85092304cda8cb38d2d68454b29609a8013620b",
37+
"version" : "1.2.1"
3838
}
3939
},
4040
{
41-
"identity" : "xctest-dynamic-overlay",
41+
"identity" : "swift-libass",
4242
"kind" : "remoteSourceControl",
43-
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
43+
"location" : "https://github.com/mihai8804858/swift-libass",
4444
"state" : {
45-
"revision" : "6f30bdba373bbd7fbfe241dddd732651f2fbd1e2",
46-
"version" : "1.1.2"
45+
"revision" : "a097db001228834c57ffb8c5245f3bccc8df8124",
46+
"version" : "1.3.1"
4747
}
4848
}
4949
],

Package.resolved

+15-15
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"kind" : "remoteSourceControl",
66
"location" : "https://github.com/pointfreeco/combine-schedulers",
77
"state" : {
8-
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
9-
"version" : "1.0.0"
8+
"revision" : "487a4d151e795a5e076a7e7aedcd13c2ebff6c31",
9+
"version" : "1.0.1"
1010
}
1111
},
1212
{
@@ -27,6 +27,15 @@
2727
"version" : "1.1.0"
2828
}
2929
},
30+
{
31+
"identity" : "swift-issue-reporting",
32+
"kind" : "remoteSourceControl",
33+
"location" : "https://github.com/pointfreeco/swift-issue-reporting",
34+
"state" : {
35+
"revision" : "c85092304cda8cb38d2d68454b29609a8013620b",
36+
"version" : "1.2.1"
37+
}
38+
},
3039
{
3140
"identity" : "swift-libass",
3241
"kind" : "remoteSourceControl",
@@ -42,25 +51,16 @@
4251
"location" : "https://github.com/mihai8804858/swift-snapshot-testing",
4352
"state" : {
4453
"branch" : "main",
45-
"revision" : "15166f1b1166080f3d57ca6b568c92c8f2888dec"
54+
"revision" : "472017f0c1bc500a495af5801dadcb343a37d57b"
4655
}
4756
},
4857
{
4958
"identity" : "swift-syntax",
5059
"kind" : "remoteSourceControl",
51-
"location" : "https://github.com/apple/swift-syntax",
52-
"state" : {
53-
"revision" : "303e5c5c36d6a558407d364878df131c3546fad8",
54-
"version" : "510.0.2"
55-
}
56-
},
57-
{
58-
"identity" : "xctest-dynamic-overlay",
59-
"kind" : "remoteSourceControl",
60-
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
60+
"location" : "https://github.com/swiftlang/swift-syntax",
6161
"state" : {
62-
"revision" : "6f30bdba373bbd7fbfe241dddd732651f2fbd1e2",
63-
"version" : "1.1.2"
62+
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c",
63+
"version" : "600.0.0-prerelease-2024-06-12"
6464
}
6565
}
6666
],
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

+13-4
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

+12-20
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

+15-15
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"kind" : "remoteSourceControl",
66
"location" : "https://github.com/pointfreeco/combine-schedulers",
77
"state" : {
8-
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
9-
"version" : "1.0.0"
8+
"revision" : "487a4d151e795a5e076a7e7aedcd13c2ebff6c31",
9+
"version" : "1.0.1"
1010
}
1111
},
1212
{
@@ -27,6 +27,15 @@
2727
"version" : "1.1.0"
2828
}
2929
},
30+
{
31+
"identity" : "swift-issue-reporting",
32+
"kind" : "remoteSourceControl",
33+
"location" : "https://github.com/pointfreeco/swift-issue-reporting",
34+
"state" : {
35+
"revision" : "c85092304cda8cb38d2d68454b29609a8013620b",
36+
"version" : "1.2.1"
37+
}
38+
},
3039
{
3140
"identity" : "swift-libass",
3241
"kind" : "remoteSourceControl",
@@ -42,25 +51,16 @@
4251
"location" : "https://github.com/mihai8804858/swift-snapshot-testing",
4352
"state" : {
4453
"branch" : "main",
45-
"revision" : "15166f1b1166080f3d57ca6b568c92c8f2888dec"
54+
"revision" : "472017f0c1bc500a495af5801dadcb343a37d57b"
4655
}
4756
},
4857
{
4958
"identity" : "swift-syntax",
5059
"kind" : "remoteSourceControl",
51-
"location" : "https://github.com/apple/swift-syntax",
52-
"state" : {
53-
"revision" : "303e5c5c36d6a558407d364878df131c3546fad8",
54-
"version" : "510.0.2"
55-
}
56-
},
57-
{
58-
"identity" : "xctest-dynamic-overlay",
59-
"kind" : "remoteSourceControl",
60-
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
60+
"location" : "https://github.com/swiftlang/swift-syntax",
6161
"state" : {
62-
"revision" : "6f30bdba373bbd7fbfe241dddd732651f2fbd1e2",
63-
"version" : "1.1.2"
62+
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c",
63+
"version" : "600.0.0-prerelease-2024-06-12"
6464
}
6565
}
6666
],

Tests/FontConfig/FontConfigTests.swift

+13-3
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)