Skip to content

Commit

Permalink
skip named glyphs if code point already present in charmap
Browse files Browse the repository at this point in the history
  • Loading branch information
mgieseki committed Feb 17, 2025
1 parent 8ef96ff commit f7b0049
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 16 deletions.
23 changes: 15 additions & 8 deletions src/FontEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,29 +169,36 @@ void FontEngine::buildGidToCharCodeMap (RangeMap &charmap) const {
// In case the Unicode map of the font doesn't cover all characters, some
// of them could still be identified by their names if present in the font.
if (FT_HAS_GLYPH_NAMES(_currentFace)) {
NumericRanges<uint32_t> usedCodepoints;
for (size_t i=0; i < charmap.numRanges(); i++)
usedCodepoints.addRange(charmap.getRange(i).minval(), charmap.getRange(i).maxval());
if (charmap.empty())
addCharsByGlyphNames(1, getNumGlyphs(), charmap);
addCharsByGlyphNames(1, getNumGlyphs(), charmap, usedCodepoints);
else {
addCharsByGlyphNames(1, charmap.minKey()-1, charmap);
addCharsByGlyphNames(1, charmap.minKey()-1, charmap, usedCodepoints);
for (size_t i=1; i < charmap.numRanges(); i++)
addCharsByGlyphNames(charmap.getRange(i-1).max()+1, charmap.getRange(i).min()-1, charmap);
addCharsByGlyphNames(charmap.maxKey()+1, getNumGlyphs(), charmap);
addCharsByGlyphNames(charmap.getRange(i-1).max()+1, charmap.getRange(i).min()-1, charmap, usedCodepoints);
addCharsByGlyphNames(charmap.maxKey()+1, getNumGlyphs(), charmap, usedCodepoints);
}
}
}


/** Looks for known glyph names in a given GID range and adds the corresponding
* GID->code point mapping to a character map.
* GID->code point mapping to a character map if the code point is not already present.
* @param[in] minGID minimum GID of range to iterate
* @param[in] maxGID maximum GID of range to iterate
* @param[in,out] charmap character map taking the new mappings */
void FontEngine::addCharsByGlyphNames (uint32_t minGID, uint32_t maxGID, RangeMap &charmap) const {
* @param[in,out] charmap character map taking the new mappings
* @param[in,out] ucp collection of code points already present in the character map */
void FontEngine::addCharsByGlyphNames (uint32_t minGID, uint32_t maxGID, RangeMap &charmap, CodepointRanges &ucp) const {
for (uint32_t gid=minGID; gid <= maxGID; gid++) {
char glyphName[64];
if (FT_Get_Glyph_Name(_currentFace, gid, glyphName, 64) == 0) {
if (int32_t cp = Unicode::aglNameToCodepoint(glyphName))
const int32_t cp = Unicode::aglNameToCodepoint(glyphName);
if (cp && !ucp.valueExists(cp)) {
charmap.addRange(gid, gid, cp);
ucp.addRange(cp);
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/FontEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@
#include "Character.hpp"
#include "CharMapID.hpp"
#include "Glyph.hpp"
#include "NumericRanges.hpp"
#include "RangeMap.hpp"

class Font;

/** This class provides methods to handle font files and font data.
* It's a wrapper for the Freetype font library. */
class FontEngine {
using CodepointRanges = NumericRanges<uint32_t>;
public:
~FontEngine ();
static FontEngine& instance ();
Expand Down Expand Up @@ -75,7 +77,7 @@ class FontEngine {
FontEngine ();
bool setFont (const std::string &fname, int fontindex, const CharMapID &charmapID);
int charIndex (const Character &c) const;
void addCharsByGlyphNames (uint32_t minGID, uint32_t maxGID, RangeMap &charmap) const;
void addCharsByGlyphNames (uint32_t minGID, uint32_t maxGID, RangeMap &charmap, CodepointRanges &ucp) const;

private:
FT_Face _currentFace = nullptr;
Expand Down
8 changes: 4 additions & 4 deletions src/ToUnicodeMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ bool ToUnicodeMap::addMissingMappings (uint32_t maxIndex) {
// collect Unicode points already in assigned
NumericRanges<uint32_t> codepoints;
for (size_t i=0; i < numRanges(); i++)
codepoints.addRange(rangeAt(i).minval(), rangeAt(i).maxval());
codepoints.addRange(getRange(i).minval(), getRange(i).maxval());
// fill unmapped ranges
bool success;
if (empty()) // no Unicode mapping present at all?
success = fillRange(1, maxIndex, 1, codepoints, true);
else { // (partial) Unicode mapping present?
success = fillRange(1, rangeAt(0).min()-1, rangeAt(0).minval()-1, codepoints, false);
success = fillRange(1, getRange(0).min()-1, getRange(0).minval()-1, codepoints, false);
for (size_t i=0; i < numRanges()-1 && success; i++)
success = fillRange(rangeAt(i).max()+1, rangeAt(i+1).min()-1, rangeAt(i).maxval()+1, codepoints, true);
success = fillRange(getRange(i).max()+1, getRange(i+1).min()-1, getRange(i).maxval()+1, codepoints, true);
if (success)
success = fillRange(rangeAt(numRanges()-1).max()+1, maxIndex, rangeAt(numRanges()-1).maxval()+1, codepoints, true);
success = fillRange(getRange(numRanges()-1).max()+1, maxIndex, getRange(numRanges()-1).maxval()+1, codepoints, true);
}
return success;
}
Expand Down
5 changes: 2 additions & 3 deletions src/ToUnicodeMap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@
#include "RangeMap.hpp"


/** Represents a mapping from character indexes to unicode points. */
class ToUnicodeMap : public RangeMap
{
/** Represents a mapping from character indexes to Unicode points. */
class ToUnicodeMap : public RangeMap {
public:
bool addMissingMappings (uint32_t maxIndex);

Expand Down

0 comments on commit f7b0049

Please sign in to comment.