[latex3-commits] [git/LaTeX3-latex3-luaotfload] dev: Create first/second discretionaries if appropriate (4c52ebd)

Marcel Fabian Krüger tex at 2krueger.de
Fri Oct 30 09:31:53 CET 2020


Repository : https://github.com/latex3/luaotfload
On branch  : dev
Link       : https://github.com/latex3/luaotfload/commit/4c52ebd16df5659b3ffdc7e11d9817989f59f741

>---------------------------------------------------------------

commit 4c52ebd16df5659b3ffdc7e11d9817989f59f741
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Fri Oct 30 08:00:58 2020 +0100

    Create first/second discretionaries if appropriate


>---------------------------------------------------------------

4c52ebd16df5659b3ffdc7e11d9817989f59f741
 src/luaotfload-harf-plug.lua | 97 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 90 insertions(+), 7 deletions(-)

diff --git a/src/luaotfload-harf-plug.lua b/src/luaotfload-harf-plug.lua
index 3d25ffa..5cc3772 100644
--- a/src/luaotfload-harf-plug.lua
+++ b/src/luaotfload-harf-plug.lua
@@ -96,6 +96,8 @@ local pdfliteral_t      = node.subtype("pdf_literal")
 
 local line_t            = 1
 local explicitdisc_t    = 1
+local firstdisc_t       = 4
+local seconddisc_t      = 5
 local fontkern_t        = 0
 local italiccorr_t      = 3
 local regulardisc_t     = 3
@@ -410,7 +412,6 @@ function shape(head, firstnode, run)
     local break_glyph, break_cluster, break_node = 1, offset, node
     local disc_glyph, disc_cluster, disc_node
     local disc_cluster
-    -- local disc2_node, disc2_index -- TODO: Hopefully later
     local i = 0
     local glyph
     -- The following is a repeat {...} while glyph {...} loop.
@@ -434,10 +435,19 @@ function shape(head, firstnode, run)
           or not unsafetobreak(glyph)) then
         -- Should we change the discretionary state?
         local anchor_cluster, after_cluster = offset + discs.anchor_cluster, offset + discs.after_cluster
+        local saved_anchor, saved_after = (discs.next and discs.next.anchor_cluster or math.huge) + offset
         while disc_cluster and after_cluster <= cluster
            or not disc_cluster and anchor_cluster <= cluster do
           if disc_cluster then
-
+            if not saved_after and saved_anchor < cluster then
+              saved_after = discs.next.after_cluster + offset
+              if saved_after > cluster then
+                saved_after, after_cluster = after_cluster, saved_after
+                break
+              end
+            elseif saved_after then
+              saved_after, after_cluster = after_cluster, saved_after
+            end
             local rep_glyphs = table.move(glyphs, disc_glyph, i - 1, 1, {})
             for j = 1, #rep_glyphs do
               local glyph = rep_glyphs[j]
@@ -445,13 +455,13 @@ function shape(head, firstnode, run)
               glyph.nextcluster = glyph.nextcluster - disc_cluster
             end
             do
-              local cluster_offset = 1 + disc_cluster - cluster -- The offset the glyph indices will move
+              local cluster_offset = disc_cluster - cluster + (saved_after and 2 or 1) -- The offset the glyph indices will move
               for j = i, #glyphs do
                 local glyph = glyphs[j]
                 glyph.cluster = glyph.cluster + cluster_offset
               end
               len = len + cluster_offset
