Skip to content
Open
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
162 changes: 142 additions & 20 deletions components/captionTask.bs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ sub init()
m.captionList = []
m.reader = createObject("roUrlTransfer")
m.font = CreateObject("roSGNode", "Font")
m.tags = CreateObject("roRegex", "{\\an\d*}|&lt;.*?&gt;|<.*?>", "s")
m.undesirableTags = CreateObject("roRegex", "{\\an\d*}|&lt;.*?&gt;|<(?!\/?font\b).*?>", "s")
m.fontColor = CreateObject("roRegex", "color\s*?[=]\s*?""?(\S*)""?\b", "i")

' Caption Style
m.fontSizeDict = { "Default": 60, "Large": 60, "Extra Large": 70, "Medium": 50, "Small": 40, "Extra Small": 30 }
Expand All @@ -44,7 +45,6 @@ sub setFont()

if fs.Exists("tmp:/font")
m.font.uri = "tmp:/font"
m.font.size = m.fontSize
else
m.font = "font:LargeSystemFont"
end if
Expand All @@ -64,18 +64,9 @@ sub fetchCaption()
end if
end sub

function newlabel(txt)
label = CreateObject("roSGNode", "Label")
label.text = txt
label.font = m.font
label.font.size = m.fontSize
label.color = m.textColor
return label
end function

function newLayoutGroup(labels)
function newLayoutGroup(label)
newlg = CreateObject("roSGNode", "LayoutGroup")
newlg.appendchildren(labels)
newlg.appendchild(label)
newlg.layoutDirection = "vert"
newlg.horizalignment = "left"
newlg.vertalignment = "top"
Expand Down Expand Up @@ -103,7 +94,6 @@ function newRect(lg, id as string)
return rect
end function


sub updateCaption()
if LCase(m.top.playerState.right(1)) = "w"
m.top.playerState = m.top.playerState.left(len (m.top.playerState) - 1)
Expand All @@ -120,15 +110,147 @@ sub updateCaption()
for each entry in m.captionList
if entry["start"] <= m.top.currentPos and m.top.currentPos < entry["end"]

labels = []
for each text in entry["text"]
labels.push(newlabel(text))
fullText = entry["text"].Join(Chr(10))

