| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 | 
							- /* Copyright 2014 Mozilla Foundation
 
-  *
 
-  * Licensed under the Apache License, Version 2.0 (the "License");
 
-  * you may not use this file except in compliance with the License.
 
-  * You may obtain a copy of the License at
 
-  *
 
-  *     http://www.apache.org/licenses/LICENSE-2.0
 
-  *
 
-  * Unless required by applicable law or agreed to in writing, software
 
-  * distributed under the License is distributed on an "AS IS" BASIS,
 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-  * See the License for the specific language governing permissions and
 
-  * limitations under the License.
 
-  */
 
- const fs = require("fs");
 
- const path = require("path");
 
- const parseAdobeCMap = require("./parse.js").parseAdobeCMap;
 
- const optimizeCMap = require("./optimize.js").optimizeCMap;
 
- function compressCmap(srcPath, destPath, verify) {
 
-   const content = fs.readFileSync(srcPath).toString();
 
-   const inputData = parseAdobeCMap(content);
 
-   optimizeCMap(inputData);
 
-   let out = writeByte((inputData.type << 1) | inputData.wmode);
 
-   if (inputData.comment) {
 
-     out += writeByte(0xe0) + writeString(inputData.comment);
 
-   }
 
-   if (inputData.usecmap) {
 
-     out += writeByte(0xe1) + writeString(inputData.usecmap);
 
-   }
 
-   let i = 0;
 
-   while (i < inputData.body.length) {
 
-     const item = inputData.body[i++],
 
-       subitems = item.items;
 
-     const first = item.items[0];
 
-     const sequence = item.sequence === true;
 
-     const flags = (item.type << 5) | (sequence ? 0x10 : 0);
 
-     let nextStart, nextCode;
 
-     switch (item.type) {
 
-       case 0:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.start)) +
 
-           writeNumber(subitems.length);
 
-         out += first.start + writeNumber(subHex(first.end, first.start));
 
-         nextStart = incHex(first.end);
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             writeNumber(subHex(subitems[j].start, nextStart)) +
 
-             writeNumber(subHex(subitems[j].end, subitems[j].start));
 
-           nextStart = incHex(subitems[j].end);
 
-         }
 
-         break;
 
-       case 1:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.start)) +
 
-           writeNumber(subitems.length);
 
-         out +=
 
-           first.start +
 
-           writeNumber(subHex(first.end, first.start)) +
 
-           writeNumber(first.code);
 
-         nextStart = incHex(first.end);
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             writeNumber(subHex(subitems[j].start, nextStart)) +
 
-             writeNumber(subHex(subitems[j].end, subitems[j].start)) +
 
-             writeNumber(subitems[j].code);
 
-           nextStart = incHex(subitems[j].end);
 
-         }
 
-         break;
 
-       case 2:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.char)) +
 
-           writeNumber(subitems.length);
 
-         out += first.char + writeNumber(first.code);
 
-         nextStart = incHex(first.char);
 
-         nextCode = first.code + 1;
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             (sequence ? "" : writeNumber(subHex(subitems[j].char, nextStart))) +
 
-             writeSigned(subitems[j].code - nextCode);
 
-           nextStart = incHex(subitems[j].char);
 
-           nextCode = item.items[j].code + 1;
 
-         }
 
-         break;
 
-       case 3:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.start)) +
 
-           writeNumber(subitems.length);
 
-         out +=
 
-           first.start +
 
-           writeNumber(subHex(first.end, first.start)) +
 
-           writeNumber(first.code);
 
-         nextStart = incHex(first.end);
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             (sequence
 
-               ? ""
 
-               : writeNumber(subHex(subitems[j].start, nextStart))) +
 
-             writeNumber(subHex(subitems[j].end, subitems[j].start)) +
 
-             writeNumber(subitems[j].code);
 
-           nextStart = incHex(subitems[j].end);
 
-         }
 
-         break;
 
-       case 4:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.code)) +
 
-           writeNumber(subitems.length);
 
-         out += first.char + first.code;
 
-         nextStart = incHex(first.char);
 
-         nextCode = incHex(first.code);
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             (sequence ? "" : writeNumber(subHex(subitems[j].char, nextStart))) +
 
-             writeSigned(subHex(subitems[j].code, nextCode));
 
-           nextStart = incHex(subitems[j].char);
 
-           nextCode = incHex(subitems[j].code);
 
-         }
 
-         break;
 
