Skip to content

Commit 7d904ee

Browse files
authored
Add experimental EPUB decoration positioning (#665)
1 parent ba6d8c0 commit 7d904ee

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ All notable changes to this project will be documented in this file. Take a look
1212
* By default, the navigator uses the window's `safeAreaInsets`, which can cause content to shift when the status bar is shown or hidden (since those insets change). To avoid this, implement `navigatorContentInset(_:)` and return insets that remain stable across status bar visibility changes — for example, a top inset large enough to accommodate the maximum expected status bar height.
1313
* Added `[TTSVoice].filterByLanguage(_:)` to filter TTS voices by language and region.
1414
* Added `[TTSVoice].sorted()` to sort TTS voices by region, quality, and gender.
15+
* New experimental positioning of EPUB decorations that places highlights behind text to improve legibility with opaque decorations (contributed by [@ddfreiling](https://github.com/readium/swift-toolkit/pull/665)).
16+
* To opt-in, initialize the `EPUBNavigatorViewController.Configuration` object with `decorationTemplates: HTMLDecorationTemplate.defaultTemplates(alpha: 1.0, experimentalPositioning: true)`.
1517

1618
#### LCP
1719

Sources/Navigator/EPUB/HTMLDecorationTemplate.swift

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,28 @@ public struct HTMLDecorationTemplate {
5959
defaultTint: UIColor = .yellow,
6060
lineWeight: Int = 2,
6161
cornerRadius: Int = 3,
62-
alpha: Double = 0.3
62+
alpha: Double = 0.3,
63+
experimentalPositioning: Bool = false
6364
) -> [Decoration.Style.Id: HTMLDecorationTemplate] {
6465
let padding = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 1)
6566
return [
66-
.highlight: .highlight(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha),
67-
.underline: .underline(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha),
67+
.highlight: .highlight(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning),
68+
.underline: .underline(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning),
6869
]
6970
}
7071

7172
/// Creates a new decoration template for the `highlight` style.
72-
public static func highlight(defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double) -> HTMLDecorationTemplate {
73-
makeTemplate(asHighlight: true, defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha)
73+
public static func highlight(defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double, experimentalPositioning: Bool = false) -> HTMLDecorationTemplate {
74+
makeTemplate(asHighlight: true, defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning)
7475
}
7576

7677
/// Creates a new decoration template for the `underline` style.
77-
public static func underline(defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double) -> HTMLDecorationTemplate {
78-
makeTemplate(asHighlight: false, defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha)
78+
public static func underline(defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double, experimentalPositioning: Bool = false) -> HTMLDecorationTemplate {
79+
makeTemplate(asHighlight: false, defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning)
7980
}
8081

8182
/// - Parameter asHighlight: When true, the non active style is of an highlight. Otherwise, it is an underline.
82-
private static func makeTemplate(asHighlight: Bool, defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double) -> HTMLDecorationTemplate {
83+
private static func makeTemplate(asHighlight: Bool, defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double, experimentalPositioning: Bool = false) -> HTMLDecorationTemplate {
8384
let className = makeUniqueClassName(key: asHighlight ? "highlight" : "underline")
8485
return HTMLDecorationTemplate(
8586
layout: .boxes,
@@ -94,6 +95,11 @@ public struct HTMLDecorationTemplate {
9495
if !asHighlight || isActive {
9596
css += "--underline-color: \(tint.cssValue());"
9697
}
98+
if experimentalPositioning {
99+
// Experimental positioning:
100+
// Decoration is placed behind the publication's text, to prevent it from affecting text-color.
101+
css += "--decoration-z-index: -1;"
102+
}
97103
return "<div class=\"\(className)\" style=\"\(css)\"/>"
98104
},
99105
stylesheet:
@@ -104,6 +110,7 @@ public struct HTMLDecorationTemplate {
104110
border-radius: \(cornerRadius)px;
105111
box-sizing: border-box;
106112
border: 0 solid var(--underline-color);
113+
z-index: var(--decoration-z-index);
107114
}
108115
109116
/* Horizontal (default) */
@@ -121,7 +128,7 @@ public struct HTMLDecorationTemplate {
121128
[data-writing-mode="vertical-lr"].\(className),
122129
[data-writing-mode="sideways-lr"].\(className) {
123130
border-right-width: \(lineWeight)px;
124-
}
131+
}
125132
"""
126133
)
127134
}

TestApp/Sources/Reader/EPUB/EPUBViewController.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class EPUBViewController: VisualReaderViewController<EPUBNavigatorViewController
3030
preferencesStore: AnyUserPreferencesStore<EPUBPreferences>,
3131
httpServer: HTTPServer
3232
) throws {
33-
var templates = HTMLDecorationTemplate.defaultTemplates()
33+
// Create default templates, but make highlights opaque with experimental positioning.
34+
var templates = HTMLDecorationTemplate.defaultTemplates(alpha: 1.0, experimentalPositioning: true)
3435
templates[.pageList] = .pageList
3536

3637
let resources = FileURL(url: Bundle.main.resourceURL!)!

0 commit comments

Comments
 (0)