-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrich_features_test.go
More file actions
232 lines (199 loc) · 6.07 KB
/
Copy pathrich_features_test.go
File metadata and controls
232 lines (199 loc) · 6.07 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package wordwrap
import (
"image"
"image/color"
"testing"
"golang.org/x/image/math/fixed"
)
// TestAdvancedRichFeatures tests extensive use cases including linear style changes,
// groups, containers, min size, and reset functionality.
func TestAdvancedRichFeatures(t *testing.T) {
// Setup
fontFace := FontFace16DPI180ForTest(t)
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
// largeFont := ... (Use same font for now, just checking logic)
t.Run("Linear Style Changes", func(t *testing.T) {
args := []interface{}{
fontFace,
"Plain",
Color(red),
"Red",
Color(blue),
"Blue",
Reset(),
"PlainAgain",
}
contents, _, _, _, _, _ := ProcessRichArgs(args...)
if len(contents) != 4 {
t.Fatalf("Expected 4 content blocks, got %d", len(contents))
}
// Check Plain
if c0 := contents[0]; c0.text != "Plain" || (c0.style != nil && c0.style.FontDrawerSrc != nil) {
t.Errorf("Content[0] should be plain, got text %q style %v", c0.text, c0.style)
}
// Check Red
if c1 := contents[1]; c1.text != "Red" {
t.Errorf("Content[1] text mismatch")
} else if c1.style == nil || c1.style.FontDrawerSrc == nil {
t.Errorf("Content[1] missing style")
} else {
// Verify color (FontDrawerSrc is uniform)
u, ok := c1.style.FontDrawerSrc.(*image.Uniform)
if !ok || u.C != red {
t.Errorf("Content[1] color mismatch")
}
}
// Check Blue
if c2 := contents[2]; c2.text != "Blue" {
t.Errorf("Content[2] text mismatch")
} else {
u, ok := c2.style.FontDrawerSrc.(*image.Uniform)
if !ok || u.C != blue {
t.Errorf("Content[2] color mismatch, got %v", u.C)
}
}
// Check Reset
if c3 := contents[3]; c3.text != "PlainAgain" {
t.Errorf("Content[3] text mismatch")
} else {
if c3.style != nil && c3.style.FontDrawerSrc != nil {
t.Errorf("Content[3] should be reset to plain, got style %v", c3.style)
}
}
})
t.Run("Group Scoping with Reset", func(t *testing.T) {
args := []interface{}{
Group{
Args: []interface{}{
Color(red),
"Red",
Reset(), // Reset style state within the group scope.
"PlainInGroup",
},
},
"PlainOutside",
}
contents, _, _, _, _, _ := ProcessRichArgs(args...)
if len(contents) != 3 {
t.Fatalf("Expected 3 content blocks, got %d", len(contents))
}
if c1 := contents[1]; c1.text != "PlainInGroup" {
t.Errorf("Content[1] mismatch")
} else if c1.style != nil && c1.style.FontDrawerSrc != nil {
t.Errorf("Reset inside group did not clear style")
}
if c2 := contents[2]; c2.text != "PlainOutside" {
t.Errorf("Content[2] mismatch")
} else if c2.style != nil && c2.style.FontDrawerSrc != nil {
t.Errorf("Group scope leaked style or reset logic failed")
}
})
t.Run("MinSize Constraints", func(t *testing.T) {
// Test MinWidth
width := 100
args := []interface{}{
fontFace,
MinWidth(width),
"Short",
}
contents, _, _, _, _, _ := ProcessRichArgs(args...)
c := contents[0]
if c.style == nil || c.style.MinSize.X != fixed.I(width) {
t.Errorf("Style MinSize mismatch")
}
// We can't verify layout without running Wrapper.
// Content has decorators.
// We rely on integration test or inspect decorators loop (hard).
// Let's run basic layout.
wrapper := NewRichWrapper(args...)
lines, _, err := wrapper.TextToRect(image.Rect(0, 0, 200, 200))
if err != nil {
t.Fatalf("Layout error: %v", err)
}
// The line should be at least width pixels long?
// "Short" is definitely < 100px.
// AdvanceRect of the box should be max(textAdv, 100).
if len(lines) == 0 {
t.Fatal("No lines")
}
// Calculate line width used
// lines[0].Size().Max.X?
// Or sum of boxes AdvanceRect?
boxes := lines[0].Boxes()
totalAdv := fixed.Int26_6(0)
for _, b := range boxes {
totalAdv += b.AdvanceRect()
}
// MinWidth is 100 * 64
minAdv := fixed.I(100)
if totalAdv < minAdv {
t.Errorf("Total advance %d < specified min width %d", totalAdv, minAdv)
}
})
t.Run("Container Isolation", func(t *testing.T) {
// Container with Margin.
// Children should not inherit margin.
margin := fixed.R(10, 0, 0, 0)
args := []interface{}{
fontFace,
Container(
Margin(margin),
"Child",
),
}
contents, _, _, _, _, _ := ProcessRichArgs(args...)
// 0: fontFace, 1: Container
if len(contents) != 1 { // fontFace does not create a content block
t.Fatalf("Expected 1 content (container), got %d", len(contents))
}
// The container itself is wrapped.
// Testing structure is hard via contents inspection.
// We trust layout test.
wrapper := NewRichWrapper(args...)
lines, _, err := wrapper.TextToRect(image.Rect(0, 0, 200, 200))
if err != nil {
t.Fatalf("Layout error: %v", err)
}
if len(lines) == 0 {
t.Error("Expected lines")
}
// Spacemap integration is verified in consumers.
// Check that line length includes margin.
// "Child" width + 10 margin.
// Also check that if we add Color to container, CHILD gets it.
// But Margin is NOT applied to Child box twice?
// Actually "Margin" wraps "Container".
// Container wraps Children.
// Children do NOT get Margin decorator.
// Let's test checking Color.
argsColor := []interface{}{
fontFace,
Container(
Color(blue),
"BlueChild",
),
}
contentsC, _, _, _, _, _ := ProcessRichArgs(argsColor...)
// contentsC[0] is fontFace (Content?) No, fontFace does not create Content if type is font.Face?
// ProcessRichArgs loop: case font.Face: sets state. No content added.
// So contentsC length depends on if fontFace produces content.
// rich.go: case font.Face: s.currentFont = v. No append.
// So contents length is still 1 (Container).
container := contentsC[0]
if len(container.children) != 1 {
t.Errorf("Expected 1 child in container, got %d", len(container.children))
} else {
child := container.children[0]
if child.text != "BlueChild" {
t.Errorf("Child text mismatch")
}
// Child inherits Font/Color from the container.
// Verify
u, ok := child.style.FontDrawerSrc.(*image.Uniform)
if !ok || u.C != blue {
t.Errorf("Child did not inherit color")
}
}
})
}