fix the algorithms, and try to add a bigframe initially.

This commit is contained in:
Tan, Kian-ting 2023-11-13 23:45:02 +08:00
parent a4f79a3761
commit f12842e5a4
80 changed files with 2233 additions and 437 deletions

View file

@ -35,6 +35,7 @@
- 20231029-30: hyphenating for english. - 20231029-30: hyphenating for english.
- 20231105-06: 利用fontkit算文字的對應px寬度 initially pushed. - 20231105-06: 利用fontkit算文字的對應px寬度 initially pushed.
- 20231109-10: Keng-kái oa̍h-chōa ián-sǹg-hoat. - 20231109-10: Keng-kái oa̍h-chōa ián-sǹg-hoat.
- 20231113: the algorithm is basically fixed, and make a `bigFrame` to prepare for convert to boxes and positions.
## 之後的做法 ## 之後的做法
- 先做一個前處理註冊器,註冊下列的前處理 - 先做一個前處理註冊器,註冊下列的前處理

2
b.clo
View file

@ -1,2 +1,2 @@
--- ---
The book of the generation of Jesus Christ, the son of David, In the beginning was the Word, and the Word was with God, and the Word was God. The same was in the beginning with God.

View file

@ -1 +1 @@
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA42XW0/bMBSA/0ue0TYYsI230gZWoGnUZAMJocqkbuPVsaPEKa2m/fe5iZM6t+M8leZ8/hpfzvHh9a8l8F5YN1aA2A5ZZ1aMRCi/RnyVUZx+zh9/CkVEZWxL2Mq6uTizgpDQVYKZdfNaCXz54YkDxScJZllUKqpwXfb931nN8IzJJhT9iiLe7xhTfhpMmMDJGgXVPGS0MZer6/rgMY8iJCOgQ0GQ6o6z5mq0TBUDidYScqXA9RwUYReRBDC2YUjtTu4mPMgizLQFF4e40mlAw/Plx7fzq4vG3nkiwSj6xUiPrs6YjOtydXx+/POkXGcsEIQzfdIaWPdeX2rKOBPHd+hXKaCleNMk8hnetxMlfzwoUUJM4wlOg5NjhxKC3jWLIuq6r/rqxAmX256Oks2uazqFR4PAKVHyHuh5U86peD5oUhOS4Py3m6mrHFV8YOoGFKXp6RVaiXt+oQ+95fvOrFCjZRjM1UQmi0FRMpBndLmcOkv3pWtjlaZEgJ0N/mx3t5QH23TKFnijn7WWrsUavDkjC4ScHTNodRSwrvAaZVTky9Oody1tizV7Oy6VPm3PBVOzhoc4xOyOJ7Wzdkqb8sBrGFBOCszf+gnGRluBQcVJ+NzdA54CAAxpTIkYPzz+BiQVA3jEB19gkSUs9bmDPyhh0PQ6aLDYxChJcdIuNsXzYa0G32L2SPRruig2ylHF+4uNaOxacU+p8aJjr9oX1Hju+Lbjd51M5VEEcCCnM3e+gBQFYDTYttFh20aLZ5R4gMOZ+8sRNJcCMBqWvv1i1uQU4HIX83tAcgwDoz37fgbvrSJAx2w6nj/NHdCiGMBD8V7Pl5YjjwPjeSZkX2Pr2dJyVIzR8xMjs+gIGU0zslp1F/aaq8AAG4pjeji25Li7S1Q2HQOKn8JkAzDElmMm2zSKeWKUFdQwVzpMlppsDhej3pZY91WgyeiiAW+XQ4NMz0SE8hgMW8H2CNNveHgz5NQozGyLyJhTvQfu8ynQaIxlD+o8GX0FZrIN2WjDHhOm/kXyeV/Xo2wNEmo3ZNjnDx4gK5GOxuLtPxjWUt7DEAAA" window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA52YXXObOBRA/4ufM9s223Z38+Y4JHEbYyZm28xkOh4Fy0a1kBghUrs7/e8rQIBAcMX0KQn36OgD6V6R5/9mEp/k7GoWIfaKZhezFMlY/ZnwXU5x9qZ8/EcsE6piR8J2s6vLi1kUE7oTmM2unhvBLWdyI88UtxLM8qRWNOGu7O9fF40hVD++YnKI5bCijY87FpS3jQmTWOxR1MxDRXtz+fCx23jBkwSpCOjQEKQqxtpbDcvUMJBor9YtUIJg46MEB4gIwGjDkDq4ub3hUZ5gZiy4PKeNzgB6nrf//PXuw6U1X4FR8i8jI7ou4zLu6w0T8uLXVrnPWSQJZ+akDbDr/fjeUKa5LMYwrtKApfhmSGIk9i/5z5/2Wakjk45LDYc4GxxQKzNAcGDqGT7ZoyofTxsSpukNzqLW8YoEQS+GRRNd3Z/ma0sFV/sxm4vD69C0Ko8BgVOi5CUyD3Q9p+r5pEndEIHLvvs5RTua+MScElGUZe0QrIzy7tJses1Pg8dVt1Zh6IBeq7NyDDgxd/+ApKHA3Kb2kWM0GoEst0LlFYemZiDP/R3Nh1OjlpQAuDb8hLOlxEk/17RLW8VdeWb+frv0t8HT0K7XrhoBtn30/fh6TXl0zJbsER/Mg2jpLNbhLRmV1tUaMYfWRAHrDu9RTmX5pnpVytJarNs7UPzGtCM1sLsGiEY5RRKXFwCyk/F975bQ5pd6LUaaAMVhrMk8P/1GR6oV0NeeUPWGvCSVZ1UQCTsAPVgs4I3PaYzZLRedlGUpTcxpC4+hwNhpqzCo+MqQB9BSVgBgyNIiQ4S8THhpNy1aNhsGzZTIxafPX0ChZgCP/MEfscwFUx37+AclDFq4AXpCNXzzUszoQcHZWGHctsikGnld43N64ILI2Eiq3Xpnmu1WdiU0h58ikWFhj7l6PmmgIT9i9pmY9/OqmGtHEx8v5rK3nauiodvLgU1sV4zF2g89PxxKbtqjCSCnLVfB+hFSVIDT4HlOh+c5LRunZAM4/HW4nUNzqQCnYRt6T25NSQGu4HF9B0iKMNB6492t4HerCdCxWi7WD2sftGgG8FB8Ms+L5SjjQHueS/VB45mnxXI0jNNzj5FbVEBO04rsdsN3g46rwgAbSlN6Lr7F8XAl0DYTA3K3xtRNdIqtxFy2ZZJy4ZRV1DRXNk2WuWw+l/PRb2HT14AuY4AmjK6EJpm+qnqitsG0FbRbuPrY4MOUXaMxty0hC07Nb8wxnwadxuL24j84fRXmsk150Y53TJj+30jIx66D2tYjoduSCof80waQ1Qh4L0p3+xViJC3v4QP3CzPcq+2/vv0PRTFWxwIVAAA="

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,95 +1,149 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.totalCost = void 0; exports.BreakLineAlgorithm = void 0;
/** /**
* Algorithms in LATEX language * Algorithms in LATEX-like language
TotalCost(i) = min_{j}~TotalCost(j) + LineCost(j, i)~~~~j=0, 1, ..., i-1
LineCost(j, i)= \begin{cases}
\infty ~~~ if~~LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]) < 0 \\
\infty~~if~~NOT~~breakable(item[i]) \\
(LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]))^3 ~~elsewhere
\end{cases} */
/**check if a boeitem is BreakPoint Type */
function isBreakPoint(item) {
return item.newLined !== undefined;
}
/**check if a boeitem is BreakPoint Type */
function isHGlue(item) {
return item.stretchFactor !== undefined;
}
/** measuring original advance width */
function origWidth(item) {
if (isBreakPoint(item)) {
console.log(item);
return origWidth(item.original);
}
else if (Array.isArray(item)) {
return item.map((x) => origWidth(x))
.reduce((acc, current) => acc + current, 0.0);
}
else if (isHGlue(item)) {
return 0.0;
}
else {
return item.width;
}
}
/** measuring new-line triggered advance width */
function newLineWidth(item) {
if (isBreakPoint(item)) {
return origWidth(item.newLined);
}
else {
// impossible to make a new line
return Infinity;
}
}
let lineCostStorage = new Object();
/**
* check the total cost item[0..j].
* @param items
* @param i
* @param lineWidth
*/ */
function totalCost(items, j, lineWidth) { class BreakLineAlgorithm {
if (j in lineCostStorage) { constructor() {
return lineCostStorage[j]; this.prevNodes = [];
this.totalCostAuxStorage = [];
this.lineCostStorage = [[]];
} }
var returnCost = Infinity; /**check if a boeitem is BreakPoint Type */
for (var i = -1; i <= j; i++) { isBreakPoint(item) {
// lineCost return item.newLined !== undefined;
let lCost = lineCost(items, i, j, lineWidth); }
if (returnCost > lCost) { /**check if a boeitem is BreakPoint Type */
returnCost = lCost; isHGlue(item) {
return item.stretchFactor !== undefined;
}
/** measuring original advance width */
origWidth(item) {
if (this.isBreakPoint(item)) {
return this.origWidth(item.original);
}
else if (Array.isArray(item)) {
return item.map((x) => this.origWidth(x))
.reduce((acc, current) => acc + current, 0.0);
}
else if (this.isHGlue(item)) {
return 0.0;
}
else {
return item.width;
} }
} }
lineCostStorage[j] = returnCost; segmentedNodes(items, lineWidth) {
return returnCost; this.totalCost(items, lineWidth);
} let nodeList = this.generateBreakLineNodeList();
exports.totalCost = totalCost; console.log("~~~", nodeList);
/** let res = [];
* check the line cost of a line containing items[i+1..j] let low = -1;
* @param items items of box let up = nodeList[0];
* @param i beginning (excluded) for (var i = 0; i < nodeList.length; i++) {
* @param j end of the line res.push(items.slice(low + 1, up + 1));
* @param lineWidth line width low = nodeList[i];
*/ up = nodeList[i + 1];
function lineCost(items, i, j, lineWidth) {
if (!isBreakPoint(items[j])) {
return Infinity;
}
else {
var tmpItemWidth = 0;
for (var k = i + 1; k < j; k++) {
tmpItemWidth += origWidth(items[k]);
} }
tmpItemWidth += newLineWidth(items[j]); return res;
if (tmpItemWidth > lineWidth) { }
/**genrate the list of point of breaking line. it returns a correct list ascending*/
generateBreakLineNodeList() {
let res = [];
var pointer = this.prevNodes.length - 1;
while (this.prevNodes[pointer] !== undefined) {
res.push(pointer);
pointer = this.prevNodes[pointer];
}
return res.reverse();
}
/** measuring new-line triggered advance width */
newLineWidth(item) {
if (this.isBreakPoint(item)) {
return this.origWidth(item.newLined);
}
else {
// impossible to make a new line
return Infinity;
}
}
/**
* check all the total cost of paragraphes of the segnemt
*/
totalCost(items, lineWidth) {
let itemsLength = items.length;
this.lineCostStorage = Array(itemsLength);
this.prevNodes = Array(itemsLength).fill(null);
for (var i = 0; i < itemsLength; i++) {
this.lineCostStorage[i] = Array(itemsLength).fill(undefined);
}
this.totalCostAuxStorage = Array(itemsLength).fill(undefined);
console.log("===", itemsLength);
let a = this.totalCostAux(items, itemsLength - 1, lineWidth);
console.log(this.lineCostStorage);
return a;
}
/**
* check the total cost item[0..j].
* @param items
* @param i
* @param lineWidth
*/
totalCostAux(items, j, lineWidth) {
if (this.totalCostAuxStorage[j] !== undefined) {
return this.totalCostAuxStorage[j];
}
let rawLineCost = this.lineCost(items, 0, j, lineWidth);
if (rawLineCost != Infinity) {
this.totalCostAuxStorage[j] = rawLineCost;
return rawLineCost;
}
else {
var returnCost = Infinity;
for (var k = 0; k < j; k++) {
let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k + 1, j, lineWidth);
if (returnCost > tmp) {
this.prevNodes[j] = k;
returnCost = tmp;
}
}
this.totalCostAuxStorage[j] = returnCost;
return returnCost;
}
return returnCost;
}
/**
* check the line cost of a line containing items[i..j]
* @param items items of box
* @param i beginning (excluded)
* @param j end of the line
* @param lineWidth line width
*/
lineCost(items, i, j, lineWidth) {
if (this.lineCostStorage[i] !== undefined && this.lineCostStorage[i][j] !== undefined) {
return this.lineCostStorage[i][j];
}
if (!this.isBreakPoint(items[j])) {
this.lineCostStorage[i][j] = Infinity;
return Infinity; return Infinity;
} }
else { else {
return (lineWidth - tmpItemWidth) ** 3.0; var tmpItemWidth = 0;
for (var k = i; k < j; k++) {
tmpItemWidth += this.origWidth(items[k]);
}
tmpItemWidth += this.newLineWidth(items[j]);
if (tmpItemWidth > lineWidth) {
this.lineCostStorage[i][j] = Infinity;
return Infinity;
}
else {
let returnValue = (lineWidth - tmpItemWidth) ** 3.0;
this.lineCostStorage[i][j] = returnValue;
return returnValue;
}
} }
} }
} }
exports.BreakLineAlgorithm = BreakLineAlgorithm;

