basic types laying.
This commit is contained in:
parent
9c51921978
commit
e9819c8bc2
11 changed files with 337 additions and 108 deletions
|
@ -36,6 +36,7 @@
|
|||
- 20231105-06: 利用fontkit算文字的對應px寬度 initially pushed.
|
||||
- 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.
|
||||
- 20231115-16: grid and basic types laying.
|
||||
|
||||
## 之後的做法
|
||||
- 先做一個前處理註冊器,註冊下列的前處理
|
||||
|
|
4
b.clo
4
b.clo
|
@ -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
4
b.js
|
@ -9,7 +9,9 @@ let clo = new cloLib.Clo();
|
|||
|
||||
/* CLO: beginning 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.generatePdf();
|
||||
/*CLO : end of end part*/
|
||||
|
|
BIN
blank.pdf
BIN
blank.pdf
Binary file not shown.
BIN
output.pdf
Normal file
BIN
output.pdf
Normal file
Binary file not shown.
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -9,6 +9,7 @@
|
|||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"canvas": "^2.11.2",
|
||||
"fontkit": "^2.0.2",
|
||||
"hyphen": "^1.7.0",
|
||||
|
@ -742,6 +743,14 @@
|
|||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||
|
@ -11768,6 +11777,14 @@
|
|||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"canvas": "^2.11.2",
|
||||
"fontkit": "^2.0.2",
|
||||
"hyphen": "^1.7.0",
|
||||
|
|
|
@ -35,7 +35,8 @@ class BreakLineAlgorithm {
|
|||
}
|
||||
}
|
||||
segmentedNodes(items, lineWidth) {
|
||||
this.totalCost(items, lineWidth);
|
||||
let lineWidthFixed = lineWidth * 0.75;
|
||||
this.totalCost(items, lineWidthFixed);
|
||||
let nodeList = this.generateBreakLineNodeList();
|
||||
console.log("~~~", nodeList);
|
||||
let res = [];
|
||||
|
@ -46,6 +47,7 @@ class BreakLineAlgorithm {
|
|||
low = nodeList[i];
|
||||
up = nodeList[i + 1];
|
||||
}
|
||||
console.log("===", res.length);
|
||||
return res;
|
||||
}
|
||||
/**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.prevNodes = Array(itemsLength).fill(null);
|
||||
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);
|
||||
console.log("===", itemsLength);
|
||||
this.totalCostAuxStorage = Array(itemsLength).fill(null);
|
||||
let a = this.totalCostAux(items, itemsLength - 1, lineWidth);
|
||||
console.log(this.lineCostStorage);
|
||||
return a;
|
||||
}
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ class BreakLineAlgorithm {
|
|||
* @param lineWidth
|
||||
*/
|
||||
totalCostAux(items, j, lineWidth) {
|
||||
if (this.totalCostAuxStorage[j] !== undefined) {
|
||||
if (this.totalCostAuxStorage[j] !== null) {
|
||||
return this.totalCostAuxStorage[j];
|
||||
}
|
||||
let rawLineCost = this.lineCost(items, 0, j, lineWidth);
|
||||
|
@ -121,7 +121,7 @@ class BreakLineAlgorithm {
|
|||
* @param lineWidth line width
|
||||
*/
|
||||
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];
|
||||
}
|
||||
if (!this.isBreakPoint(items[j])) {
|
||||
|
|
|
@ -51,7 +51,8 @@ export class BreakLineAlgorithm {
|
|||
}
|
||||
|
||||
segmentedNodes(items : BoxesItem[], lineWidth : number) : BoxesItem[][]{
|
||||
this.totalCost(items ,lineWidth);
|
||||
let lineWidthFixed = lineWidth * 0.75;
|
||||
this.totalCost(items ,lineWidthFixed);
|
||||
let nodeList = this.generateBreakLineNodeList();
|
||||
console.log("~~~", nodeList);
|
||||
let res = [];
|
||||
|
@ -64,6 +65,7 @@ export class BreakLineAlgorithm {
|
|||
up = nodeList[i+1];
|
||||
|
||||
}
|
||||
console.log("===", res.length);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -98,13 +100,11 @@ export class BreakLineAlgorithm {
|
|||
|
||||
|
||||
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);
|
||||
console.log("===", itemsLength);
|
||||
this.totalCostAuxStorage = Array(itemsLength).fill(null);
|
||||
let a = this.totalCostAux(items, itemsLength-1, lineWidth);
|
||||
console.log(this.lineCostStorage);
|
||||
return a;
|
||||
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ export class BreakLineAlgorithm {
|
|||
*/
|
||||
totalCostAux(items : BoxesItem[], j : number, lineWidth: number): number{
|
||||
|
||||
if (this.totalCostAuxStorage[j] !== undefined){
|
||||
if (this.totalCostAuxStorage[j] !== null){
|
||||
return this.totalCostAuxStorage[j];
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ export class BreakLineAlgorithm {
|
|||
* @param lineWidth line width
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,7 @@ exports.Clo = exports.calculateTextWidthHeightAux = exports.calculateTextWidthHe
|
|||
const canva_1 = require("../canva");
|
||||
const fontkit = __importStar(require("fontkit"));
|
||||
const breakLines = __importStar(require("./breakLines"));
|
||||
require("pdfkit");
|
||||
const pdf_lib_1 = require("pdf-lib");
|
||||
const PDFDocument = require('pdfkit');
|
||||
const fs = __importStar(require("fs"));
|
||||
/**
|
||||
* TYPES
|
||||
|
@ -71,8 +70,8 @@ exports.defaultFrameStyle = {
|
|||
direction: Direction.TTB,
|
||||
baseLineskip: ptToPx(15),
|
||||
textStyle: exports.defaultTextStyle,
|
||||
x: exports.A4_IN_PX.width * 0.10,
|
||||
y: exports.A4_IN_PX.height * 0.10,
|
||||
x: exports.A4_IN_PX.width * 0.10 * 0.75,
|
||||
y: exports.A4_IN_PX.height * 0.10 * 0.75,
|
||||
width: exports.A4_IN_PX.width * 0.80,
|
||||
height: exports.A4_IN_PX.height * 0.80,
|
||||
content: null,
|
||||
|
@ -278,8 +277,8 @@ function calculateTextWidthHeightAux(element, style) {
|
|||
y: null,
|
||||
textStyle: style,
|
||||
direction: Direction.LTR,
|
||||
width: (runGlyphsItem.advanceWidth) * (style.size) / 1000,
|
||||
height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) / 1000,
|
||||
width: (runGlyphsItem.advanceWidth) * (style.size) * 0.75 / 1000,
|
||||
height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) * 0.75 / 1000,
|
||||
content: element[j],
|
||||
minX: runGlyphsItem.bbox.minX,
|
||||
maxX: runGlyphsItem.bbox.maxX,
|
||||
|
@ -360,46 +359,140 @@ class Clo {
|
|||
preprocessed = this.preprocessors[i](preprocessed, this);
|
||||
}
|
||||
// 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 breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
|
||||
// TODO
|
||||
//console.log(breakLineAlgorithms.totalCost(a,70));
|
||||
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, 70);
|
||||
console.log(this.segmentedNodesToFrameBox(segmentedNodes, this.attrs["defaultFrameStyle"]));
|
||||
// generate pdf
|
||||
const pdfDoc = yield pdf_lib_1.PDFDocument.create();
|
||||
var page = pdfDoc.addPage();
|
||||
page.drawText('You can create PDFs!');
|
||||
for (var j = 0; j < 1000; j += 5) {
|
||||
if (j % 50 == 0) {
|
||||
page.drawText(j.toString(), { x: 50, y: j });
|
||||
}
|
||||
page.drawLine({
|
||||
start: { x: 0, y: j },
|
||||
end: { x: 1000, y: j },
|
||||
thickness: 0.5,
|
||||
color: (0, pdf_lib_1.rgb)(0.75, 0.2, 0.2),
|
||||
opacity: 0.20,
|
||||
});
|
||||
}
|
||||
for (var i = 0; i < 1000; i += 5) {
|
||||
if (i % 50 == 0) {
|
||||
page.drawText(i.toString(), { x: i, y: 50 });
|
||||
}
|
||||
page.drawLine({
|
||||
start: { x: i, y: 0 },
|
||||
end: { x: i, y: 1000 },
|
||||
thickness: 0.5,
|
||||
color: (0, pdf_lib_1.rgb)(0.75, 0.2, 0.2),
|
||||
opacity: 0.20,
|
||||
});
|
||||
}
|
||||
pdfDoc.save();
|
||||
const pdfBytes = yield pdfDoc.save();
|
||||
fs.writeFileSync("blank.pdf", pdfBytes);
|
||||
let segmentedNodes = breakLineAlgorithms.segmentedNodes(a, this.attrs.defaultFrameStyle.width);
|
||||
console.log(this.attrs.defaultFrameStyle.width);
|
||||
let segmentedNodesToBox = this.segmentedNodesToFrameBox(segmentedNodes, this.attrs.defaultFrameStyle);
|
||||
let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox);
|
||||
// generate pdf7
|
||||
const doc = new PDFDocument({ size: 'A4' });
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
let baseLineskip = frame.baseLineskip;
|
||||
let boxArrayEmpty = [];
|
||||
|
@ -415,7 +508,7 @@ class Clo {
|
|||
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++) {
|
||||
for (var i = 0; i < segmentedNodeUnglue.length; i++) {
|
||||
var currentLineSkip = baseLineskip;
|
||||
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
|
||||
if (currentLineSkip === null || glyphMaxHeight > currentLineSkip) {
|
||||
|
@ -468,7 +561,8 @@ class Clo {
|
|||
return 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 = [];
|
||||
for (var i = 0; i < nodeLine.length; i++) {
|
||||
var ele = nodeLine[i];
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
import { isBoxedPrimitive, isKeyObject, isStringObject } from "util/types";
|
||||
import {tkTree} from "../parser";
|
||||
import {FontStyle, TextStyle, TextWeight, fontStyleTofont} from "../canva";
|
||||
import { JSDOM } from "jsdom";
|
||||
import * as fontkit from "fontkit";
|
||||
import * as util from "node:util";
|
||||
import * as breakLines from "./breakLines";
|
||||
import "pdfkit";
|
||||
import PDFKitPage from "pdfkit/js/page";
|
||||
import { ColorTypes, PDFDocument, rgb } from "pdf-lib";
|
||||
const PDFDocument = require('pdfkit');
|
||||
import * as fs from "fs";
|
||||
|
||||
|
||||
/**
|
||||
* TYPES
|
||||
*/
|
||||
|
@ -98,10 +94,10 @@ export const defaultFrameStyle : FrameBox = {
|
|||
direction : Direction.TTB,
|
||||
baseLineskip : ptToPx(15),
|
||||
textStyle : defaultTextStyle,
|
||||
x : A4_IN_PX.width * 0.10,
|
||||
y : A4_IN_PX.height * 0.10,
|
||||
width : A4_IN_PX.width * 0.80,
|
||||
height : A4_IN_PX.height * 0.80,
|
||||
x : A4_IN_PX.width * 0.10 * 0.75,
|
||||
y : A4_IN_PX.height * 0.10 * 0.75,
|
||||
width : A4_IN_PX.width * 0.80 ,
|
||||
height : A4_IN_PX.height * 0.80 ,
|
||||
content : null,
|
||||
};
|
||||
|
||||
|
@ -332,8 +328,8 @@ export async function calculateTextWidthHeightAux(element : tkTree, style : Text
|
|||
y : null,
|
||||
textStyle : style,
|
||||
direction : Direction.LTR,
|
||||
width : (runGlyphsItem.advanceWidth)*(style.size)/1000,
|
||||
height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)/1000,
|
||||
width : (runGlyphsItem.advanceWidth)*(style.size)*0.75/1000,
|
||||
height : (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY)*(style.size)*0.75/1000,
|
||||
content : element[j],
|
||||
minX : runGlyphsItem.bbox.minX,
|
||||
maxX : runGlyphsItem.bbox.maxX,
|
||||
|
@ -439,54 +435,169 @@ export class Clo{
|
|||
}
|
||||
// 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 breakLineAlgorithms = new breakLines.BreakLineAlgorithm();
|
||||
// TODO
|
||||
//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, <FrameBox>this.attrs["defaultFrameStyle"]));
|
||||
console.log(this.attrs.defaultFrameStyle.width);
|
||||
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){
|
||||
page.drawText(j.toString(), {x: 50, y: j});
|
||||
}
|
||||
|
||||
page.drawLine({
|
||||
start: { x: 0, y: j },
|
||||
end: { x: 1000, y: j },
|
||||
thickness: 0.5,
|
||||
color: rgb(0.75, 0.2, 0.2),
|
||||
opacity: 0.20,
|
||||
});
|
||||
}
|
||||
let boxesFixed = this.fixenBoxesPosition(segmentedNodesToBox);
|
||||
|
||||
for (var i = 0; i<1000; i+=5){
|
||||
if (i % 50 == 0){
|
||||
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();
|
||||
|
||||
|
||||
|
||||
// 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();
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
fs.writeFileSync("blank.pdf", pdfBytes);
|
||||
}
|
||||
|
||||
async putText(doc : PDFKit.PDFDocument, box : Box): Promise<PDFKit.PDFDocument>{
|
||||
|
||||
if (box.textStyle !== null){
|
||||
let fontInfo = 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 = 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{
|
||||
let baseLineskip = frame.baseLineskip;
|
||||
let boxArrayEmpty : Box[] = [];
|
||||
|
@ -505,8 +616,8 @@ export class Clo{
|
|||
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++){
|
||||
|
||||
for (var i=0; i<segmentedNodeUnglue.length; i++){
|
||||
var currentLineSkip = baseLineskip;
|
||||
var glyphMaxHeight = this.getGlyphMaxHeight(segmentedNodesFixed[i]);
|
||||
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;}})
|
||||
.reduce((acc, cur)=>acc+cur , 0);
|
||||
let offset = frame.width - glueRemovedWidth;
|
||||
let offset = frame.width * 0.75 - glueRemovedWidth;
|
||||
console.log("OFFSET", offset);
|
||||
var res = [];
|
||||
for (var i=0; i<nodeLine.length; i++){
|
||||
var ele = nodeLine[i];
|
||||
|
|
Loading…
Reference in a new issue