Skip to content

Commit

Permalink
Merge ad27644 into 0e0aec7
Browse files Browse the repository at this point in the history
  • Loading branch information
Omikhleia committed Apr 1, 2023
2 parents 0e0aec7 + ad27644 commit bded5fc
Show file tree
Hide file tree
Showing 9 changed files with 704 additions and 183 deletions.
32 changes: 16 additions & 16 deletions core/hyphenator-liang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,23 +113,19 @@ local hyphenateNode = function (node)
if #segments > 1 then
local hyphen = SILE.shaper:createNnodes(SILE.settings:get("font.hyphenchar"), node.options)
local newnodes = {}
local leadingApostrophe, nextLeadingApostrophe
for j, segment in ipairs(segments) do
local leadingApostrophe
if segment == "" then
SU.dump{ j, segments }
SU.dump({ j, segments })
SU.error("No hyphenation segment should ever be empty", true)
end
if node.options.language == "tr" then
local nextSegment = segments[j+1]
leadingApostrophe, nextLeadingApostrophe = nextLeadingApostrophe, nextSegment and luautf8.match(nextSegment, "^['’]")
if j < #segments then
segments[j+1] = luautf8.gsub(nextSegment, "^['’]", "")
end
if leadingApostrophe then
local replacement = SILE.shaper:createNnodes(leadingApostrophe, node.options)
local newNode = SILE.nodefactory.discretionary({ prebreak = hyphen, replacement = replacement })
newNode.parent = node
table.insert(newnodes, newNode)
local nextApostrophe = j < #segments and luautf8.match(segments[j+1], "^['’]")
if nextApostrophe then
segments[j+1] = luautf8.gsub(segments[j+1], "^['’]", "")
local replacement = SILE.shaper:createNnodes(nextApostrophe, node.options)
leadingApostrophe = SILE.nodefactory.discretionary({ replacement = replacement, prebreak = hyphen })
leadingApostrophe.parent = node
end
end
for _, newNode in ipairs(SILE.shaper:createNnodes(segment, node.options)) do
Expand All @@ -138,10 +134,14 @@ local hyphenateNode = function (node)
table.insert(newnodes, newNode)
end
end
if j < #segments and not nextLeadingApostrophe then
local newNode = SILE.nodefactory.discretionary({ prebreak = hyphen })
newNode.parent = node
table.insert(newnodes, newNode)
if j < #segments then
if leadingApostrophe then
table.insert(newnodes, leadingApostrophe)
else
local newNode = SILE.nodefactory.discretionary({ prebreak = hyphen })
newNode.parent = node
table.insert(newnodes, newNode)
end
end
end
node.children = newnodes
Expand Down
40 changes: 35 additions & 5 deletions core/nodefactory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,25 @@ function nodefactory.nnode:absolute ()
end

function nodefactory.nnode:outputYourself (typesetter, line)
-- See typesetter:computeLineRatio() which implements the currently rather messy
-- and probably slightly dubious 'hyphenated' logic.
-- Example: consider the word "out-put".
-- The node queue therefore contains N(out)D(-)N(put) all pointing to the same
-- parent N(output).
if self.parent and not self.parent.hyphenated then
-- When we hit N(out) and are not hyphenated, we output N(output) directly
-- and mark it as used, so as to skip D(-)N(put) afterwards.
-- I guess this was done to ensure proper kerning (vs. outputting each of
-- the nodes separately).
if not self.parent.used then
self.parent:outputYourself(typesetter, line)
end
self.parent.used = true
else
-- It's possible not to have a parent, e.g. N(word) without hyphenation points.
-- Either that, or we have a hyphenated parent but are in the case we are
-- outputting one of the elements e.g. N(out)D(-) [line break] N(put).
-- (ignoring the G(margin) nodes and potentially zerohbox nodes also on either side of the line break)
for _, node in ipairs(self.nodes) do node:outputYourself(typesetter, line) end
end
end
Expand Down Expand Up @@ -275,14 +288,27 @@ function nodefactory.discretionary:toText ()
end

function nodefactory.discretionary:outputYourself (typesetter, line)
-- TODO this is an indication of a deeper bug. If we were asked to output
-- discretionaries but the parent nnode is not hyphenated then we're
-- outputting things that were only used for measuring "what if" scenarios in
-- break point calculations. These nodes shouldn't exist at this point.
-- See typesetter:computeLineRatio() which implements the currently rather
-- messy hyphenated checks.
-- Example: consider the word "out-put-ter".
-- The node queue contains N(out)D(-)N(put)D(-)N(ter) all pointing to the same
-- parent N(output), and here we hit D(-)

-- Non-hyphenated parent: when N(out) was hit, we went for outputting
-- the whole parent, so all other elements must now be skipped.
if self.parent and not self.parent.hyphenated then return end

-- It's possible not to have a parent (e.g. on a discretionary directly
-- added in the queue and not coming from the hyphenator logic).
-- Eiher that, or we have a hyphenate parent.
if self.used then
-- This is the actual hyphenation point.
-- Skip margin glue and zero boxes.
-- If we then reach our discretionary, it means its the first in the line,
-- i.e. a postbreak. Otherwise, its a prebreak (near the end of the line,
-- notwithstanding glues etc.)
local i = 1
while (line.nodes[i].is_glue and line.nodes[i].value == "lskip")
while (line.nodes[i].is_glue and line.nodes[i].value == "margin")
or line.nodes[i].type == "zerohbox" do
i = i + 1
end
Expand All @@ -292,6 +318,10 @@ function nodefactory.discretionary:outputYourself (typesetter, line)
for _, node in ipairs(self.prebreak) do node:outputYourself(typesetter, line) end
end
else
-- This is not the hyphenation point (but another discretionary in the queue)
-- E.g. we were in the case where we have N(out)D(-) [line break] N(out)D(-)N(ter)
-- and now hit the second D(-).
-- Unused discretionaries are obviously replaced.
for _, node in ipairs(self.replacement) do node:outputYourself(typesetter, line) end
end
end
Expand Down

0 comments on commit bded5fc

Please sign in to comment.