Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hbox fixes for RTL languages #1822

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
34 changes: 23 additions & 11 deletions packages/bidi/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ local splitNodeAtPos = function (n, splitstart, p)
end
end

local splitNodelistIntoBidiRuns = function (typesetter)
local nl = typesetter.state.nodes
local splitNodelistIntoBidiRuns = function (nl, typesetter)
if not nl then nl = typesetter.state.nodes end
if #nl == 0 then return nl end
local owners, text = nodeListToText(nl)
local base_level = typesetter.frame:writingDirection() == "RTL" and 1 or 0
Expand Down Expand Up @@ -149,26 +149,33 @@ local splitNodelistIntoBidiRuns = function (typesetter)
return nl
end

local bidiBoxupNodes = function (typesetter)
local bidiBoxUpNodes = function (typesetter)
local allDone = true
for i = 1, #typesetter.state.nodes do
if not typesetter.state.nodes[i].bidiDone then allDone = false end
end
if allDone then return typesetter:nobidi_boxUpNodes() end
local newNodeList = splitNodelistIntoBidiRuns(typesetter)
local newNodeList = splitNodelistIntoBidiRuns(nil, typesetter)
typesetter:shapeAllNodes(newNodeList)
typesetter.state.nodes = newNodeList
local vboxlist = typesetter:nobidi_boxUpNodes()
-- Scan for out-of-direction material
for i = 1, #vboxlist do
local v = vboxlist[i]
if v.is_vbox then package.reorder(nil, v, typesetter) end
if v.is_vbox then v.nodes = package.reorder(nil, v.nodes, typesetter) end
end
return vboxlist
end

function package.reorder (_, n, typesetter)
local nl = n.nodes
-- We run UBA on hboxes here since they are not handled in bidiBoxUpNodes
local bidiMakeHbox = function (typesetter, content)
local hbox, hlist = typesetter:nobidi_makeHbox(content)
hbox.value = splitNodelistIntoBidiRuns(hbox.value, typesetter)
hbox.value = package.reorder(nil, hbox.value, typesetter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling a package method with a nil self pointer and bypassing inheritance has heavy code smell.

return hbox, hlist
end

function package.reorder (_, nl, typesetter)
-- local newNl = {}
-- local matrix = {}
local levels = {}
Expand Down Expand Up @@ -229,23 +236,28 @@ function package.reorder (_, n, typesetter)
nl[i].bidiDone = true
-- rv[i] = nl[i]
end
n.nodes = SU.compress(rv)
nl = SU.compress(rv)
return nl
end

function package:bidiEnableTypesetter (typesetter)
if typesetter.nobidi_boxUpNodes and self.class._initialized then
if typesetter.nobidi_boxUpNodes and typesetter.nobidi_makeHbox and self.class._initialized then
return SU.warn("BiDi already enabled, nothing to turn on")
end
typesetter.nobidi_boxUpNodes = typesetter.boxUpNodes
typesetter.boxUpNodes = bidiBoxupNodes
typesetter.boxUpNodes = bidiBoxUpNodes
typesetter.nobidi_makeHbox = typesetter.makeHbox
typesetter.makeHbox = bidiMakeHbox
end

function package:bidiDisableTypesetter (typesetter)
if not typesetter.nobidi_boxUpNodes and self.class._initialized then
if not typesetter.nobidi_boxUpNodes and not typesetter.nobidi_makeHbox and self.class._initialized then
return SU.warn("BiDi not enabled, nothing to turn off")
end
typesetter.boxUpNodes = typesetter.nobidi_boxUpNodes
typesetter.nobidi_boxUpNodes = nil
typesetter.makeHbox = typesetter.nobidi_makeHbox
typesetter.nobidi_makeHbox = nil
end

function package:_init ()
Expand Down
2 changes: 1 addition & 1 deletion shapers/base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function shaper:formNnode (contents, token, options)
nodes = nnodeContents,
text = token,
misfit = misfit,
options = options,
options = pl.tablex.copy(options),
language = options.language
})
end
Expand Down
12 changes: 1 addition & 11 deletions typesetters/base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -864,15 +864,6 @@ end
-- is responsible of doing it, if the hbox is built for anything
-- else than e.g. measuring it. Likewise, the call has to decide
-- what to do with the migrating content.
local _rtl_pre_post = function (box, atypesetter, line)
local advance = function () atypesetter.frame:advanceWritingDirection(box:scaledWidth(line)) end
if atypesetter.frame:writingDirection() == "RTL" then
advance()
return function () end
else
return advance
end
end
function typesetter:makeHbox (content)
local recentContribution = {}
local migratingNodes = {}
Expand Down Expand Up @@ -936,7 +927,6 @@ function typesetter:makeHbox (content)
depth = d,
value = recentContribution,
outputYourself = function (box, atypesetter, line)
local _post = _rtl_pre_post(box, atypesetter, line)
local ox = atypesetter.frame.state.cursorX
local oy = atypesetter.frame.state.cursorY
SILE.outputter:setCursor(atypesetter.frame.state.cursorX, atypesetter.frame.state.cursorY)
Expand All @@ -945,7 +935,7 @@ function typesetter:makeHbox (content)
end
atypesetter.frame.state.cursorX = ox
atypesetter.frame.state.cursorY = oy
_post()
atypesetter.frame:advanceWritingDirection(box:scaledWidth(line))
SU.debug("hboxes", function ()
SILE.outputter:debugHbox(box, box:scaledWidth(line))
return "Drew debug outline around hbox"
Expand Down