jessekrubin / pbfont

pbf-font(s)
Other
2 stars 2 forks source link

Add test for #91 v2 #97

Closed acalcutt closed 2 months ago

acalcutt commented 2 months ago

Continuation of https://github.com/jessekrubin/pbfont/pull/96 . Change to the composite file from @mapbox/glyph-pbf-composite for expected results.

Don't set a name, use what is in the files

jessekrubin commented 2 months ago

@acalcutt I am on my phone but here is a dumb solution... tho it does not actually check for any validity...

/**
 * Combine any number of glyph (SDF) PBFs.
 * Returns a re-encoded PBF with the combined font faces, composited using array order
 * to determine glyph priority.
 * @param buffers An array of SDF PBFs.
 * @param fontstackName Optional font stack name.
 * @returns Combined glyph PBF.
 */
export function combine(
  buffers: Uint8Array[],
  fontstackName?: string,
): Uint8Array | undefined {
  if (buffers.length === 0) return;
  if (buffers.length === 1) return buffers[0];
  const coverage = new Map<number, boolean>();
  const combinedGlyphs: glyph[] = []; // Initialize an empty array to hold the combined glyphs
  const names: string[] = [];
  const rangeStrings: string[] = [];
  for (const buffer of buffers) {
    const decodedGlyphs = decode(buffer);
    const currentFontstack = decodedGlyphs.stacks[0];
    const currentGlyphs = currentFontstack?.glyphs || [];
    const fsRange = currentFontstack?.range;
    if (fsRange) {
      rangeStrings.push(fsRange);
    }
    // Combine glyphs and check for duplicates
    for (const glyph of currentGlyphs) {
      const gid = glyph.id;
      if (gid !== undefined && !coverage.has(gid)) {
        combinedGlyphs.push(glyph);
        coverage.set(gid, true);
      }
    }

    const currentFontstackName = currentFontstack?.name;
    // Combine font stack names
    if (currentFontstackName) {
      names.push(currentFontstackName);
    }
  }

  // Sort the combined glyphs by id
  combinedGlyphs.sort((a, b) => {
    return a.id - b.id;
  });
  const allids = [...coverage.keys()];
  let rangeStr: string = "";
  if (allids.length === 0 && rangeStrings.length > 0) {
    rangeStr = rangeStrings.pop() || "";
  }else{
    const minId = allids.length === 0 ? 0 : Math.min(...allids);
    const range = range256(minId);
    rangeStr = range.str;
  }

  // Create the result glyphs message
  const theFontstackObj = {
    name: fontstackName || names.join(", "), // Use provided font stack name or the combined one
    glyphs: combinedGlyphs,
    range: rangeStr,
  };
  const thefontstack = create(fontstackSchema, theFontstackObj);
  const result = create(glyphsSchema, { stacks: [thefontstack] });
  return encode(result);
}
acalcutt commented 2 months ago

Looks like your idea is close to what i tried in the last commit. that seemed to work (though mine is a bit half-assed)

Seems like this happens because in both fonts, currentFontstack has not glyphs.