diff --git a/lib/mudbrick/text_block/output.ex b/lib/mudbrick/text_block/output.ex index adc69e9..7c45981 100644 --- a/lib/mudbrick/text_block/output.ex +++ b/lib/mudbrick/text_block/output.ex @@ -16,7 +16,7 @@ defmodule Mudbrick.TextBlock.Output do alias Mudbrick.Path alias Mudbrick.TextBlock.Line - defmodule LeftAlign do + defmodule Align do @moduledoc false alias Mudbrick.TextBlock.Output @@ -26,62 +26,80 @@ defmodule Mudbrick.TextBlock.Output do |> Output.add(%TL{leading: line.leading}) end - def reduce_lines(output, [line]) do + def reduce_lines(output, [line], x_offsetter) do output |> leading(line) - |> reduce_parts(line, Tj, :first_line) + |> reset_offset(x_offsetter.(line)) + |> reduce_parts(line, Tj, :first_line, x_offsetter) + |> offset(x_offsetter.(line)) end - def reduce_lines(output, [line | lines]) do + def reduce_lines(output, [line | lines], x_offsetter) do output |> leading(line) - |> reduce_parts(line, Tj, nil) - |> reduce_lines(lines) + |> reset_offset(x_offsetter.(line)) + |> reduce_parts(line, Tj, nil, x_offsetter) + |> offset(x_offsetter.(line)) + |> reduce_lines(lines, x_offsetter) end - defp reduce_parts(output, %Line{parts: []}, _operator, :first_line) do + defp offset(output, offset) do + Output.td(output, {-offset, 0}) + end + + defp reset_offset(output, offset) do + Output.td(output, {offset, 0}) + end + + defp reduce_parts(output, %Line{parts: []}, _operator, :first_line, _x_offsetter) do output end - defp reduce_parts(output, %Line{parts: [part]}, _operator, :first_line) do + defp reduce_parts(output, %Line{parts: [part]} = line, _operator, :first_line, x_offsetter) do output |> Output.add_part(part, Tj) - |> underline(part) + |> underline(part, x_offsetter.(line)) end - defp reduce_parts(output, %Line{parts: []}, _operator, nil) do + defp reduce_parts(output, %Line{parts: []}, _operator, nil, _x_offsetter) do output |> Output.add(%Tj{font: output.font, text: ""}) |> Output.add(%TStar{}) end - defp reduce_parts(output, %Line{parts: [part]}, _operator, nil) do + defp reduce_parts(output, %Line{parts: [part]} = line, _operator, nil, x_offsetter) do output |> Output.add_part(part, Tj) |> Output.add(%TStar{}) - |> underline(part) + |> underline(part, x_offsetter.(line)) end - defp reduce_parts(output, %Line{parts: [part | parts]} = line, operator, line_kind) do + defp reduce_parts( + output, + %Line{parts: [part | parts]} = line, + operator, + line_kind, + x_offsetter + ) do output |> Output.add_part(part, operator) - |> underline(part) - |> reduce_parts(%{line | parts: parts}, Tj, line_kind) + |> underline(part, x_offsetter.(line)) + |> reduce_parts(%{line | parts: parts}, Tj, line_kind, x_offsetter) end - defp underline(output, %Line.Part{underline: nil}), do: output + defp underline(output, %Line.Part{underline: nil}, _line_x_offset), do: output - defp underline(output, part) do + defp underline(output, part, line_x_offset) do Map.update!(output, :drawings, fn drawings -> - [underline_path(output, part) | drawings] + [underline_path(output, part, line_x_offset) | drawings] end) end - defp underline_path(output, part) do + defp underline_path(output, part, line_x_offset) do {x, y} = output.position {offset_x, offset_y} = part.left_offset - x = x + offset_x + x = x + offset_x - line_x_offset y = y + offset_y - 2 Path.new() @@ -91,43 +109,6 @@ defmodule Mudbrick.TextBlock.Output do end end - defmodule RightAlign do - @moduledoc false - - alias Mudbrick.TextBlock.Output - - def reduce_lines(output, [line], measure) do - output - |> Output.end_block() - |> reduce_parts(line) - |> measure.(line, 1) - |> Output.start_block() - end - - def reduce_lines(output, [line | lines], measure) do - output - |> Output.end_block() - |> reduce_parts(line) - |> measure.(line, length(lines) + 1) - |> Output.start_block() - |> reduce_lines(lines, measure) - end - - defp reduce_parts(output, %Line{parts: []}) do - output - end - - defp reduce_parts(output, %Line{parts: [part]}) do - Output.add_part(output, part, Tj) - end - - defp reduce_parts(output, %Line{parts: [part | parts]} = line) do - output - |> Output.add_part(part, Tj) - |> reduce_parts(%{line | parts: parts}) - end - end - defp drawings(output) do Map.update!(output, :operations, fn ops -> for drawing <- output.drawings, reduce: ops do @@ -139,10 +120,9 @@ defmodule Mudbrick.TextBlock.Output do def from( %Mudbrick.TextBlock{ - align: :left, font: font, font_size: font_size, - position: position = {x, y} + position: position } = tb ) do tl = %TL{leading: tb.leading} @@ -150,8 +130,11 @@ defmodule Mudbrick.TextBlock.Output do %__MODULE__{position: position, font: font, font_size: font_size} |> end_block() - |> LeftAlign.reduce_lines(tb.lines) - |> add(%Td{tx: x, ty: y}) + |> Align.reduce_lines( + tb.lines, + if(tb.align == :left, do: fn _ -> 0 end, else: &Line.width/1) + ) + |> td(position) |> add(tl) |> add(tf) |> start_block() @@ -161,28 +144,8 @@ defmodule Mudbrick.TextBlock.Output do |> Map.update!(:operations, &Enum.reverse/1) end - def from( - %Mudbrick.TextBlock{ - align: :right, - font: font, - font_size: font_size - } = tb - ) do - tf = %Tf{font: font, size: font_size} - - %__MODULE__{font: font, font_size: font_size} - |> RightAlign.reduce_lines(tb.lines, fn output, line, line_number -> - right_offset(output, tb, line, line_number) - end) - |> add(%TL{leading: tb.leading}) - |> add(tf) - |> deduplicate(tf) - |> Map.update!(:operations, &Enum.reverse/1) - end - - def add(%__MODULE__{} = output, op) do - Map.update!(output, :operations, &[op | &1]) - end + def td(output, {0, 0}), do: output + def td(output, {x, y}), do: add(output, %Td{tx: x, ty: y}) def add_part(output, part, operator) do output @@ -230,6 +193,10 @@ defmodule Mudbrick.TextBlock.Output do }) end + def add(%__MODULE__{} = output, op) do + Map.update!(output, :operations, &[op | &1]) + end + defp deduplicate(output, initial_operator) do Map.update!(output, :operations, fn ops -> ops diff --git a/test/mudbrick/text_block_test.exs b/test/mudbrick/text_block_test.exs index 97612c8..fd1e770 100644 --- a/test/mudbrick/text_block_test.exs +++ b/test/mudbrick/text_block_test.exs @@ -389,33 +389,36 @@ defmodule Mudbrick.TextBlockTest do describe "right-aligned" do test "newlines become Tjs with offsets" do assert [ + "BT", "/F1 10 Tf", "12.0 TL", - "BT", - "384.82 500.0 Td", + "400 500 Td", + "-15.180000000000001 0 Td", "0 0 0 rg", "<00A5> Tj", "1 0 0 rg", "<00A500A5> Tj", - "ET", - "BT", - "379.42 488.0 Td", + "15.180000000000001 0 Td", + "-20.580000000000002 0 Td", + "T*", "0 0 0 rg", "<013801380138> Tj", - "ET", - "BT", - "314.3 476.0 Td", + "20.580000000000002 0 Td", + "-85.7 0 Td", + "T*", "<008800550088> Tj", "0 1 0 rg", "<0088005500880055008800550088> Tj", - "ET", - "BT", - "400.0 464.0 Td", - "ET", - "BT", - "390.74 452.0 Td", + "85.7 0 Td", + "-0.0 0 Td", + "T*", + "() Tj", + "0.0 0 Td", + "-9.26 0 Td", + "T*", "0 0 0 rg", "<00D500D9> Tj", + "9.26 0 Td", "ET" ] = output(fn %{fonts: fonts} -> @@ -452,10 +455,11 @@ defmodule Mudbrick.TextBlockTest do test "inline font change is written with Tfs" do assert [ + "BT", "/F1 10 Tf", "12.0 TL", - "BT", - "225.67999999999998 500.0 Td", + "400 500 Td", + "-174.32000000000002 0 Td", "0 0 0 rg", "<011D00D500D9011601B700D9011601B7> Tj", "/F2 10 Tf", @@ -465,6 +469,7 @@ defmodule Mudbrick.TextBlockTest do "/F3 10 Tf", "<015A01050109015201F00109015201F000FF014B00C30125011B011E01090125> Tj", "/F1 10 Tf", + "174.32000000000002 0 Td", "ET" ] = output(fn %{fonts: fonts} -> diff --git a/test/text_test.exs b/test/text_test.exs index 6e3e31b..e8d6c26 100644 --- a/test/text_test.exs +++ b/test/text_test.exs @@ -28,12 +28,14 @@ defmodule Mudbrick.TextTest do test "parts inherit fonts" do assert [ + "BT", "/F1 14 Tf", "16.8 TL", - "BT", - "171.65 700.0 Td", + "200 700 Td", + "-28.35 0 Td", "1 0 0 rg", "<00110055017401B7> Tj", + "28.35 0 Td", "ET" ] = new( @@ -73,7 +75,6 @@ defmodule Mudbrick.TextTest do "BT", "/F1 10 Tf", "14 TL", - "0 0 Td", "0 0 0 rg", "<00D500C000ED00ED00FC01B7011D00D500C0010F00C0> Tj", "ET" @@ -123,7 +124,6 @@ defmodule Mudbrick.TextTest do BT /F1 10 Tf 12.0 TL - 0 0 Td 1.0 0.0 0.0 rg <011D00D500D9011601B700D9011601B700A500ED00ED01B7> Tj <010F00C000BB> Tj @@ -153,7 +153,6 @@ defmodule Mudbrick.TextTest do BT /F1 10 Tf 12.0 TL - 0 0 Td 0 0 0 rg <00B400ED00A500B500EA01B700A500F400BB01B7> Tj 1.0 0.0 0.0 rg