ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
* how to simulate \hss in luametatex?
@ 2022-11-11  2:37 黄复雄 via ntg-context
  2022-11-11  9:53 ` Max Chernoff via ntg-context
  0 siblings, 1 reply; 5+ messages in thread
From: 黄复雄 via ntg-context @ 2022-11-11  2:37 UTC (permalink / raw)
  To: ntg-context; +Cc: 黄复雄

[-- Attachment #1: Type: text/plain, Size: 1614 bytes --]

Hi list,
I want to  simulate \hss  in lua end in ConTeXt/luametatex environment.
For example,

```ConTeXt
a{\raise 1.5ex\hbox to 0pt{\hss b}}c
```

should get 'b' on top of 'a', as follows:

```pdf
b
ac
```
and in lua, I see a <glue userskip> before "b" node, width
width:0, stretch:65536, shrink:65536, stretchorder:2, shrinkorder:2

And in lua, I do as follows(part of my app seen in attachment):

```lua
    local hss = node_new(glue_id)
    hss.stretch = 65536
    hss.stretchorder = 2
    hss.shrink = 65536
    hss.shrinkorder = 2
    hss.width = 0
    list,_ = node_insertbefore(list, list, hss)  -- b is in the list
    -- I got a <glue userskip> with
    width:0, stretch:65536, shrink:65536, stretchorder:2, shrinkorder:2

    local box = node_new(hlist_id, "box")
    box.head = list
    box.width = 0
    box.shift = -tex_sp("1ex")
    -- I got <hlist box>  width:0       height:0       deep:0
shift: -503424

    head, current = node_insertbefore(head,current, box)  -- current is 'c' node
```

And got 'b' on top of 'c' in pdf as follows:

```pdf
  b
