From 66ad95c4703b9888c87205bda842feff90a9f9f7 Mon Sep 17 00:00:00 2001 From: Andrew Bruce Date: Sat, 1 Feb 2025 09:59:12 +0000 Subject: [PATCH] Parse negative kerns, add missing exception message. --- lib/mudbrick/font.ex | 2 +- lib/mudbrick/parser/ast.ex | 4 +- lib/mudbrick/parser/helpers.ex | 2 +- test/mudbrick/parser/roundtrip_test.exs | 35 ++++++++-- test/mudbrick/parser/text_content_test.exs | 33 ++++++--- test/mudbrick/parser_test.exs | 78 +++++++++++----------- 6 files changed, 99 insertions(+), 55 deletions(-) diff --git a/lib/mudbrick/font.ex b/lib/mudbrick/font.ex index 99735e6..404819c 100644 --- a/lib/mudbrick/font.ex +++ b/lib/mudbrick/font.ex @@ -26,7 +26,7 @@ defmodule Mudbrick.Font do ] defmodule MustBeChosen do - defexception [:message] + defexception message: "You must choose a font unless you have exactly one font" end defmodule Unregistered do diff --git a/lib/mudbrick/parser/ast.ex b/lib/mudbrick/parser/ast.ex index 31b5099..c0d1048 100644 --- a/lib/mudbrick/parser/ast.ex +++ b/lib/mudbrick/parser/ast.ex @@ -67,8 +67,8 @@ defmodule Mudbrick.Parser.AST do {:glyph_id, id}, acc -> [id | acc] - {:offset, offset}, [last_glyph | acc] -> - [{last_glyph, String.to_integer(offset)} | acc] + {:offset, {:integer, offset}}, [last_glyph | acc] -> + [{last_glyph, offset |> Enum.join() |> String.to_integer()} | acc] end) %TJ{ diff --git a/lib/mudbrick/parser/helpers.ex b/lib/mudbrick/parser/helpers.ex index ab2dc21..ae87eb6 100644 --- a/lib/mudbrick/parser/helpers.ex +++ b/lib/mudbrick/parser/helpers.ex @@ -154,7 +154,7 @@ defmodule Mudbrick.Parser.Helpers do |> repeat( choice([ glyph_id_hex(), - non_negative_integer() |> unwrap_and_tag(:offset) + integer() |> unwrap_and_tag(:offset) ]) |> ignore(whitespace()) ) diff --git a/test/mudbrick/parser/roundtrip_test.exs b/test/mudbrick/parser/roundtrip_test.exs index e9dc578..acbf721 100644 --- a/test/mudbrick/parser/roundtrip_test.exs +++ b/test/mudbrick/parser/roundtrip_test.exs @@ -8,24 +8,51 @@ defmodule Mudbrick.ParseRoundtripTest do alias Mudbrick.Parser property "documents" do - check all document_options <- document_options(), + check all fonts <- fonts(), + document_options <- document_options(), pages_options <- list_of(page_options()), images_options <- list_of(image_options()), + text_writes <- list_of(string(:alphanumeric)), max_runs: 75 do - doc = new(document_options) + doc = new(Keyword.merge(document_options, fonts: fonts)) images = Keyword.get(document_options, :images, %{}) input = - Enum.zip([pages_options, cycle(images_options), cycle(Map.keys(images))]) - |> Enum.reduce(doc, fn {page_options, image_options, image_identifier}, context -> + Enum.zip([ + pages_options, + cycle(images_options), + cycle(Map.keys(images)), + cycle(text_writes) + ]) + |> Enum.reduce(doc, fn { + page_options, + image_options, + image_identifier, + text_write + }, + context -> context |> page(page_options) |> then(fn page_context -> if Enum.empty?(image_options) or Enum.empty?(document_options[:images]) do page_context else + text_options = + if fonts && map_size(fonts) > 1 do + [font: Map.keys(fonts) |> List.first()] + else + [] + end + page_context |> image(image_identifier, image_options) + |> then(fn context -> + if fonts && map_size(fonts) > 0 do + text(context, text_write, text_options) + else + context + end + end) end end) end) diff --git a/test/mudbrick/parser/text_content_test.exs b/test/mudbrick/parser/text_content_test.exs index 9c4e372..7722e3f 100644 --- a/test/mudbrick/parser/text_content_test.exs +++ b/test/mudbrick/parser/text_content_test.exs @@ -36,6 +36,23 @@ defmodule Mudbrick.ParseTextContentTest do %{stream: stream} end + test "can parse a text block with negative kerns" do + raw = + """ + BT + [ <00F3> -32 <0010> ] TJ + ET + """ + + assert Parser.parse(raw, :content_blocks) == [ + text_block: [ + BT: [], + TJ: [glyph_id: "00F3", offset: {:integer, ["-", "32"]}, glyph_id: "0010"], + ET: [] + ] + ] + end + test "can turn text content to Mudbrick", %{stream: stream} do assert %Mudbrick.ContentStream{ compress: false, @@ -90,7 +107,7 @@ defmodule Mudbrick.ParseTextContentTest do rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ glyph_id: "00D5", - offset: "24", + offset: {:integer, ["24"]}, glyph_id: "00C0", glyph_id: "00ED", glyph_id: "00ED", @@ -100,7 +117,7 @@ defmodule Mudbrick.ParseTextContentTest do glyph_id: "0138", glyph_id: "00FC", glyph_id: "010F", - offset: "12", + offset: {:integer, ["12"]}, glyph_id: "00ED", glyph_id: "00BB", glyph_id: "0197" @@ -115,7 +132,7 @@ defmodule Mudbrick.ParseTextContentTest do rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ glyph_id: "0105", - offset: "44", + offset: {:integer, ["44"]}, glyph_id: "00EA", glyph_id: "011E", glyph_id: "011E", @@ -127,16 +144,16 @@ defmodule Mudbrick.ParseTextContentTest do glyph_id: "00C3", glyph_id: "0125", glyph_id: "012C", - offset: "35", + offset: {:integer, ["35"]}, glyph_id: "015A", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "0105", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "00EA", - offset: "63", + offset: {:integer, ["63"]}, glyph_id: "014B", glyph_id: "01F0", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "00FF", glyph_id: "012C", glyph_id: "0125", diff --git a/test/mudbrick/parser_test.exs b/test/mudbrick/parser_test.exs index 739b63e..d66fed2 100644 --- a/test/mudbrick/parser_test.exs +++ b/test/mudbrick/parser_test.exs @@ -200,7 +200,7 @@ defmodule Mudbrick.ParserTest do rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ glyph_id: "00D5", - offset: "24", + offset: {:integer, ["24"]}, glyph_id: "00C0", glyph_id: "00ED", glyph_id: "00ED", @@ -210,7 +210,7 @@ defmodule Mudbrick.ParserTest do glyph_id: "0138", glyph_id: "00FC", glyph_id: "010F", - offset: "12", + offset: {:integer, ["12"]}, glyph_id: "00ED", glyph_id: "00BB", glyph_id: "0197" @@ -224,7 +224,7 @@ defmodule Mudbrick.ParserTest do rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ glyph_id: "0105", - offset: "44", + offset: {:integer, ["44"]}, glyph_id: "00EA", glyph_id: "011E", glyph_id: "011E", @@ -236,16 +236,16 @@ defmodule Mudbrick.ParserTest do glyph_id: "00C3", glyph_id: "0125", glyph_id: "012C", - offset: "35", + offset: {:integer, ["35"]}, glyph_id: "015A", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "0105", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "00EA", - offset: "63", + offset: {:integer, ["63"]}, glyph_id: "014B", glyph_id: "01F0", - offset: "13", + offset: {:integer, ["13"]}, glyph_id: "00FF", glyph_id: "012C", glyph_id: "0125", @@ -316,7 +316,7 @@ defmodule Mudbrick.ParserTest do BT: [], q: [], m: [real: ["7", ".", "0"], real: ["23", ".", "0"]], - RG: [{:integer, ["0"]}, {:integer, ["0"]}, {:integer, ["0"]}], + RG: [integer: ["0"], integer: ["0"], integer: ["0"]], w: [real: ["0", ".", "5"]], l: [real: ["293", ".", "29999999999995"], real: ["23", ".", "0"]], Tf: ["1", "12"], @@ -324,7 +324,7 @@ defmodule Mudbrick.ParserTest do rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ glyph_id: "00D5", - offset: "24", + offset: {:integer, ["24"]}, glyph_id: "00C0", glyph_id: "00ED", glyph_id: "00ED", @@ -334,7 +334,7 @@ defmodule Mudbrick.ParserTest do glyph_id: "0138", glyph_id: "00FC", glyph_id: "010F", - offset: "12", + offset: {:integer, ["12"]}, glyph_id: "00ED", glyph_id: "00BB", glyph_id: "0197" @@ -350,34 +350,34 @@ defmodule Mudbrick.ParserTest do TL: [real: ["14", ".", "399999999999999"]], rg: [integer: ["0"], integer: ["0"], integer: ["0"]], TJ: [ - {:glyph_id, "0105"}, - {:offset, "44"}, - {:glyph_id, "00EA"}, - {:glyph_id, "011E"}, - {:glyph_id, "011E"}, - {:glyph_id, "012C"}, - {:glyph_id, "01F0"}, - {:glyph_id, "0109"}, - {:glyph_id, "0125"}, - {:glyph_id, "01F0"}, - {:glyph_id, "00C3"}, - {:glyph_id, "0125"}, - {:glyph_id, "012C"}, - {:offset, "35"}, - {:glyph_id, "015A"}, - {:offset, "13"}, - {:glyph_id, "0105"}, - {:offset, "1"}, - {:offset, "3"}, - {:glyph_id, "00EA"}, - {:offset, "63"}, - {:glyph_id, "014B"}, - {:glyph_id, "01F0"}, - {:offset, "13"}, - {:glyph_id, "00FF"}, - {:glyph_id, "012C"}, - {:glyph_id, "0125"}, - {:glyph_id, "015A"} + glyph_id: "0105", + offset: {:integer, ["44"]}, + glyph_id: "00EA", + glyph_id: "011E", + glyph_id: "011E", + glyph_id: "012C", + glyph_id: "01F0", + glyph_id: "0109", + glyph_id: "0125", + glyph_id: "01F0", + glyph_id: "00C3", + glyph_id: "0125", + glyph_id: "012C", + offset: {:integer, ["35"]}, + glyph_id: "015A", + offset: {:integer, ["13"]}, + glyph_id: "0105", + offset: {:integer, ["1"]}, + offset: {:integer, ["3"]}, + glyph_id: "00EA", + offset: {:integer, ["63"]}, + glyph_id: "014B", + glyph_id: "01F0", + offset: {:integer, ["13"]}, + glyph_id: "00FF", + glyph_id: "012C", + glyph_id: "0125", + glyph_id: "015A" ], ET: [] ]