[latex3-commits] [git/LaTeX3-latex3-luaotfload] variable-cff2: Composite glyphs, but leads to issues due to LuaTeX remapping (70092e7)

Marcel Fabian Krüger tex at 2krueger.de
Sat Aug 7 04:33:25 CEST 2021


Repository : https://github.com/latex3/luaotfload
On branch  : variable-cff2
Link       : https://github.com/latex3/luaotfload/commit/70092e72e36f161f944d2eff141e2df545ce188d

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

commit 70092e72e36f161f944d2eff141e2df545ce188d
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Sat Aug 7 04:33:01 2021 +0200

    Composite glyphs, but leads to issues due to LuaTeX remapping


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

70092e72e36f161f944d2eff141e2df545ce188d
 src/luaotfload-harf-var-ttf.lua | 200 ++++++++++++++++++++++++----------------
 1 file changed, 122 insertions(+), 78 deletions(-)

diff --git a/src/luaotfload-harf-var-ttf.lua b/src/luaotfload-harf-var-ttf.lua
index f587456..efe2a29 100644
--- a/src/luaotfload-harf-var-ttf.lua
+++ b/src/luaotfload-harf-var-ttf.lua
@@ -118,7 +118,16 @@ local function parse_glyf(loca, glyf, gid)
   -- local ymax = sio.readinteger2(glyf, offset + 8)
   if num_contours < 0 then
     -- composite
-    local components = {}
+    local xmin = sio.readinteger2(glyf, offset + 2)
+    local ymin = sio.readinteger2(glyf, offset + 4)
+    local xmax = sio.readinteger2(glyf, offset + 6)
+    local ymax = sio.readinteger2(glyf, offset + 8)
+    local components = { -- FIXME: These are likely incorrect
+      xmin = xmin,
+      ymin = ymin,
+      xmax = xmax,
+      ymax = ymax,
+    }
     local flags
     offset = offset + 10
     repeat
