Skip to content

Instantly share code, notes, and snippets.

@line0
Created June 16, 2017 01:03
Show Gist options
  • Save line0/c8a9758e8e32ecbd00525e5c8b51c1b8 to your computer and use it in GitHub Desktop.
Save line0/c8a9758e8e32ecbd00525e5c8b51c1b8 to your computer and use it in GitHub Desktop.
export script_name = "Count Layout Lines"
export script_description = "Counts the number of layout lines produced on the canvas per subtitle line."
export script_version = "0.1.0"
export script_author = "line0"
export script_namespace = "l0.CountLayoutLines"
DependencyControl = require "l0.DependencyControl"
depRec = DependencyControl {
feed: "https://raw.githubusercontent.com/TypesettingTools/line0-Aegisub-Scripts/master/DependencyControl.json",
{
{"a-mo.LineCollection", version: "1.0.1", url: "https://github.com/torque/Aegisub-Motion",
feed: "https://raw.githubusercontent.com/TypesettingTools/Aegisub-Motion/DepCtrl/DependencyControl.json"},
{"l0.ASSFoundation", version: "0.2.4", url: "https://github.com/TypesettingTools/ASSFoundation",
feed: "https://raw.githubusercontent.com/TypesettingTools/ASSFoundation/master/DependencyControl.json"}
}
}
LineCollection, ASS = depRec\requireModules!
class LayoutLineCounter
new: (@lines, @style, @maxHeight) =>
@referenceHeights = {0}
getLayoutLineCount: (line, heightDiffThreshold = 0.2) =>
ass = ASS\parse line
lineHeight = (ass\getLineBounds!).h
-- if the subtitle is covering the whole screen we have no way to tell how many lines exactly it produces
-- since some of them may not be within the canvas bounds and therefore not seen by SubInspector
if lineHeight >= @maxHeight
return -1
layoutLineCount, prevRefHeight = 0, -math.huge
while true
refHeight = @referenceHeights[layoutLineCount+1]
-- stop early when we failed retrieving the reference height before
return -1 if refHeight == -1
-- get an additional reference height if our layout height for this subtitle is larger
-- than the reference height of the highest line count we have already tested
unless refHeight
refHeight = @getReferenceHeight layoutLineCount
if refHeight <= prevRefHeight
@referenceHeights[layoutLineCount] = -1
return -1
-- If we picked a reference text that does not range from ascender to descender
-- we may run into situations where our actual layout is large than the reference,
-- despite having the same number of lines.
-- Assuming regular typeface metrics, we expect a layout of n+1 lines to have a roughly proportionally
-- larger height than a layout of n lines.
-- If the difference is much smaller, we probably are in this situation and should account for it
if lineHeight < (refHeight - prevRefHeight) * heightDiffThreshold + prevRefHeight
return layoutLineCount - 1
-- subtitle layouts of smaller or equal height than the reference have at most the same number of lines
elseif lineHeight <= refHeight
return layoutLineCount
prevRefHeight = refHeight
layoutLineCount += 1
return layoutLineCount
getReferenceHeight: (layoutLineCount = 1, referenceText = "gybhQ") =>
-- create a reference line with the desired number of rendered lines shown on the screen
testText = ASS.Section.Text table.concat [referenceText for i = 1, layoutLineCount], "\\N"
testLine = ASS\createLine {{testText}, @lines, style: @style}
bounds = testLine.ASS\getLineBounds!
return bounds.h
countLayoutLines = (sub, sel) ->
lines = LineCollection sub, sel
counters = {}
canvasHeight = tonumber (ASS\getScriptInfo sub).PlayResY
lines\runCallback (_, line) ->
unless counters[line.style]
counters[line.style] = LayoutLineCounter lines, line.style, canvasHeight
layoutLineCount = counters[line.style]\getLayoutLineCount line
line\setExtraData script_namespace, :layoutLineCount
lines\replaceLines!
depRec\registerMacros {
{"Count Layout Lines", "Counts the number of layout lines produced on the canvas per subtitle line and writes it into extradata.", countLayoutLines}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment