async readToUnicode(cmapObj) {
    if (!cmapObj) {
      return null;
    }
    if (cmapObj instanceof Name) {
      const cmap = await CMapFactory.create({
        encoding: cmapObj,
        fetchBuiltInCMap: this._fetchBuiltInCMapBound,
        useCMap: null,
      });

      if (cmap instanceof IdentityCMap) {
        return new IdentityToUnicodeMap(0, 0xffff);
      }
      return new ToUnicodeMap(cmap.getMap());
    }
    if (cmapObj instanceof BaseStream) {
      try {
        const cmap = await CMapFactory.create({
          encoding: cmapObj,
          fetchBuiltInCMap: this._fetchBuiltInCMapBound,
          useCMap: null,
        });

        if (cmap instanceof IdentityCMap) {
          return new IdentityToUnicodeMap(0, 0xffff);
        }
        const map = new Array(cmap.length);
        // Convert UTF-16BE
        // NOTE: cmap can be a sparse array, so use forEach instead of
        // `for(;;)` to iterate over all keys.
        cmap.forEach(function (charCode, token) {
          // Some cmaps contain *only* CID characters (fixes issue9367.pdf).
          if (typeof token === "number") {
            map[charCode] = String.fromCodePoint(token);
            return;
          }
          // Add back omitted leading zeros on odd length tokens
          // (fixes issue #18099)
          if (token.length % 2 !== 0) {
            token = "\u0000" + token;
          }
          const str = [];
          for (let k = 0; k < token.length; k += 2) {
            const w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
            if ((w1 & 0xf800) !== 0xd800) {
              // w1 < 0xD800 || w1 > 0xDFFF
              str.push(w1);
              continue;
            }
            k += 2;
            const w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
            str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
          }
          map[charCode] = String.fromCodePoint(...str);
        });
        return new ToUnicodeMap(map);
      } catch (reason) {
        if (reason instanceof AbortException) {
          return null;
        }
        if (this.options.ignoreErrors) {
          warn(`readToUnicode - ignoring ToUnicode data: "${reason}".`);
          return null;
        }
        throw reason;
      }
    }
    return null;
  }
Builds a char code to unicode map based on section 9.10 of the spec.
@param {Object} properties Font properties object.
@returns {Promise} A Promise that is resolved with a
  {ToUnicodeMap|IdentityToUnicodeMap} object.