ac
```

How can I get 'b' on top of 'a' as \hss do?

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry
to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

[-- Attachment #2: t-zhpunc.lua --]
[-- Type: application/octet-stream, Size: 22250 bytes --]

Moduledata = Moduledata or {}
Moduledata.zhpunc = Moduledata.zhpunc or {}
-- 配合竖排
-- 竖排模块(判断是否挂载竖排,以便处理旋转的标点)
Moduledata.vtypeset = Moduledata.vtypeset or {}
Moduledata.vtypeset.appended = Moduledata.vtypeset.appended or false

-- 标点模式配置,默认全角
local quanjiao, kaiming, banjiao, yuanyang = "quanjiao", "kaiming", "banjiao","yuanyang"

local hlist_id   = nodes.nodecodes.hlist
local vlist_id   = nodes.nodecodes.vlist
local rule_id    = nodes.nodecodes.rule
local glyph_id   = nodes.nodecodes.glyph --node.id ('glyph')
local glue_id    = nodes.nodecodes.glue
local kern_id    = nodes.nodecodes.kern
local indentskip_id = nodes.subtypes.glue.indentskip

local fonthashes = fonts.hashes
local fontdata   = fonthashes.identifiers --字体身份表

local node_traverse = node.traverse
local node_tail = node.tail
local node_hpack = node.hpack
local node_insertbefore = node.insertbefore
local node_insertafter = node.insertafter
local nodes_pool_kern = nodes.pool.kern
local node_new = node.new
local node_copy = node.copy
local node_copylist = node.copylist
local node_remove = node.remove
local node_free = node.free
local nodes_tasks_appendaction = nodes.tasks.appendaction
local tex_sp = tex.sp

---[[ 结点跟踪工具
local function show_detail(n, label)
    local l = label or "======="
    print(">>>>>>>>>"..l.."<<<<<<<<<<")
    print(nodes.toutf(n))
    for i in node.traverse(n) do
        local char
        if i.id == glyph_id then
            char = utf8.char(i.char)
            print(i, char)
        elseif i.id == nodes.nodecodes.penalty then
            print(i, i.penalty)
        elseif i.id == nodes.nodecodes.glue then
            print(i, i.width, i.stretch, i.shrink, i.stretchorder, i.shrinkorder)
        elseif i.id == nodes.nodecodes.hlist then
            print(i, nodes.toutf(i.list),i.width,i.height,i.depth,i.shift,i.glue_set,i.glue_sign,i.glue_order)
        elseif i.id == nodes.nodecodes.kern then
            print(i, i.kern, i.expension)
        else
            print(i)
        end
    end
end
--]]


-- 标点缓存数据
-- {
--     font={
--         [0x2018]={kern_l, kern_r, one_side_space, final_quad}, -- 左kern、右kern、单侧空(左右对齐用)、最终应用宽度(角,用于判断是否加空)
--         ...
--     },
--     ...
-- }
local puncs_font = {}

-- 标点分类
-- 语义单元前
local puncs_left_sign     = 'puncs_left_sign'     -- 左半标号,如《
-- 语义单元后
local puncs_right_sign    = 'puncs_right_sign'    -- 右半标号,如》
local puncs_inner_point   = 'puncs_inner_point'   -- 句内点号,如、
local puncs_ending_point  = 'puncs_ending_point'  -- 句末点号,如。
-- 语义单元中(视同)
local puncs_ellipsis      = 'puncs_ellipsis'      -- 省略号…
local puncs_dash          = 'puncs_dash'          -- 破折号—
-- 语义单元中
local puncs_full_junction = 'puncs_full_junction' -- 全角连接号~
local puncs_half_junction = 'puncs_half_junction' -- 半角连接号,如-
-- 非
local puncs_no            = 'puncs_no'          -- 非标点的可视结点

-- 加空的组合与数量
local inserting_space = {
    -- 开明
    [kaiming] = {
        [puncs_ending_point] =   {puncs_left_sign = 1,  --。《
                                  puncs_no        = 1}, --。囗
    },
    -- 全角
    [quanjiao] = {
        [puncs_no]           =   {puncs_left_sign = 1}, --囗《
        [puncs_right_sign]   =   {puncs_left_sign = 1,  --》《
                                  puncs_no        = 1}, --》囗
        [puncs_inner_point]  =   {puncs_left_sign = 1,  --、《
                                  puncs_no        = 1}, --、囗
        [puncs_ending_point] =   {puncs_left_sign = 1,  --。《
                                  puncs_no        = 1}, --。囗
    },
}

-- 所有标点
local puncs = {
    -- 左半标号
    [0x2018] = puncs_left_sign, -- ‘
    [0x201C] = puncs_left_sign, -- “
    [0x3008] = puncs_left_sign, -- 〈
    [0x300A] = puncs_left_sign, -- 《
    [0x3010] = puncs_left_sign, -- 【
    [0x3014] = puncs_left_sign, -- 〔
    [0xFF08] = puncs_left_sign, -- (
    [0xFF3B] = puncs_left_sign, -- [
    -- ext
    [0x300C] = puncs_left_sign, -- 「
    [0x300E] = puncs_left_sign, -- 『
    [0x3016] = puncs_left_sign, -- 〖
    [0xFF5B] = puncs_left_sign, -- {

    -- 右半标号
    [0x2019] = puncs_right_sign, -- ’
    [0x201D] = puncs_right_sign, -- ”
    [0x3009] = puncs_right_sign, -- 〉
    [0x300B] = puncs_right_sign, -- 》
    [0x3011] = puncs_right_sign, -- 】
    [0x3015] = puncs_right_sign, -- 〕
    [0xFF09] = puncs_right_sign, -- )
    [0xFF3D] = puncs_right_sign, -- ]
    -- ext
    [0x300D] = puncs_right_sign, -- 」
    [0x300F] = puncs_right_sign, -- 』
    [0x3017] = puncs_right_sign, -- 〗
    [0xFF5D] = puncs_right_sign, -- }

    -- 句内点号
    [0x3001] = puncs_inner_point,   -- 、
    [0xFF0C] = puncs_inner_point,   -- ,
    [0xFF1A] = puncs_inner_point,   -- :
    [0xFF1B] = puncs_inner_point,   -- ;

    -- 句末点号
    [0xFF01] = puncs_ending_point,   -- !
    [0xFF1F] = puncs_ending_point,   -- ?
    [0x3002] = puncs_ending_point,   -- 。
    -- ext
    [0xFF0E] = puncs_ending_point,   -- .

    -- 省略号
    [0x2026] = puncs_ellipsis, -- …

    -- 破折号
    [0x2014] = puncs_dash, -- — 半字线,兼puncs_full_junction

    -- 全角连接号
    [0xff5e] = puncs_full_junction, -- ~ 半字线

    -- 半角连接号
    [0x00b7] = puncs_half_junction, -- ·   MIDDLE DOT
    [0x002D] = puncs_half_junction, -- -   Hyphen-Minus. Will there be any side effects?
    [0x002F] = puncs_half_junction, -- /   Solidus
    -- ext
    [0xff0f] = puncs_half_junction, -- /   Solidus
}

-- 竖排时要旋转的标点/竖排标点(装在hlist中)
local puncs_to_rotate = {
    [0x3001] = true,   -- 、
    [0xFF0C] = true,   -- ,
    [0x3002] = true,   -- 。
    [0xFF0E] = true,   -- .
    [0xFF1A] = true,   -- :
    -- 以下,后两位压缩值与前两位相乘后相等,即与竖排模块的“居中”一致
    [0xFF01] = true,   -- !
    [0xFF1B] = true,   -- ;
    [0xFF1F] = true,   -- ?
}

-- 行间符号
local puncs_to_hangjian = {
    [0x3001] = true,   -- 、
    [0xFF0C] = true,   -- ,
    [0x3002] = true,   -- 。
    [0xFF0E] = true,   -- .
    [0xFF1A] = true,   -- :

    [0xFF01] = true,   -- !
    [0xFF1B] = true,   -- ;
    [0xFF1F] = true,   -- ?

    [0x2018] = true,  -- ‘
    [0x2019] = true,  -- ’
    [0x201C] = true,  -- “
    [0x201D] = true,  -- ”
}

-- 是标点结点
-- @n: glyph | hlist
-- @return: false | 1 | 2 (不是标点 | 一般标点 | 将要旋转的标点)
local function is_punc(n)
    if n.id == glyph_id then
        -- 竖排旋转标点
        if Moduledata.vtypeset.appended and puncs_to_rotate[n.char] then
            return 2
        elseif puncs[n.char] then
            return 1
        else
            return false
        end
    else
        return false
    end
end

-- 是左标号
local function is_left_sign(n)
    if puncs[n.char] == puncs_left_sign then
        return true
    else
        return false
    end
end

-- 是右标号
local function is_right_sign(n)
    local p_class = puncs[n.char]
    if p_class == puncs_right_sign
    or p_class == puncs_inner_point
    or p_class == puncs_ending_point
    then
        return true
    else
        return false
    end
end

-- 同组末尾结点

local function is_visible_node(n)
    local ids = {
        [hlist_id] = true,
        [vlist_id] = true,
        [rule_id ] = true,
        [glyph_id] = true,
    }
    if ids[n.id] then --  and n.width > 0且有实际宽度(必要吗???)
        return true
    else
        return false
    end
end

-- 后一个可见节点是标点
local function next_punc(n)
    local next_n = n.next
    while next_n do
        if is_visible_node(next_n) then
            if is_punc(next_n) then
                return next_n
            else
                return false
            end
        end
        next_n = next_n.next
    end
    return nil -- n顶头
end

-- 前一个可见节点是标点
local function prev_punc(n)
    local prev_n = n.prev
    while prev_n do
        if is_visible_node(prev_n) then
            if is_punc(prev_n) then
                return prev_n
            else
                return false
            end
        end
        prev_n = prev_n.prev
    end
    return nil --n顶头
end

-- 标点类别,-1:左;0:中;1:右
local function punc_class(n)
    if is_left_sign(n) then
        return  -1
    elseif is_right_sign(n) then
        return 1
    else
        return 0
    end
end

local function node_remove_list(head, n, m)
    local to_freed
    while n and n ~= m do
        if to_freed then
            node_free(to_freed)
        end
        to_freed = n
        head,n = node_remove(head, n)
    end
    return head, n
end

-- 剪切从某个起始的同类标点(左标点、右标点、其余/中标点)组的末尾
local function cut_punc_group(head, n)
    local begin = n
    local p_class = punc_class(n)
    local the_end = n.next
    n = next_punc(n)
    while n do
        if puncs_to_hangjian[n.char] and p_class == punc_class(n) then
            the_end = n.next
            n = next_punc(n)
        else
            break
        end
    end

    -- 覆盖前后的kern TODO 更可靠的逻辑
    local pre = begin.prev
    if pre and pre.id == kern_id then
        begin = pre
    end
    if the_end and the_end.id == kern_id then
        the_end = the_end.next
    end
    local copyed_list = node_copylist(begin, the_end)
    local current
    head, current = node_remove_list(head, begin, the_end)
    return head, current, copyed_list, p_class
end

-- 以hlist形式插入列表
local function insert_list_before(head, current, list, p_class)
    -- local l = node_new(hlist_id)
    -- l.head = list

    -- 模拟\hss,插入列表首尾
    local hss = node_new(glue_id)
    hss.stretch = 65536
    hss.stretchorder = 2
    hss.shrink = 65536
    hss.shrinkorder = 2
    hss.width = 0
    if p_class == 1 then
        list,_ = node_insertbefore(list, list, hss)
    elseif p_class == -1 then
        list,_ = node_insertafter(list, node_tail(list), hss)
    end

    -- 把列表装入0宽度的盒子中
    local box = node_new(hlist_id, "box")
    box.head = list
    -- local box, _ = node_hpack(list)
    box.width = 0
    box.shift = -tex_sp("1ex")

    head, current = node_insertbefore(head,current, box)

    show_detail(box.head, "boxhead")
    show_detail(current, "current")

    return head, current
end

-- 处理每个标点前后的kern
local function process_punc (head, n)
    
    -- 取得结点字体的描述(未缩放的原始字模信息)
    local char = n.char
    local font = n.font

    -- 左右实际kern
    local l_kern
    local r_kern
    -- 单侧空白(两侧相同)
    local one_side_space
    -- 最终应用宽度
    local final_quad

    puncs_font[font] = puncs_font[font] or {}
    -- 空铅
    puncs_font[font]["quad"] = puncs_font[font]["quad"] or fontdata[font].parameters.quad -- 用结点宽度代替???
    local quad = puncs_font[font]["quad"]

    puncs_font[font][char] = puncs_font[font][char] or {}
    if  #puncs_font[font][char] >0 then -- 从表中取用
        l_kern =  puncs_font[font][char][1]
        r_kern =  puncs_font[font][char][2]
        one_side_space = puncs_font[font][char][3]
        final_quad = puncs_font[font][char][4]
    else -- 计算并缓存
        local desc = fontdata[font].descriptions[char]
        local desc_width = desc.width
        
        if not desc then return end --???
        local boundingbox = desc.boundingbox
        local x1 =  boundingbox[1]
        local x2 =  boundingbox[3]
        local w_in --内框宽度
        local left_space --前空
        local right_space -- 后空
        if is_punc(n) == 1 then -- 一般标点
            left_space = x1
            right_space = desc_width - x2
            w_in = x2 - x1
        elseif is_punc(n) == 2 then --旋转的标点
            left_space = x1
            -- 有些字体可能没有深度(整体在线上时)、高度(整体在线下时)数据
            local desc_depth = desc.depth or -desc.boundingbox[2]
            right_space = desc_width - left_space - desc_depth - desc.height
            w_in =  desc_depth + desc.height
        end
        
        local two_space -- 两侧总空
        if w_in < (desc_width / 2) then
            -- 半角标点,半字宽
            two_space = (desc_width / 2) - w_in
            final_quad = 0.5
        else
            -- 全角标点,整字宽
            two_space = desc_width - w_in
            final_quad = 1
        end
        -- 再居中
        l_kern = (two_space/2 - left_space) / desc_width * quad  --左kern比例
        puncs_font[font][char][1] = l_kern
        r_kern = (two_space/2 - right_space) / desc_width * quad --右kern比例
        puncs_font[font][char][2] = r_kern

        -- 左、右侧空白(供对齐行头、右侧收缩用)  TODO
        one_side_space = (two_space/2) / desc_width * quad
        puncs_font[font][char][3] = one_side_space

        -- 实际字宽(角)
        puncs_font[font][char][4] = final_quad
    end


    local prev = prev_punc(n)
    local next = next_punc(n)

    -- 实际占位半角的标点可能加空
    if  final_quad == 0.5
        and (Moduledata.zhpunc.model == quanjiao or  Moduledata.zhpunc.model == kaiming)
            then
        
        local space_table = inserting_space[ Moduledata.zhpunc.model]
        
        -- 后加空
        local next_space
        local next_space_table = space_table[puncs[n.char]]
        if next_space_table then
            if next then -- 后面是标点
                next_space = next_space_table[puncs[next.char]]
            elseif next == false then -- 是非标点可见结点(不是末尾nil)
                next_space = next_space_table[puncs_no]
            end
            if next_space then
                local space = node_new(glue_id)
                space.width = next_space * quad * Moduledata.zhpunc.space_quad
                head,_ = node_insertafter (head, n, space)
            end
        end
        
        -- 全角(前面无标点、不是行头时)前加空
        if  Moduledata.zhpunc.model == quanjiao then
            local pre_space
            if prev == false then
                pre_space = space_table[puncs_no][puncs[n.char]]
            end
            if pre_space then
                local space = node_new(glue_id)
                space.width = pre_space * quad * Moduledata.zhpunc.space_quad
                head,_ = node_insertbefore (head, n, space)
            end
        end
    end

    -- 尽可能调整为半字标点
    if  Moduledata.zhpunc.model ~= yuanyang then
        -- 插入kern
        local k
        head,k = node_insertbefore (head, n, nodes_pool_kern (l_kern))
        head,k = node_insertafter (head, n, nodes_pool_kern (r_kern))

        -- 更改系统插入右标点后、所有标点前的半字收缩胶 TODO 或更改scrp-cjk.lua
        if next or prev then
            local g = k.next
            while g do
                if g.id == glyph_id then
                    break
                elseif g.id == glue_id and g.shrink then
                    g.shrink = one_side_space
                    break
                end
                g = g.next
            end
        end
    end

    return head

end

-- 压缩标点
local function compress_punc (head)
    -- show_detail(head,"1111111111")
    for n in node_traverse(head) do
        if is_punc(n) then
            head = process_punc (head, n)
        end
    end
    return head
end

-- 实现行间标点
local function raise_punc_to_hangjian(head)
    show_detail(head,"1111111111")
    local n = head
    while n do
        if puncs_to_hangjian[n.char] then
            local list, p_class
            head, n, list, p_class = cut_punc_group(head,n)
            show_detail(list,"list")
            head, n = insert_list_before(head, n, list, p_class)
        else
            n = n.next
        end
    end
    return head
end

-- 包装回调任务:分行前的过滤器
function Moduledata.zhpunc.my_linebreak_filter (head)
    show_detail(head, "head")
    head = compress_punc (head)
    if Moduledata.zhpunc.hangjian then
        head = raise_punc_to_hangjian(head)
    end
    return head, true
end

-- 分行后处理对齐
function Moduledata.zhpunc.align_left_puncs(head)
    local it = head
    while it do
        if it.id == hlist_id then
            -- show_detail(it.head,"align before")
            local e = it.head
            local neg_kern = nil
            local hit = nil
            while e do
                if is_punc(e) then
                    if is_left_sign(e) then
                        hit = e
                    end
                    break
                end
                e = e.next
            end
            if hit ~= nil then
                -- 文本行整体向左偏移
                    -- local quad = quaddata[font]
                neg_kern = -puncs_font[hit.font][hit.char][3] --ah21
                -- neg_kern = -left_puncs[hit.char] * fontdata[hit.font].parameters.quad --ah21
                node_insertbefore(head, hit, nodes_pool_kern(neg_kern))
                -- 统计字符个数
                local w = 0
                local x = hit
                while x do
                    if is_punc(x) then w = w + 1 end
                    x = x.next
                end
                if w == 0 then w = 1 end
                -- 将 neg_kern 分摊出去
                x = it.head -- 重新遍历
                local av_neg_kern = -neg_kern/w
                local i = 0
                while x do
                    if is_punc(x) then
                        i = i + 1
                        -- 最后一个字符之后不插入 kern
                        if i < w then 
                            node_insertafter(head, x, nodes_pool_kern(av_neg_kern))
                        end
                    end
                    x = x.next
                end
            end
        end
        it = it.next

        -- show_detail(it.head,"align after")
    end

    return head, done
end

-- 传参设置
function Moduledata.zhpunc.set(pattern, spacequad, hangjian)
    Moduledata.zhpunc.model = pattern
    if hangjian == "false" then
        hangjian = false
    elseif hangjian == "true" then
        hangjian = true
    else
        hangjian = false
    end
    Moduledata.zhpunc.hangjian = hangjian
    Moduledata.zhpunc.space_quad = spacequad
end

-- 挂载/启动任务
function Moduledata.zhpunc.append()
    -- 段落分行前回调(最后调用)
    nodes_tasks_appendaction("processors","after","Moduledata.zhpunc.my_linebreak_filter")
    -- 段落分行后回调(最后调用)
    nodes_tasks_appendaction("finalizers", "after", "Moduledata.zhpunc.align_left_puncs")
end



local function update_protrusions()
    
    -- 合并两表到新表myvector,而不是修改font-ext.lua中的vectors.quality
    -- TODO 补齐,使用实测数据并缓存
    -- 横排时    
    local my_vectors_quality = {
        [0x2018] = { 0.60, 0 },  -- ‘
        [0x2019] = { 0, 0.60 },  -- ’
        [0x201C] = { 0.50, 0 },  -- “
        [0x201D] = { 0, 0.35 },  -- ”
        [0x300C] = { 0.50, 0 }, -- 「
        [0x300E] = { 0.50, 0 }, -- 『
        [0x300A] = { 0.40, 0 },  -- 《
        [0x300B] = { 0, 0.60 },  -- 》
        [0x3009] = { 0, 0.60 }, -- 〉
        [0x3011] = { 0, 0.50 }, -- 】
        [0xFF08] = { 0.50, 0 },  -- (
        [0xFF09] = { 0, 0.60 },  -- )
        [0x3001] = { 0, 0.65 },  -- 、
        [0xFF0c] = { 0, 0.65 },  -- ,
        [0x3002] = { 0, 0.60 },  -- 。
        [0xFF0E] = { 0, 0.50 },  -- .
        [0xFF01] = { 0, 0.65 },   -- !
        [0xFF1F] = { 0, 0.65 },  -- ?
        [0xFF1B] = { 0, 0.17 },   -- ;
        [0xFF1A] = { 0, 0.65 },   -- :
    }
    -- 竖排时更新
    if Moduledata.vtypeset.appended then
        local puncs_to_rotated = {
            [0x3001] = {0, 0.65},   -- 、
            [0xFF0C] = {0, 0.5},   -- ,
            [0x3002] = {0, 0.6},   -- 。
            [0xFF0E] = {0, 0.6},   -- .
            [0xFF1A] = {0, 0.3},   -- :
            [0xFF01] = {0, 0.1},   -- !
            [0xFF1B] = {0, 0.15},   -- ;
            [0xFF1F] = {0, 0.1},   -- ?
        }
        my_vectors_quality = table.merged (my_vectors_quality, puncs_to_rotated)
    end

    -- 挂载悬挂表、注册悬挂类
    local classes = fonts.protrusions.classes
    classes.myvector = {
        vector = 'myvector',
        factor = 1,
    }
    
    -- 标点悬挂/突出
    local vectors = fonts.protrusions.vectors
    vectors.myvector = table.merged (vectors.quality,my_vectors_quality)
    
    -- 扩展原有的字体特性default(后)为default(前)
    context.definefontfeature({"default"},{"default"},{mode="node",protrusion="myvector",liga="yes"})
    -- 在字体定义中应用或立即应用( 注意脚本的引用时机; 只能一种字体?? TODO)
    context.definedfont({"Serif*default"})

end
update_protrusions() --更新标点悬挂数据

return Moduledata.zhpunc



[-- Attachment #3: Type: text/plain, Size: 496 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: how to simulate \hss in luametatex?
  2022-11-11  2:37 how to simulate \hss in luametatex? 黄复雄 via ntg-context
@ 2022-11-11  9:53 ` Max Chernoff via ntg-context
  2022-11-11 10:50   ` Hans Hagen via ntg-context
  2022-11-11 10:53   ` 黄复雄 via ntg-context
  0 siblings, 2 replies; 5+ messages in thread