View file

@ -3,107 +3,182 @@
*/ */
import { join } from "path"; import { join } from "path";
import {BreakPoint, BoxesItem, HGlue} from "./index.js"; import {BreakPoint, BoxesItem, HGlue} from "./index.js";
import { listenerCount } from "process";
import { unwatchFile } from "fs";
/** /**
* Algorithms in LATEX language * Algorithms in LATEX-like language
TotalCost(i) = min_{j}~TotalCost(j) + LineCost(j, i)~~~~j=0, 1, ..., i-1
LineCost(j, i)= \begin{cases}
\infty ~~~ if~~LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]) < 0 \\
\infty~~if~~NOT~~breakable(item[i]) \\
(LineWidth - \sum_{k=j+1}^{i-1} OrigWidth(item[k]) - newLineWidth(item[i]))^3 ~~elsewhere
\end{cases} */
/**check if a boeitem is BreakPoint Type */
function isBreakPoint (item : any) : item is BreakPoint{
return (item as BreakPoint).newLined !== undefined;
}
/**check if a boeitem is BreakPoint Type */
function isHGlue (item : any) : item is HGlue{
return (item as HGlue).stretchFactor !== undefined;
}
/** measuring original advance width */
function origWidth(item : BoxesItem) : number{
if (isBreakPoint(item)){
console.log(item);
return origWidth(item.original);
}else if(Array.isArray(item)){
return item.map((x)=>origWidth(x))
.reduce((acc, current) => acc + current,
0.0,)
}else if(isHGlue(item)){
return 0.0;
}
else{
return item.width;
}
}
/** measuring new-line triggered advance width */
function newLineWidth(item : BoxesItem) : number{
if (isBreakPoint(item)){
return origWidth(item.newLined);
}else{
// impossible to make a new line
return Infinity;
}
}
let lineCostStorage : any = new Object();
/**
* check the total cost item[0..j].
* @param items
* @param i
* @param lineWidth
*/ */
export function totalCost(items : BoxesItem[], j : number, lineWidth: number){
if (j in lineCostStorage){ export class BreakLineAlgorithm {
return lineCostStorage[j];
lineCostStorage : number[][];
totalCostAuxStorage : number[];
prevNodes : number[];
constructor(){
this.prevNodes = [];
this.totalCostAuxStorage = [];
this.lineCostStorage = [[]];
} }
var returnCost = Infinity;
for(var i=-1; i<=j; i++){ /**check if a boeitem is BreakPoint Type */
// lineCost isBreakPoint (item : any) : item is BreakPoint{
let lCost = lineCost(items, i, j, lineWidth); return (item as BreakPoint).newLined !== undefined;
}
if (returnCost > lCost){ /**check if a boeitem is HGlue Type */
returnCost = lCost; isHGlue (item : any) : item is HGlue{
return (item as HGlue).stretchFactor !== undefined;
}
/** measuring original advance width */
origWidth(item : BoxesItem) : number{
if (this.isBreakPoint(item)){
return this.origWidth(item.original);
}else if(Array.isArray(item)){
return item.map((x)=>this.origWidth(x))
.reduce((acc, current) => acc + current,
0.0,)
}else if(this.isHGlue(item)){
return 0.0;
}
else{
return item.width;
} }
} }
lineCostStorage[j] = returnCost; segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{
return returnCost; this.totalCost(items ,lineWidth);
let nodeList = this.generateBreakLineNodeList();
console.log("~~~", nodeList);
let res = [];
let low = -1;
let up = nodeList[0];
} for(var i=0; i<nodeList.length; i++){
res.push(items.slice(low+1, up+1));
low = nodeList[i];
up = nodeList[i+1];
}
return res;
}
/**genrate the list of point of breaking line. it returns a correct list ascending*/
generateBreakLineNodeList() : number[]{
let res : number[] = [];
var pointer = this.prevNodes.length-1;
while (this.prevNodes[pointer] !== undefined){
res.push(pointer);
pointer = this.prevNodes[pointer];
}
return res.reverse();
}
/** measuring new-line triggered advance width */
newLineWidth(item : BoxesItem) : number{
if (this.isBreakPoint(item)){
return this.origWidth(item.newLined);
}else{
// impossible to make a new line
return Infinity;
}
}
/**
* check all the total cost of paragraphes of the segnemt
*/
totalCost(items : BoxesItem[], lineWidth: number) : number{
let itemsLength = items.length;
this.lineCostStorage = Array(itemsLength);
this.prevNodes = Array(itemsLength).fill(null);
for (var i=0; i<itemsLength; i++){
/** this.lineCostStorage[i] = Array(itemsLength).fill(undefined);
* check the line cost of a line containing items[i+1..j]
* @param items items of box
* @param i beginning (excluded)
* @param j end of the line
* @param lineWidth line width
*/
function lineCost(items : BoxesItem[], i : number, j : number, lineWidth: number){
if (!isBreakPoint(items[j])){
return Infinity;
}else{
var tmpItemWidth = 0;
for (var k = i+1; k<j; k++){
tmpItemWidth += origWidth(items[k]);
} }
tmpItemWidth += newLineWidth(items[j]); this.totalCostAuxStorage = Array(itemsLength).fill(undefined);
console.log("===", itemsLength);
let a = this.totalCostAux(items, itemsLength-1, lineWidth);
console.log(this.lineCostStorage);
return a;
if (tmpItemWidth > lineWidth){ }
/**
* check the total cost item[0..j].
* @param items
* @param i
* @param lineWidth
*/
totalCostAux(items : BoxesItem[], j : number, lineWidth: number): number{
if (this.totalCostAuxStorage[j] !== undefined){
return this.totalCostAuxStorage[j];
}
let rawLineCost = this.lineCost(items, 0, j, lineWidth);
if (rawLineCost != Infinity){
this.totalCostAuxStorage[j] = rawLineCost;
return rawLineCost;
}else{
var returnCost = Infinity;
for(var k=0; k<j; k++){
let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k+1,j, lineWidth);
if (returnCost > tmp){
this.prevNodes[j] = k;
returnCost = tmp;
}
}
this.totalCostAuxStorage[j] = returnCost;
return returnCost;
}
return returnCost;
}
/**
* check the line cost of a line containing items[i..j]
* @param items items of box
* @param i beginning (excluded)
* @param j end of the line
* @param lineWidth line width
*/
lineCost(items : BoxesItem[], i : number, j : number, lineWidth: number) : number{
if (this.lineCostStorage[i] !== undefined && this.lineCostStorage[i][j] !== undefined){
return this.lineCostStorage[i][j];
}
if (!this.isBreakPoint(items[j])){
this.lineCostStorage[i][j] = Infinity;
return Infinity; return Infinity;
}else{ }else{
return (lineWidth - tmpItemWidth)**3.0; var tmpItemWidth = 0;
for (var k = i; k<j; k++){
tmpItemWidth += this.origWidth(items[k]);
}
tmpItemWidth += this.newLineWidth(items[j]);
if (tmpItemWidth > lineWidth){
this.lineCostStorage[i][j] = Infinity;
return Infinity;
}else{
let returnValue = (lineWidth - tmpItemWidth)**3.0;
this.lineCostStorage[i][j] = returnValue;
return returnValue;
}
} }
} }
} }

