Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ All notable changes to this project will be documented in this file. Take a look
* 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.
* Added `[TTSVoice].filterByLanguage(_:)` to filter TTS voices by language and region.
* Added `[TTSVoice].sorted()` to sort TTS voices by region, quality, and gender.
* 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)).
* To opt-in, initialize the `EPUBNavigatorViewController.Configuration` object with `decorationTemplates: HTMLDecorationTemplate.defaultTemplates(alpha: 1.0, experimentalPositioning: true)`.

#### LCP

Expand Down
25 changes: 16 additions & 9 deletions Sources/Navigator/EPUB/HTMLDecorationTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,28 @@ public struct HTMLDecorationTemplate {
defaultTint: UIColor = .yellow,
lineWeight: Int = 2,
cornerRadius: Int = 3,
alpha: Double = 0.3
alpha: Double = 0.3,
experimentalPositioning: Bool = false
) -> [Decoration.Style.Id: HTMLDecorationTemplate] {
let padding = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 1)
return [
.highlight: .highlight(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha),
.underline: .underline(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha),
.highlight: .highlight(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning),
.underline: .underline(defaultTint: defaultTint, padding: padding, lineWeight: lineWeight, cornerRadius: cornerRadius, alpha: alpha, experimentalPositioning: experimentalPositioning),
]
}

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

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

/// - Parameter asHighlight: When true, the non active style is of an highlight. Otherwise, it is an underline.
private static func makeTemplate(asHighlight: Bool, defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double) -> HTMLDecorationTemplate {
private static func makeTemplate(asHighlight: Bool, defaultTint: UIColor, padding: UIEdgeInsets, lineWeight: Int, cornerRadius: Int, alpha: Double, experimentalPositioning: Bool = false) -> HTMLDecorationTemplate {
let className = makeUniqueClassName(key: asHighlight ? "highlight" : "underline")
return HTMLDecorationTemplate(
layout: .boxes,
Expand All @@ -94,6 +95,11 @@ public struct HTMLDecorationTemplate {
if !asHighlight || isActive {
css += "--underline-color: \(tint.cssValue());"
}
if experimentalPositioning {
// Experimental positioning:
// Decoration is placed behind the publication's text, to prevent it from affecting text-color.
css += "--decoration-z-index: -1;"
}
return "<div class=\"\(className)\" style=\"\(css)\"/>"
},
stylesheet:
Expand All @@ -104,6 +110,7 @@ public struct HTMLDecorationTemplate {
border-radius: \(cornerRadius)px;
box-sizing: border-box;
border: 0 solid var(--underline-color);
z-index: var(--decoration-z-index);
}

/* Horizontal (default) */
Expand All @@ -121,7 +128,7 @@ public struct HTMLDecorationTemplate {
[data-writing-mode="vertical-lr"].\(className),
[data-writing-mode="sideways-lr"].\(className) {
border-right-width: \(lineWeight)px;
}
}
"""
)
}
Expand Down
3 changes: 2 additions & 1 deletion TestApp/Sources/Reader/EPUB/EPUBViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class EPUBViewController: VisualReaderViewController<EPUBNavigatorViewController
preferencesStore: AnyUserPreferencesStore<EPUBPreferences>,
httpServer: HTTPServer
) throws {
var templates = HTMLDecorationTemplate.defaultTemplates()
// Create default templates, but make highlights opaque with experimental positioning.
var templates = HTMLDecorationTemplate.defaultTemplates(alpha: 1.0, experimentalPositioning: true)
templates[.pageList] = .pageList

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