From: Tan Kian-ting Date: Wed, 15 Nov 2023 17:16:44 +0000 (+0800) Subject: basic types laying. X-Git-Url: https://git.kianting.info/?a=commitdiff_plain;h=e9819c8bc28d209d79461117d5b70f7b6b94abb6;p=clo basic types laying. --- diff --git a/README.md b/README.md index b5717d2..91a1643 100644 --- a/README.md +++ b/README.md @@ -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. ## 之後的做法 - 先做一個前處理註冊器,註冊下列的前處理 diff --git a/b.clo b/b.clo index 5c654a2..ca06b07 100644 --- a/b.clo +++ b/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. \ No newline at end of file +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. \ No newline at end of file diff --git a/b.js b/b.js index bd26c0e..5f90185 100644 --- a/b.js +++ b/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*/ diff --git a/blank.pdf b/blank.pdf deleted file mode 100644 index 927e353..0000000 Binary files a/blank.pdf and /dev/null differ diff --git a/output.pdf b/output.pdf new file mode 100644 index 0000000..054d885 Binary files /dev/null and b/output.pdf differ diff --git a/package-lock.json b/package-lock.json index 52593f4..485944b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 90711f6..df0bcad 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/libclo/breakLines.js b/src/libclo/breakLines.js index b94d123..9367d53 100644 --- a/src/libclo/breakLines.js +++ b/src/libclo/breakLines.js @@ -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])) { diff --git a/src/libclo/breakLines.ts b/src/libclo/breakLines.ts index 0392a23..45ffe65 100644 --- a/src/libclo/breakLines.ts +++ b/src/libclo/breakLines.ts @@ -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 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]; diff --git a/src/libclo/index.ts b/src/libclo/index.ts index b9c3b09..fa8c660 100644 --- a/src/libclo/index.ts +++ b/src/libclo/index.ts @@ -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.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); + + await this.putText(doc, boxesFixed); + // putChar + doc.end(); + + } + + async putText(doc : PDFKit.PDFDocument, box : Box): Promise{ + + 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; kthis.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}); + 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(); } - 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, - }); + doc + .save() + .lineWidth(0.2) + .strokeColor("#dddddd") + .moveTo(j*0.75, 0) + .lineTo(j*0.75, 1000) + .stroke(); } - for (var i = 0; i<1000; i+=5){ - if (i % 50 == 0){ - page.drawText(i.toString(), {x: i, y: 50}); + 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(); } - 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, - }); + 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; ithis.removeBreakPoints (x).flat()); let segmentedNodeUnglue = segmentedNodesFixed.map((x)=>this.removeGlue(x, frame).flat()); - - for (var i=0; icurrentLineSkip ){ @@ -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