]> git.kianting.info Git - clo/blob - src/libclo/index.js
5cfaabe918cb0fb18ac1d7e2485a06180526956c
[clo] / src / libclo / index.js
1 "use strict";
2 var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 var desc = Object.getOwnPropertyDescriptor(m, k);
5 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 desc = { enumerable: true, get: function() { return m[k]; } };
7 }
8 Object.defineProperty(o, k2, desc);
9 }) : (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 o[k2] = m[k];
12 }));
13 var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 Object.defineProperty(o, "default", { enumerable: true, value: v });
15 }) : function(o, v) {
16 o["default"] = v;
17 });
18 var __importStar = (this && this.__importStar) || function (mod) {
19 if (mod && mod.__esModule) return mod;
20 var result = {};
21 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 __setModuleDefault(result, mod);
23 return result;
24 };
25 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27 return new (P || (P = Promise))(function (resolve, reject) {
28 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31 step((generator = generator.apply(thisArg, _arguments || [])).next());
32 });
33 };
34 Object.defineProperty(exports, "__esModule", { value: true });
35 exports.Clo = exports.calculateTextWidthHeightAux = exports.calculateTextWidthHeight = exports.hyphenTkTree = exports.filterEmptyString = exports.spacesToBreakpoint = exports.hyphenForClo = exports.splitCJKV = exports.twoReturnsToNewline = exports.ptToPx = exports.cjkvRegexPattern = exports.cjkvBlocksInRegex = exports.defaultFrameStyle = exports.defaultTextStyle = exports.A4_IN_PX = exports.Direction = void 0;
36 const canva_1 = require("../canva");
37 const fontkit = __importStar(require("fontkit"));
38 /**
39 * TYPES
40 */
41 /**
42 * text direction
43 * LTR - left to right
44 * TTB - top to bottom
45 * etc.
46 */
47 var Direction;
48 (function (Direction) {
49 Direction[Direction["LTR"] = 0] = "LTR";
50 Direction[Direction["RTL"] = 1] = "RTL";
51 Direction[Direction["TTB"] = 2] = "TTB";
52 Direction[Direction["BTT"] = 3] = "BTT";
53 })(Direction || (exports.Direction = Direction = {}));
54 /**
55 * DEFAULT CONST PART
56 */
57 exports.A4_IN_PX = { "width": 793.7,
58 "height": 1122.5 };
59 exports.defaultTextStyle = {
60 family: "FreeSerif",
61 size: ptToPx(12),
62 textWeight: canva_1.TextWeight.REGULAR,
63 fontStyle: canva_1.FontStyle.ITALIC,
64 };
65 exports.defaultFrameStyle = {
66 directionInsideLine: Direction.LTR,
67 direction: Direction.TTB,
68 baseLineskip: ptToPx(15),
69 textStyle: exports.defaultTextStyle,
70 x: exports.A4_IN_PX.width * 0.10,
71 y: exports.A4_IN_PX.height * 0.10,
72 width: exports.A4_IN_PX.width * 0.80,
73 height: exports.A4_IN_PX.height * 0.80,
74 content: null,
75 };
76 /**
77 * definition for cjk scripts
78 * - Hani : Han Character
79 * - Hang : Hangul
80 * - Bopo : Bopomofo
81 * - Kana : Katakana
82 * - Hira : Hiragana
83 */
84 exports.cjkvBlocksInRegex = ["Hani", "Hang", "Bopo", "Kana", "Hira"];
85 exports.cjkvRegexPattern = new RegExp("((?:" +
86 exports.cjkvBlocksInRegex.map((x) => "\\p{Script_Extensions=" + x + "}").join("|") + ")+)", "gu");
87 /**
88 * FUNCTION PART
89 */
90 /**
91 * convert from ptToPx
92 * @param pt pt size value
93 * @returns the corresponding px value
94 */
95 function ptToPx(pt) {
96 return pt * 4.0 / 3.0;
97 }
98 exports.ptToPx = ptToPx;
99 /**
100 * REGISTER PART
101 */
102 /**
103 * convert '\n\n' to newline command ["nl"]
104 * @param arr the input `tkTree`
105 * @param clo the `Clo` object
106 * @returns the input tktree
107 */
108 function twoReturnsToNewline(arr, clo) {
109 var middle = [];
110 for (let i = 0; i < arr.length; i++) {
111 var item = arr[i];
112 if (!Array.isArray(item)) {
113 middle = middle.concat(item.split(/(\n\n)/g));
114 }
115 else {
116 middle.push(item);
117 }
118 }
119 var result = [];
120 for (let j = 0; j < middle.length; j++) {
121 var item = middle[j];
122 if (!Array.isArray(item) && item == "\n\n") {
123 result.push(["nl"]); // push a newline command to the result `tkTree`
124 }
125 else {
126 result.push(middle[j]);
127 }
128 }
129 return result;
130 }
131 exports.twoReturnsToNewline = twoReturnsToNewline;
132 /**
133 * split CJKV and non-CJKV
134 *
135 * @param arr : input tkTree
136 * @returns a splitted tkTree (by CJK and NonCJK)
137 * - Examples:
138 * ```
139 * [`many臺中daylight`] => [`many`, `臺中`, `dahylight`]
140 * ```
141 */
142 function splitCJKV(arr, clo) {
143 var result = [];
144 for (let i = 0; i < arr.length; i++) {
145 var item = arr[i];
146 if (!Array.isArray(item)) {
147 result = result.concat(item.split(exports.cjkvRegexPattern));
148 }
149 else {
150 result.push(item);
151 }
152 }
153 return result;
154 }
155 exports.splitCJKV = splitCJKV;
156 /**
157 * hyphenation for a clo document
158 * @param arr the array for a `tkTree`
159 * @param clo the Clo object
160 */
161 function hyphenForClo(arr, clo) {
162 let hyphenLanguage = clo.attrs["hyphenLanguage"];
163 let res = hyphenTkTree(arr, hyphenLanguage);
164 return res;
165 }
166 exports.hyphenForClo = hyphenForClo;
167 /**
168 * convert spaces to Breakpoint
169 * \s+ => ["bp" [\s+] ""]
170 * @param arr the tkTree input text stream
171 * @param clo the Clo object
172 * @returns the converted object
173 */
174 function spacesToBreakpoint(arr, clo) {
175 let spacePattern = /^([ \t]+)$/g;
176 var result = [];
177 for (let i = 0; i < arr.length; i++) {
178 var item = arr[i];
179 if (!Array.isArray(item) && item.match(spacePattern)) {
180 result.push(['bp', item, ""]); // push a newline command to the result `tkTree`
181 }
182 else {
183 result.push(item);
184 }
185 }
186 return result;
187 }
188 exports.spacesToBreakpoint = spacesToBreakpoint;
189 /**
190 * remove all the `` (empty string) in the arr
191 * @param arr the tkTree to be filtered
192 * @param clo the Clo file
193 */
194 function filterEmptyString(arr, clo) {
195 if (Array.isArray(arr)) {
196 arr.filter((x) => { return x != ``; });
197 }
198 return arr;
199 }
200 exports.filterEmptyString = filterEmptyString;
201 /**
202 * OTHER FUNCTIONS
203 */
204 /**
205 * hyphenate for a tkTree
206 * - hyphenation => ["bp", "", "-"]
207 * @param arr the tkTree array
208 * @param lang ISO 639 code for the language
209 */
210 function hyphenTkTree(arr, lang) {
211 // import corresponding hyphen language data and function
212 let hyphen = require("hyphen/" + lang);
213 let result = [];
214 for (let i = 0; i < arr.length; i++) {
215 let element = arr[i];
216 let splitter = "分"; // a CJKV
217 if (!Array.isArray(element)) {
218 let hyphenatedElement = hyphen.hyphenateSync(element, { hyphenChar: splitter });
219 let hyphenatedSplitted = hyphenatedElement.split(splitter);
220 var newSplitted = [];
221 for (var j = 0; j < hyphenatedSplitted.length - 1; j++) {
222 newSplitted.push(hyphenatedSplitted[j]);
223 // "bp" for breakpoint
224 newSplitted.push(["bp", "", "-"]); //insert a breakable point (bp) mark
225 }
226 newSplitted.push(hyphenatedSplitted[hyphenatedSplitted.length - 1]);
227 result = result.concat(newSplitted);
228 }
229 else {
230 result.push(element);
231 }
232 }
233 return result;
234 }
235 exports.hyphenTkTree = hyphenTkTree;
236 /**
237 * calculate the text width and Height with a given `TextStyle`
238 * @param preprocessed
239 * @param defaultFontStyle
240 */
241 function calculateTextWidthHeight(element, style) {
242 return __awaiter(this, void 0, void 0, function* () {
243 var res = [];
244 for (var i = 0; i < element.length; i++) {
245 res.push(yield calculateTextWidthHeightAux(element[i], style));
246 }
247 console.log(res);
248 return res;
249 });
250 }
251 exports.calculateTextWidthHeight = calculateTextWidthHeight;
252 /**
253 * calculate the text width and Height with a given `TextStyle`
254 * @param preprocessed
255 * @param defaultFontStyle
256 */
257 function calculateTextWidthHeightAux(element, style) {
258 return __awaiter(this, void 0, void 0, function* () {
259 var result = [];
260 let fontPair = (0, canva_1.fontStyleTofont)(style);
261 if (fontPair.path.match(/\.ttc$/)) {
262 var font = yield fontkit.openSync(fontPair.path, fontPair.psName);
263 }
264 else {
265 var font = yield fontkit.openSync(fontPair.path);
266 }
267 if (!Array.isArray(element)) {
268 var run = font.layout(element, undefined, undefined, undefined, "ltr");
269 for (var j = 0; j < run.glyphs.length; j++) {
270 let runGlyphsItem = run.glyphs[j];
271 let item = {
272 x: null,
273 y: null,
274 textStyle: style,
275 direction: Direction.LTR,
276 width: (runGlyphsItem.advanceWidth) * (style.size) / 1000,
277 height: (runGlyphsItem.bbox.maxY - runGlyphsItem.bbox.minY) * (style.size) / 1000,
278 content: element[j],
279 minX: runGlyphsItem.bbox.minX,
280 maxX: runGlyphsItem.bbox.maxX,
281 minY: runGlyphsItem.bbox.minY,
282 maxY: runGlyphsItem.bbox.maxY
283 };
284 result.push(item);
285 }
286 return result;
287 }
288 else if (element[0] == "bp") {
289 let beforeNewLine = yield calculateTextWidthHeightAux(element[1], style);
290 let afterNewLine = yield calculateTextWidthHeightAux(element[2], style);
291 return ["bp", beforeNewLine, afterNewLine];
292 }
293 else {
294 return calculateTextWidthHeight(element[1], style);
295 }
296 });
297 }
298 exports.calculateTextWidthHeightAux = calculateTextWidthHeightAux;
299 /**
300 * whole document-representing class
301 */
302 class Clo {
303 constructor() {
304 this.preprocessors = [];
305 this.mainStream = [];
306 this.attrs = {
307 "page": exports.A4_IN_PX,
308 "defaultFrameStyle": exports.defaultFrameStyle,
309 "hyphenLanguage": 'en' // hyphenated in the language (in ISO 639)
310 };
311 // register the precessor functions
312 this.preprocessorRegister(splitCJKV);
313 this.preprocessorRegister(hyphenForClo);
314 this.preprocessorRegister(twoReturnsToNewline);
315 this.preprocessorRegister(spacesToBreakpoint);
316 this.preprocessorRegister(filterEmptyString);
317 }
318 setAttr(attr, val) {
319 Object.assign(this.attrs, attr, val);
320 }
321 getAttr(attr) {
322 if (Object.keys(this.attrs).length === 0) {
323 return this.attrs[attr];
324 }
325 else {
326 return undefined;
327 }
328 }
329 /**
330 * register a function of preprocessor
331 * @param f a function
332 */
333 preprocessorRegister(f) {
334 this.preprocessors.push(f);
335 }
336 generatePdf() {
337 // preprocessed
338 var preprocessed = this.mainStream;
339 for (var i = 0; i < this.preprocessors.length; i++) {
340 preprocessed = this.preprocessors[i](preprocessed, this);
341 }
342 // generate the width and height of the stream
343 let defaultFontStyle = this.attrs["defaultFrameStyle"].textStyle;
344 calculateTextWidthHeight(preprocessed, defaultFontStyle);
345 // TODO
346 console.log(preprocessed);
347 }
348 }
349 exports.Clo = Clo;
350 /*
351 export let a = new Clo();
352 export default a; */