]> git.kianting.info Git - clo/blob - src/libclo/breakLines.ts
add line-breaking algorithm initially
[clo] / src / libclo / breakLines.ts
1 /**
2 * Algorithms and functions for LineBreaking
3 */
4 import { join } from "path";
5 import {BreakPoint, BoxesItem, HGlue} from "./index.js";
6 /**
7 * Algorithms in LATEX language
8 TotalCost(i) = min_{j}~TotalCost(j) + LineCost(j, i)~~~~j=0, 1, ..., i-1
9
10 LineCost(j, i)= \begin{cases}
11 \infty ~~~ if~~LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]) < 0 \\
12 \infty~~if~~NOT~~breakable(item[i]) \\
13 (LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]))^3 ~~elsewhere
14 \end{cases} */
15
16 /**check if a boeitem is BreakPoint Type */
17 function isBreakPoint (item : any) : item is BreakPoint{
18 return (item as BreakPoint).newLined !== undefined;
19 }
20
21 /**check if a boeitem is BreakPoint Type */
22 function isHGlue (item : any) : item is HGlue{
23 return (item as HGlue).stretchFactor !== undefined;
24 }
25
26
27 /** measuring original advance width */
28 function origWidth(item : BoxesItem) : number{
29 if (isBreakPoint(item)){
30 console.log(item);
31 return origWidth(item.original);
32 }else if(Array.isArray(item)){
33 return item.map((x)=>origWidth(x))
34 .reduce((acc, current) => acc + current,
35 0.0,)
36 }else if(isHGlue(item)){
37 return 0.0;
38 }
39 else{
40 return item.width;
41 }
42 }
43
44 /** measuring new-line triggered advance width */
45 function newLineWidth(item : BoxesItem) : number{
46 if (isBreakPoint(item)){
47 return origWidth(item.newLined);
48 }else{
49 // impossible to make a new line
50 return Infinity;
51 }
52 }
53
54 let lineCostStorage : any = new Object();
55
56 /**
57 * check the total cost item[0..j].
58 * @param items
59 * @param i
60 * @param lineWidth
61 */
62 export function totalCost(items : BoxesItem[], j : number, lineWidth: number){
63 if (j in lineCostStorage){
64 return lineCostStorage[j];
65 }
66 var returnCost = Infinity;
67
68 for(var i=-1; i<=j; i++){
69 // lineCost
70 let lCost = lineCost(items, i, j, lineWidth);
71
72 if (returnCost > lCost){
73 returnCost = lCost;
74 }
75 }
76
77 lineCostStorage[j] = returnCost;
78 return returnCost;
79
80 }
81
82
83
84 /**
85 * check the line cost of a line containing items[i+1..j]
86 * @param items items of box
87 * @param i beginning (excluded)
88 * @param j end of the line
89 * @param lineWidth line width
90 */
91 function lineCost(items : BoxesItem[], i : number, j : number, lineWidth: number){
92 if (!isBreakPoint(items[j])){
93 return Infinity;
94 }else{
95 var tmpItemWidth = 0;
96 for (var k = i+1; k<j; k++){
97 tmpItemWidth += origWidth(items[k]);
98 }
99
100 tmpItemWidth += newLineWidth(items[j]);
101
102 if (tmpItemWidth > lineWidth){
103 return Infinity;
104 }else{
105 return (lineWidth - tmpItemWidth)**3.0;
106 }
107 }
108
109 }