2007-01-05 15:53:21 +01:00
|
|
|
|
--[[
|
|
|
|
|
Copyright (c) 2007, Niels Martin Hansen, Rodrigo Braz Monteiro
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
* Neither the name of the Aegisub Group nor the names of its contributors
|
|
|
|
|
may be used to endorse or promote products derived from this software
|
|
|
|
|
without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
]]
|
|
|
|
|
|
|
|
|
|
-- Aegisub Automation 4 Lua karaoke skeleton
|
|
|
|
|
|
2007-01-18 09:15:02 +01:00
|
|
|
|
-- Compatibility hatch
|
|
|
|
|
if aegisub.lua_automation_version < 4 then
|
|
|
|
|
include("karaskel.auto3")
|
|
|
|
|
return
|
2007-01-05 15:53:21 +01:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
include("utils.lua")
|
|
|
|
|
include("unicode.lua")
|
|
|
|
|
|
|
|
|
|
-- Make sure karaskel table exists
|
|
|
|
|
if not karaskel then
|
|
|
|
|
karaskel = {}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Collect styles and metadata from the subs
|
|
|
|
|
function karaskel.collect_head(subs)
|
|
|
|
|
local meta = { res_x = 0, res_y = 0 }
|
|
|
|
|
local styles = { n = 0 }
|
|
|
|
|
|
|
|
|
|
for i = 1, #subs do
|
|
|
|
|
local l = subs[i]
|
|
|
|
|
if l.class == "style" then
|
|
|
|
|
styles.n = styles.n + 1
|
|
|
|
|
styles[n] = l
|
|
|
|
|
styles[l.name] = l
|
|
|
|
|
elseif l.class == "info" then
|
|
|
|
|
local k = l.key:lower()
|
|
|
|
|
if k == "playresx" then
|
|
|
|
|
meta.res_x = math.floor(l.value)
|
|
|
|
|
elseif k == "playresy" then
|
|
|
|
|
meta.res_y = math.floor(l.value)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Fix missing resolution data
|
|
|
|
|
if meta.res_x == 0 and meta_res_y == 0 then
|
|
|
|
|
meta.res_x = 384
|
|
|
|
|
meta.res_y = 288
|
|
|
|
|
elseif meta.res_x == 0 then
|
|
|
|
|
-- This is braindead, but it's how TextSub does things...
|
|
|
|
|
if meta.res_y == 1024 then
|
|
|
|
|
meta.res_x = 1280
|
|
|
|
|
else
|
|
|
|
|
meta.res_x = meta.res_y / 3 * 4
|
|
|
|
|
end
|
|
|
|
|
elseif meta.res_y == 0 then
|
|
|
|
|
-- As if 1280x960 didn't exist
|
|
|
|
|
if meta.res_x == 1280 then
|
|
|
|
|
meta.res_y = 1024
|
|
|
|
|
else
|
|
|
|
|
meta.res_y = meta.res_x * 3 / 4
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return meta, styles
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Precalc some info on a line
|
|
|
|
|
-- Modifies the line parameter
|
|
|
|
|
function karaskel.preproc_line(subs, meta, styles, line)
|
|
|
|
|
-- Assume line is class=dialogue
|
|
|
|
|
local kara = aegisub.parse_karaoke_data(line.text)
|
|
|
|
|
line.kara = { n = 0 }
|
|
|
|
|
line.furi = { n = 0 }
|
|
|
|
|
|
|
|
|
|
if styles[line.style] then
|
|
|
|
|
line.style = styles[line.style]
|
|
|
|
|
else
|
2007-02-02 02:01:12 +01:00
|
|
|
|
aegisub.debug.out("WARNING: Style not found: " .. line.style .. "\n")
|
2007-01-05 15:53:21 +01:00
|
|
|
|
line.style = styles[1]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
line.text_stripped = ""
|
|
|
|
|
|
|
|
|
|
local curx = 0
|
|
|
|
|
local worksyl = { }
|
|
|
|
|
for i = 0, #line.kara do
|
|
|
|
|
local syl = line.kara[i]
|
|
|
|
|
|
|
|
|
|
-- Spaces at the start and end of the syllable are best ignored
|
|
|
|
|
local prespace, syltext, postspace = syl.text_stripped:match("^([ \t]*)(.-)([ \t]*)$")
|
|
|
|
|
|
|
|
|
|
local prefix = syltext:sub(1,unicode.charwidth(syltext,1))
|
|
|
|
|
if prefix ~= "#" and prefix ~= "#" and i > 0 then
|
|
|
|
|
line.kara[line.kara.n] = worksyl
|
|
|
|
|
line.kara.n = line.kara.n + 1
|
|
|
|
|
worksyl = { }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Check if there is a chance of furigana
|
|
|
|
|
if syltext:find("|") or syltext:find("|") then
|
|
|
|
|
syltext = syltext:gsub("|", "|")
|
|
|
|
|
local maintext, furitext = syl:match("^(.-)|(.-)$")
|
|
|
|
|
syltext = maintext
|
|
|
|
|
|
|
|
|
|
local furi = { }
|
|
|
|
|
furi.syl = worksyl
|
|
|
|
|
|
|
|
|
|
local prefix = furitext:sub(1,unicode.charwidth(furitext,1))
|
|
|
|
|
if prefix == "!" or prefix == "!" then
|
2007-02-02 02:01:12 +01:00
|
|
|
|
furi.isbreak = true
|
2007-01-05 15:53:21 +01:00
|
|
|
|
furi.spillback = false
|
|
|
|
|
elseif prefix == "<" or prefix == "<" then
|
2007-02-02 02:01:12 +01:00
|
|
|
|
furi.isbreak = true
|
2007-01-05 15:53:21 +01:00
|
|
|
|
furi.spillback = true
|
|
|
|
|
else
|
2007-02-02 02:01:12 +01:00
|
|
|
|
furi.isbreak = false
|
2007-01-05 15:53:21 +01:00
|
|
|
|
furi.spillback = false
|
|
|
|
|
end
|
2007-02-02 02:01:12 +01:00
|
|
|
|
if furi.isbreak then
|
2007-01-05 15:53:21 +01:00
|
|
|
|
furitext = furitext:sub(unicode.charwidth(furitext,1)+1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
furi.start_time = syl.start_time
|
|
|
|
|
furi.end_time = syl.end_time
|
|
|
|
|
furi.duration = syl.duration
|
|
|
|
|
furi.text = furitext
|
|
|
|
|
|
|
|
|
|
line.furi.n = line.furi.n + 1
|
|
|
|
|
line.furi[line.furi.n] = furi
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- If this is the start of a highlight group, do regular processing
|
|
|
|
|
if prefix ~= "#" and prefix ~= "#" then
|
|
|
|
|
-- Update stripped line-text
|
|
|
|
|
line.text_stripped = line.text_stripped + syl.text_stripped
|
|
|
|
|
|
|
|
|
|
-- Copy data from syl to worksyl
|
|
|
|
|
worksyl.text = syl.text
|
|
|
|
|
worksyl.duration = syl.duration
|
|
|
|
|
worksyl.kdur = syl.duration / 10
|
|
|
|
|
worksyl.start_time = syl.start_time
|
|
|
|
|
worksyl.end_time = syl.end_time
|
|
|
|
|
worksyl.tag = syl.tag
|
|
|
|
|
worksyl.line = line
|
|
|
|
|
worksyl.style = line.style
|
|
|
|
|
|
|
|
|
|
-- And add new data to worksyl
|
|
|
|
|
worksyl.text_stripped = syltext
|
|
|
|
|
worksyl.width = aegisub.text_extents(line.style, syltext)
|
|
|
|
|
curx = curx + aegisub.text_extents(line.style, prespace)
|
|
|
|
|
worksyl.left = curx
|
|
|
|
|
worksyl.center = curx + worksyl.width/2
|
|
|
|
|
worksyl.right = curx + worksyl.width
|
|
|
|
|
curx = curx + worksyl.width + aegisub.text_extents(line.style, postspace)
|
|
|
|
|
|
|
|
|
|
-- TODO: inlinefx here
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- And in either case, add highlight data
|
|
|
|
|
local hl = {
|
|
|
|
|
start_time = worksyl.start_time,
|
|
|
|
|
end_time = worksyl.end_time,
|
|
|
|
|
duration = worksyl.duration
|
|
|
|
|
}
|
|
|
|
|
worksyl.highlights = { n = 1, [1] = hl }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Add last syllable
|
|
|
|
|
line.kara[line.kara.n] = worksyl
|
|
|
|
|
|
|
|
|
|
-- Full line sizes
|
|
|
|
|
line.width, line.height, line.descent, line.extlead = aegisub.text_extents(line.style, line.text_stripped)
|
|
|
|
|
|
|
|
|
|
-- Generate furigana style
|
|
|
|
|
local furistyle = table.copy(line.style)
|
|
|
|
|
furistyle.fontsize = furistyle.fontsize / 2
|
|
|
|
|
furistyle.outline = furistyle.outline / 2
|
|
|
|
|
|
|
|
|
|
-- Layout furigana
|
|
|
|
|
for i = 1, line.furi.n do
|
|
|
|
|
end
|
|
|
|
|
end
|