summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luaharfbuzz/spec/shaping_spec.lua
blob: 8ab810e3da4c5fd9d63850e1dad99e242bc787e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
local harfbuzz = require("harfbuzz")

local compare_glyphs_against_fixture = function(glyphs, fixture)
  local json = require('dkjson')
  local f = io.open("fixtures/"..fixture)
  local s = f:read("*all")
  f:close()
  local hb_shape_glyphs = json.decode(s)
  assert.are_equal(#hb_shape_glyphs, #glyphs)
  for c = 1, #glyphs do
    local g = glyphs[c]
    local h = hb_shape_glyphs[c]
    assert.are_equal(h.g, g.codepoint)
    assert.are_equal(h.cl, g.cluster)
    assert.are_equal(h.ax, g.x_advance)
    assert.are_equal(h.ay, g.y_advance)
    assert.are_equal(h.dx, g.x_offset)
    assert.are_equal(h.dy, g.y_offset)
    assert.are_equal(h.fl, g.flags)
  end
end


describe("harfbuzz module shaping functions", function()
  local face = harfbuzz.Face.new('fonts/notonastaliq.ttf')
  local font = harfbuzz.Font.new(face)
  local urdu_text = "یہ" -- U+06CC U+06C1

  it("can take a buffer and font and shape it, with output matching hb-shape", function()
    local buf = harfbuzz.Buffer.new()
    buf:add_utf8(urdu_text)

    harfbuzz.shape(font, buf)
    local glyphs = buf:get_glyphs()
    assert.True(#glyphs > 0)

    -- Compare against output of hb-shape
    compare_glyphs_against_fixture(glyphs, 'notonastaliq_U06CC_U06C1.json')
  end)

  it("can take a buffer, font and an options table with script, language and direction settings.", function()
    local buf = harfbuzz.Buffer.new()
    buf:add_utf8(urdu_text)

    harfbuzz.shape(font, buf, { language = harfbuzz.Language.new("urd"), script = harfbuzz.Script.new("Arab"), direction = harfbuzz.Direction.HB_DIRECTION_RTL })
    local glyphs = buf:get_glyphs()
    assert.True(#glyphs > 0)

    -- Compare against output of hb-shape
    compare_glyphs_against_fixture(glyphs, 'notonastaliq_U06CC_U06C1.json')
  end)

  it("can take codepoints, font and an options table with script, language and direction settings. #mac", function()
    local buf = harfbuzz.Buffer.new()
    local korean_text = { 0xAC00, 0xB098, 0xB2E4 }
    buf:add_codepoints(korean_text)

    local face_korean = harfbuzz.Face.new('/Library/Fonts/AppleGothic.ttf')
    local font_korean = harfbuzz.Font.new(face_korean)

    harfbuzz.shape(font_korean, buf, { language = harfbuzz.Language.new("KOR"), script = harfbuzz.Script.new("hang"), direction = harfbuzz.Direction.HB_DIRECTION_LTR })
    local glyphs = buf:get_glyphs()
    assert.True(#glyphs > 0)

    -- Compare against output of hb-shape
    compare_glyphs_against_fixture(glyphs, 'AppleGothic_korean_issue_22.json')
  end)

  it("can take a string containing a comma-delimited list of valid features", function()
    local buf = harfbuzz.Buffer.new()
    buf:add_utf8(urdu_text)

    harfbuzz.shape(font, buf, { language = harfbuzz.Language.new("urd"), script = harfbuzz.Script.new("Arab"), direction = harfbuzz.Direction.HB_DIRECTION_RTL, features = "+kern,smcp" })
    local glyphs = buf:get_glyphs()
    assert.True(#glyphs > 0)
  end)

  describe("features option", function()
    local buf
    local options

    before_each(function()
      buf= harfbuzz.Buffer.new()
      buf:add_utf8(urdu_text)
      options = { language = harfbuzz.Language.new("urd"), script = harfbuzz.Script.new("Arab"), direction = harfbuzz.Direction.HB_DIRECTION_RTL }
    end)

    it("can take a table containing a valid features", function()
      options.features = {
        harfbuzz.Feature.new('+kern'),
        harfbuzz.Feature.new('smcp')
      }

      harfbuzz.shape(font, buf, options)
      local glyphs = buf:get_glyphs()
      assert.True(#glyphs > 0)
    end)

    it("throws an error if feature string is invalid", function()
      options.features = "#kern"
      assert.has_error(function()
        harfbuzz.shape(font, buf, options)
      end, "Invalid feature string: '#kern'")
    end)

    it("throws an error if feature option is not a table or string", function()
      options.features = 25
      assert.has_error(function()
        harfbuzz.shape(font, buf, options)
      end, "Invalid features option")
    end)

    it("throws an error if features table does not contain a feature", function()
      options.features = {
        harfbuzz.Feature.new('+kern'),
        25,
        harfbuzz.Feature.new('smcp')
      }
      assert.has_error(function()
        harfbuzz.shape(font, buf, options)
      end, "bad argument #-1 to 'shape_full' (harfbuzz.Feature expected, got number)")
    end)

    it("shapes a string appropriately with the features turned on",function()
      buf= harfbuzz.Buffer.new()
      buf:add_utf8("123")
      local opts = { language = harfbuzz.Language.new("eng"), script = harfbuzz.Script.new("Latn"), direction = harfbuzz.Direction.HB_DIRECTION_LTR }
      local amiri_face = harfbuzz.Face.new('fonts/amiri-regular.ttf')
      local amiri_font = harfbuzz.Font.new(amiri_face)

      -- Check normal shaping w/o features
      buf= harfbuzz.Buffer.new()
      buf:add_utf8("123")

      harfbuzz.shape(amiri_font, buf, opts)
      local glyphs = buf:get_glyphs()
      compare_glyphs_against_fixture(glyphs, "amiri-regular_123.json")

      -- Check shaping with '+numr'
      buf= harfbuzz.Buffer.new()
      buf:add_utf8("123")
      opts.features = "+numr"
      harfbuzz.shape(amiri_font, buf, opts)
      glyphs = buf:get_glyphs()
      compare_glyphs_against_fixture(glyphs, "amiri-regular_123_numr.json")
    end)

    it("can set specefic shaper",function()
      options.shapers = { "fallback"}
      harfbuzz.shape(font, buf, options)
      local glyphs = buf:get_glyphs()
      assert.are_equal(2, #glyphs)
      assert.are_equal(906, glyphs[1].codepoint)
      assert.are_equal(909, glyphs[2].codepoint)
    end)
  end)
end)