Skip to content

Commit

Permalink
Attempt to fix leading
Browse files Browse the repository at this point in the history
Needed to handle chosen opts for a line separately to those merged into
defaults.
  • Loading branch information
camelpunch committed Nov 10, 2024
1 parent 2c1a5da commit ddb933d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 23 deletions.
34 changes: 23 additions & 11 deletions lib/mudbrick/text_block.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ defmodule Mudbrick.TextBlock do
%{tb | lines: lines}
end

defp write_lines(tb, text, opts) do
defp write_lines(tb, text, chosen_opts) do
line_texts = String.split(text, "\n")

text_block_opts = [
Expand All @@ -115,36 +115,43 @@ defmodule Mudbrick.TextBlock do
leading: tb.leading
]

opts =
merged_opts =
Keyword.merge(
text_block_opts,
opts,
chosen_opts,
&prefer_lhs_over_nil/3
)

Map.update!(tb, :lines, fn
[] ->
add_texts([], line_texts, opts, text_block_opts)
add_texts([], line_texts, merged_opts, text_block_opts)

existing_lines ->
case line_texts do
# \n at beginning of new line
["" | new_line_texts] ->
existing_lines
|> add_texts(new_line_texts, opts, text_block_opts)
|> add_texts(new_line_texts, merged_opts, text_block_opts)

# didn't start with \n, so first part belongs to previous line
[first_new_line_text | new_line_texts] ->
existing_lines
|> update_previous_line(first_new_line_text, opts)
|> add_texts(new_line_texts, opts, text_block_opts)
# Update previous line with chosen opts, to allow logic around
# choices.
|> update_previous_line(first_new_line_text, merged_opts, chosen_opts)
|> add_texts(new_line_texts, merged_opts, text_block_opts)
end
end)
end

defp update_previous_line([previous_line | existing_lines], first_new_line_text, opts) do
defp update_previous_line(
[previous_line | existing_lines],
first_new_line_text,
merged_opts,
opts
) do
[
Line.append(previous_line, first_new_line_text, opts)
Line.append(previous_line, first_new_line_text, merged_opts, opts)
| existing_lines
]
end
Expand All @@ -160,6 +167,11 @@ defmodule Mudbrick.TextBlock do
end
end

defp prefer_lhs_over_nil(_key, lhs, nil), do: lhs
defp prefer_lhs_over_nil(_key, _lhs, rhs), do: rhs
defp prefer_lhs_over_nil(_key, lhs, nil) do
lhs
end

defp prefer_lhs_over_nil(_key, _lhs, rhs) do
rhs
end
end
9 changes: 4 additions & 5 deletions lib/mudbrick/text_block/line.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,11 @@ defmodule Mudbrick.TextBlock.Line do
struct(__MODULE__, Keyword.put(opts, :parts, [Part.new(text, opts)]))
end

def append(line, text, opts) do
line = Map.update!(line, :parts, &[Part.new(text, opts) | &1])
new_leading = Keyword.fetch!(opts, :leading)
def append(line, text, merged_opts, chosen_opts) do
line = Map.update!(line, :parts, &[Part.new(text, merged_opts) | &1])

if new_leading > line.leading do
Map.put(line, :leading, new_leading)
if chosen_opts[:leading] do
Map.put(line, :leading, chosen_opts[:leading])
else
line
end
Expand Down
10 changes: 3 additions & 7 deletions lib/mudbrick/text_block/output.ex
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ defmodule Mudbrick.TextBlock.Output do
position: position = {x, y}
} = tb
) do
tl = %TL{leading: leading(tb)}
tl = %TL{leading: tb.leading}
tf = %Tf{font: font, size: font_size}

%__MODULE__{position: position, font: font, font_size: font_size}
Expand Down Expand Up @@ -175,7 +175,7 @@ defmodule Mudbrick.TextBlock.Output do
|> RightAlign.reduce_lines(tb.lines, fn output, line, line_number ->
right_offset(output, tb, line, line_number)
end)
|> add(%TL{leading: leading(tb)})
|> add(%TL{leading: tb.leading})
|> add(tf)
|> deduplicate(tf)
|> Map.update!(:operations, &Enum.reverse/1)
Expand Down Expand Up @@ -227,7 +227,7 @@ defmodule Mudbrick.TextBlock.Output do

add(output, %Td{
tx: x - Line.width(line),
ty: y - leading(tb) * n
ty: y - tb.leading * n
})
end

Expand Down Expand Up @@ -263,8 +263,4 @@ defmodule Mudbrick.TextBlock.Output do
defp remove(output, operation) do
Map.update!(output, :operations, &List.delete(&1, operation))
end

defp leading(tb) do
tb.leading || tb.font_size * 1.2
end
end
48 changes: 48 additions & 0 deletions test/mudbrick/text_block_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,54 @@ defmodule Mudbrick.TextBlockTest do
end

describe "leading" do
test "is set correctly for lines composed with writes" do
output(fn %{fonts: fonts} ->
heading_leading = 70
overlap_leading = 20
# 120% of default 80 font size
expected_final_leading = 96.0

text_block =
TextBlock.new(
align: :left,
font: fonts.regular,
font_size: 80,
position: {0, 500}
)
|> TextBlock.write("Warning!\n", font_size: 140, leading: heading_leading)
|> TextBlock.write("Leading ", leading: overlap_leading)
|> TextBlock.write("changes")
|> TextBlock.write("\nthis overlaps")

assert [
^expected_final_leading,
^overlap_leading,
^heading_leading
] =
Enum.map(text_block.lines, & &1.leading)

text_block
end)
end

test "is set correctly for linebreaks inside writes" do
output(fn %{fonts: fonts} ->
text_block =
TextBlock.new(
align: :left,
font: fonts.regular,
font_size: 80,
position: {0, 500}
)
|> TextBlock.write("Warning!\n", font_size: 140, leading: 20)
|> TextBlock.write("Steps under\nconstruction", leading: 70)

assert [70, 70, 20] = Enum.map(text_block.lines, & &1.leading)

text_block
end)
end

test "can be set per line" do
block =
TextBlock.new(font_size: 10)
Expand Down

0 comments on commit ddb933d

Please sign in to comment.