Exemple #1
0
def decompositionBase(value):
    letterCategories = ("Ll", "Lu", "Lt", "Lo")
    try:
        c = unichr(value)
    # see not in category function
    except ValueError:
        return -1
    decomposition = unicodedata.decomposition(c)
    if decomposition.startswith("<"):
        return -1
    if " " not in decomposition:
        return -1
    parts = decomposition.split(" ")
    unichrs = [unichr(int(i, 16)) for i in parts if i]
    letters = [
        ord(i) for i in unichrs if unicodedata.category(i) in letterCategories
    ]
    letterCount = len(letters)
    if letterCount != 1:
        return -1
    decomposedUniValue = letters[0]
    furtherDecomposedUniValue = decompositionBase(decomposedUniValue)
    if furtherDecomposedUniValue != -1:
        furtherFurtherDecomposedUniValue = decompositionBase(
            furtherDecomposedUniValue)
        if furtherFurtherDecomposedUniValue != -1:
            decomposedUniValue = furtherFurtherDecomposedUniValue
        else:
            decomposedUniValue = furtherDecomposedUniValue
    return decomposedUniValue
Exemple #2
0
    def input_from_name(self, name, seen=None, pad=False):
        """Given glyph name, return input to harbuzz to render this glyph.

        Returns input in the form of a (features, text) tuple, where `features`
        is a list of feature tags to activate and `text` is an input string.

        Argument `seen` is used by the method to avoid following cycles when
        recursively looking for possible input. `pad` can be used to add
        whitespace to text output, for non-spacing glyphs.

        Can return None in two situations: if no possible input is found (no
        simple unicode mapping or substitution rule exists to generate the
        glyph), or if the requested glyph already exists in `seen` (in which
        case this path of generating input should not be followed further).
        """

        if name in self.memo:
            return self.memo[name]

        inputs = []

        # avoid following cyclic paths through features
        if seen is None:
            seen = set()
        if name in seen:
            return None
        seen.add(name)

        # see if this glyph has a simple unicode mapping
        if name in self.reverse_cmap:
            text = unichr(self.reverse_cmap[name])
            if text != unichr(0):
                inputs.append(((), text))

        # check the substitution features
        inputs.extend(self._inputs_from_gsub(name, seen))
        # seen.remove(name)

        # since this method sometimes returns None to avoid cycles, the
        # recursive calls that it makes might have themselves returned None,
        # but we should avoid returning None here if there are other options
        inputs = [i for i in inputs if i is not None]
        if not inputs:
            return None

        features, text = min(inputs)
        # can't pad if we don't support space
        if pad and self.space_width > 0:
            width, space = self.widths[name], self.space_width
            padding = ' ' * (width // space + (1 if width % space else 0))
            text = padding + text
        self.memo[name] = features, text
        return self.memo[name]
    def __init__(self, parentWindow):

        data = getExtensionDefault(self.identifier, dict())
        self.w = Sheet((470, 580), parentWindow=parentWindow)

        self.w.tabs = Tabs((10, 10, -10, -40), ["TTF AutoHint", "HTML Preview"])
        self.w.tabs[0].settings = self.settings = TTFAutoHintGroup((0, 0, -0, -0))
        self.settings.set(data)

        y = 10
        self.w.tabs[1].htmlText = TextBox((10, y, 100, 22), "HTML preview:")
        y += 30
        self.w.tabs[1].html = self.html = CodeEditor((10, y, -10, 250), getExtensionDefault("%s.htmlPreview" % settingsIdentifier, htmlPreviewDefault), lexer="html")
        self.html.showLineNumbers(False)
        y += 260
        self.w.tabs[1].globalCssText = TextBox((10, y, 100, 22), "CSS Style:")
        y += 30
        self.w.tabs[1].globalCss = self.globalCss = CodeEditor((10, y, -10, -10), getExtensionDefault("%s.globalCSSPreview" % settingsIdentifier, ""), lexer="css")
        self.globalCss.showLineNumbers(False)

        self.w.saveButton = Button((-100, -30, -10, 20), "Save settings", callback=self.saveCallback, sizeStyle="small")
        self.w.setDefaultButton(self.w.saveButton)

        self.w.closeButton = Button((-190, -30, -110, 20), "Cancel", callback=self.closeCallback, sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.resetButton = Button((-280, -30, -200, 20), "Reset", callback=self.resetCallback, sizeStyle="small")
        self.w.open()
    def __init__(self, parentWindow):

        data = getExtensionDefault(self.identifier, dict())
        updateWithDefaultValues(data, defaultOptions)

        width = 380
        height = 1000

        self.w = Sheet((width, height), parentWindow=parentWindow)

        y = 10
        self.w.threaded = CheckBox((10, y, -10, 22), "Threaded", value=data["threaded"])

        y += 30
        self.w.exportInFolders = CheckBox((10, y, -10, 22), "Export in Sub Folders", value=data["exportInFolders"])

        y += 30
        self.w.keepFileNames = CheckBox((10, y, -10, 22), "Keep file names (otherwise use familyName-styleName)", value=data["keepFileNames"])

        y += 35
        self.w.saveButton = Button((-100, y, -10, 20), "Save settings", callback=self.saveCallback, sizeStyle="small")
        self.w.setDefaultButton(self.w.saveButton)

        self.w.closeButton = Button((-190, y, -110, 20), "Cancel", callback=self.closeCallback, sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.resetButton = Button((-280, y, -200, 20), "Reset", callback=self.resetCallback, sizeStyle="small")

        y += 30
        self.w.resize(width, y, False)

        self.w.open()
    def getInputString(self, field, stripColon):
        """Read an input string from a field, and convert it to a list of glyphnames."""
        inputString = field.get()
        pattern = re.compile(" *, *| +")
        if stripColon:
            i = inputString.find(":")
            if i != -1:
                inputString = inputString[i+1:]
        result1 = pattern.split(inputString)

        result2 = []
        for c in result1:
            if len(c)>1: # glyph names
                if self.f is not None:
                    if self.f.has_key(c):
                        g = self.f[c]
                        try:
                            value = unicode(unichr(int(g.unicode)))
                            result2.append(value)
                        except TypeError: # unicode not set
                            message ("word-o-mat: Glyph \"%s\" was found, but does not appear to have a Unicode value set. It can therefore not be processed, and will be skipped." % c)
                    else:
                        message ("word-o-mat: Conflict: Character \"%s\" was specified as required, but not found. It will be skipped." % c)
                else:
                        message ("word-o-mat: Sorry, matching by glyph name is only supported when a font is open. Character \"%s\" will be skipped." % c)
            else: # character values
                result2.append(c)
        result = [unicode(s) for s in result2 if s]
        return result
Exemple #6
0
    def getInputString(self, field, stripColon):
        """Read an input string from a field, and convert it to a list of glyphnames."""
        inputString = field.get()
        pattern = re.compile(" *, *| +")
        if stripColon:
            i = inputString.find(":")
            if i != -1:
                inputString = inputString[i + 1:]
        result1 = pattern.split(inputString)

        result2 = []
        for c in result1:
            if len(c) > 1:  # glyph names
                if self.f is not None:
                    if self.f.has_key(c):
                        g = self.f[c]
                        try:
                            value = unicode(unichr(int(g.unicode)))
                            result2.append(value)
                        except TypeError:  # unicode not set
                            message(
                                "word-o-mat: Glyph \"%s\" was found, but does not appear to have a Unicode value set. It can therefore not be processed, and will be skipped."
                                % c)
                    else:
                        message(
                            "word-o-mat: Conflict: Character \"%s\" was specified as required, but not found. It will be skipped."
                            % c)
                else:
                    message(
                        "word-o-mat: Sorry, matching by glyph name is only supported when a font is open. Character \"%s\" will be skipped."
                        % c)
            else:  # character values
                result2.append(c)
        result = [unicode(s) for s in result2 if s]
        return result
Exemple #7
0
    def __init__(self, parentWindow=None):
        self.needsUpdate = False
        self.__version__ = __version__
        if not getDefault("DrawBotCheckForUpdatesAtStartup", True):
            return
        self.currentVersion = getCurrentVersion()
        self.needsUpdate = StrictVersion(__version__) < StrictVersion(self.currentVersion)
        if not self.needsUpdate:
            return
        if parentWindow:
            self.w = vanilla.Sheet((450, 130), parentWindow=parentWindow)
        else:
            self.w = vanilla.Window((450, 130))

        self.w.appIcon = vanilla.ImageView((25, 15, 65, 65))
        self.w.appIcon.setImage(imageObject=AppKit.NSApp().applicationIconImage())

        title = "There is a new version of DrawBot!"
        txt = AppKit.NSAttributedString.alloc().initWithString_attributes_(title, {AppKit.NSFontAttributeName: AppKit.NSFont.boldSystemFontOfSize_(0)})
        self.w.introBold = vanilla.TextBox((100, 15, -15, 20), txt)

        self.w.intro = vanilla.TextBox((100, 45, -15, 200), "DrawBot %s is out now (you have %s).\nWould you like to download it now?" % (self.currentVersion, __version__), sizeStyle="small")

        self.w.cancelButton = vanilla.Button((-270, -30, 60, 20), "Cancel", callback=self.cancelCallback, sizeStyle="small")
        self.w.cancelButton.bind(".", ["command"])
        self.w.cancelButton.bind(unichr(27), [])

        self.w.openInBrowser = vanilla.Button((-200, -30, 120, 20), "Show In Browser", callback=self.openInBrowserCallback, sizeStyle="small")
        self.w.okButton = vanilla.Button((-70, -30, 55, 20), "OK", callback=self.okCallback, sizeStyle="small")
        self.w.setDefaultButton(self.w.okButton)

        self.w.open()
Exemple #8
0
def font(indextable):
    font = TTFont()
    # ['a', 'b', 'c', ...]
    ch = 0x61
    n = len(indextable.indices)
    font.glyphOrder = [unichr(i) for i in range(ch, ch+n)]
    font['TSI0'] = indextable
    return font
def font(indextable):
    font = TTFont()
    # ['a', 'b', 'c', ...]
    ch = 0x61
    n = len(indextable.indices)
    font.glyphOrder = [unichr(i) for i in range(ch, ch + n)]
    font['TSI0'] = indextable
    return font
Exemple #10
0
def unicodeInScripts(uv, scripts):
    """ Check UnicodeData's ScriptExtension property for unicode codepoint
    'uv' and return True if it intersects with the set of 'scripts' provided,
    False if it does not intersect.
    Return None for 'Common' script ('Zyyy').
    """
    sx = unicodedata.script_extension(unichr(uv))
    if "Zyyy" in sx:
        return None
    return not sx.isdisjoint(scripts)
def unicodeBidiType(uv):
    """Return "R" for characters with RTL direction, or "L" for LTR (whether
    'strong' or 'weak'), or None for neutral direction.
    """
    char = unichr(uv)
    bidiType = unicodedata.bidirectional(char)
    if bidiType in RTL_BIDI_TYPES:
        return "R"
    elif bidiType in LTR_BIDI_TYPES:
        return "L"
    else:
        return None
def to_upper(char):
  """Returns the upper case for a lower case character.
  This is not full upper casing, but simply reflects the 1-1
  mapping in UnicodeData.txt."""
  load_data()
  cp = _char_to_int(char)
  try:
    if _general_category_data[cp] == 'Ll':
      return unichr(_lower_to_upper_case[cp])
  except KeyError:
    pass
  return char
Exemple #13
0
def _load_unicode_data_txt():
    """Load character data from UnicodeData.txt."""
    global _defined_characters
    global _bidi_mirroring_characters
    if _defined_characters:
        return

    with open_unicode_data_file("UnicodeData.txt") as unicode_data_txt:
        unicode_data = _parse_semicolon_separated_data(unicode_data_txt.read())

    for line in unicode_data:
        code = int(line[0], 16)
        char_name = line[1]
        general_category = line[2]
        combining_class = int(line[3])

        decomposition = line[5]
        if decomposition.startswith('<'):
            # We only care about canonical decompositions
            decomposition = ''
        decomposition = decomposition.split()
        decomposition = [unichr(int(char, 16)) for char in decomposition]
        decomposition = ''.join(decomposition)

        bidi_mirroring = (line[9] == 'Y')
        if general_category == 'Ll':
            upcode = line[12]
            if upcode:
                upper_case = int(upcode, 16)
                _lower_to_upper_case[code] = upper_case

        if char_name.endswith("First>"):
            last_range_opener = code
        elif char_name.endswith("Last>"):
            # Ignore surrogates
            if "Surrogate" not in char_name:
                for char in xrange(last_range_opener, code + 1):
                    _general_category_data[char] = general_category
                    _combining_class_data[char] = combining_class
                    if bidi_mirroring:
                        _bidi_mirroring_characters.add(char)
                    _defined_characters.add(char)
        else:
            _character_names_data[code] = char_name
            _general_category_data[code] = general_category
            _combining_class_data[code] = combining_class
            if bidi_mirroring:
                _bidi_mirroring_characters.add(code)
            _decomposition_data[code] = decomposition
            _defined_characters.add(code)

    _defined_characters = frozenset(_defined_characters)
    _bidi_mirroring_characters = frozenset(_bidi_mirroring_characters)
Exemple #14
0
def _load_unicode_data_txt():
  """Load character data from UnicodeData.txt."""
  global _defined_characters
  global _bidi_mirroring_characters
  if _defined_characters:
    return

  with open_unicode_data_file("UnicodeData.txt") as unicode_data_txt:
    unicode_data = _parse_semicolon_separated_data(unicode_data_txt.read())

  for line in unicode_data:
    code = int(line[0], 16)
    char_name = line[1]
    general_category = line[2]
    combining_class = int(line[3])

    decomposition = line[5]
    if decomposition.startswith('<'):
        # We only care about canonical decompositions
        decomposition = ''
    decomposition = decomposition.split()
    decomposition = [unichr(int(char, 16)) for char in decomposition]
    decomposition = ''.join(decomposition)

    bidi_mirroring = (line[9] == 'Y')
    if general_category == 'Ll':
      upcode = line[12]
      if upcode:
        upper_case = int(upcode, 16)
        _lower_to_upper_case[code] = upper_case

    if char_name.endswith("First>"):
      last_range_opener = code
    elif char_name.endswith("Last>"):
      # Ignore surrogates
      if "Surrogate" not in char_name:
        for char in xrange(last_range_opener, code+1):
          _general_category_data[char] = general_category
          _combining_class_data[char] = combining_class
          if bidi_mirroring:
            _bidi_mirroring_characters.add(char)
          _defined_characters.add(char)
    else:
      _character_names_data[code] = char_name
      _general_category_data[code] = general_category
      _combining_class_data[code] = combining_class
      if bidi_mirroring:
        _bidi_mirroring_characters.add(code)
      _decomposition_data[code] = decomposition
      _defined_characters.add(code)

  _defined_characters = frozenset(_defined_characters)
  _bidi_mirroring_characters = frozenset(_bidi_mirroring_characters)
Exemple #15
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')
Exemple #16
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')
Exemple #17
0
def unicodeBidiType(uv):
    # return "R", "L", "N" (for numbers), or None for everything else
    char = unichr(uv)
    bidiType = unicodedata.bidirectional(char)
    if bidiType in STRONG_RTL_BIDI_TYPES:
        return "R"
    elif bidiType == STRONG_LTR_BIDI_TYPE:
        return "L"
    elif bidiType in LTR_NUMBER_BIDI_TYPES:
        return "N"
    else:
        return None
Exemple #18
0
def to_upper(char):
  """Returns the upper case for a lower case character.
  This is not full upper casing, but simply reflects the 1-1
  mapping in UnicodeData.txt."""
  load_data()
  cp = _char_to_int(char)
  try:
    if _general_category_data[cp] == 'Ll':
      return unichr(_lower_to_upper_case[cp])
  except KeyError:
    pass
  return char
Exemple #19
0
    def input_from_name(self, name, seen=None, pad=False):
        """Given glyph name, return input to harbuzz to render this glyph.

        Returns input in the form of a (features, text) tuple, where `features`
        is a list of feature tags to activate and `text` is an input string.

        Argument `seen` is used by the method to avoid following cycles when
        recursively looking for possible input. `pad` can be used to add
        whitespace to text output, for non-spacing glyphs.

        Can return None in two situations: if no possible input is found (no
        simple unicode mapping or substitution rule exists to generate the
        glyph), or if the requested glyph already exists in `seen` (in which
        case this path of generating input should not be followed further).
        """

        if name in self.memo:
            return self.memo[name]

        inputs = []

        # avoid following cyclic paths through features
        if seen is None:
            seen = set()
        if name in seen:
            return None
        seen.add(name)

        # see if this glyph has a simple unicode mapping
        if name in self.reverse_cmap:
            text = unichr(self.reverse_cmap[name])
            inputs.append(((), text))

        # check the substitution features
        inputs.extend(self._inputs_from_gsub(name, seen))
        seen.remove(name)

        # since this method sometimes returns None to avoid cycles, the
        # recursive calls that it makes might have themselves returned None,
        # but we should avoid returning None here if there are other options
        inputs = [i for i in inputs if i is not None]
        if not inputs:
            return None

        features, text = min(inputs)
        # can't pad if we don't support space
        if pad and self.space_width > 0:
            width, space = self.widths[name], self.space_width
            padding = ' ' * (width // space + (1 if width % space else 0))
            text = padding + text
        self.memo[name] = features, text
        return self.memo[name]
 def fontCharacters(self, font):
     """Check which Unicode characters are available in the font."""
     if not font:
         return []
     charset = []
     gnames = []
     for g in font:
         if g.unicode is not None:
             try:
                 charset.append(unichr(int(g.unicode)))
                 gnames.append(g.name)
             except ValueError:
                 pass
     return charset, gnames
Exemple #21
0
 def fontCharacters(self, font):
     """Check which Unicode characters are available in the font."""
     if not font:
         return []
     charset = []
     gnames = []
     for g in font:
         if g.unicode is not None:
             try:
                 charset.append(unichr(int(g.unicode)))
                 gnames.append(g.name)
             except ValueError:
                 pass
     return charset, gnames
Exemple #22
0
    def __init__(self, parentWindow):

        data = getExtensionDefault(self.identifier, dict())
        updateWithDefaultValues(data, defaultOptions)

        width = 380
        height = 1000

        self.w = Sheet((width, height), parentWindow=parentWindow)

        y = 10
        self.w.threaded = CheckBox((10, y, -10, 22),
                                   "Threaded",
                                   value=data["threaded"])

        y += 30
        self.w.exportInFolders = CheckBox((10, y, -10, 22),
                                          "Export in Sub Folders",
                                          value=data["exportInFolders"])

        y += 30
        self.w.keepFileNames = CheckBox(
            (10, y, -10, 22),
            "Keep file names (otherwise use familyName-styleName)",
            value=data["keepFileNames"])

        y += 35
        self.w.saveButton = Button((-100, y, -10, 20),
                                   "Save settings",
                                   callback=self.saveCallback,
                                   sizeStyle="small")
        self.w.setDefaultButton(self.w.saveButton)

        self.w.closeButton = Button((-190, y, -110, 20),
                                    "Cancel",
                                    callback=self.closeCallback,
                                    sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.resetButton = Button((-280, y, -200, 20),
                                    "Reset",
                                    callback=self.resetCallback,
                                    sizeStyle="small")

        y += 30
        self.w.resize(width, y, False)

        self.w.open()
Exemple #23
0
def _get_unicode_category(unistr):
    # We use data for a fixed Unicode version (3.2) so that our generated
    # data files are independent of Python runtime that runs the rules.
    # By switching to current Unicode data, we could save some entries
    # in our exception tables, but the gains are not very large; only
    # about one thousand entries.
    if not unistr:
        return None
    if NARROW_PYTHON_BUILD:
        utf32_str = unistr.encode("utf-32-be")
        nchars = len(utf32_str) // 4
        first_char = unichr(struct.unpack('>%dL' % nchars, utf32_str)[0])
    else:
        first_char = unistr[0]
    return unicodedata.ucd_3_2_0.category(first_char)
    def __init__(self, parentWindow):

        data = getExtensionDefault(self.identifier, dict())
        self.w = Sheet((470, 580), parentWindow=parentWindow)

        self.w.tabs = Tabs((10, 10, -10, -40),
                           ["TTF AutoHint", "HTML Preview"])
        self.w.tabs[0].settings = self.settings = TTFAutoHintGroup(
            (0, 0, -0, -0))
        self.settings.set(data)

        y = 10
        self.w.tabs[1].htmlText = TextBox((10, y, 100, 22), "HTML preview:")
        y += 30
        self.w.tabs[1].html = self.html = CodeEditor(
            (10, y, -10, 250),
            getExtensionDefault("%s.htmlPreview" % settingsIdentifier,
                                htmlPreviewDefault),
            lexer="html")
        self.html.showLineNumbers(False)
        y += 260
        self.w.tabs[1].globalCssText = TextBox((10, y, 100, 22), "CSS Style:")
        y += 30
        self.w.tabs[1].globalCss = self.globalCss = CodeEditor(
            (10, y, -10, -10),
            getExtensionDefault("%s.globalCSSPreview" % settingsIdentifier,
                                ""),
            lexer="css")
        self.globalCss.showLineNumbers(False)

        self.w.saveButton = Button((-100, -30, -10, 20),
                                   "Save settings",
                                   callback=self.saveCallback,
                                   sizeStyle="small")
        self.w.setDefaultButton(self.w.saveButton)

        self.w.closeButton = Button((-190, -30, -110, 20),
                                    "Cancel",
                                    callback=self.closeCallback,
                                    sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.resetButton = Button((-280, -30, -200, 20),
                                    "Reset",
                                    callback=self.resetCallback,
                                    sizeStyle="small")
        self.w.open()
def name(char, *args):
  """Returns the name of a character.

  Raises a ValueError exception if the character is undefined, unless an
  extra argument is given, in which case it will return that argument.
  """
  if type(char) is int:
    char = unichr(char)
  # First try and get the name from unidata, which is faster and supports
  # CJK and Hangul automatic names
  try:
      return unicodedata.name(char)
  except ValueError as val_error:
    load_data()
    if ord(char) in _character_names_data:
      return _character_names_data[ord(char)]
    elif args:
      return args[0]
    else:
      raise Exception('no name for "%0x"' % ord(char))
Exemple #26
0
    def buildBaseWindow(self, parentWindow):
        """ Make the base window. """
        self._dirty = False
        self._sheetWidth = 315
        self._sheetHeight = 200
        if parentWindow is None:
            self.w = vanilla.Window(
                (self._sheetWidth, self._sheetHeight),
                title=self._title,
                closable=False,
                miniaturizable=False,
                minSize=(self._sheetWidth, self._sheetHeight),
                textured=False)
        else:
            self.w = vanilla.Sheet(
                (self._sheetWidth, self._sheetHeight),
                parentWindow,
                minSize=(self._sheetWidth, self._sheetHeight),
            )
        # cancel button
        self.w.cancelButton = vanilla.Button(
            (-205, -30, 100, 20),
            'Cancel',
            callback=self.callbackCancelButton,
            sizeStyle='small')
        self.w.cancelButton.bind(".", ["command"])
        self.w.cancelButton.bind(unichr(27), [])
        # ok button
        self.w.applyButton = vanilla.Button((-100, -30, -10, 20),
                                            'Add Glyphs',
                                            callback=self.callbackApplyButton,
                                            sizeStyle='small')
        self.w.setDefaultButton(self.w.applyButton)

        # get the specialised stuff in
        self.fillSheet()
        self.setUpBaseWindowBehavior()
        #self.refresh()
        self.w.open()
Exemple #27
0
def name(char, *args):
  """Returns the name of a character.

  Raises a ValueError exception if the character is undefined, unless an
  extra argument is given, in which case it will return that argument.
  """
  if type(char) is int:
    char = unichr(char)
  # First try and get the name from unidata, which is faster and supports
  # CJK and Hangul automatic names
  try:
      return unicodedata.name(char)
  except ValueError as val_error:
    cp = ord(char)
    load_data()
    if cp in _character_names_data:
      return _character_names_data[cp]
    elif (cp,) in _emoji_sequence_data:
      return _emoji_sequence_data[(cp,)][0]
    elif args:
      return args[0]
    else:
      raise Exception('no name for "%0x"' % ord(char))
    def __init__(self, parentWindow, callback=None):
        self.callback = callback

        self.w = vanilla.Sheet((350, 90), parentWindow=parentWindow)

        self.w.glyphNameText = vanilla.TextBox((10, 17, 100, 22),
                                               "Glyph Name:")
        self.w.glyphName = vanilla.EditText((100, 17, -10, 22))

        self.w.addButton = vanilla.Button((-70, -30, -10, 20),
                                          "Add",
                                          callback=self.addCallback,
                                          sizeStyle="small")
        self.w.setDefaultButton(self.w.addButton)

        self.w.closeButton = vanilla.Button((-150, -30, -80, 20),
                                            "Cancel",
                                            callback=self.closeCallback,
                                            sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.open()
Exemple #29
0
    def buildBaseWindow(self, parentWindow):
        """ Make the base window. """
        self._dirty = False
        self._sheetWidth = 400
        self._sheetHeight = 500
        if parentWindow is None:
            self.w = vanilla.Window((self._sheetWidth, self._sheetHeight),
                title = self._title,
                closable=False,
                miniaturizable=False,
                minSize=(self._sheetWidth, self._sheetHeight),
                textured=False)
        else:
            self.w = vanilla.Sheet((self._sheetWidth, self._sheetHeight),
                parentWindow,
                minSize=(self._sheetWidth, self._sheetHeight),
            )
        # cancel button
        self.w.cancelButton = vanilla.Button((-205, -30, 100, 20),
            'Cancel',
            callback=self.callbackCancelButton,
            sizeStyle='small')
        self.w.cancelButton.bind(".", ["command"])
        self.w.cancelButton.bind(unichr(27), [])
        # ok button
        self.w.applyButton = vanilla.Button((-100, -30, -10, 20),
            'Add Glyphs',
            callback=self.callbackApplyAddGlyphsToTargetFont,
            sizeStyle='small')
        self.w.setDefaultButton(self.w.applyButton)

        # get the specialised stuff in
        self.fillSheet()
        self.setUpBaseWindowBehavior()
        #self.refresh()
        self.w.open()
Exemple #30
0
def category(value):
    c = unichr(value)
    return unicodedata.category(c)
def unicodeToChar(uni):
    import struct
    if uni < 0xFFFF:
        return unichr(uni)
    else:
        return struct.pack('i', uni).decode('utf-32')
Exemple #32
0
def unicodeToChar(uni):
    import struct
    if uni < 0xFFFF:
        return unichr(uni)
    else:
        return struct.pack('i', uni).decode('utf-32')
Exemple #33
0
                          'b': [('b.color1', 1), ('b.color2', 0)],
                          'c': [('c.color2', 1), ('c.color1', 0)]}

    def test_colr_cpal_raw(self, FontClass):
        testufo = FontClass(getpath("ColorTestRaw.ufo"))
        assert "com.github.googlei18n.ufo2ft.colorLayers" in testufo.lib
        assert "com.github.googlei18n.ufo2ft.colorPalettes" in testufo.lib
        result = compileTTF(testufo)
        palettes = [[(c.red, c.green, c.blue, c.alpha) for c in p] for p in result["CPAL"].palettes]
        assert palettes == [[(255, 76, 26, 255), (0, 102, 204, 255)]]
        layers = {gn: [(layer.name, layer.colorID) for layer in layers]
                      for gn, layers in result["COLR"].ColorLayers.items()}
        assert layers == {"a": [('a.color1', 0), ('a.color2', 1)]}


ASCII = [unichr(c) for c in range(0x20, 0x7E)]


@pytest.mark.parametrize(
    "unicodes, expected",
    [
        [ASCII + ["Þ"], {0}],  # Latin 1
        [ASCII + ["Ľ"], {1}],  # Latin 2: Eastern Europe
        [ASCII + ["Ľ", "┤"], {1, 58}],  # Latin 2
        [["Б"], {2}],  # Cyrillic
        [["Б", "Ѕ", "┤"], {2, 57}],  # IBM Cyrillic
        [["Б", "╜", "┤"], {2, 49}],  # MS-DOS Russian
        [["Ά"], {3}],  # Greek
        [["Ά", "½", "┤"], {3, 48}],  # IBM Greek
        [["Ά", "√", "┤"], {3, 60}],  # Greek, former 437 G
        [ASCII + ["İ"], {4}],  # Turkish
Exemple #34
0
    Fallback to *ascender + typoLineGap*.
    """
    return info.ascender + getAttrWithFallback(info, "openTypeOS2TypoLineGap")


def openTypeOS2WinDescentFallback(info):
    """
    Fallback to *descender*.
    """
    return abs(info.descender)


# postscript

_postscriptFontNameExceptions = set("[](){}<>/%")
_postscriptFontNameAllowed = set([unichr(i) for i in range(33, 127)])


def normalizeStringForPostscript(s, allowSpaces=True):
    s = tounicode(s)
    normalized = []
    for c in s:
        if c == " " and not allowSpaces:
            continue
        if c in _postscriptFontNameExceptions:
            continue
        if c not in _postscriptFontNameAllowed:
            # Use compatibility decomposed form, to keep parts in ascii
            c = unicodedata.normalize("NFKD", c)
            if not set(c) < _postscriptFontNameAllowed:
                c = tounicode(tobytes(c, errors="replace"))
    def __init__(self):
        self.w = vanilla.FloatingWindow((310, 300),
                                        "Ramsay St. Settings",
                                        minSize=(310, 250),
                                        maxSize=(310, 700))

        self.w.showPreview = vanilla.CheckBox(
            (10, 10, -10, 22),
            "Show Preview",
            value=RamsayStData.showPreview,
            callback=self.showPreviewCallback)

        self.w.fillColorText = vanilla.TextBox((10, 40, 110, 22),
                                               "Fill Color:")
        self.w.fillColor = vanilla.ColorWell((10, 60, 110, 40),
                                             color=RamsayStData.fillColor,
                                             callback=self.fillColorCallback)

        self.w.strokeColorText = vanilla.TextBox((130, 40, -10, 22),
                                                 "Stroke Color:")
        self.w.strokeColor = vanilla.ColorWell(
            (130, 60, -10, 40),
            color=RamsayStData.strokeColor,
            callback=self.strokeColorCallback)

        items = RamsayStData.getItems()
        columnDescriptions = [
            dict(title="Glyph Name", key="glyphName"),
            dict(title="Left", key="left"),
            dict(title="Right", key="right"),
        ]

        self.w.dataList = vanilla.List((10, 110, -10, -40),
                                       items,
                                       columnDescriptions=columnDescriptions,
                                       editCallback=self.dataListEditCallback)

        segmentDescriptions = [
            dict(title="+"),
            dict(title="-"),
            dict(title="import"),
            dict(title="export")
        ]
        self.w.addDel = vanilla.SegmentedButton((12, -32, -140, 20),
                                                segmentDescriptions,
                                                selectionStyle="momentary",
                                                callback=self.addDelCallback)
        self.w.addDel.getNSSegmentedButton().setSegmentStyle_(
            NSSegmentStyleSmallSquare)

        self.w.okButton = vanilla.Button((-70, -30, -15, 20),
                                         "Apply",
                                         callback=self.okCallback,
                                         sizeStyle="small")

        self.w.setDefaultButton(self.w.okButton)

        self.w.closeButton = vanilla.Button((-140, -30, -80, 20),
                                            "Cancel",
                                            callback=self.closeCallback,
                                            sizeStyle="small")
        self.w.closeButton.bind(".", ["command"])
        self.w.closeButton.bind(unichr(27), [])

        self.w.open()
Exemple #36
0
def _dict_cmap_glyphs(cmap_glyphs):
    """[(ordinal, name)...] --> [{'char': uniXXXX, 'name': name}]"""
    mp = []
    for uni, name in cmap_glyphs:
        mp.append({'char': unichr(uni), 'name': name})
    return mp
Exemple #37
0
def calcCodePageRanges(unicodes):
    """ Given a set of Unicode codepoints (integers), calculate the
    corresponding OS/2 CodePage range bits.
    This is a direct translation of FontForge implementation:
    https://github.com/fontforge/fontforge/blob/7b2c074/fontforge/tottf.c#L3158
    """
    codepageRanges = set()

    chars = [unichr(u) for u in unicodes]

    hasAscii = set(range(0x20, 0x7E)).issubset(unicodes)
    hasLineart = "┤" in chars

    for char in chars:
        if char == "Þ" and hasAscii:
            codepageRanges.add(0)  # Latin 1
        elif char == "Ľ" and hasAscii:
            codepageRanges.add(1)  # Latin 2: Eastern Europe
            if hasLineart:
                codepageRanges.add(58)  # Latin 2
        elif char == "Б":
            codepageRanges.add(2)  # Cyrillic
            if "Ѕ" in chars and hasLineart:
                codepageRanges.add(57)  # IBM Cyrillic
            if "╜" in chars and hasLineart:
                codepageRanges.add(49)  # MS-DOS Russian
        elif char == "Ά":
            codepageRanges.add(3)  # Greek
            if hasLineart and "½" in chars:
                codepageRanges.add(48)  # IBM Greek
            if hasLineart and "√" in chars:
                codepageRanges.add(60)  # Greek, former 437 G
        elif char == "İ" and hasAscii:
            codepageRanges.add(4)  # Turkish
            if hasLineart:
                codepageRanges.add(56)  # IBM turkish
        elif char == "א":
            codepageRanges.add(5)  # Hebrew
            if hasLineart and "√" in chars:
                codepageRanges.add(53)  # Hebrew
        elif char == "ر":
            codepageRanges.add(6)  # Arabic
            if "√" in chars:
                codepageRanges.add(51)  # Arabic
            if hasLineart:
                codepageRanges.add(61)  # Arabic; ASMO 708
        elif char == "ŗ" and hasAscii:
            codepageRanges.add(7)  # Windows Baltic
            if hasLineart:
                codepageRanges.add(59)  # MS-DOS Baltic
        elif char == "₫" and hasAscii:
            codepageRanges.add(8)  # Vietnamese
        elif char == "ๅ":
            codepageRanges.add(16)  # Thai
        elif char == "エ":
            codepageRanges.add(17)  # JIS/Japan
        elif char == "ㄅ":
            codepageRanges.add(18)  # Chinese: Simplified chars
        elif char == "ㄱ":
            codepageRanges.add(19)  # Korean wansung
        elif char == "央":
            codepageRanges.add(20)  # Chinese: Traditional chars
        elif char == "곴":
            codepageRanges.add(21)  # Korean Johab
        elif char == "♥" and hasAscii:
            codepageRanges.add(30)  # OEM Character Set
        # TODO: Symbol bit has a special meaning (check the spec), we need
        # to confirm if this is wanted by default.
        # elif unichr(0xF000) <= char <= unichr(0xF0FF):
        #    codepageRanges.add(31)          # Symbol Character Set
        elif char == "þ" and hasAscii and hasLineart:
            codepageRanges.add(54)  # MS-DOS Icelandic
        elif char == "╚" and hasAscii:
            codepageRanges.add(62)  # WE/Latin 1
            codepageRanges.add(63)  # US
        elif hasAscii and hasLineart and "√" in chars:
            if char == "Å":
                codepageRanges.add(50)  # MS-DOS Nordic
            elif char == "é":
                codepageRanges.add(52)  # MS-DOS Canadian French
            elif char == "õ":
                codepageRanges.add(55)  # MS-DOS Portuguese

    if hasAscii and "‰" in chars and "∑" in chars:
        codepageRanges.add(29)  # Macintosh Character Set (US Roman)

    # when no codepage ranges can be enabled, fall back to enabling bit 0
    # (Latin 1) so that the font works in MS Word:
    # https://github.com/googlei18n/fontmake/issues/468
    if not codepageRanges:
        codepageRanges.add(0)

    return codepageRanges
    def makeWords(self, sender=None):
        """Parse user input, save new values to prefs, compile and display the resulting words.

        I think this function is too long and bloated, it should be taken apart. ########
        """

        global warned
        self.f = CurrentFont()

        if self.f is not None:
            self.fontChars, self.glyphNames = self.fontCharacters(self.f)
            self.glyphNamesForValues = {self.fontChars[i]: self.glyphNames[i] for i in range(len(self.fontChars))}
        else:
            self.fontChars = []
            self.glyphNames = []

        self.wordCount = self.getIntegerValue(self.g1.wordCount)
        self.minLength = self.getIntegerValue(self.g1.minLength)
        self.maxLength = self.getIntegerValue(self.g1.maxLength)
        self.case = self.g1.case.get()
        self.customCharset = []

        charset = self.g1.base.get()
        self.limitToCharset = True
        if charset == 0:
            self.limitToCharset = False

        elif charset == 2: # use selection
            if len(self.f.selection) == 0: # nothing selected
                message("word-o-mat: No glyphs were selected in the font window. Will use any characters available in the current font.")
                self.g1.base.set(1) # use font chars
            else:
                try:
                    self.customCharset = []
                    for gname in self.f.selection:
                        if self.f[gname].unicode is not None:
                            try:
                                self.customCharset.append(unichr(int(self.f[gname].unicode)))
                            except ValueError:
                                pass
                except AttributeError:
                    pass

        elif charset == 3: # use mark color
            c = self.g1.colorWell.get()

            if c is None:
                pass
            elif c.className() == "NSCachedWhiteColor": # not set, corresponds to mark color set to None
                c = None

            self.customCharset = []
            self.reqMarkColor = (c.redComponent(), c.greenComponent(), c.blueComponent(), c.alphaComponent()) if c is not None else None
            for g in self.f:
                if g.mark == self.reqMarkColor:
                    try:
                        self.customCharset.append(unichr(int(g.unicode)))
                    except:
                        pass
            if len(self.customCharset) == 0:
                message("word-o-mat: Found no glyphs that match the specified mark color. Will use any characters available in the current font.")
                self.g1.base.set(1) # use font chars
                self.toggleColorSwatch(0)

        self.matchMode = "text" if self.g2.matchMode.get() == 0 else "grep" # braucht es diese zeile noch?

        self.requiredLetters = self.getInputString(self.g2.textMode.mustLettersBox, False)
        self.requiredGroups[0] = self.getInputString(self.g2.textMode.group1box, True)
        self.requiredGroups[1] = self.getInputString(self.g2.textMode.group2box, True)
        self.requiredGroups[2] = self.getInputString(self.g2.textMode.group3box, True)
        self.matchPattern = self.g2.grepMode.grepBox.get()

        self.banRepetitions = self.g3.checkbox0.get()
        self.outputWords = [] # initialize/empty

        self.source = self.g1.source.get()
        languageCount = len(self.textfiles)
        if self.source == languageCount: # User Dictionary
            self.allWords = self.dictWords["user"]
        elif self.source == languageCount+1: # Use all languages
            for i in range(languageCount):
                # if any language: concatenate all the wordlists
                self.allWords.extend(self.dictWords[self.textfiles[i]])
        elif self.source == languageCount+2: # Custom word list
            try:
                if self.customWords != []:
                    self.allWords = self.customWords
                else:
                    self.allWords = self.dictWords["ukacd"]
                    self.g1.source.set(0)
            except AttributeError:
                self.allWords = self.dictWords["ukacd"]
                self.g1.source.set(0)
        else: # language lists
            for i in range(languageCount):
                if self.source == i:
                    self.allWords = self.dictWords[self.textfiles[i]]

        # store new values as defaults

        markColorPref = self.reqMarkColor if self.reqMarkColor is not None else "None"

        extDefaults = {
            "wordCount": self.wordCount,
            "minLength": self.minLength,
            "maxLength": self.maxLength,
            "case": self.case,
            "limitToCharset": self.writeExtDefaultBoolean(self.limitToCharset),
            "source": self.source,
            "matchMode": self.matchMode,
            "matchPattern": self.matchPattern, # non compiled string
            "markColor": markColorPref,
            }
        for key, value in extDefaults.items():
            setExtensionDefault("com.ninastoessinger.word-o-mat."+key, value)

        # go make words
        if self.checkInput(self.limitToCharset, self.fontChars, self.customCharset, self.requiredLetters, self.minLength, self.maxLength, self.case) == True:

            checker = wordcheck.wordChecker(self.limitToCharset, self.fontChars, self.customCharset, self.requiredLetters, self.requiredGroups, self.matchPatternRE, self.banRepetitions, self.minLength, self.maxLength, matchMode=self.matchMode)

            for i in self.allWords:
                if len(self.outputWords) >= self.wordCount:
                    break
                else:
                    w = choice(self.allWords)
                    if self.case == 1:   w = w.lower()
                    elif self.case == 2:
                        # special capitalization rules for Dutch IJ
                        # this only works when Dutch is selected as language, not "any".
                        try:
                            ijs = ["ij", "IJ", "Ij"]
                            if self.languageNames[self.source] == "Dutch" and w[:2] in ijs:
                                wNew = "IJ" + w[2:]
                                w = wNew
                            else:
                                w = w.title()
                        except IndexError:
                            w = w.title()
                    elif self.case == 3:
                        # special capitalization rules for German double s
                        if u"ß" in w:
                            w2 = w.replace(u"ß", "ss")
                            w = w2
                        w = w.upper()

                    if checker.checkWord(w, self.outputWords):
                        self.outputWords.append(w)

            # output
            if len(self.outputWords) < 1:
                message("word-o-mat: no matching words found <sad trombone>")
            else:
                joinString = " "
                if self.g3.listOutput.get() == True:
                    joinString = "\\n"
                    self.outputWords = self.sortWordsByWidth(self.outputWords)
                outputString = joinString.join(self.outputWords)
                try:
                    sp = OpenSpaceCenter(CurrentFont())
                    sp.setRaw(outputString)
                except:
                    if warned == False:
                        message("word-o-mat: No open fonts found; words will be displayed in the Output Window.")
                    warned = True
                    print("word-o-mat: %s" % outputString)
        else:
            print("word-o-mat: Aborted because of errors")
Exemple #39
0
def unicodeScriptDirection(uv):
    sc = unicodedata.script(unichr(uv))
    if sc in DFLT_SCRIPTS:
        return None
    return unicodedata.script_horizontal_direction(sc)
Exemple #40
0
 def _unescape_fn(m):
     if m.group(1):
         return unichr(int(m.group(1), 8))
     return unichr(int(m.group(2), 16))
Exemple #41
0
def block(value):
    char = unichr(value)
    return unicodedata.block(char)
Exemple #42
0
def script(value):
    char = unichr(value)
    return unicodedata.script_name(unicodedata.script(char), default="Unknown")
Exemple #43
0
 def _unescape_fn(m):
     if m.group(1):
         return unichr(int(m.group(1)[1:], 8))
     return unichr(int(m.group(2)[2:], 16))
Exemple #44
0
    """
    font = info.getParent()
    if font is None:
        return abs(getAttrWithFallback(info, "descender"))
    bounds = getFontBounds(font)
    if bounds is None:
        return abs(getAttrWithFallback(info, "descender"))
    xMin, yMin, xMax, yMax = bounds
    if yMin > 0:
        return 0
    return abs(yMin)

# postscript

_postscriptFontNameExceptions = set("[](){}<>/%")
_postscriptFontNameAllowed = set([unichr(i) for i in range(33, 137)])

def normalizeStringForPostscript(s, allowSpaces=True):
    s = tounicode(s)
    normalized = []
    for c in s:
        if c == " " and not allowSpaces:
            continue
        if c in _postscriptFontNameExceptions:
            continue
        if c not in _postscriptFontNameAllowed:
            c = unicodedata.normalize("NFKD", c)
        normalized.append(tostr(c))
    return "".join(normalized)

def normalizeNameForPostscript(name):