]> git.kianting.info Git - clo/blob - src/libclo/breakLines.js
cdd4f6e99d3d25f1ee90cb24cf4bfa4ba2d50f2b
[clo] / src / libclo / breakLines.js
1 "use strict";
2 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10 };
11 Object.defineProperty(exports, "__esModule", { value: true });
12 exports.BreakLineAlgorithm = void 0;
13 /**
14 * Algorithms in LATEX-like language
15 */
16 class BreakLineAlgorithm {
17 constructor() {
18 this.prevNodes = [];
19 this.totalCostAuxStorage = [];
20 this.lineCostStorage = [[]];
21 }
22 /**check if a boeitem is BreakPoint Type */
23 isBreakPoint(item) {
24 return item.newLined !== undefined;
25 }
26 /**check if a boeitem is HGlue Type */
27 isHGlue(item) {
28 return item.stretchFactor !== undefined;
29 }
30 /** measuring original advance width */
31 origWidth(item) {
32 if (this.isBreakPoint(item)) {
33 return this.origWidth(item.original);
34 }
35 else if (Array.isArray(item)) {
36 return item.map((x) => this.origWidth(x))
37 .reduce((acc, current) => acc + current, 0.0);
38 }
39 else if (this.isHGlue(item)) {
40 return 0.0;
41 }
42 else {
43 return item.width;
44 }
45 }
46 segmentedNodes(items, lineWidth) {
47 let lineWidthFixed = lineWidth;
48 this.totalCost(items, lineWidthFixed);
49 let nodeList = this.generateBreakLineNodeList();
50 let res = [];
51 let low = -1;
52 let up = nodeList[0];
53 for (var i = 0; i < nodeList.length; i++) {
54 res.push(items.slice(low + 1, up + 1));
55 low = nodeList[i];
56 up = nodeList[i + 1];
57 }
58 return res;
59 }
60 /**genrate the list of point of breaking line. it returns a correct list ascending*/
61 generateBreakLineNodeList() {
62 let res = [];
63 var pointer = this.prevNodes.length - 1;
64 while (this.prevNodes[pointer] !== undefined) {
65 res.push(pointer);
66 pointer = this.prevNodes[pointer];
67 }
68 return res.reverse();
69 }
70 /** measuring new-line triggered advance width */
71 newLineWidth(item) {
72 if (this.isBreakPoint(item)) {
73 return this.origWidth(item.newLined);
74 }
75 else {
76 // impossible to make a new line
77 return Infinity;
78 }
79 }
80 /**
81 * check all the total cost of paragraphes of the segnemt
82 */
83 totalCost(items, lineWidth) {
84 return __awaiter(this, void 0, void 0, function* () {
85 let lineWidthFixed = lineWidth * 0.75;
86 let itemsLength = items.length;
87 this.lineCostStorage = Array(itemsLength);
88 this.prevNodes = Array(itemsLength).fill(null);
89 for (var i = 0; i < itemsLength; i++) {
90 this.lineCostStorage[i] = Array(itemsLength).fill(null);
91 }
92 this.totalCostAuxStorage = Array(itemsLength).fill(null);
93 let a = Infinity;
94 for (var k = itemsLength - 2; (yield this.lineCost(items, k + 1, itemsLength - 1, lineWidthFixed)) < Infinity; k--) {
95 let tmp = yield this.totalCostAux(items, k, lineWidthFixed);
96 if (a > tmp) {
97 this.prevNodes[itemsLength - 1] = k;
98 a = tmp;
99 }
100 }
101 console.log("~~~", lineWidth);
102 console.log(items[itemsLength - 2]);
103 return a;
104 });
105 }
106 /**
107 * check the total cost item[0..j].
108 * @param items
109 * @param i
110 * @param lineWidth
111 */
112 totalCostAux(items, j, lineWidth) {
113 return __awaiter(this, void 0, void 0, function* () {
114 if (this.totalCostAuxStorage[j] !== null) {
115 return this.totalCostAuxStorage[j];
116 }
117 let rawLineCost = yield this.lineCost(items, 0, j, lineWidth);
118 if (rawLineCost != Infinity) {
119 this.totalCostAuxStorage[j] = rawLineCost ** 3.0;
120 return rawLineCost ** 3.0;
121 }
122 else {
123 var returnCost = Infinity;
124 for (var k = 0; k < j; k++) {
125 let tmp1 = yield Promise.all([this.totalCostAux(items, k, lineWidth), this.lineCost(items, k + 1, j, lineWidth)]);
126 let tmp = tmp1[0] + tmp1[1] ** 3;
127 if (returnCost > tmp) {
128 this.prevNodes[j] = k;
129 returnCost = tmp;
130 }
131 }
132 this.totalCostAuxStorage[j] = returnCost;
133 return returnCost;
134 }
135 });
136 }
137 /**
138 * check the line cost of a line containing items[i..j]
139 * @param items items of box
140 * @param i beginning (excluded)
141 * @param j end of the line
142 * @param lineWidth line width
143 */
144 lineCost(items, i, j, lineWidth) {
145 return __awaiter(this, void 0, void 0, function* () {
146 if (this.lineCostStorage[i] !== null && this.lineCostStorage[i][j] !== null) {
147 return this.lineCostStorage[i][j];
148 }
149 if (!this.isBreakPoint(items[j])) {
150 this.lineCostStorage[i][j] = Infinity;
151 return Infinity;
152 }
153 else {
154 var tmpItemWidth = 0;
155 for (var k = i; k < j; k++) {
156 tmpItemWidth += this.origWidth(items[k]);
157 }
158 tmpItemWidth += this.newLineWidth(items[j]);
159 if (tmpItemWidth > lineWidth) {
160 this.lineCostStorage[i][j] = Infinity;
161 return Infinity;
162 }
163 else {
164 let returnValue = (lineWidth - tmpItemWidth);
165 this.lineCostStorage[i][j] = returnValue;
166 return returnValue;
167 }
168 }
169 });
170 }
171 }
172 exports.BreakLineAlgorithm = BreakLineAlgorithm;