From: Max Chernoff via ntg-context @ 2022-11-11  9:53 UTC (permalink / raw)
  To: ntg-context; +Cc: Max Chernoff

Hi,

> I want to  simulate \hss  in lua end in ConTeXt/luametatex environment.
> For example,
> 
> ```ConTeXt
> a{\raise 1.5ex\hbox to 0pt{\hss b}}c
> ```

> And in lua, I do as follows(part of my app seen in attachment):

Your code doesn't compile as is. I think that this is the same thing
though:

   \starttext
   \startluacode
   local a = node.new"glyph"
   a.char = string.byte("a")
   a.font = font.current()
   
   local b = node.new"glyph"
   b.char = string.byte("b")
   b.font = font.current()
   
   local c = node.new"glyph"
   c.char = string.byte("c")
   c.font = font.current()
   
   local hss = node.new("glue")
   hss.stretch = 65536
   hss.stretchorder = 2
   hss.shrink = 65536
   hss.shrinkorder = 2
   hss.width = 0
   b = node.insertbefore(b, b, hss)
   
   local box = node.new("hlist", "box")
   box.head = b
   box.width = 0
   box.shift = -tex.sp("1ex")
   
   tex.forcehmode()
   node.write(a + box + c)
   \stopluacode
   \stoptext

> And got 'b' on top of 'c' in pdf as follows:
> 
> ```pdf
>   b
> ac
> ```