-       case 5:
 
-         out +=
 
-           writeByte(flags | getHexSize(first.code)) +
 
-           writeNumber(subitems.length);
 
-         out +=
 
-           first.start +
 
-           writeNumber(subHex(first.end, first.start)) +
 
-           first.code;
 
-         nextStart = incHex(first.end);
 
-         for (let j = 1; j < subitems.length; j++) {
 
-           out +=
 
-             (sequence
 
-               ? ""
 
-               : writeNumber(subHex(subitems[j].start, nextStart))) +
 
-             writeNumber(subHex(subitems[j].end, subitems[j].start)) +
 
-             subitems[j].code;
 
-           nextStart = incHex(subitems[j].end);
 
-         }
 
-         break;
 
-     }
 
-   }
 
-   fs.writeFileSync(destPath, Buffer.from(out, "hex"));
 
-   if (verify) {
 
-     const result2 = parseCMap(out);
 
-     const isGood = JSON.stringify(inputData) === JSON.stringify(result2);
 
-     if (!isGood) {
 
-       throw new Error("Extracted data does not match the expected result");
 
-     }
 
-   }
 
-   return {
 
-     orig: fs.statSync(srcPath).size,
 
-     packed: out.length >> 1,
 
-   };
 
- }
 
- function parseCMap(binaryData) {
 
-   const reader = {
 
-     buffer: binaryData,
 
-     pos: 0,
 
-     end: binaryData.length,
 
-     readByte() {
 
-       if (this.pos >= this.end) {
 
-         return -1;
 
-       }
 
-       const d1 = fromHexDigit(this.buffer[this.pos]);
 
-       const d2 = fromHexDigit(this.buffer[this.pos + 1]);
 
-       this.pos += 2;
 
-       return (d1 << 4) | d2;
 
-     },
 
-     readNumber() {
 
-       let n = 0;
 
-       let last;
 
-       do {
 
-         const b = this.readByte();
 
-         last = !(b & 0x80);
 
-         n = (n << 7) | (b & 0x7f);
 
-       } while (!last);
 
-       return n;
 
-     },
 
-     readSigned() {
 
-       const n = this.readNumber();
 
-       return n & 1 ? -(n >>> 1) - 1 : n >>> 1;
 
-     },
 
-     readHex(size) {
 
-       const lengthInChars = (size + 1) << 1;
 
-       const s = this.buffer.substring(this.pos, this.pos + lengthInChars);
 
-       this.pos += lengthInChars;
 
-       return s;
 
-     },
 
-     readHexNumber(size) {
 
-       const lengthInChars = (size + 1) << 1,
 
-         stack = [];
 
-       let last;
 
-       do {
 
-         const b = this.readByte();
 
-         last = !(b & 0x80);
 
-         stack.push(b & 0x7f);
 
-       } while (!last);
 
-       let s = "",
 
-         buffer = 0,
 
-         bufferSize = 0;
 
-       while (s.length < lengthInChars) {
 
-         while (bufferSize < 4 && stack.length > 0) {
 
-           buffer |= stack.pop() << bufferSize;
 
-           bufferSize += 7;
 
-         }
 
-         s = toHexDigit(buffer & 15) + s;
 
-         buffer >>= 4;
 
-         bufferSize -= 4;
 
-       }
 
-       return s;
 
-     },
 
-     readHexSigned(size) {
 
-       const num = this.readHexNumber(size);
 
-       const sign = fromHexDigit(num[num.length - 1]) & 1 ? 15 : 0;
 
-       let c = 0;
 
-       let result = "";
 
-       for (const digit of num) {
 
-         c = (c << 4) | fromHexDigit(digit);
 
-         result += toHexDigit(sign ? (c >> 1) ^ sign : c >> 1);
 
-         c &= 1;
 
-       }
 
-       return result;
 
-     },
 
-     readString() {
 
-       const len = this.readNumber();
 
-       let s = "";
 
-       for (let i = 0; i < len; i++) {
 
-         s += String.fromCharCode(this.readNumber());
 
-       }
 
-       return s;
 
-     },
 
-   };
 
-   const header = reader.readByte();
 
-   const result = {
 
-     type: header >> 1,
 
-     wmode: header & 1,
 
-     comment: null,
 
-     usecmap: null,
 
-     body: [],
 
-   };
 
-   let b;
 
-   while ((b = reader.readByte()) >= 0) {
 
-     const type = b >> 5;
 
-     if (type === 7) {
 
-       switch (b & 0x1f) {
 
-         case 0:
 
-           result.comment = reader.readString();
 
-           break;
 
-         case 1:
 
-           result.usecmap = reader.readString();
 
-           break;
 
-       }
 
-       continue;
 
-     }
 
-     const sequence = !!(b & 0x10);
 
-     const dataSize = b & 15;
 
-     const subitems = [];
 
-     const item = {
 
-       type,
 
-       items: subitems,
 
-     };
 
-     if (sequence) {
 
-       item.sequence = true;
 
-     }
 
-     const ucs2DataSize = 1;
 
-     const subitemsCount = reader.readNumber();
 
-     let start, end, code, char;
 
-     switch (type) {
 
-       case 0:
 
-         start = reader.readHex(dataSize);
 
-         end = addHex(reader.readHexNumber(dataSize), start);
 
-         subitems.push({ start, end });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           start = addHex(reader.readHexNumber(dataSize), incHex(end));
 
-           end = addHex(reader.readHexNumber(dataSize), start);
 
-           subitems.push({ start, end });
 
-         }
 
-         break;
 
-       case 1:
 
-         start = reader.readHex(dataSize);
 
-         end = addHex(reader.readHexNumber(dataSize), start);
 
-         code = reader.readNumber();
 
-         subitems.push({ start, end, code });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           start = addHex(reader.readHexNumber(dataSize), incHex(end));
 
-           end = addHex(reader.readHexNumber(dataSize), start);
 
-           code = reader.readNumber();
 
-           subitems.push({ start, end, code });
 
-         }
 
-         break;
 
-       case 2:
 
-         char = reader.readHex(dataSize);
 
-         code = reader.readNumber();
 
-         subitems.push({ char, code });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           char = sequence
 
-             ? incHex(char)
 
-             : addHex(reader.readHexNumber(dataSize), incHex(char));
 
-           code = reader.readSigned() + (code + 1);
 
-           subitems.push({ char, code });
 
-         }
 
-         break;
 
-       case 3:
 
-         start = reader.readHex(dataSize);
 
-         end = addHex(reader.readHexNumber(dataSize), start);
 
-         code = reader.readNumber();
 
-         subitems.push({ start, end, code });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           start = sequence
 
-             ? incHex(end)
 
-             : addHex(reader.readHexNumber(dataSize), incHex(end));
 
-           end = addHex(reader.readHexNumber(dataSize), start);
 
-           code = reader.readNumber();
 
-           subitems.push({ start, end, code });
 
-         }
 
-         break;
 
-       case 4:
 
-         char = reader.readHex(ucs2DataSize);
 
-         code = reader.readHex(dataSize);
 
-         subitems.push({ char, code });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           char = sequence
 
-             ? incHex(char)
 
-             : addHex(reader.readHexNumber(ucs2DataSize), incHex(char));
 
-           code = addHex(reader.readHexSigned(dataSize), incHex(code));
 
-           subitems.push({ char, code });
 
-         }
 
-         break;
 
-       case 5:
 
-         start = reader.readHex(ucs2DataSize);
 
-         end = addHex(reader.readHexNumber(ucs2DataSize), start);
 
-         code = reader.readHex(dataSize);
 
-         subitems.push({ start, end, code });
 
-         for (let i = 1; i < subitemsCount; i++) {
 
-           start = sequence
 
-             ? incHex(end)
 
-             : addHex(reader.readHexNumber(ucs2DataSize), incHex(end));
 
-           end = addHex(reader.readHexNumber(ucs2DataSize), start);
 
-           code = reader.readHex(dataSize);
 
-           subitems.push({ start, end, code });
 
-         }
 
-         break;
 
-       default:
 
-         throw new Error("Unknown type: " + type);
 
-     }
 
-     result.body.push(item);
 
-   }
 
-   return result;
 
- }
 
- function toHexDigit(n) {
 
-   return n.toString(16);
 
- }
 
- function fromHexDigit(s) {
 
-   return parseInt(s, 16);
 
- }
 
- function getHexSize(s) {
 
-   return (s.length >> 1) - 1;
 
- }
 
- function writeByte(b) {
 
-   return toHexDigit((b >> 4) & 15) + toHexDigit(b & 15);
 
- }
 
