basic types laying.

This commit is contained in:
Tan, Kian-ting 2023-11-16 01:16:44 +08:00
parent 9c51921978
commit e9819c8bc2
11 changed files with 337 additions and 108 deletions

View file

@ -36,6 +36,7 @@
- 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. - 20231113: the algorithm is basically fixed, and make a `bigFrame` to prepare for convert to boxes and positions.
- 20231115-16: grid and basic types laying.
## 之後的做法 ## 之後的做法
- 先做一個前處理註冊器,註冊下列的前處理 - 先做一個前處理註冊器,註冊下列的前處理

4
b.clo
View file

@ -1,2 +1,4 @@
--- ---
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. 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 him was life; and the life was the light of men.
And the light shineth in darkness; and the darkness comprehended it not.

4
b.js
View file

@ -9,7 +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.`, ` `]; [`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`, ` `, `him`, ` `, `was`, ` `, `life`, `;`, ` `, `and`, ` `, `the`, ` `, `life`, ` `, `was`, ` `, `the`, ` `, `light`, ` `, `of`, ` `, `men.`, `
`, `And`, ` `, `the`, ` `, `light`, ` `, `shineth`, ` `, `in`, ` `, `darkness`, `;`, ` `, `and`, ` `, `the`, ` `, `darkness`, ` `, `comprehended`, ` `, `it`, ` `, `not.`, ` `];
/* CLO: beginning of end part*/ /* CLO: beginning of end part*/
clo.generatePdf(); clo.generatePdf();
/*CLO : end of end part*/ /*CLO : end of end part*/

BIN
blank.pdf

Binary file not shown.

BIN
output.pdf Normal file

Binary file not shown.

17
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "0.0.1", "version": "0.0.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@pdf-lib/fontkit": "^1.1.1",
"canvas": "^2.11.2", "canvas": "^2.11.2",
"fontkit": "^2.0.2", "fontkit": "^2.0.2",
"hyphen": "^1.7.0", "hyphen": "^1.7.0",
@ -742,6 +743,14 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@pdf-lib/fontkit": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-1.1.1.tgz",
"integrity": "sha512-KjMd7grNapIWS/Dm0gvfHEilSyAmeLvrEGVcqLGi0VYebuqqzTbgF29efCx7tvx+IEbG3zQciRSWl3GkUSvjZg==",
"dependencies": {
"pako": "^1.0.6"
}
},
"node_modules/@pdf-lib/standard-fonts": { "node_modules/@pdf-lib/standard-fonts": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
@ -11768,6 +11777,14 @@
"fastq": "^1.6.0" "fastq": "^1.6.0"
} }
}, },
"@pdf-lib/fontkit": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-1.1.1.tgz",
"integrity": "sha512-KjMd7grNapIWS/Dm0gvfHEilSyAmeLvrEGVcqLGi0VYebuqqzTbgF29efCx7tvx+IEbG3zQciRSWl3GkUSvjZg==",
"requires": {
"pako": "^1.0.6"
}
},
"@pdf-lib/standard-fonts": { "@pdf-lib/standard-fonts": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",

View file

@ -42,6 +42,7 @@
"typescript": "^5.2.2" "typescript": "^5.2.2"
}, },
"dependencies": { "dependencies": {
"@pdf-lib/fontkit": "^1.1.1",
"canvas": "^2.11.2", "canvas": "^2.11.2",
"fontkit": "^2.0.2", "fontkit": "^2.0.2",
"hyphen": "^1.7.0", "hyphen": "^1.7.0",

View file

@ -35,7 +35,8 @@ class BreakLineAlgorithm {
} }
} }
segmentedNodes(items, lineWidth) { segmentedNodes(items, lineWidth) {
this.totalCost(items, lineWidth); let lineWidthFixed = lineWidth * 0.75;
this.totalCost(items, lineWidthFixed);
let nodeList = this.generateBreakLineNodeList(); let nodeList = this.generateBreakLineNodeList();
console.log("~~~", nodeList); console.log("~~~", nodeList);
let res = []; let res = [];
@ -46,6 +47,7 @@ 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*/
@ -76,12 +78,10 @@ class BreakLineAlgorithm {
this.lineCostStorage = Array(itemsLength); this.lineCostStorage = Array(itemsLength);
this.prevNodes = Array(itemsLength).fill(null); this.prevNodes = Array(itemsLength).fill(null);
for (var i = 0; i < itemsLength; i++) { for (var i = 0; i < itemsLength; i++) {
this.lineCostStorage[i] = Array(itemsLength).fill(undefined); this.lineCostStorage[i] = Array(itemsLength).fill(null);
} }
this.totalCostAuxStorage = Array(itemsLength).fill(undefined); this.totalCostAuxStorage = Array(itemsLength).fill(null);
console.log("===", itemsLength);
let a = this.totalCostAux(items, itemsLength - 1, lineWidth); let a = this.totalCostAux(items, itemsLength - 1, lineWidth);
console.log(this.lineCostStorage);
return a; return a;
} }
/** /**
@ -91,7 +91,7 @@ class BreakLineAlgorithm {
* @param lineWidth * @param lineWidth
*/ */
totalCostAux(items, j, lineWidth) { totalCostAux(items, j, lineWidth) {
if (this.totalCostAuxStorage[j] !== undefined) { if (this.totalCostAuxStorage[j] !== null) {
return this.totalCostAuxStorage[j]; return this.totalCostAuxStorage[j];
} }
let rawLineCost = this.lineCost(items, 0, j, lineWidth); let rawLineCost = this.lineCost(items, 0, j, lineWidth);
@ -121,7 +121,7 @@ class BreakLineAlgorithm {
* @param lineWidth line width * @param lineWidth line width
*/ */
lineCost(items, i, j, lineWidth) { lineCost(items, i, j, lineWidth) {
if (this.lineCostStorage[i] !== undefined && this.lineCostStorage[i][j] !== undefined) { if (this.lineCostStorage[i] !== null && this.lineCostStorage[i][j] !== null) {
return this.lineCostStorage[i][j]; return this.lineCostStorage[i][j];
} }
if (!this.isBreakPoint(items[j])) { if (!this.isBreakPoint(items[j])) {

View file

@ -51,7 +51,8 @@ export class BreakLineAlgorithm {
} }
segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{ segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{
this.totalCost(items ,lineWidth); let lineWidthFixed = lineWidth * 0.75;
this.totalCost(items ,lineWidthFixed);
let nodeList = this.generateBreakLineNodeList(); let nodeList = this.generateBreakLineNodeList();
console.log("~~~", nodeList); console.log("~~~", nodeList);
let res = []; let res = [];
@ -64,6 +65,7 @@ export class BreakLineAlgorithm {
up = nodeList[i+1]; up = nodeList[i+1];
} }
console.log("===", res.length);
return res; return res;
} }
@ -98,13 +100,11 @@ export class BreakLineAlgorithm {
for (var i=0; i<itemsLength; i++){ for (var i=0; i<itemsLength; i++){
this.lineCostStorage[i] = Array(itemsLength).fill(undefined); this.lineCostStorage[i] = Array(itemsLength).fill(null);
} }
this.totalCostAuxStorage = Array(itemsLength).fill(undefined); this.totalCostAuxStorage = Array(itemsLength).fill(null);
console.log("===", itemsLength);
let a = this.totalCostAux(items, itemsLength-1, lineWidth); let a = this.totalCostAux(items, itemsLength-1, lineWidth);
console.log(this.lineCostStorage);
return a; return a;
} }
@ -117,7 +117,7 @@ export class BreakLineAlgorithm {
*/ */
totalCostAux(items : BoxesItem[], j : number, lineWidth: number): number{ totalCostAux(items : BoxesItem[], j : number, lineWidth: number): number{
if (this.totalCostAuxStorage[j] !== undefined){ if (this.totalCostAuxStorage[j] !== null){
return this.totalCostAuxStorage[j]; return this.totalCostAuxStorage[j];
} }
@ -154,7 +154,7 @@ export class BreakLineAlgorithm {
* @param lineWidth line width * @param lineWidth line width
*/ */
lineCost(items : BoxesItem[], i : number, j : number, lineWidth: number) : number{ lineCost(items : BoxesItem[], i : number, j : number, lineWidth: number) : number{
if (this.lineCostStorage[i] !== undefined && this.lineCostStorage[i][j] !== undefined){ if (this.lineCostStorage[i] !== null && this.lineCostStorage[i][j] !== null){
return this.lineCostStorage[i][j]; return this.lineCostStorage[i][j];
} }

View file

@ -36,8 +36,7 @@ exports.Clo = exports.calculateTextWidthHeightAux = exports.calculateTextWidthHe
const canva_1 = require("../canva"); const canva_1 = require("../canva");
const fontkit = __importStar(require("fontkit")); const fontkit = __importStar(require("fontkit"));
const breakLines = __importStar(require("./breakLines")); const breakLines = __importStar(require("./breakLines"));
require("pdfkit"); const PDFDocument = require('pdfkit');
const pdf_lib_1 = require("pdf-lib");
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
/** /**
* TYPES * TYPES
@ -71,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, x: exports.A4_IN_PX.width * 0.10 * 0.75,
y: exports.A4_IN_PX.height * 0.10, y: exports.A4_IN_PX.height * 0.10 * 0.75,
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,
@ -278,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) / 1000, width: (runGlyphsItem.advanceWidth) * (style.size) * 0.75 / 1000,
height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) / 1000, height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) * 0.75 / 1000,
content: element[j], content: element[j],
minX: runGlyphsItem.bbox.minX, minX: runGlyphsItem.bbox.minX,
maxX: runGlyphsItem.bbox.maxX, maxX: runGlyphsItem.bbox.maxX,
@ -360,46 +359,140 @@ class Clo {
preprocessed = this.preprocessors[i](preprocessed, this); preprocessed = this.preprocessors[i](preprocessed, this);
} }
// 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(); let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
// TODO // TODO
//console.log(breakLineAlgorithms.totalCost(a,70)); //console.log(breakLineAlgorithms.totalCost(a,70));
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, 70); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width);
console.log(this.segmentedNodesToFrameBox(segmentedNodes, this.attrs["defaultFrameStyle"])); console.log(this.attrs.defaultFrameStyle.width);
// generate pdf let segmentedNodesToBox = this.segmentedNodesToFrameBox(segmentedNodes, this.attrs.defaultFrameStyle);
const pdfDoc = yield pdf_lib_1.PDFDocument.create(); let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox);
var page = pdfDoc.addPage(); // generate pdf7
page.drawText('You can create PDFs!'); const doc = new PDFDocument({ size: 'A4' });
for (var j = 0; j < 1000; j += 5) { doc.pipe(fs.createWriteStream('output.pdf'));
this.grid(doc);
yield this.putText(doc, boxesFixed);
// putChar
doc.end();
});
}
putText(doc, box) {
return __awaiter(this, void 0, void 0, function* () {
if (box.textStyle !== null) {
let fontInfo = (0, canva_1.fontStyleTofont)(box.textStyle);
if (fontInfo.path.match(/\.ttc$/g)) {
doc
.font(fontInfo.path, fontInfo.psName)
.fontSize(box.textStyle.size * 0.75);
}
else {
doc
.font(fontInfo.path)
.fontSize(box.textStyle.size * 0.75);
}
if (box.textStyle.color !== undefined) {
doc.fill(box.textStyle.color);
}
if (Array.isArray(box.content)) {
for (var k = 0; k < box.content.length; k++) {
doc = yield this.putText(doc, box.content[k]);
}
}
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));
}
}
return doc;
});
}
;
grid(doc) {
for (var j = 0; j < exports.A4_IN_PX.width; j += 5) {
if (j % 50 == 0) { if (j % 50 == 0) {
page.drawText(j.toString(), { x: 50, y: j }); doc.save().fill('#000000')
.fontSize(8).text(j.toString(), j * 0.75, 50);
doc
.save()
.lineWidth(0.4)
.strokeColor("#dddddd")
.moveTo(j * 0.75, 0)
.lineTo(j * 0.75, 1000)
.stroke();
} }
page.drawLine({ doc
start: { x: 0, y: j }, .save()
end: { x: 1000, y: j }, .lineWidth(0.2)
thickness: 0.5, .strokeColor("#dddddd")
color: (0, pdf_lib_1.rgb)(0.75, 0.2, 0.2), .moveTo(j * 0.75, 0)
opacity: 0.20, .lineTo(j * 0.75, 1000)
}); .stroke();
} }
for (var i = 0; i < 1000; i += 5) { for (var i = 0; i < 1050; i += 5) {
if (i % 50 == 0) { if (i % 50 == 0) {
page.drawText(i.toString(), { x: i, y: 50 }); doc.save()
.fontSize(8).text(i.toString(), 50, i * 0.75);
doc
.save()
.lineWidth(0.4)
.strokeColor("#bbbbbb")
.moveTo(0, i * 0.75)
.lineTo(1000, i * 0.75)
.stroke();
} }
page.drawLine({ doc
start: { x: i, y: 0 }, .save()
end: { x: i, y: 1000 }, .lineWidth(0.2)
thickness: 0.5, .strokeColor("#bbbbbb")
color: (0, pdf_lib_1.rgb)(0.75, 0.2, 0.2), .moveTo(0, i * 0.75)
opacity: 0.20, .lineTo(1000, i * 0.75)
}); .stroke();
} }
pdfDoc.save(); doc
const pdfBytes = yield pdfDoc.save(); .save()
fs.writeFileSync("blank.pdf", pdfBytes); .moveTo(0, 200)
}); .lineTo(1000, 200)
.fill('#FF3300');
} }
/**
* make all the nest boxes's position fixed
* @param box the main boxes
* @returns the fixed boxes
*/
fixenBoxesPosition(box) {
console.log("~~~~~", box);
var currX = (box.x !== null ? box.x : 0); // current x
var currY = (box.y !== null ? box.y : 0); // current y
if (Array.isArray(box.content)) {
for (var i = 0; i < box.content.length; i++) {
if (box.direction == Direction.LTR) {
box.content[i].x = currX;
box.content[i].y = currY;
let elementWidth = box.content[i].width;
if (elementWidth !== null) {
currX += elementWidth;
}
}
if (box.direction == Direction.TTB) {
box.content[i].x = currX;
box.content[i].y = currY;
let elementHeight = box.content[i].height;
if (elementHeight !== null) {
currY += elementHeight;
}
}
box.content[i] = this.fixenBoxesPosition(box.content[i]);
}
}
return box;
}
/**
* input a `segmentedNodes` and a layed `frame`, return a big `Box` that nodes is put in.
* @param segmentedNodes the segmentnodes to be input
* @param frame the frame to be layed out.
* @returns the big `Box`.
*/
segmentedNodesToFrameBox(segmentedNodes, frame) { segmentedNodesToFrameBox(segmentedNodes, frame) {
let baseLineskip = frame.baseLineskip; let baseLineskip = frame.baseLineskip;
let boxArrayEmpty = []; let boxArrayEmpty = [];
@ -415,7 +508,7 @@ class Clo {
var bigBoxContent = boxArrayEmpty; var bigBoxContent = boxArrayEmpty;
let segmentedNodesFixed = segmentedNodes.map((x) => this.removeBreakPoints(x).flat()); let segmentedNodesFixed = segmentedNodes.map((x) => this.removeBreakPoints(x).flat());
let segmentedNodeUnglue = segmentedNodesFixed.map((x) => this.removeGlue(x, frame).flat()); let segmentedNodeUnglue = segmentedNodesFixed.map((x) => this.removeGlue(x, frame).flat());
for (var i = 0; i < segmentedNodesFixed.length - 1; i++) { for (var i = 0; i < segmentedNodeUnglue.length; i++) {
var currentLineSkip = baseLineskip; var currentLineSkip = baseLineskip;
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]); var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
if (currentLineSkip === null || glyphMaxHeight > currentLineSkip) { if (currentLineSkip === null || glyphMaxHeight > currentLineSkip) {
@ -468,7 +561,8 @@ class Clo {
return 0; return 0;
} }) } })
.reduce((acc, cur) => acc + cur, 0); .reduce((acc, cur) => acc + cur, 0);
let offset = frame.width - 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];

View file

@ -1,15 +1,11 @@
import { isBoxedPrimitive, isKeyObject, isStringObject } from "util/types";
import {tkTree} from "../parser"; import {tkTree} from "../parser";
import {FontStyle, TextStyle, TextWeight, fontStyleTofont} from "../canva"; import {FontStyle, TextStyle, TextWeight, fontStyleTofont} from "../canva";
import { JSDOM } from "jsdom";
import * as fontkit from "fontkit"; import * as fontkit from "fontkit";
import * as util from "node:util";
import * as breakLines from "./breakLines"; import * as breakLines from "./breakLines";
import "pdfkit"; const PDFDocument = require('pdfkit');
import PDFKitPage from "pdfkit/js/page";
import { ColorTypes, PDFDocument, rgb } from "pdf-lib";
import * as fs from "fs"; import * as fs from "fs";
/** /**
* TYPES * TYPES
*/ */
@ -98,10 +94,10 @@ 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, x : A4_IN_PX.width * 0.10 * 0.75,
y : A4_IN_PX.height * 0.10, y : A4_IN_PX.height * 0.10 * 0.75,
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,
}; };
@ -332,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)/1000, width : (runGlyphsItem.advanceWidth)*(style.size)*0.75/1000,
height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)/1000, height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)*0.75/1000,
content : element[j], content : element[j],
minX : runGlyphsItem.bbox.minX, minX : runGlyphsItem.bbox.minX,
maxX : runGlyphsItem.bbox.maxX, maxX : runGlyphsItem.bbox.maxX,
@ -439,54 +435,169 @@ export class Clo{
} }
// generate the width and height of the stream // generate the width and height of the stream
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(); let breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
// TODO // TODO
//console.log(breakLineAlgorithms.totalCost(a,70)); //console.log(breakLineAlgorithms.totalCost(a,70));
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, 70); let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width);
console.log( console.log(this.attrs.defaultFrameStyle.width);
this.segmentedNodesToFrameBox(segmentedNodes, <FrameBox>this.attrs["defaultFrameStyle"])); let segmentedNodesToBox =
this.segmentedNodesToFrameBox(segmentedNodes, <FrameBox>this.attrs.defaultFrameStyle);
// generate pdf
const pdfDoc = await PDFDocument.create();
var page = pdfDoc.addPage();
page.drawText('You can create PDFs!');
for (var j = 0; j<1000; j+=5){
if (j %50 == 0){ let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox);
page.drawText(j.toString(), {x: 50, y: j});
// generate pdf7
const doc = new PDFDocument({size: 'A4'});
doc.pipe(fs.createWriteStream('output.pdf'));
this.grid(doc);
await this.putText(doc, boxesFixed);
// putChar
doc.end();
} }
page.drawLine({ async putText(doc : PDFKit.PDFDocument, box : Box): Promise<PDFKit.PDFDocument>{
start: { x: 0, y: j },
end: { x: 1000, y: j }, if (box.textStyle !== null){
thickness: 0.5, let fontInfo = fontStyleTofont(box.textStyle);
color: rgb(0.75, 0.2, 0.2),
opacity: 0.20, if (fontInfo.path.match(/\.ttc$/g)){
}); doc
.font(fontInfo.path, fontInfo.psName)
.fontSize(box.textStyle.size*0.75);}
else{
doc
.font(fontInfo.path)
.fontSize(box.textStyle.size*0.75);
} }
for (var i = 0; i<1000; i+=5){ if (box.textStyle.color !== undefined){
if (i % 50 == 0){ doc.fill(box.textStyle.color);
page.drawText(i.toString(), {x: i, y: 50});
}
page.drawLine({
start: { x: i, y: 0 },
end: { x: i, y: 1000 },
thickness: 0.5,
color: rgb(0.75, 0.2, 0.2),
opacity: 0.20,
});
}
pdfDoc.save();
const pdfBytes = await pdfDoc.save();
fs.writeFileSync("blank.pdf", pdfBytes);
} }
if (Array.isArray(box.content)){
for (var k=0; k<box.content.length; k++){
doc = await this.putText(doc, box.content[k]);
}
}else if (box.content !== null){
console.log(box.content, box.x, box.y);
await doc.text(box.content,
(box.x!==null? box.x: undefined),
(box.y!==null? box.y: undefined));
}
}
return doc;
};
private grid(doc: any) {
for (var j = 0; j < A4_IN_PX.width; j += 5) {
if (j % 50 == 0) {
doc.save().fill('#000000')
.fontSize(8).text(j.toString(), j*0.75, 50);
doc
.save()
.lineWidth(0.4)
.strokeColor("#dddddd")
.moveTo(j*0.75, 0)
.lineTo(j*0.75, 1000)
.stroke();
}
doc
.save()
.lineWidth(0.2)
.strokeColor("#dddddd")
.moveTo(j*0.75, 0)
.lineTo(j*0.75, 1000)
.stroke();
}
for (var i = 0; i < 1050; i += 5) {
if (i % 50 == 0) {
doc.save()
.fontSize(8).text(i.toString(), 50, i*0.75);
doc
.save()
.lineWidth(0.4)
.strokeColor("#bbbbbb")
.moveTo(0, i*0.75)
.lineTo(1000, i*0.75)
.stroke();
}
doc
.save()
.lineWidth(0.2)
.strokeColor("#bbbbbb")
.moveTo(0, i*0.75)
.lineTo(1000, i*0.75)
.stroke();
}
doc
.save()
.moveTo(0, 200)
.lineTo(1000, 200)
.fill('#FF3300');
}
/**
* make all the nest boxes's position fixed
* @param box the main boxes
* @returns the fixed boxes
*/
fixenBoxesPosition(box : Box) : Box{
console.log("~~~~~", box);
var currX : number = (box.x!==null?box.x:0); // current x
var currY : number =(box.y!==null?box.y:0); // current y
if (Array.isArray(box.content)){
for (var i=0; i<box.content.length; i++){
if (box.direction == Direction.LTR){
box.content[i].x = currX;
box.content[i].y = currY;
let elementWidth = box.content[i].width;
if(elementWidth !== null){
currX += elementWidth;
}
}
if (box.direction == Direction.TTB){
box.content[i].x = currX;
box.content[i].y = currY;
let elementHeight = box.content[i].height;
if(elementHeight !== null){
currY += elementHeight;
}
}
box.content[i] = this.fixenBoxesPosition(box.content[i]);
}
}
return box;
}
/**
* input a `segmentedNodes` and a layed `frame`, return a big `Box` that nodes is put in.
* @param segmentedNodes the segmentnodes to be input
* @param frame the frame to be layed out.
* @returns the big `Box`.
*/
segmentedNodesToFrameBox(segmentedNodes : BoxesItem[][], frame : FrameBox) : Box{ segmentedNodesToFrameBox(segmentedNodes : BoxesItem[][], frame : FrameBox) : Box{
let baseLineskip = frame.baseLineskip; let baseLineskip = frame.baseLineskip;
let boxArrayEmpty : Box[] = []; let boxArrayEmpty : Box[] = [];
@ -506,7 +617,7 @@ export class Clo{
(x).flat()); (x).flat());
let segmentedNodeUnglue = segmentedNodesFixed.map((x)=>this.removeGlue(x, frame).flat()); let segmentedNodeUnglue = segmentedNodesFixed.map((x)=>this.removeGlue(x, frame).flat());
for (var i=0; i<segmentedNodesFixed.length-1; i++){ for (var i=0; i<segmentedNodeUnglue.length; i++){
var currentLineSkip = baseLineskip; var currentLineSkip = baseLineskip;
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]); var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
if (currentLineSkip === null || glyphMaxHeight >currentLineSkip ){ if (currentLineSkip === null || glyphMaxHeight >currentLineSkip ){
@ -552,7 +663,8 @@ 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 - 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];