The \hss isn't the problem here. The problem is actually with the box.
When you manually make the \hbox like that, I think (although I could be
wrong) that you're bypassing all of TeX's glue calculations. You should
probably use "node.hpack" instead:

   \starttext
   \startluacode
   local a = node.new"glyph"
   a.char = string.byte("a")
   a.font = font.current()
   
   local b = node.new"glyph"
   b.char = string.byte("b")
   b.font = font.current()
   
   local c = node.new"glyph"
   c.char = string.byte("c")
   c.font = font.current()
   
   local hss = node.new("glue")
   hss.stretch = 65536
   hss.stretchorder = 2
   hss.shrink = 65536
   hss.shrinkorder = 2
   hss.width = 0
   
   local box = node.hpack(hss + b, "exactly", 0)
   box.shift = -tex.sp("1ex")
   
   tex.forcehmode()
   a.next = box
   box.next = c
   node.write(a)
   \stopluacode
   \stoptext

-- Max

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: how to simulate \hss in luametatex?
  2022-11-11  9:53 ` Max Chernoff via ntg-context
@ 2022-11-11 10:50   ` Hans Hagen via ntg-context
  2022-11-11 11:00     ` 黄复雄 via ntg-context
  2022-11-11 10:53   ` 黄复雄 via ntg-context
  1 sibling, 1 reply; 5+ messages in thread