- function writeNumber(n) {
 
-   if (typeof n === "string") {
 
-     let s = "",
 
-       buffer = 0,
 
-       bufferSize = 0;
 
-     let i = n.length;
 
-     while (i > 0) {
 
-       --i;
 
-       buffer |= fromHexDigit(n[i]) << bufferSize;
 
-       bufferSize += 4;
 
-       if (bufferSize >= 7) {
 
-         s = writeByte((buffer & 0x7f) | (s.length > 0 ? 0x80 : 0)) + s;
 
-         buffer >>>= 7;
 
-         bufferSize -= 7;
 
-       }
 
-     }
 
-     if (buffer > 0) {
 
-       s = writeByte((buffer & 0x7f) | (s.length > 0 ? 0x80 : 0)) + s;
 
-     }
 
-     while (s.indexOf("80") === 0) {
 
-       s = s.substring(2);
 
-     }
 
-     return s;
 
-   }
 
-   let s = writeByte(n & 0x7f);
 
-   n >>>= 7;
 
-   while (n > 0) {
 
-     s = writeByte((n & 0x7f) | 0x80) + s;
 
-     n >>>= 7;
 
-   }
 
-   return s;
 
- }
 
- function writeSigned(n) {
 
-   if (typeof n === "string") {
 
-     let t = "";
 
-     let c = fromHexDigit(n[0]);
 
-     const neg = c >= 8;
 
-     c = neg ? c ^ 15 : c;
 
-     for (let i = 1; i < n.length; i++) {
 
-       const d = fromHexDigit(n[i]);
 
-       c = (c << 4) | (neg ? d ^ 15 : d);
 
-       t += toHexDigit(c >> 3);
 
-       c &= 7;
 
-     }
 
-     t += toHexDigit((c << 1) | (neg ? 1 : 0));
 
-     return writeNumber(t);
 
-   }
 
-   return n < 0 ? writeNumber(-2 * n - 1) : writeNumber(2 * n);
 
- }
 
- function writeString(s) {
 
-   let t = writeNumber(s.length);
 
-   for (let i = 0; i < s.length; i++) {
 
-     t += writeNumber(s.charCodeAt(i));
 
-   }
 
-   return t;
 
- }
 
- function addHex(a, b) {
 
-   let c = 0,
 
-     s = "";
 
-   for (let i = a.length - 1; i >= 0; i--) {
 
-     c += fromHexDigit(a[i]) + fromHexDigit(b[i]);
 
-     if (c >= 16) {
 
-       s = toHexDigit(c - 16) + s;
 
-       c = 1;
 
-     } else {
 
-       s = toHexDigit(c) + s;
 
-       c = 0;
 
-     }
 
-   }
 
-   return s;
 
- }
 
- function subHex(a, b) {
 
-   let c = 0,
 
-     s = "";
 
-   for (let i = a.length - 1; i >= 0; i--) {
 
-     c += fromHexDigit(a[i]) - fromHexDigit(b[i]);
 
-     if (c < 0) {
 
-       s = toHexDigit(c + 16) + s;
 
-       c = -1;
 
-     } else {
 
-       s = toHexDigit(c) + s;
 
-       c = 0;
 
-     }
 
-   }
 
-   return s;
 
- }
 
- function incHex(a) {
 
-   let c = 1,
 
-     s = "";
 
-   for (let i = a.length - 1; i >= 0; i--) {
 
-     c += fromHexDigit(a[i]);
 
-     if (c >= 16) {
 
-       s = toHexDigit(c - 16) + s;
 
-       c = 1;
 
-     } else {
 
-       s = toHexDigit(c) + s;
 
-       c = 0;
 
-     }
 
-   }
 
-   return s;
 
- }
 
- exports.compressCmaps = function (src, dest, verify) {
 
-   const files = fs.readdirSync(src).filter(function (fn) {
 
-     return !fn.includes("."); // skipping files with the extension
 
-   });
 
-   files.forEach(function (fn) {
 
-     const srcPath = path.join(src, fn);
 
-     const destPath = path.join(dest, fn + ".bcmap");
 
-     const stats = compressCmap(srcPath, destPath, verify);
 
-     console.log(
 
-       "Compressing " +
 
-         fn +
 
-         ": " +
 
-         stats.orig +
 
-         " vs " +
 
-         stats.packed +
 
-         " " +
 
-         ((stats.packed / stats.orig) * 100).toFixed(1) +
 
-         "%"
 
-     );
 
-   });
 
- };
 
 
  |