- [v] add pdf page 240410 (addPDFPages)
- [v] create pdf 240410
- [ ] close pdf
- - [ ] add character
+ - [v] add character
- [ ] add path
- [ ] basic typesetting format
\ No newline at end of file
"version": "0.0.1",
"license": "MIT",
"dependencies": {
+ "@pdf-lib/fontkit": "^1.1.1",
"pdf-lib": "^1.17.1",
"typescript-parsec": "^0.3.4"
},
"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",
"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",
"author": "Tan Kian-ting",
"license": "MIT",
"dependencies": {
+ "@pdf-lib/fontkit": "^1.1.1",
"pdf-lib": "^1.17.1",
"typescript-parsec": "^0.3.4"
},
__setModuleDefault(result, mod);
return result;
};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const pdf_lib_1 = require("pdf-lib");
+const fontkit_1 = __importDefault(require("@pdf-lib/fontkit"));
const typescript_parsec_1 = require("typescript-parsec");
const typescript_parsec_2 = require("typescript-parsec");
/** input lisp file */
};
return rtnList;
}
+/* PDF manipulation */
+async function drawText(pageIndex, fontFamily, textSize, color, x, y, text) {
+ let currentPage = pdfDoc.getPages()[0];
+ const fcMatch = await (0, child_process_1.spawnSync)('fc-match', ['--format=%{file}', fontFamily]);
+ const path = fcMatch.stdout.toString();
+ pdfDoc.registerFontkit(fontkit_1.default);
+ const fontBytes = fs.readFileSync(path);
+ console.log("A2A", (0, pdf_lib_1.rgb)(0, 0, 0));
+ const customFont = await pdfDoc.embedFont(fontBytes);
+ console.log("A3A", (0, pdf_lib_1.rgb)(0, 0, 0));
+ const rgbColor = await hexColorToRGB(color);
+ console.log("A4A", (0, pdf_lib_1.rgb)(0, 0, 0));
+ let a = await pdfDoc.getPage(0).drawText(text, {
+ x: x,
+ y: y,
+ size: textSize,
+ font: customFont,
+ color: rgbColor,
+ });
+ await pdfDoc.save();
+}
+async function hexColorToRGB(hex) {
+ let rgbHex = /[#]?(\d{2})(\d{2})(\d{2})/.exec(hex);
+ let r = parseInt(rgbHex[1], 16) / 256.0;
+ let g = parseInt(rgbHex[2], 16) / 256.0;
+ let b = parseInt(rgbHex[3], 16) / 256.0;
+ return (0, pdf_lib_1.rgb)(r, g, b);
+}
function listRef(l, i) {
const realI = i.int;
if (realI >= l.list.length || realI < 0) {
function isClosure(x) {
return x.hasOwnProperty('type') && x.hasOwnProperty('vars');
}
-function interp(prog, env) {
+async function interp(prog, env) {
if (Array.isArray(prog)) {
if (!Array.isArray(prog[0])) {
const op = prog[0];
const vari = binding[0];
if (vari.hasOwnProperty("id")) {
const variName = vari.id;
- const data = interp(binding[1], env);
+ const data = await interp(binding[1], env);
if (op.id === "letrec") {
newEnv = extendEnv(newEnv, variName, true, data);
}
throw invalidLengthException('if', 3);
}
else {
- const cond = interp(prog[1], env);
+ const cond = await interp(prog[1], env);
if (Array.isArray(cond)) {
throw new Error("cond can't be reduced to a constant");
}
}
}
else {
- const argsMapped = prog.slice(1).map((x) => {
+ const argsMapped = await Promise.all(prog.slice(1).map(async (x) => {
return interp(x, env);
- });
+ }));
// binary basic operator
if (op.id === "+") {
return interpBinary(add, argsMapped);
return { type: ItemType.Unit };
}
}
+ // PDFManipulation
else if (op.id === "addPDFPage") {
if (prog.length !== 2) {
throw invalidLengthException('addPDFPage', 1);
type: ItemType.Unit,
};
}
- const rtn = argsMapped[argsMapped.length - 1];
- return rtn;
+ }
+ else if (op.id === "drawText") {
+ if (prog.length !== 7) {
+ throw invalidLengthException('drawText', 6);
+ }
+ else {
+ const fontFamily = argsMapped[0].str;
+ const textSize = argsMapped[1].int;
+ const color = argsMapped[2].str;
+ const x = argsMapped[3].flo;
+ const y = argsMapped[4].flo;
+ const text = argsMapped[5].str;
+ drawText(pdfDoc.getPageCount() - 1, fontFamily, textSize, color, x, y, text);
+ return {
+ type: ItemType.Unit,
+ };
+ }
}
// procedures returning the last called command
else if (op.id === "begin") {
}
// other named function call
else {
- const caller = interp(prog[0], env);
+ const caller = await interp(prog[0], env);
const varArgs = caller.vars;
const varArgLen = varArgs.length;
const argsMappedLen = argsMapped.length;
// the caller which is a higher-function call
}
else {
- const argsMapped = prog.slice(1).map((x) => {
+ const argsMapped = await Promise.all(prog.slice(1).map((x) => {
return interp(x, env);
- });
- const caller = interp(prog[0], env);
+ }));
+ const caller = await interp(prog[0], env);
const varArgs = caller.vars;
const varArgLen = varArgs.length;
const argsMappedLen = argsMapped.length;
}
}
}
-function evaluate(expr) {
+async function evaluate(expr) {
const input = (0, typescript_parsec_1.expectSingleResult)((0, typescript_parsec_1.expectEOF)(LISP.parse(tokenizer.parse(expr))));
- const interped = interp(input, emptyEnv);
+ const interped = await interp(input, emptyEnv);
return astToString(interped);
}
// evaluate(`(main '((text 12)) [ 快狐跳懶狗\\\\\\\[\\\]\\\(\\\)(italic "fox and dog") (bold [OK])])`)
// eval print loop
const readline = require("node:readline");
const node_process_1 = require("node:process");
+const child_process_1 = require("child_process");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
async function run() {
pdfDoc = await pdf_lib_1.PDFDocument.create();
const prog = fs.readFileSync(filename, { encoding: 'utf8' });
- console.log(evaluate(prog));
+ console.log(await evaluate(prog));
const pdfBytes = await pdfDoc.save();
fs.writeFileSync(filename + '.pdf', pdfBytes, 'binary');
(0, node_process_1.exit)(0);
import * as fs from 'fs';
-import { PDFDocument } from 'pdf-lib'
+import { PDFDocument , RGB, rgb, StandardFonts} from 'pdf-lib';
+import fontkit from '@pdf-lib/fontkit';
import { Token } from "typescript-parsec";
import {
buildLexer,
return rtnList;
}
+/* PDF manipulation */
+async function drawText(pageIndex : number,
+ fontFamily : string,
+ textSize : number,
+ color : string,
+ x : number,
+ y : number,
+ text : string){
+ let currentPage = pdfDoc.getPages()[0];
+
+const fcMatch = await spawnSync('fc-match', ['--format=%{file}', fontFamily]);
+const path = fcMatch.stdout.toString();
+ pdfDoc.registerFontkit(fontkit);
+ const fontBytes = fs.readFileSync(path);
+ console.log("A2A",rgb(0,0,0));
+
+ const customFont = await pdfDoc.embedFont(fontBytes);
+ console.log("A3A",rgb(0,0,0));
+
+ const rgbColor = await hexColorToRGB(color);
+ console.log("A4A",rgb(0,0,0));
+
+ let a = await pdfDoc.getPage(0).drawText(text, {
+ x: x,
+ y: y,
+ size: textSize,
+ font: customFont,
+ color: rgbColor,
+ });
+ await pdfDoc.save();
+
+}
+
+
+async function hexColorToRGB(hex: string): Promise<RGB>{
+ let rgbHex = /[#]?(\d{2})(\d{2})(\d{2})/.exec(hex);
+ let r = parseInt((rgbHex as RegExpExecArray)[1], 16)/256.0;
+ let g = parseInt((rgbHex as RegExpExecArray)[2], 16)/256.0;
+ let b = parseInt((rgbHex as RegExpExecArray)[3], 16)/256.0;
+ return rgb(r,g,b);
+}
+
function listRef(l: List, i: ItemInt): AST {
const realI = i.int;
if (realI >= l.list.length || realI < 0){
return x.hasOwnProperty('type') && x.hasOwnProperty('vars');
}
-function interp(prog: AST, env: Env): AST {
+async function interp(prog: AST, env: Env): Promise<AST> {
if (Array.isArray(prog)) {
if (!Array.isArray(prog[0])) {
const op = prog[0];
const vari = binding[0];
if (vari.hasOwnProperty("id")){
const variName = (vari as ItemId).id;
- const data = interp(binding[1], env);
+ const data = await interp(binding[1], env);
if (op.id === "letrec"){
newEnv = extendEnv(newEnv, variName , true, data);
}else{
if (prog.length !== 4){
throw invalidLengthException('if', 3);
}else{
- const cond = interp(prog[1], env);
+ const cond = await interp(prog[1], env);
if (Array.isArray(cond)){
throw new Error("cond can't be reduced to a constant");
}else if (cond.type !== ItemType.Bool){
}
else{
- const argsMapped = prog.slice(1).map((x) => {
+ const argsMapped = await Promise.all( prog.slice(1).map(async (x) => {
return interp(x, env);
- });
+ }));
// binary basic operator
if (op.id === "+") {
return interpBinary(add, argsMapped);
return {type:ItemType.Unit};
}
}
+ // PDFManipulation
else if (op.id === "addPDFPage"){
if (prog.length !== 2){
throw invalidLengthException('addPDFPage', 1);
type:ItemType.Unit,
}
}
-
- const rtn = argsMapped[argsMapped.length-1];
- return rtn;
+ }
+ else if (op.id === "drawText"){
+ if (prog.length !== 7){
+ throw invalidLengthException('drawText', 6);
+ }else{
+ const fontFamily = (argsMapped[0] as ItemStr).str;
+ const textSize = (argsMapped[1] as ItemInt).int;
+ const color = (argsMapped[2] as ItemStr).str;
+ const x = (argsMapped[3] as ItemFlo).flo;
+ const y = (argsMapped[4] as ItemFlo).flo;
+ const text = (argsMapped[5] as ItemStr).str;
+ drawText(
+ pdfDoc.getPageCount()-1,
+ fontFamily,
+ textSize,
+ color,
+ x,
+ y,
+ text);
+ return {
+ type:ItemType.Unit,
+ }
+ }
}
// procedures returning the last called command
else if (op.id === "begin"){
const rtn = argsMapped[argsMapped.length-1];
return rtn;
}
+
// other named function call
else {
- const caller = interp(prog[0],env);
+ const caller = await interp(prog[0],env);
const varArgs = ((caller as Closure).vars as ItemId[]);
}
// the caller which is a higher-function call
} else {
- const argsMapped = prog.slice(1).map((x) => {
+ const argsMapped = await Promise.all(prog.slice(1).map((x) => {
return interp(x, env);
- });
- const caller = interp(prog[0], env);
+ }));
+ const caller = await interp(prog[0], env);
const varArgs = (caller as Closure).vars as ItemId[];
const varArgLen = varArgs.length;
}
}
-function evaluate(expr: string): string {
+async function evaluate(expr: string): Promise<string> {
const input = expectSingleResult(expectEOF(LISP.parse(tokenizer.parse(expr))));
- const interped = interp(input, emptyEnv);
+ const interped = await interp(input, emptyEnv);
return astToString(interped);
}
// eval print loop
import readline = require("node:readline");
import { exit } from "node:process";
+import { spawnSync } from 'child_process';
const rl = readline.createInterface({
input: process.stdin,
const prog = fs.readFileSync(filename, { encoding: 'utf8' });
- console.log(evaluate(prog));
+ console.log(await evaluate(prog));
const pdfBytes = await pdfDoc.save();
fs.writeFileSync(filename+'.pdf', pdfBytes, 'binary');
-(letrec ((
- map (lambda (f l)
+(letrec (
+ (defaultFontFormat
+ '(("fontFamily" "Gentium")
+
+ ("color" "#000000")
+ ("size" 12)
+ )
+ )
+ (map (lambda (f l)
(if (!= l '())
(cons (f (car l)) (map f (cdr l)))
- '()))
-))
+ '())))
+ (emptyDict '())
+ (extendDict (lambda (dict var data) (cons (cons var (cons data '())) dict)))
+ (dictRef (lambda (dict key)
+ (if (= dict '()) false
+ (if (= key (car (car dict))) (car (cdr (car dict))) (dictRef (cdr dict) key))
+ )))
+ )
+
(begin
(addPDFPage '())
+(drawText
+ (dictRef defaultFontFormat "fontFamily")
+ (dictRef defaultFontFormat "size")
+ (dictRef defaultFontFormat "color")
+ 40.0
+ 50.0
+ "blah"
+)
(addPDFPage '())
-(map (lambda (x) (+ x 2)) '(8 9 10))
-))
\ No newline at end of file
+(map (lambda (x) (+ x 2)) '(8 9 10))
+(let ((dict emptyDict))
+ (let ((dictExtended
+ (extendDict
+ (extendDict emptyDict 1 2) 2 4)))
+ (dictRef dictExtended 2)
+))))
\ No newline at end of file