L ir-^UdZddlmZddlZddlmZddlmZmZm Z m Z m Z ddl m Z ddlmcmZddlmZmZddlmZdd lmZmZdd lmZmZdd lmZdd lm Z dd l!m"Z"m#Z#m$Z$ddl%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,er*ddl-m.Z.m/Z/m0Z0ddlm1Z1ddl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:ddl;md<ej~e@ZAde>d<dZBdZCGdde"ZDGddZEGddeZFdjd ZG dk dld"ZH dm dnd#ZI dk dod$ZJdpd%ZKdpd&ZLdpd'ZMdpd(ZN dqd*ZOdrd+ZP dqd,ZQdpd-ZReSeTe'.eSeSe(.d/ZUdsd0ZVdtd1ZWdud2ZXdvd3ZYddeDjd!f dwd4Z[ dx dyd5Z\ dz d{d6Z]eDje\eDje]iZ`d7e>d8<d|d9Zad}d:Zbd~d;Zcdd<Zddd=Zed>hZfd)e>d?<hd@Zgd)e>dA<egd>hzZhd)e>dB<hdCZid)e>dD<eid>hzZjd)e>dE<dFdGhZkd)e>dH<hdIZld)e>dJ< ddKZmddLZn ddMZo ddNZp ddOZq ddPZr ddQZs ddRZt ddSZu ddTZvddUZwddVZxGdWdXeyZzGdYdZZ{dd[Z|Gd\d]e{Z}dd^Z~Gd_d`e{ZddaZGdbdce{ZgddZdee>df<GdgdheZe@dik(rddlZej yy)a~ Generic module for reading and writing the .glif format. More info about the .glif format (GLyphInterchangeFormat) can be found here: http://unifiedfontobject.org The main class in this module is :class:`GlyphSet`. It manages a set of .glif files in a folder. It offers two ways to read glyph data, and one way to write glyph data. See the class doc string for details. ) annotationsN) OrderedDict) TYPE_CHECKINGAnyOptionalUnioncast)warn)etreeplistlib)tobytes)AbstractPointPenPointToSegmentPen)UFOFormatVersion _UFOBaseIO) GlifLibError)userNameToFileName)BaseFormatVersionnormalizeFormatVersion numberTypes)anchorsValidatorcolorValidatorgenericTypeValidatorglyphLibValidatorguidelinesValidatoridentifierValidatorimageValidator)CallableIterableSet)Logger) ElementType FormatVersionFormatVersionsGLIFFormatVersionInputGlyphNameToFileNameFuncIntFloatPathOrFSUFOFormatVersionInput)FS)GlyphSetrreadGlyphFromStringwriteGlyphToStringglyphNameToFileName list[str]__all__r!loggerzcontents.plistzlayerinfo.plistc`eZdZdZdZdZe d dfd Ze d dfd ZxZ S) GLIFFormatVersiona{Class representing the versions of the .glif format supported by the UFO version in use. For a given :mod:`fontTools.ufoLib.UFOFormatVersion`, the :func:`supported_versions` method will return the supported versions of the GLIF file format. If the UFO version is unspecified, the :func:`supported_versions` method will return all available GLIF format versions. )r)rcX|t|j|St| SN)maxsupported_versionssuperdefault)clsufoFormatVersion __class__s ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/fontTools/ufoLib/glifLib.pyr;zGLIFFormatVersion.defaultYs/  's--.>?@ @w  c|t|S|jh}|tjk\r|j |j t|Sr7)r:r9 FORMAT_1_0r FORMAT_3_0add FORMAT_2_0 frozenset)r<r=versionsr>s r?r9z$GLIFFormatVersion.supported_versionsasO  #7-/ /NN# /:: : LL (""r@r7)r=Optional[UFOFormatVersion]returnr3)r=rHrIzfrozenset[GLIFFormatVersion]) __name__ __module__ __qualname____doc__rBrE classmethodr;r9 __classcell__r>s@r?r3r3Ns`JJ<@!9! !!<@ #9 # % # #r@r3c*eZdZdZddZdddZd dZy) Glyphz Minimal glyph object. It has no glyph attributes until either the draw() or the drawPoints() method has been called. c ||_||_yr7) glyphNameglyphSet)selfrTrUs r?__init__zGlyph.__init__zs'"* r@c@t||}|j|y)z9 Draw this glyph onto a *FontTools* Pen. )outputImpliedClosingLineN)r drawPoints)rVpenrYpointPens r?drawz Glyph.draw~s"% *B  !r@cR|jj|j||y)z2 Draw this glyph onto a PointPen. N)rU readGlyphrT)rVr\s r?rZzGlyph.drawPointss h?r@N)rTstrrUr+rINoneF)r[rrYboolrIra)r\rrIra)rJrKrLrMrWr]rZr@r?rRrRts +"@r@rRcDeZdZdZeZ d ddZdddZddZddZ dddZ dd dZ d!d Z d"d Z d# d$d Z d% d&d Zd'd Zd(dZd)dZeZd*dZd+dZ d d,dZ d d-dZ d d.dZddZd/dZd0dZy)1r+aL GlyphSet manages a set of .glif files inside one directory. GlyphSet's constructor takes a path to an existing directory as it's first argument. Reading glyph data can either be done through the readGlyph() method, or by using GlyphSet's dictionary interface, where the keys are glyph names and the values are (very) simple glyph objects. To write a glyph to the glyph set, you use the writeGlyph() method. The simple glyph objects returned through the dict interface do not support writing, they are just a convenient way to get at the glyph data. Nc t|t}t |dr|j }t|tr( tjj|} d|_n`t|tj j"r|} | j%d |_n!t)d t+|j,z | j/d }tj2j5||_| |_ | j9t:|_|r|j<stt:d |j>|_ ||_!|tD}||_"||_#||_$d|_%d|_&|jOy#t$r}ddlm}|d||d}~wwxYw#tjj$rtd|zwxYw#tjj&$rtd| zwxYw#tjj0$rt| }YewxYw) a 'path' should be a path (string) to an existing local directory, or an instance of fs.base.FS class. The optional 'glyphNameToFileNameFunc' argument must be a callback function that takes two arguments: a glyph name and a list of all existing filenames (if any exist). It should return a file name (including the .glif extension). The glyphNameToFileName function is called whenever a file name is created for a given glyph name. ``validateRead`` will validate read operations. Its default is ``True``. ``validateWrite`` will validate write operations. Its default is ``True``. ``expectContentsFile`` will raise a GlifLibError if a contents.plist file is not found on the glyph set file system. This should be set to ``True`` if you are reading an existing UFO and ``False`` if you create a fresh glyph set. r)UnsupportedUFOFormatzUnsupported UFO format: N __fspath__zNo glyphs directory '%s'Tzthe filesystem '%s' is closedFz-Expected a path string or fs object, found %s/z is missing.)(rr ValueErrorfontTools.ufoLib.errorsrghasattrrh isinstancer`fsosfsOSFSerrors CreateFailedr _shouldClosebaser*checkFilesystemClosed TypeErrortyperJ getsyspath NoSysPathpathbasenamedirNameexistsCONTENTS_FILENAME_havePreviousFilemajorr=ufoFormatVersionTupler. _validateRead_validateWrite_existingFileNames_reverseContentsrebuildContents) rVr{glyphNameToFileNameFuncr= validateRead validateWriteexpectContentsFileerg filesystems r?rWzGlyphSet.__init__s2 5 "2   4 &??$D dC  F!#d!3 '+D  bggjj )J Q  "!&D ?$t*BUBUU  #((-DGG,,T2  '1'8'89J'K d&<&<"3!4LAB B%5%;%;7G" " *&9 # #  $0$137:> m  D&*+;*>?  99)) F"#=#DEE F99-- Q"#BZ#OPP Qyy"" #z?D #s@FF4 G#H F1F,,F14,G #,H(H>=H>c| |j}|jti}|rd}t|tsd}nl|j D]Y\}}t|t sd}t|t sd}+|jj|rGttd||rtdtz||_ d|_ d|_ y)z Rebuild the contents dict by loading contents.plist. ``validateRead`` will validate the data, by default it is set to the class's ``validateRead`` value, can be overridden. NFTz( references a file that does not exist: z%s is not properly formatted) r _getPlistrrmdictitemsr`rnr~rcontentsrr)rVrr invalidFormatnamefileNames r?rzGlyphSet.rebuildContentss  --L>>"3R8 !Mh- $ &.nn&6 ND(%dC0(, %h4(, !WW^^H5*0(< "#ADU#UVV(0 "& $r@c|j>i}|jjD]\}}|||j<||_|jS)a Return a reversed dict of self.contents, mapping file names to glyph names. This is primarily an aid for custom glyph name to file name schemes that want to make sure they don't generate duplicate file names. The file names are converted to lowercase so we can reliably check for duplicates that only differ in case, which is important for case-insensitive file systems. )rrrlower)rVdkvs r?getReverseContentszGlyphSet.getReverseContentssX  (A ++- !1 !'')  !$%D !$$$r@cD|jt|jy)zv Write the contents.plist file out to disk. Call this method when you're done writing glyphs. N) _writePlistrrrVs r? writeContentszGlyphSet.writeContents(s *DMM:r@c| |j}|jti}|r&t|ts t dt |}|jD]\}} t|||y#t$rt d|zwxYw)z ``validateRead`` will validate the data, by default it is set to the class's ``validateRead`` value, can be overridden. Nz*layerinfo.plist is not properly formatted.zSThe supplied layer info object does not support setting a necessary attribute (%s).) rrLAYERINFO_FILENAMErmrrvalidateLayerInfoVersion3DatarsetattrAttributeError)rVinforinfoDictattrvalues r? readLayerInfozGlyphSet.readLayerInfo1s  --L>>"4b9 h-"#OPP4X>H#>>+ KD% dE* " "i s $ A44B c8| |j}|jjdkr"td|jjzi}tj D]+}t ||s t||}||dk(r|s'|||<-|r$|r t|}|jt|y|jr@|jjtr |jjtyyy#t$rtd|zwxYw)z ``validateWrite`` will validate the data, by default it is set to the class's ``validateWrite`` value, can be overridden. Nz)layerinfo.plist is not allowed in UFO %d.zMThe supplied info object does not support getting a necessary attribute (%s).lib)rrrrlayerInfoVersion3ValueDatakeysrlgetattrrrrrrrnr~remove)rVrrinfoDatarrs r?writeLayerInfozGlyphSet.writeLayerInfoGs!   //M  % % + +a /;,,223  .335 'DtT"#D$/E =TU]5!& ' 8B   / :  # #7I(J GGNN- .)K #&&gs 1 DDc |j|} |jj|S#tjj$rt d|d|d|jwxYw)a Get the raw GLIF text for a given glyph name. This only works for GLIF files that are already on disk. This method is useful in situations when the raw XML needs to be read from a glyph set for a particular glyph before fully parsing it into an object structure via the readGlyph method. Raises KeyError if 'glyphName' is not in contents.plist, or GlifLibError if the file associated with can't be found. z The file 'z' associated with glyph 'z&' in contents.plist does not exist on )rrn readbytesrqResourceNotFoundrrVrTrs r?getGLIFzGlyphSet.getGLIFksc==+ 77$$X. .yy)) *2ItwwH  s ,>+; <  ,%%hnn&67 MM) $r@cHt|jjSr7)listrrrs r?rz GlyphSet.keysQsDMM&&())r@c||jvSr7)rrVrTs r?has_keyzGlyphSet.has_keyTsDMM))r@c,t|jSr7)lenrrs r?__len__zGlyphSet.__len__Ys4==!!r@cX||jvr t||j||Sr7)rKeyError glyphClassrs r? __getitem__zGlyphSet.__getitem__\s* DMM )9% %y$//r@ci}||jj}|D]!}|j|}t|||<#|S)aC Return a dictionary that maps glyph names to lists containing the unicode value[s] for that glyph, if any. This parses the .glif files partially, so it is a lot faster than parsing all files completely. By default this checks all glyphs, but a subset can be passed with glyphNames. )rrr_fetchUnicodes)rV glyphNamesunicodesrTrs r? getUnicodeszGlyphSet.getUnicodescsT  ++-J# 7I<< *D"0"6HY  7r@ci}||jj}|D]!}|j|}t|||<#|S)aF Return a dictionary that maps glyph names to lists containing the base glyph name of components in the glyph. This parses the .glif files partially, so it is a lot faster than parsing all files completely. By default this checks all glyphs, but a subset can be passed with glyphNames. )rrr_fetchComponentBases)rVr componentsrTrs r?getComponentReferenceszGlyphSet.getComponentReferencestsU  ++-J# ?I<< *D$8$>Jy ! ?r@ci}||jj}|D]!}|j|}t|||<#|S)a9 Return a dictionary that maps glyph names to the file name of the image referenced by the glyph. This parses the .glif files partially, so it is a lot faster than parsing all files completely. By default this checks all glyphs, but a subset can be passed with glyphNames. )rrr_fetchImageFileName)rVrimagesrTrs r?getImageReferenceszGlyphSet.getImageReferencessT  ++-J# :I<< *D 3D 9F9  : r@cR|jr|jjyyr7)rsrnclosers r?rzGlyphSet.closes    GGMMO r@c|Sr7rdrs r? __enter__zGlyphSet.__enter__s r@c$|jyr7)r)rVexc_type exc_valueexc_tbs r?__exit__zGlyphSet.__exit__s  r@)NNTTF)r{r(rr&r=r)rrcrrcrrcrIrarb)rrcrIra)rIdict[str, str]rIrar7)rrrOptional[bool]rIra)rrrrrIra)rTr`rIbytes)rTr`rIzOptional[float])NNN) rTr`r Optional[Any]r\Optional[AbstractPointPen]rrrIraNNNN) rTr`rrrz,Optional[Callable[[AbstractPointPen], None]]rr%rrrIra)rTr`rIra)rIr/)rTr`rIrc)rIint)rTr`rIr)rOptional[Iterable[str]]rIzdict[str, list[int]])rrrIzdict[str, list[str]])rrrIzdict[str, Optional[str]])rIr+)rrrrrrrIra)rJrKrLrMrRrrWrrrrrrrr_rrrr __contains__rrrrrrrrrdr@r?r+r+s J <@26!"#(SS"9S0 S  S  S!S Sj%@% ;,"/H* 6 &*/3#' OO#O- O ! O  Oh&*GK04#' c+c+#c+E c+ . c+ ! c+ c+J %**L"0591 $591 $591 !"r@r+c6| t}t||dS)z Wrapper around the userNameToFileName function in filenames.py Note that existingFileNames should be a set for large glyphsets or performance will suffer. z.glif)existingsuffix)setr)rTexistingFileNamess r?r.r.s" E i2CG TTr@TcBt|}|tj}nMtt}}|D]$} t |t} |j | &|st d|t|||||y#t $r|j |YdwxYw)a/ Read .glif data from a string into a glyph object. The 'glyphObject' argument can be any kind of object (even None); the readGlyphFromString() method will attempt to set the following attributes on it: width the advance width of the glyph height the advance height of the glyph unicodes a list of unicode values for this glyph note a string lib a dictionary containing custom data image a dictionary containing image data guidelines a list of guideline data dictionaries anchors a list of anchor data dictionaries All attributes are optional, in two ways: 1) An attribute *won't* be set if the .glif file doesn't contain data for it. 'glyphObject' will have to deal with default values itself. 2) If setting the attribute fails with an AttributeError (for example if the 'glyphObject' attribute is read- only), readGlyphFromString() will not propagate that exception, but ignore that attribute. To retrieve outline information, you need to pass an object conforming to the PointPen protocol as the 'pointPen' argument. This argument may be None if you don't need the outline data. The formatVersions optional argument define the GLIF format versions that are allowed to be read. The type is Optional[Iterable[tuple[int, int], int]]. It can contain either integers (for the major versions to be allowed, with minor digits defaulting to 0), or tuples of integers to specify both (major, minor) versions. By default when formatVersions is None all the GLIF format versions currently defined are allowed to be read. ``validate`` will validate the read data. It is set to ``True`` by default. Nz9None of the requested GLIF formatVersions are supported: r)rr3r9rrrDrjr) aStringrr\rrrvalidFormatVersionsinvalidFormatVersionsrrs r?r,r,sp w 'D  0 0 2 69UCE2 7A 7 6q:K L $'' 6  7#K!$&   *  -%))!, -sBBBcF t|t}|rt |t s td|rt|dk(r tdtd|fdt|jfg}|jdk7rt|j|d<tjd |}t} t!|||t#|d d r t%|||t#|d d r t'||||jd k\rt#|dd r t)||||jd k\rt#|dd rt+||| |t#|dd } |jd k\r| rt-||| ||\tj.|d} t1| | |} || |jdk(r| r t3| | |t| sd| _t#|dd r t7|||tj8|ddd} | S#t$rddlm}|dwxYw)z>Return .glif data for a glyph as a UTF-8 encoded bytes string.rrz2Unsupported GLIF format version: {formatVersion!r}z)The glyph name is not properly formatted.zThe glyph name is empty.rformat formatMinorglyphrNnoter5image guidelinesanchorsoutline) identifiersrr4 rzUTF-8T)encodingxml_declaration pretty_print)rr3rjrkrrmr`rrrreprrminorr Elementr _writeAdvancer_writeUnicodes _writeNote _writeImage_writeGuidelines _writeAnchors SubElement GLIFPointPen_writeAnchorsFormat1r _writeLibtostring)rTrrwriterrrr glyphAttrsrootrrrr[rs r?rr s .}>OP  9c2FGGC Na'566 ) xm.A.A)BCDJa$()<)<$= =! ==* -DEK+tX.{J-{D(3{FD);h/aGK$$GKx0aGKt$LdKBk9d3GaGk4h?!""437 hOs   ! # gx 87|!GL{E4(+tX. >> w4 D Kk  A# @   s HH cDt|||||}|jdS)a Return .glif data for a glyph as a string. The XML declaration's encoding is always set to "UTF-8". The 'glyphObject' argument can be any kind of object (even None); the writeGlyphToString() method will attempt to get the following attributes from it: width the advance width of the glyph height the advance height of the glyph unicodes a list of unicode values for this glyph note a string lib a dictionary containing custom data image a dictionary containing image data guidelines a list of guideline data dictionaries anchors a list of anchor data dictionaries All attributes are optional: if 'glyphObject' doesn't have the attribute, it will simply be skipped. To write outline data to the .glif file, writeGlyphToString() needs a function (any callable object actually) that will take one argument: an object that conforms to the PointPen protocol. The function will be called by writeGlyphToString(); it has to call the proper PointPen methods to transfer the outline to the .glif file. The GLIF format version can be specified with the formatVersion argument. This accepts either a tuple of integers for (major, minor), or a single integer for the major digit only (with minor digit implied as 0). By default when formatVesion is None the latest GLIF format version will be used; currently it's 2.0, which is equivalent to formatVersion=(2, 0). An UnsupportedGLIFFormat exception is raised if the requested UFO formatVersion is not supported. ``validate`` will validate the written data. It is set to ``True`` by default. )rrrrutf-8)rdecode)rTrrrrrs r?r-r-Ps/f %#  D ;;w r@c t|dd}|$|rt|ts td|dk(rd}t|dd}|$|rt|ts td|dk(rd}|;|9t j |dt dt|fdt|fgy|+t j |dtt|y|+t j |dtt|yy) Nwidthz$width attribute must be int or floatrheightz%height attribute must be int or floatadvance)r.)r/) rrmrrr r"rrr)relementrr.r/s r?rrs K$ /E  Juk:EF F A:E [(D 1F  Jv{;FG G Q;F V/    (DL1GT%[3IJ K   )TU -DE   )Tf-FG r@ct|dg}|rt|tr|g}t}|D][}|rt|ts t d||vr%|j |d|z}t j|dt|]y)Nrzunicode values must be intz%04Xunicode)hex) rrmrrrrDr r"r)rr1rrseencodehexCodes r?rrs{J3HJx-: 5D@ JtS1;< < 4<  4- )Tg->?@r@ct|dd}|rt|ts tdt|tr4|j }d|zdz}|t j |d_yy)Nrznote attribute must be str )rrmr`rstripr r"r)rr1rrs r?rrse ; -D 4-788$zz|d{T!15&).r@c<t|dd}|y|rt|s tdtd|dfg}tD]+\}}|j ||}||k7st |||<-|j d}|||d<tj|d|y)NrzMimage attribute must be a dict or dict-like object with the proper structure.rcolor) rrrr_transformationInforrr r") rr1rrattrsrr;rr<s r?rrs K$ /E }u- [   *eJ&789 :E,& g $( G u+E$K& IIg E g Wgu-r@set[str]c>t|dg}|rt|s td|D]}t}|j d}|t ||d<|j d}|t ||d<|j d} | t | |d<|j d} | | |d<|j d} | | |d<|j d} | *|r| |vrtd | z| |d<|j | tj|d |y) Nrz8guidelines attribute does not have the proper structure.xyanglerr< identifier"identifier used more than once: %s guideline) rrrrrrrDr r") rr1rrrrFr>rArBrCrr<rDs r?r r s1lB7J+J7UVV6   MM#  =aE#J MM#  =aE#J g&  !%[E'N}}V$   E&M g&  "E'N]]<0  !J+5"#G*#TUU",E,  OOJ ' +u5/6r@c.|rt|s td|D]x}i}|d}t||d<|d}t||d<|jd}|||d<|j |j ||fd||j zy)N5anchors attribute does not have the proper structure.rArBrmove) segmentTyper)rrrr beginPathaddPointendPath)r[rranchorr>rArBrs r?r$r$s(1RSS  3K!Wc 3K!Wc zz&!   E&M  aVd ;  r@ct|dg}|rt|s td|D]}t}|d}t ||d<|d}t ||d<|j d} | | |d<|j d} | | |d<|j d} | *|r| |vrtd| z| |d<|j | tj|d |y) NrrHrArBrr<rDrErN) rrrrrrrDr r") rr1rrrrNr>rArBrr<rDs r?r!r!s k9b1G(1RSS3  3K!Wc 3K!Wc zz&!   E&M 7#  "E'NZZ -  !J+5"#G*#TUU",E,  OOJ ' (E2%3r@c t|dd}|sy|rt|\}}|s t|t|ts t |}t j |d}tj|dj|y)Nrr5) indent_level) rrrrmrr totreer r"append)rr1rrvalidmessagers r?r%r%"ss +ud +C *3/ww' ' c4 3i!,A We$++A.r@)rxvalueValidator)r<rc|tvryt|}|jd}|jd}|jd}t|sJ| |||}|S|tk(r |||}|S||}|S)a This performs very basic validation of the value for attribute following the UFO 3 fontinfo.plist specification. The results of this should not be interpretted as *correct* for the font that they are part of. This merely indicates that the value is of the proper type and, where the specification defines a set range of possible values for an attribute, that the value is in the accepted range. FrxrV valueOptions)rrcallabler)rrdataValidationDict valueType validatorrX isValidValues r?*validateLayerInfoVersion3ValueForAttributer^<s --3D9"&&v.I"&&'78I%)).9L I    5   , ,$UI6L %U+L r@c|jD];\}}|tvrtd|zt||}|r+td|d|d|S)a This performs very basic validation of the value for infoData following the UFO 3 layerinfo.plist specification. The results of this should not be interpretted as *correct* for the font that they are part of. This merely indicates that the values are of the proper type and, where the specification defines a set range of possible values for an attribute, that the value is in the accepted range. zUnknown attribute %s.zInvalid value for attribute z (z).)rrrr^)rrrr]s r?rrYsk ~~'S e 1 16=> >A$N !=dV2eYbQR R S Or@cdtjr,tj|tjd}ntj|}|j }|j dk7r t d|jr(|jjdk7r t d|S)NTremove_commentsparserr#The GLIF is not properly formatted.Invalid GLIF structure.) r _have_lxmlparse XMLParsergetroottagrrr:)aFilerr)s r?_glifTreeFromFilernqs {{5)NO{{5! <<>D xx7@AA yyTYY__&",455 Kr@ct|d} tjr,tj|tjd}ntj|}|jdk7r t d|jr(|jjd k7r t d |S#t $r}t d|d}~wwxYw) Nr+)rTrarczGLIF contains invalid XML.rrerfrg) r r rh fromstringrj Exceptionrrlrr:)rrr)etree_exceptions r?rr~s 7W -DN   ##DQU1VWD##D)D xx7@AA yyTYY__&",455 K N78oMNsAB00 C 9 CC c|jd}||r tdd}|jdd} tt|t|f}|r||vrtd | t|} | |||||j y#t$rN}d|d|} |rddlm} | | |tj}tjd| |Yd}~d}~wwxYw#t$r t|wxYw) Nr z#Unspecified format version in GLIF.rr zUnsupported GLIF format: rrz_%s. Assuming the latest supported version (%s). Some data may be skipped or parsed incorrectly.zForbidden GLIF format version: )rrr\rr )rrr3rrjrkrr;r1warning_READ_GLYPH_FROM_TREE_FUNCSrNotImplementedErrorr) rrr\rrformatVersionMajorformatVersionMinorrrmsgrreadGlyphFromTrees r?rrs*(+! DE E-3 ) # $c*<&= > *M7<]      . 1!-001s$B * C% C"ACC"%C:c Zt|||g}dx}x}x}} |D]f} || jdk(rk|rX|r td| jr td| jr(| jj dk7r tdd}t ||| || jdk(r|r |r td d}t|| | jd k(rA| jd } | td  t| d } | |vr|j| | jdk(r|r | r tdd} t|| ,| jdk(r |r |r tdd}t|| |[td| z|rt|d|yy#t$r tdwxYw)NFr*The outline element occurs more than once.0The outline element contains unknown attributes.rfInvalid outline structure.Tr0*The advance element occurs more than once.r3r48A unicode element is missing its required hex attribute.3Illegal value for hex attribute of unicode element.r'The note element occurs more than once.r&The lib element occurs more than once.Unknown element in GLIF: %sr) _readNamerlrattribrr:buildOutlineFormat1 _readAdvancerrrSrj _readNote_readLib_relaxedSetattr) rrr\rkwargsrhaveSeenAdvancehaveSeenOutline haveSeenLib haveSeenNoter1rs r?_readGlyphFromTreeFormat1rsk4*HEJJOJoJ l.H    ;;) #"&'STT>>&J<&'CDD"O  Xw I [[I %O"#OPP"O g . [[I % E"Ay"N 2JH$OOA& [[F "L"#LMML k7 + [[E !K"#KLLK ['8 4>&J<&'CDD"O##7K[[I %O"#OPP"O g . [[I % E"Ay"N 2JH$OOA& [[K 'CL"#KLL'..)F+ 96>#*6$<#8F4L 9   f % [[H $CL"#HII'..)F" 97>>)#*6$<#8F4L 9 NN6 " [[G # &'QRRw<&'KLL M {GX 6 [[F "L"#LMML k7 + [[E !K"#KLLK ['8 4 ,WkBFG G Y8c "I s !L!!L6z+dict[GLIFFormatVersion, Callable[..., Any]]rucj|jd}|r |s td|r|t|d|yyy)NrzEmpty glyph name in GLIF.)rrr)rr)rrTs r?rrss< I 677[, VY7-yr@ct|jdd}t|d|t|jdd}t|d|y)Nr.rr/)rrr)rr0r.r/s r?rr{sD GKK+ ,EK%0 W[[1- .FK62r@c|jy|jjd}djd|D}t|d|y)Nr9c3^K|]%}|js|j'ywr7)r:).0lines r? z_readNote..sDdtzz|TZZ\Ds--r)rsplitjoinr)rrliness r?rrsA yy IIOOD !E 99DeD DDK.r@ct|dk(sJ|d}tj|}|rt|\}}|s t |t |d|y)Nr4rr)rr fromtreerrr)rrrchildplistrTrUs r?rrsV s8q== FE   e $E*51ww' 'K.r@ct|j}tD]%\}}|j||}t |||<'|rt |s t dt|d|y)Nz,The image element is not properly formatted.r)rrr=rrrrr)rrr imageDatarr;rs r?rrsdU\\"I,) g dG,!%. $)y1IJJK)4r@rDcontourAttributesFormat2>rtxScaleyScalexOffsetxyScaleyOffsetyxScalecomponentAttributesFormat1componentAttributesFormat2>rArBrrxsmoothpointAttributesFormat1pointAttributesFormat2noyespointSmoothOptions>rrIcurveqcurveoffcurvepointTypeOptionscg}|D]}|jdk(rSt|dk(r4|d}|jdk(r t||}||j|T|Wt |||e|jdk(r|wt |||t d|z|)|r&|rt|s t dt|d|yyy) Ncontourr4rpoint component&Unknown element in outline element: %sz*GLIF 1 anchors are not properly formatted.r) rlr_buildAnchorFormat1rS_buildOutlineContourFormat1_buildOutlineComponentFormat1rrr)rr[rrrr1rrNs r?rrs GS ;;) #7|q  99'0AF)v. +C(C [[K '-c7HEG'QR RS 7 ,W5KL L Y8$+r@c0|jddk7ry|jd}|y|jd}|jd}|r | td|J|r | td|Jt|}t|}t|||}|S) NrxrIrrArBz1Required x attribute is missing in point element.z1Required y attribute is missing in point element.)rArBr)rrrr)rrrrArBrNs r?rrs yyF" 99V D | #A #AAINOO ==AINOO == A A A &F Mr@c|r|jr td|jt|rt |t d|}t |||jy)Nz&Unknown attributes in contour element.T)openContourOffCurveLeniencyr)rrrKr"_validateAndMassagePointStructuresr_buildOutlinePointsFormat1rM)r[rrmassageds r?rrsTGNNCDDMMO 7|5  "(,   #31KKMr@cr|D]2}|d}|d}|d}|d}|d}|j||f|||4y)NrArBrJrrrJrr)rL)r[rrrArBrJrrs r?rrs[P #J #JM* xV} aVV$ O Pr@c |rKtr tdjjD]}|tvs td|zj d}|r | td|Jt fdtD}tt ttttttf|}|j||y)N,Unknown child elements of component element.*Unknown attribute in component element: %srt3The base attribute is not defined in the component.c3`K|]%\}}tj|xs|'ywr7rrrrr;rs r?rz0_buildOutlineComponentFormat1..-4AD' d#.w/+.) rrrrrrtupler=r float addComponent)r[rrr baseGlyphNametransformations ` r?rrs y>MN N$$))+ XD55"#ORV#VWW XMM&)MM)PQQ  $$ $EXN eUE5%67N]N3r@c|D]U}|jdk(rt||||!|jdk(rt||||?td|jzy)Nrrr)rl_buildOutlineContourFormat2_buildOutlineComponentFormat2r)rr[rrrr1s r?rrs^W ;;) # 'Wk8 L [[K ' )#w X NG'++UV V Wr@c|r5|jjD]}|tvs td|z|j d}|>|r+||vrtd|zt |std|z|j | |j|t|r t|t|}t|||||jy#t$r#|jtdtYgwxYw)Nz(Unknown attribute in contour element: %srD)The identifier %s is used more than once.z'The contour identifier %s is not valid.rDzbThe beginPath method needs an identifier kwarg. The contour's identifier value has been discarded.)r)rrrrrrrDrKrwr DeprecationWarningrrr_buildOutlinePointsFormat2rM)r[rrrrrDrs r?rr-sNN'') VD33"#MPT#TUU V\*J [("?*L'z2"= J  #   , 7|5 +h  #3+xHKKM    p   s C)DDc|D]}|d}|d}|d}|d}|d} |jd} | >|r+| |vrtd| zt| std| z|j|  |j ||f||| | y#t $r*|j ||f||| t d tYwxYw) NrArBrJrrrDrThe identifier %s is not valid.)rJrrrDrz_The addPoint method needs an identifier kwarg. The point's identifier value has been discarded.)rrrrDrLrwr r) r[rrrrrArBrJrrrDs r?rrPs  #J #JM* xV}YY|,  !,&CjP+:6&'H:'UVV OOJ '  LLA'%  #0  LL!Q[dL S q"  s1B  0B?>B?c |rKtr tdjjD]}|tvs td|zj d}|r | td|Jt fdtD}tt ttttttf|}j d}|@|r-||vrtd|z|rt|std|z|j| |j||| y#t$r%|j||td tYywxYw) Nrrrtrc3`K|]%\}}tj|xs|'ywr7rrs r?rz0_buildOutlineComponentFormat2..rrrDrrrzgThe addComponent method needs an identifier kwarg. The component's identifier value has been discarded.)rrrrrrrr=r rrrDrrwr r)r[rrrrrrrDs ` r?rrvsg y>MN N$$))+ XD55"#ORV#VWW XMM&)MM)PQQ  $$ $EXN eUE5%67N|,J [("?*L 3J ?"#Dz#QRR #  :N   7 u   sD%%+EEc|t|syd}d}g}t|D][\}}|jdk7rtd|jzt |j } |j | |r=| jD]} | |vstd| zt|r tddD]} t| | | | <| jd d } |r| tvrtd | z| d k(rd} | | d <| d }n|}|r| dk(r|dk7r td| jdd} |r| | tvrtd| z| dk(} | | d<|r| r | tdd|j vsWd| d<^|r1|dd dk(r&d}t|D]} | d |dz }n|r|d| }|ri|rg|et|dz |z }|D]O} | d }||dz }|r<|dk(r td|dk(r td|dk(r|dkDrtd|dk(rn d}Q|S#t$r} td| d| d} ~ wwxYw)NFrz.Unknown child element (%s) of contour element.z&Unknown attribute in point element: %sz(Unknown child elements in point element.rz Required z' attribute is missing in point element.rxrzUnknown point type: %srJTrIrz9A move point occurs after the first point in the contour.rrzUnknown point smooth value: %srz*smooth attribute set in an offcurve point.rr4zmove can not have an offcurve.rzline can not have an offcurve.rr5z%Too many offcurves defined for curve.r)r enumeraterlrrrrSrrrpoprrrreversed)rpointAttributesrrlastOnCurvePointhaveOffCurvePointrindexr1rrr pointTypercountoffCurvesCountrJs r?rrs  w<H#G,4!w ;;' !@7;;N W^^$   X.&'ORV'VWW X7|"#MNN D %eDk2d  IIfj1  )997)CD D  "I(m   $ $   V+ K 8T* *//"#Cf#LMM5 h 9#4KL L  ' E&Mi4!j# A;} % /E!(+ '/QJE   #GeV,%*:*FX*-== #E .K"!#!"f,*+KLL$.*+KLL$/)A-"./V"WW$0!") #* OO "v%LM s7H H;&H66H;c> t|||y#t$rYywxYwr7)rr)objectrrs r?rr s% e$    s  c t|}|S#t$rYnwxYw t|}|S#t$rtd|zwxYw)a Given a numeric string, return an integer or a float, whichever the string indicates. _number("1") will return the integer 1, _number("1.0") will return the float 1.0. >>> _number("1") 1 >>> _number("1.0") 1.0 >>> _number("a") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... GlifLibError: Could not convert a to an int or float. z(Could not convert %s to an int or float.)rrjrr)sns r?rrs] !f    K !H KEIJJKs   ,Ac eZdZy) _DoneParsingN)rJrKrLrdr@r?rr6sr@rc,eZdZddZddZddZd dZy) _BaseParsercg|_yr7) _elementStackrs r?rWz_BaseParser.__init__;s (*r@cddlm}|}|j|_|j|_|j |dy)Nr) ParserCreateT)xml.parsers.expatrstartElementHandlerStartElementHandlerendElementHandlerEndElementHandlerParse)rVrrrds r?riz_BaseParser.parse>s62%)%=%="#'#9#9  T4 r@c:|jj|yr7)rrS)rVrr>s r?rz_BaseParser.startElementHandlerFs !!$'r@cH|jjd}||k(sJy)N)rr)rVrothers r?rz_BaseParser.endElementHandlerIs$""&&r*}}r@Nr)rr)rr`r>rrIrarr`rIra)rJrKrLrWrirrrdr@r?rr:s+!(r@rcPt}|j||jS)z0 Get a list of unicodes listed in glif. )_FetchUnicodesParserrirglifrds r?rrQs"" #F LL ??r@c,eZdZdfd Zdfd ZxZS)r c0g|_t| yr7)rr:rWrVr>s r?rWz_FetchUnicodesParser.__init__[s#%  r@c|dk(rg|jr[|jddk(rI|jd}|6 t|d}||jvr|jj |t |||y#t $rYwxYw)Nr3rrr4r)rrrrrSrjr:r)rVrr>rintValuer>s r?rz(_FetchUnicodesParser.startElementHandler_s I """"2&'1IIe$E "5"~Ht}}4 ,,X6 #D%0"s5A?? B  B rrr`r>rrIrarJrKrLrWrrOrPs@r?r r Zs11r@r ct} |j||jS#t$rY|jSwxYw)z1 The image file name (if any) from glif. )_FetchImageFileNameParserrirrr s r?rrssG' (F  T ??   ?? s) AAc,eZdZdfd Zdfd ZxZS)rc0d|_t| yr7)rr:rWrs r?rWz"_FetchImageFileNameParser.__init__s'+  r@c|dk(r:|jr.|jddk(r|jd|_tt|||y)Nrrrr)rrrrr:r)rVrr>r>s r?rz-_FetchImageFileNameParser.startElementHandlersJ 7?t11d6H6H6LPW6W!IIj1DM  #D%0r@rrrrPs@r?rrs11r@rct} |j|t|jS#t$rY wxYw)z= Get a list of component base glyphs listed in glif. )_FetchComponentBasesParserrirrbasesr s r?rrsB( )F  T      s 2 >>c8eZdZdfd Zdfd Zdfd ZxZS)rc0g|_t| yr7)rr:rWrs r?rWz#_FetchComponentBasesParser.__init__s "  r@c|dk(rL|jr@|jddk(r.|jd}||jj|t|||y)Nrrrrt)rrrrSr:r)rVrr>rtr>s r?rz._FetchComponentBasesParser.startElementHandlers\ K """"2&)399V$D !!$' #D%0r@c:|dk(rtt| |y)Nr)rr:r)rVrr>s r?rz,_FetchComponentBasesParser.endElementHandlers 9   !$'r@rrr )rJrKrLrWrrrOrPs@r?rrs 1((r@r))rr4)rr)rr)rr4)rr)rrzlist[tuple[str, int]]r=cReZdZdZ d d dZd dZdZ d dZd dZy) r#zb Helper class using the PointPen protocol to write the part of .glif files. Nc| t}t|t|_||_||_d|_d|_g|_||_ y)Nr) rrr3rrrrprevOffCurveCountprevPointTypesr)rVr1rrrs r?rWzGLIFPointPen.__init__sN  %K3MCTU&  !")+  r@c jt}|z|jjdk\ra|jr5||jvrt d|zt |st d|z||d<|jj|tj|jd||_ d|_ y)Nr5rE%identifier not formatted properly: %srDrr) rrrrrrrrDr r"rrr#)rVrDrr>s r?rKzGLIFPointPen.beginPaths   !d&8&8&>&>!&C}}!1!11&coords r?rLzGLIFPointPen.addPoints  >}}OE%e[9*+MNNObeE#JbeE#J * $K ==f$)<)<"V//''''+z9"#E #STTg%$*@*@1*D"#QRR  "'E&M$K * $  " "a ' "%&D " "";/ }} !:"#KLL#E(O   E&M  !d&8&8&>&>!&C}}!1!11&rr;rs r?rzGLIFPointPen.addComponent/sfi012&)*=~&N * "OT7U}}Z{%C"#OPP"5kd  *  !d&8&8&>&>!&C}}!1!11&rKs@ ##<<&&*,G909 77   3#""8,,%&#)#L@@>KzKf U&"&"%) S SSS# S  S  Sp"&6: -1 @@@4@  @ + @  @ @J"&6:-1 : : : 4: + :  :  : zH2 @6.(66*69A6MQ6 6@"33 33 3  3< /*s> : T*> ? :0 &"&+/->-Q-Q-S 2 22)2+ 2  2  2n"&+/ =; =;=;)=; =;  =;  =;D"&+/ f9 f9f9)f9 f9  f9  f9T  ";  ";LH 83//5'3^(3(H(B\N'RHR#GG#9\N#JJ $e}H,L(L 99 #9#9 9  9:( $/;? " P  P$8 P  P4 4&14=A4 42 W W  W# W W  W  W   $/ >F RV   F# # !## #  #L$ $ &1$ @H$ TX$  $ VKOeZ KD 9 .1;12  1 1 ((4.*C;#C;L zGOOr@