Example #1
0
    def _glyphIsRtl(self, name):
        """Return whether the closest-associated unicode character is RTL."""

        delims = ('.', '_')
        uv = self.font[name].unicode
        while uv is None and any(d in name for d in delims):
            name = name[:max(name.rfind(d) for d in delims)]
            if name in self.font:
                uv = self.font[name].unicode
        if uv is None:
            return False
        return unicodedata.bidirectional(unichr(uv)) in ('R', 'AL')
Example #2
0
    def _glyphIsRtl(self, name):
        """Return whether the closest-associated unicode character is RTL."""

        delims = ('.', '_')
        uv = self.font[name].unicode
        while uv is None and any(d in name for d in delims):
            name = name[:max(name.rfind(d) for d in delims)]
            if name in self.font:
                uv = self.font[name].unicode
        if uv is None:
            return False
        return unicodedata.bidirectional(unichr(uv)) in ('R', 'AL')
Example #3
0
    def getPairItemDirection(self, item):
        """
        Return one of: "LTR", "RTL", "MIX", False

        Note that when mentioning "groups" that includes single glyphs.
        A single item is treated as a group with just one member.

        This was the initial description

        * Associate each glyph to a Unicode character,
        * Exclude from RTL kern table all glyphs associated
                with Unicode characters that have Bidi_Type=L,
        * Exclude from LTR kern table all glyphs associated
               with Unicode characters that have Bidi_Type=R or Bidi_Type=AL.

        However, the exclusion model got altered into an inclusion model
        because groups could define mixed directions and thus would have
        to stay in all kern tables.

        An alternative way could be to break up the groups and reorder
        them to create a couple of better defined groups.

        FILTERING:
        Only if all memnbers of a group are `False` the whole group and
        subsequently pair is dissmissed. Alternativeley we could dismiss
        the whole group when at least one member is `False`. But I believe
        that would create more problems.
        Rather: we should filter the group contents much earlier in
        KernFeatureWriter.getPairs or KernFeatureWriter.getGroups

        See also: the docs for options.ignoreMissingUnicodeInGroupItems
                  in __init__
        """
        # Note: KernFeatureWriter.getPairs should already have filtered
        # empty groups and nonexisting pairs, thus it is not checked here.
        if item.startswith(side1FeaPrefix) or item.startswith(side2FeaPrefix):
            groups = self.side1Groups if item.startswith(side1FeaPrefix) \
                                      else self.side2Groups
            names = groups[item]
        else:
            names = [item]

        writingDirs = set()
        for name in names:
            unicodeChar = self.getUnicodeFromGlyphName(name)
            # http://unicode.org/reports/tr9/#Table_Bidirectional_Character_Types
            if unicodeChar == False:
                if not self.options['ignoreMissingUnicodeInGroupItems']:
                    # may result in a "MIX" pair if this is a bigger group
                    writingDirs.add(False)
                continue
            bidiType = unicodedata.bidirectional(unicodeChar)

            # L: Left-to-Right
            if bidiType == 'L':
                writingDirs.add('LTR')
            # R: Right-to-Left
            # AL: Right-to-Left Arabic
            elif bidiType in ('R', 'AL'):
                writingDirs.add('RTL')
            # AN: Arabic Number
            # FIXME: remove bidiType == 'AN' this from kerning? This
            # filtering should rather happen earlier, somewhere in
            # KernFeatureWriter.getPairs or KernFeatureWriter.getGroups
            # elif bidiType == 'AN':
            #    writingDirs.add(False)
            else:
                writingDirs.add('MIX')

        # if writingDirs.has(False)
        #     return False
        if len(writingDirs) > 1:
            return 'MIX'
        elif len(writingDirs) == 0:
            return False
        return writingDirs.pop() # "LTR", "RTL", "MIX" or False
Example #4
0
    def getPairItemDirection(self, item):
        """
        Return one of: "LTR", "RTL", "MIX", False

        Note that when mentioning "groups" that includes single glyphs.
        A single item is treated as a group with just one member.

        This was the initial description

        * Associate each glyph to a Unicode character,
        * Exclude from RTL kern table all glyphs associated
                with Unicode characters that have Bidi_Type=L,
        * Exclude from LTR kern table all glyphs associated
               with Unicode characters that have Bidi_Type=R or Bidi_Type=AL.

        However, the exclusion model got altered into an inclusion model
        because groups could define mixed directions and thus would have
        to stay in all kern tables.

        An alternative way could be to break up the groups and reorder
        them to create a couple of better defined groups.

        FILTERING:
        Only if all memnbers of a group are `False` the whole group and
        subsequently pair is dissmissed. Alternativeley we could dismiss
        the whole group when at least one member is `False`. But I believe
        that would create more problems.
        Rather: we should filter the group contents much earlier in
        KernFeatureWriter.getPairs or KernFeatureWriter.getGroups

        See also: the docs for options.ignoreMissingUnicodeInGroupItems
                  in __init__
        """
        # Note: KernFeatureWriter.getPairs should already have filtered
        # empty groups and nonexisting pairs, thus it is not checked here.
        if item.startswith(side1FeaPrefix) or item.startswith(side2FeaPrefix):
            groups = self.side1Groups if item.startswith(side1FeaPrefix) \
                                      else self.side2Groups
            names = groups[item]
        else:
            names = [item]

        writingDirs = set()
        for name in names:
            unicodeChar = self.getUnicodeFromGlyphName(name)
            # http://unicode.org/reports/tr9/#Table_Bidirectional_Character_Types
            if unicodeChar == False:
                if not self.options['ignoreMissingUnicodeInGroupItems']:
                    # may result in a "MIX" pair if this is a bigger group
                    writingDirs.add(False)
                continue
            bidiType = unicodedata.bidirectional(unicodeChar)

            # L: Left-to-Right
            if bidiType == 'L':
                writingDirs.add('LTR')
            # R: Right-to-Left
            # AL: Right-to-Left Arabic
            elif bidiType in ('R', 'AL'):
                writingDirs.add('RTL')
            # AN: Arabic Number
            # FIXME: remove bidiType == 'AN' this from kerning? This
            # filtering should rather happen earlier, somewhere in
            # KernFeatureWriter.getPairs or KernFeatureWriter.getGroups
            # elif bidiType == 'AN':
            #    writingDirs.add(False)
            else:
                writingDirs.add('MIX')

        # if writingDirs.has(False)
        #     return False
        if len(writingDirs) > 1:
            return 'MIX'
        elif len(writingDirs) == 0:
            return False
        return writingDirs.pop()  # "LTR", "RTL", "MIX" or False