231120 fix the algorithm

This commit is contained in:
Tan, Kian-ting 2023-11-20 21:48:10 +08:00
parent e9819c8bc2
commit ea033498d7
8 changed files with 65 additions and 51 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ node_modules
.vscode .vscode
activate.sh activate.sh
docs/.nojekyll docs/.nojekyll
debug.log

7
b.clo
View file

@ -1,4 +1,5 @@
--- ---
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. All things were made by him; and without him was not any thing made that was made. In the beginning was the Word, and the Word was with God, and the Word was God. The same was
In him was life; and the life was the light of men. in the beginning with God. All things were made by him; and without him was not any thing made that
And the light shineth in darkness; and the darkness comprehended it not. was made. In him was life; and the life was the light of men. And the light shineth in darkness; and
the darkness comprehended it not. There was a man sent from God, whose name was John.

6
b.js
View file

@ -9,9 +9,9 @@ let clo = new cloLib.Clo();
/* CLO: beginning of middle part*/ /* CLO: beginning of middle part*/
clo.mainStream = /* CLO: end of middle part*/ clo.mainStream = /* CLO: end of middle part*/
[`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.`, ` `, `All`, ` `, `things`, ` `, `were`, ` `, `made`, ` `, `by`, ` `, `him`, `;`, ` `, `and`, ` `, `without`, ` `, `him`, ` `, `was`, ` `, `not`, ` `, `any`, ` `, `thing`, ` `, `made`, ` `, `that`, ` `, `was`, ` `, `made.`, ` [`In`, ` `, `the`, ` `, `beginning`, ` `, `was`, ` `, `the`, ` `, `Word,`, ` `, `and`, ` `, `the`, ` `, `Word`, ` `, `was`, ` `, `with`, ` `, `God,`, ` `, `and`, ` `, `the`, ` `, `Word`, ` `, `was`, ` `, `God.`, ` `, `The`, ` `, `same`, ` `, `was`, `
`, `In`, ` `, `him`, ` `, `was`, ` `, `life`, `;`, ` `, `and`, ` `, `the`, ` `, `life`, ` `, `was`, ` `, `the`, ` `, `light`, ` `, `of`, ` `, `men.`, ` `, `in`, ` `, `the`, ` `, `beginning`, ` `, `with`, ` `, `God.`, ` `, `All`, ` `, `things`, ` `, `were`, ` `, `made`, ` `, `by`, ` `, `him`, `;`, ` `, `and`, ` `, `without`, ` `, `him`, ` `, `was`, ` `, `not`, ` `, `any`, ` `, `thing`, ` `, `made`, ` `, `that`, `
`, `And`, ` `, `the`, ` `, `light`, ` `, `shineth`, ` `, `in`, ` `, `darkness`, `;`, ` `, `and`, ` `, `the`, ` `, `darkness`, ` `, `comprehended`, ` `, `it`, ` `, `not.`, ` `]; `, `was`, ` `, `made.`, ` `, `In`, ` `, `him`, ` `, `was`, ` `, `life`, `;`, ` `, `and`, ` `, `the`, ` `, `life`, ` `, `was`, ` `, `the`, ` `, `light`, ` `, `of`, ` `, `men.`, ` `, `And`, ` `, `the`, ` `, `light`, ` `, `shineth`, ` `, `in`, ` `, `darkness`, `;`, ` `, `and`, ` `, `the`, ` `, `darkness`, ` `, `comprehended`, ` `, `it`, ` `, `not.`, ["hglue", "10000"], " "];
/* CLO: beginning of end part*/ /* CLO: beginning of end part*/
clo.generatePdf(); clo.generatePdf();
/*CLO : end of end part*/ /*CLO : end of end part*/

Binary file not shown.

View file

