cvdl-ts 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AnyLayout.d.ts +2 -11
- package/dist/AnyLayout.js +16 -88
- package/dist/DataSchema.d.ts +37 -25
- package/dist/DataSchema.js +79 -4
- package/dist/Elem.d.ts +73 -0
- package/dist/Elem.js +302 -0
- package/dist/FileStorage.d.ts +2 -2
- package/dist/FileStorage.js +25 -1
- package/dist/Font.d.ts +10 -9
- package/dist/Font.js +45 -44
- package/dist/Layout.d.ts +48 -107
- package/dist/Layout.js +361 -572
- package/dist/LayoutSchema.d.ts +7 -7
- package/dist/LayoutSchema.js +30 -7
- package/dist/LocalStorage.d.ts +2 -2
- package/dist/LocalStorage.js +29 -6
- package/dist/OldLayout.d.ts +0 -0
- package/dist/OldLayout.js +691 -0
- package/dist/PdfLayout.d.ts +3 -4
- package/dist/PdfLayout.js +30 -14
- package/dist/RemoteStorage.d.ts +2 -2
- package/dist/RemoteStorage.js +0 -2
- package/dist/Resume.js +0 -1
- package/dist/Row.d.ts +29 -0
- package/dist/Row.js +145 -0
- package/dist/Stack.d.ts +23 -0
- package/dist/Stack.js +85 -0
- package/dist/Storage.d.ts +2 -2
- package/dist/Utils.d.ts +4 -0
- package/dist/Utils.js +7 -0
- package/package.json +9 -3
package/dist/Layout.js
CHANGED
|
@@ -23,495 +23,407 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
27
|
-
const Margin = __importStar(require("./Margin"));
|
|
28
|
-
const Alignment = __importStar(require("./Alignment"));
|
|
26
|
+
exports.ColorMap = exports.computeTextboxPositions = exports.computeBoxes = exports.breakLines = exports.fillFonts = exports.normalize = exports.scaleWidth = exports.boundWidth = exports.instantiate = exports.isInstantiated = exports.totalElementsWidth = exports.withWidth = exports.withAlignment = exports.withMargin = exports.fonts = exports.isRef = exports.isFill = exports.isContainer = exports.toJson = exports.tag_ = exports.type_ = exports.fromJson = exports.empty = exports.default_ = void 0;
|
|
29
27
|
const Width = __importStar(require("./Width"));
|
|
30
|
-
const
|
|
31
|
-
const Resume_1 = require("./Resume");
|
|
28
|
+
const Font = __importStar(require("./Font"));
|
|
32
29
|
const Box_1 = require("./Box");
|
|
33
|
-
const AnyLayout_1 = require("./AnyLayout");
|
|
34
30
|
const Point_1 = require("./Point");
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
const Stack = __importStar(require("./Stack"));
|
|
32
|
+
const Row = __importStar(require("./Row"));
|
|
33
|
+
const Elem = __importStar(require("./Elem"));
|
|
34
|
+
function default_(tag) {
|
|
35
|
+
switch (tag) {
|
|
36
|
+
case "Stack": return Stack.default_();
|
|
37
|
+
case "FlexRow": return Row.default_();
|
|
38
|
+
case "FrozenRow": return Row.withFrozen(Row.default_(), true);
|
|
39
|
+
case "Text": return Elem.default_();
|
|
40
|
+
case "Ref": return Elem.asRef(Elem.default_());
|
|
39
41
|
}
|
|
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
|
-
inner.background_color = (_a = json[key].background_color) !== null && _a !== void 0 ? _a : "Transparent";
|
|
88
|
-
return new SectionLayout(inner);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
throw new Error(`Invalid layout ${key}`);
|
|
92
|
-
}
|
|
93
|
-
toJson() {
|
|
94
|
-
switch (this.type_()) {
|
|
95
|
-
case "Stack":
|
|
96
|
-
case "Row": {
|
|
97
|
-
const container = this.inner;
|
|
98
|
-
return {
|
|
99
|
-
[this.tag_()]: {
|
|
100
|
-
elements: container.elements.map(e => e.toJson()),
|
|
101
|
-
margin: container.margin,
|
|
102
|
-
alignment: container.alignment,
|
|
103
|
-
width: Width.toJson(container.width),
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
case "Elem": {
|
|
108
|
-
const elem = this.inner;
|
|
109
|
-
return {
|
|
110
|
-
[this.tag_()]: {
|
|
111
|
-
item: elem.item,
|
|
112
|
-
margin: elem.margin,
|
|
113
|
-
alignment: elem.alignment,
|
|
114
|
-
width: Width.toJson(elem.width),
|
|
115
|
-
text_width: Width.toJson(elem.text_width),
|
|
116
|
-
font: elem.font.toJson(),
|
|
117
|
-
url: elem.url,
|
|
118
|
-
background_color: elem.background_color,
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
42
|
+
}
|
|
43
|
+
exports.default_ = default_;
|
|
44
|
+
function empty() {
|
|
45
|
+
return default_("Stack");
|
|
46
|
+
}
|
|
47
|
+
exports.empty = empty;
|
|
48
|
+
function fromJson(json) {
|
|
49
|
+
var _a;
|
|
50
|
+
const key = Object.keys(json)[0];
|
|
51
|
+
switch (key) {
|
|
52
|
+
case 'Stack':
|
|
53
|
+
case 'FlexRow':
|
|
54
|
+
case 'FrozenRow': {
|
|
55
|
+
const container = default_(key);
|
|
56
|
+
container.elements = json[key].elements.map((element) => fromJson(element));
|
|
57
|
+
container.margin = json[key].margin;
|
|
58
|
+
container.alignment = json[key].alignment;
|
|
59
|
+
container.width = Width.fromJson(json[key].width);
|
|
60
|
+
return container;
|
|
61
|
+
}
|
|
62
|
+
case 'Ref':
|
|
63
|
+
case 'Text': {
|
|
64
|
+
const inner = default_(key);
|
|
65
|
+
inner.item = json[key].item;
|
|
66
|
+
inner.margin = json[key].margin;
|
|
67
|
+
inner.alignment = json[key].alignment;
|
|
68
|
+
inner.width = Width.fromJson(json[key].width);
|
|
69
|
+
inner.text_width = Width.fromJson(json[key].text_width);
|
|
70
|
+
inner.font = Font.fromJson(json[key].font);
|
|
71
|
+
inner.url = json[key].url;
|
|
72
|
+
inner.background_color = (_a = json[key].background_color) !== null && _a !== void 0 ? _a : "Transparent";
|
|
73
|
+
return inner;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`Invalid layout ${key}`);
|
|
77
|
+
}
|
|
78
|
+
exports.fromJson = fromJson;
|
|
79
|
+
function type_(l) {
|
|
80
|
+
return l.tag;
|
|
81
|
+
}
|
|
82
|
+
exports.type_ = type_;
|
|
83
|
+
function tag_(l) {
|
|
84
|
+
switch (l.tag) {
|
|
85
|
+
case "Stack": return "Stack";
|
|
86
|
+
case "Row": {
|
|
87
|
+
const row = l;
|
|
88
|
+
return row.is_frozen ? "FrozenRow" : "FlexRow";
|
|
122
89
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
is_container() {
|
|
128
|
-
return this.inner.tag === "Stack" || this.inner.tag === "Row";
|
|
129
|
-
}
|
|
130
|
-
is_fill() {
|
|
131
|
-
switch (this.type_()) {
|
|
132
|
-
case "Stack":
|
|
133
|
-
return this.inner.is_fill && this.inner.elements.map(e => e.is_fill()).reduce((a, b) => a && b, true);
|
|
134
|
-
case "Row":
|
|
135
|
-
return this.inner.is_fill && this.inner.elements.map(e => e.is_fill()).reduce((a, b) => a && b, true);
|
|
136
|
-
case "Elem":
|
|
137
|
-
return this.inner.is_fill;
|
|
90
|
+
case "Elem": {
|
|
91
|
+
const elem = l;
|
|
92
|
+
return elem.is_ref ? "Ref" : "Text";
|
|
138
93
|
}
|
|
139
94
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
95
|
+
}
|
|
96
|
+
exports.tag_ = tag_;
|
|
97
|
+
function toJson(l) {
|
|
98
|
+
switch (l.tag) {
|
|
99
|
+
case "Stack":
|
|
100
|
+
case "Row": {
|
|
101
|
+
const container = l;
|
|
102
|
+
return {
|
|
103
|
+
[tag_(container)]: {
|
|
104
|
+
elements: container.elements.map(e => toJson(e)),
|
|
105
|
+
margin: container.margin,
|
|
106
|
+
alignment: container.alignment,
|
|
107
|
+
width: Width.toJson(container.width),
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
case "Elem": {
|
|
112
|
+
const elem = l;
|
|
113
|
+
return {
|
|
114
|
+
[tag_(elem)]: {
|
|
115
|
+
item: elem.item,
|
|
116
|
+
margin: elem.margin,
|
|
117
|
+
alignment: elem.alignment,
|
|
118
|
+
width: Width.toJson(elem.width),
|
|
119
|
+
text_width: Width.toJson(elem.text_width),
|
|
120
|
+
font: elem.font,
|
|
121
|
+
url: elem.url,
|
|
122
|
+
background_color: elem.background_color,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
154
125
|
}
|
|
155
126
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
127
|
+
}
|
|
128
|
+
exports.toJson = toJson;
|
|
129
|
+
function isContainer(l) {
|
|
130
|
+
return l.tag === "Stack" || l.tag === "Row";
|
|
131
|
+
}
|
|
132
|
+
exports.isContainer = isContainer;
|
|
133
|
+
function isFill(l) {
|
|
134
|
+
switch (l.tag) {
|
|
135
|
+
case "Stack":
|
|
136
|
+
return l.is_fill && l.elements.map(e => isFill(e)).reduce((a, b) => a && b, true);
|
|
137
|
+
case "Row":
|
|
138
|
+
return l.is_fill && l.elements.map(e => isFill(e)).reduce((a, b) => a && b, true);
|
|
139
|
+
case "Elem":
|
|
140
|
+
return l.is_fill;
|
|
165
141
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
142
|
+
}
|
|
143
|
+
exports.isFill = isFill;
|
|
144
|
+
function isRef(l) {
|
|
145
|
+
return l.tag === "Elem" && l.is_ref;
|
|
146
|
+
}
|
|
147
|
+
exports.isRef = isRef;
|
|
148
|
+
function fonts(l) {
|
|
149
|
+
switch (l.tag) {
|
|
150
|
+
case "Stack":
|
|
151
|
+
return l.elements.map(e => fonts(e)).reduce((a, b) => a.concat(b), []);
|
|
152
|
+
case "Row":
|
|
153
|
+
return l.elements.map(e => fonts(e)).reduce((a, b) => a.concat(b), []);
|
|
154
|
+
case "Elem":
|
|
155
|
+
return [l.font];
|
|
169
156
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
157
|
+
}
|
|
158
|
+
exports.fonts = fonts;
|
|
159
|
+
function withMargin(l, margin) {
|
|
160
|
+
switch (l.tag) {
|
|
161
|
+
case "Stack":
|
|
162
|
+
return Stack.withMargin(l, margin);
|
|
163
|
+
case "Row":
|
|
164
|
+
return Row.withMargin(l, margin);
|
|
165
|
+
case "Elem":
|
|
166
|
+
return Elem.withMargin(l, margin);
|
|
173
167
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
168
|
+
}
|
|
169
|
+
exports.withMargin = withMargin;
|
|
170
|
+
function withAlignment(l, alignment) {
|
|
171
|
+
switch (l.tag) {
|
|
172
|
+
case "Stack":
|
|
173
|
+
return Stack.withAlignment(l, alignment);
|
|
174
|
+
case "Row":
|
|
175
|
+
return Row.withAlignment(l, alignment);
|
|
176
|
+
case "Elem":
|
|
177
|
+
return Elem.withAlignment(l, alignment);
|
|
177
178
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return
|
|
184
|
-
|
|
179
|
+
}
|
|
180
|
+
exports.withAlignment = withAlignment;
|
|
181
|
+
function withWidth(l, width) {
|
|
182
|
+
switch (l.tag) {
|
|
183
|
+
case "Stack":
|
|
184
|
+
return Stack.withWidth(l, width);
|
|
185
|
+
case "Row":
|
|
186
|
+
return Row.withWidth(l, width);
|
|
187
|
+
case "Elem":
|
|
188
|
+
return Elem.withWidth(l, width);
|
|
185
189
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return
|
|
192
|
-
|
|
190
|
+
}
|
|
191
|
+
exports.withWidth = withWidth;
|
|
192
|
+
function totalElementsWidth(l) {
|
|
193
|
+
switch (l.tag) {
|
|
194
|
+
case "Stack":
|
|
195
|
+
return l.elements.map(e => totalElementsWidth(e)).reduce((a, b) => a + b, 0.0);
|
|
196
|
+
case "Row":
|
|
197
|
+
return l.elements.map(e => totalElementsWidth(e)).reduce((a, b) => a + b, 0.0);
|
|
198
|
+
case "Elem":
|
|
199
|
+
return Width.get_fixed_unchecked(l.width);
|
|
193
200
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return SectionLayout.instantiate_ref_element(this.inner, section);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
return this;
|
|
203
|
-
}
|
|
201
|
+
}
|
|
202
|
+
exports.totalElementsWidth = totalElementsWidth;
|
|
203
|
+
function isInstantiated(l) {
|
|
204
|
+
if (isContainer(l)) {
|
|
205
|
+
return l.elements.map(e => isInstantiated(e)).reduce((a, b) => a && b, true);
|
|
204
206
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (text === undefined) {
|
|
208
|
-
return new SectionLayout(new Stack([], Margin.default_(), Alignment.default_(), Width.default_()));
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
element.item = Resume_1.ItemContent.toString(text);
|
|
212
|
-
element.is_ref = false;
|
|
213
|
-
if (text.tag === "Url") {
|
|
214
|
-
return new SectionLayout(element.with_url(text.value.url).with_item(text.value.text));
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
return new SectionLayout(element);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
207
|
+
else {
|
|
208
|
+
return !isRef(l);
|
|
220
209
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.inner = this.inner.bound_width(bound - this.inner.margin.left - this.inner.margin.right);
|
|
232
|
-
return this;
|
|
210
|
+
}
|
|
211
|
+
exports.isInstantiated = isInstantiated;
|
|
212
|
+
function instantiate(l, section, fields) {
|
|
213
|
+
switch (l.tag) {
|
|
214
|
+
case "Stack":
|
|
215
|
+
return Stack.withElements(l, l.elements.map(e => instantiate(e, section, fields)));
|
|
216
|
+
case "Row":
|
|
217
|
+
return Row.withElements(l, l.elements.map(e => instantiate(e, section, fields)));
|
|
218
|
+
case "Elem":
|
|
219
|
+
return Elem.instantiate(l, section, fields);
|
|
233
220
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
221
|
+
}
|
|
222
|
+
exports.instantiate = instantiate;
|
|
223
|
+
function boundWidth(l, width) {
|
|
224
|
+
const bound = l.width.tag === "Absolute" ? Math.min(l.width.value, width)
|
|
225
|
+
: l.width.tag === "Fill" ? width
|
|
226
|
+
: null;
|
|
227
|
+
if (bound === null) {
|
|
228
|
+
throw new Error("Cannot bound width of non-unitized widths!");
|
|
229
|
+
}
|
|
230
|
+
if (l.tag === "Elem" && l.is_ref) {
|
|
231
|
+
throw new Error("Cannot propagate widths of uninstantiated layout");
|
|
232
|
+
}
|
|
233
|
+
switch (l.tag) {
|
|
234
|
+
case "Stack":
|
|
235
|
+
return Stack.boundWidth(l, bound - l.margin.left - l.margin.right);
|
|
236
|
+
case "Row":
|
|
237
|
+
return Row.boundWidth(l, bound - l.margin.left - l.margin.right);
|
|
238
|
+
case "Elem":
|
|
239
|
+
return Elem.boundWidth(l, bound - l.margin.left - l.margin.right);
|
|
239
240
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
console.debug("Lines broken.");
|
|
254
|
-
return broken_layout;
|
|
241
|
+
}
|
|
242
|
+
exports.boundWidth = boundWidth;
|
|
243
|
+
function scaleWidth(l, document_width) {
|
|
244
|
+
if (isRef(l)) {
|
|
245
|
+
throw new Error("Cannot scale width of uninstantiated layout");
|
|
246
|
+
}
|
|
247
|
+
switch (l.tag) {
|
|
248
|
+
case "Stack":
|
|
249
|
+
return Stack.scaleWidth(l, document_width);
|
|
250
|
+
case "Row":
|
|
251
|
+
return Row.scaleWidth(l, document_width);
|
|
252
|
+
case "Elem":
|
|
253
|
+
return Elem.scaleWidth(l, document_width);
|
|
255
254
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
255
|
+
}
|
|
256
|
+
exports.scaleWidth = scaleWidth;
|
|
257
|
+
function normalize(l, width, font_dict) {
|
|
258
|
+
console.debug(`Normalizing document, checking if document is instantiated...`);
|
|
259
|
+
if (!isInstantiated(l)) {
|
|
260
|
+
throw Error(`Cannot normalize uninstantiated layout ${JSON.stringify(l)}`);
|
|
261
|
+
}
|
|
262
|
+
console.debug("Document is instantiated. Scaling widths...");
|
|
263
|
+
const scaled_layout = scaleWidth(l, width);
|
|
264
|
+
console.debug("Widths are scaled. Bounding widths...");
|
|
265
|
+
const bounded_layout = boundWidth(scaled_layout, width);
|
|
266
|
+
console.debug("Widths are bounded. Filling fonts...");
|
|
267
|
+
const font_filled_layout = fillFonts(bounded_layout, font_dict);
|
|
268
|
+
console.debug("Fonts filled. Breaking lines...");
|
|
269
|
+
// const broken_layout = breakLines(font_filled_layout, font_dict);
|
|
270
|
+
console.debug("Lines broken.");
|
|
271
|
+
// return broken_layout;
|
|
272
|
+
return font_filled_layout;
|
|
273
|
+
}
|
|
274
|
+
exports.normalize = normalize;
|
|
275
|
+
function fillFonts(l, font_dict) {
|
|
276
|
+
if (isRef(l)) {
|
|
277
|
+
throw new Error("Cannot fill fonts of uninstantiated layout");
|
|
278
|
+
}
|
|
279
|
+
switch (l.tag) {
|
|
280
|
+
case "Stack":
|
|
281
|
+
case "Row": {
|
|
282
|
+
const filledFonts = l.elements.map(e => fillFonts(e, font_dict));
|
|
283
|
+
l = { ...l, elements: filledFonts };
|
|
284
|
+
if (isFill(l)) {
|
|
285
|
+
const total_width = totalElementsWidth(l);
|
|
286
|
+
if (total_width <= Width.get_fixed_unchecked(l.width)) {
|
|
287
|
+
// throw `Cannot fill fonts of row with width ${JSON.stringify(this.width())} and total width ${total_width}`
|
|
288
|
+
return withWidth(l, Width.absolute(total_width));
|
|
270
289
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
this.inner = this.inner.fill_fonts(font_dict);
|
|
274
|
-
break;
|
|
290
|
+
}
|
|
291
|
+
return l;
|
|
275
292
|
}
|
|
276
|
-
|
|
293
|
+
case "Elem":
|
|
294
|
+
return Elem.fillFonts(l, font_dict);
|
|
277
295
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
row.elements = row.elements.map(e => e.break_lines(font_dict));
|
|
297
|
-
}
|
|
296
|
+
}
|
|
297
|
+
exports.fillFonts = fillFonts;
|
|
298
|
+
function breakLines(l, font_dict) {
|
|
299
|
+
switch (l.tag) {
|
|
300
|
+
case "Stack": {
|
|
301
|
+
const stack = l;
|
|
302
|
+
return Stack.withElements(stack, stack.elements.map(e => breakLines(e, font_dict)));
|
|
303
|
+
}
|
|
304
|
+
case "Row": {
|
|
305
|
+
const row = l;
|
|
306
|
+
if (row.is_frozen) {
|
|
307
|
+
const total_width = row
|
|
308
|
+
.elements
|
|
309
|
+
.map(e => Width.get_fixed_unchecked(e.width))
|
|
310
|
+
.reduce((a, b) => a + b, 0.0);
|
|
311
|
+
if (total_width > Width.get_fixed_unchecked(row.width)) {
|
|
312
|
+
throw `Cannot break lines of frozen row with width ${row.width} and total width ${total_width}`;
|
|
298
313
|
}
|
|
299
314
|
else {
|
|
300
|
-
|
|
301
|
-
return new SectionLayout(new Stack(lines, row.margin, row.alignment, row.width));
|
|
315
|
+
row.elements = row.elements.map(e => breakLines(e, font_dict));
|
|
302
316
|
}
|
|
303
|
-
return this;
|
|
304
317
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
const elem = this.inner;
|
|
310
|
-
const lines = elem.break_lines(font_dict).map(l => new SectionLayout(l));
|
|
311
|
-
// Make last line left if it's justified
|
|
312
|
-
if (lines[lines.length - 1].inner.alignment === "Justified") {
|
|
313
|
-
lines[lines.length - 1] = lines[lines.length - 1].with_alignment("Left");
|
|
314
|
-
}
|
|
315
|
-
return new SectionLayout(new Stack(lines, elem.margin, elem.alignment, elem.width));
|
|
318
|
+
else {
|
|
319
|
+
const lines = Row.breakLines(row, font_dict);
|
|
320
|
+
return Stack.stack(lines, row.margin, row.alignment, row.width, false);
|
|
316
321
|
}
|
|
322
|
+
return row;
|
|
317
323
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const top_left = new Point_1.Point(0.0, 0.0);
|
|
322
|
-
const depth = this.compute_textbox_positions(textbox_positions, top_left, font_dict);
|
|
323
|
-
console.error("compute_boxes: BBOX: ", this);
|
|
324
|
-
const bounding_box = new Box_1.Box(new Point_1.Point(0.0, 0.0), new Point_1.Point(Width.get_fixed_unchecked(this.width()), depth));
|
|
325
|
-
return [new AnyLayout_1.ElementBox(bounding_box, textbox_positions), this];
|
|
326
|
-
}
|
|
327
|
-
compute_textbox_positions(textbox_positions, top_left, font_dict) {
|
|
328
|
-
let depth = top_left.y;
|
|
329
|
-
switch (this.type_()) {
|
|
330
|
-
case "Stack": {
|
|
331
|
-
const stack = this.inner;
|
|
332
|
-
top_left = top_left.move_y_by(stack.margin.top).move_x_by(stack.margin.left);
|
|
333
|
-
const originalTopLeft = top_left;
|
|
334
|
-
for (const element of stack.elements) {
|
|
335
|
-
depth = element.compute_textbox_positions(textbox_positions, top_left, font_dict);
|
|
336
|
-
top_left = top_left.move_y_to(depth);
|
|
337
|
-
}
|
|
338
|
-
this.bounding_box = new Box_1.Box(originalTopLeft, originalTopLeft.move_y_by(depth).move_x_by(Width.get_fixed_unchecked(stack.width)));
|
|
339
|
-
console.error("Stack bounding box", this.bounding_box);
|
|
340
|
-
return depth;
|
|
324
|
+
case "Elem": {
|
|
325
|
+
if (isRef(l)) {
|
|
326
|
+
throw new Error("Cannot break lines of uninstantiated layout");
|
|
341
327
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
switch (row.alignment) {
|
|
348
|
-
case "Center":
|
|
349
|
-
top_left = top_left.move_x_by((Width.get_fixed_unchecked(row.width) - row.elements_width()) / 2.0);
|
|
350
|
-
break;
|
|
351
|
-
case "Right":
|
|
352
|
-
top_left = top_left.move_x_by(Width.get_fixed_unchecked(row.width) - row.elements_width());
|
|
353
|
-
break;
|
|
354
|
-
case "Justified":
|
|
355
|
-
per_elem_space = (Width.get_fixed_unchecked(row.width) - row.elements_width()) / (row.elements.length - 1);
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
for (const element of row.elements) {
|
|
359
|
-
depth = Math.max(depth, element.compute_textbox_positions(textbox_positions, top_left, font_dict));
|
|
360
|
-
top_left =
|
|
361
|
-
top_left.move_x_by(Width.get_fixed_unchecked(element.width()) + per_elem_space);
|
|
362
|
-
}
|
|
363
|
-
console.error("Row bounding box", top_left, depth);
|
|
364
|
-
this.bounding_box = new Box_1.Box(originalTopLeft, originalTopLeft.move_y_by(depth).move_x_by(Width.get_fixed_unchecked(row.width)));
|
|
365
|
-
return depth;
|
|
366
|
-
}
|
|
367
|
-
case "Elem": {
|
|
368
|
-
const elem = this.inner;
|
|
369
|
-
if (elem.is_ref) {
|
|
370
|
-
throw new Error("Cannot compute textbox positions of uninstantiated layout");
|
|
371
|
-
}
|
|
372
|
-
if (elem.item === "") {
|
|
373
|
-
return top_left.y;
|
|
374
|
-
}
|
|
375
|
-
const height = elem.font.get_height(font_dict);
|
|
376
|
-
const width = Width.get_fixed_unchecked(elem.text_width);
|
|
377
|
-
top_left = top_left.move_y_by(elem.margin.top).move_x_by(elem.margin.left);
|
|
378
|
-
switch (elem.alignment) {
|
|
379
|
-
case "Center":
|
|
380
|
-
top_left = top_left.move_x_by((Width.get_fixed_unchecked(elem.width) - width) / 2.0);
|
|
381
|
-
break;
|
|
382
|
-
case "Right":
|
|
383
|
-
top_left = top_left.move_x_by(Width.get_fixed_unchecked(elem.width) - width);
|
|
384
|
-
break;
|
|
385
|
-
}
|
|
386
|
-
const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height));
|
|
387
|
-
textbox_positions.push([textbox, elem]);
|
|
388
|
-
this.bounding_box = textbox;
|
|
389
|
-
return top_left.y + height;
|
|
328
|
+
const elem = l;
|
|
329
|
+
const lines = Elem.break_lines(elem, font_dict);
|
|
330
|
+
// Make last line left if it's justified
|
|
331
|
+
if (lines[lines.length - 1].alignment === "Justified") {
|
|
332
|
+
lines[lines.length - 1] = withAlignment(lines[lines.length - 1], "Left");
|
|
390
333
|
}
|
|
334
|
+
return Stack.stack(lines, elem.margin, elem.alignment, elem.width, false);
|
|
391
335
|
}
|
|
392
336
|
}
|
|
393
337
|
}
|
|
394
|
-
exports.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
this.elements = elements;
|
|
399
|
-
this.margin = margin !== null && margin !== void 0 ? margin : Margin.default_();
|
|
400
|
-
this.alignment = alignment !== null && alignment !== void 0 ? alignment : Alignment.default_();
|
|
401
|
-
this.width = width !== null && width !== void 0 ? width : Width.default_();
|
|
402
|
-
this.is_fill = is_fill !== null && is_fill !== void 0 ? is_fill : false;
|
|
403
|
-
}
|
|
404
|
-
static stack(elements, margin, alignment, width, is_fill) {
|
|
405
|
-
return new SectionLayout(new Stack(elements, margin, alignment, width, is_fill));
|
|
406
|
-
}
|
|
407
|
-
copy() {
|
|
408
|
-
return new Stack(this.elements.map((e) => e.copy()), Margin.copy(this.margin), this.alignment, Width.copy(this.width));
|
|
409
|
-
}
|
|
410
|
-
static default_() {
|
|
411
|
-
return new Stack([]);
|
|
412
|
-
}
|
|
413
|
-
instantiate(section) {
|
|
414
|
-
return new Stack(this.elements.map(e => e.instantiate(section)), this.margin, this.alignment, this.width, this.is_fill);
|
|
415
|
-
}
|
|
416
|
-
with_elements(elements) {
|
|
417
|
-
return new Stack(elements, this.margin, this.alignment, this.width, this.is_fill);
|
|
418
|
-
}
|
|
419
|
-
with_margin(margin) {
|
|
420
|
-
return new Stack(this.elements, margin, this.alignment, this.width, this.is_fill);
|
|
421
|
-
}
|
|
422
|
-
with_alignment(alignment) {
|
|
423
|
-
return new Stack(this.elements, this.margin, alignment, this.width, this.is_fill);
|
|
424
|
-
}
|
|
425
|
-
with_width(width) {
|
|
426
|
-
return new Stack(this.elements, this.margin, this.alignment, width, this.is_fill);
|
|
427
|
-
}
|
|
428
|
-
bound_width(width) {
|
|
429
|
-
const bound = this.width.tag === "Absolute" ? Math.min(this.width.value, width)
|
|
430
|
-
: this.width.tag === "Fill" ? width
|
|
431
|
-
: null;
|
|
432
|
-
if (bound === null) {
|
|
433
|
-
throw new Error("Cannot bound width of non-unitized widths!");
|
|
434
|
-
}
|
|
435
|
-
return new Stack(this.elements.map(e => e.bound_width(bound)), this.margin, this.alignment, Width.absolute(bound), Width.is_fill(this.width));
|
|
436
|
-
}
|
|
437
|
-
scale_width(w) {
|
|
438
|
-
return this.with_elements(this.elements.map(e => e.scale_width(w))).with_width(Width.scale(this.width, w));
|
|
439
|
-
}
|
|
338
|
+
exports.breakLines = breakLines;
|
|
339
|
+
function computeBoxes(l, font_dict) {
|
|
340
|
+
const top_left = new Point_1.Point(0.0, 0.0);
|
|
341
|
+
return computeTextboxPositions(l, top_left, font_dict).renderedLayout;
|
|
440
342
|
}
|
|
441
|
-
exports.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
return this.elements.map(e => Width.get_fixed_unchecked(e.width())).reduce((a, b) => a + b, 0.0);
|
|
478
|
-
}
|
|
479
|
-
bound_width(width) {
|
|
480
|
-
const bound = this.width.tag === "Absolute" ? Math.min(this.width.value, width)
|
|
481
|
-
: this.width.tag === "Fill" ? width
|
|
482
|
-
: null;
|
|
483
|
-
if (bound === null) {
|
|
484
|
-
throw new Error("Cannot bound width of non-unitized widths!");
|
|
485
|
-
}
|
|
486
|
-
return new Row(this.elements.map(e => e.bound_width(bound)), this.is_frozen, this.margin, this.alignment, Width.absolute(bound), Width.is_fill(this.width));
|
|
487
|
-
}
|
|
488
|
-
scale_width(w) {
|
|
489
|
-
return this.with_elements(this.elements.map(e => e.scale_width(w))).with_width(Width.scale(this.width, w));
|
|
490
|
-
}
|
|
491
|
-
break_lines(font_dict) {
|
|
492
|
-
const lines = [];
|
|
493
|
-
let current_line = [];
|
|
494
|
-
let current_width = 0.0;
|
|
495
|
-
const elements = this
|
|
496
|
-
.elements
|
|
497
|
-
.map(e => e.break_lines(font_dict));
|
|
498
|
-
for (const element of elements) {
|
|
499
|
-
const element_width = Width.get_fixed_unchecked(element.width());
|
|
500
|
-
if (current_width + element_width > Width.get_fixed_unchecked(this.width)) {
|
|
501
|
-
lines.push(this.with_elements(current_line));
|
|
502
|
-
current_line = [];
|
|
503
|
-
current_width = 0.0;
|
|
343
|
+
exports.computeBoxes = computeBoxes;
|
|
344
|
+
function computeTextboxPositions(l, top_left, font_dict) {
|
|
345
|
+
let depth = top_left.y;
|
|
346
|
+
switch (l.tag) {
|
|
347
|
+
case "Stack": {
|
|
348
|
+
const stack = l;
|
|
349
|
+
top_left = top_left.move_y_by(stack.margin.top).move_x_by(stack.margin.left);
|
|
350
|
+
const originalTopLeft = top_left;
|
|
351
|
+
const renderedElements = [];
|
|
352
|
+
for (const element of stack.elements) {
|
|
353
|
+
const result = computeTextboxPositions(element, top_left, font_dict);
|
|
354
|
+
depth = result.depth;
|
|
355
|
+
top_left = top_left.move_y_to(depth);
|
|
356
|
+
renderedElements.push(result.renderedLayout);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
depth, renderedLayout: {
|
|
360
|
+
...l, bounding_box: new Box_1.Box(originalTopLeft, top_left.move_x_by(Width.get_fixed_unchecked(stack.width))), elements: renderedElements
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
case "Row": {
|
|
365
|
+
const row = l;
|
|
366
|
+
top_left = top_left.move_y_by(row.margin.top).move_x_by(row.margin.left);
|
|
367
|
+
const originalTopLeft = top_left;
|
|
368
|
+
let per_elem_space = 0.0;
|
|
369
|
+
switch (row.alignment) {
|
|
370
|
+
case "Center":
|
|
371
|
+
top_left = top_left.move_x_by((Width.get_fixed_unchecked(row.width) - Row.elementsWidth(row)) / 2.0);
|
|
372
|
+
break;
|
|
373
|
+
case "Right":
|
|
374
|
+
top_left = top_left.move_x_by(Width.get_fixed_unchecked(row.width) - Row.elementsWidth(row));
|
|
375
|
+
break;
|
|
376
|
+
case "Justified":
|
|
377
|
+
per_elem_space = (Width.get_fixed_unchecked(row.width) - Row.elementsWidth(row)) / (row.elements.length - 1);
|
|
378
|
+
break;
|
|
504
379
|
}
|
|
505
|
-
|
|
506
|
-
|
|
380
|
+
const renderedElements = [];
|
|
381
|
+
for (const element of row.elements) {
|
|
382
|
+
const result = computeTextboxPositions(element, top_left, font_dict);
|
|
383
|
+
depth = Math.max(depth, result.depth);
|
|
384
|
+
top_left =
|
|
385
|
+
top_left.move_x_by(Width.get_fixed_unchecked(element.width) + per_elem_space);
|
|
386
|
+
renderedElements.push(result.renderedLayout);
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
depth, renderedLayout: {
|
|
390
|
+
...l, bounding_box: new Box_1.Box(originalTopLeft, originalTopLeft.move_y_by(depth).move_x_by(Width.get_fixed_unchecked(row.width))), elements: renderedElements
|
|
391
|
+
}
|
|
392
|
+
};
|
|
507
393
|
}
|
|
508
|
-
|
|
509
|
-
|
|
394
|
+
case "Elem": {
|
|
395
|
+
const elem = l;
|
|
396
|
+
if (elem.is_ref) {
|
|
397
|
+
throw new Error("Cannot compute textbox positions of uninstantiated layout");
|
|
398
|
+
}
|
|
399
|
+
const height = Font.get_height(elem.font, font_dict);
|
|
400
|
+
const width = Width.get_fixed_unchecked(elem.text_width);
|
|
401
|
+
top_left = top_left.move_y_by(elem.margin.top).move_x_by(elem.margin.left);
|
|
402
|
+
let line = 1;
|
|
403
|
+
let cursor = top_left.x;
|
|
404
|
+
elem.spans.forEach(span => {
|
|
405
|
+
if (cursor + span.width > Width.get_fixed_unchecked(elem.width) - elem.margin.right) {
|
|
406
|
+
cursor = top_left.x;
|
|
407
|
+
line += 1;
|
|
408
|
+
}
|
|
409
|
+
span.bbox = new Box_1.Box(new Point_1.Point(cursor, (line - 1) * height), new Point_1.Point(cursor + span.width, line * height));
|
|
410
|
+
cursor += span.width;
|
|
411
|
+
console.log(span);
|
|
412
|
+
});
|
|
413
|
+
switch (elem.alignment) {
|
|
414
|
+
case "Center":
|
|
415
|
+
top_left = top_left.move_x_by((Width.get_fixed_unchecked(elem.width) - width) / 2.0);
|
|
416
|
+
break;
|
|
417
|
+
case "Right":
|
|
418
|
+
top_left = top_left.move_x_by(Width.get_fixed_unchecked(elem.width) - width);
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height));
|
|
422
|
+
return { depth: top_left.y + height, renderedLayout: { ...l, bounding_box: textbox } };
|
|
510
423
|
}
|
|
511
|
-
return lines;
|
|
512
424
|
}
|
|
513
425
|
}
|
|
514
|
-
exports.
|
|
426
|
+
exports.computeTextboxPositions = computeTextboxPositions;
|
|
515
427
|
exports.ColorMap = {
|
|
516
428
|
"Transparent": "transparent",
|
|
517
429
|
"Light Yellow": "#FFC96F",
|
|
@@ -521,126 +433,3 @@ exports.ColorMap = {
|
|
|
521
433
|
"Light Blue": "#EEF7FF",
|
|
522
434
|
"Blue": "#4793AF",
|
|
523
435
|
};
|
|
524
|
-
class Elem {
|
|
525
|
-
constructor(item, url, is_ref, is_fill, text_width, font, margin, alignment, width, background_color) {
|
|
526
|
-
this.tag = "Elem";
|
|
527
|
-
this.item = item;
|
|
528
|
-
this.url = url;
|
|
529
|
-
this.is_ref = is_ref;
|
|
530
|
-
this.is_fill = is_fill;
|
|
531
|
-
this.text_width = text_width;
|
|
532
|
-
this.font = font;
|
|
533
|
-
this.margin = margin;
|
|
534
|
-
this.alignment = alignment;
|
|
535
|
-
this.width = width;
|
|
536
|
-
this.background_color = background_color;
|
|
537
|
-
}
|
|
538
|
-
static elem(item, url, is_ref, is_fill, text_width, font, margin, alignment, width, background_color) {
|
|
539
|
-
return new SectionLayout(new Elem(item, url, is_ref, is_fill, text_width, font, margin, alignment, width, background_color));
|
|
540
|
-
}
|
|
541
|
-
copy() {
|
|
542
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, Width.copy(this.text_width), this.font, Margin.copy(this.margin), this.alignment, Width.copy(this.width), this.background_color);
|
|
543
|
-
}
|
|
544
|
-
static default_() {
|
|
545
|
-
return new Elem("", null, false, false, Width.default_(), Font_1.Font.default_(), Margin.default_(), Alignment.default_(), Width.default_(), "Transparent");
|
|
546
|
-
}
|
|
547
|
-
with_item(item) {
|
|
548
|
-
return new Elem(item, this.url, this.is_ref, this.is_fill, this.text_width, this.font, this.margin, this.alignment, this.width, this.background_color);
|
|
549
|
-
}
|
|
550
|
-
as_ref() {
|
|
551
|
-
return new Elem(this.item, this.url, true, this.is_fill, this.text_width, this.font, this.margin, this.alignment, this.width, this.background_color);
|
|
552
|
-
}
|
|
553
|
-
with_font(font) {
|
|
554
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, this.text_width, font, this.margin, this.alignment, this.width, this.background_color);
|
|
555
|
-
}
|
|
556
|
-
with_url(url) {
|
|
557
|
-
return new Elem(this.item, url, this.is_ref, this.is_fill, this.text_width, this.font, this.margin, this.alignment, this.width, this.background_color);
|
|
558
|
-
}
|
|
559
|
-
with_margin(margin) {
|
|
560
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, this.text_width, this.font, margin, this.alignment, this.width, this.background_color);
|
|
561
|
-
}
|
|
562
|
-
with_alignment(alignment) {
|
|
563
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, this.text_width, this.font, this.margin, alignment, this.width, this.background_color);
|
|
564
|
-
}
|
|
565
|
-
with_width(width) {
|
|
566
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, this.text_width, this.font, this.margin, this.alignment, width, this.background_color);
|
|
567
|
-
}
|
|
568
|
-
with_text_width(text_width) {
|
|
569
|
-
return new Elem(this.item, this.url, this.is_ref, this.is_fill, text_width, this.font, this.margin, this.alignment, this.width, this.background_color);
|
|
570
|
-
}
|
|
571
|
-
with_is_fill(is_fill) {
|
|
572
|
-
return new Elem(this.item, this.url, this.is_ref, is_fill, this.text_width, this.font, this.margin, this.alignment, this.width, this.background_color);
|
|
573
|
-
}
|
|
574
|
-
scale_width(w) {
|
|
575
|
-
return this.with_width(Width.scale(this.width, w));
|
|
576
|
-
}
|
|
577
|
-
fill_fonts(fonts) {
|
|
578
|
-
const text_width_with_font = this.font.get_width(this.item, fonts);
|
|
579
|
-
if (this.is_fill) {
|
|
580
|
-
return this.with_width(Width.absolute(Math.min(Width.get_fixed_unchecked(this.width), text_width_with_font)))
|
|
581
|
-
.with_text_width(Width.absolute(text_width_with_font));
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
return this.with_text_width(Width.absolute(text_width_with_font));
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
justified_lines(lines, font_dict) {
|
|
588
|
-
const rowLines = [];
|
|
589
|
-
for (const line of lines.slice(0, -1)) {
|
|
590
|
-
const words = line.item.split(/\s+/);
|
|
591
|
-
const row = new Row([], false, line.margin, line.alignment, line.width);
|
|
592
|
-
words.forEach(word => {
|
|
593
|
-
const word_width = this.font.get_width(word, font_dict);
|
|
594
|
-
row.elements.push(new SectionLayout(new Elem(word, null, false, false, Width.absolute(word_width), this.font, Margin.default_(), Alignment.default_(), Width.absolute(word_width), this.background_color)));
|
|
595
|
-
});
|
|
596
|
-
rowLines.push(row);
|
|
597
|
-
}
|
|
598
|
-
rowLines.push(new Row([new SectionLayout(lines[lines.length - 1]).with_alignment("Left")], false, lines[0].margin, "Left", lines[0].width));
|
|
599
|
-
return rowLines;
|
|
600
|
-
}
|
|
601
|
-
break_lines(font_dict) {
|
|
602
|
-
if (Width.get_fixed_unchecked(this.text_width) <= Width.get_fixed_unchecked(this.width)) {
|
|
603
|
-
return [this];
|
|
604
|
-
}
|
|
605
|
-
const lines = [];
|
|
606
|
-
// todo: I'm sure this implementation is pretty buggy. Note to future me, fix
|
|
607
|
-
// this.
|
|
608
|
-
const words = this.item.split(/\s+/);
|
|
609
|
-
const widths = words.map((word) => this.font.get_width(word, font_dict));
|
|
610
|
-
const space_width = this.font.get_width(" ", font_dict);
|
|
611
|
-
let start = 0;
|
|
612
|
-
let width = widths[0];
|
|
613
|
-
const max_width = Width.get_fixed_unchecked(this.width);
|
|
614
|
-
for (let i = 1; i < words.length; i++) {
|
|
615
|
-
const candidate_width = width + space_width + widths[i];
|
|
616
|
-
if (candidate_width > max_width) {
|
|
617
|
-
const line = words.slice(start, i).join(" ");
|
|
618
|
-
const line_width = this.font.get_width(line, font_dict);
|
|
619
|
-
lines.push(this.with_item(line)
|
|
620
|
-
.with_text_width(Width.absolute(line_width)));
|
|
621
|
-
start = i;
|
|
622
|
-
width = widths[i];
|
|
623
|
-
}
|
|
624
|
-
else {
|
|
625
|
-
width += space_width + widths[i];
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
const line = words.slice(start).join(" ");
|
|
629
|
-
const line_width = this.font.get_width(line, font_dict);
|
|
630
|
-
lines.push(this.with_item(line)
|
|
631
|
-
.with_text_width(Width.absolute(line_width)));
|
|
632
|
-
if (this.alignment === "Justified") {
|
|
633
|
-
return this.justified_lines(lines, font_dict);
|
|
634
|
-
}
|
|
635
|
-
return lines;
|
|
636
|
-
}
|
|
637
|
-
bound_width(width) {
|
|
638
|
-
if (!Width.is_fill(this.width)) {
|
|
639
|
-
return this.with_width(Width.absolute(Math.min(Width.get_fixed_unchecked(this.width), width))).with_is_fill(false);
|
|
640
|
-
}
|
|
641
|
-
else {
|
|
642
|
-
return this.with_width(Width.absolute(width)).with_is_fill(true);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
exports.Elem = Elem;
|