1
1
defmodule Mudbrick.TextBlock.Output do
2
2
@ moduledoc false
3
3
4
- defstruct font: nil , font_size: nil , operations: [ ]
4
+ defstruct position: nil ,
5
+ font: nil ,
6
+ font_size: nil ,
7
+ operations: [ ] ,
8
+ drawings: [ ]
5
9
6
10
alias Mudbrick.ContentStream . { BT , ET }
7
11
alias Mudbrick.ContentStream.Rg
8
12
alias Mudbrick.ContentStream.Td
9
13
alias Mudbrick.ContentStream.Tf
10
14
alias Mudbrick.ContentStream . { Apostrophe , Tj }
11
15
alias Mudbrick.ContentStream.TL
16
+ alias Mudbrick.Path
12
17
alias Mudbrick.TextBlock.Line
13
18
14
19
defmodule LeftAlign do
15
20
@ moduledoc false
16
21
17
22
alias Mudbrick.TextBlock.Output
18
23
19
- defp leading ( output , % Line { leading: nil } ) do
20
- output
21
- end
22
-
23
24
defp leading ( output , line ) do
24
- Output . add ( output , % TL { leading: line . leading } )
25
+ output
26
+ |> Output . add ( % TL { leading: line . leading } )
25
27
end
26
28
27
29
def reduce_lines ( output , [ line ] ) do
@@ -42,7 +44,9 @@ defmodule Mudbrick.TextBlock.Output do
42
44
end
43
45
44
46
defp reduce_parts ( output , % Line { parts: [ part ] } , _operator , :first_line ) do
45
- Output . add_part ( output , part , Tj )
47
+ output
48
+ |> Output . add_part ( part , Tj )
49
+ |> underline ( part )
46
50
end
47
51
48
52
defp reduce_parts ( output , % Line { parts: [ ] } , _operator , nil ) do
@@ -52,13 +56,40 @@ defmodule Mudbrick.TextBlock.Output do
52
56
53
57
defp reduce_parts ( output , % Line { parts: [ part ] } , _operator , nil ) do
54
58
Output . add_part ( output , part , Apostrophe )
59
+ |> underline ( part )
55
60
end
56
61
57
62
defp reduce_parts ( output , % Line { parts: [ part | parts ] } = line , operator , line_kind ) do
58
63
output
59
64
|> Output . add_part ( part , operator )
65
+ |> underline ( part )
60
66
|> reduce_parts ( % { line | parts: parts } , Tj , line_kind )
61
67
end
68
+
69
+ defp underline ( output , part ) do
70
+ output
71
+ |> then ( fn output ->
72
+ if part . underline do
73
+ { x , y } = output . position
74
+ { offset_x , offset_y } = part . left_offset
75
+
76
+ x = x + offset_x
77
+ y = y + offset_y - 2
78
+
79
+ path_output =
80
+ Path . new ( )
81
+ |> Path . move ( to: { x , y } )
82
+ |> Path . line ( to: { x + Line.Part . width ( part ) , y } )
83
+ |> Path.Output . from ( )
84
+
85
+ Map . update! ( output , :drawings , fn drawings ->
86
+ [ path_output | drawings ]
87
+ end )
88
+ else
89
+ output
90
+ end
91
+ end )
92
+ end
62
93
end
63
94
64
95
defmodule RightAlign do
@@ -98,26 +129,37 @@ defmodule Mudbrick.TextBlock.Output do
98
129
end
99
130
end
100
131
132
+ defp drawings ( output ) do
133
+ Map . update! ( output , :operations , fn ops ->
134
+ for drawing <- output . drawings , reduce: ops do
135
+ ops ->
136
+ Enum . reverse ( drawing . operations ) ++ ops
137
+ end
138
+ end )
139
+ end
140
+
101
141
def from (
102
142
% Mudbrick.TextBlock {
103
143
align: :left ,
104
144
font: font ,
105
145
font_size: font_size ,
106
- position: { x , y }
146
+ position: position = { x , y }
107
147
} = tb
108
148
) do
109
149
tl = % TL { leading: leading ( tb ) }
110
150
tf = % Tf { font: font , size: font_size }
111
151
112
- % __MODULE__ { font: font , font_size: font_size }
152
+ % __MODULE__ { position: position , font: font , font_size: font_size }
113
153
|> end_block ( )
114
154
|> LeftAlign . reduce_lines ( tb . lines )
115
155
|> add ( % Td { tx: x , ty: y } )
116
156
|> add ( tl )
117
157
|> add ( tf )
118
158
|> start_block ( )
159
+ |> drawings ( )
119
160
|> deduplicate ( tl )
120
161
|> deduplicate ( tf )
162
+ |> Map . update! ( :operations , & Enum . reverse / 1 )
121
163
end
122
164
123
165
def from (
@@ -136,6 +178,7 @@ defmodule Mudbrick.TextBlock.Output do
136
178
|> add ( % TL { leading: leading ( tb ) } )
137
179
|> add ( tf )
138
180
|> deduplicate ( tf )
181
+ |> Map . update! ( :operations , & Enum . reverse / 1 )
139
182
end
140
183
141
184
def add ( % __MODULE__ { } = output , op ) do
@@ -145,21 +188,17 @@ defmodule Mudbrick.TextBlock.Output do
145
188
def add_part ( output , part , operator ) do
146
189
output
147
190
|> with_font (
148
- struct! ( operator , font: part . font || output . font , text: part . text ) ,
191
+ struct! ( operator , font: part . font , text: part . text ) ,
149
192
part
150
193
)
151
194
|> colour ( part . colour )
152
195
end
153
196
154
197
def with_font ( output , op , part ) do
155
- if part . font in [ nil , output . font ] and part . font_size == nil do
156
- add ( output , op )
157
- else
158
- output
159
- |> add ( % Tf { font: output . font , size: output . font_size } )
160
- |> add ( op )
161
- |> add ( % Tf { font: part . font || output . font , size: part . font_size || output . font_size } )
162
- end
198
+ output
199
+ |> add ( % Tf { font: output . font , size: output . font_size } )
200
+ |> add ( op )
201
+ |> add ( % Tf { font: part . font , size: part . font_size } )
163
202
end
164
203
165
204
def colour ( output , { r , g , b } ) do
0 commit comments