@ -35,10 +35,9 @@ class BreakLineAlgorithm {
} }
} }
segmentedNodes(items, lineWidth) { segmentedNodes(items, lineWidth) {
let lineWidthFixed = lineWidth * 0.75; let lineWidthFixed = lineWidth;
this.totalCost(items, lineWidthFixed); this.totalCost(items, lineWidthFixed);
let nodeList = this.generateBreakLineNodeList(); let nodeList = this.generateBreakLineNodeList();
console.log("~~~", nodeList);
let res = []; let res = [];
let low = -1; let low = -1;
let up = nodeList[0]; let up = nodeList[0];
@ -47,7 +46,6 @@ class BreakLineAlgorithm {
low = nodeList[i]; low = nodeList[i];
up = nodeList[i + 1]; up = nodeList[i + 1];
} }
console.log("===", res.length);
return res; return res;
} }
/**genrate the list of point of breaking line. it returns a correct list ascending*/ /**genrate the list of point of breaking line. it returns a correct list ascending*/
@ -74,6 +72,7 @@ class BreakLineAlgorithm {
* check all the total cost of paragraphes of the segnemt * check all the total cost of paragraphes of the segnemt
*/ */
totalCost(items, lineWidth) { totalCost(items, lineWidth) {
let lineWidthFixed = lineWidth * 0.75;
let itemsLength = items.length; let itemsLength = items.length;
this.lineCostStorage = Array(itemsLength); this.lineCostStorage = Array(itemsLength);
this.prevNodes = Array(itemsLength).fill(null); this.prevNodes = Array(itemsLength).fill(null);
@ -81,7 +80,16 @@ class BreakLineAlgorithm {
this.lineCostStorage[i] = Array(itemsLength).fill(null); this.lineCostStorage[i] = Array(itemsLength).fill(null);
} }
this.totalCostAuxStorage = Array(itemsLength).fill(null); this.totalCostAuxStorage = Array(itemsLength).fill(null);
let a = this.totalCostAux(items, itemsLength - 1, lineWidth); let a = Infinity;
for (var k = itemsLength - 2; this.lineCost(items, k + 1, itemsLength - 1, lineWidthFixed) < Infinity; k--) {
let tmp = this.totalCostAux(items, k, lineWidthFixed);
if (a > tmp) {
this.prevNodes[itemsLength - 1] = k;
a = tmp;
}
}
console.log("~~~", lineWidth);
console.log(items[itemsLength - 2]);
return a; return a;
} }
/** /**
@ -96,13 +104,13 @@ class BreakLineAlgorithm {
} }
let rawLineCost = this.lineCost(items, 0, j, lineWidth); let rawLineCost = this.lineCost(items, 0, j, lineWidth);
if (rawLineCost != Infinity) { if (rawLineCost != Infinity) {
this.totalCostAuxStorage[j] = rawLineCost; this.totalCostAuxStorage[j] = rawLineCost ** 3.0;
return rawLineCost; return rawLineCost ** 3.0;
} }
else { else {
var returnCost = Infinity; var returnCost = Infinity;
for (var k = 0; k < j; k++) { for (var k = 0; k < j; k++) {
let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k + 1, j, lineWidth); let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k + 1, j, lineWidth) ** 3.0;
if (returnCost > tmp) { if (returnCost > tmp) {
this.prevNodes[j] = k; this.prevNodes[j] = k;
returnCost = tmp; returnCost = tmp;
@ -139,7 +147,7 @@ class BreakLineAlgorithm {
return Infinity; return Infinity;
} }
else { else {
let returnValue = (lineWidth - tmpItemWidth) ** 3.0; let returnValue = (lineWidth - tmpItemWidth);
this.lineCostStorage[i][j] = returnValue; this.lineCostStorage[i][j] = returnValue;
return returnValue; return returnValue;
} }

View file

@ -2,7 +2,7 @@
* Algorithms and functions for LineBreaking * Algorithms and functions for LineBreaking
*/ */
import { join } from "path"; import { join } from "path";
import {BreakPoint, BoxesItem, HGlue} from "./index.js"; import {BreakPoint, BoxesItem, HGlue, CharBox} from "./index.js";
import { listenerCount } from "process"; import { listenerCount } from "process";
import { unwatchFile } from "fs"; import { unwatchFile } from "fs";
/** /**
@ -51,10 +51,9 @@ export class BreakLineAlgorithm {
} }
segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{ segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{
let lineWidthFixed = lineWidth * 0.75; let lineWidthFixed = lineWidth;
this.totalCost(items ,lineWidthFixed); this.totalCost(items ,lineWidthFixed);
let nodeList = this.generateBreakLineNodeList(); let nodeList = this.generateBreakLineNodeList();
console.log("~~~", nodeList);
let res = []; let res = [];
let low = -1; let low = -1;
let up = nodeList[0]; let up = nodeList[0];
@ -65,7 +64,6 @@ export class BreakLineAlgorithm {
up = nodeList[i+1]; up = nodeList[i+1];
} }
console.log("===", res.length);
return res; return res;
} }
@ -93,7 +91,7 @@ export class BreakLineAlgorithm {
* check all the total cost of paragraphes of the segnemt * check all the total cost of paragraphes of the segnemt
*/ */
totalCost(items : BoxesItem[], lineWidth: number) : number{ totalCost(items : BoxesItem[], lineWidth: number) : number{
let lineWidthFixed = lineWidth * 0.75;
let itemsLength = items.length; let itemsLength = items.length;
this.lineCostStorage = Array(itemsLength); this.lineCostStorage = Array(itemsLength);
this.prevNodes = Array(itemsLength).fill(null); this.prevNodes = Array(itemsLength).fill(null);
@ -104,7 +102,19 @@ export class BreakLineAlgorithm {
} }
this.totalCostAuxStorage = Array(itemsLength).fill(null); this.totalCostAuxStorage = Array(itemsLength).fill(null);
let a = this.totalCostAux(items, itemsLength-1, lineWidth);
let a = Infinity;
for(var k=itemsLength-2; this.lineCost(items, k+1,itemsLength-1, lineWidthFixed) < Infinity; k--){
let tmp = this.totalCostAux(items, k, lineWidthFixed);
if (a > tmp){
this.prevNodes[itemsLength-1] = k
a = tmp;
}
}
console.log("~~~", lineWidth);
console.log((<CharBox>items[itemsLength-2]));
return a; return a;
} }
@ -123,12 +133,12 @@ export class BreakLineAlgorithm {
let rawLineCost = this.lineCost(items, 0, j, lineWidth); let rawLineCost = this.lineCost(items, 0, j, lineWidth);
if (rawLineCost != Infinity){ if (rawLineCost != Infinity){
this.totalCostAuxStorage[j] = rawLineCost; this.totalCostAuxStorage[j] = rawLineCost**3.0;
return rawLineCost; return rawLineCost**3.0;
}else{ }else{
var returnCost = Infinity; var returnCost = Infinity;
for(var k=0; k<j; k++){ for(var k=0; k<j; k++){
let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k+1,j, lineWidth); let tmp = this.totalCostAux(items, k, lineWidth) + this.lineCost(items, k+1,j, lineWidth)**3.0;
if (returnCost > tmp){ if (returnCost > tmp){
this.prevNodes[j] = k; this.prevNodes[j] = k;
returnCost = tmp; returnCost = tmp;
@ -173,7 +183,7 @@ export class BreakLineAlgorithm {
this.lineCostStorage[i][j] = Infinity; this.lineCostStorage[i][j] = Infinity;
return Infinity; return Infinity;
}else{ }else{
let returnValue = (lineWidth - tmpItemWidth)**3.0; let returnValue = (lineWidth - tmpItemWidth);
this.lineCostStorage[i][j] = returnValue; this.lineCostStorage[i][j] = returnValue;
return returnValue; return returnValue;
} }

View file

@ -70,8 +70,8 @@ exports.defaultFrameStyle = {
direction: Direction.TTB, direction: Direction.TTB,
baseLineskip: ptToPx(15), baseLineskip: ptToPx(15),
textStyle: exports.defaultTextStyle, textStyle: exports.defaultTextStyle,
x: exports.A4_IN_PX.width * 0.10 * 0.75, x: exports.A4_IN_PX.width * 0.10,
y: exports.A4_IN_PX.height * 0.10 * 0.75, y: exports.A4_IN_PX.height * 0.10,
width: exports.A4_IN_PX.width * 0.80, width: exports.A4_IN_PX.width * 0.80,
height: exports.A4_IN_PX.height * 0.80, height: exports.A4_IN_PX.height * 0.80,
content: null, content: null,
@ -277,8 +277,8 @@ function calculateTextWidthHeightAux(element, style) {
y: null, y: null,
textStyle: style, textStyle: style,
direction: Direction.LTR, direction: Direction.LTR,
width: (runGlyphsItem.advanceWidth) * (style.size) * 0.75 / 1000, width: (runGlyphsItem.advanceWidth) * (style.size) / 1000 * 0.75,
height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) * 0.75 / 1000, height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) / 1000 * 0.75,
content: element[j], content: element[j],
minX: runGlyphsItem.bbox.minX, minX: runGlyphsItem.bbox.minX,
maxX: runGlyphsItem.bbox.maxX, maxX: runGlyphsItem.bbox.maxX,
@ -365,7 +365,6 @@ class Clo {
// TODO // TODO
//console.log(breakLineAlgorithms.totalCost(a,70)); //console.log(breakLineAlgorithms.totalCost(a,70));
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width);
console.log(this.attrs.defaultFrameStyle.width);
let segmentedNodesToBox = this.segmentedNodesToFrameBox(segmentedNodes, this.attrs.defaultFrameStyle); let segmentedNodesToBox = this.segmentedNodesToFrameBox(segmentedNodes, this.attrs.defaultFrameStyle);
let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox); let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox);
// generate pdf7 // generate pdf7
@ -389,7 +388,7 @@ class Clo {
else { else {
doc doc
.font(fontInfo.path) .font(fontInfo.path)
.fontSize(box.textStyle.size * 0.75); .fontSize(box.textStyle.size * 0.75); // 0.75 must added!
} }
if (box.textStyle.color !== undefined) { if (box.textStyle.color !== undefined) {
doc.fill(box.textStyle.color); doc.fill(box.textStyle.color);
@ -400,7 +399,6 @@ class Clo {
} }
} }
else if (box.content !== null) { else if (box.content !== null) {
console.log(box.content, box.x, box.y);
yield doc.text(box.content, (box.x !== null ? box.x : undefined), (box.y !== null ? box.y : undefined)); yield doc.text(box.content, (box.x !== null ? box.x : undefined), (box.y !== null ? box.y : undefined));
} }
} }
@ -461,7 +459,6 @@ class Clo {
* @returns the fixed boxes * @returns the fixed boxes
*/ */
fixenBoxesPosition(box) { fixenBoxesPosition(box) {
console.log("~~~~~", box);
var currX = (box.x !== null ? box.x : 0); // current x var currX = (box.x !== null ? box.x : 0); // current x
var currY = (box.y !== null ? box.y : 0); // current y var currY = (box.y !== null ? box.y : 0); // current y
if (Array.isArray(box.content)) { if (Array.isArray(box.content)) {
@ -497,8 +494,8 @@ class Clo {
let baseLineskip = frame.baseLineskip; let baseLineskip = frame.baseLineskip;
let boxArrayEmpty = []; let boxArrayEmpty = [];
let bigBox = { let bigBox = {
x: frame.x, x: (frame.x !== null ? frame.x * 0.75 : null),
y: frame.y, y: (frame.y !== null ? frame.y * 0.75 : null),
textStyle: frame.textStyle, textStyle: frame.textStyle,
direction: frame.direction, direction: frame.direction,
width: frame.width, width: frame.width,
@ -562,7 +559,6 @@ class Clo {
} }) } })
.reduce((acc, cur) => acc + cur, 0); .reduce((acc, cur) => acc + cur, 0);
let offset = frame.width * 0.75 - glueRemovedWidth; let offset = frame.width * 0.75 - glueRemovedWidth;
console.log("OFFSET", offset);
var res = []; var res = [];
for (var i = 0; i < nodeLine.length; i++) { for (var i = 0; i < nodeLine.length; i++) {
var ele = nodeLine[i]; var ele = nodeLine[i];
@ -572,6 +568,7 @@ class Clo {
y: null, y: null,
textStyle: null, textStyle: null,
direction: frame.directionInsideLine, direction: frame.directionInsideLine,
//width : 0, // ragged
width: ele.stretchFactor / sumStretchFactor * offset, width: ele.stretchFactor / sumStretchFactor * offset,
height: 0, height: 0,
content: "", content: "",

View file

@ -58,11 +58,11 @@ export interface CharBox extends Box{
/** /**
* a basic Box * a basic Box
* - x : * - x : pt
* - y : * - y : pt
* - textStyle : * - textStyle :
* - direction : * - direction :
* - width : x_advance * - width : x_advance pt
* - content : * - content :
*/ */
export interface Box{ export interface Box{
@ -94,8 +94,8 @@ export const defaultFrameStyle : FrameBox = {
direction : Direction.TTB, direction : Direction.TTB,
baseLineskip : ptToPx(15), baseLineskip : ptToPx(15),
textStyle : defaultTextStyle, textStyle : defaultTextStyle,
x : A4_IN_PX.width * 0.10 * 0.75, x : A4_IN_PX.width * 0.10 ,
y : A4_IN_PX.height * 0.10 * 0.75, y : A4_IN_PX.height * 0.10 ,
width : A4_IN_PX.width * 0.80 , width : A4_IN_PX.width * 0.80 ,
height : A4_IN_PX.height * 0.80 , height : A4_IN_PX.height * 0.80 ,
content : null, content : null,
@ -328,8 +328,8 @@ export async function calculateTextWidthHeightAux(element : tkTree, style : Text
y : null, y : null,
textStyle : style, textStyle : style,
direction : Direction.LTR, direction : Direction.LTR,
width : (runGlyphsItem.advanceWidth)*(style.size)*0.75/1000, width : (runGlyphsItem.advanceWidth)*(style.size)/1000 * 0.75, // in pt
height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)*0.75/1000, height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)/1000 * 0.75, // in pt
content : element[j], content : element[j],
minX : runGlyphsItem.bbox.minX, minX : runGlyphsItem.bbox.minX,
maxX : runGlyphsItem.bbox.maxX, maxX : runGlyphsItem.bbox.maxX,
@ -443,7 +443,6 @@ export class Clo{
//console.log(breakLineAlgorithms.totalCost(a,70)); //console.log(breakLineAlgorithms.totalCost(a,70));
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width);
console.log(this.attrs.defaultFrameStyle.width);
let segmentedNodesToBox = let segmentedNodesToBox =
this.segmentedNodesToFrameBox(segmentedNodes, <FrameBox>this.attrs.defaultFrameStyle); this.segmentedNodesToFrameBox(segmentedNodes, <FrameBox>this.attrs.defaultFrameStyle);
@ -473,11 +472,11 @@ export class Clo{
if (fontInfo.path.match(/\.ttc$/g)){ if (fontInfo.path.match(/\.ttc$/g)){
doc doc
.font(fontInfo.path, fontInfo.psName) .font(fontInfo.path, fontInfo.psName)
.fontSize(box.textStyle.size*0.75);} .fontSize(box.textStyle.size * 0.75);}
else{ else{
doc doc
.font(fontInfo.path) .font(fontInfo.path)
.fontSize(box.textStyle.size*0.75); .fontSize(box.textStyle.size * 0.75); // 0.75 must added!
} }
if (box.textStyle.color !== undefined){ if (box.textStyle.color !== undefined){
@ -490,7 +489,6 @@ export class Clo{
doc = await this.putText(doc, box.content[k]); doc = await this.putText(doc, box.content[k]);
} }
}else if (box.content !== null){ }else if (box.content !== null){
console.log(box.content, box.x, box.y);
await doc.text(box.content, await doc.text(box.content,
(box.x!==null? box.x: undefined), (box.x!==null? box.x: undefined),
(box.y!==null? box.y: undefined)); (box.y!==null? box.y: undefined));
@ -560,7 +558,6 @@ export class Clo{
* @returns the fixed boxes * @returns the fixed boxes
*/ */
fixenBoxesPosition(box : Box) : Box{ fixenBoxesPosition(box : Box) : Box{
console.log("~~~~~", box);
var currX : number = (box.x!==null?box.x:0); // current x var currX : number = (box.x!==null?box.x:0); // current x
var currY : number =(box.y!==null?box.y:0); // current y var currY : number =(box.y!==null?box.y:0); // current y
if (Array.isArray(box.content)){ if (Array.isArray(box.content)){
@ -602,12 +599,12 @@ export class Clo{
let baseLineskip = frame.baseLineskip; let baseLineskip = frame.baseLineskip;
let boxArrayEmpty : Box[] = []; let boxArrayEmpty : Box[] = [];
let bigBox : Box = { let bigBox : Box = {
x : frame.x, x : (frame.x !==null? frame.x * 0.75 : null),
y : frame.y, y : (frame.y !==null? frame.y * 0.75 : null),
textStyle : frame.textStyle, textStyle : frame.textStyle,
direction : frame.direction, direction : frame.direction,
width : frame.width, width : frame.width,
height : frame.height, height :frame.height,
content : boxArrayEmpty, content : boxArrayEmpty,
} }
@ -664,7 +661,6 @@ export class Clo{
let glueRemovedWidth = glueRemoved.map((x)=>{if("width" in x){ return x.width} else{return 0;}}) let glueRemovedWidth = glueRemoved.map((x)=>{if("width" in x){ return x.width} else{return 0;}})
.reduce((acc, cur)=>acc+cur , 0); .reduce((acc, cur)=>acc+cur , 0);
let offset = frame.width * 0.75 - glueRemovedWidth; let offset = frame.width * 0.75 - glueRemovedWidth;
console.log("OFFSET", offset);
var res = []; var res = [];
for (var i=0; i<nodeLine.length; i++){ for (var i=0; i<nodeLine.length; i++){
var ele = nodeLine[i]; var ele = nodeLine[i];
@ -674,6 +670,7 @@ export class Clo{
y : null, y : null,
textStyle : null, textStyle : null,
direction : frame.directionInsideLine, direction : frame.directionInsideLine,
//width : 0, // ragged
width : ele.stretchFactor / sumStretchFactor * offset, width : ele.stretchFactor / sumStretchFactor * offset,
height : 0, height : 0,
content : "", content : "",