From: Hans Hagen via ntg-context @ 2022-11-11 10:50 UTC (permalink / raw)
  To: Max Chernoff via ntg-context; +Cc: Hans Hagen

On 11/11/2022 10:53 AM, Max Chernoff via ntg-context wrote:
> Hi,
> 
>> I want to  simulate \hss  in lua end in ConTeXt/luametatex environment.
>> For example,
>>
>> ```ConTeXt
>> a{\raise 1.5ex\hbox to 0pt{\hss b}}c
>> ```
> 
>> And in lua, I do as follows(part of my app seen in attachment):
> 
> Your code doesn't compile as is. I think that this is the same thing
> though:
> 
>     \starttext
>     \startluacode
>     local a = node.new"glyph"
>     a.char = string.byte("a")
>     a.font = font.current()
>     
>     local b = node.new"glyph"
>     b.char = string.byte("b")
>     b.font = font.current()
>     
>     local c = node.new"glyph"
>     c.char = string.byte("c")
>     c.font = font.current()
>     
>     local hss = node.new("glue")
>     hss.stretch = 65536
>     hss.stretchorder = 2
>     hss.shrink = 65536
>     hss.shrinkorder = 2
>     hss.width = 0
>     b = node.insertbefore(b, b, hss)
>     
>     local box = node.new("hlist", "box")
>     box.head = b
>     box.width = 0
>     box.shift = -tex.sp("1ex")
>     
>     tex.forcehmode()
>     node.write(a + box + c)
>     \stopluacode
>     \stoptext
> 
>> And got 'b' on top of 'c' in pdf as follows:
>>
>> ```pdf
>>    b
>> ac
>> ```
> 
> The \hss isn't the problem here. The problem is actually with the box.
> When you manually make the \hbox like that, I think (although I could be
> wrong) that you're bypassing all of TeX's glue calculations. You should
> probably use "node.hpack" instead:
> 
>     \starttext
>     \startluacode
>     local a = node.new"glyph"
>     a.char = string.byte("a")
>     a.font = font.current()
>     
>     local b = node.new"glyph"
>     b.char = string.byte("b")
>     b.font = font.current()
>     
>     local c = node.new"glyph"
>     c.char = string.byte("c")
>     c.font = font.current()
>     
>     local hss = node.new("glue")
>     hss.stretch = 65536
>     hss.stretchorder = 2
>     hss.shrink = 65536
>     hss.shrinkorder = 2
>     hss.width = 0
>     
>     local box = node.hpack(hss + b, "exactly", 0)
>     box.shift = -tex.sp("1ex")
>     
>     tex.forcehmode()
>     a.next = box
>     box.next = c
>     node.write(a)
>     \stopluacode
>     \stoptext
indeed, an dafter that you can check it

  box.glueorder  : 2
  box.glueset    : 6.6683349609375
  box.gluesign   : 2