-              table.move(glyphs, i, #glyphs + i - disc_glyph, disc_glyph + 1)
+              table.move(glyphs, i, #glyphs + i - disc_glyph, disc_glyph + (saved_after and 2 or 1))
 
               local discs = discs.next
               while discs do
@@ -462,7 +472,7 @@ function shape(head, firstnode, run)
             end
 
             local pre, post, _, _, lastpost, _ = getdisc(discs.disc, true)
-            local precodes, postcodes = {}, {}
+            local precodes, postcodes, repcodes = {}, {}
             table.move(codes, disc_cluster + 1, anchor_cluster, 1, precodes)
             for n in traverse(pre) do
               precodes[#precodes + 1] = is_char(n, fontid) or 0xFFFC
@@ -471,8 +481,15 @@ function shape(head, firstnode, run)
               postcodes[#postcodes + 1] = is_char(n, fontid) or 0xFFFC
             end
             table.move(codes, after_cluster + 1, cluster, #postcodes + 1, postcodes)
-            table.move(codes, cluster + 1, #codes + cluster - disc_cluster, disc_cluster + 2)
-            codes[disc_cluster + 1] = 0xFFFC
+
+            if saved_after then
+              repcodes = table.move(codes, disc_cluster + 1, cluster, 1, {})
+              table.move(codes, cluster + 1, #codes + cluster - disc_cluster, disc_cluster + 3)
+              codes[disc_cluster + 1], codes[disc_cluster + 2] = 0xFFFC, 0xFFFC
+            else
+              table.move(codes, cluster + 1, #codes + cluster - disc_cluster, disc_cluster + 2)
+              codes[disc_cluster + 1] = 0xFFFC
+            end
 
             do
               local iter = disc_node
@@ -517,6 +534,71 @@ function shape(head, firstnode, run)
               nextcluster = disc_cluster + 1,
               codepoint = 0xFFFC,
             }
+            if saved_after then
+              local next_disc = discs.next
+              setlink(discs.disc, next_disc.disc, node)
+              local next_pre, next_post, _, _, next_lastpost, _ = getdisc(next_disc.disc, true)
+              local next_rep = copynodelist(next_pre)
+              -- Let's play the game again. We need three parts:
+              -- The pre and post branches in the outer post branch
+              local next_precodes, next_postcodes, next_repcodes = {}, {}, {}
+              do
+                local saved_offset = length(post) - cluster
+                local saved_anchor, saved_after = saved_anchor + saved_offset, saved_after + saved_offset
+                table.move(postcodes, 1, saved_anchor, 1, next_precodes)
+                for n in traverse(next_pre) do
+                  next_precodes[#next_precodes + 1] = is_char(n, fontid) or 0xFFFC
+                end
+                for n in traverse(next_post) do
+                  next_postcodes[#next_postcodes + 1] = is_char(n, fontid) or 0xFFFC
+                end
+                table.move(postcodes, saved_after + 1, #postcodes, #next_postcodes + 1, next_postcodes)
+
+                local iter = post
+                for _ = 1, saved_anchor do iter = getnext(iter) end
+                if iter ~= post then
+                  local newpre = copynodelist(post, iter)
+                  setlink(tail(newpre), next_pre)
+                  next_pre = newpre
+                end
+                for _ = saved_anchor, saved_after - 1 do iter = getnext(iter) end
+                if next_post then
+                  setlink(next_lastpost, copynodelist(iter))
+                else
+                  next_post = copynodelist(iter)
+                end
+              end
+              -- The pre branch in the outer replace branch. The post branch is implicitly the same as the previous one
+              do
+                local saved_anchor = saved_anchor - disc_cluster
+                table.move(repcodes, 1, saved_anchor, 1, next_repcodes)
+                for n in traverse(next_rep) do
+                  next_repcodes[#next_repcodes + 1] = is_char(n, fontid) or 0xFFFC
+                end
+
+                local rep = glyphs[disc_glyph].replace.head
+                local iter = rep
+                for _ = 1, saved_anchor do iter = getnext(iter) end
+                if iter ~= rep then
+                  local newpre = copynodelist(rep, iter)
+                  setlink(tail(newpre), next_rep)
+                  next_rep = newpre
+                end
+              end
+              setsubtype(discs.disc, firstdisc_t)
+              setsubtype(next_disc.disc, seconddisc_t)
+              discs = discs.next
+              disc_glyph = disc_glyph + 1
+              disc_cluster = disc_cluster + 1
+              glyphs[disc_glyph] = {
+                replace = makesub(run, next_repcodes, next_rep),
+                pre = makesub(run, next_precodes, next_pre),
+                post = makesub(run, next_postcodes, next_post),
+                cluster = disc_cluster,
+                nextcluster = disc_cluster + 1,
+                codepoint = 0xFFFC,
+              }
+            end
             i = disc_glyph
             node = discs.disc
             cluster = disc_cluster
@@ -529,6 +611,7 @@ function shape(head, firstnode, run)
             end
             if not discs then break end
             anchor_cluster, after_cluster = offset + discs.anchor_cluster, offset + discs.after_cluster
+            saved_anchor, saved_after = (discs.next and discs.next.anchor_cluster or math.huge) + offset
           elseif anchor_cluster == cluster then
             disc_glyph, disc_cluster, disc_node = i, cluster, node
           else





More information about the latex3-commits mailing list.