From: Tan Kian-ting Date: Sun, 21 Apr 2024 11:09:52 +0000 (+0800) Subject: 加上量字功能 X-Git-Url: https://git.kianting.info/?a=commitdiff_plain;h=0ccf7a2fa274c250831c94b4956a01b04b34d0ab;p=anotherTypesetter 加上量字功能 --- diff --git a/src/index.js b/src/index.js index dae4421..2c6488f 100644 --- a/src/index.js +++ b/src/index.js @@ -44,7 +44,8 @@ var TokenKind; TokenKind[TokenKind["SpaceNL"] = 9] = "SpaceNL"; TokenKind[TokenKind["BSlash"] = 10] = "BSlash"; TokenKind[TokenKind["Apos"] = 11] = "Apos"; - TokenKind[TokenKind["Other"] = 12] = "Other"; + TokenKind[TokenKind["Cmt"] = 12] = "Cmt"; + TokenKind[TokenKind["Other"] = 13] = "Other"; })(TokenKind || (TokenKind = {})); var ItemType; (function (ItemType) { @@ -71,16 +72,16 @@ const tokenizer = (0, typescript_parsec_1.buildLexer)([ [true, /^'/g, TokenKind.Apos], [true, /^(\s|\t|\r?\n)+/g, TokenKind.SpaceNL], [true, /^\\/g, TokenKind.BSlash], + [false, /^\/\/[^\/\r\n]+(\r?\n)/g, TokenKind.Cmt], [true, /^([^+\-*/a-zA-Z_0-9\[\]()'\s\t\r\n\\]+)/g, TokenKind.Other], ]); /* * ## BNF -LISP = UNIT | LISPS | CON_STR +LISP = SINGLE | LISPS | CON_STR LISPS = "(" LISP ")" | "'" "(" LISP ")" -SINGLE = "{" CONSTR_INNR | LISP "}" -UNIT = INT | NUMBER | STRING | ID -CONSTR = "[" (CONSTR_INNER "]" -CONSTR_INNER = ([^\\\[\][]] | [\\][{}\[\]]) | LISPS)* +SINGLE = INT | NUMBER | STRING | ID +CON_STR = "[" CONSTR_INNER "]" +CONSTR_INNER = ([^\\\[\]{}] | [\\][{}\[\]]) | LISPS)* */ const SINGLE = (0, typescript_parsec_1.rule)(); const LISPS = (0, typescript_parsec_1.rule)(); @@ -151,7 +152,7 @@ function applyStrings(value) { return merged; } /** for convinence to omit the spaces and newlines */ -const __ = (0, typescript_parsec_2.opt)((0, typescript_parsec_2.tok)(TokenKind.SpaceNL)); +const __ = (0, typescript_parsec_2.rep_sc)((0, typescript_parsec_2.tok)(TokenKind.SpaceNL)); LISP.setPattern((0, typescript_parsec_2.alt)((0, typescript_parsec_2.kleft)(SINGLE, __), (0, typescript_parsec_2.kleft)(LISPS, __), (0, typescript_parsec_2.kleft)(CON_STR, __))); SINGLE.setPattern((0, typescript_parsec_2.alt)((0, typescript_parsec_2.apply)((0, typescript_parsec_2.tok)(TokenKind.Id), applyId), (0, typescript_parsec_2.apply)((0, typescript_parsec_2.tok)(TokenKind.Int), applyInt), (0, typescript_parsec_2.apply)((0, typescript_parsec_2.tok)(TokenKind.Flo), applyFlo), (0, typescript_parsec_2.apply)((0, typescript_parsec_2.tok)(TokenKind.Str), applyStr), (0, typescript_parsec_2.apply)((0, typescript_parsec_2.tok)(TokenKind.Bool), applyBool))); LISPS.setPattern((0, typescript_parsec_2.alt)((0, typescript_parsec_2.apply)((0, typescript_parsec_2.kmid)((0, typescript_parsec_2.seq)((0, typescript_parsec_2.str)("("), __), (0, typescript_parsec_2.rep_sc)(LISP), (0, typescript_parsec_2.str)(")")), applyList), (0, typescript_parsec_2.apply)((0, typescript_parsec_2.kright)((0, typescript_parsec_2.str)("'"), (0, typescript_parsec_2.kmid)((0, typescript_parsec_2.seq)((0, typescript_parsec_2.str)("("), __), (0, typescript_parsec_2.rep_sc)(LISP), (0, typescript_parsec_2.str)(")"))), applyQuoted))); @@ -175,7 +176,7 @@ async function measureWidthPx(inputString, fontFamily, fontSizePt) { var blob = hb.createBlob(fontdata); // Load the font data into something Harfbuzz can use var face = hb.createFace(blob, 0); // Select the first font in the file (there's normally only one!) var font = hb.createFont(face); // Create a Harfbuzz font object from the face - font.setScale(fontSizePt * 4 / 3 * 1000, fontSizePt * 4 / 3 * 1000); + font.setScale(fontSizePt * 1000, fontSizePt * 1000); var buffer = hb.createBuffer(); // Make a buffer to hold some text buffer.addText(inputString); // Fill it with some stuff buffer.guessSegmentProperties(); // Set script, language and direction @@ -401,21 +402,21 @@ function cons(h, t) { } /* PDF manipulation */ async function drawText(pageIndex, fontFamily, textSize, color, x, y, text) { - let currentPage = pdfDoc.getPages()[0]; + let pdfPages = pdfDoc.getPages(); + let currentPage = pdfPages[pageIndex]; 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); const customFont = await pdfDoc.embedFont(fontBytes); const rgbColor = await hexColorToRGB(color); - let a = await pdfDoc.getPage(0).drawText(text, { + let _ = await currentPage.drawText(text, { x: x, y: y, size: textSize, font: customFont, color: rgbColor, }); - await pdfDoc.save(); } async function hexColorToRGB(hex) { let rgbHex = /[#]?([\dA-Fa-f]{2})([\dA-Fa-f]{2})([\dA-Fa-f]{2})/.exec(hex); @@ -825,7 +826,7 @@ async function interp(prog, env) { throw new Error("the type of replace and variable should be the same."); } else { - env[vari.id][0].value = prog[2]; + env[vari.id][0].value = replacer; return { type: ItemType.Unit }; } } @@ -850,7 +851,7 @@ async function interp(prog, env) { } else { const fontFamily = argsMapped[0].str; - const textSize = argsMapped[1].int; + const textSize = argsMapped[1].flo; const color = argsMapped[2].str; const x = argsMapped[3].flo; const y = argsMapped[4].flo; @@ -861,6 +862,26 @@ async function interp(prog, env) { }; } } + // print to the console + else if (op.id === "print") { + if (prog.length !== 2) { + throw invalidLengthException('print', 1); + } + else { + let data = argsMapped[0]; + let dataString; + if (data.hasOwnProperty("list")) { + dataString = astToString(data, true); + } + else { + dataString = astToString(data, false); + } + console.log(dataString); + return { + type: ItemType.Unit, + }; + } + } // procedures returning the last called command else if (op.id === "begin") { const rtn = argsMapped[argsMapped.length - 1]; diff --git a/src/index.ts b/src/index.ts index 9260f7f..cfb1c1d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,8 @@ enum TokenKind { RBrack, SpaceNL, BSlash, - Apos, + Apos, // Apostrophe + Cmt, // comment Other, } @@ -124,17 +125,17 @@ const tokenizer = buildLexer([ [true, /^'/g, TokenKind.Apos], [true, /^(\s|\t|\r?\n)+/g, TokenKind.SpaceNL], [true, /^\\/g, TokenKind.BSlash], + [false, /^\/\/[^\/\r\n]+(\r?\n)/g, TokenKind.Cmt], // omit the comment [true, /^([^+\-*/a-zA-Z_0-9\[\]()'\s\t\r\n\\]+)/g, TokenKind.Other], ]); /* * ## BNF -LISP = UNIT | LISPS | CON_STR +LISP = SINGLE | LISPS | CON_STR LISPS = "(" LISP ")" | "'" "(" LISP ")" -SINGLE = "{" CONSTR_INNR | LISP "}" -UNIT = INT | NUMBER | STRING | ID -CONSTR = "[" (CONSTR_INNER "]" -CONSTR_INNER = ([^\\\[\][]] | [\\][{}\[\]]) | LISPS)* +SINGLE = INT | NUMBER | STRING | ID +CON_STR = "[" CONSTR_INNER "]" +CONSTR_INNER = ([^\\\[\]{}] | [\\][{}\[\]]) | LISPS)* */ const SINGLE = rule(); @@ -216,7 +217,7 @@ function applyStrings(value: AST[]): AST { } /** for convinence to omit the spaces and newlines */ -const __ = opt(tok(TokenKind.SpaceNL)); +const __ = rep_sc(tok(TokenKind.SpaceNL)); LISP.setPattern(alt(kleft(SINGLE, __), kleft(LISPS, __), kleft(CON_STR, __))); @@ -286,7 +287,7 @@ async function measureWidthPx(inputString: string, fontFamily : string, fontSize var blob = hb.createBlob(fontdata); // Load the font data into something Harfbuzz can use var face = hb.createFace(blob, 0); // Select the first font in the file (there's normally only one!) var font = hb.createFont(face); // Create a Harfbuzz font object from the face - font.setScale(fontSizePt * 4/3* 1000 , fontSizePt*4/3 * 1000 ); + font.setScale(fontSizePt * 1000 , fontSizePt * 1000 ); var buffer = hb.createBuffer(); // Make a buffer to hold some text buffer.addText(inputString); // Fill it with some stuff buffer.guessSegmentProperties(); // Set script, language and direction @@ -309,7 +310,7 @@ async function measureWidthPx(inputString: string, fontFamily : string, fontSize face.destroy(); blob.destroy(); - return totalX / 1000; + return totalX / 1000; }); } @@ -523,7 +524,8 @@ async function drawText(pageIndex : number, x : number, y : number, text : string){ - let currentPage = pdfDoc.getPages()[0]; + let pdfPages = pdfDoc.getPages(); + let currentPage = pdfPages[pageIndex]; const fcMatch = await spawnSync('fc-match', ['--format=%{file}', fontFamily]); const path = fcMatch.stdout.toString(); @@ -534,14 +536,14 @@ const path = fcMatch.stdout.toString(); const rgbColor = await hexColorToRGB(color); - let a = await pdfDoc.getPage(0).drawText(text, { + let _ = await currentPage.drawText(text, { x: x, y: y, size: textSize, font: customFont, color: rgbColor, }); - await pdfDoc.save(); + } @@ -918,7 +920,7 @@ async function interp(prog: AST, env: Env): Promise { || (env[vari.id][0].value as Item).type != replacer.type ){ throw new Error("the type of replace and variable should be the same.") }else{ - env[vari.id][0].value = prog[2]; + env[vari.id][0].value = replacer; return {type:ItemType.Unit}; } } @@ -940,7 +942,7 @@ async function interp(prog: AST, env: Env): Promise { throw invalidLengthException('drawText', 6); }else{ const fontFamily = (argsMapped[0] as ItemStr).str; - const textSize = (argsMapped[1] as ItemInt).int; + const textSize = (argsMapped[1] as ItemFlo).flo; const color = (argsMapped[2] as ItemStr).str; const x = (argsMapped[3] as ItemFlo).flo; const y = (argsMapped[4] as ItemFlo).flo; @@ -958,6 +960,24 @@ async function interp(prog: AST, env: Env): Promise { } } } + // print to the console + else if (op.id === "print"){ + if (prog.length !== 2){ + throw invalidLengthException('print', 1); + }else{ + let data = argsMapped[0]; + let dataString; + if (data.hasOwnProperty("list")){ + dataString = astToString(data, true); + }else{ + dataString = astToString(data, false); + } + console.log(dataString); + return { + type:ItemType.Unit, + } + } + } // procedures returning the last called command else if (op.id === "begin"){ const rtn = argsMapped[argsMapped.length-1]; diff --git a/text.lisp b/text.lisp index 3023dbd..f0e1b2e 100644 --- a/text.lisp +++ b/text.lisp @@ -1,8 +1,8 @@ (begin (define defaultFontFormat - '(("fontFamily" "Gentium") + '(("fontFamily" "FreeSerif") ("color" "#ff0000") - ("fontSize" 12) + ("fontSize" 12.0) ) ) @@ -23,6 +23,13 @@ (setDictItemAux dict '() key data) ))) +(define addDictItem (lambda (dict key data) + (if (= (dictRef dict key) false) + (extendDict dict key data) + dict + ) +)) + (define setDictItemAux (lambda (oldDict newDict key data) (if (= oldDict '()) newDict (if (= (car(car oldDict)) key) @@ -30,36 +37,89 @@ (setDictItemAux (cdr oldDict) (cons (car oldDict) newDict) key data) )))) + (addPDFPage '()) (addPDFPage '()) (define text2boxAux2 (lambda (format text) (if (isList text) + // set font size (if (= (listRef text 0) "fontSize") (let ((newFormat (setDictItem format "fontSize" (listRef text 1)))) (text2boxAux1 newFormat (listRef text 2))) text) - (cons format (cons text '()))) + (cons (cons "content" (cons text '())) format) + ) )) (define text2boxAux1 (lambda (format txt) (if (isList txt) (map (lambda (x) (text2boxAux2 format x)) txt) -(cons format (cons txt '())) +(cons (cons "content" (cons txt '())) format) +))) + +// (measureWidthPx "1314abc" "Gentium" 12.0) + +(define measureBoxItem (lambda (boxList) (map measureBoxItemAux boxList))) +(define measureBoxItemAux (lambda (boxDict) + (let + ((fontFamily (dictRef boxDict "fontFamily")) + (fontSize (dictRef boxDict "fontSize")) + (content (dictRef boxDict "content"))) + (let + ((measuredWidthPx (measureWidthPx content fontFamily fontSize))) + (addDictItem boxDict "widthPx" measuredWidthPx) + ) +))) + +(define text2box (lambda (txt) + (let ((tmp1 (text2boxAux1 defaultFontFormat txt))) + (let ((res (measureBoxItem tmp1))) res) ))) -(define text2box (lambda (txt) (text2boxAux1 defaultFontFormat txt))) -(drawText -(dictRef defaultFontFormat "fontFamily") -(dictRef defaultFontFormat "fontSize") -(dictRef defaultFontFormat "color") -40.0 -50.0 -"blah" +//(drawText +//(dictRef defaultFontFormat "fontFamily") +//(dictRef defaultFontFormat "fontSize") +//(dictRef defaultFontFormat "color") +//40.0 +//50.0 +//"blah" +//) +(define x 0.0) + +(define text '("abracabra" ("fontSize" 18.0 "cat") "foo")) + +(define putOnChar (lambda (boxDict x) +(let + ((content (dictRef boxDict "content")) + (fontFamily (dictRef boxDict "fontFamily")) + (fontSize (dictRef boxDict "fontSize")) + (color (dictRef boxDict "color")) + (widthPx (dictRef boxDict "widthPx")) + ) + (begin + (drawText fontFamily fontSize color x 100.0 content) + (+ x widthPx)) // return an updated x + +))) + +(define putOnChars (lambda (ls x) + (if (= ls '()) + '() + (let + ((newX (putOnChar (car ls) x))) + (putOnChars (cdr ls) newX)) + )) ) -(define text '("abracabra" ("fontSize" 18 "貓") "foo")) -(text2box text) -(measureWidthPx "1314abc" "Gentium" 12.0) + +(let ((boxOfText (text2box text))) + (putOnChars boxOfText 0.0) +) + + + + (text2box text) +// (measureWidthPx "1314abc" "Gentium" 12.0) ) \ No newline at end of file diff --git a/text.lisp.pdf b/text.lisp.pdf index 335d569..3fef838 100644 Binary files a/text.lisp.pdf and b/text.lisp.pdf differ