which will be applied (in the backend) to glues

Hans

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: how to simulate \hss in luametatex?
  2022-11-11  9:53 ` Max Chernoff via ntg-context
  2022-11-11 10:50   ` Hans Hagen via ntg-context
@ 2022-11-11 10:53   ` 黄复雄 via ntg-context
  1 sibling, 0 replies; 5+ messages in thread
From: 黄复雄 via ntg-context @ 2022-11-11 10:53 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: 黄复雄

Dear Max,
I am very grateful that you took the time to tweak and test my
non-running code snippet
and found the problem.

 > local box = node.hpack(hss + b, "exactly", 0)

You are absolutely right, the cause of the problem was that I wasn't
using node.hpack().
Actually, I tried to use it, but used it wrong, as follows:

local box, _ = node_hpack(list)
box.width = 0
box.shift = -tex_sp("1ex")

My app works fine now. Also, I learned a lot from your code, like
font.current(), hss + b
and tex.forcehmode() - I immediately used the last one to set
box.shift, making it relative.

Best regards

Huang Fusyong(黄复雄)

Max Chernoff via ntg-context <ntg-context@ntg.nl> 于2022年11月11日周五 17:55写道:
>
> Hi,
>
> > I want to  simulate \hss  in lua end in ConTeXt/luametatex environment.
> > For example,
> >
> > ```ConTeXt
> > a{\raise 1.5ex\hbox to 0pt{\hss b}}c
> > ```
>
> > And in lua, I do as follows(part of my app seen in attachment):
>
> Your code doesn't compile as is. I think that this is the same thing
> though:
>
>    \starttext
>    \startluacode
>    local a = node.new"glyph"
>    a.char = string.byte("a")
>    a.font = font.current()
>
>    local b = node.new"glyph"
>    b.char = string.byte("b")
>    b.font = font.current()
>
>    local c = node.new"glyph"
>    c.char = string.byte("c")
>    c.font = font.current()
>
>    local hss = node.new("glue")
>    hss.stretch = 65536
>    hss.stretchorder = 2
>    hss.shrink = 65536
>    hss.shrinkorder = 2
>    hss.width = 0
>    b = node.insertbefore(b, b, hss)
>
>    local box = node.new("hlist", "box")
>    box.head = b
>    box.width = 0
>    box.shift = -tex.sp("1ex")
>
>    tex.forcehmode()
>    node.write(a + box + c)
>    \stopluacode
>    \stoptext
>
> > And got 'b' on top of 'c' in pdf as follows:
> >
> > ```pdf
> >   b
> > ac
> > ```
>
> The \hss isn't the problem here. The problem is actually with the box.
> When you manually make the \hbox like that, I think (although I could be
> wrong) that you're bypassing all of TeX's glue calculations. You should
> probably use "node.hpack" instead:
>
>    \starttext
>    \startluacode
>    local a = node.new"glyph"
>    a.char = string.byte("a")
>    a.font = font.current()
>
>    local b = node.new"glyph"
>    b.char = string.byte("b")
>    b.font = font.current()
>
>    local c = node.new"glyph"
>    c.char = string.byte("c")
>    c.font = font.current()
>
>    local hss = node.new("glue")
>    hss.stretch = 65536
>    hss.stretchorder = 2
>    hss.shrink = 65536
>    hss.shrinkorder = 2
>    hss.width = 0
>
>    local box = node.hpack(hss + b, "exactly", 0)
>    box.shift = -tex.sp("1ex")
>
>    tex.forcehmode()
>    a.next = box
>    box.next = c
>    node.write(a)
>    \stopluacode
>    \stoptext
>
> -- Max
>
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to the Wiki!
>
> maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
> archive  : https://bitbucket.org/phg/context-mirror/commits/
> wiki     : https://contextgarden.net
> ___________________________________________________________________________________
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: how to simulate \hss in luametatex?
  2022-11-11 10:50   ` Hans Hagen via ntg-context
