diff -Nru defcon-0.7.2/appveyor.yml defcon-0.3.5/appveyor.yml --- defcon-0.7.2/appveyor.yml 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/appveyor.yml 2017-10-02 10:54:57.000000000 +0000 @@ -1,18 +1,36 @@ environment: matrix: - - - JOB: "3.6 64-bit" - PYTHON_HOME: "C:\\Python36-x64" - - - JOB: "3.7 64-bit" - PYTHON_HOME: "C:\\Python37-x64" - -skip_branch_with_pr: true - -matrix: - fast_finish: true + - JOB: "2.7.12 32-bit" + PYTHON_HOME: "C:\\Python27" + TOXENV: "py27" + TOXPYTHON: "C:\\Python27\\python.exe" + + - JOB: "3.5.2 32-bit" + PYTHON_HOME: "C:\\Python35" + TOXENV: "py35" + TOXPYTHON: "C:\\Python35\\python.exe" + + - JOB: "2.7.12 64-bit" + PYTHON_HOME: "C:\\Python27-x64" + TOXENV: "py27" + TOXPYTHON: "C:\\Python27-x64\\python.exe" + + - JOB: "3.5.2 64-bit" + PYTHON_HOME: "C:\\Python35-x64" + TOXENV: "py35" + TOXPYTHON: "C:\\Python35-x64\\python.exe" install: + # If there is a newer build queued for the same PR, cancel this one. + # The AppVeyor 'rollout builds' option is supposed to serve the same + # purpose but it is problematic because it tends to cancel builds pushed + # directly to master instead of just PR builds (or the converse). + # credits: JuliaLang developers. + - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` + https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` + Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` + throw "There are newer queued builds for this pull request, failing early." } + # Prepend Python to the PATH of this build - "SET PATH=%PYTHON_HOME%;%PYTHON_HOME%\\Scripts;%PATH%" @@ -31,4 +49,4 @@ build: false test_script: - - "tox -e py" + - "tox" diff -Nru defcon-0.7.2/.coveragerc defcon-0.3.5/.coveragerc --- defcon-0.7.2/.coveragerc 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/.coveragerc 2017-10-02 10:54:57.000000000 +0000 @@ -3,16 +3,9 @@ # See: http://coverage.readthedocs.org/en/coverage-4.0.3/branch.html#branch branch = True -# list of directories or modules to measure -source = defcon - -# these are treated as equivalent when combining data -[paths] +# list of directories to measure source = Lib/defcon - .tox/*/lib/python*/site-packages/defcon - .tox/*/Lib/site-packages/defcon - .tox/pypy*/site-packages/defcon [report] # Regexes for lines to exclude from consideration diff -Nru defcon-0.7.2/debian/changelog defcon-0.3.5/debian/changelog --- defcon-0.7.2/debian/changelog 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/changelog 2021-08-23 00:50:55.000000000 +0000 @@ -1,58 +1,8 @@ -defcon (0.7.2-2) unstable; urgency=medium +defcon (0.3.5-1~16.04.sav0) xenial; urgency=low - * Team upload. + * Backport to Xenial - [ Yao Wei (魏銘廷) ] - * debian/watch: Change GitHub archive URL - - [ Hideki Yamane ] - * debian/control - - Set Standards-Version: 4.5.1 - - Set debhelper-compat (= 13) - - Add Rules-Requires-Root: no - - Add Testsuite: autopkgtest-pkg-python - - -- Hideki Yamane Sat, 10 Jul 2021 09:36:04 +0900 - -defcon (0.7.2-1) unstable; urgency=medium - - * New upstream version 0.7.2 - * Use debhelper 12 - * debian/control: - - Bump Standards-Version to 4.5.0 - - Update dependencies from upstream - - Add sphinxdoc dependency - - -- Yao Wei (魏銘廷) Sun, 31 May 2020 10:13:33 +0800 - -defcon (0.6.0-1) unstable; urgency=medium - - * New upstream release - * debian/control: - - Update team mailing list and uploader address - - Update dependency - - Bump policy version to 4.2.1 - - -- Yao Wei (魏銘廷) Thu, 29 Nov 2018 16:05:57 +0800 - -defcon (0.5.2-2) unstable; urgency=medium - - * Recommend python3-fontpens - - -- Jeremy Bicha Wed, 05 Sep 2018 09:20:12 -0400 - -defcon (0.5.2-1) unstable; urgency=medium - - [ Yao Wei (魏銘廷) ] - * New upstream release. - * debian/control: - - Update team mailing list address - - [ Jeremy Bicha ] - * Bump python3-fonttools to >= 3.29.0 & python3-ufolib to >= 2.3.1 - * Bump debhelper compat to 11 - - -- Jeremy Bicha Mon, 03 Sep 2018 13:43:59 -0400 + -- Rob Savoury Sun, 22 Aug 2021 17:50:55 -0700 defcon (0.3.5-1) unstable; urgency=low diff -Nru defcon-0.7.2/debian/compat defcon-0.3.5/debian/compat --- defcon-0.7.2/debian/compat 1970-01-01 00:00:00.000000000 +0000 +++ defcon-0.3.5/debian/compat 2017-11-18 14:11:54.000000000 +0000 @@ -0,0 +1 @@ +10 diff -Nru defcon-0.7.2/debian/control defcon-0.3.5/debian/control --- defcon-0.7.2/debian/control 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/control 2017-11-18 14:11:54.000000000 +0000 @@ -1,22 +1,20 @@ Source: defcon Section: devel Priority: optional -Maintainer: Debian Fonts Task Force -Uploaders: Yao Wei (魏銘廷) -Build-Depends: debhelper-compat (= 13), +Maintainer: Debian Fonts Task Force +Uploaders: Yao Wei (魏銘廷) +Build-Depends: debhelper (>=10), dh-python, python3-all, python3-setuptools, - python3-fonttools (>= 4.10.2), - python3-fontpens (>= 0.1.0), - python3-appdirs, + python3-fonttools, + python3-ufolib (>= 2.1.0), python3-sphinx -Standards-Version: 4.5.1 +Standards-Version: 4.1.0 Homepage: https://github.com/typesupply/defcon -Vcs-Git: https://salsa.debian.org/fonts-team/defcon.git -Vcs-Browser: https://salsa.debian.org/fonts-team/defcon -Rules-Requires-Root: no -Testsuite: autopkgtest-pkg-python +Vcs-Git: https://anonscm.debian.org/git/pkg-fonts/defcon.git +Vcs-Browser: https://anonscm.debian.org/cgit/pkg-fonts/defcon.git +X-Python3-Version: >= 3.4 Package: python3-defcon Architecture: all @@ -24,8 +22,8 @@ Multi-Arch: foreign Depends: ${misc:Depends}, ${python3:Depends}, - ${sphinxdoc:Depends} -Recommends: python3-fontpens (>= 0.1.0) + fonttools (>= 3.13.1), + python3-ufolib (>= 2.1.0) Description: UFO based objects for use in font editing applications Defcon is a set of UFO based objects optimized for use in font editing applications. The objects are built to be lightweight, fast @@ -33,4 +31,5 @@ to be end-all, be-all objects. Rather, they are meant to provide base functionality so that you can focus on your application’s behavior, not object observing or maintaining cached data. Defcon implements - UFO3 as described by the UFO font format. + UFO3 as described by the UFO font format. + diff -Nru defcon-0.7.2/debian/copyright defcon-0.3.5/debian/copyright --- defcon-0.7.2/debian/copyright 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/copyright 2017-11-18 14:11:54.000000000 +0000 @@ -1,4 +1,4 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: defcon Source: https://github.com/typesupply/defcon diff -Nru defcon-0.7.2/debian/gbp.conf defcon-0.3.5/debian/gbp.conf --- defcon-0.7.2/debian/gbp.conf 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -[DEFAULT] -pristine-tar = True -debian-branch = master -patch-numbers = False diff -Nru defcon-0.7.2/debian/rules defcon-0.3.5/debian/rules --- defcon-0.7.2/debian/rules 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/rules 2017-11-18 14:11:54.000000000 +0000 @@ -7,5 +7,5 @@ dh $@ --with python3,sphinxdoc --buildsystem=pybuild override_dh_sphinxdoc: - PYTHONPATH=$(CURDIR)/Lib sphinx-build -b html $(CURDIR)/documentation/source/ $(CURDIR)/debian/python3-defcon/usr/share/doc/defcon/html/ + PYTHONPATH=$(CURDIR)/Lib sphinx-build -b html $(CURDIR)/documentation/source/ $(CURDIR)/debian/python3-ufolib/usr/share/doc/ufolib/html/ dh_sphinxdoc diff -Nru defcon-0.7.2/debian/watch defcon-0.3.5/debian/watch --- defcon-0.7.2/debian/watch 2021-07-10 00:36:04.000000000 +0000 +++ defcon-0.3.5/debian/watch 2017-11-18 14:11:54.000000000 +0000 @@ -1,3 +1,3 @@ version=4 https://github.com/typesupply/defcon/releases \ - .*/archive/refs/tags/@ANY_VERSION@@ARCHIVE_EXT@ + .*/archive/@ANY_VERSION@@ARCHIVE_EXT@ diff -Nru defcon-0.7.2/dev-requirements.txt defcon-0.3.5/dev-requirements.txt --- defcon-0.7.2/dev-requirements.txt 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/dev-requirements.txt 2017-10-02 10:54:57.000000000 +0000 @@ -1,4 +1,3 @@ pytest>=2.8 virtualenv>=15.0 tox>=2.3 -fontPens>=0.1.0 diff -Nru defcon-0.7.2/documentation/source/concepts/externalchanges.rst defcon-0.3.5/documentation/source/concepts/externalchanges.rst --- defcon-0.7.2/documentation/source/concepts/externalchanges.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/concepts/externalchanges.rst 2017-10-02 10:54:57.000000000 +0000 @@ -6,9 +6,9 @@ External Changes ================ -It may be advantageous for your application to notice changes to a UFO that were made outside of your application. the :class:`~defcon.Font` object can help you with this. This object has a :meth:`~defcon.Font.testForExternalChanges` method. This method will compare the data that has been loaded into the font, glyphs, etc. with the data in the UFO on disk. It will report anything that is different from when the UFO was last loaded/saved. +It may be advantagious for your application to notice changes to a UFO that were made outside of your application. the :class:`~defcon.Font` object can help you with this. This object has a :meth:`~defcon.Font.testForExternalChanges` method. This method will compare the data that has been loaded into the font, glyphs, etc. with the data in the UFO on disk. It will report anything that is different from when the UFO was last loaded/saved. -To do this in a relatively effiecient way, it stores the modification data and raw text of the UFO file inside the object. When the :meth:`~defcon.Font.testForExternalChanges` method is called, the modification date of the UFO file and the stored modification date are compared. A mismatch between these two will trigger a comparison between the raw text in the UFO file and the stored raw text. This helps cut down on a significant number of false positives. +To do this in a relatively effecient way, it stores the modification data and raw text of the UFO file inside the object. When the :meth:`~defcon.Font.testForExternalChanges` method is called, the modification date of the UFO file and the stored modification date are compared. A mismatch between these two will trigger a comparison between the raw text in the UFO file and the stored raw text. This helps cut down on a significant number of false positives. The :meth:`~defcon.Font.testForExternalChanges` method will return a dictionary describing what could have changed. You can then reload the data as appropriate. The :class:`~defcon.Font` object has a number of *reload* methods specifically for doing this. diff -Nru defcon-0.7.2/documentation/source/concepts/representations.rst defcon-0.3.5/documentation/source/concepts/representations.rst --- defcon-0.7.2/documentation/source/concepts/representations.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/concepts/representations.rst 2017-10-02 10:54:57.000000000 +0000 @@ -8,38 +8,35 @@ One of the painful parts of developing an app that modifies glyphs is managing the visual representation of the glyphs. When the glyph changes, all representations of it in cached data, the user interface, etc. need to change. There are several ways to handle this, but they are all cumbersome. defcon gives you a very simple way of dealing with this: *representations* and *representation factories*. -.. note:: - - Representations have been extended to allow other font object classes, so that fonts, layers, glyphs, contours, etc. can have representations too. - Representations and Representation Factories ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A *representation* is an object that represents a glyph. As mentioned above, it can be a visual representation of a glyph, such as a NSBezierPath. Representations aren't just limited to visuals, they can be any type of data that describes a glyph or something about a glyph, for example a string of GLIF text, a tree of point location tuples or anything else you can imagine. A *representation factory* is a function that creates a representation. You don't manage the representations yourself. Rather, you register the factory and then ask the glyphs for the representations you need. When the glyphs change, the related representations are destroyed and recreated as needed. + Example ^^^^^^^ As an example, here is a representation factory that creates a NSBezierPath representation:: - def NSBezierPathFactory(glyph): + def NSBezierPathFactory(glyph, font): from fontTools.pens.cocoaPen import CocoaPen - pen = CocoaPen(glyph.getParent()) + pen = CocoaPen(font) glyph.draw(pen) return pen.path To register this factory, you do this:: - from defcon import Glyph, registerRepresentationFactory - registerRepresentationFactory(Glyph, "NSBezierPath", NSBezierPathFactory) + from defcon import addRepresentationFactory + addRepresentationFactory("NSBezierPath", NSBezierPathFactory) Now, when you need a representation, you simply do this:: - path = glyph.getRepresentation("NSBezierPath") + path = glyph.getRepresentation("NSBezierFactory") Not only do you only have to register this *once* to be able get the representation for *all* glyphs, the representation is always up to date. So, if you change the outline in the glyph, all you have to do to get the updated representation is:: - path = glyph.getRepresentation("NSBezierPath") + path = glyph.getRepresentation("NSBezierFactory") Implementation Details @@ -48,10 +45,10 @@ Representation Factories """""""""""""""""""""""" -Representation factories should be functions that accept a font object class (such as :class:`~defcon.Glyph`, :class:`~defcon.Font`, :class:`~defcon.Contour` etc.) as first argument. After that, you are free to define any keyword arguments you need. You must register the factory with the ``registerRepresentationFactory`` function. When doing this, you must define a unique name for your representation. The recommendation is that you follow the format of "applicationOrPackageName.representationName" to prevent conflicts. Some examples:: +Representation factories should be functions that accept at least two arguments. The first argument is always a glyph and the second argument is always a font. After that, you are free to define any keyword arguments you need. You must register the factory with the ``addRepresentationFactory`` function. When doing this, you must define a unique name for your representation. The recommendation is that you follow the format of "applicationOrPackageName.representationName" to prevent conflicts. Some examples:: - registerRepresentationFactory(Glyph, "MetricsMachine.groupEditorGlyphCellImage", groupEditorGlyphCellImageFactory) - registerRepresentationFactory(Glyph, "Prepolator.previewGlyph", previewGlyphFactory) + addRepresentationFactory("MetricsMachine.groupEditorGlyphCellImage", groupEditorGlyphCellImageFactory) + addRepresentationFactory("Prepolator.previewGlyph", previewGlyphFactory) Representations """""""""""""""" @@ -67,19 +64,3 @@ These keyword arguments will be passed along to the representation factory. This makes it possible to have very dynamic factories. All of this is highly optimized. The representation will be created the first time you request it and then it will be cached within the glyph. The next time you request it, the cached representation will be returned. If the glyph is changed, the representation will automatically be destroyed. When this happens, the representation will not be recreated automatically. It will be recreated the next time you ask for it. - -Destroying representations -"""""""""""""""""""""""""" - -You can now also specify which notifications should destroy representations. (Previously, any change to a glyph would destroy all representations. That wasn't ideal. Changing the glyph.note would destroy the expensive-to-calculate bounding box representation.) - -Each class has a list of notifications that it posts. When you register a factory, you can give a list of notification names that should destroy representations created by the factory you are registering. Here's an example:: - - def layerCMAPRepresentationFactory(layer): - cmap = {} - for g in layer: - if g.unicode is not None: - cmap[chr(g.unicode)] = g.name - return cmap - - registerRepresentationFactory(Layer, "CMAP", layerCMAPRepresentationFactory, destructiveNotifications=["Layer.GlyphUnicodesChanged"]) diff -Nru defcon-0.7.2/documentation/source/conf.py defcon-0.3.5/documentation/source/conf.py --- defcon-0.7.2/documentation/source/conf.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/conf.py 2017-10-02 10:54:57.000000000 +0000 @@ -49,9 +49,9 @@ # built documents. # # The short X.Y version. -version = '0.7.0' +version = '0.2.0' # The full version, including alpha/beta/rc tags. -release = '0.7.0' +release = '0.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -94,7 +94,7 @@ # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. -# html_style = 'default.css' +html_theme = 'classic' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". @@ -115,7 +115,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] +html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -188,5 +188,3 @@ # If false, no module index is generated. #latex_use_modindex = True - -autodoc_mock_imports = ['fs'] diff -Nru defcon-0.7.2/documentation/source/index.rst defcon-0.3.5/documentation/source/index.rst --- defcon-0.7.2/documentation/source/index.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/index.rst 2017-10-02 10:54:57.000000000 +0000 @@ -54,14 +54,9 @@ Dependencies ^^^^^^^^^^^^ -* `FontTools `_ >= 3.31.0, installed with - the `fonttools[ufo]` extra, required to import ``fonttools.ufoLib`` module. +* `FontTools `_ +* `ufoLib `_ -Optional Dependencies -^^^^^^^^^^^^^^^^^^^^^ - -* `fontPens `_ -* `lxml `_ Indices and tables ================== diff -Nru defcon-0.7.2/documentation/source/objects/contour.rst defcon-0.3.5/documentation/source/objects/contour.rst --- defcon-0.7.2/documentation/source/objects/contour.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/objects/contour.rst 2017-10-02 10:54:57.000000000 +0000 @@ -15,7 +15,6 @@ Reference Data """""""""""""" -* :attr:`~defcon.Contour.area` * :attr:`~defcon.Contour.bounds` * :attr:`~defcon.Contour.controlPointBounds` * :attr:`~defcon.Contour.open` @@ -45,7 +44,6 @@ Hit Testing """"""""""" -* :meth:`~defcon.Contour.contourInside` * :meth:`~defcon.Contour.pointInside` Drawing diff -Nru defcon-0.7.2/documentation/source/objects/glyph.rst defcon-0.3.5/documentation/source/objects/glyph.rst --- defcon-0.7.2/documentation/source/objects/glyph.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/documentation/source/objects/glyph.rst 2017-10-02 10:54:57.000000000 +0000 @@ -32,7 +32,6 @@ Reference Data """""""""""""" -* :attr:`~defcon.Glyph.area` * :attr:`~defcon.Glyph.bounds` * :attr:`~defcon.Glyph.controlPointBounds` @@ -51,7 +50,6 @@ * :meth:`~defcon.Glyph.insertContour` * :meth:`~defcon.Glyph.contourIndex` * :meth:`~defcon.Glyph.autoContourDirection` -* :meth:`~defcon.Glyph.correctContourDirection` Components """""""""" diff -Nru defcon-0.7.2/.gitignore defcon-0.3.5/.gitignore --- defcon-0.7.2/.gitignore 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/.gitignore 2017-10-02 10:54:57.000000000 +0000 @@ -16,7 +16,6 @@ .coverage .coverage.* .tox -.pytest_cache htmlcov # OS X Finder diff -Nru defcon-0.7.2/Lib/defcon/__init__.py defcon-0.3.5/Lib/defcon/__init__.py --- defcon-0.7.2/Lib/defcon/__init__.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/__init__.py 2017-10-02 10:54:57.000000000 +0000 @@ -3,7 +3,7 @@ of font development tools. This works on UFO files. """ from __future__ import absolute_import -version = __version__ = "0.7.2" +version = __version__ = "0.3.5" from defcon.errors import DefconError @@ -39,7 +39,7 @@ def unregisterRepresentationFactory(cls, name): """ - Unregister the representation factory stored under + Unegister the representation factory stored under **name** in all instances of **cls**. """ del cls.representationFactories[name] diff -Nru defcon-0.7.2/Lib/defcon/objects/anchor.py defcon-0.3.5/Lib/defcon/objects/anchor.py --- defcon-0.7.2/Lib/defcon/objects/anchor.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/anchor.py 2017-10-02 10:54:57.000000000 +0000 @@ -12,12 +12,16 @@ **This object posts the following notifications:** - - Anchor.Changed - - Anchor.XChanged - - Anchor.YChanged - - Anchor.NameChanged - - Anchor.ColorChanged - - Anchor.IdentifierChanged + ======================== + Name + ======================== + Anchor.Changed + Anchor.XChanged + Anchor.YChanged + Anchor.NameChanged + Anchor.ColorChanged + Anchor.IdentifierChanged + ======================== During initialization an anchor dictionary can be passed. If so, the new object will be populated with the data from the dictionary. diff -Nru defcon-0.7.2/Lib/defcon/objects/base.py defcon-0.3.5/Lib/defcon/objects/base.py --- defcon-0.7.2/Lib/defcon/objects/base.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/base.py 2017-10-02 10:54:57.000000000 +0000 @@ -9,11 +9,15 @@ **This object posts the following notifications:** - - BaseObject.Changed - - BaseObject.BeginUndo - - BaseObject.EndUndo - - BaseObject.BeginRedo - - BaseObject.EndRedo + ==================== + Name + ==================== + BaseObject.Changed + BaseObject.BeginUndo + BaseObject.EndUndo + BaseObject.BeginRedo + BaseObject.EndRedo + ==================== Keep in mind that subclasses will not post these same notifications. @@ -133,24 +137,22 @@ return self.dispatcher.hasObserver(observer=observer, notification=notification, observable=self) return False - def holdNotifications(self, notification=None, note=None): + def holdNotifications(self, notification=None): """ Hold this object's notifications until told to release them. * **notification** The specific notification to hold. This is optional. If no *notification* is given, all notifications will be held. - * **note** An arbitrary string containing information about why the hold - has been requested, the requester, etc. This is used for reference only. This is a convenience method that does the same thing as:: dispatcher = anObject.dispatcher dispatcher.holdNotifications( - observable=anObject, notification=notification, note=note) + observable=anObject, notification=notification) """ dispatcher = self.dispatcher if dispatcher is not None: - dispatcher.holdNotifications(observable=self, notification=notification, note=note) + dispatcher.holdNotifications(observable=self, notification=notification) def releaseHeldNotifications(self, notification=None): """ @@ -297,22 +299,15 @@ representation name. **\*\*kwargs** will be passed to the appropriate representation factory. """ - # only store the representation if the object has a - # dispatcher. otherwise, notifications may not be - # destroyed after an object change. - if self.dispatcher is None: + if name not in self._representations: + self._representations[name] = {} + representations = self._representations[name] + subKey = self._makeRepresentationSubKey(**kwargs) + if subKey not in representations: factory = self.representationFactories[name] - return factory["factory"](self, **kwargs) - else: - if name not in self._representations: - self._representations[name] = {} - representations = self._representations[name] - subKey = self._makeRepresentationSubKey(**kwargs) - if subKey not in representations: - factory = self.representationFactories[name] - representation = factory["factory"](self, **kwargs) - representations[subKey] = representation - return representations[subKey] + representation = factory["factory"](self, **kwargs) + representations[subKey] = representation + return representations[subKey] def destroyRepresentation(self, name, **kwargs): """ @@ -441,13 +436,6 @@ data[key] = getter(key) return data - # ============================================= - # = ufo lib writer/reader validation settings = - # ============================================= - - ufoLibReadValidate = True - ufoLibWriteValidate = True - class BaseDictObject(dict, BaseObject): @@ -520,7 +508,7 @@ def update(self, other): super(BaseDictObject, self).update(other) if self.updateNotificationName is not None: - self.postNotification(self.updateNotificationName, data=dict(other=other)) + self.postNotification(self.updateNotificationName) self.dirty = True # ----------------------------- @@ -541,20 +529,6 @@ self.update(data) -def setUfoLibReadValidate(value): - """ - Set the default read validation. - """ - BaseObject.ufoLibReadValidate = value - - -def setUfoLibWriteValidate(value): - """ - Set the default write validation. - """ - BaseObject.ufoLibWriteValidate = value - - if __name__ == "__main__": import doctest doctest.testmod() diff -Nru defcon-0.7.2/Lib/defcon/objects/color.py defcon-0.3.5/Lib/defcon/objects/color.py --- defcon-0.7.2/Lib/defcon/objects/color.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/color.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,3 +1,5 @@ +from fontTools.misc.py23 import basestring + class Color(str): @@ -15,7 +17,7 @@ def __new__(self, value): # convert from string - if isinstance(value, str): + if isinstance(value, basestring): value = _stringToSequence(value) r, g, b, a = value # validate the values diff -Nru defcon-0.7.2/Lib/defcon/objects/component.py defcon-0.3.5/Lib/defcon/objects/component.py --- defcon-0.7.2/Lib/defcon/objects/component.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/component.py 2017-10-02 10:54:57.000000000 +0000 @@ -16,12 +16,15 @@ **This object posts the following notifications:** - - Component.Changed - - Component.BaseGlyphChanged - - Component.BaseGlyphDataChanged - - Component.TransformationChanged - - Component.IdentifierChanged - + =============================== + Name + =============================== + Component.Changed + Component.BaseGlyphChanged + Component.BaseGlyphDataChanged + Component.TransformationChanged + Component.IdentifierChanged + =============================== """ changeNotificationName = "Component.Changed" @@ -171,7 +174,7 @@ """ Draw the component with **pen**. """ - from fontTools.pens.pointPen import PointToSegmentPen + from ufoLib.pointPen import PointToSegmentPen pointPen = PointToSegmentPen(pen) self.drawPoints(pointPen) diff -Nru defcon-0.7.2/Lib/defcon/objects/contour.py defcon-0.3.5/Lib/defcon/objects/contour.py --- defcon-0.7.2/Lib/defcon/objects/contour.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/contour.py 2017-10-02 10:54:57.000000000 +0000 @@ -2,12 +2,10 @@ import weakref from warnings import warn from fontTools.misc import bezierTools -from fontTools.misc import arrayTools from defcon.objects.base import BaseObject from defcon.tools import bezierMath from defcon.tools.representations import contourBoundsRepresentationFactory,\ - contourControlPointBoundsRepresentationFactory, contourAreaRepresentationFactory,\ - contourFlattenedRepresentationFactory + contourControlPointBoundsRepresentationFactory, contourClockwiseRepresentationFactory from defcon.tools.identifiers import makeRandomIdentifier @@ -18,10 +16,14 @@ **This object posts the following notifications:** - - Contour.Changed - - Contour.WindingDirectionChanged - - Contour.PointsChanged - - Contour.IdentifierChanged + =============================== + Name + =============================== + Contour.Changed + Contour.WindingDirectionChanged + Contour.PointsChanged + Contour.IdentifierChanged + =============================== The Contour object has list like behavior. This behavior allows you to interact with point data directly. For example, to get a particular point:: @@ -50,14 +52,10 @@ factory=contourControlPointBoundsRepresentationFactory, destructiveNotifications=("Contour.PointsChanged") ), - "defcon.contour.area" : dict( - factory=contourAreaRepresentationFactory, + "defcon.contour.clockwise" : dict( + factory=contourClockwiseRepresentationFactory, destructiveNotifications=("Contour.PointsChanged", "Contour.WindingDirectionChanged") ), - "defcon.contour.flattened" : dict( - factory=contourFlattenedRepresentationFactory, - destructiveNotifications=("Contour.PointsChanged", "Contour.WindingDirectionChanged") - ) } def __init__(self, glyph=None, pointClass=None): @@ -262,12 +260,12 @@ """ Reverse the direction of the contour. It's important to note that the actual points stored in this object will be completely - replaced by new points. + repalced by new points. This will post *Contour.WindingDirectionChanged*, *Contour.PointsChanged* and *Contour.Changed* notifications. """ - from fontTools.pens.pointPen import ReverseContourPointPen + from ufoLib.pointPen import ReverseContourPointPen oldDirection = self.clockwise # put the current points in another contour otherContour = self.__class__(glyph=None, pointClass=self.pointClass) @@ -407,8 +405,7 @@ # clockwise def _get_clockwise(self): - area = self.getRepresentation("defcon.contour.area") - return area < 0 + return self.getRepresentation("defcon.contour.clockwise") def _set_clockwise(self, value): if self.clockwise != value: @@ -441,15 +438,6 @@ controlPointBounds = property(_get_controlPointBounds, doc="The control bounds of all points in the contour. This only measures the point positions, it does not measure curves. So, curves without points at the extrema will not be properly measured.") # ---- - # Area - # ---- - - def _get_area(self): - return abs(self.getRepresentation("defcon.contour.area")) - - area = property(_get_area, doc="The area of the contour's outline.") - - # ---- # Move # ---- @@ -507,49 +495,6 @@ self.draw(pen) return pen.getResult() - # -------------- - # Contour Inside - # -------------- - - def contourInside(self, other, segmentLength=10): - """ - Returns a boolean indicating if **other** is in the - "black" area of the contour. This uses a flattened - version of other's curves to calculate the location - of the curves within this contour. **segmentLength** - defines the desired length for the flattening process. - A lower value will yeild higher accuracy but will require - more computation time. - """ - if segmentLength < 1: - segmentLength = 1 - # test bounding boxes for intersection - rect1 = self.bounds - rect2 = other.bounds - if not arrayTools.sectRect(rect1, rect2)[0]: - return False - # test existing on curves - testedPoints = set() - for point in other: - if point.segmentType is None: - continue - pt = (point.x, point.y) - if pt in testedPoints: - continue - if not self.pointInside(pt): - return False - testedPoints.add(pt) - # flatten into line and test new points - flat2 = other.getRepresentation("defcon.contour.flattened", approximateSegmentLength=segmentLength, segmentLines=True) - for point in flat2: - pt = (point.x, point.y) - if pt in testedPoints: - continue - if not self.pointInside(pt): - return False - testedPoints.add(pt) - return True - # --------- # Splitting # --------- @@ -642,7 +587,7 @@ """ Draw the contour with **pen**. """ - from fontTools.pens.pointPen import PointToSegmentPen + from ufoLib.pointPen import PointToSegmentPen pointPen = PointToSegmentPen(pen) self.drawPoints(pointPen) diff -Nru defcon-0.7.2/Lib/defcon/objects/dataSet.py defcon-0.3.5/Lib/defcon/objects/dataSet.py --- defcon-0.7.2/Lib/defcon/objects/dataSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/dataSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,7 +1,7 @@ from __future__ import absolute_import import os import weakref -from fontTools.ufoLib import UFOReader, UFOLibError +from ufoLib import UFOReader, UFOLibError from defcon.objects.base import BaseObject @@ -12,7 +12,11 @@ **This object posts the following notifications:** - - DataSet.Changed + =============== + Name + =============== + DataSet.Changed + =============== """ @@ -63,8 +67,8 @@ def __getitem__(self, fileName): if self._data[fileName]["data"] is None: path = self.font.path - reader = self.font._reader - path = "%s/%s" % ("data", fileName) + reader = UFOReader(path) + path = os.path.join("data", fileName) data = reader.readBytesFromPath(path) onDiskModTime = reader.getFileModificationTime(path) self._data[fileName] = _dataDict(data=data, onDisk=True, onDiskModTime=onDiskModTime) @@ -110,27 +114,34 @@ if saveAs: font = self.font if font is not None and font.path is not None and os.path.exists(font.path): - with UFOReader(font.path, validate=False) as reader: - readerDataDirectoryListing = reader.getDataDirectoryListing() - for fileName, data in self._data.items(): - path = "%s/%s" % ("data", fileName) - if data["data"] is not None or fileName not in readerDataDirectoryListing: - continue - writer.copyFromReader(reader, path, path) + reader = UFOReader(font.path) + readerDataDirectoryListing = reader.getDataDirectoryListing() + for fileName, data in self._data.items(): + path = os.path.join("data", fileName) + if data["data"] is not None or fileName not in readerDataDirectoryListing: + continue + writer.copyFromReader(reader, path, path) for fileName in self._scheduledForDeletion: - # instead of trying to maintain a list of in UFO - # vs. in memory, simply skip and move on when - # something can't be deleted because it isn't - # in the UFO. - writer.removePath("%s/%s" % ("data", fileName), force=True) + try: + path = os.path.join("data", fileName) + writer.removeFileForPath(path) + except UFOLibError: + # this will be raised if the file doesn't exist. + # instead of trying to maintain a list of in UFO + # vs. in memory, simply fail and move on when + # something can't be deleted because it isn't + # in the UFO. + pass self._scheduledForDeletion.clear() + reader = UFOReader(writer.path) for fileName, data in self._data.items(): if not data["dirty"]: continue - writer.writeBytesToPath("%s/%s" % ("data", fileName), data["data"]) + path = os.path.join("data", fileName) + writer.writeBytesToPath(path, data["data"]) data["dirty"] = False data["onDisk"] = True - data["onDiskModTime"] = writer.getFileModificationTime("%s/%s" % ("data", fileName)) + data["onDiskModTime"] = reader.getFileModificationTime(os.path.join("data", fileName)) self.dirty = False # --------------------- @@ -150,14 +161,12 @@ added.append(fileName) elif not self._scheduledForDeletion[fileName]["onDisk"]: added.append(fileName) - elif self._scheduledForDeletion[fileName]["onDiskModTime"] != reader.getFileModificationTime( - "%s/%s" % ("data", fileName) - ): + elif self._scheduledForDeletion[fileName]["onDiskModTime"] != reader.getFileModificationTime(os.path.join("data", fileName)): added.append(fileName) for fileName, data in self._data.items(): # file on disk and has been loaded if fileName in filesOnDisk and data["data"] is not None: - path = "%s/%s" % ("data", fileName) + path = os.path.join("data", fileName) newModTime = reader.getFileModificationTime(path) if newModTime != data["onDiskModTime"]: newData = reader.readBytesFromPath(path) diff -Nru defcon-0.7.2/Lib/defcon/objects/features.py defcon-0.3.5/Lib/defcon/objects/features.py --- defcon-0.7.2/Lib/defcon/objects/features.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/features.py 2017-10-02 10:54:57.000000000 +0000 @@ -10,13 +10,16 @@ **This object posts the following notifications:** - - Features.Changed - - Features.BeginUndo - - Features.EndUndo - - Features.BeginRedo - - Features.EndRedo - - Features.TextChanged - + ================ + Name + ================ + Features.Changed + Features.BeginUndo + Features.EndUndo + Features.BeginRedo + Features.EndRedo + Features.TextChanged + ================ """ changeNotificationName = "Features.Changed" diff -Nru defcon-0.7.2/Lib/defcon/objects/font.py defcon-0.3.5/Lib/defcon/objects/font.py --- defcon-0.7.2/Lib/defcon/objects/font.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/font.py 2017-10-02 10:54:57.000000000 +0000 @@ -3,7 +3,7 @@ import re import tempfile import shutil -from fontTools.ufoLib import UFOReader, UFOWriter, UFOLibError, UFOFileStructure, UFOFormatVersion +from ufoLib import UFOReader, UFOWriter from defcon.objects.base import BaseObject from defcon.objects.layerSet import LayerSet from defcon.objects.info import Info @@ -16,10 +16,6 @@ from defcon.objects.guideline import Guideline from defcon.tools.notifications import NotificationCenter from functools import partial -import logging - - -logger = logging.getLogger(__name__) class Font(BaseObject): @@ -35,12 +31,15 @@ **This object posts the following notifications:** - - Font.Changed - - Font.ReloadedGlyphs - - Font.GlyphOrderChanged - - Font.GuidelinesChanged - - Font.GuidelineWillBeDeleted - - Font.GuidelineWillBeAdded + ====================== + Name + ====================== + Font.Changed + Font.ReloadedGlyphs + Font.GlyphOrderChanged + Font.GuidelinesChanged + Font.GuidelineWillBeDeleted + ====================== The Font object has some dict like behavior. For example, to get a glyph:: @@ -114,7 +113,6 @@ self._path = path self._ufoFormatVersion = None - self._ufoFileStructure = None self._kerning = None self._info = None @@ -133,23 +131,16 @@ self._guidelines = [] self._identifiers = set() - self._reader = None self._dirty = False if path: - if not isinstance(path, str) and not hasattr(path, "__fspath__"): - raise TypeError( - "invalid path: expected string or os.PathLike, found %s" - % type(path).__name__ - ) - self._reader = reader = UFOReader(self._path, validate=self.ufoLibReadValidate) - self._ufoFormatVersion = reader.formatVersionTuple - self._ufoFileStructure = reader.fileStructure + reader = UFOReader(self._path) + self._ufoFormatVersion = reader.formatVersion # go ahead and load the layers self._layers.disableNotifications() layerNames = reader.getLayerNames() for layerName in layerNames: - glyphSet = reader.getGlyphSet(layerName, validateRead=self._layers.ufoLibReadValidate, validateWrite=self._layers.ufoLibWriteValidate) + glyphSet = reader.getGlyphSet(layerName) layer = self._layers.newLayer(layerName, glyphSet=glyphSet) layer.dirty = False self._beginSelfLayerNotificationObservation(layer) @@ -167,14 +158,15 @@ self._data.fileNames = reader.getDataDirectoryListing() self._data.enableNotifications() # if the UFO version is 1, do some conversion. - if self._ufoFormatVersion == UFOFormatVersion.FORMAT_1_0: + if self._ufoFormatVersion == 1: self._convertFromFormatVersion1RoboFabData() # if the ufo version is < 3, read the kerning and groups # right now. do this by creating a reference to the reader. # otherwise a situation could arise where the groups # are modified by an external source before being read. # that could create a data corruption within this object. - if self._ufoFormatVersion < UFOFormatVersion.FORMAT_3_0: + if self._ufoFormatVersion < 3: + self._reader = reader self._kerningGroupConversionRenameMaps = reader.getKerningGroupConversionRenameMaps() k = self.kerning g = self.groups @@ -187,21 +179,6 @@ layer = self.newLayer("public.default") self._layers.defaultLayer = layer - def close(self): - # close file systems - if self._reader is not None: - self._reader.close() - del self._reader - for layer in self.layers: - if layer._glyphSet is not None: - layer._glyphSet.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, exc_tb): - self.close() - def _get_dispatcher(self): return self._dispatcher @@ -275,49 +252,23 @@ def _set_path(self, path): # XXX: this needs to be reworked for layers - if not isinstance(path, str) and not hasattr(path, "__fspath__"): - raise TypeError( - "invalid path: expected string or os.PathLike, found %s" - % type(path).__name__ - ) # the file must already exist assert os.path.exists(path) + # the glyphs directory must already exist + glyphsDir = os.path.join(path, "glyphs") + assert os.path.exists(glyphsDir) + # set the internal reference self._path = path + # set the glyph set reference + if self._glyphSet is not None: + self._glyphSet.dirName = glyphsDir path = property(_get_path, _set_path, doc="The location of the file on disk. Setting the path should only be done when the user has moved the file in the OS interface. Setting the path is not the same as a save operation.") def _get_ufoFormatVersion(self): - import warnings - - warnings.warn( - "The 'ufoFormatVersion' attribute is deprecated; use the 'ufoFormatVersionTuple'", - DeprecationWarning, - stacklevel=2, - ) - if self._ufoFormatVersion is None: - return None - else: - return self._ufoFormatVersion.major - - ufoFormatVersion = property(_get_ufoFormatVersion, doc="The UFO format major version that will be used when saving. This is taken from a loaded UFO during __init__. If this font was not loaded from a UFO, this will return None until the font has been saved. Deprecated, use ufoFormatVersionTuple instead.") - - def _get_ufoFormatVersionTuple(self): return self._ufoFormatVersion - ufoFormatVersionTuple = property(_get_ufoFormatVersionTuple, doc="The UFO format (major, minor) version tuple that will be used when saving. This is taken from a loaded UFO during __init__. If this font was not loaded from a UFO, this will return None until the font has been saved.") - - def _get_ufoFileStructure(self): - return self._ufoFileStructure - - ufoFileStructure = property( - _get_ufoFileStructure, - doc=( - "The UFO file structure that will be used when saving. " - "This is taken from a loaded UFO during __init__. " - "If this font was not loaded from a UFO, this will return None " - "until the font has been saved." - ) - ) + ufoFormatVersion = property(_get_ufoFormatVersion, doc="The UFO format version that will be used when saving. This is taken from a loaded UFO during __init__. If this font was not loaded from a UFO, this will return None until the font has been saved.") def _get_kerningGroupConversionRenameMaps(self): return self._kerningGroupConversionRenameMaps @@ -419,17 +370,17 @@ # and bookkeep dirty dirty = self.dirty self.disableNotifications() - with UFOReader(self._path, validate=False) as reader: - self._info.disableNotifications() - reader.readInfo(self._info, validate=self._info.ufoLibReadValidate) - self._info.dirty = False - self._info.enableNotifications() - # - self._stampInfoDataState(reader) + # + self._info.disableNotifications() + reader = UFOReader(self._path) + reader.readInfo(self._info) + self._info.dirty = False + self._info.enableNotifications() + # self.dirty = dirty self.enableNotifications() - else: - self._stampInfoDataState() + # + self._stampInfoDataState(reader) return self._info info = property(_get_info, doc="The font's :class:`Info` object.") @@ -438,29 +389,31 @@ def _loadKerningAndGroups(self): # read - with UFOReader(self._path, validate=False) as reader: - # instantiate everything and store it if valid - self._groups = self.instantiateGroups() - self.beginSelfGroupsNotificationObservation() - self._kerning = self.instantiateKerning() - self.beginSelfKerningNotificationObservation() - # load data - kerning = reader.readKerning(validate=self._kerning.ufoLibReadValidate) - groups = reader.readGroups(validate=self._groups.ufoLibReadValidate) - # Note: the incoming kerning data has not been validated. - # Gremlins may be sneaking in through here. - ## store groups - self._groups.disableNotifications() - self._groups.update(groups) - self._groups.dirty = False - self._groups.enableNotifications() - self._stampGroupsDataState(reader) - ## store kerning - self._kerning.disableNotifications() - self._kerning.update(kerning) - self._kerning.dirty = False - self._kerning.enableNotifications() - self._stampKerningDataState(reader) + if hasattr(self, "_reader"): + reader = self._reader + else: + reader = UFOReader(self._path) + kerning = reader.readKerning() + groups = reader.readGroups() + # instantiate everything and store it if valid + self._groups = self.instantiateGroups() + self.beginSelfGroupsNotificationObservation() + self._kerning = self.instantiateKerning() + self.beginSelfKerningNotificationObservation() + # Note: the incoming kerning data has not been validated. + # Gremlins may be sneaking in through here. + ## store groups + self._groups.disableNotifications() + self._groups.update(groups) + self._groups.dirty = False + self._groups.enableNotifications() + self._stampGroupsDataState(reader) + ## store kerning + self._kerning.disableNotifications() + self._kerning.update(kerning) + self._kerning.dirty = False + self._kerning.enableNotifications() + self._stampKerningDataState(reader) def instantiateKerning(self): kerning = self._kerningClass( @@ -550,15 +503,13 @@ self.beginSelfFeaturesNotificationObservation() reader = None if self._path is not None: - with UFOReader(self._path, validate=False) as reader: - self._features.disableNotifications() - t = reader.readFeatures() - self._features.text = t - self._features.dirty = False - self._features.enableNotifications() - self._stampFeaturesDataState(reader) - else: - self._stampFeaturesDataState() + self._features.disableNotifications() + reader = UFOReader(self._path) + t = reader.readFeatures() + self._features.text = t + self._features.dirty = False + self._features.enableNotifications() + self._stampFeaturesDataState(reader) return self._features features = property(_get_features, doc="The font's :class:`Features` object.") @@ -588,14 +539,12 @@ self.beginSelfLibNotificationObservation() reader = None if self._path is not None: - with UFOReader(self._path, validate=False) as reader: - self._lib.disableNotifications() - d = reader.readLib(validate=self._lib.ufoLibReadValidate) - self._lib.update(d) - self._lib.enableNotifications() - self._stampLibDataState(reader) - else: - self._stampLibDataState() + self._lib.disableNotifications() + reader = UFOReader(self._path) + d = reader.readLib() + self._lib.update(d) + self._lib.enableNotifications() + self._stampLibDataState(reader) return self._lib lib = property(_get_lib, doc="The font's :class:`Lib` object.") @@ -731,14 +680,7 @@ count += self.layers.getSaveProgressBarTickCount(formatVersion) return count - def save( - self, - path=None, - formatVersion=None, - removeUnreferencedImages=False, - progressBar=None, - structure=None, - ): + def save(self, path=None, formatVersion=None, removeUnreferencedImages=False, progressBar=None): """ Save the font to **path**. If path is None, the path from the last save or when the font was first opened @@ -754,69 +696,12 @@ Optionally, the UFO can be purged of unreferenced images during this operation. To do this, pass ``True`` as the value for the removeUnreferencedImages argument. - - 'structure' can be either None, "zip" or "package". If it's None, - the destination UFO will use the same structure as original, provided - that is compatible with any previous UFO at the output path. - If 'structure' is "zip" the UFO will be saved as compressed archive, - else it is saved as a regular folder or "package". - """ - isNewFont = self._path is None - if path is None: - if isNewFont: - from defcon.errors import DefconError - raise DefconError("Can't save new font without a 'path'") - # saving in-place to the same original path - path = self._path - saveAs = False - else: - if not isinstance(path, str) and not hasattr(path, "__fspath__"): - raise TypeError( - "invalid path: expected string or os.PathLike, found %s" - % type(path).__name__ - ) - if isNewFont: - # saving a new font is always a 'saveAs' operation - saveAs = True - else: - # 'saveAs' if source and destination path are different - saveAs = not samepath(self._path, path) - - # validate 'structure' argument - if structure is not None: - try: - structure = UFOFileStructure(structure) - except ValueError: - from defcon.errors import DefconError - raise DefconError( - "'%s' is not a valid UFOFileStructure; choose between %s" - % (structure, tuple(e.value for e in UFOFileStructure)) - ) - elif self._ufoFileStructure is not None: - # if structure is None, fall back to the same as when first loaded - structure = self._ufoFileStructure + """ + saveAs = False + if path is not None and path != self._path: + saveAs = True else: - # if both None, default to "package" structure - structure = UFOFileStructure.PACKAGE - - # if destination is an existing path, ensure matches the desired structure - isExistingOSPath = os.path.exists(path) - if isExistingOSPath: - try: - with UFOReader(path, validate=True) as reader: - existingStructure = reader.fileStructure - except UFOLibError: - # destination is an existing file but not a valid UFO, we'll - # silently overwrite it. Perhaps we should blow up... - saveAs = True - if not saveAs and structure and structure is not existingStructure: - from defcon.errors import DefconError - raise DefconError( - "Can't save font in-place with a different structure; " - "expected %s, got %s" - % (existingStructure.value, structure.value) - ) - + path = self._path # sanity checks on layer data before doing anything destructive assert self.layers.defaultLayer is not None if self.layers.defaultLayer.name != "public.default": @@ -826,45 +711,18 @@ # came in when the UFO was loaded if formatVersion is None and self._ufoFormatVersion is not None: formatVersion = self._ufoFormatVersion - # otherwise fallback to the default + # otherwise fallback to 3 elif formatVersion is None: - formatVersion = UFOFormatVersion.default() - else: - # convert it to a UFOFormatVersion object - formatVersion = UFOFormatVersion(formatVersion) - # if down-converting in-place or "saving as" to a pre-existing path, - # we first write to a temporary folder, then move to destination - overwritePath = None - if ((not saveAs and formatVersion != self._ufoFormatVersion) or - (saveAs and isExistingOSPath)): + formatVersion = 3 + # if down-converting, use a temp directory + convertinginPlace = False + if path == self._path and formatVersion != self._ufoFormatVersion: + convertinginPlace = True saveAs = True - overwritePath = path path = os.path.join(tempfile.mkdtemp(), "temp.ufo") try: # make a UFOWriter - try: - writer = UFOWriter( - path, - formatVersion=formatVersion, - validate=self.ufoLibWriteValidate, - structure=structure, - ) - except UFOLibError: - if overwritePath is None and isExistingOSPath: - logger.exception("Invalid ufo found '%s', the existing ufo " - "will be removed. Save will be handled as " - "save-as.", path) - saveAs = True - overwritePath = path - path = os.path.join(tempfile.mkdtemp(), "temp.ufo") - writer = UFOWriter( - path, - formatVersion=formatVersion, - validate=self.ufoLibWriteValidate, - structure=structure, - ) - else: - raise + writer = UFOWriter(path, formatVersion=formatVersion) # if changing ufo format versions, flag all objects # as dirty so that they will be saved if self._ufoFormatVersion != formatVersion: @@ -872,10 +730,10 @@ self.groups.dirty = True self.kerning.dirty = True self.lib.dirty = True - if formatVersion > UFOFormatVersion.FORMAT_1_0: + if formatVersion > 1: self.features.dirty = True # set the kerning group remap if necessary - if formatVersion < UFOFormatVersion.FORMAT_3_0 and self._kerningGroupConversionRenameMaps is not None: + if formatVersion < 3 and self._kerningGroupConversionRenameMaps is not None: writer.setKerningGroupConversionRenameMaps(self._kerningGroupConversionRenameMaps) # save the objects self._saveInfo(writer=writer, saveAs=saveAs, progressBar=progressBar) @@ -884,32 +742,25 @@ # Gremlins may be sneaking out through here. self._saveKerning(writer=writer, saveAs=saveAs, progressBar=progressBar) self._saveLib(writer=writer, saveAs=saveAs, progressBar=progressBar) - if formatVersion >= UFOFormatVersion.FORMAT_2_0: + if formatVersion >= 2: self._saveFeatures(writer=writer, saveAs=saveAs, progressBar=progressBar) - if formatVersion >= UFOFormatVersion.FORMAT_3_0: + if formatVersion >= 3: self.saveImages(writer=writer, removeUnreferencedImages=removeUnreferencedImages, saveAs=saveAs, progressBar=progressBar) self.saveData(writer=writer, saveAs=saveAs, progressBar=progressBar) self.layers.save(writer, saveAs=saveAs, progressBar=progressBar) - # we must close the writer's filesystem - writer.close() writer.setModificationTime() - if overwritePath is not None: - if os.path.isfile(overwritePath): - os.remove(overwritePath) - elif os.path.isdir(overwritePath): - shutil.rmtree(overwritePath) - shutil.move(path, overwritePath) + if convertinginPlace: + shutil.rmtree(self._path) + shutil.move(path, self._path) finally: - # if down converting in place or overwriting, handle the temp - if overwritePath is not None: + # if down converting in place, handle the temp + if convertinginPlace: shutil.rmtree(os.path.dirname(path)) - path = overwritePath + path = self._path # done self._path = path self._ufoFormatVersion = formatVersion - self._ufoFileStructure = writer.fileStructure self.dirty = False - self.layers._fontSaveWasCompleted() def _saveInfo(self, writer, saveAs=False, progressBar=None): # info should always be saved @@ -917,7 +768,7 @@ progressBar.update(text="Saving info...", increment=0) self.saveInfo(writer) self.info.dirty = False - self._stampInfoDataState(writer) + self._stampInfoDataState(UFOReader(writer.path)) if progressBar is not None: progressBar.update() @@ -926,7 +777,7 @@ Save info. This method should not be called externally. Subclasses may override this method to implement custom saving behavior. """ - writer.writeInfo(self.info, validate=self.info.ufoLibWriteValidate) + writer.writeInfo(self.info) def _saveGroups(self, writer, saveAs=False, progressBar=None): # groups should always be saved @@ -934,7 +785,7 @@ progressBar.update(text="Saving groups...", increment=0) self.saveGroups(writer) self.groups.dirty = False - self._stampGroupsDataState(writer) + self._stampGroupsDataState(UFOReader(writer.path)) if progressBar is not None: progressBar.update() @@ -943,7 +794,7 @@ Save groups. This method should not be called externally. Subclasses may override this method to implement custom saving behavior. """ - writer.writeGroups(self.groups, validate=self.groups.ufoLibWriteValidate) + writer.writeGroups(self.groups) def _saveKerning(self, writer, saveAs=False, progressBar=None): if self.kerning.dirty or saveAs: @@ -951,7 +802,7 @@ progressBar.update(text="Saving kerning...", increment=0) self.saveKerning(writer) self.kerning.dirty = False - self._stampKerningDataState(writer) + self._stampKerningDataState(UFOReader(writer.path)) if progressBar is not None: progressBar.update() @@ -960,7 +811,7 @@ Save kerning. This method should not be called externally. Subclasses may override this method to implement custom saving behavior. """ - writer.writeKerning(self.kerning, validate=self.kerning.ufoLibWriteValidate) + writer.writeKerning(self.kerning) def _saveFeatures(self, writer, saveAs=False, progressBar=None): if self.features.dirty or saveAs: @@ -969,7 +820,7 @@ if self.features.text is not None: self.saveFeatures(writer) self.features.dirty = False - self._stampFeaturesDataState(writer) + self._stampFeaturesDataState(UFOReader(writer.path)) if progressBar is not None: progressBar.update() @@ -978,7 +829,7 @@ Save features. This method should not be called externally. Subclasses may override this method to implement custom saving behavior. """ - writer.writeFeatures(self.features.text, validate=self.features.ufoLibWriteValidate) + writer.writeFeatures(self.features.text) def _saveLib(self, writer, saveAs=False, progressBar=None): # lib should always be saved @@ -986,7 +837,7 @@ progressBar.update(text="Saving lib...", increment=0) self.saveLib(writer) self.lib.dirty = False - self._stampLibDataState(writer) + self._stampLibDataState(UFOReader(writer.path)) if progressBar is not None: progressBar.update() @@ -999,9 +850,9 @@ # temporary down conversion before # passing the lib to the writer libCopy = dict(self.lib) - if writer.formatVersionTuple == UFOFormatVersion.FORMAT_1_0: + if writer.formatVersion == 1: self._convertToFormatVersion1RoboFabData(libCopy) - writer.writeLib(libCopy, validate=self.lib.ufoLibWriteValidate) + writer.writeLib(libCopy) def saveImages(self, writer, removeUnreferencedImages=False, saveAs=False, progressBar=None): """ @@ -1049,7 +900,7 @@ def _set_guidelines(self, value): self.clearGuidelines() - self.holdNotifications(note="Requested by Font._set_guidelines.") + self.holdNotifications() for guideline in value: self.appendGuideline(guideline) self.releaseHeldNotifications() @@ -1095,7 +946,6 @@ if not isinstance(guideline, self._guidelineClass): guideline = self.instantiateGuideline(guidelineDict=guideline) assert guideline.font in (self, None), "This guideline belongs to another font." - self.postNotification(notification="Font.GuidelineWillBeAdded") if guideline.font is None: assert guideline.glyph is None, "This guideline belongs to a glyph." if guideline.font is None: @@ -1139,7 +989,7 @@ This posts a *Font.Changed* notification. """ - self.holdNotifications(note="Requested by Font.clearGuidelines.") + self.holdNotifications() for guideline in reversed(self._guidelines): self.removeGuideline(guideline) self.releaseHeldNotifications() @@ -1233,16 +1083,14 @@ def _stampFontDataState(self, obj, fileName, reader=None): # font is not on disk - if self.path is None and reader is None: + if self.path is None: return # data has not been loaded if obj is None: return # make a reader if necessary - closeReader = False if reader is None: - closeReader = True - reader = UFOReader(self.path, validate=False) + reader = UFOReader(self.path) # get the mod time from the reader modTime = reader.getFileModificationTime(fileName) # file is not in the UFO @@ -1255,8 +1103,6 @@ # store the data obj._dataOnDisk = data obj._dataOnDiskTimeStamp = modTime - if closeReader: - reader.close() def _stampInfoDataState(self, reader=None): self._stampFontDataState(self._info, "fontinfo.plist", reader=reader) @@ -1319,19 +1165,19 @@ this decision up to you. """ assert self.path is not None - with UFOReader(self.path, validate=self.ufoLibReadValidate) as reader: - infoChanged = self._testInfoForExternalModifications(reader) - kerningChanged = self._testKerningForExternalModifications(reader) - groupsChanged = self._testGroupsForExternalModifications(reader) - featuresChanged = self._testFeaturesForExternalModifications(reader) - libChanged = self._testLibForExternalModifications(reader) - layerChanges = self.layers.testForExternalChanges(reader) - modifiedImages = addedImages = deletedImages = [] - if self._images is not None: - modifiedImages, addedImages, deletedImages = self._images.testForExternalChanges(reader) - modifiedData = addedData = deletedData = [] - if self._data is not None: - modifiedData, addedData, deletedData = self._data.testForExternalChanges(reader) + reader = UFOReader(self.path) + infoChanged = self._testInfoForExternalModifications(reader) + kerningChanged = self._testKerningForExternalModifications(reader) + groupsChanged = self._testGroupsForExternalModifications(reader) + featuresChanged = self._testFeaturesForExternalModifications(reader) + libChanged = self._testLibForExternalModifications(reader) + layerChanges = self.layers.testForExternalChanges(reader) + modifiedImages = addedImages = deletedImages = [] + if self._images is not None: + modifiedImages, addedImages, deletedImages = self._images.testForExternalChanges(reader) + modifiedData = addedData = deletedData = [] + if self._data is not None: + modifiedData, addedData, deletedData = self._data.testForExternalChanges(reader) # deprecated stuff defaultLayerName = self.layers.defaultLayer.name modifiedGlyphs = layerChanges["modified"].get(defaultLayerName, {}).get("modified") @@ -1368,28 +1214,22 @@ if obj is None: return # make a reader if necessary - closeReader = False if reader is None: - closeReader = True - reader = UFOReader(self.path, validate=False) + reader = UFOReader(self.path) # get the mod time from the reader modTime = reader.getFileModificationTime(fileName) - # fallback - result = False # file is not in the UFO if modTime is None: if obj._dataOnDisk: - result = True - result = False + return True + return False # time stamp mismatch - elif modTime != obj._dataOnDiskTimeStamp: + if modTime != obj._dataOnDiskTimeStamp: data = reader.readBytesFromPath(fileName) if data != obj._dataOnDisk: - result = True - if closeReader: - reader.close() + return True # fallback - return result + return False def _testInfoForExternalModifications(self, reader=None): return self._testFontDataForExternalModifications(self._info, "fontinfo.plist", reader=reader) @@ -1413,35 +1253,35 @@ Reload the data in the :class:`Info` object from the fontinfo.plist file in the UFO. """ - from fontTools.ufoLib import deprecatedFontInfoAttributesVersion2 + from ufoLib import deprecatedFontInfoAttributesVersion2 if self._info is None: obj = self.info else: - with UFOReader(self.path, validate=False) as reader: - newInfo = Info() - reader.readInfo(newInfo, validate=self._info.ufoLibReadValidate) - oldInfo = self._info - for attr in dir(newInfo): - if attr in deprecatedFontInfoAttributesVersion2: - continue - if attr.startswith("_"): - continue - if attr == "dirty": - continue - if attr == "dispatcher": - continue - if attr == "font": - continue - if not hasattr(oldInfo, attr): - continue - newValue = getattr(newInfo, attr) - oldValue = getattr(oldInfo, attr) - if hasattr(newValue, "im_func"): - continue - if oldValue == newValue: - continue - setattr(oldInfo, attr, newValue) - self._stampInfoDataState(reader) + reader = UFOReader(self.path) + newInfo = Info() + reader.readInfo(newInfo) + oldInfo = self._info + for attr in dir(newInfo): + if attr in deprecatedFontInfoAttributesVersion2: + continue + if attr.startswith("_"): + continue + if attr == "dirty": + continue + if attr == "dispatcher": + continue + if attr == "font": + continue + if not hasattr(oldInfo, attr): + continue + newValue = getattr(newInfo, attr) + oldValue = getattr(oldInfo, attr) + if hasattr(newValue, "im_func"): + continue + if oldValue == newValue: + continue + setattr(oldInfo, attr, newValue) + self._stampInfoDataState(reader) def reloadKerning(self): """ @@ -1455,13 +1295,13 @@ if self._kerning is None: obj = self.kerning else: - with UFOReader(self._path, validate=False) as reader: - kerning = reader.readKerning(validate=self._kerning.ufoLibReadValidate) - # Note: the incoming kerning data has not been validated. - # Gremlins may be sneaking in through here. - self._kerning.clear() - self._kerning.update(kerning) - self._stampKerningDataState(reader) + reader = UFOReader(self._path) + kerning = reader.readKerning() + # Note: the incoming kerning data has not been validated. + # Gremlins may be sneaking in through here. + self._kerning.clear() + self._kerning.update(kerning) + self._stampKerningDataState(reader) def reloadGroups(self): """ @@ -1471,11 +1311,11 @@ if self._groups is None: obj = self.groups else: - with UFOReader(self._path, validate=False) as reader: - d = reader.readGroups(validate=self._groups.ufoLibReadValidate) - self._groups.clear() - self._groups.update(d) - self._stampGroupsDataState(reader) + reader = UFOReader(self._path) + d = reader.readGroups() + self._groups.clear() + self._groups.update(d) + self._stampGroupsDataState(reader) def reloadFeatures(self): """ @@ -1485,10 +1325,10 @@ if self._features is None: obj = self.features else: - with UFOReader(self._path, validate=False) as reader: - text = reader.readFeatures() - self._features.text = text - self._stampFeaturesDataState(reader) + reader = UFOReader(self._path) + text = reader.readFeatures() + self._features.text = text + self._stampFeaturesDataState(reader) def reloadLib(self): """ @@ -1498,11 +1338,11 @@ if self._lib is None: obj = self.lib else: - with UFOReader(self._path, validate=False) as reader: - d = reader.readLib(validate=self._lib.ufoLibReadValidate) - self._lib.clear() - self._lib.update(d) - self._stampLibDataState(reader) + reader = UFOReader(self._path) + d = reader.readLib() + self._lib.clear() + self._lib.update(d) + self._stampLibDataState(reader) def reloadImages(self, fileNames): """ @@ -1801,16 +1641,6 @@ setter(key, data[key]) -def samepath(p1, p2): - """Return True if p1 and p2 refer to the same path. That is, when both - are strings or os.PathLike objects, compare their absolute, case - insensitive representation. - """ - return os.path.normcase(os.path.realpath(os.path.abspath(p1))) == ( - os.path.normcase(os.path.realpath(os.path.abspath(p2))) - ) - - if __name__ == "__main__": import doctest doctest.testmod() diff -Nru defcon-0.7.2/Lib/defcon/objects/glyph.py defcon-0.3.5/Lib/defcon/objects/glyph.py --- defcon-0.7.2/Lib/defcon/objects/glyph.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/glyph.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,7 +1,7 @@ from __future__ import absolute_import import weakref from warnings import warn -from fontTools.misc.arrayTools import unionRect +from fontTools.misc.py23 import basestring from defcon.objects.base import BaseObject from defcon.objects.contour import Contour from defcon.objects.point import Point @@ -11,7 +11,7 @@ from defcon.objects.guideline import Guideline from defcon.objects.image import Image from defcon.objects.color import Color -from defcon.tools.representations import glyphAreaRepresentationFactory +from defcon.tools.representations import glyphBoundsRepresentationFactory, glyphControlPointBoundsRepresentationFactory from defcon.pens.decomposeComponentPointPen import DecomposeComponentPointPen @@ -32,42 +32,38 @@ **This object posts the following notifications:** - - Glyph.Changed - - Glyph.BeginUndo - - Glyph.EndUndo - - Glyph.BeginRedo - - Glyph.EndRedo - - Glyph.NameWillChange - - Glyph.NameChanged - - Glyph.UnicodesChanged - - Glyph.WidthChanged - - Glyph.HeightChanged - - Glyph.LeftMarginWillChange - - Glyph.LeftMarginDidChange - - Glyph.RightMarginWillChange - - Glyph.RightMarginDidChange - - Glyph.TopMarginWillChange - - Glyph.TopMarginDidChange - - Glyph.BottomMarginWillChange - - Glyph.BottomMarginDidChange - - Glyph.NoteChanged - - Glyph.LibChanged - - Glyph.ImageChanged - - Glyph.ImageWillBeDeleted - - Glyph.ContourWillBeAdded - - Glyph.ContourWillBeDeleted - - Glyph.ContoursChanged - - Glyph.ComponentWillBeAdded - - Glyph.ComponentWillBeDeleted - - Glyph.ComponentsChanged - - Glyph.AnchorWillBeAdded - - Glyph.AnchorWillBeDeleted - - Glyph.AnchorsChanged - - Glyph.GuidelineWillBeAdded - - Glyph.GuidelineWillBeDeleted - - Glyph.GuidelinesChanged - - Glyph.MarkColorChanged - - Glyph.VerticalOriginChanged + ============================ + Name + ============================ + Glyph.Changed + Glyph.BeginUndo + Glyph.EndUndo + Glyph.BeginRedo + Glyph.EndRedo + Glyph.NameWillChange + Glyph.NameChanged + Glyph.UnicodesChanged + Glyph.WidthChanged + Glyph.HeightChanged + Glyph.NoteChanged + Glyph.LibChanged + Glyph.ImageChanged + Glyph.ImageWillBeDeleted + Glyph.ContourWillBeAdded + Glyph.ContourWillBeDeleted + Glyph.ContoursChanged + Glyph.ComponentWillBeAdded + Glyph.ComponentWillBeDeleted + Glyph.ComponentsChanged + Glyph.AnchorWillBeAdded + Glyph.AnchorWillBeDeleted + Glyph.AnchorsChanged + Glyph.GuidelineWillBeAdded + Glyph.GuidelineWillBeDeleted + Glyph.GuidelinesChanged + Glyph.MarkColorChanged + Glyph.VerticalOriginChanged + ============================ The Glyph object has list like behavior. This behavior allows you to interact with contour data directly. For example, to get a particular contour:: @@ -92,8 +88,12 @@ beginRedoNotificationName = "Glyph.BeginRedo" endRedoNotificationName = "Glyph.EndRedo" representationFactories = { - "defcon.glyph.area" : dict( - factory=glyphAreaRepresentationFactory, + "defcon.glyph.bounds" : dict( + factory=glyphBoundsRepresentationFactory, + destructiveNotifications=("Glyph.ContoursChanged", "Glyph.ComponentsChanged", "Glyph.ComponentBaseGlyphDataChanged") + ), + "defcon.glyph.controlPointBounds" : dict( + factory=glyphControlPointBoundsRepresentationFactory, destructiveNotifications=("Glyph.ContoursChanged", "Glyph.ComponentsChanged", "Glyph.ComponentBaseGlyphDataChanged") ) } @@ -223,7 +223,7 @@ def _set_unicodes(self, value): oldValue = self.unicodes if oldValue != value: - self._unicodes = list(value) + self._unicodes = value self.postNotification(notification="Glyph.UnicodesChanged", data=dict(oldValue=oldValue, newValue=value)) self.dirty = True @@ -238,7 +238,11 @@ if value is None: self.unicodes = [] else: - self.unicodes = [value] + existing = list(self._unicodes) + if value in existing: + existing.pop(existing.index(value)) + existing.insert(0, value) + self.unicodes = existing unicode = property(_get_unicode, _set_unicode, doc="The primary unicode value for the glyph. This is the equivalent of ``glyph.unicodes[0]``. This is a convenience attribute that works with the ``unicodes`` attribute.") @@ -248,36 +252,16 @@ # bounds - def _getContourComponentBounds(self, attr): - bounds = None - subObjects = [contour for contour in self] - subObjects += [component for component in self.components] - for subObject in subObjects: - b = getattr(subObject, attr) - if b is not None: - if bounds is None: - bounds = b - else: - bounds = unionRect(bounds, b) - return bounds - def _get_bounds(self): - return self._getContourComponentBounds("bounds") + return self.getRepresentation("defcon.glyph.bounds") bounds = property(_get_bounds, doc="The bounds of the glyph's outline expressed as a tuple of form (xMin, yMin, xMax, yMax).") def _get_controlPointBounds(self): - return self._getContourComponentBounds("controlPointBounds") + return self.getRepresentation("defcon.glyph.controlPointBounds") controlPointBounds = property(_get_controlPointBounds, doc="The control bounds of all points in the glyph. This only measures the point positions, it does not measure curves. So, curves without points at the extrema will not be properly measured.") - # area - - def _get_area(self): - return self.getRepresentation("defcon.glyph.area") - - area = property(_get_area, doc="The area of the glyph's outline.") - # margins def _get_leftMargin(self): @@ -295,13 +279,11 @@ oldValue = xMin diff = value - xMin if value != oldValue: - self.postNotification(notification="Glyph.LeftMarginWillChange", data=dict(oldValue=oldValue, newValue=value)) self.move((diff, 0)) self.width += diff self.dirty = True - self.postNotification(notification="Glyph.LeftMarginDidChange", data=dict(oldValue=oldValue, newValue=value)) - leftMargin = property(_get_leftMargin, _set_leftMargin, doc="The left margin of the glyph. Setting this posts *Glyph.WidthChanged*, *Glyph.LeftMarginWillChange*, *Glyph.LeftMarginDidChange* and *Glyph.Changed* notifications among others.") + leftMargin = property(_get_leftMargin, _set_leftMargin, doc="The left margin of the glyph. Setting this post *Glyph.WidthChanged* and *Glyph.Changed* notifications among others.") def _get_rightMargin(self): bounds = self.bounds @@ -317,12 +299,10 @@ xMin, yMin, xMax, yMax = bounds oldValue = self._width - xMax if oldValue != value: - self.postNotification(notification="Glyph.RightMarginWillChange", data=dict(oldValue=oldValue, newValue=value)) self.width = xMax + value self.dirty = True - self.postNotification(notification="Glyph.RightMarginDidChange", data=dict(oldValue=oldValue, newValue=value)) - rightMargin = property(_get_rightMargin, _set_rightMargin, doc="The right margin of the glyph. Setting this posts *Glyph.WidthChanged*, *Glyph.RightMarginWillChange*, *Glyph.RightMarginDidChange* and *Glyph.Changed* notifications among others.") + rightMargin = property(_get_rightMargin, _set_rightMargin, doc="The right margin of the glyph. Setting this posts *Glyph.WidthChanged* and *Glyph.Changed* notifications among others.") def _get_bottomMargin(self): bounds = self.bounds @@ -346,12 +326,10 @@ oldValue = yMin - (self.verticalOrigin - self.height) diff = value - oldValue if value != oldValue: - self.postNotification(notification="Glyph.BottomMarginWillChange", data=dict(oldValue=oldValue, newValue=value)) self.height += diff self.dirty = True - self.postNotification(notification="Glyph.BottomMarginDidChange", data=dict(oldValue=oldValue, newValue=value)) - bottomMargin = property(_get_bottomMargin, _set_bottomMargin, doc="The bottom margin of the glyph. Setting this posts *Glyph.HeightChanged*, *Glyph.BottomMarginWillChange*, *Glyph.BottomMarginDidChange* and *Glyph.Changed* notifications among others.") + bottomMargin = property(_get_bottomMargin, _set_bottomMargin, doc="The bottom margin of the glyph. Setting this post *Glyph.HeightChanged* and *Glyph.Changed* notifications among others.") def _get_topMargin(self): bounds = self.bounds @@ -374,13 +352,11 @@ oldValue = self.verticalOrigin - yMax diff = value - oldValue if oldValue != value: - self.postNotification(notification="Glyph.TopMarginWillChange", data=dict(oldValue=oldValue, newValue=value)) self.verticalOrigin = yMax + value self.height += diff self.dirty = True - self.postNotification(notification="Glyph.TopMarginWillChange", data=dict(oldValue=oldValue, newValue=value)) - topMargin = property(_get_topMargin, _set_topMargin, doc="The top margin of the glyph. Setting this posts *Glyph.HeightChanged*, *Glyph.VerticalOriginChanged*, *Glyph.TopMarginWillChange*, *Glyph.TopMarginDidChange* and *Glyph.Changed* notifications among others.") + topMargin = property(_get_topMargin, _set_topMargin, doc="The top margin of the glyph. Setting this posts *Glyph.HeightChanged*, *Glyph.VerticalOriginChanged* and *Glyph.Changed* notifications among others.") # width @@ -473,7 +449,7 @@ """ Draw the glyph with **pen**. """ - from fontTools.pens.pointPen import PointToSegmentPen + from ufoLib.pointPen import PointToSegmentPen pointPen = PointToSegmentPen(pen) self.drawPoints(pointPen) @@ -504,7 +480,7 @@ """ Get the pen used to draw into this glyph. """ - from fontTools.pens.pointPen import SegmentToPointPen + from ufoLib.pointPen import SegmentToPointPen return SegmentToPointPen(self.getPointPen()) def getPointPen(self): @@ -586,7 +562,7 @@ """ assert contour not in self assert contour.glyph in (self, None), "This contour belongs to another glyph." - self.postNotification(notification="Glyph.ContourWillBeAdded", data=dict(object=contour)) + self.postNotification(notification="Glyph.ContourWillBeAdded") if contour.glyph is None: identifiers = self._identifiers if contour.identifier is not None: @@ -635,41 +611,11 @@ This posts a *Glyph.Changed* notification. """ - self.holdNotifications(note="Requested by Glyph.clearContours.") + self.holdNotifications() for contour in reversed(self): self.removeContour(contour) self.releaseHeldNotifications() - def correctContourDirection(self, trueType=False, segmentLength=10): - """ - Correct the direction of all contours in the glyph. - - This posts a *Glyph.Changed* notification. - """ - # set the contours to the same direction - for contour in self: - contour.clockwise = False - # sort the contours by area in reverse (i.e. largest first) - contours = sorted(self, key=lambda contour: -contour.area) - # build a tree of nested contours - tree = {} - for largeIndex, largeContour in enumerate(contours): - for smallContour in contours[largeIndex + 1:]: - if largeContour.contourInside(smallContour, segmentLength=segmentLength): - if largeContour not in tree: - tree[largeContour] = [] - tree[largeContour].append(smallContour) - # run through the tree, largest to smallest, flipping - # the direction of each contour nested within another contour - for largeContour in contours: - if largeContour in tree: - for smallContour in tree[largeContour]: - smallContour.reverse() - # set to the opposite if needed - if trueType: - for contour in self: - contour.reverse() - # ---------- # Components # ---------- @@ -726,7 +672,7 @@ """ assert component not in self._components assert component.glyph in (self, None), "This component belongs to another glyph." - self.postNotification(notification="Glyph.ComponentWillBeAdded", data=dict(object=component)) + self.postNotification(notification="Glyph.ComponentWillBeAdded") if component.glyph is None: if component.identifier is not None: identifiers = self._identifiers @@ -765,7 +711,7 @@ This posts a *Glyph.Changed* notification. """ - self.holdNotifications(note="Requested by Glyph.clearComponents.") + self.holdNotifications() for component in reversed(self._components): self.removeComponent(component) self.releaseHeldNotifications() @@ -779,7 +725,7 @@ This posts *Glyph.ComponentsChanged*, *Glyph.ContoursChanged* and *Glyph.Changed* notifications. """ - self.holdNotifications(note="Requested by Glyph.decomposeComponent.") + self.holdNotifications() layer = self.layer pointPen = DecomposeComponentPointPen(self, layer) self._decomposeComponent(component, layer, pointPen) @@ -798,7 +744,7 @@ """ if not self.components: return - self.holdNotifications(note="Requested by Glyph.decomposeAllComponents.") + self.holdNotifications() layer = self.layer pointPen = DecomposeComponentPointPen(self, layer) for component in self.components: @@ -825,7 +771,7 @@ def _set_anchors(self, value): self.clearAnchors() - self.holdNotifications(note="Requested by Glyph._set_anchors.") + self.holdNotifications() for anchor in value: self.appendAnchor(anchor) self.releaseHeldNotifications() @@ -912,7 +858,7 @@ This posts a *Glyph.Changed* notification. """ - self.holdNotifications(note="Requested by Glyph.clearAnchors.") + self.holdNotifications() for anchor in reversed(self._anchors): self.removeAnchor(anchor) self.releaseHeldNotifications() @@ -931,7 +877,7 @@ def _set_guidelines(self, value): self.clearGuidelines() - self.holdNotifications(note="Requested by Glyph._set_guidelines.") + self.holdNotifications() for guideline in value: self.appendGuideline(guideline) self.releaseHeldNotifications() @@ -1020,7 +966,7 @@ This posts a *Glyph.Changed* notification. """ - self.holdNotifications(note="Requested by Glyph.clearGuidelines.") + self.holdNotifications() for guideline in reversed(self._guidelines): self.removeGuideline(guideline) self.releaseHeldNotifications() @@ -1034,7 +980,7 @@ def _set_note(self, value): if value is not None: - assert isinstance(value, str) + assert isinstance(value, basestring) oldValue = self._note if oldValue != value: self._note = value @@ -1221,7 +1167,7 @@ This posts a *Glyph.Changed* notification. """ - self.holdNotifications(note="Requested by Glyph.clear.") + self.holdNotifications() self.clearContours() self.clearComponents() self.clearAnchors() diff -Nru defcon-0.7.2/Lib/defcon/objects/groups.py defcon-0.3.5/Lib/defcon/objects/groups.py --- defcon-0.7.2/Lib/defcon/objects/groups.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/groups.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,7 +1,6 @@ from __future__ import absolute_import import weakref from defcon.objects.base import BaseDictObject -from defcon.tools.representations import kerningSide1GroupsRepresentationFactory, kerningSide2GroupsRepresentationFactory, glyphToKerningSide1GroupsRepresentationFactory, glyphToKerningSide2GroupsRepresentationFactory class Groups(BaseDictObject): @@ -11,15 +10,19 @@ **This object posts the following notifications:** - - Groups.Changed - - Groups.BeginUndo - - Groups.EndUndo - - Groups.BeginRedo - - Groups.EndRedo - - Groups.GroupSet - - Groups.GroupDeleted - - Groups.Cleared - - Groups.Updated + =================== + Name + =================== + Groups.Changed + Groups.BeginUndo + Groups.EndUndo + Groups.BeginRedo + Groups.EndRedo + Groups.GroupSet + Groups.GroupDeleted + Groups.Cleared + Groups.Updated + =================== This object behaves like a dict. The keys are group names and the values are lists of glyph names:: @@ -72,24 +75,7 @@ deleteItemNotificationName = "Groups.GroupDeleted" clearNotificationName = "Groups.Cleared" updateNotificationName = "Groups.Updated" - representationFactories = { - "defcon.groups.kerningSide1Groups" : dict( - factory=kerningSide1GroupsRepresentationFactory, - destructiveNotifications=("Groups.Changed") - ), - "defcon.groups.kerningSide2Groups" : dict( - factory=kerningSide2GroupsRepresentationFactory, - destructiveNotifications=("Groups.Changed") - ), - "defcon.groups.kerningGlyphToSide1Group" : dict( - factory=glyphToKerningSide1GroupsRepresentationFactory, - destructiveNotifications=("Groups.Changed") - ), - "defcon.groups.kerningGlyphToSide2Group" : dict( - factory=glyphToKerningSide2GroupsRepresentationFactory, - destructiveNotifications=("Groups.Changed") - ), -} + representationFactories = {} def __init__(self, font=None): self._font = None diff -Nru defcon-0.7.2/Lib/defcon/objects/guideline.py defcon-0.3.5/Lib/defcon/objects/guideline.py --- defcon-0.7.2/Lib/defcon/objects/guideline.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/guideline.py 2017-10-02 10:54:57.000000000 +0000 @@ -12,12 +12,16 @@ **This object posts the following notifications:** - - Guideline.Changed - - Guideline.XChanged - - Guideline.YChanged - - Guideline.AngleChanged - - Guideline.NameChanged - - Guideline.IdentifierChanged + =========================== + Name + =========================== + Guideline.Changed + Guideline.XChanged + Guideline.YChanged + Guideline.AngleChanged + Guideline.NameChanged + Guideline.IdentifierChanged + =========================== During initialization a guideline dictionary, following the format defined in the UFO spec, can be passed. If so, the new object will be populated diff -Nru defcon-0.7.2/Lib/defcon/objects/image.py defcon-0.3.5/Lib/defcon/objects/image.py --- defcon-0.7.2/Lib/defcon/objects/image.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/image.py 2017-10-02 10:54:57.000000000 +0000 @@ -20,11 +20,15 @@ **This object posts the following notifications:** - - Image.Changed - - Image.FileNameChanged - - Image.TransformationChanged - - Image.ColorChanged - - Image.ImageDataChanged + =========================== + Name + =========================== + Image.Changed + Image.FileNameChanged + Image.TransformationChanged + Image.ColorChanged + Image.ImageDataChanged + =========================== During initialization an image dictionary, following the format defined in the UFO spec, can be passed. If so, the new object will be populated @@ -157,7 +161,7 @@ return xScale, xyScale, yxScale, yScale, xOffset, yOffset = transformation # hold the notifications so that only one is sent out - self.holdNotifications(note="Requested by Image._set_transformation.") + self.holdNotifications() self["xScale"] = xScale self["xyScale"] = xyScale self["yxScale"] = yxScale @@ -201,7 +205,7 @@ if not (xOffset or yOffset): return oldTransformation = self.transformation - self.holdNotifications(note="Requested by Image.move.") + self.holdNotifications() self["xOffset"] += xOffset self["yOffset"] += yOffset self.releaseHeldNotifications() diff -Nru defcon-0.7.2/Lib/defcon/objects/imageSet.py defcon-0.3.5/Lib/defcon/objects/imageSet.py --- defcon-0.7.2/Lib/defcon/objects/imageSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/imageSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -3,11 +3,10 @@ import hashlib import weakref from defcon.objects.base import BaseObject -from fontTools.ufoLib import UFOReader, UFOLibError -from fontTools.ufoLib.filenames import ( - userNameToFileName, illegalCharacters, reservedFileNames, maxFileNameLength -) -from fontTools.ufoLib.validators import pngSignature +from fontTools.misc.py23 import unicode +from ufoLib import UFOReader, UFOLibError +from ufoLib.filenames import userNameToFileName, illegalCharacters, reservedFileNames, maxFileNameLength +from ufoLib.validators import pngSignature class ImageSet(BaseObject): @@ -17,13 +16,17 @@ **This object posts the following notifications:** - - ImageSet.Changed - - ImageSet.FileNamesChanged - - ImageSet.ImageChanged - - ImageSet.ImageWillBeAdded - - ImageSet.ImageAdded - - ImageSet.ImageWillBeDeleted - - ImageSet.ImageDeleted + =========================== + Name + =========================== + ImageSet.Changed + ImageSet.FileNamesChanged + ImageSet.ImageChanged + ImageSet.ImageWillBeAdded + ImageSet.ImageAdded + ImageSet.ImageWillBeDeleted + ImageSet.ImageDeleted + =========================== This object behaves like a dict. For example, to get the raw image data for a particular image:: @@ -113,12 +116,13 @@ def __getitem__(self, fileName): d = self._data[fileName] if d["data"] is None: - reader = self.font._reader - data = reader.readImage(fileName, validate=self.ufoLibReadValidate) + path = self.font.path + reader = UFOReader(path) + data = reader.readImage(fileName) d["data"] = data d["digest"] = _makeDigest(data) d["onDisk"] = True - d["onDiskModTime"] = reader.getFileModificationTime("%s/%s" % ("images", fileName)) + d["onDiskModTime"] = reader.getFileModificationTime(os.path.join("images", fileName)) return d["data"] def __setitem__(self, fileName, data): @@ -184,15 +188,15 @@ if saveAs: font = self.font if font is not None and font.path is not None and os.path.exists(font.path): - with UFOReader(font.path, validate=False) as reader: - readerImageNames = reader.getImageDirectoryListing(validate=self.ufoLibReadValidate) - for fileName, data in self._data.items(): - if data["data"] is not None or fileName not in readerImageNames: - continue - writer.copyImageFromReader(reader, fileName, fileName, validate=self.ufoLibWriteValidate) + reader = UFOReader(font.path) + readerImageNames = reader.getImageDirectoryListing() + for fileName, data in self._data.items(): + if data["data"] is not None or fileName not in readerImageNames: + continue + writer.copyImageFromReader(reader, fileName, fileName) for fileName in self._scheduledForDeletion: try: - writer.removeImage(fileName, validate=self.ufoLibWriteValidate) + writer.removeImage(fileName) except UFOLibError: # this will be raised if the file doesn't exist. # instead of trying to maintain a list of in UFO @@ -201,13 +205,14 @@ # in the UFO. pass self._scheduledForDeletion.clear() + reader = UFOReader(writer.path) for fileName, data in self._data.items(): if not data["dirty"]: continue - writer.writeImage(fileName, data["data"], validate=self.ufoLibWriteValidate) + writer.writeImage(fileName, data["data"]) data["dirty"] = False data["onDisk"] = True - data["onDiskModTime"] = writer.getFileModificationTime("%s/%s" % ("images", fileName)) + data["onDiskModTime"] = reader.getFileModificationTime(os.path.join("images", fileName)) self.dirty = False # --------------- @@ -218,7 +223,7 @@ """ Make a file system legal version of **fileName**. """ - fileName = str(fileName) + fileName = unicode(fileName) suffix = "" if fileName.lower().endswith(".png"): suffix = fileName[-4:] @@ -267,14 +272,12 @@ addedImages.append(fileName) elif not self._scheduledForDeletion[fileName]["onDisk"]: addedImages.append(fileName) - elif self._scheduledForDeletion[fileName]["onDiskModTime"] != reader.getFileModificationTime( - "%s/%s" % ("images", fileName) - ): + elif self._scheduledForDeletion[fileName]["onDiskModTime"] != reader.getFileModificationTime(os.path.join("images", fileName)): addedImages.append(fileName) for fileName, imageData in self._data.items(): # file on disk and has been loaded if fileName in filesOnDisk and imageData["data"] is not None: - newModTime = reader.getFileModificationTime("%s/%s" % ("images", fileName)) + newModTime = reader.getFileModificationTime(os.path.join("images", fileName)) if newModTime != imageData["onDiskModTime"]: newData = reader.readImage(fileName) newDigest = _makeDigest(newData) @@ -390,7 +393,7 @@ True """ # must be a unicode - if not isinstance(value, str): + if not isinstance(value, unicode): return False # must not be longer then the max fileName length if len(value) > maxFileNameLength: diff -Nru defcon-0.7.2/Lib/defcon/objects/info.py defcon-0.3.5/Lib/defcon/objects/info.py --- defcon-0.7.2/Lib/defcon/objects/info.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/info.py 2017-10-02 10:54:57.000000000 +0000 @@ -4,7 +4,7 @@ import weakref from warnings import warn -from fontTools import ufoLib +import ufoLib from defcon.objects.base import BaseObject from copy import copy from functools import partial @@ -59,12 +59,16 @@ **This object posts the following notifications:** - - Info.Changed - - Info.BeginUndo - - Info.EndUndo - - Info.BeginRedo - - Info.EndRedo - - Info.ValueChanged + =========================== + Name + =========================== + Info.Changed + Info.BeginUndo + Info.EndUndo + Info.BeginRedo + Info.EndRedo + Info.ValueChanged + =========================== **Note:** The documentation strings here were automatically generated from the `UFO specification `_. diff -Nru defcon-0.7.2/Lib/defcon/objects/kerning.py defcon-0.3.5/Lib/defcon/objects/kerning.py --- defcon-0.7.2/Lib/defcon/objects/kerning.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/kerning.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,6 +1,5 @@ from __future__ import absolute_import import weakref -from fontTools.ufoLib.kerning import lookupKerningValue from defcon.objects.base import BaseDictObject @@ -11,15 +10,19 @@ **This object posts the following notifications:** - - Kerning.Changed - - Kerning.BeginUndo - - Kerning.EndUndo - - Kerning.BeginRedo - - Kerning.EndRedo - - Kerning.PairSet - - Kerning.PairDeleted - - Kerning.Cleared - - Kerning.Updated + =================== + Name + =================== + Kerning.Changed + Kerning.BeginUndo + Kerning.EndUndo + Kerning.BeginRedo + Kerning.EndRedo + Kerning.PairSet + Kerning.PairDeleted + Kerning.Cleared + Kerning.Updated + ==================== This object behaves like a dict. For example, to get a list of all kerning pairs:: @@ -82,26 +85,6 @@ def get(self, pair, default=0): return super(Kerning, self).get(pair, default) - def find(self, pair, default=0): - """ - This will find the value for **pair** even if - **pair** is not specifically defined. For example: - You have a group named `public.kern1.A` with - the contents `["A", "Aacute"]` and you have a - group named `public.kern2.C` with the contents - `["C", "Ccedilla"]`. The only defined kerning is - `("public.kern1.A", public.kern2.C) = 100`. - If you use this method to find the value for - `("A", "Ccedilla")` you will get `100`. - """ - from defcon.errors import DefconError - font = self.font - if font is None: - raise DefconError("The find method requires a parent font.") - glyphToFirstGroup = font.groups.getRepresentation("defcon.groups.kerningGlyphToSide1Group") - glyphToSecondGroup = font.groups.getRepresentation("defcon.groups.kerningGlyphToSide2Group") - return lookupKerningValue(pair, self, font.groups, fallback=default, glyphToFirstGroup=glyphToFirstGroup, glyphToSecondGroup=glyphToSecondGroup) - # ------------------------ # Notification Observation # ------------------------ diff -Nru defcon-0.7.2/Lib/defcon/objects/layer.py defcon-0.3.5/Lib/defcon/objects/layer.py --- defcon-0.7.2/Lib/defcon/objects/layer.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/layer.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,7 +1,7 @@ from __future__ import absolute_import import weakref -from fontTools.ufoLib import UFOFileStructure from fontTools.misc.arrayTools import unionRect +from fontTools.misc.py23 import tounicode from defcon.objects.base import BaseObject from defcon.objects.glyph import Glyph from defcon.objects.lib import Lib @@ -17,17 +17,31 @@ **This object posts the following notifications:** - - Layer.Changed - - Layer.GlyphsChanged - - Layer.GlyphChanged - - Layer.GlyphWillBeAdded - - Layer.GlyphAdded - - Layer.GlyphWillBeDeleted - - Layer.GlyphDeleted - - Layer.GlyphNameChanged - - Layer.GlyphUnicodesChanged - - Layer.NameChanged - - Layer.ColorChanged + +----------------------------+ + |Name | + +============================+ + |Layer.Changed | + +----------------------------+ + |Layer.GlyphsChanged | + +----------------------------+ + |Layer.GlyphChanged | + +----------------------------+ + |Layer.GlyphWillBeAdded | + +----------------------------+ + |Layer.GlyphAdded | + +----------------------------+ + |Layer.GlyphWillBeDeleted | + +----------------------------+ + |Layer.GlyphDeleted | + +----------------------------+ + |Layer.GlyphNameChanged | + +----------------------------+ + |Layer.GlyphUnicodesChanged | + +----------------------------+ + |Layer.NameChanged | + +----------------------------+ + |Layer.ColorChanged | + +----------------------------+ The Layer object has some dict like behavior. For example, to get a glyph:: @@ -160,7 +174,7 @@ Load a glyph from the glyph set. This should not be called externally, but subclasses may override it for custom behavior. """ - if self._glyphSet is None or name not in self._glyphSet or name in self._scheduledForDeletion: + if self._glyphSet is None or name not in self._glyphSet: raise KeyError("%s not in layer" % name) glyph = self.instantiateGlyphObject() glyph.disableNotifications() @@ -216,7 +230,7 @@ if name is None: name = source.name self.postNotification("Layer.GlyphWillBeAdded", data=(dict(name=name))) - self.holdNotifications(note="Requested by Layer.insertGlyph.") + self.holdNotifications() dest = self.newGlyph(name) dest.copyDataFromGlyph(glyph) self.releaseHeldNotifications() @@ -294,7 +308,7 @@ # name def _set_name(self, value): - value = str(value) + value = tounicode(value) oldName = self._name if oldName != value: self._name = value @@ -561,31 +575,29 @@ """ if glyph.dirty or saveAs: glyphSet.writeGlyph(glyph.name, glyph, glyph.drawPoints) - self._stampGlyphDataState(glyph, glyphSet=glyphSet) + self._stampGlyphDataState(glyph) glyph.dirty = False # --------------------- # External Edit Support # --------------------- - def _stampGlyphDataState(self, glyph, glyphSet=None): - if glyphSet is None: - glyphSet = self._glyphSet - if glyphSet is None: + def _stampGlyphDataState(self, glyph): + if self._glyphSet is None: return + glyphSet = self._glyphSet glyphName = glyph.name if glyphName not in glyphSet.contents: return - modTime = glyphSet.getGLIFModificationTime(glyphName) - text = glyphSet.getGLIF(glyphName) + modTime = self._glyphSet.getGLIFModificationTime(glyphName) + text = self._glyphSet.getGLIF(glyphName) glyph._dataOnDisk = text glyph._dataOnDiskTimeStamp = modTime - def testForExternalChanges(self, reader): + def testForExternalChanges(self): """ Test for external changes. This should not be called externally. """ - self._glyphSet = reader.getGlyphSet(layerName=self.name, validateRead=self.ufoLibReadValidate) glyphSet = self._glyphSet if glyphSet is None: return [], [], [] diff -Nru defcon-0.7.2/Lib/defcon/objects/layerSet.py defcon-0.3.5/Lib/defcon/objects/layerSet.py --- defcon-0.7.2/Lib/defcon/objects/layerSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/layerSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,6 +1,6 @@ from __future__ import absolute_import import weakref -from fontTools.ufoLib import UFOReader, UFOFileStructure, UFOFormatVersion +from ufoLib import UFOReader from defcon.objects.base import BaseObject from defcon.objects.layer import Layer @@ -12,16 +12,29 @@ **This object posts the following notifications:** - - LayerSet.Changed - - LayerSet.LayersChanged - - LayerSet.LayerChanged - - LayerSet.DefaultLayerWillChange - - LayerSet.DefaultLayerChanged - - LayerSet.LayerOrderChanged - - LayerSet.LayerAdded - - LayerSet.LayerDeleted - - LayerSet.LayerWillBeDeleted - - LayerSet.LayerNameChanged + +-------------------------------+ + |Name | + +===============================+ + |LayerSet.Changed | + +-------------------------------+ + |LayerSet.LayersChanged | + +-------------------------------+ + |LayerSet.LayerChanged | + +-------------------------------+ + |LayerSet.DefaultLayerWillChange| + +-------------------------------+ + |LayerSet.DefaultLayerChanged | + +-------------------------------+ + |LayerSet.LayerOrderChanged | + +-------------------------------+ + |LayerSet.LayerAdded | + +-------------------------------+ + |LayerSet.LayerDeleted | + +-------------------------------+ + |LayerSet.LayerWillBeDeleted | + +-------------------------------+ + |LayerSet.LayerNameChanged | + +-------------------------------+ This object behaves like a dict. For example, to get a particular layer:: @@ -270,8 +283,6 @@ newName = actionData["newName"] if oldName in writer.layerContents: writer.renameGlyphSet(oldName, newName) - if newName == self.defaultLayer.name: - writer.renameGlyphSet(newName, newName, defaultLayer=True) elif action == "default": newDefault = actionData["newDefault"] oldDefault = actionData["oldDefault"] @@ -288,12 +299,11 @@ # this will be handled by the creation of the glyph set pass # save the layers - - if writer.formatVersionTuple < UFOFormatVersion.FORMAT_3_0: + if writer.formatVersion < 3: if progressBar is not None: progressBar.update(text="Saving glyphs...", increment=0) layer = self.defaultLayer - glyphSet = writer.getGlyphSet(layerName=None, defaultLayer=True, validateRead=self.ufoLibReadValidate, validateWrite=self.ufoLibWriteValidate) + glyphSet = writer.getGlyphSet(layerName=None, defaultLayer=True) layer.save(glyphSet, saveAs=saveAs, progressBar=progressBar) if progressBar is not None: progressBar.update() @@ -303,7 +313,7 @@ progressBar.update(text="Saving layer \"%s\"..." % layerName, increment=0) layer = self[layerName] isDefaultLayer = layer == self.defaultLayer - glyphSet = writer.getGlyphSet(layerName=layerName, defaultLayer=isDefaultLayer, validateRead=self.ufoLibReadValidate, validateWrite=self.ufoLibWriteValidate) + glyphSet = writer.getGlyphSet(layerName=layerName, defaultLayer=isDefaultLayer) layer.save(glyphSet, saveAs=saveAs, progressBar=progressBar) # this prevents us from saving when the color was deleted #if layer.lib or layer.color: @@ -322,22 +332,6 @@ continue self._layerActionHistory.append(dict(action="new", name=layer.name)) - def _fontSaveWasCompleted(self): - """ - When saving a UFOZ, the underlying ZipFS object is closed. - The objects then stored in layer._glyphSet contain references - to a closed, and therefore unusable, filesystem. To remedy this, - after the save is completed this method will be called and new - GlyphSet objects will be created and assigned to the layers. - """ - font = self.font - font.close() - font._reader = reader = UFOReader(font.path, validate=font.ufoLibReadValidate) - if reader.fileStructure is UFOFileStructure.ZIP: - for layerName in self.layerOrder: - layer = self[layerName] - layer._glyphSet = reader.getGlyphSet(layerName=layerName, validateRead=self.ufoLibReadValidate) - # ------------------------ # Notification Observation # ------------------------ @@ -405,15 +399,13 @@ # modified layers modifiedLayers = {} for layerName in self.layerOrder: - if layerName in deletedLayers: - continue layer = self[layerName] - modifiedGlyphs, addedGlyphs, deletedGlyphs = layer.testForExternalChanges(reader) newLayerInfo = _StaticLayerInfoMaker() layerInfoChanged = False if layer._glyphSet is not None: layer._glyphSet.readLayerInfo(newLayerInfo) layerInfoChanged = layer._dataOnDisk != newLayerInfo.pack() + modifiedGlyphs, addedGlyphs, deletedGlyphs = layer.testForExternalChanges() if modifiedGlyphs or addedGlyphs or deletedGlyphs or layerInfoChanged: modifiedLayers[layerName] = dict( info=layerInfoChanged, @@ -436,37 +428,37 @@ """ Reload the layers. This should not be called externally. """ - with UFOReader(self.font.path, validate=self.font.ufoLibReadValidate) as reader: - # handle the layers - currentLayerOrder = self.layerOrder - for layerName, l in layerData.get("layers", {}).items(): - # new layer - if layerName not in currentLayerOrder: - glyphSet = reader.getGlyphSet(layerName, validateRead=self.ufoLibReadValidate, validateWrite=self.font.ufoLibWriteValidate) - self.newLayer(layerName, glyphSet) - # get the layer - layer = self[layerName] - # reload the layer info - if l.get("info"): - layer.color = None - layer.lib.clear() - layer._glyphSet.readLayerInfo(layer) - self._stampLayerInfoDataState(layer) - # reload the glyphs - glyphNames = l.get("glyphNames", []) - if glyphNames: - layer.reloadGlyphs(glyphNames) - # handle the order - if layerData.get("order", False): - newLayerOrder = reader.getLayerNames() - for layerName in self.layerOrder: - if layerName not in newLayerOrder: - newLayerOrder.append(layerName) - self.layerOrder = newLayerOrder - # handle the default layer - if layerData.get("default", False): - newDefaultLayerName = reader.getDefaultLayerName() - self.defaultLayer = self[newDefaultLayerName] + reader = UFOReader(self.font.path) + # handle the layers + currentLayerOrder = self.layerOrder + for layerName, l in layerData.get("layers", {}).items(): + # new layer + if layerName not in currentLayerOrder: + glyphSet = reader.getGlyphSet(layerName) + self.newLayer(layerName, glyphSet) + # get the layer + layer = self[layerName] + # reload the layer info + if l.get("info"): + layer.color = None + layer.lib.clear() + layer._glyphSet.readLayerInfo(layer) + self._stampLayerInfoDataState(layer) + # reload the glyphs + glyphNames = l.get("glyphNames", []) + if glyphNames: + layer.reloadGlyphs(glyphNames) + # handle the order + if layerData.get("order", False): + newLayerOrder = reader.getLayerNames() + for layerName in self.layerOrder: + if layerName not in newLayerOrder: + newLayerOrder.append(layerName) + self.layerOrder = newLayerOrder + # handle the default layer + if layerData.get("default", False): + newDefaultLayerName = reader.getDefaultLayerName() + self.defaultLayer = self[newDefaultLayerName] # ----------------------------- # Serialization/Deserialization @@ -503,13 +495,13 @@ self.color = None def pack(self): - from fontTools.misc import plistlib + from ufoLib.plistlib import writePlistToString data = {} if self.lib: data["lib"] = self.lib if self.color is not None: data["color"] = self.color - return plistlib.dumps(data) + return writePlistToString(data) if __name__ == "__main__": diff -Nru defcon-0.7.2/Lib/defcon/objects/layoutEngine.py defcon-0.3.5/Lib/defcon/objects/layoutEngine.py --- defcon-0.7.2/Lib/defcon/objects/layoutEngine.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/layoutEngine.py 2017-10-02 10:54:57.000000000 +0000 @@ -53,7 +53,11 @@ **This object posts the following notifications:** - - LayoutEngine.Changed + ==================== + Name + ==================== + LayoutEngine.Changed + ==================== This object monitors the font's feature text and character mapping. When those change, the compiled tables will be flagged for recompilation and diff -Nru defcon-0.7.2/Lib/defcon/objects/lib.py defcon-0.3.5/Lib/defcon/objects/lib.py --- defcon-0.7.2/Lib/defcon/objects/lib.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/lib.py 2017-10-02 10:54:57.000000000 +0000 @@ -10,15 +10,19 @@ **This object posts the following notifications:** - - Lib.Changed - - Lib.BeginUndo - - Lib.EndUndo - - Lib.BeginRedo - - Lib.EndRedo - - Lib.ItemSet - - Lib.ItemDeleted - - Lib.Cleared - - Lib.Updated + =============== + Name + =============== + Lib.Changed + Lib.BeginUndo + Lib.EndUndo + Lib.BeginRedo + Lib.EndRedo + Lib.ItemSet + Lib.ItemDeleted + Lib.Cleared + Lib.Updated + =============== This object behaves like a dict. For example, to get a particular item from the lib:: diff -Nru defcon-0.7.2/Lib/defcon/objects/uniData.py defcon-0.3.5/Lib/defcon/objects/uniData.py --- defcon-0.7.2/Lib/defcon/objects/uniData.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/objects/uniData.py 2017-10-02 10:54:57.000000000 +0000 @@ -2,6 +2,7 @@ import weakref import unicodedata from fontTools.agl import AGL2UV +from fontTools.misc.py23 import basestring, range from defcon.tools import unicodeTools from defcon.objects.base import BaseDictObject @@ -13,7 +14,11 @@ **This object posts the following notifications:** - - UnicodeData.Changed + =================== + Name + =================== + UnicodeData.Changed + =================== This object behaves like a dict. The keys are Unicode values and the values are lists of glyph names associated with that unicode value:: @@ -573,7 +578,7 @@ def _sortRecurse(self, blocks, sortMethod, ascending, allowPseudoUnicode, function): if not blocks: return [] - if not isinstance(list(blocks)[0], str): + if not isinstance(list(blocks)[0], basestring): sortedBlocks = [] for block in blocks: block = self._sortRecurse(block, sortMethod, ascending, allowPseudoUnicode, function) diff -Nru defcon-0.7.2/Lib/defcon/pens/glyphObjectPointPen.py defcon-0.3.5/Lib/defcon/pens/glyphObjectPointPen.py --- defcon-0.7.2/Lib/defcon/pens/glyphObjectPointPen.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/pens/glyphObjectPointPen.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,4 +1,4 @@ -from fontTools.pens.pointPen import AbstractPointPen +from ufoLib.pointPen import AbstractPointPen class GlyphObjectPointPen(AbstractPointPen): diff -Nru defcon-0.7.2/Lib/defcon/pens/reverseContourPointPen.py defcon-0.3.5/Lib/defcon/pens/reverseContourPointPen.py --- defcon-0.7.2/Lib/defcon/pens/reverseContourPointPen.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/pens/reverseContourPointPen.py 2017-10-02 10:54:57.000000000 +0000 @@ -2,14 +2,14 @@ PointPen for reversing the winding direction of contours. NOTE: The module is deprecated and the ``ReverseContourPointPen`` class has -been moved to ``fontTools.pens.pointPen`` module. +been moved to ``ufoLib.pointPen`` module. """ -from fontTools.pens.pointPen import AbstractPointPen, ReverseContourPointPen +from ufoLib.pointPen import AbstractPointPen, ReverseContourPointPen import warnings warnings.warn( "Importing the `defcon.pens.reverseContourPointPen` module is deprecated. " - "Use `from fontTools.pens.pointPen import ReverseContourPointPen` instead.", + "Use `from ufoLib.pointPen import ReverseContourPointPen` instead.", DeprecationWarning, stacklevel=2) diff -Nru defcon-0.7.2/Lib/defcon/pens/transformPointPen.py defcon-0.3.5/Lib/defcon/pens/transformPointPen.py --- defcon-0.7.2/Lib/defcon/pens/transformPointPen.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/pens/transformPointPen.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,36 +1,30 @@ -from fontTools.pens.pointPen import AbstractPointPen -from warnings import warn - +from ufoLib.pointPen import AbstractPointPen class TransformPointPen(AbstractPointPen): - """PointPen that transforms all coordinates, and passes them to another - PointPen. It also transforms the transformation given to addComponent(). - """ - - def __init__(self, outPen, transformation): - if not hasattr(transformation, "transformPoint"): - from fontTools.misc.transform import Transform - transformation = Transform(*transformation) - self._transformation = transformation - self._transformPoint = transformation.transformPoint - self._outPen = outPen - self._stack = [] - - def beginPath(self, identifier=None): - self._outPen.beginPath(identifier=identifier) - - def endPath(self): - self._outPen.endPath() - - def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs): - pt = self._transformPoint(pt) - self._outPen.addPoint(pt, segmentType, smooth, name, **kwargs) - - def addComponent(self, glyphName, transformation, identifier=None): - transformation = self._transformation.transform(transformation) - try: - self._outPen.addComponent(glyphName, transformation, identifier) - except TypeError: - self._outPen.addComponent(glyphName, transformation) - warn("The addComponent method needs an identifier kwarg. The component's identifier value has been discarded.", DeprecationWarning) + """PointPen that transforms all coordinates, and passes them to another + PointPen. It also transforms the transformation given to addComponent(). + """ + + def __init__(self, outPen, transformation): + if not hasattr(transformation, "transformPoint"): + from fontTools.misc.transform import Transform + transformation = Transform(*transformation) + self._transformation = transformation + self._transformPoint = transformation.transformPoint + self._outPen = outPen + self._stack = [] + + def beginPath(self): + self._outPen.beginPath() + + def endPath(self): + self._outPen.endPath() + + def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs): + pt = self._transformPoint(pt) + self._outPen.addPoint(pt, segmentType, smooth, name, **kwargs) + + def addComponent(self, glyphName, transformation): + transformation = self._transformation.transform(transformation) + self._outPen.addComponent(glyphName, transformation) diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_base.py defcon-0.3.5/Lib/defcon/test/objects/test_base.py --- defcon-0.7.2/Lib/defcon/test/objects/test_base.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_base.py 2017-10-02 10:54:57.000000000 +0000 @@ -124,8 +124,6 @@ del self.obj def test_object_representations(self): - notificationCenter = NotificationCenter() - self.obj._dispatcher = weakref.ref(notificationCenter) self.obj.representationFactories = dict( test=dict( factory=_representationTestFactory, @@ -180,16 +178,6 @@ self.assertEqual(self.obj.representationKeys(), [('foo', {})]) - def test_object_representations_no_dispatcher(self): - self.obj.representationFactories = dict( - test=dict( - factory=_representationTestFactory, - destructiveNotifications=["BaseObject.Changed"])) - self.assertEqual(self.obj.getRepresentation("test"), "()") - self.assertEqual( - [], - [] - ) class TestBaseDictObject(BaseDictObject): diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_contour.py defcon-0.3.5/Lib/defcon/test/objects/test_contour.py --- defcon-0.7.2/Lib/defcon/test/objects/test_contour.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_contour.py 2017-10-02 10:54:57.000000000 +0000 @@ -377,25 +377,6 @@ contour.identifier = None self.assertEqual(contour.identifier, "contour 2") self.assertEqual(sorted(glyph.identifiers), ["contour 1", "contour 2"]) - - def test_correct_direction_same_area(self): - glyph = Glyph() - pen = glyph.getPointPen() - pen.beginPath() - pen.addPoint((0, 0), segmentType="line") - pen.addPoint((0, 50), segmentType="line") - pen.addPoint((50, 50), segmentType="line") - pen.endPath() - pen.beginPath() - pen.addPoint((50, 50), segmentType="line") - pen.addPoint((50, 100), segmentType="line") - pen.addPoint((100, 100), segmentType="line") - pen.endPath() - try: - glyph.correctContourDirection() - except Exception as e: - self.fail("glyph.correctContourDirection() raised unexpected exception: " - + str(e)) if __name__ == "__main__": unittest.main() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_dataSet.py defcon-0.3.5/Lib/defcon/test/objects/test_dataSet.py --- defcon-0.7.2/Lib/defcon/test/objects/test_dataSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_dataSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,15 +1,11 @@ import unittest import os import shutil -import fs -import fs.copy -import fs.path from defcon import Font from defcon.test.testTools import ( getTestFontPath, getTestFontCopyPath, makeTestFontCopy, - openTestFontAsFileSystem, closeTestFontAsFileSystem, tearDownTestFontCopy) -from fontTools.ufoLib import UFOReader +from ufoLib import UFOReader class DataSetTest(unittest.TestCase): @@ -26,18 +22,23 @@ path = getTestFontPath() font = Font(path) fileNames = [ - "com.typesupply.defcon.test.directory/file 1.txt", - "com.typesupply.defcon.test.directory/sub directory/file 2.txt", + os.path.join("com.typesupply.defcon.test.directory", "file 1.txt"), + os.path.join("com.typesupply.defcon.test.directory", + "sub directory", "file 2.txt"), "com.typesupply.defcon.test.file"] for i, fileName in enumerate(sorted(font.data.fileNames)): if True in [j.startswith(".") for j in fileName.split(os.sep)]: continue self.assertEqual(fileName, fileNames[i]) self.assertEqual( - font.data["com.typesupply.defcon.test.directory/file 1.txt"], + font.data[ + os.path.join("com.typesupply.defcon.test.directory", + "file 1.txt")], b"This is file 1.") self.assertEqual( - font.data["com.typesupply.defcon.test.directory/sub directory/file 2.txt"], + font.data[ + os.path.join("com.typesupply.defcon.test.directory", + "sub directory", "file 2.txt")], b"This is file 2.") self.assertEqual( font.data["com.typesupply.defcon.test.file"], @@ -45,137 +46,127 @@ def test_write(self): path = makeTestFontCopy() - with Font(path) as font: - font.data["com.typesupply.defcon.test.newdirectory/file.txt"] = b"hello." - del font.data["com.typesupply.defcon.test.directory/sub directory/file 2.txt"] - font.save() - p = os.path.join(path, "data", - "com.typesupply.defcon.test.newdirectory", "file.txt") - self.assertTrue(os.path.exists(p)) - with open(p, "r") as f: - t = f.read() - self.assertEqual(t, "hello.") - p = os.path.join(path, "data", - "com.typesupply.defcon.test.directory", - "sub directory", "file 2.txt") - self.assertFalse(os.path.exists(p)) + font = Font(path) + font.data[ + os.path.join("com.typesupply.defcon.test.newdirectory", + "file.txt")] = b"hello." + del font.data[ + os.path.join("com.typesupply.defcon.test.directory", + "sub directory", "file 2.txt")] + font.save() + p = os.path.join(path, "data", + "com.typesupply.defcon.test.newdirectory", "file.txt") + self.assertTrue(os.path.exists(p)) + with open(p, "r") as f: + t = f.read() + self.assertEqual(t, "hello.") + p = os.path.join(path, "data", + "com.typesupply.defcon.test.directory", + "sub directory", "file 2.txt") + self.assertFalse(os.path.exists(p)) tearDownTestFontCopy() def test_save_as(self): path = getTestFontPath() - with Font(path) as font: - saveAsPath = getTestFontCopyPath(path) - font.save(saveAsPath) - dataDirectory = os.path.join(saveAsPath, "data") - self.assertTrue(os.path.exists(dataDirectory)) - self.assertTrue(os.path.exists(os.path.join( - dataDirectory, - os.path.join("com.typesupply.defcon.test.directory", - "file 1.txt")))) - self.assertTrue(os.path.exists(os.path.join( - dataDirectory, - os.path.join("com.typesupply.defcon.test.directory", - "sub directory", "file 2.txt")))) - self.assertTrue(os.path.exists(os.path.join( - dataDirectory, - "com.typesupply.defcon.test.file"))) + font = Font(path) + saveAsPath = getTestFontCopyPath(path) + font.save(saveAsPath) + dataDirectory = os.path.join(saveAsPath, "data") + self.assertTrue(os.path.exists(dataDirectory)) + self.assertTrue(os.path.exists(os.path.join( + dataDirectory, + os.path.join("com.typesupply.defcon.test.directory", + "file 1.txt")))) + self.assertTrue(os.path.exists(os.path.join( + dataDirectory, + os.path.join("com.typesupply.defcon.test.directory", + "sub directory", "file 2.txt")))) + self.assertTrue(os.path.exists(os.path.join( + dataDirectory, + "com.typesupply.defcon.test.file"))) tearDownTestFontCopy(saveAsPath) def test_testForExternalChanges_remove_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - del font.data["com.typesupply.defcon.test.file"] - with UFOReader(path) as reader: - self.assertEqual(font.data.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + del font.data["com.typesupply.defcon.test.file"] + reader = UFOReader(path) + self.assertEqual(font.data.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testForExternalChanges_add_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - font.data["com.typesupply.defcon.test.file2"] = "blah" - with UFOReader(path) as reader: - self.assertEqual(font.data.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + font.data["com.typesupply.defcon.test.file2"] = "blah" + reader = UFOReader(path) + self.assertEqual(font.data.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testForExternalChanges_modify_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - with UFOReader(path) as reader: - font.data["com.typesupply.defcon.test.file"] = "blah" - self.assertEqual(font.data.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + reader = UFOReader(path) + font.data["com.typesupply.defcon.test.file"] = "blah" + self.assertEqual(font.data.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testForExternalChanges_remove_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - # image = font.data["com.typesupply.defcon.test.file"] - font.data["com.typesupply.defcon.test.file"] - fileSystem = openTestFontAsFileSystem(font.path) - fileSystem.remove(fs.path.join("data", - "com.typesupply.defcon.test.file")) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.data.testForExternalChanges(reader), - ([], [], ["com.typesupply.defcon.test.file"])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + reader = UFOReader(path) + # image = font.data["com.typesupply.defcon.test.file"] + font.data["com.typesupply.defcon.test.file"] + os.remove(os.path.join(path, "data", + "com.typesupply.defcon.test.file")) + self.assertEqual(font.data.testForExternalChanges(reader), + ([], [], ["com.typesupply.defcon.test.file"])) + tearDownTestFontCopy() def test_testForExternalChanges_add_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(font.path) - source = fs.path.join("data", "com.typesupply.defcon.test.file") - dest = fs.path.join("data", "com.typesupply.defcon.test.file2") - fileSystem.copy(source, dest) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.data.testForExternalChanges(reader), - ([], ["com.typesupply.defcon.test.file2"], [])) - tearDownTestFontCopy(font.path) + import shutil + path = makeTestFontCopy() + font = Font(path) + reader = UFOReader(path) + source = os.path.join(path, "data", "com.typesupply.defcon.test.file") + dest = os.path.join(path, "data", "com.typesupply.defcon.test.file2") + shutil.copy(source, dest) + self.assertEqual(font.data.testForExternalChanges(reader), + ([], ["com.typesupply.defcon.test.file2"], [])) + tearDownTestFontCopy() def test_testForExternalChanges_modify_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - # d = font.data["com.typesupply.defcon.test.file"] - font.data["com.typesupply.defcon.test.file"] - fileSystem = openTestFontAsFileSystem(font.path) - filePath = fs.path.join("data", - "com.typesupply.defcon.test.file") - fileSystem.writebytes(filePath, b"blah") - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.data.testForExternalChanges(reader), - (["com.typesupply.defcon.test.file"], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + reader = UFOReader(path) + # d = font.data["com.typesupply.defcon.test.file"] + font.data["com.typesupply.defcon.test.file"] + filePath = os.path.join(path, "data", + "com.typesupply.defcon.test.file") + f = open(filePath, "wb") + f.write(b"blah") + f.close() + reader = UFOReader(path) + self.assertEqual(font.data.testForExternalChanges(reader), + (["com.typesupply.defcon.test.file"], [], [])) + tearDownTestFontCopy() def test_reload_data(self): path = makeTestFontCopy() - with Font(path) as font: - # d = font.data["com.typesupply.defcon.test.file"] - font.data["com.typesupply.defcon.test.file"] - filePath = os.path.join(path, "data", - "com.typesupply.defcon.test.file") - newData = b"blah" - f = open(filePath, "wb") - f.write(newData) - f.close() - font.data.reloadData(["com.typesupply.defcon.test.file"]) - data = font.data["com.typesupply.defcon.test.file"] - self.assertEqual(data, newData) + font = Font(path) + # d = font.data["com.typesupply.defcon.test.file"] + font.data["com.typesupply.defcon.test.file"] + filePath = os.path.join(path, "data", + "com.typesupply.defcon.test.file") + newData = b"blah" + f = open(filePath, "wb") + f.write(newData) + f.close() + font.data.reloadData(["com.typesupply.defcon.test.file"]) + data = font.data["com.typesupply.defcon.test.file"] + self.assertEqual(data, newData) tearDownTestFontCopy() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_font.py defcon-0.3.5/Lib/defcon/test/objects/test_font.py --- defcon-0.7.2/Lib/defcon/test/objects/test_font.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_font.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,22 +1,11 @@ import unittest import os import glob -import tempfile -import shutil -import fs -import fs.copy -import fs.path from defcon import Font, Glyph, LayerSet, Guideline -from defcon.errors import DefconError from defcon.tools.notifications import NotificationCenter from defcon.test.testTools import ( getTestFontPath, getTestFontCopyPath, makeTestFontCopy, - openTestFontAsFileSystem, closeTestFontAsFileSystem, tearDownTestFontCopy) -from fontTools.ufoLib import UFOReader, UFOWriter, UFOFileStructure -import zipfile -import logging -from fontTools.misc.loggingTools import CapturingLogHandler try: from plistlib import load, dump @@ -47,10 +36,6 @@ def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) - # Python 3 renamed assertRaisesRegexp to assertRaisesRegex, - # and fires deprecation warnings if a program uses the old name. - if not hasattr(self, "assertRaisesRegex"): - self.assertRaisesRegex = self.assertRaisesRegexp def tearDown(self): if os.path.exists(getTestFontCopyPath()): @@ -118,55 +103,46 @@ self.assertEqual(sorted(fileNames), ["B_.glif", "C_.glif"]) with self.assertRaises(KeyError): del font["NotInFont"] + tearDownTestFontCopy() def test_delitem_glyph_not_dirty(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - font["A"] # glyph = font["A"] - fileSystem = openTestFontAsFileSystem(path) - glyphPath = fs.path.join("glyphs", "A_.glif") - fileSystem.remove(glyphPath) - contentsPath = fs.path.join("glyphs", "contents.plist") - with fileSystem.open(contentsPath, "rb") as f: - plist = load(f) - del plist["A"] - with fileSystem.open(contentsPath, "wb") as f: - dump(plist, f) - closeTestFontAsFileSystem(fileSystem, path) - r = font.testForExternalChanges() - self.assertEqual(r["deletedGlyphs"], ["A"]) - del font["A"] - font.save() - self.assertFalse(os.path.exists(glyphPath)) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + font["A"] # glyph = font["A"] + glyphPath = os.path.join(path, "glyphs", "A_.glif") + os.remove(glyphPath) + contentsPath = os.path.join(path, "glyphs", "contents.plist") + with open(contentsPath, "rb") as f: + plist = load(f) + del plist["A"] + with open(contentsPath, "wb") as f: + dump(plist, f) + r = font.testForExternalChanges() + self.assertEqual(r["deletedGlyphs"], ["A"]) + del font["A"] + font.save() + self.assertFalse(os.path.exists(glyphPath)) + tearDownTestFontCopy() def test_delitem_glyph_dirty(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - glyph = font["A"] - glyph.dirty = True - fileSystem = openTestFontAsFileSystem(path) - glyphPath = fs.path.join("glyphs", "A_.glif") - fileSystem.remove(glyphPath) - contentsPath = fs.path.join("glyphs", "contents.plist") - with fileSystem.open(contentsPath, "rb") as f: - plist = load(f) - del plist["A"] - with fileSystem.open(contentsPath, "wb") as f: - dump(plist, f) - closeTestFontAsFileSystem(fileSystem, path) - r = font.testForExternalChanges() - self.assertEqual(r["deletedGlyphs"], ["A"]) - del font["A"] - font.save() - fileSystem = openTestFontAsFileSystem(path) - self.assertFalse(fileSystem.exists(glyphPath)) - closeTestFontAsFileSystem(fileSystem, path) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + glyph = font["A"] + glyph.dirty = True + glyphPath = os.path.join(path, "glyphs", "A_.glif") + os.remove(glyphPath) + contentsPath = os.path.join(path, "glyphs", "contents.plist") + with open(contentsPath, "rb") as f: + plist = load(f) + del plist["A"] + with open(contentsPath, "wb") as f: + dump(plist, f) + r = font.testForExternalChanges() + self.assertEqual(r["deletedGlyphs"], ["A"]) + del font["A"] + font.save() + self.assertFalse(os.path.exists(glyphPath)) + tearDownTestFontCopy() def test_len(self): font = Font(getTestFontPath()) @@ -201,6 +177,7 @@ self.assertIsNone(font.path) def test_path_set(self): + import shutil path1 = getTestFontPath() font = Font(path1) path2 = getTestFontPath("setPathTest.ufo") @@ -418,209 +395,73 @@ self.assertEqual(font.guidelines, []) def test_save(self): - for ufo in (u"TestFont.ufo", u"TestFont.ufoz"): - path = makeTestFontCopy(getTestFontPath(ufo)) - try: - with Font(path) as font: - origFileStructure = font.ufoFileStructure - for glyph in font: - glyph.dirty = True - font.save() - fileNames = sorted( - [ - fs.path.basename(m.path) - for m in UFOReader(path).fs.glob("glyphs/*.glif") - ] - ) - self.assertEqual(fileNames, ["A_.glif", "B_.glif", "C_.glif"]) - self.assertEqual(origFileStructure, font.ufoFileStructure) - finally: - tearDownTestFontCopy(path) + path = makeTestFontCopy() + font = Font(path) + for glyph in font: + glyph.dirty = True + font.save() + fileNames = glob.glob(os.path.join(path, 'glyphs', '*.glif')) + fileNames = [os.path.basename(fileName) for fileName in fileNames] + self.assertEqual(sorted(fileNames), ["A_.glif", "B_.glif", "C_.glif"]) + tearDownTestFontCopy() def test_save_as(self): - for ufo in (u"TestFont.ufo", u"TestFont.ufoz"): - path = getTestFontPath(ufo) - font = Font(path) - origFileStructure = font.ufoFileStructure - saveAsPath = getTestFontCopyPath(path) - self.assertFalse(os.path.exists(saveAsPath)) - font.save(saveAsPath) - try: - fileNames = sorted( - [ - fs.path.basename(m.path) - for m in UFOReader(saveAsPath).fs.glob("glyphs/*.glif") - ] - ) - self.assertEqual(fileNames, ["A_.glif", "B_.glif", "C_.glif"]) - self.assertEqual(font.path, saveAsPath) - self.assertEqual(origFileStructure, font.ufoFileStructure) - finally: - font.close() - tearDownTestFontCopy(saveAsPath) - - def test_save_same_path(self): - for ufo in (u"TestFont.ufo", u"TestFont.ufoz"): - path = makeTestFontCopy(getTestFontPath(ufo)) - isZip = zipfile.is_zipfile(path) - font = Font(path) - try: - font = Font(path) - font.save(path) - if isZip: - self.assertTrue(zipfile.is_zipfile(path)) - else: - self.assertTrue(os.path.isdir(path)) - finally: - font.close() - tearDownTestFontCopy(path) - - def test_save_same_path_different_structure(self): - for ufo in ("TestFont.ufo", "TestFont.ufoz"): - path = makeTestFontCopy(getTestFontPath(ufo)) - isZip = zipfile.is_zipfile(path) - with Font(path) as font: - with self.assertRaisesRegex( - DefconError, - "Can't save font in-place with a different structure" - ): - font.save(path, structure="package" if isZip else "zip") - tearDownTestFontCopy(path) - - def test_save_new_font_without_path(self): - font = Font() - msg = "Can't save new font without a 'path'" - with self.assertRaisesRegex(DefconError, msg): - font.save() - - def test_save_new_font_to_exsisting_directory(self): - for ufo in ("TestFont.ufo", "TestFont.ufoz"): - path = makeTestFontCopy(getTestFontPath(ufo)) - font = Font() - try: - self.assertTrue(os.path.exists(path)) - font.save(path) - self.assertTrue(os.path.isdir(path)) - finally: - font.close() - tearDownTestFontCopy(path) - - def test_save_ufoz(self): path = getTestFontPath() - tmpdir = tempfile.mkdtemp() - dest = os.path.join(tmpdir, "TestFont.ufoz") font = Font(path) - try: - self.assertFalse(os.path.exists(dest)) - self.assertEqual(font.path, path) - font.save(dest, structure="zip") - self.assertTrue(os.path.exists(dest)) - self.assertTrue(zipfile.is_zipfile(dest)) - self.assertEqual(font.path, dest) - self.assertEqual(font.ufoFileStructure, UFOFileStructure.ZIP) - fileNames = sorted( - [ - fs.path.basename(m.path) - for m in UFOReader(dest).fs.glob("glyphs/*.glif") - ] - ) - self.assertEqual(fileNames, ["A_.glif", "B_.glif", "C_.glif"]) - finally: - font.close() - shutil.rmtree(tmpdir) - - def test_save_new_font_to_existing_file(self): - with tempfile.NamedTemporaryFile(delete=False) as tmp: - pass - path = tmp.name - self.assertTrue(os.path.exists(path)) - try: - font = Font() - font.save(path) - self.assertTrue(os.path.isdir(path)) - finally: - if os.path.isfile(path): - os.remove(path) - elif os.path.isdir(path): - shutil.rmtree(path) - - def test_new_font_format(self): - font = Font() - self.assertEqual(font.ufoFormatVersion, None) - self.assertEqual(font.ufoFormatVersionTuple, None) + saveAsPath = getTestFontCopyPath(path) + font.save(saveAsPath) + fileNames = glob.glob(os.path.join(saveAsPath, 'glyphs', '*.glif')) + fileNames = [os.path.basename(fileName) for fileName in fileNames] + self.assertEqual(sorted(fileNames), ["A_.glif", "B_.glif", "C_.glif"]) + self.assertEqual(font.path, saveAsPath) + tearDownTestFontCopy(saveAsPath) - def test_save_in_place_different_format(self): - path = makeTestFontCopy() + def test_testForExternalChanges(self): + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) - self.assertEqual(font.ufoFormatVersion, 3) - self.assertEqual(font.ufoFormatVersionTuple, (3, 0)) - font.save(formatVersion=2) - self.assertEqual(font.ufoFormatVersion, 2) - self.assertEqual(font.ufoFormatVersionTuple, (2, 0)) - def test_save_in_place_invalid_ufo(self): - path = makeTestFontCopy() - font = Font(path) - layercontents = os.path.join(path, "layercontents.plist") - os.remove(layercontents) - self.assertFalse(os.path.exists(layercontents)) - - logger = logging.getLogger("defcon.objects.font") - with CapturingLogHandler(logger, level="ERROR") as captor: - font.save() - captor.assertRegex("Invalid ufo found") + # load all the objects so that they get stamped + font.info # i = font.info + k = font.kerning + font.groups # g = font.groups + font.lib # l = font.lib + font["A"] # g = font["A"] + + d = font.testForExternalChanges() + self.assertFalse(d["info"]) + self.assertFalse(d["kerning"]) + self.assertFalse(d["groups"]) + self.assertFalse(d["lib"]) - self.assertTrue(os.path.exists(layercontents)) - font = Font(path) - _ = font.layers - font.save() + # make a simple change to the kerning data + path = os.path.join(font.path, "kerning.plist") + f = open(path, "r") + t = f.read() + f.close() + t += " " + f = open(path, "w") + f.write(t) + f.close() + os.utime(path, + (k._dataOnDiskTimeStamp + 1, k._dataOnDiskTimeStamp + 1)) - def test_testForExternalChanges(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - # load all the objects so that they get stamped - font.info # i = font.info - k = font.kerning - font.groups # g = font.groups - font.lib # l = font.lib - font["A"] # g = font["A"] - - d = font.testForExternalChanges() - self.assertFalse(d["info"]) - self.assertFalse(d["kerning"]) - self.assertFalse(d["groups"]) - self.assertFalse(d["lib"]) - - # make a simple change to the kerning data - fileSystem = openTestFontAsFileSystem(font.path) - path = u"kerning.plist" - t = fileSystem.readbytes(path) - t += b"" - fileSystem.writebytes(path, t) - k._dataOnDiskTimeStamp -= 1 - closeTestFontAsFileSystem(fileSystem, font.path) - - d = font.testForExternalChanges() - self.assertTrue(d["kerning"]) - self.assertFalse(d["groups"]) - self.assertFalse(d["info"]) - self.assertFalse(d["lib"]) - - # save the kerning data and test again - font.kerning.dirty = True - font.save() - d = font.testForExternalChanges() - self.assertFalse(d["kerning"]) - self.assertFalse(d["groups"]) - self.assertFalse(d["info"]) - self.assertFalse(d["lib"]) + d = font.testForExternalChanges() + self.assertTrue(d["kerning"]) + self.assertFalse(d["groups"]) + self.assertFalse(d["info"]) + self.assertFalse(d["lib"]) - tearDownTestFontCopy(font.path) + # save the kerning data and test again + font.kerning.dirty = True + font.save() + d = font.testForExternalChanges() + self.assertFalse(d["kerning"]) + self.assertFalse(d["groups"]) + self.assertFalse(d["info"]) + self.assertFalse(d["lib"]) def test_reloadInfo(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) info = font.info @@ -643,7 +484,7 @@ f.close() def test_reloadKerning(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) kerning = font.kerning @@ -666,7 +507,7 @@ f.close() def test_reloadGroups(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) groups = font.groups @@ -689,7 +530,7 @@ f.close() def test_reloadLib(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) lib = font.lib @@ -714,7 +555,7 @@ f.close() def test_reloadGlyphs(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") font = Font(path) glyph = font["A"] diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_glyph.py defcon-0.3.5/Lib/defcon/test/objects/test_glyph.py --- defcon-0.7.2/Lib/defcon/test/objects/test_glyph.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_glyph.py 2017-10-02 10:54:57.000000000 +0000 @@ -101,20 +101,6 @@ self.assertEqual(glyph.unicodes, [123, 456]) self.assertTrue(glyph.dirty) - def test_unicode_get(self): - font = Font(getTestFontPath()) - glyph = font["A"] - self.assertEqual(glyph.unicode, 65) - - def test_unicode_set(self): - font = Font(getTestFontPath()) - glyph = font["A"] - glyph.unicode = 123 - self.assertEqual(glyph.unicodes, [123]) - glyph.unicode = 456 - self.assertEqual(glyph.unicodes, [456]) - self.assertTrue(glyph.dirty) - def test_bounds(self): font = Font(getTestFontPath()) glyph = font["A"] @@ -609,25 +595,6 @@ self.assertFalse(glyph.pointInside((350, 350))) self.assertFalse(glyph.pointInside((-100, -100))) - def test_area(self): - font = Font() - - baseGlyph = font.newGlyph("baseGlyph") - pointPen = baseGlyph.getPointPen() - pointPen.beginPath() - pointPen.addPoint((0, 0), "move") - pointPen.addPoint((0, 100), "line") - pointPen.addPoint((100, 100), "line") - pointPen.addPoint((100, 0), "line") - pointPen.addPoint((0, 0), "line") - pointPen.endPath() - self.assertEqual(baseGlyph.area, 10000) - - componentGlyph = font.newGlyph("componentGlyph") - pointPen = componentGlyph.getPointPen() - pointPen.addComponent("baseGlyph", [1, 0, 0, 1, 0, 0]) - self.assertEqual(componentGlyph.area, 10000) - if __name__ == "__main__": unittest.main() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_groups.py defcon-0.3.5/Lib/defcon/test/objects/test_groups.py --- defcon-0.7.2/Lib/defcon/test/objects/test_groups.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_groups.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -import unittest -from defcon import Font - - -class GroupsTest(unittest.TestCase): - - def __init__(self, methodName): - unittest.TestCase.__init__(self, methodName) - - def test_side1KerningGroups(self): - font = Font() - groups = font.groups - groups["a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningSide1Groups") - self.assertEqual(result, {}) - groups["public.kern1.a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningSide1Groups") - self.assertEqual(result, {"public.kern1.a" : ["a"]}) - groups["public.kern1.a"] = ["b"] - result = groups.getRepresentation("defcon.groups.kerningSide1Groups") - self.assertEqual(result, {"public.kern1.a" : ["b"]}) - groups["public.kern2.a"] = ["b"] - result = groups.getRepresentation("defcon.groups.kerningSide1Groups") - self.assertEqual(result, {"public.kern1.a" : ["b"]}) - - def test_side2KerningGroups(self): - font = Font() - groups = font.groups - groups["a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningSide2Groups") - self.assertEqual(result, {}) - groups["public.kern2.a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningSide2Groups") - self.assertEqual(result, {"public.kern2.a" : ["a"]}) - groups["public.kern2.a"] = ["b"] - result = groups.getRepresentation("defcon.groups.kerningSide2Groups") - self.assertEqual(result, {"public.kern2.a" : ["b"]}) - groups["public.kern1.a"] = ["b"] - result = groups.getRepresentation("defcon.groups.kerningSide2Groups") - self.assertEqual(result, {"public.kern2.a" : ["b"]}) - - def test_side1glyphToKerningGroups(self): - font = Font() - groups = font.groups - groups["public.kern1.a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningGlyphToSide1Group") - self.assertEqual(result, {'a': 'public.kern1.a'}) - del groups["public.kern1.a"] - groups["public.kern1.b"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningGlyphToSide1Group") - self.assertEqual(result, {'a': 'public.kern1.b'}) - - def test_side2glyphToKerningGroups(self): - font = Font() - groups = font.groups - groups["public.kern2.a"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningGlyphToSide2Group") - self.assertEqual(result, {'a': 'public.kern2.a'}) - del groups["public.kern2.a"] - groups["public.kern2.b"] = ["a"] - result = groups.getRepresentation("defcon.groups.kerningGlyphToSide2Group") - self.assertEqual(result, {'a': 'public.kern2.b'}) - -if __name__ == "__main__": - unittest.main() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_imageSet.py defcon-0.3.5/Lib/defcon/test/objects/test_imageSet.py --- defcon-0.7.2/Lib/defcon/test/objects/test_imageSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_imageSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,15 +1,11 @@ from __future__ import unicode_literals import unittest import os -import fs -import fs.copy -import fs.path -from fontTools.ufoLib import UFOReader +from ufoLib import UFOReader from defcon import Font from defcon.objects.imageSet import fileNameValidator from defcon.test.testTools import ( getTestFontPath, getTestFontCopyPath, makeTestFontCopy, - openTestFontAsFileSystem, closeTestFontAsFileSystem, tearDownTestFontCopy) pngSignature = b"\x89PNG\r\n\x1a\n" @@ -98,78 +94,68 @@ self.assertEqual(font.images.findDuplicateImage(data), "image 2.png") def test_testExternalChanges_remove_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font, UFOReader(path) as reader: - del font.images["image 1.png"] - self.assertEqual(font.images.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + del font.images["image 1.png"] + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testExternalChanges_add_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font, UFOReader(path) as reader: - font.images["image 3.png"] = pngSignature + b"blah" - self.assertEqual(font.images.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + font.images["image 3.png"] = pngSignature + b"blah" + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testExternalChanges_modify_in_memory_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font, UFOReader(path) as reader: - font.images["image 1.png"] = pngSignature + b"blah" - self.assertEqual(font.images.testForExternalChanges(reader), - ([], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + font.images["image 1.png"] = pngSignature + b"blah" + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + ([], [], [])) + tearDownTestFontCopy() def test_testExternalChanges_remove_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(font.path) - fileSystem.remove(fs.path.join("images", "image 1.png")) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.images.testForExternalChanges(reader), - ([], [], ["image 1.png"])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + os.remove(os.path.join(path, "images", "image 1.png")) + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + ([], [], ["image 1.png"])) + tearDownTestFontCopy() def test_testExternalChanges_add_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(font.path) - source = fs.path.join("images", "image 1.png") - dest = fs.path.join("images", "image 3.png") - fileSystem.copy(source, dest) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.images.testForExternalChanges(reader), - ([], ["image 3.png"], [])) - tearDownTestFontCopy(font.path) + import shutil + path = makeTestFontCopy() + font = Font(path) + source = os.path.join(path, "images", "image 1.png") + dest = os.path.join(path, "images", "image 3.png") + shutil.copy(source, dest) + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + ([], ["image 3.png"], [])) + tearDownTestFontCopy() def test_testExternalChanges_modify_on_disk_and_scan(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - font.images["image 1.png"] # image = font.images["image 1.png"] - fileSystem = openTestFontAsFileSystem(font.path) - imagePath = fs.path.join("images", "image 1.png") - data = fileSystem.readbytes(imagePath) - fileSystem.writebytes(imagePath, data + b"blah") - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(path) as reader: - self.assertEqual(font.images.testForExternalChanges(reader), - (["image 1.png"], [], [])) - tearDownTestFontCopy(font.path) + path = makeTestFontCopy() + font = Font(path) + font.images["image 1.png"] # image = font.images["image 1.png"] + imagePath = os.path.join(path, "images", "image 1.png") + f = open(imagePath, "rb") + data = f.read() + f.close() + f = open(imagePath, "wb") + f.write(data + b"blah") + f.close() + reader = UFOReader(path) + self.assertEqual(font.images.testForExternalChanges(reader), + (["image 1.png"], [], [])) + tearDownTestFontCopy() def test_reloadImages(self): path = makeTestFontCopy() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_kerning.py defcon-0.3.5/Lib/defcon/test/objects/test_kerning.py --- defcon-0.7.2/Lib/defcon/test/objects/test_kerning.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_kerning.py 2017-10-02 10:54:57.000000000 +0000 @@ -62,16 +62,6 @@ [("A", "A"), ("A", "B"), ("X", "X")]) self.assertTrue(font.kerning.dirty) - def test_find(self): - font = Font() - font.groups["public.kern1.A"] = ["A", "A.alt"] - font.groups["public.kern2.C"] = ["C", "C.alt"] - font.kerning["public.kern1.A", "public.kern2.C"] = 1 - font.kerning["public.kern1.A", "C.alt"] = 2 - font.kerning["A.alt", "C.alt"] = 3 - self.assertEqual(font.kerning.find(("A", "C")), 1) - self.assertEqual(font.kerning.find(("A", "C.alt")), 2) - self.assertEqual(font.kerning.find(("A.alt", "C.alt")), 3) if __name__ == "__main__": unittest.main() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_layer.py defcon-0.3.5/Lib/defcon/test/objects/test_layer.py --- defcon-0.7.2/Lib/defcon/test/objects/test_layer.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_layer.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,14 +1,9 @@ import unittest import glob import os -import fs -import fs.copy -import fs.path -from fontTools.ufoLib import UFOReader, UFOFileStructure from defcon import Font, Glyph, Color, Component, Anchor, Guideline from defcon.test.testTools import ( getTestFontPath, makeTestFontCopy, getTestFontCopyPath, - openTestFontAsFileSystem, closeTestFontAsFileSystem, tearDownTestFontCopy) try: @@ -176,72 +171,68 @@ self.assertTrue(layer.lib.dirty) def test_testForExternalChanges(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - try: - with Font(path) as font: - - with UFOReader(font.path) as reader: - self.assertEqual(font.layers[None].testForExternalChanges(reader), - ([], [], [])) - - # make a simple change to a glyph - fileSystem = openTestFontAsFileSystem(font.path) - g = font.layers[None]["A"] - path = fs.path.join("glyphs", "A_.glif") - t = fileSystem.readbytes(path) - t += b"" - fileSystem.writebytes(path, t) - g._dataOnDiskTimeStamp -= 1 - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(font.path) as reader: - self.assertEqual(font.layers[None].testForExternalChanges(reader), - (["A"], [], [])) - - # save the glyph and test again - font["A"].dirty = True - font.save() - with UFOReader(font.path) as reader: - self.assertEqual(font.layers[None].testForExternalChanges(reader), - ([], [], [])) - - # add a glyph - fileSystem = openTestFontAsFileSystem(font.path) - path = fs.path.join("glyphs", "A_.glif") - t = fileSystem.readbytes(path) - t = t.replace(b'', - b'') - path = fs.path.join("glyphs", "XYZ.glif") - fileSystem.writebytes(path, t) - path = fs.path.join("glyphs", "contents.plist") - with fileSystem.open(path, "rb") as f: - plist = load(f) - savePlist = dict(plist) - plist["XYZ"] = "XYZ.glif" - with fileSystem.open(path, "wb") as f: - dump(plist, f) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(font.path) as reader: - self.assertEqual(font.layers[None].testForExternalChanges(reader), - ([], ["XYZ"], [])) - path = font.path - - # delete a glyph - with Font(path) as font: - g = font["XYZ"] - fileSystem = openTestFontAsFileSystem(font.path) - path = fs.path.join("glyphs", "contents.plist") - with fileSystem.open(path, "wb") as f: - dump(savePlist, f) - path = fs.path.join("glyphs", "XYZ.glif") - fileSystem.remove(path) - closeTestFontAsFileSystem(fileSystem, font.path) - with UFOReader(font.path) as reader: - self.assertEqual(font.layers[None].testForExternalChanges(reader), - ([], [], ["XYZ"])) - finally: - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + font = Font(path) + + self.assertEqual(font.layers[None].testForExternalChanges(), + ([], [], [])) + + # make a simple change to a glyph + g = font.layers[None]["A"] + path = os.path.join(font.path, "glyphs", "A_.glif") + f = open(path, "r") + t = f.read() + f.close() + t += " " + f = open(path, "w") + f.write(t) + f.close() + os.utime(path, + (g._dataOnDiskTimeStamp + 1, g._dataOnDiskTimeStamp + 1)) + self.assertEqual(font.layers[None].testForExternalChanges(), + (["A"], [], [])) + + # save the glyph and test again + font["A"].dirty = True + font.save() + self.assertEqual(font.layers[None].testForExternalChanges(), + ([], [], [])) + + # add a glyph + path = os.path.join(font.path, "glyphs", "A_.glif") + f = open(path, "r") + t = f.read() + f.close() + t = t.replace('', + '') + path = os.path.join(font.path, "glyphs", "XYZ.glif") + f = open(path, "w") + f.write(t) + f.close() + path = os.path.join(font.path, "glyphs", "contents.plist") + with open(path, "rb") as f: + plist = load(f) + savePlist = dict(plist) + plist["XYZ"] = "XYZ.glif" + with open(path, "wb") as f: + dump(plist, f) + self.assertEqual(font.layers[None].testForExternalChanges(), + ([], ["XYZ"], [])) + path = font.path + + # delete a glyph + font = Font(path) + g = font["XYZ"] + path = os.path.join(font.path, "glyphs", "contents.plist") + with open(path, "wb") as f: + dump(savePlist, f) + path = os.path.join(font.path, "glyphs", "XYZ.glif") + os.remove(path) + self.assertEqual(font.layers[None].testForExternalChanges(), + ([], [], ["XYZ"])) + + tearDownTestFontCopy(font.path) def test_reloadGlyphs(self): path = getTestFontPath("TestExternalEditing.ufo") @@ -408,44 +399,44 @@ with self.assertRaises(KeyError): del layer["NotInFont"] - # def test_delitem_glyph_not_dirty(self): - # path = self.path - # font = Font(path) - # layer = font.layers["public.default"] - # # glyph = layer["A"] - # glyphPath = os.path.join(path, "glyphs", "A_.glif") - # os.remove(glyphPath) - # contentsPath = os.path.join(path, "glyphs", "contents.plist") - # with open(contentsPath, "rb") as f: - # plist = load(f) - # del plist["A"] - # with open(contentsPath, "wb") as f: - # dump(plist, f) - # r = font.testForExternalChanges() - # self.assertEqual(r["deletedGlyphs"], ["A"]) - # del layer["A"] - # font.save() - # self.assertFalse(os.path.exists(glyphPath)) - - # def test_delitem_glyph_dirty(self): - # path = self.path - # font = Font(path) - # layer = font.layers["public.default"] - # glyph = layer["A"] - # glyph.dirty = True - # glyphPath = os.path.join(path, "glyphs", "A_.glif") - # os.remove(glyphPath) - # contentsPath = os.path.join(path, "glyphs", "contents.plist") - # with open(contentsPath, "rb") as f: - # plist = load(f) - # del plist["A"] - # with open(contentsPath, "wb") as f: - # dump(plist, f) - # r = font.testForExternalChanges() - # self.assertEqual(r["deletedGlyphs"], ["A"]) - # del layer["A"] - # font.save() - # self.assertFalse(os.path.exists(glyphPath)) + def test_delitem_glyph_not_dirty(self): + path = self.path + font = Font(path) + layer = font.layers["public.default"] + # glyph = layer["A"] + glyphPath = os.path.join(path, "glyphs", "A_.glif") + os.remove(glyphPath) + contentsPath = os.path.join(path, "glyphs", "contents.plist") + with open(contentsPath, "rb") as f: + plist = load(f) + del plist["A"] + with open(contentsPath, "wb") as f: + dump(plist, f) + r = font.testForExternalChanges() + self.assertEqual(r["deletedGlyphs"], ["A"]) + del layer["A"] + font.save() + self.assertFalse(os.path.exists(glyphPath)) + + def test_delitem_glyph_dirty(self): + path = self.path + font = Font(path) + layer = font.layers["public.default"] + glyph = layer["A"] + glyph.dirty = True + glyphPath = os.path.join(path, "glyphs", "A_.glif") + os.remove(glyphPath) + contentsPath = os.path.join(path, "glyphs", "contents.plist") + with open(contentsPath, "rb") as f: + plist = load(f) + del plist["A"] + with open(contentsPath, "wb") as f: + dump(plist, f) + r = font.testForExternalChanges() + self.assertEqual(r["deletedGlyphs"], ["A"]) + del layer["A"] + font.save() + self.assertFalse(os.path.exists(glyphPath)) if __name__ == "__main__": diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_layerSet.py defcon-0.3.5/Lib/defcon/test/objects/test_layerSet.py --- defcon-0.7.2/Lib/defcon/test/objects/test_layerSet.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_layerSet.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,18 +1,13 @@ import unittest import os import shutil -import fs -import fs.copy -from fontTools.ufoLib import UFOReader +from ufoLib import UFOReader from defcon import Font from defcon.test.testTools import ( - getTestFontPath, getTestFontCopyPath, makeTestFontCopy, - openTestFontAsFileSystem, closeTestFontAsFileSystem, - tearDownTestFontCopy) - + getTestFontPath, makeTestFontCopy, tearDownTestFontCopy) try: - from plistlib import load, dump, dumps + from plistlib import load, dump except ImportError: from plistlib import readPlist as load, writePlist as dump @@ -24,10 +19,6 @@ if not hasattr(self, "assertRaisesRegex"): self.assertRaisesRegex = self.assertRaisesRegexp - def tearDown(self): - if os.path.exists(getTestFontCopyPath()): - tearDownTestFontCopy() - def test_set_parent_data_in_layer(self): font = Font(getTestFontPath()) layers = font.layers @@ -99,147 +90,130 @@ font.save() self.assertFalse(os.path.exists(os.path.join(path, "A_.glif"))) self.assertTrue(os.path.exists(os.path.join(path, "B_.glif"))) + tearDownTestFontCopy() def test_len(self): - with Font(getTestFontPath()) as font: - layers = font.layers - self.assertEqual(len(layers), 3) + font = Font(getTestFontPath()) + layers = font.layers + self.assertEqual(len(layers), 3) font = Font() layers = font.layers self.assertEqual(len(layers), 1) def test_contains(self): - with Font(getTestFontPath()) as font: - layers = font.layers - self.assertIn("public.default", layers) - self.assertNotIn("NotInFont", layers) + font = Font(getTestFontPath()) + layers = font.layers + self.assertIn("public.default", layers) + self.assertNotIn("NotInFont", layers) def test_testForExternalChanges(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font, UFOReader(path) as reader: - self.assertEqual(font.layers.testForExternalChanges(reader), - {"deleted": [], "added": [], "modified": {}, - "defaultLayer": False, "order": False}) - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + font = Font(path) + reader = UFOReader(path) + self.assertEqual(font.layers.testForExternalChanges(reader), + {"deleted": [], "added": [], "modified": {}, + "defaultLayer": False, "order": False}) + tearDownTestFontCopy(font.path) def test_testForExternalChanges_layerinfo(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - # layerinfo.plist - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - data = {"lib": {}} - data["lib"]["testForExternalChanges.test"] = 1 - fileSystem = openTestFontAsFileSystem(path) - p = fs.path.join("glyphs", "layerinfo.plist") - with fileSystem.open(p, mode="wb") as f: - dump(data, f) - closeTestFontAsFileSystem(fileSystem, path) - with UFOReader(path) as reader: - self.assertTrue( - font.layers.testForExternalChanges(reader) - ["modified"]["public.default"]["info"]) - tearDownTestFontCopy(font.path) + # layerinfo.plist + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + font = Font(path) + reader = UFOReader(path) + p = os.path.join(path, "glyphs", "layerinfo.plist") + data = {"lib": {}} + data["lib"]["testForExternalChanges.test"] = 1 + with open(p, "wb") as f: + dump(data, f) + self.assertTrue( + font.layers.testForExternalChanges(reader) + ["modified"]["public.default"]["info"]) + tearDownTestFontCopy(font.path) def test_testForExternalChanges_add_a_layer(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(path) - fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test") - with fileSystem.open(u"layercontents.plist", "rb") as f: - contents = load(f) - contents.append(("test", "glyphs.test")) - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with UFOReader(path) as reader: - self.assertEqual(font.layers.testForExternalChanges(reader)["added"], - ["test"]) - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + font = Font(path) + shutil.copytree(os.path.join(path, "glyphs"), + os.path.join(path, "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "rb") as f: + contents = load(f) + contents.append(("test", "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + reader = UFOReader(path) + self.assertEqual(font.layers.testForExternalChanges(reader)["added"], + ["test"]) + tearDownTestFontCopy(font.path) def test_testForExternalChanges_remove_a_layer(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - fileSystem = openTestFontAsFileSystem(path) - fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test") - with fileSystem.open(u"layercontents.plist", "rb") as f: - contents = load(f) - contents.append(("test", "glyphs.test")) - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - font = Font(path) - with font: - fileSystem = openTestFontAsFileSystem(path) - fileSystem.removetree(u"glyphs.test") - with fileSystem.open(u"layercontents.plist", "rb") as f: - contents = load(f) - del contents[-1] - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with UFOReader(path) as reader: - self.assertEqual(font.layers.testForExternalChanges(reader)["deleted"], - ["test"]) - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + shutil.copytree(os.path.join(path, "glyphs"), + os.path.join(path, "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "rb") as f: + contents = load(f) + contents.append(("test", "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + font = Font(path) + shutil.rmtree(os.path.join(path, "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "rb") as f: + contents = load(f) + contents.pop(1) # n = contents.pop(1) + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + reader = UFOReader(path) + self.assertEqual(font.layers.testForExternalChanges(reader)["deleted"], + ["test"]) + tearDownTestFontCopy(font.path) def test_testForExternalChanges_change_layer_order(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - fileSystem = openTestFontAsFileSystem(path) - fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test") - with fileSystem.open(u"layercontents.plist", "rb") as f: - contents = load(f) - contents.append(("test", "glyphs.test")) - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(path) - with fileSystem.open(u"layercontents.plist", "rb") as f: - contents = load(f) - contents.reverse() - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with UFOReader(path) as reader: - self.assertEqual(font.layers.testForExternalChanges(reader), - {"deleted": [], "added": [], "modified": {}, - "defaultLayer": False, "order": True}) - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + shutil.copytree(os.path.join(path, "glyphs"), + os.path.join(path, "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "rb") as f: + contents = load(f) + contents.append(("test", "glyphs.test")) + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + font = Font(path) + with open(os.path.join(path, "layercontents.plist"), "rb") as f: + contents = load(f) + contents.reverse() + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + reader = UFOReader(path) + self.assertEqual(font.layers.testForExternalChanges(reader), + {"deleted": [], "added": [], "modified": {}, + "defaultLayer": False, "order": True}) + tearDownTestFontCopy(font.path) def test_testForExternalChanges_change_default_layer(self): - for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"): - path = getTestFontPath(ufo) - path = makeTestFontCopy(path) - - fileSystem = openTestFontAsFileSystem(path) - fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test") - contents = [("foo", "glyphs"), ("test", "glyphs.test")] - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with Font(path) as font: - fileSystem = openTestFontAsFileSystem(path) - contents = [("foo", "glyphs.test"), ("test", "glyphs")] - with fileSystem.open(u"layercontents.plist", "wb") as f: - dump(contents, f) - closeTestFontAsFileSystem(fileSystem, path) - with UFOReader(path) as reader: - self.assertEqual(font.layers.testForExternalChanges(reader), - {"deleted": [], "added": [], "modified": {}, - "defaultLayer": True, "order": False}) - tearDownTestFontCopy(font.path) + path = getTestFontPath("TestExternalEditing.ufo") + path = makeTestFontCopy(path) + shutil.copytree(os.path.join(path, "glyphs"), + os.path.join(path, "glyphs.test")) + contents = [("foo", "glyphs"), ("test", "glyphs.test")] + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + font = Font(path) + contents = [("test", "glyphs"), ("foo", "glyphs.test")] + contents.reverse() + with open(os.path.join(path, "layercontents.plist"), "wb") as f: + dump(contents, f) + reader = UFOReader(path) + self.assertEqual(font.layers.testForExternalChanges(reader), + {"deleted": [], "added": [], "modified": {}, + "defaultLayer": True, "order": False}) + tearDownTestFontCopy(font.path) def test_reloadLayers_layerinfo(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") path = makeTestFontCopy(path) font = Font(path) p = os.path.join(path, "glyphs", "layerinfo.plist") @@ -253,7 +227,7 @@ tearDownTestFontCopy(font.path) def test_reloadLayers_add_a_layer(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") path = makeTestFontCopy(path) font = Font(path) shutil.copytree(os.path.join(path, "glyphs"), @@ -268,7 +242,7 @@ tearDownTestFontCopy(font.path) def test_reloadLayers_change_layer_order(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") path = makeTestFontCopy(path) shutil.copytree(os.path.join(path, "glyphs"), os.path.join(path, "glyphs.test")) @@ -288,7 +262,7 @@ tearDownTestFontCopy(font.path) def test_reloadLayers_change_default_layer(self): - path = getTestFontPath(u"TestExternalEditing.ufo") + path = getTestFontPath("TestExternalEditing.ufo") path = makeTestFontCopy(path) shutil.copytree(os.path.join(path, "glyphs"), os.path.join(path, "glyphs.test")) @@ -338,15 +312,5 @@ ["public.default", "Name Change Test", "Layer 1"]) self.assertTrue(layer.dirty) - def test_rename_default_layer(self): - # https://github.com/unified-font-object/ufoLib/issues/123 - path = getTestFontCopyPath() - font = Font() - font.save(path) - font.layers.defaultLayer.name = "somethingElse" - font.save() - self.assertEqual(Font(path).layers.defaultLayer.name, "somethingElse") - - if __name__ == "__main__": unittest.main() diff -Nru defcon-0.7.2/Lib/defcon/test/objects/test_validation.py defcon-0.3.5/Lib/defcon/test/objects/test_validation.py --- defcon-0.7.2/Lib/defcon/test/objects/test_validation.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/objects/test_validation.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -import unittest -from defcon import Font, Info, Kerning, Groups -from defcon.objects.base import setUfoLibReadValidate, setUfoLibWriteValidate -from defcon.test.testTools import getTestFontPath - - -class UFOReadWriteValidateTest(unittest.TestCase): - - def __init__(self, methodName): - unittest.TestCase.__init__(self, methodName) - - def test_ufoLibReadValidate_defaults(self): - font = Font() - self.assertTrue(font.ufoLibReadValidate) - self.assertTrue(font.ufoLibWriteValidate) - self.assertTrue(font.info.ufoLibReadValidate) - self.assertTrue(font.info.ufoLibWriteValidate) - - def test_ufoLibReadValidate_settingDefaults(self): - setUfoLibReadValidate(False) - setUfoLibWriteValidate(False) - font = Font() - self.assertFalse(font.ufoLibReadValidate) - self.assertFalse(font.ufoLibWriteValidate) - self.assertFalse(font.info.ufoLibReadValidate) - self.assertFalse(font.info.ufoLibWriteValidate) - - setUfoLibReadValidate(False) - setUfoLibWriteValidate(True) - font = Font() - self.assertFalse(font.ufoLibReadValidate) - self.assertTrue(font.ufoLibWriteValidate) - self.assertFalse(font.info.ufoLibReadValidate) - self.assertTrue(font.info.ufoLibWriteValidate) - - setUfoLibReadValidate(True) - setUfoLibWriteValidate(False) - font = Font() - self.assertTrue(font.ufoLibReadValidate) - self.assertFalse(font.ufoLibWriteValidate) - self.assertTrue(font.info.ufoLibReadValidate) - self.assertFalse(font.info.ufoLibWriteValidate) - - def test_customClasses(self): - - class CustomInfo(Info): - - ufoLibReadValidate = False - ufoLibWriteValidate = False - - class CustomKerning(Kerning): - - ufoLibReadValidate = True - ufoLibWriteValidate = False - - font = Font(infoClass=CustomInfo, kerningClass=CustomKerning) - self.assertTrue(font.ufoLibReadValidate) - self.assertTrue(font.ufoLibWriteValidate) - self.assertFalse(font.info.ufoLibReadValidate) - self.assertFalse(font.info.ufoLibWriteValidate) - self.assertTrue(font.kerning.ufoLibReadValidate) - self.assertFalse(font.kerning.ufoLibWriteValidate) - - -if __name__ == "__main__": - unittest.main() diff -Nru "/tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/file 1.txt" "/tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/file 1.txt" --- "/tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/file 1.txt" 2020-05-29 10:55:00.000000000 +0000 +++ "/tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/file 1.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is file 1. \ No newline at end of file diff -Nru "/tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/sub directory/file 2.txt" "/tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/sub directory/file 2.txt" --- "/tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/sub directory/file 2.txt" 2020-05-29 10:55:00.000000000 +0000 +++ "/tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.directory/sub directory/file 2.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is file 2. \ No newline at end of file diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.file defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.file --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.file 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/data/com.typesupply.defcon.test.file 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -This is a top level test file. \ No newline at end of file diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/fontinfo.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/fontinfo.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/fontinfo.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/fontinfo.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,38 +1,38 @@ - + - - ascender - 750 - capHeight - 700 - descender - -250 - guidelines - - italicAngle - 0 - postscriptBlueValues - - postscriptFamilyBlues - - postscriptFamilyOtherBlues - - postscriptOtherBlues - - postscriptStemSnapH - - postscriptStemSnapV - - unitsPerEm - 1000 - versionMajor - 1 - versionMinor - 0 - xHeight - 500 - year - 0 - + + ascender + 750 + capHeight + 700 + descender + -250 + guidelines + + italicAngle + 0 + postscriptBlueValues + + postscriptFamilyBlues + + postscriptFamilyOtherBlues + + postscriptOtherBlues + + postscriptStemSnapH + + postscriptStemSnapV + + unitsPerEm + 1000 + versionMajor + 1 + versionMinor + 0 + xHeight + 500 + year + 0 + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/contents.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/contents.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/contents.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/contents.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,12 +1,12 @@ - + - - A - A_.glif - B - B_.glif - C - C_.glif - + + A + A_.glif + B + B_.glif + C + C_.glif + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/layerinfo.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/layerinfo.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/layerinfo.plist 1970-01-01 00:00:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/glyphs/layerinfo.plist 2017-10-02 10:54:57.000000000 +0000 @@ -0,0 +1,5 @@ + + + + + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/groups.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/groups.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/groups.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/groups.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,10 +1,10 @@ - + - - TestGroup - - A - - + + TestGroup + + A + + Binary files /tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/images/image 1.png and /tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/images/image 1.png differ Binary files /tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/images/image 2.png and /tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/images/image 2.png differ diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/kerning.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/kerning.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/kerning.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/kerning.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,11 +1,11 @@ - + - - A - - A - -100 - - + + A + + A + -100 + + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/layercontents.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/layercontents.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/layercontents.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/layercontents.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,10 +1,10 @@ - + - - - public.default - glyphs - - + + + public.default + glyphs + + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/lib.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/lib.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/lib.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/lib.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,12 +1,12 @@ - + - - org.robofab.glyphOrder - - A - B - C - - + + org.robofab.glyphOrder + + A + B + C + + diff -Nru defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/metainfo.plist defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/metainfo.plist --- defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufo/metainfo.plist 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufo/metainfo.plist 2017-10-02 10:54:57.000000000 +0000 @@ -1,10 +1,10 @@ - + - - creator - com.github.fonttools.ufoLib - formatVersion - 3 - + + creator + org.robofab.ufoLib + formatVersion + 3 + Binary files /tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestExternalEditing.ufoz and /tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestExternalEditing.ufoz differ Binary files /tmp/tmp7btw7r3g/2e9yfygsty/defcon-0.7.2/Lib/defcon/test/testdata/TestFont.ufoz and /tmp/tmp7btw7r3g/NgeRKre89L/defcon-0.3.5/Lib/defcon/test/testdata/TestFont.ufoz differ diff -Nru defcon-0.7.2/Lib/defcon/test/testTools.py defcon-0.3.5/Lib/defcon/test/testTools.py --- defcon-0.7.2/Lib/defcon/test/testTools.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/testTools.py 2017-10-02 10:54:57.000000000 +0000 @@ -2,11 +2,7 @@ import os import shutil from pkg_resources import resource_filename -import zipfile -import fs.osfs -import fs.tempfs -import fs.zipfs -import fs.copy + TESTDATA_DIR = resource_filename("defcon.test", 'testdata') @@ -19,57 +15,22 @@ if testFontPath is None: testFontPath = getTestFontPath() dirName, fileName = os.path.split(testFontPath) - fileName, ext = os.path.splitext(fileName) - return os.path.join(dirName, fileName + 'Copy' + ext) + fileName = os.path.splitext(fileName)[0] + 'Copy.ufo' + return os.path.join(dirName, fileName) def makeTestFontCopy(testFontPath=None): if testFontPath is None: testFontPath = getTestFontPath() copyPath = getTestFontCopyPath(testFontPath) - if os.path.isdir(testFontPath): - shutil.copytree(testFontPath, copyPath) - else: - shutil.copyfile(testFontPath, copyPath) + shutil.copytree(testFontPath, copyPath) return copyPath def tearDownTestFontCopy(testFontPath=None): if testFontPath is None: testFontPath = getTestFontCopyPath() - if os.path.isdir(testFontPath): - shutil.rmtree(testFontPath) - else: - os.remove(testFontPath) - - -def openTestFontAsFileSystem(testFontPath=None): - if testFontPath is None: - testFontPath = getTestFontPath() - if zipfile.is_zipfile(testFontPath): - parentFS = fs.tempfs.TempFS() - with fs.zipfs.ZipFS(testFontPath, encoding="utf-8") as origFS: - fs.copy.copy_fs(origFS, parentFS) - rootDirs = [ - p.name for p in parentFS.scandir(u"/") - if p.is_dir and p.name != "__MACOSX" - ] - fileSystem = parentFS.opendir( - rootDirs[0], factory=fs.subfs.ClosingSubFS - ) - else: - fileSystem = fs.osfs.OSFS(testFontPath) - return fileSystem - - -def closeTestFontAsFileSystem(fileSystem, testFontPath=None): - if testFontPath is None: - testFontPath = getTestFontPath() - if not zipfile.is_zipfile(testFontPath): - return - rootDir = os.path.splitext(os.path.basename(testFontPath))[0] + ".ufo" - with fs.zipfs.ZipFS(testFontPath, write=True, encoding="utf-8") as destFS: - fs.copy.copy_fs(fileSystem, destFS.makedir(rootDir)) + shutil.rmtree(testFontPath) class NotificationTestObserver(object): diff -Nru defcon-0.7.2/Lib/defcon/test/tools/test_unicodeTools.py defcon-0.3.5/Lib/defcon/test/tools/test_unicodeTools.py --- defcon-0.7.2/Lib/defcon/test/tools/test_unicodeTools.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/test/tools/test_unicodeTools.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -import unittest -from defcon.tools.unicodeTools import ( - decompositionBase, openRelative, closeRelative, category, script, block -) - - -class UnicodeToolsTest(unittest.TestCase): - - def __init__(self, methodName): - unittest.TestCase.__init__(self, methodName) - - def test_decompositionBase(self): - self.assertEqual(decompositionBase(ord("ç")), ord("c")) - self.assertEqual(decompositionBase(ord("a")), -1) - self.assertEqual(decompositionBase(0x0001000), -1) - - def test_openRelative(self): - self.assertEqual(openRelative(ord(")")), ord("(")) - self.assertIsNone(openRelative(ord("a"))) - self.assertIsNone(openRelative(0x0001000)) - - def test_closeRelative(self): - self.assertEqual(closeRelative(ord("(")), ord(")")) - self.assertIsNone(closeRelative(ord("a"))) - self.assertIsNone(closeRelative(0x0001000)) - - def test_category(self): - self.assertEqual(category(ord("a")), "Ll") - self.assertEqual(category(0x0001000), "Lo") - - def test_script(self): - self.assertEqual(script(ord("a")), "Latin") - self.assertEqual(script(0x00010000), "Linear B") - - def test_block(self): - self.assertEqual(block(ord("a")), "Basic Latin") - self.assertEqual(block(0x00010000), "Linear B Syllabary") diff -Nru defcon-0.7.2/Lib/defcon/tools/bezierMath.py defcon-0.3.5/Lib/defcon/tools/bezierMath.py --- defcon-0.7.2/Lib/defcon/tools/bezierMath.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/tools/bezierMath.py 2017-10-02 10:54:57.000000000 +0000 @@ -2,7 +2,7 @@ Contributed by Frederik Berlaen. """ -from math import sqrt, atan2, radians, degrees +from math import sqrt, atan2 def _distance(coordinates1, coordinates2): (x1, y1) = coordinates1 @@ -25,48 +25,32 @@ (off3X, off3Y) = offCoords3 (off4X, off4Y) = offCoords4 (on3X, on3Y) = onCoords3 - if (on1X, on1Y) == (off1X, off1Y) and (off2X, off2Y) == (on2X, on2Y) == (off3X, off3Y) and (off4X, off4Y) == (on3X, on3Y): + if (on1X, on1Y) == (off1X, off1Y) and (off2X, off2Y) == (on2X, on2Y) == (off3X, off3Y) and (off4X, off4Y) == (on3X, on3Y): ## a two line segments return (on1X, on1Y), (off4X, off4Y), (on3X, on3Y) if (on1X, on1Y) == (off1X, off1Y) and (off2X, off2Y) == (on2X, on2Y): ## first is a line segement - lineAngle = atan2(on2X - on1X, on2Y - on1Y) - handleAngle = atan2(off3X - on2X, off3Y - on2Y) - if radians(-30) < lineAngle - handleAngle < radians(30): - d1 = _distance((on1X, on1Y), (off2X, off2Y)) - d2 = d1 + _distance((on2X, on2Y), (off3X, off3Y)) - if d1 == 0: - x, y = off3X, off3Y - else: - factor = d2 / d1 - x = on1X + (off2X - on1X) * factor - y = on1Y + (off2Y - on1Y) * factor - return (x, y), (off4X, off4Y), (on3X, on3Y) + d1 = _distance((on1X, on1Y), (off2X, off2Y)) + d2 = d1 + _distance((on2X, on2Y), (off3X, off3Y)) + if d1 == 0: + x, y = off3X, off3Y else: - # just move the off curve point - x = off3X - (off2X - on1X) - y = off3Y - (off2Y - on1Y) - return (x, y), (off4X, off4Y), (on3X, on3Y) + factor = d2 / d1 + x = on1X + (off2X - on1X) * factor + y = on1Y + (off2Y - on1Y) * factor + return (x, y), (off4X, off4Y), (on3X, on3Y) if (on2X, on2Y) == (off3X, off3Y) and (off4X, off4Y) == (on3X, on3Y): ## last is a line segment - handleAngle = atan2(on2X - off2X, on2Y - off2Y) - lineAngle = atan2(on3X - on2X, on3Y - on2Y) - if radians(-30) < lineAngle - handleAngle < radians(30): - d1 = _distance((on3X, on3Y), (off3X, off3Y)) - d2 = d1 + _distance((on2X, on2Y), (off2X, off2Y)) - if d1 == 0: - x, y = off2X, off2Y - else: - factor = d2 / d1 - x = on3X + (off3X - on3X) * factor - y = on3Y + (off3Y - on3Y) * factor - return (off1X, off1Y), (x, y), (on3X, on3Y) + d1 = _distance((on3X, on3Y), (off3X, off3Y)) + d2 = d1 + _distance((on2X, on2Y), (off2X, off2Y)) + if d1 == 0: + x, y = off2X, off2Y else: - # just move the off curve point - x = off2X + (off4X - on2X) - y = off2Y + (off4Y - on2Y) - return (off1X, off1Y), (x, y), (on3X, on3Y) + factor = d2 / d1 + x = on3X + (off3X - on3X) * factor + y = on3Y + (off3Y - on3Y) * factor + return (off1X, off1Y), (x, y), (on3X, on3Y) if (off2X, off2Y) == (on2X, on2Y) == (off3X, off3Y) or (off2X, off2Y) == (on2X, on2Y) or (on2X, on2Y) == (off3X, off3Y): ## one or more bcps are on the joined point @@ -89,7 +73,7 @@ if abs(a1 - a2) < 0.05: smooth = True - # first calculate an approximaly t + # first calculate an aproximaly t d1 = _distance((on2X, on2Y), (off2X, off2Y)) d2 = d1 + _distance((off3X, off3Y), (on2X, on2Y)) diff -Nru defcon-0.7.2/Lib/defcon/tools/notifications.py defcon-0.3.5/Lib/defcon/tools/notifications.py --- defcon-0.7.2/Lib/defcon/tools/notifications.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/tools/notifications.py 2017-10-02 10:54:57.000000000 +0000 @@ -54,7 +54,7 @@ Add an observer to this notification dispatcher. * **observer** An object that can be referenced with weakref. - * **methodName** A string representing the method to be called + * **methodName** A string epresenting the method to be called when the notification is posted. * **notification** The notification that the observer should be notified of. If this is None, all notifications for @@ -204,7 +204,7 @@ # Hold # ---- - def holdNotifications(self, observable=None, notification=None, observer=None, note=None): + def holdNotifications(self, observable=None, notification=None, observer=None): """ Hold all notifications posted to all objects observing **notification** in **observable**. @@ -214,11 +214,9 @@ * **notification** The name of the notification. This is optional. If no *notification* is given, *all* notifications for *observable* will be held. - * **observer** The specific observer to not hold notifications for. - If no *observer* is given, the appropriate notifications will be - held for all observers. - * **note** An arbitrary string containing information about why the hold - has been requested, the requester, etc. This is used for reference only. + * **observer** The specific observer to not hold notifications for. + If no *observer* is given, the appropriate notifications will be + held for all observers. Held notifications will be posted after the matching *notification* and *observable* have been passed to :meth:`Notification.releaseHeldNotifications`. @@ -233,10 +231,8 @@ observer = weakref.ref(observer) key = (notification, observable, observer) if key not in self._holds: - self._holds[key] = dict(count=0, notifications=[], notes=[]) + self._holds[key] = dict(count=0, notifications=[]) self._holds[key]["count"] += 1 - if note is not None: - self._holds[key]["notes"].append(note) def releaseHeldNotifications(self, observable=None, notification=None, observer=None): """ @@ -275,31 +271,6 @@ key = (notification, observable, observer) return key in self._holds - def getHeldNotifications(self): - """ - Returns a list of all held notifications. This will be a - tuple of the form: - - (notification, observable, observer) - """ - return self._holds.keys() - - def getHeldNotificationNotes(self, observable=None, notification=None, observer=None): - """ - Returns a list of notes defined for notification holds observing - **notification** in **observable** are being held. - - * **observable** The object that the notification belongs to. This is optional. - * **notification** The name of the notification. This is optional. - * **observer** The observer. This is optional. - """ - if observable is not None: - observable = weakref.ref(observable) - if observer is not None: - observer = weakref.ref(observer) - key = (notification, observable, observer) - return self._holds[key]["notes"] - # ------- # Disable # ------- diff -Nru defcon-0.7.2/Lib/defcon/tools/representations.py defcon-0.3.5/Lib/defcon/tools/representations.py --- defcon-0.7.2/Lib/defcon/tools/representations.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/tools/representations.py 2017-10-02 10:54:57.000000000 +0000 @@ -3,46 +3,19 @@ from fontTools.pens.boundsPen import ControlBoundsPen, BoundsPen from fontTools.misc.arrayTools import unionRect -# ------ -# Groups -# ------ - -def kerningSide1GroupsRepresentationFactory(groups): - return _gatherGroupsWithPrefix(groups, "public.kern1.") - -def kerningSide2GroupsRepresentationFactory(groups): - return _gatherGroupsWithPrefix(groups, "public.kern2.") - -def _gatherGroupsWithPrefix(groups, prefix): - found = {} - for name, glyphNames in groups.items(): - if name.startswith(prefix): - found[name] = glyphNames - return found - -def glyphToKerningSide1GroupsRepresentationFactory(groups): - groups = groups.getRepresentation("defcon.groups.kerningSide1Groups") - return _makeGlyphToGroupMapping(groups) - -def glyphToKerningSide2GroupsRepresentationFactory(groups): - groups = groups.getRepresentation("defcon.groups.kerningSide2Groups") - return _makeGlyphToGroupMapping(groups) - -def _makeGlyphToGroupMapping(groups): - glyphToGroup = {} - for groupName, glyphNames in groups.items(): - for glyphName in glyphNames: - glyphToGroup[glyphName] = groupName - return glyphToGroup - # ----- # Glyph # ----- -def glyphAreaRepresentationFactory(glyph): - pen = AreaPen(glyph.layer) +def glyphBoundsRepresentationFactory(glyph): + pen = BoundsPen(glyph.layer) glyph.draw(pen) - return abs(pen.value) + return pen.bounds + +def glyphControlPointBoundsRepresentationFactory(glyph): + pen = ControlBoundsPen(glyph.layer) + glyph.draw(pen) + return pen.bounds # ------- # Contour @@ -60,26 +33,13 @@ obj.draw(pen) return pen.bounds -# area +# winding direction -def contourAreaRepresentationFactory(contour): +def contourClockwiseRepresentationFactory(contour): pen = AreaPen() - pen._endPath = pen._closePath + pen.endPath = pen.closePath contour.draw(pen) - return pen.value - -# flattened - -def contourFlattenedRepresentationFactory(contour, approximateSegmentLength=5, segmentLines=False): - from fontPens.flattenPen import FlattenPen - from defcon.objects.glyph import Glyph - contourClass = contour.__class__ - glyph = Glyph(contourClass=contourClass) - outputPen = glyph.getPen() - flattenPen = FlattenPen(outputPen, approximateSegmentLength=approximateSegmentLength, segmentLines=segmentLines) - contour.draw(flattenPen) - output = glyph[0] - return output + return pen.value < 0 # --------- # Component diff -Nru defcon-0.7.2/Lib/defcon/tools/unicodeTools.py defcon-0.3.5/Lib/defcon/tools/unicodeTools.py --- defcon-0.7.2/Lib/defcon/tools/unicodeTools.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/Lib/defcon/tools/unicodeTools.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,6 +1,2955 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from fontTools import unicodedata +import unicodedata +from fontTools.misc.py23 import unichr + +_scriptsText = """ +# Scripts-9.0.0.txt +# Date: 2016-03-02, 18:55:13 GMT +# © 2016 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# For more information, see: +# UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/ +# Especially the sections: +# http://www.unicode.org/reports/tr24/#Assignment_Script_Values +# http://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values +# + +# ================================================ + +# Property: Script + +# All code points not explicitly listed for Script +# have the value Unknown (Zzzz). + +# @missing: 0000..10FFFF; Unknown + +# ================================================ + +0000..001F ; Common # Cc [32] .. +0020 ; Common # Zs SPACE +0021..0023 ; Common # Po [3] EXCLAMATION MARK..NUMBER SIGN +0024 ; Common # Sc DOLLAR SIGN +0025..0027 ; Common # Po [3] PERCENT SIGN..APOSTROPHE +0028 ; Common # Ps LEFT PARENTHESIS +0029 ; Common # Pe RIGHT PARENTHESIS +002A ; Common # Po ASTERISK +002B ; Common # Sm PLUS SIGN +002C ; Common # Po COMMA +002D ; Common # Pd HYPHEN-MINUS +002E..002F ; Common # Po [2] FULL STOP..SOLIDUS +0030..0039 ; Common # Nd [10] DIGIT ZERO..DIGIT NINE +003A..003B ; Common # Po [2] COLON..SEMICOLON +003C..003E ; Common # Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN +003F..0040 ; Common # Po [2] QUESTION MARK..COMMERCIAL AT +005B ; Common # Ps LEFT SQUARE BRACKET +005C ; Common # Po REVERSE SOLIDUS +005D ; Common # Pe RIGHT SQUARE BRACKET +005E ; Common # Sk CIRCUMFLEX ACCENT +005F ; Common # Pc LOW LINE +0060 ; Common # Sk GRAVE ACCENT +007B ; Common # Ps LEFT CURLY BRACKET +007C ; Common # Sm VERTICAL LINE +007D ; Common # Pe RIGHT CURLY BRACKET +007E ; Common # Sm TILDE +007F..009F ; Common # Cc [33] .. +00A0 ; Common # Zs NO-BREAK SPACE +00A1 ; Common # Po INVERTED EXCLAMATION MARK +00A2..00A5 ; Common # Sc [4] CENT SIGN..YEN SIGN +00A6 ; Common # So BROKEN BAR +00A7 ; Common # Po SECTION SIGN +00A8 ; Common # Sk DIAERESIS +00A9 ; Common # So COPYRIGHT SIGN +00AB ; Common # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00AC ; Common # Sm NOT SIGN +00AD ; Common # Cf SOFT HYPHEN +00AE ; Common # So REGISTERED SIGN +00AF ; Common # Sk MACRON +00B0 ; Common # So DEGREE SIGN +00B1 ; Common # Sm PLUS-MINUS SIGN +00B2..00B3 ; Common # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE +00B4 ; Common # Sk ACUTE ACCENT +00B5 ; Common # L& MICRO SIGN +00B6..00B7 ; Common # Po [2] PILCROW SIGN..MIDDLE DOT +00B8 ; Common # Sk CEDILLA +00B9 ; Common # No SUPERSCRIPT ONE +00BB ; Common # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +00BC..00BE ; Common # No [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS +00BF ; Common # Po INVERTED QUESTION MARK +00D7 ; Common # Sm MULTIPLICATION SIGN +00F7 ; Common # Sm DIVISION SIGN +02B9..02C1 ; Common # Lm [9] MODIFIER LETTER PRIME..MODIFIER LETTER REVERSED GLOTTAL STOP +02C2..02C5 ; Common # Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD +02C6..02D1 ; Common # Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON +02D2..02DF ; Common # Sk [14] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER CROSS ACCENT +02E5..02E9 ; Common # Sk [5] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER EXTRA-LOW TONE BAR +02EC ; Common # Lm MODIFIER LETTER VOICING +02ED ; Common # Sk MODIFIER LETTER UNASPIRATED +02EE ; Common # Lm MODIFIER LETTER DOUBLE APOSTROPHE +02EF..02FF ; Common # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW +0374 ; Common # Lm GREEK NUMERAL SIGN +037E ; Common # Po GREEK QUESTION MARK +0385 ; Common # Sk GREEK DIALYTIKA TONOS +0387 ; Common # Po GREEK ANO TELEIA +0589 ; Common # Po ARMENIAN FULL STOP +0605 ; Common # Cf ARABIC NUMBER MARK ABOVE +060C ; Common # Po ARABIC COMMA +061B ; Common # Po ARABIC SEMICOLON +061C ; Common # Cf ARABIC LETTER MARK +061F ; Common # Po ARABIC QUESTION MARK +0640 ; Common # Lm ARABIC TATWEEL +06DD ; Common # Cf ARABIC END OF AYAH +08E2 ; Common # Cf ARABIC DISPUTED END OF AYAH +0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA +0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT +0FD5..0FD8 ; Common # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS +10FB ; Common # Po GEORGIAN PARAGRAPH SEPARATOR +16EB..16ED ; Common # Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION +1735..1736 ; Common # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION +1802..1803 ; Common # Po [2] MONGOLIAN COMMA..MONGOLIAN FULL STOP +1805 ; Common # Po MONGOLIAN FOUR DOTS +1CD3 ; Common # Po VEDIC SIGN NIHSHVASA +1CE1 ; Common # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA +1CE9..1CEC ; Common # Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL +1CEE..1CF1 ; Common # Lo [4] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ANUSVARA UBHAYATO MUKHA +1CF2..1CF3 ; Common # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA +1CF5..1CF6 ; Common # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA +2000..200A ; Common # Zs [11] EN QUAD..HAIR SPACE +200B ; Common # Cf ZERO WIDTH SPACE +200E..200F ; Common # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK +2010..2015 ; Common # Pd [6] HYPHEN..HORIZONTAL BAR +2016..2017 ; Common # Po [2] DOUBLE VERTICAL LINE..DOUBLE LOW LINE +2018 ; Common # Pi LEFT SINGLE QUOTATION MARK +2019 ; Common # Pf RIGHT SINGLE QUOTATION MARK +201A ; Common # Ps SINGLE LOW-9 QUOTATION MARK +201B..201C ; Common # Pi [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK +201D ; Common # Pf RIGHT DOUBLE QUOTATION MARK +201E ; Common # Ps DOUBLE LOW-9 QUOTATION MARK +201F ; Common # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK +2020..2027 ; Common # Po [8] DAGGER..HYPHENATION POINT +2028 ; Common # Zl LINE SEPARATOR +2029 ; Common # Zp PARAGRAPH SEPARATOR +202A..202E ; Common # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE +202F ; Common # Zs NARROW NO-BREAK SPACE +2030..2038 ; Common # Po [9] PER MILLE SIGN..CARET +2039 ; Common # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A ; Common # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +203B..203E ; Common # Po [4] REFERENCE MARK..OVERLINE +203F..2040 ; Common # Pc [2] UNDERTIE..CHARACTER TIE +2041..2043 ; Common # Po [3] CARET INSERTION POINT..HYPHEN BULLET +2044 ; Common # Sm FRACTION SLASH +2045 ; Common # Ps LEFT SQUARE BRACKET WITH QUILL +2046 ; Common # Pe RIGHT SQUARE BRACKET WITH QUILL +2047..2051 ; Common # Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY +2052 ; Common # Sm COMMERCIAL MINUS SIGN +2053 ; Common # Po SWUNG DASH +2054 ; Common # Pc INVERTED UNDERTIE +2055..205E ; Common # Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS +205F ; Common # Zs MEDIUM MATHEMATICAL SPACE +2060..2064 ; Common # Cf [5] WORD JOINER..INVISIBLE PLUS +2066..206F ; Common # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES +2070 ; Common # No SUPERSCRIPT ZERO +2074..2079 ; Common # No [6] SUPERSCRIPT FOUR..SUPERSCRIPT NINE +207A..207C ; Common # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN +207D ; Common # Ps SUPERSCRIPT LEFT PARENTHESIS +207E ; Common # Pe SUPERSCRIPT RIGHT PARENTHESIS +2080..2089 ; Common # No [10] SUBSCRIPT ZERO..SUBSCRIPT NINE +208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN +208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS +208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS +20A0..20BE ; Common # Sc [31] EURO-CURRENCY SIGN..LARI SIGN +2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT +2102 ; Common # L& DOUBLE-STRUCK CAPITAL C +2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA +2107 ; Common # L& EULER CONSTANT +2108..2109 ; Common # So [2] SCRUPLE..DEGREE FAHRENHEIT +210A..2113 ; Common # L& [10] SCRIPT SMALL G..SCRIPT SMALL L +2114 ; Common # So L B BAR SYMBOL +2115 ; Common # L& DOUBLE-STRUCK CAPITAL N +2116..2117 ; Common # So [2] NUMERO SIGN..SOUND RECORDING COPYRIGHT +2118 ; Common # Sm SCRIPT CAPITAL P +2119..211D ; Common # L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R +211E..2123 ; Common # So [6] PRESCRIPTION TAKE..VERSICLE +2124 ; Common # L& DOUBLE-STRUCK CAPITAL Z +2125 ; Common # So OUNCE SIGN +2127 ; Common # So INVERTED OHM SIGN +2128 ; Common # L& BLACK-LETTER CAPITAL Z +2129 ; Common # So TURNED GREEK SMALL LETTER IOTA +212C..212D ; Common # L& [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C +212E ; Common # So ESTIMATED SYMBOL +212F..2131 ; Common # L& [3] SCRIPT SMALL E..SCRIPT CAPITAL F +2133..2134 ; Common # L& [2] SCRIPT CAPITAL M..SCRIPT SMALL O +2135..2138 ; Common # Lo [4] ALEF SYMBOL..DALET SYMBOL +2139 ; Common # L& INFORMATION SOURCE +213A..213B ; Common # So [2] ROTATED CAPITAL Q..FACSIMILE SIGN +213C..213F ; Common # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI +2140..2144 ; Common # Sm [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y +2145..2149 ; Common # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J +214A ; Common # So PROPERTY LINE +214B ; Common # Sm TURNED AMPERSAND +214C..214D ; Common # So [2] PER SIGN..AKTIESELSKAB +214F ; Common # So SYMBOL FOR SAMARITAN SOURCE +2150..215F ; Common # No [16] VULGAR FRACTION ONE SEVENTH..FRACTION NUMERATOR ONE +2189 ; Common # No VULGAR FRACTION ZERO THIRDS +218A..218B ; Common # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE +2190..2194 ; Common # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW +2195..2199 ; Common # So [5] UP DOWN ARROW..SOUTH WEST ARROW +219A..219B ; Common # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE +219C..219F ; Common # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW +21A0 ; Common # Sm RIGHTWARDS TWO HEADED ARROW +21A1..21A2 ; Common # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL +21A3 ; Common # Sm RIGHTWARDS ARROW WITH TAIL +21A4..21A5 ; Common # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR +21A6 ; Common # Sm RIGHTWARDS ARROW FROM BAR +21A7..21AD ; Common # So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW +21AE ; Common # Sm LEFT RIGHT ARROW WITH STROKE +21AF..21CD ; Common # So [31] DOWNWARDS ZIGZAG ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE +21CE..21CF ; Common # Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE +21D0..21D1 ; Common # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW +21D2 ; Common # Sm RIGHTWARDS DOUBLE ARROW +21D3 ; Common # So DOWNWARDS DOUBLE ARROW +21D4 ; Common # Sm LEFT RIGHT DOUBLE ARROW +21D5..21F3 ; Common # So [31] UP DOWN DOUBLE ARROW..UP DOWN WHITE ARROW +21F4..22FF ; Common # Sm [268] RIGHT ARROW WITH SMALL CIRCLE..Z NOTATION BAG MEMBERSHIP +2300..2307 ; Common # So [8] DIAMETER SIGN..WAVY LINE +2308 ; Common # Ps LEFT CEILING +2309 ; Common # Pe RIGHT CEILING +230A ; Common # Ps LEFT FLOOR +230B ; Common # Pe RIGHT FLOOR +230C..231F ; Common # So [20] BOTTOM RIGHT CROP..BOTTOM RIGHT CORNER +2320..2321 ; Common # Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL +2322..2328 ; Common # So [7] FROWN..KEYBOARD +2329 ; Common # Ps LEFT-POINTING ANGLE BRACKET +232A ; Common # Pe RIGHT-POINTING ANGLE BRACKET +232B..237B ; Common # So [81] ERASE TO THE LEFT..NOT CHECK MARK +237C ; Common # Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW +237D..239A ; Common # So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL +239B..23B3 ; Common # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM +23B4..23DB ; Common # So [40] TOP SQUARE BRACKET..FUSE +23DC..23E1 ; Common # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET +23E2..23FE ; Common # So [29] WHITE TRAPEZIUM..POWER SLEEP SYMBOL +2400..2426 ; Common # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO +2440..244A ; Common # So [11] OCR HOOK..OCR DOUBLE BACKSLASH +2460..249B ; Common # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP +249C..24E9 ; Common # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z +24EA..24FF ; Common # No [22] CIRCLED DIGIT ZERO..NEGATIVE CIRCLED DIGIT ZERO +2500..25B6 ; Common # So [183] BOX DRAWINGS LIGHT HORIZONTAL..BLACK RIGHT-POINTING TRIANGLE +25B7 ; Common # Sm WHITE RIGHT-POINTING TRIANGLE +25B8..25C0 ; Common # So [9] BLACK RIGHT-POINTING SMALL TRIANGLE..BLACK LEFT-POINTING TRIANGLE +25C1 ; Common # Sm WHITE LEFT-POINTING TRIANGLE +25C2..25F7 ; Common # So [54] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE CIRCLE WITH UPPER RIGHT QUADRANT +25F8..25FF ; Common # Sm [8] UPPER LEFT TRIANGLE..LOWER RIGHT TRIANGLE +2600..266E ; Common # So [111] BLACK SUN WITH RAYS..MUSIC NATURAL SIGN +266F ; Common # Sm MUSIC SHARP SIGN +2670..2767 ; Common # So [248] WEST SYRIAC CROSS..ROTATED FLORAL HEART BULLET +2768 ; Common # Ps MEDIUM LEFT PARENTHESIS ORNAMENT +2769 ; Common # Pe MEDIUM RIGHT PARENTHESIS ORNAMENT +276A ; Common # Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT +276B ; Common # Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT +276C ; Common # Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT +276D ; Common # Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT +276E ; Common # Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT +276F ; Common # Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT +2770 ; Common # Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT +2771 ; Common # Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT +2772 ; Common # Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT +2773 ; Common # Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT +2774 ; Common # Ps MEDIUM LEFT CURLY BRACKET ORNAMENT +2775 ; Common # Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT +2776..2793 ; Common # No [30] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN +2794..27BF ; Common # So [44] HEAVY WIDE-HEADED RIGHTWARDS ARROW..DOUBLE CURLY LOOP +27C0..27C4 ; Common # Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET +27C5 ; Common # Ps LEFT S-SHAPED BAG DELIMITER +27C6 ; Common # Pe RIGHT S-SHAPED BAG DELIMITER +27C7..27E5 ; Common # Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK +27E6 ; Common # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET +27E7 ; Common # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET +27E8 ; Common # Ps MATHEMATICAL LEFT ANGLE BRACKET +27E9 ; Common # Pe MATHEMATICAL RIGHT ANGLE BRACKET +27EA ; Common # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET +27EB ; Common # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET +27EC ; Common # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET +27ED ; Common # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET +27EE ; Common # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS +27EF ; Common # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS +27F0..27FF ; Common # Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW +2900..2982 ; Common # Sm [131] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..Z NOTATION TYPE COLON +2983 ; Common # Ps LEFT WHITE CURLY BRACKET +2984 ; Common # Pe RIGHT WHITE CURLY BRACKET +2985 ; Common # Ps LEFT WHITE PARENTHESIS +2986 ; Common # Pe RIGHT WHITE PARENTHESIS +2987 ; Common # Ps Z NOTATION LEFT IMAGE BRACKET +2988 ; Common # Pe Z NOTATION RIGHT IMAGE BRACKET +2989 ; Common # Ps Z NOTATION LEFT BINDING BRACKET +298A ; Common # Pe Z NOTATION RIGHT BINDING BRACKET +298B ; Common # Ps LEFT SQUARE BRACKET WITH UNDERBAR +298C ; Common # Pe RIGHT SQUARE BRACKET WITH UNDERBAR +298D ; Common # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER +298E ; Common # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +298F ; Common # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +2990 ; Common # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER +2991 ; Common # Ps LEFT ANGLE BRACKET WITH DOT +2992 ; Common # Pe RIGHT ANGLE BRACKET WITH DOT +2993 ; Common # Ps LEFT ARC LESS-THAN BRACKET +2994 ; Common # Pe RIGHT ARC GREATER-THAN BRACKET +2995 ; Common # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET +2996 ; Common # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET +2997 ; Common # Ps LEFT BLACK TORTOISE SHELL BRACKET +2998 ; Common # Pe RIGHT BLACK TORTOISE SHELL BRACKET +2999..29D7 ; Common # Sm [63] DOTTED FENCE..BLACK HOURGLASS +29D8 ; Common # Ps LEFT WIGGLY FENCE +29D9 ; Common # Pe RIGHT WIGGLY FENCE +29DA ; Common # Ps LEFT DOUBLE WIGGLY FENCE +29DB ; Common # Pe RIGHT DOUBLE WIGGLY FENCE +29DC..29FB ; Common # Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS +29FC ; Common # Ps LEFT-POINTING CURVED ANGLE BRACKET +29FD ; Common # Pe RIGHT-POINTING CURVED ANGLE BRACKET +29FE..2AFF ; Common # Sm [258] TINY..N-ARY WHITE VERTICAL BAR +2B00..2B2F ; Common # So [48] NORTH EAST WHITE ARROW..WHITE VERTICAL ELLIPSE +2B30..2B44 ; Common # Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET +2B45..2B46 ; Common # So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW +2B47..2B4C ; Common # Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR +2B4D..2B73 ; Common # So [39] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR +2B76..2B95 ; Common # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW +2B98..2BB9 ; Common # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX +2BBD..2BC8 ; Common # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED +2BCA..2BD1 ; Common # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN +2BEC..2BEF ; Common # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS +2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER +2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET +2E03 ; Common # Pf RIGHT SUBSTITUTION BRACKET +2E04 ; Common # Pi LEFT DOTTED SUBSTITUTION BRACKET +2E05 ; Common # Pf RIGHT DOTTED SUBSTITUTION BRACKET +2E06..2E08 ; Common # Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER +2E09 ; Common # Pi LEFT TRANSPOSITION BRACKET +2E0A ; Common # Pf RIGHT TRANSPOSITION BRACKET +2E0B ; Common # Po RAISED SQUARE +2E0C ; Common # Pi LEFT RAISED OMISSION BRACKET +2E0D ; Common # Pf RIGHT RAISED OMISSION BRACKET +2E0E..2E16 ; Common # Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE +2E17 ; Common # Pd DOUBLE OBLIQUE HYPHEN +2E18..2E19 ; Common # Po [2] INVERTED INTERROBANG..PALM BRANCH +2E1A ; Common # Pd HYPHEN WITH DIAERESIS +2E1B ; Common # Po TILDE WITH RING ABOVE +2E1C ; Common # Pi LEFT LOW PARAPHRASE BRACKET +2E1D ; Common # Pf RIGHT LOW PARAPHRASE BRACKET +2E1E..2E1F ; Common # Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW +2E20 ; Common # Pi LEFT VERTICAL BAR WITH QUILL +2E21 ; Common # Pf RIGHT VERTICAL BAR WITH QUILL +2E22 ; Common # Ps TOP LEFT HALF BRACKET +2E23 ; Common # Pe TOP RIGHT HALF BRACKET +2E24 ; Common # Ps BOTTOM LEFT HALF BRACKET +2E25 ; Common # Pe BOTTOM RIGHT HALF BRACKET +2E26 ; Common # Ps LEFT SIDEWAYS U BRACKET +2E27 ; Common # Pe RIGHT SIDEWAYS U BRACKET +2E28 ; Common # Ps LEFT DOUBLE PARENTHESIS +2E29 ; Common # Pe RIGHT DOUBLE PARENTHESIS +2E2A..2E2E ; Common # Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK +2E2F ; Common # Lm VERTICAL TILDE +2E30..2E39 ; Common # Po [10] RING POINT..TOP HALF SECTION SIGN +2E3A..2E3B ; Common # Pd [2] TWO-EM DASH..THREE-EM DASH +2E3C..2E3F ; Common # Po [4] STENOGRAPHIC FULL STOP..CAPITULUM +2E40 ; Common # Pd DOUBLE HYPHEN +2E41 ; Common # Po REVERSED COMMA +2E42 ; Common # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK +2E43..2E44 ; Common # Po [2] DASH WITH LEFT UPTURN..DOUBLE SUSPENSION MARK +2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID +3000 ; Common # Zs IDEOGRAPHIC SPACE +3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK +3004 ; Common # So JAPANESE INDUSTRIAL STANDARD SYMBOL +3006 ; Common # Lo IDEOGRAPHIC CLOSING MARK +3008 ; Common # Ps LEFT ANGLE BRACKET +3009 ; Common # Pe RIGHT ANGLE BRACKET +300A ; Common # Ps LEFT DOUBLE ANGLE BRACKET +300B ; Common # Pe RIGHT DOUBLE ANGLE BRACKET +300C ; Common # Ps LEFT CORNER BRACKET +300D ; Common # Pe RIGHT CORNER BRACKET +300E ; Common # Ps LEFT WHITE CORNER BRACKET +300F ; Common # Pe RIGHT WHITE CORNER BRACKET +3010 ; Common # Ps LEFT BLACK LENTICULAR BRACKET +3011 ; Common # Pe RIGHT BLACK LENTICULAR BRACKET +3012..3013 ; Common # So [2] POSTAL MARK..GETA MARK +3014 ; Common # Ps LEFT TORTOISE SHELL BRACKET +3015 ; Common # Pe RIGHT TORTOISE SHELL BRACKET +3016 ; Common # Ps LEFT WHITE LENTICULAR BRACKET +3017 ; Common # Pe RIGHT WHITE LENTICULAR BRACKET +3018 ; Common # Ps LEFT WHITE TORTOISE SHELL BRACKET +3019 ; Common # Pe RIGHT WHITE TORTOISE SHELL BRACKET +301A ; Common # Ps LEFT WHITE SQUARE BRACKET +301B ; Common # Pe RIGHT WHITE SQUARE BRACKET +301C ; Common # Pd WAVE DASH +301D ; Common # Ps REVERSED DOUBLE PRIME QUOTATION MARK +301E..301F ; Common # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK +3020 ; Common # So POSTAL MARK FACE +3030 ; Common # Pd WAVY DASH +3031..3035 ; Common # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF +3036..3037 ; Common # So [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL +303C ; Common # Lo MASU MARK +303D ; Common # Po PART ALTERNATION MARK +303E..303F ; Common # So [2] IDEOGRAPHIC VARIATION INDICATOR..IDEOGRAPHIC HALF FILL SPACE +309B..309C ; Common # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +30A0 ; Common # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN +30FB ; Common # Po KATAKANA MIDDLE DOT +30FC ; Common # Lm KATAKANA-HIRAGANA PROLONGED SOUND MARK +3190..3191 ; Common # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK +3192..3195 ; Common # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK +3196..319F ; Common # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK +31C0..31E3 ; Common # So [36] CJK STROKE T..CJK STROKE Q +3220..3229 ; Common # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN +322A..3247 ; Common # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO +3248..324F ; Common # No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE +3250 ; Common # So PARTNERSHIP SIGN +3251..325F ; Common # No [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE +327F ; Common # So KOREAN STANDARD SYMBOL +3280..3289 ; Common # No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN +328A..32B0 ; Common # So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT +32B1..32BF ; Common # No [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY +32C0..32CF ; Common # So [16] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..LIMITED LIABILITY SIGN +3358..33FF ; Common # So [168] IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO..SQUARE GAL +4DC0..4DFF ; Common # So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION +A700..A716 ; Common # Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR +A717..A71F ; Common # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK +A720..A721 ; Common # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE +A788 ; Common # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT +A789..A78A ; Common # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN +A830..A835 ; Common # No [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS +A836..A837 ; Common # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK +A838 ; Common # Sc NORTH INDIC RUPEE MARK +A839 ; Common # So NORTH INDIC QUANTITY MARK +A92E ; Common # Po KAYAH LI SIGN CWI +A9CF ; Common # Lm JAVANESE PANGRANGKEP +AB5B ; Common # Sk MODIFIER BREVE WITH INVERTED BREVE +FD3E ; Common # Pe ORNATE LEFT PARENTHESIS +FD3F ; Common # Ps ORNATE RIGHT PARENTHESIS +FE10..FE16 ; Common # Po [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK +FE17 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET +FE18 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET +FE19 ; Common # Po PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS +FE30 ; Common # Po PRESENTATION FORM FOR VERTICAL TWO DOT LEADER +FE31..FE32 ; Common # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH +FE33..FE34 ; Common # Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE +FE35 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS +FE36 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS +FE37 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET +FE38 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET +FE39 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET +FE3A ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET +FE3B ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET +FE3C ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET +FE3D ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET +FE3E ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET +FE3F ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET +FE40 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET +FE41 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET +FE42 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET +FE43 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET +FE44 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET +FE45..FE46 ; Common # Po [2] SESAME DOT..WHITE SESAME DOT +FE47 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET +FE48 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET +FE49..FE4C ; Common # Po [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE +FE4D..FE4F ; Common # Pc [3] DASHED LOW LINE..WAVY LOW LINE +FE50..FE52 ; Common # Po [3] SMALL COMMA..SMALL FULL STOP +FE54..FE57 ; Common # Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK +FE58 ; Common # Pd SMALL EM DASH +FE59 ; Common # Ps SMALL LEFT PARENTHESIS +FE5A ; Common # Pe SMALL RIGHT PARENTHESIS +FE5B ; Common # Ps SMALL LEFT CURLY BRACKET +FE5C ; Common # Pe SMALL RIGHT CURLY BRACKET +FE5D ; Common # Ps SMALL LEFT TORTOISE SHELL BRACKET +FE5E ; Common # Pe SMALL RIGHT TORTOISE SHELL BRACKET +FE5F..FE61 ; Common # Po [3] SMALL NUMBER SIGN..SMALL ASTERISK +FE62 ; Common # Sm SMALL PLUS SIGN +FE63 ; Common # Pd SMALL HYPHEN-MINUS +FE64..FE66 ; Common # Sm [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN +FE68 ; Common # Po SMALL REVERSE SOLIDUS +FE69 ; Common # Sc SMALL DOLLAR SIGN +FE6A..FE6B ; Common # Po [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT +FEFF ; Common # Cf ZERO WIDTH NO-BREAK SPACE +FF01..FF03 ; Common # Po [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN +FF04 ; Common # Sc FULLWIDTH DOLLAR SIGN +FF05..FF07 ; Common # Po [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE +FF08 ; Common # Ps FULLWIDTH LEFT PARENTHESIS +FF09 ; Common # Pe FULLWIDTH RIGHT PARENTHESIS +FF0A ; Common # Po FULLWIDTH ASTERISK +FF0B ; Common # Sm FULLWIDTH PLUS SIGN +FF0C ; Common # Po FULLWIDTH COMMA +FF0D ; Common # Pd FULLWIDTH HYPHEN-MINUS +FF0E..FF0F ; Common # Po [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS +FF10..FF19 ; Common # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE +FF1A..FF1B ; Common # Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON +FF1C..FF1E ; Common # Sm [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN +FF1F..FF20 ; Common # Po [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT +FF3B ; Common # Ps FULLWIDTH LEFT SQUARE BRACKET +FF3C ; Common # Po FULLWIDTH REVERSE SOLIDUS +FF3D ; Common # Pe FULLWIDTH RIGHT SQUARE BRACKET +FF3E ; Common # Sk FULLWIDTH CIRCUMFLEX ACCENT +FF3F ; Common # Pc FULLWIDTH LOW LINE +FF40 ; Common # Sk FULLWIDTH GRAVE ACCENT +FF5B ; Common # Ps FULLWIDTH LEFT CURLY BRACKET +FF5C ; Common # Sm FULLWIDTH VERTICAL LINE +FF5D ; Common # Pe FULLWIDTH RIGHT CURLY BRACKET +FF5E ; Common # Sm FULLWIDTH TILDE +FF5F ; Common # Ps FULLWIDTH LEFT WHITE PARENTHESIS +FF60 ; Common # Pe FULLWIDTH RIGHT WHITE PARENTHESIS +FF61 ; Common # Po HALFWIDTH IDEOGRAPHIC FULL STOP +FF62 ; Common # Ps HALFWIDTH LEFT CORNER BRACKET +FF63 ; Common # Pe HALFWIDTH RIGHT CORNER BRACKET +FF64..FF65 ; Common # Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT +FF70 ; Common # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK +FF9E..FF9F ; Common # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +FFE0..FFE1 ; Common # Sc [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN +FFE2 ; Common # Sm FULLWIDTH NOT SIGN +FFE3 ; Common # Sk FULLWIDTH MACRON +FFE4 ; Common # So FULLWIDTH BROKEN BAR +FFE5..FFE6 ; Common # Sc [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN +FFE8 ; Common # So HALFWIDTH FORMS LIGHT VERTICAL +FFE9..FFEC ; Common # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW +FFED..FFEE ; Common # So [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE +FFF9..FFFB ; Common # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR +FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHARACTER +10100..10102 ; Common # Po [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK +10107..10133 ; Common # No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND +10137..1013F ; Common # So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT +10190..1019B ; Common # So [12] ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN +101D0..101FC ; Common # So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND +102E1..102FB ; Common # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED +1BCA0..1BCA3 ; Common # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP +1D000..1D0F5 ; Common # So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO +1D100..1D126 ; Common # So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2 +1D129..1D164 ; Common # So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE +1D165..1D166 ; Common # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM +1D16A..1D16C ; Common # So [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3 +1D16D..1D172 ; Common # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 +1D173..1D17A ; Common # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE +1D183..1D184 ; Common # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN +1D18C..1D1A9 ; Common # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH +1D1AE..1D1E8 ; Common # So [59] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KIEVAN FLAT SIGN +1D300..1D356 ; Common # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING +1D360..1D371 ; Common # No [18] COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE +1D400..1D454 ; Common # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G +1D456..1D49C ; Common # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A +1D49E..1D49F ; Common # L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D +1D4A2 ; Common # L& MATHEMATICAL SCRIPT CAPITAL G +1D4A5..1D4A6 ; Common # L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K +1D4A9..1D4AC ; Common # L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q +1D4AE..1D4B9 ; Common # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D +1D4BB ; Common # L& MATHEMATICAL SCRIPT SMALL F +1D4BD..1D4C3 ; Common # L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N +1D4C5..1D505 ; Common # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B +1D507..1D50A ; Common # L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G +1D50D..1D514 ; Common # L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q +1D516..1D51C ; Common # L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y +1D51E..1D539 ; Common # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B +1D53B..1D53E ; Common # L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G +1D540..1D544 ; Common # L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M +1D546 ; Common # L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O +1D54A..1D550 ; Common # L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y +1D552..1D6A5 ; Common # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J +1D6A8..1D6C0 ; Common # L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA +1D6C1 ; Common # Sm MATHEMATICAL BOLD NABLA +1D6C2..1D6DA ; Common # L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA +1D6DB ; Common # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL +1D6DC..1D6FA ; Common # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA +1D6FB ; Common # Sm MATHEMATICAL ITALIC NABLA +1D6FC..1D714 ; Common # L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA +1D715 ; Common # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL +1D716..1D734 ; Common # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA +1D735 ; Common # Sm MATHEMATICAL BOLD ITALIC NABLA +1D736..1D74E ; Common # L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA +1D74F ; Common # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL +1D750..1D76E ; Common # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA +1D76F ; Common # Sm MATHEMATICAL SANS-SERIF BOLD NABLA +1D770..1D788 ; Common # L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA +1D789 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL +1D78A..1D7A8 ; Common # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA +1D7A9 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA +1D7AA..1D7C2 ; Common # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA +1D7C3 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL +1D7C4..1D7CB ; Common # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1D7CE..1D7FF ; Common # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE +1F000..1F02B ; Common # So [44] MAHJONG TILE EAST WIND..MAHJONG TILE BACK +1F030..1F093 ; Common # So [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06 +1F0A0..1F0AE ; Common # So [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES +1F0B1..1F0BF ; Common # So [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER +1F0C1..1F0CF ; Common # So [15] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD BLACK JOKER +1F0D1..1F0F5 ; Common # So [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21 +1F100..1F10C ; Common # No [13] DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO +1F110..1F12E ; Common # So [31] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED WZ +1F130..1F16B ; Common # So [60] SQUARED LATIN CAPITAL LETTER A..RAISED MD SIGN +1F170..1F1AC ; Common # So [61] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VOD +1F1E6..1F1FF ; Common # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z +1F201..1F202 ; Common # So [2] SQUARED KATAKANA KOKO..SQUARED KATAKANA SA +1F210..1F23B ; Common # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D +1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 +1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT +1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA +1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 +1F400..1F6D2 ; Common # So [723] RAT..SHOPPING TROLLEY +1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING +1F6F0..1F6F6 ; Common # So [7] SATELLITE..CANOE +1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE +1F780..1F7D4 ; Common # So [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR +1F800..1F80B ; Common # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD +1F810..1F847 ; Common # So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW +1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW +1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW +1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS +1F910..1F91E ; Common # So [15] ZIPPER-MOUTH FACE..HAND WITH INDEX AND MIDDLE FINGERS CROSSED +1F920..1F927 ; Common # So [8] FACE WITH COWBOY HAT..SNEEZING FACE +1F930 ; Common # So PREGNANT WOMAN +1F933..1F93E ; Common # So [12] SELFIE..HANDBALL +1F940..1F94B ; Common # So [12] WILTED FLOWER..MARTIAL ARTS UNIFORM +1F950..1F95E ; Common # So [15] CROISSANT..PANCAKES +1F980..1F991 ; Common # So [18] CRAB..SQUID +1F9C0 ; Common # So CHEESE WEDGE +E0001 ; Common # Cf LANGUAGE TAG +E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG + +# Total code points: 7279 + +# ================================================ + +0041..005A ; Latin # L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z +0061..007A ; Latin # L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z +00AA ; Latin # Lo FEMININE ORDINAL INDICATOR +00BA ; Latin # Lo MASCULINE ORDINAL INDICATOR +00C0..00D6 ; Latin # L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS +00D8..00F6 ; Latin # L& [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS +00F8..01BA ; Latin # L& [195] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL +01BB ; Latin # Lo LATIN LETTER TWO WITH STROKE +01BC..01BF ; Latin # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN +01C0..01C3 ; Latin # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK +01C4..0293 ; Latin # L& [208] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER EZH WITH CURL +0294 ; Latin # Lo LATIN LETTER GLOTTAL STOP +0295..02AF ; Latin # L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL +02B0..02B8 ; Latin # Lm [9] MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y +02E0..02E4 ; Latin # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP +1D00..1D25 ; Latin # L& [38] LATIN LETTER SMALL CAPITAL A..LATIN LETTER AIN +1D2C..1D5C ; Latin # Lm [49] MODIFIER LETTER CAPITAL A..MODIFIER LETTER SMALL AIN +1D62..1D65 ; Latin # Lm [4] LATIN SUBSCRIPT SMALL LETTER I..LATIN SUBSCRIPT SMALL LETTER V +1D6B..1D77 ; Latin # L& [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G +1D79..1D9A ; Latin # L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK +1D9B..1DBE ; Latin # Lm [36] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL EZH +1E00..1EFF ; Latin # L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP +2071 ; Latin # Lm SUPERSCRIPT LATIN SMALL LETTER I +207F ; Latin # Lm SUPERSCRIPT LATIN SMALL LETTER N +2090..209C ; Latin # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T +212A..212B ; Latin # L& [2] KELVIN SIGN..ANGSTROM SIGN +2132 ; Latin # L& TURNED CAPITAL F +214E ; Latin # L& TURNED SMALL F +2160..2182 ; Latin # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND +2183..2184 ; Latin # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C +2185..2188 ; Latin # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND +2C60..2C7B ; Latin # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E +2C7C..2C7D ; Latin # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V +2C7E..2C7F ; Latin # L& [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL +A722..A76F ; Latin # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON +A770 ; Latin # Lm MODIFIER LETTER US +A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T +A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT +A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT +A790..A7AE ; Latin # L& [31] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER SMALL CAPITAL I +A7B0..A7B7 ; Latin # L& [8] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER OMEGA +A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I +A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE +A7FA ; Latin # L& LATIN LETTER SMALL CAPITAL TURNED M +A7FB..A7FF ; Latin # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M +AB30..AB5A ; Latin # L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG +AB5C..AB5F ; Latin # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK +AB60..AB64 ; Latin # L& [5] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER INVERTED ALPHA +FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST +FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z +FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z + +# Total code points: 1350 + +# ================================================ + +0370..0373 ; Greek # L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI +0375 ; Greek # Sk GREEK LOWER NUMERAL SIGN +0376..0377 ; Greek # L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA +037A ; Greek # Lm GREEK YPOGEGRAMMENI +037B..037D ; Greek # L& [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL +037F ; Greek # L& GREEK CAPITAL LETTER YOT +0384 ; Greek # Sk GREEK TONOS +0386 ; Greek # L& GREEK CAPITAL LETTER ALPHA WITH TONOS +0388..038A ; Greek # L& [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS +038C ; Greek # L& GREEK CAPITAL LETTER OMICRON WITH TONOS +038E..03A1 ; Greek # L& [20] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER RHO +03A3..03E1 ; Greek # L& [63] GREEK CAPITAL LETTER SIGMA..GREEK SMALL LETTER SAMPI +03F0..03F5 ; Greek # L& [6] GREEK KAPPA SYMBOL..GREEK LUNATE EPSILON SYMBOL +03F6 ; Greek # Sm GREEK REVERSED LUNATE EPSILON SYMBOL +03F7..03FF ; Greek # L& [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL +1D26..1D2A ; Greek # L& [5] GREEK LETTER SMALL CAPITAL GAMMA..GREEK LETTER SMALL CAPITAL PSI +1D5D..1D61 ; Greek # Lm [5] MODIFIER LETTER SMALL BETA..MODIFIER LETTER SMALL CHI +1D66..1D6A ; Greek # Lm [5] GREEK SUBSCRIPT SMALL LETTER BETA..GREEK SUBSCRIPT SMALL LETTER CHI +1DBF ; Greek # Lm MODIFIER LETTER SMALL THETA +1F00..1F15 ; Greek # L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA +1F18..1F1D ; Greek # L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA +1F20..1F45 ; Greek # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA +1F48..1F4D ; Greek # L& [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA +1F50..1F57 ; Greek # L& [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI +1F59 ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA +1F5B ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA +1F5D ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA +1F5F..1F7D ; Greek # L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA +1F80..1FB4 ; Greek # L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI +1FB6..1FBC ; Greek # L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FBD ; Greek # Sk GREEK KORONIS +1FBE ; Greek # L& GREEK PROSGEGRAMMENI +1FBF..1FC1 ; Greek # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI +1FC2..1FC4 ; Greek # L& [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI +1FC6..1FCC ; Greek # L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FCD..1FCF ; Greek # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI +1FD0..1FD3 ; Greek # L& [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD6..1FDB ; Greek # L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA +1FDD..1FDF ; Greek # Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI +1FE0..1FEC ; Greek # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA +1FED..1FEF ; Greek # Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA +1FF2..1FF4 ; Greek # L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI +1FF6..1FFC ; Greek # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI +1FFD..1FFE ; Greek # Sk [2] GREEK OXIA..GREEK DASIA +2126 ; Greek # L& OHM SIGN +AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA +10140..10174 ; Greek # Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS +10175..10178 ; Greek # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN +10179..10189 ; Greek # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN +1018A..1018B ; Greek # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN +1018C..1018E ; Greek # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN +101A0 ; Greek # So GREEK SYMBOL TAU RHO +1D200..1D241 ; Greek # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 +1D242..1D244 ; Greek # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME +1D245 ; Greek # So GREEK MUSICAL LEIMMA + +# Total code points: 518 + +# ================================================ + +0400..0481 ; Cyrillic # L& [130] CYRILLIC CAPITAL LETTER IE WITH GRAVE..CYRILLIC SMALL LETTER KOPPA +0482 ; Cyrillic # So CYRILLIC THOUSANDS SIGN +0483..0484 ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC PALATALIZATION +0487 ; Cyrillic # Mn COMBINING CYRILLIC POKRYTIE +0488..0489 ; Cyrillic # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN +048A..052F ; Cyrillic # L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER +1C80..1C88 ; Cyrillic # L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK +1D2B ; Cyrillic # L& CYRILLIC LETTER SMALL CAPITAL EL +1D78 ; Cyrillic # Lm MODIFIER LETTER CYRILLIC EN +2DE0..2DFF ; Cyrillic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS +A640..A66D ; Cyrillic # L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O +A66E ; Cyrillic # Lo CYRILLIC LETTER MULTIOCULAR O +A66F ; Cyrillic # Mn COMBINING CYRILLIC VZMET +A670..A672 ; Cyrillic # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN +A673 ; Cyrillic # Po SLAVONIC ASTERISK +A674..A67D ; Cyrillic # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK +A67E ; Cyrillic # Po CYRILLIC KAVYKA +A67F ; Cyrillic # Lm CYRILLIC PAYEROK +A680..A69B ; Cyrillic # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O +A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN +A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E +FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + +# Total code points: 443 + +# ================================================ + +0531..0556 ; Armenian # L& [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH +0559 ; Armenian # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING +055A..055F ; Armenian # Po [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK +0561..0587 ; Armenian # L& [39] ARMENIAN SMALL LETTER AYB..ARMENIAN SMALL LIGATURE ECH YIWN +058A ; Armenian # Pd ARMENIAN HYPHEN +058D..058E ; Armenian # So [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN +058F ; Armenian # Sc ARMENIAN DRAM SIGN +FB13..FB17 ; Armenian # L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH + +# Total code points: 93 + +# ================================================ + +0591..05BD ; Hebrew # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG +05BE ; Hebrew # Pd HEBREW PUNCTUATION MAQAF +05BF ; Hebrew # Mn HEBREW POINT RAFE +05C0 ; Hebrew # Po HEBREW PUNCTUATION PASEQ +05C1..05C2 ; Hebrew # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT +05C3 ; Hebrew # Po HEBREW PUNCTUATION SOF PASUQ +05C4..05C5 ; Hebrew # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT +05C6 ; Hebrew # Po HEBREW PUNCTUATION NUN HAFUKHA +05C7 ; Hebrew # Mn HEBREW POINT QAMATS QATAN +05D0..05EA ; Hebrew # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV +05F0..05F2 ; Hebrew # Lo [3] HEBREW LIGATURE YIDDISH DOUBLE VAV..HEBREW LIGATURE YIDDISH DOUBLE YOD +05F3..05F4 ; Hebrew # Po [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM +FB1D ; Hebrew # Lo HEBREW LETTER YOD WITH HIRIQ +FB1E ; Hebrew # Mn HEBREW POINT JUDEO-SPANISH VARIKA +FB1F..FB28 ; Hebrew # Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV +FB29 ; Hebrew # Sm HEBREW LETTER ALTERNATIVE PLUS SIGN +FB2A..FB36 ; Hebrew # Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH +FB38..FB3C ; Hebrew # Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH +FB3E ; Hebrew # Lo HEBREW LETTER MEM WITH DAGESH +FB40..FB41 ; Hebrew # Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH +FB43..FB44 ; Hebrew # Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH +FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED + +# Total code points: 133 + +# ================================================ + +0600..0604 ; Arabic # Cf [5] ARABIC NUMBER SIGN..ARABIC SIGN SAMVAT +0606..0608 ; Arabic # Sm [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY +0609..060A ; Arabic # Po [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN +060B ; Arabic # Sc AFGHANI SIGN +060D ; Arabic # Po ARABIC DATE SEPARATOR +060E..060F ; Arabic # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA +0610..061A ; Arabic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA +061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK +0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE +0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH +0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW +0660..0669 ; Arabic # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE +066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR +066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF +0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE +06D4 ; Arabic # Po ARABIC FULL STOP +06D5 ; Arabic # Lo ARABIC LETTER AE +06D6..06DC ; Arabic # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN +06DE ; Arabic # So ARABIC START OF RUB EL HIZB +06DF..06E4 ; Arabic # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA +06E5..06E6 ; Arabic # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH +06E7..06E8 ; Arabic # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON +06E9 ; Arabic # So ARABIC PLACE OF SAJDAH +06EA..06ED ; Arabic # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM +06EE..06EF ; Arabic # Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V +06F0..06F9 ; Arabic # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE +06FA..06FC ; Arabic # Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW +06FD..06FE ; Arabic # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN +06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V +0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE +08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW +08B6..08BD ; Arabic # Lo [8] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON +08D4..08E1 ; Arabic # Mn [14] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA +08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA +FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM +FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW +FBD3..FD3D ; Arabic # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM +FD50..FD8F ; Arabic # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM +FD92..FDC7 ; Arabic # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM +FDF0..FDFB ; Arabic # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU +FDFC ; Arabic # Sc RIAL SIGN +FDFD ; Arabic # So ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM +FE70..FE74 ; Arabic # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM +FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM +10E60..10E7E ; Arabic # No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS +1EE00..1EE03 ; Arabic # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL +1EE05..1EE1F ; Arabic # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF +1EE21..1EE22 ; Arabic # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM +1EE24 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL HEH +1EE27 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL HAH +1EE29..1EE32 ; Arabic # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF +1EE34..1EE37 ; Arabic # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH +1EE39 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL DAD +1EE3B ; Arabic # Lo ARABIC MATHEMATICAL INITIAL GHAIN +1EE42 ; Arabic # Lo ARABIC MATHEMATICAL TAILED JEEM +1EE47 ; Arabic # Lo ARABIC MATHEMATICAL TAILED HAH +1EE49 ; Arabic # Lo ARABIC MATHEMATICAL TAILED YEH +1EE4B ; Arabic # Lo ARABIC MATHEMATICAL TAILED LAM +1EE4D..1EE4F ; Arabic # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN +1EE51..1EE52 ; Arabic # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF +1EE54 ; Arabic # Lo ARABIC MATHEMATICAL TAILED SHEEN +1EE57 ; Arabic # Lo ARABIC MATHEMATICAL TAILED KHAH +1EE59 ; Arabic # Lo ARABIC MATHEMATICAL TAILED DAD +1EE5B ; Arabic # Lo ARABIC MATHEMATICAL TAILED GHAIN +1EE5D ; Arabic # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON +1EE5F ; Arabic # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF +1EE61..1EE62 ; Arabic # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM +1EE64 ; Arabic # Lo ARABIC MATHEMATICAL STRETCHED HEH +1EE67..1EE6A ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF +1EE6C..1EE72 ; Arabic # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF +1EE74..1EE77 ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH +1EE79..1EE7C ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH +1EE7E ; Arabic # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH +1EE80..1EE89 ; Arabic # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH +1EE8B..1EE9B ; Arabic # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN +1EEA1..1EEA3 ; Arabic # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL +1EEA5..1EEA9 ; Arabic # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH +1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN +1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL + +# Total code points: 1279 + +# ================================================ + +0700..070D ; Syriac # Po [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS +070F ; Syriac # Cf SYRIAC ABBREVIATION MARK +0710 ; Syriac # Lo SYRIAC LETTER ALAPH +0711 ; Syriac # Mn SYRIAC LETTER SUPERSCRIPT ALAPH +0712..072F ; Syriac # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH +0730..074A ; Syriac # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH +074D..074F ; Syriac # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE + +# Total code points: 77 + +# ================================================ + +0780..07A5 ; Thaana # Lo [38] THAANA LETTER HAA..THAANA LETTER WAAVU +07A6..07B0 ; Thaana # Mn [11] THAANA ABAFILI..THAANA SUKUN +07B1 ; Thaana # Lo THAANA LETTER NAA + +# Total code points: 50 + +# ================================================ + +0900..0902 ; Devanagari # Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA +0903 ; Devanagari # Mc DEVANAGARI SIGN VISARGA +0904..0939 ; Devanagari # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA +093A ; Devanagari # Mn DEVANAGARI VOWEL SIGN OE +093B ; Devanagari # Mc DEVANAGARI VOWEL SIGN OOE +093C ; Devanagari # Mn DEVANAGARI SIGN NUKTA +093D ; Devanagari # Lo DEVANAGARI SIGN AVAGRAHA +093E..0940 ; Devanagari # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II +0941..0948 ; Devanagari # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI +0949..094C ; Devanagari # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU +094D ; Devanagari # Mn DEVANAGARI SIGN VIRAMA +094E..094F ; Devanagari # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW +0950 ; Devanagari # Lo DEVANAGARI OM +0953..0957 ; Devanagari # Mn [5] DEVANAGARI GRAVE ACCENT..DEVANAGARI VOWEL SIGN UUE +0958..0961 ; Devanagari # Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL +0962..0963 ; Devanagari # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL +0966..096F ; Devanagari # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE +0970 ; Devanagari # Po DEVANAGARI ABBREVIATION SIGN +0971 ; Devanagari # Lm DEVANAGARI SIGN HIGH SPACING DOT +0972..097F ; Devanagari # Lo [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA +A8E0..A8F1 ; Devanagari # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA +A8F2..A8F7 ; Devanagari # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA +A8F8..A8FA ; Devanagari # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET +A8FB ; Devanagari # Lo DEVANAGARI HEADSTROKE +A8FC ; Devanagari # Po DEVANAGARI SIGN SIDDHAM +A8FD ; Devanagari # Lo DEVANAGARI JAIN OM + +# Total code points: 154 + +# ================================================ + +0980 ; Bengali # Lo BENGALI ANJI +0981 ; Bengali # Mn BENGALI SIGN CANDRABINDU +0982..0983 ; Bengali # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA +0985..098C ; Bengali # Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L +098F..0990 ; Bengali # Lo [2] BENGALI LETTER E..BENGALI LETTER AI +0993..09A8 ; Bengali # Lo [22] BENGALI LETTER O..BENGALI LETTER NA +09AA..09B0 ; Bengali # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA +09B2 ; Bengali # Lo BENGALI LETTER LA +09B6..09B9 ; Bengali # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA +09BC ; Bengali # Mn BENGALI SIGN NUKTA +09BD ; Bengali # Lo BENGALI SIGN AVAGRAHA +09BE..09C0 ; Bengali # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II +09C1..09C4 ; Bengali # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR +09C7..09C8 ; Bengali # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI +09CB..09CC ; Bengali # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU +09CD ; Bengali # Mn BENGALI SIGN VIRAMA +09CE ; Bengali # Lo BENGALI LETTER KHANDA TA +09D7 ; Bengali # Mc BENGALI AU LENGTH MARK +09DC..09DD ; Bengali # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA +09DF..09E1 ; Bengali # Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL +09E2..09E3 ; Bengali # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL +09E6..09EF ; Bengali # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE +09F0..09F1 ; Bengali # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL +09F2..09F3 ; Bengali # Sc [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN +09F4..09F9 ; Bengali # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN +09FA ; Bengali # So BENGALI ISSHAR +09FB ; Bengali # Sc BENGALI GANDA MARK + +# Total code points: 93 + +# ================================================ + +0A01..0A02 ; Gurmukhi # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI +0A03 ; Gurmukhi # Mc GURMUKHI SIGN VISARGA +0A05..0A0A ; Gurmukhi # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU +0A0F..0A10 ; Gurmukhi # Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI +0A13..0A28 ; Gurmukhi # Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA +0A2A..0A30 ; Gurmukhi # Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA +0A32..0A33 ; Gurmukhi # Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA +0A35..0A36 ; Gurmukhi # Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA +0A38..0A39 ; Gurmukhi # Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA +0A3C ; Gurmukhi # Mn GURMUKHI SIGN NUKTA +0A3E..0A40 ; Gurmukhi # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II +0A41..0A42 ; Gurmukhi # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU +0A47..0A48 ; Gurmukhi # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI +0A4B..0A4D ; Gurmukhi # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA +0A51 ; Gurmukhi # Mn GURMUKHI SIGN UDAAT +0A59..0A5C ; Gurmukhi # Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA +0A5E ; Gurmukhi # Lo GURMUKHI LETTER FA +0A66..0A6F ; Gurmukhi # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE +0A70..0A71 ; Gurmukhi # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK +0A72..0A74 ; Gurmukhi # Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR +0A75 ; Gurmukhi # Mn GURMUKHI SIGN YAKASH + +# Total code points: 79 + +# ================================================ + +0A81..0A82 ; Gujarati # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA +0A83 ; Gujarati # Mc GUJARATI SIGN VISARGA +0A85..0A8D ; Gujarati # Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E +0A8F..0A91 ; Gujarati # Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O +0A93..0AA8 ; Gujarati # Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA +0AAA..0AB0 ; Gujarati # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA +0AB2..0AB3 ; Gujarati # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA +0AB5..0AB9 ; Gujarati # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA +0ABC ; Gujarati # Mn GUJARATI SIGN NUKTA +0ABD ; Gujarati # Lo GUJARATI SIGN AVAGRAHA +0ABE..0AC0 ; Gujarati # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II +0AC1..0AC5 ; Gujarati # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E +0AC7..0AC8 ; Gujarati # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI +0AC9 ; Gujarati # Mc GUJARATI VOWEL SIGN CANDRA O +0ACB..0ACC ; Gujarati # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU +0ACD ; Gujarati # Mn GUJARATI SIGN VIRAMA +0AD0 ; Gujarati # Lo GUJARATI OM +0AE0..0AE1 ; Gujarati # Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL +0AE2..0AE3 ; Gujarati # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL +0AE6..0AEF ; Gujarati # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE +0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN +0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN +0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA + +# Total code points: 85 + +# ================================================ + +0B01 ; Oriya # Mn ORIYA SIGN CANDRABINDU +0B02..0B03 ; Oriya # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA +0B05..0B0C ; Oriya # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L +0B0F..0B10 ; Oriya # Lo [2] ORIYA LETTER E..ORIYA LETTER AI +0B13..0B28 ; Oriya # Lo [22] ORIYA LETTER O..ORIYA LETTER NA +0B2A..0B30 ; Oriya # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA +0B32..0B33 ; Oriya # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA +0B35..0B39 ; Oriya # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA +0B3C ; Oriya # Mn ORIYA SIGN NUKTA +0B3D ; Oriya # Lo ORIYA SIGN AVAGRAHA +0B3E ; Oriya # Mc ORIYA VOWEL SIGN AA +0B3F ; Oriya # Mn ORIYA VOWEL SIGN I +0B40 ; Oriya # Mc ORIYA VOWEL SIGN II +0B41..0B44 ; Oriya # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR +0B47..0B48 ; Oriya # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI +0B4B..0B4C ; Oriya # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU +0B4D ; Oriya # Mn ORIYA SIGN VIRAMA +0B56 ; Oriya # Mn ORIYA AI LENGTH MARK +0B57 ; Oriya # Mc ORIYA AU LENGTH MARK +0B5C..0B5D ; Oriya # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA +0B5F..0B61 ; Oriya # Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL +0B62..0B63 ; Oriya # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL +0B66..0B6F ; Oriya # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE +0B70 ; Oriya # So ORIYA ISSHAR +0B71 ; Oriya # Lo ORIYA LETTER WA +0B72..0B77 ; Oriya # No [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS + +# Total code points: 90 + +# ================================================ + +0B82 ; Tamil # Mn TAMIL SIGN ANUSVARA +0B83 ; Tamil # Lo TAMIL SIGN VISARGA +0B85..0B8A ; Tamil # Lo [6] TAMIL LETTER A..TAMIL LETTER UU +0B8E..0B90 ; Tamil # Lo [3] TAMIL LETTER E..TAMIL LETTER AI +0B92..0B95 ; Tamil # Lo [4] TAMIL LETTER O..TAMIL LETTER KA +0B99..0B9A ; Tamil # Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA +0B9C ; Tamil # Lo TAMIL LETTER JA +0B9E..0B9F ; Tamil # Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA +0BA3..0BA4 ; Tamil # Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA +0BA8..0BAA ; Tamil # Lo [3] TAMIL LETTER NA..TAMIL LETTER PA +0BAE..0BB9 ; Tamil # Lo [12] TAMIL LETTER MA..TAMIL LETTER HA +0BBE..0BBF ; Tamil # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I +0BC0 ; Tamil # Mn TAMIL VOWEL SIGN II +0BC1..0BC2 ; Tamil # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU +0BC6..0BC8 ; Tamil # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI +0BCA..0BCC ; Tamil # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU +0BCD ; Tamil # Mn TAMIL SIGN VIRAMA +0BD0 ; Tamil # Lo TAMIL OM +0BD7 ; Tamil # Mc TAMIL AU LENGTH MARK +0BE6..0BEF ; Tamil # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE +0BF0..0BF2 ; Tamil # No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND +0BF3..0BF8 ; Tamil # So [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN +0BF9 ; Tamil # Sc TAMIL RUPEE SIGN +0BFA ; Tamil # So TAMIL NUMBER SIGN + +# Total code points: 72 + +# ================================================ + +0C00 ; Telugu # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE +0C01..0C03 ; Telugu # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA +0C05..0C0C ; Telugu # Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L +0C0E..0C10 ; Telugu # Lo [3] TELUGU LETTER E..TELUGU LETTER AI +0C12..0C28 ; Telugu # Lo [23] TELUGU LETTER O..TELUGU LETTER NA +0C2A..0C39 ; Telugu # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA +0C3D ; Telugu # Lo TELUGU SIGN AVAGRAHA +0C3E..0C40 ; Telugu # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II +0C41..0C44 ; Telugu # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR +0C46..0C48 ; Telugu # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI +0C4A..0C4D ; Telugu # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA +0C55..0C56 ; Telugu # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK +0C58..0C5A ; Telugu # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C60..0C61 ; Telugu # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL +0C62..0C63 ; Telugu # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL +0C66..0C6F ; Telugu # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE +0C78..0C7E ; Telugu # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR +0C7F ; Telugu # So TELUGU SIGN TUUMU + +# Total code points: 96 + +# ================================================ + +0C80 ; Kannada # Lo KANNADA SIGN SPACING CANDRABINDU +0C81 ; Kannada # Mn KANNADA SIGN CANDRABINDU +0C82..0C83 ; Kannada # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA +0C85..0C8C ; Kannada # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L +0C8E..0C90 ; Kannada # Lo [3] KANNADA LETTER E..KANNADA LETTER AI +0C92..0CA8 ; Kannada # Lo [23] KANNADA LETTER O..KANNADA LETTER NA +0CAA..0CB3 ; Kannada # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA +0CB5..0CB9 ; Kannada # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA +0CBC ; Kannada # Mn KANNADA SIGN NUKTA +0CBD ; Kannada # Lo KANNADA SIGN AVAGRAHA +0CBE ; Kannada # Mc KANNADA VOWEL SIGN AA +0CBF ; Kannada # Mn KANNADA VOWEL SIGN I +0CC0..0CC4 ; Kannada # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR +0CC6 ; Kannada # Mn KANNADA VOWEL SIGN E +0CC7..0CC8 ; Kannada # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI +0CCA..0CCB ; Kannada # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO +0CCC..0CCD ; Kannada # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA +0CD5..0CD6 ; Kannada # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK +0CDE ; Kannada # Lo KANNADA LETTER FA +0CE0..0CE1 ; Kannada # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL +0CE2..0CE3 ; Kannada # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL +0CE6..0CEF ; Kannada # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE +0CF1..0CF2 ; Kannada # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + +# Total code points: 88 + +# ================================================ + +0D01 ; Malayalam # Mn MALAYALAM SIGN CANDRABINDU +0D02..0D03 ; Malayalam # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA +0D05..0D0C ; Malayalam # Lo [8] MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L +0D0E..0D10 ; Malayalam # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI +0D12..0D3A ; Malayalam # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA +0D3D ; Malayalam # Lo MALAYALAM SIGN AVAGRAHA +0D3E..0D40 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II +0D41..0D44 ; Malayalam # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR +0D46..0D48 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI +0D4A..0D4C ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU +0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA +0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH +0D4F ; Malayalam # So MALAYALAM SIGN PARA +0D54..0D56 ; Malayalam # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL +0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK +0D58..0D5E ; Malayalam # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH +0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL +0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL +0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE +0D70..0D78 ; Malayalam # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS +0D79 ; Malayalam # So MALAYALAM DATE MARK +0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K + +# Total code points: 114 + +# ================================================ + +0D82..0D83 ; Sinhala # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA +0D85..0D96 ; Sinhala # Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA +0D9A..0DB1 ; Sinhala # Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA +0DB3..0DBB ; Sinhala # Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA +0DBD ; Sinhala # Lo SINHALA LETTER DANTAJA LAYANNA +0DC0..0DC6 ; Sinhala # Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA +0DCA ; Sinhala # Mn SINHALA SIGN AL-LAKUNA +0DCF..0DD1 ; Sinhala # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA +0DD2..0DD4 ; Sinhala # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA +0DD6 ; Sinhala # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA +0DD8..0DDF ; Sinhala # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA +0DE6..0DEF ; Sinhala # Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE +0DF2..0DF3 ; Sinhala # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA +0DF4 ; Sinhala # Po SINHALA PUNCTUATION KUNDDALIYA +111E1..111F4 ; Sinhala # No [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND + +# Total code points: 110 + +# ================================================ + +0E01..0E30 ; Thai # Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A +0E31 ; Thai # Mn THAI CHARACTER MAI HAN-AKAT +0E32..0E33 ; Thai # Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM +0E34..0E3A ; Thai # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU +0E40..0E45 ; Thai # Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO +0E46 ; Thai # Lm THAI CHARACTER MAIYAMOK +0E47..0E4E ; Thai # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN +0E4F ; Thai # Po THAI CHARACTER FONGMAN +0E50..0E59 ; Thai # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE +0E5A..0E5B ; Thai # Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT + +# Total code points: 86 + +# ================================================ + +0E81..0E82 ; Lao # Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG +0E84 ; Lao # Lo LAO LETTER KHO TAM +0E87..0E88 ; Lao # Lo [2] LAO LETTER NGO..LAO LETTER CO +0E8A ; Lao # Lo LAO LETTER SO TAM +0E8D ; Lao # Lo LAO LETTER NYO +0E94..0E97 ; Lao # Lo [4] LAO LETTER DO..LAO LETTER THO TAM +0E99..0E9F ; Lao # Lo [7] LAO LETTER NO..LAO LETTER FO SUNG +0EA1..0EA3 ; Lao # Lo [3] LAO LETTER MO..LAO LETTER LO LING +0EA5 ; Lao # Lo LAO LETTER LO LOOT +0EA7 ; Lao # Lo LAO LETTER WO +0EAA..0EAB ; Lao # Lo [2] LAO LETTER SO SUNG..LAO LETTER HO SUNG +0EAD..0EB0 ; Lao # Lo [4] LAO LETTER O..LAO VOWEL SIGN A +0EB1 ; Lao # Mn LAO VOWEL SIGN MAI KAN +0EB2..0EB3 ; Lao # Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM +0EB4..0EB9 ; Lao # Mn [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU +0EBB..0EBC ; Lao # Mn [2] LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN LO +0EBD ; Lao # Lo LAO SEMIVOWEL SIGN NYO +0EC0..0EC4 ; Lao # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI +0EC6 ; Lao # Lm LAO KO LA +0EC8..0ECD ; Lao # Mn [6] LAO TONE MAI EK..LAO NIGGAHITA +0ED0..0ED9 ; Lao # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE +0EDC..0EDF ; Lao # Lo [4] LAO HO NO..LAO LETTER KHMU NYO + +# Total code points: 67 + +# ================================================ + +0F00 ; Tibetan # Lo TIBETAN SYLLABLE OM +0F01..0F03 ; Tibetan # So [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA +0F04..0F12 ; Tibetan # Po [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD +0F13 ; Tibetan # So TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN +0F14 ; Tibetan # Po TIBETAN MARK GTER TSHEG +0F15..0F17 ; Tibetan # So [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS +0F18..0F19 ; Tibetan # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS +0F1A..0F1F ; Tibetan # So [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG +0F20..0F29 ; Tibetan # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE +0F2A..0F33 ; Tibetan # No [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO +0F34 ; Tibetan # So TIBETAN MARK BSDUS RTAGS +0F35 ; Tibetan # Mn TIBETAN MARK NGAS BZUNG NYI ZLA +0F36 ; Tibetan # So TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN +0F37 ; Tibetan # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS +0F38 ; Tibetan # So TIBETAN MARK CHE MGO +0F39 ; Tibetan # Mn TIBETAN MARK TSA -PHRU +0F3A ; Tibetan # Ps TIBETAN MARK GUG RTAGS GYON +0F3B ; Tibetan # Pe TIBETAN MARK GUG RTAGS GYAS +0F3C ; Tibetan # Ps TIBETAN MARK ANG KHANG GYON +0F3D ; Tibetan # Pe TIBETAN MARK ANG KHANG GYAS +0F3E..0F3F ; Tibetan # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES +0F40..0F47 ; Tibetan # Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA +0F49..0F6C ; Tibetan # Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA +0F71..0F7E ; Tibetan # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO +0F7F ; Tibetan # Mc TIBETAN SIGN RNAM BCAD +0F80..0F84 ; Tibetan # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA +0F85 ; Tibetan # Po TIBETAN MARK PALUTA +0F86..0F87 ; Tibetan # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS +0F88..0F8C ; Tibetan # Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN +0F8D..0F97 ; Tibetan # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA +0F99..0FBC ; Tibetan # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA +0FBE..0FC5 ; Tibetan # So [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE +0FC6 ; Tibetan # Mn TIBETAN SYMBOL PADMA GDAN +0FC7..0FCC ; Tibetan # So [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL +0FCE..0FCF ; Tibetan # So [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM +0FD0..0FD4 ; Tibetan # Po [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA +0FD9..0FDA ; Tibetan # Po [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS + +# Total code points: 207 + +# ================================================ + +1000..102A ; Myanmar # Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU +102B..102C ; Myanmar # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA +102D..1030 ; Myanmar # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU +1031 ; Myanmar # Mc MYANMAR VOWEL SIGN E +1032..1037 ; Myanmar # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW +1038 ; Myanmar # Mc MYANMAR SIGN VISARGA +1039..103A ; Myanmar # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT +103B..103C ; Myanmar # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA +103D..103E ; Myanmar # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA +103F ; Myanmar # Lo MYANMAR LETTER GREAT SA +1040..1049 ; Myanmar # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE +104A..104F ; Myanmar # Po [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE +1050..1055 ; Myanmar # Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL +1056..1057 ; Myanmar # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR +1058..1059 ; Myanmar # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL +105A..105D ; Myanmar # Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE +105E..1060 ; Myanmar # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA +1061 ; Myanmar # Lo MYANMAR LETTER SGAW KAREN SHA +1062..1064 ; Myanmar # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO +1065..1066 ; Myanmar # Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA +1067..106D ; Myanmar # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 +106E..1070 ; Myanmar # Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA +1071..1074 ; Myanmar # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE +1075..1081 ; Myanmar # Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA +1082 ; Myanmar # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA +1083..1084 ; Myanmar # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E +1085..1086 ; Myanmar # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y +1087..108C ; Myanmar # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 +108D ; Myanmar # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE +108E ; Myanmar # Lo MYANMAR LETTER RUMAI PALAUNG FA +108F ; Myanmar # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 +1090..1099 ; Myanmar # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE +109A..109C ; Myanmar # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A +109D ; Myanmar # Mn MYANMAR VOWEL SIGN AITON AI +109E..109F ; Myanmar # So [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION +A9E0..A9E4 ; Myanmar # Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA +A9E5 ; Myanmar # Mn MYANMAR SIGN SHAN SAW +A9E6 ; Myanmar # Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION +A9E7..A9EF ; Myanmar # Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA +A9F0..A9F9 ; Myanmar # Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE +A9FA..A9FE ; Myanmar # Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA +AA60..AA6F ; Myanmar # Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA +AA70 ; Myanmar # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION +AA71..AA76 ; Myanmar # Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM +AA77..AA79 ; Myanmar # So [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO +AA7A ; Myanmar # Lo MYANMAR LETTER AITON RA +AA7B ; Myanmar # Mc MYANMAR SIGN PAO KAREN TONE +AA7C ; Myanmar # Mn MYANMAR SIGN TAI LAING TONE-2 +AA7D ; Myanmar # Mc MYANMAR SIGN TAI LAING TONE-5 +AA7E..AA7F ; Myanmar # Lo [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA + +# Total code points: 223 + +# ================================================ + +10A0..10C5 ; Georgian # L& [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE +10C7 ; Georgian # L& GEORGIAN CAPITAL LETTER YN +10CD ; Georgian # L& GEORGIAN CAPITAL LETTER AEN +10D0..10FA ; Georgian # Lo [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN +10FC ; Georgian # Lm MODIFIER LETTER GEORGIAN NAR +10FD..10FF ; Georgian # Lo [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN +2D00..2D25 ; Georgian # L& [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE +2D27 ; Georgian # L& GEORGIAN SMALL LETTER YN +2D2D ; Georgian # L& GEORGIAN SMALL LETTER AEN + +# Total code points: 127 + +# ================================================ + +1100..11FF ; Hangul # Lo [256] HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN +302E..302F ; Hangul # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK +3131..318E ; Hangul # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE +3200..321E ; Hangul # So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU +3260..327E ; Hangul # So [31] CIRCLED HANGUL KIYEOK..CIRCLED HANGUL IEUNG U +A960..A97C ; Hangul # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH +AC00..D7A3 ; Hangul # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH +D7B0..D7C6 ; Hangul # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E +D7CB..D7FB ; Hangul # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH +FFA0..FFBE ; Hangul # Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH +FFC2..FFC7 ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E +FFCA..FFCF ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE +FFD2..FFD7 ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU +FFDA..FFDC ; Hangul # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I + +# Total code points: 11739 + +# ================================================ + +1200..1248 ; Ethiopic # Lo [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA +124A..124D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE +1250..1256 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO +1258 ; Ethiopic # Lo ETHIOPIC SYLLABLE QHWA +125A..125D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE +1260..1288 ; Ethiopic # Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA +128A..128D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE +1290..12B0 ; Ethiopic # Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA +12B2..12B5 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE +12B8..12BE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO +12C0 ; Ethiopic # Lo ETHIOPIC SYLLABLE KXWA +12C2..12C5 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE +12C8..12D6 ; Ethiopic # Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O +12D8..1310 ; Ethiopic # Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA +1312..1315 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE +1318..135A ; Ethiopic # Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA +135D..135F ; Ethiopic # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK +1360..1368 ; Ethiopic # Po [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR +1369..137C ; Ethiopic # No [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND +1380..138F ; Ethiopic # Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE +1390..1399 ; Ethiopic # So [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT +2D80..2D96 ; Ethiopic # Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE +2DA0..2DA6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO +2DA8..2DAE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO +2DB0..2DB6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO +2DB8..2DBE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO +2DC0..2DC6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO +2DC8..2DCE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO +2DD0..2DD6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO +2DD8..2DDE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO +AB01..AB06 ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO +AB09..AB0E ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO +AB11..AB16 ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO +AB20..AB26 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO +AB28..AB2E ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO + +# Total code points: 495 + +# ================================================ + +13A0..13F5 ; Cherokee # L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV +13F8..13FD ; Cherokee # L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV +AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA + +# Total code points: 172 + +# ================================================ + +1400 ; Canadian_Aboriginal # Pd CANADIAN SYLLABICS HYPHEN +1401..166C ; Canadian_Aboriginal # Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA +166D..166E ; Canadian_Aboriginal # Po [2] CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLABICS FULL STOP +166F..167F ; Canadian_Aboriginal # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W +18B0..18F5 ; Canadian_Aboriginal # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S + +# Total code points: 710 + +# ================================================ + +1680 ; Ogham # Zs OGHAM SPACE MARK +1681..169A ; Ogham # Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH +169B ; Ogham # Ps OGHAM FEATHER MARK +169C ; Ogham # Pe OGHAM REVERSED FEATHER MARK + +# Total code points: 29 + +# ================================================ + +16A0..16EA ; Runic # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X +16EE..16F0 ; Runic # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL +16F1..16F8 ; Runic # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC + +# Total code points: 86 + +# ================================================ + +1780..17B3 ; Khmer # Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU +17B4..17B5 ; Khmer # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA +17B6 ; Khmer # Mc KHMER VOWEL SIGN AA +17B7..17BD ; Khmer # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA +17BE..17C5 ; Khmer # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU +17C6 ; Khmer # Mn KHMER SIGN NIKAHIT +17C7..17C8 ; Khmer # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU +17C9..17D3 ; Khmer # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT +17D4..17D6 ; Khmer # Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH +17D7 ; Khmer # Lm KHMER SIGN LEK TOO +17D8..17DA ; Khmer # Po [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT +17DB ; Khmer # Sc KHMER CURRENCY SYMBOL RIEL +17DC ; Khmer # Lo KHMER SIGN AVAKRAHASANYA +17DD ; Khmer # Mn KHMER SIGN ATTHACAN +17E0..17E9 ; Khmer # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE +17F0..17F9 ; Khmer # No [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON +19E0..19FF ; Khmer # So [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC + +# Total code points: 146 + +# ================================================ + +1800..1801 ; Mongolian # Po [2] MONGOLIAN BIRGA..MONGOLIAN ELLIPSIS +1804 ; Mongolian # Po MONGOLIAN COLON +1806 ; Mongolian # Pd MONGOLIAN TODO SOFT HYPHEN +1807..180A ; Mongolian # Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU +180B..180D ; Mongolian # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180E ; Mongolian # Cf MONGOLIAN VOWEL SEPARATOR +1810..1819 ; Mongolian # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE +1820..1842 ; Mongolian # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI +1843 ; Mongolian # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN +1844..1877 ; Mongolian # Lo [52] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER MANCHU ZHA +1880..1884 ; Mongolian # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA +1885..1886 ; Mongolian # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +1887..18A8 ; Mongolian # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA +18A9 ; Mongolian # Mn MONGOLIAN LETTER ALI GALI DAGALGA +18AA ; Mongolian # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA +11660..1166C ; Mongolian # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT + +# Total code points: 166 + +# ================================================ + +3041..3096 ; Hiragana # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE +309D..309E ; Hiragana # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK +309F ; Hiragana # Lo HIRAGANA DIGRAPH YORI +1B001 ; Hiragana # Lo HIRAGANA LETTER ARCHAIC YE +1F200 ; Hiragana # So SQUARE HIRAGANA HOKA + +# Total code points: 91 + +# ================================================ + +30A1..30FA ; Katakana # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO +30FD..30FE ; Katakana # Lm [2] KATAKANA ITERATION MARK..KATAKANA VOICED ITERATION MARK +30FF ; Katakana # Lo KATAKANA DIGRAPH KOTO +31F0..31FF ; Katakana # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO +32D0..32FE ; Katakana # So [47] CIRCLED KATAKANA A..CIRCLED KATAKANA WO +3300..3357 ; Katakana # So [88] SQUARE APAATO..SQUARE WATTO +FF66..FF6F ; Katakana # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU +FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N +1B000 ; Katakana # Lo KATAKANA LETTER ARCHAIC E + +# Total code points: 300 + +# ================================================ + +02EA..02EB ; Bopomofo # Sk [2] MODIFIER LETTER YIN DEPARTING TONE MARK..MODIFIER LETTER YANG DEPARTING TONE MARK +3105..312D ; Bopomofo # Lo [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH +31A0..31BA ; Bopomofo # Lo [27] BOPOMOFO LETTER BU..BOPOMOFO LETTER ZY + +# Total code points: 70 + +# ================================================ + +2E80..2E99 ; Han # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP +2E9B..2EF3 ; Han # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE +2F00..2FD5 ; Han # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE +3005 ; Han # Lm IDEOGRAPHIC ITERATION MARK +3007 ; Han # Nl IDEOGRAPHIC NUMBER ZERO +3021..3029 ; Han # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE +3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY +303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK +3400..4DB5 ; Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5 +4E00..9FD5 ; Han # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5 +F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D +FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 +20000..2A6D6 ; Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6 +2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 +2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D +2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 +2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D + +# Total code points: 81734 + +# ================================================ + +A000..A014 ; Yi # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +A015 ; Yi # Lm YI SYLLABLE WU +A016..A48C ; Yi # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR +A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE + +# Total code points: 1220 + +# ================================================ + +10300..1031F ; Old_Italic # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS +10320..10323 ; Old_Italic # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY + +# Total code points: 36 + +# ================================================ + +10330..10340 ; Gothic # Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA +10341 ; Gothic # Nl GOTHIC LETTER NINETY +10342..10349 ; Gothic # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL +1034A ; Gothic # Nl GOTHIC LETTER NINE HUNDRED + +# Total code points: 27 + +# ================================================ + +10400..1044F ; Deseret # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW + +# Total code points: 80 + +# ================================================ + +0300..036F ; Inherited # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X +0485..0486 ; Inherited # Mn [2] COMBINING CYRILLIC DASIA PNEUMATA..COMBINING CYRILLIC PSILI PNEUMATA +064B..0655 ; Inherited # Mn [11] ARABIC FATHATAN..ARABIC HAMZA BELOW +0670 ; Inherited # Mn ARABIC LETTER SUPERSCRIPT ALEF +0951..0952 ; Inherited # Mn [2] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI STRESS SIGN ANUDATTA +1AB0..1ABD ; Inherited # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW +1ABE ; Inherited # Me COMBINING PARENTHESES OVERLAY +1CD0..1CD2 ; Inherited # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA +1CD4..1CE0 ; Inherited # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA +1CE2..1CE8 ; Inherited # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL +1CED ; Inherited # Mn VEDIC SIGN TIRYAK +1CF4 ; Inherited # Mn VEDIC TONE CANDRA ABOVE +1CF8..1CF9 ; Inherited # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE +1DC0..1DF5 ; Inherited # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE +1DFB..1DFF ; Inherited # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +200C..200D ; Inherited # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER +20D0..20DC ; Inherited # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE +20DD..20E0 ; Inherited # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH +20E1 ; Inherited # Mn COMBINING LEFT RIGHT ARROW ABOVE +20E2..20E4 ; Inherited # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE +20E5..20F0 ; Inherited # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE +302A..302D ; Inherited # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK +3099..309A ; Inherited # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +FE00..FE0F ; Inherited # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 +FE20..FE2D ; Inherited # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON BELOW +101FD ; Inherited # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE +102E0 ; Inherited # Mn COPTIC EPACT THOUSANDS MARK +1D167..1D169 ; Inherited # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 +1D17B..1D182 ; Inherited # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE +1D185..1D18B ; Inherited # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE +1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO +E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + +# Total code points: 564 + +# ================================================ + +1700..170C ; Tagalog # Lo [13] TAGALOG LETTER A..TAGALOG LETTER YA +170E..1711 ; Tagalog # Lo [4] TAGALOG LETTER LA..TAGALOG LETTER HA +1712..1714 ; Tagalog # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + +# Total code points: 20 + +# ================================================ + +1720..1731 ; Hanunoo # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA +1732..1734 ; Hanunoo # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD + +# Total code points: 21 + +# ================================================ + +1740..1751 ; Buhid # Lo [18] BUHID LETTER A..BUHID LETTER HA +1752..1753 ; Buhid # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + +# Total code points: 20 + +# ================================================ + +1760..176C ; Tagbanwa # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA +176E..1770 ; Tagbanwa # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA +1772..1773 ; Tagbanwa # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + +# Total code points: 18 + +# ================================================ + +1900..191E ; Limbu # Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA +1920..1922 ; Limbu # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U +1923..1926 ; Limbu # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU +1927..1928 ; Limbu # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O +1929..192B ; Limbu # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA +1930..1931 ; Limbu # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA +1932 ; Limbu # Mn LIMBU SMALL LETTER ANUSVARA +1933..1938 ; Limbu # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA +1939..193B ; Limbu # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I +1940 ; Limbu # So LIMBU SIGN LOO +1944..1945 ; Limbu # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK +1946..194F ; Limbu # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + +# Total code points: 68 + +# ================================================ + +1950..196D ; Tai_Le # Lo [30] TAI LE LETTER KA..TAI LE LETTER AI +1970..1974 ; Tai_Le # Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6 + +# Total code points: 35 + +# ================================================ + +10000..1000B ; Linear_B # Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE +1000D..10026 ; Linear_B # Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO +10028..1003A ; Linear_B # Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO +1003C..1003D ; Linear_B # Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE +1003F..1004D ; Linear_B # Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO +10050..1005D ; Linear_B # Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 +10080..100FA ; Linear_B # Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 + +# Total code points: 211 + +# ================================================ + +10380..1039D ; Ugaritic # Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU +1039F ; Ugaritic # Po UGARITIC WORD DIVIDER + +# Total code points: 31 + +# ================================================ + +10450..1047F ; Shavian # Lo [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW + +# Total code points: 48 + +# ================================================ + +10480..1049D ; Osmanya # Lo [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO +104A0..104A9 ; Osmanya # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + +# Total code points: 40 + +# ================================================ + +10800..10805 ; Cypriot # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA +10808 ; Cypriot # Lo CYPRIOT SYLLABLE JO +1080A..10835 ; Cypriot # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO +10837..10838 ; Cypriot # Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE +1083C ; Cypriot # Lo CYPRIOT SYLLABLE ZA +1083F ; Cypriot # Lo CYPRIOT SYLLABLE ZO + +# Total code points: 55 + +# ================================================ + +2800..28FF ; Braille # So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678 + +# Total code points: 256 + +# ================================================ + +1A00..1A16 ; Buginese # Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA +1A17..1A18 ; Buginese # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U +1A19..1A1A ; Buginese # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O +1A1B ; Buginese # Mn BUGINESE VOWEL SIGN AE +1A1E..1A1F ; Buginese # Po [2] BUGINESE PALLAWA..BUGINESE END OF SECTION + +# Total code points: 30 + +# ================================================ + +03E2..03EF ; Coptic # L& [14] COPTIC CAPITAL LETTER SHEI..COPTIC SMALL LETTER DEI +2C80..2CE4 ; Coptic # L& [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI +2CE5..2CEA ; Coptic # So [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA +2CEB..2CEE ; Coptic # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA +2CEF..2CF1 ; Coptic # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS +2CF2..2CF3 ; Coptic # L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI +2CF9..2CFC ; Coptic # Po [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER +2CFD ; Coptic # No COPTIC FRACTION ONE HALF +2CFE..2CFF ; Coptic # Po [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER + +# Total code points: 137 + +# ================================================ + +1980..19AB ; New_Tai_Lue # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA +19B0..19C9 ; New_Tai_Lue # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2 +19D0..19D9 ; New_Tai_Lue # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE +19DA ; New_Tai_Lue # No NEW TAI LUE THAM DIGIT ONE +19DE..19DF ; New_Tai_Lue # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV + +# Total code points: 83 + +# ================================================ + +2C00..2C2E ; Glagolitic # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +2C30..2C5E ; Glagolitic # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +1E000..1E006 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Glagolitic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Glagolitic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Glagolitic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + +# Total code points: 132 + +# ================================================ + +2D30..2D67 ; Tifinagh # Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO +2D6F ; Tifinagh # Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK +2D70 ; Tifinagh # Po TIFINAGH SEPARATOR MARK +2D7F ; Tifinagh # Mn TIFINAGH CONSONANT JOINER + +# Total code points: 59 + +# ================================================ + +A800..A801 ; Syloti_Nagri # Lo [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I +A802 ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN DVISVARA +A803..A805 ; Syloti_Nagri # Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O +A806 ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN HASANTA +A807..A80A ; Syloti_Nagri # Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO +A80B ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN ANUSVARA +A80C..A822 ; Syloti_Nagri # Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO +A823..A824 ; Syloti_Nagri # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I +A825..A826 ; Syloti_Nagri # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E +A827 ; Syloti_Nagri # Mc SYLOTI NAGRI VOWEL SIGN OO +A828..A82B ; Syloti_Nagri # So [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4 + +# Total code points: 44 + +# ================================================ + +103A0..103C3 ; Old_Persian # Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA +103C8..103CF ; Old_Persian # Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH +103D0 ; Old_Persian # Po OLD PERSIAN WORD DIVIDER +103D1..103D5 ; Old_Persian # Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED + +# Total code points: 50 + +# ================================================ + +10A00 ; Kharoshthi # Lo KHAROSHTHI LETTER A +10A01..10A03 ; Kharoshthi # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R +10A05..10A06 ; Kharoshthi # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O +10A0C..10A0F ; Kharoshthi # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA +10A10..10A13 ; Kharoshthi # Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA +10A15..10A17 ; Kharoshthi # Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA +10A19..10A33 ; Kharoshthi # Lo [27] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER TTTHA +10A38..10A3A ; Kharoshthi # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW +10A3F ; Kharoshthi # Mn KHAROSHTHI VIRAMA +10A40..10A47 ; Kharoshthi # No [8] KHAROSHTHI DIGIT ONE..KHAROSHTHI NUMBER ONE THOUSAND +10A50..10A58 ; Kharoshthi # Po [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES + +# Total code points: 65 + +# ================================================ + +1B00..1B03 ; Balinese # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG +1B04 ; Balinese # Mc BALINESE SIGN BISAH +1B05..1B33 ; Balinese # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA +1B34 ; Balinese # Mn BALINESE SIGN REREKAN +1B35 ; Balinese # Mc BALINESE VOWEL SIGN TEDUNG +1B36..1B3A ; Balinese # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA +1B3B ; Balinese # Mc BALINESE VOWEL SIGN RA REPA TEDUNG +1B3C ; Balinese # Mn BALINESE VOWEL SIGN LA LENGA +1B3D..1B41 ; Balinese # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG +1B42 ; Balinese # Mn BALINESE VOWEL SIGN PEPET +1B43..1B44 ; Balinese # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG +1B45..1B4B ; Balinese # Lo [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK +1B50..1B59 ; Balinese # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE +1B5A..1B60 ; Balinese # Po [7] BALINESE PANTI..BALINESE PAMENENG +1B61..1B6A ; Balinese # So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE +1B6B..1B73 ; Balinese # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG +1B74..1B7C ; Balinese # So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING + +# Total code points: 121 + +# ================================================ + +12000..12399 ; Cuneiform # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U +12400..1246E ; Cuneiform # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM +12470..12474 ; Cuneiform # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON +12480..12543 ; Cuneiform # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU + +# Total code points: 1234 + +# ================================================ + +10900..10915 ; Phoenician # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU +10916..1091B ; Phoenician # No [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE +1091F ; Phoenician # Po PHOENICIAN WORD SEPARATOR + +# Total code points: 29 + +# ================================================ + +A840..A873 ; Phags_Pa # Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU +A874..A877 ; Phags_Pa # Po [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD + +# Total code points: 56 + +# ================================================ + +07C0..07C9 ; Nko # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE +07CA..07EA ; Nko # Lo [33] NKO LETTER A..NKO LETTER JONA RA +07EB..07F3 ; Nko # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE +07F4..07F5 ; Nko # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE +07F6 ; Nko # So NKO SYMBOL OO DENNEN +07F7..07F9 ; Nko # Po [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK +07FA ; Nko # Lm NKO LAJANYALAN + +# Total code points: 59 + +# ================================================ + +1B80..1B81 ; Sundanese # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR +1B82 ; Sundanese # Mc SUNDANESE SIGN PANGWISAD +1B83..1BA0 ; Sundanese # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA +1BA1 ; Sundanese # Mc SUNDANESE CONSONANT SIGN PAMINGKAL +1BA2..1BA5 ; Sundanese # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU +1BA6..1BA7 ; Sundanese # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG +1BA8..1BA9 ; Sundanese # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG +1BAA ; Sundanese # Mc SUNDANESE SIGN PAMAAEH +1BAB..1BAD ; Sundanese # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA +1BAE..1BAF ; Sundanese # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA +1BB0..1BB9 ; Sundanese # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE +1BBA..1BBF ; Sundanese # Lo [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M +1CC0..1CC7 ; Sundanese # Po [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA + +# Total code points: 72 + +# ================================================ + +1C00..1C23 ; Lepcha # Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A +1C24..1C2B ; Lepcha # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU +1C2C..1C33 ; Lepcha # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T +1C34..1C35 ; Lepcha # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG +1C36..1C37 ; Lepcha # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA +1C3B..1C3F ; Lepcha # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK +1C40..1C49 ; Lepcha # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE +1C4D..1C4F ; Lepcha # Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA + +# Total code points: 74 + +# ================================================ + +1C50..1C59 ; Ol_Chiki # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE +1C5A..1C77 ; Ol_Chiki # Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH +1C78..1C7D ; Ol_Chiki # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD +1C7E..1C7F ; Ol_Chiki # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD + +# Total code points: 48 + +# ================================================ + +A500..A60B ; Vai # Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG +A60C ; Vai # Lm VAI SYLLABLE LENGTHENER +A60D..A60F ; Vai # Po [3] VAI COMMA..VAI QUESTION MARK +A610..A61F ; Vai # Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG +A620..A629 ; Vai # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE +A62A..A62B ; Vai # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO + +# Total code points: 300 + +# ================================================ + +A880..A881 ; Saurashtra # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA +A882..A8B3 ; Saurashtra # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA +A8B4..A8C3 ; Saurashtra # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU +A8C4..A8C5 ; Saurashtra # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU +A8CE..A8CF ; Saurashtra # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA +A8D0..A8D9 ; Saurashtra # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + +# Total code points: 82 + +# ================================================ + +A900..A909 ; Kayah_Li # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE +A90A..A925 ; Kayah_Li # Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO +A926..A92D ; Kayah_Li # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU +A92F ; Kayah_Li # Po KAYAH LI SIGN SHYA + +# Total code points: 47 + +# ================================================ + +A930..A946 ; Rejang # Lo [23] REJANG LETTER KA..REJANG LETTER A +A947..A951 ; Rejang # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R +A952..A953 ; Rejang # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA +A95F ; Rejang # Po REJANG SECTION MARK + +# Total code points: 37 + +# ================================================ + +10280..1029C ; Lycian # Lo [29] LYCIAN LETTER A..LYCIAN LETTER X + +# Total code points: 29 + +# ================================================ + +102A0..102D0 ; Carian # Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3 + +# Total code points: 49 + +# ================================================ + +10920..10939 ; Lydian # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C +1093F ; Lydian # Po LYDIAN TRIANGULAR MARK + +# Total code points: 27 + +# ================================================ + +AA00..AA28 ; Cham # Lo [41] CHAM LETTER A..CHAM LETTER HA +AA29..AA2E ; Cham # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE +AA2F..AA30 ; Cham # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI +AA31..AA32 ; Cham # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE +AA33..AA34 ; Cham # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA +AA35..AA36 ; Cham # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA +AA40..AA42 ; Cham # Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG +AA43 ; Cham # Mn CHAM CONSONANT SIGN FINAL NG +AA44..AA4B ; Cham # Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS +AA4C ; Cham # Mn CHAM CONSONANT SIGN FINAL M +AA4D ; Cham # Mc CHAM CONSONANT SIGN FINAL H +AA50..AA59 ; Cham # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE +AA5C..AA5F ; Cham # Po [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA + +# Total code points: 83 + +# ================================================ + +1A20..1A54 ; Tai_Tham # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA +1A55 ; Tai_Tham # Mc TAI THAM CONSONANT SIGN MEDIAL RA +1A56 ; Tai_Tham # Mn TAI THAM CONSONANT SIGN MEDIAL LA +1A57 ; Tai_Tham # Mc TAI THAM CONSONANT SIGN LA TANG LAI +1A58..1A5E ; Tai_Tham # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA +1A60 ; Tai_Tham # Mn TAI THAM SIGN SAKOT +1A61 ; Tai_Tham # Mc TAI THAM VOWEL SIGN A +1A62 ; Tai_Tham # Mn TAI THAM VOWEL SIGN MAI SAT +1A63..1A64 ; Tai_Tham # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA +1A65..1A6C ; Tai_Tham # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW +1A6D..1A72 ; Tai_Tham # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI +1A73..1A7C ; Tai_Tham # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN +1A7F ; Tai_Tham # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT +1A80..1A89 ; Tai_Tham # Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE +1A90..1A99 ; Tai_Tham # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE +1AA0..1AA6 ; Tai_Tham # Po [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA +1AA7 ; Tai_Tham # Lm TAI THAM SIGN MAI YAMOK +1AA8..1AAD ; Tai_Tham # Po [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG + +# Total code points: 127 + +# ================================================ + +AA80..AAAF ; Tai_Viet # Lo [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O +AAB0 ; Tai_Viet # Mn TAI VIET MAI KANG +AAB1 ; Tai_Viet # Lo TAI VIET VOWEL AA +AAB2..AAB4 ; Tai_Viet # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U +AAB5..AAB6 ; Tai_Viet # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O +AAB7..AAB8 ; Tai_Viet # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA +AAB9..AABD ; Tai_Viet # Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN +AABE..AABF ; Tai_Viet # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK +AAC0 ; Tai_Viet # Lo TAI VIET TONE MAI NUENG +AAC1 ; Tai_Viet # Mn TAI VIET TONE MAI THO +AAC2 ; Tai_Viet # Lo TAI VIET TONE MAI SONG +AADB..AADC ; Tai_Viet # Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG +AADD ; Tai_Viet # Lm TAI VIET SYMBOL SAM +AADE..AADF ; Tai_Viet # Po [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI + +# Total code points: 72 + +# ================================================ + +10B00..10B35 ; Avestan # Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE +10B39..10B3F ; Avestan # Po [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION + +# Total code points: 61 + +# ================================================ + +13000..1342E ; Egyptian_Hieroglyphs # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 + +# Total code points: 1071 + +# ================================================ + +0800..0815 ; Samaritan # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF +0816..0819 ; Samaritan # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH +081A ; Samaritan # Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT +081B..0823 ; Samaritan # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A +0824 ; Samaritan # Lm SAMARITAN MODIFIER LETTER SHORT A +0825..0827 ; Samaritan # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U +0828 ; Samaritan # Lm SAMARITAN MODIFIER LETTER I +0829..082D ; Samaritan # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA +0830..083E ; Samaritan # Po [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU + +# Total code points: 61 + +# ================================================ + +A4D0..A4F7 ; Lisu # Lo [40] LISU LETTER BA..LISU LETTER OE +A4F8..A4FD ; Lisu # Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU +A4FE..A4FF ; Lisu # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP + +# Total code points: 48 + +# ================================================ + +A6A0..A6E5 ; Bamum # Lo [70] BAMUM LETTER A..BAMUM LETTER KI +A6E6..A6EF ; Bamum # Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM +A6F0..A6F1 ; Bamum # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS +A6F2..A6F7 ; Bamum # Po [6] BAMUM NJAEMLI..BAMUM QUESTION MARK +16800..16A38 ; Bamum # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ + +# Total code points: 657 + +# ================================================ + +A980..A982 ; Javanese # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR +A983 ; Javanese # Mc JAVANESE SIGN WIGNYAN +A984..A9B2 ; Javanese # Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA +A9B3 ; Javanese # Mn JAVANESE SIGN CECAK TELU +A9B4..A9B5 ; Javanese # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG +A9B6..A9B9 ; Javanese # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT +A9BA..A9BB ; Javanese # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE +A9BC ; Javanese # Mn JAVANESE VOWEL SIGN PEPET +A9BD..A9C0 ; Javanese # Mc [4] JAVANESE CONSONANT SIGN KERET..JAVANESE PANGKON +A9C1..A9CD ; Javanese # Po [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH +A9D0..A9D9 ; Javanese # Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE +A9DE..A9DF ; Javanese # Po [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN + +# Total code points: 90 + +# ================================================ + +AAE0..AAEA ; Meetei_Mayek # Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA +AAEB ; Meetei_Mayek # Mc MEETEI MAYEK VOWEL SIGN II +AAEC..AAED ; Meetei_Mayek # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI +AAEE..AAEF ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU +AAF0..AAF1 ; Meetei_Mayek # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM +AAF2 ; Meetei_Mayek # Lo MEETEI MAYEK ANJI +AAF3..AAF4 ; Meetei_Mayek # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK +AAF5 ; Meetei_Mayek # Mc MEETEI MAYEK VOWEL SIGN VISARGA +AAF6 ; Meetei_Mayek # Mn MEETEI MAYEK VIRAMA +ABC0..ABE2 ; Meetei_Mayek # Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM +ABE3..ABE4 ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP +ABE5 ; Meetei_Mayek # Mn MEETEI MAYEK VOWEL SIGN ANAP +ABE6..ABE7 ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP +ABE8 ; Meetei_Mayek # Mn MEETEI MAYEK VOWEL SIGN UNAP +ABE9..ABEA ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG +ABEB ; Meetei_Mayek # Po MEETEI MAYEK CHEIKHEI +ABEC ; Meetei_Mayek # Mc MEETEI MAYEK LUM IYEK +ABED ; Meetei_Mayek # Mn MEETEI MAYEK APUN IYEK +ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE + +# Total code points: 79 + +# ================================================ + +10840..10855 ; Imperial_Aramaic # Lo [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW +10857 ; Imperial_Aramaic # Po IMPERIAL ARAMAIC SECTION SIGN +10858..1085F ; Imperial_Aramaic # No [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND + +# Total code points: 31 + +# ================================================ + +10A60..10A7C ; Old_South_Arabian # Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH +10A7D..10A7E ; Old_South_Arabian # No [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY +10A7F ; Old_South_Arabian # Po OLD SOUTH ARABIAN NUMERIC INDICATOR + +# Total code points: 32 + +# ================================================ + +10B40..10B55 ; Inscriptional_Parthian # Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW +10B58..10B5F ; Inscriptional_Parthian # No [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND + +# Total code points: 30 + +# ================================================ + +10B60..10B72 ; Inscriptional_Pahlavi # Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW +10B78..10B7F ; Inscriptional_Pahlavi # No [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND + +# Total code points: 27 + +# ================================================ + +10C00..10C48 ; Old_Turkic # Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH + +# Total code points: 73 + +# ================================================ + +11080..11081 ; Kaithi # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA +11082 ; Kaithi # Mc KAITHI SIGN VISARGA +11083..110AF ; Kaithi # Lo [45] KAITHI LETTER A..KAITHI LETTER HA +110B0..110B2 ; Kaithi # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II +110B3..110B6 ; Kaithi # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI +110B7..110B8 ; Kaithi # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU +110B9..110BA ; Kaithi # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +110BB..110BC ; Kaithi # Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN +110BD ; Kaithi # Cf KAITHI NUMBER SIGN +110BE..110C1 ; Kaithi # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA + +# Total code points: 66 + +# ================================================ + +1BC0..1BE5 ; Batak # Lo [38] BATAK LETTER A..BATAK LETTER U +1BE6 ; Batak # Mn BATAK SIGN TOMPI +1BE7 ; Batak # Mc BATAK VOWEL SIGN E +1BE8..1BE9 ; Batak # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE +1BEA..1BEC ; Batak # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O +1BED ; Batak # Mn BATAK VOWEL SIGN KARO O +1BEE ; Batak # Mc BATAK VOWEL SIGN U +1BEF..1BF1 ; Batak # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H +1BF2..1BF3 ; Batak # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN +1BFC..1BFF ; Batak # Po [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT + +# Total code points: 56 + +# ================================================ + +11000 ; Brahmi # Mc BRAHMI SIGN CANDRABINDU +11001 ; Brahmi # Mn BRAHMI SIGN ANUSVARA +11002 ; Brahmi # Mc BRAHMI SIGN VISARGA +11003..11037 ; Brahmi # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA +11038..11046 ; Brahmi # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA +11047..1104D ; Brahmi # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS +11052..11065 ; Brahmi # No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND +11066..1106F ; Brahmi # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE +1107F ; Brahmi # Mn BRAHMI NUMBER JOINER + +# Total code points: 109 + +# ================================================ + +0840..0858 ; Mandaic # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN +0859..085B ; Mandaic # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK +085E ; Mandaic # Po MANDAIC PUNCTUATION + +# Total code points: 29 + +# ================================================ + +11100..11102 ; Chakma # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA +11103..11126 ; Chakma # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA +11127..1112B ; Chakma # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU +1112C ; Chakma # Mc CHAKMA VOWEL SIGN E +1112D..11134 ; Chakma # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA +11136..1113F ; Chakma # Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE +11140..11143 ; Chakma # Po [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK + +# Total code points: 67 + +# ================================================ + +109A0..109B7 ; Meroitic_Cursive # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA +109BC..109BD ; Meroitic_Cursive # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF +109BE..109BF ; Meroitic_Cursive # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN +109C0..109CF ; Meroitic_Cursive # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY +109D2..109FF ; Meroitic_Cursive # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS + +# Total code points: 90 + +# ================================================ + +10980..1099F ; Meroitic_Hieroglyphs # Lo [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2 + +# Total code points: 32 + +# ================================================ + +16F00..16F44 ; Miao # Lo [69] MIAO LETTER PA..MIAO LETTER HHA +16F50 ; Miao # Lo MIAO LETTER NASALIZATION +16F51..16F7E ; Miao # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG +16F8F..16F92 ; Miao # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW +16F93..16F9F ; Miao # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 + +# Total code points: 133 + +# ================================================ + +11180..11181 ; Sharada # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA +11182 ; Sharada # Mc SHARADA SIGN VISARGA +11183..111B2 ; Sharada # Lo [48] SHARADA LETTER A..SHARADA LETTER HA +111B3..111B5 ; Sharada # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II +111B6..111BE ; Sharada # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O +111BF..111C0 ; Sharada # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA +111C1..111C4 ; Sharada # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM +111C5..111C9 ; Sharada # Po [5] SHARADA DANDA..SHARADA SANDHI MARK +111CA..111CC ; Sharada # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK +111CD ; Sharada # Po SHARADA SUTRA MARK +111D0..111D9 ; Sharada # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE +111DA ; Sharada # Lo SHARADA EKAM +111DB ; Sharada # Po SHARADA SIGN SIDDHAM +111DC ; Sharada # Lo SHARADA HEADSTROKE +111DD..111DF ; Sharada # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2 + +# Total code points: 94 + +# ================================================ + +110D0..110E8 ; Sora_Sompeng # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE +110F0..110F9 ; Sora_Sompeng # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE + +# Total code points: 35 + +# ================================================ + +11680..116AA ; Takri # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA +116AB ; Takri # Mn TAKRI SIGN ANUSVARA +116AC ; Takri # Mc TAKRI SIGN VISARGA +116AD ; Takri # Mn TAKRI VOWEL SIGN AA +116AE..116AF ; Takri # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II +116B0..116B5 ; Takri # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU +116B6 ; Takri # Mc TAKRI SIGN VIRAMA +116B7 ; Takri # Mn TAKRI SIGN NUKTA +116C0..116C9 ; Takri # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE + +# Total code points: 66 + +# ================================================ + +10530..10563 ; Caucasian_Albanian # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +1056F ; Caucasian_Albanian # Po CAUCASIAN ALBANIAN CITATION MARK + +# Total code points: 53 + +# ================================================ + +16AD0..16AED ; Bassa_Vah # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I +16AF0..16AF4 ; Bassa_Vah # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE +16AF5 ; Bassa_Vah # Po BASSA VAH FULL STOP + +# Total code points: 36 + +# ================================================ + +1BC00..1BC6A ; Duployan # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M +1BC70..1BC7C ; Duployan # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK +1BC80..1BC88 ; Duployan # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL +1BC90..1BC99 ; Duployan # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW +1BC9C ; Duployan # So DUPLOYAN SIGN O WITH CROSS +1BC9D..1BC9E ; Duployan # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK +1BC9F ; Duployan # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP + +# Total code points: 143 + +# ================================================ + +10500..10527 ; Elbasan # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE + +# Total code points: 40 + +# ================================================ + +11300..11301 ; Grantha # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU +11302..11303 ; Grantha # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA +11305..1130C ; Grantha # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L +1130F..11310 ; Grantha # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI +11313..11328 ; Grantha # Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA +1132A..11330 ; Grantha # Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA +11332..11333 ; Grantha # Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA +11335..11339 ; Grantha # Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA +1133C ; Grantha # Mn GRANTHA SIGN NUKTA +1133D ; Grantha # Lo GRANTHA SIGN AVAGRAHA +1133E..1133F ; Grantha # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I +11340 ; Grantha # Mn GRANTHA VOWEL SIGN II +11341..11344 ; Grantha # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR +11347..11348 ; Grantha # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI +1134B..1134D ; Grantha # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA +11350 ; Grantha # Lo GRANTHA OM +11357 ; Grantha # Mc GRANTHA AU LENGTH MARK +1135D..11361 ; Grantha # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL +11362..11363 ; Grantha # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL +11366..1136C ; Grantha # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX +11370..11374 ; Grantha # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + +# Total code points: 85 + +# ================================================ + +16B00..16B2F ; Pahawh_Hmong # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU +16B30..16B36 ; Pahawh_Hmong # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM +16B37..16B3B ; Pahawh_Hmong # Po [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM +16B3C..16B3F ; Pahawh_Hmong # So [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB +16B40..16B43 ; Pahawh_Hmong # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM +16B44 ; Pahawh_Hmong # Po PAHAWH HMONG SIGN XAUS +16B45 ; Pahawh_Hmong # So PAHAWH HMONG SIGN CIM TSOV ROG +16B50..16B59 ; Pahawh_Hmong # Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE +16B5B..16B61 ; Pahawh_Hmong # No [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS +16B63..16B77 ; Pahawh_Hmong # Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS +16B7D..16B8F ; Pahawh_Hmong # Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ + +# Total code points: 127 + +# ================================================ + +11200..11211 ; Khojki # Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA +11213..1122B ; Khojki # Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA +1122C..1122E ; Khojki # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II +1122F..11231 ; Khojki # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI +11232..11233 ; Khojki # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU +11234 ; Khojki # Mn KHOJKI SIGN ANUSVARA +11235 ; Khojki # Mc KHOJKI SIGN VIRAMA +11236..11237 ; Khojki # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA +11238..1123D ; Khojki # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN +1123E ; Khojki # Mn KHOJKI SIGN SUKUN + +# Total code points: 62 + +# ================================================ + +10600..10736 ; Linear_A # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 +10740..10755 ; Linear_A # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE +10760..10767 ; Linear_A # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 + +# Total code points: 341 + +# ================================================ + +11150..11172 ; Mahajani # Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA +11173 ; Mahajani # Mn MAHAJANI SIGN NUKTA +11174..11175 ; Mahajani # Po [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK +11176 ; Mahajani # Lo MAHAJANI LIGATURE SHRI + +# Total code points: 39 + +# ================================================ + +10AC0..10AC7 ; Manichaean # Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW +10AC8 ; Manichaean # So MANICHAEAN SIGN UD +10AC9..10AE4 ; Manichaean # Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW +10AE5..10AE6 ; Manichaean # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW +10AEB..10AEF ; Manichaean # No [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED +10AF0..10AF6 ; Manichaean # Po [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER + +# Total code points: 51 + +# ================================================ + +1E800..1E8C4 ; Mende_Kikakui # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON +1E8C7..1E8CF ; Mende_Kikakui # No [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE +1E8D0..1E8D6 ; Mende_Kikakui # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + +# Total code points: 213 + +# ================================================ + +11600..1162F ; Modi # Lo [48] MODI LETTER A..MODI LETTER LLA +11630..11632 ; Modi # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II +11633..1163A ; Modi # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI +1163B..1163C ; Modi # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU +1163D ; Modi # Mn MODI SIGN ANUSVARA +1163E ; Modi # Mc MODI SIGN VISARGA +1163F..11640 ; Modi # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA +11641..11643 ; Modi # Po [3] MODI DANDA..MODI ABBREVIATION SIGN +11644 ; Modi # Lo MODI SIGN HUVA +11650..11659 ; Modi # Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE + +# Total code points: 79 + +# ================================================ + +16A40..16A5E ; Mro # Lo [31] MRO LETTER TA..MRO LETTER TEK +16A60..16A69 ; Mro # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE +16A6E..16A6F ; Mro # Po [2] MRO DANDA..MRO DOUBLE DANDA + +# Total code points: 43 + +# ================================================ + +10A80..10A9C ; Old_North_Arabian # Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH +10A9D..10A9F ; Old_North_Arabian # No [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY + +# Total code points: 32 + +# ================================================ + +10880..1089E ; Nabataean # Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW +108A7..108AF ; Nabataean # No [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED + +# Total code points: 40 + +# ================================================ + +10860..10876 ; Palmyrene # Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW +10877..10878 ; Palmyrene # So [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON +10879..1087F ; Palmyrene # No [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY + +# Total code points: 32 + +# ================================================ + +11AC0..11AF8 ; Pau_Cin_Hau # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL + +# Total code points: 57 + +# ================================================ + +10350..10375 ; Old_Permic # Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA +10376..1037A ; Old_Permic # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + +# Total code points: 43 + +# ================================================ + +10B80..10B91 ; Psalter_Pahlavi # Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW +10B99..10B9C ; Psalter_Pahlavi # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT +10BA9..10BAF ; Psalter_Pahlavi # No [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED + +# Total code points: 29 + +# ================================================ + +11580..115AE ; Siddham # Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA +115AF..115B1 ; Siddham # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II +115B2..115B5 ; Siddham # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR +115B8..115BB ; Siddham # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU +115BC..115BD ; Siddham # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA +115BE ; Siddham # Mc SIDDHAM SIGN VISARGA +115BF..115C0 ; Siddham # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA +115C1..115D7 ; Siddham # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES +115D8..115DB ; Siddham # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U +115DC..115DD ; Siddham # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + +# Total code points: 92 + +# ================================================ + +112B0..112DE ; Khudawadi # Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA +112DF ; Khudawadi # Mn KHUDAWADI SIGN ANUSVARA +112E0..112E2 ; Khudawadi # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II +112E3..112EA ; Khudawadi # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA +112F0..112F9 ; Khudawadi # Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE + +# Total code points: 69 + +# ================================================ + +11480..114AF ; Tirhuta # Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA +114B0..114B2 ; Tirhuta # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II +114B3..114B8 ; Tirhuta # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL +114B9 ; Tirhuta # Mc TIRHUTA VOWEL SIGN E +114BA ; Tirhuta # Mn TIRHUTA VOWEL SIGN SHORT E +114BB..114BE ; Tirhuta # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU +114BF..114C0 ; Tirhuta # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA +114C1 ; Tirhuta # Mc TIRHUTA SIGN VISARGA +114C2..114C3 ; Tirhuta # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA +114C4..114C5 ; Tirhuta # Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG +114C6 ; Tirhuta # Po TIRHUTA ABBREVIATION SIGN +114C7 ; Tirhuta # Lo TIRHUTA OM +114D0..114D9 ; Tirhuta # Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE + +# Total code points: 82 + +# ================================================ + +118A0..118DF ; Warang_Citi # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO +118E0..118E9 ; Warang_Citi # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE +118EA..118F2 ; Warang_Citi # No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY +118FF ; Warang_Citi # Lo WARANG CITI OM + +# Total code points: 84 + +# ================================================ + +11700..11719 ; Ahom # Lo [26] AHOM LETTER KA..AHOM LETTER JHA +1171D..1171F ; Ahom # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA +11720..11721 ; Ahom # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA +11722..11725 ; Ahom # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU +11726 ; Ahom # Mc AHOM VOWEL SIGN E +11727..1172B ; Ahom # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER +11730..11739 ; Ahom # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE +1173A..1173B ; Ahom # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY +1173C..1173E ; Ahom # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +1173F ; Ahom # So AHOM SYMBOL VI + +# Total code points: 57 + +# ================================================ + +14400..14646 ; Anatolian_Hieroglyphs # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 + +# Total code points: 583 + +# ================================================ + +108E0..108F2 ; Hatran # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH +108F4..108F5 ; Hatran # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW +108FB..108FF ; Hatran # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED + +# Total code points: 26 + +# ================================================ + +11280..11286 ; Multani # Lo [7] MULTANI LETTER A..MULTANI LETTER GA +11288 ; Multani # Lo MULTANI LETTER GHA +1128A..1128D ; Multani # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA +1128F..1129D ; Multani # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA +1129F..112A8 ; Multani # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA +112A9 ; Multani # Po MULTANI SECTION MARK + +# Total code points: 38 + +# ================================================ + +10C80..10CB2 ; Old_Hungarian # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US +10CC0..10CF2 ; Old_Hungarian # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US +10CFA..10CFF ; Old_Hungarian # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND + +# Total code points: 108 + +# ================================================ + +1D800..1D9FF ; SignWriting # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD +1DA00..1DA36 ; SignWriting # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN +1DA37..1DA3A ; SignWriting # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE +1DA3B..1DA6C ; SignWriting # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT +1DA6D..1DA74 ; SignWriting # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING +1DA75 ; SignWriting # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS +1DA76..1DA83 ; SignWriting # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH +1DA84 ; SignWriting # Mn SIGNWRITING LOCATION HEAD NECK +1DA85..1DA86 ; SignWriting # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS +1DA87..1DA8B ; SignWriting # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS +1DA9B..1DA9F ; SignWriting # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 +1DAA1..1DAAF ; SignWriting # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + +# Total code points: 672 + +# ================================================ + +1E900..1E943 ; Adlam # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA +1E944..1E94A ; Adlam # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA +1E950..1E959 ; Adlam # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE +1E95E..1E95F ; Adlam # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK + +# Total code points: 87 + +# ================================================ + +11C00..11C08 ; Bhaiksuki # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L +11C0A..11C2E ; Bhaiksuki # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA +11C2F ; Bhaiksuki # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Bhaiksuki # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3B ; Bhaiksuki # Mc [4] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI VOWEL SIGN AU +11C3C..11C3D ; Bhaiksuki # Mn [2] BHAIKSUKI SIGN CANDRABINDU..BHAIKSUKI SIGN ANUSVARA +11C3E ; Bhaiksuki # Mc BHAIKSUKI SIGN VISARGA +11C3F ; Bhaiksuki # Mn BHAIKSUKI SIGN VIRAMA +11C40 ; Bhaiksuki # Lo BHAIKSUKI SIGN AVAGRAHA +11C41..11C45 ; Bhaiksuki # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2 +11C50..11C59 ; Bhaiksuki # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE +11C5A..11C6C ; Bhaiksuki # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK + +# Total code points: 97 + +# ================================================ + +11C70..11C71 ; Marchen # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD +11C72..11C8F ; Marchen # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A +11C92..11CA7 ; Marchen # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Marchen # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Marchen # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Marchen # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Marchen # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Marchen # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Marchen # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + +# Total code points: 68 + +# ================================================ + +11400..11434 ; Newa # Lo [53] NEWA LETTER A..NEWA LETTER HA +11435..11437 ; Newa # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Newa # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Newa # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11442..11444 ; Newa # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA +11445 ; Newa # Mc NEWA SIGN VISARGA +11446 ; Newa # Mn NEWA SIGN NUKTA +11447..1144A ; Newa # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI +1144B..1144F ; Newa # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN +11450..11459 ; Newa # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE +1145B ; Newa # Po NEWA PLACEHOLDER MARK +1145D ; Newa # Po NEWA INSERTION SIGN + +# Total code points: 92 + +# ================================================ + +104B0..104D3 ; Osage # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +104D8..104FB ; Osage # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + +# Total code points: 72 + +# ================================================ + +16FE0 ; Tangut # Lm TANGUT ITERATION MARK +17000..187EC ; Tangut # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC +18800..18AF2 ; Tangut # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755 + +# Total code points: 6881 + +# EOF +""" + +_blocksText = """ +# Blocks-9.0.0.txt +# Date: 2016-02-05, 23:48:00 GMT [KW] +# © 2016 Unicode®, Inc. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Format: +# Start Code..End Code; Block Name + +# ================================================ + +# Note: When comparing block names, casing, whitespace, hyphens, +# and underbars are ignored. +# For example, "Latin Extended-A" and "latin extended a" are equivalent. +# For more information on the comparison of property values, +# see UAX #44: http://www.unicode.org/reports/tr44/ +# +# All block ranges start with a value where (cp MOD 16) = 0, +# and end with a value where (cp MOD 16) = 15. In other words, +# the last hexadecimal digit of the start of range is ...0 +# and the last hexadecimal digit of the end of range is ...F. +# This constraint on block ranges guarantees that allocations +# are done in terms of whole columns, and that code chart display +# never involves splitting columns in the charts. +# +# All code points not explicitly listed for Block +# have the value No_Block. + +# Property: Block +# +# @missing: 0000..10FFFF; No_Block + +0000..007F; Basic Latin +0080..00FF; Latin-1 Supplement +0100..017F; Latin Extended-A +0180..024F; Latin Extended-B +0250..02AF; IPA Extensions +02B0..02FF; Spacing Modifier Letters +0300..036F; Combining Diacritical Marks +0370..03FF; Greek and Coptic +0400..04FF; Cyrillic +0500..052F; Cyrillic Supplement +0530..058F; Armenian +0590..05FF; Hebrew +0600..06FF; Arabic +0700..074F; Syriac +0750..077F; Arabic Supplement +0780..07BF; Thaana +07C0..07FF; NKo +0800..083F; Samaritan +0840..085F; Mandaic +08A0..08FF; Arabic Extended-A +0900..097F; Devanagari +0980..09FF; Bengali +0A00..0A7F; Gurmukhi +0A80..0AFF; Gujarati +0B00..0B7F; Oriya +0B80..0BFF; Tamil +0C00..0C7F; Telugu +0C80..0CFF; Kannada +0D00..0D7F; Malayalam +0D80..0DFF; Sinhala +0E00..0E7F; Thai +0E80..0EFF; Lao +0F00..0FFF; Tibetan +1000..109F; Myanmar +10A0..10FF; Georgian +1100..11FF; Hangul Jamo +1200..137F; Ethiopic +1380..139F; Ethiopic Supplement +13A0..13FF; Cherokee +1400..167F; Unified Canadian Aboriginal Syllabics +1680..169F; Ogham +16A0..16FF; Runic +1700..171F; Tagalog +1720..173F; Hanunoo +1740..175F; Buhid +1760..177F; Tagbanwa +1780..17FF; Khmer +1800..18AF; Mongolian +18B0..18FF; Unified Canadian Aboriginal Syllabics Extended +1900..194F; Limbu +1950..197F; Tai Le +1980..19DF; New Tai Lue +19E0..19FF; Khmer Symbols +1A00..1A1F; Buginese +1A20..1AAF; Tai Tham +1AB0..1AFF; Combining Diacritical Marks Extended +1B00..1B7F; Balinese +1B80..1BBF; Sundanese +1BC0..1BFF; Batak +1C00..1C4F; Lepcha +1C50..1C7F; Ol Chiki +1C80..1C8F; Cyrillic Extended-C +1CC0..1CCF; Sundanese Supplement +1CD0..1CFF; Vedic Extensions +1D00..1D7F; Phonetic Extensions +1D80..1DBF; Phonetic Extensions Supplement +1DC0..1DFF; Combining Diacritical Marks Supplement +1E00..1EFF; Latin Extended Additional +1F00..1FFF; Greek Extended +2000..206F; General Punctuation +2070..209F; Superscripts and Subscripts +20A0..20CF; Currency Symbols +20D0..20FF; Combining Diacritical Marks for Symbols +2100..214F; Letterlike Symbols +2150..218F; Number Forms +2190..21FF; Arrows +2200..22FF; Mathematical Operators +2300..23FF; Miscellaneous Technical +2400..243F; Control Pictures +2440..245F; Optical Character Recognition +2460..24FF; Enclosed Alphanumerics +2500..257F; Box Drawing +2580..259F; Block Elements +25A0..25FF; Geometric Shapes +2600..26FF; Miscellaneous Symbols +2700..27BF; Dingbats +27C0..27EF; Miscellaneous Mathematical Symbols-A +27F0..27FF; Supplemental Arrows-A +2800..28FF; Braille Patterns +2900..297F; Supplemental Arrows-B +2980..29FF; Miscellaneous Mathematical Symbols-B +2A00..2AFF; Supplemental Mathematical Operators +2B00..2BFF; Miscellaneous Symbols and Arrows +2C00..2C5F; Glagolitic +2C60..2C7F; Latin Extended-C +2C80..2CFF; Coptic +2D00..2D2F; Georgian Supplement +2D30..2D7F; Tifinagh +2D80..2DDF; Ethiopic Extended +2DE0..2DFF; Cyrillic Extended-A +2E00..2E7F; Supplemental Punctuation +2E80..2EFF; CJK Radicals Supplement +2F00..2FDF; Kangxi Radicals +2FF0..2FFF; Ideographic Description Characters +3000..303F; CJK Symbols and Punctuation +3040..309F; Hiragana +30A0..30FF; Katakana +3100..312F; Bopomofo +3130..318F; Hangul Compatibility Jamo +3190..319F; Kanbun +31A0..31BF; Bopomofo Extended +31C0..31EF; CJK Strokes +31F0..31FF; Katakana Phonetic Extensions +3200..32FF; Enclosed CJK Letters and Months +3300..33FF; CJK Compatibility +3400..4DBF; CJK Unified Ideographs Extension A +4DC0..4DFF; Yijing Hexagram Symbols +4E00..9FFF; CJK Unified Ideographs +A000..A48F; Yi Syllables +A490..A4CF; Yi Radicals +A4D0..A4FF; Lisu +A500..A63F; Vai +A640..A69F; Cyrillic Extended-B +A6A0..A6FF; Bamum +A700..A71F; Modifier Tone Letters +A720..A7FF; Latin Extended-D +A800..A82F; Syloti Nagri +A830..A83F; Common Indic Number Forms +A840..A87F; Phags-pa +A880..A8DF; Saurashtra +A8E0..A8FF; Devanagari Extended +A900..A92F; Kayah Li +A930..A95F; Rejang +A960..A97F; Hangul Jamo Extended-A +A980..A9DF; Javanese +A9E0..A9FF; Myanmar Extended-B +AA00..AA5F; Cham +AA60..AA7F; Myanmar Extended-A +AA80..AADF; Tai Viet +AAE0..AAFF; Meetei Mayek Extensions +AB00..AB2F; Ethiopic Extended-A +AB30..AB6F; Latin Extended-E +AB70..ABBF; Cherokee Supplement +ABC0..ABFF; Meetei Mayek +AC00..D7AF; Hangul Syllables +D7B0..D7FF; Hangul Jamo Extended-B +D800..DB7F; High Surrogates +DB80..DBFF; High Private Use Surrogates +DC00..DFFF; Low Surrogates +E000..F8FF; Private Use Area +F900..FAFF; CJK Compatibility Ideographs +FB00..FB4F; Alphabetic Presentation Forms +FB50..FDFF; Arabic Presentation Forms-A +FE00..FE0F; Variation Selectors +FE10..FE1F; Vertical Forms +FE20..FE2F; Combining Half Marks +FE30..FE4F; CJK Compatibility Forms +FE50..FE6F; Small Form Variants +FE70..FEFF; Arabic Presentation Forms-B +FF00..FFEF; Halfwidth and Fullwidth Forms +FFF0..FFFF; Specials +10000..1007F; Linear B Syllabary +10080..100FF; Linear B Ideograms +10100..1013F; Aegean Numbers +10140..1018F; Ancient Greek Numbers +10190..101CF; Ancient Symbols +101D0..101FF; Phaistos Disc +10280..1029F; Lycian +102A0..102DF; Carian +102E0..102FF; Coptic Epact Numbers +10300..1032F; Old Italic +10330..1034F; Gothic +10350..1037F; Old Permic +10380..1039F; Ugaritic +103A0..103DF; Old Persian +10400..1044F; Deseret +10450..1047F; Shavian +10480..104AF; Osmanya +104B0..104FF; Osage +10500..1052F; Elbasan +10530..1056F; Caucasian Albanian +10600..1077F; Linear A +10800..1083F; Cypriot Syllabary +10840..1085F; Imperial Aramaic +10860..1087F; Palmyrene +10880..108AF; Nabataean +108E0..108FF; Hatran +10900..1091F; Phoenician +10920..1093F; Lydian +10980..1099F; Meroitic Hieroglyphs +109A0..109FF; Meroitic Cursive +10A00..10A5F; Kharoshthi +10A60..10A7F; Old South Arabian +10A80..10A9F; Old North Arabian +10AC0..10AFF; Manichaean +10B00..10B3F; Avestan +10B40..10B5F; Inscriptional Parthian +10B60..10B7F; Inscriptional Pahlavi +10B80..10BAF; Psalter Pahlavi +10C00..10C4F; Old Turkic +10C80..10CFF; Old Hungarian +10E60..10E7F; Rumi Numeral Symbols +11000..1107F; Brahmi +11080..110CF; Kaithi +110D0..110FF; Sora Sompeng +11100..1114F; Chakma +11150..1117F; Mahajani +11180..111DF; Sharada +111E0..111FF; Sinhala Archaic Numbers +11200..1124F; Khojki +11280..112AF; Multani +112B0..112FF; Khudawadi +11300..1137F; Grantha +11400..1147F; Newa +11480..114DF; Tirhuta +11580..115FF; Siddham +11600..1165F; Modi +11660..1167F; Mongolian Supplement +11680..116CF; Takri +11700..1173F; Ahom +118A0..118FF; Warang Citi +11AC0..11AFF; Pau Cin Hau +11C00..11C6F; Bhaiksuki +11C70..11CBF; Marchen +12000..123FF; Cuneiform +12400..1247F; Cuneiform Numbers and Punctuation +12480..1254F; Early Dynastic Cuneiform +13000..1342F; Egyptian Hieroglyphs +14400..1467F; Anatolian Hieroglyphs +16800..16A3F; Bamum Supplement +16A40..16A6F; Mro +16AD0..16AFF; Bassa Vah +16B00..16B8F; Pahawh Hmong +16F00..16F9F; Miao +16FE0..16FFF; Ideographic Symbols and Punctuation +17000..187FF; Tangut +18800..18AFF; Tangut Components +1B000..1B0FF; Kana Supplement +1BC00..1BC9F; Duployan +1BCA0..1BCAF; Shorthand Format Controls +1D000..1D0FF; Byzantine Musical Symbols +1D100..1D1FF; Musical Symbols +1D200..1D24F; Ancient Greek Musical Notation +1D300..1D35F; Tai Xuan Jing Symbols +1D360..1D37F; Counting Rod Numerals +1D400..1D7FF; Mathematical Alphanumeric Symbols +1D800..1DAAF; Sutton SignWriting +1E000..1E02F; Glagolitic Supplement +1E800..1E8DF; Mende Kikakui +1E900..1E95F; Adlam +1EE00..1EEFF; Arabic Mathematical Alphabetic Symbols +1F000..1F02F; Mahjong Tiles +1F030..1F09F; Domino Tiles +1F0A0..1F0FF; Playing Cards +1F100..1F1FF; Enclosed Alphanumeric Supplement +1F200..1F2FF; Enclosed Ideographic Supplement +1F300..1F5FF; Miscellaneous Symbols and Pictographs +1F600..1F64F; Emoticons +1F650..1F67F; Ornamental Dingbats +1F680..1F6FF; Transport and Map Symbols +1F700..1F77F; Alchemical Symbols +1F780..1F7FF; Geometric Shapes Extended +1F800..1F8FF; Supplemental Arrows-C +1F900..1F9FF; Supplemental Symbols and Pictographs +20000..2A6DF; CJK Unified Ideographs Extension B +2A700..2B73F; CJK Unified Ideographs Extension C +2B740..2B81F; CJK Unified Ideographs Extension D +2B820..2CEAF; CJK Unified Ideographs Extension E +2F800..2FA1F; CJK Compatibility Ideographs Supplement +E0000..E007F; Tags +E0100..E01EF; Variation Selectors Supplement +F0000..FFFFF; Supplementary Private Use Area-A +100000..10FFFF; Supplementary Private Use Area-B + +# EOF +""" _openClosePairText = """ # This was automatically generated from UnicodeData.txt and then @@ -276,42 +3225,33 @@ # load the data -_openToClose = {} -_closeToOpen = {} -openValue = None -for line in _openClosePairText.splitlines(): - line = line.split("#")[0].strip() - if not line: - continue - value, name, category = line.split(";") - value = int(value, 16) - if openValue is not None: - closeValue = value - if openValue not in _openToClose: - _openToClose[openValue] = closeValue - if closeValue not in _closeToOpen: - _closeToOpen[closeValue] = openValue - openValue = None - else: - openValue = value +def _parseRangeText(text): + result = [] + orderedTags = [] + for line in text.splitlines(): + line = line.split("#")[0] + line = line.strip() + if not line: + continue + valueRange, name = line.split(";") + valueRange = valueRange.strip() + name = name.strip() + if ".." in valueRange: + minValue, maxValue = valueRange.split("..") + else: + minValue = maxValue = valueRange + minValue = int(minValue, 16) + maxValue = int(maxValue, 16) + result.append((minValue, maxValue, name)) + if name not in orderedTags: + orderedTags.append(name) + result = list(sorted(result)) + return result, orderedTags -# ordered sets -orderedScripts = [] -for value in unicodedata.Scripts.VALUES: - value = unicodedata.script_name(value) - if value == "Unknown": - continue - if value not in orderedScripts: - orderedScripts.append(value) +scriptRanges, orderedScripts = _parseRangeText(_scriptsText) orderedScripts.append("Unknown") - -orderedBlocks = [] -for value in unicodedata.Blocks.VALUES: - if value == "No_Block": - continue - if value not in orderedBlocks: - orderedBlocks.append(value) +blockRanges, orderedBlocks = _parseRangeText(_blocksText) orderedCategories = """Lu Ll @@ -344,12 +3284,32 @@ Co Cn""".splitlines() +_openToClose = {} +_closeToOpen = {} + +openValue = None +for line in _openClosePairText.splitlines(): + line = line.split("#")[0].strip() + if not line: + continue + value, name, category = line.split(";") + value = int(value, 16) + if openValue is not None: + closeValue = value + if openValue not in _openToClose: + _openToClose[openValue] = closeValue + if closeValue not in _closeToOpen: + _closeToOpen[closeValue] = openValue + openValue = None + else: + openValue = value + # functions def decompositionBase(value): letterCategories = ("Ll", "Lu", "Lt", "Lo") try: - c = chr(value) + c = unichr(value) # see not in category function except ValueError: return -1 @@ -359,7 +3319,7 @@ if " " not in decomposition: return -1 parts = decomposition.split(" ") - unichrs = [chr(int(i, 16)) for i in parts if i] + 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: @@ -381,13 +3341,45 @@ return _openToClose.get(value) def category(value): - c = chr(value) - return unicodedata.category(c) + try: + c = unichr(value) + return unicodedata.category(c) + # values larger than Python can use to create a + # unichr will raise a value error. when this happens, + # return Cn. + except ValueError: + return "Cn" def script(value): - char = chr(value) - return unicodedata.script_name(unicodedata.script(char), default="Unknown") + scriptName = _searchRanges(value, scriptRanges) + if scriptName is None: + scriptName = "Unknown" + return scriptName def block(value): - char = chr(value) - return unicodedata.block(char) + blockName = _searchRanges(value, blockRanges) + if blockName is None: + blockName = "No_Block" + return blockName + +def _searchRanges(value, available): + count = len(available) + if count == 0: + return None + elif count == 1: + test = available[0] + lessRange = greaterRange = [] + else: + half = int(count / 2) + test = available[half] + lessRange = available[:half] + greaterRange = available[half:] + minValue, maxValue, name = test + if value < minValue: + return _searchRanges(value, lessRange) + elif value > maxValue: + return _searchRanges(value, greaterRange) + else: + return name + + diff -Nru defcon-0.7.2/README.rst defcon-0.3.5/README.rst --- defcon-0.7.2/README.rst 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/README.rst 2017-10-02 10:54:57.000000000 +0000 @@ -26,26 +26,11 @@ pip install --upgrade defcon -To install with the `fontPens `_ package —used for ``Glyph.correctDirection()`` and ``Contour.contourInside()``— do: - -.. code:: - - pip install --upgrade defcon[pens] - -To optionally install defcon with support for `lxml `_, -a faster XML reader and writer library, you can do: - -.. code:: - - pip install --upgrade defcon[lxml] - -You can separate multiple extras using a comma: ``defcon[pens,lxml]``. - Documentation ~~~~~~~~~~~~~ Documentation for Defcon lives at -`defcon.robotools.dev `_. +`ts-defcon.readthedocs.io `_. Copyrights ~~~~~~~~~~ @@ -60,12 +45,12 @@ names from PostScript and the OpenType FDK, copyright `Adobe `_. -.. |Travis Build Status| image:: https://travis-ci.org/robotools/defcon.svg?branch=master - :target: https://travis-ci.org/robotools/defcon -.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/github/robotools/defcon?branch=master&svg=true - :target: https://ci.appveyor.com/project/robotools/defcon/branch/master -.. |Coverage Status| image:: https://coveralls.io/repos/github/robotools/defcon/badge.svg?branch=master - :target: https://coveralls.io/github/robotools/defcon?branch=master -.. |Python Versions| image:: https://img.shields.io/badge/python-3.6%2C%203.7-blue.svg +.. |Travis Build Status| image:: https://travis-ci.org/typesupply/defcon.svg?branch=master + :target: https://travis-ci.org/typesupply/defcon +.. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/github/typesupply/defcon?branch=master&svg=true + :target: https://ci.appveyor.com/project/typesupply/defcon/branch/master +.. |Coverage Status| image:: https://coveralls.io/repos/github/typesupply/defcon/badge.svg?branch=master + :target: https://coveralls.io/github/typesupply/defcon?branch=master +.. |Python Versions| image:: https://img.shields.io/badge/python-2.7%2C%203.5-blue.svg .. |PyPI Version| image:: https://img.shields.io/pypi/v/defcon.svg :target: https://pypi.org/project/defcon/ diff -Nru defcon-0.7.2/requirements.txt defcon-0.3.5/requirements.txt --- defcon-0.7.2/requirements.txt 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/requirements.txt 2017-10-02 10:54:57.000000000 +0000 @@ -1,2 +1,3 @@ -fonttools==4.10.2 +fonttools==3.13.1 +ufoLib==2.1.0 # git+https://github.com/typesupply/compositor diff -Nru defcon-0.7.2/setup.cfg defcon-0.3.5/setup.cfg --- defcon-0.7.2/setup.cfg 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/setup.cfg 2017-10-02 10:54:57.000000000 +0000 @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.7.2 +current_version = 0.3.5 commit = True tag = False tag_name = {new_version} @@ -28,6 +28,9 @@ dist = build_sphinx sdist bdist_wheel test = pytest +[wheel] +universal = 1 + [sdist] formats = zip @@ -41,7 +44,8 @@ [tool:pytest] minversion = 2.8 -testpaths = defcon +testpaths = + Lib/defcon python_files = test_*.py python_classes = @@ -51,4 +55,4 @@ -r a --doctest-modules --doctest-ignore-import-errors - --pyargs + diff -Nru defcon-0.7.2/setup.py defcon-0.3.5/setup.py --- defcon-0.7.2/setup.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/setup.py 2017-10-02 10:54:57.000000000 +0000 @@ -1,134 +1,6 @@ #!/usr/bin/env python -from setuptools import setup, find_packages, Command +from setuptools import setup, find_packages import sys -from distutils import log - - -class bump_version(Command): - - description = "increment the package version and commit the changes" - - user_options = [ - ("major", None, "bump the first digit, for incompatible API changes"), - ("minor", None, "bump the second digit, for new backward-compatible features"), - ("patch", None, "bump the third digit, for bug fixes (default)"), - ] - - def initialize_options(self): - self.minor = False - self.major = False - self.patch = False - - def finalize_options(self): - part = None - for attr in ("major", "minor", "patch"): - if getattr(self, attr, False): - if part is None: - part = attr - else: - from distutils.errors import DistutilsOptionError - raise DistutilsOptionError( - "version part options are mutually exclusive") - self.part = part or "patch" - - def bumpversion(self, part, **kwargs): - """ Run bump2version.main() with the specified arguments. - """ - import bumpversion - - args = ['--verbose'] if self.verbose > 1 else [] - for k, v in kwargs.items(): - k = "--{}".format(k.replace("_", "-")) - is_bool = isinstance(v, bool) and v is True - args.extend([k] if is_bool else [k, str(v)]) - args.append(part) - - log.debug( - "$ bumpversion %s" % " ".join(a.replace(" ", "\\ ") for a in args)) - - bumpversion.main(args) - - def run(self): - log.info("bumping '%s' version" % self.part) - self.bumpversion(self.part) - - -class release(bump_version): - """Drop the developmental release '.devN' suffix from the package version, - open the default text $EDITOR to write release notes, commit the changes - and generate a git tag. - Release notes can also be set with the -m/--message option, or by reading - from standard input. - """ - - description = "tag a new release" - - user_options = [ - ("message=", 'm', "message containing the release notes"), - ] - - def initialize_options(self): - self.message = None - - def finalize_options(self): - import re - - current_version = self.distribution.metadata.get_version() - if not re.search(r"\.dev[0-9]+", current_version): - from distutils.errors import DistutilsSetupError - raise DistutilsSetupError( - "current version (%s) has no '.devN' suffix.\n " - "Run 'setup.py bump_version' with any of " - "--major, --minor, --patch options" % current_version) - - message = self.message - if message is None: - if sys.stdin.isatty(): - # stdin is interactive, use editor to write release notes - message = self.edit_release_notes() - else: - # read release notes from stdin pipe - message = sys.stdin.read() - - if not message.strip(): - from distutils.errors import DistutilsSetupError - raise DistutilsSetupError("release notes message is empty") - - self.message = "v{new_version}\n\n%s" % message - - @staticmethod - def edit_release_notes(): - """Use the default text $EDITOR to write release notes. - If $EDITOR is not set, use 'nano'.""" - from tempfile import mkstemp - import os - import shlex - import subprocess - - text_editor = shlex.split(os.environ.get('EDITOR', 'nano')) - - fd, tmp = mkstemp(prefix='bumpversion-') - try: - os.close(fd) - with open(tmp, 'w') as f: - f.write("\n\n# Write release notes.\n" - "# Lines starting with '#' will be ignored.") - subprocess.check_call(text_editor + [tmp]) - with open(tmp, 'r') as f: - changes = "".join( - l for l in f.readlines() if not l.startswith('#')) - finally: - os.remove(tmp) - return changes - - def run(self): - log.info("stripping developmental release suffix") - # drop '.dev0' suffix, commit with given message and create git tag - self.bumpversion("release", - tag=True, - message="Release {new_version}", - tag_message=self.message) - needs_sphinx = {'build_sphinx', 'dist'}.intersection(sys.argv) sphinx = ['sphinx'] if needs_sphinx else [] @@ -136,52 +8,39 @@ pytest_runner = ['pytest_runner'] if needs_pytest else [] needs_wheel = {'bdist_wheel'}.intersection(sys.argv) wheel = ['wheel'] if needs_wheel else [] -needs_bump2version = {'release', 'bump_version'}.intersection(sys.argv) -bump2version = ['bump2version'] if needs_bump2version else [] with open('README.rst', 'r') as f: long_description = f.read() -setup_params = dict( +setup( name="defcon", - version="0.7.2", + version="0.3.5", description="A set of flexible objects for representing UFO data.", long_description=long_description, author="Tal Leming", author_email="tal@typesupply.com", - url="https://github.com/robotools/defcon", + url="http://code.typesupply.com", license="MIT", package_dir={"": "Lib"}, packages=find_packages("Lib"), include_package_data=True, - python_requires=">=3.6", - setup_requires=pytest_runner + sphinx + wheel + bump2version, + setup_requires=pytest_runner + sphinx + wheel, tests_require=[ 'pytest>=3.0.3', ], install_requires=[ - "fonttools[ufo,unicode] >= 4.10.0", + "fonttools>=3.1.2", + "ufoLib>=2.1.0", ], - extras_require={ - 'pens': ["fontPens>=0.1.0"], - 'lxml': ["fonttools[lxml] >= 4.10.0"], - }, - cmdclass={ - "release": release, - "bump_version": bump_version, - }, classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Multimedia :: Graphics :: Editors :: Vector-Based', 'Topic :: Software Development :: Libraries :: Python Modules', ], ) - - -if __name__ == "__main__": - setup(**setup_params) diff -Nru defcon-0.7.2/tools/openClosedUniGenerator.py defcon-0.3.5/tools/openClosedUniGenerator.py --- defcon-0.7.2/tools/openClosedUniGenerator.py 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/tools/openClosedUniGenerator.py 2017-10-02 10:54:57.000000000 +0000 @@ -13,12 +13,19 @@ for line in text.splitlines(): line = line.split(";") value, name, category = line[:3] - if category in ("Ps", "Pi"): - openValue = (value, name, category) - elif category in ("Pe", "Pf") and openValue is not None: - result.append("%s;%s;%s" % openValue) - result.append("%s;%s;%s" % (value, name, category)) - result.append("") - openValue = None + if category in ("Ps", "Pe", "Pi", "Pf"): + if openValue is None: + #assert category in ("Ps", "Pi") + openValue = (value, name, category) + else: + #assert category in ("Pe", "Pf") + if category not in ("Pe", "Pf"): + result.append("#%s;%s;%s" % (value, name, category)) + result.append("") + else: + result.append("%s;%s;%s" % openValue) + result.append("%s;%s;%s" % (value, name, category)) + result.append("") + openValue = None print("\n".join(result)) diff -Nru defcon-0.7.2/tox.ini defcon-0.3.5/tox.ini --- defcon-0.7.2/tox.ini 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/tox.ini 2017-10-02 10:54:57.000000000 +0000 @@ -1,36 +1,38 @@ [tox] -envlist = py{36,37}-cov,coverage -skip_missing_interpreters = true +envlist = py27, py35 [testenv] +basepython = + py27: {env:TOXPYTHON:python2.7} + py35: {env:TOXPYTHON:python3.5} deps = pytest -rrequirements.txt - cov: coverage +install_command = + {envpython} -m pip install -v {opts} {packages} commands = # run the test suite against the package installed inside tox env - !cov: py.test {posargs} - # if `*-cov` factor in the tox env name, also collect test coverage - cov: coverage run --parallel-mode -m pytest {posargs} + py.test {posargs:--pyargs defcon} [testenv:coverage] +basepython = {env:TOXPYTHON:python3.5} deps = - coverage + {[testenv]deps} + pytest-cov skip_install = true commands= - coverage combine - coverage report - coverage html + # measure test coverage and create html report + py.test --cov --cov-report html {posargs} [testenv:coveralls] -description = upload coverage report to coveralls passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH +basepython=python3.5 deps = {[testenv:coverage]deps} coveralls skip_install = true ignore_outcome = true -download = true commands= - coverage combine + # measure test coverage and upload report to coveralls + py.test --cov coveralls diff -Nru defcon-0.7.2/.travis.yml defcon-0.3.5/.travis.yml --- defcon-0.7.2/.travis.yml 2020-05-29 10:55:00.000000000 +0000 +++ defcon-0.3.5/.travis.yml 2017-10-02 10:54:57.000000000 +0000 @@ -1,32 +1,27 @@ +sudo: false language: python -env: - global: - - TWINE_USERNAME="anthrotype" - - secure: piLAOQojWKQ8qLE8sfe4cfP8qKiZjgAMpe+e+4YVdMRX853qY8b3Ndnqo5kKnNObHiW46BiLh1A12lLaL+yxxyF6S+eGS0TIRZGhZjiqll+aScIg+M4jXGKsQdnWOns5VFNw5uqll1098HrWcP67w6YCHZjXcNCJJx+icw8f3nH74Drzb3CXGVUn1plRFBtwZrMk9ysCP+icB7OA5maSGcZE38WqoseoxH+lbOa9cIK4mn9v+zhfS1E+WRcQCpKfrwzYRxp/mo4IaxlIhRmihMaAoDSiE7/KcYOjJtXwK00Vui/go5UP1xGZute+CpgS+tfZNHeQs4HJ6Z+P1wI3SlBNkcWh6RXRH0uPeF+ioE1w1rBLp9IIE3Km/G/QJOh7NzGzgquFw3co1svou7lWzRyv8hnzQ0C4OP3WBP+6/oA+Tw+OfbX1a3QTTn9wCfnbr+ChZ6uCayVuvU7wH1FElGNkphM7AN67vUg4QMofrk7HxcL+ynSuBFCa5E0h1HjAIZXpFCQ9lSEnXpRYg5knGaGtJXgUzQH3S7N5VFFCmLF8KSvIjd7VnK/VoXccZzCDAOTmHVNsNkKPs+PnlYDvbkRWG+FjJOCrCGYFrWGWk5PbOtmUPX3rt5cDzBlhQflb5NFWpYl6D22SSeQQE8fiq+6U07y/gkQfEi2RHmZzKuk= matrix: - include: - - python: 3.6 - env: TOXENV=py36-cov - - python: 3.7 - env: - - TOXENV=py37-cov - - BUILD_DIST=true - # required to run python3.7 on Travis CI - # https://github.com/travis-ci/travis-ci/issues/9815 - dist: xenial + include: + - python: 2.7 + - python: 3.5 + env: BUILD_DIST=true + - python: 3.5 + env: TOXENV=coveralls install: - pip install --upgrade pip setuptools wheel - pip install tox-travis script: - tox -after_success: - # upload test coverage data to coveralls - - tox -e coveralls - # if it's a tagged commit, upload distribution packages to PyPI - - | - if [ -n "$TRAVIS_TAG" ] && [ "$TRAVIS_REPO_SLUG" == "robotools/defcon" ] && [ "$BUILD_DIST" == true ]; then - pip install --upgrade twine pip setuptools wheel - python setup.py sdist - pip wheel --no-deps --wheel-dir dist . - twine upload dist/*.whl dist/*.zip - fi +deploy: + # deploy to PyPI on tags + provider: pypi + server: https://upload.pypi.org/legacy/ + on: + repo: typesupply/defcon + tags: true + all_branches: true + condition: "$BUILD_DIST == true" + user: anthrotype + password: + secure: tTYoV50bPVFHTAM9wYVwBxKGJbzh0+eHSYtXKoEv/3RO1y2DyRjutsMBDXw52EUeVgiWhJxbyIGVZb20/9IJxmQziRjyg9uRmBVCkqu6QuxcH2ffmFQZBEVan8f+e1pdt1xJXGsOLtFLQFDhhVUML747aBhHkunK9IbSq0jhJj3sHMtNFk93noPyTsHgMEyepbU8a1kMffzH5IRTlMYSXknEOfbHuF6DjFCDS3+SNZysCOIRqe6vHhILvuYTlWW/+UamFAO28quc46mKUTULCoWZpBn5Mbw+BtY0cUWVSoxWtMTXGwFhzvX4S3o/0cBhRwIoYGCcPH+tV6sm18bp/h2m2E2vwfZsT5x/wRsKv5rlfyd67rlxRco6xN0JXtFAkbcGHSaZauGuOfM6AUQnbcMNHXBU4JH/Ks1qDHljoc6CQOOGLFlxipqhvG0kdoMR4NfkrTIIZZvtZ3ad4Nc0BZ1PPAPZF76zpnrPGiZvlb+Oyo2Q39d2HnsQ1dn3VmuY0pZ3at8IWqdSgG+H+7Oz/pBuo1jxt3RtdrqjT85Bi3eqvrH61lfrFm7z3q4aXM4lLBmxkERnueAGLJuYiBJq0VYpBgsv8ERdslkUlGArAlFIWtmiSlxTaJHkZZ68n/vUNFrmEZD1ce+qqARZgEqcQU/6qZYZJP5CmRhKf4TTPJs= + distributions: sdist bdist_wheel