View file

@ -35,7 +35,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.Clo = exports.calculateTextWidthHeightAux = exports.calculateTextWidthHeight = exports.hyphenTkTree = exports.filterEmptyString = exports.spacesToBreakpoint = exports.hyphenForClo = exports.splitCJKV = exports.twoReturnsToNewline = exports.ptToPx = exports.cjkvRegexPattern = exports.cjkvBlocksInRegex = exports.defaultFrameStyle = exports.defaultTextStyle = exports.A4_IN_PX = exports.Direction = void 0; exports.Clo = exports.calculateTextWidthHeightAux = exports.calculateTextWidthHeight = exports.hyphenTkTree = exports.filterEmptyString = exports.spacesToBreakpoint = exports.hyphenForClo = exports.splitCJKV = exports.twoReturnsToNewline = exports.ptToPx = exports.cjkvRegexPattern = exports.cjkvBlocksInRegex = exports.defaultFrameStyle = exports.defaultTextStyle = exports.A4_IN_PX = exports.Direction = void 0;
const canva_1 = require("../canva"); const canva_1 = require("../canva");
const fontkit = __importStar(require("fontkit")); const fontkit = __importStar(require("fontkit"));
const util = __importStar(require("node:util"));
const breakLines = __importStar(require("./breakLines")); const breakLines = __importStar(require("./breakLines"));
/** /**
* TYPES * TYPES
@ -360,11 +359,127 @@ class Clo {
// generate the width and height of the stream // generate the width and height of the stream
let defaultFontStyle = this.attrs["defaultFrameStyle"].textStyle; let defaultFontStyle = this.attrs["defaultFrameStyle"].textStyle;
let a = yield calculateTextWidthHeight(preprocessed, defaultFontStyle); let a = yield calculateTextWidthHeight(preprocessed, defaultFontStyle);
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
// TODO // TODO
console.log(util.inspect(a, true, 100)); //console.log(breakLineAlgorithms.totalCost(a,70));
console.log(breakLines.totalCost(a, 3, 100)); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, 70);
console.log(this.segmentedNodesToFrameBox(segmentedNodes, this.attrs["defaultFrameStyle"]));
}); });
} }
segmentedNodesToFrameBox(segmentedNodes, frame) {
let baseLineskip = frame.baseLineskip;
let boxArrayEmpty = [];
let bigBox = {
x: frame.x,
y: frame.y,
textStyle: frame.textStyle,
direction: frame.direction,
width: frame.width,
height: frame.height,
content: boxArrayEmpty,
};
var bigBoxContent = boxArrayEmpty;
let segmentedNodesFixed = segmentedNodes.map((x) => this.removeBreakPoints(x).flat());
let segmentedNodeUnglue = segmentedNodesFixed.map((x) => this.removeGlue(x, frame).flat());
for (var i = 0; i < segmentedNodesFixed.length - 1; i++) {
var currentLineSkip = baseLineskip;
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
if (currentLineSkip === null || glyphMaxHeight > currentLineSkip) {
currentLineSkip = glyphMaxHeight;
}
var currentLineBox = {
x: null,
y: null,
textStyle: exports.defaultTextStyle,
direction: frame.directionInsideLine,
width: frame.width,
height: currentLineSkip,
content: segmentedNodeUnglue[i],
};
bigBoxContent.push(currentLineBox);
}
bigBox.content = bigBoxContent;
return bigBox;
}
/**
* get the max height of the glyph`[a, b, c]`
* @param nodeLine the node line [a, b, c, ...]
* @returns
*/
getGlyphMaxHeight(nodeLine) {
let segmentedNodeLineHeight = nodeLine.map((x) => { if ("height" in x && x.height > 0.0) {
return x.height;
}
else {
return 0.0;
} });
let maxHeight = Math.max(...segmentedNodeLineHeight);
return maxHeight;
}
removeGlue(nodeLine, frame) {
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
let glueRemoved = nodeLine.filter((x) => !breakLineAlgorithms.isHGlue(x));
let onlyGlue = nodeLine.filter((x) => breakLineAlgorithms.isHGlue(x));
let sumStretchFactor = onlyGlue.map((x) => { if ("stretchFactor" in x) {
return x.stretchFactor;
}
else {
return 0;
} })
.reduce((acc, cur) => acc + cur, 0);
let glueRemovedWidth = glueRemoved.map((x) => { if ("width" in x) {
return x.width;
}
else {
return 0;
} })
.reduce((acc, cur) => acc + cur, 0);
let offset = frame.width - glueRemovedWidth;
var res = [];
for (var i = 0; i < nodeLine.length; i++) {
var ele = nodeLine[i];
if (breakLineAlgorithms.isHGlue(ele)) {
let tmp = {
x: null,
y: null,
textStyle: null,
direction: frame.directionInsideLine,
width: ele.stretchFactor / sumStretchFactor * offset,
height: 0,
content: "",
};
res.push(tmp);
}
else {
res.push(ele);
}
}
return res;
}
/**
* remove breakpoints
* @param boxitemline boxitem in a line with a breakpoint
* @returns boxitemline with break points removed
*/
removeBreakPoints(boxitemline) {
var res = [];
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
for (var i = 0; i < boxitemline.length; i++) {
let ele = boxitemline[i];
if (breakLineAlgorithms.isBreakPoint(ele)) {
if (i == boxitemline.length - 1) {
res.push(ele.newLined);
}
else {
res.push(ele.original);
}
}
else {
res.push(ele);
}
}
return res;
}
} }
exports.Clo = Clo; exports.Clo = Clo;
/* /*

View file

@ -438,14 +438,133 @@ export class Clo{
let defaultFontStyle : TextStyle = this.attrs["defaultFrameStyle"].textStyle; let defaultFontStyle : TextStyle = this.attrs["defaultFrameStyle"].textStyle;
let a = await calculateTextWidthHeight(preprocessed, defaultFontStyle); let a = await calculateTextWidthHeight(preprocessed, defaultFontStyle);
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
// TODO // TODO
console.log(util.inspect(a, true, 100)); //console.log(breakLineAlgorithms.totalCost(a,70));
console.log(breakLines.totalCost(a,3,100)); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, 70);
console.log(this.segmentedNodesToFrameBox(segmentedNodes, <FrameBox>this.attrs["defaultFrameStyle"]));
}
segmentedNodesToFrameBox(segmentedNodes : BoxesItem[][], frame : FrameBox) : Box{
let baseLineskip = frame.baseLineskip;
let boxArrayEmpty : Box[] = [];
let bigBox : Box = {
x : frame.x,
y : frame.y,
textStyle : frame.textStyle,
direction : frame.direction,
width : frame.width,
height : frame.height,
content : boxArrayEmpty,
}
var bigBoxContent : Box[] = boxArrayEmpty;
let segmentedNodesFixed = segmentedNodes.map((x)=>this.removeBreakPoints
(x).flat());
let segmentedNodeUnglue = segmentedNodesFixed.map((x)=>this.removeGlue(x, frame).flat());
for (var i=0; i<segmentedNodesFixed.length-1; i++){
var currentLineSkip = baseLineskip;
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
if (currentLineSkip === null || glyphMaxHeight >currentLineSkip ){
currentLineSkip = glyphMaxHeight;
}
var currentLineBox : Box = {
x : null,
y : null,
textStyle : defaultTextStyle,
direction : frame.directionInsideLine,
width : frame.width,
height : currentLineSkip,
content : <Box[]>segmentedNodeUnglue[i],
}
bigBoxContent.push(currentLineBox);
}
bigBox.content = bigBoxContent;
return bigBox;
}
/**
* get the max height of the glyph`[a, b, c]`
* @param nodeLine the node line [a, b, c, ...]
* @returns
*/
getGlyphMaxHeight(nodeLine : BoxesItem[]) : number{
let segmentedNodeLineHeight = nodeLine.map((x : BoxesItem)=>{if ("height" in x && x.height > 0.0){return x.height}else{return 0.0}});
let maxHeight = Math.max(...segmentedNodeLineHeight);
return maxHeight;
}
removeGlue(nodeLine : BoxesItem[], frame : FrameBox) : BoxesItem[]{
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
let glueRemoved = nodeLine.filter((x)=>!breakLineAlgorithms.isHGlue(x));
let onlyGlue = nodeLine.filter((x)=>breakLineAlgorithms.isHGlue(x));
let sumStretchFactor = onlyGlue.map((x)=>{if("stretchFactor" in x){ return x.stretchFactor} else{return 0;}})
.reduce((acc, cur)=>acc+cur , 0);
let glueRemovedWidth = glueRemoved.map((x)=>{if("width" in x){ return x.width} else{return 0;}})
.reduce((acc, cur)=>acc+cur , 0);
let offset = frame.width - glueRemovedWidth;
var res = [];
for (var i=0; i<nodeLine.length; i++){
var ele = nodeLine[i];
if (breakLineAlgorithms.isHGlue(ele)){
let tmp : Box = {
x : null,
y : null,
textStyle : null,
direction : frame.directionInsideLine,
width : ele.stretchFactor / sumStretchFactor * offset,
height : 0,
content : "",
}
res.push(tmp);
}else{
res.push(ele);
}
}
return res;
}
/**
* remove breakpoints
* @param boxitemline boxitem in a line with a breakpoint
* @returns boxitemline with break points removed
*/
removeBreakPoints(boxitemline : BoxesItem[]) : BoxesItem[]{
var res : BoxesItem[] = [];
let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
for (var i = 0; i<boxitemline.length; i++){
let ele = boxitemline[i];
if (breakLineAlgorithms.isBreakPoint(ele)){
if (i == boxitemline.length-1){
res.push(ele.newLined);
}else{
res.push(ele.original);
}
}else{
res.push(ele);
}
}
return res;
} }
} }
/* /*
export let a = new Clo(); export let a = new Clo();
export default a; */ export default a; */