@@ -159,8 +168,6 @@ local function parse_glyf(loca, glyf, gid)
       component.payload = glyf:sub(offset, offset + payload_length - 1)
       components[#components+1] = component
     until flags & 0x20 == 0
-    print(gid)
-    table.print{[gid] = components}
     return components
   else
     local end_contours = sio.readcardinaltable(glyf, offset+10, num_contours, 2)
@@ -308,10 +315,23 @@ local function serialize_glyf(points)
         flagdata[#flagdata+1] = last_flags
       end
     end
-    local header = string.pack(">I2i2i2i2i2" .. string.rep('I2', #contours), #contours, xmin, ymin, xmax, ymax, table.unpack(contours))
+    local header = string.pack(">i2i2i2i2i2" .. string.rep('I2', #contours), #contours, xmin, ymin, xmax, ymax, table.unpack(contours))
     return header .. string.pack(">s2", points.instructions) .. string.char(table.unpack(flagdata)) .. string.char(table.unpack(xdata)) .. string.char(table.unpack(ydata))
   else
-    error'Composite glyphs not yet supported'
+    local result = string.pack(">i2i2i2i2i2", -1, points.xmin, points.ymin, points.xmax, points.ymax)
+    for i = 1, #points do
+      local component = points[i]
+      local x, y = component.x, component.y
+      x = x and math.floor(x + .5)
+      y = y and math.floor(y + .5)
+      result = result
+          .. string.pack(component.flags & 0x2 == 0 and '>I2I2'
+                      or component.flags & 0x1 == 0x1 and '>I2I2i2i2'
+                      or '>I2I2i1i1',
+              component.flags, component.glyph, x, y)
+          .. component.payload
+    end
+    return result
   end
 end
 
@@ -413,89 +433,113 @@ local function interpolate_glyf(loca, gvar_index, gvar, glyf, gid, coords)
       local x_deltas, y_deltas
       x_deltas, suboffset = read_deltas(gvar, suboffset, count)
       y_deltas, suboffset = read_deltas(gvar, suboffset, count)
-      if base_points == true then
-        for i=1, #points do
-          local point = points[i]
-          point.x = point.x + factor * x_deltas[i]
-          point.y = point.y + factor * y_deltas[i]
-        end
-      else
-        local contours = points.contours
-        local contour = 1
-        local last, last_x, last_y, last_dx, last_dy
-        local first, first_x, first_y, first_dx, first_dy
-        local cur = 1
-        local skip = base_points[1] > contours[1] + 1
-        for i = 1, #points do
-          if i == contours[contour] + 2 then
-            contour = contour + 1
-            last_x, last_y, last_dx, last_dy = nil
-            first_x, first_y, first_dx, first_dy = nil
-            skip = base_points[cur] > contours[contour] + 1
-          end
-          if not skip then
+      local contours = points.contours
+      if contours then
+        if base_points == true then
+          for i=1, #points do
             local point = points[i]
-            local this_x, this_y = point.x, point.y
-            if base_points[cur] == i then
-              last_x, last_y = this_x, this_y
-              last_dx, last_dy = x_deltas[cur], y_deltas[cur]
-              if not first_x then
-                first_x, first_y, first_dx, first_dy = last_x, last_y, last_dx, last_dy
-              end
-              point.x = last_x + factor * last_dx
-              point.y = last_y + factor * last_dy
-              cur = cur + 1
-            else
-              if not last_x then -- We started a new contour and haven't seen a real point yet. Look for the last one instead.
-                local idx = cur
-                while base_points[idx + 1] <= contours[contour] + 1 do
-                  idx = idx + 1
-                end
-                local idx_point = points[base_points[idx]]
-                last_x, last_y = idx_point.x, idx_point.y
-                last_dx, last_dy = x_deltas[idx], y_deltas[idx]
-              end
-              local after_x, after_y, after_dx, after_dy
-              if base_points[cur] <= contours[contour] + 1 then -- If the next point is part of the contour, use it. Otherwise use the first point in our contour.
-                local next_point = points[base_points[cur]]
-                after_x, after_y = next_point.x, next_point.y
-                after_dx, after_dy = x_deltas[cur], y_deltas[cur]
+            point.x = point.x + factor * x_deltas[i]
+            point.y = point.y + factor * y_deltas[i]
+          end
+        else
+          local contour = 1
+          local last, last_x, last_y, last_dx, last_dy
+          local first, first_x, first_y, first_dx, first_dy
+          local cur = 1
+          local skip = base_points[1] > contours[1] + 1
+          local n_points = #points
+          for i = 1, n_points do
+            if i == contours[contour] + 2 then
+              contour = contour + 1
+              last_x, last_y, last_dx, last_dy = nil
+              first_x, first_y, first_dx, first_dy = nil
+              skip = (base_points[cur] or n_points + 1) > contours[contour] + 1
+            end
+            if not skip then
+              local point = points[i]
+              local this_x, this_y = point.x, point.y
+              if base_points[cur] == i then
+                repeat
+                  last_x, last_y = this_x, this_y
+                  last_dx, last_dy = x_deltas[cur], y_deltas[cur]
+                  if not first_x then
+                    first_x, first_y, first_dx, first_dy = last_x, last_y, last_dx, last_dy
+                  end
+                  point.x = last_x + factor * last_dx
+                  point.y = last_y + factor * last_dy
+                  cur = cur + 1
+                until base_points[cur] ~= i
               else
-                after_x, after_y = first_x, first_y
-                after_dx, after_dy = first_dx, first_dy
-              end
+                if not last_x then -- We started a new contour and haven't seen a real point yet. Look for the last one instead.
+                  local idx = cur
+                  while (base_points[idx + 1] or n_points + 1) <= contours[contour] + 1 do
+                    idx = idx + 1
+                  end
+                  local idx_point = points[base_points[idx]]
+                  last_x, last_y = idx_point.x, idx_point.y
+                  last_dx, last_dy = x_deltas[idx], y_deltas[idx]
+                end
+                local after_x, after_y, after_dx, after_dy
+                if (base_points[cur] or n_points + 1) <= contours[contour] + 1 then -- If the next point is part of the contour, use it. Otherwise use the first point in our contour)
+                  local next_point = points[base_points[cur]]
+                  after_x, after_y = next_point.x, next_point.y
+                  after_dx, after_dy = x_deltas[cur], y_deltas[cur]
+                else
+                  after_x, after_y = first_x, first_y
+                  after_dx, after_dy = first_dx, first_dy
+                end
 
-              -- The first case is a bit weird, but afterwards we just interpolate while clipping to the boundaries.
-              -- See the gvar spec for details.
-              if last_x == after_x then
-                if last_dx == after_dx then
-                  point.x = this_x + factor * last_dx
+                -- The first case is a bit weird, but afterwards we just interpolate while clipping to the boundaries.
+                -- See the gvar spec for details.
+                if last_x == after_x then
+                  if last_dx == after_dx then
+                    point.x = this_x + factor * last_dx
+                  end
+                elseif this_x <= last_x and this_x <= after_x then
+                  point.x = this_x + factor * (last_x < after_x and last_dx or after_dx)
+                elseif this_x >= last_x and this_x >= after_x then
+                  point.x = this_x + factor * (last_x > after_x and last_dx or after_dx)
+                else -- We have to interpolate
+                  local t = (this_x - last_x) / (after_x - last_x)
+                  point.x = this_x + factor * ((1-t) * last_dx + t * after_dx)
                 end
-              elseif this_x <= last_x and this_x <= after_x then
-                point.x = this_x + factor * (last_x < after_x and last_dx or after_dx)
-              elseif this_x >= last_x and this_x >= after_x then
-                point.x = this_x + factor * (last_x > after_x and last_dx or after_dx)
-              else -- We have to interpolate
-                local t = (this_x - last_x) / (after_x - last_x)
-                point.x = this_x + factor * ((1-t) * last_dx + t * after_dx)
-              end
 
-              -- And again for y
-              if last_y == after_y then
-                if last_dy == after_dy then
-                  point.y = this_y + factor * last_dy
+                -- And again for y
+                if last_y == after_y then
+                  if last_dy == after_dy then
+                    point.y = this_y + factor * last_dy
+                  end
+                elseif this_y <= last_y and this_y <= after_y then
+                  point.y = this_y + factor * (last_y < after_y and last_dy or after_dy)
+                elseif this_y >= last_y and this_y >= after_y then
+                  point.y = this_y + factor * (last_y > after_y and last_dy or after_dy)
+                else -- We have to interpolate
+                  local t = (this_y - last_y) / (after_y - last_y)
+                  point.y = this_y + factor * ((1-t) * last_dy + t * after_dy)
                 end
-              elseif this_y <= last_y and this_y <= after_y then
-                point.y = this_y + factor * (last_y < after_y and last_dy or after_dy)
-              elseif this_y >= last_y and this_y >= after_y then
-                point.y = this_y + factor * (last_y > after_y and last_dy or after_dy)
-              else -- We have to interpolate
-                local t = (this_y - last_y) / (after_y - last_y)
-                point.y = this_y + factor * ((1-t) * last_dy + t * after_dy)
               end
             end
           end
         end
+      else
+        -- Composite glyph
+        if base_points == true then
+          for i=1, #points do
+            local point = points[i]
+            if point.x then
+              point.x = point.x + factor * x_deltas[i]
+              point.y = point.y + factor * y_deltas[i]
+            end
+          end
+        else
+          for i=1, #base_points do
+            local point = points[base_points[i]]
+            if point and point.x then
+              point.x = point.x + factor * x_deltas[i]
+              point.y = point.y + factor * y_deltas[i]
+            end
+          end
+        end
       end
       assert(suboffset == offset + size)
     end





More information about the latex3-commits mailing list.