petermikitsh / ligatures

Get ligatures for fonts
https://petermikitsh.github.io/ligatures
8 stars 1 forks source link

how to get the fontkit glyph for the returned ligatures? #8

Open Typogram opened 10 months ago

Typogram commented 10 months ago

Thanks for this awesoem package, I was able to get an array returned that looks like this:

['ſſb', 'ſſh', 'ſſi', 'ſſj', 'ſſk', 'ſſl', 'ſſt', 'ſb', 'ſh', 'ſi', 'ſj', 'ſk', 'ſl', 'ſſ', 'ſs', 'ſt', 'ffi', 'ffl', 'ff', 'fi', 'fl', 'fine', 'ok', 'paper', 'scissors', 'stone', 'arrowrightarrowright', 'arrowdownarrowdown', 'arrowleftarrowleft', 'arrowuparrowup', 'arrowright4', 'arrowright/', 'arrowright3', 'arrowright2', 'arrowupdown', 'arrowboth/', 'arrowdown2', 'arrowleft4', 'arrowleft<', 'arrowleft/', 'arrowleft3', 'arrowleft2', 'arrowright', 'arrowboth', 'arrowdown', 'arrowleft', 'arrowup2', 'arrowup', 'northeast', 'northwest', 'southeast', 'southwest', 'Qy', 'Th', 'ch', 'ck', 'ct', 'ffb', 'ffh', 'ffi', 'ffj', 'ffk', 'ffl', 'fft', 'fb', 'ff', 'fh', 'fj', 'fk', 'ft', 'qꝫ', 'st', 'ſſb', 'ſſh', 'ſſi', 'ſſj', 'ſſk', 'ſſl', 'ſſt', 'ſb', 'ſh', 'ſi', 'ſj', 'ſk', 'ſl', 'ſſ', 'ſs', 'ſt', 'tt']

from this array of string, how do I get the fontkit Glyph of each character?

Typogram commented 10 months ago

I figured it out by revising the code a little bit. I also rewrote it to avoid using Array.reduce() because I had a hard time reading it because unfamiliarity. Hope this code can help someone else:

function getLigatures(font) {
  if (!font.GSUB) {
    return [];
  }

  const ligatures = [];

  const lookupLists = font.GSUB.lookupList.toArray();
  for (let lookupList of lookupLists) {
    // Table Type 4 is ligature substitutions
    if (lookupList.lookupType !== 4) {
      continue;
    }

    const {
      coverage: { glyphs, rangeRecords },
      ligatureSets
    } = lookupList.subTables[0];

    let leadingChars = [];

    if (rangeRecords) {
      for (let { start, end } of rangeRecords) {
        for (let x = start; x <= end; x++) {
          const char = font.stringsForGlyph(x)[0];
          leadingChars.push(char);
        }
      }
    } else {
      for (let glyph of glyphs) {
        const result = font.stringsForGlyph(glyph);
        leadingChars.push(result.join(''));
      }
    }

    const ligatureSetsArray = ligatureSets.toArray();

    ligatureSetsArray.forEach((ligatureSet, i) => {
      ligatureSet.forEach((ligature) => {
        const fullLigature =
          leadingChars[i] +
          ligature.components.map((x) => font.stringsForGlyph(x)[0]).join('');
        ligature.content = fullLigature;
        ligatures.push(ligature);
      });
    });
  }

  return ligatures;
}

the returned object not only contain the string like 'ſſb' under the content property, but it also return glyphId via glyph property. Then you are free to grab the Glyph object from fontkit by calling:

font.getGlyph(ligature.glyph)

Thanks again for this awesome project ,saved me a ton of time!