' look for style tags
drawingStyles = {
"default": {
"fontUri": m.font,
"fontSize": m.fontSize,
"color": m.textColor
}
}
openTags = []
styledText = string.EMPTY
parts = fullText.Split("<")
firstIter = true
for each part in parts
if firstIter
' first part will either be "" if it starts with a tag,
' or plain text before the first tag, so just add it and continue
styledText += part
firstIter = false
continue for
end if
tagEnd = part.Instr(0, ">")
nextNewLine = part.Instr(0, Chr(10))
if tagEnd = -1 or (nextNewLine <> -1 and nextNewLine < tagEnd)
' no end bracket on the same line - treat as literal less-than sign
styledText += `<${part}`
continue for
end if
tagValue = LCase(part.Mid(0, tagEnd).Trim())
replaceTagWith = string.EMPTY
if tagValue.StartsWith("font")
' opening font tag
colorName = invalid
color = m.fontColor.Match(tagValue)
if color.Count() > 1
color = color[1].Replace("""", string.EMPTY).Trim()
if color.StartsWith("#")
' hex color code (must be 3 or 6 digits)
sanitizedColor = "#"
colorChars = color.Mid(1).Split(string.EMPTY)
isShortColor = colorChars.Count() = 3
for each c in colorChars
if c >= "0" and c <= "9" or c >= "a" and c <= "f"
sanitizedColor += c
if isShortColor
sanitizedColor += c
end if
end if
end for
if sanitizedColor.Len() = 7
color = sanitizedColor
colorName = color
end if
else if color.StartsWith("rgb(") or color.StartsWith("rgba(")
' rgb or rgba color code (alpha is ignored)
rgbValues = color.Mid(color.Instr("(") + 1).Replace(")", string.EMPTY).Split(",")
if rgbValues.Count() >= 3
r = rgbValues[0].Trim()
g = rgbValues[1].Trim()
b = rgbValues[2].Trim()
' verify they're numbers
' can't rely on val() because it returns 0 and the text will end up black
if r.Left(1) >= "0" and r.Left(1) <= "9" and g.Left(1) >= "0" and g.Left(1) <= "9" and b.Left(1) >= "0" and b.Left(1) <= "9"
r = val(r, 10)
g = val(g, 10)
b = val(b, 10)
if r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255
color = "#%02x%02x%02x".Format(r, g, b)
colorName = color
end if
end if
end if
else
' is it the name of a color?
cssColor = chainLookup(m.global.constants.cssColorDict, color)
if isValid(cssColor)
colorName = color
color = cssColor
end if
end if
if isValid(colorName)
drawingStyles.AddReplace(colorName, {
"fontUri": m.font,
"fontSize": m.fontSize,
"color": `${color}${m.textOpac}`
})
replaceTagWith += `${colorName}`
end if
end if
' keep track of invalid tags
if not isValid(colorName)
openTags.push(colorName)
end if
else if tagValue.StartsWith("/font")
' closing tag
if openTags.Count() > 0
openTag = openTags.pop()
if isValid(openTag)
replaceTagWith = `/${openTag}`
end if
end if
end if
if replaceTagWith.Len() > 0
' MultiStyleLabel doesn't support nested tags, so if this is nested,
' we need to close the previous one before opening a new one,
' and reopen it after
isClosing = replaceTagWith.StartsWith("/")
lastValidTag = invalid
for i = openTags.count() - 1 to 0 step -1
' do we have a valid tag still open?
if isValid(openTags[i])
lastValidTag = openTags[i]
exit for
end if
end for
if isValid(lastValidTag)
if isClosing
styledText += `<${replaceTagWith}><${lastValidTag}>`
else
openTags.push(replaceTagWith)
styledText += `</${lastValidTag}><${replaceTagWith}>`
end if
else
if not isClosing
openTags.push(replaceTagWith)
end if
styledText += `<${replaceTagWith}>`
end if
end if
styledText += part.Mid(tagEnd + 1)
end for

lines = newLayoutGroup(labels)
label = CreateObject("roSGNode", "MultiStyleLabel")
label.drawingStyles = drawingStyles
label.text = styledText
label.horizAlign = "center"
lines = newLayoutGroup(label)
rect = newRect(lines, entry.LookupCI("id"))

finalStyles = prepareStyles(entry["styles"], rect, labels.count())
finalStyles = prepareStyles(entry["styles"], rect, entry["text"].count())
rect.translation = finalStyles.translation

adjustForCaptionOverlaps(rect, captions)
Expand Down Expand Up @@ -317,7 +439,7 @@ function parseVTT(lines)

if isNewLine
trimmed = lines[i].trim()
finalText = m.tags.replaceAll(trimmed, "")
finalText = m.undesirableTags.replaceAll(trimmed, "")

' We reached a blank line
if isStringEqual(finalText, string.EMPTY)
Expand Down
4 changes: 4 additions & 0 deletions source/static/whatsNew/3.1.8.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,9 @@
{
"description": "Add setting to select how many items are loaded together on library screens",
"author": "brianpardy"
},
{
"description": "Support font color tags in subtitles",
"author": "gabeluci"
}
]
4 changes: 3 additions & 1 deletion source/utils/globals.bs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ sub setConstants()
descending_white: "pkg:/images/icons/down_white.png",
check_black: "pkg:/images/icons/check_black.png",
check_white: "pkg:/images/icons/check_white.png"
}
},

cssColorDict: { "aliceblue": "#f0f8ff", "antiquewhite": "#faebd7", "aqua": "#00ffff", "aquamarine": "#7fffd4", "azure": "#f0ffff", "beige": "#f5f5dc", "bisque": "#ffe4c4", "black": "#000000", "blanchedalmond": "#ffebcd", "blue": "#0000ff", "blueviolet": "#8a2be2", "brown": "#a52a2a", "burlywood": "#deb887", "cadetblue": "#5f9ea0", "chartreuse": "#7fff00", "chocolate": "#d2691e", "coral": "#ff7f50", "cornflowerblue": "#6495ed", "cornsilk": "#fff8dc", "crimson": "#dc143c", "cyan": "#00ffff", "darkblue": "#00008b", "darkcyan": "#008b8b", "darkgoldenrod": "#b8860b", "darkgray": "#a9a9a9", "darkgreen": "#006400", "darkgrey": "#a9a9a9", "darkkhaki": "#bdb76b", "darkmagenta": "#8b008b", "darkolivegreen": "#556b2f", "darkorange": "#ff8c00", "darkorchid": "#9932cc", "darkred": "#8b0000", "darksalmon": "#e9967a", "darkseagreen": "#8fbc8f", "darkslateblue": "#483d8b", "darkslategray": "#2f4f4f", "darkslategrey": "#2f4f4f", "darkturquoise": "#00ced1", "darkviolet": "#9400d3", "deeppink": "#ff1493", "deepskyblue": "#00bfff", "dimgray": "#696969", "dimgrey": "#696969", "dodgerblue": "#1e90ff", "firebrick": "#b22222", "floralwhite": "#fffaf0", "forestgreen": "#228b22", "fuchsia": "#ff00ff", "gainsboro": "#dcdcdc", "ghostwhite": "#f8f8ff", "gold": "#ffd700", "goldenrod": "#daa520", "gray": "#808080", "green": "#008000", "greenyellow": "#adff2f", "grey": "#808080", "honeydew": "#f0fff0", "hotpink": "#ff69b4", "indianred": "#cd5c5c", "indigo": "#4b0082", "ivory": "#fffff0", "khaki": "#f0e68c", "lavender": "#e6e6fa", "lavenderblush": "#fff0f5", "lawngreen": "#7cfc00", "lemonchiffon": "#fffacd", "lightblue": "#add8e6", "lightcoral": "#f08080", "lightcyan": "#e0ffff", "lightgoldenrodyellow": "#fafad2", "lightgray": "#d3d3d3", "lightgreen": "#90ee90", "lightgrey": "#d3d3d3", "lightpink": "#ffb6c1", "lightsalmon": "#ffa07a", "lightseagreen": "#20b2aa", "lightskyblue": "#87cefa", "lightslategray": "#778899", "lightslategrey": "#778899", "lightsteelblue": "#b0c4de", "lightyellow": "#ffffe0", "lime": "#00ff00", "limegreen": "#32cd32", "linen": "#faf0e6", "magenta": "#ff00ff", "maroon": "#800000", "mediumaquamarine": "#66cdaa", "mediumblue": "#0000cd", "mediumorchid": "#ba55d3", "mediumpurple": "#9370db", "mediumseagreen": "#3cb371", "mediumslateblue": "#7b68ee", "mediumspringgreen": "#00fa9a", "mediumturquoise": "#48d1cc", "mediumvioletred": "#c71585", "midnightblue": "#191970", "mintcream": "#f5fffa", "mistyrose": "#ffe4e1", "moccasin": "#ffe4b5", "navajowhite": "#ffdead", "navy": "#000080", "oldlace": "#fdf5e6", "olive": "#808000", "olivedrab": "#6b8e23", "orange": "#ffa500", "orangered": "#ff4500", "orchid": "#da70d6", "palegoldenrod": "#eee8aa", "palegreen": "#98fb98", "paleturquoise": "#afeeee", "palevioletred": "#db7093", "papayawhip": "#ffefd5", "peachpuff": "#ffdab9", "peru": "#cd853f", "pink": "#ffc0cb", "plum": "#dda0dd", "powderblue": "#b0e0e6", "purple": "#800080", "red": "#ff0000", "rosybrown": "#bc8f8f", "royalblue": "#4169e1", "saddlebrown": "#8b4513", "salmon": "#fa8072", "sandybrown": "#f4a460", "seagreen": "#2e8b57", "seashell": "#fff5ee", "sienna": "#a0522d", "silver": "#c0c0c0", "skyblue": "#87ceeb", "slateblue": "#6a5acd", "slategray": "#708090", "slategrey": "#708090", "snow": "#fffafa", "springgreen": "#00ff7f", "steelblue": "#4682b4", "tan": "#d2b48c", "teal": "#008080", "thistle": "#d8bfd8", "tomato": "#ff6347", "turquoise": "#40e0d0", "violet": "#ee82ee", "wheat": "#f5deb3", "white": "#ffffff", "whitesmoke": "#f5f5f5", "yellow": "#ffff00", "yellowgreen": "#9acd32" }
}
})
end sub
Expand Down