@ 2022-11-11 11:00     ` 黄复雄 via ntg-context
  0 siblings, 0 replies; 5+ messages in thread
From: 黄复雄 via ntg-context @ 2022-11-11 11:00 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: 黄复雄

Hans,
thank you.
By your and Max's answers, I understand that
there must be box.glueset for the glues in the box.list to actually work.

Best regards

Huang Fusyong(黄复雄)

Hans Hagen via ntg-context <ntg-context@ntg.nl> 于2022年11月11日周五 18:52写道:
>
> On 11/11/2022 10:53 AM, Max Chernoff via ntg-context wrote:
> > Hi,
> >
> >> I want to  simulate \hss  in lua end in ConTeXt/luametatex environment.
> >> For example,
> >>
> >> ```ConTeXt
> >> a{\raise 1.5ex\hbox to 0pt{\hss b}}c
> >> ```
> >
> >> And in lua, I do as follows(part of my app seen in attachment):
> >
> > Your code doesn't compile as is. I think that this is the same thing
> > though:
> >
> >     \starttext
> >     \startluacode
> >     local a = node.new"glyph"
> >     a.char = string.byte("a")
> >     a.font = font.current()
> >
> >     local b = node.new"glyph"
> >     b.char = string.byte("b")
> >     b.font = font.current()
> >
> >     local c = node.new"glyph"
> >     c.char = string.byte("c")
> >     c.font = font.current()
> >
> >     local hss = node.new("glue")
> >     hss.stretch = 65536
> >     hss.stretchorder = 2
> >     hss.shrink = 65536
> >     hss.shrinkorder = 2
> >     hss.width = 0
> >     b = node.insertbefore(b, b, hss)
> >
> >     local box = node.new("hlist", "box")
> >     box.head = b
> >     box.width = 0
> >     box.shift = -tex.sp("1ex")
> >
> >     tex.forcehmode()
> >     node.write(a + box + c)
> >     \stopluacode
> >     \stoptext
> >
> >> And got 'b' on top of 'c' in pdf as follows:
> >>
> >> ```pdf
> >>    b
> >> ac
> >> ```
> >
> > The \hss isn't the problem here. The problem is actually with the box.
> > When you manually make the \hbox like that, I think (although I could be
> > wrong) that you're bypassing all of TeX's glue calculations. You should
> > probably use "node.hpack" instead:
> >
> >     \starttext
> >     \startluacode
> >     local a = node.new"glyph"
> >     a.char = string.byte("a")
> >     a.font = font.current()
> >
> >     local b = node.new"glyph"
> >     b.char = string.byte("b")
> >     b.font = font.current()
> >
> >     local c = node.new"glyph"
> >     c.char = string.byte("c")
> >     c.font = font.current()
> >
> >     local hss = node.new("glue")
> >     hss.stretch = 65536
> >     hss.stretchorder = 2
> >     hss.shrink = 65536
> >     hss.shrinkorder = 2
> >     hss.width = 0
> >
> >     local box = node.hpack(hss + b, "exactly", 0)
> >     box.shift = -tex.sp("1ex")
> >
> >     tex.forcehmode()
> >     a.next = box
> >     box.next = c
> >     node.write(a)
> >     \stopluacode
> >     \stoptext
> indeed, an dafter that you can check it
>
>   box.glueorder  : 2
>   box.glueset    : 6.6683349609375
>   box.gluesign   : 2
>
> which will be applied (in the backend) to glues
>
> Hans
>
> -----------------------------------------------------------------
>                                            Hans Hagen | PRAGMA ADE
>                Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
>         tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
> -----------------------------------------------------------------
>
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to the Wiki!
>
> maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
> archive  : https://bitbucket.org/phg/context-mirror/commits/
> wiki     : https://contextgarden.net
> ___________________________________________________________________________________
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : https://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : https://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-11-11 11:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-11  2:37 how to simulate \hss in luametatex? 黄复雄 via ntg-context
2022-11-11  9:53 ` Max Chernoff via ntg-context
2022-11-11 10:50   ` Hans Hagen via ntg-context
2022-11-11 11:00     ` 黄复雄 via ntg-context
2022-11-11 10:53   ` 黄复雄 via ntg-context

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).