freetype-py-2.5.1/0000775000175000017500000000000014664131406014175 5ustar georgeskgeorgeskfreetype-py-2.5.1/README.rst0000664000175000017500000001266514664131406015676 0ustar georgeskgeorgeskFreeType (high-level Python API) ================================ Freetype Python provides bindings for the FreeType library. Only the high-level API is bound. Documentation available at: http://freetype-py.readthedocs.org/en/latest/ Installation ============ **From PyPI, recommended**: `pip install freetype-py`. This will install the library with a bundled FreeType binary, so you're ready to go on Windows, macOS and Linux (all with 32 and 64 bit x86 architecture support). Do note: if you specify the `--no-binary` paramater to pip, or use a different architecture for which we don't pre-compile binaries, the package will default to using an external FreeType library. Specify the environment variable `FREETYPEPY_BUNDLE_FT=1` before calling pip to compile a binary yourself. Installation with compiling FreeType from source ------------------------------------------------ If you don't want to or can't use the pre-built binaries, build FreeType yourself: `export FREETYPEPY_BUNDLE_FT=yesplease && pip install .`. This will download and compile FreeType with Harfbuzz support as specified in `setup-build-freetype.py`. Set the environment variable `PYTHON_ARCH` to 32 or 64 to explicitly set an architecture, default is whatever your host machine uses. On macOS, we will always build a universal 32 and 64 bit Intel binary. - Windows: You need CMake and a C and C++ compiler, e.g. the Visual Code Community 2017 distribution with the desktop C++ workload. - macOS: You need CMake and the XCode tools (full IDE not necessary) - Linux: You need CMake, gcc and g++. For building a 32 bit library on a 64 bit machine, you need gcc-multilib and g++-multilib (Debian) or glibc-devel.i686 and libstdc++-devel.i686 (Fedora). Installation with an external FreeType library (the default) ------------------------------------------------------------ Install just the pure Python library and let it find a system-wide installed FreeType at runtime. Mac users ~~~~~~~~~ Freetype should be already installed on your system. If not, either install it using `homebrew `_ or compile it and place the library binary file in '/usr/local/lib'. Linux users ~~~~~~~~~~~ Freetype should be already installed on your system. If not, either install relevant package from your package manager or compile from sources and place the library binary file in '/usr/local/lib'. Window users ~~~~~~~~~~~~ There are no official Freetype binary releases available, but they offer some links to precompiled Windows DLLs. Please see the `FreeType Downloads `_ page for links. You can also compile the FreeType library from source yourself. If you are using freetype-py on Windows with a 32-Bit version of Python, you need the 32-Bit version of the Freetype binary. The same applies for a 64-Bit version of Python. Because of the way Windows searches for dll files, make sure the resulting file is named 'freetype.dll' (and not something like Freetype245.dll). Windows expects the library in one of the directories listed in the $PATH environment variable. As it is not recommended to place the dll in a Windows system folder, you can choose one of the following ways to solve this: * Place library in a folder of your choice and edit the $PATH user environment variable * Place library in a folder of your choice and edit the $PATH system environment variable * For development purpose, place the library in the working directory of the application * Place the library in one of the existing directories listed in $PATH To get a complete list of all the directories in the $PATH environment variable (user and system), open a command promt and type .. code:: echo %PATH% Usage example ============= .. code:: python import freetype face = freetype.Face("Vera.ttf") face.set_char_size( 48*64 ) face.load_char('S') bitmap = face.glyph.bitmap print(bitmap.buffer) Screenshots =========== Screenshot below comes from the wordle.py example. No clever tricks here, just brute force. .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/wordle.png Screenshots below comes from the glyph-vector.py and glyph-vector-2.py examples showing how to access a glyph outline information and use it to draw the glyph. Rendering (with Bézier curves) is done using matplotlib. .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/S.png .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/G.png Screenshot below comes from the glyph-color.py showing how to draw and combine a glyph outline with the regular glyph. .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/outline.png The screenshot below comes from the hello-world.py example showing how to draw text in a bitmap (that has been zoomed in to show antialiasing). .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/hello-world.png The screenshot below comes from the agg-trick.py example showing an implementation of ideas from the `Texts Rasterization Exposures `_ by Maxim Shemarev. .. image:: https://raw.githubusercontent.com/rougier/freetype-py/master/doc/_static/agg-trick.png Freezing apps ============= Freetype implements a hook for PyInstaller to help simplify the freezing process (it e.g. ensures that the freetype DLL is included). This hook requires PyInstaller version 4+. freetype-py-2.5.1/examples/0000775000175000017500000000000014664131406016013 5ustar georgeskgeorgeskfreetype-py-2.5.1/examples/sfnt-names.py0000664000175000017500000000414614664131406020445 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from __future__ import print_function from __future__ import division from freetype import * def platform_name(platform_id): for key, value in TT_PLATFORMS.items(): if value == platform_id: return key return 'Unknown platform' def encoding_name(platform_id, encoding_id): if platform_id == TT_PLATFORM_APPLE_UNICODE: encodings = TT_APPLE_IDS elif platform_id == TT_PLATFORM_MACINTOSH: encodings = TT_MAC_IDS elif platform_id == TT_PLATFORM_MICROSOFT: encodings = TT_MS_IDS elif platform_id == TT_PLATFORM_ADOBE: encodings = TT_ADOBE_IDS else: return 'Unknown encoding' for key, value in encodings.items(): if value == encoding_id: return key return 'Unknown encoding' def language_name(platform_id, language_id): if platform_id == TT_PLATFORM_MACINTOSH: languages = TT_MAC_LANGIDS elif platform_id == TT_PLATFORM_MICROSOFT: languages = TT_MS_LANGIDS else: return 'Unknown language' for key, value in languages.items(): if value == language_id: return key return 'Unknown language' if __name__ == '__main__': import os, sys if len(sys.argv) < 2: print("Usage: %s font_filename" % sys.argv[0]) sys.exit() face = Face(sys.argv[1]) name = face.get_sfnt_name(0) print( 'platform_id:', platform_name(name.platform_id) ) print( 'encoding_id:', encoding_name(name.platform_id, name.encoding_id) ) print( 'language_id:', language_name(name.platform_id, name.language_id) ) for i in range(face.sfnt_name_count): name = face.get_sfnt_name(i).string print(i, name.decode('utf-8', 'ignore')) freetype-py-2.5.1/examples/SourceSansVariable-LICENSE.md0000664000175000017500000001060614664131406023153 0ustar georgeskgeorgeskCopyright 2010-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. freetype-py-2.5.1/examples/ftdump.py0000664000175000017500000002272314664131406017672 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from __future__ import print_function from __future__ import division import sys from freetype import * verbose = 0 debug = 0 name_tables = 0 def usage( execname ): print( ) print( "ftdump: simple font dumper -- part of the FreeType project" ) print( "----------------------------------------------------------" ) print( "Usage: %s [options] fontname", execname ) print( ) print( " -n print SFNT name tables" ) print( " -v be verbose" ) print( ) sys.exit() def Print_Name( face ): print( "font name entries" ); print( " family: %s" % face.family_name.decode("ascii", errors='ignore') ) print( " style: %s" % face.style_name.decode("ascii", errors='ignore') ) ps_name = face.postscript_name or "UNAVAILABLE" print( " postscript: %s" % ps_name.decode("ascii", errors='ignore') ) def Print_Type( face ): print( "font type entries" ) # module = &face->driver->root; # printf( " FreeType driver: %s\n", module->clazz->module_name ); # Is it better to dump all sfnt tag names? print( " sfnt wrapped: ",end="") if face.is_sfnt: print( "yes") else: print( "no") # is scalable ? print( " type: ", end="") if face.is_scalable: print( "scalable, ", end="") if face.has_multiple_masters: print( "multiple_masters, ", end="") if face.has_fixed_sizes: print( "fixed size",end="") print() # Direction print( " direction: ", end="" ) if face.has_horizontal: print( "horizontal, ", end="") if face.has_vertical: print( "vertical", end="") print( ) # Fixed width print( " fixed width: ", end="") if face.is_fixed_width: print( "yes") else: print( "no") # Glyph names print( " glyph names: ", end="") if face.has_glyph_names: print( "yes") else: print( "no") if face.is_scalable: print( " EM size: %d" % face.units_per_EM ) print( " global BBox: (%ld,%ld):(%ld,%ld)" % (face.bbox.xMin, face.bbox.yMin, face.bbox.xMax, face.bbox.yMax )) print( " ascent: %d" % face.ascender ) print( " descent: %d" % face.descender ) print( " text height: %d" % face.height ) def get_platform_id( platform_id ): if platform_id == TT_PLATFORM_APPLE_UNICODE: return "Apple (Unicode)" elif platform_id == TT_PLATFORM_MACINTOSH: return "Macintosh" elif platform_id == TT_PLATFORM_ISO: return "ISO (deprecated)" elif platform_id == TT_PLATFORM_MICROSOFT: return "Microsoft" elif platform_id == TT_PLATFORM_CUSTOM: return "custom" elif platform_id == TT_PLATFORM_ADOBE: return "Adobe" else: return "UNKNOWN" def get_name_id( name_id ): if name_id == TT_NAME_ID_COPYRIGHT: return "copyright" elif name_id == TT_NAME_ID_FONT_FAMILY: return "font family" elif name_id == TT_NAME_ID_FONT_SUBFAMILY: return "font subfamily" elif name_id == TT_NAME_ID_UNIQUE_ID: return "unique ID" elif name_id == TT_NAME_ID_FULL_NAME: return "full name" elif name_id == TT_NAME_ID_VERSION_STRING: return "version string" elif name_id == TT_NAME_ID_PS_NAME: return "PostScript name" elif name_id == TT_NAME_ID_TRADEMARK: return "trademark" # the following values are from the OpenType spec elif name_id == TT_NAME_ID_MANUFACTURER: return "manufacturer" elif name_id == TT_NAME_ID_DESIGNER: return "designer" elif name_id == TT_NAME_ID_DESCRIPTION: return "description" elif name_id == TT_NAME_ID_VENDOR_URL: return "vendor URL" elif name_id == TT_NAME_ID_DESIGNER_URL: return "designer URL" elif name_id == TT_NAME_ID_LICENSE: return "license" elif name_id == TT_NAME_ID_LICENSE_URL: return "license URL" # number 15 is reserved elif name_id == TT_NAME_ID_PREFERRED_FAMILY: return "preferred family" elif name_id == TT_NAME_ID_PREFERRED_SUBFAMILY: return "preferred subfamily" elif name_id == TT_NAME_ID_MAC_FULL_NAME: return "Mac full name" # The following code is new as of 2000-01-21 elif name_id == TT_NAME_ID_SAMPLE_TEXT: return "sample text" # This is new in OpenType 1.3 elif name_id == TT_NAME_ID_CID_FINDFONT_NAME: return "CID 'findfont' name" else: return "UNKNOWN"; def Print_Sfnt_Names( face ): print( "font string entries" ); for i in range(face.sfnt_name_count): name = face.get_sfnt_name(i) print( " %-15s [%s]" % ( get_name_id( name.name_id ), get_platform_id( name.platform_id )),end="") if name.platform_id == TT_PLATFORM_APPLE_UNICODE: if name.encoding_id in [TT_APPLE_ID_DEFAULT, TT_APPLE_ID_UNICODE_1_1, TT_APPLE_ID_ISO_10646, TT_APPLE_ID_UNICODE_2_0]: print(name.string.decode('utf-16be', 'ignore')) else: print( "{unsupported encoding %d}" % name.encoding_id ) elif name.platform_id == TT_PLATFORM_MACINTOSH: if name.language_id != TT_MAC_LANGID_ENGLISH: print( " (language=%d)" % name.language_id ) print ( " : " ) if name.encoding_id == TT_MAC_ID_ROMAN: # FIXME: convert from MacRoman to ASCII/ISO8895-1/whatever # (MacRoman is mostly like ISO8895-1 but there are differences) print(name.string) else: print( "{unsupported encoding %d}" % name.encoding_id ) elif name.platform_id == TT_PLATFORM_ISO: if name.encoding_id in [ TT_ISO_ID_7BIT_ASCII, TT_ISO_ID_8859_1]: print(name.string) print ( " : " ) if name.encoding_id == TT_ISO_ID_10646: print(name.string.decode('utf-16be', 'ignore')) else: print( "{unsupported encoding %d}" % name.encoding_id ) elif name.platform_id == TT_PLATFORM_MICROSOFT: if name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES: print( " (language=0x%04x)" % name.language_id ); print( " : " ) if name.encoding_id in [TT_MS_ID_SYMBOL_CS, TT_MS_ID_UNICODE_CS]: print(name.string.decode('utf-16be', 'ignore')) else: print( "{unsupported encoding %d}" % name.encoding_id ) else: print( "{unsupported platform}" ) print( ) def Print_Fixed( face ): # num_fixed_size print( "fixed size\n" ) # available size for i,bsize in enumerate(face.available_sizes): print( " %3d: height %d, width %d" % ( i, bsize.height, bsize.width ) ) print( " size %.3f, x_ppem %.3f, y_ppem %.3f" % ( bsize.size / 64.0, bsize.x_ppem / 64.0, bsize.y_ppem / 64.0 ) ) def Print_Charmaps( face ): global verbose active = -1 if face.charmap: active = face.charmap.index # CharMaps print( "charmaps" ) for i,charmap in enumerate(face.charmaps): print( " %d: platform %d, encoding %d, language %d" % (i, charmap.platform_id, charmap.encoding_id, int(charmap.cmap_language_id)), end="" ) if i == active: print( " (active)", end="" ) print ( ) if verbose: face.set_charmap( charmap ) charcode, gindex = face.get_first_char() while ( gindex ): print( " 0x%04lx => %d" % (charcode, gindex) ) charcode, gindex = face.get_next_char( charcode, gindex ) # ----------------------------------------------------------------------------- if __name__ == '__main__': import getopt execname = sys.argv[0] if len(sys.argv) < 2: usage( execname ) try: opts, args = getopt.getopt(sys.argv[1:], ':nv') except getopt.GetoptError: usage( execname ) verbose = False name_tables = False for o, a in opts: if o == "-v": verbose = True elif o == "-n": name_tables = True else: usage( execname ) face = Face(args[0]) num_faces = face.num_faces if num_faces > 1: print( "There are %d faces in this file." % num_faces) else: print( "There is 1 face in this file.") for i in range(num_faces): face = Face(args[0], i) print( "\n----- Face number: %d -----\n" % i ) Print_Name( face ) print( "" ) Print_Type( face ) print( " glyph count: %d" % face.num_glyphs ) if name_tables and face.is_sfnt: print( ) Print_Sfnt_Names( face ) if face.num_fixed_sizes: print( ) Print_Fixed( face ) if face.num_charmaps: print( ) Print_Charmaps( face ) freetype-py-2.5.1/examples/glyph-color.py0000664000175000017500000000566114664131406020634 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph colored rendering (with outline) ''' from freetype import * if __name__ == '__main__': import numpy as np import matplotlib.pyplot as plt face = Face('./Vera.ttf') face.set_char_size( 96*64 ) RGBA = [('R',float), ('G',float), ('B',float), ('A',float)] # Outline flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph glyph = slot.get_glyph() stroker = Stroker( ) stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ) glyph.stroke( stroker , True ) blyph = glyph.to_bitmap(FT_RENDER_MODE_NORMAL, Vector(0,0), True ) bitmap = blyph.bitmap width, rows, pitch = bitmap.width, bitmap.rows, bitmap.pitch top, left = blyph.top, blyph.left data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = np.array(data).reshape(rows, width)/255.0 O = np.zeros((rows,width), dtype=RGBA) O['A'] = Z O['R'] = 1 O['G'] = 0 O['B'] = 0 # Plain flags = FT_LOAD_RENDER face.load_char('S', flags) F = np.zeros((rows,width), dtype=RGBA) Z = np.zeros((rows, width)) bitmap = face.glyph.bitmap width, rows, pitch = bitmap.width, bitmap.rows, bitmap.pitch top, left = face.glyph.bitmap_top, face.glyph.bitmap_left dy = blyph.top - face.glyph.bitmap_top dx = face.glyph.bitmap_left - blyph.left data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z[dx:dx+rows,dy:dy+width] = np.array(data).reshape(rows, width)/255. F['R'] = 1 F['G'] = 1 F['B'] = 0 F['A'] = Z # Combine outline and plain R1,G1,B1,A1 = O['R'],O['G'],O['B'],O['A'] R2,G2,B2,A2 = F['R'],F['G'],F['B'],F['A'] Z = np.zeros(O.shape, dtype=RGBA) Z['R'] = (A1 * R1 + A2 * (1 - A1) * R2) Z['G'] = (A1 * G1 + A2 * (1 - A1) * G2) Z['B'] = (A1 * B1 + A2 * (1 - A1) * B2) Z['A'] = (A1 + A2 * (1 - A1)) # Draw plt.figure(figsize=(12,5)) plt.subplot(1,3,1) plt.title('Plain') plt.xticks([]), plt.yticks([]) I = F.view(dtype=float).reshape(O.shape[0],O.shape[1],4) plt.imshow(I, interpolation='nearest', origin='lower') plt.subplot(1,3,2) plt.title('Outline') plt.xticks([]), plt.yticks([]) I = O.view(dtype=float).reshape(O.shape[0],O.shape[1],4) plt.imshow(I, interpolation='nearest', origin='lower') plt.subplot(1,3,3) plt.title('Outline + Plain') plt.xticks([]), plt.yticks([]) I = Z.view(dtype=float).reshape(O.shape[0],O.shape[1],4) plt.imshow(I, interpolation='nearest', origin='lower') plt.show() freetype-py-2.5.1/examples/VeraMono.ttf0000664000175000017500000014011014664131406020255 0ustar georgeskgeorgeskOS/2_*,VPCLT!?6cmapXcvt  0fpgmp((Tgasp glyf(thdmx32`Hheadم'6hhea ?$hmtx ε`4locamaxp name` postn]4prep:!8::h:: mR0u   y t  0   t 0  0   ~ 6 H `   0 & Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans MonoBitstreamVeraSansMono-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans MonoBitstreamVeraSansMono-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comf 7X!uu9!{Xm{o{RoZ!=fs +b#1N {T\q#w`j#fy```{{w`b{!{RNNfffHF?{L'oo5jo{-{3=foD7f}s]A GA% } % 2  %%@Y}2}Y&Y@&//2G@Gddkߖږ؍ }:Ս :  ϊ̖ˋ%}Ś   ]%]@%AA dd@2(-}-d   ..A]%]@%%%A  %d%BSx~}~}}|{zwvut uu@t tss@rqponSonm(nSm(lk2ji2hgfedcbcbba`_^Z ^]d\[Z [Z YXWVUU2TSRQ}PONM-MLK(JIJ7ICIHEHGCGdFEFEDCD7CBCC@@ BABB@ A@AA@ @? @@@ ? ? ?@@d>=-=<;(:9B9d818K76-65K404K3032B21-10/-/. .-,--@ ,,,@@+*%+* *%):)('&%B%E$#""! -!} -KBBF-B-B-B@  @   @    @  @7    -:-:-d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++, %Id@QX Y!-,%Id@QX Y!-,  P y PXY%%# P y PXY%-,KPX EDY!-,%E`D-,KSX%%EDY!!-,ED-hh/10!%!!hsr) @ <2991/03#3#qeR@1<20###Ѯ++J@0     91/<<<<<<<2220333!3!###!5!!5!#3hiiThiih)T/hTaabbNZ /d@9($)%/%$(!$, ( 0<2<1/2999906654&'#&&'5&&546753&&'n|phumdfbdcӿdOTUPDNtd]gp^Vd-.)>B+/Qš ! *9V@/7(" "7(.+  % 4  + :99991/9999032654&#"4632#"&'%32654&#"4632#"&iNMklLNi@s..2H#)iOMllMMk@u--1?NjkMMljO0./t?``OikMMkjN0--uA9*7@b  -,.+2345617B7 1 +"1"!% (! 7+!(!(! .899999991/9990KSX999Y"6654''3#'#"5467&&54632&&#"3267667#'&JKNSj抋20ǭAF;}Eap:6\[ț*\,#1h F'XmFD ̉dHG'%[M;I\ 10#+u @  29910#&547u;:\' @  299103#654\<<J+N@,       <2<2991<22990%#'%%73%+f9s9f9PsPbybcyXqy '@    <<1<<0!!#!5!CDDD/@ 103#Śc/dm10!!d 11/03#1fB7@ 103#ymL # @  $!"!$10@////////// / / ?????????? ? ? OOOO O ____ _    F////////// / / __________ _ _  $]]4632#"&"32'2#"M68PO98K7PP78NL0670xx~F &@ ## 1/20%!5%3!!:P6ȪuLJժ#Q@)%%B   "$91/20KSX92Y"%!!5676654&#"56632uu5dF[pga Yd8ժ.>zO}BC12`tA7(G@)  #)&" )9190#"&'532654&##532654&#"56632ggfbYhyI'Ǖ&$54zms{(( ۵{fo B@   B    $<291/<290KSXY"!33##!5)!3d-=@"   "190!!6632#"&'532654&#"+W,wN\aQFժ 21%%L$=@#  %"& "%190&&#"6632# !2"32654&?M0n#J݁%'dkuzl75@%%B"991/0KSXY"!#!5V+N #/C@% '-'0 $*$ "!0991990"32654&%&&54632#"$54632654&#"hʁ򑁖Myz{yŗT!Ѳ!!ȟɠbx~~xzF $;@" ""%"  &%1902654&#"532#"543 !"&T?M/nI%'!dk  os'@ <21/03#3#'9' %@  103#3#Śc /Xyw!@('29190 5yR!÷X`y@ <210!!!!X!! BXyw!@('<919055X!R^^="{@B  %%B !    ) #99991/9990KSX99Y"#546776654&#"566323#=TZ>/mNb^hC^XE&bRY;X1YnED98L\VBT=/s 4p@1(+$ 4 '$+1+5' ( + . !+ -.5<991999990@ ]4&#"326#5#"&5463254&#"!267# !2kkkk%RӡP$J6l90?{:]x<!o?DF=?z% @A%%%% % % %  % B   / 91/<90KSXY"]@    ]]!3#!#hnl#+{q =@#   21 0!29991/9032654&#32654&#%!2!!qﰖ뒃JF{f>p}qdƵϠ1.@  2 10210%# !2&&#"32671M[?[MJVXI5))pn))=@@=R(@  2 1099991/0%26&!# !!`dVDѦHKw/N )@  13 21/0!!!!!!vTrwժFX $@14 21/0!!!!#o\eժH7fP<@!   6251990%# !2&&#"3267#5!PQv@^PQ_ſCe){KMon56MI!H &@ 1 0 221/<203!3#!#)d+9 %@ 77 221/220!!!!5!!=99ժm,@    51990753265!5!#"&m[hqG`=QQD, @!% %B  0 291/<290KSXY"]@L&&6FUWX dzy{ ',+&:IGG[WXXWkzx]]33 ##wVhs@ 141/03!!dժVy @,  B    / 0 91/<290KSXY" ]@$  &)&) 6968  ]]! !###V+'F m@B10 991/<2990KSXY"]@&)&8Wdjuz &)FIWgh]]!3!#3+3u\ #@ 2 62510#"32#"32IIz~u+@  2 8 3291/032654&#%!2###ꌝL/ϔu\=@   2 625999919990"#"32#"32ȗyHdIj@8  %%B     21  0299991/<9990KSX9Y"#&&###!232654&#NnRٲM{cݑohy]ҔYJ'@=  %  %B %( &919"0(9999190KSX99Y"]@ ]].#"#"&'532654&/.54$32\^mjikshulм V;9L@)%%%%B/091/290KSXY"%3#3h_KKѪ++ @D    %%% % B    /91/<<90KSXY" ]@^ //+ ??8 ZZ  &*%*(+ % & 5:5:;: 4 6 TTZXWV[[RW X ] gh yvy v #]]333# #ŏӬ߿ʿD"+w @K % % % %%%% % B   ;/; 0 91/<290KSXY"7]@8  '()& X xyw !%+% 5UYX es]]3 3 # #VHNAu3B}%Y@.%%%%B<< 9991/290KSXY"33#%lk!mb E@%%B/0 991/0KSXY"]]!!!5!" ՚ow@=210!#3!XfB7@ 10#%mZ@=210!53#5XޏH@ 91290##Ȳu-m/10!5mPPf1@ <10K TKT[X@878Y #fx#{ )n@*  ! $   D >*22991/99990@00 0!0" ]#"326757#5#"&546;5.#"5>32=zl;^[fX=& 3qpepӺ)Ld_y64''RR2X 0@  G F221/9904&#"3266632#"&'#3,fd./xRXWS%{/@   F210%# !2&&#"3267%JR%QNI]`A9++88*,A:;>{0@G H221/9903#5#"3232654&#"Z.deCSW;7W {X{E@&    IH991990!3267# 32&&#"X㿮Xmi[ ^Z89++9 @Ţ'4@     <<2991/22990#"!!#!5!5463'cM+Qgc/яN{H{ )H@' '  $(*' G!H*221999904&#"326#"&'5326=#"3253ZLSbC,ml/9.,}^\::VZ,@  J  F21/<990#4&#"#36632jq1sJ`cD .@ L LK <<1/20!!!5!!3#mnm`/BCV 8@   <2991990!5!##53263#XZZӜ} @:  B  DE 291/<90KSXY"]@R546Ffuv ('(;;797JIYYkiiiyxyy]]33 ##Gb{ZFB?  &@   L 991/99033#"&5!5![Y饵|~mo{"@'  MNMNME#<91/<<<299990@G000000 0 0 ????????? #]K TKT[KT[X#@##878YKTX###@878Y>32#4&#"#4&#"#3>32"iJo5FP;9JI9!c?LeHEws{p{``10"32654&'2#"hڜ-.VT{3@ GF221990%#36632#"&4&#"326w.df SWWRw 3@   G>22199032654&#"#"3253#L-ed.+SY7:WSj{O@   21/990@%  0030@@C@PPPP].#"#3>32;zI.Dv6y.*`w"${'u@@    B %( OI"E(99991990KSX99Y"&&#"#"&'532654/&&54632OS}{\JSjgTzEZ9..QSKJ#}##55cY1!1@  <<2991/<2990!!33#"&5!5!f^^uϪ+|b`>^,@    JF21/2990332653#5#"&økp1qJyaddm`e@)BIE91/290KSXY"']@%]]3 3#dEFr`T` @E      B    /91/<<90KSXY" ]@      &&)&))#, 96993< EI F J VX W Y fifij e vzx| r -   ++>>< H Y jih {yz|  ]]333# #àö`wBfL` @H      B  IE 91/<290KSXY" ]@ fivy  :4 ZV ]] # # 3 ^oo)'`?HkhV`@E       B   IE9129990KSX9Y"8]@v  &&8IIY ]]+532673 3Z.Gc".\mQ\GOLGhu:NN^Nlb X@BIE 2991/0KSXY"8]@68EJWXejuz ]!!!5!-}bܖ%$f@5 %   !  % $  = %<<29999999199999990#"&554&##5326554633#"3@k>>j@FU[noZUtrݓWV10#$j@7%   #%#= %<2<999999919999999032655467&&554&##53233#"##DVZon[VD>k@@k>XXrtݔXy &@  '1<2990#"'&'&&#"56632326yKOZq Mg3OINS5dJ t]F ;73 !;?<6 7=%N'$u%m !@W % %%% %!%! %!! % !B     !  PPK/K!"2299999991/<9990KSXY"]@  ]]4&#"326!.54632#!#Y?@WX??Y:Arr@;nlZ?YWA?XXP!yIrrIv${u1'&dNk'(uF^'1uu\N'2u=N'8u#f'D#f'DC#f'D#'D#7'D#'Du%{'Fh{Xf'H{Xf'HC{Xf'H{X'HDf'Df'CDf'D'7'QHf'RHf'RCHf'RH'RH7'Rf'Xf'XCf'X'X;/ '@  RQ R <<1<203!!#!5!nn\]+u @ STS 102#"&546"32654&hAu,-/OomOPqp1.-rBoPPlnNOp%!N@*   " E"<<<2212<990&&'667#&5473%C??BI9gg9ބ5(,-("9="+` 츸X>@     <<1/2<2990&&#"!!!!53#5354632D>Cs3A,,ُ/я= 2>j@<#$93 $*0?#=><''PGZsweZ54m@''TLf{xf[1,pE-Z/L-Z/L?!   V 104632#"&?}|}||{|j; #@WW1 9120!###&&54$FfNݸ}/V@1-'!  **.  !' $'$-DF099991/9904632#"&'532654&''&&5467&&#"#7C:oEBL;lAxC\[yqyrq|d1M*%]taQG_J'8O#kr}N4L@I  ] ] B   A)5)M  \\ [G#X;#Y//29999129990KSX9Y"2#'&&####32654&2#"&'&&546766"32676654&'&&XXP:&rk1=-7ffZJJDZZ\[[[~}[[[\ZZ~jKKMMKLijLLKLKKLbeG]C;P*T6?>5VZZ[~}[[[[[[}~[ZZgJKKjhKLLLLLijKKJ}N1ID@'  &>>2J\ ^,8 8YD/210&&#"3267#"&54632'"32676654&'&&'2#"&'&&546766`:o:u8g24r=г=rjKKMMKLijLLKLKKkZZ\[[[~}[[[\ZZ/lhȬJKKjhKLLLLLijKKJgZZ[~}[[[[[[}~[ZZfh@6    B     ` `_`_/91<<2<<90KSXY"###5!3###r}r7q^^-Bf1@ <10KTK T[X@878Y3#f?F\@aa1<20K TK T[KT[X@878YK TKT[X@878Y3#%3#?X%y<@     <291<2<<990!3!!!'7#5!7!X}y}J;fժhӬg@7 % %%%B    c /<291/<20KSXY"!!!!!!#!3eex5ժFժ +k@:+)&  *&&, #* #)+262#5,999999991/9999990324&'&&#"#"&''7&5327sT sV)+y=g %s9d/NZIn-QUPeQzQQFIRPJ) /7@$ '! -0 $dd*099991<2<299032654&#"&&#"32676632#"&'#"&546329[=G[TFBi8\=G[SDCj~/[w~SNAU}^sdlkutcjmvu۠d|k֥sXy.@    <2<21/<<07!!!!#!5!X!dCDLIVw? (@( ' <2291/905!5w!!LK Xy? (@ (' <<291/90%%5!!X#!!V%@D% % %%B  < e e<<2<299991/2<2<290KSXY"333!!!#!5!5'!53%lkVoqZmo#o o#oT` L@*  !   JF!99912<9903326533267#"&'#"&'øxo ! &D">K .Y\,T H;8 OOPNLP-):@'! '! @ * $$*99919906654&#"#"&54632#"&54324&#"32JIH7$$0e՘ݢe WOmVPmmWKt,>bFأ[t}t{L= 7   @  <91990!!55!!LR%# Չ\P_L9@ 120!#!L^PL?@!   hggf91/2299990!#3267#"&5!##P117,#J%q\TL@H? HL%1  @ & &1026732#"&'&&#"#"&54632j Pd@7*9  kOeD=!0 l9TA6?&#Hn!bSA8?T %)d@6  (&&  #*& (' j kji*22999199990"326557#5#"&5463354&#"56632!!|WHi1Rwu3}CD?kdPDN@Ms=@pABtZ\#! { 3@   jkji9910"32654&'2#"&546!!hfssfeusgʫ˫\{u༻߻`{J>@#qqro prol 991/<20353&5323!5654#"J{n !o{1xx 7oȼ߅LI L){ C@I=70 6 %C "76. 3@:("D%=/.M/u MCM6+sD299912<2<2<999990@ 05060708]5#"32654&#"!3267#"&'#"&546;54&#"5>32>321xYS\JMWWLepO27Gn 'aȿuc^8>M<[|%!YHZqYa4+#"33)+RNPPXx+'#!?@=B/ +s@>+,&  )&  *&& &,+,* # )#D>,9999999919999999032654&'&&#"&&5327#"&''m1$eA H#cC')d<]*,g9\ //4o0.0tGGq.78MBz;/mNb^hC^XC&DbRY;X1YnED98L\V@T? @ <2991/0533)eqXsy^@ '10!#!X!^?; /@     99190'%3##d)#Ӕ/}b%9V#@N   B   !$  /912299990KSX99Y"&&#"!!#"&'53267#5!6632$R,fs-/d+Ǻ9f.1d0`yu1Ɣ1c|ɏ!JX1y7K@&' 10+5  * 5'.810*8<2991<2<<99990#"'&'&&#"56632326#"'&'&&#"566323326yKOZq Mg3OINS5dK t]FJKOZq Sc1NJOR` t]Dï;73 ";@<7  6<а;83 $77 7=O@*iiiiB91/90KSXY"#3 !qw# /@    v v<2991<299055L-+-+#RR\# /@   vv <<991<29905%5+-:+-#^R^  ^R^  P1 #@   1/<<2203#3#3#P3f111%k'$u%^'$uu\^'2uH;@     -299991/220%! !!!!!"33(RH=MKF{ 8i@92/ & 8   #5/)#92& MuMCM,s9299912<229999904654&#"265&#"!3267#"&'#"326632PVWMfRPhgPPcpP/;}Jb04TY/%W & +#T53+)CBDA88>A>Ay/10!!/yy/10!!/y %@   1<20#53#53Ěb5Ǚb~~ '@   1<203#%3#řb5Ěb-@ 10#53Ěb~-@ 103#1řbXyo '@ w <<103#3#!!j!u#\u"@91990 h 9%-hV'\%N'<ufB7@ 103#ymLB /@ (-  * -'! @') -0)$ !'$* xyx( $02299999999912299999999904&#"3267'#"&''7&&5467'76632d|[Z}}Z[|Z^.[20`0\^.[3.^Z{{Z\}~t]1]02[-^Z3].2]-_Z/#@ v291905/-+#Ry#@ v<91905+-#^R^  #7N@*        JEE<2<2991/<299903#'#"!#!##535463wcM%ɩQge/яN#7B@#    JE E<<991/<29990#!"!!##5354637cM%۸ɩ{Qge/яN;/<@  R Q R <<2<<212<220%!#!5!!5!3!!!/nnnn\\/`103#`/103#Śc// * @  1<203#%3#řb5Ěb/'3?Kt@%1= 1%+C@&7IF:4(:PFz4P@ PzP"P.zP@(/99991/<22299990'32654&#"4632#"&32654&#"4632#"&32654&#"4632#"&H%'H_EDbcCE_yxxwyLaEEacCEayyxxy aEF`bDEayyxxy7a`JGacECcaEyxyEaaECcaExxy"GaaGCcaExxy%m'$uNm'(u%k'$uNN'(uNk'(uk',um',uN',uk',uu\k'2uu\m'2uu\k'2u=k'8u=m'8u=k'8uD` "@LLK 1/20!!!5!!mnm`/B)f7@  91290K TKT[X@878Y3#'#f7@!   PP99991<<99990K TK T[X@878YKTX@878Y@?       ]'.#"#>3232673#"&d9!&$|f['@%9! '$}f['@Z7JQ!7JQ=b10!!=V/)H 8 @ PP1<0K TX@878Y332673#"&/w `WU`w HLJJLD6@ a10K TK T[KT[X@878Y3#V{ W @  P{P10K TK T[X@878YK TX@878Y#"&546324&#"326{tsst{X@@WW@@Xssss?XW@AWXu)'  @ |1/90!#"&'532654&'85xv-W,"K/:=,,>i0Y[ 0.W=XfZ@991<20K TKT[X@878YK TX@878Y3#3# fxu"  @  |1/90!33267#"&546w-+76 >&Dzs5=X.. W]0i)f7@  91<90K TKT[X@878Y373xs 7@   1 4<2.9991/903%!!'7;NwdPo;jnL >@!    <<2999991/999033#"&5'!5!%[Y饵P{;Pu|~$o/nJm'6uf'Vm'=uf']!<210##  N ;@!    21 0 0<291/220 !!#5326&!#!!VD}}/`ŕ{HK+H)@O B $ *'! !'D! >*999999199990KSX9Y"#"32&&''7'3%&&#"32654&Ŷ"#!H&!!#R-:/(  (-Y,\bPȑ^b n%k'<uhVf'\4 @  28  32299991/032654&#33 !##ꞝL!󄃃VT3@ GF221990%#36632#"&4&#"326w.dfSWWX-y10!!X!ת;T .@     <91<2907^t^_t\t%\^u^uw^X 9A      @  aW}a 12035733!j c)t'+nB}a@WWBA     @9991990KSX9Y"!!576654&#"56632eQdR1q?Ay;Jwrnaz3=L$$}k9wuF(\A          @#) & )99190#"&'532654&##532654&#"56632^c:r;Eq-evnmBJ]b`W,p;Eu2X`lP|yQDJLl?<8?yvcG]Z{''  VZ{'' VZ''  VfPm'* u{HH'JP', uuJ'6u{'V1k'&Zu%f'FZ1m'&Zu%f'FZ{$H@ "  @"   GH%<<1/<2990!5!533##5#"3232654&#"Z1.de5yySW;7W dm10!!d /`103#`%%3p@< 1& (# #43('1)-&- 2'-4229999999999122<2032&&#"!!!!3267#"#73&'&54767#70TJBN1Fi1OCHU,1u1!(*=Dl-.&nC>*( n -/ l?Q@ aa1<20KTX@878YKTK T[X@878Y3#%3#?Zk10K TX@878YKTX@878Y@&  //// //]]3#@   99991<<990KTKT[X@878Y@t        !      ]]'.#"#4632326=3#"&d9 #(}gU$=19#(}fT"<9! 2-ev 3)dwyi10K TX@878YKTX@878YKTX@878Y@ //]#1Ś7]@ 91<90K TX@878YKTX@878Y@ //, ]3#'# ӌ7i@ 91290KTX@878YK TX@878Y@ //*//]373 ӌ Zj@ 9910'3$ll  5   @  W <291<29033##5!5!wtt}oyc/ @ PP120332673#"&/w dRSaw 6978w{za103#  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>: ~1BSax~ & 0 : !""""+"H"e%  0AR^x}  0 9 !""""+"H"`%^ChVjq_8 (Bbcdefghjikmlnoqprsutvwxzy{}|~hR!9\XdffXXX%fmVuu/9%fZH{{{mjdLhX%%u{{{{+?j?X)XVX%PJ)/X;XwP%%uHXuh%fZ##%%uuu)=/VX)L%hXXBFf{{d%?y77 /+   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      sfthyphenperiodcenteredEuroc6459c6460c6461c6468c6470c6472c6477c6478c6475c6476%%%%KmJz6b iP~Abj \ . [ ) ^ A  [ ?`m2l)*rd O TJlV|cp} &3@MZgtPJ ! !M!!"l"##3#a#$#$$$% %u%&-&'('(#(J(f()))**A*m*m*z***+k++++, ,),V,,,,-?-`--..W.o../e/r//////////0000(0O0|111S1{122C2t223"3/3<3I3V3{34S4`4m445 5E5x5696J6[6l6y666666667>7T7l78/8r99K999:$:N:d MF@Wm GBGSf   JBits@ mB`#cVeraSansMono6628R00@             䥉_<lmfreetype-py-2.5.1/examples/shader.py0000664000175000017500000001237614664131406017644 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (C) 2009-2010 Nicolas P. Rougier # # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. # ----------------------------------------------------------------------------- # # Copyright Tristam Macdonald 2008. # # Distributed under the Boost Software License, Version 1.0 # (see http://www.boost.org/LICENSE_1_0.txt) # ''' Base shader class. Example: -------- shader = Shader() shader.bind() glActiveTexture(GL_TEXTURE1) glBindTexture(lut.target, lut.id) shader.uniformi('lut', 1) glActiveTexture(GL_TEXTURE0) glBindTexture(texture.target, texture.id) shader.uniformi('texture', 0) shader.uniformf('pixel', 1.0/texture.width, 1.0/texture.height) texture.blit(x,y,w,h) shader.unbind() ''' import os import OpenGL.GL as gl import ctypes class Shader: ''' Base shader class. ''' def __init__(self, vert = None, frag = None, name=''): ''' vert, frag and geom take arrays of source strings the arrays will be concatenated into one string by OpenGL.''' self.uniforms = {} self.name = name # create the program handle self.handle = gl.glCreateProgram() # we are not linked yet self.linked = False # create the vertex shader self._build_shader(vert, gl.GL_VERTEX_SHADER) # create the fragment shader self._build_shader(frag, gl.GL_FRAGMENT_SHADER) # the geometry shader will be the same, once pyglet supports the # extension self.createShader(frag, GL_GEOMETRY_SHADER_EXT) attempt to # link the program self._link() def _build_shader(self, strings, stype): ''' Actual building of the shader ''' count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = gl.glCreateShader(stype) # Upload shader code gl.glShaderSource(shader, strings) # compile the shader gl.glCompileShader(shader) # retrieve the compile status status = gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS) # if compilation failed, print the log if not status: # display the log print (gl.glGetShaderInfoLog(shader)) else: # all is well, so attach the shader to the program gl.glAttachShader(self.handle, shader) def _link(self): ''' Link the program ''' gl.glLinkProgram(self.handle) # retrieve the link status temp = ctypes.c_int(0) gl.glGetProgramiv(self.handle, gl.GL_LINK_STATUS, ctypes.byref(temp)) # if linking failed, print the log if not temp: # retrieve the log length gl.glGetProgramiv(self.handle, gl.GL_INFO_LOG_LENGTH, ctypes.byref(temp)) # create a buffer for the log #buffer = ctypes.create_string_buffer(temp.value) # retrieve the log text log = gl.glGetProgramInfoLog(self.handle) #, temp, None, buffer) # print the log to the console print (log) else: # all is well, so we are linked self.linked = True def bind(self): ''' Bind the program, i.e. use it. ''' gl.glUseProgram(self.handle) def unbind(self): ''' Unbind whatever program is currently bound - not necessarily this program, so this should probably be a class method instead. ''' gl.glUseProgram(0) def uniformf(self, name, *vals): ''' Uploads float uniform(s), program must be currently bound. ''' loc = self.uniforms.get(name, gl.glGetUniformLocation(self.handle,name)) self.uniforms[name] = loc # Check there are 1-4 values if len(vals) in range(1, 5): # Select the correct function { 1 : gl.glUniform1f, 2 : gl.glUniform2f, 3 : gl.glUniform3f, 4 : gl.glUniform4f # Retrieve uniform location, and set it }[len(vals)](loc, *vals) def uniformi(self, name, *vals): ''' Upload integer uniform(s), program must be currently bound. ''' loc = self.uniforms.get(name, gl.glGetUniformLocation(self.handle,name)) self.uniforms[name] = loc # Checks there are 1-4 values if len(vals) in range(1, 5): # Selects the correct function { 1 : gl.glUniform1i, 2 : gl.glUniform2i, 3 : gl.glUniform3i, 4 : gl.glUniform4i # Retrieves uniform location, and set it }[len(vals)](loc, *vals) def uniform_matrixf(self, name, mat): ''' Upload uniform matrix, program must be currently bound. ''' loc = self.uniforms.get(name, gl.glGetUniformLocation(self.handle,name)) self.uniforms[name] = loc # Upload the 4x4 floating point matrix gl.glUniformMatrix4fv(loc, 1, False, (ctypes.c_float * 16)(*mat)) freetype-py-2.5.1/examples/glyph-outline-cairo.py0000775000175000017500000000346414664131406022272 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-outline example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # # ----------------------------------------------------------------------------- ''' Glyph outline rendering ''' from freetype import * # using Matrix class from Cairo, instead of FreeType's from cairo import Context, ImageSurface, FORMAT_ARGB32, SurfacePattern, FILTER_BEST, Matrix from bitmap_to_surface import make_image_surface if __name__ == '__main__': from PIL import Image face = Face('./Vera.ttf') face.set_char_size( 4*48*64 ) flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph glyph = slot.get_glyph() stroker = Stroker( ) stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ) glyph.stroke( stroker , True ) blyph = glyph.to_bitmap(FT_RENDER_MODE_NORMAL, Vector(0,0), True ) bitmap = blyph.bitmap width, rows, pitch = bitmap.width, bitmap.rows, bitmap.pitch surface = ImageSurface(FORMAT_ARGB32, 600, 800) ctx = Context(surface) Z = make_image_surface(bitmap) ctx.set_source_surface(Z, 0, 0) scale = 640.0 / rows patternZ = ctx.get_source() SurfacePattern.set_filter(patternZ, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(300.0 - width *scale /2.0 ), -80) patternZ.set_matrix(scalematrix) ctx.set_source_rgb (0 , 0, 1) ctx.mask(patternZ) ctx.fill() surface.flush() surface.write_to_png("glyph-outline-cairo.png") Image.open("glyph-outline-cairo.png").show() freetype-py-2.5.1/examples/texture_font.py0000664000175000017500000002763414664131406021127 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Texture font class ''' import sys import math import numpy as np import OpenGL.GL as gl from freetype import * class TextureAtlas: ''' Group multiple small data regions into a larger texture. The algorithm is based on the article by Jukka Jylänki : "A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing", February 27, 2010. More precisely, this is an implementation of the Skyline Bottom-Left algorithm based on C++ sources provided by Jukka Jylänki at: http://clb.demon.fi/files/RectangleBinPack/ Example usage: -------------- atlas = TextureAtlas(512,512,3) region = atlas.get_region(20,20) ... atlas.set_region(region, data) ''' def __init__(self, width=1024, height=1024, depth=1): ''' Initialize a new atlas of given size. Parameters ---------- width : int Width of the underlying texture height : int Height of the underlying texture depth : 1 or 3 Depth of the underlying texture ''' self.width = int(math.pow(2, int(math.log(width, 2) + 0.5))) self.height = int(math.pow(2, int(math.log(height, 2) + 0.5))) self.depth = depth self.nodes = [ (0,0,self.width), ] self.data = np.zeros((self.height, self.width, self.depth), dtype=np.ubyte) self.texid = 0 self.used = 0 def upload(self): ''' Upload atlas data into video memory. ''' if not self.texid: self.texid = gl.glGenTextures(1) gl.glBindTexture( gl.GL_TEXTURE_2D, self.texid ) gl.glTexParameteri( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP ) gl.glTexParameteri( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP ) gl.glTexParameteri( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR ) gl.glTexParameteri( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR ) if self.depth == 1: gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, self.width, self.height, 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, self.data ) else: gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGB, self.width, self.height, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, self.data ) def set_region(self, region, data): ''' Set a given region width provided data. Parameters ---------- region : (int,int,int,int) an allocated region (x,y,width,height) data : numpy array data to be copied into given region ''' x, y, width, height = region self.data[y:y+height,x:x+width, :] = data def get_region(self, width, height): ''' Get a free region of given size and allocate it Parameters ---------- width : int Width of region to allocate height : int Height of region to allocate Return ------ A newly allocated region as (x,y,width,height) or (-1,-1,0,0) ''' best_height = sys.maxsize best_index = -1 best_width = sys.maxsize region = 0, 0, width, height for i in range(len(self.nodes)): y = self.fit(i, width, height) if y >= 0: node = self.nodes[i] if (y+height < best_height or (y+height == best_height and node[2] < best_width)): best_height = y+height best_index = i best_width = node[2] region = node[0], y, width, height if best_index == -1: return -1,-1,0,0 node = region[0], region[1]+height, width self.nodes.insert(best_index, node) i = best_index+1 while i < len(self.nodes): node = self.nodes[i] prev_node = self.nodes[i-1] if node[0] < prev_node[0]+prev_node[2]: shrink = prev_node[0]+prev_node[2] - node[0] x,y,w = self.nodes[i] self.nodes[i] = x+shrink, y, w-shrink if self.nodes[i][2] <= 0: del self.nodes[i] i -= 1 else: break else: break i += 1 self.merge() self.used += width*height return region def fit(self, index, width, height): ''' Test if region (width,height) fit into self.nodes[index] Parameters ---------- index : int Index of the internal node to be tested width : int Width or the region to be tested height : int Height or the region to be tested ''' node = self.nodes[index] x,y = node[0], node[1] width_left = width if x+width > self.width: return -1 i = index while width_left > 0: node = self.nodes[i] y = max(y, node[1]) if y+height > self.height: return -1 width_left -= node[2] i += 1 return y def merge(self): ''' Merge nodes ''' i = 0 while i < len(self.nodes)-1: node = self.nodes[i] next_node = self.nodes[i+1] if node[1] == next_node[1]: self.nodes[i] = node[0], node[1], node[2]+next_node[2] del self.nodes[i+1] else: i += 1 class TextureFont: ''' A texture font gathers a set of glyph relatively to a given font filename and size. ''' def __init__(self, atlas, filename, size): ''' Initialize font Parameters: ----------- atlas: TextureAtlas Texture atlas where glyph texture will be stored filename: str Font filename size : float Font size ''' self.atlas = atlas self.filename = filename self.size = size self.glyphs = {} face = Face( self.filename ) face.set_char_size( int(self.size*64)) self._dirty = False metrics = face.size self.ascender = metrics.ascender/64.0 self.descender = metrics.descender/64.0 self.height = metrics.height/64.0 self.linegap = self.height - self.ascender + self.descender self.depth = atlas.depth try: set_lcd_filter(FT_LCD_FILTER_LIGHT) except: pass def __getitem__(self, charcode): ''' x.__getitem__(y) <==> x[y] ''' if charcode not in self.glyphs.keys(): self.load('%c' % charcode) return self.glyphs[charcode] def get_texid(self): ''' Get underlying texture identity . ''' if self._dirty: self.atlas.upload() self._dirty = False return self.atlas.texid texid = property(get_texid, doc='''Underlying texture identity.''') def load(self, charcodes = ''): ''' Build glyphs corresponding to individual characters in charcodes. Parameters: ----------- charcodes: [str | unicode] Set of characters to be represented ''' face = Face( self.filename ) pen = Vector(0,0) hres = 16*72 hscale = 1.0/16 for charcode in charcodes: face.set_char_size( int(self.size * 64), 0, hres, 72 ) matrix = Matrix( int((hscale) * 0x10000), int((0.0) * 0x10000), int((0.0) * 0x10000), int((1.0) * 0x10000) ) face.set_transform( matrix, pen ) if charcode in self.glyphs.keys(): continue self.dirty = True flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT flags |= FT_LOAD_TARGET_LCD face.load_char( charcode, flags ) bitmap = face.glyph.bitmap left = face.glyph.bitmap_left top = face.glyph.bitmap_top width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch x,y,w,h = self.atlas.get_region(width/self.depth+2, rows+2) if x < 0: print ('Missed !') continue x,y = x+1, y+1 w,h = w-2, h-2 data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) data = np.array(data,dtype=np.ubyte).reshape(h,w,3) gamma = 1.5 Z = ((data/255.0)**(gamma)) data = (Z*255).astype(np.ubyte) self.atlas.set_region((x,y,w,h), data) # Build glyph size = w,h offset = left, top advance= face.glyph.advance.x, face.glyph.advance.y u0 = (x + 0.0)/float(self.atlas.width) v0 = (y + 0.0)/float(self.atlas.height) u1 = (x + w - 0.0)/float(self.atlas.width) v1 = (y + h - 0.0)/float(self.atlas.height) texcoords = (u0,v0,u1,v1) glyph = TextureGlyph(charcode, size, offset, advance, texcoords) self.glyphs[charcode] = glyph # Generate kerning for g in self.glyphs.values(): # 64 * 64 because of 26.6 encoding AND the transform matrix used # in texture_font_load_face (hres = 64) kerning = face.get_kerning(g.charcode, charcode, mode=FT_KERNING_UNFITTED) if kerning.x != 0: glyph.kerning[g.charcode] = kerning.x/(64.0*64.0) kerning = face.get_kerning(charcode, g.charcode, mode=FT_KERNING_UNFITTED) if kerning.x != 0: g.kerning[charcode] = kerning.x/(64.0*64.0) # High resolution advance.x calculation # gindex = face.get_char_index( charcode ) # a = face.get_advance(gindex, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD)/(64*72) # glyph.advance = a, glyph.advance[1] class TextureGlyph: ''' A texture glyph gathers information relative to the size/offset/advance and texture coordinates of a single character. It is generally built automatically by a TextureFont. ''' def __init__(self, charcode, size, offset, advance, texcoords): ''' Build a new texture glyph Parameter: ---------- charcode : char Represented character size: tuple of 2 ints Glyph size in pixels offset: tuple of 2 floats Glyph offset relatively to anchor point advance: tuple of 2 floats Glyph advance texcoords: tuple of 4 floats Texture coordinates of bottom-left and top-right corner ''' self.charcode = charcode self.size = size self.offset = offset self.advance = advance self.texcoords = texcoords self.kerning = {} def get_kerning(self, charcode): ''' Get kerning information Parameters: ----------- charcode: char Character preceding this glyph ''' if charcode in self.kerning.keys(): return self.kerning[charcode] else: return 0 freetype-py-2.5.1/examples/SourceSansVariable-Roman.otf0000664000175000017500000162172014664131406023343 0ustar georgeskgeorgeskOTTO0BASEe]XFCFF2T-Z{DSIGnxGDEFƉn GPOSUjrJGSUB:'}xSHVAR MVARy o#FOS/2^`STAT 6ԖzavarymX`&cmapD8fvarwW`head?<6hhea t$hmtxzjX"jmaxpPnameobpost2W M;_<s3rw< F F  xf , V r`6,&0R&nr`6fV >,&  R  p       P  2  l @ 0   6   2   D  F   d Pr F  "& $H  R l  p       P  2   "&   (%  )  a  g  l (% L) a    [     s ] (-)     [ J ] ()   [ Q c i  x S ] ()         [ 6 : N ] ()   [ 1 ] ()   [ 2 3 4 7 8 9 ? B F H I ] ]   [    4 ; Y ]   [   6 :  ]     [ 0 ]   [ 0 ]       [ J ] () 2010 - 2019 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name Source .Source Sans VariableRegular3.006;ADBO;SourceSansVariable-Roman;ADOBEVersion 3.006;hotconv 1.0.111;makeotfexe 2.5.65597SourceSansVariable-RomanSource is a trademark of Adobe Systems Incorporated in the United States and/or other countries.Adobe Systems IncorporatedPaul D. Hunthttp://www.adobe.com/typeThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFL. This Font Software is distributed on an AS IS  BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.http://scripts.sil.org/OFLRomanSourceSansRomanSerifed I (% i)Simple aSimple gSimple l (% L)Serifed aCentered ogoneks [     s ] (Na-Den)N-shaped Eng [ J ] (Sami)Greek alternates for phonetics [ Q c i  x S ] (IPA)Greek cursive beta [  ]Greek alternate theta [  ]Greek alternate phi [  ]Cyrillic lowercase alternates with ascenders [ 6 : N ] (Bulgarian)Cyrillic cursive be [ 1 ] (Serbian)Cyrillic cursive forms [ 2 3 4 7 8 9 ? B F H I ] ]Cyrillic geometric forms [    4 ; Y ]Cyrillic simple forms [   6 :  ]Capital figuresDotted zero [ 0 ]Slashed zero [ 0 ]Simple a g lItalicWeightExtraLightSourceSansRoman-ExtraLightLightSourceSansRoman-LightSourceSansRoman-RegularSemiboldSourceSansRoman-SemiboldBoldSourceSansRoman-BoldBlackSourceSansRoman-Black A 70A5G:0<8 (% V)@>AB0O 0@>AB0O ;0B8=A:0O g@>AB0O  (% )0 A 70A5G:0<3>=M:8 F5=B@8@>20==K5 [     s ] (0-5=5)-=3 N->1@07=0O [ J ] (!00<A:0O)@5G5A:85 0;LB5@=0B82=K5 1C:2K 4;O D>=5B8:8 [ Q c i  x S ] ($)@5G5A:0O 15B0 :C@A82=0O [  ]@5G5A:0O B5B0 0;LB5@=0B82=0O [  ]@5G5A:0O D8B0 0;LB5@=0B82=0O [  ]!B@>G=K5 0;LB5@=0B82=K5 A 2>AE>4OI8<8 [ 6 : N ] (>;30@A:85)C@A82=0O 1 (!5@1A:0O)C@A82=K5 1C:2K [ 2 3 4 7 8 9 ? B F H I ] ]8@8;;8G5A:85 :C@A82=K5 1C:2K [ 2 3 4 7 8 9 ? B F H I ] ]@>ABK5 1C:2K [   6 :  ]03;02=K5 F8D@K>;L A ?C=:B8@>< [ 0 ]5@5G5@:=CBK9 =>;L [ 0 ]@>ABK5, 35><5B@8G5A:85 1C:2K [      4 6 : ; Y  ]$0$ 0 /9@Z`z~7AC\ct{~  *,14=@EO_auz~/_cu%CIMPRX[!+;IScgoEMQWY[]}   " & 0 3 5 : ? D I q ~  !!!! !"!&!.!^!!!!!""""""""")"+"7"H"a"e####!#%#+%%%%%%%%%& &&&<&B&`&c&f&k''R'd'..%.;S 0:A[a{7ACP^du}#,.49@BO_atz~0br%CGMORV[ $2>RVfj~ HPRY[]_   & / 2 5 9 < D G p t  !!!! !"!&!.!P!!!!!""""""""")"+"7"H"`"d#####%#+%%%%%%%%%& &&&:&?&`&c&e&j''R'd'..".:S{9() 3YXL5 768kj+de~[pvpN,k_["vqgnuMZBV  "$"$ ,0HNRLVV`dflr|"0@&pp0JTx|DXr#B! ]YWZ"&9<'tuv6789:=NT`abd -3>?@Bbcdf;<L+U4V5X7W6Y8^=eCfDgEpNcAvTwUxVyW~[aeghlm norsutzy~ 0^}?iQP/zXuS>O.    C 8@EG:AF  !#%')45679;=>KMNOghij k!l"m#n$o%p&q'r(s)t*u+v,-wx.y/z0{1|2}3~4560239;>BCR1S2Z9[:\;]<rPtR{Y]\_`pqvwx{|}^@A B!C"D#E$F%G&H'I(J)K*hFiGjHkIlJmKnLoMjkLMPQRSTUYZ]^_`abefghij lmpqrstu  |}$'(+,-./0NO[\cdno~23456789;<=>?@ABDEFGHIJKVWX1k:vwyzx{  %& !)*C($%s)-*,+7n`d\lij;wxyz{|}~/012     DEF )v !!""##D$$X%%r&&''()**#++,,--..//09:;<<==>>??@@BAZ[[\\!]]^^__``az{{|| }}~~]YWZ"&9<'t6=NT`d -3>Bbf;<L+U4V  5  X  7  W  6Y8^=eCfDgEpNcAvTwU  x!!V""y##W$$~%%[&&''a(())e**++g,,--h..//l0011m22 334455n6677o88r99::s;;<<u==>>t??@@zAABByCCDD~EEFFGGHHIIJJ KKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^__``aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~0_ ^}A?iQP/zXuS>O.77AA CCQPPQQRSTTUUVXY\^cddeg hh iijjknotu{}~&(-=C ?:;68@EG:AF          !#%') +#&4''9((;)*=,,?.1@44E9=F@@BBKCEMOO__RaaStuzz~~ /0_7bbccgrrsshttuuij k!l"m#n$o%p&q'r(s)t*u+v,wx.y/z0{1|2}3~456%%9CC/GG0HI2MM5OO9PP;RR=VV>WXB[[D14HR1S2  Z  9  [  :\;]<rPtR  {!!Y$$%%]&&''\(())_**++`2233p4455q6677v8899w::;;x>>??{@@AA|BBCC}DDEEFFGGHHIIRRSSVVWWXXYYZZ[[\\]]^^__``aabbccffggjjkkllmmnnoo~~^@A B!C"D#E$F%G&H'I(J)K*hFiGjHkIlJmKnLoMjkLP  Y] !a"'e()*/01l27p89 :?@A|BEHIJMPQRWYY[["]]#__$`abghi'jo+pqNrs[tucvwnxy~z{|}2;DVX1k:vyx{ % )C               (             !$ " " & & / / 0 0s 2 3 5 5 9 : < <) = =- > ? D Do G G* H H, I I+ p p q q7 t ~  <  L _ n ` a c d \ k e g l i m!!!!!!!!;! ! >!"!"=!&!&!.!.!P!P!Q!R!S!Zw![!^!!!!!!!!!!!!!!""""""""""""""""p""""""""")")"+"+"7"7"H"H"`"`"a"a"d"e##########/# #!#%#%#+#+%%%% %%%%%% %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& & &&&&&:&;&<&<&?&B&`&`&c&c&e&e&f&f&j&k'''R'R'd'd''3....".%5.:.;SSDE//:jl?2 wght !",#$%&X'()*+ideoromnDFLTcyrlgreklatn V %fI$&f-4@@p` >d28XdddX8zdd,&dddxd8d8d0vb4<`666"6 `P``&``6`62`". X                          $$$F">d>d2828282828XdXdXdXdXdl&0ddddddddddddddddddd.dX8X8X8X8X8X8X8X8X8zdzdzdz$zdzd& 0RBT"&,&d&d&d0ddddddddxdxdxdxdxdxdxdxd88888888888888888::<8<<<<<<8dddddddd00000000|dvbvbvbvbvbvbvbvbvbvbvbvbvbvbvbvbbbbbbbvb444444l&,d@bddd0 d"8vb<<<<<<<<<<<<<(<<<<<<<<<<<<< ``66666666666666666666666(666666&"66666666 ` ` ` `  ` 2>N`````*`2`  `&`&`&`````````866666666666.66666..T66666666`2`22D2`2N2N2""""""""`"....... . X X X X X X X X X X X X X X X X X X X X X X X X         >``P`2<66 XX$<``666&$6`&l&6(6666 X ` `"`**`. $```&X&X&```66<z62222`(``."..,X  v$6N  DXD"""" ",*,*,*,,,,,,*,,*,*,*,*xd66666666666666266666666666<<<<<<<<<<<<<<(<<<<<<<<<<<<666666666`$`P ``". >dd"d4zd8d&ddxd.8vdd00H. 6\ >66 \D`X` &6"\ 6Jz6 ~J<6X8z666 \`6JJ<J  rlrl00  PP  ::$$p@$$ XRXR`dn.  666666666666666666666 \ \ \ \ \ \ \ \ \ \ \>.266666666\\JJJJJJJJJJEJJJJJ<<<<<<<<<<<666666666666 X X X X X X X X X X X X<<<<<<<<<<<<H66`0DDRJ`xjvRR 4d>ddd$d "0dd&d`dzd8vdd280ld<HPdJdd4d2(jd*ddd280d,zd&ddvd^8d&J "0Td~d28@H<dd  $d@d88<>``6t,&`&``d`"`6``6 6 `D``>n```.66`6"P` `&` `,6 `",`<`6  D `t`<<6&&`66  d$ &d0&dJ Td 66<<t` z6 ``<t6X$6 X X`&` X&X&X$ Xt``t`AF2&2V(6,(,228P<( @,:4882V(8,(":P<0@,0*2V(8,(,D0D0lXX$4TPT:8P:P88P8:*6*6&(( (((( (D($$    Zd$h`h`J>>4*T`X$nXn$$4ddJdJdd444XX"X X X "44$ d8ddd8<dd,ddhd8d88d88d04bu4                         &dd88888ddddd&&DddddddddddddTddddddd.888888888<d<d<d<$<d<d^& 0RBT" &,ddd6dddddhdhdhd8d8d8d8d8d8d8d8d88888888888888888888888888888888888.8.888888888888888dddddddd00000000z00d4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b>b>b>b>b>b>b4buuuuuuuu444444&&d4@dd8d1d0 d"884b ddd4<d88ddhd8d.886dd0uf0CH0,u $d, ddd$d 18d8ddhd<d886dd8b0*dHdd`dd(dddFd80d,dLd8d4d 88d& 1dV<d8uuHdd  d4@8d8888$ de0d dV &8D<(#$E!<5XX.>.>TPT:8P:P8&(((Zd$h*h`h2h*h0h*h4h2h2h*h"h"h"B*,"h*h`h2h*h0h*h4h2h2h*h"h"h"B*,"h*h`h2h*h0h*h4h2h2h*B*,"h*h`h2h*h0h*h4h2h2h*B*,"N,l&f"W{?q"?Q?7?"??/m?1???"n?"o?UU>@: #aN,l<,"l&H H$`<06<< <d<f"l<l&<h<&$H H H H`<!l&l&<,([(1( >6  >B6F6BJ""88N\N\N\*~*L L * L2 L2*(0 L* L L**  LL*""4""""""""D"**""2"*0*RPRJ"<XX4 .D` "h .ll,l&l,lmljlmlrll,l&l,llhlFXXXPXdXXXXX(X<X<X:X:X<X<X&X&XXXXX0JJH XXXX XXX(XXXXX<XHXHXXX<X<R"X,XjxP6|~``n|p~|~VRn|n||nn``h``DB\<<X$Pvn|n|xvn|l|~n6&d  ddx""dd&`&`dd66$wghtital$8L`t ",^$^&X( * $ d6 $8&0&f@&f@@@@!#IKNQS4>A  ceg3LV_p/25@K)5AJS]fo|    ) B L U f  ' 1 :    w  / : D M X *4>HR\fpz#-G`jtVYdoz"+4GPYclu"+.8BLV`cmxqAD '1;R Oveoy>IT]fpy )GF  +4?IR[enw    ) 2 ; E O Y l } !!!8!A!S!]!i!s!}!!!!!!!!!!""")"4">"H"S"^"g"o"y"""####+##%%%%*%5%@%K%N%Y%b%j%s%|%%%%%%%%%%%&&&&&&&'' ''''''''( (((=(N(|((((((((()3)6)@)K)V)`)j)t)~))))))))))))**+++$++++,g,q,|,- --./F/050~1;1d12x34\5:66667#78'8F8c8f88889P9a99:Q:e:h:;3;;<<<==>?N?Q?b?s?@%@rA ABBBCC5C`CD[D^EEEF5FGHGHIJ6JJKeKKLLLLLLM.M0M:MCMLMVM_MhMrM|MMMMMNANCNMNWNaNkNuNNNNOO OO<OaOlOwOOOP:P@P\PPPQQ'Q0Q:QEQOQYQpQQQQQRR;RFRQRbRRSSS:T.T1T;TTUUUU$U/U9UCUMUSU\UhUpUyUUUUUUUUUUUUV@VBVDVFVkVmVpVsVuVwVVVVVVVWWWxW~WWWWWWWWWWXYEYZ[M[O[[\ \]$]^W^Y^^_z___`N``awb<bccccccccccccccddd3dId`dvdyd|ddddddddddeeee"e%e(e+e.e1e4eAeQe`eneeeeef f ff(f9fLf^ffg gRgagpg~ggghh hhh"h1h4hIhZhohhhhhhhhii1i=iIiPigisiiiiiiiiijj j>jXjdjpjzjjjjjjjjjjjjjkkkk#k,k5k>kHkRk[kekokykkkkkkkkkkkkkll lll&lFlIllllllllllm mmm'm0m:mCmLmUm^mgmpmymmmnn nn n)n2n;nDnMnWnanknmnvnnnnnnnnnnnnnnnoooo!o,o6o@oBoKoTo]ofopoyoooooppSpq qsqvqyqqqqqqr rrr'r2rIrLrVr`rjrtr~rrrrs-s6s?sHsWs`sosxssst#t&t)ttttu?uJuMuqusuuuwuzu}uuuvvvIvTv}vww>wYwx_xxxyxyzzzz&z)zYzzzz{ {9{{|H|v|}m}~}~~8~I~L~x~~(+58BLOYdf57:'} 8^)Y[^gx"hs~Mw]q^bdqs} [f(*57Ahknqt#.@T~Vfpy;V`v*-5] ^aJ@CK j`[SNQ_be $4DM{?~Lr&/.Jx$?qV3jj;(1dd68;=p*4=Kf '3?KWc?IS\fis}}"KT^gpBKT^v "+4=FIs}‡’œ¥°¸`juÀËÕßéó !+6@KU_iăĜĦİOř%7HY\gq{ƅƎƘƪƴƽ kt}ȆȎȗȠȶ!*7AJhɈɒɽ'1;DMV_hqzʃʍʗʡʪʴʽ1ˍ"̝̚͡ʹ oqsuγεθλξEGILOORUйлот !$&(+.025 ZӇӯԃՋՕ՘0 @לקײ׼:=67ک۲*47Aܬܶܿ!$'*->݈ݓݭ5@{ߧ.p> Gs %09BKV_hs}#,7AKU]f  *()x>er(sTI;r=9Md?T*.VM/' I       xEh=T]t| 0ku~P,7#?]`i+ Z)uc  : } !!A!o!!""w"""#6#M#t####$$$$'$O$R$w$$%-%%&&'z((q))6)*+,-./01O12;234 4i4s4}445K55666%6/686B6S6\6f6m6w66666667889999(919;9E9N9W9Z9c9f9o9w9999999:: ::::::::::;!;[;;;< <}<<<<<<<==!=?=d={========>'>.>P>Y>a>k>t>}>>>>>?x????????@@@*@d@@@@@@A AAlAAAAB+B5BOBxBBBC=CHCCCCDD%DEDDDEEE#EEEEEEEEEEG&GjGHHHHHHHHHHHHIyIIIIIIIJ D (DA (8 D\?@ zo!D{q]A `:K#}S-<9J-! 6 h{E T+ s-)yum E+ Asy)oymY U 6 n 6 n& }! e+ w){I]Ù g+ wu/ñI_c |v 6 (p1 q |j}y (oH(: $ ۣϣI;y{c 9G; Kۓ V7os": 5 5 x{" 5 _' }LT M)ٟъy9zo{@(fM -"bGe1/Q]$`Cte ɌÌ 3ai ^Ap]ѓ ь*9?_Y89 S; $L8( R # K`[oP Mfg" fm& sfA, to( .>> , R_! ~m' <}! 6# Wfg" fm& }fQ, }fQ A`moP A`m to( F_! . W@yi呔6DIIcS+_a'67On<0 o4ٽ_SG_u_ny4DoɔDPmK;,7WM/K\`ï{qssKEWoϓ Z, ho( HloP Ql R_! #6# ;li0 ugU7`M#7 ߍ5 J fg. J Wfg" J fm& J rg4 J +xwi0 J cm' J hy J \ | J Sfw J }f9, J +xwi sw ?Ylø J +xwi ՟ šSYg[A J }M J +xwi ՛ōuu /YSMuA J F_! J u`o{E Yf}g" fg. w`m{E rg4 F_! ? R_! < Zg. < (Zg" < Zm& < li0 y Zg. y gZg" y 'Zm& y ;li0 y ho( y R_! y T{E y fg4 BZg" hZU, vho( Zm& zR_! 6}# }eQ8 ō( {teq_sc p_ \ zN S-陡@ $ @ O 7( k(q \  S"gG]"=kïՓÌ & )CAYW]׃`k(s -Ÿ޿Ɇ|hnqGT=Js{{W]᥽ks Lu Ih1 )E_aahv{ywu3ͱ߉`O3-UE&WYy`  QQ flō \Gn : nɌ A0u" Q0u" < WH." ? K0{u" < k!- < s!% < U_ 7 < b/ < qS$F < OM# ER Y gy Eb < o9cWWceSSeaa < t9 < %)K < bo(! < U#_ < ]q bN s-{I{i< ]q -N ss !Iiy{< ]q t < ]q < U_ 7 } OR Y kqOb g魳 s{Sso_E i sw !÷sSUy OR Y kqOb wyUQK } É}k{ p{hB B ER Y gy Eb w] h } zwz}xk  _ {S]kcWY Fx h )  ɷy|szmqewo` y~w wiuh}ekg[Y{N Yx Z ݳɏwj}tYW㍐ ӯ{}qci qic}UO YGaC}}eMJ ^  |qZ wgy{qg yscuS ɏw}u{q5=jTХ ` ׻\|mXjVl\xt@D d ZiO[Ip_iQo]ImWskB oI]% ##K# ,M |댍}s wk6" gsq_ eSSym<ézoueugw}s 3A1#_CwūŲ˓p_F | ܿ*! | +FM# C`OoP aމ% u{7 ;K e!  9*! b0! #F]# G|I P  w{Kfm~ {q6"1YcQ /$,9 }b y[ɟlWkUmYp_cIdIzoywiI bGF^׏oL#O7> n#]- > +]% > O7 > 4BeK > 7F > K# > B'a > B'9! > B\'3! > ,__ > W/ bN s-{I{i -N ss !Iiy{ ` [WK s}I} u}m[ 9 qn 牥 /yaD{h W t z > O7 } h } շ ~zord}qaj uxmqc_U r h }~ Әw{q|y|x{o}qaדqgayU iSVnlX[ Nr鰿 > K# 寱 ( :( [% 7 # $!  yM'K u# / m& i0 LR_! 6# EloP LzŇ "hQɷscvg{qyzoݭW!o[y"wQ YeWW~u wk6"=ܒ_I ͉- oՉ% ){7 ă/ EcF #w# э ЇK k ! m m! rmr"6"~ ~ mM7 . lom qCaqq o d kn l . 8R_! . 6# ) "y I?I J.Pg*mr" 5eg"  3`Mom qCaqq o d kn l }Fo_! .Im' l}! *M# b "x QQ ݉% e! R_! ݉% xՉ- >ЏK ̃/ lom qCaqq o d kn l Le! BR_! 6# @ ]@ C ‡- C _% C {7 C ~ / C 5o*F C i# C Y C }A#K C b. C uq_ { bN s-{I{i{ -N ss !Iiy{{ ` [WK s}I} u}m[ C ! C {7 } C  C i# 寱  ~u}}~uh  o[vigOn[q_mYo[mYǧZeA ccim U [iO[_Y[YǻZe cm.u% Ͻ}~u}smY1Q㣳wӳym}sci si_{U%;`B]FzbFJ "E;GQ/i{qi==iSw)/42/wh  '? /A1%ëraiSjSkUp_iShQmYíéśbiKaKo`eMp]Ip_q_H _“%  uu_ V / b.! G ܡ*! % Ol УK e! R_! {w# s! !6# W޵% ޟ{7 ueK ueG gq qcgiW (կ C`ooP C`o e! F_!  ٽ>`ewGciU5%ECoMAyo Iӱ_OSwqg/k'&`(Y]UgWC_ggywc+g{  IV7ۧ}"g  3xs! /`coP /`c yF_! *c# BzsqF {k]@L# P Pɫ} }{q\ -1zoqE4{ M#*9Ssc{qH ޻- H {É% H 5ޯ{7 H 䲃/ H QcF H /w# H ڿ H ¿cWWceSSeaa H uڽ H uK v g$oͽIYd$Y v +S H X] {/;ep /{{/eiC-? v Í uu-WaOŅ+S H F_! H k {޿% ޷- k 䥃/ F_! &h m"CO_kO 8jg> y ͽûuA H R_! = h߉- = % = {7 = cF g ^yg- g g% g mY7 g aAF g 2}C! g G! g ci_ g pa/ *ҟ% HQK Ve! {j LR_! 6# 4.߱iz` }uO9&5#YΐY!-= y5éӻY[puJFvqmaQK9/$5w{#UT22u߮k7gW weuuy YyohmDY"ӎH  &S M]Syu su\ ~ ַ ֥7! 4u@"aŻッI7?Uac{egk{uy9ˇ{ӻaK?ecWi{P QQ Fx oՉ% J [% h w i[ ekg[Y{ w s!% h ) w moӘwqyxo}aדqgayU SVnlX[ Nr9 +]% m [% G _% H K% ͱ}{q_umQiQ~vqӍՋ[=t KHiWVxՆ{qF&2eL A OQgc[} Njymwuugwyq'w}D[ gu_ | *' : [ iu  ʺ˓ iRt͞{ /9\` ϨЅ{z@8J5_eRsrf͍OIU~m  ]/-TAShqhrjҗo'G#GG7GUȿI 럱ld}u[UiG%9 um{scmYmYufrawjviyüi kaI'052/ɻůtP!+5Uzo|qxk~w{{}iY;}quors&~͙M)vcc lEqr~~K*P>ҧquk&+N~pnU}pጀ* }kǏi+N5i*>Lw~  s}mj "1^ s{B1gǗaɏ͌t 1ɛ|n {wQdc/9\B^ 4 f 009{qte;="ym}wwcHI- ρ{ղɐU[i}ura[;qwӁ{"ߩAO-p]ymteiSwiӊDX }} Do%!] ]M 4 ) @ Z|ʞ}rO%h%"R 9 ! r Pm s sc4B!:gi8չKi"HD M 註]E$*4&<Yu  xo}{pv~wxmulwnь L~ m "*= t~-+hpƔcsl/!ow!$tğq :[lCmM ib恘) 7"u0 pjqU f áSosy1")DB% ,EڸnIO{JR *,XPFXRkQQOiwi¬Ψ]m!SkWF & rm"h & fmq"h ~ m/"-eWi_yqY Źū}Z1gljY͏L~ H<鱿k}Q 1gzNݏa"Sɣli ywquo@JV7\֡ l"aKZ9ҳF){px&r`D~5 "bK+[;nDDSh2p^vg!ی6"{w0,zs"nE witet&rmhҘ6"Ǽݐ3Da--g톃nZogwg2Sð䦸~sfsdvgp^f![;ێgtS.S/"j yi-0,v{~ǹuwwSɥj"}s}j s}se7?QUœk۽wspvdXxٍiY[i)WQIwok9oq|{ÅwoKyUa[;KSW_4/cwMϏ~4 l4 :4y4׏?*s3uo}majqu%љ_Me"o"41!on~T 4q_o #XS DE+    W]zay6wiL0_;hcM)MͷɳW^`cah6oL!i]aW?  4$_7y{g{|{o)ϫE O DKew̩xFm"'S㆓q ֗Wc ac_օ_]ac_։U$re23{]]]}}1a2 ruΙQc aWc΅M Z~ٓg٥[{we}y{y9[;AsaNo`اύ@}D"k<‰ 56xfwivf͐* uww56Ii&e~zi[eG}{DžR~-&kn~p5o;!7tğq 4\gOuM hc쀕ۭ qWaga {|y]`_tl߃ke\ \M-7;Gf||fmW__i^y|{ug'} ɼv fm^q"1[gU- 3a &R캲w]ȬSag^GJoyiWW^kVI5kpW^kD"oc!`ğqUL&FA>?_mPtwuS7ja \;ASWő~k׼ztpxd\z j^Yxq-YQIsmk9nr}}woK}Uu[H#bୁɮ|zpT=h4qu4{?s#!C1e n V E}ɶq4q1QM rud Rxɗ˛qva xzsBhc/6MwRx\ 4te"ra y ;!/U]cg{oyyu\=݅yraM1'OM MmY}uޏ^ug ,ym_^`C?ym ,w"ra y ;!/U]cg{oyyu\=݅yraM1'OM MmY}uޏ,{m_^_C?ym R ,w [AN>#@= *N>#@= : d _) 2Ǐks HO2  |qwi}t|s}swi 3Mr rM)3mY_An[y^An[o[yըՖ2}ww}}wu}{yuywyyy{zuyw{{z V* bx + r- # $ "K٩ǡemk qosuA[['Aaь+ v6 #6 5Zg. Zg" Zm& Ofg4 li0 ~m' \y ho( Zh, T{E R_!   R0|u" F,}sugͫוʗ O Hi ى߇Rt̓} zyOϵy{A9 R-ciXx{}HnjfXOIUt``` Ih{g]/CY3oksşo+C)#GG7ImöbHq(ÉυS5q{k}(?+Bt55RAo|sGe(sR^tِaw]k ץ"677V3Qœyk׷isuoUm1QWqs'a[WEnx{oQ]|cY&|yӐU/)C ׿XPgsK<yPэ/ +6 Ӹ„znZm k zosbpcukvjgYn y Ԙsgwmp_uc}zq{a]QwB {qwm}uG C9Q|}J˅[3|1="}A:Dl ;=Syo9!΍΋ml9LpDfmӐ0Y񁙉wwi}k ^  |qym}t}s}sym 3Mr rM)3gOeKzoymR-mYmYym霧˝ǩ8䗟"DܧoscP'? څ;;[6uy0C4-[k*Td1$S 8^9*0RG _g9iycmsg{woͩK miqf0 ݋{ZU}uiӷwwqs Am}a {$$}Aim$"NX~Wж;k_im&y"yt s6,8uyk}$C23ws+?"#C5+_SSUaWMgɻ {{}m6YVDkO D#gPOsWW͏; H >5 T(J1S VڧdB5"wis .BmRX% s*ě C}?om )#;$waˏ.>䩃}}i㠗y< T9}/97Ϗo!y< ] DqEo95{E罫smSfelk}kgIz#17.(Ymhn}wshil{rc[ys nKٳׁ}?= R/yeTrok> Uᇉ}R B당֍7\H Ve|ea/#7=XngmƮo-쾏u 9-)KG-Qq P -=!فGul`i}"gzlݍU)GA;KYsKKg_iZzߵqQŅkoqqqT]ݰH989xxﱻ-)+mwy{``ϫͿq' 6(G+I[Q"}cWc{1>  ԟ{KX{w~s ݍMB[@l:AuO б ^ x" ? mГ ? KcF  ; ȅ ; *cF ] ۅ O - C M eg M W M Ca .M `:h ,V 4M 2 V .M `:h W 4M 2 ɏW + * 6 o' e t TI Pz8Oh ,V XZI "z t @I Pz$Oh W XFI "z ) ( 6 1 C n1 M eg ,1 .M `:h ,V j1 4M 2 V j1 .M `:h W "r1 4M 2 ɏW "r1 + tj1 * tF1 @ e *Qqwuzuumgo}c[| zx{vvUᅫ&W;y7F ˏϊ~o{s+%tss]ձMM}L|g-@ E4q@  V  Q ˧׏os sXq$Xw/sKo[y?# x ess _ͫ =aks Pi * k k  m 噙wg# 3>[eek[3͌>935>3kqIq9@m@ } [ G k X} F wPLa $ (! ' 6s (! [F( -"kov G)a 2= \&EYEaՓ݌$ <  29 ~o# $ N *  "ߌ 2Z )8=Eecgmg{}uѓ ɧn( (P`3"?SWOm˿˯šqwwE Qg煓5=oQ$ RR ;W b *dd!**#dd*mm 3RR  RR3ûYCC[WSS[ӻÛ:g(J K9e[Scb>+יGϱy][kwU?׎M}2^g`ZP=lj9 Zg.  R 0"1"^Xi{sqnoV &Y[a 5~dW=aM{rIaῡmy)$ S GCZg" ܥ ůŽwE ,1bP.ɿoaǯKIWqKEywiO?>!ll:cyy=oQ A A ;li0  }IO\ 0 G LK $ 0  k G <K [ 5Ñ|gp _ Zdŏ^^wG"[TfonoV &Y[a (Zq" k Zq. 7 hy| a PX(k  ^s L }PLn[() 5&vikTp_7  +4\=$`&I]_Ateד#݌NP)+0HHoiSE r_H@Uŝs  ti>tQuuT}1q9{Oq:Q* oyq i\ l(o$ G\q @(ĕ}U78 ߍ r &YBA:A:YBՍ&fLiA䳧XsC  {" [ix$]oo:H! ]:Hg]i[|oo}{i 2sLfiէS D3 r @  (灍oj)a k( % A8u: L[?仟XmC {y\t| Qpd~)H& ]' j a όD w[Cȧt(97  L  So"P:u # w  =oyPGu $ Gĉ}rteU[^^u$3$Q_ik([ A . \y| 6 (p| 5 9 I\y|  k ~w' D +Zy,0  7 }m' 7 fw <  0AGGgGW{ygEɥ[amm3A//O6JFlͥեOQ/;uso}YsNmewgϐR#{y? @ Z|ʖ}|rO%vhrim{yR|9{o`}VL!> 0 q YU` E wizo{zuV ͇}{omINXd$|swiГ_oxlQ7fCFI_=OY[gNq`xyun[W5\z K 1 +(c KJVrm!*I m (ˍmr6!9~up Hɉ  } fkfRVr!"(~}~8sdc7 \χ imwmkY?$Ì Y?/$s ]ZhaG}urg \#3 |bxaya* {y{<gr$4~5 a C ) VVrr"76"u t gVDoDV"7gE!gߓg rwHKq{6(Sfd{qkyӑ^m^I͎Djkf'=w 3CHˌ'͍,V߮j¨SaglGVx{v"hgmiU ~qces$uuu}-Q+5Jzdz˽" foj KVmV y7"27"u@urm gqgYũ]m"u _e{jŒ) r Vh V 77 uj Ao !{ =Z r Vh V 77 ulY #XpoRV]/!Yߑ_ Q -Ō)  -Xmr]"u_ I 7͌oI% ) * Xmr]"u_ A ՌH <@-=ammkyugyu_Aǃ}~{xk;$"E;Q_iymugyyup_^?goͅIocߌoQ7) ~ lmr"SW_"u ter "W4#Ai--c~~uwgsh l]?ˍ'̛,NȨꪾtfqesblXb'dJ̎ndJ{w/:nqDzkV~uF> n#]- > 7F ~h{sugKIWiWW󎑁y wk6""fMɹsctd{p}vh?TM+7{{mZwƭĿq~uO'sYC ) Q "7Q7uԫ% ɽ}yraٍki]qUU E""smscmYmYterazo}s|s׍kaI 9><9|qzoXoco`C߶Q7 EcF ~ ֥7! } |rruHV ~]'~}~8sdc7 vY A) "O0 mhhmr]"0c"uާvY A) "Q "w G mfk"=ܗIr#=  % p tŇ- g 2}i T ] 2rmV 6"87"uL XY !<`` m >o>V)_K"˽!Y_ K +ˌ Vy:$ [Cşs  wi=qWoo[Ef|]|[}a<* {w{ʏ ) V"7I\s@r5 {YGBFIw Q ύ ō CZ 5 `Y  " 4YU` E io{zu ͅ}omINXd$siГ_ol7fCFI_=OY[N`xyu[5\zJ@ e@ r塍poR1!Y mr u xij Ao !{ Z rmhhmr"O8 8c"u Y  " ͌4 Zr r"o]Jrk<X  ŽO'i8Nr~G rާE= ,r r"o]Jrk<X  ŽO'i8Nr~G r kZ  8 Ao !} KoZ rm gqgYũ]m"u _e{jŒ 0 / < w# > B'_ ( p u# C 5o*F g [U# g {c w Pp&P {/\s  / li l3 {k )G `#2O _#EYEeՓ (Zq" r *Z=A;A;Z=ՍH fHig\ @׹! ]@]g\ Hif: r @P  ja o)j a  \y| = =  B B r#  @ Z{) Z  F se {}u{u{w{q{qw {}u}u{w{q{qwDR* c AX] 5vUj<Y4a97Q) MemYrjїo'EG#CI+\^Ⱦ6 N~KwGǓՁ}>*E_gqzugayu1O Ňwa+AR;rdç“WoÍ# G'!AE33[eUkǯ{wwS9aa탕H H Ì/ bsm ;"CO_kO ͽûu[ Mw! 0 |m ;V Yk] yV [k[ =g Qu Ocٓñ} Uu! 6 qs% H ޻- } ^o^5ɐ]elhegmJ*rՐ) "]-*_.6i9ѩk~= o}1ecwW ^mf5") ~ `mf"SW/" } ' vis j ^o^5ǐje v'{) "])&c 0xyi2j ^mf5"ᓙ ˚e9# ՅgKOOSV4~}{{}gIӓ,C vm}uYdK|qznq`e AˏqoqV4}twuwsoCg', my}qK!{K;;KS')Qۑ{{ٌG]ٹϹW=?]UGte{pznwkviq_q_wk!Co}sYO ųýе槛mq-e9SKY_SgM7C竳kW88UwsgG?UO7&Nkgcyu[m{a[Y} J{n~Yaɯß]_wmhl,SHcG~u ?mmq=UUq٩ q ,o7t_ C | RZ -!{sy8 q{{wy I9#lrS}y37 u  9 P] :0bwPkoGAJQA ˑ> N% IccvGZZvϳͼ ww ymwwym-OZZ#ZZO-fLwjxkwcImYmYw͞ʩnVM;$m$ۥym_;q|q íBjji@SSi֬ÛB q"' 7zgggP[ %y~oKAUeSYw{y{} w I9# lrSyߔw=7 w  9 e c :,bsShob JUA ˑL V% L``mJYYn̶ʽ ww ymwwyH 'KZZ#ZZK'fKwkxkxcImXlXx͞˪lXM;$m$ۥym[;q~u ^\EE+\^+ouuo}}T B@+@BO+-qACeqaaeձ q' v,o7d_ ~ ggg@4 ECYqo8 s{wy {I9%!)jLM}Ӕw58 Eur [ D H p T 9 Ec:.bsekob JSA Ǒ> V9r  *83 Aw?qks{{ DZŹm} Ud 15']c֐QuimU[=w㵭{kwuc+gslj ^\EE+\^+ouuo}}T B@+@BO+-qACeqaaeձB q"' 7 l @4 @@ZtoO?WaW]p}wy vx I9%))jLJהw58 Eur [ D H p 9 e E]:,bz^mob JUA ÑN t 9r  *83 Aw?qks{{ DZŹm} Ud 15']c֐QuimU[=w㵭{kwuc+gslj }zEEz}qssqT `\\`O-PkVQ]jpd^[q[֙)EؾҳckbesXzcdqPg V R?/=3 @ŲĹRYyouwl}z` >SNlV%a 10']͓LjnqRa8|ck}E sDž} *U ;  惌 惌  T}+ ɇHw2s3HMw25 y t `+ Ͻv U 7g]oIqco1>J9G_ > > X @ XA @ W W @Íauugez|h}wu{weG]ium[wiUkk{q l q ͌64w8{ao/8l ͌8s8wy46{sak{i~c $$oۓ; ddoۓ; toۓ;poH;ۏ oQ; ddoۓ;GQ 2a[[[[cIIckks{{sWκ\HI[VDDVͰnfeosoosÌ[iícSSic[6_\\\\+3.{Sllll  Í<8<86_獍x^ x^3 .sS!H !H ōJJkgkdˌ] xX x31 oF !X !΍dKJ#J#g] x/x ? !!#JgdK#J~]剎x3_ x_ F!H !HwSJJkgkdˌ"oKS M]ɹɹ]MM]]My}{{}yfe;35 'OpɌpkM΅ ~ѿwwcɍGY1W1Yww{cMEMrB& a.4u4.u Y$DD$B$DDY$9y1 .44a.; Y  ϫkCR ,ӌ' uCGkGr,kϛK{Ӧqw͑|{ez|Յ͜{|ӛwqpm{cCgq'wAICc{cEt EIA'qӁR ӯՃчgы ӓՑggCwmucG{˛gCpISASise|gUASIzqC{gK ? $@ $ ? $@ $pop]9]lolu9r19U㭃/sퟔxnqM'/siU5{unxPyvh ]  * nnc] nnc *o|[_ͽΌ@ӍN," ]kkiwr u߯OK!+[mdݡǔp$k#MЙSFLCQ t `+ Ͻv 7g뻩g}M9uOp$Mɇ}{Fw-N,k"ws9Gq . DKkC&D' .CGkˑ[{r ,.sDϫK#[r ,Ds.uӏ#˫G ,hhϱeύijcR hhuuGeG(ύijc , GkCB&B' ,CGkϏY ,sϫG#BR ,ӌBs,u#ϫ 3 ͯzygǍkkoyS7S۵{mue[iuvy{ocW-7A G鏃Y a;3QeugiyWzM+%SK9Qoksj}yygOes̓{ !g3 WAõSAsq{6呍>ME͵sUKaoIwy3ьXڵy9))9=?홓}}7Gӕ}C++GE7Iyٽuq=Y}eeIdo󯆍٭m{{soukumqoMosCoɓV  ǯueYoy~w{{s}ywkkUcoY_u}svq y~iksucesqwwg[oy:>1냣S ngˍngKS +s>_ѕ=Wk3 kUqe_=l h wisuwkS]ཻxqnnuuwymi|;QM))Kنtl ׌nj[-z}CUۿ-qׯYB@gWAd~al ֌\hɳcMv*T7ۊda~d`pwZx~M!7C/-m(WVt"ugɝÍ}zuύm[UwGJ VB0L>D&99KKu룦wqgwyz{ocu{uk]LqW=cwog I-1_ǹyqsiy Ws

0-#I40V3v͞ ، %0iU5aG^C}uF m fM)8 7 8ug7 ~uX  #V }3 w{eT3 eT!3aVb}}o[Y #n[]Y~uoc % 0~5 뛥 }{qzo}}# åtegOhQq_raiShQq_ůǥś0  ~po}|| > -ĶcZP`aRQ_Ƽś4."u}zr@Utoiy4 8 D0 8 Vx' D | = 8 2N, 8 ! 8 ,E T+ s-)yum E+ Asy)oymY U 8 2 8 2&  e+ w){I]Ù g+ wu/ñI_c |v 8 41 D e D y ZnEYu"ĢɝNO}c O[LăxPǓ ; 3 3 :" 3 b^t' y1L Đ}Eym{&dJ~5 Í\7#u* ZJpeؓ)|I;^@: iRra֌:M= _B< XI 9( P # >`goP U~s" y& {8, {( 8", !7( l=+! P # P }_ F< ;ƌ@--;@|iWfc [5 Z S 3vͪ ،T  ͌A109`R1C#D_rphv?ztzyMmĥ~{v:aciK׌L,E&2.|ѩ9zk+ @ hs. @ s" @ y& @ &a,  @ y @ 4䱅 @ 4{( @ >R_! @ ܗE @ s4  T+ s-)yum  E+ Asy)oymY  U @ y @ y& q! j}}|s׍}y ˯yynym}t %0iU5aG^C}u|s_og]U j}}|s׍}y ͽyzoy|s 8%0iU5aG^C}ugqc]S @ y ß ϗ]Oq[F 7{( P oXvovzoӡC#G+U0# ^qs" y& { {{( A`dom qCaqq o d kn l +, Uy' ss4 5 % vtcNWpcKt}ٍm_Ax x6uv}~}maisarulWz`m~ y& u0 NR_! $ m M8 8g u NzŇ 6# { SL"8uU kt gM)8 7 8vy7 ~uX s. X gs" X 'y& X s4 n X #y' X х X {( X ⁍, X ܷE X R_! {WR!7u9  y& l LR_! 6# ms" V"ו l 0R_! )y' ēq! 6# 0oﵗTH=[qŏg٫Qo}=0u `LR Yu  opvwmln` ptQ 0s" d{( dR_! s" s. Fo, s4 lom qCaqq o d kn l T{( TR_! 6# 2 Б. 2 W}" 2 Г& 2 4 2 +u0 2 a' 2 ҇ 2 S 2 }7, 2 d.! 2 umE  T+ s-)yum  E+ Asy)oymY  U 2 +Љ 2 Г&  2 a' ß ϗ]Oq[ }{q{p||~ wijUlWtdtelXlWsclcE#ZN c}yim" }qp||~! iUWdeXWclc#ZN }ym8qw" ҥp 0eW^G8$--&GZ_Z|7F#7Io^sW,]WdS2 Z 2 Z 0 e" 2 Z W y. 2 Z UE 2 Z qK4 2 Z #*po! I 0 ";b( Ts" .}, {( hl R_! y' ĵq! 6# \s" y& J, J B`hoP P`kom qCaqq o d kn l {( F_! Ľ\@xA}Keê{dƽøukfhpX|i kUHw{0GY?Ggodxxny` mxswGqvKUa4GRc›usW _kރЌ`"voߑQTj[9d`5CDqګЈ  ̴gaTey[rzrR/t]O0Mb[@WcgƬ{wusYEesŗ ⁍, {( IloP Ql R_! #6# d 1eKe xkYA`M#7 R;Ս) L s. L Ws" L y& L s4 L +wu0 L cy' L L 䉓| L S L }9, L +wu sw ?Ylø L +wu ՟ šSYg[A L }NM L +wu ՛ōuu /YSMuA L F_! L uoE Ws" s. uoE s4 F_! = R_! ; rs. ; s" ; y& ; u0 s. ks" +y& ?u0 {( R_! ܯE s4 "s" H[, V{( y& ^R_! 6{# }o_ bF9 Q; |wilWufc n[~5 Z S]>0-#I40V3v͞ ،$  _QԽBfk| 0 ~U p46Sh Amѓ" 456GQkki{qyyuZ Æ{ kUymǯƫ¡fM]G4.1㛥z} zo aQ9NMacd׈nk*wu Jѵ~fosTEJ]OVw}~Zbƣmt+ 2J g倂E1;Qcei`d{}uw7΅z׽`F;c]Wmw\xteħؔŏm؈>n[]Y~uoc % 0~uno Gb\{zp~uR, ptQ Pto \lEn ; 2" jv 8% G}" Q}" I W}" = K{" 8  6ߍVMmDVɍy7&AC+otArE+V@ " ~po}yy! eZZbaXWa%,``oO+X P o?#Wiio(+PtmާoA#2 4 0  ߸X|UuB3&z"J>\~a_Ϻҏy7 $ z ^3 l$PV vT PhlSZ^^l  n ?u0 8 SDݍl  8 $ 6$ Ͻ= ~n\[/u |?k=7QeCgϓ ی  | J. yw Duo"rgu|{/}ތ+ӞPOLRm @ / WExśŁ{C gO}|qsY7Ìz|rcMEYg raxkۓeqzoQ; bGlW~vvsiRW3WsᏒy 3)8] }kZX n5b :}{* mi>~uo PÙ| : Nw 2 4 0 6 }0 10u}sg01F E0}ullsY C ۩_mlm`;ˌ N()CM ;mۓsKq7o z |e Kvkv y/ B/ u@i $ vn ://u. Ao { YZ vn ://un_(l tpoPvU%e !ٌ$ l #tkU u +ٌ,o-! $ 2l tkU u  ٌfd @62C`}sxk{psc_uZ Ɓzy~v 1$/E6 KWgmXwjȬÝz|wu`C[;eg׊GiWomY멽I+$ 33 M g u& 88+,%6:#ur|~ > /ʸaUS^]LM]ɛ{q0 dIGg)0Z}scrash|[;Սӛ!Y}sese|qmYq^AӎjbG{{ 9l@ufscL"@ hs.  ڰ ? ]io|}iNb$o6vU Kwysd0)KkX~wLgپoy($ R /K?uħ" Ӻw`Ci _c`wP@*)óukmYmYiR}trbgN~u{ӻi m[I{ -):<%sc}u|qsiWomY멽I+ X n  : :wǎ tU B $  M<ǐ kt U x D/ uwL 2]ՌW v3k _ zO ѓ;Ɍ4 '&qK3 RcCj 1vhpApWo3|JTjp >@ aE"zZ0K]oggynzn|s}}wcIج^Z'-u;rbѹ׊ɎeKwkQ3MD{L`C |sscsc}sxkxkvixk^k˹wlW͍fi_x]>j鍡ۣxlxaE]?vgMˉɇD}T/wR-ь"{pKSypJ }sscsc}sxkwiwkxk  $0  $0A  ] B ܧoۇ;B o;r& a Y $$  $$Y 9y1 %a;% %,$ PϫkCw%,P' $uӟCGkGr%kϛK{Ŧt~ez|ýś~tpm{cCgu7w~zV]Vc{cEt W]W7ux%ӯߟqы~ pgCwmucG{˛mQp[eYSizegUYe[|zxQ{mK u "a .{a .{a D"a2 .au u "aq "aw ".ma+ "a "au 8VsT? A 6K. ,I I &ao ƓA- u Jw >{w >{w DJw2 >wu u Jwq Jww ">mw+ Jw Jwu 8 sr? _ ߁i. ,_ _ Fwo W- u  {1 {^MWo~r[E[]ieuw}yuy]O }}}eOGQOuy{Ŕw]D'  u   "m P :Q9EWSCCU۷{Xn~ \ak}cMkïѵM#"GUOouymqszgh_}Ϳ}qiY}{,Es Es ׭ #k- u { { u s w "m+ u ,\i \i o :a-  &3 c ^{u?iW[q{ssuSx l_Ua EQkÏ{M kmm};ˌgeg{k!  a^X^Vc.Dn /D)PWWrvI ˵cJ` S3x `G 栍:3_ܵsSQgo0_q“>nV#`mLBUo3]j2n&aóz[ilix^,P 첫ypi^_zk]}sdX?44q Kuor%oG э K ?X<SƖBΌ lUEE8fշ hծ&_\D eEEAeUkի-cXDr&aĸ@riD`ِwve~c'P vsj``xi_tfQ=44s nn[DnQQn0m0D Dn0% &3 ڪѦng0EpkUgquu}P]dsy *c&Z^W3 3|h+in60D {^+nհA0D )7-pg qh< g^is7ߍDaU81i+ٗh0}p]=`W;%  0+6MDž|N- DpX6*aab~sYMǑ= kN.% j&3 @!#?63󙖈}y׌2O > P<0l^amhfbp NXgƴQ)s TG g服X5fuBC_n2]v8j&3 @"#?62󜔆zxӌ2O > P;1kaamifdp .}Ǎ~wQbyxk2 Q`z [S]ĴRr4^G tN K:]ڶtJJ`m uÑo Y/cqg}qMU a> 牍<_W_Rg/2PՍon#/&aɍFo@1/gyci uqs}( ścOk" uqs}( ścOk qEaemikk_aksko pqu}əcOi s?aeskmj uA{ q uƇr}}˅a3aissou\A2r _i\uEmj qkgf ##M᳭}M: )2ɍ?i qqee{wuTՌmik{kU .u3 liťyՍ}eoscsÈ &aǷUYcguy}uo{skc{KiacSwy{wr` }{eioo]_koyukWsw*&aǍ}}}a}{^+s-u͡w?#Xs\KQcs{4&w3 [ o՛/aaiykU M}ǫqsZo`/EY.3 {m7CXg/iCXUm3 {.}aVi9/Vmݏxm<U`q5Ϙ{sQ`GiOS`s5ϒ{sS`Gk5}{.a߳gcyQ7m8,k/Y=kW iWٓki-*:wŭ{}qm7IXmӍmk}=XCm1ՃrY{oieoO.3 ZЎTH+dq>YIOT{[hk wymYOk kw{Ymwc  ug}y{qȸy|~}}r{qo}eOQDZe/xtgxmxi{q}uumu ~qk`th];DFO!Qݟx|x~~aoia_Yy0&r3 U3]oy{qwun[{ձSAuey~{U/vgˍCoϣxiocdH9aaM Yvn ɍyw}Nh][sA=r  ~zo5BTmroҎBTDm2 =~{nk:nV{jlfpp}sxjjquys.am~;e˒oðʻwqtzznwucQAS_=?aas{\! @rݽ׬uvBmomg?IM')M᳧~~WwKecJhim}srWu}Jˍ?i gjondg{zuDތkgmyk non}/&ao c Əg''stQA uYA vvuY aϑlzyGIϐʐ|swIFJʇka_z^azmlIwuFJLsk}aZ\bk IGuLL{=IG++II=i__igggi ͌V47Ͻ˱uemncjqٍk]Cy{{3GK3\|iHBiv9[Q3CSgu{yyQ3]i}{y( YwyrZ_z( {ien|эo]Iy%MK%siym/9-=m=?_wy3mv=I qC 6>>>2"yuw×ugwéFpe_Ok7F Ǿߏ* suu'^X7i6"DqgǍ0o<;2"UwקFuokF ߒ* suu'^7i"Dw0oͳMSIf ww>ͳNUK  ѻǯwA׍UiasS WSOm]]y~ w kg~yq)mwMIy$ gY*owuugK}e)C[kUug?oJL{q dUpU1 nq{b~U1bGlXؑiS ,*2~oG}uu{{ O'鑖k 97 )dQT}F-sMsvgy~uj BgOj[T}F-sMsvgy~u~uBgOk[ L$oN"N%wk^?R+vi@D"ף,}Cs07sjUzo |qj 7 aEj["ף,}Cs07sjUzo |qj 7 aEj[ L"K9wkdI NdUviݎN_M$$o׳^?cSxkw{q` 5y;L!±; ygGY[:sdܓeE O?ԧQ) yue  ppCk:[89&OL7 C 6 6 qG y R y أ^MWo~r[E[]ieuw}yuy]O }}}eOGQOuy{Ŕw]D2 m 4  T~ }  6~  Xr }  : p :r u yˇ :r  P s <  2  L8 p 88 s 88 m+ V8  4:Q9EWSCCU۷{Xn~ \ak}cMkïѵM#"GUOouymqszgh_}Ϳ}qiY}{0 Y 8ӕ  u Q 6~ pu`NN`k`NoN`ss// kO qiqʥkqkJʥiJLqL ^^ qiiqumou qiiqumouQQ 4q/ / \c J,Qy _ =_Q yg;(6y,Q(6ϝی(6Gz = ٷb J,ύy Qu u9QQ g#(6ϣ(,G ,(6s(6Gsz 9œ b , pύfNNdkdNoNf1[//N%G uuj_#j_*g'*G wSӌD 硎@cW穎D iC;: oq/u!@oy/m;: g { \cuI[sq{mQ[?wecqUq}}qoSŻ/}{*su|(o`G/su`(|ssGG{u珍Km{yqq{珎 ==; uoou|ru(,kH[/_BAM-2LEO_Чq|gU7m=KS59Oׯa{sU|nxgES} QWѽǻ_Geek{soOcUWI oIWGdmwqoݹRBG_S?o,ZGUSSUaACaémmu}u[ieWYie[< < ` sVoM牑$=[` *,rv5SYseiQRzsw5}EhP?2?KsI{Y {ᶬ^]p~C/yqgݍ]MM"?{/ E〇2۝蛜_ wa{{9y- 0{|r e{CO}q)o$diwa{{9y- 0{|rbl2۟虜DmHcCO}q)ߌn4 m9Vԇ{{T}}{}'[qϫ1oW*NQH(eks o;sGs9ۗ* sso zy;i\ (e:  z ` h> ;  d:#8qUAGُqAw ppX 2 e q  0K;;KO!#Mۑ{{ G]߹ϹS79]QGpihhshhh~ {]ߍssswaU]xQ m54D+ryqusw&cu $T''>WWbzzbɁ?99?M'%OvncenvՁuYcmm Q]Ź]*@4wWYas=61Iw;˸~* oYWqxxq9X:)$r uYcmm Q]Ź w2D8iMY]sB:4E;˹* mWSqx~y9X7& ywr ݹLJP&qKIugui}y5{YqKqq/SWWatsuqwT >' qKqq/SWWasuqǧwT MiQqq/SWWa~suqV]y5O["{O;MWk3o㍌oYK;OI"{ 6 ̦JvO9ww}q}ɓK;;KUAhVMq}ww9OY1/Iݕ}wwS { :FvÅQt{tQ=.`ýАf s6 66 66 66 6uuyy&#**&&!**#!&}}}}=e* 0* =TN ŽᕊsoOw[sKK[wuso}5Y㗍KU U 0U U f s.**!..!**.yyyy=o{qkk{qo0o{qkk{qo=T3Q၅Oqˡ˻ǟu}5Q[330‰Tq}um7 /Og#q}qO/{ 7?Tu sްڸYA|0>C"J |{ >)&45Q)|pp|ܴYOCTM;e>k4ͫìtyȊw44_MwSkytv_?x`cc}c1@ _N^}afwp}_Ȇ~u{{}{}qia䝓 pN_N]/TM 'oN_eC_oyN{peK 䓌pa鍌3]ׁ{?]c3{*` ዡi5qssw[q@ዡi5qo ssw[qf s-YI77oo:IY"-y{ R@**K@R5 yowwLqxCCYCȐsx. @ yLmm}їkb`zxR2bj|vsz`jbYcE$یc]4wS))SK|rr|~4]ccwc$B a{hZe{oa{B]ww]Ihy4cݳU/gxwddx4f 2 }} sakjshgi{t](+k-+o-煝y/[y/œ ; U_O33_uq; Q=gf a qq wghlvlkk{]Q$&&$k$&o&$_症//f y6 66 66 66 6yy}}ь&#**&&!**#!&soossoos{gykoEGECCGї i qq vhgkwkll(`ak7Aߌ_o7j`aw#>f ,_A!!A?%%?g}}gjj׌5MM33MM5~xx}~yy}}[ UUˍ%wwKK#ߌwKˍ#%w <Mu w o/X o/nwKˍ#%w <_ˍ%wwKK#vGq v}::c+:: E";@>$q/a1wo$>;@E"wa mtnjrʟg'rʟ 6[Wkq6k[840 S S .awϩɅSEQdnnto{YwűlXWkk9ksy'.a瓍9k}Żwoty~swtdQESfBMemo}{7 _G_%G3+s '3+s '3jps9o{yō}{iyכ$U2 n4ҕ- rҝ% ,҉{7 OK {g wY G;ҝ% *ҕ- { ،/ u }cF &ww# Ι + cWWceSSeaa lΗ e! t lmoP e w{{w}}iEeig]Y 셊~y{~vx~o~x|~vw~y{~wvÊ~z{~xu ~z{~ux0~y{~wvJ~y{~ww/~z|~xu ~z|~vx~Œ~z|}vx~ ||z~vwo~z|}ww҇- Zg. _ 噙wg_ҏ% WZg" ķ {{7 Zm& ~/ fg4 ~em' ~em' ΍ \y  Đ~ WqYCCql|mRFpe ho seesumouL cF +lyi0 uqk uTq{E cWWceSSeaa PcUUckWWkggemwaamweyy{}}{YΉ SZw }AK o }Z;, W \Wq*Ō *Q=O5:q{4ѩ3i}Ɍ5:q{4ѩ3i}9ZWw5&q{ ˩y9_nj5&q{ ˩y9_ y OR @fŃk|  ’t S k[HW oqS THb ε !\u~npΫ[Wpͽ „e4wt|4eHT|wb͒ y}}zk{{}[sqyac{xewx uqk myHo?o?ǧOWAmyoHOom o!ǟSWL{  5Xqc@Co!CoOW}myӧ@o!ljWW}myӧCo?Co?OW5:qm@@oWWR_ 5PogF cWWceSSeaa Ali ؙ} h w{{w}}iEeig]Y j}N y{}wo=egiaY {W z}N H$|$U7Éo}rAK z zw p~/ 6i# 6ħیo;Xk [y ~}|$qHq$SUS~}{|(|(ocëH/Hu7ߏ,r`{ǁ袢jHg~{Οt.a~ǕjYlkn|] nkYjf&myXkXXwgXXXwwggXXXwg~/ fg4 )a _ͫ =a󷝾 Pi e! ho( 80QmܧoILƥk LR Ӎc{ cc{)C { -N ss !Iiy{+Zm E+ Asy)oymY { bN s-{I{i+Zm T+ s-)yum { +Zm {v }S G +Z s c ? {v u۰ ikmoNNmqi{f^v+Z ۰ U: kmoNNmqUf^h {t +Zm U {v ?] }#Km]p #}y=]ym}+Z M }-GYp -}{9Yo 寱 ~em' ß ϗ]Oq[ i sw !÷sSUy t g+ wu/ñI_c U g魳 s{Sso_ t e+ w){I]Ù ŷqSegaFFgw} S_wQ镑}h M ~o z \. U wyUQK } É}k{ p{hB t |v L { Í uu-WaOŅ+S +lyi ՛ōuu /YSMuA )a _ ={g; L { +S +lyi ՟ šSYg[A P [ ixypQ{AXvaix[ j śUՃp4)wS L { g$oͽIYd$Y +lyi sw ?Ylø }LU] {/;ep /{{/eiC-? }O  PñcUy}y;Y[Cr||rkYiemwaamweyy{}}{}AG gq qcgiW (կ }Z; Qʁ} my~ Ɲ )Y{ 9]z wy \F@wW/UL8R{rw~zhwU/W5wrq@*:|~h:R8L~z~8f ̄cc[`kNT:LfL8.XN`ªe9LްLL:ET'Bl\TWsȗg'EʰFȶk[cscWUkԗLcVO0ݫ6K ㏎3eK3OU3ew3aɌwҟMs D)/ f wɣMҟ{w/)7D/ ]cwlYE y 3lEՍHYˍ#S #H˽ێDsU]U{{yE V bPx )Íqᔤ\Hjywiq5d;~Twmc/o?Aqǫwy{s$nM5dQ - Zg. ~m' Չ- Vw# s c ? M }-GYp -}{9YoQ }S G Q ?] }#Km]p #}y=]ym} dErŗ{{~zm b_     N!%)-DHNRh{$)-c/O  n}"2EMY]emqx "&\-y  Q Y ^ f    ' , G i n   ! ( 0 7 > F P X ` g n z     " & , 2 8 > D J P V ] e%nszpx~F Dq 2>[{ ,BGah!17CI[mt|#-7?FJSX^iq| &.6>FNV^fnv~).Jp#?HR]#5:C^SY_ekqw}   !!"2"##^#######$$$S$a$k$v$$$%s&&'5't'z'((((()) )x)|**+++, ,,-&---g-.8.// /000b0l0q0001i1w1111112b233F3L3j3}334"4D4V4Z4^45 5555556U6_677v78<899{999:6:L:h:x::;;T;^;;;;>>R>l>???m??@*@1@G@u@@@A:AIAAAAB BB"B+B8BBBBBBBBCC#CQC{CCCDDD#D'DQDDDEE E(EiEEFF1FGFaFFFFGGWGGHHOHdHHHHHHI I7IqIIIIIJ-JXJJJK%KMKYK|KKL LLJL}LLLM M:McMMMMMMNNGNQN\NeNkNNNNOO=OAOKOoOOOOOOOP$PHPZPfPPPPPQQ)QLQjQQQQRR4RXRxRRRRRSSS;SLSiSSSSSSSSSST TT"T(TDTbTTTTTTUU#U/U3UEUUU[UuUzUUUUUUUVVV)VAVRVmVVVVVVVVWW*WAWXWkWzWWWWWWXXXXX/XGXNXeXsXxXXXXXXXXYYYY(YbKbSb[bcbkbsb{bbbbbbbbbbbcccc&c2c>cJcVcbcnczcccccccccccccccd+d/dHdOdTdXdldpddddeeedehenerezeefff/f^ffffffggOgSg^gghh hhhii iiiii.iGiRiZi_idiij*jjjjjjjjjkJkkkkkkkkkklll l ll#l.l3l>lHllllllllllllllllmmm m|n!n'n+n/n3n[nwn|nnnoooop@ppppppppppqqq qqqqq!rSrs0sqsssst8tvttttttttttttttuuuv(vVvvwww&wyw}wwwwwwwwwxx yr \ ’sT w .{3 ׌\y΍.u3 ? gω((oG/U y qs Vmrvk{ V . o $ LT Q3yч}9oy@(M $Gg)9QY$Caŵ ɌՌ @i AYѓ ь$ 1L ĔEm}&J5 \* Ieٓ)Ō|G: E\œƓό$ V }3 {T3 T3aVb}}[Y e [5  qqu IV7f$%g $ ( {e_c _ \ z -顡@ $  |iWfc [5 Z S 3vͪ ،$ H c L?GC&ZFP}e&6k $ ~ C"4v;C9$H 6hkyc\ @k( O V O ɏW qn 牥 /yaD{h W t z   |kXkUk]yu?Bq  ɹYCC]WMM]ӹɛˍ{mS/]yedʏ sccskikkPk#),2""$QōաSy㙏׍}yAS?m;!}{;?}}שmUכw}CG ?73}3y7S=}G E ) w @ m{t]jN_dlW55WAAᕟww Ia͵IaGIaqqyaccyt o! cUUckWWkggD e j x~aDž2o   |XU]uBq uS K!u =y}y ` [WK s}I} u}m[ yyyy{{{{wwu So"PU   S =!kt ’t 3  # dU[ m ߗɟGC"vYcQ u]oHk"KS-Oo,])I* cQ5oE UUYmS*% M]Srs:team ?   }yy}ww{yy{}wu}ƌ@--;@' p y{ &  o{c}Yw}uu ujAJG m & n %PBB=P`XX/`` =SKmo!u =gg> " `牎&& l f z*S wScqog`lՌ 7 gggsuwwY ?;t 6 iw# R?* {y{L  ا"I ՍH Y  ىsqq_ 4oF sw|qYM0e3ŭq]J ).6a is  iswyͫLw] s omfKZE}ɏx1e8imm((ό-FVi(?spugJmV {u)m.aύ}y}OOgaYy[ɍZ ݳɒjtYW㐔 ӯ{}ci qic}UO GC}MJ ^  qZ gyqg ycu ɑwuq5=Tж i] ` ׻\|XV\tD d £ZOI_Q]IWkBŷqS: egaFFgw} S_wQ镑}h M ~o z P 9 {n  /y S k[HHkqqS S k[HHkqqS }#U=#}y/Uqy9=9 T- $ "K٩ǡemk qosuA[['Aaь VG7j(H>g I k[HW n~ I ` D +H( D2 }euw [} Ƀ{qPH 8 2 6 n 2 +Љ & # |sjmfW" [ gs  dz˓C ! )3E8c mrr3Iޓ <0|i\ --}ty{o~* y|+-6i/0<{~8@ 2 ÉosOwǡwu6(K#/;-oweaIVXWUQ["[,-C+19Y{gEudz˽ H Q{ :Q9EWSCCU۷{Xn~ \ak}cMkïѵM#"GUOouymqszgh_}Ϳ}qiY}{k S k[HHkqqS u q   ) K (KJVrm!I (mˍmr!u$ 8] }ZX nb :{* miu$ & u h w{{urmr"uggkcY r $  .W}MSMeyF(i(z?.Xy ˍɑe ~u4{?IMh@OqO"%wlly{]y[{a iy=I> =Ov M ? = _ͫ =a󷝾 L û˹q[}yYKM[aQa{{{sucugcWQYٗr} O[{soaiykeoquyppsoX+ Oesyu}{m}s}Mme]_eU QUӔwy}M1CK1G[myi{uOkEK3'?ꁻ5/륁{UKAQkWQ]opg^[q[Ι)EտѳckaesXycg#pQg "ĢɝNO}c O[LăxPǓ&ZnEYG D  ۣϣI;y{c 9G; Kۓu (oH(: ) j 뫏yk[}٥"8+-%88!~pp||G?hqPe} | ?&&  ŵeOQaaQ e yqqmh}[ 9z uo~ekg[Y{N e  ۨww{tiѥկ  KIkqQc} }x  rDmDCӏh_5 B I k[HW n~ I M 3% < o% ` : j ŷyosm5~x ]emc]S I SxU j dzywoiۛ{u ]ajg^U = 12 = > )O z9O s c C zO s c C ǩ{OgcWsG;a˩Ýgieyy` ǭiW-WYuqiosmu/ۯ]]QUuQuXv=m9s/}EMz "]Y YF_V 34p4144 v q%5MO"3 йq%_ Rxɗ˛|q~va xz}sBhc/X6fMwRxF ww q}uO' M7sџx}|3%Q;Cgaesw-˧ρmw[7,LZ%_gĴܓ_oo)X "3R'1SKEQƽouwG)Co񓑣wU G$uqD [WEs ~s{u}me . zd  Ocٓñ} ?E m"KSYk] yV [k[ =g Qu٩y@..@{}um@+..'@}{ww.+.ѱe[[eeE.3+/.EeѓuYg9TmTù} U: ajeHHj{{qU]Sq W ,V :T q1o {: V ɏW x wypzu Ń SqřΌyw,=mp m! ՊŐ& õ][{WK[}{coiq}wy_{k]]]a9mys]mUS_kW]all{ssyYceg{  /=7EDZŹaYuouup{ [#a /5!adnϓPhpqTa8߉}E sÅ}ű}- ,-txum-,A >-xtlm};ϯ\ong_GŌI$%;FGgϓuQ%p3l hA+ckkhE \Nԣ}wk,`y푎muwg}u}y`)i2N\w e uӚEmomgf 'M ͍?i issogg{uwN͌kgmykU `ox ԝ 8Z ->;Gkaamy{w/˥ρy*XX3 (/BSiſɷ;=dB뱎|{~R8kء 2Z 22ll2}ww} "-bR""Rb-"Ƿ_?O_YOO_׷ǛLo  5Yg|vig i I=A3/YYo 9r  5j g }" a I=A3/YYo 7 &OGommYϏ*8*zk&;yq{qyqŔ* yy{9Qi**x8 |s}s  ɧmY`C_Co]lWfMfMo]Ӷӧɛ}s{uk}gA]ۋ]e~] qwQݕ Pf gukfӣKUdd CGKnH&K>F`\jTKJjºλtD*üovz^#33#AZuxwuzoqѿa;_eyiih nq~tɫ_SSg]UEa"ǧg{ckIWuug{r;;Q:G`j{ w1>\sjy iy}x}r yo{߯OKUͥX } $  a *Z=A;A;Z=ՍH fHig\ @׹! ]@]g\ Hif: V _g 9 li0 $ S?NAÍ Z aKͲ_p zzcv}=\on7  m 8 4׍k 6 (pۍk jv \ w  *rA̤l3 hx:lg] ) @ u0 a " Owq_ظcctf|qvhiSufźٍiX4w7K KM|szyȤ0jɹ ͻyo{sN gqg]S % A8u: L[?仟XmC {y\t| Qpd~)H&  ' vis j jojeǐje v'{ T 6 V 8AI T 6 DW 0 V 8AI 0 DW  <<+,)<<ꘘ~po}~~' <,( 5(,;3iTX`eXW_·^g,.o.+*[ Kxk e DW   2i9Ψn= n~4fbwW jmre 2MSMSM2MÍ >(og"tϩ'tmt'mːtmg"(>oyſSCksw2 ) *ݭeRAw-i;(p\m g_eww n[Z k2] źَ \=i1 te 9E m6"CO_kO9iugr> y6 ~uӺwG׍_c`wP@&%ukƫ]VQubFx}׍m[K}"-#68#awtd wj;¬Œj4^ ̎ dJi3':ŒjTd ύѣ AI3߃keLjmaacnpm[[omS"Iy93emIե˗}y{wowɽy[lj\rUC uméaSSa_eiskaI'/42/oq}iÍyuq}eE[ݽͱwqiisqmsÍuo_=EO!!O}ørH}{# { EW_KdtfsRSe & uf f  2433/42/{yq 'E /G1)ùaSS]_SYYý yooyussuA 8,gU 1냣S ngˍngKS +s>_ѕ=Wk3 kUqe_= 6) q}s{}sus{}}}e[}k}oeuuoQloP yvygs~{][iaWU AlioP r_Dr(qks  p9zOo:* oyq ~i\ l(o:  M m{scwW_{dl~s j }a{ zg &K Vy6Hru X 珇 ʏ SbBJwk #uL|\uMߕ* uzu"7is MrG &3 K;;KO!#Mۑ{{ G]߹ϹS79]QGpihhshhh;u0 _ mK!5"F yu s}uN\ "e~ ׃{qr5 uI[sq{mQ[?wecqUq}}qoSŻ/}{sS lvoWwEU_kqVÃUрmy y{wkyeyhá{wÍ[im]GQ{wkkewUi[ V@ $B Yo|}|p mwwH 'KZZ#ZZK'ʛÐqq; `_lK{JRobwuiuş'ظ ) ɟ2 H52  mwwmT ZZ#ZZO-ُyqyyssu[coqkguiUQmaasz}UdsIF yu su\ ( (kު i[M C_HkH$Y(ʺe{trЌk u p( ś{uw}uuw[musiougY|z_SukaguyS.4ua4.a;aō$DwD$[9wwQ0 3{ u q! ] ]M  , , = ` + } 0' k mi]#M꽹gkc ^{xyc Jr ) $ S=LCÍ X8qe",tͩ m bz)O $ zO 6 }Iim SQ YeYY ׃{qru"e pqu˙cOg s?acqkm aSSQ_YYQŵ ]=&W 9 Zm &n 6H#ǥramZtdzorH4CXfqznynƦ usw}q>  0xi.j jmre  ͩXo8nWGiiOwK./RR 2ջ& A7t; b_g,Z幍$ ^ ũAG{H^ h e{y  O QKQMSMIKIMSMœy~gpְIQp~ѽ Ƀf&yy{&f7Mzzkђ sw!tpswmmY  ɷysmeo` yw4qg*9cstekw^ š]A]G{aHJ "h wmmwwoqyj y{~{w}}8m2*"*R k I k[HW n~ I ER Y gy Eb  ˉaKUwa‹n``tnTwaTtz‹zKahPU~Phˍ~ߋucka uqwq5UO?^ǐsm%QpM66pždm%O7[[-UU{}eMS{e=WSeY_{ ׃|qr.LJ..JL.ysusws wzwz}rýemqwqP ĩ"eûemswoP  w ݌uJ {r]}_eu%yI YeYY [ O{h 4  @*@ L f{% w 1IwLcscwLI[1}qeE m"CO_kO N yj2m*=J1U)+3JŗI*k2Y َ`UyuY׏ e! ͽyoysma Bc::D ÓSks4_qeяO Sag_GIoyiI ɉÉɖ a__x+(VoeiwLMyuq}{өS=3]QM_}u Տu64w8{ao/8T 463 31641 kk o08 |ߌ j }u}.mյu8s8wy46{sak{i  ݝǧM~c :O9 O]S  &yo\ &{_}. m -eWi_yqY "ʙQ3M[LTggiaY d [o$ uZ )-,45 ðys|v~͍#UL%˫ʛO/c a[]ʇO)+YOseq˱_ݑK9) rmhhmr"O8 8c"uP (ooóIA8QV ߓɗ4}' *c *oc qu'  qX t tq @&^\&@@&\^&@LCQ  ;Q V x + poP%e k u} t qU {}{|Q]_Qk ㊃ qt8@8@8>8>w8@8@wu8>8>uJ # $ ԧ( 3U.GC ߌ}s׍}y ĩ"Q  ]o|y| $ uud GZL>uUiasS emwaamweyy{}}{]wuͰ Džs} Y?;UI,dlz A 5׌p }{󻇨}|#rg $$m$o$x{ϛwEG}{{{{{ut|yy3  $  (B( L + %áPUT C]W[Ke_D V37 qS;䆃mw}a {. ?raiSEra$ vv /8 uem{+izw|~qCuyq}guuUǎT o_}R esmyscuS \c 4w7 }uu}yyyy }uu}ussu͌ ǧӑeO 3C{oo{qiiq/ U1tedKHue)m%9 |cmݭ9i =ouP Źū}[ 1Q1Oso]|V?&&ɱ  Ņ   hhI I hh QYӻf ~II~  $ 9i Q_/  ua {{_፣i5kssy_kUL&BA8gl{syPFVw#V}éoeg ˌ@ukK@: 8:++5:85ouq% 5  =&& >0-#I402; 77+,$77" ]kcWY? muS ?bG`C > /wk5=iSѧc -  \kPdodZX~c  rpu}wwV V}gqc]S qqqqweewosV獧$R T/eK]?~u L''++ -t 7X'*$78##dxtQ "Y7iQX7~u_NgLї'yg LgYN'aD&{3 _ eSSm(i uF ww  EeՓ2 m16K/1IO1/Wen`te{y~ ~d .HgmHc}  ѓ d00 0#=5=7# 0w, {ۓYAqGo}c[  W vͽIkQ YeWW/ JryG .#">+ "B0 ] k tt "6"~ i  v` 047C_umc hhE E  4{?s  m1s{( &yy 1 u88++%88ky{ q5&9yym4q5:3ym  %= /=1% K@ re H"ayyyy}sq}k OQgeN YxRR RR- "{q6"o{)eQ_Ƿś4))/42/$bǩѽykc  @l A swg6HrG kDn({<#^9seUe;=C_9?_UG Ows -A+#Cw";ӣ ml[ w* yyy"$""wG9ol-6u6ys/s 0udVVc W_Wn{||3‘+ pɌpkM[kek1 2  â+ or"llmg1 o +1 * yyy!$* }}}ĝyyyy}qs}eimV 8AIq@u@{{eGW ׌E{* uww55* qus!j ǥKP;C t qO M7k# w}k-W }q* {{{5$wAύaiYsY$1^^s?ыcaѢቒwyGJnzbbX§ "q" ,k, y+O񡝋i si_{UE"['5YE!'+00- Ő?MM+ŏ$yCyC{C}e}e}e"$yY{YyYrA-AUgaa{wmwiugT QY݇wi%55xfwhvf\ !ju[q]q[ 4qh}Z  ,,  ӽ= {yqyͭߕɟݹ龀9Scq]yIQ(6GٯW!_wv G;/lo/oˍ_o$ ۽VDx1_caxwmm_wm hh1${C}C{C '^u^u`qY|E7A[rlco[YmA3IMokk1Aa;Yaw k /* Ga_-;X~1gzNݏmq3mHgH h?/>n< qK?SaW]oc o +9{b:o7}a  He$FoFoE݌|o9|vFoFv j`oj Z  6jQRbgFFooѧEOnGG[h HhշİueT _}R u嫍;0UGCuŭϣZk kkvnvkmVhVm(z qS;ICKY?i} * uFݍa ~zW{]fPw?$ዏk Mu}}uwGu%=KK%ys}ewuSUIWǩmgsGLL IgJCUf#ɌϷWO(k=7QgIkl /ygGr Qͽûfmf $YwM Y G; (*s".{ݓC?iGwS 'ǧo4{o  seesumoue^ kOA wOok , ws0AY5ۃʛÏvĉq; y_K{JR{iSۇş'yiukz T   }qo}}# ÷eOQ_aS ač 5 [vklQw={mWoZRvnV j }ş9ـs|muwM j  K o  6}iǁ< ;9}&EG7CIA×ͅmm[keJkJJ]}YяZ { i] w ro! 4 ӳ{}ci si_{U N9 * 6 $$}Aim8 S % o Z { esmycu1# ww i] w # ء SQ; yQ{ mo{eJ  xnnxvppv@Ì xnnxvppvu|u" b9=:g=:((::=%9SKeQEEesb(',mswyUN# 88# N,)Kyy{{ywm(oΣ ]{ {]]_W % J | ñճ}u A}e~a }qu>mwom sɩ sCK[})+=2<󅃉v -U+w$ZgL]UU\}+ &=6;m oa oEc5}}mn l  QfI@; ՙ)}cHgmH})c$ & @fŃ@(\ 曥0`nj*iQݐq{c77-}}aIGYI+~F|e"bdmxy+K`YK[ ۻqSmw}sS=c%'&?فo*HK|$e7ASi/Sq  m ؟"{ӹC[scϧW!565m{ąak  M7kU }Jr ݻգxȧTsUk}c{W{a* yw{Α Z~}_=qaQO{ow)][A yQwamuqoyu_ۍSQ3 ={gkqmcK qc呻mqy3ui$^HO `& ] 2Di ^ e t { $  $ 8 Đ~ WqYCCql| RFp&  & ͅ  om qCaqq o d kn l lN - )  z @F@t oW_ _M d WY[{qc5kwͅ" b  XP\_NKoyiI  \@xA}Keê{dƽøukfhpX|i kUHw{0GY?Ggodxxny` mxswGqvKUa4GRc›usW _kރ 3yemo__moeyy~zz~ {n  /y e9d 7}?QUŅg۽ztnufYy i]Wys)WQI9owokwwqÈwoKrUa[;?ac}ywU?cŁq HB%|\FwXɽoa\ghYmeM;vz!;K-)drgwpzzw]v mo3tĐ7GQ!;E[¹{yuuG1Qa탟p !G1G3!cQQ[aUU[Ż) iyQa}_Iyiu{$y >d j;Œj^ ̐ Ji':Td D [WK q ~kssmsok$ $ ) n a}U  ;D qk(9u~[!sx!Awu}wy{}}siqiq{4_q}uq/CC+ykoQ[qw}km_}gq}_ko_a;U2EMT67MQEggcekcce!O˯mku}mgwD׳uSKCIj{œ Ӹ€zZm k obckjYn y Ԟgm_c}q{a]QwB qmuG C9Q}$ FɉÉɝ a__x(V(m@"MOKye ( " keSGCmYEu{ݍiU3{B @BDFHJLPQRZdnx|jt~ DFLT0cyrlgrek0latn4`BGR `MKD `SRB `JF APPHFATH FAZE FCHP FCRT FIPPHFNAV FNSM FSKS FSLA FTRK Fkernmark mkmk2size8d $4DTdt    *  @  !. "*2:BJRZbjrz#^#$$D%$%n0X>LL\PڜY FT "%*"88(JN)PQ.Va0dy<{RH  !"#$%&'()*+,-./012345LMN_pqs}   +,-NOQmy     !"#$%&'()*+,-./0123456789:;<=>?@ABCIUWXopr   '(/147:<=?AEJMNRTUV[hirsEFGHIJKLMNOPQRSTUVWXYZ[\]^uvw457@ADEFHIKLNPS]`bcegkpxz{|^Ypfppfppfpfpfpfpfpfpfpfpfpfpfpfpfpfpfpppppppfpppfpfpfpfpfpfpfpfpfpfpfpfpfppfppfpfpffpppppp z HvVV*  t* n : VD NNXr @b` 0rlvvV ( n n2< @FV @ V`jtt~ d  d dbH d   *4>HXbr| d & @",6@JT^hr &   * d44 n n n>HXbl| n n P Z"2BLV`jt~ n x @    @ & 0 0 @ P Z d n x r   8    ( 2 B B R r r b l | .   . 8 H X h r * | @  * @ V lZ > ,  T j <d 0 \& $ ?Z t F j `J~p P F <- BB 8n      _"d,@ bB %HpB<zp<|f:F\RRJH8>Jx* 6 &v, p,x " v#fFRHn> 6v n, xT^TJ@( fxxRnd>D:nF|v 2B(P  T [4Jv ^`F<~ t jX|Z6PFJ< .H>  48pt Zp F PdnD`Bl6xb>XN D+ 4Y$@0t 2D  RD hPlD V 4vtdj `V LS  <2,; \2X2 =2z2 p.+2 `;$2:Px2 FG 2^62T,2 "KH2:2 Q2 C2 N22 I2 a222,2,2p2<|2zr 2Rh2^2 T12.Dt2:2042&$2 :2 2 B2 M2 F X2N  >2 < OT2N2 02t2*j2 H2 JR2`:2 0"2 @@2 W* D9 L"( $7 (- '7 6F9: ./0/GWX  *:JT^hxR 2 78H> G " 0 @ > 9 D( $ .+,/7=D FIOO85__3ss4}}56789:  ;  =-->QQ?mm@yyABCEFGHLCMIIWXrrETV^4577@ADFHIKLNNPPSSEE^^bbbbbbbbbbbbbbbbbbbbbbbb",6@ JT^nxt~j62NJPj6,  0:DNXhxJj6j(2<FPZdt~",6j@JT^n x,",6FLV`jt~6fv&6FPZjzV &6FVfv$zR$*,t|DB *^@ND(N :b K0BLx&N8&. SxT~4 ]B: 9P6.n V  t Qpx&Rj, "@ "&B '2& zpZ&J&n 6^ `&P6& \_&2&((` 2FJ@&d&&n:&02&2& &p 1P T RZ  [&&J\&bXN X|x@&~&lt YZ&L<< :FFjp`FR C8t$ D 0D ; JH FD O0 I ^ ? < L B > . ) @t^4 H$Z Av N P G2& W7( $ (E( $0 $4.*0SY 0@P`v C* "f V4 FH G N7 '9 Zj;<!  $*0sQm /IXrEIMSY !DT^nx j *:JZjz 6@n LD: 9b6T 7x Id E Ft R 2 [ U| C  0t Y :X *n H < G( $ F^ "%*"88(JN)PQ.Va0dy<{R     PYvfvvfvvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvvvvvvvfvvvfvfvfvfvfvfvfvfvfvfvfvfvfvvfvvfvfvffvvvvvv " 7 &6&6ffFVf 1 R L [ G P Dd( e(f(g( "Df! bcJd<Je<>f<>g<Jh<Ji<DjJJ0 b<d<ePf<g<h<i<D,#()-87GD*8^3tR[\]d( e(f(g( " bcJd<Je<>f<>g<Jh<Ji<DjJJ0 b<d<ePf<g<h<i<87&DDDDD<<<<<<<DDD^aci{} =(87BDvvvvvv~~~~~~~  ~ 2 &G8 f0    5"   """"""6"7"8"   # * , -   "*,1 2  !"#$%&'()*+,-./3456789:;<=>?@ABCDEFGHIJKLMNOPSTUVWXYZ      !"5 :XYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~< 2 !"/1235 !"#$%&'()*+,-./RSTUVWXYZ).5678;<DEFGHrstuvwxyz{|}~       !#< =^-"9%b(,d(,eP>f(2g(8hPiP>R[G7zD866.66>L n F f n   8 X x 8   #&'+23456<=>?@D !"#$%s  d  d%5 d d    d d d d d d !"#$%&'()*+,-./n d d d d d d+,6 d7 d8 drstuvwxyz{|}~     #<< j= 1  #8 ""%..1 2 r5 """"""""""" "!"""#"$"%"&"'"(")"*"+","-"."/"STUVWXYZn.  r r r r."..*+.,.5 678r"s"t"u"v"w"x"y"z"{"|"}"~""""""""""""""(((*@ r*@ r((     .4! r<V: r*@  "% .1x2d5  !"#$%&'()*+,-./STUVWXYZn xdddd   *+ , 5x678rstuvwxyz{|}~*2d*2d &!d<V,Gd*2$09 G3)3)#T=3zz)z<<b=<hzz+(Jb(d(ePf(,g(2hPiP[Gd(e(f(g(h(i(( (b<d<ePf<g<h<i<QS]^_`lmnot(u(v<2Rnttuvn t u vwntunxtxuxv ] ^ _ ` mno^tdudv(w(ntxuxv(w(ntlulv(Xw(Xl 8m 8n(t<2u<2v<8L0<000 7ntu ]8^8_8`8n(t(>u(>v<w<"Dp.>LLL>6>>LLT &dRr0\$DD.....6D      < t  & L l   l  z p&opqrswxyz{ %*+56;LMPijprstu/13U^_`adrsvXYZ\^ ] ^ _ ` n(t(Hu(Hv<w<   (^P2  0 ` ` ` ` `2  ((<(<((<k ;(   0  p      ]  v v] v J  $ $ $]      ]   ]    ]  h h ( N N ( . 8]vv,]$>>>]>~~~~~]LLLL &&D]<(<(((t<(t< (t <(!)*( b(dPXePXfPXgPXhPXiPXnPX<8;B`ahhGaEGKNpSUWp^_`abcdefghijklmnopqrstuv}~pppppppppp,-./01;>wNNNN0242ww 0w oxt*wxxxx*xf\ XR8>zDz'530,@) *- nnnddnnh &(,&& JVVVPV+ nhhbhHnt^C09\bb 1b<d<ePf<g<h<i<7=(><?(@2 "oDr2w ~셺 څ؅Ȇ؆ &,28>DJPVȆ\چbh ntzĆꆌ؆؆؆    "(.4:@FL RևX ^djpv|쇂⇈쇲-$   ֈ$* 06<B HNTZ`flrxֈ~숄؈숖 ؈ʉʉ؉ &, 28>D܉J PV\b؉hntz 쉆쉌؉Ή쉤쉪‰؉  " (.-4:@F$LRX^dj pv | ؊؊ Ԋ؊$ $*06 <BHNTZ`ʋfʋl rx؋~ ΋؋싴 &,28>DJ(PV\bhntz쌆ꌤ*    #$',/06PYs3~NT`  29<>Q[mssux{  #%'(134  59;<@B!$C))G..H11IEJ1Xarstvyz|  }~,,22==?DFFNORRVVcdffooww}}EEHILLQSUUYY_y  224688;< >?"ef$hj&ll)tu*xx,||-.012345     ## $$''() *+//6M NPY_`rss~     , -/029<>PQQ[a blssux{      !"$$..11EEFFGHIVWWpqr  1KLX akl{|   ,,22==?@AABDFFNORRVVccddffooww}}EE HHIILLQRSSUUYY_v wy22456688;; <<>>??efhjlltuxx||g c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU==="09*0"7%7"""""9@"'G''-%"%'""779"")@"GG7 -""""""0"""9"10'%0)"0-%"9" "'"**"97700.0""10 ""%""09"077070"0@7""""970""0""""""""00"0"""""7"""C0"000"9"""0"%"0109"""""""""""G"" "*""01" oDqft t tttVtt VV V,VV tt؃t ttփzt\D\\x<t\tƃJVVt\؃\ttV ,؃2\tt ⃆Vt⃆V2tڃJVtȂn tVttzJtV؃VP؃hJtt \\2V샆 tV샆\샆ttt2t&t P\ttVDt VtV؃VVVV샆؃⃆htVVV샆؃VV(\ttVt\\샆샆V Vtt\t tt> t tttt >VVttttttt\V \Vt2ttttVttttt샌<2zV tttt(2tt\((V((2V؃2(2ĂV\샆Vփz(2tJ Vt8t؃tJ΃ttʃtƒztʂʂVփzЂxVt܂\2ʃ΂؃V2V(\V\t >t Vt\ tV \ttV샆& VƃJăht΃΃ăhDD؃ƃP΃؂t؃ƒzăh⃆΃Jփzh؃~⃆؃V⃆ăt*J⃆؃؃V؃h؃t΃ t \tăVtVttV2؃Vt\t ⃆V VtƃJtV\t\\,؃2ڃJ(V2tttttt(VtV tt,JtJtJt؃DJ@Vt tt VVt t \tt tVV&D2Vtt t(2샆 \VV tttttt V( (h⃌t⃆؃Jt샌&(2VV Vttt,t t V2t샆V t>tVtt⃌ V8>tVVփzV tDJt⃆VtV샆VtVP⃆V\샆b샆샆⃌t샆thn샆tփz샆샆t؃փz⃆샌⃀؃؃) "-.45uvwxyz{|}34567STUVWXYZ &'*6; !"#$%&'()*+,-./0YZ[\]^_`  $-134;EGKMPTUhpu|~KPVWX]^$%&'()*+,-./019FHKLOXZ[\cgkz{s  ""--..44 55u}37 SZ       &'**66;;  &Y`   $$--1134;;EEGGKKMMPPTUhhppuu||~KKPPVVWW XX]]^^ $+,199FFHHKLOOXXZ\cc gg kkz{      g c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU===+   &! 'L:RJ H%4*1)6G-"9@07D6x@X@F LRj : < (<(((|PP : 2 ( (*P R ((<<(( 2  R FF ::p (F(((F((:  j  <@     |tt8LVR  F F((dF("  <<<PP2FR<2**F((V(`:P<P(:. j4  :( @XFjLR ^X<^d<j p|<<PPv<t|||<|(<     r  < !%&123QRSTUVWXt8Rnopqrt%(+2345<D   "%&*+./0569:<>HJQSWXZ[`abegjklmnqvz{)*+,-/13FGO[z{|}~ !"#@J]^_`abdnpqsvwy}~/2678:;<?CDEGMNPQR^? !!(%%&&11922332QStt? 883RR(nnortt3  9&%$$%&&%%&(($++%24;559<<%DD(3. 0"=  0" ""%%&&0**++.../0 56"99:::*<<>>:HH4JJ-QQ SS WXZZ*[[4`a bb,ee-gg jk*ll+mm:nn+qq4vv,z{-.= +,5'7878   ))5*+',,5--'// 11 33 FFGGOO![[z|}! #@@<JJ<]]/^_``aabbddnn1pp#qq>ssvvwwyy}~1#1/#/>//226677886::;<??6CCDE)GG)MMNN)PPQQ6RR^^(872g c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU===/<C6& .91(-+$! R GL )*2@7%' 0"J oDo|p   &,28(>D(JP V\bhntz        ΀"΀(.4:@րFLRX؀^jd jpv*|؀؀~쀦쀬怸怾2؀΀Ā΀  ؁$ *06<BHNTZ(`fl rx~䁢ꁴ ȁ 6‚2 &(,28>DJPV‚\bhntz(((( "(.4:@؃FLRX^djăpv|샔؃؃ڃ؃؃ڃ؃؃؃ ؄$*06<؄BH؄NڄT؄Z`flrx؄~؄섨  &,28>DJPV\bhntz؅؅؅؅؅؅؅ ؅؅؅؅؆  " (.4:@FLRX^djpv|( 솬솸    $*06 < BHNʇTʇZ`؇flćr·x~쇄‡쇐؇؇ć Ĉ&,؈28>DJPV\؈bhn؈t؈zΈ숌숒( 숶  "(.4:@FLRΉX^؉dΉjpĉv|쉈 jĉ4 7LtyJNTZACDGNSUYr0     77 LLttyy  NNTTZZ  AACCDDGGNNSSUUYYrrg c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU==="""")""""""""""0"""0'0-70*90BR"700"1P0)00@"7"--"070@"90R""""1P"""""0$00""7.)!*)$)))"77"*6'H007"""9""GJ"""""""""""""""7"""""7"""""770""10"77"0"*"""77*00"1"7"7"""0"""$+G7"" "*"@@@@"77R70"""""00"0"""0""""7""""""""""""""%""*""""""0"""""77"0""""00" """"0"*""""""""-907700GR""GR00@1PoDoTp ~~ ~~~~~~~~~~<~~~~~~~~t~ ~~~~ ~~~~ ~~~~~ ~~  ~~~~~~~~~~~~     ~~~            ~ ~(~< < ~~< ((~(~~~~ ~~ ~~~~~<< ~~~((< ~(~~<  <  ~(       ~   ~~~ ~~~   ~   ~~~   ~  ~~~~ ~  ~~~~(~~~~ ~ ~ ~ ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~(~(~~ ~~~~~~ ~ ~~~~~~~~~~~~ ~~~~~~  ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~  ~~  ~ ~   ~ ~~~  ~  ~ ~ ~~     '7BIPQRTVWmo       ''77BBIIPPQQRRTTVVWWoo  g c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU===_[W' 91)JG@LR70"Dޔ@ @ @@FF@ F@ 4 @F @ FFF: F F@F@@ 4 @FF 4F @FF@ F @F@FFFFF:F@""FFFFF@F4F@:F@"4"FF""@"F"F""""(@(@(@@"(@P@"@""P@F@F@(FF@@@FFFF"F@F"FF4FFF" FF"  FF 44F(@(@@:@@::FF FF@::":4@F@F4FFFF@F@F@F@F@F@F<<:(@  FF(@F@x.F@FF"@""F@F4@4F@4F(@(@(@@F4@:@@:::FFFFF@FF@FF F@F@FFFFFFF4:44. 4.@F4@. :...@.F4F@F"F"@@F@"" F@ F@"" @"@4 @4" F @" F F"" F"F(@ F(@" F"  """ FF" FF4F@@@@@FFP.(:4(:F4(:F(:4"FF"FFFF FFFF<. (@4F:@@FFF@@@F@@F@F4(@".:..:.@@."P"..:@@@ F F:"@ F F("((@@<.@(:4FFF2: 4(@ 4FFF<@<.@4@4FFFF2:4(@4:@F@=>8IY\irs!\EM?"==>>?$>'1524-7 :!   88 II6YY\\iirr8ss9;/.(&3!! \\EEMM%0#),*+=<g c%&j:(/ !!""*##$$%%1&'() **++ ,,-- ..$//00 11Y22@33=44#55"6MNPKQQNTX^^Nu}c%&j:(/N    /00l123PRRSZ*[`aalblmm nn1oqrr sxzz{  $ Y@#" 1   ss1#       x=   1 "#%X&& (( ))=**$+,1..11 24Z55Y68"::;<==>>DHIVXqr x8g8gE}e9FE. !Q7oWQ !78  9!F%&E'*.11829;<CCeDE.LX Y`!aklm7nnoo7p{|W o7A4O_,,2C]a[2  O      2,_2C,!!4""O##$$2%%&&,''))a**[+,--4..A//{00112234,56C77<889: ;;<<==+>>z?A BBqCD EEFF GGHHIIHJJJKKLLvMM NNmOP QQHRS TTUU VVWXYYpZZ [[\\]^w__``qaa bbpcd eeJff gghhiiTjj kkll+mmznn ooHpp qqrsTttvuumww+yz<{{||}} ~J4A]A424<+ rr + H+ ++>n>RIyUVUV>tutu??666!!##))R**I++R,-I006226446<<==EEFFGGHJKKLLMMNNdORSSTTUUVVWW XX'YYZZk[[;\\]])^^0_vwyL{|}d 'k #;$+),103356778:;;<=>>??@@MABCCDDEEFFGGhHIJJMKLMMNNhOPQQRRSSiTTUU~VVWWfXXYYiZZM[[\\f]]B^` aabb cc5ddPeg hh`ij kk-lm nn-oo3ppDqq^rrbss tt\uv ww3xy zzP{{ ||}~ 3 - ` 3 D - 5P 3 -b\ 5B|  -D5 B^ B 5 35//001355G6788G9<==>>G??@@CCDESGGGILMMNNSPQRR^^VU===69)J%+'$@G C-*120 7 " ~ DFLTcyrlgreklatn4/ !"#$%&*,-./0123456789|BGR MKD |SRB 0 !"#$%&),-./01234567890 !"#$%&),-./01234567890 !"#$%&),-./01234567890  !"#$%&+,-./0123456789F APPHFATH AZE CHP xCRT IPPHFNAV NSM SKS SLA xTRK 0 !"#$%&',-./01234567890 !"#$%&',-./01234567890 !"#$%&',-./0123456789/ !"#$%&,-./0123456789/ !"#$%&(,-./0123456789:aalt^c2scfcaserccmp~cv01cv02cv03cv04cv05cv06cv07cv08&cv09:cv10Ncv11bcv12vcv13cv14cv15cv16cv17cv18cv19dnomfracliga&locl,locl2locl:loclFloclLloclTlocl\numrbonumhordnnpnumtsaltzsinfjsmcpsmcpsmcpsmcpsmcpss01ss02ss03ss04ss05(ss066ss07@ss08Lss09Vss10`subsjsupsptitl|zero@AB =>1?   !"#$%&'()* + , - . /0123879:I((&5/,65('5-47 !"%#$&'()*+,-./0123HDA CDA GA DEFGAEFA  !"#$)*+/0") #*/ $+0%&.'1213J f6#`&&&&''J'`'t'(B(|)-782828L9V9j99:<:V:;;H<<6 >6>t>>>?f???@@DDDE GdGHII\_`abcdefghijklmnopqrstwxyz{|}~      !"#$%&'()*+,-./01234679:;<>?wxyz{|}~M      !"#$%&'()*+,-./0123567:<=>?78rstuvwxyz{|}~p@ABCDEFGIJKLMNOPQRSTUVW@DFHNSYWCDEFIJKLMNOPQRVWQ@DFHXNSYWXY@@@@@@@@@@@@DDDDDDDDFFFFFFFFFFHHHHHHHHHHNNNNNNNNPSSSSSSSSWWWWWWWWWWZZZZZZZZZ[[[[[[[[[\\\\\\\\\@@@@@@@@@@@@@DDDDDDDDFFFFFFFFFFFHHHHHHHHHHHHHXXXNNNNNNNNPPSSSSSSSSSSSSSYYYWWWWWWWWWWWZZZZZZZZZZZZ[[[[[[[[[[[[\\\\\\\\\\\\]^_`bdefijklmnoprstuvwxyz{|}~bijkmnprtwxyz|}~^_`adeflosuv{SqCQR/[    "$&(*:<LQTWY[]_acegikmruwy{x6KNor9 L -=@MOR[]_q{>D[rtuz{  |}==~Wnpq ""%,.6<<CEGHJJLLNNQTVY[_abekmm pv z)ABEFGQ[\f-.kBBmn55~::PPZZ    !!##%%''))99;;KKPPSSVVXXZZ\\^^``bbddffhhjjllqqttvvxxzz &,2<BHNTZbhpv| &,28@HPX`hpx $*06<BHNTZ`flrx~ &,2:@FLT\bhnv|*<N`r EFGHIJKLIMNOP Q!R"S#T$U%V&W'X(Y)Z*[+\,]-^.XrE/F0G1H2I3J4K5L6M7N8O9P:Q;R<S=T>U?V@WAXBYCZD[E\F]G^HMuqJKLMNOPQRSTUW5V=Ys_Zt`[ua\vb]wc^xd_ye`zfa{gb|hc}id~jekflgmhniojpkqlrmsnt,oupvIJOK9q;4LpIHNX@ABGH0S"TUPHOHacghqIN]^_`acdefghloqsuv{cg      TUV/Pop=5LL4pp56  BC,D>?\NN^SZ_^^gszhpqrstoouvwx{}!!#$--7;=BFFIIKKMMOPUUZZ``cdllnowy//nnB/0123456789:;<=>?@ABCDEFGHIJKL5>?NNSTUVX(  . . X)    "$&:<LQTWY[]_acegikmoruwy{)  !#%9;KPSVXZ\^`bdfhjlnqtvxz "(.4:@HNTZbjrz "(.4:@HPX`hpv| $*06>DJPV\bhntz "(.4:@HNTZ`hntz $*06<BHNTZ`flrx~    " * 2 : B J R Z ` f l r x ~    & , 2 8 > D J P V \ b h n t z     $ * 0 6 < B H N T Z ` f l t |     $ * 0 6 < B H N T Z ` f l r x ~     " ( . 4 : @ F L R X ^ d j p v | +6KOPR]`o$rr4t|5~>DKNXtuz*./1<>MPPR`bknq sx{!238HO_dw  |}33~XX^^~~  4 4 4NN C:4C: 4  4 7     4 : @ C            4  7 4 C   7 4 4  C4 74C  4 4  4744 C:74:74C   4 444 4CLp 444-- C94C9          4       4  !"""""8"" "###4#C#9#@mmmmm mmm$4&7&4&C'''7'4'4 'C(((4)))))7))4)C****** ***4******4** 4+--7---4-4 -C.....9.7..4///9/7/4/C/000000 00000 00004041422224444444445555545C+N<mEd @6?AE GJOPRRUZ`gin$rr*tx+z|0~35<>?ACGHQVW[_cdftuy $&)./1149>EGLPPRVX\bjnnst{|~ T@ST[\]hy23:;<FW]^_`kopquvx} b@ eC>h  &\b ;H+,/7=C FIOO!  !%'()*-.9;EJKMNP2m$%l  6V`D6na $<qn* ;eCgd.  $$**00:;deBCfg   $*0 :dBf: T^"(.4X^bV`\ Zd hflj$*06<qvnt sKsNpxz &,}|~K~}| &,K  '()*)Xv",J\z$.8BLV`jt~;;L;;;p;|;;; ;;;;;;;;+;8;;N; W9Z;;l;'t;;;;;;;;;;;;;;;;;9)  "$'*/07Lap +?Nclm 2D4>j|HZ 8 z .>FNV^fnv~ 7}3(5|9~62*487O}3O(5O|9O~6O2O*4O8O}(|~11O* $*06<}(|*:BJRZbjrz@}<(>|B~?;*=A@O}<O(>O|BO~?O;O*=OAO}(| ~::O* "(.4:@FLRX^d } (|  * $*06<}(|*(  &,28>D!#}("|$~% & :BJRZbjrzI}E(G|K~HD*FJIO}EO(GO|KO~HODO*FOJO*.}((,|0~)CCO-+/'4<DLT\dlt|OO}O(O|O~OOO*OOOKOS}M(Q|U~VNORL*PTW XK$*06<\`}Z(^|[_Y*]08@HPX`hpxOO}O(O|O~OOO*OOOKdh}b(f|j~cOga*eikK$*06<BHNTZ`flrx~os}m(q|u~vzqyn{snrl*ptw xK$*06<}}(|~|* (*$*06<BHNTZ`flrx~}(|~qns* K08@HPX`hpxOO}O(O|O~OOO*OOOK}(|~O*K$*06<7}3(5|9~62*48$*06<@}<(>|B~?;*=A$*06<I}E(G|K~HD*FJ $*06<BHNT}(|~*K $*06<BHNT}(|~*K $*06<BHNT}(|~*K1:C 2R>>JJ]^ ^l  !!##&'6 K6z (    "$&:<LQWY[]_acegikmoruwy{$F 4!#&'/+S"IJKLMNOPQRSTUV  INPO >,28>DJPV\b IIIIIIIIII INBXYZ[\]^_`abcdefghijklmnopqP,77yy// Q""SZ55  R 'stuvwxyz:=rstuvwxyz{|}~prstuvwxyz{|}~p// ,Xq775yy679//;PP<Lp+NoL 0" =AUf8  9:;>?@FIMOPZd;BK`(!#$-=Aclnowx, (*p')n  9:>?@FIMOPdL     "  R .P; ;oqn<$ ^V(    "$&:<LQWY[]_acegikmoruwy{(  !#%9;KPVXZ\^`bdfhjlnqtvxzBEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuwxyz{|}~      !"#$%&'()*+,-./012345679:;<=>?8@ABCDEFGHIJKLMNOPQRSTUVW@DFHXNSYW@@@@@@@@@@@@DDDDDDDDFFFFFFFFFFHHHHHHHHHHHHNNNNNNNNPSSSSSSSSWWWWWWWWWWZZZZZZZZZ[[[[[[[[[\\\\\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 6LNp1rTWWK6y2 -.$EFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~M      !"#$%&'()*+,-./01235679:;<=>?47 5qsw  ==N$@ABCDEFGHIJKLMNOPQRSTUVWQ@DFHXNSYWXYy@@@@@@@@@@@@@DDDDDDDDFFFFFFFFFFFHHHHHHHHHHHHHXXXNNNNNNNNPPSSSSSSSSSSSSSYYYWWWWWWWWWWWZZZZZZZZZZZZ[[[[[[[[[[[[\\\\\\\\\\\\Li]^_`abcdefghijklmnopqrstuvwxyz{|}~^_`adeflosuvcg{7KcZ$H!/D!G/!2}&f@&f@@@@Y  !"#$&'(*,-./0123468:;<>@ABDFGHIJKLNOPRTUVWXZ[\^_`abdfhjklnprstvxz{|}~.  "$(**,.00234 4 6!7"8#:$<%>(B)D,I0N0P2P2T4V5X7\8^;b>hAlEsIzL~>D  *4>DJPVdjNPSZbd+-:+6/-D ?RL-)-.Q.*&N$T R6++++++++++++++++++++++++""" J- ::::::::::::A+666//////B /666$-DDDDDDD :$$$$$$?))))LLLLLLLL3.L+:""""""""""""""""""""""? L--------))))))-----------.QQQQ.Q....***&&&&&&&&NNNNNNN$$$$$$$$VBFFFFFFF%%%%%%%%%%%%%%%%%%%%%%%%TXXXXRRRRRRRR666666&D1" -%6)T&)) R.LR.R***&&BXNNNNF$FF TXRN66N9*+!3QQQQQQQQQQQQQQ%-Q----0-L+O :6?6:-L?RQ1  :$L56LA<OX/L:L)/ XGG5)X5"<< G<    )+)+++  %(%(  &)&)  1313:: )+$'"$$56LL24,. ,%8989,,&&7878##/-<=:;))5555555555555""""""""<<<<<<<<<<<<<<<< GGGGGGGGGGG555555555555GGGGGGGGGGGGO%9NNNNNS<FFS88+/F6)6 ->/R)/8ISA5" ::+  6>G"<<'*R:/:F+">>"O QB/RF >9R)&9 $--.G-)QR%TOI9 S)." RR/F6??:<6<<'FBQTXRNOG5$6%%&*%*F$%N9N...........A?&.?.8&$8A..........)?.).)'*)..........NNNN-NN::N+NN++N+NNN.N>>>>>>>>>>>>>>$??????''<VV. II???????? ;GGG  10':/>41&:,$ET111111111111111111111111+++&&&&&-$$$$$$$$$$$$$$$$$0$'''''''''))))))::::::::::::?/>>>444444@A4:::''''''''''''''''''.'''''''1:::::::,,,,,,,,A$$$$$$$$$$$$$$$$$$$$$$$******$E2222PPPPPPPP84 1$:'$1U$)':>C:@')1$PJTW>:P 1$@$ ?/:)')1$BHT.6M%I$$%,::/*?B#'K%G36TD6: 1+$ ''BB@ ?CK:H?G3 GA+7A+.2!-NN::N+NN ?????? .... .... .... .... %$'")%#(/=7  . 3 /)37?3 6> ......L....1S*9 1*1**H1*11***1*..................../3N+NLX.+-89 5?.N>><1.1"A..66** stroxhgt &f@&f@@ freetype-py-2.5.1/examples/skia_ot_svg_module.py0000664000175000017500000001446414664131406022253 0ustar georgeskgeorgesk# skia_ot_svg_module # Copyright 2023 Hin-Tak Leung # Typical usage: # # from freetype import get_handle, FT_Property_Set # from skia_ot_svg_module import hooks # ... # library = get_handle() # FT_Property_Set( library, b"ot-svg", b"svg-hooks", byref(hooks) ) # # After these lines (or equivalent), COLOR OT-SVG font support is enabled. # You just use freetype-py as usual. Color bitmaps are returned for OT-SVG # fonts in FT_Load_Char()/FT_Load_Glyph(). from freetype import FT_SVG_Document, FT_Err_Ok, SVG_RendererHooks, \ SVG_Lib_Init_Func, SVG_Lib_Free_Func, SVG_Lib_Render_Func, \ SVG_Lib_Preset_Slot_Func, SizeMetrics, FT_UShort, FT_PIXEL_MODE_BGRA, \ FT_GLYPH_FORMAT_BITMAP import ctypes from ctypes import py_object, pythonapi, cast, c_char_p import skia from skia import Size, ImageInfo, ColorType, AlphaType, Canvas, \ PictureRecorder, Rect, ScalarNegativeInfinity, ScalarInfinity, RTreeFactory from packaging import version assert(version.parse(skia.__version__) > version.parse("116.0b2")), "Needs Skia-Python 116.0b2+" pythonapi.PyMemoryView_FromMemory.restype = py_object # include/private/base/SkFixed.h def SkFixedToFloat(x): return ((x) * 1.52587890625e-5) from math import ceil, floor _state = None def svg_init(ctx): global _state _state = {} ctx.contents.value = _state return FT_Err_Ok def svg_free(ctx): global _state _state = None # "None" is strictly speaking a special pyobject, # this line does not do what it should, i.e. setting the # pointer to NULL. ctx.contents = None return # void def svg_render(slot, ctx): state = ctx.contents.value dstBitmap = skia.Bitmap() dstBitmap.setInfo(ImageInfo.Make(slot.contents.bitmap.width, slot.contents.bitmap.rows, ColorType.kBGRA_8888_ColorType, AlphaType.kPremul_AlphaType), slot.contents.bitmap.pitch) dstBitmap.setPixels(pythonapi.PyMemoryView_FromMemory(cast(slot.contents.bitmap.buffer, c_char_p), slot.contents.bitmap.rows * slot.contents.bitmap.pitch, 0x200), # Read-Write ) canvas = Canvas(dstBitmap) canvas.clear(skia.ColorTRANSPARENT) canvas.translate( -state['x'], -state['y'] ) canvas.drawPicture( state['picture'] ) slot.contents.bitmap.pixel_mode = FT_PIXEL_MODE_BGRA slot.contents.bitmap.num_grays = 256 slot.contents.format = FT_GLYPH_FORMAT_BITMAP state['picture'] = None return FT_Err_Ok def svg_preset_slot(slot, cached, ctx): state = ctx.contents.value document = ctypes.cast(slot.contents.other, FT_SVG_Document) metrics = SizeMetrics(document.contents.metrics) units_per_EM = FT_UShort(document.contents.units_per_EM) end_glyph_id = FT_UShort(document.contents.end_glyph_id) start_glyph_id = FT_UShort(document.contents.start_glyph_id) doc = ctypes.string_at(document.contents.svg_document, # not terminated size=document.contents.svg_document_length) data = skia.Data(doc) svgmem = skia.MemoryStream(data) svg = skia.SVGDOM.MakeFromStream(svgmem) if (svg.containerSize().isEmpty()): size = Size.Make(units_per_EM.value, units_per_EM.value) svg.setContainerSize(size) recorder = PictureRecorder() infiniteRect = Rect.MakeLTRB(ScalarNegativeInfinity, ScalarNegativeInfinity, ScalarInfinity, ScalarInfinity) bboxh = RTreeFactory()() recordingCanvas = recorder.beginRecording(infiniteRect, bboxh) ftMatrix = document.contents.transform ftOffset = document.contents.delta m = skia.Matrix() m.setAll( SkFixedToFloat(ftMatrix.xx), -SkFixedToFloat(ftMatrix.xy), SkFixedToFloat(ftOffset.x), -SkFixedToFloat(ftMatrix.yx), SkFixedToFloat(ftMatrix.yy), -SkFixedToFloat(ftOffset.y), 0 , 0 , 1 ) m.postScale(SkFixedToFloat(document.contents.metrics.x_scale) / 64.0, SkFixedToFloat(document.contents.metrics.y_scale) / 64.0) recordingCanvas.concat(m) if ( start_glyph_id.value < end_glyph_id.value ): id = "glyph%u" % ( slot.contents.glyph_index ) svg.renderNode(recordingCanvas, id) else: svg.render(recordingCanvas) state['picture'] = recorder.finishRecordingAsPicture() bounds = state['picture'].cullRect() width = ceil(bounds.right()) - floor(bounds.left()) height = ceil(bounds.bottom()) - floor(bounds.top()) x = floor(bounds.left()) y = floor(bounds.top()) state['x'] = x state['y'] = y slot.contents.bitmap_left = int(state['x']) # float to int conversion slot.contents.bitmap_top = int(-state['y']) slot.contents.bitmap.rows = ceil( height ) # float to int slot.contents.bitmap.width = ceil( width ) slot.contents.bitmap.pitch = slot.contents.bitmap.width * 4 slot.contents.bitmap.pixel_mode = FT_PIXEL_MODE_BGRA metrics_width = width metrics_height = height horiBearingX = state['x'] horiBearingY = -state['y'] vertBearingX = slot.contents.metrics.horiBearingX / 64.0 - slot.contents.metrics.horiAdvance / 64.0 / 2 vertBearingY = ( slot.contents.metrics.vertAdvance / 64.0 - slot.contents.metrics.height / 64.0 ) / 2 slot.contents.metrics.width = int(round( width * 64 )) slot.contents.metrics.height = int(round( height * 64 )) slot.contents.metrics.horiBearingX = int( horiBearingX * 64 ) slot.contents.metrics.horiBearingY = int( horiBearingY * 64 ) slot.contents.metrics.vertBearingX = int( vertBearingX * 64 ) slot.contents.metrics.vertBearingY = int( vertBearingY * 64 ) if ( slot.contents.metrics.vertAdvance == 0 ): slot.contents.metrics.vertAdvance = int( height * 1.2 * 64 ) if ( cached == False ): state['picture'] = None state['x'] = 0 state['y'] = 0 return FT_Err_Ok hooks = SVG_RendererHooks(svg_init=SVG_Lib_Init_Func(svg_init), svg_free=SVG_Lib_Free_Func(svg_free), svg_render=SVG_Lib_Render_Func(svg_render), svg_preset_slot=SVG_Lib_Preset_Slot_Func(svg_preset_slot)) freetype-py-2.5.1/examples/glyph-monochrome.py0000664000175000017500000000235714664131406021663 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph bitmap monochrome rendring ''' from freetype import * def bits(x): data = [] for i in range(8): data.insert(0, int((x & 1) == 1)) x = x >> 1 return data if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_MONO ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch data = [] for i in range(bitmap.rows): row = [] for j in range(bitmap.pitch): row.extend(bits(bitmap.buffer[i*bitmap.pitch+j])) data.extend(row[:bitmap.width]) Z = numpy.array(data).reshape(bitmap.rows, bitmap.width) plt.imshow(Z, interpolation='nearest', cmap=plt.cm.gray, origin='lower') plt.show() freetype-py-2.5.1/examples/ot-svg-example-skia.py0000775000175000017500000000514214664131406022167 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # # OT-SVG example, alternative version based on Skia # # Copyright 2023 Hin-Tak Leung # Distributed under the terms of the new BSD license. # See also the other one, the rsvg-based OT-SVG example. # "ot-svg-draw-skia.py" was written based on skia m87. # This example requires m117, and also accelerated GL integration; # should work on any OT-SVG font, unlike "ot-svg-draw-skia.py". if __name__ == '__main__': import sys from ctypes import byref, pythonapi, cast, c_char_p from freetype import Face, get_handle, FT_Property_Set, FT_LOAD_COLOR, FT_LOAD_RENDER from OpenGL import GL import glfw import skia from skia import ImageInfo, ColorType, AlphaType from skia_ot_svg_module import hooks from skia_glfw_module import glfw_window, skia_surface execname = sys.argv[0] if len(sys.argv) < 2: print("Example usage: %s TrajanColor-Concept.otf" % execname) exit(1) face = Face(sys.argv[1]) face.set_char_size( 160*64 ) library = get_handle() FT_Property_Set( library, b"ot-svg", b"svg-hooks", byref(hooks) ) # python 3 only syntax face.load_char('A', FT_LOAD_COLOR | FT_LOAD_RENDER ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows if ( face.glyph.bitmap.pitch != width * 4 ): raise RuntimeError('pitch != width * 4 for color bitmap: Please report this.') WIDTH, HEIGHT = 2*width, rows glyphBitmap = skia.Bitmap() glyphBitmap.setInfo(ImageInfo.Make(bitmap.width, bitmap.rows, ColorType.kBGRA_8888_ColorType, AlphaType.kPremul_AlphaType), bitmap.pitch) glyphBitmap.setPixels(pythonapi.PyMemoryView_FromMemory(cast(bitmap._FT_Bitmap.buffer, c_char_p), bitmap.rows * bitmap.pitch, 0x200), # Read-Write ) with glfw_window(WIDTH, HEIGHT) as window: GL.glClear(GL.GL_COLOR_BUFFER_BIT) with skia_surface(window) as surface: with surface as canvas: canvas.drawBitmap(glyphBitmap, 0, 0) canvas.drawBitmap(glyphBitmap, width/2, 0) canvas.drawBitmap(glyphBitmap, width, 0) surface.flushAndSubmit() glfw.swap_buffers(window) while (glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and not glfw.window_should_close(window)): glfw.wait_events() freetype-py-2.5.1/examples/glyph-alpha.py0000664000175000017500000000173314664131406020577 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph bitmap monochrome rendering ''' from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S', FT_LOAD_RENDER ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = numpy.array(data,dtype=numpy.ubyte).reshape(rows, width) plt.imshow(Z, interpolation='nearest', cmap=plt.cm.gray, origin='lower') plt.show() freetype-py-2.5.1/examples/ascii.py0000664000175000017500000001022314664131406017453 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- import numpy import os, sys from freetype import * class ColorMap: ''' A colormap is used to map scalar values to colors. It is build by adding couples of (value,color) where value must be between 0 and 1. The 'scale' method allows to specify the range of the colormap and the 'color' method then returns a color for any value. ''' def __init__ (self, colors): self.colors = colors self.min = 0 self.max = 1 def scale (self, min, max): self.min, self.max = min,max def color (self, value): ''' Return the color corresponding to value. ''' if not len(self.colors): return (0,0,0) elif len(self.colors) == 1: return self.colors[0][1] elif value < self.min: return self.colors[0][1] elif value > self.max: return self.colors[-1][1] value = (value-self.min)/(self.max-self.min) sup_color = self.colors[0] inf_color = self.colors[-1] for i in range (len(self.colors)-1): if value < self.colors[i+1][0]: inf_color = self.colors[i] sup_color = self.colors[i+1] break r = (value-inf_color[0]) / (sup_color[0] - inf_color[0]) if r < 0: r = -r color = [sup_color[1][0]*r + inf_color[1][0]*(1-r), sup_color[1][1]*r + inf_color[1][1]*(1-r), sup_color[1][2]*r + inf_color[1][2]*(1-r)] return color # Some colormaps CM_IceAndFire = ColorMap([(0.00, (0.0, 0.0, 1.0)), (0.25, (0.0, 0.5, 1.0)), (0.50, (1.0, 1.0, 1.0)), (0.75, (1.0, 1.0, 0.0)), (1.00, (1.0, 0.0, 0.0))]) CM_Ice = ColorMap([(0.00, (0.0, 0.0, 1.0)), (0.50, (0.5, 0.5, 1.0)), (1.00, (1.0, 1.0, 1.0))]) CM_Fire = ColorMap([(0.00, (1.0, 1.0, 1.0)), (0.50, (1.0, 1.0, 0.0)), (1.00, (1.0, 0.0, 0.0))]) CM_Hot = ColorMap([(0.00, (0.0, 0.0, 0.0)), (0.33, (1.0, 0.0, 0.0)), (0.66, (1.0, 1.0, 0.0)), (1.00, (1.0, 1.0, 1.0))]) CM_Grey = ColorMap([(0.00, (0.0, 0.0, 0.0)), (1.00, (1.0, 1.0, 1.0))]) def imshow (Z, vmin=None, vmax=None, cmap=CM_Hot, show_cmap=False): ''' Show a 2D numpy array using terminal colors ''' if len(Z.shape) != 2: print ("Cannot display non 2D array") return vmin = vmin or Z.min() vmax = vmax or Z.max() cmap.scale (vmin, vmax) # Build initialization string that setup terminal colors init = '' for i in range(240): v = cmap.min + (i/240.0)* (cmap.max - cmap.min) r,g,b = cmap.color (v) init += "\x1b]4;%d;rgb:%02x/%02x/%02x\x1b\\" % (16+i, int(r*255),int(g*255),int(b*255)) # Build array data string data = '' for i in range(Z.shape[0]): for j in range(Z.shape[1]): c = 16 + int( ((Z[Z.shape[0]-i-1,j]-cmap.min) / (cmap.max-cmap.min))*239) if (c < 16): c=16 elif (c > 255): c=255 data += "\x1b[48;5;%dm " % c u = cmap.max - (i/float(Z.shape[0]-1)) * ((cmap.max-cmap.min)) if show_cmap: data += "\x1b[0m " data += "\x1b[48;5;%dm " % (16 + (1-i/float(Z.shape[0]))*239) data += "\x1b[0m %+.2f" % u data += "\x1b[0m\n" print (init+data[:-1]+'\x1b[0m') if __name__ == '__main__': face = Face('./Vera.ttf') face.set_char_size( 32*64 ) face.load_glyph(face.get_char_index('S')) slot = face.glyph bitmap = slot.bitmap data, rows, width = bitmap.buffer, bitmap.rows, bitmap.width Z = numpy.array(data,dtype=float).reshape(rows,width) Z = Z[::-1,:] imshow (Z, cmap=CM_Grey) freetype-py-2.5.1/examples/opengl.py0000664000175000017500000001051014664131406017646 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- import numpy from freetype import * import OpenGL.GL as gl import OpenGL.GLUT as glut base, texid = 0, 0 text = '''Hello World !''' def on_display( ): global texid gl.glClearColor(1,1,1,1) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glBindTexture( gl.GL_TEXTURE_2D, texid ) gl.glColor(0,0,0,1) gl.glPushMatrix( ) gl.glTranslate( 10, 100, 0 ) gl.glPushMatrix( ) gl.glListBase( base+1 ) gl.glCallLists( [ord(c) for c in text] ) gl.glPopMatrix( ) gl.glPopMatrix( ) glut.glutSwapBuffers( ) def on_reshape( width, height ): gl.glViewport( 0, 0, width, height ) gl.glMatrixMode( gl.GL_PROJECTION ) gl.glLoadIdentity( ) gl.glOrtho( 0, width, 0, height, -1, 1 ) gl.glMatrixMode( gl.GL_MODELVIEW ) gl.glLoadIdentity( ) def on_keyboard( key, x, y ): if key == '\033': sys.exit( ) def makefont(filename, size): global texid # Load font and check it is monotype face = Face(filename) face.set_char_size( size*64 ) if not face.is_fixed_width: raise 'Font is not monotype' # Determine largest glyph size width, height, ascender, descender = 0, 0, 0, 0 for c in range(32,128): face.load_char( chr(c), FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT ) bitmap = face.glyph.bitmap width = max( width, bitmap.width ) ascender = max( ascender, face.glyph.bitmap_top ) descender = max( descender, bitmap.rows-face.glyph.bitmap_top ) height = ascender+descender # Generate texture data Z = numpy.zeros((height*6, width*16), dtype=numpy.ubyte) for j in range(6): for i in range(16): face.load_char(chr(32+j*16+i), FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT ) bitmap = face.glyph.bitmap x = i*width + face.glyph.bitmap_left y = j*height + ascender - face.glyph.bitmap_top Z[y:y+bitmap.rows,x:x+bitmap.width].flat = bitmap.buffer # Bound texture texid = gl.glGenTextures(1) gl.glBindTexture( gl.GL_TEXTURE_2D, texid ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR ) gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, Z.shape[1], Z.shape[0], 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, Z ) # Generate display lists dx, dy = width/float(Z.shape[1]), height/float(Z.shape[0]) base = gl.glGenLists(8*16) for i in range(8*16): c = chr(i) x = i%16 y = i//16-2 gl.glNewList(base+i, gl.GL_COMPILE) if (c == '\n'): gl.glPopMatrix( ) gl.glTranslatef( 0, -height, 0 ) gl.glPushMatrix( ) elif (c == '\t'): gl.glTranslatef( 4*width, 0, 0 ) elif (i >= 32): gl.glBegin( gl.GL_QUADS ) gl.glTexCoord2f( (x )*dx, (y+1)*dy ), gl.glVertex( 0, -height ) gl.glTexCoord2f( (x )*dx, (y )*dy ), gl.glVertex( 0, 0 ) gl.glTexCoord2f( (x+1)*dx, (y )*dy ), gl.glVertex( width, 0 ) gl.glTexCoord2f( (x+1)*dx, (y+1)*dy ), gl.glVertex( width, -height ) gl.glEnd( ) gl.glTranslatef( width, 0, 0 ) gl.glEndList( ) if __name__ == '__main__': import sys glut.glutInit( sys.argv ) glut.glutInitDisplayMode( glut.GLUT_DOUBLE | glut.GLUT_RGB | glut.GLUT_DEPTH ) glut.glutCreateWindow( "Freetype OpenGL" ) glut.glutReshapeWindow( 600, 100 ) glut.glutDisplayFunc( on_display ) glut.glutReshapeFunc( on_reshape ) glut.glutKeyboardFunc( on_keyboard ) gl.glTexEnvf( gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE ) gl.glEnable( gl.GL_DEPTH_TEST ) gl.glEnable( gl.GL_BLEND ) gl.glEnable( gl.GL_COLOR_MATERIAL ) gl.glColorMaterial( gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT_AND_DIFFUSE ) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) gl.glEnable( gl.GL_TEXTURE_2D ) makefont( './VeraMono.ttf', 64 ) glut.glutMainLoop( ) freetype-py-2.5.1/examples/Vera.ttf0000664000175000017500000020061414664131406017432 0ustar georgeskgeorgeskOS/2_cpVPCLTъ^6cmaplXcvt 9fpgm&`gaspH glyf tA&~hdmx4!Hhead݄T6hheaEoL$hmtx Ǝ0kernRՙ-loca=maxpG:, nameټȵpostZ/prep; h::_:: dM0l   p t  &   Y &  &   c . 5 `  s 0 & {Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.com5fqu-J3T99NR7s`s3VV9s3D{o{RoHT3fs +b-{T#\q#H99`#fy```{w``b{{Rffw;{J/}oo5jo{-{T7fD)fs@%2%%A:B2SAS//2ݖ}ٻ֊A}G}G͖2ƅ%]%]@@%d%d%A2dA  d   A(]%]@%..%A  %d%@~}}~}}|d{T{%zyxw v utsrqponl!kjBjSih}gBfedcba:`^ ][ZYX YX WW2VUTUBTSSRQJQP ONMNMLKJKJIJI IH GFEDC-CBAK@?>=>=<=<; <@; :987876765 65 43 21 21 0/ 0 / .- .- ,2+*%+d*)*%)('%(A'%&% &% $#"!! d d BBBdB-B}d       -d@--d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++, %Id@QX Y!-,%Id@QX Y!-,  P y PXY%%# P y PXY%-,KPX EDY!-,%E`D-,KSX%%EDY!!-,ED-ff@ /10!%!!fsr)5 @@ <2991/0K TX @ 878Y P ]%3#3#5qeM@1<20KTKT[X@878Y@0 @ P ` p ]#!#o$++`@1      91/<<<<<<<2220@   ]!! !3!!!!#!#!5!!5!T%Dh$ig8R>hggh`TifaabbNm!(/@U" '&( /)/))/B" ) *!#*- ) " & 0<<<1/299990KSX99Y"K TX0@00878YK TKT[KT[X000@878Y#.'5.546753.'>54&dijfod]SS\dtzq{---@A$*.U# jXV`OnZXhq) #'3@6$%&%&'$'B .$ &($4'!%   ! + 1 49912<0KSXY"K TK T[K T[KT[KT[K T[X4@44878Y"32654&'2#"&546"32654&%3#2#"&546WccWUccUVcbWWcd1Zܻۻa ۻۼ 0@      !         B  (('+'$ .  .'.'!!199999991/9990KSX99999999Y"2]@ " ) **&:4D ^YZ UZZY0g{ "-  ' (   2'') #**(/2; 49?2J LKFO2VZ Y UY\_2j i`2uy z 2229]]3267 >73#'#"5467.54632.#"[UԠ_I{;B h]hΆ02޸SUWDi;#QX?@Yr~YW׀c?}<$$/1oX3goB@ 10KTKT[X@878Y@ @P`p]#o+{ O@  29910KTX@878YKTX@878Y#&547{>;o @ <99103#654<:=JN@,       <2<2991<22990%#'%%73%g:r:g:PrPbybcy #@   <<1/<<0!!#!5!-Ө-Ӫ--@ 1073#ӤR@d10!!d1/073#B-@B/9910KSXY"3#m #@  10"32'2#"  P3343ssyzZ K@B  1/20KSXY"KTX  @878Y]7!5%3!!JeJsHHժJ@'B   91/20KSX9Y"KTKT[KT[X@878Y@2UVVzzvtvust]]%!!567>54&#"5>32Ls3aM_xzXE[w:mIwBC12\ps({@.    #)&  )99190KTKT[X)@))878Y@ daa d!]!"&'532654&+532654&#"5>32?^jTmǹSrsY %Đ%%12wps{$& Ѳ|d @   B    <291/<290KSXY"K TK T[X@878Y@* *HYiw+&+6NO O Vfuz ]] !33##!55^%3`du@#    190KTKT[X@878YKTX@878Y!!>32!"&'532654&#",X,$^hZkʭQTժ 10$& $X@$  "% " !%190@]]"32654&.#">32# !2 LL;kPL;y$&W]ybhc@B991/0KSXY"KTX@878Y@X9Hg]]!#!3V+ #/C@% '-'0 $*$ !0991990"32654&%&&54632#"$54632654&#"HŚV г "Əُattt$X@# %!"" %190@]]7532#"543 !"&2654&#"LK:lL>$& V\s[#@<21/073#3### %@  <2103#3#ӤR#٬@^M@*B$#29190KSXY" 5Ѧ`@ #<210!!!!^O@+B$#<9190KSXY"55//m$p@+$     &%99991/9990K TX%@%%878Yy z z ]%3##546?>54&#"5>32ſ8ZZ93lOa^gHZX/'eVY5^1YnFC98ŸLVV/5<4q L@2  L4307$7CM34( (+(I+*(I,=M<9912990K TK T[KT[KT[KT[XMMM@878Y@ NN/N?N]32654&#"#"&5463253>54&'&$#"3267#"$'&5476$32|{zy!orqp ˘s'6@   0210].# !267# !2'ffjzSb_^^_HHghG.@   2 99991/0`]3 !%! )5BhPa/w.,~ .@   21/0 ]!!!!!!9>ժF# )@ 21/0 ]!!!!#ZpPժH7s9@ 43 1990%!5!# !2&&# !26uu^opkSUmnHF_`%; ,@ 8  221/<20P ]3!3#!#"d+991/0KTX@878Y@ 0@P`]3#+f M@  9 991990KTX  @878Y@ 0 @ P ` ]3+53265M?nj @(B  291/<290KSXY"]@ ((764GFCUgvw    (+*66650 A@E@@@ b`hgwp  ,]q]q3! !#3wH1j%@ :1/0@ 0P]3!!_ժ @4  B    >  91/<290KSXY"p]@V   && & 45 i|{y   #,'( 4<VY ej vy ]]! !###-}-+3 y@B6 991/<2990KSXY" ]@068HGif FIWXeiy ]]!3!#j+s #@  310"32' ! ':xyLHH[[bb:@   ? 291/0@ ?_]32654&#%!2+#8/ϒs R@*  B     39991990KSX9Y""32#'# ! '? !#y;:xLHHab[T@5  B    ?  299991/<9990KSX9Y"@]@Bz%%%&'&&& 66FFhuuw]]#.+#! 32654&#A{>ٿJx~hb؍O'~@<    B %( "-"(9999190KSX99Y")])/)O)].#"!"&'532654&/.54$32Hs_wzj{r{i76vce+ٶ0/EF~n|-&J@@@1/20K TX@878Y@  @ p ]!!#!ժ+)K@   8A1299990KTX@878Y]332653! ˮ®u\*$h@'B91/290KSXY"P]@b*GGZ} *&&))% 833<<7HEEIIGYVfiizvvyyu)]]!3 3J+D {@I      B     91/<2290KSXY"]@  ($ >>4 0 LMB @ Yjkg ` {|      !   # $ %  <:5306 9 ? 0FFJ@E@BBB@@ D M @@XVY Pfgab```d d d wv{xwtyywpx   []]3 3 3# #D:9:9+=; ]@F      B    91/<290KSXY"K TK T[KT[X  @878Y@ '' 486 KX[fkww       &()&(' ) 54<;:;4 4 8 ? H O X _ eejjhiil l xyyx}  x   @]]3 3 # #su \Y+3{@(B@@ 91/290KSXY" ]@<5000F@@@QQQe &)78@ ghxp ]]3 3#f9\ @BB 991/0KSXY"K TK T[X @ 878Y@@ )&8HGH    / 59? GJO UYfio wx ]]!!!5!sP=g՚oXS@C210K TX@878YKTKT[X@878Y!#3!XB-@B/9910KSXY"#mo<@C<10KTKT[X@878Y!53#5oXޏ@ 91290##HHu-10!5f1@ D10K TKT[X@878Y #ofv{-{ %@'   #   E&22991/9990@n0000 0!0"?'@@@@ @!@"PPPP P!P"P'p' !"'''000 0!@@@ @!PPP P!``` `!ppp p! !]]"326=7#5#"&5463!54&#"5>32߬o?`TeZ3f{bsٴ)Lfa..'' 8@  G F221/0`]4&#"326>32#"&'#3姒:{{:/Rdaadq{?@  HE210@ ].#"3267#"!2NPƳPNM]-U5++++$$>:#qZ8@G E221/0`]3#5#"3232654&#":||ǧ^daDDaq{p@$   KE9190@)?p?????,// , ooooo ]q]!3267# 32.#" ͷjbck)^Z44*,8 Cė/p@     L<<991/22990K TX@878YKTX@878Y@P]#"!!##535463cM/ѹPhc/яNqVZ{ (J@#  &#' & G E)221/990`***]4&#"326!"&'5326=#"3253aQQR9||9=,*[cb::bcd4@  N  F21/<90`]#4&#"#3>32d||Bu\edy+@F<21/0@  @ P ` p ]3#3#`Vy D@   O  F<2991990@ @P`p]3+532653#F1iL`a( @)B F 291/<90KSXY" ]@_ ')+Vfgsw    ('(++@ h` ]q]33 ##%kǹi#y"F1/0@ @P`p]3#{"Z@&   PPF#291/<<<290@0$P$p$$$$$$$ ]>32#4&#"#4&#"#3>32)Erurw?yz|v\`gb|d{6@  N  F21/<90`]#4&#"#3>32d||Bu\`edqu{ J@  QE10@#?{{   {  {]"32654&'2#"s98V{>@ GF2210@ `]%#3>32#"&4&#"326s:{{8 daaqVZ{ >@   GE2210@ `]32654&#"#"3253#/s:||:/daDDadJ{0@    F21/90P].#"#3>32JI,:.˾`fco{'@<  S  SB %( R"E(9999190KSX99Y"']@m   . , , , ; ; ; ; $( ( *//*(() )!$'      '/)?)_))))))]]q.#"#"&'532654&/.54632NZb?ĥZlfae@f?((TT@I!*##55YQKP%$78@  F<<2991/<2990]!!;#"&5#53w{KsբN`>X`6@    NF21/290`]332653#5#"&||Cua{fc=`@'B91/290KSXY"K TX@878YKTKT[X@878Y@Hj{  &&)) 55::0FFIIFH@VVYYPffiigh`ut{{uz>]]3 3#=^^\`TV5` @IU U U U   B     91/<2290KSXY"K TKT[KT[KT[K T[X  @878YK TK T[KT[X @ 878Y@" 5 IIF @ [[U P nnf yy          %%#'!%""%' $ ! # 9669 0FHF@B@@@D D D @@VVVPQRRPS T U cdejejjjn a g ouuy}x}zzxy  { v } @/   y]]333# #V`jjj;y` Z@F      B   91/<290KSXY"K TKT[KT[KT[X  @878YKTX @ 878Y@   & =1 UWX f vzvt        )&% * :9746 9 0 IFE J @ YVYYWVYVV Y P o x  /]] # # 3 dkr))`HJq=V`@C        B     9129990KSX2Y"K TKT[X@878YKTX@878Y@     # 5 I O N Z Z j        '$$  )( % $ $ ' ** 755008 6 6 8 990A@@@@@@@@B E G II@TQQUPPVUVW W U U YYPffh ii`{xx   e]]+5326?3 3N|lLT3!;^^hzHTNlX` @B 2991/0KSXY"K TK T[X @ 878YKTX  @878Y@B&GI  + 690 @@E@@CWY_ ``f``b ]]!!!5!qjL}e`ۓ%$@4 %   !  % $  C %<<29999999199999990K TX%%%@878Y&]#"&=4&+5326=46;#"3>l==k>DV[noZVtsݓXX10#$@6%   #%#C %<2<9999999199999990K TX%@%%878YKTX%%%@878Y&]326=467.=4&+532;#"+FUZooZUF?l>>l?VWstݔ1#@  1990#"'&'&'&#"56632326ian ^Xbian ^V1OD;>MSOE<>LhN'$uhm !@T   !!  ! !!!B     !  VV!"2299999991/<9990KSXY" #]@  s P#f iu {yyv v!# ]]4&#"326!.54632#!#TY?@WX??Y!X=>sr?<҈_Z?YWA?XXN)sIsrFv)su''&-k'(u3^'1usN'2'u)N'8u{-f'DR{-f'DCR{-f'DR{-'DR{-7'DR{-'DRqu{'Fqf'Hqf'HCqf'Hq'Hof'f'C\f'F'd7'Qquf'Rsquf'RCsquf'Rsqu'Rsqu7'RsXf'X{Xf'XC{Xf'X{X'X{9; '@  YW Y <<1<203!!#!5!oo\]u=  @  Z[Z10"32654&'2#"&546PnnPPnoO@v+..ooPOmmOOp1.-rB#!Q@+     "  "<<<221<9990%&&'667#&73JDFHAMf fIX⸹)**'# 32!b`@!    <<1/2<2990K TX@878Y66].#"!!!!53#535632NL=ty-=))׏/я\= >@54&.#"#"&'532654/.5467.54632{?>?>S8alӃ\]>9̭IXW:fqր][;;ȦI.Z.L-[.K''PGZsweZ54m@''TLf{xf[1,pE3!   \ 104632#"&3~|}}||};9 %@]] 91290!###&&54$yfNݸ/@0-'!  **.  !' $'$-F099991/990@@'(     ! "&  : :!MM I!I"jj  ]]4632#"&'532654&/.5467.#"#:A9`@IPAtx;e\`Wqqs`/Q*%jd_[?T>7;[gp/8L`@6EBC?2H09JC 9 $HE301BKL?gwyVpMI`3D/IC@&=>:A$104G$ 7aD=0^* D^ J21/02#"$'&5476$"32676654&'&&&&#"3267#"&54632mmllmmmmllmm^^``^^⃄^]]^\^BB@zBCFInmmmmnnmmmmng^^^傁^^__^]⃅]^^! "'F >@!    b b cbc91<<2<<903#######5Jq7rqr/B^^sRf1@ D10K TKT[X@878Y3#fF)@dd1<20K TK T[X@878YK TK T[KT[KT[X@878YKTKT[X@878Y@````pppp]3#%3#^y'>@"     <291<2<<990!!!!!'7!5!7!}/H{};fըfӪH@9  B     <291/<0KSXY"]@gww  ]!!!!!!#!59=qժF՞f +@< +,  )&  *&& &,+,* # )#3,99999999199999990@*WZWU!je!{vu! FYVjddj(|svz( ]] 324&'.#"&5!27!"&''3>_'y=_''NOy;WfNPƀ[gX@CHp@CpDfbMKYg[KKX /@- !$'!!0 $*0999919990@     $$$   $$ $ ***///***55500055 5 :::???:::EEE@@@EE E JJJOOOJJJV !"&'()]]32654&#".#"326#"&54632>32#"&1TevYR1UfvYRF^_HDa^/XZie7XXjeߦ~᧯w .@     <2<21/<<0!!#!5!!!-Ө-}} T@.B $# <2291/90KSXY" 5!!@po V@/B$ # <<291/90KSXY"55!5AǪR@F  B     fe f e<2299991/2<2<290KSXY"K TX@878Y@(' ' ')((79  ]]!#!5!5'!5!3 3!!!c`Tþ{yT9{3{JD{3V` M@%  !   NF!2912<990"`""]3326533267#"&'#"&'#% )I#ER2bf*V H<9 NPOONNh-)b@'! '!* $$*9991990K TK T[KT[KT[KT[X*@**878Y>54&#"#"&54632#"&54324&#"32IH7$$0e՘ݢe WOmVPmmWKt,>bFأ[t}t{w; ]@    91990@0QVPZ spvupz  Z pp{ t  ]]!! !!5 7AJI3!wq@gg120!#!# }/#@1 " $ #" #h#$9999991/<229990K TX$$$@878Y@V             ##(]]#3267#"&5467!##"#>3!i/7.%7vy"Pµ)6< yJ\:1fd.xo@E}/%&@  & iji&1026732#"&'&&#"#"&546327j Pd@7*8  kOeD=!0 l9TA6?&#Hn!bSA8?Ss;)_@3(%%  * "(kl"k *22999199990!!#5#"&5463354&#"56632"32655P,]uu>DIE~bRhP{@p?Dq[[""CO@Mr`d.@  klk 9910!!2#"&546"32654&PXγгi~hi}|P{ݿܾsN@@"   mm  9991/<20%!5654#"!5!&5! Dz?1/aL"a*>w؍{o{3>@C'-%= 4%:.-*1 %?47&%7& =&-7"E?<9999912<<29990@0+0,0-0.0/00@+@,@-@.@/@0P+P,P-P.P/P0+0@@@@@@@@@??? ??0,0-0.0/@,@-@.@/P,P-P.P/ooo oo`,`-`.`/p,p-p.p/,-./]q].#">32!3267#"&'#"&5463!54&#"5>32"326=DJԄ ̷hddjMI؏`TeZ߬o0Z^Z55*,ywxx..''`f{bsٴ)H +@<+,&  )&  *&& &,+,* # #Q)E,22999999199999990@p(?-YVUV jf!{    { z{ {!"#$%{&%--&YVUZ(ifej(ztvz($$]] 32654&'.#".5327#"&'')gA\*g>}66]C_56`?`!*(Ou))Hn.Mw834OMx43N $@/  !# #%" " "!& %999919990KTKT[KT[X%%%@878Y@ ttttv]33267#"&546?>7>5#537ZZ:3mN`^gIYX0&DeWX5^1YnFC98ŸLVV/5<65 b@ <2991/0K TX @ 878YKTKT[KT[X  @878Y P ]#53#3+e^@ 10!#!^=} *@    91903##'%\sB}}`s-Pb;V#@@   B   !$  $912299990KSX29Y"K TX$$$@878Y.#"!!#"&'53267#5!>32&P,`r<::d/4a/am"?$Ɨ5dzɏ!!J;?@.9*-" *19" <-<<219999990#"'&'&'&#"56632326#"'&'&'&#"56632326ian ^Xbian ^Vgian ^Xbian ^VoNE;=LTNE;=KڲOE;=LSNE;=K`8@91/90@cmpxyvn]] !3!^DC?%# @I    B   o o n<2991<2990KSXY"55%-+#-+#RRH# @I  B   o op<<991<2990KSXY"5%5+-+-#^R^  ^R^   #@   1/<<220%3#%3#%3#hk'$uh^'$us^'2'us ;@   299991/220!!!!! !# !39OAg@AժF|pm|q{'3@1 . ("%4"1 K1 Q+E499912<2290@%?5_5p55555????? ooooo ]q].#"!3267#"&'#"32>32%"32654& H ̷jbdjQGьBN5Z44*,nmnm98olkp݇y/10!!yy/10!!ym '@   1<20#53#53ӤRӤR??m '@   1<203#%3#ӤRӤRլ@@@ 10#53ӤR?@ q103#ӤR՘?o )@ r <<103#3#!!oA#u"@91990  9%-=V'\^N'<su+@B10KSXY"3#-\^R#/@I -'! - -'!0 *$0* $ $(st*(s099999999919999999907'#"&''7&&5467'766324&#"326{r%$&(r;t=:x=q%%&&s7t@?s9q(&%%s>v:@t8s'%$|pprs#G@%Bon29190KSXY"5s-+#R#I@&Bop<9190KSXY"5+-#^R^  /J@(   L<2<2991/<22990K TX@878YKTX@878Y@0P]]#!##53546;#"3#JcM`/яNPhc/J@!    L<<991/<22990K TX@878YKTX@878Y@0P ]!#!"!!##53546JcM/ѹ{Phc/яN9;>@   Y W Y <<2<<2122220%!#!5!!5!3!!!oooo\\HF103#F@ 10%3#ӤR@m '@    1<20%3#%3#ӤRfӤR@@q L #'3?K@D$%&%&'$'B@ .(F4 :&$L%IC'1+C =  1 =I 7+ ! L9912<<2220KSXY"KTK T[K T[K T[K T[KT[XL@LL878Y"32654&'2#"&5462#"&546!3#"32654&2#"&546"32654&WddWUccUt%ZVcbWWcdWccWUccܻۻۻۼܻۻhm'$um'(uhk'$uN'(uk'(uk',/u`m',/uXN',/u;k',/usk'2'usm'2'usk'2'u)k'8u)m'8u)k'8uy` F1/0@ @P`p]3#`?f7@ u91290K TKT[X@878Y3#'#fJ7c@$   VwVv99991<<99990K TK T[X@878Y'.#"#>3232673#"&9! &$}f[&@%9! &$}f[&@Z7IR!7IRb+/10K TKT[X@878Y!!V)9H W@ VV1<0K TX@878YKTKT[KT[X@878Y332673#"&v aWV` v HKKJLDf,@ d10K TX@878Y3# _@ V xV10K TK T[X@878YK TK T[K T[X@878Y4&#"3267#"&54632X@AWWA@Xzssss?XW@AWX@sss#u@  ' 1/90!#"&'532654&'T76xv.W+"J/;<+->i0Y[ 0.W=fB@991<20K TKT[X@878Y3#3#߉fxLu @   '1/90!33267#"&546w-+76 >&Dzs5=X.. W]0i?f7@ u91<90K TKT[X@878Y373xu ?@   : y<<991/900P]3%!!'79Pw^Mo;jnH ^@  z z <<991/90KTX @ 878Y@ @ P ` sz p ]37#'7Ǹ}Lɸ{JZjXjm'6uof'V\m'=uXf']@ <210##    g@    2  y<291/220@(   ]]! )#53!!3 !iP`P5~.,qu('@^%{&%#${##{#({'(#&'('%$%(('"#" ! B('&%"! ## #)&' ! (%#" QE)999999919990KSXY"?*]@v%+("/#/$)%-&-'*(6%F%X X!` `!f"u u!u"%#%$&&&''(6$6%F$E%Z Z!b b!z{     {zzv v!x"**']].#"32654&#"5432''%'3%F2X)6 ~r4*!M!ü޼z&77kc\̑oabk'<su=Vf'\^ =@   ? 2291/0@ ?_]332+#32654&#'ђV>@ GF2210@ `]%#3>32#"&4&#"326s:{{8daa-10!!ת? @M    B   <291<290KSXY" '77w55v8vL57y5yy5 ,@   |]|| 12035733! c)t'+n^J@$}}B ~9190KSX2Y"!!56754&#"56632 "?XhU4zHM98rn81^BQ##{l0b(H@'    #)~&~ )999190#"&'532654&##532654&#"56632 \e9}F4wCmxolV^^ad_(fQI7Z`mR|yOFJLl?<:=svcE`''5 d?''5db''5 dsm'* uqVZH'JP', /uu'6ou{'Vs'k'&-uqf'Fs'm'&-uqf'Fq$J@$ "    GE%<<1/<20`&&&]!5!533##5#"3232654&#"F:||ǧN}}daDDad10!!dHF103#F1@: "+ /) 2+"!)#&  , & &*!/<29999999999122<20K TK T[K T[KT[KT[KT[X222@878Y@z  1Ti lnooooiko o!o"o#n$l%i'i-  !"#$%&'()*+,-2   USjg ]].#"!!!!3267#"#734&5465#7332[f A78 ʝf[Y`(77(6bbiZȻ{.# .{ZiHH"{/ #/{"G)@ dd1<20KTKT[X@878YKTK T[KT[X@878YKTKT[X@878YKTX@878Y@````pppp]3#%3#^ys@B10KSXY"K TX@878YKTX@878Y@ %%6FVjg //]]3#7Ju@!  VV 99991<2990K TX@878YKTX@878Y ]'.#"#4632326=3#"&9 $(}gV$=09" (}gT";9! 2-ev 3)dw @B10KSXY"K TX@878YKTX@878Y@*$$5CUU//]]#ę1w@ 91<90K TX@878YKTX@878YKTX@878Y@ //- ]3#'#Ӌ1@ 91290K TK T[K T[K T[X@878YKTX@878YKTX@878Y@ "  ]373Ӌ ? @   ] <291<290KTKT[KT[KT[K T[K T[X@878YKTKT[X@878Y@T /9IFYi       "5GK S[ e]] !33##5!55bf]my9 j@ VV120K TX@878YKTX@878YKTKT[X@878Y332673#"&v cSRav 6978w{zf103#  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>: ~1BSax~ & 0 : !""""+"H"e%  0AR^x}  0 9 !""""+"H"`%^ChVjq_8 (Bbcdefghjikmlnoqprsutvwxzy{}|~f55q=3=dd?y}s)3s\\?uLsLsyD{={\{fqqq/q999qqJ+o#7=V;=3XyysLs{{{{{{fqqqqq9999qqqqq9\3 'sLfR#hd+/s`N{H?55=ZyyLss/q%%=V^33 / /9% qyy\\\\;LsLsLs9#LF+o{\3X3 q=55^5bb3sq\+osfqsfqqds 5?+   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468c6469""""XO!nE~Le  R s  X : i  = z /Eu)pP@"m#{CwRw [ r !5!B!!!" ""#"0"="J"W"d"q"~"""""""""## ##'#4#A#N#[#h##$4$%3%S%&&'K''((X()_*%*\**+z+,D,,-P-..R./0A011!1P12H2z23F3p3p3}3334z44445595g55556[667C77888J999)969C9P9]9j9w99999999::{::;;^;;;<"<_<<<<<<=c>;>H>U>>>?a??@:@K@\@m@z@@@@@@@@A@AVAkBEBBC_CCDUDE*E?- x$%&')*K+-r./2934K57D9:;< =IQR&UYZ\bdg9xy&z&{&|&}&9 999 K$$$$$9$&$*$2$4$6$7a$8$9}$:$;$> 6) + left x1 = x0 + width y0 = (pen.y >> 6) - (rows - top) y1 = y0 + rows xmin, xmax = min(xmin, x0), max(xmax, x1) ymin, ymax = min(ymin, y0), max(ymax, y1) pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L = np.zeros((ymax-ymin, xmax-xmin),dtype=np.ubyte) previous = 0 pen.x, pen.y = 0, 0 for c in text: face.load_char(c, flags) kerning = face.get_kerning(previous, c) previous = c bitmap = face.glyph.bitmap pitch = face.glyph.bitmap.pitch width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows top = face.glyph.bitmap_top left = face.glyph.bitmap_left pen.x += kerning.x x = (pen.x >> 6) - xmin + left y = (pen.y >> 6) - ymin - (rows - top) data = [] for j in range(rows): data.extend(bitmap.buffer[j*pitch:j*pitch+width]) if len(data): Z = np.array(data,dtype=np.ubyte).reshape(rows, width) L[y:y+rows,x:x+width] |= Z[::-1,::1] pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y return L if __name__ == '__main__': from PIL import Image n_words = 100 H, W, dpi = 600, 800, 72.0 I = np.zeros((H, W, 3), dtype=np.ubyte) S = np.random.normal(0,1,n_words) S = (S-S.min())/(S.max()-S.min()) S = np.sort(1-np.sqrt(S))[::-1] sizes = (12 + S*48).astype(int).tolist() def spiral(): eccentricity = 1.5 radius = 8 step = 0.1 t = 0 while True: t += step yield eccentricity*radius*t*math.cos(t), radius*t*math.sin(t) fails = 0 for size in sizes: angle = np.random.randint(-25,25) L = make_label('Hello', './Vera.ttf', size, angle=angle) h,w = L.shape if h < H and w < W: x0 = W//2 + (np.random.uniform()-.1)*50 y0 = H//2 + (np.random.uniform()-.1)*50 for dx,dy in spiral(): c = .25+.75*np.random.random() x = int(x0+dx) y = int(y0+dy) if x <= w//2 or y <= h//2 or x >= (W-w//2) or y >= (H-h//2): fails += 1 break if (I[y-h//2:y-h//2+h, x-w//2:x-w//2+w,0] * L).sum() == 0: I[y-h//2:y-h//2+h, x-w//2:x-w//2+w,0] |= (c * L).astype('ubyte') I[y-h//2:y-h//2+h, x-w//2:x-w//2+w,1] |= (c * L).astype('ubyte') I[y-h//2:y-h//2+h, x-w//2:x-w//2+w,2] |= (c * L).astype('ubyte') break print ("Number of fails: {}".format(fails)) fig = plt.figure(figsize=(W/dpi,H/dpi), dpi=dpi) ax = fig.add_axes([0,0,1,1], frameon=False) ax.imshow(I, interpolation='nearest', cmap=plt.cm.gray, origin='upper') #plt.axis('off') plt.show() I = Image.fromarray(I[::-1,::1,::1], mode='RGB') I.save('wordle.png') freetype-py-2.5.1/examples/glyph-mono+alpha-cairo.py0000775000175000017500000000440314664131406022636 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-mono/alpha example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - Not immitating the upside-downness of glyph-monochrome/glyph-alpha # This script default to normal(8-bit) rendering, but render to mono # if any argument is specified. # # Mono rendering requires libtiff on small-endian platforms. See # comments in bitmap_to_surface.py. # # ----------------------------------------------------------------------------- ''' Glyph bitmap monochrome/alpha rendring ''' from freetype import * # use Matrix() from Cairo instead of from Freetype from cairo import Context, ImageSurface, FORMAT_ARGB32, SurfacePattern, FILTER_BEST, Matrix from bitmap_to_surface import make_image_surface if __name__ == '__main__': from PIL import Image import sys face = Face('./Vera.ttf') face.set_char_size( 48*64 ) if len(sys.argv) < 2: # Normal(8-bit) Rendering face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL ) else: # Mono(1-bit) Rendering face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_MONO ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch glyph_surface = make_image_surface(face.glyph.bitmap) surface = ImageSurface(FORMAT_ARGB32, 800, 600) ctx = Context(surface) ctx.rectangle(0,0,800,600) ctx.set_line_width(0) ctx.set_source_rgb (0.5 , 0.5, 0.5) ctx.fill() # scale = 480.0 / rows ctx.set_source_surface(glyph_surface, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(400.0 - width *scale /2.0 ), -60) pattern.set_matrix(scalematrix) ctx.set_source_rgb (0 , 0, 1) ctx.mask(pattern) ctx.fill() surface.flush() surface.write_to_png("glyph-mono+alpha-cairo.png") Image.open("glyph-mono+alpha-cairo.png").show() freetype-py-2.5.1/examples/example_1.py0000664000175000017500000000611014664131406020236 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- # # Direct translation of example 1 from the freetype tutorial: # http://www.freetype.org/freetype2/docs/tutorial/step1.html # import math import matplotlib.pyplot as plt from freetype.raw import * from PIL import Image WIDTH, HEIGHT = 640, 480 image = Image.new('L', (WIDTH,HEIGHT)) def to_c_str(text): ''' Convert python strings to null terminated c strings. ''' cStr = create_string_buffer(text.encode(encoding='UTF-8')) return cast(pointer(cStr), POINTER(c_char)) def draw_bitmap( bitmap, x, y): global image x_max = x + bitmap.width y_max = y + bitmap.rows p = 0 for p,i in enumerate(range(x,x_max)): for q,j in enumerate(range(y,y_max)): if i < 0 or j < 0 or i >= WIDTH or j >= HEIGHT: continue; pixel = image.getpixel((i,j)) pixel |= int(bitmap.buffer[q * bitmap.width + p]); image.putpixel((i,j), pixel) def main(): library = FT_Library() matrix = FT_Matrix() face = FT_Face() pen = FT_Vector() filename= 'Vera.ttf' text = 'Hello World !' num_chars = len(text) angle = ( 25.0 / 360 ) * 3.14159 * 2 # initialize library, error handling omitted error = FT_Init_FreeType( byref(library) ) # create face object, error handling omitted error = FT_New_Face( library, to_c_str(filename), 0, byref(face) ) # set character size: 50pt at 100dpi, error handling omitted error = FT_Set_Char_Size( face, 50 * 64, 0, 100, 0 ) slot = face.contents.glyph # set up matrix matrix.xx = (int)( math.cos( angle ) * 0x10000 ) matrix.xy = (int)(-math.sin( angle ) * 0x10000 ) matrix.yx = (int)( math.sin( angle ) * 0x10000 ) matrix.yy = (int)( math.cos( angle ) * 0x10000 ) # the pen position in 26.6 cartesian space coordinates; */ # start at (300,200) relative to the upper left corner */ pen.x = 200 * 64; pen.y = ( HEIGHT - 300 ) * 64 for n in range(num_chars): # set transformation FT_Set_Transform( face, byref(matrix), byref(pen) ) # load glyph image into the slot (erase previous one) charcode = ord(text[n]) index = FT_Get_Char_Index( face, charcode ) FT_Load_Glyph( face, index, FT_LOAD_RENDER ) # now, draw to our target surface (convert position) draw_bitmap( slot.contents.bitmap, slot.contents.bitmap_left, HEIGHT - slot.contents.bitmap_top ) # increment pen position pen.x += slot.contents.advance.x pen.y += slot.contents.advance.y FT_Done_Face(face) FT_Done_FreeType(library) plt.imshow(image, origin='lower', interpolation='nearest', cmap=plt.cm.gray) plt.show() if __name__ == '__main__': main() freetype-py-2.5.1/examples/example_1-cairo.py0000775000175000017500000000620714664131406021343 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based FreeType example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # # ----------------------------------------------------------------------------- # # Direct translation of example 1 from the freetype tutorial: # http://www.freetype.org/freetype2/docs/tutorial/step1.html # # Except we uses FreeType's own trigonometric functions instead of those # from the system/python's math library. from cairo import Context, ImageSurface, FORMAT_A8 from bitmap_to_surface import make_image_surface from freetype.raw import * from PIL import Image WIDTH, HEIGHT = 640, 480 image = ImageSurface(FORMAT_A8, WIDTH, HEIGHT) ctx = Context(image) def to_c_str(text): ''' Convert python strings to null terminated c strings. ''' cStr = create_string_buffer(text.encode(encoding='UTF-8')) return cast(pointer(cStr), POINTER(c_char)) def draw_bitmap( bitmap, x, y): global image, ctx # cairo does not like zero-width surface if (bitmap.width > 0): glyph_surface = make_image_surface(bitmap) ctx.set_source_surface(glyph_surface, x, y) ctx.paint() def main(): library = FT_Library() matrix = FT_Matrix() face = FT_Face() pen = FT_Vector() filename= 'Vera.ttf' text = 'Hello World !' num_chars = len(text) # FT_Angle is a 16.16 fixed-point value expressed in degrees. angle = FT_Angle(25 * 65536) # initialize library, error handling omitted error = FT_Init_FreeType( byref(library) ) # create face object, error handling omitted error = FT_New_Face( library, to_c_str(filename), 0, byref(face) ) # set character size: 50pt at 100dpi, error handling omitted error = FT_Set_Char_Size( face, 50 * 64, 0, 100, 0 ) slot = face.contents.glyph # set up matrix matrix.xx = FT_Cos( angle ) matrix.xy = - FT_Sin( angle ) matrix.yx = FT_Sin( angle ) matrix.yy = FT_Cos( angle ) # the pen position in 26.6 cartesian space coordinates; */ # start at (300,200) relative to the upper left corner */ pen.x = 200 * 64; pen.y = ( HEIGHT - 300 ) * 64 for n in range(num_chars): # set transformation FT_Set_Transform( face, byref(matrix), byref(pen) ) # load glyph image into the slot (erase previous one) charcode = ord(text[n]) index = FT_Get_Char_Index( face, charcode ) FT_Load_Glyph( face, index, FT_LOAD_RENDER ) # now, draw to our target surface (convert position) draw_bitmap( slot.contents.bitmap, slot.contents.bitmap_left, HEIGHT - slot.contents.bitmap_top ) # increment pen position pen.x += slot.contents.advance.x pen.y += slot.contents.advance.y FT_Done_Face(face) FT_Done_FreeType(library) image.flush() image.write_to_png("example_1-cairo.png") Image.open("example_1-cairo.png").show() if __name__ == '__main__': main() freetype-py-2.5.1/examples/glyph-metrics.py0000664000175000017500000001705414664131406021163 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Show glyph metrics in horizontal and vertical layout ''' from freetype import * def arrow( x,y, dx, dy, **kwargs): kwargs['shape'] = 'full' kwargs['head_width'] = 30 kwargs['head_length'] = 40 kwargs['length_includes_head'] =True kwargs['facecolor'] = 'k' kwargs['edgecolor'] ='k' kwargs['linewidth'] =.5 plt.arrow(x,y,dx,dy,**kwargs) def double_arrow(x, y, dx, dy, **kwargs): cx,cy = x+dx/2., y+dy/2. dx /= 2.0 dy /= 2.0 arrow(cx,cy,+dx,+dy,**kwargs) arrow(cx,cy,-dx,-dy,**kwargs) def line(x, y, dx, dy, **kwargs): kwargs['color'] = 'k' kwargs['linewidth'] =.5 plt.plot([x,x+dx],[y,y+dy],**kwargs) def point(x, y, r, **kwargs): kwargs['color'] = 'k' plt.scatter([x],[y],r,**kwargs) def text( x,y,text, **kwargs): kwargs['fontsize'] = 18 plt.text(x, y, text, **kwargs) if __name__ == '__main__': import numpy as np import matplotlib.pyplot as plt from matplotlib.path import Path import matplotlib.patches as patches face = Face('./Vera.ttf') face.set_char_size( 32*64 ) face.load_char('g') slot = face.glyph bitmap = slot.bitmap width = slot.bitmap.width rows = slot.bitmap.rows pitch = slot.bitmap.pitch outline= slot.outline start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour for i in range(len(outline.contours)): end = outline.contours[i] points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0]) segments = [ [points[0],], ] for j in range(1, len(points) ): segments[-1].append(points[j]) if tags[j] & (1 << 0) and j < (len(points)-1): segments.append( [points[j],] ) verts = [points[0], ] codes = [Path.MOVETO,] for segment in segments: if len(segment) == 2: verts.extend(segment[1:]) codes.extend([Path.LINETO]) elif len(segment) == 3: verts.extend(segment[1:]) codes.extend([Path.CURVE3, Path.CURVE3]) else: verts.append(segment[1]) codes.append(Path.CURVE3) for i in range(1,len(segment)-2): A,B = segment[i], segment[i+1] C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0) verts.extend([ C, B ]) codes.extend([ Path.CURVE3, Path.CURVE3]) verts.append(segment[-1]) codes.append(Path.CURVE3) VERTS.extend(verts) CODES.extend(codes) start = end+1 VERTS = np.array(VERTS) x,y = VERTS[:,0], VERTS[:,1] VERTS[:,0], VERTS[:,1] = x, y path = Path(VERTS, CODES) xmin, xmax = x.min(), x.max() ymin, ymax = y.min(), y.max() width,height = xmax-xmin, ymax-ymin dw, dh = 0.2*width, 0.1*height bearing = xmin - slot.metrics.horiBearingX, ymin - slot.metrics.horiBearingY advance = slot.advance origin = bearing figure = plt.figure(figsize=(16,10), frameon=False, facecolor="white") axes = plt.subplot(121, frameon=False, aspect=1) glyph = patches.PathPatch(path, fill = True, facecolor='k', lw=0) plt.xlim(xmin - .25*width, xmax + .75*width) plt.ylim(ymin - .5*height, xmax + .75*height) plt.xticks([]), plt.yticks([]) axes.add_patch(glyph) # Y axis arrow(origin[0], ymin-dh, 0, height+3*dh) # X axis arrow(origin[0]-dw, 0, width+3*dw, 0) # origin point(0,0,50) text( -20, -20, "$origin$", va='top', ha='right') # Bounding box bbox = patches.Rectangle( (xmin,ymin), width, height, fill = False, lw=.5) axes.add_patch(bbox) # Width line(xmin, ymax, 0, 3*dh, linestyle="dotted") text( xmin, ymax+3.25*dh, "$x_{min}$", va='bottom', ha='center') line(xmax, ymax, 0, 3*dh, linestyle="dotted") text( xmax, ymax+3.25*dh, "$x_{max}$", va='bottom', ha='center') double_arrow(xmin, ymax+2.5*dh, width, 0) text(xmin+width/2., ymax+1.75*dh, "$width$", va='bottom', ha='center') # Height line(xmax, ymin, 3*dw, 0, linestyle="dotted") text(xmax+3.25*dw, ymin, "$y_{min}$", va='baseline', ha='left') line(xmax, ymax, 3*dw, 0, linestyle="dotted") text(xmax+3.25*dw, ymax, "$y_{max}$", va='baseline', ha='left') double_arrow(xmax+2.5*dw, ymin, 0, height) text(xmax+2.75*dw, ymin+height/2., "$height$", va='center', ha='left') # Advance point(advance.x,0,50) line(advance.x, 0, 0, ymin-dh, linestyle="dotted") arrow(0, ymin-.5*dh, advance.x, 0) text(advance.x/2., ymin-1.25*dh, "$advance$", va='bottom', ha='center') # Bearing Y arrow(xmax+.25*dw, 0, 0, ymax) text(xmax+.5*dw, ymax/2, "$Y_{bearing}$", va='center', ha='left') # Bearing X arrow(0, ymax/2., xmin, 0) text(-10, ymax/2, "$X_{bearing}$", va='baseline', ha='right') # ------------------------------------------------------------------------- axes = plt.subplot(122, frameon=False, aspect=1) glyph = patches.PathPatch(path, fill = True, facecolor='k', lw=0) axes.add_patch(glyph) plt.xlim(xmin - .25*width, xmax + .75*width) plt.ylim(ymin - .5*height, xmax + .75*height) plt.xticks([]), plt.yticks([]) advance = slot.metrics.vertAdvance x_bearing = slot.metrics.vertBearingX y_bearing = slot.metrics.vertBearingY # Y axis arrow(xmin-x_bearing, ymax+y_bearing+2*dh, 0, -advance-3*dh) # X axis arrow(xmin-2*dw, ymax+y_bearing, width+4*dw, 0) # origin point( xmin-x_bearing, ymax+y_bearing, 50) text( xmin-x_bearing-30, ymax+y_bearing+10, "$origin$", va='bottom', ha='right') # Bounding box bbox = patches.Rectangle( (xmin,ymin), width, height, fill = False, lw=.5) axes.add_patch(bbox) # # Advance point(xmin-x_bearing, ymax+y_bearing-advance, 50) line(xmin-x_bearing, ymax+y_bearing-advance, xmax-dw, 0, linestyle="dotted") arrow(xmax+dw, ymax+y_bearing, 0, -advance) text(xmax+1.25*dw, ymax+y_bearing-advance/2., "$advance$", va='baseline', ha='left') # Width line(xmin, ymin, 0, -4*dh, linestyle="dotted") text( xmin, ymin-4.25*dh, "$x_{min}$", va='top', ha='center') line(xmax, ymin, 0, -4*dh, linestyle="dotted") text( xmax, ymin-4.25*dh, "$x_{max}$", va='top', ha='center') double_arrow(xmin, ymin-3.5*dh, width, 0) text(xmin+width/2., ymin-3.75*dh, "$width$", va='top', ha='center') # Height line(xmin, ymin, -3*dw, 0, linestyle="dotted") text(xmin-1.5*dw, ymin, "$y_{min}$", va='baseline', ha='right') line(xmin, ymax, -3*dw, 0, linestyle="dotted") text(xmin-1.5*dw, ymax, "$y_{max}$", va='baseline', ha='right') double_arrow(xmin-.5*dw, ymin, 0, height) text(xmin-.75*dw, ymin+height/2., "$height$", va='center', ha='right') #point(xmin-x_bearing, ymax+y_bearing, 50) # Bearing Y arrow(xmax-.5*dw, ymax+y_bearing, 0, -y_bearing) text(xmax-.5*dw, ymax+y_bearing+.25*dh, "$Y_{bearing}$", va='bottom', ha='center') # # Bearing X line(xmin, ymax, 0, 3*dh, linestyle="dotted") arrow(xmin-x_bearing, ymax+y_bearing+dh, x_bearing, 0) text(xmin-.25*dw, ymax+y_bearing+dh, "$X_{bearing}$", va='baseline', ha='right') plt.savefig('glyph-metrics.pdf') plt.show() freetype-py-2.5.1/examples/ot-svg-draw-skia.py0000775000175000017500000000547514664131406021502 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # # OT-SVG example with Skia # # Copyright 2023 Hin-Tak Leung # Distributed under the terms of the new BSD license. # This is an older example which works on skia m87 with known limitations. # See "ot-svg-example-skia.py" for a full example which requires m117. # Limitation: # Skia-python bundles with Skia m87 (at time of writing this). # # Skia m88 is first version where SkSVG* is considered no longer experimental. # # Skia m103 is the first Skia build which contains 9cbadcd9280dc139af2f4d41d25a6c9a750e0302. # That introduces "SkSVGDOM::renderNode()" among other stuff, # necessary for rendering "some" OT-SVG fonts. Guess what, that commit # is titled "Add optional OT-SVG support to FreeType"! # # So the example below only works correctly for "some" glyphs in # "some other" OT-SVG fonts, and also with very limited functionality # beyond what is used below. # # The missing functionality (and support for beyond Skia m103) is filed # as skia-python issue #192. from freetype import * import skia if __name__ == '__main__': import sys execname = sys.argv[0] if len(sys.argv) < 2: print("Example usage: %s TrajanColor-Concept.otf" % execname) exit(1) face = Face(sys.argv[1]) face.set_char_size( 160*64 ) face.load_char('A', FT_LOAD_COLOR ) slot = face.glyph._FT_GlyphSlot if (face.glyph.format == FT_GLYPH_FORMAT_SVG): document = ctypes.cast(slot.contents.other, FT_SVG_Document) doc = ctypes.string_at(document.contents.svg_document, # not terminated size=document.contents.svg_document_length) d = skia.Data(doc) # skia-python #194 - the raw c++ api actually has a (ptr, len, bool) method! # Data() shouldn't be needed. m = skia.MemoryStream(d) h = skia.SVGDOM.MakeFromStream(m) WIDTH, HEIGHT = 160, 160 size = skia.Size() size.fHeight = WIDTH size.fWidth = HEIGHT h.setContainerSize(size) surface = skia.Surface(WIDTH * 2, HEIGHT) with surface as canvas: canvas.translate(0,HEIGHT) h.render(canvas) canvas.translate(WIDTH/4,0) h.render(canvas) canvas.translate(WIDTH/4,0) h.render(canvas) canvas.translate(WIDTH/4,0) h.render(canvas) canvas.translate(WIDTH/4,0) h.render(canvas) canvas.translate(WIDTH/4,0) h.render(canvas) surface.flushAndSubmit() image = surface.makeImageSnapshot() image.save("ot-svg-draw-skia.png", skia.kPNG) from PIL import Image Image.open("ot-svg-draw-skia.png").show() else: print("Not SVG glyph.format") freetype-py-2.5.1/examples/ot-svg-example.py0000775000175000017500000002163114664131406021243 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # # OT-SVG example # # Copyright 2023 Hin-Tak Leung # Distributed under the terms of the new BSD license. # This is largely a python re-write of freetype2-demos:src/rsvg-port.c . # It is designed to be embeddable as a module in another python script . # # To use, rename this to, for example "otsvg.py", then insert # # ''' # from otsvg import hooks # # library = get_handle() # FT_Property_Set( library, b"ot-svg", b"svg-hooks", byref(hooks) # ''' # # in your script, and add "FT_LOAD_COLOR | FT_LOAD_RENDER" # to load_glyph() or load_char() calls. As in "__main__" below, # but also in the longer example of hb-view-ot-svg.py # in https://github.com/HinTak/harfbuzz-python-demos/ . # # Limitation: it is necessary to have "_state" as a module-level global # partially (in svg_init/svg_free, not in svg_render/svg_preset_slot) # to stop python destroying it when execution is in the c-side. # # Note: # Strictly-speaking, cairo.FORMAT_ARGB32 is host-order, # while freetype.FT_PIXEL_MODE_BGRA is small-endian. They are # different on big-endian platforms. The below # works in all circumstances, only because the bitmap is both # generated by cairo at the beginning and also consumed # by cairo in the end. # # The use of "pythonapi.PyMemoryView_FromMemory" is flaky - # specific to CPython 3.3+. # # Uses librsvg 2.52+ only. Or deprecation warnings per run. # # Not using Rsvg.Handle.render_document() . # Rsvg.Handle.render_layer(..., None, ...) does the same work. # # The original C-code does not check # start_glyph_id <= glyph_index <= end_glyph_id.value . import gi gi.require_version('Rsvg', '2.0') from gi.repository import Rsvg as rsvg from freetype import * from cairo import * # cairo.Matrix shadows freetype.Matrix from math import ceil _state = None def svg_init(ctx): global _state _state = {} ctx.contents.value = _state return FT_Err_Ok def svg_free(ctx): global _state _state = None # "None" is strictly speaking a special pyobject, # this line does not do what it should, i.e. setting the # pointer to NULL. ctx.contents = None return # void def svg_render(slot, ctx): state = ctx.contents.value #pythonapi is imported from ctypes pythonapi.PyMemoryView_FromMemory.argtypes = (c_char_p, c_ssize_t, c_int) pythonapi.PyMemoryView_FromMemory.restype = py_object surface = ImageSurface.create_for_data( pythonapi.PyMemoryView_FromMemory(cast(slot.contents.bitmap.buffer, c_char_p), slot.contents.bitmap.rows * slot.contents.bitmap.pitch, 0x200), FORMAT_ARGB32, slot.contents.bitmap.width, slot.contents.bitmap.rows, slot.contents.bitmap.pitch ) cr = Context( surface ) cr.translate( -state['x'], -state['y'] ) cr.set_source_surface( state['rec_surface'] ) # 0,0 is default cr.paint() surface.flush() slot.contents.bitmap.pixel_mode = FT_PIXEL_MODE_BGRA slot.contents.bitmap.num_grays = 256 slot.contents.format = FT_GLYPH_FORMAT_BITMAP state['rec_surface'] = None # Let python destroy the surface return FT_Err_Ok def svg_preset_slot(slot, cached, ctx): state = ctx.contents.value document = ctypes.cast(slot.contents.other, FT_SVG_Document) metrics = SizeMetrics(document.contents.metrics) units_per_EM = FT_UShort(document.contents.units_per_EM) end_glyph_id = FT_UShort(document.contents.end_glyph_id) start_glyph_id = FT_UShort(document.contents.start_glyph_id) dimension_svg = rsvg.DimensionData() handle = rsvg.Handle.new_from_data( ctypes.string_at(document.contents.svg_document, # not terminated size=document.contents.svg_document_length) ) (out_has_width, out_width, out_has_height, out_height, out_has_viewbox, out_viewbox) = handle.get_intrinsic_dimensions() if ( out_has_viewbox == True ): dimension_svg.width = out_viewbox.width dimension_svg.height = out_viewbox.height else: # "out_has_width" and "out_has_height" are True always dimension_svg.width = units_per_EM.value dimension_svg.height = units_per_EM.value if (( out_width.length != 1) or (out_height.length != 1 )): dimension_svg.width = out_width.length dimension_svg.height = out_height.length x_svg_to_out = metrics.x_ppem / dimension_svg.width y_svg_to_out = metrics.y_ppem / dimension_svg.height state['rec_surface'] = RecordingSurface( Content.COLOR_ALPHA, None ) rec_cr = Context( state['rec_surface'] ) xx = document.contents.transform.xx / ( 1 << 16 ) xy = -document.contents.transform.xy / ( 1 << 16 ) yx = -document.contents.transform.yx / ( 1 << 16 ) yy = document.contents.transform.yy / ( 1 << 16 ) x0 = document.contents.delta.x / 64 * dimension_svg.width / metrics.x_ppem y0 = -document.contents.delta.y / 64 * dimension_svg.height / metrics.y_ppem transform_matrix = Matrix(xx, yx, xy, yy, x0, y0) # cairo.Matrix rec_cr.scale( x_svg_to_out, y_svg_to_out ) rec_cr.transform( transform_matrix ) viewport = rsvg.Rectangle() viewport.x = 0 viewport.y = 0 viewport.width = dimension_svg.width viewport.height = dimension_svg.height str = None # render whole document - not using Handle.render_document() if ( start_glyph_id.value < end_glyph_id.value ): str = "#glyph%u" % (slot.contents.glyph_index ) handle.render_layer( rec_cr, str, viewport ) (state['x'], state['y'], width, height) = state['rec_surface'].ink_extents() slot.contents.bitmap_left = int(state['x']) slot.contents.bitmap_top = int(-state['y']) slot.contents.bitmap.rows = ceil( height ) slot.contents.bitmap.width = ceil( width ) slot.contents.bitmap.pitch = slot.contents.bitmap.width * 4 slot.contents.bitmap.pixel_mode = FT_PIXEL_MODE_BGRA metrics_width = width metrics_height = height horiBearingX = state['x'] horiBearingY = -state['y'] vertBearingX = slot.contents.metrics.horiBearingX / 64.0 - slot.contents.metrics.horiAdvance / 64.0 / 2 vertBearingY = ( slot.contents.metrics.vertAdvance / 64.0 - slot.contents.metrics.height / 64.0 ) / 2 slot.contents.metrics.width = int(round( metrics_width * 64 )) slot.contents.metrics.height = int(round( metrics_height * 64 )) slot.contents.metrics.horiBearingX = int( horiBearingX * 64 ) slot.contents.metrics.horiBearingY = int( horiBearingY * 64 ) slot.contents.metrics.vertBearingX = int( vertBearingX * 64 ) slot.contents.metrics.vertBearingY = int( vertBearingY * 64 ) if ( slot.contents.metrics.vertAdvance == 0 ): slot.contents.metrics.vertAdvance = int( metrics_height * 1.2 * 64 ) if ( cached == False ): state['rec_surface'] = None state['x'] = 0 state['y'] = 0 return FT_Err_Ok hooks = SVG_RendererHooks(svg_init=SVG_Lib_Init_Func(svg_init), svg_free=SVG_Lib_Free_Func(svg_free), svg_render=SVG_Lib_Render_Func(svg_render), svg_preset_slot=SVG_Lib_Preset_Slot_Func(svg_preset_slot)) if __name__ == '__main__': import sys execname = sys.argv[0] if len(sys.argv) < 2: print("Example usage: %s TrajanColor-Concept.otf" % execname) exit(1) face = Face(sys.argv[1]) face.set_char_size( 160*64 ) library = get_handle() FT_Property_Set( library, b"ot-svg", b"svg-hooks", byref(hooks) ) # python 3 only syntax face.load_char('A', FT_LOAD_COLOR | FT_LOAD_RENDER ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows if ( face.glyph.bitmap.pitch != width * 4 ): raise RuntimeError('pitch != width * 4 for color bitmap: Please report this.') I = ImageSurface.create_for_data( pythonapi.PyMemoryView_FromMemory(cast(bitmap._FT_Bitmap.buffer, c_char_p), bitmap.rows * bitmap.pitch, 0x200), # Read-Write FORMAT_ARGB32, width, rows, bitmap.pitch ) surface = ImageSurface(FORMAT_ARGB32, 2*width, rows) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) ctx.paint() ctx.set_source_surface(I, width/2, 0) ctx.paint() ctx.set_source_surface(I, width , 0) ctx.paint() surface.write_to_png("ot-svg-example.png") from PIL import Image Image.open("ot-svg-example.png").show() freetype-py-2.5.1/examples/glyph-vector-cairo.py0000775000175000017500000001315714664131406022115 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-vector example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - The code is incomplete and over-simplified, as it ignores the 3rd order # bezier curve bit when intepolating between off-curve points. # This is only correct for truetype fonts (which only use 2nd order bezier curves). # - Also it seems to assume the first point is always on curve; this is # unusual but legal. # # Can cope with well-behaved Postscript/CFF fonts too. # # ----------------------------------------------------------------------------- ''' Show how to access glyph outline description. ''' from freetype import * # using Matrix class from Cairo, instead of FreeType's from cairo import Context, ImageSurface, FORMAT_ARGB32, Matrix # use math.pi for drawing circles import math if __name__ == '__main__': import numpy from PIL import Image # Replacement for Path enums: STOP, MOVETO, LINETO, CURVE3, CURVE4 = 0, 1, 2, 3, 4 face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S') slot = face.glyph outline = slot.outline points = numpy.array(outline.points, dtype=[('x',float), ('y',float)]) x, y = points['x'], points['y'] cbox = outline.get_cbox() surface = ImageSurface(FORMAT_ARGB32, (cbox.xMax - cbox.xMin)//4 + 20, (cbox.yMax - cbox.yMin)//4 + 20) ctx = Context(surface) ctx.scale(0.25,0.25) ctx.translate(-cbox.xMin + 40,-cbox.yMin + 40) ctx.transform(Matrix(1,0,0,-1)) ctx.translate(0, -(cbox.yMax + cbox.yMin)) # difference! Curve_Tag = [FT_Curve_Tag(tag) for tag in outline.tags] start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour ctx.set_source_rgb(0.5,0.5,0.5) for i in range(len(outline.contours)): end = outline.contours[i] ctx.move_to(outline.points[start][0],outline.points[start][1]) for j in range(start, end+1): point = outline.points[j] ctx.line_to(point[0],point[1]) #back to origin ctx.line_to(outline.points[start][0], outline.points[start][1]) start = end+1 ctx.fill_preserve() ctx.set_source_rgb(0,1,0) ctx.stroke() start, end = 0, 0 for i in range(len(outline.contours)): end = outline.contours[i] ctx.new_path() ctx.set_source_rgb(0,0,1) for j in range(start, end+1): if ( Curve_Tag[j] == FT_Curve_Tag_On ): point = outline.points[j] ctx.move_to(point[0],point[1]) ctx.arc(point[0], point[1], 40, 0, 2 * math.pi) ctx.fill() ctx.new_path() ctx.set_source_rgb(1,0,0) for j in range(start, end+1): if ( Curve_Tag[j] != FT_Curve_Tag_On ): point = outline.points[j] ctx.move_to(point[0],point[1]) ctx.arc(point[0], point[1], 10, 0, 2 * math.pi) ctx.fill() points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0]) segments = [ [points[0],], ] for j in range(1, len(points) ): segments[-1].append(points[j]) if ( FT_Curve_Tag( tags[j] ) == FT_Curve_Tag_On ) and j < (len(points)-1): segments.append( [points[j],] ) verts = [points[0], ] codes = [MOVETO,] tags.pop() for segment in segments: if len(segment) == 2: verts.extend(segment[1:]) codes.extend([LINETO]) elif len(segment) == 3: verts.extend(segment[1:]) codes.extend([CURVE3, CURVE3]) elif ( len(segment) == 4 ) \ and ( FT_Curve_Tag(tags[1]) == FT_Curve_Tag_Cubic ) \ and ( FT_Curve_Tag(tags[2]) == FT_Curve_Tag_Cubic ): verts.extend(segment[1:]) codes.extend([CURVE4, CURVE4, CURVE4]) else: # Intepolation code verts.append(segment[1]) codes.append(CURVE3) for i in range(1,len(segment)-2): A,B = segment[i], segment[i+1] C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0) verts.extend([ C, B ]) codes.extend([ CURVE3, CURVE3]) verts.append(segment[-1]) codes.append(CURVE3) [tags.pop() for x in range(len(segment) - 1)] VERTS.extend(verts) CODES.extend(codes) start = end+1 ctx.new_path() ctx.set_source_rgba(1,1,0, 0.5) i = 0 while (i < len(CODES)): if (CODES[i] == MOVETO): ctx.move_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == LINETO): ctx.line_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == CURVE3): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], # undocumented VERTS[i+1][0],VERTS[i+1][1]) i += 2 elif (CODES[i] == CURVE4): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], VERTS[i+2][0],VERTS[i+2][1]) i += 3 ctx.fill() surface.flush() surface.write_to_png("glyph-vector-cairo.png") Image.open("glyph-vector-cairo.png").show() freetype-py-2.5.1/examples/hello-vf.py0000664000175000017500000000427414664131406020110 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # Variable Font example - Copyright 2020 Josh Hadley, based on hello-world.py # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./SourceSansVariable-Roman.otf') text = 'Hello variable fonts!' face.set_char_size( 48*64 ) slot = face.glyph face.set_var_design_coords((900,)) # set to widest for width calc. # First pass to compute bbox width, height, baseline = 0, 0, 0 previous = 0 for i,c in enumerate(text): face.load_char(c) bitmap = slot.bitmap height = max(height, bitmap.rows + max(0,-(slot.bitmap_top-bitmap.rows))) baseline = max(baseline, max(0,-(slot.bitmap_top-bitmap.rows))) kerning = face.get_kerning(previous, c) width += (slot.advance.x >> 6) + (kerning.x >> 6) previous = c height *= 12 Z = numpy.zeros((height,width), dtype=numpy.ubyte) # Second pass for actual rendering. Iterate through some weight axis values # and render the result, one per line. for i, wght in enumerate((900, 750, 675, 600, 500, 450, 325, 275, 100)): face.set_var_design_coords((wght,)) # set the weight axis value using "design coords" x, y = 0, 0 previous = 0 for c in text: face.load_char(c) bitmap = slot.bitmap top = slot.bitmap_top left = slot.bitmap_left w,h = bitmap.width, bitmap.rows y = (height - baseline - top) - (i * 48) kerning = face.get_kerning(previous, c) x += (kerning.x >> 6) Z[y:y+h,x+left:x+left+w] += numpy.array(bitmap.buffer, dtype='ubyte').reshape(h,w) x += (slot.advance.x >> 6) previous = c plt.figure(figsize=(10, 10*Z.shape[0]/float(Z.shape[1]))) plt.imshow(Z, interpolation='nearest', origin='upper', cmap=plt.cm.gray) plt.xticks([]), plt.yticks([]) plt.show() freetype-py-2.5.1/examples/wordle-cairo.py0000775000175000017500000001433414664131406020764 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based wordle example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - Cairo can paint partly off-screen, so this example does! # # This example behaves differently under pycairo 1.11+ (released in 2017-04-09). # Auto-checked. On older pycairo, it does not draw partial patterns at the edges. # Also, Suface.get_data() is not in the "python 3, pycairo < 1.11" combination. # # ----------------------------------------------------------------------------- from math import cos, sin from numpy import random, sort, sqrt, ndarray, ubyte from freetype import * try: # pycairo 1.11+: from cairo import Region, RectangleInt, REGION_OVERLAP_OUT except ImportError: # stubs for pycairo < 1.11: class Region: def __init__(self): return def union(self, rec): return def contains_rectangle(self, rec): # inhibit drawing return True class RectangleInt: def __init__(self, x, y, w, h): return REGION_OVERLAP_OUT = False from cairo import Context, ImageSurface, FORMAT_A8, FORMAT_ARGB32, Matrix from bitmap_to_surface import make_image_surface def make_label(text, filename, size=12, angle=0): ''' Parameters: ----------- text : string Text to be displayed filename : string Path to a font size : int Font size in 1/64th points angle : float Text angle in degrees ''' face = Face(filename) face.set_char_size( size*64 ) # FT_Angle is a 16.16 fixed-point value expressed in degrees. angle = FT_Angle(angle * 65536) matrix = FT_Matrix( FT_Cos( angle ), - FT_Sin( angle ), FT_Sin( angle ) , FT_Cos( angle ) ) flags = FT_LOAD_RENDER pen = FT_Vector(0,0) FT_Set_Transform( face._FT_Face, byref(matrix), byref(pen) ) previous = 0 xmin, xmax = 0, 0 ymin, ymax = 0, 0 for c in text: face.load_char(c, flags) kerning = face.get_kerning(previous, c) previous = c bitmap = face.glyph.bitmap pitch = face.glyph.bitmap.pitch width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows top = face.glyph.bitmap_top left = face.glyph.bitmap_left pen.x += kerning.x x0 = (pen.x >> 6) + left x1 = x0 + width y0 = (pen.y >> 6) - (rows - top) y1 = y0 + rows xmin, xmax = min(xmin, x0), max(xmax, x1) ymin, ymax = min(ymin, y0), max(ymax, y1) pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L = ImageSurface(FORMAT_A8, xmax-xmin, ymax-ymin) previous = 0 pen.x, pen.y = 0, 0 ctx = Context(L) for c in text: face.load_char(c, flags) kerning = face.get_kerning(previous, c) previous = c bitmap = face.glyph.bitmap pitch = face.glyph.bitmap.pitch width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows top = face.glyph.bitmap_top left = face.glyph.bitmap_left pen.x += kerning.x x = (pen.x >> 6) - xmin + left y = - (pen.y >> 6) + ymax - top if (width > 0): glyph_surface = make_image_surface(face.glyph.bitmap) ctx.set_source_surface(glyph_surface, x, y) ctx.paint() pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L.flush() return L if __name__ == '__main__': from PIL import Image n_words = 200 H, W, dpi = 600, 800, 72.0 I = ImageSurface(FORMAT_A8, W, H) ctxI = Context(I) ctxI.rectangle(0,0,800,600) ctxI.set_source_rgba (0.9, 0.9, 0.9, 0) ctxI.fill() S = random.normal(0,1,n_words) S = (S-S.min())/(S.max()-S.min()) S = sort(1-sqrt(S))[::-1] sizes = (12 + S*48).astype(int).tolist() def spiral(): eccentricity = 1.5 radius = 8 step = 0.1 t = 0 while True: t += step yield eccentricity*radius*t*cos(t), radius*t*sin(t) drawn_regions = Region() for size in sizes: angle = random.randint(-25,25) try: L = make_label('Hello', './Vera.ttf', size, angle=angle) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") h = L.get_height() w = L.get_width() if h < H and w < W: x0 = W//2 + (random.uniform()-.1)*50 y0 = H//2 + (random.uniform()-.1)*50 for dx,dy in spiral(): c = .25+.75*random.random() x = int(x0+dx) y = int(y0+dy) checked = False I.flush() if not (x <= w//2 or y <= h//2 or x >= (W-w//2) or y >= (H-h//2)): ndI = ndarray(shape=(h,w), buffer=I.get_data(), dtype=ubyte, order='C', offset=(x-w//2) + I.get_stride() * (y-h//2), strides=[I.get_stride(), 1]) ndL = ndarray(shape=(h,w), buffer=L.get_data(), dtype=ubyte, order='C', strides=[L.get_stride(), 1]) if ((ndI * ndL).sum() == 0): checked = True new_region = RectangleInt(x-w//2, y-h//2, w, h) if (checked or ( drawn_regions.contains_rectangle(new_region) == REGION_OVERLAP_OUT )): ctxI.set_source_surface(L, 0, 0) pattern = ctxI.get_source() scalematrix = Matrix() scalematrix.scale(1.0,1.0) scalematrix.translate(w//2 - x, h//2 - y) pattern.set_matrix(scalematrix) ctxI.set_source_rgba(c,c,c,c) ctxI.mask(pattern) drawn_regions.union(new_region) break I.flush() I.write_to_png("wordle-cairo.png") Image.open("wordle-cairo.png").show() freetype-py-2.5.1/examples/bitmap_to_surface.py0000664000175000017500000000764314664131406022065 0ustar georgeskgeorgesk# FT_Bitmap to CAIRO_SURFACE_TYPE_IMAGE module # ============================================ # # Copyright 2017 Hin-Tak Leung # # FreeType is under FTL (BSD license with an advertising clause) or GPLv2+. # Cairo is under LGPLv2 or MPLv1.1. # # This is a heavily modified copy of a few routines from Lawrence D'Oliveiro[1], # adjusted for freetype-py, and bugfix/workaround for mono-rendering [2]. # # The bugfix/workaround requires libtiff on small-endian platforms. # # TODO: Look into using FreeType's FT_Bitmap_Convert() instead. However, libtiff # is common enough, and probably not important. # #[1] https://github.com/ldo/python_freetype # https://github.com/ldo/python_freetype_examples # #[2] https://github.com/ldo/python_freetype/issues/1 # https://github.com/ldo/python_freetype_examples/issues/1 # ''' FT_Bitmap to CAIRO_SURFACE_TYPE_IMAGE module ============================================ Converting from Freetype's FT_Bitmap to Cairo's CAIRO_SURFACE_TYPE_IMAGE Usage: from bitmap_to_surface import make_image_surface Works with cairocffi too. (Replace "from cairo ..." with "from cairocffi ...") Limitation: Surface.create_for_data is not in the "python 3, pycairo < 1.11" combo. ''' from freetype import FT_PIXEL_MODE_MONO, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_BGRA, FT_Pointer, FT_Bitmap from cairo import ImageSurface, FORMAT_A1, FORMAT_A8, FORMAT_ARGB32 #from cairocffi import ImageSurface, FORMAT_A1, FORMAT_A8, FORMAT_ARGB32 from array import array from ctypes import cast, memmove, CDLL, c_void_p, c_int from sys import byteorder def make_image_surface(bitmap, copy = True) : if ( type(bitmap) == FT_Bitmap ): # bare FT_Bitmap content = bitmap else: # wrapped Bitmap instance content = bitmap._FT_Bitmap "creates a Cairo ImageSurface containing (a copy of) the Bitmap pixels." if content.pixel_mode == FT_PIXEL_MODE_MONO : cairo_format = FORMAT_A1 elif content.pixel_mode == FT_PIXEL_MODE_GRAY : cairo_format = FORMAT_A8 elif content.pixel_mode == FT_PIXEL_MODE_BGRA : # small-endian cairo_format = FORMAT_ARGB32 # platform native else : raise NotImplementedError("unsupported bitmap format %d" % content.pixel_mode) src_pitch = content.pitch dst_pitch = ImageSurface.format_stride_for_width(cairo_format, content.width) if not copy and dst_pitch == src_pitch and content.buffer != None : pixels = content.buffer else : pixels = to_array(content, content.pixel_mode, dst_pitch) result = ImageSurface.create_for_data( pixels, cairo_format, content.width, content.rows, dst_pitch) return result def to_array(content, pixel_mode, dst_pitch = None) : "returns a Python array object containing a copy of the Bitmap pixels." if dst_pitch == None : dst_pitch = content.pitch buffer_size = content.rows * dst_pitch buffer = array("B", b"0" * buffer_size) dstaddr = buffer.buffer_info()[0] srcaddr = cast(content.buffer, FT_Pointer).value src_pitch = content.pitch if dst_pitch == src_pitch : memmove(dstaddr, srcaddr, buffer_size) else : # have to copy a row at a time if src_pitch < 0 or dst_pitch < 0 : raise NotImplementedError("can't cope with negative bitmap pitch") assert dst_pitch > src_pitch for i in range(content.rows) : memmove(dstaddr, srcaddr, src_pitch) dstaddr += dst_pitch srcaddr += src_pitch # pillow/PIL itself requires libtiff so it is assumed to be around. # swap the bit-order from freetype's (MSB) to cairo's (host order) if needed if ( ( byteorder == 'little' ) and (pixel_mode == FT_PIXEL_MODE_MONO ) ): libtiff = CDLL("libtiff.so.5") libtiff.TIFFReverseBits.restype = None libtiff.TIFFReverseBits.argtypes = (c_void_p, c_int) libtiff.TIFFReverseBits(buffer.buffer_info()[0], buffer_size) return buffer freetype-py-2.5.1/examples/subpixel-positioning.py0000664000175000017500000001631714664131406022570 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Subpixel rendering AND positioning using OpenGL and shaders. ''' import numpy as np import OpenGL.GL as gl import OpenGL.GLUT as glut from texture_font import TextureFont, TextureAtlas from shader import Shader vert=''' uniform sampler2D texture; uniform vec2 pixel; attribute float modulo; varying float m; void main() { gl_FrontColor = gl_Color; gl_TexCoord[0].xy = gl_MultiTexCoord0.xy; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; m = modulo; } ''' frag=''' uniform sampler2D texture; uniform vec2 pixel; varying float m; void main() { float gamma = 1.0; vec2 uv = gl_TexCoord[0].xy; vec4 current = texture2D(texture, uv); vec4 previous= texture2D(texture, uv+vec2(-1,0)*pixel); current = pow(current, vec4(1.0/gamma)); previous = pow(previous, vec4(1.0/gamma)); float r = current.r; float g = current.g; float b = current.b; float a = current.a; if( m <= 0.333 ) { float z = m/0.333; r = mix(current.r, previous.b, z); g = mix(current.g, current.r, z); b = mix(current.b, current.g, z); } else if( m <= 0.666 ) { float z = (m-0.33)/0.333; r = mix(previous.b, previous.g, z); g = mix(current.r, previous.b, z); b = mix(current.g, current.r, z); } else if( m < 1.0 ) { float z = (m-0.66)/0.334; r = mix(previous.g, previous.r, z); g = mix(previous.b, previous.g, z); b = mix(current.r, previous.b, z); } float t = max(max(r,g),b); vec4 color = vec4(0.,0.,0., (r+g+b)/2.); color = t*color + (1.-t)*vec4(r,g,b, min(min(r,g),b)); gl_FragColor = vec4( color.rgb, color.a); } ''' class Label: def __init__(self, text, font, color=(1.0, 1.0, 1.0, 0.0), x=0, y=0, width=None, height=None, anchor_x='left', anchor_y='baseline'): self.text = text self.vertices = np.zeros((len(text)*4,3), dtype=np.float32) self.indices = np.zeros((len(text)*6, ), dtype=np.uint) self.colors = np.zeros((len(text)*4,4), dtype=np.float32) self.texcoords= np.zeros((len(text)*4,2), dtype=np.float32) self.attrib = np.zeros((len(text)*4,1), dtype=np.float32) pen = [x,y] prev = None for i,charcode in enumerate(text): glyph = font[charcode] kerning = glyph.get_kerning(prev) x0 = pen[0] + glyph.offset[0] + kerning dx = x0-int(x0) x0 = int(x0) y0 = pen[1] + glyph.offset[1] x1 = x0 + glyph.size[0] y1 = y0 - glyph.size[1] u0 = glyph.texcoords[0] v0 = glyph.texcoords[1] u1 = glyph.texcoords[2] v1 = glyph.texcoords[3] index = i*4 indices = [index, index+1, index+2, index, index+2, index+3] vertices = [[x0,y0,1],[x0,y1,1],[x1,y1,1], [x1,y0,1]] texcoords = [[u0,v0],[u0,v1],[u1,v1], [u1,v0]] colors = [color,]*4 self.vertices[i*4:i*4+4] = vertices self.indices[i*6:i*6+6] = indices self.texcoords[i*4:i*4+4] = texcoords self.colors[i*4:i*4+4] = colors self.attrib[i*4:i*4+4] = dx pen[0] = pen[0]+glyph.advance[0]/64.0 + kerning pen[1] = pen[1]+glyph.advance[1]/64.0 prev = charcode width = pen[0]-glyph.advance[0]/64.0+glyph.size[0] if anchor_y == 'top': dy = -round(font.ascender) elif anchor_y == 'center': dy = +round(-font.height/2-font.descender) elif anchor_y == 'bottom': dy = -round(font.descender) else: dy = 0 if anchor_x == 'right': dx = -width/1.0 elif anchor_x == 'center': dx = -width/2.0 else: dx = 0 self.vertices += (round(dx), round(dy), 0) def draw(self): gl.glEnable( gl.GL_TEXTURE_2D ) gl.glDisable( gl.GL_DEPTH_TEST ) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glEnableClientState(gl.GL_COLOR_ARRAY) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertices) gl.glColorPointer(4, gl.GL_FLOAT, 0, self.colors) gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, self.texcoords) r,g,b = 0,0,0 gl.glColor( 1, 1, 1, 1 ) gl.glEnable( gl.GL_BLEND ) #gl.glBlendFunc( gl.GL_CONSTANT_COLOR_EXT, gl.GL_ONE_MINUS_SRC_COLOR ) #gl.glBlendColor(r,g,b,1) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) gl.glBlendColor( 1, 1, 1, 1 ) gl.glEnableVertexAttribArray( 1 ); gl.glVertexAttribPointer( 1, 1, gl.GL_FLOAT, gl.GL_FALSE, 0, self.attrib) shader.bind() shader.uniformi('texture', 0) shader.uniformf('pixel', 1.0/512, 1.0/512) gl.glDrawElements(gl.GL_TRIANGLES, len(self.indices), gl.GL_UNSIGNED_INT, self.indices) shader.unbind() gl.glDisableVertexAttribArray( 1 ); gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_COLOR_ARRAY) gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glDisable( gl.GL_TEXTURE_2D ) gl.glDisable( gl.GL_BLEND ) if __name__ == '__main__': import sys atlas = TextureAtlas(512,512,3) def on_display( ): #gl.glClearColor(0,0,0,1) gl.glClearColor(1,1,1,1) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glBindTexture( gl.GL_TEXTURE_2D, atlas.texid ) for label in labels: label.draw() gl.glColor(0,0,0,1) gl.glBegin(gl.GL_LINES) gl.glVertex2i(15,0) gl.glVertex2i(15, 330) gl.glVertex2i(225, 0) gl.glVertex2i(225, 330) gl.glEnd() glut.glutSwapBuffers( ) def on_reshape( width, height ): gl.glViewport( 0, 0, width, height ) gl.glMatrixMode( gl.GL_PROJECTION ) gl.glLoadIdentity( ) gl.glOrtho( 0, width, 0, height, -1, 1 ) gl.glMatrixMode( gl.GL_MODELVIEW ) gl.glLoadIdentity( ) def on_keyboard( key, x, y ): if key == '\033': sys.exit( ) glut.glutInit( sys.argv ) glut.glutInitDisplayMode( glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH ) glut.glutCreateWindow( "Freetype OpenGL" ) glut.glutReshapeWindow( 240, 330 ) glut.glutDisplayFunc( on_display ) glut.glutReshapeFunc( on_reshape ) glut.glutKeyboardFunc( on_keyboard ) font = TextureFont(atlas, './Vera.ttf', 9) text = "|... A Quick Brown Fox Jumps Over The Lazy Dog" labels = [] x,y = 20,310 for i in range(30): labels.append(Label(text=text, font=font, x=x, y=y)) x += 0.1000000000001 y -= 10 atlas.upload() shader = Shader(vert,frag) glut.glutMainLoop( ) freetype-py-2.5.1/examples/hello-world-cairo.py0000775000175000017500000000376214664131406021723 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based "Hello World" example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # # ----------------------------------------------------------------------------- from freetype import * from cairo import Context, ImageSurface, FORMAT_A8 from bitmap_to_surface import make_image_surface if __name__ == '__main__': from PIL import Image face = Face('./Vera.ttf') text = 'Hello World !' face.set_char_size( 48*64 ) slot = face.glyph # First pass to compute bbox width, height, baseline = 0, 0, 0 previous = 0 for i,c in enumerate(text): face.load_char(c) bitmap = slot.bitmap height = max(height, bitmap.rows + max(0,-(slot.bitmap_top-bitmap.rows))) baseline = max(baseline, max(0,-(slot.bitmap_top-bitmap.rows))) kerning = face.get_kerning(previous, c) width += (slot.advance.x >> 6) + (kerning.x >> 6) previous = c Z = ImageSurface(FORMAT_A8, width, height) ctx = Context(Z) # Second pass for actual rendering x, y = 0, 0 previous = 0 for c in text: face.load_char(c) bitmap = slot.bitmap top = slot.bitmap_top left = slot.bitmap_left w,h = bitmap.width, bitmap.rows y = height-baseline-top kerning = face.get_kerning(previous, c) x += (kerning.x >> 6) # cairo does not like zero-width bitmap from the space character! if (bitmap.width > 0): glyph_surface = make_image_surface(face.glyph.bitmap) ctx.set_source_surface(glyph_surface, x+left, y) ctx.paint() x += (slot.advance.x >> 6) previous = c Z.flush() Z.write_to_png("hello-world-cairo.png") Image.open("hello-world-cairo.png").show() freetype-py-2.5.1/examples/outline-test.py0000775000175000017500000000753014664131406021031 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Basic outline wrapper test ''' from freetype import * import ctypes import contextlib @contextlib.contextmanager def new_outline(n_points, n_contours): library = get_handle() raw_ft_outline = FT_Outline() err = FT_Outline_New( library, FT_UInt(n_points), FT_Int(n_contours), ctypes.byref(raw_ft_outline) ) if err: raise FT_Exception(err) try: raw_ft_outline.n_points = 0 raw_ft_outline.n_contours = 0 yield Outline(raw_ft_outline) finally: FT_Outline_Done(library, ctypes.byref(raw_ft_outline)) if __name__ == '__main__': face = Face('./Vera.ttf') face.set_char_size( 4*48*64 ) flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph outline = slot.outline bbox = outline.get_bbox() cbox = outline.get_cbox() assert (bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax) == \ (810, -192, 7116, 9152) assert (cbox.xMin, cbox.yMin, cbox.xMax, cbox.yMax) == \ (810, -192, 7116, 9152) assert outline.get_outside_border() == 0 assert outline.get_inside_border() == 1 assert len(outline.contours) == 1 assert len(outline.points) == 40 assert len(outline.tags) == 40 stroker = Stroker() stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0) stroker.parse_outline(outline, False) n_points, n_contours = stroker.get_counts() with new_outline(n_points, n_contours) as stroked_outline: stroker.export(stroked_outline) bbox = stroked_outline.get_bbox() cbox = stroked_outline.get_cbox() assert (bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax) == \ (746, -256, 7180, 9216) assert (cbox.xMin, cbox.yMin, cbox.xMax, cbox.yMax) == \ (746, -256, 7180, 9216) assert stroked_outline.get_outside_border() == 0 assert stroked_outline.get_inside_border() == 1 assert len(stroked_outline.contours) == 2 assert len(stroked_outline.points) == 225 assert len(stroked_outline.tags) == 225 border = outline.get_outside_border() n_points, n_contours = stroker.get_border_counts(border) with new_outline(n_points, n_contours) as outer_outline: stroker.export_border(border, outer_outline) bbox = outer_outline.get_bbox() cbox = outer_outline.get_cbox() assert (bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax) == \ (746, -256, 7180, 9216) assert (cbox.xMin, cbox.yMin, cbox.xMax, cbox.yMax) == \ (746, -256, 7180, 9216) assert outer_outline.get_outside_border() == 0 assert outer_outline.get_inside_border() == 1 assert len(outer_outline.contours) == 1 assert len(outer_outline.points) == 121 assert len(outer_outline.tags) == 121 border = outline.get_inside_border() n_points, n_contours = stroker.get_border_counts(border) with new_outline(n_points, n_contours) as inner_outline: stroker.export_border(border, inner_outline) bbox = inner_outline.get_bbox() cbox = inner_outline.get_cbox() assert (bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax) == \ (813, -128, 7052, 9088) assert (cbox.xMin, cbox.yMin, cbox.xMax, cbox.yMax) == \ (813, -128, 7052, 9088) assert inner_outline.get_outside_border() == 1 assert inner_outline.get_inside_border() == 0 assert len(inner_outline.contours) == 1 assert len(inner_outline.points) == 104 assert len(inner_outline.tags) == 104 freetype-py-2.5.1/examples/glyph-color-cairo.py0000775000175000017500000000566514664131406021736 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-color example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - The two side-glyphs are positioned only roughly equivalently. # # ----------------------------------------------------------------------------- ''' Glyph colored rendering (with outline) ''' from freetype import * # using Matrix class from Cairo, instead of FreeType's from cairo import Context, ImageSurface, FORMAT_ARGB32, SurfacePattern, FILTER_BEST, Matrix from bitmap_to_surface import make_image_surface if __name__ == '__main__': from PIL import Image face = Face('./Vera.ttf') face.set_char_size( 96*64 ) # Outline flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph glyph = slot.get_glyph() stroker = Stroker( ) stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ) glyph.stroke( stroker , True ) del stroker blyph = glyph.to_bitmap(FT_RENDER_MODE_NORMAL, Vector(0,0), True ) bitmap = blyph.bitmap widthZ, rowsZ, pitch = bitmap.width, bitmap.rows, bitmap.pitch Z = make_image_surface(bitmap) # Plain flags = FT_LOAD_RENDER face.load_char('S', flags) bitmap = face.glyph.bitmap widthF, rowsF, pitch = bitmap.width, bitmap.rows, bitmap.pitch F = make_image_surface(bitmap) # Draw surface = ImageSurface(FORMAT_ARGB32, 1200, 500) ctx = Context(surface) # fill background as gray ctx.rectangle(0,0,1200,500) ctx.set_source_rgb (0.5 , 0.5, 0.5) ctx.fill() # use the stroked font's size as scale, as it is likely slightly larger scale = 400.0 / rowsZ # draw bitmap first ctx.set_source_surface(F, 0, 0) patternF = ctx.get_source() SurfacePattern.set_filter(patternF, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(600.0 - widthF *scale /2.0 ), -50) patternF.set_matrix(scalematrix) ctx.set_source_rgb (1 , 1, 0) ctx.mask(patternF) ctx.fill() scalematrix.translate(+400,0) patternF.set_matrix(scalematrix) ctx.mask(patternF) ctx.fill() # stroke on top ctx.set_source_surface(Z, 0, 0) patternZ = ctx.get_source() SurfacePattern.set_filter(patternZ, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(600.0 - widthZ *scale /2.0 ), -50) patternZ.set_matrix(scalematrix) ctx.set_source_rgb (1 , 0, 0) ctx.mask(patternZ) ctx.fill() scalematrix.translate(-400,0) patternZ.set_matrix(scalematrix) ctx.mask(patternZ) ctx.fill() surface.flush() surface.write_to_png("glyph-color-cairo.png") Image.open("glyph-color-cairo.png").show() freetype-py-2.5.1/examples/glyph-vector-decompose.py0000664000175000017500000000244014664131406022764 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright 2018 Dean Serenevy # SPDX-License-Identifier: BSD-3-Clause-Clear ''' Show how to use outline decompose. ''' import os import sys sys.path.append(os.path.dirname(__file__)) sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import freetype def move_to(a, ctx): ctx.append("M {},{}".format(a.x, a.y)) def line_to(a, ctx): ctx.append("L {},{}".format(a.x, a.y)) def conic_to(a, b, ctx): ctx.append("Q {},{} {},{}".format(a.x, a.y, b.x, b.y)) def cubic_to(a, b, c, ctx): ctx.append("C {},{} {},{} {},{}".format(a.x, a.y, b.x, b.y, c.x, c.y)) if __name__ == '__main__': face = freetype.Face('./Vera.ttf') face.set_char_size( 18*64 ) face.load_char('B', freetype.FT_LOAD_DEFAULT | freetype.FT_LOAD_NO_BITMAP) ctx = [] face.glyph.outline.decompose(ctx, move_to=move_to, line_to=line_to, conic_to=conic_to, cubic_to=cubic_to) print(""" """.format(" ".join(ctx))) freetype-py-2.5.1/examples/emoji-color-cairo.py0000775000175000017500000000564414664131406021713 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # # pycairo/cairocffi-based emoji-color example - Copyright 2017-2023 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # This script demonstrates overlapping emojis. # # There are 4 kinds. sbix (Apple's) and CBDT/CBLC (Google's) only work # at specific sizes; OT-SVG (Adobe/Mozilla's) and COLR v0 (Microsoft's) # work at arbitrary sizes, but need the FT_LOAD_RENDER flags (this has # no effect on sbix and CBDT/CBLC, so can be added). It is added below # so this would work as is for COLR v0 (Microsoft's). In addition, # OT-SVG needs an external render. See ot-svg-example.py and comments # inside. Basically you need 3 more lines (rename "ot-svg-example.py" as # "otsvg.py", then add 3 lines "from otsvg import hooks", # get library handle, set the "ot-svg" "svg-hooks" property, to load it) # # Note: On Mac OS X before Sierra (10.12), change ttc->ttf; # try Google's NotoColorEmoji.ttf at size 109 on Linux. # # Updated 2023, now somewhat specific to pycairo and CPython 3.3+, # and also small-endian (from FORMAT_ARGB32 vs FT_PIXEL_MODE_BGRA), # but no longer needs numpy. # # Older 2017 version (depends on numpy): # Limitation: Suface.get_data() is not in the "python 3, pycairo < 1.11" combo. import freetype from PIL import Image from cairo import ImageSurface, FORMAT_ARGB32, Context face = freetype.Face("/System/Library/Fonts/Apple Color Emoji.ttc") # Not all char sizes are valid for emoji fonts; # Google's NotoColorEmoji only accept size 109 to get 136x128 bitmaps face.set_char_size( 160*64 ) face.load_char('😀', freetype.FT_LOAD_COLOR | freetype.FT_LOAD_RENDER) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows if ( face.glyph.bitmap.pitch != width * 4 ): raise RuntimeError('pitch != width * 4 for color bitmap: Please report this.') # See https://stackoverflow.com/questions/59574816/obtaining-a-memoryview-object-from-a-ctypes-c-void-p-object from ctypes import pythonapi, c_char_p, c_ssize_t, c_int, py_object, cast pythonapi.PyMemoryView_FromMemory.argtypes = (c_char_p, c_ssize_t, c_int) pythonapi.PyMemoryView_FromMemory.restype = py_object I = ImageSurface.create_for_data( pythonapi.PyMemoryView_FromMemory(cast(bitmap._FT_Bitmap.buffer, c_char_p), bitmap.rows * bitmap.pitch, 0x200), # Read-Write FORMAT_ARGB32, width, rows, bitmap.pitch ) surface = ImageSurface(FORMAT_ARGB32, 2*width, rows) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) ctx.paint() ctx.set_source_surface(I, width/2, 0) ctx.paint() ctx.set_source_surface(I, width , 0) ctx.paint() surface.write_to_png("emoji-color-cairo.png") Image.open("emoji-color-cairo.png").show() freetype-py-2.5.1/examples/uvs-harness.py0000775000175000017500000000432114664131406020646 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # shorter Unicode Variation Sequences example from #195, with comparison to hb-shape. # The test file used and known to work is v2.004 of https://github.com/adobe-fonts/source-han-sans/blob/release/OTF/Japanese/SourceHanSans-Regular.otf import importlib uvs = importlib.import_module("unicode-variation-sequences") read_freetype_cmap = uvs.read_freetype_cmap if __name__ == "__main__": import os, io directory = os.path.dirname(__file__) font_path = os.path.join(directory, 'SourceHanSans-Regular.otf') memory_file = io.BytesIO() with open(font_path, 'rb') as fontfile: memory_file.write(fontfile.read()) memory_file.seek(0) from freetype import * library = FT_Library() error = FT_Init_FreeType(byref(library)) if error: raise FT_Exception(error) freetype_face = FT_Face() data = memory_file.getvalue() error = FT_New_Memory_Face(library, data, len(data), 0, byref(freetype_face)) if error: raise FT_Exception(error) all_freetype_characters = read_freetype_cmap(freetype_face) # {'邉' : ['邉󠄁', '邉󠄂', '邉󠄃', '邉󠄄', '邉󠄅', '邉󠄆', '邉󠄇', '邉󠄈', '邉󠄉', '邉󠄊', '邉󠄋', '邉󠄌', '邉󠄍', '邉󠄎', '邉󠄀']} print(all_freetype_characters['邉'], all_freetype_characters['邉󠄁'], all_freetype_characters['邉󠄂'], all_freetype_characters['邉󠄃'], all_freetype_characters['邉󠄄'], all_freetype_characters['邉󠄅'], all_freetype_characters['邉󠄆'], all_freetype_characters['邉󠄇'], all_freetype_characters['邉󠄈'], all_freetype_characters['邉󠄉'], all_freetype_characters['邉󠄊'], all_freetype_characters['邉󠄋'], all_freetype_characters['邉󠄌'], all_freetype_characters['邉󠄍'], all_freetype_characters['邉󠄎'], all_freetype_characters['邉󠄀'], sep='|') print('The above should be identical to the output of this hb-shape command:') print(' hb-shape --no-glyph-names --no-positions --no-clusters --no-advances SourceHanSans-Regular.otf "邉邉󠄁邉󠄂邉󠄃邉󠄄邉󠄅邉󠄆邉󠄇邉󠄈邉󠄉邉󠄊邉󠄋邉󠄌邉󠄍邉󠄎邉󠄀"') freetype-py-2.5.1/examples/unicode-variation-sequences.py0000775000175000017500000002553114664131406024007 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # The test file used and known to work is v2.004 of https://github.com/adobe-fonts/source-han-sans/blob/release/OTF/Japanese/SourceHanSans-Regular.otf import io import os import traceback from typing import Dict from fontTools.ttLib import TTFont from ctypes import byref from freetype import ( FT_Done_Face, FT_Done_FreeType, FT_Exception, FT_Face, FT_Get_First_Char, FT_Get_Next_Char, FT_Init_FreeType, FT_Library, FT_New_Memory_Face, FT_UInt, FT_Get_Char_Index, FT_Face_GetVariantSelectors, FT_Face_GetCharsOfVariant, FT_Face_GetCharVariantIndex, FT_Face_GetCharVariantIsDefault ) _ALL_IVS_NUMBERS = [x for x in range( 0xe0100, 0xe01f0)] # Supplemental _ALL_IVS_NUMBERS += [x for x in range( 0xfe00, 0xfe10)] # IVS def _read_cmap_uvs(uvsDict): global _ALL_IVS_NUMBERS all_characters = {} all_default_characters = [] for item, item_list in uvsDict.items(): ivs_val = int(item) if ivs_val in _ALL_IVS_NUMBERS: ivs_chr = chr(ivs_val) for character_tuple in item_list: character_val = character_tuple[0] glyph_name = character_tuple[1] if glyph_name: if glyph_name == '.notdef': continue character = chr(int(character_val)) ivs_character = character + ivs_chr assert ivs_character not in all_characters all_characters[ivs_character] = glyph_name else: character = chr(int(character_val)) ivs_character = character + ivs_chr all_default_characters.append(ivs_character) return all_characters, all_default_characters def _read_character(character_value, encoding): if encoding == 'utf_16_be': character_string = chr(character_value) else: return None return character_string _CMAP_PRIORITY_LIST = [ (3, 10), # Windows Unicode full repertoire (0, 6), # Unicode full repertoire (format 13 subtable) (0, 4), # Unicode 2.0 full repertoire (3, 1), # Windows Unicode BMP (0, 3), # Unicode 2.0 BMP (0, 2), # Unicode ISO/IEC 10646 (0, 1), # Unicode 1.1 (0, 0) # Unicode 1.0 ] def read_fonttools_cmap(font) -> Dict[str, str]: global _CMAP_PRIORITY_LIST assert isinstance(font, TTFont) if not hasattr(font["cmap"], 'tables'): return None all_characters = {} all_default_characters = [] best_read_index = None all_tables = font["cmap"].tables for table in all_tables: encoding = table.getEncoding() if not encoding: continue if encoding != 'utf_16_be': continue try: if table.format == 14: if hasattr(table, 'uvsDict'): all_uvs_data, default_characters = _read_cmap_uvs(table.uvsDict) all_default_characters += default_characters for character, glyphname in all_uvs_data.items(): if character in all_characters: assert all_characters[character] == glyphname else: all_characters[character] = glyphname else: print('Unknown CMAP Format 14: {}:'.format(vars(table))) elif hasattr(table, 'cmap'): tuple_value = (table.platformID, table.platEncID) if tuple_value in _CMAP_PRIORITY_LIST: index_value = _CMAP_PRIORITY_LIST.index(tuple_value) if best_read_index: if index_value < best_read_index: best_read_index = index_value else: continue else: best_read_index = index_value all_items = table.cmap.items() length = len(all_items) if length == 0: if table.format != 6: print('Unknown CMAP Format {}: {}:'.format(table.format, vars(table))) for item in all_items: character = _read_character(item[0], encoding) glyphname = item[1] if glyphname == '.notdef': continue if character is not None: if character in all_characters: if all_characters[character] != glyphname: all_characters[character] = glyphname else: all_characters[character] = glyphname except: traceback.print_exc() continue if all_default_characters: for ivs_character in all_default_characters: first_character = ivs_character[0] if first_character in all_characters: glyphname = all_characters[first_character] all_characters[ivs_character] = glyphname return all_characters def read_freetype_cmap(face: FT_Face) -> Dict[str, int]: platID = face.contents.charmap.contents.platform_id encodingID = face.contents.charmap.contents.encoding_id if platID == 3: if encodingID not in [1, 10]: return {} elif platID == 0: # all unicode pass else: # everything else return {} all_characters = [] gindex = FT_UInt() charcode = FT_Get_First_Char( face, byref(gindex) ) while gindex.value != 0: character = chr(charcode) all_characters.append(character) charcode = FT_Get_Next_Char( face, charcode, byref(gindex) ) variant_selectors_list = FT_Face_GetVariantSelectors(face) if bool(variant_selectors_list): all_selectors = [] selector_value = variant_selectors_list[0] index = 0 while selector_value != 0: all_selectors.append(selector_value) index += 1 selector_value = variant_selectors_list[index] for selector_value in all_selectors: character_value_list = FT_Face_GetCharsOfVariant(face, selector_value) assert(bool(character_value_list)) character_value = character_value_list[0] index = 0 while character_value != 0: character = chr(character_value) + chr(selector_value) all_characters.append(character) index += 1 character_value = character_value_list[index] character_to_glyphID = {} for character in all_characters: if len(character) == 2: character_value = ord(character[0]) selector_value = ord(character[1]) glyphID = FT_Face_GetCharVariantIndex(face, character_value, selector_value) if glyphID != 0: assert character not in character_to_glyphID character_to_glyphID[character] = glyphID else: assert len(character) == 1 character_value = ord(character) glyphID = FT_Get_Char_Index(face, character_value) if glyphID != 0: assert character not in character_to_glyphID character_to_glyphID[character] = glyphID return character_to_glyphID def _convert_character_to_hex(text: str): assert len(text) == 1 value = ord(text) if 0x0000 <= value <= 0xFFFF: assert len(hex(value)) <= 6 return '{0:04x}'.format(value) elif value <= 0xFFFFF: assert len(hex(value)) <= 7 return '{0:05x}'.format(value) elif value <= 0xFFFFFF: assert len(hex(value)) <= 8 return '{0:06x}'.format(value) elif value <= 0xFFFFFFF: assert len(hex(value)) <= 9 return '{0:07x}'.format(value) elif value <= 0xFFFFFFFF: assert len(hex(value)) <= 9 return '{0:08x}'.format(value) else: raise RuntimeError() def convert_string_to_hex(text: str): assert isinstance(text, str) result = '' for count, character in enumerate(text): if count > 0: result += '-{}'.format(_convert_character_to_hex(character)) else: result += '{}'.format(_convert_character_to_hex(character)) return result if __name__ == "__main__": directory = os.path.dirname(__file__) font_path = os.path.join(directory, 'SourceHanSans-Regular.otf') memory_file = io.BytesIO() with open(font_path, 'rb') as fontfile: memory_file.write(fontfile.read()) memory_file.seek(0) fonttools_font = TTFont(memory_file, 0, allowVID=0, ignoreDecompileErrors=True, fontNumber=-1) library = FT_Library() error = FT_Init_FreeType(byref(library)) if error: raise FT_Exception(error) freetype_face = FT_Face() data = memory_file.getvalue() error = FT_New_Memory_Face(library, data, len(data), 0, byref(freetype_face)) if error: raise FT_Exception(error) all_freetype_characters = read_freetype_cmap(freetype_face) all_fonttools_characters = read_fonttools_cmap(fonttools_font) print('Read {} Free Type Characters'.format(len(all_freetype_characters))) print('Read {} Font Tools Characters'.format(len(all_fonttools_characters))) print('Checking Mapping') for character, glyphID in all_freetype_characters.items(): glyphname = fonttools_font.getGlyphName(glyphID) if character in all_fonttools_characters: ft_glyphname = all_fonttools_characters[character] if ft_glyphname != glyphname: character_hex = convert_string_to_hex(character) print('Glyph Mismatch: {} Free Type: {} Font Tools: {}'.format(character_hex, glyphname, ft_glyphname)) else: character_hex = convert_string_to_hex(character) print('Glyph Missing in Font Tools: {}'.format(character_hex)) for character, glyphname in all_fonttools_characters.items(): if character in all_freetype_characters: ft_glyphID = all_freetype_characters[character] ft_glyphname = fonttools_font.getGlyphName(ft_glyphID) if ft_glyphname != glyphname: character_hex = convert_string_to_hex(character) print('Glyph Mismatch: {} Font Tools: {} Free Type: {}'.format(character_hex, glyphname, ft_glyphname)) else: character_hex = convert_string_to_hex(character) print('Glyph Missing in Free Type: {}'.format(character_hex)) print('Finished Checking Mapping') FT_Done_Face(freetype_face) FT_Done_FreeType(library) freetype-py-2.5.1/examples/agg-trick.py0000664000175000017500000000475214664131406020245 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from freetype import * import numpy as np from PIL import Image def render(filename = "Vera.ttf", hinting = (False,False), gamma = 1.5, lcd=False): text = "A Quick Brown Fox Jumps Over The Lazy Dog 0123456789" W,H,D = 680, 280, 1 Z = np.zeros( (H,W), dtype=np.ubyte ) face = Face(filename) pen = Vector(5*64, (H-10)*64) flags = FT_LOAD_RENDER if hinting[1]: flags |= FT_LOAD_FORCE_AUTOHINT else: flags |= FT_LOAD_NO_HINTING if hinting[0]: hres, hscale = 72, 1.0 else: hres, hscale = 72*10, 0.1 if lcd: flags |= FT_LOAD_TARGET_LCD Z = np.zeros( (H,W,3), dtype=np.ubyte ) try: set_lcd_filter( FT_LCD_FILTER_DEFAULT ) except: pass for size in range(9,23): face.set_char_size( size * 64, 0, hres, 72 ) matrix = Matrix( int((hscale) * 0x10000), int((0.0) * 0x10000), int((0.0) * 0x10000), int((1.0) * 0x10000) ) previous = 0 pen.x = 5*64 for current in text: face.set_transform( matrix, pen ) face.load_char( current, flags) kerning = face.get_kerning( previous, current, FT_KERNING_UNSCALED ) pen.x += kerning.x glyph = face.glyph bitmap = glyph.bitmap x, y = glyph.bitmap_left, glyph.bitmap_top w, h, p = bitmap.width, bitmap.rows, bitmap.pitch buff = np.array(bitmap.buffer, dtype=np.ubyte).reshape((h,p)) if lcd: Z[H-y:H-y+h,x:x+w/3].flat |= buff[:,:w].flatten() else: Z[H-y:H-y+h,x:x+w].flat |= buff[:,:w].flatten() pen.x += glyph.advance.x previous = current pen.y -= (size+4)*64 # Gamma correction Z = (Z/255.0)**(gamma) Z = ((1-Z)*255).astype(np.ubyte) if lcd: I = Image.fromarray(Z, mode='RGB') else: I = Image.fromarray(Z, mode='L') name = filename.split('.')[0] filename = '%s-gamma(%.1f)-hinting(%d,%d)-lcd(%d).png' % (name,gamma,hinting[0],hinting[1],lcd) I.save(filename) if __name__ == '__main__': render('Vera.ttf', (0,1), 1.25, True) freetype-py-2.5.1/examples/user-code-from-issue-193.py0000664000175000017500000000324614664131406022661 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # Corrected version of user-submitted code in https://github.com/rougier/freetype-py/issues/193 # Comments: # The original version missed "freetype.FT_LOAD_RENDER" and # "freetype.FT_LOAD_TARGET_MONO", and also has the unfortunate # setting of pixel size "16". Thus for some glyphs on 'simsun.ttc', # the code returns the embedded bitmap, while for other glyphs without # embedded bitmaps, it returns garbage for the bitmap buffer # (if you do not check "font.glyph.format" and "font.glyph.bitmap.pixel_mode" ; # font.glyph.format == FT_GLYPH_FORMAT_OUTLINE in that case). "bitmap.pitch" was also # not used in the original, and hard-coded length of scanline was used. import freetype font = freetype.Face(r"simsun.ttc") # 绘制字符 font.set_pixel_sizes(19, 19) font.load_char('1', freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO) #font.load_char('字', freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO) bitmap = font.glyph.bitmap print(bitmap.rows, bitmap.width, bitmap.pitch) assert(font.glyph.format == freetype.FT_GLYPH_FORMAT_BITMAP) assert(font.glyph.bitmap.pixel_mode == freetype.FT_PIXEL_MODE_MONO) print(bitmap.buffer) print(len(bitmap.buffer)) left = [] right = [] for b, j in enumerate(bitmap.buffer): b_res = list(format(j, "08b")) for r in b_res: if r == "1": print("\033[1;30;46m \033[0m", end="") else: print("\033[1;30;40m \033[0m", end="") if (b + 1) % bitmap.pitch == 0 and b > 0: right.append(format(j, "02X")) print() else: left.append(format(j, "02X")) print(' '.join(left)) print(' '.join(right)) freetype-py-2.5.1/examples/glyph-lcd.py0000664000175000017500000000201014664131406020241 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph bitmap LCD display (sub-pixel) rendering ''' from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_LCD ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = numpy.array(data,dtype=numpy.ubyte).reshape(rows, width/3, 3) plt.imshow(Z, interpolation='nearest', origin='lower') plt.show() freetype-py-2.5.1/examples/glyph-vector.py0000664000175000017500000000626014664131406021014 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # - The code is incomplete and over-simplified, as it ignores the 3rd order # bezier curve bit and always intepolate between off-curve points. # This is only correct for truetype fonts (which only use 2nd order bezier curves). # - Also it seems to assume the first point is always on curve; this is # unusual but legal. # # ----------------------------------------------------------------------------- ''' Show how to access glyph outline description. ''' from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt from matplotlib.path import Path import matplotlib.patches as patches face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S') slot = face.glyph outline = slot.outline points = numpy.array(outline.points, dtype=[('x',float), ('y',float)]) x, y = points['x'], points['y'] figure = plt.figure(figsize=(8,10)) axis = figure.add_subplot(111) #axis.scatter(points['x'], points['y'], alpha=.25) start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour for i in range(len(outline.contours)): end = outline.contours[i] points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0]) segments = [ [points[0],], ] for j in range(1, len(points) ): segments[-1].append(points[j]) if tags[j] & (1 << 0) and j < (len(points)-1): segments.append( [points[j],] ) verts = [points[0], ] codes = [Path.MOVETO,] for segment in segments: if len(segment) == 2: verts.extend(segment[1:]) codes.extend([Path.LINETO]) elif len(segment) == 3: verts.extend(segment[1:]) codes.extend([Path.CURVE3, Path.CURVE3]) else: verts.append(segment[1]) codes.append(Path.CURVE3) for i in range(1,len(segment)-2): A,B = segment[i], segment[i+1] C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0) verts.extend([ C, B ]) codes.extend([ Path.CURVE3, Path.CURVE3]) verts.append(segment[-1]) codes.append(Path.CURVE3) VERTS.extend(verts) CODES.extend(codes) start = end+1 # Draw glyph lines path = Path(VERTS, CODES) glyph = patches.PathPatch(path, facecolor='.75', lw=1) # Draw "control" lines for i, code in enumerate(CODES): if code == Path.CURVE3: CODES[i] = Path.LINETO path = Path(VERTS, CODES) patch = patches.PathPatch(path, ec='.5', fill=False, ls='dashed', lw=1 ) axis.add_patch(patch) axis.add_patch(glyph) axis.set_xlim(x.min()-100, x.max()+100) plt.xticks([]) axis.set_ylim(y.min()-100, y.max()+100) plt.yticks([]) plt.show() freetype-py-2.5.1/examples/hello-world.py0000664000175000017500000000345614664131406020625 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./Vera.ttf') text = 'Hello World !' fontsize = 48 face.set_char_size( fontsize*64 ) slot = face.glyph # First pass to compute bbox width = 0 top = -fontsize #The distance from baseline to the top row of the bbox bot = fontsize #The distance from baseline to the bottom row of the bbox (may be negative) previous = 0 for i,c in enumerate(text): face.load_char(c) bitmap = slot.bitmap top = max(top, slot.bitmap_top) bot = min(bot, slot.bitmap_top - bitmap.rows) kerning = face.get_kerning(previous, c) width += (slot.advance.x >> 6) + (kerning.x >> 6) previous = c height = top - bot Z = numpy.zeros((height,width), dtype=numpy.ubyte) # Second pass for actual rendering x, y = 0, 0 previous = 0 for c in text: face.load_char(c) bitmap = slot.bitmap w,h = bitmap.width, bitmap.rows y = top - slot.bitmap_top kerning = face.get_kerning(previous, c) x += (kerning.x >> 6) Z[y:y+h,x+left:x+left+w] += numpy.array(bitmap.buffer, dtype='ubyte').reshape(h,w) x += (slot.advance.x >> 6) previous = c plt.figure(figsize=(10, 10*Z.shape[0]/float(Z.shape[1]))) plt.imshow(Z, interpolation='nearest', origin='upper', cmap=plt.cm.gray) plt.xticks([]), plt.yticks([]) plt.show() freetype-py-2.5.1/examples/color-glyph-format-detect.py0000775000175000017500000000412314664131406023363 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # # Identify the color glyph format. # # Copyright 2023 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # Note: # This is a per-glyph property. # # Glyph 1426 in SEGUIEMJ.TTF is a glyph layer of glyph 1425. # Glyph 1426 is a plain outline, 1425 is a COLRv0 glyph. # # Noto Color Emoji is only valid for size 109. # # Apple Color Emoji works for size 160 and a few other specific sizes. # # SVG and COLRv1 is not exclusive - some fonts have both. from freetype import * if __name__ == '__main__': import sys execname = sys.argv[0] if len(sys.argv) < 3: print("Example usage: %s TrajanColor-Concept.otf [size]" % execname) exit(1) face = Face(sys.argv[1]) glyph_id = c_uint(int(sys.argv[2])) if (len(sys.argv) > 3): size = int(sys.argv[3]) else: size = 160 face.set_char_size( size*64 ) face.load_glyph( glyph_id, FT_LOAD_COLOR ) print("glyph id %d is " % (glyph_id.value), end='') if (face.glyph.format == FT_GLYPH_FORMAT_SVG): print("SVG; ", end='') if (face.glyph.format == FT_GLYPH_FORMAT_BITMAP): print("Bitmap; ", end='') if (face.glyph.format == FT_GLYPH_FORMAT_OUTLINE): print("Outline; ", end='') opaqueLayerPaint = FT_OpaquePaint(None, 1) if (FT_Get_Color_Glyph_Paint(face._FT_Face, glyph_id, FT_COLOR_INCLUDE_ROOT_TRANSFORM, byref(opaqueLayerPaint))): print("COLRv1; ", end='') else: layerGlyphIndex = FT_UInt(0) layerColorIndex = FT_UInt(0) layerIterator = FT_LayerIterator( 0, 0, None ) layer_count = 0 if (FT_Get_Color_Glyph_Layer(face._FT_Face, glyph_id, byref(layerGlyphIndex), byref(layerColorIndex), byref(layerIterator))): if (layerGlyphIndex.value != 0): print("COLRv0; ", end='') print ("") # line ending freetype-py-2.5.1/examples/glyph-lcd-cairo.py0000775000175000017500000001066714664131406021360 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-lcd example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - Not immitating the upside-downness # - Do LCD_V side by side also # # Limitation: Suface.get_data() is not in the "python 3, pycairo < 1.11" combo. # # ----------------------------------------------------------------------------- ''' Glyph bitmap LCD display (sub-pixel) rendering ''' from freetype import * # use Matrix() from Cairo instead of from Freetype from cairo import Context, ImageSurface, FORMAT_ARGB32, SurfacePattern, FILTER_BEST, Matrix if __name__ == '__main__': from PIL import Image from numpy import ndarray, ubyte, uint32 face = Face('./Vera.ttf') face.set_char_size( 48*64 ) face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_LCD ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width//3 rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch copybuffer = (c_ubyte * (pitch * rows))() memmove(pointer(copybuffer), bitmap._FT_Bitmap.buffer, pitch * rows) I = ImageSurface(FORMAT_ARGB32, width, rows) ndR = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=0, strides=[pitch, 3]) ndG = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=1, strides=[pitch, 3]) ndB = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=2, strides=[pitch, 3]) try: ndI = ndarray(shape=(rows,width), buffer=I.get_data(), dtype=uint32, order='C', strides=[I.get_stride(), 4]) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") # 255 * 2**24 = opaque ndI[:,:] = 255 * 2**24 + ndR[:,:] * 2**16 + ndG[:,:] * 2**8 + ndB[:,:] I.mark_dirty() surface = ImageSurface(FORMAT_ARGB32, 800, 600) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) scale = 480.0 / rows scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(400.0 - width *scale /2.0 )+200, -60) pattern.set_matrix(scalematrix) ctx.paint() # we need this later for shifting the taller LCD_V glyph up. rows_old = rows # LCD_V face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_LCD_V ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows//3 pitch = face.glyph.bitmap.pitch copybuffer = (c_ubyte * (pitch * face.glyph.bitmap.rows))() memmove(pointer(copybuffer), bitmap._FT_Bitmap.buffer, pitch * face.glyph.bitmap.rows) I = ImageSurface(FORMAT_ARGB32, width, rows) ndR = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=0, strides=[pitch*3, 1]) ndG = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=pitch, strides=[pitch*3, 1]) ndB = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=2*pitch, strides=[pitch*3, 1]) ndI = ndarray(shape=(rows,width), buffer=I.get_data(), dtype=uint32, order='C', strides=[I.get_stride(), 4]) # 255 * 2**24 = opaque ndI[:,:] = 255 * 2**24 + ndR[:,:] * 2**16 + ndG[:,:] * 2**8 + ndB[:,:] I.mark_dirty() ctx.set_source_surface(I, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) # Re-use the sane scale (LVD_V taller than LCD), # but adjust vertical position to line up mid-height of glyphs adjust = (rows - rows_old) * 240.0 /rows scalematrix.translate(-400, adjust) pattern.set_matrix(scalematrix) ctx.paint() # surface.flush() surface.write_to_png("glyph-lcd-cairo.png") Image.open("glyph-lcd-cairo.png").show() freetype-py-2.5.1/examples/glyph-vector-2.py0000664000175000017500000000726514664131406021161 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # - The code is incomplete and over-simplified, as it ignores the 3rd order # bezier curve bit and always intepolate between off-curve points. # This is only correct for truetype fonts (which only use 2nd order bezier curves). # - Also it seems to assume the first point is always on curve; this is # unusual but legal. # # ----------------------------------------------------------------------------- ''' Show how to access glyph outline description. ''' from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt from matplotlib.path import Path import matplotlib.patches as patches face = Face('./Vera.ttf') face.set_char_size( 32*64 ) face.load_char('g') slot = face.glyph bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = numpy.array(data,dtype=numpy.ubyte).reshape(rows, width) outline = slot.outline points = numpy.array(outline.points, dtype=[('x',float), ('y',float)]) x, y = points['x'], points['y'] figure = plt.figure(figsize=(8,10)) axis = figure.add_subplot(111) #axis.scatter(points['x'], points['y'], alpha=.25) start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour for i in range(len(outline.contours)): end = outline.contours[i] points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0]) segments = [ [points[0],], ] for j in range(1, len(points) ): segments[-1].append(points[j]) if tags[j] & (1 << 0) and j < (len(points)-1): segments.append( [points[j],] ) verts = [points[0], ] codes = [Path.MOVETO,] for segment in segments: if len(segment) == 2: verts.extend(segment[1:]) codes.extend([Path.LINETO]) elif len(segment) == 3: verts.extend(segment[1:]) codes.extend([Path.CURVE3, Path.CURVE3]) else: verts.append(segment[1]) codes.append(Path.CURVE3) for i in range(1,len(segment)-2): A,B = segment[i], segment[i+1] C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0) verts.extend([ C, B ]) codes.extend([ Path.CURVE3, Path.CURVE3]) verts.append(segment[-1]) codes.append(Path.CURVE3) VERTS.extend(verts) CODES.extend(codes) start = end+1 # Draw glyph path = Path(VERTS, CODES) glyph = patches.PathPatch(path, fill = True, facecolor=(0.8,0.5,0.8), alpha=.25, lw=0) glyph_outline = patches.PathPatch(path, fill = False, edgecolor='black', lw=3) plt.imshow(Z, extent=[x.min(), x.max(),y.min(), y.max()], origin='lower', interpolation='nearest', cmap = plt.cm.gray_r, vmin=0, vmax=400) plt.xticks(numpy.linspace(x.min(), x.max(), Z.shape[1]+1), ()) plt.yticks(numpy.linspace(y.min(), y.max(), Z.shape[0]+1), ()) plt.grid(color='k', linewidth=1, linestyle='-') axis.add_patch(glyph) axis.add_patch(glyph_outline) axis.set_xlim(x.min(), x.max()) axis.set_ylim(y.min(), y.max()) plt.savefig('glyph-vector-2.svg') plt.show() freetype-py-2.5.1/examples/glyph-outline.py0000664000175000017500000000242014664131406021163 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph outline rendering ''' from freetype import * if __name__ == '__main__': import numpy import matplotlib.pyplot as plt face = Face('./Vera.ttf') face.set_char_size( 4*48*64 ) flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph glyph = slot.get_glyph() stroker = Stroker( ) stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ) glyph.stroke( stroker , True ) blyph = glyph.to_bitmap(FT_RENDER_MODE_NORMAL, Vector(0,0), True ) bitmap = blyph.bitmap width, rows, pitch = bitmap.width, bitmap.rows, bitmap.pitch top, left = blyph.top, blyph.left data = [] for i in range(rows): data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = numpy.array(data,dtype=numpy.ubyte).reshape(rows, width) plt.figure(figsize=(6,8)) plt.imshow(Z, interpolation='nearest', cmap=plt.cm.gray_r, origin='lower') plt.show() freetype-py-2.5.1/examples/font-info.py0000664000175000017500000000400714664131406020265 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- from freetype import * if __name__ == '__main__': import sys if len(sys.argv) < 2: print("Usage: %s font_filename" % sys.argv[0]) sys.exit() face = Face(sys.argv[1]) print ('Family name: {}'.format(face.family_name.decode("ascii", errors='ignore'))) print ('Style name: {}'.format(face.style_name.decode("ascii", errors='ignore'))) print ('Charmaps: {}'.format([charmap.encoding_name for charmap in face.charmaps])) print ('') print ('Face number: {}'.format(face.num_faces)) print ('Glyph number: {}'.format(face.num_glyphs)) # FT_Bitmap_Size.size is in F26.6. Need to divide by 64: print ('Available sizes: {}'.format([bitmap_size.size/64 for bitmap_size in face.available_sizes])) print ('') print ('units per em: {}'.format(face.units_per_EM)) print ('ascender: {}'.format(face.ascender)) print ('descender: {}'.format(face.descender)) print ('height: {}'.format(face.height)) print ('') print ('max_advance_width: {}'.format(face.max_advance_width)) print ('max_advance_height: {}'.format(face.max_advance_height)) print ('') print ('underline_position: {}'.format(face.underline_position)) print ('underline_thickness: {}'.format(face.underline_thickness)) print ('') print ('Has horizontal: {}'.format(face.has_horizontal)) print ('Has vertical: {}'.format(face.has_vertical)) print ('Has kerning: {}'.format(face.has_kerning)) print ('Is fixed width: {}'.format(face.is_fixed_width)) print ('Is scalable: {}'.format(face.is_scalable)) print ('') freetype-py-2.5.1/examples/glyph-vector-2-cairo.py0000775000175000017500000001274514664131406022256 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based glyph-vector-2 example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - The code is incomplete and over-simplified, as it ignores the 3rd order # bezier curve bit when intepolating between off-curve points. # This is only correct for truetype fonts (which only use 2nd order bezier curves). # - Also it seems to assume the first point is always on curve; this is # unusual but legal. # # Can cope with well-behaved Postscript/CFF fonts too. # # ----------------------------------------------------------------------------- ''' Show how to access glyph outline description. ''' from freetype import * # using Matrix class from Cairo, instead of FreeType's from cairo import Context, SVGSurface, Matrix, SurfacePattern, FILTER_BEST from bitmap_to_surface import make_image_surface if __name__ == '__main__': import numpy from PIL import Image # Replacement for Path enums: STOP, MOVETO, LINETO, CURVE3, CURVE4 = 0, 1, 2, 3, 4 face = Face('./Vera.ttf') face.set_char_size( 32*64 ) face.load_char('g') slot = face.glyph bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch Z = make_image_surface(bitmap) outline = slot.outline points = numpy.array(outline.points, dtype=[('x',float), ('y',float)]) x, y = points['x'], points['y'] bbox = outline.get_cbox() MARGIN = 10 scale = 3 def Floor64(x): return (x//64) * 64 def Ceil64(x): return ((x+63)//64) * 64 width_s = (width * 64)//scale + 2 * MARGIN height_s = (rows * 64)//scale + 2 * MARGIN surface = SVGSurface('glyph-vector-2-cairo.svg', width_s, height_s) ctx = Context(surface) ctx.set_source_rgb(1,1,1) ctx.paint() ctx.save() ctx.scale(1.0/scale,1.0/scale) ctx.translate(-Floor64(bbox.xMin) + MARGIN * scale,-Floor64(bbox.yMin) + MARGIN * scale) ctx.transform(Matrix(1,0,0,-1)) ctx.translate(0, -(Ceil64(bbox.yMax) + Floor64(bbox.yMin))) # difference! start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour for i in range(len(outline.contours)): end = outline.contours[i] points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0]) segments = [ [points[0],], ] for j in range(1, len(points) ): segments[-1].append(points[j]) if ( FT_Curve_Tag( tags[j] ) == FT_Curve_Tag_On ) and j < (len(points)-1): segments.append( [points[j],] ) verts = [points[0], ] codes = [MOVETO,] tags.pop() for segment in segments: if len(segment) == 2: verts.extend(segment[1:]) codes.extend([LINETO]) elif len(segment) == 3: verts.extend(segment[1:]) codes.extend([CURVE3, CURVE3]) elif ( len(segment) == 4 ) \ and ( FT_Curve_Tag(tags[1]) == FT_Curve_Tag_Cubic ) \ and ( FT_Curve_Tag(tags[2]) == FT_Curve_Tag_Cubic ): verts.extend(segment[1:]) codes.extend([CURVE4, CURVE4, CURVE4]) else: # Interpolating verts.append(segment[1]) codes.append(CURVE3) for i in range(1,len(segment)-2): A,B = segment[i], segment[i+1] C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0) verts.extend([ C, B ]) codes.extend([ CURVE3, CURVE3]) verts.append(segment[-1]) codes.append(CURVE3) [tags.pop() for x in range(len(segment) - 1)] VERTS.extend(verts) CODES.extend(codes) start = end+1 # Draw glyph ctx.new_path() ctx.set_source_rgba(0.8,0.5,0.8, 1) i = 0 while (i < len(CODES)): if (CODES[i] == MOVETO): ctx.move_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == LINETO): ctx.line_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == CURVE3): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], # undocumented VERTS[i+1][0],VERTS[i+1][1]) i += 2 elif (CODES[i] == CURVE4): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], VERTS[i+2][0],VERTS[i+2][1]) i += 3 ctx.fill_preserve() ctx.set_source_rgb(0,0,0) ctx.set_line_width(6) ctx.stroke() ctx.restore() scale2 = (height_s - 2.0 * MARGIN)/rows ctx.set_source_surface(Z, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale2, 1.0/scale2) scalematrix.translate(-( width_s/2.0 - width *scale2 /2.0 ), -MARGIN) pattern.set_matrix(scalematrix) ctx.set_source_rgba (0, 0, 0, 0.7) ctx.mask(pattern) ctx.fill() surface.flush() surface.write_to_png("glyph-vector-2-cairo.png") surface.finish() Image.open("glyph-vector-2-cairo.png").show() freetype-py-2.5.1/MANIFEST.in0000664000175000017500000000063114664131406015733 0ustar georgeskgeorgesk# ----------------------------------------------------------------------------- # # FreeType high-level python API - copyright 2011 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- recursive-include examples * include MANIFEST.in include LICENSE.txt include README.rst include setup-build-freetype.py freetype-py-2.5.1/.gitignore0000664000175000017500000000131614664131406016166 0ustar georgeskgeorgesk# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg *.eggs venv # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ # Visual Studio Code .vscode/ freetype-py-2.5.1/setup-build-freetype.py0000664000175000017500000001755014664131406020635 0ustar georgeskgeorgesk# This will build a FreeType binary for bundling with freetype-py on Windows, # Linux and macOS. The environment determines if it's a 32 or 64 bit build (on # Windows, set $env:PYTHON_ARCH="64" for a x64 build; on Linux, set it to "32" # to explicitly make a 32 bit build). # It can be used stand-alone, in conjunction with setup.py and on CI services # like Travis and Appveyor. You need CMake and some C/C++ compiler suite (e.g. # GCC, Visual Studio Community 2017, ...) import distutils.dir_util import distutils.file_util import distutils.spawn import glob import hashlib import os import shutil import ssl import subprocess import sys import tarfile import urllib.request from os import path import platform # Needed for the GitHub Actions macOS CI runner, which appears to come without CAs. import certifi FREETYPE_HOST = "https://mirrors.sarata.com/non-gnu/freetype/" FREETYPE_TARBALL = "freetype-2.13.2.tar.xz" FREETYPE_URL = FREETYPE_HOST + FREETYPE_TARBALL FREETYPE_SHA256 = "12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d" HARFBUZZ_HOST = "https://github.com/harfbuzz/harfbuzz/releases/download/8.3.0/" HARFBUZZ_TARBALL = "harfbuzz-8.3.0.tar.xz" HARFBUZZ_URL = HARFBUZZ_HOST + HARFBUZZ_TARBALL HARFBUZZ_SHA256 = "109501eaeb8bde3eadb25fab4164e993fbace29c3d775bcaa1c1e58e2f15f847" root_dir = "." build_dir = path.join(root_dir, "build") # CMake requires an absolute path to a prefix. prefix_dir = path.abspath(path.join(build_dir, "local")) lib_dir = path.join(prefix_dir, "lib") build_dir_ft = path.join(build_dir, FREETYPE_TARBALL.split(".tar")[0], "build") build_dir_hb = path.join(build_dir, HARFBUZZ_TARBALL.split(".tar")[0], "build") CMAKE_GLOBAL_SWITCHES = ( "-DCMAKE_COLOR_MAKEFILE=false " '-DCMAKE_PREFIX_PATH="{}" ' '-DCMAKE_INSTALL_PREFIX="{}" ' ).format(prefix_dir, prefix_dir) # Try to use Ninja to build things if it's available. Much faster. # On Windows, I first need to figure out how to make it aware of VC, bitness, # etc. if sys.platform != "win32" and distutils.spawn.find_executable("ninja"): CMAKE_GLOBAL_SWITCHES += "-G Ninja " bitness = None if sys.platform == "win32": if os.environ.get("PYTHON_ARCH", "") == "64": print("# Making a 64 bit build.") bitness = 64 CMAKE_GLOBAL_SWITCHES += ( "-DCMAKE_GENERATOR_PLATFORM=x64 " '-DCMAKE_GENERATOR_TOOLSET="host=x64" ' ) else: print("# Making a 32 bit build.") bitness = 32 if sys.platform == "darwin": print("# Making a 64 bit build.") CMAKE_GLOBAL_SWITCHES += ( '-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" ' '-DCMAKE_OSX_DEPLOYMENT_TARGET="10.9" ' '-DCMAKE_C_FLAGS="-O2" ' '-DCMAKE_CXX_FLAGS="-O2" ' ) bitness = 64 if "linux" in sys.platform: c_flags = cxx_flags = "-O2" ld_flags = "" if platform.machine() == "x86_64": if ( os.environ.get("PYTHON_ARCH", "") == "32" or platform.architecture() == "32bit" ): print("# Making a 32 bit build.") # On a 64 bit Debian/Ubuntu, this needs gcc-multilib and g++-multilib. # On a 64 bit Fedora, install glibc-devel and libstdc++-devel. c_flags = "-m32 {}".format(c_flags) cxx_flags = "-m32 {}".format(cxx_flags) ld_flags = "-m32" bitness = 32 else: print("# Making a 64 bit build.") c_flags = "-m64 {}".format(c_flags) cxx_flags = "-m64 {}".format(cxx_flags) ld_flags = "-m64" bitness = 64 else: print("# Making a '{}' build.".format(platform.machine())) if platform.architecture() == "32bit": bitness = 32 else: bitness = 64 CMAKE_GLOBAL_SWITCHES += ( '-DCMAKE_C_FLAGS="{}" '.format(c_flags) + '-DCMAKE_CXX_FLAGS="{}" '.format(cxx_flags) + '-DCMAKE_LD_FLAGS="{}" '.format(ld_flags) ) def shell(cmd, cwd=None): """Run a shell command specified by cmd string.""" subprocess.run(cmd, shell=True, check=True, cwd=cwd) def download(url, target_path): """Download url to target_path.""" print("Downloading {}...".format(url)) # Create a custom context and fill in certifi CAs because GitHub Action's macOS CI # runners don't seem to have certificates installed, leading to a download # failure... context = ssl.create_default_context( ssl.Purpose.SERVER_AUTH, cafile=certifi.where() ) with urllib.request.urlopen(url, context=context) as response, open( target_path, "wb" ) as f: shutil.copyfileobj(response, f) def ensure_downloaded(url, sha256_sum): """Download .tar.bz2 tarball at url unless already present, extract.""" filename = path.basename(url) tarball = path.join(build_dir, filename) tarball_dir = filename.split(".tar")[0] if not path.exists(tarball): download(url, tarball) if not path.exists(path.join(build_dir, tarball_dir, "CMakeLists.txt")): hasher = hashlib.sha256() with open(tarball, "rb") as tb: hasher.update(tb.read()) assert hasher.hexdigest() == sha256_sum with tarfile.open(tarball, "r:xz") as tb: tb.extractall(build_dir) distutils.dir_util.mkpath(build_dir) distutils.dir_util.mkpath(prefix_dir) distutils.dir_util.mkpath(build_dir_ft) distutils.dir_util.mkpath(build_dir_hb) ensure_downloaded(FREETYPE_URL, FREETYPE_SHA256) ensure_downloaded(HARFBUZZ_URL, HARFBUZZ_SHA256) print("# First, build FreeType without Harfbuzz support") shell( "cmake -DBUILD_SHARED_LIBS=OFF " "-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE -DFT_WITH_HARFBUZZ=OFF " "-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE " "{} ..".format(CMAKE_GLOBAL_SWITCHES), cwd=build_dir_ft, ) shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_ft) print("\n# Next, build Harfbuzz and point it to the FreeType we just build.") shell( "cmake -DBUILD_SHARED_LIBS=OFF " + # https://stackoverflow.com/questions/3961446 ("-DCMAKE_POSITION_INDEPENDENT_CODE=ON " if bitness > 32 else "") + "-DHB_HAVE_FREETYPE=ON -DHB_HAVE_GLIB=OFF -DHB_HAVE_CORETEXT=OFF " "{} ..".format(CMAKE_GLOBAL_SWITCHES), cwd=build_dir_hb, ) shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_hb) print("\n# Lastly, rebuild FreeType, this time with Harfbuzz support.") harfbuzz_includes = path.join(prefix_dir, "include", "harfbuzz") shell( "cmake -DBUILD_SHARED_LIBS=ON " "-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=FALSE -DFT_WITH_HARFBUZZ=ON " "-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE " "-DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE " '-DPKG_CONFIG_EXECUTABLE="" ' # Prevent finding system libraries '-DHARFBUZZ_INCLUDE_DIRS="{}" ' "-DSKIP_INSTALL_HEADERS=ON " "{} ..".format(harfbuzz_includes, CMAKE_GLOBAL_SWITCHES), cwd=build_dir_ft, ) shell("cmake --build . --config Release --target install --parallel", cwd=build_dir_ft) # Move libraries from PREFIX/bin to PREFIX/lib if need be (Windows DLLs are # treated as runtimes and may end up in bin/). This keeps setup.py simple. target_dir = path.join(prefix_dir, "lib") bin_so = glob.glob(path.join(prefix_dir, "bin", "*freetype*")) bin_so.extend(glob.glob(path.join(prefix_dir, "lib64", "*freetype*"))) bin_so.extend(glob.glob(path.join(prefix_dir, "lib", "freetype*.dll"))) for so in bin_so: so_target_name = path.basename(so) if not so_target_name.startswith("lib"): so_target_name = "lib" + so_target_name lib_path = path.join(target_dir, so_target_name) print("# Moving '{}' to '{}'".format(so, lib_path)) if not path.exists(target_dir): os.makedirs(target_dir) os.replace(so, lib_path) freetype-py-2.5.1/_custom_build/0000775000175000017500000000000014664131406017025 5ustar georgeskgeorgeskfreetype-py-2.5.1/_custom_build/backend.py0000664000175000017500000000201014664131406020757 0ustar georgeskgeorgesk"""Custom PEP 517 build backend to provide different dependencies for wheel builds. We need some extra dependencies when we build a wheel that bundles the FreeType shared library (triggered when FREETYPEPY_BUNDLE_FT environment variable is set), as opposed to a pure Python wheel (py3-none-any.whl). For more info see: https://setuptools.pypa.io/en/latest/build_meta.html#dynamic-build-dependencies-and-other-build-meta-tweaks https://github.com/rougier/freetype-py/issues/183 """ import os from setuptools import build_meta as _orig from setuptools.build_meta import * def get_requires_for_build_wheel(config_settings=None): build_wheel_deps = _orig.get_requires_for_build_wheel(config_settings) if os.environ.get("FREETYPEPY_BUNDLE_FT"): build_wheel_deps += ["certifi", "cmake"] return build_wheel_deps def get_requires_for_build_editable(config_settings=None): # ensure pip install -e . uses same build deps as regular pip install/wheel return get_requires_for_build_wheel(config_settings) freetype-py-2.5.1/LICENSE.txt0000664000175000017500000000306114664131406016020 0ustar georgeskgeorgeskfreetype-py is licensed under the terms of the new or revised BSD license, as follows: Copyright (c) 2011-2014, Nicolas P. Rougier All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the freetype-py Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. freetype-py-2.5.1/pyproject.toml0000664000175000017500000000040114664131406017104 0ustar georgeskgeorgesk[build-system] requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"] # https://setuptools.pypa.io/en/latest/build_meta.html#dynamic-build-dependencies-and-other-build-meta-tweaks build-backend = "backend" backend-path = ["_custom_build"] freetype-py-2.5.1/freetype/0000775000175000017500000000000014664131406016020 5ustar georgeskgeorgeskfreetype-py-2.5.1/freetype/raw.py0000664000175000017500000003370314664131406017171 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # ----------------------------------------------------------------------------- ''' Freetype raw API This is the raw ctypes freetype binding. ''' import os import platform from ctypes import * import ctypes.util import freetype from freetype.ft_types import * from freetype.ft_enums import * from freetype.ft_errors import * from freetype.ft_structs import * # First, look for a bundled FreeType shared object on the top-level of the # installed freetype-py module. system = platform.system() if system == 'Windows': library_name = 'libfreetype.dll' elif system == 'Darwin': library_name = 'libfreetype.dylib' else: library_name = 'libfreetype.so' filename = os.path.join(os.path.dirname(freetype.__file__), library_name) # If no bundled shared object is found, look for a system-wide installed one. if not os.path.exists(filename): # on windows all ctypes does when checking for the library # is to append .dll to the end and look for an exact match # within any entry in PATH. filename = ctypes.util.find_library('freetype') if filename is None: if platform.system() == 'Windows': # Check current working directory for dll as ctypes fails to do so filename = os.path.join(os.path.realpath('.'), "freetype.dll") else: filename = library_name try: _lib = ctypes.CDLL(filename) except (OSError, TypeError): _lib = None raise RuntimeError('Freetype library not found') FT_Init_FreeType = _lib.FT_Init_FreeType FT_Done_FreeType = _lib.FT_Done_FreeType FT_Library_Version = _lib.FT_Library_Version try: FT_Library_SetLcdFilter= _lib.FT_Library_SetLcdFilter except AttributeError: def FT_Library_SetLcdFilter (*args, **kwargs): return 0 try: FT_Library_SetLcdFilterWeights = _lib.FT_Library_SetLcdFilterWeights except AttributeError: pass FT_New_Face = _lib.FT_New_Face FT_New_Memory_Face = _lib.FT_New_Memory_Face FT_Open_Face = _lib.FT_Open_Face FT_Attach_File = _lib.FT_Attach_File FT_Attach_Stream = _lib.FT_Attach_Stream try: FT_Reference_Face = _lib.FT_Reference_Face except AttributeError: pass FT_Done_Face = _lib.FT_Done_Face FT_Done_Glyph = _lib.FT_Done_Glyph FT_Select_Size = _lib.FT_Select_Size FT_Request_Size = _lib.FT_Request_Size FT_Set_Char_Size = _lib.FT_Set_Char_Size FT_Set_Pixel_Sizes = _lib.FT_Set_Pixel_Sizes FT_Load_Glyph = _lib.FT_Load_Glyph FT_Load_Char = _lib.FT_Load_Char FT_Set_Transform = _lib.FT_Set_Transform FT_Render_Glyph = _lib.FT_Render_Glyph FT_Get_Kerning = _lib.FT_Get_Kerning FT_Get_Track_Kerning = _lib.FT_Get_Track_Kerning FT_Get_Glyph_Name = _lib.FT_Get_Glyph_Name FT_Get_Glyph = _lib.FT_Get_Glyph FT_Glyph_Get_CBox = _lib.FT_Glyph_Get_CBox FT_Get_Postscript_Name = _lib.FT_Get_Postscript_Name FT_Get_Postscript_Name.restype = c_char_p FT_Select_Charmap = _lib.FT_Select_Charmap FT_Set_Charmap = _lib.FT_Set_Charmap FT_Get_Charmap_Index = _lib.FT_Get_Charmap_Index FT_Get_CMap_Language_ID= _lib.FT_Get_CMap_Language_ID try: #introduced between 2.2.x and 2.3.x FT_Get_CMap_Format = _lib.FT_Get_CMap_Format except AttributeError: pass FT_Get_Char_Index = _lib.FT_Get_Char_Index FT_Get_First_Char = _lib.FT_Get_First_Char FT_Get_Next_Char = _lib.FT_Get_Next_Char FT_Get_Name_Index = _lib.FT_Get_Name_Index FT_Get_SubGlyph_Info = _lib.FT_Get_SubGlyph_Info try: FT_Get_FSType_Flags = _lib.FT_Get_FSType_Flags FT_Get_FSType_Flags.restype = c_ushort except AttributeError: pass FT_Get_X11_Font_Format = _lib.FT_Get_X11_Font_Format FT_Get_X11_Font_Format.restype = c_char_p FT_Get_Sfnt_Name_Count = _lib.FT_Get_Sfnt_Name_Count FT_Get_Sfnt_Name = _lib.FT_Get_Sfnt_Name try: # introduced between 2.2.x and 2.3.x FT_Get_Advance = _lib.FT_Get_Advance except AttributeError: pass FT_Outline_GetInsideBorder = _lib.FT_Outline_GetInsideBorder FT_Outline_GetOutsideBorder = _lib.FT_Outline_GetOutsideBorder FT_Outline_Get_BBox = _lib.FT_Outline_Get_BBox FT_Outline_Get_CBox = _lib.FT_Outline_Get_CBox try: # since 2.4.10 FT_Outline_EmboldenXY = _lib.FT_Outline_EmboldenXY except AttributeError: pass FT_Stroker_New = _lib.FT_Stroker_New FT_Stroker_Set = _lib.FT_Stroker_Set FT_Stroker_Rewind = _lib.FT_Stroker_Rewind FT_Stroker_ParseOutline = _lib.FT_Stroker_ParseOutline FT_Stroker_BeginSubPath = _lib.FT_Stroker_BeginSubPath FT_Stroker_EndSubPath = _lib.FT_Stroker_EndSubPath FT_Stroker_LineTo = _lib.FT_Stroker_LineTo FT_Stroker_ConicTo = _lib.FT_Stroker_ConicTo FT_Stroker_CubicTo = _lib.FT_Stroker_CubicTo FT_Stroker_GetBorderCounts = _lib.FT_Stroker_GetBorderCounts FT_Stroker_ExportBorder = _lib.FT_Stroker_ExportBorder FT_Stroker_GetCounts = _lib.FT_Stroker_GetCounts FT_Stroker_Export = _lib.FT_Stroker_Export FT_Stroker_Done = _lib.FT_Stroker_Done FT_Glyph_Stroke = _lib.FT_Glyph_Stroke FT_Glyph_StrokeBorder = _lib.FT_Glyph_StrokeBorder FT_Glyph_To_Bitmap = _lib.FT_Glyph_To_Bitmap # FT_Property_Get/FT_Property_Set requires FreeType 2.7.x+ try: FT_Property_Get = _lib.FT_Property_Get FT_Property_Set = _lib.FT_Property_Set except AttributeError: pass # These two are only found when TT debugger is enabled try: TT_New_Context = _lib.TT_New_Context TT_RunIns = _lib.TT_RunIns except AttributeError: pass # Routines for variable font support. These were introduced at different # points in FreeType's history (except for FT_Get_MM_Var which has been # around for a long time). FT_Get_MM_Var = _lib.FT_Get_MM_Var # v2.old # -- since 2.8.1 for sure (some 2.7.1 or possibly older, but to be safe, # implementation should check FT version >= 2.8.1 try: FT_Get_Var_Axis_Flags = _lib.FT_Get_Var_Axis_Flags FT_Get_Var_Blend_Coordinates = _lib.FT_Get_Var_Blend_Coordinates FT_Get_Var_Design_Coordinates = _lib.FT_Get_Var_Design_Coordinates FT_Set_Var_Blend_Coordinates = _lib.FT_Set_Var_Blend_Coordinates FT_Set_Var_Design_Coordinates = _lib.FT_Set_Var_Design_Coordinates except AttributeError: pass # -- since v2.9; we can work around if these are not present. try: FT_Done_MM_Var = _lib.FT_Done_MM_Var FT_Set_Named_Instance = _lib.FT_Set_Named_Instance except AttributeError: pass # Wholesale import of 102 routines which can be reasonably expected # to be found in freetype 2.2.x onwards. Some of these might need # to be protected with try:/except AttributeError: in some freetype builds. FTC_CMapCache_Lookup = _lib.FTC_CMapCache_Lookup FTC_CMapCache_New = _lib.FTC_CMapCache_New FTC_ImageCache_Lookup = _lib.FTC_ImageCache_Lookup FTC_ImageCache_New = _lib.FTC_ImageCache_New FTC_Manager_Done = _lib.FTC_Manager_Done FTC_Manager_LookupFace = _lib.FTC_Manager_LookupFace FTC_Manager_LookupSize = _lib.FTC_Manager_LookupSize FTC_Manager_New = _lib.FTC_Manager_New FTC_Manager_RemoveFaceID = _lib.FTC_Manager_RemoveFaceID FTC_Manager_Reset = _lib.FTC_Manager_Reset FTC_Node_Unref = _lib.FTC_Node_Unref FTC_SBitCache_Lookup = _lib.FTC_SBitCache_Lookup FTC_SBitCache_New = _lib.FTC_SBitCache_New FT_Activate_Size = _lib.FT_Activate_Size FT_Add_Default_Modules = _lib.FT_Add_Default_Modules FT_Add_Module = _lib.FT_Add_Module FT_Angle_Diff = _lib.FT_Angle_Diff FT_Atan2 = _lib.FT_Atan2 FT_Bitmap_Convert = _lib.FT_Bitmap_Convert FT_Bitmap_Copy = _lib.FT_Bitmap_Copy FT_Bitmap_Done = _lib.FT_Bitmap_Done FT_Bitmap_Embolden = _lib.FT_Bitmap_Embolden FT_Bitmap_New = _lib.FT_Bitmap_New FT_CeilFix = _lib.FT_CeilFix FT_ClassicKern_Free = _lib.FT_ClassicKern_Free FT_ClassicKern_Validate = _lib.FT_ClassicKern_Validate FT_Cos = _lib.FT_Cos FT_DivFix = _lib.FT_DivFix FT_Done_Library = _lib.FT_Done_Library FT_Done_Size = _lib.FT_Done_Size FT_FloorFix = _lib.FT_FloorFix try: # Not in default windows build of 2.8.x FT_Get_BDF_Charset_ID = _lib.FT_Get_BDF_Charset_ID FT_Get_BDF_Property = _lib.FT_Get_BDF_Property except AttributeError: pass try: FT_Get_Color_Glyph_Layer = _lib.FT_Get_Color_Glyph_Layer # 2.10 FT_Get_Color_Glyph_Layer.restype = FT_Bool FT_Get_Color_Glyph_Layer.argtypes = [FT_Face, FT_UInt, POINTER(FT_UInt), POINTER(FT_UInt), POINTER(FT_LayerIterator)] FT_Get_Color_Glyph_Paint = _lib.FT_Get_Color_Glyph_Paint # 2.13 FT_Get_Color_Glyph_Paint.restype = FT_Bool FT_Get_Color_Glyph_Paint.argtypes = [FT_Face, FT_UInt, FT_UInt, # FT_Color_Root_Transform enums POINTER(FT_OpaquePaint)] except AttributeError: pass try: FT_Face_GetCharVariantIndex = _lib.FT_Face_GetCharVariantIndex FT_Face_GetCharVariantIndex.argtypes = [FT_Face, FT_ULong, FT_ULong] FT_Face_GetCharVariantIndex.restype = FT_UInt FT_Face_GetCharVariantIsDefault = _lib.FT_Face_GetCharVariantIsDefault FT_Face_GetCharVariantIsDefault.argtypes = [FT_Face, FT_ULong, FT_ULong] FT_Face_GetCharVariantIsDefault.restype = FT_Int FT_Face_GetVariantSelectors = _lib.FT_Face_GetVariantSelectors FT_Face_GetVariantSelectors.argtypes = [FT_Face] FT_Face_GetVariantSelectors.restype = POINTER(FT_UInt32) FT_Face_GetVariantsOfChar = _lib.FT_Face_GetVariantsOfChar FT_Face_GetVariantsOfChar.argtypes = [FT_Face, FT_ULong] FT_Face_GetVariantsOfChar.restype = POINTER(FT_UInt32) FT_Face_GetCharsOfVariant = _lib.FT_Face_GetCharsOfVariant FT_Face_GetVariantsOfChar.argtypes = [FT_Face, FT_ULong] FT_Face_GetCharsOfVariant.restype = POINTER(FT_UInt32) except AttributeError: pass FT_Get_Module = _lib.FT_Get_Module FT_Get_Multi_Master = _lib.FT_Get_Multi_Master FT_Get_PFR_Advance = _lib.FT_Get_PFR_Advance FT_Get_PFR_Kerning = _lib.FT_Get_PFR_Kerning FT_Get_PFR_Metrics = _lib.FT_Get_PFR_Metrics FT_Get_PS_Font_Info = _lib.FT_Get_PS_Font_Info FT_Get_PS_Font_Private = _lib.FT_Get_PS_Font_Private FT_Get_Renderer = _lib.FT_Get_Renderer FT_Get_Sfnt_Table = _lib.FT_Get_Sfnt_Table FT_Get_TrueType_Engine_Type = _lib.FT_Get_TrueType_Engine_Type FT_Get_WinFNT_Header = _lib.FT_Get_WinFNT_Header FT_Glyph_Copy = _lib.FT_Glyph_Copy FT_GlyphSlot_Embolden = _lib.FT_GlyphSlot_Embolden FT_GlyphSlot_Oblique = _lib.FT_GlyphSlot_Oblique FT_GlyphSlot_Own_Bitmap = _lib.FT_GlyphSlot_Own_Bitmap FT_Glyph_Transform = _lib.FT_Glyph_Transform FT_Has_PS_Glyph_Names = _lib.FT_Has_PS_Glyph_Names FT_List_Add = _lib.FT_List_Add FT_List_Finalize = _lib.FT_List_Finalize FT_List_Find = _lib.FT_List_Find FT_List_Insert = _lib.FT_List_Insert FT_List_Iterate = _lib.FT_List_Iterate FT_List_Remove = _lib.FT_List_Remove FT_List_Up = _lib.FT_List_Up FT_Load_Sfnt_Table = _lib.FT_Load_Sfnt_Table FT_Matrix_Invert = _lib.FT_Matrix_Invert FT_Matrix_Multiply = _lib.FT_Matrix_Multiply FT_MulDiv = _lib.FT_MulDiv FT_MulFix = _lib.FT_MulFix FT_New_Library = _lib.FT_New_Library FT_New_Size = _lib.FT_New_Size FT_OpenType_Free = _lib.FT_OpenType_Free FT_OpenType_Validate = _lib.FT_OpenType_Validate FT_Outline_Check = _lib.FT_Outline_Check FT_Outline_Copy = _lib.FT_Outline_Copy FT_Outline_Decompose = _lib.FT_Outline_Decompose FT_Outline_Done = _lib.FT_Outline_Done FT_Outline_Embolden = _lib.FT_Outline_Embolden FT_Outline_Get_Bitmap = _lib.FT_Outline_Get_Bitmap FT_Outline_Get_Orientation = _lib.FT_Outline_Get_Orientation FT_Outline_New = _lib.FT_Outline_New FT_Outline_Render = _lib.FT_Outline_Render FT_Outline_Reverse = _lib.FT_Outline_Reverse FT_Outline_Transform = _lib.FT_Outline_Transform FT_Outline_Translate = _lib.FT_Outline_Translate FT_Remove_Module = _lib.FT_Remove_Module FT_Render_Glyph = _lib.FT_Render_Glyph FT_RoundFix = _lib.FT_RoundFix FT_Set_Debug_Hook = _lib.FT_Set_Debug_Hook FT_Set_MM_Blend_Coordinates = _lib.FT_Set_MM_Blend_Coordinates FT_Set_MM_Design_Coordinates = _lib.FT_Set_MM_Design_Coordinates FT_Set_Renderer = _lib.FT_Set_Renderer FT_Sfnt_Table_Info = _lib.FT_Sfnt_Table_Info FT_Sin = _lib.FT_Sin FT_Stream_OpenGzip = _lib.FT_Stream_OpenGzip FT_Stream_OpenLZW = _lib.FT_Stream_OpenLZW FT_Tan = _lib.FT_Tan FT_TrueTypeGX_Free = _lib.FT_TrueTypeGX_Free FT_TrueTypeGX_Validate = _lib.FT_TrueTypeGX_Validate FT_Vector_From_Polar = _lib.FT_Vector_From_Polar FT_Vector_Length = _lib.FT_Vector_Length FT_Vector_Polarize = _lib.FT_Vector_Polarize FT_Vector_Rotate = _lib.FT_Vector_Rotate FT_Vector_Transform = _lib.FT_Vector_Transform FT_Vector_Unit = _lib.FT_Vector_Unit # Wholesale import ends freetype-py-2.5.1/freetype/__init__.py0000664000175000017500000027066714664131406020153 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' FreeType high-level python API This the bindings for the high-level API of FreeType (that must be installed somewhere on your system). Note: C Library will be searched using the ctypes.util.find_library. However, this search might fail. In such a case (or for other reasons), you may have to specify an explicit path below. ''' import io import sys from ctypes import * import ctypes.util import struct from freetype.raw import * # Hack to get unicode class in python3 PY3 = sys.version_info[0] == 3 if PY3: unicode = str def unmake_tag(i): # roughly opposite of FT_MAKE_TAG, converts 32-bit int to Python string # could do with .to_bytes if limited to Python 3.2 or higher... b = struct.pack('>I', i) return b.decode('ascii', errors='replace') _handle = None FT_Library_filename = filename class _FT_Library_Wrapper(FT_Library): '''Subclass of FT_Library to help with calling FT_Done_FreeType''' # for some reason this doesn't get carried over and ctypes complains _type_ = FT_Library._type_ # Store ref to FT_Done_FreeType otherwise it will be deleted before needed. _ft_done_freetype = FT_Done_FreeType def __del__(self): # call FT_Done_FreeType # This does not work properly (seg fault on sime system (OSX)) # self._ft_done_freetype(self) pass def _init_freetype(): global _handle _handle = _FT_Library_Wrapper() error = FT_Init_FreeType( byref(_handle) ) if error: raise FT_Exception(error) try: set_lcd_filter( FT_LCD_FILTER_DEFAULT ) except: pass # ----------------------------------------------------------------------------- # High-level API of FreeType 2 # ----------------------------------------------------------------------------- def get_handle(): ''' Get unique FT_Library handle ''' if not _handle: _init_freetype() return _handle def version(): ''' Return the version of the FreeType library being used as a tuple of ( major version number, minor version number, patch version number ) ''' amajor = FT_Int() aminor = FT_Int() apatch = FT_Int() library = get_handle() FT_Library_Version(library, byref(amajor), byref(aminor), byref(apatch)) return (amajor.value, aminor.value, apatch.value) # ----------------------------------------------------------------------------- # Stand alone functions # ----------------------------------------------------------------------------- def set_lcd_filter(filt): ''' This function is used to apply color filtering to LCD decimated bitmaps, like the ones used when calling FT_Render_Glyph with FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V. **Note** This feature is always disabled by default. Clients must make an explicit call to this function with a 'filter' value other than FT_LCD_FILTER_NONE in order to enable it. Due to PATENTS covering subpixel rendering, this function doesn't do anything except returning 'FT_Err_Unimplemented_Feature' if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not defined in your build of the library, which should correspond to all default builds of FreeType. The filter affects glyph bitmaps rendered through FT_Render_Glyph, FT_Outline_Get_Bitmap, FT_Load_Glyph, and FT_Load_Char. It does not affect the output of FT_Outline_Render and FT_Outline_Get_Bitmap. If this feature is activated, the dimensions of LCD glyph bitmaps are either larger or taller than the dimensions of the corresponding outline with regards to the pixel grid. For example, for FT_RENDER_MODE_LCD, the filter adds up to 3 pixels to the left, and up to 3 pixels to the right. The bitmap offset values are adjusted correctly, so clients shouldn't need to modify their layout and glyph positioning code when enabling the filter. ''' library = get_handle() error = FT_Library_SetLcdFilter(library, filt) if error: raise FT_Exception(error) def set_lcd_filter_weights(a,b,c,d,e): ''' Use this function to override the filter weights selected by FT_Library_SetLcdFilter. By default, FreeType uses the quintuple (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10, 0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and FT_LCD_FILTER_LEGACY. **Note** Only available if version > 2.4.0 ''' if version()>=(2,4,0): library = get_handle() weights = FT_Char(5)(a,b,c,d,e) error = FT_Library_SetLcdFilterWeights(library, weights) if error: raise FT_Exception(error) else: raise RuntimeError( 'set_lcd_filter_weights require freetype > 2.4.0') def _encode_filename(filename): encoded = filename.encode(sys.getfilesystemencoding()) if "?" not in filename and b"?" in encoded: # A bug, decoding mbcs always ignore exception, still isn't fixed in Python 2, # view http://bugs.python.org/issue850997 for detail raise UnicodeError() return encoded # ----------------------------------------------------------------------------- # Direct wrapper (simple renaming) # ----------------------------------------------------------------------------- Vector = FT_Vector Matrix = FT_Matrix # ----------------------------------------------------------------------------- # Handling for FT_Done_MM_Var, which was added in FreeType 2.9. Prior to that, # we need to import libc and use libc free on the memory allocated for the # FT_MM_Var data structure. See Face.get_variation_info(). # ----------------------------------------------------------------------------- if version() < (2,9,1): if platform.system() == "Windows": libcpath = ctypes.util.find_library("msvcrt") else: libcpath = ctypes.util.find_library("c") libc = CDLL(libcpath) libc.free.argtypes = [c_void_p] libc.free.restype = None def FT_Done_MM_Var_func(p): libc.free(p) else: def FT_Done_MM_Var_func(p): error = FT_Done_MM_Var(get_handle(), p) if error: raise FT_Exception("Failure calling FT_Done_MM_Var") # ----------------------------------------------------------------------------- class BBox( object ): ''' FT_BBox wrapper. A structure used to hold an outline's bounding box, i.e., the coordinates of its extrema in the horizontal and vertical directions. **Note** The bounding box is specified with the coordinates of the lower left and the upper right corner. In PostScript, those values are often called (llx,lly) and (urx,ury), respectively. If 'yMin' is negative, this value gives the glyph's descender. Otherwise, the glyph doesn't descend below the baseline. Similarly, if 'ymax' is positive, this value gives the glyph's ascender. 'xMin' gives the horizontal distance from the glyph's origin to the left edge of the glyph's bounding box. If 'xMin' is negative, the glyph extends to the left of the origin. ''' def __init__(self, bbox): ''' Create a new BBox object. :param bbox: a FT_BBox or a tuple of 4 values ''' if type(bbox) is FT_BBox: self._FT_BBox = bbox else: self._FT_BBox = FT_BBox(*bbox) xMin = property(lambda self: self._FT_BBox.xMin, doc = 'The horizontal minimum (left-most).') yMin = property(lambda self: self._FT_BBox.yMin, doc = 'The vertical minimum (bottom-most).') xMax = property(lambda self: self._FT_BBox.xMax, doc = 'The horizontal maximum (right-most).') yMax = property(lambda self: self._FT_BBox.yMax, doc = 'The vertical maximum (top-most).') # ----------------------------------------------------------------------------- class GlyphMetrics( object ): ''' A structure used to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has been used while loading the glyph, values are expressed in font units instead. **Note** If not disabled with FT_LOAD_NO_HINTING, the values represent dimensions of the hinted glyph (in case hinting is applicable). Stroking a glyph with an outside border does not increase ‘horiAdvance’ or ‘vertAdvance’; you have to manually adjust these values to account for the added width and height. ''' def __init__(self, metrics ): ''' Create a new GlyphMetrics object. :param metrics: a FT_Glyph_Metrics ''' self._FT_Glyph_Metrics = metrics width = property( lambda self: self._FT_Glyph_Metrics.width, doc = '''The glyph's width.''' ) height = property( lambda self: self._FT_Glyph_Metrics.height, doc = '''The glyph's height.''' ) horiBearingX = property( lambda self: self._FT_Glyph_Metrics.horiBearingX, doc = '''Left side bearing for horizontal layout.''' ) horiBearingY = property( lambda self: self._FT_Glyph_Metrics.horiBearingY, doc = '''Top side bearing for horizontal layout.''' ) horiAdvance = property( lambda self: self._FT_Glyph_Metrics.horiAdvance, doc = '''Advance width for horizontal layout.''' ) vertBearingX = property( lambda self: self._FT_Glyph_Metrics.vertBearingX, doc = '''Left side bearing for vertical layout.''' ) vertBearingY = property( lambda self: self._FT_Glyph_Metrics.vertBearingY, doc = '''Top side bearing for vertical layout. Larger positive values mean further below the vertical glyph origin.''' ) vertAdvance = property( lambda self: self._FT_Glyph_Metrics.vertAdvance, doc = '''Advance height for vertical layout. Positive values mean the glyph has a positive advance downward.''' ) # ----------------------------------------------------------------------------- class SizeMetrics( object ): ''' The size metrics structure gives the metrics of a size object. **Note** The scaling values, if relevant, are determined first during a size changing operation. The remaining fields are then set by the driver. For scalable formats, they are usually set to scaled values of the corresponding fields in Face. Note that due to glyph hinting, these values might not be exact for certain fonts. Thus they must be treated as unreliable with an error margin of at least one pixel! Indeed, the only way to get the exact metrics is to render all glyphs. As this would be a definite performance hit, it is up to client applications to perform such computations. The SizeMetrics structure is valid for bitmap fonts also. ''' def __init__(self, metrics ): ''' Create a new SizeMetrics object. :param metrics: a FT_SizeMetrics ''' self._FT_Size_Metrics = metrics x_ppem = property( lambda self: self._FT_Size_Metrics.x_ppem, doc = '''The width of the scaled EM square in pixels, hence the term 'ppem' (pixels per EM). It is also referred to as 'nominal width'.''' ) y_ppem = property( lambda self: self._FT_Size_Metrics.y_ppem, doc = '''The height of the scaled EM square in pixels, hence the term 'ppem' (pixels per EM). It is also referred to as 'nominal height'.''' ) x_scale = property( lambda self: self._FT_Size_Metrics.x_scale, doc = '''A 16.16 fractional scaling value used to convert horizontal metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats.''' ) y_scale = property( lambda self: self._FT_Size_Metrics.y_scale, doc = '''A 16.16 fractional scaling value used to convert vertical metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats.''' ) ascender = property( lambda self: self._FT_Size_Metrics.ascender, doc = '''The ascender in 26.6 fractional pixels. See Face for the details.''' ) descender = property( lambda self: self._FT_Size_Metrics.descender, doc = '''The descender in 26.6 fractional pixels. See Face for the details.''' ) height = property( lambda self: self._FT_Size_Metrics.height, doc = '''The height in 26.6 fractional pixels. See Face for the details.''' ) max_advance = property(lambda self: self._FT_Size_Metrics.max_advance, doc = '''The maximal advance width in 26.6 fractional pixels. See Face for the details.''' ) # ----------------------------------------------------------------------------- class BitmapSize( object ): ''' FT_Bitmap_Size wrapper This structure models the metrics of a bitmap strike (i.e., a set of glyphs for a given point size and resolution) in a bitmap font. It is used for the 'available_sizes' field of Face. **Note** Windows FNT: The nominal size given in a FNT font is not reliable. Thus when the driver finds it incorrect, it sets 'size' to some calculated values and sets 'x_ppem' and 'y_ppem' to the pixel width and height given in the font, respectively. TrueType embedded bitmaps: 'size', 'width', and 'height' values are not contained in the bitmap strike itself. They are computed from the global font parameters. ''' def __init__(self, size ): ''' Create a new SizeMetrics object. :param size: a FT_Bitmap_Size ''' self._FT_Bitmap_Size = size height = property( lambda self: self._FT_Bitmap_Size.height, doc = '''The vertical distance, in pixels, between two consecutive baselines. It is always positive.''') width = property( lambda self: self._FT_Bitmap_Size.width, doc = '''The average width, in pixels, of all glyphs in the strike.''') size = property( lambda self: self._FT_Bitmap_Size.size, doc = '''The nominal size of the strike in 26.6 fractional points. This field is not very useful.''') x_ppem = property( lambda self: self._FT_Bitmap_Size.x_ppem, doc = '''The horizontal ppem (nominal width) in 26.6 fractional pixels.''') y_ppem = property( lambda self: self._FT_Bitmap_Size.y_ppem, doc = '''The vertical ppem (nominal width) in 26.6 fractional pixels.''') # ----------------------------------------------------------------------------- class Bitmap(object): ''' FT_Bitmap wrapper A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various depths through the 'pixel_mode' field. *Note*: For now, the only pixel modes supported by FreeType are mono and grays. However, drivers might be added in the future to support more 'colorful' options. ''' def __init__(self, bitmap): ''' Create a new Bitmap object. :param bitmap: a FT_Bitmap ''' self._FT_Bitmap = bitmap rows = property(lambda self: self._FT_Bitmap.rows, doc = '''The number of bitmap rows.''') width = property(lambda self: self._FT_Bitmap.width, doc = '''The number of pixels in bitmap row.''') pitch = property(lambda self: self._FT_Bitmap.pitch, doc = '''The pitch's absolute value is the number of bytes taken by one bitmap row, including padding. However, the pitch is positive when the bitmap has a 'down' flow, and negative when it has an 'up' flow. In all cases, the pitch is an offset to add to a bitmap pointer in order to go down one row. Note that 'padding' means the alignment of a bitmap to a byte border, and FreeType functions normally align to the smallest possible integer value. For the B/W rasterizer, 'pitch' is always an even number. To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert. Alternatively, you might use callback functions to directly render to the application's surface; see the file 'example2.py' in the tutorial for a demonstration.''') def _get_buffer(self): data = [self._FT_Bitmap.buffer[i] for i in range(self.rows*self.pitch)] return data buffer = property(_get_buffer, doc = '''A typeless pointer to the bitmap buffer. This value should be aligned on 32-bit boundaries in most cases.''') num_grays = property(lambda self: self._FT_Bitmap.num_grays, doc = '''This field is only used with FT_PIXEL_MODE_GRAY; it gives the number of gray levels used in the bitmap.''') pixel_mode = property(lambda self: self._FT_Bitmap.pixel_mode, doc = '''The pixel mode, i.e., how pixel bits are stored. See FT_Pixel_Mode for possible values.''') palette_mode = property(lambda self: self._FT_Bitmap.palette_mode, doc ='''This field is intended for paletted pixel modes; it indicates how the palette is stored. Not used currently.''') palette = property(lambda self: self._FT_Bitmap.palette, doc = '''A typeless pointer to the bitmap palette; this field is intended for paletted pixel modes. Not used currently.''') # ----------------------------------------------------------------------------- class Charmap( object ): ''' FT_Charmap wrapper. A handle to a given character map. A charmap is used to translate character codes in a given encoding into glyph indexes for its parent's face. Some font formats may provide several charmaps per font. Each face object owns zero or more charmaps, but only one of them can be 'active' and used by FT_Get_Char_Index or FT_Load_Char. The list of available charmaps in a face is available through the 'face.num_charmaps' and 'face.charmaps' fields of FT_FaceRec. The currently active charmap is available as 'face.charmap'. You should call FT_Set_Charmap to change it. **Note**: When a new face is created (either through FT_New_Face or FT_Open_Face), the library looks for a Unicode charmap within the list and automatically activates it. **See also**: See FT_CharMapRec for the publicly accessible fields of a given character map. ''' def __init__( self, charmap ): ''' Create a new Charmap object. Parameters: ----------- charmap : a FT_Charmap ''' self._FT_Charmap = charmap encoding = property( lambda self: self._FT_Charmap.contents.encoding, doc = '''An FT_Encoding tag identifying the charmap. Use this with FT_Select_Charmap.''') platform_id = property( lambda self: self._FT_Charmap.contents.platform_id, doc = '''An ID number describing the platform for the following encoding ID. This comes directly from the TrueType specification and should be emulated for other formats.''') encoding_id = property( lambda self: self._FT_Charmap.contents.encoding_id, doc = '''A platform specific encoding number. This also comes from the TrueType specification and should be emulated similarly.''') def _get_encoding_name(self): encoding = self.encoding for key,value in FT_ENCODINGS.items(): if encoding == value: return key return 'Unknown encoding' encoding_name = property( _get_encoding_name, doc = '''A platform specific encoding name. This also comes from the TrueType specification and should be emulated similarly.''') def _get_index( self ): return FT_Get_Charmap_Index( self._FT_Charmap ) index = property( _get_index, doc = '''The index into the array of character maps within the face to which 'charmap' belongs. If an error occurs, -1 is returned.''') def _get_cmap_language_id( self ): return FT_Get_CMap_Language_ID( self._FT_Charmap ) cmap_language_id = property( _get_cmap_language_id, doc = '''The language ID of 'charmap'. If 'charmap' doesn't belong to a TrueType/sfnt face, just return 0 as the default value.''') def _get_cmap_format( self ): return FT_Get_CMap_Format( self._FT_Charmap ) cmap_format = property( _get_cmap_format, doc = '''The format of 'charmap'. If 'charmap' doesn't belong to a TrueType/sfnt face, return -1.''') # ----------------------------------------------------------------------------- class Outline( object ): ''' FT_Outline wrapper. This structure is used to describe an outline to the scan-line converter. ''' def __init__( self, outline ): ''' Create a new Outline object. :param charmap: a FT_Outline ''' self._FT_Outline = outline n_contours = property(lambda self: self._FT_Outline.n_contours) def _get_contours(self): n = self._FT_Outline.n_contours data = [self._FT_Outline.contours[i] for i in range(n)] return data contours = property(_get_contours, doc = '''The number of contours in the outline.''') n_points = property(lambda self: self._FT_Outline.n_points) def _get_points(self): n = self._FT_Outline.n_points data = [] for i in range(n): v = self._FT_Outline.points[i] data.append( (v.x,v.y) ) return data points = property( _get_points, doc = '''The number of points in the outline.''') def _get_tags(self): n = self._FT_Outline.n_points data = [self._FT_Outline.tags[i] for i in range(n)] return data tags = property(_get_tags, doc = '''A list of 'n_points' chars, giving each outline point's type. If bit 0 is unset, the point is 'off' the curve, i.e., a Bezier control point, while it is 'on' if set. Bit 1 is meaningful for 'off' points only. If set, it indicates a third-order Bezier arc control point; and a second-order control point if unset. If bit 2 is set, bits 5-7 contain the drop-out mode (as defined in the OpenType specification; the value is the same as the argument to the SCANMODE instruction). Bits 3 and 4 are reserved for internal purposes.''') flags = property(lambda self: self._FT_Outline.flags, doc = '''A set of bit flags used to characterize the outline and give hints to the scan-converter and hinter on how to convert/grid-fit it. See FT_OUTLINE_FLAGS.''') def get_inside_border( self ): ''' Retrieve the FT_StrokerBorder value corresponding to the 'inside' borders of a given outline. :return: The border index. FT_STROKER_BORDER_RIGHT for empty or invalid outlines. ''' return FT_Outline_GetInsideBorder( byref(self._FT_Outline) ) def get_outside_border( self ): ''' Retrieve the FT_StrokerBorder value corresponding to the 'outside' borders of a given outline. :return: The border index. FT_STROKER_BORDER_RIGHT for empty or invalid outlines. ''' return FT_Outline_GetOutsideBorder( byref(self._FT_Outline) ) def get_bbox(self): ''' Compute the exact bounding box of an outline. This is slower than computing the control box. However, it uses an advanced algorithm which returns very quickly when the two boxes coincide. Otherwise, the outline Bezier arcs are traversed to extract their extrema. ''' bbox = FT_BBox() error = FT_Outline_Get_BBox(byref(self._FT_Outline), byref(bbox)) if error: raise FT_Exception(error) return BBox(bbox) def get_cbox(self): ''' Return an outline's 'control box'. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline which contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the 'ftbbox' component which is dedicated to this single task. ''' bbox = FT_BBox() FT_Outline_Get_CBox(byref(self._FT_Outline), byref(bbox)) return BBox(bbox) _od_move_to_noop = FT_Outline_MoveToFunc(lambda a, b: 0) def _od_move_to_builder(self, cb): if cb is None: return self._od_move_to_noop def move_to(a, b): return cb(a[0], b) or 0 return FT_Outline_MoveToFunc(move_to) _od_line_to_noop = FT_Outline_LineToFunc(lambda a, b: 0) def _od_line_to_builder(self, cb): if cb is None: return self._od_line_to_noop def line_to(a, b): return cb(a[0], b) or 0 return FT_Outline_LineToFunc(line_to) _od_conic_to_noop = FT_Outline_ConicToFunc(lambda a, b, c: 0) def _od_conic_to_builder(self, cb): if cb is None: return self._od_conic_to_noop def conic_to(a, b, c): return cb(a[0], b[0], c) or 0 return FT_Outline_ConicToFunc(conic_to) _od_cubic_to_noop = FT_Outline_CubicToFunc(lambda a, b, c, d: 0) def _od_cubic_to_builder(self, cb): if cb is None: return self._od_cubic_to_noop def cubic_to(a, b, c, d): return cb(a[0], b[0], c[0], d) or 0 return FT_Outline_CubicToFunc(cubic_to) def decompose(self, context=None, move_to=None, line_to=None, conic_to=None, cubic_to=None, shift=0, delta=0): ''' Decompose the outline into a sequence of move, line, conic, and cubic segments. :param context: Arbitrary contextual object which will be passed as the last parameter of all callbacks. Typically an object to be drawn to, but can be anything. :param move_to: Callback which will be passed an `FT_Vector` control point and the context. Called when outline needs to jump to a new path component. :param line_to: Callback which will be passed an `FT_Vector` control point and the context. Called to draw a straight line from the current position to the control point. :param conic_to: Callback which will be passed two `FT_Vector` control points and the context. Called to draw a second-order Bézier curve from the current position using the passed control points. :param curve_to: Callback which will be passed three `FT_Vector` control points and the context. Called to draw a third-order Bézier curve from the current position using the passed control points. :param shift: Passed to FreeType which will transform vectors via `x = (x << shift) - delta` and `y = (y << shift) - delta` :param delta: Passed to FreeType which will transform vectors via `x = (x << shift) - delta` and `y = (y << shift) - delta` :since: 1.3 ''' func = FT_Outline_Funcs( move_to = self._od_move_to_builder(move_to), line_to = self._od_line_to_builder(line_to), conic_to = self._od_conic_to_builder(conic_to), cubic_to = self._od_cubic_to_builder(cubic_to), shift = shift, delta = FT_Pos(delta), ) error = FT_Outline_Decompose( byref(self._FT_Outline), byref(func), py_object(context) ) if error: raise FT_Exception( error ) # ----------------------------------------------------------------------------- class Glyph( object ): ''' FT_Glyph wrapper. The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed float format. ''' def __init__( self, glyph ): ''' Create Glyph object from an FT glyph. :param glyph: valid FT_Glyph object ''' self._FT_Glyph = glyph def __del__( self ): ''' Destroy glyph. ''' FT_Done_Glyph( self._FT_Glyph ) def _get_format( self ): return self._FT_Glyph.contents.format format = property( _get_format, doc = '''The format of the glyph's image.''') def stroke( self, stroker, destroy=False ): ''' Stroke a given outline glyph object with a given stroker. :param stroker: A stroker handle. :param destroy: A Boolean. If 1, the source glyph object is destroyed on success. **Note**: The source glyph is untouched in case of error. ''' error = FT_Glyph_Stroke( byref(self._FT_Glyph), stroker._FT_Stroker, destroy ) if error: raise FT_Exception( error ) def to_bitmap( self, mode, origin, destroy=False ): ''' Convert a given glyph object to a bitmap glyph object. :param mode: An enumeration that describes how the data is rendered. :param origin: A pointer to a vector used to translate the glyph image before rendering. Can be 0 (if no translation). The origin is expressed in 26.6 pixels. We also detect a plain vector and make a pointer out of it, if that's the case. :param destroy: A boolean that indicates that the original glyph image should be destroyed by this function. It is never destroyed in case of error. **Note**: This function does nothing if the glyph format isn't scalable. The glyph image is translated with the 'origin' vector before rendering. The first parameter is a pointer to an FT_Glyph handle, that will be replaced by this function (with newly allocated data). Typically, you would use (omitting error handling): ''' if ( type(origin) == FT_Vector ): error = FT_Glyph_To_Bitmap( byref(self._FT_Glyph), mode, byref(origin), destroy ) else: error = FT_Glyph_To_Bitmap( byref(self._FT_Glyph), mode, origin, destroy ) if error: raise FT_Exception( error ) return BitmapGlyph( self._FT_Glyph ) def get_cbox(self, bbox_mode): ''' Return an outline's 'control box'. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline which contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the 'ftbbox' component which is dedicated to this single task. :param mode: The mode which indicates how to interpret the returned bounding box values. **Note**: Coordinates are relative to the glyph origin, using the y upwards convention. If the glyph has been loaded with FT_LOAD_NO_SCALE, 'bbox_mode' must be set to FT_GLYPH_BBOX_UNSCALED to get unscaled font units in 26.6 pixel format. The value FT_GLYPH_BBOX_SUBPIXELS is another name for this constant. Note that the maximum coordinates are exclusive, which means that one can compute the width and height of the glyph image (be it in integer or 26.6 pixels) as: width = bbox.xMax - bbox.xMin; height = bbox.yMax - bbox.yMin; Note also that for 26.6 coordinates, if 'bbox_mode' is set to FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, which corresponds to: bbox.xMin = FLOOR(bbox.xMin); bbox.yMin = FLOOR(bbox.yMin); bbox.xMax = CEILING(bbox.xMax); bbox.yMax = CEILING(bbox.yMax); To get the bbox in pixel coordinates, set 'bbox_mode' to FT_GLYPH_BBOX_TRUNCATE. To get the bbox in grid-fitted pixel coordinates, set 'bbox_mode' to FT_GLYPH_BBOX_PIXELS. ''' bbox = FT_BBox() FT_Glyph_Get_CBox(byref(self._FT_Glyph.contents), bbox_mode, byref(bbox)) return BBox(bbox) # ----------------------------------------------------------------------------- class BitmapGlyph( object ): ''' FT_BitmapGlyph wrapper. A structure used for bitmap glyph images. This really is a 'sub-class' of FT_GlyphRec. ''' def __init__( self, glyph ): ''' Create Glyph object from an FT glyph. Parameters: ----------- glyph: valid FT_Glyph object ''' self._FT_BitmapGlyph = cast(glyph, FT_BitmapGlyph) # def __del__( self ): # ''' # Destroy glyph. # ''' # FT_Done_Glyph( cast(self._FT_BitmapGlyph, FT_Glyph) ) def _get_format( self ): return self._FT_BitmapGlyph.contents.format format = property( _get_format, doc = '''The format of the glyph's image.''') def _get_bitmap( self ): return Bitmap( self._FT_BitmapGlyph.contents.bitmap ) bitmap = property( _get_bitmap, doc = '''A descriptor for the bitmap.''') def _get_left( self ): return self._FT_BitmapGlyph.contents.left left = property( _get_left, doc = '''The left-side bearing, i.e., the horizontal distance from the current pen position to the left border of the glyph bitmap.''') def _get_top( self ): return self._FT_BitmapGlyph.contents.top top = property( _get_top, doc = '''The top-side bearing, i.e., the vertical distance from the current pen position to the top border of the glyph bitmap. This distance is positive for upwards y!''') # ----------------------------------------------------------------------------- class GlyphSlot( object ): ''' FT_GlyphSlot wrapper. FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be they in outline or bitmap format. ''' def __init__( self, slot ): ''' Create GlyphSlot object from an FT glyph slot. Parameters: ----------- glyph: valid FT_GlyphSlot object ''' self._FT_GlyphSlot = slot def render( self, render_mode ): ''' Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, finding the relevant renderer, and invoking it. :param render_mode: The render mode used to render the glyph image into a bitmap. See FT_Render_Mode for a list of possible values. If FT_RENDER_MODE_NORMAL is used, a previous call of FT_Load_Glyph with flag FT_LOAD_COLOR makes FT_Render_Glyph provide a default blending of colored glyph layers associated with the current glyph slot (provided the font contains such layers) instead of rendering the glyph slot's outline. This is an experimental feature; see FT_LOAD_COLOR for more information. **Note**: To get meaningful results, font scaling values must be set with functions like FT_Set_Char_Size before calling FT_Render_Glyph. When FreeType outputs a bitmap of a glyph, it really outputs an alpha coverage map. If a pixel is completely covered by a filled-in outline, the bitmap contains 0xFF at that pixel, meaning that 0xFF/0xFF fraction of that pixel is covered, meaning the pixel is 100% black (or 0% bright). If a pixel is only 50% covered (value 0x80), the pixel is made 50% black (50% bright or a middle shade of grey). 0% covered means 0% black (100% bright or white). On high-DPI screens like on smartphones and tablets, the pixels are so small that their chance of being completely covered and therefore completely black are fairly good. On the low-DPI screens, however, the situation is different. The pixels are too large for most of the details of a glyph and shades of gray are the norm rather than the exception. This is relevant because all our screens have a second problem: they are not linear. 1 + 1 is not 2. Twice the value does not result in twice the brightness. When a pixel is only 50% covered, the coverage map says 50% black, and this translates to a pixel value of 128 when you use 8 bits per channel (0-255). However, this does not translate to 50% brightness for that pixel on our sRGB and gamma 2.2 screens. Due to their non-linearity, they dwell longer in the darks and only a pixel value of about 186 results in 50% brightness – 128 ends up too dark on both bright and dark backgrounds. The net result is that dark text looks burnt-out, pixely and blotchy on bright background, bright text too frail on dark backgrounds, and colored text on colored background (for example, red on green) seems to have dark halos or ‘dirt’ around it. The situation is especially ugly for diagonal stems like in ‘w’ glyph shapes where the quality of FreeType's anti-aliasing depends on the correct display of grays. On high-DPI screens where smaller, fully black pixels reign supreme, this doesn't matter, but on our low-DPI screens with all the gray shades, it does. 0% and 100% brightness are the same things in linear and non-linear space, just all the shades in-between aren't. The blending function for placing text over a background is dst = alpha * src + (1 - alpha) * dst which is known as the OVER operator. To correctly composite an anti-aliased pixel of a glyph onto a surface, take the foreground and background colors (e.g., in sRGB space) and apply gamma to get them in a linear space, use OVER to blend the two linear colors using the glyph pixel as the alpha value (remember, the glyph bitmap is an alpha coverage bitmap), and apply inverse gamma to the blended pixel and write it back to the image. Internal testing at Adobe found that a target inverse gamma of 1.8 for step 3 gives good results across a wide range of displays with an sRGB gamma curve or a similar one. This process can cost performance. There is an approximation that does not need to know about the background color; see https://bel.fi/alankila/lcd/ and https://bel.fi/alankila/lcd/alpcor.html for details. **ATTENTION:** Linear blending is even more important when dealing with subpixel-rendered glyphs to prevent color-fringing! A subpixel-rendered glyph must first be filtered with a filter that gives equal weight to the three color primaries and does not exceed a sum of 0x100, see section ‘Subpixel Rendering’. Then the only difference to gray linear blending is that subpixel-rendered linear blending is done 3 times per pixel: red foreground subpixel to red background subpixel and so on for green and blue. ''' error = FT_Render_Glyph( self._FT_GlyphSlot, render_mode ) if error: raise FT_Exception( error ) def get_glyph( self ): ''' A function used to extract a glyph image from a slot. Note that the created FT_Glyph object must be released with FT_Done_Glyph. ''' aglyph = FT_Glyph() error = FT_Get_Glyph( self._FT_GlyphSlot, byref(aglyph) ) if error: raise FT_Exception( error ) return Glyph( aglyph ) def _get_bitmap( self ): return Bitmap( self._FT_GlyphSlot.contents.bitmap ) bitmap = property( _get_bitmap, doc = '''This field is used as a bitmap descriptor when the slot format is FT_GLYPH_FORMAT_BITMAP. Note that the address and content of the bitmap buffer can change between calls of FT_Load_Glyph and a few other functions.''') def _get_metrics( self ): return GlyphMetrics( self._FT_GlyphSlot.contents.metrics ) metrics = property( _get_metrics, doc = '''The metrics of the last loaded glyph in the slot. The returned values depend on the last load flags (see the FT_Load_Glyph API function) and can be expressed either in 26.6 fractional pixels or font units. Note that even when the glyph image is transformed, the metrics are not.''') def _get_next( self ): return GlyphSlot( self._FT_GlyphSlot.contents.next ) next = property( _get_next, doc = '''In some cases (like some font tools), several glyph slots per face object can be a good thing. As this is rare, the glyph slots are listed through a direct, single-linked list using its 'next' field.''') advance = property( lambda self: self._FT_GlyphSlot.contents.advance, doc = '''This shorthand is, depending on FT_LOAD_IGNORE_TRANSFORM, the transformed advance width for the glyph (in 26.6 fractional pixel format). As specified with FT_LOAD_VERTICAL_LAYOUT, it uses either the 'horiAdvance' or the 'vertAdvance' value of 'metrics' field.''') def _get_outline( self ): return Outline( self._FT_GlyphSlot.contents.outline ) outline = property( _get_outline, doc = '''The outline descriptor for the current glyph image if its format is FT_GLYPH_FORMAT_OUTLINE. Once a glyph is loaded, 'outline' can be transformed, distorted, embolded, etc. However, it must not be freed.''') format = property( lambda self: self._FT_GlyphSlot.contents.format, doc = '''This field indicates the format of the image contained in the glyph slot. Typically FT_GLYPH_FORMAT_BITMAP, FT_GLYPH_FORMAT_OUTLINE, or FT_GLYPH_FORMAT_COMPOSITE, but others are possible.''') bitmap_top = property( lambda self: self._FT_GlyphSlot.contents.bitmap_top, doc = '''This is the bitmap's top bearing expressed in integer pixels. Remember that this is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive.''') bitmap_left = property( lambda self: self._FT_GlyphSlot.contents.bitmap_left, doc = '''This is the bitmap's left bearing expressed in integer pixels. Of course, this is only valid if the format is FT_GLYPH_FORMAT_BITMAP.''') linearHoriAdvance = property( lambda self: self._FT_GlyphSlot.contents.linearHoriAdvance, doc = '''The advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs.''') linearVertAdvance = property( lambda self: self._FT_GlyphSlot.contents.linearVertAdvance, doc = '''The advance height of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs.''') # ----------------------------------------------------------------------------- # Face wrapper # ----------------------------------------------------------------------------- class Face( object ): ''' FT_Face wrapper FreeType root face class structure. A face object models a typeface in a font file. ''' def __init__( self, path_or_stream, index = 0 ): ''' Build a new Face :param Union[str, typing.BinaryIO] path_or_stream: A path to the font file or an io.BytesIO stream. :param int index: The index of the face within the font. The first face has index 0. ''' library = get_handle( ) face = FT_Face( ) self._FT_Face = None #error = FT_New_Face( library, path_or_stream, 0, byref(face) ) self._filebodys = [] if hasattr(path_or_stream, "read"): error = self._init_from_memory(library, face, index, path_or_stream.read()) else: try: error = self._init_from_file(library, face, index, path_or_stream) except UnicodeError: with open(path_or_stream, mode="rb") as f: filebody = f.read() error = self._init_from_memory(library, face, index, filebody) if error: raise FT_Exception(error) self._index = index self._FT_Face = face self._name_strings = dict() def _init_from_file(self, library, face, index, path): u_filename = c_char_p(_encode_filename(path)) error = FT_New_Face(library, u_filename, index, byref(face)) return error def _init_from_memory(self, library, face, index, byte_stream): error = FT_New_Memory_Face( library, byte_stream, len(byte_stream), index, byref(face) ) self._filebodys.append(byte_stream) # prevent gc return error def _init_name_string_map(self): # build map of (nID, pID, eID, lID) keys to name string bytes self._name_strings = dict() for nidx in range(self._get_sfnt_name_count()): namerec = self.get_sfnt_name(nidx) nk = (namerec.name_id, namerec.platform_id, namerec.encoding_id, namerec.language_id) self._name_strings[nk] = namerec.string @classmethod def from_bytes(cls, bytes_, index=0): return cls(io.BytesIO(bytes_), index) def __del__( self ): ''' Discard face object, as well as all of its child slots and sizes. ''' # We check FT_Done_Face because by the time we're called it # may already be gone (see #44 and discussion in #169) if FT_Done_Face is not None and self._FT_Face is not None: FT_Done_Face( self._FT_Face ) def attach_file( self, filename ): ''' Attach data to a face object. Normally, this is used to read additional information for the face object. For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other metrics. :param filename: Filename to attach **Note** The meaning of the 'attach' (i.e., what really happens when the new file is read) is not fixed by FreeType itself. It really depends on the font format (and thus the font driver). Client applications are expected to know what they are doing when invoking this function. Most drivers simply do not implement file attachments. ''' try: u_filename = c_char_p(_encode_filename(filename)) error = FT_Attach_File( self._FT_Face, u_filename ) except UnicodeError: with open(filename, mode='rb') as f: filebody = f.read() parameters = FT_Open_Args() parameters.flags = FT_OPEN_MEMORY parameters.memory_base = filebody parameters.memory_size = len(filebody) parameters.stream = None error = FT_Attach_Stream( self._FT_Face, parameters ) self._filebodys.append(filebody) # prevent gc if error: raise FT_Exception( error) def set_char_size( self, width=0, height=0, hres=72, vres=72 ): ''' This function calls FT_Request_Size to request the nominal size (in points). :param float width: The nominal width, in 26.6 fractional points. :param float height: The nominal height, in 26.6 fractional points. :param float hres: The horizontal resolution in dpi. :param float vres: The vertical resolution in dpi. **Note** If either the character width or height is zero, it is set equal to the other value. If either the horizontal or vertical resolution is zero, it is set equal to the other value. A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are set to 72dpi. Don't use this function if you are using the FreeType cache API. ''' error = FT_Set_Char_Size( self._FT_Face, width, height, hres, vres ) if error: raise FT_Exception( error) def set_pixel_sizes( self, width, height ): ''' This function calls FT_Request_Size to request the nominal size (in pixels). :param width: The nominal width, in pixels. :param height: The nominal height, in pixels. ''' error = FT_Set_Pixel_Sizes( self._FT_Face, width, height ) if error: raise FT_Exception(error) def select_charmap( self, encoding ): ''' Select a given charmap by its encoding tag (as listed in 'freetype.h'). **Note**: This function returns an error if no charmap in the face corresponds to the encoding queried here. Because many fonts contain more than a single cmap for Unicode encoding, this function has some special code to select the one which covers Unicode best ('best' in the sense that a UCS-4 cmap is preferred to a UCS-2 cmap). It is thus preferable to FT_Set_Charmap in this case. ''' error = FT_Select_Charmap( self._FT_Face, encoding ) if error: raise FT_Exception(error) def set_charmap( self, charmap ): ''' Select a given charmap for character code to glyph index mapping. :param charmap: A handle to the selected charmap, or an index to face->charmaps[] ''' if ( type(charmap) == Charmap ): error = FT_Set_Charmap( self._FT_Face, charmap._FT_Charmap ) # Type 14 is allowed to fail, to match ft2demo's behavior. if ( charmap.cmap_format == 14 ): error = 0 else: # Treat "charmap" as plain number error = FT_Set_Charmap( self._FT_Face, self._FT_Face.contents.charmaps[charmap] ) if error : raise FT_Exception(error) def get_char_index( self, charcode ): ''' Return the glyph index of a given character code. This function uses a charmap object to do the mapping. :param charcode: The character code. **Note**: If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index returned by this function doesn't always correspond to the internal indices used within the file. This is done to ensure that value 0 always corresponds to the 'missing glyph'. ''' if isinstance(charcode, (str,unicode)): charcode = ord(charcode) return FT_Get_Char_Index( self._FT_Face, charcode ) def get_glyph_name(self, agindex, buffer_max=64): ''' This function is used to return the glyph name for the given charcode. :param agindex: The glyph index. :param buffer_max: The maximum number of bytes to use to store the glyph name. :param glyph_name: The glyph name, possibly truncated. ''' buff = create_string_buffer(buffer_max) error = FT_Get_Glyph_Name(self._FT_Face, FT_UInt(agindex), byref(buff), FT_UInt(buffer_max)) if error: raise FT_Exception(error) return buff.value def get_chars( self ): ''' This generator function is used to return all unicode character codes in the current charmap of a given face. For each character it also returns the corresponding glyph index. :return: character code, glyph index **Note**: Note that 'agindex' is set to 0 if the charmap is empty. The character code itself can be 0 in two cases: if the charmap is empty or if the value 0 is the first valid character code. ''' charcode, agindex = self.get_first_char() yield charcode, agindex while agindex != 0: charcode, agindex = self.get_next_char(charcode, 0) yield charcode, agindex def get_first_char( self ): ''' This function is used to return the first character code in the current charmap of a given face. It also returns the corresponding glyph index. :return: Glyph index of first character code. 0 if charmap is empty. **Note**: You should use this function with get_next_char to be able to parse all character codes available in a given charmap. The code should look like this: Note that 'agindex' is set to 0 if the charmap is empty. The result itself can be 0 in two cases: if the charmap is empty or if the value 0 is the first valid character code. ''' agindex = FT_UInt() charcode = FT_Get_First_Char( self._FT_Face, byref(agindex) ) return charcode, agindex.value def get_next_char( self, charcode, agindex ): ''' This function is used to return the next character code in the current charmap of a given face following the value 'charcode', as well as the corresponding glyph index. :param charcode: The starting character code. :param agindex: Glyph index of next character code. 0 if charmap is empty. **Note**: You should use this function with FT_Get_First_Char to walk over all character codes available in a given charmap. See the note for this function for a simple code example. Note that 'agindex' is set to 0 when there are no more codes in the charmap. ''' agindex = FT_UInt( 0 ) #agindex ) charcode = FT_Get_Next_Char( self._FT_Face, charcode, byref(agindex) ) return charcode, agindex.value def get_name_index( self, name ): ''' Return the glyph index of a given glyph name. This function uses driver specific objects to do the translation. :param name: The glyph name. ''' if not isinstance(name, bytes): raise FT_Exception(0x06, "FT_Get_Name_Index() expects a binary " "string for the name parameter.") return FT_Get_Name_Index( self._FT_Face, name ) def set_transform( self, matrix, delta ): ''' A function used to set the transformation that is applied to glyph images when they are loaded into a glyph slot through FT_Load_Glyph. :param matrix: A pointer to the transformation's 2x2 matrix. Use 0 for the identity matrix. :parm delta: A pointer to the translation vector. Use 0 for the null vector. **Note**: The transformation is only applied to scalable image formats after the glyph has been loaded. It means that hinting is unaltered by the transformation and is performed on the character size given in the last call to FT_Set_Char_Size or FT_Set_Pixel_Sizes. Note that this also transforms the 'face.glyph.advance' field, but not the values in 'face.glyph.metrics'. ''' FT_Set_Transform( self._FT_Face, byref(matrix), byref(delta) ) def select_size( self, strike_index ): ''' Select a bitmap strike. :param strike_index: The index of the bitmap strike in the 'available_sizes' field of Face object. ''' error = FT_Select_Size( self._FT_Face, strike_index ) if error: raise FT_Exception( error ) def load_glyph( self, index, flags = FT_LOAD_RENDER ): ''' A function used to load a single glyph into the glyph slot of a face object. :param index: The index of the glyph in the font file. For CID-keyed fonts (either in PS or in CFF format) this argument specifies the CID value. :param flags: A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc). **Note**: The loaded glyph may be transformed. See FT_Set_Transform for the details. For subsetted CID-keyed fonts, 'FT_Err_Invalid_Argument' is returned for invalid CID values (this is, for CID values which don't have a corresponding glyph in the font). See the discussion of the FT_FACE_FLAG_CID_KEYED flag for more details. ''' error = FT_Load_Glyph( self._FT_Face, index, flags ) if error: raise FT_Exception( error ) def load_char( self, char, flags = FT_LOAD_RENDER ): ''' A function used to load a single glyph into the glyph slot of a face object, according to its character code. :param char: The glyph's character code, according to the current charmap used in the face. :param flags: A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc). **Note**: This function simply calls FT_Get_Char_Index and FT_Load_Glyph. ''' # python 2 with ascii input if ( isinstance(char, str) and ( len(char) == 1 ) ): char = ord(char) # python 2 with utf8 string input if ( isinstance(char, str) and ( len(char) != 1 ) ): char = ord(char.decode('utf8')) # python 3 or python 2 with __future__.unicode_literals if ( isinstance(char, unicode) and ( len(char) == 1 ) ): char = ord(char) # allow bare integer to pass through error = FT_Load_Char( self._FT_Face, char, flags ) if error: raise FT_Exception( error ) def get_advance( self, gindex, flags ): ''' Retrieve the advance value of a given glyph outline in an FT_Face. By default, the unhinted advance is returned in font units. :param gindex: The glyph index. :param flags: A set of bit flags similar to those used when calling FT_Load_Glyph, used to determine what kind of advances you need. :return: The advance value, in either font units or 16.16 format. If FT_LOAD_VERTICAL_LAYOUT is set, this is the vertical advance corresponding to a vertical layout. Otherwise, it is the horizontal advance in a horizontal layout. ''' padvance = FT_Fixed(0) error = FT_Get_Advance( self._FT_Face, gindex, flags, byref(padvance) ) if error: raise FT_Exception( error ) return padvance.value def get_kerning( self, left, right, mode = FT_KERNING_DEFAULT ): ''' Return the kerning vector between two glyphs of a same face. :param left: The index of the left glyph in the kern pair. :param right: The index of the right glyph in the kern pair. :param mode: See FT_Kerning_Mode for more information. Determines the scale and dimension of the returned kerning vector. **Note**: Only horizontal layouts (left-to-right & right-to-left) are supported by this method. Other layouts, or more sophisticated kernings, are out of the scope of this API function -- they can be implemented through format-specific interfaces. ''' left_glyph = self.get_char_index( left ) right_glyph = self.get_char_index( right ) kerning = FT_Vector(0,0) error = FT_Get_Kerning( self._FT_Face, left_glyph, right_glyph, mode, byref(kerning) ) if error: raise FT_Exception( error ) return kerning def get_format(self): ''' Return a string describing the format of a given face, using values which can be used as an X11 FONT_PROPERTY. Possible values are 'TrueType', 'Type 1', 'BDF', ‘PCF', ‘Type 42', ‘CID Type 1', ‘CFF', 'PFR', and ‘Windows FNT'. ''' return FT_Get_X11_Font_Format( self._FT_Face ) def get_fstype(self): ''' Return the fsType flags for a font (embedding permissions). The return value is a tuple containing the freetype enum name as a string and the actual flag as an int ''' flag = FT_Get_FSType_Flags( self._FT_Face ) for k, v in FT_FSTYPES.items(): if v == flag: return k, v def _get_sfnt_name_count(self): return FT_Get_Sfnt_Name_Count( self._FT_Face ) sfnt_name_count = property(_get_sfnt_name_count, doc = '''Number of name strings in the SFNT 'name' table.''') def get_sfnt_name( self, index ): ''' Retrieve a string of the SFNT 'name' table for a given index :param index: The index of the 'name' string. **Note**: The 'string' array returned in the 'aname' structure is not null-terminated. The application should deallocate it if it is no longer in use. Use FT_Get_Sfnt_Name_Count to get the total number of available 'name' table entries, then do a loop until you get the right platform, encoding, and name ID. ''' name = FT_SfntName( ) error = FT_Get_Sfnt_Name( self._FT_Face, index, byref(name) ) if error: raise FT_Exception( error ) return SfntName( name ) def get_best_name_string(self, nameID, default_string='', preferred_order=None): ''' Retrieve a name string given nameID. Searches available font names matching nameID and returns the decoded bytes of the best match. "Best" is defined as a preferred list of platform/encoding/languageIDs which can be overridden by supplying a preferred_order matching the scheme of 'sort_order' (see below). The routine will attempt to decode the string's bytes to a Python str, when the platform/encoding[/langID] are known (Windows, Mac, or Unicode platforms). If you prefer more control over name string selection and decoding than this routine provides: - call self._init_name_string_map() - use (nameID, platformID, encodingID, languageID) as a key into the self._name_strings dict ''' if not(self._name_strings): self._init_name_string_map() sort_order = preferred_order or ( (3, 1, 1033), # Microsoft/Windows/US English (1, 0, 0), # Mac/Roman/English (0, 6, 0), # Unicode/SMP/* (0, 4, 0), # Unicode/SMP/* (0, 3, 0), # Unicode/BMP/* (0, 2, 0), # Unicode/10646-BMP/* (0, 1, 0), # Unicode/1.1/* ) # get all keys matching nameID keys_present = [k for k in self._name_strings.keys() if k[0] == nameID] if keys_present: # sort found keys by sort_order key_order = {k: v for v, k in enumerate(sort_order)} keys_present.sort(key=lambda x: key_order.get(x[1:4])) best_key = keys_present[0] nsbytes = self._name_strings[best_key] if best_key[1:3] == (3, 1) or best_key[1] == 0: enc = "utf-16-be" elif best_key[1:4] == (1, 0, 0): enc = "mac-roman" else: enc = "unicode_escape" ns = nsbytes.decode(enc) else: ns = default_string return ns def get_variation_info(self): ''' Retrieves variation space information for the current face. ''' if version() < (2, 8, 1): raise NotImplementedError("freetype-py VF support requires FreeType 2.8.1 or later") p_amaster = pointer(FT_MM_Var()) error = FT_Get_MM_Var(self._FT_Face, byref(p_amaster)) if error: raise FT_Exception(error) vsi = VariationSpaceInfo(self, p_amaster) FT_Done_MM_Var_func(p_amaster) return vsi def get_var_blend_coords(self): ''' Get the current blend coordinates (-1.0..+1.0) ''' vsi = self.get_variation_info() num_coords = len(vsi.axes) ft_coords = (FT_Fixed * num_coords)() error = FT_Get_Var_Blend_Coordinates(self._FT_Face, num_coords, byref(ft_coords)) if error: raise FT_Exception(error) coords = tuple([ft_coords[ai]/65536.0 for ai in range(num_coords)]) return coords def set_var_blend_coords(self, coords, reset=False): ''' Set blend coords. Using reset=True will set all axes to their default coordinates. ''' if reset: error = FT_Set_Var_Blend_Coordinates(self._FT_Face, 0, 0) else: num_coords = len(coords) ft_coords = [int(round(c * 65536.0)) for c in coords] coords_array = (FT_Fixed * num_coords)(*ft_coords) error = FT_Set_Var_Blend_Coordinates(self._FT_Face, num_coords, byref(coords_array)) if error: raise FT_Exception(error) def get_var_design_coords(self): ''' Get the current design coordinates ''' vsi = self.get_variation_info() num_coords = len(vsi.axes) ft_coords = (FT_Fixed * num_coords)() error = FT_Get_Var_Design_Coordinates(self._FT_Face, num_coords, byref(ft_coords)) if error: raise FT_Exception(error) coords = tuple([ft_coords[ai]/65536.0 for ai in range(num_coords)]) return coords def set_var_design_coords(self, coords, reset=False): ''' Set design coords. Using reset=True will set all axes to their default coordinates. ''' if reset: error = FT_Set_Var_Design_Coordinates(self._FT_Face, 0, 0) else: num_coords = len(coords) ft_coords = [int(round(c * 65536.0)) for c in coords] coords_array = (FT_Fixed * num_coords)(*ft_coords) error = FT_Set_Var_Design_Coordinates(self._FT_Face, num_coords, byref(coords_array)) if error: raise FT_Exception(error) def set_var_named_instance(self, instance_name): ''' Set instance by name. This will work with any FreeType with variable support (for our purposes: v2.8.1 or later). If the actual FT_Set_Named_Instance() function is available (v2.9.1 or later), we use it (which, despite what you might expect from its name, sets instances by *index*). Otherwise we just use the coords of the named instance (if found) and call self.set_var_design_coords. ''' have_func = freetype.version() >= (2, 9, 1) vsi = self.get_variation_info() for inst_idx, inst in enumerate(vsi.instances, start=1): if inst.name == instance_name: if have_func: error = FT_Set_Named_Instance(self._FT_Face, inst_idx) else: error = self.set_var_design_coords(inst.coords) if error: raise FT_Exception(error) break # named instance not found; do nothing def _get_postscript_name( self ): return FT_Get_Postscript_Name( self._FT_Face ) postscript_name = property( _get_postscript_name, doc = '''ASCII PostScript name of face, if available. This only works with PostScript and TrueType fonts.''') def _has_horizontal( self ): return bool( self.face_flags & FT_FACE_FLAG_HORIZONTAL ) has_horizontal = property( _has_horizontal, doc = '''True whenever a face object contains horizontal metrics (this is true for all font formats though).''') def _has_vertical( self ): return bool( self.face_flags & FT_FACE_FLAG_VERTICAL ) has_vertical = property( _has_vertical, doc = '''True whenever a face object contains vertical metrics.''') def _has_kerning( self ): return bool( self.face_flags & FT_FACE_FLAG_KERNING ) has_kerning = property( _has_kerning, doc = '''True whenever a face object contains kerning data that can be accessed with FT_Get_Kerning.''') def _is_scalable( self ): return bool( self.face_flags & FT_FACE_FLAG_SCALABLE ) is_scalable = property( _is_scalable, doc = '''true whenever a face object contains a scalable font face (true for TrueType, Type 1, Type 42, CID, OpenType/CFF, and PFR font formats.''') def _is_sfnt( self ): return bool( self.face_flags & FT_FACE_FLAG_SFNT ) is_sfnt = property( _is_sfnt, doc = '''true whenever a face object contains a font whose format is based on the SFNT storage scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts. If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available.''') def _is_fixed_width( self ): return bool( self.face_flags & FT_FACE_FLAG_FIXED_WIDTH ) is_fixed_width = property( _is_fixed_width, doc = '''True whenever a face object contains a font face that contains fixed-width (or 'monospace', 'fixed-pitch', etc.) glyphs.''') def _has_fixed_sizes( self ): return bool( self.face_flags & FT_FACE_FLAG_FIXED_SIZES ) has_fixed_sizes = property( _has_fixed_sizes, doc = '''True whenever a face object contains some embedded bitmaps. See the 'available_sizes' field of the FT_FaceRec structure.''') def _has_glyph_names( self ): return bool( self.face_flags & FT_FACE_FLAG_GLYPH_NAMES ) has_glyph_names = property( _has_glyph_names, doc = '''True whenever a face object contains some glyph names that can be accessed through FT_Get_Glyph_Name.''') def _has_multiple_masters( self ): return bool( self.face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) has_multiple_masters = property( _has_multiple_masters, doc = '''True whenever a face object contains some multiple masters. The functions provided by FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want.''') def _is_cid_keyed( self ): return bool( self.face_flags & FT_FACE_FLAG_CID_KEYED ) is_cid_keyed = property( _is_cid_keyed, doc = '''True whenever a face object contains a CID-keyed font. See the discussion of FT_FACE_FLAG_CID_KEYED for more details. If this macro is true, all functions defined in FT_CID_H are available.''') def _is_tricky( self ): return bool( self.face_flags & FT_FACE_FLAG_TRICKY ) is_tricky = property( _is_tricky, doc = '''True whenever a face represents a 'tricky' font. See the discussion of FT_FACE_FLAG_TRICKY for more details.''') num_faces = property(lambda self: self._FT_Face.contents.num_faces, doc = '''The number of faces in the font file. Some font formats can have multiple faces in a font file.''') face_index = property(lambda self: self._FT_Face.contents.face_index, doc = '''The index of the face in the font file. It is set to 0 if there is only one face in the font file.''') face_flags = property(lambda self: self._FT_Face.contents.face_flags, doc = '''A set of bit flags that give important information about the face; see FT_FACE_FLAG_XXX for the details.''') style_flags = property(lambda self: self._FT_Face.contents.style_flags, doc = '''A set of bit flags indicating the style of the face; see FT_STYLE_FLAG_XXX for the details.''') num_glyphs = property(lambda self: self._FT_Face.contents.num_glyphs, doc = '''The number of glyphs in the face. If the face is scalable and has sbits (see 'num_fixed_sizes'), it is set to the number of outline glyphs. For CID-keyed fonts, this value gives the highest CID used in the font.''') family_name = property(lambda self: self._FT_Face.contents.family_name, doc = '''The face's family name. This is an ASCII string, usually in English, which describes the typeface's family (like 'Times New Roman', 'Bodoni', 'Garamond', etc). This is a least common denominator used to list fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. Applications should use the format specific interface to access them. Can be NULL (e.g., in fonts embedded in a PDF file).''') style_name = property(lambda self: self._FT_Face.contents.style_name, doc = '''The face's style name. This is an ASCII string, usually in English, which describes the typeface's style (like 'Italic', 'Bold', 'Condensed', etc). Not all font formats provide a style name, so this field is optional, and can be set to NULL. As for 'family_name', some formats provide localized and Unicode versions of this string. Applications should use the format specific interface to access them.''') num_fixed_sizes = property(lambda self: self._FT_Face.contents.num_fixed_sizes, doc = '''The number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap strikes, which are called 'sbits' in that case.''') def _get_available_sizes( self ): sizes = [] n = self.num_fixed_sizes FT_sizes = self._FT_Face.contents.available_sizes for i in range(n): sizes.append( BitmapSize(FT_sizes[i]) ) return sizes available_sizes = property(_get_available_sizes, doc = '''A list of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap strike.''') num_charmaps = property(lambda self: self._FT_Face.contents.num_charmaps) def _get_charmaps( self ): charmaps = [] n = self._FT_Face.contents.num_charmaps FT_charmaps = self._FT_Face.contents.charmaps for i in range(n): charmaps.append( Charmap(FT_charmaps[i]) ) return charmaps charmaps = property(_get_charmaps, doc = '''A list of the charmaps of the face.''') # ('generic', FT_Generic), def _get_bbox( self ): return BBox( self._FT_Face.contents.bbox ) bbox = property( _get_bbox, doc = '''The font bounding box. Coordinates are expressed in font units (see 'units_per_EM'). The box is large enough to contain any glyph from the font. Thus, 'bbox.yMax' can be seen as the 'maximal ascender', and 'bbox.yMin' as the 'minimal descender'. Only relevant for scalable formats. Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for further discussion.''') units_per_EM = property(lambda self: self._FT_Face.contents.units_per_EM, doc = '''The number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and 1000 for Type 1 fonts. Only relevant for scalable formats.''') ascender = property(lambda self: self._FT_Face.contents.ascender, doc = '''The typographic ascender of the face, expressed in font units. For font formats not having this information, it is set to 'bbox.yMax'. Only relevant for scalable formats.''') descender = property(lambda self: self._FT_Face.contents.descender, doc = '''The typographic descender of the face, expressed in font units. For font formats not having this information, it is set to 'bbox.yMin'. Note that this field is usually negative. Only relevant for scalable formats.''') height = property(lambda self: self._FT_Face.contents.height, doc = '''The height is the vertical distance between two consecutive baselines, expressed in font units. It is always positive. Only relevant for scalable formats.''') max_advance_width = property(lambda self: self._FT_Face.contents.max_advance_width, doc = '''The maximal advance width, in font units, for all glyphs in this face. This can be used to make word wrapping computations faster. Only relevant for scalable formats.''') max_advance_height = property(lambda self: self._FT_Face.contents.max_advance_height, doc = '''The maximal advance height, in font units, for all glyphs in this face. This is only relevant for vertical layouts, and is set to 'height' for fonts that do not provide vertical metrics. Only relevant for scalable formats.''') underline_position = property(lambda self: self._FT_Face.contents.underline_position, doc = '''The position, in font units, of the underline line for this face. It is the center of the underlining stem. Only relevant for scalable formats.''') underline_thickness = property(lambda self: self._FT_Face.contents.underline_thickness, doc = '''The thickness, in font units, of the underline for this face. Only relevant for scalable formats.''') def _get_glyph( self ): return GlyphSlot( self._FT_Face.contents.glyph ) glyph = property( _get_glyph, doc = '''The face's associated glyph slot(s).''') def _get_size( self ): size = self._FT_Face.contents.size metrics = size.contents.metrics return SizeMetrics(metrics) size = property( _get_size, doc = '''The current active size for this face.''') def _get_charmap( self ): return Charmap( self._FT_Face.contents.charmap) charmap = property( _get_charmap, doc = '''The current active charmap for this face.''') # ----------------------------------------------------------------------------- # SfntName wrapper # ----------------------------------------------------------------------------- class SfntName( object ): ''' SfntName wrapper A structure used to model an SFNT 'name' table entry. ''' def __init__(self, name): ''' Create a new SfntName object. :param name : SFNT 'name' table entry. ''' self._FT_SfntName = name platform_id = property(lambda self: self._FT_SfntName.platform_id, doc = '''The platform ID for 'string'.''') encoding_id = property(lambda self: self._FT_SfntName.encoding_id, doc = '''The encoding ID for 'string'.''') language_id = property(lambda self: self._FT_SfntName.language_id, doc = '''The language ID for 'string'.''') name_id = property(lambda self: self._FT_SfntName.name_id, doc = '''An identifier for 'string'.''') #string = property(lambda self: self._FT_SfntName.string) string_len = property(lambda self: self._FT_SfntName.string_len, doc = '''The length of 'string' in bytes.''') def _get_string(self): # #s = self._FT_SfntName s = string_at(self._FT_SfntName.string, self._FT_SfntName.string_len) return s # #return s.decode('utf-16be', 'ignore') # return s.decode('utf-8', 'ignore') # #n = s.string_len # #data = [s.string[i] for i in range(n)] # #return data string = property(_get_string, doc = '''The 'name' string. Note that its format differs depending on the (platform,encoding) pair. It can be a Pascal String, a UTF-16 one, etc. Generally speaking, the string is not zero-terminated. Please refer to the TrueType specification for details.''') # ----------------------------------------------------------------------------- class Stroker( object ): ''' FT_Stroker wrapper This component generates stroked outlines of a given vectorial glyph. It also allows you to retrieve the 'outside' and/or the 'inside' borders of the stroke. This can be useful to generate 'bordered' glyph, i.e., glyphs displayed with a coloured (and anti-aliased) border around their shape. ''' def __init__( self ): ''' Create a new Stroker object. ''' library = get_handle( ) stroker = FT_Stroker( ) error = FT_Stroker_New( library, byref(stroker) ) if error: raise FT_Exception( error ) self._FT_Stroker = stroker def __del__( self ): ''' Destroy object. ''' FT_Stroker_Done( self._FT_Stroker ) def set( self, radius, line_cap, line_join, miter_limit ): ''' Reset a stroker object's attributes. :param radius: The border radius. :param line_cap: The line cap style. :param line_join: The line join style. :param miter_limit: The miter limit for the FT_STROKER_LINEJOIN_MITER style, expressed as 16.16 fixed point value. **Note**: The radius is expressed in the same units as the outline coordinates. ''' FT_Stroker_Set( self._FT_Stroker, radius, line_cap, line_join, miter_limit ) def rewind( self ): ''' Reset a stroker object without changing its attributes. You should call this function before beginning a new series of calls to FT_Stroker_BeginSubPath or FT_Stroker_EndSubPath. ''' FT_Stroker_Rewind( self._FT_Stroker ) def parse_outline( self, outline, opened ): ''' A convenience function used to parse a whole outline with the stroker. The resulting outline(s) can be retrieved later by functions like FT_Stroker_GetCounts and FT_Stroker_Export. :param outline: The source outline. :pram opened: A boolean. If 1, the outline is treated as an open path instead of a closed one. **Note**: If 'opened' is 0 (the default), the outline is treated as a closed path, and the stroker generates two distinct 'border' outlines. If 'opened' is 1, the outline is processed as an open path, and the stroker generates a single 'stroke' outline. This function calls 'rewind' automatically. ''' error = FT_Stroker_ParseOutline( self._FT_Stroker, byref(outline._FT_Outline), opened) if error: raise FT_Exception( error ) def begin_subpath( self, to, _open ): ''' Start a new sub-path in the stroker. :param to A pointer to the start vector. :param _open: A boolean. If 1, the sub-path is treated as an open one. **Note**: This function is useful when you need to stroke a path that is not stored as an 'Outline' object. ''' error = FT_Stroker_BeginSubPath( self._FT_Stroker, to, _open ) if error: raise FT_Exception( error ) def end_subpath( self ): ''' Close the current sub-path in the stroker. **Note**: You should call this function after 'begin_subpath'. If the subpath was not 'opened', this function 'draws' a single line segment to the start position when needed. ''' error = FT_Stroker_EndSubPath( self._FT_Stroker) if error: raise FT_Exception( error ) def line_to( self, to ): ''' 'Draw' a single line segment in the stroker's current sub-path, from the last position. :param to: A pointer to the destination point. **Note**: You should call this function between 'begin_subpath' and 'end_subpath'. ''' error = FT_Stroker_LineTo( self._FT_Stroker, to ) if error: raise FT_Exception( error ) def conic_to( self, control, to ): ''' 'Draw' a single quadratic Bezier in the stroker's current sub-path, from the last position. :param control: A pointer to a Bezier control point. :param to: A pointer to the destination point. **Note**: You should call this function between 'begin_subpath' and 'end_subpath'. ''' error = FT_Stroker_ConicTo( self._FT_Stroker, control, to ) if error: raise FT_Exception( error ) def cubic_to( self, control1, control2, to ): ''' 'Draw' a single quadratic Bezier in the stroker's current sub-path, from the last position. :param control1: A pointer to the first Bezier control point. :param control2: A pointer to second Bezier control point. :param to: A pointer to the destination point. **Note**: You should call this function between 'begin_subpath' and 'end_subpath'. ''' error = FT_Stroker_CubicTo( self._FT_Stroker, control1, control2, to ) if error: raise FT_Exception( error ) def get_border_counts( self, border ): ''' Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export one of the 'border' or 'stroke' outlines generated by the stroker. :param border: The border index. :return: number of points, number of contours ''' anum_points = FT_UInt() anum_contours = FT_UInt() error = FT_Stroker_GetBorderCounts( self._FT_Stroker, border, byref(anum_points), byref(anum_contours) ) if error: raise FT_Exception( error ) return anum_points.value, anum_contours.value def export_border( self , border, outline ): ''' Call this function after 'get_border_counts' to export the corresponding border to your own 'Outline' structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays. :param border: The border index. :param outline: The target outline. **Note**: Always call this function after get_border_counts to get sure that there is enough room in your 'Outline' object to receive all new data. When an outline, or a sub-path, is 'closed', the stroker generates two independent 'border' outlines, named 'left' and 'right' When the outline, or a sub-path, is 'opened', the stroker merges the 'border' outlines with caps. The 'left' border receives all points, while the 'right' border becomes empty. Use the function export instead if you want to retrieve all borders at once. ''' FT_Stroker_ExportBorder( self._FT_Stroker, border, byref(outline._FT_Outline) ) def get_counts( self ): ''' Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export all points/borders from the stroked outline/path. :return: number of points, number of contours ''' anum_points = FT_UInt() anum_contours = FT_UInt() error = FT_Stroker_GetCounts( self._FT_Stroker, byref(anum_points), byref(anum_contours) ) if error: raise FT_Exception( error ) return anum_points.value, anum_contours.value def export( self, outline ): ''' Call this function after get_border_counts to export all borders to your own 'Outline' structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays. :param outline: The target outline. ''' FT_Stroker_Export( self._FT_Stroker, byref(outline._FT_Outline) ) # ----------------------------------------------------------------------------- # Classes related to Variable Font support # class VariationAxis(object): tag = None coords = tuple() def __init__(self, ftvaraxis): self.tag = unmake_tag(ftvaraxis.tag) self.name = ftvaraxis.name.decode('ascii') self.minimum = ftvaraxis.minimum/65536.0 self.default = ftvaraxis.default/65536.0 self.maximum = ftvaraxis.maximum/65536.0 self.strid = ftvaraxis.strid # do we need this? Should be same as 'name'... def __repr__(self): return "".format( self.tag, self.name, self.minimum, self.default, self.maximum) class VariationInstance(object): def __init__(self, name, psname, coords): self.name = name self.psname = psname self.coords = coords def __repr__(self): return "".format( self.name, self.coords) class VariationSpaceInfo(object): """ VF info (axes & instances). """ def __init__(self, face, p_ftmmvar): """ Build a VariationSpaceInfo object given face (freetype.Face) and p_ftmmvar (pointer to FT_MM_Var). """ ftmv = p_ftmmvar.contents axes = [] for axidx in range(ftmv.num_axis): axes.append(VariationAxis(ftmv.axis[axidx])) self.axes = tuple(axes) inst = [] for instidx in range(ftmv.num_namedstyles): instinfo = ftmv.namedstyle[instidx] nid = instinfo.strid name = face.get_best_name_string(nid) psid = instinfo.psid psname = face.get_best_name_string(psid) coords = [] for cidx in range(len(self.axes)): coords.append(instinfo.coords[cidx]/65536.0) inst.append(VariationInstance(name, psname, tuple(coords))) self.instances = tuple(inst) freetype-py-2.5.1/freetype/ft_structs.py0000664000175000017500000011740614664131406020603 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Freetype structured types ------------------------- FT_Library: A handle to a FreeType library instance. FT_Vector: A simple structure used to store a 2D vector. FT_BBox: A structure used to hold an outline's bounding box. FT_Matrix: A simple structure used to store a 2x2 matrix. FT_UnitVector: A simple structure used to store a 2D vector unit vector. FT_Bitmap: A structure used to describe a bitmap or pixmap to the raster. FT_Data: Read-only binary data represented as a pointer and a length. FT_Generic: Client applications generic data. FT_Bitmap_Size: Metrics of a bitmap strike. FT_Charmap: The base charmap structure. FT_Glyph_Metrics:A structure used to model the metrics of a single glyph. FT_Outline: This structure is used to describe an outline to the scan-line converter. FT_GlyphSlot: FreeType root glyph slot class structure. FT_Glyph: The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed float format. FT_Size_Metrics: The size metrics structure gives the metrics of a size object. FT_Size: FreeType root size class structure. FT_Face: FreeType root face class structure. FT_Parameter: A simple structure used to pass more or less generic parameters to FT_Open_Face. FT_Open_Args: A structure used to indicate how to open a new font file or stream. FT_SfntName: A structure used to model an SFNT 'name' table entry. FT_Stroker: Opaque handler to a path stroker object. FT_BitmapGlyph: A structure used for bitmap glyph images. ''' from freetype.ft_types import * # ----------------------------------------------------------------------------- # A handle to a FreeType library instance. Each 'library' is completely # independent from the others; it is the 'root' of a set of objects like fonts, # faces, sizes, etc. class FT_LibraryRec(Structure): ''' A handle to a FreeType library instance. Each 'library' is completely independent from the others; it is the 'root' of a set of objects like fonts, faces, sizes, etc. ''' _fields_ = [ ] FT_Library = POINTER(FT_LibraryRec) # ----------------------------------------------------------------------------- # A simple structure used to store a 2D vector; coordinates are of the FT_Pos # type. class FT_Vector(Structure): ''' A simple structure used to store a 2D vector; coordinates are of the FT_Pos type. x: The horizontal coordinate. y: The vertical coordinate. ''' _fields_ = [('x', FT_Pos), ('y', FT_Pos)] # ----------------------------------------------------------------------------- # A structure used to hold an outline's bounding box, i.e., the coordinates of # its extrema in the horizontal and vertical directions. # # The bounding box is specified with the coordinates of the lower left and the # upper right corner. In PostScript, those values are often called (llx,lly) # and (urx,ury), respectively. # # If 'yMin' is negative, this value gives the glyph's descender. Otherwise, the # glyph doesn't descend below the baseline. Similarly, if 'ymax' is positive, # this value gives the glyph's ascender. # # 'xMin' gives the horizontal distance from the glyph's origin to the left edge # of the glyph's bounding box. If 'xMin' is negative, the glyph extends to the # left of the origin. class FT_BBox(Structure): ''' A structure used to hold an outline's bounding box, i.e., the coordinates of its extrema in the horizontal and vertical directions. The bounding box is specified with the coordinates of the lower left and the upper right corner. In PostScript, those values are often called (llx,lly) and (urx,ury), respectively. If 'yMin' is negative, this value gives the glyph's descender. Otherwise, the glyph doesn't descend below the baseline. Similarly, if 'ymax' is positive, this value gives the glyph's ascender. 'xMin' gives the horizontal distance from the glyph's origin to the left edge of the glyph's bounding box. If 'xMin' is negative, the glyph extends to the left of the origin. xMin: The horizontal minimum (left-most). yMin: The vertical minimum (bottom-most). xMax: The horizontal maximum (right-most). yMax: The vertical maximum (top-most). ''' _fields_ = [('xMin', FT_Pos), ('yMin', FT_Pos), ('xMax', FT_Pos), ('yMax', FT_Pos)] # ----------------------------------------------------------------------------- # A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 # fixed float format. The computation performed is: # x' = x*xx + y*xy # y' = x*yx + y*yy class FT_Matrix(Structure): ''' A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 fixed float format. The computation performed is: x' = x*xx + y*xy y' = x*yx + y*yy xx: Matrix coefficient. xy: Matrix coefficient. yx: Matrix coefficient. yy: Matrix coefficient. ''' _fields_ = [('xx', FT_Fixed), ('xy', FT_Fixed), ('yx', FT_Fixed), ('yy', FT_Fixed)] # ----------------------------------------------------------------------------- # A simple structure used to store a 2D vector unit vector. Uses FT_F2Dot14 # types. class FT_UnitVector(Structure): ''' A simple structure used to store a 2D vector unit vector. Uses FT_F2Dot14 types. x: The horizontal coordinate. y: The vertical coordinate. ''' _fields_ = [('x', FT_F2Dot14), ('y', FT_F2Dot14)] # ----------------------------------------------------------------------------- # A structure used to describe a bitmap or pixmap to the raster. Note that we # now manage pixmaps of various depths through the 'pixel_mode' field. class FT_Bitmap(Structure): ''' A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various depths through the 'pixel_mode' field. rows: The number of bitmap rows. width: The number of pixels in bitmap row. pitch: The pitch's absolute value is the number of bytes taken by one bitmap row, including padding. However, the pitch is positive when the bitmap has a 'down' flow, and negative when it has an 'up' flow. In all cases, the pitch is an offset to add to a bitmap pointer in order to go down one row. Note that 'padding' means the alignment of a bitmap to a byte border, and FreeType functions normally align to the smallest possible integer value. For the B/W rasterizer, 'pitch' is always an even number. To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert. Alternatively, you might use callback functions to directly render to the application's surface; see the file 'example2.py' in the tutorial for a demonstration. buffer: A typeless pointer to the bitmap buffer. This value should be aligned on 32-bit boundaries in most cases. num_grays: This field is only used with FT_PIXEL_MODE_GRAY; it gives the number of gray levels used in the bitmap. pixel_mode: The pixel mode, i.e., how pixel bits are stored. See FT_Pixel_Mode for possible values. palette_mode: This field is intended for paletted pixel modes; it indicates how the palette is stored. Not used currently. palette: A typeless pointer to the bitmap palette; this field is intended for paletted pixel modes. Not used currently. ''' _fields_ = [ ('rows', c_int), ('width', c_int), ('pitch', c_int), # declaring buffer as c_char_p confuses ctypes ('buffer', POINTER(c_ubyte)), ('num_grays', c_short), ('pixel_mode', c_ubyte), ('palette_mode', c_char), ('palette', c_void_p) ] # ----------------------------------------------------------------------------- # Read-only binary data represented as a pointer and a length. # - While it is used internally within FreeType, the only public # references to this structure are in include/freetype/ftincrem.h # where it is used as glyph data bytes returned by incremental loading APIs. # This is a specialist usage, and the only known use-case is # by ghostscript, in ghostscript/base/fapi_ft.c . # Hence there are no python examples for this. class FT_Data(Structure): ''' Read-only binary data represented as a pointer and a length. pointer: The data. length: The length of the data in bytes. ''' _fields_ = [('pointer', POINTER(FT_Byte)), ('length', FT_UInt)] # ----------------------------------------------------------------------------- # Client applications often need to associate their own data to a variety of # FreeType core objects. For example, a text layout API might want to associate # a glyph cache to a given size object. # # Most FreeType object contains a 'generic' field, of type FT_Generic, which # usage is left to client applications and font servers. # # It can be used to store a pointer to client-specific data, as well as the # address of a 'finalizer' function, which will be called by FreeType when the # object is destroyed (for example, the previous client example would put the # address of the glyph cache destructor in the 'finalizer' field). class FT_Generic(Structure): ''' Client applications often need to associate their own data to a variety of FreeType core objects. For example, a text layout API might want to associate a glyph cache to a given size object. Most FreeType object contains a 'generic' field, of type FT_Generic, which usage is left to client applications and font servers. It can be used to store a pointer to client-specific data, as well as the address of a 'finalizer' function, which will be called by FreeType when the object is destroyed (for example, the previous client example would put the address of the glyph cache destructor in the 'finalizer' field). data: A typeless pointer to any client-specified data. This field is completely ignored by the FreeType library. finalizer: A pointer to a 'generic finalizer' function, which will be called when the object is destroyed. If this field is set to NULL, no code will be called. ''' _fields_ = [('data', c_void_p), ('finalizer', FT_Generic_Finalizer)] # ----------------------------------------------------------------------------- # This structure models the metrics of a bitmap strike (i.e., a set of glyphs # for a given point size and resolution) in a bitmap font. It is used for the # 'available_sizes' field of FT_Face. class FT_Bitmap_Size(Structure): ''' This structure models the metrics of a bitmap strike (i.e., a set of glyphs for a given point size and resolution) in a bitmap font. It is used for the 'available_sizes' field of FT_Face. height: The vertical distance, in pixels, between two consecutive baselines. It is always positive. width: The average width, in pixels, of all glyphs in the strike. size: The nominal size of the strike in 26.6 fractional points. This field is not very useful. x_ppem: The horizontal ppem (nominal width) in 26.6 fractional pixels. y_ppem: The vertical ppem (nominal height) in 26.6 fractional pixels. ''' _fields_ = [ ('height', FT_Short), ('width', FT_Short), ('size', FT_Pos), ('x_ppem', FT_Pos), ('y_ppem', FT_Pos) ] # ----------------------------------------------------------------------------- # The base charmap structure. class FT_CharmapRec(Structure): ''' The base charmap structure. face : A handle to the parent face object. encoding : An FT_Encoding tag identifying the charmap. Use this with FT_Select_Charmap. platform_id: An ID number describing the platform for the following encoding ID. This comes directly from the TrueType specification and should be emulated for other formats. encoding_id: A platform specific encoding number. This also comes from the TrueType specification and should be emulated similarly. ''' _fields_ = [ ('face', c_void_p), # Shoudl be FT_Face ('encoding', FT_Encoding), ('platform_id', FT_UShort), ('encoding_id', FT_UShort), ] FT_Charmap = POINTER(FT_CharmapRec) # ----------------------------------------------------------------------------- # A structure used to model the metrics of a single glyph. The values are # expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has # been used while loading the glyph, values are expressed in font units # instead. class FT_Glyph_Metrics(Structure): ''' A structure used to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has been used while loading the glyph, values are expressed in font units instead. width: The glyph's width. height: The glyph's height. horiBearingX: Left side bearing for horizontal layout. horiBearingY: Top side bearing for horizontal layout. horiAdvance: Advance width for horizontal layout. vertBearingX: Left side bearing for vertical layout. vertBearingY: Top side bearing for vertical layout. vertAdvance: Advance height for vertical layout. ''' _fields_ = [ ('width', FT_Pos), ('height', FT_Pos), ('horiBearingX', FT_Pos), ('horiBearingY', FT_Pos), ('horiAdvance', FT_Pos), ('vertBearingX', FT_Pos), ('vertBearingY', FT_Pos), ('vertAdvance', FT_Pos), ] # ----------------------------------------------------------------------------- # This structure is used to describe an outline to the scan-line converter. class FT_Outline(Structure): ''' This structure is used to describe an outline to the scan-line converter. n_contours: The number of contours in the outline. n_points: The number of points in the outline. points: A pointer to an array of 'n_points' FT_Vector elements, giving the outline's point coordinates. tags: A pointer to an array of 'n_points' chars, giving each outline point's type. If bit 0 is unset, the point is 'off' the curve, i.e., a Bezier control point, while it is 'on' if set. Bit 1 is meaningful for 'off' points only. If set, it indicates a third-order Bezier arc control point; and a second-order control point if unset. If bit 2 is set, bits 5-7 contain the drop-out mode (as defined in the OpenType specification; the value is the same as the argument to the SCANMODE instruction). Bits 3 and 4 are reserved for internal purposes. contours: An array of 'n_contours' shorts, giving the end point of each contour within the outline. For example, the first contour is defined by the points '0' to 'contours[0]', the second one is defined by the points 'contours[0]+1' to 'contours[1]', etc. flags: A set of bit flags used to characterize the outline and give hints to the scan-converter and hinter on how to convert/grid-fit it. See FT_OUTLINE_FLAGS. ''' _fields_ = [ ('n_contours', c_short), ('n_points', c_short), ('points', POINTER(FT_Vector)), # declaring buffer as c_char_p would prevent us to acces all tags ('tags', POINTER(c_ubyte)), ('contours', POINTER(c_short)), ('flags', c_int), ] # ----------------------------------------------------------------------------- # Callback functions used in FT_Outline_Funcs FT_Outline_MoveToFunc = CFUNCTYPE(c_int, POINTER(FT_Vector), py_object) FT_Outline_LineToFunc = CFUNCTYPE(c_int, POINTER(FT_Vector), py_object) FT_Outline_ConicToFunc = CFUNCTYPE(c_int, POINTER(FT_Vector), POINTER(FT_Vector), py_object) FT_Outline_CubicToFunc = CFUNCTYPE(c_int, POINTER(FT_Vector), POINTER(FT_Vector), POINTER(FT_Vector), py_object) # ----------------------------------------------------------------------------- # Struct of callback functions for FT_Outline_Decompose() class FT_Outline_Funcs(Structure): ''' This structure holds a set of callbacks which are called by FT_Outline_Decompose. move_to: Callback when outline needs to jump to a new path component. line_to: Callback to draw a straight line from the current position to the control point. conic_to: Callback to draw a second-order Bézier curve from the current position using the passed control points. curve_to: Callback to draw a third-order Bézier curve from the current position using the passed control points. shift: Passed to FreeType which will transform vectors via `x = (x << shift) - delta` and `y = (y << shift) - delta` delta: Passed to FreeType which will transform vectors via `x = (x << shift) - delta` and `y = (y << shift) - delta` ''' _fields_ = [ ('move_to', FT_Outline_MoveToFunc), ('line_to', FT_Outline_LineToFunc), ('conic_to', FT_Outline_ConicToFunc), ('cubic_to', FT_Outline_CubicToFunc), ('shift', c_int), ('delta', FT_Pos), ] # ----------------------------------------------------------------------------- # The root glyph structure contains a given glyph image plus its advance width # in 16.16 fixed float format. class FT_GlyphRec(Structure): ''' The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed float format. library: A handle to the FreeType library object. clazz: A pointer to the glyph's class. Private. format: The format of the glyph's image. advance: A 16.16 vector that gives the glyph's advance width. ''' _fields_ = [ ('library', FT_Library), ('clazz', c_void_p), ('format', FT_Glyph_Format), ('advance', FT_Vector) ] FT_Glyph = POINTER(FT_GlyphRec) # ----------------------------------------------------------------------------- # FreeType root glyph slot class structure. A glyph slot is a container where # individual glyphs can be loaded, be they in outline or bitmap format. class FT_GlyphSlotRec(Structure): ''' FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be they in outline or bitmap format. library: A handle to the FreeType library instance this slot belongs to. face: A handle to the parent face object. next: In some cases (like some font tools), several glyph slots per face object can be a good thing. As this is rare, the glyph slots are listed through a direct, single-linked list using its 'next' field. generic: A typeless pointer which is unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each glyph slot object. metrics: The metrics of the last loaded glyph in the slot. The returned values depend on the last load flags (see the FT_Load_Glyph API function) and can be expressed either in 26.6 fractional pixels or font units. Note that even when the glyph image is transformed, the metrics are not. linearHoriAdvance: The advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs. linearVertAdvance: The advance height of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs. advance: This shorthand is, depending on FT_LOAD_IGNORE_TRANSFORM, the transformed advance width for the glyph (in 26.6 fractional pixel format). As specified with FT_LOAD_VERTICAL_LAYOUT, it uses either the 'horiAdvance' or the 'vertAdvance' value of 'metrics' field. format: This field indicates the format of the image contained in the glyph slot. Typically FT_GLYPH_FORMAT_BITMAP, FT_GLYPH_FORMAT_OUTLINE, or FT_GLYPH_FORMAT_COMPOSITE, but others are possible. bitmap: This field is used as a bitmap descriptor when the slot format is FT_GLYPH_FORMAT_BITMAP. Note that the address and content of the bitmap buffer can change between calls of FT_Load_Glyph and a few other functions. bitmap_left: This is the bitmap's left bearing expressed in integer pixels. Of course, this is only valid if the format is FT_GLYPH_FORMAT_BITMAP. bitmap_top: This is the bitmap's top bearing expressed in integer pixels. Remember that this is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive. outline: The outline descriptor for the current glyph image if its format is FT_GLYPH_FORMAT_OUTLINE. Once a glyph is loaded, 'outline' can be transformed, distorted, embolded, etc. However, it must not be freed. num_subglyphs: The number of subglyphs in a composite glyph. This field is only valid for the composite glyph format that should normally only be loaded with the FT_LOAD_NO_RECURSE flag. For now this is internal to FreeType. subglyphs: An array of subglyph descriptors for composite glyphs. There are 'num_subglyphs' elements in there. Currently internal to FreeType. control_data: Certain font drivers can also return the control data for a given glyph image (e.g. TrueType bytecode, Type 1 charstrings, etc.). This field is a pointer to such data. control_len: This is the length in bytes of the control data. other: Really wicked formats can use this pointer to present their own glyph image to client applications. Note that the application needs to know about the image format. lsb_delta: The difference between hinted and unhinted left side bearing while autohinting is active. Zero otherwise. rsb_delta: The difference between hinted and unhinted right side bearing while autohinting is active. Zero otherwise. ''' _fields_ = [ ('library', FT_Library), ('face', c_void_p), ('next', c_void_p), ('glyph_index', c_uint), # new in FreeType 2.10; was reserved previously and retained for binary compatibility ('generic', FT_Generic), ('metrics', FT_Glyph_Metrics), ('linearHoriAdvance', FT_Fixed), ('linearVertAdvance', FT_Fixed), ('advance', FT_Vector), ('format', FT_Glyph_Format), ('bitmap', FT_Bitmap), ('bitmap_left', FT_Int), ('bitmap_top', FT_Int), ('outline', FT_Outline), ('num_subglyphs', FT_UInt), ('subglyphs', c_void_p), ('control_data', c_void_p), ('control_len', c_long), ('lsb_delta', FT_Pos), ('rsb_delta', FT_Pos), ('other', c_void_p), ('internal', c_void_p), ] FT_GlyphSlot = POINTER(FT_GlyphSlotRec) # ----------------------------------------------------------------------------- # The size metrics structure gives the metrics of a size object. class FT_Size_Metrics(Structure): ''' The size metrics structure gives the metrics of a size object. x_ppem: The width of the scaled EM square in pixels, hence the term 'ppem' (pixels per EM). It is also referred to as 'nominal width'. y_ppem: The height of the scaled EM square in pixels, hence the term 'ppem' (pixels per EM). It is also referred to as 'nominal height'. x_scale: A 16.16 fractional scaling value used to convert horizontal metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats. y_scale: A 16.16 fractional scaling value used to convert vertical metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats. ascender: The ascender in 26.6 fractional pixels. See FT_FaceRec for the details. descender: The descender in 26.6 fractional pixels. See FT_FaceRec for the details. height: The height in 26.6 fractional pixels. See FT_FaceRec for the details. max_advance: The maximal advance width in 26.6 fractional pixels. See FT_FaceRec for the details. ''' _fields_ = [ ('x_ppem', FT_UShort), ('y_ppem', FT_UShort), ('x_scale', FT_Fixed), ('y_scale', FT_Fixed), ('ascender', FT_Pos), ('descender', FT_Pos), ('height', FT_Pos), ('max_advance', FT_Pos), ] # ----------------------------------------------------------------------------- # FreeType root size class structure. A size object models a face object at a # given size. class FT_SizeRec(Structure): ''' FreeType root size class structure. A size object models a face object at a given size. face: Handle to the parent face object. generic: A typeless pointer, which is unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each size object. metrics: Metrics for this size object. This field is read-only. ''' _fields_ = [ ('face', c_void_p), ('generic', FT_Generic), ('metrics', FT_Size_Metrics), ('internal', c_void_p), ] FT_Size = POINTER(FT_SizeRec) # ----------------------------------------------------------------------------- # FreeType root face class structure. A face object models a typeface in a font # file. class FT_FaceRec(Structure): ''' FreeType root face class structure. A face object models a typeface in a font file. num_faces: The number of faces in the font file. Some font formats can have multiple faces in a font file. face_index: The index of the face in the font file. It is set to 0 if there is only one face in the font file. face_flags: A set of bit flags that give important information about the face; see FT_FACE_FLAG_XXX for the details. style_flags: A set of bit flags indicating the style of the face; see FT_STYLE_FLAG_XXX for the details. num_glyphs: The number of glyphs in the face. If the face is scalable and has sbits (see 'num_fixed_sizes'), it is set to the number of outline glyphs. For CID-keyed fonts, this value gives the highest CID used in the font. family_name: The face's family name. This is an ASCII string, usually in English, which describes the typeface's family (like 'Times New Roman', 'Bodoni', 'Garamond', etc). This is a least common denominator used to list fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. Applications should use the format specific interface to access them. Can be NULL (e.g., in fonts embedded in a PDF file). style_name: The face's style name. This is an ASCII string, usually in English, which describes the typeface's style (like 'Italic', 'Bold', 'Condensed', etc). Not all font formats provide a style name, so this field is optional, and can be set to NULL. As for 'family_name', some formats provide localized and Unicode versions of this string. Applications should use the format specific interface to access them. num_fixed_sizes: The number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap strikes, which are called 'sbits' in that case. available_sizes: An array of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap strike. num_charmaps: The number of charmaps in the face. charmaps: An array of the charmaps of the face. generic: A field reserved for client uses. See the FT_Generic type description. bbox: The font bounding box. Coordinates are expressed in font units (see 'units_per_EM'). The box is large enough to contain any glyph from the font. Thus, 'bbox.yMax' can be seen as the 'maximal ascender', and 'bbox.yMin' as the 'minimal descender'. Only relevant for scalable formats. Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for further discussion. units_per_EM: The number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and 1000 for Type 1 fonts. Only relevant for scalable formats. ascender: The typographic ascender of the face, expressed in font units. For font formats not having this information, it is set to 'bbox.yMax'. Only relevant for scalable formats. descender: The typographic descender of the face, expressed in font units. For font formats not having this information, it is set to 'bbox.yMin'. Note that this field is usually negative. Only relevant for scalable formats. height: The height is the vertical distance between two consecutive baselines, expressed in font units. It is always positive. Only relevant for scalable formats. max_advance_width: The maximal advance width, in font units, for all glyphs in this face. This can be used to make word wrapping computations faster. Only relevant for scalable formats. max_advance_height: The maximal advance height, in font units, for all glyphs in this face. This is only relevant for vertical layouts, and is set to 'height' for fonts that do not provide vertical metrics. Only relevant for scalable formats. underline_position: The position, in font units, of the underline line for this face. It is the center of the underlining stem. Only relevant for scalable formats. underline_thickness: The thickness, in font units, of the underline for this face. Only relevant for scalable formats. glyph: The face's associated glyph slot(s). size: The current active size for this face. charmap: The current active charmap for this face. ''' _fields_ = [ ('num_faces', FT_Long), ('face_index', FT_Long), ('face_flags', FT_Long), ('style_flags', FT_Long), ('num_glyphs', FT_Long), ('family_name', FT_String_p), ('style_name', FT_String_p), ('num_fixed_sizes', FT_Int), ('available_sizes', POINTER(FT_Bitmap_Size)), ('num_charmaps', c_int), ('charmaps', POINTER(FT_Charmap)), ('generic', FT_Generic), # The following member variables (down to `underline_thickness') # are only relevant to scalable outlines; cf. @FT_Bitmap_Size # for bitmap fonts. ('bbox', FT_BBox), ('units_per_EM', FT_UShort), ('ascender', FT_Short), ('descender', FT_Short), ('height', FT_Short), ('max_advance_width', FT_Short), ('max_advance_height', FT_Short), ('underline_position', FT_Short), ('underline_thickness', FT_Short), ('glyph', FT_GlyphSlot), ('size', FT_Size), ('charmap', FT_Charmap), # private ('driver', c_void_p), ('memory', c_void_p), ('stream', c_void_p), ('sizes_list_head', c_void_p), ('sizes_list_tail', c_void_p), ('autohint', FT_Generic), ('extensions', c_void_p), ('internal', c_void_p), ] FT_Face = POINTER(FT_FaceRec) # ----------------------------------------------------------------------------- # A simple structure used to pass more or less generic parameters to # FT_Open_Face. class FT_Parameter(Structure): ''' A simple structure used to pass more or less generic parameters to FT_Open_Face. tag: A four-byte identification tag. data: A pointer to the parameter data ''' _fields_ = [ ('tag', FT_ULong), ('data', FT_Pointer) ] FT_Parameter_p = POINTER(FT_Parameter) # ----------------------------------------------------------------------------- # A structure used to indicate how to open a new font file or stream. A pointer # to such a structure can be used as a parameter for the functions FT_Open_Face # and FT_Attach_Stream. class FT_Open_Args(Structure): ''' A structure used to indicate how to open a new font file or stream. A pointer to such a structure can be used as a parameter for the functions FT_Open_Face and FT_Attach_Stream. flags: A set of bit flags indicating how to use the structure. memory_base: The first byte of the file in memory. memory_size: The size in bytes of the file in memory. pathname: A pointer to an 8-bit file pathname. stream: A handle to a source stream object. driver: This field is exclusively used by FT_Open_Face; it simply specifies the font driver to use to open the face. If set to 0, FreeType tries to load the face with each one of the drivers in its list. num_params: The number of extra parameters. params: Extra parameters passed to the font driver when opening a new face. ''' _fields_ = [ ('flags', FT_UInt), ('memory_base', POINTER(FT_Byte)), ('memory_size', FT_Long), ('pathname', FT_String_p), ('stream', c_void_p), ('driver', c_void_p), ('num_params', FT_Int), ('params', FT_Parameter_p) ] # ----------------------------------------------------------------------------- # A structure used to model an SFNT 'name' table entry. class FT_SfntName(Structure): ''' platform_id: The platform ID for 'string'. encoding_id: The encoding ID for 'string'. language_id: The language ID for 'string' name_id: An identifier for 'string' string: The 'name' string. Note that its format differs depending on the (platform,encoding) pair. It can be a Pascal String, a UTF-16 one, etc. Generally speaking, the string is not zero-terminated. Please refer to the TrueType specification for details. string_len: The length of 'string' in bytes. ''' _fields_ = [ ('platform_id', FT_UShort), ('encoding_id', FT_UShort), ('language_id', FT_UShort), ('name_id', FT_UShort), # this string is *not* null-terminated! ('string', POINTER(FT_Byte)), ('string_len', FT_UInt) ] # ----------------------------------------------------------------------------- # Opaque handler to a path stroker object. class FT_StrokerRec(Structure): ''' Opaque handler to a path stroker object. ''' _fields_ = [ ] FT_Stroker = POINTER(FT_StrokerRec) # ----------------------------------------------------------------------------- # A structure used for bitmap glyph images. This really is a 'sub-class' of # FT_GlyphRec. # class FT_BitmapGlyphRec(Structure): ''' A structure used for bitmap glyph images. This really is a 'sub-class' of FT_GlyphRec. ''' _fields_ = [ ('root' , FT_GlyphRec), ('left', FT_Int), ('top', FT_Int), ('bitmap', FT_Bitmap) ] FT_BitmapGlyph = POINTER(FT_BitmapGlyphRec) # ----------------------------------------------------------------------------- # Structures related to variable fonts as used in the various VF routines. # class FT_Var_Axis(Structure): ''' A structure to model a given axis in design space for Multiple Masters, TrueType GX, and OpenType variation fonts. ''' _fields_ = [ ('name', FT_String_p), ('minimum', FT_Fixed), ('default', FT_Fixed), ('maximum', FT_Fixed), ('tag', FT_ULong), ('strid', FT_UInt) ] class FT_Var_Named_Style(Structure): ''' A structure to model a named instance in a TrueType GX or OpenType variation font. ''' _fields_ = [ ('coords', POINTER(FT_Fixed)), ('strid', FT_UInt), ('psid', FT_UInt) ] class FT_MM_Var(Structure): ''' A structure to model the axes and space of an Adobe MM, TrueType GX, or OpenType variation font. Some fields are specific to one format and not to the others. ''' _fields_ = [ ('num_axis', FT_UInt), ('num_designs', FT_UInt), ('num_namedstyles', FT_UInt), ('axis', POINTER(FT_Var_Axis)), ('namedstyle', POINTER(FT_Var_Named_Style)) ] # ----------------------------------------------------------------------------- # Structures related to OT-SVG support. See "freetype/otsvg.h". # SVG_Lib_Init_Func = CFUNCTYPE(c_int, POINTER(py_object)) SVG_Lib_Free_Func = CFUNCTYPE(None, POINTER(py_object)) SVG_Lib_Render_Func = CFUNCTYPE(c_int, FT_GlyphSlot, POINTER(py_object)) SVG_Lib_Preset_Slot_Func = CFUNCTYPE(c_int, FT_GlyphSlot, FT_Bool, POINTER(py_object)) class SVG_RendererHooks(Structure): _fields_ = [('svg_init', SVG_Lib_Init_Func), ('svg_free', SVG_Lib_Free_Func), ('svg_render', SVG_Lib_Render_Func), ('svg_preset_slot', SVG_Lib_Preset_Slot_Func)] class FT_SVG_DocumentRec(Structure): _fields_ = [('svg_document', POINTER(FT_Byte)), ('svg_document_length', FT_ULong), ('metrics', FT_Size_Metrics), ('units_per_EM', FT_UShort), ('start_glyph_id', FT_UShort), ('end_glyph_id', FT_UShort), ('transform', FT_Matrix), ('delta', FT_Vector)] FT_SVG_Document = POINTER(FT_SVG_DocumentRec) # ----------------------------------------------------------------------------- # Structures related to color support. See "freetype/ftcolor.h". # class FT_OpaquePaint(Structure): _fields_ = [('p', POINTER(FT_Byte)), ('insert_root_transform', FT_Bool)] class FT_LayerIterator(Structure): _fields_ = [('num_layers', FT_UInt), ('layer', FT_UInt), ('p', POINTER(FT_Byte))] freetype-py-2.5.1/freetype/__pyinstaller/0000775000175000017500000000000014664131406020664 5ustar georgeskgeorgeskfreetype-py-2.5.1/freetype/__pyinstaller/__init__.py0000664000175000017500000000022614664131406022775 0ustar georgeskgeorgeskimport os HERE = os.path.dirname(__file__) def get_hook_dirs(): return [HERE] def get_test_dirs(): return [os.path.join(HERE, 'tests')] freetype-py-2.5.1/freetype/__pyinstaller/hook-freetype.py0000664000175000017500000000014714664131406024021 0ustar georgeskgeorgeskfrom PyInstaller.utils.hooks import collect_dynamic_libs binaries = collect_dynamic_libs("freetype") freetype-py-2.5.1/freetype/__pyinstaller/tests/0000775000175000017500000000000014664131406022026 5ustar georgeskgeorgeskfreetype-py-2.5.1/freetype/__pyinstaller/tests/__init__.py0000664000175000017500000000000014664131406024125 0ustar georgeskgeorgeskfreetype-py-2.5.1/freetype/__pyinstaller/tests/test_freetype.py0000664000175000017500000000233414664131406025264 0ustar georgeskgeorgeskdef test_pyi_freetype(pyi_builder): pyi_builder.test_source( """ import sys import pathlib import freetype # Ensure that the freetype shared library is bundled with the frozen # application; otherwise, freetype might be using system-wide library. # Check that freetype.FT_Library_filename is an absolute path; # otherwise, it is likely using basename-only ctypes fallback. ft_library_file = pathlib.Path(freetype.FT_Library_filename) print(f"FT library file (original): {ft_library_file}", file=sys.stderr) assert ft_library_file.is_absolute(), \ "FT library file is not an absolute path!" # Check that fully-resolved freetype.FT_Library_filename is # anchored in fully-resolved frozen application directory. app_dir = pathlib.Path(__file__).resolve().parent print(f"Application directory: {app_dir}", file=sys.stderr) ft_library_path = pathlib.Path(ft_library_file).resolve() print(f"FT library file (resolved): {ft_library_path}", file=sys.stderr) assert app_dir in ft_library_path.parents, \ "FT library is not bundled with frozen application!" """ ) freetype-py-2.5.1/freetype/__pyinstaller/tests/conftest.py0000664000175000017500000000005114664131406024221 0ustar georgeskgeorgeskfrom PyInstaller.utils.conftest import * freetype-py-2.5.1/freetype/ft_errors.py0000664000175000017500000001101614664131406020376 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Internal exception with freetype error message ''' class FT_Exception(Exception): def __init__(self, errcode, message=''): self.message = message self.errcode = errcode def __str__(self): return '%s: %s (%s)'%(self.__class__.__name__, self.message, self._errors.get(self.errcode, 'unknown error')) _errors = { 0x00: "no error" , 0x01: "cannot open resource" , 0x02: "unknown file format" , 0x03: "broken file" , 0x04: "invalid FreeType version" , 0x05: "module version is too low" , 0x06: "invalid argument" , 0x07: "unimplemented feature" , 0x08: "broken table" , 0x09: "broken offset within table" , 0x0A: "array allocation size too large" , 0x0B: "missing module" , 0x0C: "missing property" , 0x10: "invalid glyph index" , 0x11: "invalid character code" , 0x12: "unsupported glyph image format" , 0x13: "cannot render this glyph format" , 0x14: "invalid outline" , 0x15: "invalid composite glyph" , 0x16: "too many hints" , 0x17: "invalid pixel size" , 0x18: "invalid SVG document" , 0x20: "invalid object handle" , 0x21: "invalid library handle" , 0x22: "invalid module handle" , 0x23: "invalid face handle" , 0x24: "invalid size handle" , 0x25: "invalid glyph slot handle" , 0x26: "invalid charmap handle" , 0x27: "invalid cache manager handle" , 0x28: "invalid stream handle" , 0x30: "too many modules" , 0x31: "too many extensions" , 0x40: "out of memory" , 0x41: "unlisted object" , 0x51: "cannot open stream" , 0x52: "invalid stream seek" , 0x53: "invalid stream skip" , 0x54: "invalid stream read" , 0x55: "invalid stream operation" , 0x56: "invalid frame operation" , 0x57: "nested frame access" , 0x58: "invalid frame read" , 0x60: "raster uninitialized" , 0x61: "raster corrupted" , 0x62: "raster overflow" , 0x63: "negative height while rastering" , 0x70: "too many registered caches" , 0x80: "invalid opcode" , 0x81: "too few arguments" , 0x82: "stack overflow" , 0x83: "code overflow" , 0x84: "bad argument" , 0x85: "division by zero" , 0x86: "invalid reference" , 0x87: "found debug opcode" , 0x88: "found ENDF opcode in execution stream" , 0x89: "nested DEFS" , 0x8A: "invalid code range" , 0x8B: "execution context too long" , 0x8C: "too many function definitions" , 0x8D: "too many instruction definitions" , 0x8E: "SFNT font table missing" , 0x8F: "horizontal header (hhea, table missing" , 0x90: "locations (loca, table missing" , 0x91: "name table missing" , 0x92: "character map (cmap, table missing" , 0x93: "horizontal metrics (hmtx, table missing" , 0x94: "PostScript (post, table missing" , 0x95: "invalid horizontal metrics" , 0x96: "invalid character map (cmap, format" , 0x97: "invalid ppem value" , 0x98: "invalid vertical metrics" , 0x99: "could not find context" , 0x9A: "invalid PostScript (post, table format" , 0x9B: "invalid PostScript (post, table" , 0x9C: "found FDEF or IDEF opcode in glyf bytecode" , 0x9D: "missing bitmap in strike" , 0x9E: "SVG hooks have not been set", 0xA0: "opcode syntax error" , 0xA1: "argument stack underflow" , 0xA2: "ignore" , 0xA3: "no Unicode glyph name found" , 0xA4: "glyph too big for hinting" , 0xB0: "`STARTFONT' field missing" , 0xB1: "`FONT' field missing" , 0xB2: "`SIZE' field missing" , 0xB3: "`FONTBOUNDINGBOX' field missing" , 0xB4: "`CHARS' field missing" , 0xB5: "`STARTCHAR' field missing" , 0xB6: "`ENCODING' field missing" , 0xB7: "`BBX' field missing" , 0xB8: "`BBX' too big" , 0xB9: "Font header corrupted or missing fields" , 0xBA: "Font glyphs corrupted or missing fields" , } FT_Err_Ok=0x00 freetype-py-2.5.1/freetype/ft_types.py0000664000175000017500000001310514664131406020227 0ustar georgeskgeorgesk#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Freetype basic data types ------------------------- FT_Byte : A simple typedef for the unsigned char type. FT_Bytes : A typedef for constant memory areas. FT_Char : A simple typedef for the signed char type. FT_Int : A typedef for the int type. FT_UInt : A typedef for the unsigned int type. FT_Int16 : A typedef for a 16bit signed integer type. FT_UInt16 : A typedef for a 16bit unsigned integer type. FT_Int32 : A typedef for a 32bit signed integer type. FT_UInt32 : A typedef for a 32bit unsigned integer type. FT_Short : A typedef for signed short. FT_UShort : A typedef for unsigned short. FT_Long : A typedef for signed long. FT_ULong : A typedef for unsigned long. FT_Bool : A typedef of unsigned char, used for simple booleans. As usual, values 1 and 0 represent true and false, respectively. FT_Offset : This is equivalent to the ANSI C 'size_t' type, i.e., the largest unsigned integer type used to express a file size or position, or a memory block size. FT_PtrDist : This is equivalent to the ANSI C 'ptrdiff_t' type, i.e., the largest signed integer type used to express the distance between two pointers. FT_String : A simple typedef for the char type, usually used for strings. FT_Tag : A typedef for 32-bit tags (as used in the SFNT format). FT_Error : The FreeType error code type. A value of 0 is always interpreted as a successful operation. FT_Fixed : This type is used to store 16.16 fixed float values, like scaling values or matrix coefficients. FT_Pointer : A simple typedef for a typeless pointer. FT_Pos : The type FT_Pos is used to store vectorial coordinates. Depending on the context, these can represent distances in integer font units, or 16.16, or 26.6 fixed float pixel coordinates. FT_FWord : A signed 16-bit integer used to store a distance in original font units. FT_UFWord : An unsigned 16-bit integer used to store a distance in original font units. FT_F2Dot14 : A signed 2.14 fixed float type used for unit vectors. FT_F26Dot6 : A signed 26.6 fixed float type used for vectorial pixel coordinates. ''' from ctypes import * FT_Byte = c_ubyte # A simple typedef for the unsigned char type. FT_Bytes = c_char_p # A typedef for constant memory areas. FT_Char = c_char # A simple typedef for the signed char type. FT_Int = c_int # A typedef for the int type. FT_UInt = c_uint # A typedef for the unsigned int type. FT_Int16 = c_short # A typedef for a 16bit signed integer type. FT_UInt16 = c_ushort # A typedef for a 16bit unsigned integer type. FT_Int32 = c_int32 # A typedef for a 32bit signed integer type. FT_UInt32 = c_uint32 # A typedef for a 32bit unsigned integer type. FT_Short = c_short # A typedef for signed short. FT_UShort = c_ushort # A typedef for unsigned short. FT_Long = c_long # A typedef for signed long. FT_ULong = c_ulong # A typedef for unsigned long. FT_Bool = c_char # A typedef of unsigned char, used for simple booleans. As # usual, values 1 and 0 represent true and false, # respectively. FT_Offset = c_size_t # This is equivalent to the ANSI C 'size_t' type, i.e., # the largest unsigned integer type used to express a file # size or position, or a memory block size. FT_PtrDist = c_longlong # This is equivalent to the ANSI C 'ptrdiff_t' type, # i.e., the largest signed integer type used to express # the distance between two pointers. FT_String = c_char # A simple typedef for the char type, usually used for strings. FT_String_p= c_char_p FT_Tag = FT_UInt32 # A typedef for 32-bit tags (as used in the SFNT format). FT_Error = c_int # The FreeType error code type. A value of 0 is always # interpreted as a successful operation. FT_Fixed = c_long # This type is used to store 16.16 fixed float values, # like scaling values or matrix coefficients. FT_Angle = FT_Fixed # This type is used to model angle values in FreeType. Note that the # angle is a 16.16 fixed-point value expressed in degrees. FT_Pointer = c_void_p # A simple typedef for a typeless pointer. FT_Pos = c_long # The type FT_Pos is used to store vectorial # coordinates. Depending on the context, these can # represent distances in integer font units, or 16.16, or # 26.6 fixed float pixel coordinates. FT_FWord = c_short # A signed 16-bit integer used to store a distance in # original font units. FT_UFWord = c_ushort # An unsigned 16-bit integer used to store a distance in # original font units. FT_F2Dot14 = c_short # A signed 2.14 fixed float type used for unit vectors. FT_F26Dot6 = c_long # A signed 26.6 fixed float type used for vectorial pixel # coordinates. FT_Glyph_Format = c_int FT_Encoding = c_int # Describe a function used to destroy the 'client' data of any FreeType # object. See the description of the FT_Generic type for details of usage. FT_Generic_Finalizer = CFUNCTYPE(None, c_void_p) freetype-py-2.5.1/freetype/ft_enums/0000775000175000017500000000000014664131406017640 5ustar georgeskgeorgeskfreetype-py-2.5.1/freetype/ft_enums/ft_pixel_modes.py0000664000175000017500000000560314664131406023217 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. FT_PIXEL_MODE_NONE Value 0 is reserved. FT_PIXEL_MODE_MONO A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in most-significant order (MSB), which means that the left-most pixel in a byte has value 128. FT_PIXEL_MODE_GRAY An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each pixel is stored in one byte. Note that the number of 'gray' levels is stored in the 'num_grays' field of the FT_Bitmap structure (it generally is 256). FT_PIXEL_MODE_GRAY2 A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. FT_PIXEL_MODE_GRAY4 A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. FT_PIXEL_MODE_LCD An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on LCD displays; the bitmap is three times wider than the original glyph image. See also FT_RENDER_MODE_LCD. FT_PIXEL_MODE_LCD_V An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on rotated LCD displays; the bitmap is three times taller than the original glyph image. See also FT_RENDER_MODE_LCD_V. FT_PIXEL_MODE_BGRA [Since 2.5] An image with four 8-bit channels per pixel, representing a color image (such as emoticons) with alpha channel. For each pixel, the format is BGRA, which means, the blue channel comes first in memory. The color channels are pre-multiplied and in the sRGB colorspace. For example, full red at half-translucent opacity will be represented as '00,00,80,80', not '00,00,FF,80'. See also @FT_LOAD_COLOR. """ FT_PIXEL_MODES = {'FT_PIXEL_MODE_NONE' : 0, 'FT_PIXEL_MODE_MONO' : 1, 'FT_PIXEL_MODE_GRAY' : 2, 'FT_PIXEL_MODE_GRAY2': 3, 'FT_PIXEL_MODE_GRAY4': 4, 'FT_PIXEL_MODE_LCD' : 5, 'FT_PIXEL_MODE_LCD_V': 6, 'FT_PIXEL_MODE_BGRA' : 7, 'FT_PIXEL_MODE_MAX' : 8} globals().update(FT_PIXEL_MODES) ft_pixel_mode_none = FT_PIXEL_MODE_NONE ft_pixel_mode_mono = FT_PIXEL_MODE_MONO ft_pixel_mode_grays = FT_PIXEL_MODE_GRAY ft_pixel_mode_pal2 = FT_PIXEL_MODE_GRAY2 ft_pixel_mode_pal4 = FT_PIXEL_MODE_GRAY4 freetype-py-2.5.1/freetype/ft_enums/ft_color_root_transform.py0000664000175000017500000000031114664131406025152 0ustar georgeskgeorgeskFT_Color_Root_Transform = { 'FT_COLOR_INCLUDE_ROOT_TRANSFORM' : 0, 'FT_COLOR_NO_ROOT_TRANSFORM' : 1, 'FT_COLOR_ROOT_TRANSFORM_MAX' : 2, } globals().update(FT_Color_Root_Transform) freetype-py-2.5.1/freetype/ft_enums/ft_kerning_modes.py0000664000175000017500000000147114664131406023532 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration used to specify which kerning values to return in FT_Get_Kerning. FT_KERNING_DEFAULT Return scaled and grid-fitted kerning distances (value is 0). FT_KERNING_UNFITTED Return scaled but un-grid-fitted kerning distances. FT_KERNING_UNSCALED Return the kerning vector in original font units. """ FT_KERNING_MODES = { 'FT_KERNING_DEFAULT' : 0, 'FT_KERNING_UNFITTED' : 1, 'FT_KERNING_UNSCALED' : 2 } globals().update(FT_KERNING_MODES) freetype-py-2.5.1/freetype/ft_enums/ft_style_flags.py0000664000175000017500000000131514664131406023217 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit-flags used to indicate the style of a given face. These are used in the 'style_flags' field of FT_FaceRec. FT_STYLE_FLAG_ITALIC Indicates that a given face style is italic or oblique. FT_STYLE_FLAG_BOLD Indicates that a given face is bold. """ FT_STYLE_FLAGS = {'FT_STYLE_FLAG_ITALIC' : 1, 'FT_STYLE_FLAG_BOLD' : 2 } globals().update(FT_STYLE_FLAGS) freetype-py-2.5.1/freetype/ft_enums/tt_ms_langids.py0000664000175000017500000005620614664131406023052 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ Possible values of the language identifier field in the name records of the TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MICROSOFT. TT_MS_LANGID_SANSKRIT_INDIA TT_MS_LANGID_ENGLISH_UNITED_KINGDOM TT_MS_LANGID_ENGLISH_BELIZE TT_MS_LANGID_ARABIC_LEBANON TT_MS_LANGID_MOLDAVIAN_MOLDAVIA TT_MS_LANGID_TURKISH_TURKEY TT_MS_LANGID_WELSH_WALES TT_MS_LANGID_GERMAN_AUSTRIA TT_MS_LANGID_DUTCH_BELGIUM TT_MS_LANGID_YI_CHINA TT_MS_LANGID_QUECHUA_ECUADOR TT_MS_LANGID_SPANISH_EL_SALVADOR TT_MS_LANGID_SWAHILI_KENYA TT_MS_LANGID_QUECHUA_BOLIVIA TT_MS_LANGID_SLOVENE_SLOVENIA TT_MS_LANGID_ORIYA_INDIA TT_MS_LANGID_FARSI_IRAN TT_MS_LANGID_ENGLISH_CANADA TT_MS_LANGID_NEPALI_NEPAL TT_MS_LANGID_DHIVEHI_MALDIVES TT_MS_LANGID_GERMAN_LIECHTENSTEI TT_MS_LANGID_TAMIL_INDIA TT_MS_LANGID_ARABIC_UAE TT_MS_LANGID_JAPANESE_JAPAN TT_MS_LANGID_TAMAZIGHT_MOROCCO TT_MS_LANGID_FRENCH_FRANCE TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_VIETNAMESE_VIET_NAM TT_MS_LANGID_HEBREW_ISRAEL TT_MS_LANGID_SAMI_NORTHERN_SWEDEN TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN TT_MS_LANGID_SWEDISH_SWEDEN TT_MS_LANGID_FRENCH_REUNION TT_MS_LANGID_ARABIC_BAHRAIN TT_MS_LANGID_ENGLISH_INDIA TT_MS_LANGID_NEPALI_INDIA TT_MS_LANGID_THAI_THAILAND TT_MS_LANGID_ENGLISH_GENERAL TT_MS_LANGID_SAMI_LULE_NORWAY TT_MS_LANGID_ARABIC_OMAN TT_MS_LANGID_SPANISH_HONDURAS TT_MS_LANGID_ENGLISH_JAMAICA TT_MS_LANGID_ESTONIAN_ESTONIA TT_MS_LANGID_FRISIAN_NETHERLANDS TT_MS_LANGID_LATIN TT_MS_LANGID_ENGLISH_INDONESIA TT_MS_LANGID_ENGLISH_IRELAND TT_MS_LANGID_TIBETAN_CHINA TT_MS_LANGID_PUNJABI_INDIA TT_MS_LANGID_FRENCH_MALI TT_MS_LANGID_GERMAN_LUXEMBOURG TT_MS_LANGID_SUTU_SOUTH_AFRICA TT_MS_LANGID_FRENCH_CAMEROON TT_MS_LANGID_FRENCH_CONGO TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA TT_MS_LANGID_MALAYALAM_INDIA TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN TT_MS_LANGID_CHEROKEE_UNITED_STATES TT_MS_LANGID_SPANISH_GUATEMALA TT_MS_LANGID_CZECH_CZECH_REPUBLIC TT_MS_LANGID_MANIPURI_INDIA TT_MS_LANGID_ENGLISH_AUSTRALIA TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC TT_MS_LANGID_ARABIC_LIBYA TT_MS_LANGID_FRENCH_WEST_INDIES TT_MS_LANGID_ENGLISH_TRINIDAD TT_MS_LANGID_ARABIC_QATAR TT_MS_LANGID_SPANISH_COLOMBIA TT_MS_LANGID_GUARANI_PARAGUAY TT_MS_LANGID_EDO_NIGERIA TT_MS_LANGID_SEPEDI_SOUTH_AFRICA TT_MS_LANGID_ENGLISH_HONG_KONG TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA TT_MS_LANGID_TATAR_TATARSTAN TT_MS_LANGID_PASHTO_AFGHANISTAN TT_MS_LANGID_KASHMIRI_PAKISTAN TT_MS_LANGID_GALICIAN_SPAIN TT_MS_LANGID_TAJIK_TAJIKISTAN TT_MS_LANGID_SAMI_INARI_FINLAND TT_MS_LANGID_KASHMIRI_SASIA TT_MS_LANGID_SPANISH_ARGENTINA TT_MS_LANGID_SAMI_SOUTHERN_NORWAY TT_MS_LANGID_CROATIAN_CROATIA TT_MS_LANGID_GUJARATI_INDIA TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_TIGRIGNA_ETHIOPIA TT_MS_LANGID_FINNISH_FINLAND TT_MS_LANGID_ENGLISH_UNITED_STATES TT_MS_LANGID_ITALIAN_SWITZERLAND TT_MS_LANGID_ARABIC_EGYPT TT_MS_LANGID_SPANISH_LATIN_AMERICA TT_MS_LANGID_LITHUANIAN_LITHUANIA TT_MS_LANGID_ARABIC_ALGERIA TT_MS_LANGID_MALAY_MALAYSIA TT_MS_LANGID_ARABIC_GENERAL TT_MS_LANGID_CHINESE_PRC TT_MS_LANGID_BENGALI_BANGLADESH TT_MS_LANGID_SPANISH_PERU TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_LATVIAN_LATVIA TT_MS_LANGID_TURKMEN_TURKMENISTAN TT_MS_LANGID_XHOSA_SOUTH_AFRICA TT_MS_LANGID_KHMER_CAMBODIA TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK TT_MS_LANGID_ARABIC_MOROCCO TT_MS_LANGID_FRENCH_SENEGAL TT_MS_LANGID_YORUBA_NIGERIA TT_MS_LANGID_CATALAN_SPAIN TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA TT_MS_LANGID_ZULU_SOUTH_AFRICA TT_MS_LANGID_SPANISH_URUGUAY TT_MS_LANGID_SPANISH_ECUADOR TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA TT_MS_LANGID_CHINESE_GENERAL TT_MS_LANGID_SPANISH_PARAGUAY TT_MS_LANGID_HINDI_INDIA TT_MS_LANGID_FRENCH_LUXEMBOURG TT_MS_LANGID_TSWANA_SOUTH_AFRICA TT_MS_LANGID_HUNGARIAN_HUNGARY TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA TT_MS_LANGID_ENGLISH_SINGAPORE TT_MS_LANGID_MALTESE_MALTA TT_MS_LANGID_SAMI_NORTHERN_FINLAND TT_MS_LANGID_FRENCH_CANADA TT_MS_LANGID_SAMI_LULE_SWEDEN TT_MS_LANGID_KANURI_NIGERIA TT_MS_LANGID_IRISH_GAELIC_IRELAND TT_MS_LANGID_ARABIC_SAUDI_ARABIA TT_MS_LANGID_FRENCH_HAITI TT_MS_LANGID_SPANISH_PUERTO_RICO TT_MS_LANGID_BURMESE_MYANMAR TT_MS_LANGID_POLISH_POLAND TT_MS_LANGID_PORTUGUESE_PORTUGAL TT_MS_LANGID_ENGLISH_CARIBBEAN TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC TT_MS_LANGID_ICELANDIC_ICELAND TT_MS_LANGID_BENGALI_INDIA TT_MS_LANGID_HAUSA_NIGERIA TT_MS_LANGID_BASQUE_SPAIN TT_MS_LANGID_UIGHUR_CHINA TT_MS_LANGID_ENGLISH_MALAYSIA TT_MS_LANGID_FRENCH_MONACO TT_MS_LANGID_SPANISH_BOLIVIA TT_MS_LANGID_SORBIAN_GERMANY TT_MS_LANGID_SINDHI_INDIA TT_MS_LANGID_CHINESE_SINGAPORE TT_MS_LANGID_FRENCH_COTE_D_IVOIRE TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC TT_MS_LANGID_SAMI_SKOLT_FINLAND TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM TT_MS_LANGID_ARABIC_JORDAN TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN TT_MS_LANGID_SERBIAN_SERBIA_LATIN TT_MS_LANGID_RUSSIAN_RUSSIA TT_MS_LANGID_ROMANIAN_ROMANIA TT_MS_LANGID_FRENCH_NORTH_AFRICA TT_MS_LANGID_MONGOLIAN_MONGOLIA TT_MS_LANGID_TSONGA_SOUTH_AFRICA TT_MS_LANGID_SOMALI_SOMALIA TT_MS_LANGID_SAAMI_LAPONIA TT_MS_LANGID_SPANISH_COSTA_RICA TT_MS_LANGID_ARABIC_SYRIA TT_MS_LANGID_SPANISH_PANAMA TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES TT_MS_LANGID_ASSAMESE_INDIA TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM TT_MS_LANGID_DUTCH_NETHERLANDS TT_MS_LANGID_SINDHI_PAKISTAN TT_MS_LANGID_MACEDONIAN_MACEDONIA TT_MS_LANGID_KAZAK_KAZAKSTAN TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN TT_MS_LANGID_BELARUSIAN_BELARUS TT_MS_LANGID_FRENCH_MOROCCO TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN TT_MS_LANGID_ALBANIAN_ALBANIA TT_MS_LANGID_SINHALESE_SRI_LANKA TT_MS_LANGID_SPANISH_MEXICO TT_MS_LANGID_ENGLISH_ZIMBABWE TT_MS_LANGID_OROMO_ETHIOPIA TT_MS_LANGID_INDONESIAN_INDONESIA TT_MS_LANGID_SAMI_NORTHERN_NORWAY TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN TT_MS_LANGID_SLOVAK_SLOVAKIA TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_GERMAN_SWITZERLAND TT_MS_LANGID_URDU_INDIA TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS TT_MS_LANGID_SYRIAC_SYRIA TT_MS_LANGID_SPANISH_CHILE TT_MS_LANGID_FILIPINO_PHILIPPINES TT_MS_LANGID_ARABIC_YEMEN TT_MS_LANGID_KONKANI_INDIA TT_MS_LANGID_AMHARIC_ETHIOPIA TT_MS_LANGID_ENGLISH_NEW_ZEALAND TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND TT_MS_LANGID_ARABIC_TUNISIA TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA TT_MS_LANGID_QUECHUA_PERU TT_MS_LANGID_DANISH_DENMARK TT_MS_LANGID_ENGLISH_PHILIPPINES TT_MS_LANGID_SPANISH_NICARAGUA TT_MS_LANGID_INUKTITUT_CANADA TT_MS_LANGID_UKRAINIAN_UKRAINE TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC TT_MS_LANGID_FRENCH_BELGIUM TT_MS_LANGID_ENGLISH_SOUTH_AFRICA TT_MS_LANGID_HAWAIIAN_UNITED_STATES TT_MS_LANGID_ARABIC_IRAQ TT_MS_LANGID_KANNADA_INDIA TT_MS_LANGID_DZONGHKA_BHUTAN TT_MS_LANGID_CHINESE_TAIWAN TT_MS_LANGID_SPANISH_UNITED_STATES TT_MS_LANGID_ARMENIAN_ARMENIA TT_MS_LANGID_LAO_LAOS TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_MARATHI_INDIA TT_MS_LANGID_ARABIC_KUWAIT TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN TT_MS_LANGID_PORTUGUESE_BRAZIL TT_MS_LANGID_TIGRIGNA_ERYTHREA TT_MS_LANGID_GREEK_GREECE TT_MS_LANGID_URDU_PAKISTAN TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN TT_MS_LANGID_YIDDISH_GERMANY TT_MS_LANGID_GERMAN_GERMANY TT_MS_LANGID_TELUGU_INDIA TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC TT_MS_LANGID_KOREAN_JOHAB_KOREA TT_MS_LANGID_ITALIAN_ITALY TT_MS_LANGID_MAORI_NEW_ZEALAND TT_MS_LANGID_SPANISH_VENEZUELA TT_MS_LANGID_IGBO_NIGERIA TT_MS_LANGID_IBIBIO_NIGERIA TT_MS_LANGID_CHINESE_HONG_KONG TT_MS_LANGID_FRENCH_SWITZERLAND TT_MS_LANGID_BULGARIAN_BULGARIA TT_MS_LANGID_FULFULDE_NIGERIA TT_MS_LANGID_RUSSIAN_MOLDAVIA TT_MS_LANGID_VENDA_SOUTH_AFRICA TT_MS_LANGID_GEORGIAN_GEORGIA TT_MS_LANGID_SWEDISH_FINLAND """ TT_MS_LANGIDS = { 'TT_MS_LANGID_ARABIC_GENERAL' : 0x0001, 'TT_MS_LANGID_ARABIC_SAUDI_ARABIA' : 0x0401, 'TT_MS_LANGID_ARABIC_IRAQ' : 0x0801, 'TT_MS_LANGID_ARABIC_EGYPT' : 0x0c01, 'TT_MS_LANGID_ARABIC_LIBYA' : 0x1001, 'TT_MS_LANGID_ARABIC_ALGERIA' : 0x1401, 'TT_MS_LANGID_ARABIC_MOROCCO' : 0x1801, 'TT_MS_LANGID_ARABIC_TUNISIA' : 0x1c01, 'TT_MS_LANGID_ARABIC_OMAN' : 0x2001, 'TT_MS_LANGID_ARABIC_YEMEN' : 0x2401, 'TT_MS_LANGID_ARABIC_SYRIA' : 0x2801, 'TT_MS_LANGID_ARABIC_JORDAN' : 0x2c01, 'TT_MS_LANGID_ARABIC_LEBANON' : 0x3001, 'TT_MS_LANGID_ARABIC_KUWAIT' : 0x3401, 'TT_MS_LANGID_ARABIC_UAE' : 0x3801, 'TT_MS_LANGID_ARABIC_BAHRAIN' : 0x3c01, 'TT_MS_LANGID_ARABIC_QATAR' : 0x4001, 'TT_MS_LANGID_BULGARIAN_BULGARIA' : 0x0402, 'TT_MS_LANGID_CATALAN_SPAIN' : 0x0403, 'TT_MS_LANGID_CHINESE_GENERAL' : 0x0004, 'TT_MS_LANGID_CHINESE_TAIWAN' : 0x0404, 'TT_MS_LANGID_CHINESE_PRC' : 0x0804, 'TT_MS_LANGID_CHINESE_HONG_KONG' : 0x0c04, 'TT_MS_LANGID_CHINESE_SINGAPORE' : 0x1004, 'TT_MS_LANGID_CHINESE_MACAU' : 0x1404, 'TT_MS_LANGID_CZECH_CZECH_REPUBLIC' : 0x0405, 'TT_MS_LANGID_DANISH_DENMARK' : 0x0406, 'TT_MS_LANGID_GERMAN_GERMANY' : 0x0407, 'TT_MS_LANGID_GERMAN_SWITZERLAND' : 0x0807, 'TT_MS_LANGID_GERMAN_AUSTRIA' : 0x0c07, 'TT_MS_LANGID_GERMAN_LUXEMBOURG' : 0x1007, 'TT_MS_LANGID_GERMAN_LIECHTENSTEI' : 0x1407, 'TT_MS_LANGID_GREEK_GREECE' : 0x0408, 'TT_MS_LANGID_ENGLISH_GENERAL' : 0x0009, 'TT_MS_LANGID_ENGLISH_UNITED_STATES' : 0x0409, 'TT_MS_LANGID_ENGLISH_UNITED_KINGDOM' : 0x0809, 'TT_MS_LANGID_ENGLISH_AUSTRALIA' : 0x0c09, 'TT_MS_LANGID_ENGLISH_CANADA' : 0x1009, 'TT_MS_LANGID_ENGLISH_NEW_ZEALAND' : 0x1409, 'TT_MS_LANGID_ENGLISH_IRELAND' : 0x1809, 'TT_MS_LANGID_ENGLISH_SOUTH_AFRICA' : 0x1c09, 'TT_MS_LANGID_ENGLISH_JAMAICA' : 0x2009, 'TT_MS_LANGID_ENGLISH_CARIBBEAN' : 0x2409, 'TT_MS_LANGID_ENGLISH_BELIZE' : 0x2809, 'TT_MS_LANGID_ENGLISH_TRINIDAD' : 0x2c09, 'TT_MS_LANGID_ENGLISH_ZIMBABWE' : 0x3009, 'TT_MS_LANGID_ENGLISH_PHILIPPINES' : 0x3409, 'TT_MS_LANGID_ENGLISH_INDONESIA' : 0x3809, 'TT_MS_LANGID_ENGLISH_HONG_KONG' : 0x3c09, 'TT_MS_LANGID_ENGLISH_INDIA' : 0x4009, 'TT_MS_LANGID_ENGLISH_MALAYSIA' : 0x4409, 'TT_MS_LANGID_ENGLISH_SINGAPORE' : 0x4809, 'TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT' : 0x040a, 'TT_MS_LANGID_SPANISH_MEXICO' : 0x080a, 'TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT' : 0x0c0a, 'TT_MS_LANGID_SPANISH_GUATEMALA' : 0x100a, 'TT_MS_LANGID_SPANISH_COSTA_RICA' : 0x140a, 'TT_MS_LANGID_SPANISH_PANAMA' : 0x180a, 'TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC' : 0x1c0a, 'TT_MS_LANGID_SPANISH_VENEZUELA' : 0x200a, 'TT_MS_LANGID_SPANISH_COLOMBIA' : 0x240a, 'TT_MS_LANGID_SPANISH_PERU' : 0x280a, 'TT_MS_LANGID_SPANISH_ARGENTINA' : 0x2c0a, 'TT_MS_LANGID_SPANISH_ECUADOR' : 0x300a, 'TT_MS_LANGID_SPANISH_CHILE' : 0x340a, 'TT_MS_LANGID_SPANISH_URUGUAY' : 0x380a, 'TT_MS_LANGID_SPANISH_PARAGUAY' : 0x3c0a, 'TT_MS_LANGID_SPANISH_BOLIVIA' : 0x400a, 'TT_MS_LANGID_SPANISH_EL_SALVADOR' : 0x440a, 'TT_MS_LANGID_SPANISH_HONDURAS' : 0x480a, 'TT_MS_LANGID_SPANISH_NICARAGUA' : 0x4c0a, 'TT_MS_LANGID_SPANISH_PUERTO_RICO' : 0x500a, 'TT_MS_LANGID_SPANISH_UNITED_STATES' : 0x540a, 'TT_MS_LANGID_SPANISH_LATIN_AMERICA' : 0xE40a, 'TT_MS_LANGID_FINNISH_FINLAND' : 0x040b, 'TT_MS_LANGID_FRENCH_FRANCE' : 0x040c, 'TT_MS_LANGID_FRENCH_BELGIUM' : 0x080c, 'TT_MS_LANGID_FRENCH_CANADA' : 0x0c0c, 'TT_MS_LANGID_FRENCH_SWITZERLAND' : 0x100c, 'TT_MS_LANGID_FRENCH_LUXEMBOURG' : 0x140c, 'TT_MS_LANGID_FRENCH_MONACO' : 0x180c, 'TT_MS_LANGID_FRENCH_WEST_INDIES' : 0x1c0c, 'TT_MS_LANGID_FRENCH_REUNION' : 0x200c, 'TT_MS_LANGID_FRENCH_CONGO' : 0x240c, 'TT_MS_LANGID_FRENCH_SENEGAL' : 0x280c, 'TT_MS_LANGID_FRENCH_CAMEROON' : 0x2c0c, 'TT_MS_LANGID_FRENCH_COTE_D_IVOIRE' : 0x300c, 'TT_MS_LANGID_FRENCH_MALI' : 0x340c, 'TT_MS_LANGID_FRENCH_MOROCCO' : 0x380c, 'TT_MS_LANGID_FRENCH_HAITI' : 0x3c0c, 'TT_MS_LANGID_FRENCH_NORTH_AFRICA' : 0xE40c, 'TT_MS_LANGID_HEBREW_ISRAEL' : 0x040d, 'TT_MS_LANGID_HUNGARIAN_HUNGARY' : 0x040e, 'TT_MS_LANGID_ICELANDIC_ICELAND' : 0x040f, 'TT_MS_LANGID_ITALIAN_ITALY' : 0x0410, 'TT_MS_LANGID_ITALIAN_SWITZERLAND' : 0x0810, 'TT_MS_LANGID_JAPANESE_JAPAN' : 0x0411, 'TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA' : 0x0412, 'TT_MS_LANGID_KOREAN_JOHAB_KOREA' : 0x0812, 'TT_MS_LANGID_DUTCH_NETHERLANDS' : 0x0413, 'TT_MS_LANGID_DUTCH_BELGIUM' : 0x0813, 'TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL' : 0x0414, 'TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK' : 0x0814, 'TT_MS_LANGID_POLISH_POLAND' : 0x0415, 'TT_MS_LANGID_PORTUGUESE_BRAZIL' : 0x0416, 'TT_MS_LANGID_PORTUGUESE_PORTUGAL' : 0x0816, 'TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND' : 0x0417, 'TT_MS_LANGID_ROMANIAN_ROMANIA' : 0x0418, 'TT_MS_LANGID_MOLDAVIAN_MOLDAVIA' : 0x0818, 'TT_MS_LANGID_RUSSIAN_RUSSIA' : 0x0419, 'TT_MS_LANGID_RUSSIAN_MOLDAVIA' : 0x0819, 'TT_MS_LANGID_CROATIAN_CROATIA' : 0x041a, 'TT_MS_LANGID_SERBIAN_SERBIA_LATIN' : 0x081a, 'TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC' : 0x0c1a, 'TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA' : 0x101a, 'TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA' : 0x141a, 'TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN' : 0x181a, 'TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC' : 0x181a, 'TT_MS_LANGID_SLOVAK_SLOVAKIA' : 0x041b, 'TT_MS_LANGID_ALBANIAN_ALBANIA' : 0x041c, 'TT_MS_LANGID_SWEDISH_SWEDEN' : 0x041d, 'TT_MS_LANGID_SWEDISH_FINLAND' : 0x081d, 'TT_MS_LANGID_THAI_THAILAND' : 0x041e, 'TT_MS_LANGID_TURKISH_TURKEY' : 0x041f, 'TT_MS_LANGID_URDU_PAKISTAN' : 0x0420, 'TT_MS_LANGID_URDU_INDIA' : 0x0820, 'TT_MS_LANGID_INDONESIAN_INDONESIA' : 0x0421, 'TT_MS_LANGID_UKRAINIAN_UKRAINE' : 0x0422, 'TT_MS_LANGID_BELARUSIAN_BELARUS' : 0x0423, 'TT_MS_LANGID_SLOVENE_SLOVENIA' : 0x0424, 'TT_MS_LANGID_ESTONIAN_ESTONIA' : 0x0425, 'TT_MS_LANGID_LATVIAN_LATVIA' : 0x0426, 'TT_MS_LANGID_LITHUANIAN_LITHUANIA' : 0x0427, 'TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA' : 0x0827, 'TT_MS_LANGID_TAJIK_TAJIKISTAN' : 0x0428, 'TT_MS_LANGID_FARSI_IRAN' : 0x0429, 'TT_MS_LANGID_VIETNAMESE_VIET_NAM' : 0x042a, 'TT_MS_LANGID_ARMENIAN_ARMENIA' : 0x042b, 'TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN' : 0x042c, 'TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC' : 0x082c, 'TT_MS_LANGID_BASQUE_SPAIN' : 0x042d, 'TT_MS_LANGID_SORBIAN_GERMANY' : 0x042e, 'TT_MS_LANGID_MACEDONIAN_MACEDONIA' : 0x042f, 'TT_MS_LANGID_SUTU_SOUTH_AFRICA' : 0x0430, 'TT_MS_LANGID_TSONGA_SOUTH_AFRICA' : 0x0431, 'TT_MS_LANGID_TSWANA_SOUTH_AFRICA' : 0x0432, 'TT_MS_LANGID_VENDA_SOUTH_AFRICA' : 0x0433, 'TT_MS_LANGID_XHOSA_SOUTH_AFRICA' : 0x0434, 'TT_MS_LANGID_ZULU_SOUTH_AFRICA' : 0x0435, 'TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA' : 0x0436, 'TT_MS_LANGID_GEORGIAN_GEORGIA' : 0x0437, 'TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS' : 0x0438, 'TT_MS_LANGID_HINDI_INDIA' : 0x0439, 'TT_MS_LANGID_MALTESE_MALTA' : 0x043a, 'TT_MS_LANGID_SAMI_NORTHERN_NORWAY' : 0x043b, 'TT_MS_LANGID_SAMI_NORTHERN_SWEDEN' : 0x083b, 'TT_MS_LANGID_SAMI_NORTHERN_FINLAND' : 0x0C3b, 'TT_MS_LANGID_SAMI_LULE_NORWAY' : 0x103b, 'TT_MS_LANGID_SAMI_LULE_SWEDEN' : 0x143b, 'TT_MS_LANGID_SAMI_SOUTHERN_NORWAY' : 0x183b, 'TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN' : 0x1C3b, 'TT_MS_LANGID_SAMI_SKOLT_FINLAND' : 0x203b, 'TT_MS_LANGID_SAMI_INARI_FINLAND' : 0x243b, 'TT_MS_LANGID_SAAMI_LAPONIA' : 0x043b, 'TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM' : 0x083c, 'TT_MS_LANGID_IRISH_GAELIC_IRELAND' : 0x043c, 'TT_MS_LANGID_YIDDISH_GERMANY' : 0x043d, 'TT_MS_LANGID_MALAY_MALAYSIA' : 0x043e, 'TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM' : 0x083e, 'TT_MS_LANGID_KAZAK_KAZAKSTAN' : 0x043f, 'TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN' : 0x0440, 'TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC' : 0x0440, 'TT_MS_LANGID_SWAHILI_KENYA' : 0x0441, 'TT_MS_LANGID_TURKMEN_TURKMENISTAN' : 0x0442, 'TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN' : 0x0443, 'TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC' : 0x0843, 'TT_MS_LANGID_TATAR_TATARSTAN' : 0x0444, 'TT_MS_LANGID_BENGALI_INDIA' : 0x0445, 'TT_MS_LANGID_BENGALI_BANGLADESH' : 0x0845, 'TT_MS_LANGID_PUNJABI_INDIA' : 0x0446, 'TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN' : 0x0846, 'TT_MS_LANGID_GUJARATI_INDIA' : 0x0447, 'TT_MS_LANGID_ORIYA_INDIA' : 0x0448, 'TT_MS_LANGID_TAMIL_INDIA' : 0x0449, 'TT_MS_LANGID_TELUGU_INDIA' : 0x044a, 'TT_MS_LANGID_KANNADA_INDIA' : 0x044b, 'TT_MS_LANGID_MALAYALAM_INDIA' : 0x044c, 'TT_MS_LANGID_ASSAMESE_INDIA' : 0x044d, 'TT_MS_LANGID_MARATHI_INDIA' : 0x044e, 'TT_MS_LANGID_SANSKRIT_INDIA' : 0x044f, 'TT_MS_LANGID_MONGOLIAN_MONGOLIA' : 0x0450, 'TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN' : 0x0850, 'TT_MS_LANGID_TIBETAN_CHINA' : 0x0451, 'TT_MS_LANGID_DZONGHKA_BHUTAN' : 0x0851, 'TT_MS_LANGID_TIBETAN_BHUTAN' : 0x0851, 'TT_MS_LANGID_WELSH_WALES' : 0x0452, 'TT_MS_LANGID_KHMER_CAMBODIA' : 0x0453, 'TT_MS_LANGID_LAO_LAOS' : 0x0454, 'TT_MS_LANGID_BURMESE_MYANMAR' : 0x0455, 'TT_MS_LANGID_GALICIAN_SPAIN' : 0x0456, 'TT_MS_LANGID_KONKANI_INDIA' : 0x0457, 'TT_MS_LANGID_MANIPURI_INDIA' : 0x0458, 'TT_MS_LANGID_SINDHI_INDIA' : 0x0459, 'TT_MS_LANGID_SINDHI_PAKISTAN' : 0x0859, 'TT_MS_LANGID_SYRIAC_SYRIA' : 0x045a, 'TT_MS_LANGID_SINHALESE_SRI_LANKA' : 0x045b, 'TT_MS_LANGID_CHEROKEE_UNITED_STATES' : 0x045c, 'TT_MS_LANGID_INUKTITUT_CANADA' : 0x045d, 'TT_MS_LANGID_AMHARIC_ETHIOPIA' : 0x045e, 'TT_MS_LANGID_TAMAZIGHT_MOROCCO' : 0x045f, 'TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN' : 0x085f, 'TT_MS_LANGID_KASHMIRI_PAKISTAN' : 0x0460, 'TT_MS_LANGID_KASHMIRI_SASIA' : 0x0860, 'TT_MS_LANGID_KASHMIRI_INDIA' : 0x0860, 'TT_MS_LANGID_NEPALI_NEPAL' : 0x0461, 'TT_MS_LANGID_NEPALI_INDIA' : 0x0861, 'TT_MS_LANGID_FRISIAN_NETHERLANDS' : 0x0462, 'TT_MS_LANGID_PASHTO_AFGHANISTAN' : 0x0463, 'TT_MS_LANGID_FILIPINO_PHILIPPINES' : 0x0464, 'TT_MS_LANGID_DHIVEHI_MALDIVES' : 0x0465, 'TT_MS_LANGID_DIVEHI_MALDIVES' : 0x0465, 'TT_MS_LANGID_EDO_NIGERIA' : 0x0466, 'TT_MS_LANGID_FULFULDE_NIGERIA' : 0x0467, 'TT_MS_LANGID_HAUSA_NIGERIA' : 0x0468, 'TT_MS_LANGID_IBIBIO_NIGERIA' : 0x0469, 'TT_MS_LANGID_YORUBA_NIGERIA' : 0x046a, 'TT_MS_LANGID_QUECHUA_BOLIVIA' : 0x046b, 'TT_MS_LANGID_QUECHUA_ECUADOR' : 0x086b, 'TT_MS_LANGID_QUECHUA_PERU' : 0x0c6b, 'TT_MS_LANGID_SEPEDI_SOUTH_AFRICA' : 0x046c, 'TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA' : 0x046c, 'TT_MS_LANGID_IGBO_NIGERIA' : 0x0470, 'TT_MS_LANGID_KANURI_NIGERIA' : 0x0471, 'TT_MS_LANGID_OROMO_ETHIOPIA' : 0x0472, 'TT_MS_LANGID_TIGRIGNA_ETHIOPIA' : 0x0473, 'TT_MS_LANGID_TIGRIGNA_ERYTHREA' : 0x0873, 'TT_MS_LANGID_TIGRIGNA_ERYTREA' : 0x0873, 'TT_MS_LANGID_GUARANI_PARAGUAY' : 0x0474, 'TT_MS_LANGID_HAWAIIAN_UNITED_STATES' : 0x0475, 'TT_MS_LANGID_LATIN' : 0x0476, 'TT_MS_LANGID_SOMALI_SOMALIA' : 0x0477, 'TT_MS_LANGID_YI_CHINA' : 0x0478, 'TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES' : 0x0479, 'TT_MS_LANGID_UIGHUR_CHINA' : 0x0480, 'TT_MS_LANGID_MAORI_NEW_ZEALAND' : 0x0481 } globals().update(TT_MS_LANGIDS) freetype-py-2.5.1/freetype/ft_enums/ft_curve_tags.py0000664000175000017500000000310414664131406023043 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration type that lists the curve tags supported by FreeType 2. Each point of an outline has a specific tag which indicates whether it describes a point used to control a line segment or an arc. The tags can take the following values: FT_CURVE_TAG_ON Used when the point is ‘on’ the curve. This corresponds to start and end points of segments and arcs. The other tags specify what is called an ‘off’ point, i.e., a point which isn't located on the contour itself, but serves as a control point for a Bézier arc. FT_CURVE_TAG_CONIC Used for an ‘off’ point used to control a conic Bézier arc. FT_CURVE_TAG_CUBIC Used for an ‘off’ point used to control a cubic Bézier arc. FT_Curve_Tag_On, FT_Curve_Tag_Conic, FT_Curve_Tag_Cubic are their correspondning mixed-case aliases. Use the FT_CURVE_TAG(tag) macro to filter out other, internally used flags. """ FT_CURVE_TAGS = { 'FT_CURVE_TAG_ON' : 1, 'FT_CURVE_TAG_CONIC' : 0, 'FT_CURVE_TAG_CUBIC' : 2} globals().update(FT_CURVE_TAGS) FT_Curve_Tag_On = FT_CURVE_TAG_ON FT_Curve_Tag_Conic = FT_CURVE_TAG_CONIC FT_Curve_Tag_Cubic = FT_CURVE_TAG_CUBIC def FT_CURVE_TAG( flag ): return ( flag & 3 ) # FreeType itself does not have mixed-case macros FT_Curve_Tag = FT_CURVE_TAG freetype-py-2.5.1/freetype/ft_enums/__init__.py0000664000175000017500000001307214664131406021754 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Freetype enum types ------------------- FT_CURVE_TAGS: An enumeration type for each point on an outline to indicate whether it describes a point used to control a line segment or an arc. FT_PIXEL_MODES: An enumeration type used to describe the format of pixels in a given bitmap. Note that additional formats may be added in the future. FT_GLYPH_BBOX_MODES: The mode how the values of FT_Glyph_Get_CBox are returned. FT_GLYPH_FORMATS: An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format. FT_ENCODINGS: An enumeration used to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function. FT_RENDER_MODES: An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. FT_LOAD_TARGETS: A list of values that are used to select a specific hinting algorithm to use by the hinter. You should OR one of these values to your 'load_flags' when calling FT_Load_Glyph. FT_LOAD_FLAGS: A list of bit-field constants used with FT_Load_Glyph to indicate what kind of operations to perform during glyph loading. FT_STYLE_FLAGS: A list of bit-flags used to indicate the style of a given face. These are used in the 'style_flags' field of FT_FaceRec. FT_FSTYPES: A list of bit flags that inform client applications of embedding and subsetting restrictions associated with a font. FT_FACE_FLAGS: A list of bit flags used in the 'face_flags' field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face. FT_OUTLINE_FLAGS: A list of bit-field constants use for the flags in an outline's 'flags' field. FT_OPEN_MODES: A list of bit-field constants used within the 'flags' field of the FT_Open_Args structure. FT_KERNING_MODES: An enumeration used to specify which kerning values to return in FT_Get_Kerning. FT_STROKER_LINEJOINS: These values determine how two joining lines are rendered in a stroker. FT_STROKER_LINECAPS: These values determine how the end of opened sub-paths are rendered in a stroke. FT_STROKER_BORDERS: These values are used to select a given stroke border in FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder. FT_LCD_FILTERS: A list of values to identify various types of LCD filters. TT_PLATFORMS: A list of valid values for the 'platform_id' identifier code in FT_CharMapRec and FT_SfntName structures. TT_APPLE_IDS: A list of valid values for the 'encoding_id' for TT_PLATFORM_APPLE_UNICODE charmaps and name entries. TT_MAC_IDS: A list of valid values for the 'encoding_id' for TT_PLATFORM_MACINTOSH charmaps and name entries. TT_MS_IDS: A list of valid values for the 'encoding_id' for TT_PLATFORM_MICROSOFT charmaps and name entries. TT_ADOBE_IDS: A list of valid values for the 'encoding_id' for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! TT_MAC_LANGIDS: Possible values of the language identifier field in the name records of the TTF `name' table if the `platform' identifier code is TT_PLATFORM_MACINTOSH. TT_MS_LANGIDS: Possible values of the language identifier field in the name records of the TTF `name' table if the `platform' identifier code is TT_PLATFORM_MICROSOFT. TT_NAME_IDS: Possible values of the `name' identifier field in the name records of the TTF `name' table. These values are platform independent. ''' from freetype.ft_enums.ft_color_root_transform import * from freetype.ft_enums.ft_curve_tags import * from freetype.ft_enums.ft_fstypes import * from freetype.ft_enums.ft_face_flags import * from freetype.ft_enums.ft_encodings import * from freetype.ft_enums.ft_glyph_bbox_modes import * from freetype.ft_enums.ft_glyph_formats import * from freetype.ft_enums.ft_kerning_modes import * from freetype.ft_enums.ft_lcd_filters import * from freetype.ft_enums.ft_load_flags import * from freetype.ft_enums.ft_load_targets import * from freetype.ft_enums.ft_open_modes import * from freetype.ft_enums.ft_outline_flags import * from freetype.ft_enums.ft_pixel_modes import * from freetype.ft_enums.ft_render_modes import * from freetype.ft_enums.ft_stroker_borders import * from freetype.ft_enums.ft_stroker_linecaps import * from freetype.ft_enums.ft_stroker_linejoins import * from freetype.ft_enums.ft_style_flags import * from freetype.ft_enums.tt_adobe_ids import * from freetype.ft_enums.tt_apple_ids import * from freetype.ft_enums.tt_mac_ids import * from freetype.ft_enums.tt_ms_ids import * from freetype.ft_enums.tt_ms_langids import * from freetype.ft_enums.tt_mac_langids import * from freetype.ft_enums.tt_name_ids import * from freetype.ft_enums.tt_platforms import * freetype-py-2.5.1/freetype/ft_enums/ft_lcd_filters.py0000664000175000017500000000305214664131406023175 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of values to identify various types of LCD filters. FT_LCD_FILTER_NONE Do not perform filtering. When used with subpixel rendering, this results in sometimes severe color fringes. FT_LCD_FILTER_DEFAULT The default filter reduces color fringes considerably, at the cost of a slight blurriness in the output. FT_LCD_FILTER_LIGHT The light filter is a variant that produces less blurriness at the cost of slightly more color fringes than the default one. It might be better, depending on taste, your monitor, or your personal vision. FT_LCD_FILTER_LEGACY This filter corresponds to the original libXft color filter. It provides high contrast output but can exhibit really bad color fringes if glyphs are not extremely well hinted to the pixel grid. In other words, it only works well if the TrueType bytecode interpreter is enabled and high-quality hinted fonts are used. This filter is only provided for comparison purposes, and might be disabled or stay unsupported in the future. """ FT_LCD_FILTERS = {'FT_LCD_FILTER_NONE' : 0, 'FT_LCD_FILTER_DEFAULT' : 1, 'FT_LCD_FILTER_LIGHT' : 2, 'FT_LCD_FILTER_LEGACY' : 16} globals().update(FT_LCD_FILTERS) freetype-py-2.5.1/freetype/ft_enums/ft_glyph_bbox_modes.py0000664000175000017500000000175114664131406024233 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ The mode how the values of FT_Glyph_Get_CBox are returned. FT_GLYPH_BBOX_UNSCALED Return unscaled font units. FT_GLYPH_BBOX_SUBPIXELS Return unfitted 26.6 coordinates. FT_GLYPH_BBOX_GRIDFIT Return grid-fitted 26.6 coordinates. FT_GLYPH_BBOX_TRUNCATE Return coordinates in integer pixels. FT_GLYPH_BBOX_PIXELS Return grid-fitted pixel coordinates. """ FT_GLYPH_BBOX_MODES = {'FT_GLYPH_BBOX_UNSCALED' : 0, 'FT_GLYPH_BBOX_SUBPIXELS' : 0, 'FT_GLYPH_BBOX_GRIDFIT' : 1, 'FT_GLYPH_BBOX_TRUNCATE' : 2, 'FT_GLYPH_BBOX_PIXELS' : 3} globals().update(FT_GLYPH_BBOX_MODES) freetype-py-2.5.1/freetype/ft_enums/ft_stroker_linejoins.py0000664000175000017500000000210414664131406024443 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ These values determine how two joining lines are rendered in a stroker. FT_STROKER_LINEJOIN_ROUND Used to render rounded line joins. Circular arcs are used to join two lines smoothly. FT_STROKER_LINEJOIN_BEVEL Used to render beveled line joins; i.e., the two joining lines are extended until they intersect. FT_STROKER_LINEJOIN_MITER Same as beveled rendering, except that an additional line break is added if the angle between the two joining lines is too closed (this is useful to avoid unpleasant spikes in beveled rendering). """ FT_STROKER_LINEJOINS = { 'FT_STROKER_LINEJOIN_ROUND' : 0, 'FT_STROKER_LINEJOIN_BEVEL' : 1, 'FT_STROKER_LINEJOIN_MITER' : 2} globals().update(FT_STROKER_LINEJOINS) freetype-py-2.5.1/freetype/ft_enums/ft_glyph_formats.py0000664000175000017500000000467614664131406023576 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format. FT_GLYPH_FORMAT_NONE The value 0 is reserved. FT_GLYPH_FORMAT_COMPOSITE The glyph image is a composite of several other images. This format is only used with FT_LOAD_NO_RECURSE, and is used to report compound glyphs (like accented characters). FT_GLYPH_FORMAT_BITMAP The glyph image is a bitmap, and can be described as an FT_Bitmap. You generally need to access the 'bitmap' field of the FT_GlyphSlotRec structure to read it. FT_GLYPH_FORMAT_OUTLINE The glyph image is a vectorial outline made of line segments and Bezier arcs; it can be described as an FT_Outline; you generally want to access the 'outline' field of the FT_GlyphSlotRec structure to read it. FT_GLYPH_FORMAT_PLOTTER The glyph image is a vectorial path with no inside and outside contours. Some Type 1 fonts, like those in the Hershey family, contain glyphs in this format. These are described as FT_Outline, but FreeType isn't currently capable of rendering them correctly. FT_GLYPH_FORMAT_SVG [Since 2.12] The glyph is represented by an SVG document in the 'SVG~' table. """ def _FT_IMAGE_TAG(a,b,c,d): return ( ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d) ) FT_GLYPH_FORMATS = { 'FT_GLYPH_FORMAT_NONE' : _FT_IMAGE_TAG( '\0','\0','\0','\0' ), 'FT_GLYPH_FORMAT_COMPOSITE' : _FT_IMAGE_TAG( 'c','o','m','p' ), 'FT_GLYPH_FORMAT_BITMAP' : _FT_IMAGE_TAG( 'b','i','t','s' ), 'FT_GLYPH_FORMAT_OUTLINE' : _FT_IMAGE_TAG( 'o','u','t','l' ), 'FT_GLYPH_FORMAT_PLOTTER' : _FT_IMAGE_TAG( 'p','l','o','t' ), 'FT_GLYPH_FORMAT_SVG' : _FT_IMAGE_TAG( 'S','V','G',' ' )} globals().update(FT_GLYPH_FORMATS) ft_glyph_format_none = FT_GLYPH_FORMAT_NONE ft_glyph_format_composite = FT_GLYPH_FORMAT_COMPOSITE ft_glyph_format_bitmap = FT_GLYPH_FORMAT_BITMAP ft_glyph_format_outline = FT_GLYPH_FORMAT_OUTLINE ft_glyph_format_plotter = FT_GLYPH_FORMAT_PLOTTER ft_glyph_format_svg = FT_GLYPH_FORMAT_SVG freetype-py-2.5.1/freetype/ft_enums/ft_outline_flags.py0000664000175000017500000000557014664131406023545 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit-field constants use for the flags in an outline's 'flags' field. FT_OUTLINE_NONE Value 0 is reserved. FT_OUTLINE_OWNER If set, this flag indicates that the outline's field arrays (i.e., 'points', 'flags', and 'contours') are 'owned' by the outline object, and should thus be freed when it is destroyed. FT_OUTLINE_EVEN_ODD_FILL By default, outlines are filled using the non-zero winding rule. If set to 1, the outline will be filled using the even-odd fill rule (only works with the smooth rasterizer). FT_OUTLINE_REVERSE_FILL By default, outside contours of an outline are oriented in clock-wise direction, as defined in the TrueType specification. This flag is set if the outline uses the opposite direction (typically for Type 1 fonts). This flag is ignored by the scan converter. FT_OUTLINE_IGNORE_DROPOUTS By default, the scan converter will try to detect drop-outs in an outline and correct the glyph bitmap to ensure consistent shape continuity. If set, this flag hints the scan-line converter to ignore such cases. See below for more information. FT_OUTLINE_SMART_DROPOUTS Select smart dropout control. If unset, use simple dropout control. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. FT_OUTLINE_INCLUDE_STUBS If set, turn pixels on for 'stubs', otherwise exclude them. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. FT_OUTLINE_HIGH_PRECISION This flag indicates that the scan-line converter should try to convert this outline to bitmaps with the highest possible quality. It is typically set for small character sizes. Note that this is only a hint that might be completely ignored by a given scan-converter. FT_OUTLINE_SINGLE_PASS This flag is set to force a given scan-converter to only use a single pass over the outline to render a bitmap glyph image. Normally, it is set for very large character sizes. It is only a hint that might be completely ignored by a given scan-converter. """ FT_OUTLINE_FLAGS = { 'FT_OUTLINE_NONE' : 0x0, 'FT_OUTLINE_OWNER' : 0x1, 'FT_OUTLINE_EVEN_ODD_FILL' : 0x2, 'FT_OUTLINE_REVERSE_FILL' : 0x4, 'FT_OUTLINE_IGNORE_DROPOUTS' : 0x8, 'FT_OUTLINE_SMART_DROPOUTS' : 0x10, 'FT_OUTLINE_INCLUDE_STUBS' : 0x20, 'FT_OUTLINE_HIGH_PRECISION' : 0x100, 'FT_OUTLINE_SINGLE_PASS' : 0x200 } globals().update(FT_OUTLINE_FLAGS) freetype-py-2.5.1/freetype/ft_enums/ft_load_flags.py0000664000175000017500000001511414664131406023000 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit-field constants used with FT_Load_Glyph to indicate what kind of operations to perform during glyph loading. FT_LOAD_DEFAULT Corresponding to 0, this value is used as the default glyph load operation. In this case, the following happens: 1. FreeType looks for a bitmap for the glyph corresponding to the face's current size. If one is found, the function returns. The bitmap data can be accessed from the glyph slot (see note below). 2. If no embedded bitmap is searched or found, FreeType looks for a scalable outline. If one is found, it is loaded from the font file, scaled to device pixels, then 'hinted' to the pixel grid in order to optimize it. The outline data can be accessed from the glyph slot (see note below). Note that by default, the glyph loader doesn't render outlines into bitmaps. The following flags are used to modify this default behaviour to more specific and useful cases. FT_LOAD_NO_SCALE Don't scale the outline glyph loaded, but keep it in font units. This flag implies FT_LOAD_NO_HINTING and FT_LOAD_NO_BITMAP, and unsets FT_LOAD_RENDER. FT_LOAD_NO_HINTING Disable hinting. This generally generates 'blurrier' bitmap glyph when the glyph is rendered in any of the anti-aliased modes. See also the note below. This flag is implied by FT_LOAD_NO_SCALE. FT_LOAD_RENDER Call FT_Render_Glyph after the glyph is loaded. By default, the glyph is rendered in FT_RENDER_MODE_NORMAL mode. This can be overridden by FT_LOAD_TARGET_XXX or FT_LOAD_MONOCHROME. This flag is unset by FT_LOAD_NO_SCALE. FT_LOAD_NO_BITMAP Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag. FT_LOAD_NO_SCALE always sets this flag. FT_LOAD_VERTICAL_LAYOUT Load the glyph for vertical text layout. Don't use it as it is problematic currently. FT_LOAD_FORCE_AUTOHINT Indicates that the auto-hinter is preferred over the font's native hinter. See also the note below. FT_LOAD_CROP_BITMAP Indicates that the font driver should crop the loaded bitmap glyph (i.e., remove all space around its black bits). Not all drivers implement this. FT_LOAD_PEDANTIC Indicates that the font driver should perform pedantic verifications during glyph loading. This is mostly used to detect broken glyphs in fonts. By default, FreeType tries to handle broken fonts also. FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH Indicates that the font driver should ignore the global advance width defined in the font. By default, that value is used as the advance width for all glyphs when the face has FT_FACE_FLAG_FIXED_WIDTH set. This flag exists for historical reasons (to support buggy CJK fonts). FT_LOAD_NO_RECURSE This flag is only used internally. It merely indicates that the font driver should not load composite glyphs recursively. Instead, it should set the 'num_subglyph' and 'subglyphs' values of the glyph slot accordingly, and set 'glyph->format' to FT_GLYPH_FORMAT_COMPOSITE. The description of sub-glyphs is not available to client applications for now. This flag implies FT_LOAD_NO_SCALE and FT_LOAD_IGNORE_TRANSFORM. FT_LOAD_IGNORE_TRANSFORM Indicates that the transform matrix set by FT_Set_Transform should be ignored. FT_LOAD_MONOCHROME This flag is used with FT_LOAD_RENDER to indicate that you want to render an outline glyph to a 1-bit monochrome bitmap glyph, with 8 pixels packed into each byte of the bitmap data. Note that this has no effect on the hinting algorithm used. You should rather use FT_LOAD_TARGET_MONO so that the monochrome-optimized hinting algorithm is used. FT_LOAD_LINEAR_DESIGN Indicates that the 'linearHoriAdvance' and 'linearVertAdvance' fields of FT_GlyphSlotRec should be kept in font units. See FT_GlyphSlotRec for details. FT_LOAD_NO_AUTOHINT Disable auto-hinter. See also the note below. FT_LOAD_COLOR This flag is used to request loading of color embedded-bitmap images. The resulting color bitmaps, if available, will have the FT_PIXEL_MODE_BGRA format. When the flag is not used and color bitmaps are found, they will be converted to 256-level gray bitmaps transparently. Those bitmaps will be in the FT_PIXEL_MODE_GRAY format. FT_LOAD_NO_SVG [Since 2.13.1] Ignore SVG glyph data when loading. FT_LOAD_COMPUTE_METRICS Compute glyph metrics from the glyph data, without the use of bundled metrics tables (for example, the `hdmx' table in TrueType fonts). This flag is mainly used by font validating or font editing applications, which need to ignore, verify, or edit those tables. Currently, this flag is only implemented for TrueType fonts. FT_LOAD_BITMAP_METRICS_ONLY Request loading of the metrics and bitmap image information of a (possibly embedded) bitmap glyph without allocating or copying the bitmap image data itself. No effect if the target glyph is not a bitmap image. This flag unsets FT_LOAD_RENDER. """ FT_LOAD_FLAGS = { 'FT_LOAD_DEFAULT' : 0x0, 'FT_LOAD_NO_SCALE' : 0x1, 'FT_LOAD_NO_HINTING' : 0x2, 'FT_LOAD_RENDER' : 0x4, 'FT_LOAD_NO_BITMAP' : 0x8, 'FT_LOAD_VERTICAL_LAYOUT' : 0x10, 'FT_LOAD_FORCE_AUTOHINT' : 0x20, 'FT_LOAD_CROP_BITMAP' : 0x40, 'FT_LOAD_PEDANTIC' : 0x80, 'FT_LOAD_ADVANCE_ONLY' : 0x100, 'FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH' : 0x200, 'FT_LOAD_NO_RECURSE' : 0x400, 'FT_LOAD_IGNORE_TRANSFORM' : 0x800, 'FT_LOAD_MONOCHROME' : 0x1000, 'FT_LOAD_LINEAR_DESIGN' : 0x2000, 'FT_LOAD_SBITS_ONLY' : 0x4000, 'FT_LOAD_NO_AUTOHINT' : 0x8000, 'FT_LOAD_COLOR' : 0x100000, 'FT_LOAD_COMPUTE_METRICS' : 0x200000, 'FT_LOAD_BITMAP_METRICS_ONLY' : 0x400000, 'FT_LOAD_NO_SVG' : 0x800000 } globals().update(FT_LOAD_FLAGS) freetype-py-2.5.1/freetype/ft_enums/ft_open_modes.py0000664000175000017500000000166314664131406023041 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit-field constants used within the 'flags' field of the FT_Open_Args structure. FT_OPEN_MEMORY This is a memory-based stream. FT_OPEN_STREAM Copy the stream from the 'stream' field. FT_OPEN_PATHNAME Create a new input stream from a C path name. FT_OPEN_DRIVER Use the 'driver' field. FT_OPEN_PARAMS Use the 'num_params' and 'params' fields. """ FT_OPEN_MODES = {'FT_OPEN_MEMORY': 0x1, 'FT_OPEN_STREAM': 0x2, 'FT_OPEN_PATHNAME': 0x4, 'FT_OPEN_DRIVER': 0x8, 'FT_OPEN_PARAMS': 0x10 } globals().update(FT_OPEN_MODES) freetype-py-2.5.1/freetype/ft_enums/tt_ms_ids.py0000664000175000017500000000307514664131406022204 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of valid values for the 'encoding_id' for TT_PLATFORM_MICROSOFT charmaps and name entries. TT_MS_ID_SYMBOL_CS Corresponds to Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL. TT_MS_ID_UNICODE_CS Corresponds to a Microsoft WGL4 charmap, matching Unicode. See FT_ENCODING_UNICODE. TT_MS_ID_SJIS Corresponds to SJIS Japanese encoding. See FT_ENCODING_SJIS. TT_MS_ID_PRC Chinese encodings as used in the People's Republic of China (PRC). This means the encodings GB~2312 and its supersets GBK and GB~18030. See FT_ENCODING_PRC. TT_MS_ID_BIG_5 Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. See FT_ENCODING_BIG5. TT_MS_ID_WANSUNG Corresponds to Korean Wansung encoding. See FT_ENCODING_WANSUNG. TT_MS_ID_JOHAB Corresponds to Johab encoding. See FT_ENCODING_JOHAB. TT_MS_ID_UCS_4 Corresponds to UCS-4 or UTF-32 charmaps. This has been added to the OpenType specification version 1.4 (mid-2001.) """ TT_MS_IDS = { 'TT_MS_ID_SYMBOL_CS' : 0, 'TT_MS_ID_UNICODE_CS' : 1, 'TT_MS_ID_SJIS' : 2, 'TT_MS_ID_PRC' : 3, 'TT_MS_ID_BIG_5' : 4, 'TT_MS_ID_WANSUNG' : 5, 'TT_MS_ID_JOHAB' : 6, 'TT_MS_ID_UCS_4' : 10 } globals().update(TT_MS_IDS) freetype-py-2.5.1/freetype/ft_enums/ft_render_modes.py0000664000175000017500000000460614664131406023357 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. For bitmap fonts and embedded bitmaps the 'bitmap->pixel_mode' field in the FT_GlyphSlotRec structure gives the format of the returned bitmap. All modes except FT_RENDER_MODE_MONO use 256 levels of opacity. FT_RENDER_MODE_NORMAL This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps. FT_RENDER_MODE_LIGHT This is equivalent to FT_RENDER_MODE_NORMAL. It is only defined as a separate value because render modes are also used indirectly to define hinting algorithm selectors. See FT_LOAD_TARGET_XXX for details. FT_RENDER_MODE_MONO This mode corresponds to 1-bit bitmaps (with 2 levels of opacity). FT_RENDER_MODE_LCD This mode corresponds to horizontal RGB and BGR sub-pixel displays like LCD screens. It produces 8-bit bitmaps that are 3 times the width of the original glyph outline in pixels, and which use the FT_PIXEL_MODE_LCD mode. FT_RENDER_MODE_LCD_V This mode corresponds to vertical RGB and BGR sub-pixel displays (like PDA screens, rotated LCD displays, etc.). It produces 8-bit bitmaps that are 3 times the height of the original glyph outline in pixels and use the FT_PIXEL_MODE_LCD_V mode. FT_RENDER_MODE_SDF This mode corresponds to 8-bit, single-channel signed distance field (SDF) bitmaps. Each pixel in the SDF grid is the value from the pixel's position to the nearest glyph's outline. The distances are calculated from the center of the pixel and are positive if they are filled by the outline (i.e., inside the outline) and negative otherwise. Check the note below on how to convert the output values to usable data. """ FT_RENDER_MODES = { 'FT_RENDER_MODE_NORMAL' : 0, 'FT_RENDER_MODE_LIGHT' : 1, 'FT_RENDER_MODE_MONO' : 2, 'FT_RENDER_MODE_LCD' : 3, 'FT_RENDER_MODE_LCD_V' : 4, 'FT_RENDER_MODE_SDF' : 5 } globals().update(FT_RENDER_MODES) freetype-py-2.5.1/freetype/ft_enums/ft_stroker_borders.py0000664000175000017500000000215314664131406024115 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ These values are used to select a given stroke border in FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder. FT_STROKER_BORDER_LEFT Select the left border, relative to the drawing direction. FT_STROKER_BORDER_RIGHT Select the right border, relative to the drawing direction. Note Applications are generally interested in the 'inside' and 'outside' borders. However, there is no direct mapping between these and the 'left' and 'right' ones, since this really depends on the glyph's drawing orientation, which varies between font formats. You can however use FT_Outline_GetInsideBorder and FT_Outline_GetOutsideBorder to get these. """ FT_STROKER_BORDERS = { 'FT_STROKER_BORDER_LEFT' : 0, 'FT_STROKER_BORDER_RIGHT' : 1} globals().update(FT_STROKER_BORDERS) freetype-py-2.5.1/freetype/ft_enums/tt_adobe_ids.py0000664000175000017500000000145514664131406022637 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of valid values for the 'encoding_id' for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! TT_ADOBE_ID_STANDARD Adobe standard encoding. TT_ADOBE_ID_EXPERT Adobe expert encoding. TT_ADOBE_ID_CUSTOM Adobe custom encoding. TT_ADOBE_ID_LATIN_1 Adobe Latin 1 encoding. """ TT_ADOBE_IDS = { 'TT_ADOBE_ID_STANDARD' : 0, 'TT_ADOBE_ID_EXPERT' : 1, 'TT_ADOBE_ID_CUSTOM' : 2, 'TT_ADOBE_ID_LATIN_1' : 3 } globals().update(TT_ADOBE_IDS) freetype-py-2.5.1/freetype/ft_enums/tt_mac_ids.py0000664000175000017500000000500414664131406022317 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of valid values for the 'encoding_id' for TT_PLATFORM_MACINTOSH charmaps and name entries. TT_MAC_ID_ROMAN TT_MAC_ID_TELUGU TT_MAC_ID_GURMUKHI TT_MAC_ID_TIBETAN TT_MAC_ID_SIMPLIFIED_CHINESE TT_MAC_ID_SINDHI TT_MAC_ID_SINHALESE TT_MAC_ID_RUSSIAN TT_MAC_ID_KANNADA TT_MAC_ID_VIETNAMESE TT_MAC_ID_MONGOLIAN TT_MAC_ID_DEVANAGARI TT_MAC_ID_HEBREW TT_MAC_ID_TAMIL TT_MAC_ID_THAI TT_MAC_ID_BURMESE TT_MAC_ID_MALDIVIAN TT_MAC_ID_TRADITIONAL_CHINESE TT_MAC_ID_JAPANESE TT_MAC_ID_GREEK TT_MAC_ID_LAOTIAN TT_MAC_ID_KHMER TT_MAC_ID_UNINTERP TT_MAC_ID_ORIYA TT_MAC_ID_RSYMBOL TT_MAC_ID_MALAYALAM TT_MAC_ID_GEEZ TT_MAC_ID_KOREAN TT_MAC_ID_GUJARATI TT_MAC_ID_BENGALI TT_MAC_ID_ARABIC TT_MAC_ID_GEORGIAN TT_MAC_ID_ARMENIAN TT_MAC_ID_SLAVIC """ TT_MAC_IDS = { 'TT_MAC_ID_ROMAN' : 0, 'TT_MAC_ID_JAPANESE' : 1, 'TT_MAC_ID_TRADITIONAL_CHINESE' : 2, 'TT_MAC_ID_KOREAN' : 3, 'TT_MAC_ID_ARABIC' : 4, 'TT_MAC_ID_HEBREW' : 5, 'TT_MAC_ID_GREEK' : 6, 'TT_MAC_ID_RUSSIAN' : 7, 'TT_MAC_ID_RSYMBOL' : 8, 'TT_MAC_ID_DEVANAGARI' : 9, 'TT_MAC_ID_GURMUKHI' : 10, 'TT_MAC_ID_GUJARATI' : 11, 'TT_MAC_ID_ORIYA' : 12, 'TT_MAC_ID_BENGALI' : 13, 'TT_MAC_ID_TAMIL' : 14, 'TT_MAC_ID_TELUGU' : 15, 'TT_MAC_ID_KANNADA' : 16, 'TT_MAC_ID_MALAYALAM' : 17, 'TT_MAC_ID_SINHALESE' : 18, 'TT_MAC_ID_BURMESE' : 19, 'TT_MAC_ID_KHMER' : 20, 'TT_MAC_ID_THAI' : 21, 'TT_MAC_ID_LAOTIAN' : 22, 'TT_MAC_ID_GEORGIAN' : 23, 'TT_MAC_ID_ARMENIAN' : 24, 'TT_MAC_ID_MALDIVIAN' : 25, 'TT_MAC_ID_SIMPLIFIED_CHINESE' : 25, 'TT_MAC_ID_TIBETAN' : 26, 'TT_MAC_ID_MONGOLIAN' : 27, 'TT_MAC_ID_GEEZ' : 28, 'TT_MAC_ID_SLAVIC' : 29, 'TT_MAC_ID_VIETNAMESE' : 30, 'TT_MAC_ID_SINDHI' : 31, 'TT_MAC_ID_UNINTERP' : 32} globals().update(TT_MAC_IDS) freetype-py-2.5.1/freetype/ft_enums/ft_face_flags.py0000664000175000017500000001136614664131406022764 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit flags used in the 'face_flags' field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face. FT_FACE_FLAG_SCALABLE Indicates that the face contains outline glyphs. This doesn't prevent bitmap strikes, i.e., a face can have both this and and FT_FACE_FLAG_FIXED_SIZES set. FT_FACE_FLAG_FIXED_SIZES Indicates that the face contains bitmap strikes. See also the 'num_fixed_sizes' and 'available_sizes' fields of FT_FaceRec. FT_FACE_FLAG_FIXED_WIDTH Indicates that the face contains fixed-width characters (like Courier, Lucido, MonoType, etc.). FT_FACE_FLAG_SFNT Indicates that the face uses the 'sfnt' storage scheme. For now, this means TrueType and OpenType. FT_FACE_FLAG_HORIZONTAL Indicates that the face contains horizontal glyph metrics. This should be set for all common formats. FT_FACE_FLAG_VERTICAL Indicates that the face contains vertical glyph metrics. This is only available in some formats, not all of them. FT_FACE_FLAG_KERNING Indicates that the face contains kerning information. If set, the kerning distance can be retrieved through the function FT_Get_Kerning. Otherwise the function always return the vector (0,0). Note that FreeType doesn't handle kerning data from the 'GPOS' table (as present in some OpenType fonts). FT_FACE_FLAG_MULTIPLE_MASTERS Indicates that the font contains multiple masters and is capable of interpolating between them. See the multiple-masters specific API for details. FT_FACE_FLAG_GLYPH_NAMES Indicates that the font contains glyph names that can be retrieved through FT_Get_Glyph_Name. Note that some TrueType fonts contain broken glyph name tables. Use the function FT_Has_PS_Glyph_Names when needed. FT_FACE_FLAG_EXTERNAL_STREAM Used internally by FreeType to indicate that a face's stream was provided by the client application and should not be destroyed when FT_Done_Face is called. Don't read or test this flag. FT_FACE_FLAG_HINTER Set if the font driver has a hinting machine of its own. For example, with TrueType fonts, it makes sense to use data from the SFNT 'gasp' table only if the native TrueType hinting engine (with the bytecode interpreter) is available and active. FT_FACE_FLAG_CID_KEYED Set if the font is CID-keyed. In that case, the font is not accessed by glyph indices but by CID values. For subsetted CID-keyed fonts this has the consequence that not all index values are a valid argument to FT_Load_Glyph. Only the CID values for which corresponding glyphs in the subsetted font exist make FT_Load_Glyph return successfully; in all other cases you get an 'FT_Err_Invalid_Argument' error. Note that CID-keyed fonts which are in an SFNT wrapper don't have this flag set since the glyphs are accessed in the normal way (using contiguous indices); the 'CID-ness' isn't visible to the application. FT_FACE_FLAG_TRICKY Set if the font is 'tricky', this is, it always needs the font format's native hinting engine to get a reasonable result. A typical example is the Chinese font 'mingli.ttf' which uses TrueType bytecode instructions to move and scale all of its subglyphs. It is not possible to autohint such fonts using FT_LOAD_FORCE_AUTOHINT; it will also ignore FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT to really disable hinting; however, you probably never want this except for demonstration purposes. Currently, there are six TrueType fonts in the list of tricky fonts; they are hard-coded in file 'ttobjs.c'. """ FT_FACE_FLAGS = { 'FT_FACE_FLAG_SCALABLE' : 1 << 0, 'FT_FACE_FLAG_FIXED_SIZES' : 1 << 1, 'FT_FACE_FLAG_FIXED_WIDTH' : 1 << 2, 'FT_FACE_FLAG_SFNT' : 1 << 3, 'FT_FACE_FLAG_HORIZONTAL' : 1 << 4, 'FT_FACE_FLAG_VERTICAL' : 1 << 5, 'FT_FACE_FLAG_KERNING' : 1 << 6, 'FT_FACE_FLAG_FAST_GLYPHS' : 1 << 7, 'FT_FACE_FLAG_MULTIPLE_MASTERS' : 1 << 8, 'FT_FACE_FLAG_GLYPH_NAMES' : 1 << 9, 'FT_FACE_FLAG_EXTERNAL_STREAM' : 1 << 10, 'FT_FACE_FLAG_HINTER' : 1 << 11, 'FT_FACE_FLAG_CID_KEYED' : 1 << 12, 'FT_FACE_FLAG_TRICKY' : 1 << 13 } globals().update(FT_FACE_FLAGS) freetype-py-2.5.1/freetype/ft_enums/tt_mac_langids.py0000664000175000017500000002333014664131406023163 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ Possible values of the language identifier field in the name records of the TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MACINTOSH. TT_MAC_LANGID_LATIN TT_MAC_LANGID_MALAY_ARABIC_SCRIPT TT_MAC_LANGID_HINDI TT_MAC_LANGID_CATALAN TT_MAC_LANGID_MARATHI TT_MAC_LANGID_ICELANDIC TT_MAC_LANGID_ARABIC TT_MAC_LANGID_SWAHILI TT_MAC_LANGID_KHMER TT_MAC_LANGID_UKRAINIAN TT_MAC_LANGID_FINNISH TT_MAC_LANGID_POLISH TT_MAC_LANGID_NEPALI TT_MAC_LANGID_UZBEK TT_MAC_LANGID_TELUGU TT_MAC_LANGID_MALTESE TT_MAC_LANGID_AFRIKAANS TT_MAC_LANGID_CHEWA TT_MAC_LANGID_BASQUE TT_MAC_LANGID_CZECH TT_MAC_LANGID_ROMANIAN TT_MAC_LANGID_QUECHUA TT_MAC_LANGID_TAGALOG TT_MAC_LANGID_HUNGARIAN TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT TT_MAC_LANGID_TONGAN TT_MAC_LANGID_SUNDANESE TT_MAC_LANGID_JAPANESE TT_MAC_LANGID_MONGOLIAN TT_MAC_LANGID_ALBANIAN TT_MAC_LANGID_NORWEGIAN TT_MAC_LANGID_SLOVAK TT_MAC_LANGID_MALAGASY TT_MAC_LANGID_DZONGKHA TT_MAC_LANGID_DUTCH TT_MAC_LANGID_MALAY_ROMAN_SCRIPT TT_MAC_LANGID_SERBIAN TT_MAC_LANGID_GERMAN TT_MAC_LANGID_SOMALI TT_MAC_LANGID_KOREAN TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT TT_MAC_LANGID_CROATIAN TT_MAC_LANGID_TURKISH TT_MAC_LANGID_MOLDAVIAN TT_MAC_LANGID_LAO TT_MAC_LANGID_ORIYA TT_MAC_LANGID_BRETON TT_MAC_LANGID_PASHTO TT_MAC_LANGID_GUARANI TT_MAC_LANGID_HEBREW TT_MAC_LANGID_SLOVENIAN TT_MAC_LANGID_ESTONIAN TT_MAC_LANGID_RUNDI TT_MAC_LANGID_URDU TT_MAC_LANGID_CHINESE_TRADITIONAL TT_MAC_LANGID_TATAR TT_MAC_LANGID_CHINESE_SIMPLIFIED TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT TT_MAC_LANGID_SANSKRIT TT_MAC_LANGID_KURDISH TT_MAC_LANGID_FAEROESE TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT TT_MAC_LANGID_TIGRINYA TT_MAC_LANGID_THAI TT_MAC_LANGID_DANISH TT_MAC_LANGID_KAZAKH TT_MAC_LANGID_YIDDISH TT_MAC_LANGID_ESPERANTO TT_MAC_LANGID_LITHUANIAN TT_MAC_LANGID_FARSI TT_MAC_LANGID_LETTISH TT_MAC_LANGID_VIETNAMESE TT_MAC_LANGID_PORTUGUESE TT_MAC_LANGID_IRISH TT_MAC_LANGID_WELSH TT_MAC_LANGID_PUNJABI TT_MAC_LANGID_GREEK TT_MAC_LANGID_INUKTITUT TT_MAC_LANGID_FRENCH TT_MAC_LANGID_GREEK_POLYTONIC TT_MAC_LANGID_AZERBAIJANI TT_MAC_LANGID_JAVANESE TT_MAC_LANGID_SWEDISH TT_MAC_LANGID_UIGHUR TT_MAC_LANGID_BENGALI TT_MAC_LANGID_RUANDA TT_MAC_LANGID_SINDHI TT_MAC_LANGID_TIBETAN TT_MAC_LANGID_ENGLISH TT_MAC_LANGID_SAAMISK TT_MAC_LANGID_INDONESIAN TT_MAC_LANGID_MANX_GAELIC TT_MAC_LANGID_BYELORUSSIAN TT_MAC_LANGID_BULGARIAN TT_MAC_LANGID_GEORGIAN TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT TT_MAC_LANGID_ITALIAN TT_MAC_LANGID_SCOTTISH_GAELIC TT_MAC_LANGID_ARMENIAN TT_MAC_LANGID_GALLA TT_MAC_LANGID_MACEDONIAN TT_MAC_LANGID_IRISH_GAELIC TT_MAC_LANGID_KIRGHIZ TT_MAC_LANGID_TAMIL TT_MAC_LANGID_SPANISH TT_MAC_LANGID_BURMESE TT_MAC_LANGID_KANNADA TT_MAC_LANGID_GALICIAN TT_MAC_LANGID_FLEMISH TT_MAC_LANGID_TAJIKI TT_MAC_LANGID_ASSAMESE TT_MAC_LANGID_SINHALESE TT_MAC_LANGID_GREELANDIC TT_MAC_LANGID_AMHARIC TT_MAC_LANGID_KASHMIRI TT_MAC_LANGID_AYMARA TT_MAC_LANGID_GUJARATI TT_MAC_LANGID_RUSSIAN TT_MAC_LANGID_TURKMEN TT_MAC_LANGID_MALAYALAM """ TT_MAC_LANGIDS = { 'TT_MAC_LANGID_ENGLISH' : 0, 'TT_MAC_LANGID_FRENCH' : 1, 'TT_MAC_LANGID_GERMAN' : 2, 'TT_MAC_LANGID_ITALIAN' : 3, 'TT_MAC_LANGID_DUTCH' : 4, 'TT_MAC_LANGID_SWEDISH' : 5, 'TT_MAC_LANGID_SPANISH' : 6, 'TT_MAC_LANGID_DANISH' : 7, 'TT_MAC_LANGID_PORTUGUESE' : 8, 'TT_MAC_LANGID_NORWEGIAN' : 9, 'TT_MAC_LANGID_HEBREW' : 10, 'TT_MAC_LANGID_JAPANESE' : 11, 'TT_MAC_LANGID_ARABIC' : 12, 'TT_MAC_LANGID_FINNISH' : 13, 'TT_MAC_LANGID_GREEK' : 14, 'TT_MAC_LANGID_ICELANDIC' : 15, 'TT_MAC_LANGID_MALTESE' : 16, 'TT_MAC_LANGID_TURKISH' : 17, 'TT_MAC_LANGID_CROATIAN' : 18, 'TT_MAC_LANGID_CHINESE_TRADITIONAL' : 19, 'TT_MAC_LANGID_URDU' : 20, 'TT_MAC_LANGID_HINDI' : 21, 'TT_MAC_LANGID_THAI' : 22, 'TT_MAC_LANGID_KOREAN' : 23, 'TT_MAC_LANGID_LITHUANIAN' : 24, 'TT_MAC_LANGID_POLISH' : 25, 'TT_MAC_LANGID_HUNGARIAN' : 26, 'TT_MAC_LANGID_ESTONIAN' : 27, 'TT_MAC_LANGID_LETTISH' : 28, 'TT_MAC_LANGID_SAAMISK' : 29, 'TT_MAC_LANGID_FAEROESE' : 30, 'TT_MAC_LANGID_FARSI' : 31, 'TT_MAC_LANGID_RUSSIAN' : 32, 'TT_MAC_LANGID_CHINESE_SIMPLIFIED' : 33, 'TT_MAC_LANGID_FLEMISH' : 34, 'TT_MAC_LANGID_IRISH' : 35, 'TT_MAC_LANGID_ALBANIAN' : 36, 'TT_MAC_LANGID_ROMANIAN' : 37, 'TT_MAC_LANGID_CZECH' : 38, 'TT_MAC_LANGID_SLOVAK' : 39, 'TT_MAC_LANGID_SLOVENIAN' : 40, 'TT_MAC_LANGID_YIDDISH' : 41, 'TT_MAC_LANGID_SERBIAN' : 42, 'TT_MAC_LANGID_MACEDONIAN' : 43, 'TT_MAC_LANGID_BULGARIAN' : 44, 'TT_MAC_LANGID_UKRAINIAN' : 45, 'TT_MAC_LANGID_BYELORUSSIAN' : 46, 'TT_MAC_LANGID_UZBEK' : 47, 'TT_MAC_LANGID_KAZAKH' : 48, 'TT_MAC_LANGID_AZERBAIJANI' : 49, 'TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT': 49, 'TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT' : 50, 'TT_MAC_LANGID_ARMENIAN' : 51, 'TT_MAC_LANGID_GEORGIAN' : 52, 'TT_MAC_LANGID_MOLDAVIAN' : 53, 'TT_MAC_LANGID_KIRGHIZ' : 54, 'TT_MAC_LANGID_TAJIKI' : 55, 'TT_MAC_LANGID_TURKMEN' : 56, 'TT_MAC_LANGID_MONGOLIAN' : 57, 'TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT' : 57, 'TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT' : 58, 'TT_MAC_LANGID_PASHTO' : 59, 'TT_MAC_LANGID_KURDISH' : 60, 'TT_MAC_LANGID_KASHMIRI' : 61, 'TT_MAC_LANGID_SINDHI' : 62, 'TT_MAC_LANGID_TIBETAN' : 63, 'TT_MAC_LANGID_NEPALI' : 64, 'TT_MAC_LANGID_SANSKRIT' : 65, 'TT_MAC_LANGID_MARATHI' : 66, 'TT_MAC_LANGID_BENGALI' : 67, 'TT_MAC_LANGID_ASSAMESE' : 68, 'TT_MAC_LANGID_GUJARATI' : 69, 'TT_MAC_LANGID_PUNJABI' : 70, 'TT_MAC_LANGID_ORIYA' : 71, 'TT_MAC_LANGID_MALAYALAM' : 72, 'TT_MAC_LANGID_KANNADA' : 73, 'TT_MAC_LANGID_TAMIL' : 74, 'TT_MAC_LANGID_TELUGU' : 75, 'TT_MAC_LANGID_SINHALESE' : 76, 'TT_MAC_LANGID_BURMESE' : 77, 'TT_MAC_LANGID_KHMER' : 78, 'TT_MAC_LANGID_LAO' : 79, 'TT_MAC_LANGID_VIETNAMESE' : 80, 'TT_MAC_LANGID_INDONESIAN' : 81, 'TT_MAC_LANGID_TAGALOG' : 82, 'TT_MAC_LANGID_MALAY_ROMAN_SCRIPT' : 83, 'TT_MAC_LANGID_MALAY_ARABIC_SCRIPT' : 84, 'TT_MAC_LANGID_AMHARIC' : 85, 'TT_MAC_LANGID_TIGRINYA' : 86, 'TT_MAC_LANGID_GALLA' : 87, 'TT_MAC_LANGID_SOMALI' : 88, 'TT_MAC_LANGID_SWAHILI' : 89, 'TT_MAC_LANGID_RUANDA' : 90, 'TT_MAC_LANGID_RUNDI' : 91, 'TT_MAC_LANGID_CHEWA' : 92, 'TT_MAC_LANGID_MALAGASY' : 93, 'TT_MAC_LANGID_ESPERANTO' : 94, 'TT_MAC_LANGID_WELSH' : 128, 'TT_MAC_LANGID_BASQUE' : 129, 'TT_MAC_LANGID_CATALAN' : 130, 'TT_MAC_LANGID_LATIN' : 131, 'TT_MAC_LANGID_QUECHUA' : 132, 'TT_MAC_LANGID_GUARANI' : 133, 'TT_MAC_LANGID_AYMARA' : 134, 'TT_MAC_LANGID_TATAR' : 135, 'TT_MAC_LANGID_UIGHUR' : 136, 'TT_MAC_LANGID_DZONGKHA' : 137, 'TT_MAC_LANGID_JAVANESE' : 138, 'TT_MAC_LANGID_SUNDANESE' : 139, 'TT_MAC_LANGID_GALICIAN' : 140, 'TT_MAC_LANGID_AFRIKAANS' : 141, 'TT_MAC_LANGID_BRETON' : 142, 'TT_MAC_LANGID_INUKTITUT' : 143, 'TT_MAC_LANGID_SCOTTISH_GAELIC' : 144, 'TT_MAC_LANGID_MANX_GAELIC' : 145, 'TT_MAC_LANGID_IRISH_GAELIC' : 146, 'TT_MAC_LANGID_TONGAN' : 147, 'TT_MAC_LANGID_GREEK_POLYTONIC' : 148, 'TT_MAC_LANGID_GREELANDIC' : 149, 'TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT' : 150 } globals().update(TT_MAC_LANGIDS) freetype-py-2.5.1/freetype/ft_enums/ft_load_targets.py0000664000175000017500000000426214664131406023357 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of values that are used to select a specific hinting algorithm to use by the hinter. You should OR one of these values to your 'load_flags' when calling FT_Load_Glyph. Note that font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType bytecode interpreter). You can set FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. Also note that FT_LOAD_TARGET_LIGHT is an exception, in that it always implies FT_LOAD_FORCE_AUTOHINT. FT_LOAD_TARGET_NORMAL This corresponds to the default hinting algorithm, optimized for standard gray-level rendering. For monochrome output, use FT_LOAD_TARGET_MONO instead. FT_LOAD_TARGET_LIGHT A lighter hinting algorithm for non-monochrome modes. Many generated glyphs are more fuzzy but better resemble its original shape. A bit like rendering on Mac OS X. As a special exception, this target implies FT_LOAD_FORCE_AUTOHINT. FT_LOAD_TARGET_MONO Strong hinting algorithm that should only be used for monochrome output. The result is probably unpleasant if the glyph is rendered in non-monochrome modes. FT_LOAD_TARGET_LCD A variant of FT_LOAD_TARGET_NORMAL optimized for horizontally decimated LCD displays. FT_LOAD_TARGET_LCD_V A variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays. """ from freetype.ft_enums.ft_render_modes import * def _FT_LOAD_TARGET_(x): return (x & 15) << 16 FT_LOAD_TARGETS = { 'FT_LOAD_TARGET_NORMAL' : _FT_LOAD_TARGET_(FT_RENDER_MODE_NORMAL), 'FT_LOAD_TARGET_LIGHT' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LIGHT), 'FT_LOAD_TARGET_MONO' : _FT_LOAD_TARGET_(FT_RENDER_MODE_MONO), 'FT_LOAD_TARGET_LCD' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LCD), 'FT_LOAD_TARGET_LCD_V' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LCD_V) } globals().update(FT_LOAD_TARGETS) #def FT_LOAD_TARGET_MODE(x): # return (x >> 16) & 15 freetype-py-2.5.1/freetype/ft_enums/tt_name_ids.py0000664000175000017500000000425014664131406022501 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ Possible values of the 'name' identifier field in the name records of the TTF 'name' table. These values are platform independent. TT_NAME_ID_COPYRIGHT TT_NAME_ID_FONT_FAMILY TT_NAME_ID_FONT_SUBFAMILY TT_NAME_ID_UNIQUE_ID TT_NAME_ID_FULL_NAME TT_NAME_ID_VERSION_STRING TT_NAME_ID_PS_NAME TT_NAME_ID_TRADEMARK TT_NAME_ID_MANUFACTURER TT_NAME_ID_DESIGNER TT_NAME_ID_DESCRIPTION TT_NAME_ID_VENDOR_URL TT_NAME_ID_DESIGNER_URL TT_NAME_ID_LICENSE TT_NAME_ID_LICENSE_URL TT_NAME_ID_PREFERRED_FAMILY TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_MAC_FULL_NAME TT_NAME_ID_SAMPLE_TEXT TT_NAME_ID_CID_FINDFONT_NAME TT_NAME_ID_WWS_FAMILY TT_NAME_ID_WWS_SUBFAMILY """ TT_NAME_IDS = { 'TT_NAME_ID_COPYRIGHT' : 0, 'TT_NAME_ID_FONT_FAMILY' : 1, 'TT_NAME_ID_FONT_SUBFAMILY' : 2, 'TT_NAME_ID_UNIQUE_ID' : 3, 'TT_NAME_ID_FULL_NAME' : 4, 'TT_NAME_ID_VERSION_STRING' : 5, 'TT_NAME_ID_PS_NAME' : 6, 'TT_NAME_ID_TRADEMARK' : 7, # the following values are from the OpenType spec 'TT_NAME_ID_MANUFACTURER' : 8, 'TT_NAME_ID_DESIGNER' : 9, 'TT_NAME_ID_DESCRIPTION' : 10, 'TT_NAME_ID_VENDOR_URL' : 11, 'TT_NAME_ID_DESIGNER_URL' : 12, 'TT_NAME_ID_LICENSE' : 13, 'TT_NAME_ID_LICENSE_URL' : 14, # number 15 is reserved 'TT_NAME_ID_PREFERRED_FAMILY' : 16, 'TT_NAME_ID_PREFERRED_SUBFAMILY' : 17, 'TT_NAME_ID_MAC_FULL_NAME' : 18, # The following code is new as of 2000-01-21 'TT_NAME_ID_SAMPLE_TEXT' : 19, # This is new in OpenType 1.3 'TT_NAME_ID_CID_FINDFONT_NAME' : 20, # This is new in OpenType 1.5 'TT_NAME_ID_WWS_FAMILY' : 21, 'TT_NAME_ID_WWS_SUBFAMILY' : 22 } globals().update(TT_NAME_IDS) freetype-py-2.5.1/freetype/ft_enums/ft_encodings.py0000664000175000017500000001002114664131406022646 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ An enumeration used to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function. FT_ENCODING_NONE The encoding value 0 is reserved. FT_ENCODING_UNICODE Corresponds to the Unicode character set. This value covers all versions of the Unicode repertoire, including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them. For example, if you want to access Unicode value U+1F028 (and the font contains it), use value 0x1F028 as the input value for FT_Get_Char_Index. FT_ENCODING_MS_SYMBOL Corresponds to the Microsoft Symbol encoding, used to encode mathematical symbols in the 32..255 character code range. For more information, see 'http://www.ceviz.net/symbol.htm'. FT_ENCODING_SJIS Corresponds to Japanese SJIS encoding. More info at at 'http://langsupport.japanreference.com/encoding.shtml'. See note on multi-byte encodings below. FT_ENCODING_PRC Corresponds to encoding systems mainly for Simplified Chinese as used in People's Republic of China (PRC). The encoding layout is based on GB~2312 and its supersets GBK and GB~18030. FT_ENCODING_BIG5 Corresponds to an encoding system for Traditional Chinese as used in Taiwan and Hong Kong. FT_ENCODING_WANSUNG Corresponds to the Korean encoding system known as Wansung. For more information see 'http://www.microsoft.com/typography/unicode/949.txt'. FT_ENCODING_JOHAB The Korean standard character set (KS C 5601-1992), which corresponds to MS Windows code page 1361. This character set includes all possible Hangeul character combinations. FT_ENCODING_ADOBE_LATIN_1 Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript font. It is limited to 256 character codes. FT_ENCODING_ADOBE_STANDARD Corresponds to the Adobe Standard encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_ADOBE_EXPERT Corresponds to the Adobe Expert encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_ADOBE_CUSTOM Corresponds to a custom encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_APPLE_ROMAN Corresponds to the 8-bit Apple roman encoding. Many TrueType and OpenType fonts contain a charmap for this encoding, since older versions of Mac OS are able to use it. FT_ENCODING_OLD_LATIN_2 This value is deprecated and was never used nor reported by FreeType. Don't use or test for it. """ def _FT_ENC_TAG(a,b,c,d): return ( ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d) ) FT_ENCODINGS = {'FT_ENCODING_NONE' : _FT_ENC_TAG('\0','\0','\0','\0'), 'FT_ENCODING_MS_SYMBOL' : _FT_ENC_TAG( 's','y','m','b' ), 'FT_ENCODING_UNICODE' : _FT_ENC_TAG( 'u','n','i','c' ), 'FT_ENCODING_SJIS' : _FT_ENC_TAG( 's','j','i','s' ), 'FT_ENCODING_PRC' : _FT_ENC_TAG( 'g','b',' ',' ' ), 'FT_ENCODING_BIG5' : _FT_ENC_TAG( 'b','i','g','5' ), 'FT_ENCODING_WANSUNG' : _FT_ENC_TAG( 'w','a','n','s' ), 'FT_ENCODING_JOHAB' : _FT_ENC_TAG( 'j','o','h','a' ), 'FT_ENCODING_ADOBE_STANDARD' : _FT_ENC_TAG( 'A','D','O','B' ), 'FT_ENCODING_ADOBE_EXPERT' : _FT_ENC_TAG( 'A','D','B','E' ), 'FT_ENCODING_ADOBE_CUSTOM' : _FT_ENC_TAG( 'A','D','B','C' ), 'FT_ENCODING_ADOBE_LATIN1' : _FT_ENC_TAG( 'l','a','t','1' ), 'FT_ENCODING_OLD_LATIN2' : _FT_ENC_TAG( 'l','a','t','2' ), 'FT_ENCODING_APPLE_ROMAN' : _FT_ENC_TAG( 'a','r','m','n' ) } globals().update(FT_ENCODINGS) freetype-py-2.5.1/freetype/ft_enums/ft_fstypes.py0000664000175000017500000000467214664131406022411 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of bit flags that inform client applications of embedding and subsetting restrictions associated with a font. FT_FSTYPE_INSTALLABLE_EMBEDDING Fonts with no fsType bit set may be embedded and permanently installed on the remote system by an application. FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING Fonts that have only this bit set must not be modified, embedded or exchanged in any manner without first obtaining permission of the font software copyright owner. FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING If this bit is set, the font may be embedded and temporarily loaded on the remote system. Documents containing Preview & Print fonts must be opened 'read-only'; no edits can be applied to the document. FT_FSTYPE_EDITABLE_EMBEDDING If this bit is set, the font may be embedded but must only be installed temporarily on other systems. In contrast to Preview & Print fonts, documents containing editable fonts may be opened for reading, editing is permitted, and changes may be saved. FT_FSTYPE_NO_SUBSETTING If this bit is set, the font may not be subsetted prior to embedding. FT_FSTYPE_BITMAP_EMBEDDING_ONLY If this bit is set, only bitmaps contained in the font may be embedded; no outline data may be embedded. If there are no bitmaps available in the font, then the font is unembeddable. """ FT_FSTYPES = {'FT_FSTYPE_INSTALLABLE_EMBEDDING' : 0x0000, 'FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING' : 0x0002, 'FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING' : 0x0004, 'FT_FSTYPE_EDITABLE_EMBEDDING' : 0x0008, 'FT_FSTYPE_NO_SUBSETTING' : 0x0100, 'FT_FSTYPE_BITMAP_EMBEDDING_ONLY' : 0x0200,} globals().update(FT_FSTYPES) ft_fstype_installable_embedding = FT_FSTYPE_INSTALLABLE_EMBEDDING ft_fstype_restricted_license_embedding = FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING ft_fstype_preview_and_print_embedding = FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING ft_fstype_editable_embedding = FT_FSTYPE_EDITABLE_EMBEDDING ft_fstype_no_subsetting = FT_FSTYPE_NO_SUBSETTING ft_fstype_bitmap_embedding_only = FT_FSTYPE_BITMAP_EMBEDDING_ONLY freetype-py-2.5.1/freetype/ft_enums/ft_stroker_linecaps.py0000664000175000017500000000161614664131406024256 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ These values determine how the end of opened sub-paths are rendered in a stroke. FT_STROKER_LINECAP_BUTT The end of lines is rendered as a full stop on the last point itself. FT_STROKER_LINECAP_ROUND The end of lines is rendered as a half-circle around the last point. FT_STROKER_LINECAP_SQUARE The end of lines is rendered as a square around the last point. """ FT_STROKER_LINECAPS = { 'FT_STROKER_LINECAP_BUTT' : 0, 'FT_STROKER_LINECAP_ROUND' : 1, 'FT_STROKER_LINECAP_SQUARE' : 2} globals().update(FT_STROKER_LINECAPS) freetype-py-2.5.1/freetype/ft_enums/tt_platforms.py0000664000175000017500000000370014664131406022730 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of valid values for the 'platform_id' identifier code in FT_CharMapRec and FT_SfntName structures. TT_PLATFORM_APPLE_UNICODE Used by Apple to indicate a Unicode character map and/or name entry. See TT_APPLE_ID_XXX for corresponding 'encoding_id' values. Note that name entries in this format are coded as big-endian UCS-2 character codes only. TT_PLATFORM_MACINTOSH Used by Apple to indicate a MacOS-specific charmap and/or name entry. See TT_MAC_ID_XXX for corresponding 'encoding_id' values. Note that most TrueType fonts contain an Apple roman charmap to be usable on MacOS systems (even if they contain a Microsoft charmap as well). TT_PLATFORM_ISO This value was used to specify ISO/IEC 10646 charmaps. It is however now deprecated. See TT_ISO_ID_XXX for a list of corresponding 'encoding_id' values. TT_PLATFORM_MICROSOFT Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for a list of corresponding 'encoding_id' values. Note that most fonts contain a Unicode charmap using (TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS). TT_PLATFORM_CUSTOM Used to indicate application-specific charmaps. TT_PLATFORM_ADOBE This value isn't part of any font format specification, but is used by FreeType to report Adobe-specific charmaps in an FT_CharMapRec structure. See TT_ADOBE_ID_XXX. """ TT_PLATFORMS = { 'TT_PLATFORM_APPLE_UNICODE' : 0, 'TT_PLATFORM_MACINTOSH' : 1, 'TT_PLATFORM_ISO' : 2, # deprecated 'TT_PLATFORM_MICROSOFT' : 3, 'TT_PLATFORM_CUSTOM' : 4, 'TT_PLATFORM_ADOBE' : 7} # artificial globals().update(TT_PLATFORMS) freetype-py-2.5.1/freetype/ft_enums/tt_apple_ids.py0000664000175000017500000000222114664131406022656 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- """ A list of valid values for the 'encoding_id' for TT_PLATFORM_APPLE_UNICODE charmaps and name entries. TT_APPLE_ID_DEFAULT Unicode version 1.0. TT_APPLE_ID_UNICODE_1_1 Unicode 1.1; specifies Hangul characters starting at U+34xx. TT_APPLE_ID_ISO_10646 Deprecated (identical to preceding). TT_APPLE_ID_UNICODE_2_0 Unicode 2.0 and beyond (UTF-16 BMP only). TT_APPLE_ID_UNICODE_32 Unicode 3.1 and beyond, using UTF-32. TT_APPLE_ID_VARIANT_SELECTOR From Adobe, not Apple. Not a normal cmap. Specifies variations on a real cmap. """ TT_APPLE_IDS = { 'TT_APPLE_ID_DEFAULT' : 0, 'TT_APPLE_ID_UNICODE_1_1' : 1, 'TT_APPLE_ID_ISO_10646' : 2, 'TT_APPLE_ID_UNICODE_2_0' : 3, 'TT_APPLE_ID_UNICODE_32' : 4, 'TT_APPLE_ID_VARIANT_SELECTOR' : 5 } globals().update(TT_APPLE_IDS) freetype-py-2.5.1/tox.ini0000664000175000017500000000014514664131406015510 0ustar georgeskgeorgesk[tox] envlist = py36 [testenv] deps= pytest wheel commands=pytest {posargs} changedir=tests freetype-py-2.5.1/doc/0000775000175000017500000000000014664131406014742 5ustar georgeskgeorgeskfreetype-py-2.5.1/doc/index.rst0000664000175000017500000000074514664131406016611 0ustar georgeskgeorgesk============================= Freetype python documentation ============================= Freetype python provides bindings for the FreeType library. Only the high-level API is bound. Freetype-py lives at https://github.com/rougier/freetype-py/, see the installation instructions there. .. toctree:: :maxdepth: 1 usage.rst screenshots.rst api.rst notes.rst license.rst Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` freetype-py-2.5.1/doc/tt_ms_langids.rst0000664000175000017500000002416114664131406020327 0ustar georgeskgeorgeskTT_MS_LANGIDS ============= Possible values of the language identifier field in the name records of the TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MICROSOFT. .. data:: TT_MS_LANGID_SANSKRIT_INDIA .. data:: TT_MS_LANGID_ENGLISH_UNITED_KINGDOM .. data:: TT_MS_LANGID_ENGLISH_BELIZE .. data:: TT_MS_LANGID_ARABIC_LEBANON .. data:: TT_MS_LANGID_MOLDAVIAN_MOLDAVIA .. data:: TT_MS_LANGID_TURKISH_TURKEY .. data:: TT_MS_LANGID_WELSH_WALES .. data:: TT_MS_LANGID_GERMAN_AUSTRIA .. data:: TT_MS_LANGID_DUTCH_BELGIUM .. data:: TT_MS_LANGID_YI_CHINA .. data:: TT_MS_LANGID_QUECHUA_ECUADOR .. data:: TT_MS_LANGID_SPANISH_EL_SALVADOR .. data:: TT_MS_LANGID_SWAHILI_KENYA .. data:: TT_MS_LANGID_QUECHUA_BOLIVIA .. data:: TT_MS_LANGID_SLOVENE_SLOVENIA .. data:: TT_MS_LANGID_ORIYA_INDIA .. data:: TT_MS_LANGID_FARSI_IRAN .. data:: TT_MS_LANGID_ENGLISH_CANADA .. data:: TT_MS_LANGID_NEPALI_NEPAL .. data:: TT_MS_LANGID_DHIVEHI_MALDIVES .. data:: TT_MS_LANGID_GERMAN_LIECHTENSTEI .. data:: TT_MS_LANGID_TAMIL_INDIA .. data:: TT_MS_LANGID_ARABIC_UAE .. data:: TT_MS_LANGID_JAPANESE_JAPAN .. data:: TT_MS_LANGID_TAMAZIGHT_MOROCCO .. data:: TT_MS_LANGID_FRENCH_FRANCE .. data:: TT_MS_LANGID_CHINESE_MACAU .. data:: TT_MS_LANGID_VIETNAMESE_VIET_NAM .. data:: TT_MS_LANGID_HEBREW_ISRAEL .. data:: TT_MS_LANGID_SAMI_NORTHERN_SWEDEN .. data:: TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN .. data:: TT_MS_LANGID_SWEDISH_SWEDEN .. data:: TT_MS_LANGID_FRENCH_REUNION .. data:: TT_MS_LANGID_ARABIC_BAHRAIN .. data:: TT_MS_LANGID_ENGLISH_INDIA .. data:: TT_MS_LANGID_NEPALI_INDIA .. data:: TT_MS_LANGID_THAI_THAILAND .. data:: TT_MS_LANGID_ENGLISH_GENERAL .. data:: TT_MS_LANGID_SAMI_LULE_NORWAY .. data:: TT_MS_LANGID_ARABIC_OMAN .. data:: TT_MS_LANGID_SPANISH_HONDURAS .. data:: TT_MS_LANGID_ENGLISH_JAMAICA .. data:: TT_MS_LANGID_ESTONIAN_ESTONIA .. data:: TT_MS_LANGID_FRISIAN_NETHERLANDS .. data:: TT_MS_LANGID_LATIN .. data:: TT_MS_LANGID_ENGLISH_INDONESIA .. data:: TT_MS_LANGID_ENGLISH_IRELAND .. data:: TT_MS_LANGID_TIBETAN_CHINA .. data:: TT_MS_LANGID_PUNJABI_INDIA .. data:: TT_MS_LANGID_FRENCH_MALI .. data:: TT_MS_LANGID_GERMAN_LUXEMBOURG .. data:: TT_MS_LANGID_SUTU_SOUTH_AFRICA .. data:: TT_MS_LANGID_FRENCH_CAMEROON .. data:: TT_MS_LANGID_FRENCH_CONGO .. data:: TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA .. data:: TT_MS_LANGID_MALAYALAM_INDIA .. data:: TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN .. data:: TT_MS_LANGID_CHEROKEE_UNITED_STATES .. data:: TT_MS_LANGID_SPANISH_GUATEMALA .. data:: TT_MS_LANGID_CZECH_CZECH_REPUBLIC .. data:: TT_MS_LANGID_MANIPURI_INDIA .. data:: TT_MS_LANGID_ENGLISH_AUSTRALIA .. data:: TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC .. data:: TT_MS_LANGID_ARABIC_LIBYA .. data:: TT_MS_LANGID_FRENCH_WEST_INDIES .. data:: TT_MS_LANGID_ENGLISH_TRINIDAD .. data:: TT_MS_LANGID_ARABIC_QATAR .. data:: TT_MS_LANGID_SPANISH_COLOMBIA .. data:: TT_MS_LANGID_GUARANI_PARAGUAY .. data:: TT_MS_LANGID_EDO_NIGERIA .. data:: TT_MS_LANGID_SEPEDI_SOUTH_AFRICA .. data:: TT_MS_LANGID_ENGLISH_HONG_KONG .. data:: TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA .. data:: TT_MS_LANGID_TATAR_TATARSTAN .. data:: TT_MS_LANGID_PASHTO_AFGHANISTAN .. data:: TT_MS_LANGID_KASHMIRI_PAKISTAN .. data:: TT_MS_LANGID_GALICIAN_SPAIN .. data:: TT_MS_LANGID_TAJIK_TAJIKISTAN .. data:: TT_MS_LANGID_SAMI_INARI_FINLAND .. data:: TT_MS_LANGID_KASHMIRI_SASIA .. data:: TT_MS_LANGID_SPANISH_ARGENTINA .. data:: TT_MS_LANGID_SAMI_SOUTHERN_NORWAY .. data:: TT_MS_LANGID_CROATIAN_CROATIA .. data:: TT_MS_LANGID_GUJARATI_INDIA .. data:: TT_MS_LANGID_TIBETAN_BHUTAN .. data:: TT_MS_LANGID_TIGRIGNA_ETHIOPIA .. data:: TT_MS_LANGID_FINNISH_FINLAND .. data:: TT_MS_LANGID_ENGLISH_UNITED_STATES .. data:: TT_MS_LANGID_ITALIAN_SWITZERLAND .. data:: TT_MS_LANGID_ARABIC_EGYPT .. data:: TT_MS_LANGID_SPANISH_LATIN_AMERICA .. data:: TT_MS_LANGID_LITHUANIAN_LITHUANIA .. data:: TT_MS_LANGID_ARABIC_ALGERIA .. data:: TT_MS_LANGID_MALAY_MALAYSIA .. data:: TT_MS_LANGID_ARABIC_GENERAL .. data:: TT_MS_LANGID_CHINESE_PRC .. data:: TT_MS_LANGID_BENGALI_BANGLADESH .. data:: TT_MS_LANGID_SPANISH_PERU .. data:: TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT .. data:: TT_MS_LANGID_DIVEHI_MALDIVES .. data:: TT_MS_LANGID_LATVIAN_LATVIA .. data:: TT_MS_LANGID_TURKMEN_TURKMENISTAN .. data:: TT_MS_LANGID_XHOSA_SOUTH_AFRICA .. data:: TT_MS_LANGID_KHMER_CAMBODIA .. data:: TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK .. data:: TT_MS_LANGID_ARABIC_MOROCCO .. data:: TT_MS_LANGID_FRENCH_SENEGAL .. data:: TT_MS_LANGID_YORUBA_NIGERIA .. data:: TT_MS_LANGID_CATALAN_SPAIN .. data:: TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA .. data:: TT_MS_LANGID_ZULU_SOUTH_AFRICA .. data:: TT_MS_LANGID_SPANISH_URUGUAY .. data:: TT_MS_LANGID_SPANISH_ECUADOR .. data:: TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA .. data:: TT_MS_LANGID_CHINESE_GENERAL .. data:: TT_MS_LANGID_SPANISH_PARAGUAY .. data:: TT_MS_LANGID_HINDI_INDIA .. data:: TT_MS_LANGID_FRENCH_LUXEMBOURG .. data:: TT_MS_LANGID_TSWANA_SOUTH_AFRICA .. data:: TT_MS_LANGID_HUNGARIAN_HUNGARY .. data:: TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA .. data:: TT_MS_LANGID_ENGLISH_SINGAPORE .. data:: TT_MS_LANGID_MALTESE_MALTA .. data:: TT_MS_LANGID_SAMI_NORTHERN_FINLAND .. data:: TT_MS_LANGID_FRENCH_CANADA .. data:: TT_MS_LANGID_SAMI_LULE_SWEDEN .. data:: TT_MS_LANGID_KANURI_NIGERIA .. data:: TT_MS_LANGID_IRISH_GAELIC_IRELAND .. data:: TT_MS_LANGID_ARABIC_SAUDI_ARABIA .. data:: TT_MS_LANGID_FRENCH_HAITI .. data:: TT_MS_LANGID_SPANISH_PUERTO_RICO .. data:: TT_MS_LANGID_BURMESE_MYANMAR .. data:: TT_MS_LANGID_POLISH_POLAND .. data:: TT_MS_LANGID_PORTUGUESE_PORTUGAL .. data:: TT_MS_LANGID_ENGLISH_CARIBBEAN .. data:: TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC .. data:: TT_MS_LANGID_ICELANDIC_ICELAND .. data:: TT_MS_LANGID_BENGALI_INDIA .. data:: TT_MS_LANGID_HAUSA_NIGERIA .. data:: TT_MS_LANGID_BASQUE_SPAIN .. data:: TT_MS_LANGID_UIGHUR_CHINA .. data:: TT_MS_LANGID_ENGLISH_MALAYSIA .. data:: TT_MS_LANGID_FRENCH_MONACO .. data:: TT_MS_LANGID_SPANISH_BOLIVIA .. data:: TT_MS_LANGID_SORBIAN_GERMANY .. data:: TT_MS_LANGID_SINDHI_INDIA .. data:: TT_MS_LANGID_CHINESE_SINGAPORE .. data:: TT_MS_LANGID_FRENCH_COTE_D_IVOIRE .. data:: TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT .. data:: TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC .. data:: TT_MS_LANGID_SAMI_SKOLT_FINLAND .. data:: TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC .. data:: TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM .. data:: TT_MS_LANGID_ARABIC_JORDAN .. data:: TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN .. data:: TT_MS_LANGID_SERBIAN_SERBIA_LATIN .. data:: TT_MS_LANGID_RUSSIAN_RUSSIA .. data:: TT_MS_LANGID_ROMANIAN_ROMANIA .. data:: TT_MS_LANGID_FRENCH_NORTH_AFRICA .. data:: TT_MS_LANGID_MONGOLIAN_MONGOLIA .. data:: TT_MS_LANGID_TSONGA_SOUTH_AFRICA .. data:: TT_MS_LANGID_SOMALI_SOMALIA .. data:: TT_MS_LANGID_SAAMI_LAPONIA .. data:: TT_MS_LANGID_SPANISH_COSTA_RICA .. data:: TT_MS_LANGID_ARABIC_SYRIA .. data:: TT_MS_LANGID_SPANISH_PANAMA .. data:: TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES .. data:: TT_MS_LANGID_ASSAMESE_INDIA .. data:: TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM .. data:: TT_MS_LANGID_DUTCH_NETHERLANDS .. data:: TT_MS_LANGID_SINDHI_PAKISTAN .. data:: TT_MS_LANGID_MACEDONIAN_MACEDONIA .. data:: TT_MS_LANGID_KAZAK_KAZAKSTAN .. data:: TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN .. data:: TT_MS_LANGID_BELARUSIAN_BELARUS .. data:: TT_MS_LANGID_FRENCH_MOROCCO .. data:: TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN .. data:: TT_MS_LANGID_ALBANIAN_ALBANIA .. data:: TT_MS_LANGID_SINHALESE_SRI_LANKA .. data:: TT_MS_LANGID_SPANISH_MEXICO .. data:: TT_MS_LANGID_ENGLISH_ZIMBABWE .. data:: TT_MS_LANGID_OROMO_ETHIOPIA .. data:: TT_MS_LANGID_INDONESIAN_INDONESIA .. data:: TT_MS_LANGID_SAMI_NORTHERN_NORWAY .. data:: TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN .. data:: TT_MS_LANGID_SLOVAK_SLOVAKIA .. data:: TT_MS_LANGID_KASHMIRI_INDIA .. data:: TT_MS_LANGID_GERMAN_SWITZERLAND .. data:: TT_MS_LANGID_URDU_INDIA .. data:: TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS .. data:: TT_MS_LANGID_SYRIAC_SYRIA .. data:: TT_MS_LANGID_SPANISH_CHILE .. data:: TT_MS_LANGID_FILIPINO_PHILIPPINES .. data:: TT_MS_LANGID_ARABIC_YEMEN .. data:: TT_MS_LANGID_KONKANI_INDIA .. data:: TT_MS_LANGID_AMHARIC_ETHIOPIA .. data:: TT_MS_LANGID_ENGLISH_NEW_ZEALAND .. data:: TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND .. data:: TT_MS_LANGID_ARABIC_TUNISIA .. data:: TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA .. data:: TT_MS_LANGID_QUECHUA_PERU .. data:: TT_MS_LANGID_DANISH_DENMARK .. data:: TT_MS_LANGID_ENGLISH_PHILIPPINES .. data:: TT_MS_LANGID_SPANISH_NICARAGUA .. data:: TT_MS_LANGID_INUKTITUT_CANADA .. data:: TT_MS_LANGID_UKRAINIAN_UKRAINE .. data:: TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL .. data:: TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC .. data:: TT_MS_LANGID_FRENCH_BELGIUM .. data:: TT_MS_LANGID_ENGLISH_SOUTH_AFRICA .. data:: TT_MS_LANGID_HAWAIIAN_UNITED_STATES .. data:: TT_MS_LANGID_ARABIC_IRAQ .. data:: TT_MS_LANGID_KANNADA_INDIA .. data:: TT_MS_LANGID_DZONGHKA_BHUTAN .. data:: TT_MS_LANGID_CHINESE_TAIWAN .. data:: TT_MS_LANGID_SPANISH_UNITED_STATES .. data:: TT_MS_LANGID_ARMENIAN_ARMENIA .. data:: TT_MS_LANGID_LAO_LAOS .. data:: TT_MS_LANGID_TIGRIGNA_ERYTREA .. data:: TT_MS_LANGID_MARATHI_INDIA .. data:: TT_MS_LANGID_ARABIC_KUWAIT .. data:: TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN .. data:: TT_MS_LANGID_PORTUGUESE_BRAZIL .. data:: TT_MS_LANGID_TIGRIGNA_ERYTHREA .. data:: TT_MS_LANGID_GREEK_GREECE .. data:: TT_MS_LANGID_URDU_PAKISTAN .. data:: TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN .. data:: TT_MS_LANGID_YIDDISH_GERMANY .. data:: TT_MS_LANGID_GERMAN_GERMANY .. data:: TT_MS_LANGID_TELUGU_INDIA .. data:: TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC .. data:: TT_MS_LANGID_KOREAN_JOHAB_KOREA .. data:: TT_MS_LANGID_ITALIAN_ITALY .. data:: TT_MS_LANGID_MAORI_NEW_ZEALAND .. data:: TT_MS_LANGID_SPANISH_VENEZUELA .. data:: TT_MS_LANGID_IGBO_NIGERIA .. data:: TT_MS_LANGID_IBIBIO_NIGERIA .. data:: TT_MS_LANGID_CHINESE_HONG_KONG .. data:: TT_MS_LANGID_FRENCH_SWITZERLAND .. data:: TT_MS_LANGID_BULGARIAN_BULGARIA .. data:: TT_MS_LANGID_FULFULDE_NIGERIA .. data:: TT_MS_LANGID_RUSSIAN_MOLDAVIA .. data:: TT_MS_LANGID_VENDA_SOUTH_AFRICA .. data:: TT_MS_LANGID_GEORGIAN_GEORGIA .. data:: TT_MS_LANGID_SWEDISH_FINLAND freetype-py-2.5.1/doc/make.bat0000664000175000017500000001065714664131406016360 0ustar georgeskgeorgesk@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\FreetypePython.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\FreetypePython.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end freetype-py-2.5.1/doc/make_enums.py0000664000175000017500000000202014664131406017432 0ustar georgeskgeorgeskimport freetype enums = [ 'ft_fstypes', 'ft_face_flags', 'ft_encodings', 'ft_glyph_bbox_modes', 'ft_glyph_formats', 'ft_kerning_modes', 'ft_lcd_filters', 'ft_load_flags', 'ft_load_targets', 'ft_open_modes', 'ft_outline_flags', 'ft_pixel_modes', 'ft_render_modes', 'ft_stroker_borders', 'ft_stroker_linecaps', 'ft_stroker_linejoins', 'ft_style_flags', 'tt_adobe_ids', 'tt_apple_ids', 'tt_mac_ids', 'tt_ms_ids', 'tt_ms_langids', 'tt_mac_langids', 'tt_name_ids', 'tt_platforms' ] for name in enums: print name module = getattr(freetype, name) doc = getattr(module, '__doc__') doc = doc.split('\n') file = open( name+'.rst', 'w') title = name.upper() file.write(title+'\n') file.write('='*len(title)+'\n') for line in doc: if line.startswith('FT_') or line.startswith('TT_'): file.write( '.. data:: '+ line + '\n') else: file.write( line + '\n') file.close() freetype-py-2.5.1/doc/ft_style_flags.rst0000664000175000017500000000047614664131406020510 0ustar georgeskgeorgeskFT_STYLE_FLAGS ============== A list of bit-flags used to indicate the style of a given face. These are used in the 'style_flags' field of FT_FaceRec. .. data:: FT_STYLE_FLAG_ITALIC Indicates that a given face style is italic or oblique. .. data:: FT_STYLE_FLAG_BOLD Indicates that a given face is bold. freetype-py-2.5.1/doc/ft_stroker_linecaps.rst0000664000175000017500000000067614664131406021545 0ustar georgeskgeorgeskFT_STROKER_LINECAPS =================== These values determine how the end of opened sub-paths are rendered in a stroke. .. data:: FT_STROKER_LINECAP_BUTT The end of lines is rendered as a full stop on the last point itself. .. data:: FT_STROKER_LINECAP_ROUND The end of lines is rendered as a half-circle around the last point. .. data:: FT_STROKER_LINECAP_SQUARE The end of lines is rendered as a square around the last point. freetype-py-2.5.1/doc/bitmap_size.rst0000664000175000017500000000013414664131406020000 0ustar georgeskgeorgesk.. currentmodule:: freetype Bitmap size =========== .. autoclass:: BitmapSize :members: freetype-py-2.5.1/doc/charmap.rst0000664000175000017500000000012114664131406017101 0ustar georgeskgeorgesk.. currentmodule:: freetype Charmap ======= .. autoclass:: Charmap :members: freetype-py-2.5.1/doc/face.rst0000664000175000017500000000022314664131406016367 0ustar georgeskgeorgesk.. currentmodule:: freetype Face ==== .. autoclass:: Face :members: freetype-py-2.5.1/doc/ft_load_targets.rst0000664000175000017500000000263614664131406020644 0ustar georgeskgeorgeskFT_LOAD_TARGETS =============== A list of values that are used to select a specific hinting algorithm to use by the hinter. You should OR one of these values to your 'load_flags' when calling FT_Load_Glyph. Note that font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType bytecode interpreter). You can set .. data:: FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. Also note that FT_LOAD_TARGET_LIGHT is an exception, in that it always implies FT_LOAD_FORCE_AUTOHINT. .. data:: FT_LOAD_TARGET_NORMAL This corresponds to the default hinting algorithm, optimized for standard gray-level rendering. For monochrome output, use FT_LOAD_TARGET_MONO instead. .. data:: FT_LOAD_TARGET_LIGHT A lighter hinting algorithm for non-monochrome modes. Many generated glyphs are more fuzzy but better resemble its original shape. A bit like rendering on Mac OS X. As a special exception, this target implies FT_LOAD_FORCE_AUTOHINT. .. data:: FT_LOAD_TARGET_MONO Strong hinting algorithm that should only be used for monochrome output. The result is probably unpleasant if the glyph is rendered in non-monochrome modes. .. data:: FT_LOAD_TARGET_LCD A variant of FT_LOAD_TARGET_NORMAL optimized for horizontally decimated LCD displays. .. data:: FT_LOAD_TARGET_LCD_V A variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays. freetype-py-2.5.1/doc/tt_mac_ids.rst0000664000175000017500000000215114664131406017601 0ustar georgeskgeorgeskTT_MAC_IDS ========== A list of valid values for the 'encoding_id' for TT_PLATFORM_MACINTOSH charmaps and name entries. .. data:: TT_MAC_ID_ROMAN .. data:: TT_MAC_ID_TELUGU .. data:: TT_MAC_ID_GURMUKHI .. data:: TT_MAC_ID_TIBETAN .. data:: TT_MAC_ID_SIMPLIFIED_CHINESE .. data:: TT_MAC_ID_SINDHI .. data:: TT_MAC_ID_SINHALESE .. data:: TT_MAC_ID_RUSSIAN .. data:: TT_MAC_ID_KANNADA .. data:: TT_MAC_ID_VIETNAMESE .. data:: TT_MAC_ID_MONGOLIAN .. data:: TT_MAC_ID_DEVANAGARI .. data:: TT_MAC_ID_HEBREW .. data:: TT_MAC_ID_TAMIL .. data:: TT_MAC_ID_THAI .. data:: TT_MAC_ID_BURMESE .. data:: TT_MAC_ID_MALDIVIAN .. data:: TT_MAC_ID_TRADITIONAL_CHINESE .. data:: TT_MAC_ID_JAPANESE .. data:: TT_MAC_ID_GREEK .. data:: TT_MAC_ID_LAOTIAN .. data:: TT_MAC_ID_KHMER .. data:: TT_MAC_ID_UNINTERP .. data:: TT_MAC_ID_ORIYA .. data:: TT_MAC_ID_RSYMBOL .. data:: TT_MAC_ID_MALAYALAM .. data:: TT_MAC_ID_GEEZ .. data:: TT_MAC_ID_KOREAN .. data:: TT_MAC_ID_GUJARATI .. data:: TT_MAC_ID_BENGALI .. data:: TT_MAC_ID_ARABIC .. data:: TT_MAC_ID_GEORGIAN .. data:: TT_MAC_ID_ARMENIAN .. data:: TT_MAC_ID_SLAVIC freetype-py-2.5.1/doc/ft_face_flags.rst0000664000175000017500000000732214664131406020243 0ustar georgeskgeorgeskFT_FACE_FLAGS ============= A list of bit flags used in the 'face_flags' field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face. .. data:: FT_FACE_FLAG_SCALABLE Indicates that the face contains outline glyphs. This doesn't prevent bitmap strikes, i.e., a face can have both this and and FT_FACE_FLAG_FIXED_SIZES set. .. data:: FT_FACE_FLAG_FIXED_SIZES Indicates that the face contains bitmap strikes. See also the 'num_fixed_sizes' and 'available_sizes' fields of FT_FaceRec. .. data:: FT_FACE_FLAG_FIXED_WIDTH Indicates that the face contains fixed-width characters (like Courier, Lucido, MonoType, etc.). .. data:: FT_FACE_FLAG_SFNT Indicates that the face uses the 'sfnt' storage scheme. For now, this means TrueType and OpenType. .. data:: FT_FACE_FLAG_HORIZONTAL Indicates that the face contains horizontal glyph metrics. This should be set for all common formats. .. data:: FT_FACE_FLAG_VERTICAL Indicates that the face contains vertical glyph metrics. This is only available in some formats, not all of them. .. data:: FT_FACE_FLAG_KERNING Indicates that the face contains kerning information. If set, the kerning distance can be retrieved through the function FT_Get_Kerning. Otherwise the function always return the vector (0,0). Note that FreeType doesn't handle kerning data from the 'GPOS' table (as present in some OpenType fonts). .. data:: FT_FACE_FLAG_MULTIPLE_MASTERS Indicates that the font contains multiple masters and is capable of interpolating between them. See the multiple-masters specific API for details. .. data:: FT_FACE_FLAG_GLYPH_NAMES Indicates that the font contains glyph names that can be retrieved through FT_Get_Glyph_Name. Note that some TrueType fonts contain broken glyph name tables. Use the function FT_Has_PS_Glyph_Names when needed. .. data:: FT_FACE_FLAG_EXTERNAL_STREAM Used internally by FreeType to indicate that a face's stream was provided by the client application and should not be destroyed when FT_Done_Face is called. Don't read or test this flag. .. data:: FT_FACE_FLAG_HINTER Set if the font driver has a hinting machine of its own. For example, with TrueType fonts, it makes sense to use data from the SFNT 'gasp' table only if the native TrueType hinting engine (with the bytecode interpreter) is available and active. .. data:: FT_FACE_FLAG_CID_KEYED Set if the font is CID-keyed. In that case, the font is not accessed by glyph indices but by CID values. For subsetted CID-keyed fonts this has the consequence that not all index values are a valid argument to FT_Load_Glyph. Only the CID values for which corresponding glyphs in the subsetted font exist make FT_Load_Glyph return successfully; in all other cases you get an 'FT_Err_Invalid_Argument' error. Note that CID-keyed fonts which are in an SFNT wrapper don't have this flag set since the glyphs are accessed in the normal way (using contiguous indices); the 'CID-ness' isn't visible to the application. .. data:: FT_FACE_FLAG_TRICKY Set if the font is 'tricky', this is, it always needs the font format's native hinting engine to get a reasonable result. A typical example is the Chinese font 'mingli.ttf' which uses TrueType bytecode instructions to move and scale all of its subglyphs. It is not possible to autohint such fonts using FT_LOAD_FORCE_AUTOHINT; it will also ignore FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT to really disable hinting; however, you probably never want this except for demonstration purposes. Currently, there are six TrueType fonts in the list of tricky fonts; they are hard-coded in file 'ttobjs.c'. freetype-py-2.5.1/doc/api.rst0000664000175000017500000000037214664131406016247 0ustar georgeskgeorgesk=== API === .. toctree:: :maxdepth: 2 face.rst bbox.rst size_metrics.rst bitmap_size.rst bitmap.rst charmap.rst outline.rst glyph.rst bitmap_glyph.rst glyph_slot.rst sfnt_name.rst stroker.rst constants.rst freetype-py-2.5.1/doc/ft_kerning_modes.rst0000664000175000017500000000061614664131406021014 0ustar georgeskgeorgeskFT_KERNING_MODES ================ An enumeration used to specify which kerning values to return in .. data:: FT_Get_Kerning. .. data:: FT_KERNING_DEFAULT Return scaled and grid-fitted kerning distances (value is 0). .. data:: FT_KERNING_UNFITTED Return scaled but un-grid-fitted kerning distances. .. data:: FT_KERNING_UNSCALED Return the kerning vector in original font units. freetype-py-2.5.1/doc/sfnt_name.rst0000664000175000017500000000012714664131406017446 0ustar georgeskgeorgesk.. currentmodule:: freetype SFNT name ========== .. autoclass:: SfntName :members: freetype-py-2.5.1/doc/notes.rst0000664000175000017500000000164614664131406016633 0ustar georgeskgeorgesk============= Release notes ============= 0.4.1 ===== * Fixed a bug in Face.load_char * Added get_format and get_fstype in Face (titusz.pan) 0.3.3 ===== * Fixed a bug in get_kerning * Added test against freetype version for FT_ReferenceFace and FT_Get_FSType_Flags 0.3.2 ===== * Added wordle.py example * Added get_bbox for Outline class * Added get_cbox for Outline and Glyph classes * Added __del__ method to Face class * Set encoding (utf-8) to all source files and examples. * Added test against freetype version for FT_Library_SetLcdFilterWeights. 0.3.1 ===== * Added FT_Stroker bindings (enums, structs and methods) * Added ft-outline and ft-color examples * Fixed first/next char in Face * Pythonic interface has been documented 0.3.0 ===== * Added ftdump.py demo and necessary functions 0.2.0 ===== * Added sfnt functions * Added TT_XXX flags in ft_enums * New examples 0.1.1 ===== * Initial release * Working examples freetype-py-2.5.1/doc/ft_outline_flags.rst0000664000175000017500000000421114664131406021016 0ustar georgeskgeorgeskFT_OUTLINE_FLAGS ================ A list of bit-field constants use for the flags in an outline's 'flags' field. .. data:: FT_OUTLINE_NONE Value 0 is reserved. .. data:: FT_OUTLINE_OWNER If set, this flag indicates that the outline's field arrays (i.e., 'points', 'flags', and 'contours') are 'owned' by the outline object, and should thus be freed when it is destroyed. .. data:: FT_OUTLINE_EVEN_ODD_FILL By default, outlines are filled using the non-zero winding rule. If set to 1, the outline will be filled using the even-odd fill rule (only works with the smooth rasterizer). .. data:: FT_OUTLINE_REVERSE_FILL By default, outside contours of an outline are oriented in clock-wise direction, as defined in the TrueType specification. This flag is set if the outline uses the opposite direction (typically for Type 1 fonts). This flag is ignored by the scan converter. .. data:: FT_OUTLINE_IGNORE_DROPOUTS By default, the scan converter will try to detect drop-outs in an outline and correct the glyph bitmap to ensure consistent shape continuity. If set, this flag hints the scan-line converter to ignore such cases. See below for more information. .. data:: FT_OUTLINE_SMART_DROPOUTS Select smart dropout control. If unset, use simple dropout control. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. .. data:: FT_OUTLINE_INCLUDE_STUBS If set, turn pixels on for 'stubs', otherwise exclude them. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. .. data:: FT_OUTLINE_HIGH_PRECISION This flag indicates that the scan-line converter should try to convert this outline to bitmaps with the highest possible quality. It is typically set for small character sizes. Note that this is only a hint that might be completely ignored by a given scan-converter. .. data:: FT_OUTLINE_SINGLE_PASS This flag is set to force a given scan-converter to only use a single pass over the outline to render a bitmap glyph image. Normally, it is set for very large character sizes. It is only a hint that might be completely ignored by a given scan-converter. freetype-py-2.5.1/doc/ft_pixel_modes.rst0000664000175000017500000000316614664131406020503 0ustar georgeskgeorgeskFT_PIXEL_MODES ============== An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. .. data:: FT_PIXEL_MODE_NONE Value 0 is reserved. .. data:: FT_PIXEL_MODE_MONO A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in most-significant order (MSB), which means that the left-most pixel in a byte has value 128. .. data:: FT_PIXEL_MODE_GRAY An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each pixel is stored in one byte. Note that the number of 'gray' levels is stored in the 'num_grays' field of the FT_Bitmap structure (it generally is 256). .. data:: FT_PIXEL_MODE_GRAY2 A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. .. data:: FT_PIXEL_MODE_GRAY4 A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. .. data:: FT_PIXEL_MODE_LCD An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on LCD displays; the bitmap is three times wider than the original glyph image. See also FT_RENDER_MODE_LCD. .. data:: FT_PIXEL_MODE_LCD_V An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on rotated LCD displays; the bitmap is three times taller than the original glyph image. See also FT_RENDER_MODE_LCD_V. freetype-py-2.5.1/doc/screenshots.rst0000664000175000017500000000200214664131406020026 0ustar georgeskgeorgesk=========== Screenshots =========== Screenshot below comes from the wordle.py example. No clever tricks here, just brute force. .. image:: _static/wordle.png Screenshots below comes from the glyph-vector.py and glyph-vectopr-2.py examples showing how to access a glyph outline information and use it to draw the glyph. Rendering (with Bézier curves) is done using matplotlib. .. image:: _static/S.png .. image:: _static/G.png Screenshot below comes from the glyph-color.py showing how to draw and combine a glyph outline with the regular glyph. .. image:: _static/outline.png The screenshot below comes from the hello-world.py example showing how to draw text in a bitmap (that has been zoomed in to show antialiasing). .. image:: _static/hello-world.png The screenshot below comes from the agg-trick.py example showing an implementation of ideas from the `Texts Rasterization Exposures `_ by Maxim Shemarev. .. image:: _static/agg-trick.png freetype-py-2.5.1/doc/usage.rst0000664000175000017500000000033714664131406016603 0ustar georgeskgeorgesk============= Usage example ============= .. code:: python import freetype face = freetype.Face("Vera.ttf") face.set_char_size( 48*64 ) face.load_char('S') bitmap = face.glyph.bitmap print bitmap.buffer freetype-py-2.5.1/doc/outline.rst0000664000175000017500000000012114664131406017145 0ustar georgeskgeorgesk.. currentmodule:: freetype Outline ======= .. autoclass:: Outline :members: freetype-py-2.5.1/doc/_static/0000775000175000017500000000000014664131406016370 5ustar georgeskgeorgeskfreetype-py-2.5.1/doc/_static/agg-trick.png0000664000175000017500000030020014664131406020741 0ustar georgeskgeorgeskPNG  IHDRIDATxy<܅k_ʚ,m( ԇV"*!-lQP7%EEZ)\}fm>g=nΜ9sf>! H 1c@Vuqmi^ }~nA+׌_j|'ʩ^=Cv{[{6]~I]af=<`s`]b~ }{k-󤅂=Z~$oI|kzo!20"Ƀ'?Vm.?`vx*?@n [ lϾs…[ٵ8  rp8gKQ ݃'tnYO&<<*a̙:k+s2-8Gp{J\VqbY|K[Z軦0ђ(ѥh s Ëx2 Yݾl,Ο;(έ^BH7 ~g>6ĵ&Ck*m(?;{ t$Zzx Bg9&`=]©⌜VCFzg!D^lGιшmٷmq߱'W HG}n$aBNu'R1+Y=b -I8m\=ֿs۾K_7~^%[[6ȼ "c6;a74r ii`Ch3;tD"b\ zE$!c2D5J<6#_ACh}8}96 Al li!\c9 k`?eb\No*)'JEJYZ|p 6_rnQ6 n|9qoF H+}@;L#2j8j vl%oMi^HVUɯxt%^1׻:mJ"5-4ƥ#7̶֥@LJ+k0E1b󬖍Js% I6hQSf͡{PPNﶭ@N-ʅ̚kMw0ؒ-q^8xjW8֘v;Cg 89- u|SF_Ҝy>&Ʈ;Wa?ӭDn}ކ>xog-5ydzo9 jҘJVɩ qLok`;9ǽfW3ZeN⻤9UB]"*2Zw'fng ;v’qK7q8W8Sx 4lM9ql>C![Gc>gu:hy̋iCǔ;Wu ej]5AyWAv!6slBwIXYR dj|.l,Mt+?gֆJ&sV=Q#'5EE#_E>3oȤ6jOmF^QPZǂ"#o A?|eynfܾ[]{RGJcm5Љj5F  Qh*2\ nv:$.8.D.&CYj!l>tH C̓ϺqC1X~̀DO\5 NvYmͶeijsoXvpu( ɟrf×~ר+չR~ﺱNS@A[UL,5@i9k-GXxh{! -l/ _u>:qs+-W*3D$˾l\FScϙb>S3_J5-T+Mp>bJ:*\〫Ժ{e%ꖾ 8i#,0W-niTyЙ߉$$!@Gn\LX-ڎ>S/]}&Ai󛳇}ʎ"=y>yŮ*X;"nKTA2$ّUìK-.'$Ed|<-4acQ,6Uqǐ+l'~J#{_jLh3e ݻ ]B@p̒ҙ0~O֊/W܆BzmU '$uQ!(cݓ-])LB@Qdf..6n0!ucJTLhcıOG9̑66s(1[ʠ#wxmd1|TG :۲hҔ$?yaB(Y|Jx`v|LesOQyE9- Ǯ]4hWyYB.qZ"}yXg R4u #Hǒwu&x:/ H1*=d#)Y ROhZ0E[qY_:Y,4f'kŋ77}Jls2vAD9І!{*RJ􁥕)y9唷E0y?|Ta礜sai  0 DGdhJkíU( b= UW,jq +-I~2M]K"Ws/R֧*X>;0hG]n`l ->eD*Oy2zٵTKy?|iUl͈MI@VWnw[GQخ1\MkM1ZS>{ $^agN34mTݓwYj#58/95-ѿiTMgzY 'IOr>1V,LܸKlǭc%${ 8,[^S[(GoL @P}gi^d' MYK:Rkk`W֨/Ss7?qԒ_a \w_%OB wKV{`ő%ܔ͋ UxO8a 3i+L4Mo*_\! ?riS{2+ KV o9㋯4oк1Nݹudv'9}KZ[3NY s6笔=ik#H*,>y?𶬸c_9ܧi}߁3WbcuT^`w$ ':!>)t쀙{~~4c%F8{]n>~XS_I,Tt:g\?tEÚUwvxٌЦ G#h8>d>|ΛdкWO=s|bׁ E_f}ԝsݪ@Naot 鎭iP&wXYSz ^xغddjNi^K=sϏ U(%~L6X{eeK ėnƇ>gėv!0dgWJz68#R_w#A!e3Y藯;2ymcFH+![n2C5}P&HdA0F]5mn7HfJHp(NL}" @Z"8@AGz>IDQQD!7AL -1B l|~:_s4Yl Jy@`F1~iVDh A Yx#7 kSL]~ז6Ti|Wpk7<uXMZ |K :(l._=23b_KHe\KniMN,\|041:N6>0'8z'ܗN6vЈSǶWՏg{-\L99Ay+kZ߮Kp474Q#0t{Ta>Wx"_א_H Blʮ2WUOߨ+$;ug(UM4[">e4ɬ&m~؀5=L{ŰK;7]/ !p-# \pݮpޤ#Ȫ-)o #} ?lL<՛Ԗ{1):/vTM=YUj ( +ߏ_f`^cj^eI: >rYISSҳ9pG4ʕΛuln[䣖]RYwHj;)+ g-8–$+Evntűͷ5WZaa{h֋&\v3ܽTS(DS4RJ)RS6,R$kygFZһ )Gme2=GZ˖ Uv+:!ƒR*60Z`^+49H=5EJTzDke`-A&'OzHMmא;O;7JK )ʦ_q6|ŚR|"T{2Y)bx3=uy q ÷mjcBR';9:/,,W q1p`>F6|*^"6yO[o>0&C?cŎs7l3&4V*RWU`aFc\-oaʐV}{_'4Iω=ٙٵl!Q/~5O 9LgӺE'־}oc!+;t (@^ ⬺V rP v8[6 bUѺv @<A@(d2I1Tݙ !Qns~PhAeq!@ńHCF>@@(8H2 ! @&}$@q9ߑ)b]Zؓ΄E+ Y4 a456j !>/ L%PI VnE _+w缞LY5ۊ*2C]}P0v/3 Q܏H3]&cr .Hb421*[xb])SiygKN[|-Efу'Z-SjGmؽm&g+VW !MNCIDNs0+ Q$8?.P0?γf=/A$" X9-7$92#XW^xw @UYu]*x>eJW|jyH-ljW啋͓NkJEvpj%fmgxR̍Ł3E' ">zqRV{%.MqI"Th&{74-rKe Aj1eNNy3^Y \Pm^Ze1{H fL|f̩ݻtF(Jp*"̕!@lvDY6fӦZ&g?/xؗzhm)9%>Oƫx";S6V\G~ |V}06k%`ɗb3R¢%>;q]NDi;ʶf37-HjEl[“_xl1-U,3Pm!xa XL`8:GƸlW|Wz/uXՓץh_mZ䵕o.B@Fq÷/?lИ IxkL"ҜΉᡧ+dIx-I aCg"UTy }GX(A"=D~e G} /̾ogmR?gܺ`}Ԫttz#[~m2XS趾 h3';Yy.+~[kPV48M.  I=HĚ3<*җoҸc% Ś>ܻҘo/L@@@/W \*7c?-V}'(,}uFr?,Q|i Gΐ88'4YvZ=z %{C9SN9[៨gv\jՅ`C6ڜV7/*9kD? &A@@@@@a C"=_O)˶-c~j>d5XYygVU}`5|O3WLa%EF]E4&b}- Ho5?[Z|kXdxZ5 f2#i-+šcrZ|IhvϠ#'6ih8EwX8?C^sКOo[Αа >r"j5?We>{.fp{Ĕ6lBH@m֟~x%_1V\r𦇎 C9hٙ6+Qqv]Z,9bD?񪮚)G $F0Z۷C o{xlSeʗ:nNvӱ.آWj0zLL^ٙKϖxS{+5>۳ x}sJd6W#[H~ϒ=~[ n,-cC@&qjmiv{'E@ +?VK ڞ !}yño}- Gy(uEB%pf]qi+V]X']|sKҲ^\/y3vԇa,pS@Idz$I J?B$BTr(TE-)[_[qh]ȝjLؚHpCc u;$j^勄FE :C12oO0yQtXġwj5ٮ7\[cy;-p8Ćm\b+L79w rjontՓN)6]sS7Q뮗gQ ,NgG|o+ۊVcM#^7/ܪDQEjmHJܚbi@v%Fkވ @0 nh[e =ެi+;U;uSNQob6xMB$I1ivnĽ )ོ,,Aj<}~+gFd޽M 籸&P%!3&L! 2(q+7qs (ej9mRzxzH6OtbW?=uNl4dö+ph3$d.1X>/I?3"ooo(Ҟ9c;~8`EmKbB-4z#PN,Blc @Dɳ]k'e$ 9~sr zYIS/>7S`<.c$%H}ͧV'j}RuTK("(()V(1Zf~[,tAՅ_} 3 jÛxͬ}sgl1$*0x("$"6`Qd2!I@ڔ8aÆ ^+ʽ7ߩ|?gd!Sc!m7y@su' `W䋭jCݎ~i8C2^HaZ%uԘ!C'n L܂;oui IxvSO.]~RȀA1뚢_˨oɩHk5G|5wF0 x] i"iNV!$t#TA2@MrbPE/PI+4a(T!1J7fkN?M]SO?J$A IW^r}bnMy@Kɨ ޸C ~+t" Rh$@@UBR B O+[%H_1q7Y[r1zQЄ骂؏M=(m挷乶kn=EF"$~9d(2B< o7f<ۉ4f:ŕ8{[}DpŠR޿YTC4`kVr腚JB"# $ Sj 4qq.yɈPeF 61q0f:@ ސx!q2Bæ*sr*['5=!|TĘCL.(@Xc$ miq5g"`ӽ-Aj瓎{ ].^PB_⻣M@@@+uXUAYdy95p FEsa<92Bv 6Y8.2ԵhSAǩCVFjÆowXkuQ/PXiLVL)]ltsw=C @!cK=> //GE+ލۦq+cL65 ښ .u q zx5YLկ񣙝VId_öQgz 6~oO 0*@MZ\ӎCBϗbű/8A"(+{b.^suw5rXoX+/.,1g,d-9hʮU*”r#ˁ/Aq` e61:ě_l]v_H䱣a㋻R*Q!d垰V՚X =3rܢ 2!{!dܲO*B!`k%')])fŬQ4Y-uSG:Y29 k#8uٙ6:V8egy 9)m{vo17@jD}wXTdXVBѺ+8-0נIiҝji}zFqU3!ę7=ħ/@vn(S>bmBT1֥ (n3y7&(48/2B)".m\`d:!'Ol. Y#4rlfg!Tk-zy1=A?х(bp?Bktܚcz{΢w&J ӱ#m[&has dպq{ɀ_*y?D ]6k#Oϫզ+XÛrͷv ?_2d!SN;hq#.& ?)F?B OW[:lOX}_Y^Փ8lۯY}n _L"9pZF_}6 _-q-oy G_ߟ_7P$ 73;JڵÏ ?WoZvnS_9/Նmc5uA3C~!? !ہFW?Ŀ.M@@@@@@?˥?a5aG-T<_-):`%9m'Ύ*g X[ Pѽ1(J|7P# 'OV?'8ιi}-[?^ݬԗ5& ZeduôG;Jdd@kEn\vVSګ̖ ѺkЧ=e쮹팷|`6d e<SiR"=`/LYǽ̞;ZaqѠ& =/m[VVüu'b[f[/*l d~"\|Rame>_adQU }e6]z8pzW_/zXgn%XgYTS N-*"&ODΪ칇:;Ie)k|һfV3z,Џ,/p_޶dUVިFB6kv>ߟ'3\ a[:e}mi1Erʍf!̢w%?'킙o%0c9ϛh09 bU B!uJ-'g޸=y4!;4lzMpͮ3ZU 8雟q^I\!άN69P/H{s# %CroM=s1GOH_kK꺳㕊܏}wZs{UXE/:(\6ߪŰ \ߴCH`[s/Ana{ƯG;=cޝL-IL ܜhBSE@r-{Ym.,nAٍ rpy? sZX8B vC/r- /0(Ey! _3c5*n [<$;=LroҽཆJhȤuXٟB&ɿX+ |+Âodw-6> )2KW(M*>2/'ٶnsAY U3ν0`m$Wq'x{8oo[F=\^@+(0;_5}7YZVcbՓ}vO.s%<؅W==dl.myqVyTїd~:0[o&ȫ4a:-=v]P#L\#F9hͳv&zNwqx9mp,盶Whԩ Ɠ6'`77?RQhŤ(d?8: IZw|uBJ#5${D Xe؈w83iϝTPTiʗm '8ٕVi X\V1VddCU?| )lmJFQ*}:tp(j֡y6:n@ H&l$<@B@@@G`Wtjz])t7؋yf_b&&㠰 +x,TPd܀d*P\N@x9 k΁]w {.JY[͘w5aXQk[O-' {D5ڭgI [{+~5 (S%P< (dIt7/2X|sv4Mw/3)n;z)z-֑v:_nUkəc,67їM  3MTh/X6HvOm WX ڠkDEtL_ݮZ}`&e흟f803>`_~ &H%ʺ&!Kϵ.o _f?e@HRYP)2/K9sK9 cs'wL!MHL\dсOo+.+ȾIHSA 9E8  ;&wtqdEŅHP CEXXJA"#gjjٺÍױ܀t] G^뮀 ۋ8:uD?6E_EԆwXS7>yrh!@"I?XCШ@<([:9:F ',>"W17>pDT^R|rIa[um3~aR+f}}uxszeKRT1xzZITXylQa_1r2h=`lѡL,baJ|cg%7k7Ծ~PI9kܬK{&[A*bLx8xJ.lb1?dn{!q)Fn;Q΄6LZh |l}7^O  V?~Pœ$hgr*:^c$1@{m0FS;ɅaT9 ꫈".YUqݗܱ hQgTQ&) c(CR#hy˹NM>d 24+#nڌE[ݴp8|^ pzB 8Ԅ ~pks9#g{c=s`{w}vҍ 6ҝQ/1w幕-cWO<ɻ@^w])MVwӾ e9EL@xz[_O4V$ć *;TՊh_\1c|Á&Ihl {p.sM '։3fhlXU')F\иkUL1.S܇_7Td0M8x{i Mƒ>9feB4zXyZ f[L"0L;ʭ[!7gu-}}Q'<,]O1[ڜ–lHjo[n]?Cׯo#C -'Sܚwwߌ{F/ W0|; 5t2uj6Oz|ܢϧF(QjuZ&7uޖ/gӎ{Mg@^ Á#?nBHLgh[u' DfyG럸jL Jx܃!8M)d&1:y$RRvTuOcA%D_l懖I]a}>r˝?ևgsz<֜5uFΫ6=7?;AFӏ N8X)k|hR њOB@@@#>Yq^uo$lz1qϪ/k(swZXd!6g5boAlmAy*F|mo a=JC _.%9j\k1.Cy" J^W،ڢJ;`KmX(w( sw_txsG84n)jL2 +Q!LBȿKgt%Ғ g:Pp@!,ol9i#,8zAR%ҲPFQEM(dcK-QS[fdG>FZxP* O'f\̓{@zǚyQn:ҺS5MϏ-טkv6,8WH?IeZO%ko>웡D1 bV9'3l}wFZHpر]NԱ;>PtǵOqv-f_;V}dV GK9 Iz rZjw] jUeJs.Siީb7<ݪ_qk~o+.W|m3#{Cv,p 5c{\zZ@*zfw(;!UTY|,cbǬ?8_bq"~|Ġp/n6l*+[=h2 [$Z d?[sx.v]DT+_u+. JQ*Ü_;;=}]F]o5 /r2ɐƟTBU gBx}ѕW|tagW~ʿr1OT` ڂ k4AY%cVsLr !lQU67?X .C(o}Nf%^uҝ:.֞5CLxzL%ro:BVW:hr/ڙoTŀ/6J̈jnx=m !.^]g)Kj_)@3Y~EIEc+~B@@_7~cУ~acV9,-$^f{3t$;E$@k叒2@(dV=]0_طR 76ܽB!#$+kl8 1MjTr*/^y{OVL KP@h$7]Hr!-i񟅵h#,@8kϾaq'&J˗HևPiB"bb¢@JR1.&F"tefa=r|mӨNZxKƑҮnme&X4--C4b~Mfq̕(L B D@X,([Jfklxgطw'M`!s¹l ' >g}dHAHr?-LòZ5B&z,3gJ]Zɓ6% i @`TJ[ pN4Vu*Qߎ *j)u,Xð~D7;VJѲ0)X]F.NOO[E\/C4_ieaD<q>' 3M=h"iW?;hаŁgY3Y*fYb=_-vV]EΪou7="ڿ<ٟOV,>y @^EGM 6 )k'79%? 8E~ߕqD|b81N;^c1]r`Aq |yAUCM滷(W,;pF9lSlLobueƛ S NR1v @G)U= \oL(jvG58\)r*{ 8bD}³nsg "AzrC#qZ&8=`(=~űq-p\\9q;M/>J:8xOx3S-Q'nx9Z{B"=yJi$zOGp eѻl**C eh2U M&tf=: {[4t6_n0;.PX!JYru_"۲ Lf:'$$$s! ݽ-~F/a& i.C{s' j4VwgTsy F/c@$ uOSa:~J?O^mҩeƸcSP|V=[`/>NLyf)5$ɩlڶLUJ3'2ЦE,q ʹ8MߓX]~}3|6t(x9Dn HzV+!ג[##vnt9ڱ7oou-;m  IS)Zۊ)ܪ'aș]ho<~WhdbNFr$$fu#3\rV!U\.5~)=$.9߮h:n. cr*oEᣁh ;c>bx9V^7~XV?wZ}]מKC;B58#8eѳl6KW& ]x[v|rKeG[# ) Y F11hҰ f/,@Ү͐@n֦=ޛ- >\^=%xl3o>wP wgoj/!l}jkWx a˕ 7:w锦#u Af;Fv؀B{Uȑ[U֔7xnJ^g/yLB~VŅ5G I#h@i<&2Ϲ%(.{vr8E 0@|?֒iqa^.֢B5{JQ{^0bۖ> V??ݸkWC !#r ՜DJ2j9ڧk䔰옩J Z~~}?RS2插`1g[\پ>hEӇY7?&).#s^ųg܉3|Tlˎ>bɃҗH6aL`_,/ܮ*(E Z>~JjxNݳ?S~;ȶ.F~P^Aa#&_{&u>ýߖ'L12n [<-B.vpї+] l{Bܜ=?N|Ͽ؞~h@-s~#BaD! ?B?sO9# Sz; )}isuְ?.sUM>K>zYI' 5jo3mut~@뒎=`)ʂܬ 1-~N@rX^QK?xSne,=Wkg_/lvr2Vy/u/sV'fݽR1㭳ϥݡOm;Nqd!,`Ok#kʄn`kؔ}UMDtpk*LP\~ʬjxw#VM[o2b QSZXpw]05;_T\D,JN`8$s>3ٽZ[~gώkf Z]#[X˧Y9Yy #׹}+fbu.yuKZ6lJNSW?];W OoL?X3y ik?9hxۇЩ25py7^*L4N^Kʏ )oNPtDQcRė?m8#"C+d ޞ1Cr<7wG"[p!Dˢu;[_=zn:}U59f|ӟ%~6MYxslӑxs#Lny%'f8=Bk.Wڼ{ /8XZNN.Aq"ʍ((Yw~>L?rgXO,|I @h4 ggeO͆sg*BJC-8GNV6=Cc7qTS}ч[W>Y_We@r 06>p=o~y;6`$_9o~o-u_ߛ#/OMǪލ07[cF{UNwEQ"V %ȣWde!'~g;D ??T]Qro!8n#i{YBIF^Rryu.B"uVG[+2K8mMi'봿=pPp` LV|ub=b}W絵eϟGȩCoovE)VF[A]Mm"&-%Gc;JPD%%i@x^O|VfVml=ujW൷\xȲ 먗+v}!T@B|>e 6(MB[*Z/{Φ! +𣕉g\Hyt!gnLҀޡbH}%PS`Dת0=;kG6ܘM3:28ewywZKVtuijRfo6< D}RYCCϕ2khNN뎦rkn ɯ\BϿ^"ur0:刼)BzQD$F(䜼Q/[0VA!+NfJj=w,ގF rc\ ߻gb3;5?0ޝf9VuV7e}Dj٭Ԃl3`PIP#UrddwbeA7&\yYӬ.u(S *"-L@!vinCgzO,$1[f(j_Z.ڥ}?C!+v)t!Is2nPC5ޮkx.jPwsxcޞ|;@ }ɮfIs{:ڰ9SC/sKF"#>܂ٓ׭4V ):=U׮vv .[ˏ.E!ZjNo H$C5hU\-!Z>Vs/ xч Bsf PX 텭ʶ& bbu7(}ڌ2v^pm/le hÁhBʛ[q76 ~ \yٚj+ ZTH BQYz KFzWB前 D¶dGeŵI 5uJxqdtvj[p^ͻ/24@u `յ;[6>^ƒ>L~ճ6IpCH^'-dCYFEܶuJ'C撱z?J2OwD=0cv0)C;xcn/kL83s8(?]B!*O]F_K)Ɏvn_hymO[:ݶ'JiӃm8k~wx|SkٕId-GsݞrgV e}xVg]Aa4HHcDB/`q&&X I זM o6_{~3+T Kn,")6p@M-ٺ[^IN'M$3e^CُLHC_WՔLٴ"RAKf\a,(%$Dl L=<"ȹ[GRlLC2$O|*v6@_q`y^b뵾CR:\@hr**EU&6rb6Y)?l[xƑ})J,64QM*HMlλt,^䍎DqNֹsͳxz9|a e*YDRDJmpm_IT("620В@'0ԭkbk0h|8arAAC- XyeK* VK%}fr6,q~pzfI=E˭cM4Eޜ|R[Nt i( t*"E0!%iPo|?}@2@FjH-Ixigcrޔڧ7+DDF۹98hfQX6&]tֳ>yְ8= Gs3=֞)A Iw.$wqκ^cbG,QXܠv/ˏHlwT+9ueK0qkꅗwΕ%С3mMUEM={ \ND%2_?,=\U;, PN sJ&@QYI'#Vmܱq*:~\/CQq8 IHF%KhL+_|R6vzcH`Oξ HWxe!Q(bJBT73n5{n[Kco1;O3͔9y JE#is C ?O:v(sba_Jץʞ ~<}mW&yM ՗-xp *}8!zwX:lC9ܮ+HIdCj1)f Bçn̫2COZq= V{f>+AII1AcvKuٳgw+7m݋O& 3Pg8I@ql{Q%a(Uo|vUZpbaBPfylѨ|[mth\:c#;GOxDV2sϻx7 hʔv8%Z9grJq!$):1RŽ#8eӹ2e X^/Lm~c(.؟ԀϠ!^n U\99KgrtOijuV=wݿw[`l/ ^Yt!)d4MJkռmY୒3`oO,Q(-q.|HPu6^+i/I GiXW7) 6Xt4KCl(%\햛XyiyӀli~3!dra^ݷh:{_O͛]Ͼ$hC>Y7\.I VB$T&ܩA{gz+ŝ#)VgS15pcbgE:Ug]삞7t˘?2Ħǖv ֚@rW <30\ǝ7?uTٳ ζr wq HԼ:ރE@@🣏>CQ':iMT7wџk&1.0!DK8H%"ף WǖR.VgHk̔@鏂=۶a~#ǪK)V+0zWur*+]A)SlݎW?Ps+?u?%&nqĮ5k<:mjUd:8'&:-@(2}D9&{wi_ŠP?{#ݿly{o=z][2ra,l0h2}6EtE]pߏxvo(4la?&$C4~~y[7eM`5ӷi'+2y {O //Zd۵uNɓ)*&Els@7>`/D${FҺQ-{_^33:+|t#!֬S" B 8(F@@@@g ?ǘCƧco5ǁ8^>U|OGYZ[8hީ# ` 6>jmy?- u_n-`ӳ. dĆ(" k xV:pRd4@. ׵sY0)#}k FǼ7ϐ^~ *zO)[|x|T]hLYt~zXBITSU*0~˂}YxU'e0{֩hsEꭋy˒3l"^#{wox62($pWrWygj'C:YL"Mbԗ6Kw_7EρD\/0wӚIymyɟ ]۾?(Rx~ }eVVkuBxS KwԣdW{W_5&2:Rv.)Yf{I"w|_;z55o8oN=*mc]VדL -;a, Ȍ4 ݗ$8{5+*|7ޱ,;LY h ]kF4w0/ !䕟)D57QV1c2HYm?#Kb4mSJQ>21X{S-=2HT*J@# 97bo}9rȺgt⭯=&e 6# ҟwY$vcIGK{=\Umƹob^Ȱ}?yE᣿cٙ>C9ف!>tJnLAh tzQ4FZ0&0doy^Ir^x I0Q,R {@Dh_0c}pWA4v(MǛ,QrWfg4ˤdW'vc͙;+< Ė=ib,:Œ׎b3/~U\6 x{NGk&d!ƃ#r8qBƌwq+<0Zr=?V`8ULko($$ ~@NV KiQ$^ގWw\5^ɹmuo}M{ꑵyG?*lOS.P*68Szi3?ݫ6U^dJG5|甿JoȪ|d-_ٹGk묺^́ctW]^r=a6 7 SƘ|+l"e]j;mweؒ=i S%X}b~.Ln9j #T䆖ms8E1+LJ(Ͽu֨C\mLH)JmIC ]){3}q7CDvMk+?FlWA5 bV=ik8=ݤs3?Haә;¼+ ewdzȕc;LV:u K{x9-8v,v~'Օ5L7M^ :Dd!22çI+ߟ܈8iofykO 2fuGO᭟.q_(z==!!ANKl\c[0jjc]pu,ۭd쾌CCDbvhj+.!DJh-Un((|]kxm9}j~.2T/\[5Wۋ@Q_(&?~؍"Y9vo\ؾ^GܣMB71}&}6fϬa*'^ѥ/VZ}&XK,[;[*AAĥo\ZjӯEPoL@rƍˌT4 l9RN#!dz i|dA+=c*;lW֮wjO3ɀ1<!d{Ivd3u|FbLh³/V#9W;>49rMο݈CߩC6TPOlhݻ%!/%magBoPLgCfDZ:7`xGS@ͫ$${9܆⌬esHj!懍TߙŁoWۅ\{i$ўI찅fl+ӑ_ !n1Xt{ٽfsgk~ҀƷLnAy#%<!$!Ok_3 ly\Rpf|Kr@k~gF`yۤvNAS1tvۙ83 $J grMM2׭g S'(Gauc mrcM\Ԁқh%۫]rԤӰ:!Y7vX̚vw\n [YG۩.65Ǜ/j,@yxmnt aϜ@ y鐓dSW>"oPCrBd?q1~ۓ4uʎo[4sXLhxm3iIn!U55BnޞnnnHY_"l1JkyƄ/H /UΆUWHlLZ6^3\#{.),!lgT LhK&cs[ϣePUzZ~T-݈C+/>.m#Ƹيsz NoLkJŰ e^}/}-ݕ~+=i"9lێ;*kվ ?7o&3odg :Dq%&pFq MRBgI%5'MZ{Ec!E`gΟȈWNgiN\tDrKRbz/ci2wȨ뗳L,G 2ONНO@Zޔc7- 6e֬aAaǮ슥=Fy!4zx‰ &K}cx=ouvSMùl^%($D^Ҁһ/k0ؖ)xpE捡frm,"#jn{NC1VQ $!sgϞ=w*UY'lXxym' $I .VR7$&*q`7Wݹ8{^jf+ _sbC&iD%_rscΡ&>i#{uba ;׃+j=ߩ4(h5wUTxlOd,070iۦ3 ɥW8Cm+<[UX(lhճ]#i@ 7rHO]jm' q= G vQziN/Fgp!9 "zkg[7F! }ym:A BCHj$8YRkNnocs niGy|dsMp0zdM,?)PZ0VD0jx/(R"=%2^=I&ݦOBDZι1M>T>cX7 0 !{bR؅,'щnN3_-@[Ò w[|1$ u]ɢ{Y\mӑ_΋SxaoX1O% ]l%(fٙ1𪋞4ݛ,I $ݯvޜA(HLWQ~c7 Ö(fssksJyT-65u~|ۄ18 g90kB&'q fkUsnY^]R_`PȾ{\}b2=cxIZt*2UM\PZ{B6#aq1`~gS;zy<_M#bTr+K$ԍn9ޭMnΓvm۴jckz[hTQեn>^.5 CI_%ԓӥ@@c6?m7m e<%7Ͱ`~)3sDRj{Wm-7X+kNh@SoPѪ{}z~`J/o^㌜˞].vG^_g3. :տ[oK^ 춧|[WwѲsoZSZϘodWߠg޿iݖSF"=pH"flxӕ̕Y A4x8`P(?P 2l9m}߮BqdfuR_v f7@ Ñ?y=>:ټS ;Rah|`QN]٫VA" 2-o jiLZ:n7 c*:]L}֪%e{wmW6hU¥@t$o7aMo{8OS88 )hig(I]y['E Erg`Ӟy2/47%<̳nan#q"tDRR]?o!KOp&ծ=9xG^K3ei?΋Ϫ〬WwEL~ws?p"%~> 4)o;9\l6z0h8$l[D eoS-oم L9HQlx0# JN@@@@/0! qSvY)h[QsB J//k%xa|cw]Mп֜vnӦmM&ڇ>{3K[.]E$@D(HPb*5"B1{Lja,`t齗e.}AM0˾?xvg޹9s>OB3?QB>,Z"~ɉ}$ bC1 l;oTAFubi^W7A_P~mOBCKfNu \I- ]CoOUg-) dۇV+oO:>^cD}/\LW;a]K~_/Ui!uBdc|Á> |&x!C g!q]/;+n2ߚG}1^xoWj/Bzہ쒳a?Оwze hIC2>^^/8m[斠KxeNkѡ3LuͳD4^d5JA\Ri`Qxӽ~FӞ{$WȦfW: 4SyK˳n.51p?鉖@"auGocև,[dJCKF, uj'|Dѣ$A%5l~)o{l攞~0+gӕ>blgf Ү1̴p |;ׇ "KsT} hSaP[i@D?Ic߉J:30!VUN9d-?FmlxX\DJ lTdf7مΒ? %oxhoIx%滲x%l $ ԎD!VE!g2Xd]⸓sb)u$Q0.֒då^WA%-=*{uwF u%3}s?rK=I70!l2\)HC%܂ެ35 D NEgn*HD9@UNAkBoD{H`O>>vz ηſ:[bbek`if=WL<2{~.cϊiJz?m6*g_fjM-=s~wTܤ>ʼ,lݚej}Ws8xmޝW]qRTr5%'Op 3XBK_r=BxщX;]S }839M-v5ɞ? מ;B 9ҐvI :ˬ&}ҋ/6Fkc]] {0Urkou;r[?N"DxLy$G8/*?p&CpLYFMnʋ ܆l)L~#r/],3KXz|U#+7 "zeX/}w#tȺR2wM SZ:DŽ”.&v\ xSh+AB@W;,5>\| z#=oNك kHbEge &(|Z?1.j.w& BX*`oA܄V` nfwV X3:Q.ǭY\²J܂1A]{#},N4}SCy,%=fY`"v-KYk\ƎJ^Ber7 Vі=6>ń!P&{a3șeѐ?}QR6'޵DM|8F!Mc3U)GWۧQ]x%=&}rbr?ݬk-'ۥQum3v_%3~Xv1-u ô׶o `t]`c'- @=ZX=X*eĥ;"vϓVDT6Z+nS#'D-9hR!Ԝm)U?bnެ0Lb|>NLVZ/P\C )MbSmt&_-;QhJ!UV1_5gk>~W\ ?vIB*sIQ+[IŖLTz={1AT^^vtP\oD!9y#SٹQnw} Nɩ*TP;Tm$B:QD_7~,ǼN= ^qE-%ҷ|$" (lc&c-/,͖ɖ.#D8o,b$^p gh]H01כ6}&"*!Lx",*7NPёӭEnĥ~N"C,kcE8i#T};X@Tq3tA5ebť?_-F.6fLD[= )`24J(wOcP!N5Xt㵄8piI6 l:\͍TEa^ZB^tnڶ{ƒ=F"Ӭ }qL(Ҭz:)[!:.|g2owkIԔ| 5ԇL"Zw;|{ Մb\wf2Veҳj) I `LG(*wATi- *)j1퇜xTg>̧‘b9vj# _` {2[V76"WD4rD#ii-ҙS|>›|oAF.^u z\ZQ$oNO |yW'$$T4&7~>a r7d`ʒ1U:E} үtws.&^Ok(LDToqEiƶāS^ȑPYT)2#u:n{#{`B(W LX30aоַJ SqrhX]o+lY{0E [0(0KKg޶m1WćpSCJ]X`IC8Nu& Ħw_AHmZ7OgYT_fP^m[W`֫]Y0jLH"F95fGӕ :j!7v]v+\ǩ[)KRՒBM=/͢dN̝|{FXqGꎋǗO9נ^NU3ODppS$6`43W::'Hpμur78zSIg7Ǯd42.X-/7ly>{EZI#@V\2!r,]*H1mg!)oGNF=H,xݳmy/jPTfQNs, uOOq5TymGUѝ~Za*G6RȘ/~q Ⱥ;>gN-"u0x p2(smgcm}oH!WM |G ¨$3/dټG`Ui!6fBEvIkښ54v=t5}8bp q[\@lǦ^N~xcSܖo$:2x c껸Xi&2:V{ [a ElD2cKȎ;ULPj}UB>5KLFхFaÃ<"bӛјc2u܂q%l"7gLq |&14ˉSqwTi e7WNZ}!ٜr J 7Ll<4mG@[Տ e֧Y<>N@rhD *۽ѳSؾ;d%t.V}$y Zi `:/9hT 3AKw&Be@~G? Dވfn7"&An|ߛ]Θ3 /[(z6!>2H-zP<>ј|(uHLXs#^F ԦƔ('ur@қaSG c:ց1m]#=/bZ<ϵ4P.Y~gGHk؅~ aj!cU'_"Nef1HXXHu'˘]'iٱ!f.rs]u9N" :_ڳeCf XbqSvqŖ2mZBrޣ6~` mKxmvi ё2>D'w ؘ}_pvTNA=/4ZxUxd۽&mchJ'Ilj/xKn7jB(8Il6NNv 3(:N}ֵU#^rPgpJ#sP[[weVqVS^\]"3{?06d{HƣJn;ڛmMMKvůg-p >W=zz ﬷ܧ#Oi,1//m| JM.LϺ@M6$OZ>a_ouּ/-7בW_]cU~zqڛo} ssFkɌ84 R4R%ɱ}fM,bN|NU[˦Y7l@ 1opj\?y6-#޶ @S We:]OFY{[/~_5Θ3bBV_?3:fQ(G  @͢B 2Ií8ſ_H D0*537>+?RO*,nofrÈLgv_omN}lJə/ 7`xM' X1!T1 s\:r5ŗ$[c ;߿ [_%NS'ZG}QLM>? ^r2߉R&g(l@Y1]D?h3lK f埍p a6-0eW95? 0 S[#Vsd +li="#VSY֫eܔYW6q׭-}FH:n7J8]}I>M'6|2<Z̹+BF083jO&֐!2Z*P,Lu حCp [7>5-j(%r:-GT@voZ!n-9؎(?a`q-~Oį"&13cHgn 9na"RiPU iY7,^404aE$ݽSX{-0єzlQ TaR:3oO,n2r-HObiMgR_Nig9Yym]RI;fN λ=9hhiTYrnl_"$Å.;DX/l>og%2}1:S{{e?Id.T|B^3#ǔy-GGu&rƛPuW_S)ݶ,~ dmDSw3ꚛ%=-u_§7~ ! oJCn~a|;DlB5K ʺ 5/^~af/ZZ~x-z)#3'j~yE!Q~G6rX"h^ISv~"9EgpћlJ ӗ7%Y佊p\M XvG O(O?12rXFe!;lh;S𳲶\PdZ 9E' c&̷' xbKJ0PI}W_8U|1LT͂U0u+=`W^B/σ.\ }cAM-&/}7+ y١o #9Wp27jSFt[$vnיyϥ8Em!9;W# 5Oڼdӓxg4k"->vī(JZ.w\pϘ+WC:R7‹NW @uItF_5V;*nLi{Qq3\zfne< NKY̤82'%U1v#P[+E|=*KFt4W5}"q@>Nųg@rXOm3JA[a<1H}PEg~ۑ؞3D\NJo7g؝f0Q5oyWLD\9M}ɍ)t)ңS؟톘$Ua勣nZ*ߙ쵃|7=2fG 0v/ ˼ōnK>;4|7j IfF@mEm#590$%yKhJݻ$1C݌e ܭ$nz*f|2|o0(K-fw:fN0H/q4?C؟CVzM5ԛkw{Q%unX:vch{U6R!j"&W*[Miu$.qt g|(Ӷ>k98aN; îj`_>;hM8HUT\n[Jk?{OT;x4D\ ~_5WފafjFiEa6f5|mv04iz Qn[EAZs~d+cjn:A_U֜* 3uՏת59jM1a# (f&K&j ?[6 GVXlQxC=ZCjȼ~q[ͱԖW6^DV-  tqXs[!n;~phi1lg+ﭵQ0l6~}Qu( PY`}*i{2Ec5MgܪR{&k(𦥈<&tq?!95I4wu$>DՍuhW5fYyӾ~.cћô-b9tHevm3t]{.(#q$in%q{OG.)Jn˕(P"=6NihηBdQzGZΤn嫷#ϚPhDa6 )1̠¤$B$-mA==`z!Dn_g,J\Oγ| o/73S@|ljWxTj.kS#.J"v.C$B媫`6DS D4%.ꌸF#{q:VBhym' qT>/=j,er@D̓}19\:0XǷ;XԖ#ꂝ*@_-\tD3'?n$B qӥ| ̌O^:|:/#I~qq͒a!) ^yy:!Ԝ"'}9Emna#䨉my2:DStĂJ5?%.R,^vd[>jTM@vc"8_#8eND 5yl8E,4M[.F/D<`QGk% 1*7HM;^D]*=u,D@yj!)q2Y|@&tyn$ bSUIsp*, 0lnuݓ UW܆IhyMҒWyX#P˽TP_-+ݕFVSLba =0RÆH9 @C][%IOgMOVXy.)*df߹{Z[/VݒB<`#<;gLѾd_5WKY.ۋYR4Ve Uxĺfu]VXtpmDՐ mѓU˲xAd=-)>e'#k=}ƾlݟSm;vxACuH/;w.ֱu@cAձ뉍Nh=eym/T& B-}GpP`9l诖r [tͤ7 _؝? !@v3BwX9lm^Dnjf!ZJ;w삉noWjP訳-)'^rFqVf(θվ9i{Hlֱs나Ԕ<tc z*}BNS&]UpVV^GT 7~wm/*xg5l@|+b]vM>V&Ekc f?[ZgqVżk(:<D#_GՏL0!!! 6b N=NZ\|;z^GPw=XޑY}UJ_>03[zzJgh%gK@Ez(BܲX) ~ĆxE^=(SH?Wtšcԝ<9&@XcLXTi{|FhiU &!1@Kؤe0?0an01 x "*c@ ?~)A&ZzxHxΔz_ZR& FdW=mvs)dsVrCĖm;>sn߷Xb~sGp#R?/_yN_6 ۼ)RxknevT=O'.~lɌ}2aFP̼O-g b|%\Lp Af8+5˒>(ib0 So7R~`6*՜c֜`:K`NfT/7733Pc1;2hURȝt36\x-!v`A6 >I﵀s0G+'O:G2Zi*̺ %=1Y}cnqnD8SXf+³l-C }enxܘנHΊBjj" Ɯ~Zm+i*IЏw|s++vqD$zzaPQ־BVPj{wӗ(o>)F:׸O@4᪖TqK.~8>1?SŋWh[1ylB+ulT(Mzη]R2"sOܲdNkfl`¤hYJF&榾HLLLL|"5^~5Ļ/2]OV a^{76P32Ț߷[f)ExSYRq$:u,Zc|7<Ձϟ,@!=U=F=uUuW vhx/,6~.`9ucisf#V$6$2B\u4;oDXYˠW[N AKQ l,Hcqm)tHccpJKbdl##;"B2 nw<cYMN8r ƂgeĸiTTT~LgѦ=jzDL^#>FI=10~ @O4y"[jO?~i{u$/m{B6RULW^v:*0o>*@l}wb6cR-̜@vHF-n/}U l箌yFM4< 7S(K6Y))o]Tt5|<`N;L}mŕr0P-똷 9ibzu†0iZC(*3- ٟXA!mY/ wu UG!vs-||<]@)Vɺ^")2 .(ÍnWa\ 316DcU\M׊ҸU@uzǘC1* Sqĕvߍ1czHx۹ϵAUpojN`HU?sAĞMڒ N4v_`1r3"Yq7+ߐ`sKs ^j[ϿV%1X~Q>!tz+F"I8o?'q.}<= V[.1Bdd]ǘa*nLn]7ٚqaY*0qݥdդĄwZ' R}l9z/]v>iel~sp^! :/iYO|i"@G80B= @~֡~zE|} r`!,6N8!ٜ?98s؟xqa !3gko-ݭAy;@%0 hCq}E5O*kƏSe:7c ·:X;\%egIWfɰ{g6K8Y4Η̊n>[B_/CdK9SVgMgAUI ?:;s}OxM~6Q6sw'eď/g'JN5u׸ -+_z#@ϋEvΓ3*יLW_ Yӣ_0@$"pAR?$pgHQ_E0Jşm.O8tҎ1dk 0o^݈9{чa3['olL|y6 0YN{v'DavO)n=An &>'[@$BN@  @ @C _E  @wHp^ q ÷IA/OI76A E+1qC}}4pלɦNUdi;j:fNLwɛy410s]{888`&e8[)AoH/6jaQ?XyXO觥K}\m'~?3`ם-A},gz,  r+aL<L<|w!AK;?PQp`aC_iu 0Չ>KV9|O^?_pᔜu7SS~m5/o=-5k}}}P}"KzOpև ZT+!#9N: "c-컳6X^Gm*e&nMR7Ȼ앇Cf!n57ӏg'H΍QfA֌+:c1K▏u9*¹:;w^̌viJ@yo:ϡYl_f:e]"߲+nSV%i@4Ŭ \!6˄!U 3}F3 s.-"*1.֌aMtԔ >'b|i=>ACXyuyD5=WuKH*[ae~3.ty>FH27T6!B|ם}y?֞5>#/|XGƣ f{ Qn%5|~s*ZOZx+52]5&ȸu<@T mHzN[ylϢL*e!:*M 57/~]7x ("9%#o53[KLPDg&fSƩrzbyۮCm2)}<>CQh=ŊKN?~Gnת 0pG:2|`rKf0|1 !NeP1+|hS[&. }pO DerPθQoS]mg UGζzJiw/!6\(1|s p ܞ ނY?=y M,5i#$f]Nުy<9P? t ~NO:TixrOi!D4f)g9M-0y# gwޒ ߽02lOg~beSw ehH ;Dub[7ٔ)/lّ ˳rlM7ggsu ǟ5 @/9IVcok,zkc]M=/^ve–-V \?}ې8G'zZT/l| X,ApXOAF̤g ᅧWO2WS @kwƘ<)-۟#k._0Uz?]4;‰ 1q$/Kߠd+E]扐XV1WhPHN[K$(Q6ύY4K]Nq:bx%-Y<;>^vô&ظ/۟ҝ6<_$/xh`Ғf ^x0uAʒPB FS5!JAq1Cf.ߊKzOޫ 5oS2XUWq#1`U9EcwMmֽbcfnE.[j ,FyAJK=,|pݼɚ[*/'e> Yr_B-얜Hm"sKO_v2jÆ;nJʻԝ<}"NtA.S nE5F-I2['xR9,\ϧ#\YfaÑ|&-u qY+f}B>5VZ~k:c[:ʻg5XzN僽 u'G7!-jx)+;>*yX%QqiO*tƆҘ`u"j9ao}KZ+dV @۲P0Lq{: Z~GeLs@6 Yjf!˯ Q{fL]YБ]Jo mY q?-h?ٚ~zU? vxͳcC'ˍбz,tI؝.yIabQ˛Fy/KTu(u!giX˹QB6c=m^OeTuMnKctj|*dx3YX~ں\ /:)5M3d1ޘvvٔQ*fm>\K0(ãNW`V4;~S_8/@%FZSQH?dnvk4%1J9ժf]wGg-&*%Iͼ[K;Z#V+S!xAX)BVz-ۗ%A@c[IiT$OF7i!xN]wJRk8p3lmW-tUWNW%SF"Z/#%8kCI&9uZ 8WI=@!FVUdw!v~ 9! ޖlBj !E6:7c2@dvVF"fBDFgu DMG !.:5]Zx̆-W-ISo,(uoۋ0ꦏ RBx]BPUtD$SaߙFlgEQLz1-*e !99z׋joۑׇ.85\S%hJ^ȩ}f0H;\nGcNS]ߖi$KLdsn!y;Gn' -Edt&YO2e*FLw9uW0b 9J`N@Z"E]C{үݻWrE܊+ls-B+gE?nNUisC~~F3'>HHHHx&+S^Y۪ aAō+9|و򽗅§"aZDf 8_g}WZx˷@eT0 `¢ӿdsjVPIK? Z?5Y /8yMV=Ý'wLi:-"yY9u%E?*Sa*5闃s)Habt*[a!{jMLR@71&BLxu1 #dHD{F=Xlivd;W ?+g~|JU-iۮT>8C#*ymlέ8y!'W 펇vyr]o[>p"76 {RV$y.BZf#xbl'{UmN_1[Ĉ @_SIe[Pd(CUf3sU8 uYq)-e`yF*VHムv&nr|7nGXj(68>befffٻ`i{>#&1DSAtAHȉT:,5Z:Z/a*+:^gٰfu米OmNnG:rQe= ,@>ҵE %? 0E.*zZqoۗP=a:P/ry/$ʑv C,:;A ޶p!١%,mؘ',x/.D8OdC#6)C4ma-hnY-Y!|B+6?fĬ5oG,؟!I .0R$cimaC˗%O{,$P l^ #G ©)-lUOY{;/}=.Qv=t^fr6~*\rEez|gVQABR*촘{gCKYHJY>6=n7Ipn7&=|ߚs6z};,Zźbgr62Q;Kf0= Qy}ޏ:+O+ ߨ`Pc-54b8L0 #6NpwX2@[W{(y,I)su uۥ~6lZe&G ښܒ&܉ bZK{<11110bٕSzN)ND&+R@d 'k$⣍x<~V#sDם725URE!7$z`+YA< T1Ӕ'ӓ\󎯞SvGDLJ?b&RTsbe3Ɣ=Y^`l۸&A+*LZ800ι ko{0"O{WjŨ텿rW3#s :"K[o75Wg!X`@r}'I0:YU(2kZP/]*BSIzDOje#He1r*o!jkR]̌3C"5C|uPYpG$-"pu!)PguiO;C1HC!v6]=ЉY1l $xm` GJ;G훩 V;c;?^ 1՘*[13֎0/xY-D N%/+4}[;a.WfKT2ꬻ햎`]A ]ߣ/Xڔ/6>pٔi", x<d6Y`!?j/U%ḧ:x(uڙ~'Zb M +Վl~\ dgB r G' ngU5|dd[H dmNtwUib 0foA0cs+**K%D{Yu/fdJ>bm8K6=|4:2{3)]Q`$ejl<@Ve}λť [jI|&Bx}AåDU}wE_7ҲzpM oxeDx\M2%í`SZnGNu[4dR">s9hw~4Ev oC`-GBtv^qޞUvL _[E qoFkk`Kɺfwu&[lNaén6[**Lp1*1K_:!t.]|5RgoJb?ғʢs?("hѪ) 8BqʯL4 sr:g"5涅,fy{zL-M9^E4)KafG'YBͤ(nk'7u]rs{@sW?' @D&Yp!\F8lQFdkƩKmya-ɤuUxýKg 9yyΚf6VEDIk[ƾbVnK"#Fˎz<hۍ9׾Oje/p1s6.A+V XۺS]hٌ!Kx煶+1riyL4$5k^mH͹aorh{^/#V2^crGDSډ; U=$_\5[ fI!YooXNi7_fᵕ,mz/ Z]c_ znlo?gج}.agr'?> pC!AzEڍH;EPs;۷u8JbH r",6N8&"q63OBrlS7el١[GD׾`n7!2`tXW\ (ieZśSj5 K:4b+WGyBlMٻtQ`pMt]m‫_(h+N`˩yCuseT^0 >>K]Ą >_D}&W/JZ^am o^͉GU/#!;6Nc`>I D.@5b4ʒ_W͹iee1*޲ds{?C@h8 䫼w}R6Iy9sU+~>LHdzn.=;0]J`~7fS'k u;$AFPBBO~ ?W  @ 4YtoopW->dէ_6v㽀3sQ ZIVc+~Q'3ۿgQ?Z ~z1nP9γ, M|R?i5vLꞡ{Wz801n^ζt mv>l[bQFX98;;βl>nm~+g30 Ô?a?9snm~G; M;{+b&1}od!`WPf^qU Il(1ޮrXėI<^b*>FNly& ܺ9_)0IlG9C}n;{'p\?3T1k^66&3pa1 ?j+sB`BR ɏ1U: & $O .ș}D(fK2-U;*!֣2xqrb!{Wbxfٻ1,ب$&h,IAh6tԋ۠}G)M弤 xk &#M!pLׂɚCC ;W[mw#0NgU28O :qL :jص3's~Gsh*pjjg1ڳ} IR1ngqղjZ[XrHRROKj|ruḊGmp&ʯnmtNT]Of0hI~(g[+s^?LxSǭgҚ+["-Y?a8MϮ+f~8@|>Roz%@8$f/#չ>zZUnʣW5Qb)fԽZ98M߽$GOf{GI7AB]CgFF)Bi.C %'&: "#ƪvU/N]_\Ѻ菊7,FEmoWq$qy9#wjW͏kcT)~Z~@?=rr0\͕MO+PTy%g4D$Rd><5`z}."C,&=x^ktL&)bQ}o;-f6{s9wg_]`2l9dKl/w: 2z$,'+oNɕeÇF;d9|jh|}(p4 ^{t0";y fUZ;5 zEkC>B̤e'Y΋^d3VEW~m>WN%D9y`ad: ?k(aZVխoD&7}R2y# ڇ~3zw ^'abpt :,n50oGޛ qfjJc"u"Jߢ(/{'cG>h92=/haNerÔw`1 8 [|-q > @<4[[hkБQ̧!Z 6[)R0iMu:1.1s4 U`*Mn?AU\FtȪX{f<c5?yUwlKNp^Rm]/b]귪xy-]瀉H ?ƍXef:5:>Q15-윭:`x$D jm/sғU@7Br"X!D_j0Dvbŭ۝fg|;Ew<ZJ_n@!2vc9)BD-Y|=Lh{zb**>j8Ë́A% Pu 4W yqN=nՓ[8mvd« 4Va'/V) 'TZBl0W_tGq 2:BLD@o}kp/J!А{ih7A2RBǭ!)9JGSkY=TMiu,NS+*Pgܨ'B b$97'Ff6oWjΈk@lyeSO 1ӣ%a$uƝf{ wBWG W\tt#!诂od!FVD%1W/vo;z琬;KFt eY{_LI |AS0;32(Kg"IlCd5z!)>f) * 6!PuVOrᦃƔ%fYc3 +kne#?8UV~6Bl~aW!XQD͎qNOQ۽=DiOrat1P_BͷgPA{qy!zpٷP[EPrcWx} :vs-hK5Ls2u0Lmt뉆3b )Q /6]qݶLTu7fKhڸywu21='oWyi!nLׄ98B @za6Hͽӈ"o8گ৿Z5$(>9EraJn$t.Qyem/T;2ViHM ~aG <0[Ƈy sy.<)ힴ#ft,=S/tKntTdh|hm|{tPkhzsX-]KZ߆ 3W|U.,CfvI}Oy#X( $^HjZ`UQ^whɏV\s0# =W/ro ZJN٣jMUkwт~Zåij!֌:DT=SZ Q=$} gc/ wW^m"h҃%@X]*$)/x""*aHδFqI !1a/ G޵yAzF0SdF4Ё:FK(JӖ͕+8v4NT>G$ܭz3.=x|u>=KwP 8g]0~ث|_6*bz0RUޮ\{83c͓lA׻#:|BSbu:DT?~‚va2F^#kޘx泋ˠ|^0D|nL0ڠ+N=(=O~x ˩PJ:0+*#0 7R%͝`iۍݷ8y:i QOrX80iB UF@Hjœ[r7&]ET\ÆJ H+i L~NIP{E/?Yx)ܗ[q@ g$_?]UZmma_nAsJޔ~vLJV-_Ү炷ek-)?Dqm{F{Rc2qg00{%dt8FfPHਫs_'tVzBnTc(jyiu'M>o`"Ak V $Pqʟ?D{Q<),.=C!о^1{:QT@OZ|_fSWc6=+>{M(uLwݽ{Mz0z[P@w k~_쑔GrqTM#@d薛l7{bW"I Z$j~_2QqW5!P ێ`u(q qIe~>޲8`~Yb0ybf, Rݪt]+-x1{Oy)snM졽n;d$}T:IZ^!eU1}P,|JGTu9/"BSw׾9jl kS"ocwY{y<8 'K;IDATyX $a'hK$Զ[Ydj˽i- il{a_lN\:d-ÎNJ{uXwL15ޘB9&!V~K1!F]x6{N:²}5ߝEw6?V^%TUpBdU::U秊ʷeAq.Orq>01OgSO?"QT˽0&CSeNrmwΎ)+g( 2D>dGlϋb#5I^#6~D(lA.Y>R9;cE#Wf'nQռM-bי\zFF@%hUIyf 2n>ÿdEc/,+s6ض1. kN)k^AW8e&寻t=cњm#V%rҏΐ񖎳* bqBx%y!yDNO:ne6}KG~v%[VD kU'lN#D4<isǏ?~<%^uYInFl9QwSEDQ$*NDu5R]07ܹsNܵ؃G( D[[lyrڌ|\Blp`EbDC:mIk#BS{߬&s{>DLve! mى{zjF s뾀.]?Q7n$@GBV0o[|}I[\buܵVdex|u5 jbZf7_Dowθ(qT\|"$Fy q SxUƹ( kw$Vug8>-"[>&l>ΫΦ5p#[읯/ <#ζH3'ۻw5+pJwpr5q%:U$LNd38w60bֺ;=r6xq:!p˭:q8in3oWB / c+r|*L\t0ݦ 3QhP*DKB kFq krEpЇ{oEsMDx(r<|^ Dd^g7aɔNv3݂1xɉY˺u42&;kjb ( To[,߶٘;L w>ؤ"zơ+%qU0`Mб,BYp%l8[|]d˛%Gt&Of5i +287 eS~~qѡVFO5HJ5oôԼ4PcA3t"[tY;L)DqVܝf]y)=N׫dc2ɶ36vN-}̼iCŽrc|U{[/Y{ih<'ܫ+l,5l$ ܶ&Wd7<6!RNJnom2q}/;YdSx^9zxLxJCq*i5.bAGO$'&Jt\)˥$_D$D`qg3L!`8`1g1L "$x-m!nrLѳt׿j}oZd_hLڽ f~ IVSqb"h}Z 1 ֝x^8xI;oh>~!LMzo?҂:</%IFT8͛ `@ o-) FΉEKw윭RVWͿf6U_*H#Wry>Pғ%?^ HZEi-oN7.}:)PGc^31N~'9]SZ{O#>/G웙NcKQoJRa_o 6(q렋~z3^|W+I sR݁K|Եvv0rƅ@dC.! N.[|l!׀9w;}˜*\lL߀%uKNoK|eOq=GaAέ5?7^?Qh F)|O |5ww+>n7#-]+%x __ (1 @? @Cv @ @? SłM:DV]" /ATމIg_5KZ^ !-eJFk _ܻrU8+_huLF`z )>#՟]|jYn3l F8,}+mࣝb=z;gu6Q ]יfz&QWBi\֓ T):[,Bclu ;_)Gc?=q,GW鍳Y.kw^ct*PLwvq5WИ`c. pN>35@_0Oo bbq9T@Lg[;,\s#}$-F'gW.eL}wސrjLC y)Yus=~*u0#^)=e7#22OӐ\'uW]ez{nv!ٴftfi-Mizzw5=DrMWQa|ݜ֟~G$ r–1#~cT/<ڞSU@e7} $fOD'c y!0<7WI:d' /9 P|ҹذ N>q s-i]T'.yԙ'%B815Xz+nXZ,3D[Ek;ƫR$8JI-|Yw䍾8;1a]#ͳkPA:o? =c$Y 8kkʚlk{B[`'{+W}͓3U@JGمg|f.=Yӊ g3suOxbKcn'+Dӫ6Jrf~;hE1BD}B┨w$B EBk OVkKo%Iˈ&~j_@ӟ'kt$4I{[s.8Pꙻ{8 9O[5^IkxR@7^a.5#[s?4ƋeȊ٘;ٔ6 4|ْJ"u]onj}*=\@y>R-~=hO!`Wb7;ѩ-cG*k챲w@=e = >ӎq+G #_cUtz=%d(P\θ⛉9};W΂ *C7Jpap!n9Io(!J[^q|R,+A~4g4TV1q!Ig+ce|]4R״& % C dr͖w84 ۇdIpX>]x[UnʣZnA$}/hq`W24w/wXaƋ<5 @'\"9mÈ?&՞d@o/["DՓTu:R+"%q^(,{I wS@C#Q[o}Zy}.3KK>.hH}mYm7Tћc6`W`brncr{ԹU5ݔp{ٕ"&`^JR] @WvL6QѪui'>?+U_eʠqΪrzRxp%`8 >ds l|nx֧,235XeOO3pY{-;Dy۱ mE2ys;y4v UI#Ux3tV@¸ s<:L42wv @ޏR0ƻ;])bt#X' 0ў޵g{'BgaN~  Qp{wMoO;9,mmb4-xjԝ:ba.rmҰ^tmg,dU&X9co:e_&U/O\{*GcMiLH[Z_ ҚE#g >>P)\ӂ3\-FxAYN%=5jL9u$@%w"h Q0L&2YEhIlM$bVb60rY+Mxo%F-y,0!u @̂kk}}t7g;O֕xg׼D1 S]Jraw:hQF̌|X )}?%LB/k ODC~NՕ0!Qzs*M-Be)%LaRT-3;xB皆7;n3RgѤ1{<\5y|S6v:Yeú}$B 4w޶KFN3B;#і3d=tC:W(KY 8V1I1`43KR}h^RWK(o{HF3Y! ߮j5] dylxe]&$t8A#Bd[NLotvxrU1Xxkig|9i8:K@> /f5\U4j2"_KLD6|5ko>lȻ{Β!N7i{3HxQ 5KγG7{_-IU?(KkJ]i竸OOf9Z9!hu_^uD좣"DRS\m2+g8E[uBY@wϚEߜ5@O߮a!) 8_uO rX |n!v)>"z)ᣁo7 SgN{! @r;z{Qrև<$7ۢ)"D7M.y5ӓm"[^7>ޔqMb׫UY9;L"{ viܭ U^qa8B%ə%?xMQ~`P\FJ0ݖncBo}*ŤL[!ےKX28 Ww]>v3yK0#5lx7'"vC.O|1@~3B/?m%*[B& qn== j_oڊob_[ܕNq&j_AA:c1 n͕iwbF6eg-{tj=]b+V_ -qbU%Ad;޴aq WF c|ݯk#5FP.$[%)8[ 0 wr"ҦK aiYҡI5X^3vOγMo3lg)n,,[LuI?N},=+$؝xM+Ws+n(XujMDIfy4Ub-G1AŨ?#b.hJ'ŷ>]KsC;C ib@Ŭ>z9V/`_ ~f#!?֮j*խiiߐ'íQϨãy婳no;Pk>:zc`qzd{UY;մ WW۰ O]U4q QfZ)|q.;Y7I'Ԛ5JI)8;1hֱY>zwZLźLeO͵yo=}ƃ7*UQု6aTRY̥{|]{8w75z3 55 /JPuQQoΐNW|o\5"*_}s{-GR䍛@QGw@3$IfxtR+b@* UUZRp^fb H*E;ٌ\ :CG~cfGg8WPT$n v|HqqzPLԴha BB@Cpc+Pix-'EL1fUN.^K8fmU NW|?fmX+W^êOҳ.B◦3 Zb@kD}թ# FU&}}a  @)1]Y @qj3?׌ۿﺧB%)DX5# =Zg!RcF(1Jŵ?j8zmLp|G<1C-2<.aNT8TDEZaU5%IvHs鹂9?0 m:z<诞/7 tnqñj5a#yEJ{(KU'^,pܷ:@WWd69 Kq+M!J\msƍ0c{u$|gׂȁ+ I1՟n=іS+׎Fєjj"I 9Qj py\FmY+ t]ZL,M-K3m:/oM㩾U6m4yF\+/~"#&P 9=XGgtW$yߖ'7M…THjB|F߶&ժ~,=]Q~7lǸIt KaBhBN3eOmGk@©5L<t[ܜ2|p+UMϱфIv hN#V\i?"ޔR70owDWrzHNLmz/lO/ TOcm1RQþ>rΞzYviΓt)z5w$E-I4z^N*ZF{.hPUWIZQc=g*QΏ 11sTps)|TA!tɵY&0—(hGjY~{jr 6c֍”ވpR5 -w:KP|*{G[.ޔ?I2Dj唝"v9VKѳmաc !H'WbFwJ:0chw۞`MꘘB$i3j΅컻F;ۑZZ.f$-q\Wj kSuY@Ӝ;e !$Etq암cܻlHBĉ]&* .i K·5gLe&V=W.7ܲ 0.j1e&PsХO, z!!mx<HgUA)=Ӌ~竭w ԫ}ut%GWL>p_cs bǺyGz2J~.§"J"/Cc;Ϫ>W/>O(pG;{&vz3)'w53t$E]<2B>6Ĕg7bM]|sqg[i;cb/]|7(R2c!&>kD?5 V/\^s39}ӧbYѽD1!DZQ*Xx>Ƹ$Ct]t}A;E),+7}WO].}TBS#,4[.Wc.zۮ!:#׋.>Gjرl>I Ps7ek|bӑW\RE*>SGyX zyƵC\܆l{&}Ƣ@MottWx^56lzEJB$9W <#>NeBeGz!(4+@gZT5;^ 5waN$Uo Q ՘wKo:ǀAzt.npmvCa͟GQoo@#4n)Uz7rKsu4UAB&PN9h`Hp){ӄFn d m~P@I_tE .Ԍ-! y[ 6V"#EJH:0ڙ*fm;::Qoţ-&wSo<&Ҋ'Wv  &~P#C||zwcu%,kAyq#{2$W>Ɨ3{=&`ֹW_\`1/(gh J&\>%W;wk# Fw=+'o(=704Ė/ " ESPDB(P$>F)P,)7"z<p^n eӃ4W~qt\PaouO6򨌨U]}ϊDPyOGV燌x¸:y9>,|};7DiDPРU5\ :x%>iaXpii(s;Q^F[9_gnwcZc|<*mf]H{c9lZ _{e|s#9OxHEH+%OLd EE+c4vhY{"8(OL>aaay;8 Ad> Le{0H_ʁ#..5i0H.v=:`舙˧w0@QrX&P_AwDlvu">to<Δyx~m4iFX%K`aay[>gBhp)YXXXX>#gaaaaan RԔ^>M7$bP}vW],S>DZuexՍ!>.|DHɞnSa*S/Sf}X>{1e Q8\ۻf`cin۪1IC~(DVCi zHMm&3qqu2p _~yi}?#G+zFL\[oȕ-~=wuP4MnJb Q0'Wsutpl2m㥬OAj5\=}"#{uuwt,6 "zzaEa!|wmߕ*f$I>Qڀ3ZOZ%ϗ:'Rvi!?YPyinҎڀZՉ_n!ѣu&"ͻ0*~B!N ]bA_Ԩͯ{V 8Fqe0G`sG_Љ{8yYSPZr9 ⣺yK@Bܞdaϣ*6fWmX@F}Т&hk1"?Tkε"Jy rzq Xְ1+Džr1vݢ?fgVuuu Ä)6rPL1SaZ:iֿ VN˯Y -oiR҄Cv'UЌ0XGgղ.2ytC[Q FeXjh\_e @·=`9TP?:^˅+TLaL?=@7 %;R\}|@~9ar}_ 7tv!2^@5iG .Ml̀Ȇk6lwZ]|v0'NBme r/ەMRt݇RTV7esH/s45h0y{!_}# fLGU=(| _LATj*‚Q3?`U4z5YkӓY2dL!_F#.(˔ߜh1X=NͭjBK|ćY|N(S|jp~KQ5L.B$y:y(2ա˯5QhM*i:/@/uCӨ/0= =SoEenPR_-km\h+YӃN{sf;ȯB!LiQ/k>bJ. 3T;(te@e#zڃ*D8= 7cJ% .VӒLOȮ_4}sгUJcUa>viBHŕuҔny{cOЈq)w?8w.U~)Rzeُ+VaΏFՋ !oI 9GX답wT)# S*-A(eRoj [&pFl>M.epͺ̽O2.1[ݗ/޷edzbD `:?A0"5o֢èMwitNr8Ǩ'"iP[u{oʘ+ۘ}CY/dnfe"Y}%? ;x:j֘t9)6@VZQF;{xo{h~yUǛsphhԬ䫥 k*H: @H\~VRRޘpT[FJi[krMGD%P W_9N=R.9ܲǦ4jsܿvœ5о4 {,' {u 1n㪸֛t7Wl] 5͝<ƭ*Xr;~SG>ptZO-dPq{A>cĎ7}GWC-K>ksK瀟YX4"|yxjWwGg7gG^{˔<\5D@w&a;:IGm?cJoǺ{'o4[瀯T%o\1o7S!+bkE .n8+F7q8~e$1jYƀ jt-ߏ=6z8Э \{FO&e#ֽ@-t 5bVqe (;ۛzC!!{v82jtInFSNgK!K|LvEkmzHJ3~@D9G]P}XTƯ @gx?'q h*q!Et?#b"JXu6><֦TUčvXH*Od /Mtj?-]<<,8.JURyÛ % a!)Br5f="l;Tc^zej_AV^3T|sBf {Rń-[uJiB+3J)6;:UL!C#m8̸/ T\c)UB0iS7pY[ZϮFBEz|GU&-BN2IA]&M0*{W{l':.bLO/΋76͉3*`!;f 6LcJoguwWwڙ xjX/"D]*'_ qM,#a >U@B*j1)bl5VcMcg"3nȥrB]p~^ !#QRBcprN 5c7pGjn= .1r.<SL>jt j)~vswؖQ{.~klߎ^0}xGK\Qk,E K[uޚ&%SjP Ct8.)΀w{V ֵdJ.s]= R1cJo;q*+!MP'Z&7@۽5ƳLqPCp|7X0G{h*!LP5Ma B*q ]˚yZX3+|I;ݹ&h=Wf+Yvy 22jE'2Ln x.Y{5i&7Iաꔐj@q6QE:[DLfFuKkkTZyhS@<~\(,SJ*ƒ*٬<$-u5Ԓ<_B^^6&6>ɪn {[7+~~3Rx-`;K1Nxzy;72540t+QI"Bu 044}Kɮ}u_ sC񪃼YW\\BPq}ජ¾\7l1Sza1=G]JNtrf[(~ &Hï+4VjeJ^ fiB(qiMծ"J /Our!WZG+7)m]'ݬ %Lu霊S3,Q ^[9.>- z6[Th/ĕ%"6(;aus<~\9U[޲X$ճQkĭݛ8 ǓMW<:]m9qi[W&5CS.l9<>65Ҩ.ޖpάzCc?[rNz&8'/9h&&N>QBvuUe&5MMSzT7UQqǷ!M̅]_TMohuڗ w˶3~0ݯ۩f~Ws0NRTi$aS5T5hv:MZ^?v7q\۴ͰG\DEF\񍘋J3J4o~2'B@VHpރlj)9Sn)kxjrӖD<eoYE-|M ۧ2Á:~,E_/g:v.|ށ9;^WwU_(8~$ ?n*W,a8Rg(5bx1 Nѡ}V+g2:e[P*~@MՀyr&xTVIa#lӟ62aIM ڿKzȖMEQ7sTL57^ѹW.j b7@)f! ݥiE;p\|,z՝UA6(0|<7@ ⳳ7$(vUy1uOǣ V iCŇ@\5mu]|h:.)eM{/s~0sogW[gGxTzZ.&tP H5TX͂ŝrU] /IjB)KMYO1M_Z̙*|G}dޯ5g>~h|mݠ7M>:OM?%"[vsTsXB#V!.>։ncESCIi9\}o-r"H4s5馕C׫ UT.$B9#}c_%fl}j(K:Y1l'@9Gv){WZx8w|tM>1{sÐMQCE~IDuLU1/-r T_ÛIoN~rIh @T*WRӮݿVoP:@mՐs|_Br^Uf}\o@zdǑm8j9fMʼnY8ɽ^ rASZ,@)tG~d\^~N2K*#zrݥN nr[)ZTTkZ@YN{ #,Uͨ1&RҊqd랉i8(ro &]ۂ8츆G|h3`d9hj!:32,p㙵Y;V/PUs_ %>#V([p:n,ߒV+ZBnj N>àˆKk{XA*H٭?6 @.x`s];oN lAh修h|/tpm{~54q 項k\"qq909&j`Ck_yWj;`b[^U=Ә*'s'L* J_j]-)1(s!%v+E[3〫CۡtԵ⚢Nzǰ{.> ]fH9sUn]296x5vֳ6 {?i`mtS@)1`ER*Fkǧϳ^ !⬓ud~ѻ2TwօB sٕ Eɛh\Y]asTC,qg ˜Ի>]ݎ8M>'%L͵{N>=Տv -u W;Zj5&Ȓ%NAr1f+|(J؏;#%7t؎:U5Zk[:CBe ILPz2Ph%6{ޚ@ iBGjC>J$i#?>t>!ll#`PcTyc WHB$'F;;VL"M]ivrEMy RrUlM/)J8`l0htkDXi֞`C@slCS(jg"Bf夻oi-M]h"sX:/@0|o`%!DsnSWޯhN^^t"n䩈0kZsj,̘LdL>mkLCElXG4C)8{!~ب3+Bzmf_rs.`3*&[BKc*sa*Ew wIh 㗴n})"DG3H#y/LE¦ cۯ*++8{~,".K8fB-[/X0y{Ed-Z7${l!!.2ݍos).y#B>t#30CL 벎zNT?e"13<~ݟV+J mg]صh2R_0>!.ܲ폅Aaq jm;I-_۪ՀǓK^F 0XN9$kk56bSkߣlQy]MdU5LA.~ڵuۍ&_/knې#5}!:Oss {/6HAqem{INA{rDwNbh8|%z)6pmżYGNf-t-UW47h:pbt|9CyM:+<2%Ў z>k(*>p}&Nm5p 0xĴe3;/u- nɠVvUpqFgsM"QRP&N>!V7ܽ[5qyMƥ[D@ =oxWk k;G7=G.:@6 : :QPs5WӴh+R~gY_guPs ]z1О>Ucer1,Z6Lڎ;.&Dtא\1۞!Ly1]=,4U ={ y5O%Ꮡ5olhbd1$|VdԼ|i@؂};L۴t4U%> ׼"507]BWf\^s𦇊f$Ado31F8wYnH~#ٙX8xt*._^:] w#Kٲ)vpfof6.^-=;rpKLk9|[B,i1 MQԿ[%Nn|~S)?׬bP,iJ" L8F*) { dߓަ((!0ELmq ;T6]>L,P *;e׈3NDtq,.\B3啵AƀՔ.oJ[T>9{kk/s7S<1⢴GQm>Q!ƽ_.*a}C.KX>G47$9̹߿3|O O"{K7m}7ZFe;-(O~jo,.w>F5rX߁ &L2vlà`o9^'P) TR͇KVWՀK;|lO Y b {=:Q{nkj}rDU=>612lfj.znڋMu(`Aμxua&o']X*ijiiCfN/ q/;}Zm[rii u uR,,_:囫><^3C6jm%9C۵ȭ$5G\ T d9!ŗ}^x'>}r՚3FqWI*ҩ;nz|P>? "d2{\O̢& Z,tl'˦1-"*vܾ2o5藰> ˇU,B 6H1a? ?+/ɽ{흿۔@J* E |v*n.wyR>>"ʦ-Tc+Fup;#H^lּgiLXkY7?tѭȐV}[ /iy#[:xx{8Y[X8&nj):0 ּU08*/vvz|jF.VCfm Fꗅ8%:mU^^n6Ʋ`.+_{ƩjDwoyõ>'tUusrr4r4lָWo!A1OHdʂ0)xpgwr4tҤw;7cM_]s['wށC{3C[E0e {#<<9\yڊWxH*ŊI==h0nUWV %6- +5^:kOg'Cżח֌ۥ]+G#W^ G )8UD~[T$lgtrYUhFy~օ<7!IdeeM']qL JiJ~ӥBb$wg)8E :Sݓ_+~B!T;_ .ΌШ{y“*yvri9}X/״l36}@3TM=ּ̼R7(~{Z0 wЧJw\$,jV{̉I+ʇ} o/+;ulއzpj@ eUx߂x6o%tYlV}$ͽuZH.m`z~_FlǞtQ& uQP_L1f(N%!K't@1gˢX0s̓ I6nm D]7ϒELqcO3=:ib̦ ޝd?j[+NK>k2*o b3ĂX[n⧋i1j]/y<ȗ}"<2cz*[}ȥ2 ; : H:`ge4Kl-RzoNmEXv 6i͕z"I ~ [>᝘GU_oI^5HemduNPY\4{stF&Un3.tTF3eqKPٻ9S.oXҲU ֬ )0@vɛ"S Dj1'liL\M ?!,kh_^|΃,qf89*L>ʫeE\1Zg ܏W/ݮyIr.{ӬO~&⸕nfn5_٠?}gP+95n%˦Gq>?^dպuXD`xsх*}`DBSmp5a%N+U~oTuG-MoZP%י yok@p&"MxzIJЈ◦Ԍo'/Pq[6ǷX) ]g^UYy,/n'oXg UdfW7nru/tYw% %iX,ԁP4~y4}4-4CFÈKso\YFZY4lIQ'ˀ=ܵ^1V n"V($E1kU H79MV (>CW)zx``e L>Ӳ:QQ⎣_Wrx|7jZ_`/8;?piunG*n/e|`V//&\X9 h(ݿW<{%Ң3:57rGZ`wߞLZ1[ਨxJ. fl\KL<#[ۨ/t vFME]@ V!&Ѳ&_̪-IAtXvϭg&FV?+Ήgo4}cl1]FIdBJZpV!cz9tم}=5̃vgQ>17[v?#؆pUTBV(^]젦py,)gaOk;noD7z]<ѫM@虋:yE4nYCUmxGeի,#-˸}dͤ^0Beݖ4/&bIMW.*kG!1 Ag!9L7o. Yq]&y\ +m fUŁrV$ j'K !0[k"|0 p^\hl?Srq1¯TZJ1QL٭AC6%EWU/&ЂN 01ͭھaILWU* W*a_-kӉr-mU"Lz*=<-)GAe"hUc?&od@J!7ǛE rL>Prtw63600n9D.M)=]ڔfoj5%kO8^^FNK+~ߠ:ߗ&!iii/evuK[pg%`?/A6TC+}ިYu8:Fkeߙ`~ G֐E5oa 봗.zx6"4{^QX[cEA7ە"za y'a&k}ۓ>m`+)x=Įཀྵ:n-rFQډ8Yxy5O }5e|(%W<[$.+......Jx\:Z6"N @IJƶ鲜r־UG 8vY=y? k#w"akT!Y6j\\,}RN\m_rf5rT才)θvֽ&|/meW)'*!hYCA̲Y4HI܆~Umsᩫ!j q#zN{Z"*D΂n-\=4P?;v9:.7ynƔ9=5iU5i6=.]1DruɝYXk T܏K`ssMԜ̧9${ژ=U^ۄc;#mǖ~^S:6(n}Liw޻waBRש7r|XPzM/pM?߻sܻ2ovJQz^V2CZ 4x&|oL<ֹ5\Xޣ)Cck¤2^v51%zU&ϰ8#U 6 ?UDH0]-I7_qbq:wjmR}7y9ӇjՂ T(Q&7լ[KYǎE| oBM̋rX"ѯ9:gCXRrB~֚^?m}s+JOMzV={rF'.?vUt:?BP?ڹj'F&OZrE54~|)`իY4dtMӼzNǜe_b>F@ѥSuع*%y\MxUb)Xʽ[rCӜX(Ɨ%;ۯl +ШSC9(,3~[rE4\5'|@E]ϒ[7s'ж*ɶ~*TYv0Rz *蒗@i# Wƀ4ugk dNE3E8uPts>PY"gTIV `Y"Kӣ. E]PsI{rY6ѐnx4VCü%no(.h(˭cdfd@\.U>Z4g.uFg!*dVNӬQ/^MemKz'b8(Tz* tnn9Ls6do2wiO?}Lݗi &}?_eb';gS7fBnTyTIyrk "F͍eN&hGݲCUxz3_y%2n`|-oȈDkǗ?ȦeI(L~оqti+RT |&z4zt]^SNboX+dϴJTUqP11-XТg6JUR>z[7C8\umuܹ6tbh^ LENHs3׮bI [ֽFq̲~Uw2#8 ACɹWlKǦ.  (ʒ]x9Njs\9I̷lY oU7iڥm× RVڧ& .gaQ=`{[A4%o+/l$dZԳstvSd&9fxpZpWdYVZ-*}u&Kfn MKn- 0 Z/3-<Ĵ_K<CN+*!v*xjxQI>>SOf+3meuR'B0 "07O_B k$.qv\a(K#W_@HwOU49A6|@SB">`q%7{S}rܓ,\*I@ubBDɛ~<F3p$Ouϱ7aAi3j -UYgwlO00VwЂ2#yڢxEVt6U?=ܒl\I֡P=\؈Vj0 }GV`;q`=".yAvmF%7iB]`]](LكU ̻^nX\4XĀ6  ?չj%j0dQr'9  {j-kإOp{ 4]pua溪f-4b=Mz6~CqEy\{NfK>L[]ϱ㖟I #Cۘ|,:+)jv]̩'Ϸ3]i[kקW_-I;0@ǣ%r-g)1snnnn.dZJ~S]7gY93`IY\@kGD|hY&<#a }҅ 7Yn]U4$Tc;Y5sh8f˽bB1=4+E\`_ϰq)0۠nSBE֦|C@C篙盺v|W8l 1af Tψͧyv, j|s/Z&6n>f !DL===|zL/5˵ ^gXt[@霐deȲKzL~xfh//YMæi0MnhvLВ'WqI9cv ) I;Hvpq0d_ hnbjǿ=,-g{xT'Q]xoDofZnwѤS;Edy?Нah_سd+:{>Iyihu%HBѴT,(B- cb$;!s2vMEфO(+=ӓNB?BU>5OCudz6}zG/<~?.ˮf)f; ,o aɽ}z TR(3˻gvj*lwٮ1+7#͎=߀Qs]Pc_CϬ O68h.ԼŽ_~|%T3ڨx%{PvI3O*M0 y2ۻ|2ǐmcX+XD;yEݿI#Ba N(6߇o~JȿH@(-f8dr:o\#iqMY{Z[_9#k}-HoOZ?}t$ T͸Wh\/wWɘ8<M,|,p?(>:'t'b+Zf,_U7mt{9>:B"f@y/}$iicνzkD%>},,q>NO%_1ų2iɌ Pk>.611H\zo(oO3g 1EoUCe}~E˪Z}׵a"-75cYX YX oԣۈ?-~X>=Ȯ>S_Y}#J?bOr~=- <xE g!DJTx'IENDB`freetype-py-2.5.1/doc/_static/wordle.png0000664000175000017500000035163114664131406020403 0ustar georgeskgeorgeskPNG  IHDR@ye CiCCPICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/9%bKGD pHYs  tIME8lMr IDATx}wXWlewECQ@DآQ,AM5ɫAFcOD%1(҅][?oޙe]&/<3;;;3~CJx<.;eRFTTTXYYQ(Rہ_ kzΝ%KZYY-]b`!!!/S( N`8pMu=>ĤѣGzzz?ø[nM4)33zI.\\\ yy͛}}}:422_C81E ֭[APLL r7Hݻ_C///2  [TT$._`7n{xx=z;wD"xDYY)s…0 APRRX,F휙@".]sҥGZYYuww/R|i'x #G<~xʕ p`Rƍt:= t)S= 3gNOLL0h8|pDDĽ{]vEDD<~ """/v|)))-cL Drr2H$ɀdܹsb1۷O*vtt *))b>c0`ÇT*Ź~:J500;;;R) RH7L: ݾ};""`JEEE'NO>|(WlHt钝]LL̫aiiiDD'|"eDD_|ܭ;""b͚5ث~ 8p}H0a_pq`033O͛7[XX())/_<66J.ooo*RW\A Qԋ/wr%7NiQQї_~ Xaǎ'N4i𰓓NGTZQQb : Ora\Bpƍ, އDDD|ؗ UVXbppDGG'''wp39rY=H{.yRH"J|>J533<>>JΙ3Gλx`L6]]czk… v T*_tݻwZZZ\ a 䊋8z(<" W^lٲ>"""x<=%Kvz*,R܅Mcڵ lAϘ19..!"R.=xPPJ~~~oohb 3++덚A@a==קzPWWG1pճfԩSlْiӦ8-z_`d̙ dT*.s34474 @dcceYԩSw!x@ #zjUUU@Ɓ(Ν;V9{,:B\EEEWWW$ai(skvvի7w ABo_2 WVVnnn&˙3gtќ9sݻwf^;dY JHH#@#͞=-lLqX,TQQA3)|4FGG߾}qÁc</]$_N]]]ZZL~u\***ɵ0J$hnll<[U$GFoQAnl1gD+ѐ+W?}ܹsk׮}g\ɓ'`uԩCCC_}Uzz:RSSKXHSqؿq> ĉOxphK.J,oP|yttP(tqq-EثXyy9|hjj2 lDrŋuDmddY;::_xqϞ=Ǐ/++R;v@ ڊ @RbH$ز3(>Á/dž ڼy3@?a``… f̘q&pK.Ǐv𦦦.fdd lŊ&MB6G4qh'9sU$ܼyիWGۡTW֭ۿ?ЯIavܻwի]]]\\\-[vر>>NOOh;88YZZmܸŋHB ***G)F q},8d 022&bl>Jn߾Yd J0r155`\RV`0qM@Ӭ)S ܬ@ W;ucŊ+Vn+""""""/_zjᅬsʕ+ ¯ ~_$BāCQ`;?$ QVVfaaoaaoJ͛7CtEMFwÇA}={,88X( ӧSN]~'N"k5۫*ૃFyyybЦ `pϟ?ooo?44tyD2#H+Kt_RRRMMPUUUbb"0i͚5MMMaaagdd>ydqqL%(颉!!666]]]wmjjn=uT@@@VVP($HjjjϞ=6mZQQ3g`ɩ֭[q¦MbccKKKm&*4>|x7Y… 2 5&&槟~:s̓'Oa͍XJC*DH4t2LOOGj͛e/TVV^~INN999YXXtwwggg*pU`!Hֳg Lb8_|vZ~w97???,,LUUU[[JbӴ8p@ p8cj*DO>ݿH$Zxq]]]{{{eeO__֭[>Vr ;O?gΜٴiӴih4ZWWד'O gڴi3g~5kTCtҜ`H7={yD[ `FF<(H\vDD;}]ab)H$ٳ8hVVVq { QUUIMM A.MMMm„ X+-- HHHJd2Y$%&&8qq7omŏyXz*`Ϟ=Rt111@08qBKKbČ&>C###9O󵴴̓wuʕ옘eee ׯ_WUU XvFSSӺul6?&_foo/2'S`K"hkkշ~w^̍w}uVXz)McL L8(h۴iSPPT*oJ"D3hٴi=zSZZ:w\T{5-ÁXuEcZTΝ;NNN?̭nnnSN?b6m``7߀ȩSwaa!3JrQ(H333#*9z###gg瑑MMM 0XVVvUp .:th޽A`q ͑Q>|>uttԚo?VTT>}z˖-t:$pa(~ L۱cGJJJ]]PEEEBBɓ'Z2㇀x<:uOUU"ʕ+-tIPQ;ddd\~?HHHֺmmm(L\E,Ѐ8xG,hk˖- 5hm1ufϞm۶ %MXLJ{CDfàS$B?>{e _uȑI.?b[^dnna@0}?<++H$N8S___WWW[L:u2d r LLL<<<;tgM~~GҍfϞ=ёbݺukٲe2 sBGKK|d333АH$KjDj EEE DUU5((hҤI?L&X Ǐ'&&Z=TZYYYWW:W婫߿_[[^zTYY"R(W9=oÇoinn;644t'Oe``ﯤTRRRVVjhhh``ysa ,--ٳbwY@`$iڴi IiӦ+V O $@؊LY *))VUUq8JGsp )mddd@/bmm/ݸA"f͚uヮ9sܹ[ӧǑ /))ZZZvz###L4B,TUU/]lٲ&PF3C` XUU5qDC[[?Ϙ1]֭[s =XKKKΜ9 add[[[/^d2?~R?\YY AT*}yQQPk֬IHHRIII{UUU}>TSS(PXd 6M3Ӹ{X,fXL&bA===9Ԉ۷ggg.^`TVV555+V}Ŧ3gμ{nqq֭[AD*$$dʔ)̙˗/zRȰ-D3gŋ L I9::?zhҤI[n /,,ӛ9s& ǻ@DF]]]uuuBPUUNc%BPKӑI{oo;wTWW(ߡCΞ=kooK.cnذaǏ?yٳgA˗[l111innNHHHKKD7nwE>+D&z{{y<2흐fgggggh"ŋp VKiyyyٳӧOaaawnllx}^ihhk F/wʔ)III+VO> ,.. .YZZ ~ qkjjLMMeիWJKK=zQxt]8H'02VD"Jvuuuuu&>>ix\.wΜ9o:oݺuǏOMM.>&O5|~ްaùsݻg9"Joܸg.iӦ/yk)>drݺu {\d BHt`)ݻAױcǖ-[gL>,BBB)ʆ d2 ~~Kۉ'17 @`K~Q@Q|fff}ƍz2c!Áw& {:::{;;;7772ݝd2t:c VrbpJoo/cŊ'O,))WB=@3,KVbXZ*EEE)));悄/_'ɰATZZZ__Յj)wpp0110;a T mmm-((6mڤcXoJO>}ǏꚛÏږ@ @R@'CCr YYYX% ww><yRLŁ=@쥹KPrssQFgϞh4]]]GPt8&BCCC쌌,%6oޜ|>L,**4H$y-\3)qvv~9,--GS܈t`)ť 11qɒ%H1??x@&A|!TSS ݱ(//rppxi+g8x B6 $ZGG$1uTuuknM2RӦMsrrb2˗/ ~i IZNNNL&E`iii ADZ`XknRZXXXAAW_}USScu\p@ ̛7uύ7@B9m2%Q}}}oo/f Wbx<L`8Z B;;;TEIII]]}``G[[ P{CzpqqDRTNOTTTTTԹsdXC$iR(=hAЭ[!uLػ˗?}4%%ҥKVVV c`y- 맼s $e;;;y<QA6r\.WYYYSSk)inn&'= ;̬R< ttthkk;88d{{{MMMUUզr777pcJWW9-K~]~att4h]8Z@5.//a---!((hҥM䄄Wlz@"N>}ئ&LFܸq}y潓Ph h46ydHp?Q+???++ /ϯ[h< ᠊eRp{`VHr Fݿt4{u$-'''6by'NrJ%K,a2<u9?|۶meee{_/7omm!2`0@c2|||DbGGӧO-Z3Pb) N`8^afrfŊEEED"1 '''~ lBWTTxzIZNNNAh 4dcccgg^Ac``BՍR477 ???} >ܹSRp6}ƤQb7*000 *++|@ @ A$iYXXhhhI?K:`-19MpsmЀ2DGP,,,Fl .7EN`8xv9,$W^=Z7aE$Q8::&$$0̥K"sssܹRA3fXz5@@}^^ɜ>}3Ba2>>>999C(++cWQM0%-Hjkkkkku2\%pfanooG9h& M5֞:u`lĉ +?eee]xQ*0 DRVVZ"I)//bM>]KK;33ڵkL&SKK#// 77W\¼y@19PY$! 3gT*}W놻eb.psFk444g##hמz]DŋAdY1B8q"bXG˗dҥKdGMOO SUUE((+W*-- A "ׯ'zzhhH$"+c 摑kߏD"qppJ `722B"NfbUTTST7778pábq~~>Av0b߮LTl60VXX(&Od2L&͖H$H700 JJJyii)XLGGۚH(++v|:>>~A2rtUUU`lllll=00p͑z,AWW׋/LMM,X PVVB|>{֤I3Ձ$;v }Xrttλ9д)$$͛퓛xqod2A"襃8dF'NXUUL&ϰVPPPVVD)))O;駟O2hc$i| ~)l$MMM---FFF r!tppptttrrՕJiii`d$i9::fdd0̐KYD}y`?cL3gP(|ERRңG A;4P4=8KiW@@Ç+++}||PN`8dC(Ąefffffjkk{zzN2*//O"ִo=%{{{UUsX,### "֯_; !bٷo߮rpp011AӖ-[?0g"Ȼ(P 1H$Λ7544"`zG#m(J744D6 ɩŋ\.pN`A5o$iU* $ |>_WWWfD9X,yW50 *{zzD5ĺ (y0~qg5R2ebbhѢE&7B[(SNo߾S;v T>I &`WAmm-HUB~I_MM gϞ]|I[[{޼y(זT*׾+M =*&urrjmmC:zzzcP`###]]]BP$ BoEEL|!Nog͚l߾d׮]XH$ZjUuu'|||TUUB0_uJJʷ~?Duuus@"2,Y~k-R),--DSSS b7>86IRCC1vH-AM DbHHF[[[MM ˽vZGGŋײX>ccc+S5܃(={3^WBNYYK4>ʂg+))Ν;z18.\P]]maa3ttt֯_?iҤ>HN_?6088xK'A7VCM.`0tttX[[}cc#-*`0jkkL[ 3vvv X )LΦ AzlpT&M<R4555...!! ^K25$ Q+I$) B!H/~rww_rk_S BqFc (JSRR u@JJ  Wc2gmmm^^D"իW'& $sztttPW!0taF>x:̼<==g͚_(ay#w ` 1uuuEXuu5jBB4ewAechm]B& du[ڵkKKK@h<<rnݲ=IiiࠅRWi{*2_J H^>H$ҤIP=ruuP(l6{`` iii-Z駟ٱcG^^ÇgΜ?]q{KC񚚚hr2g7vY)4 c~233 裏LfNNNaaa}}=ZaJ&7 b`$HLFA+HaL&rN4. `r[΅~~~`t^z5WHHȃbccq  h'APwwwSS022?*((4iʇ)-,,rttLLLΞ={6Druuuuu %%%999Š@ =&SH$[[[d!{N`vMMM J1)0555333pdD~W'0>_VVzL4 KXVV?q1P(,,χ H`~Ǐ˻F `ddE6T*J:88ܼy N>{BK$ΔPLaMHJ.iooO?mڴ 3 }ddԊ=ka5)++kll4000774iXg0b "S`iU__z2Qtppp8_|=իWIݹsd4_QU͜93::$oli&LfuuuKKX,vvvvuuE644F`b8;;y`` [ϟn)l 3336:6.pRSS]\\%ldV 䨨DEEEyyyYYYpHkʗSgv:tPYY\]]7Xj+.. .]LbXYYYJ7o$H˗/GV1CI>~i||;eJ"䊣86mڔ?kW\D9P d=P#H֯_V1771cfNNN^^^jjjmm*v|APkkcPv-[o*2Wf}RUUrmUqqqׯ_ _~G'VojiiqV`yr'''.חI&_%Q?===;wH$C&fdKXG}}=xp{L9uf0ݻ7...774K$gdd4<<\RRjdn݂ ٹ/++>}z֭c0>JWFu֓'Ozzz~&L<EEEF4woݺĤdb׮]ԆyeSN2LP.^ɓ"##~߰a)Ǒj}}}+WLb믿ZƷwwwXBEE%11;RRRruuϟ1crӵkbbb@ѱ|۶m?Vo> ###777,, S&%%AAAiO@ z 44qDL=߇ 'wBoooEZ N"H`s& ` )Tċo``'?}Q"^AAH$B@j2Px]>[!ӧOWTT?~\|w(BrQQQ!A-o.Aз~KR=z̙3gΠ"FcZٳׯ_?~qee͛7+2 q֬Y:G3 -djٲeoj**n?v`Bߟ?[өTuuu5ɔ\X,օ VZj*)Z[[׮][YY[gddkoo駟8o vvv_YY E{?a m͛75^XXpBd@" 6X^l0777H 0#c2)mdddMMMwvK&+++266FFw644TUU)/EU@TTT ;SUUE6vK&woUWW59MMM Ɯ9s)2[kkk?~ٲe|ܹJ"tB ONNp8p)%KÚQbR1`/Tjxx+W|А&sqqQRR>tg}j'Nqqqicc?;::P{" L*>z3a֚!#2W@Bf備I"x{{IɷՇpgH]^'Ox@OO履~vmhh8}cVoyxx8p}|Z__?00eaaQYYԔc%uI?^x100+(((011y7oNOOw^vvvZZ([!!|TUUduttX>  Ɍ") RQv@ZRtpppL^srr89B/..:AAA ֭X,WUU}aR9 %$$_^-&ؕ^: χÀp2̌VVVL@@盛/\pxRU[[=Pv-uuu#Lu޼ybHИJYYyL^R!0 %KHH vc3 `pee吐ڵk~~~HzFFFIIIOOÔ)S]wOxD~L&JkkklH+Z[[bbbT_~L1Onkkۼyg̘ )!#m>>>WZWWprrzK`ypL{[DݻǏ\REEE(_ਨ( zkddڵk֭C|~KK8 0#Hvvvvvv-rIII~Bǀh4NC666HHCL,La7&錌>{{{FWWwշoFٓ-YdΝ~ HMa5 FuuH$RSS{L_5rc]HDvߏ``h4˳g*++aU8$&&9pol68xE]t1ɻ >$޽ G{ɓ' e|GUUU 5}t2_YYp_J`AߺuK"?9|0x3Hܹszj~UV?C S(Jsuujooy&pWVVKa ?@mg544@d i SP455)))S}}}0vqqAAa_*G+Ν;wܶ6Pᮮ䤥ԓI`4˧NsNgg'/ِpvvv%%%Nl `N -gglʕ+O]]}ժU.\Ų8pVccĉnzU^^g@I9rF$'H$}}B ''ϥP(l6L$!!IE Y*J;vpӧ߻wLMM-00p4A6>hkkϝ;7--xbܮZZZt:} !O9O9(cffV-@uPtDn ߗȔz0d۷oT*u„ &&&nO@,y+$oM4)77t{Ȍ R)Ce% D"2(ցWd2b9\%N`oUUU`uց #ͅ{(ND"5ϟ?okk333# Ur܄]]]N f͚?PU`ddrJxddDOOJ*~~!;_%0j Jv̈́beep7d2\mm- T} WBGQw$.]*iii&&&pq @KKKKK>*􌉉 "H|> )Qb"' cHn@hJ¡L&d|()CrLM؛ &MMM ۫UZ[[+++|y3\ &/^P***/_nii믿ݻW[[ *@ ` W(bE`JJJ<!b[M| @ M$◿K Lkmm{n]]J[/[ ǾU2j8!0T000xL`b8..FSSwʔ)0o;;;{{{_z`yIIIh 96Ԝܸq#v?0Q$JmmmaKjݻG"\?SDGG'%%UWWcSpB~>ի7nXBdy@z 2q+))>>00PVwuujN.#ȁ)L&WJ222gs075<<KJJjjjnڴi]ZmeeN$͢hhh5zAGClBsȑYfQԮ_~F+,nm`X[[_Jӧ<<EL8egg755YYYƢ Z6''eeetOl*lZ'ϰ06,..)S{/"X١?ATqI$m_d322fϞ=D cj/̦&tiiT*RHL9GG~#s؂,3jԨȸsΡ}u8X,߿! ͞={̙Ͱj&FdP5ruuupp訯' &0Z[[z<<קAnW 윜 qR[[[d0cm,,,333[[[5MiiMjjjx}z߫;4ǐS ۵ZmCCBk4mȪNv---)T*AkC:99C͞=F9;; 169uuu7nrueyyyUVV|p'OюT%T*^|9J?p7Ue=hǁdz>%%̙3yyy|>?++ٳ'O]ABvy d P9}9sg_۲eː  5 D0~lIHM&< QT?TW2v+Ac#"1CBmH]Z$̰l 8Obz7^sN~~/`('>bf͚elWa"@?4Ad2P N}vEx<ޡCgff>|D"M6v30cӚ5kܹS]]?C{q,;;;##D"Ƃ t,BCb Dھ}{XX0/, ) # ~~~2L,ͭ!MOVR ,H$"()))998uuu BRgnU@SrrrfΜNNN+ 3r8w`م2KbTv1K CjKKJRT---lA<nZZGXvvF5jЙ<.!wwe˖]paϞ=1c`V 555bX1L'=XNh`F.\x ֬Xbٲe啕nnnG1!B .,,,--Ew~cc#V:͑S&r-~~~===XwINN.(( t.5>2 ooﺺ'O\]%%%׮]#3bA~honn6CwJF!`/\ӔvcQXXR\\\ut?Î8?~۷kjjr9L!GCk4qFLc8koowvvY# ^ "22[>~ rōJbq~~>q :>53zje˖,Y :t:pȼp'NÃ` 7n0___wjjj)>>>|>_ӵA ͖d zp]\\FJ\ q;&&&...44B())h ѱW# =|||`o >qld˱#3@0 b3a P 'FpFB:( ;vQ۴i|UD,[XX$&&+ö j!zN# ""G P.kW+8IR$? mhwww^^wܹ7<}4 7tG_ouu5vRYGjBq2'E]C\\::: AǫF5 #** &ԸfXL&)~*r?<88-[up IDATPCw \vmOOO}}=Ao^"ޞf#y٠ZLP(L&(( % jkkvvv h𸲲RR$K?r۶mkhhxǏnܸq $uK|Bؽ{vSFdÝؽ@ X`J*))78.33[fii9qDTL I$Gcc#9,,.##C&:72tmк}nrуqϞ=_~eˆtE7C&Յ.jjj*--j t:}ԨQ(DT y[[[3 #Ts=@ x#(777k487///d...؟\]]?ݻ.^tR*T*z}TTT{3:88x4(evtttwwhR޽{W@0xĦƊ0 ...bX.t:WWW09Sj"3}+WbsOp2޽3fVkooo +$q]ZZ t111v]Pk+Q0A.`j(LarL&sgu899>L&cmvVTT‹ RDT@daa8 )24U׷(D֖naa=pcp[nc0!!!J?:hsJ3>E||˝:::D"VYv ^2w 䬨BL>6'44T"@ Ȏ渪nI?^`+r-?ǾP(㏟Eݜ|2<7oAjV^ᅬ9777SX K -@ࡇBxm^&akkkD"xggggtNdsdd9s&M.  w{{{kkk*4"|Xe-Ph,%| ֩+%%d~g6mvꫯhǏc۫[rec?* ԑ}}}r9ILVVVP(lkk]A޼` Vh":Nh4PT:.ajV޾};۽{7͆,biAgg׮]pܹ5kOfA?$H/6 @ao BapE&}||!J;WcnqKKK{{;{j!鯦fp+njj?`coNѠZؠŔ^/++kllDfW8:LJ$f5f`jn0vѣEEEƊU9?].tٙjN&CBBʰT*I$sF EAjy<^?\p:d2@F^rdjZ_W^ zNNN@@Ν;I$Ҙ1c߿F?~fXDGG>}޽{,CUUUBlmmqumѢEyܚ|B5򪪪jJ@?>>'NuqqdaU9?O B444hHC("p"^]]]^^~t:=((($$XѣRl+,, L?Bbmmm5{0ݻ .DOƞ>}؀'M}]v~K.9sm0`%<== )ir\*h4///Z___i:Ai;&z1CunCCCAAZɉ)"m t IiYYYΝK?6dD".R hʐP*** BBBtH`8f֭[:nϞ=SLr8'_tiǎB"@qQB[v-N(6^Kzduuӳ%k$ n`N4vCzi"DH$^'OF@IѲ:::x<j(\A닉=Bϟk=yѣG|>0G`oK '0HDi0*k@H %0y$ 8~8d\gD<$;;O?4""BBB^5??Ջ/5![p0[lIԆ +++& OMM {KȘL?#Zh0)dc%L8( tN߿A^]-!.D*ӓ|x{dlu>A1WqqGxxMZH˨bGw ䷋-W*eeeհbX p؀{!5 H$< (W?bC`!ly&`„ 0 K9[$ɓ'O<ٶm[hhE/^ g}aV_WWWWW:\.:˷ EAAAGGD"Ap5j:uJG:y nnnJ;hJ݃+**ٳatzLLLLL S=]8NP(km cҥfMJBc$g[(/SSS^ZYYj9NBB`\QQbccT*CZqKKKKIIq6/ӓ'O(:ft3Bߺu߿?677z>c2'^|y߾}ǎ;uԴi>))iժU,?OLLLxxu`stt4{4t p puIMMxj`rpȺP, R=zjOE56&*vH1LʺqFNNNcc#pUblڴť:}'Oœq>3Yf-\0 @T11Q޻w(-A"}فfrtt|嗿+I$jkkkjjﻓcSSSAAlcc݁BJ N  ,a{к͝BU(xph ~tKP( 8w'vD"rٲe~>f^X?W#^J\p!J|3d5Tl޹sIիWgΜi3 חZHsϘ `&,5"\})S̝; ˎ>o <;} ~[[# ۷oܸwSRRaO8_{535bhhG!bﰳ2e1Kr-b/Bzz:D -//ohh8qFkiiYjmE$|X^ A ͖$OH`5rY"<==Aihh{n]]f.D0''Vp6mڬYbbbtzgggvvv*qz+W.]j麻 ){믱<LFpz#LY͛ǎ;z诿 -&#Z->Xsuu9V5 t:=00N:eff~{CENx֭[҄B!tM0#%%6 "H'bWƐY͚5 w殮sj}Ϟ=K"c ,Yb $577#(\ 'hp8 ͛\ܹs 2/B͛)))KMMQ%"VdMMMpKZYYM8&8cӑf%?{{9hh t 2(ff A]4/_\^^ѡVRijjM "# &azܐ}"aBydɒAiP0MիWo߾hbbb>ݻw/_#G (R*o`XԀO&ƚT*0`P(T*DE 5GX,w섿_zs&&&=zVڼysZZ^t钙\5jǎ!!!J2+++==]TzyyرJcj>ȑd0JAAA%555999---XeMvޫH$jiisHHHIIICCC^^^ddFy!4ttEGG߽{+V LVȾ1c͛7j50V T*ĉd2رc.]OMMͧ~"gzWNcǎ;;7fU!={޽{+W._s% bc㢕ռyLp2s.*n#3wH0rDE UeYj^wl޼yÆ n:qW_}E{6a# ?olllhhhkk R쪪g}v$C4 TEFFΘ1 +#===*NcӽLKK@45t aX@iWW1`Cqk@ٯszzzzxxlݺ555_G+Bss={O~T5@~O7֬YsȑsiӦx{N4 GMT#gΜ0DR?nݺ%p9TYp0k9 gNc/:ujBB˜1cPZˠ >ڢ|+Ń<<>׷O# IDAThp;y\.ɓr2X u3++ )ƌ}}}qyegLL VTwOW\956 CHZB沲Z#Y`5l Ht:H}̙[n4V(b,ܹF <%O#0 ="^Θ`P0tssW'OŠ5MR)L(t:}ҥ׮];x [̟?oqV\HGEE:uxP`H$Ҋ+`.^b^|EH̱@T$i۶mHII.M‹KJJʊPWM3d23Vi|%@$JUPP:@fHP3d)++шBڐopE8~"J\\\̙RQQޅ7X^ISN5FBa@@ܱG*Y.***--E|X Cj*JЃ~UNNРlc-J$ITUvppZx1nchP0?~99YښT*PReyEV>>MMM*c~p߿w[[3֮]K.effB/C[~~~@ 0>9H$??_|z9b:PUYffNtmnnE}gԩS*t:^{@j8}Ϡ"uvvBM 6\]]abxQnn.8߿B@`ѣ[n_WWW{bc~~7\Դ~H6sWؘ[oV΀>?c *:}ӧC ZZZbD"]t%""bѢELX333333od`݅Pg@&p:OxyyCWb\0r7ohsr+L)iii(Ҳw^\noo?vXѣRcƌlIҟ.7x(ߚ5k٣jkjj *"N0lc\]]?Բ'''wwcZl`'YKǨYxժU>|bbb\]]t'O+W#{9Yyy9p(lâHƋhLs,,33:\yӦMDݰaV%~ K:;;W^}t1`L E |ݺu˗/t֭{ @а]vmϞ=|WaaotR:U.wuu566ӴXkii9s ѣG/ AmDY^>VX|H(..HJ\[pgggDBk:uPYY }FwwwsttHP ' D˱7͛"Wq6m3gNbbbOOϑ#Gf}F8ae'N޽\.W}=2,)}}G`3<'N?tX[[Cei*[WWo@@h4iiiRҥKP5",S^X)I\ЋJcᬚxR$999`0Ԣ>}Z&ꄄ\&Oe ILVUU5DuJhK]TTR)Ȍ AAA53cƌ_{wy[RRfi4Q4۱cqܣGO>3gΛoO>mlJKK Y76Bt\4ؿ` }GXn4b2`1Ju'JbX$:zIRQTOOO \pjJ%4*"##Wp!,x̙zZ=qDhT z@";8uTLgBL V\I,KMM7T*dYYYEEEPGP¢nj' +**|||ˀ DJLLy[UUep?~mytС+WO< cƌ1Qz 6! 'u`(|^a>XnnnS$F٩GeddDDDpdpr8t"KLXt nZV(3l65a7jO|*d2A%6a[322EbWbT \fbaIc EfffCC hmdnŨ<Eii)l2e PV,\$BSBf ٕRB 8qn(18 QVK$ l6{ڴiwX+|II Q5"77^@Á?4L 7nA0:::$$䩸9`RD"33^^nQ ;w1cU*X,&&ULs2~{Ν%%%شiK-[׬Yc8W0nҥKo3A  "ǾwwwcLfpp0hg}LG"dɒ^K: dɱb l"̘.ʂg{{{6fmcz g $l}}}zz /@< # jqF^P|f4P(>kD\8h>*bD"@\.  6|Hdgg`0aH$*--moowwwsի *D"‰v XCCCvv6!c2Th4111Ǐ5}jP02CvptR T*U˲\ڵky,gKH"ܹsp: ʤdžH/"N㏳n޼&MgϞ]HHȣXqtd^L&spLZ[[߿nB;;;}Pmh`OyyyEEEkk+ a2>AݷoZ޽ܹsϟ #ɪ+///\A+W( .9Wґ7: BP,V"ڒu:ĉmllx<^zzzggٳg׮]G=y# H0z%ry~~̈́ +,,,**BC,@8f̘Ί t䀀8, ,_ښ~ܹ'X_~ڮXΝ;hrzzzPP~Hedd$v%ŨWQ~[\ /^.[ի#m4SΙ3gYUUw]vr%}0( *R(---6AZ~~Z]x1H&L |X,...Ɩތ8lMMM===B|vԨQr\(666B꾱 XR)q\ʼni 6^j,jC*ę3gݻwٍ>OOO77&ZBa}tt4$jjjPlv||;w`u~7S}}իW%Є@/⭷:y ¯СCVz饗C^\|P`]e鱡+++Y++M6]?3gĉ{5]5ͱX,$Pu:]ss31[H O. QzII  &M*))&X___ĕ/?mG}Z8t+$ɾ}Ξ=[ouӧO5jݻw^X7o}$C8qJݰvehBدNFIIIuuuSS&c Ƌ/c HN$X,՘ eƌolԩv_u@?W_}5))D"/sq$8effUrū/z}RRHZ@bƌرcmmmuuuAAApS7999[l:N@j+ k׮;]:[ vuur lz1W`ff@*X\\ 2ٹs8[g Z{ 0.!׀ &啖@fF>|"((Șqd /`.::䲲ЏO9"d2Yrr2KN6mΜ9CGBڵkӦMKlll\]]bqZZFAcgg~W_}ҥK'NLLA^c !#ߡWrBD5QJ 5`C5˝ 0zm۶mf}aMH9sߐfx<@@DE㱬dAݿ_.Snii6 .v dZXX@%s=S%ODM,R ~pmmm̙cz ryxxL>O)Vsz Eprr={6q |ff9䩻<A;@bUUUgܸq#pr?bJua˟7o㏨XLV\I5=6ƊCzmv9~v#ٶd8W>qǏ-Zbv42lXב0`ӧO7p2蘗WUUT*aGDrGZM {JLa8AZ5=SUU)//O,s8H\(NmW믋DL3 BN/YxzYC^뛫ndd 5`$HĘ1c`:Yrرc555؃T*/_^^^noo?w\+WoF$}78 oNt:Xbd9Oh7o޾}Ν;X>ǎ?ԩS LH$R]]|,'H$Ç/fЋ `fOk (ŋ6&MFT\\0cD"l uvvaşp`Dݾ-0hJ@* ENN5ƞkx>,,lv˗DW_}uƌSNJJJ_goo)uUkeeFSUUEP ^P믿f͚5qqqNBk|p#G;wn1 ͩlf'ꪥQJhS(>1'T*a%{{M9sfϞ=YfƍZXf@d| @c<44455T* C_ ZXc2{ڵ+W[n޼VF___͋00r R {1{~~~/^On߾}mݹs%C2Ҙ$NsOn2 =xN8q_k8rFO,J~mRRO?oaPH$|>sE `YYY۷o4iLߧ>1 !UUUr+HӦMBhc@e,##B8qX*8N?lmmMOORX]ئRn a:=_cOO]va+㛛w􊊊;whZ577755a-ӄB!NuĎ"J$a3p 7ҥKϞ= Dբذ{怓9,0A}BG'''<Ց/WWW#)$1Lbciiڵڵk | VKp獅T*bO=sD~mll\.%dɉbףfblٲ;]D"yyy&>-ӋAhD;w?!!m۶A}o[]\\gn߾D"ݺuÇSL_45?Ǜ_@;:Q]*YG[J& %( zVb\n]{{{QQD"a0L&/$$dTs [[[\.aK)XGGGQQQ__Akr" (#J)Ggð𸸸[nUUU]~g֬Yjm0çr?NqFUU$Ibcc gp209tǃvH|!1L4`?D"5kN;N8gaaaz ١- !1jYfNNN˗/'z{ 7aWp0w_( tppؽ{͛[ZZ[nÃQkW~YJ$!: BloK;;;d~/6~T% vvvRXkkkooaſCRT*9!ݻwfa(D 2Sġ`Mg$j@qqq` !@ xgYZZZZZZqq1ҋUz9Y{=<<|}}\ֆ)͛7ԄFFFm۶曨]=;31zQ[= l|u233{Y?,t$@ZnSRR&@} 1^_/rV(jLVTkkk3{{{r'qr&SWWo@0Ql``,ŢX h@aooOpV bxx VA^WWW6oм-Ztҥ`4Vhr$rdC+Vppp;N6ήDuիWJ06;v lڴiM&SLdK~wz7k֬_lُ?qF.KBܲeKWWӼy&O ҧOvuu5TB?122+*))'==}͚59o߾ c#..t;w&&&7())1K/D+Wlܸ1<<'QdNVZZleeG*iRyȑg~GOTOs!"P+tuus )F)O>ߪ]b޽{e2Ywwxsʕ+{|rqq1^aػK*4D nh/H :EvFz\0SSSXOѤnnnnnnjhh بDrG1 WcȎEJJ <@76?dG}ܹsZ}%ɓ's\R944T[[wԝ1caǢL30 C5r3jb`u@h&MZ`kt:]QQxOJϟ߿۷onoݺ500/))o|Nv1HW=>7mTWW7!z P Ԟye˖ ;P4C5 =GeffVTT* www///D>wޚ5kwUN7DT1t:,§888[&I$LD%ГSt:7t:1 ''ZW_ܹq~gxNNNB. 0Ȗl6{?3zX,&oLMcrdžҘZMc`(g><< x022(;mVcennnЉQ"D"3 (*e;VTT/dt:ZbիWb(xN&Jsrr\^ŋ啖>!G >}ŋϏJKKF``0˧?FQ}FQT:UV8q'a7eP* _f2%GŒX,+#JuMp  P]]][[t ҥزe ,x)Jm`7o^A00Pެ#Yz;w6ӦM?`~~>N7Ԫ#555??ʕ449]FFF ]ce`###eeeE@xyy?J `G~իW/^lGX,G G' Vzwri |O<+X8׋Dwr\ YΞ={Ν_~%))butt8pj D"qppx v^[rݻ׭[׆tvvnڴwѢE9$< $>R@s_^޾y7 VVV V YXBKPdeeQkVZu…"Fꫯ>W{<8Q\up8-Z`dXo\gX۷oHCE׮]i6zUVVVVVV:VhGP7~gUR566@jf):~ɠ!ܡիW+k !{EDDݻmV33gJ"p¨m۶ݻ |`S c*^Z󓓓zꩌ -suuj̙3QI`ZvppBjl60Q`[ss3L&FCkdd޽{111I*==}z1;-- -E?###겳ѯ޾};A>V[zggglX. 4vǚ?D` f`vvv0|)D5GWW>>>Hss34!A5v޽{ϟ?/JAuV O\I1)DvOOOe_իWM*F?m5j)D$9s,r/?u+HmReL0TXvvvbb"Z[(,,o}믿~GP7<< ex*i&r{Nm!A?sLWW{TR w\]@x$s2H?󵵵k׮Q*֭ 1 H$(oFRӨGx _,6PB1I h4cM vuuAjS|y2FP(@~ݻwڦ<~~~/NLL>|>?))iҥƟ34!B1sLKUΕ{w}wl(,, r ,@RpXXEIRhhhGGsrr4rW(Ǩ^{otq+W's&Y'|1s\YNrVPk ~)##ðSNQWh24#A  E999^ ! h4m(C$R*>>bl۶-+++%%֨!vtt$䎐~=-l Fqq1eLfTTTTTB{[JKKo߾ /#,j4>}:==}zxT  ۯ^KKKaLY-v IDATʹv횓D"jmm [:u*ӅBa~~Ǜ͛dy1GCaooiӦuUWW@(۵~`Z3maE>QШ\+**rww?|B`2*FE "eFSZZf<+ʮnOOOE-!lCrG͛7y{d2e2ŋ!--m׮] ]t{gߏZFm~a",jgLܽ{-p… J$.--- >wܹsqtt|T;w( l7D(bPFxayXPPPVV53M&999A?rR{7|fϟ?Z?66J/rvv!>,##NYT*ݿqq-[G͕d~~~S2Cah{z۞FEEEutt@Q0]3f̀Q"(JPWŋ%&&B6*svv>pz`R<'Nh4aaaO>$x|bR}}}EEEraҤI轣X{{{YYYFqtt3h b^x<. G "@kkkWWW *z` `X uFFfffMM3țL&366pNLD}ّ8]4 J䔔~ǎkmm]`'|裏l\/ tj d2Ynn.ޞݻL&wER~?bcc B|ByM@N<491j2(8\|ð~~ Bd"z!MP,__7̝; f0t:`h4:~ʠ`YSSSmmʕ+QXfffQQ:ZOO ** ZZk׮9v۷688GQ p8H$b+VH$wޅ/>_MFG2+9sh4ڍ7N:tƍ1fD"tήL$"ڊ000TTT@R3wky0Tx csbIIISS͞4ip8Rahh(--mh6!+D=>e1 F(zacDϥCR! 0333<<Ғ``\{xn݊eكVTTl< 111 #///77777&..kȄ;Ȕ᜜a)4gwj  i|%AAA[lٺuw}0hGNCN 0hlHpO<9''2r 3L:Jô "Ռ3ۛ#bWWWccJtF2mFQF]g&++A(BC&=AOѥy׭[Y˫wҤIr sٳɓSN~뭷vqчluG&ЩSYfpp0###55ƍ<=AIQ{MM ؇`ꫯ~۶m_yE4H[b8˗/ߺu^֟F`(ӨR 5H%z:4 _xS2Vfmmmde䷓!Mܽ{/ŵ...s1401LrGQF]ggϞ _`+|ggg__4ŋgΜoR}N8ap`ٟٳɆ `t:gZB0S*`1P)⸸8\}Cݻk֬ ٙz-H/5{l_?0  x(aÆ޾};!!?!'' $^z 3e>>oߖJiڝ^Q(Go -NwڕxA=x.hD"D"j4 ܉<<- 2KK.蔍 \.7!qԔk}}}YYYeee<۷oڴ)55tժUp" q22!S@G`ׯ7oBb"a0 |}} +0P/%%%׮]#!HG.WWW7ڐOB,((1d2L&Z$BEM:-+++;;FL1<|ðb2:BThA d:nΝ #88ԈDO>g]vƕ1CWVTv=E֭[nZYY900R<==}}},!@N_bٳgÇt Ö-['W_}UO?MH̚5'//{xxXVX,@0ydF:Or3g-++۷oߴiӶnJ:$(%]___^^n(3dH^ %%%z7~3g8z@_z1+W3[n8q***o~q#QY(++#\G˦F-Ɨm۶^klltttUT6N`:ۆRFɱ0iҤO?0%%kD";B/=^BV\\look.GFF>Ӽ~ 3?hTS5666^~ㅅ͘1!g&M2TA!mΝ;uxwi%??R"##| PJTƆ@ X|9aJFD,?U*l!hHF 7*ʿfRJ%vڴZmhh(%dҔJ%N׫ 4Z 5ppp駟IL&:;;E@=/0u|ԩS׿^|yǎCCC7olhhgtL!577]ONNh7n|i]d0QSSnð0PH^תTSbhh(77qLē[("3*4]$&&feeQ̍R U:6!j.H0쩧>qĕ+W` 7o6JS&CH$aFuppB~?S;wBp^ɘ#tLY?!So߾GyeΝs\Jy=jCh4hʩ+++1 3g| ;w䛝 c=[---F~: =sNW_|WI?jx_7tS,XŊ§s}I=O$2P蕡ó/a^3111111e0\.hb Bۈ|xx,po sL/a'9}`h4TBS޽(}޽۴mDDDDDL&STnT "a---555=@nX<߆<~A\uuuRӪc``N!$FDD%%%?tX'8Qf5s̴j3"G&C̙3sssAFfgϞmΜkf ME"a_===0;;88ņpbD1/"//uhh7(FK) {ؘ`###999>bppaΜ9X%F8rF? ,@pppss3ܕh|788+ t@+ (l#ܭF = X dfFrX,N| kr5.D2<<|~7nԜ7<<\ tvvR8`T'4'zƦ&\;yd3~uU/lRt:hQj`섢+ ;)޽{ĜN˻v0 743r"fHs9֝k׮-Zh~)1X{{;Vh~F.Xg͚zh~6mOΝ;fL&ߙ0L(Dyy9®nnnȮ|3vfF\`'߶ݰ?cjjj^x >)7MMMSN B0!gddH$TjjqcnnR&s|No:8͘1cddF1Lx՛/󫮮nooǷrӖ `0XYYvvƀ ~?::;;oݺE22tQcS&"rss3{ϷE_ZfWϞ={׮]~mSS<oǎhX K {hbH$ooomf@[^^f</444`f,"r999AJRcֶ{pp?,''ub:}lڴiK.ţ4a`]VUU혣`އ_l2g JW_}bve ZZv,`͛7oذðo/^`r2lxxIWWW>3-c:T*}6]]]]\\ Zfx֛9jӐ)&tuuծ./DFF566JҠӧ[9Y`0@ʄpWW0t7n$VVV&%%][0KLЮCkkD"!錵D"immrdVsN_|q0π'Bxg~n޼y޽?ׅBaYYYHHȦMzdbRԂv?N @eҥ(//omm}G^z{,88imbqrrs6m X ͤ$]QYI-ZNKK#5|~LL@X\RRnkk+//+2 `&ᄌ=,“ FTTTTTQl6z͛^>>>:ʕ+O>$d*J3 Byl;ȔK(666vww- \g`dd΀h#""ST*p820Jzx#***??|Jtu-ç~ZYY {czJ 7򊜘Xj1/ +e_|/:tСC,P`` ͤjh,&&fLl"Jz2&1uTj240Ղ_oPo.2a~O6 c ;򋊊N/_?~EE)B顡f: IDAT. !Hڠ# f|~ooH$󫪪*++2e XhV@JvO'[PmӦMǎsNzzP(O?48$$ Ÿ.,drss+jnn.,,,++I:!EEE!zS^~}˖-cddPf vCF<==jٳgV #;m3QAQ&AA:FFh?MZղ6ַ&g<oT*F6~%%R =$83gyE,hC(E&8T*Ugg'POr⡬ @TN\Bm{xxD @Cdgg_aF֛YD:V-+OaÆk׏p8ɓ'kk;w0ѣ&MM_}gV+J\RQQ /X9r$666))"Cǃ۷޽ 6뢣WZD(6fm/~agϞM^ܹfS=e !>>+ƭ̣B2afx&`lhdXYYd@_UU憯pttj 4E&88AyQUU"U>ObqCCCMMl)kuu5؟)%$$uttd2:ngg' ñF]zuƌSY/agΜ!vvvӦM3)d0еk !kΜ9frttj߿zj]]ov h^pmQJm!c dz>_ <o… GFF?쳌 x֭[G} iZhˢP(@mFuy:::PN 2%wH$дe>+`CC`F"ͽZvN!ԜL&rzP(S=x!nnnx,}FC _Y:ŋ/^dX!!!3fpwwCYN1V9>0Upx<`WrNgmmMΑ c[@wuff&a ,@mt3|'rssͯF0 uupp 0FE0}mܸqxxX.駟~)>h"c*{X,֘?HQ^ۋy{{6O4 !5Mww!9 "v$W(AI$_ L/gBhkkk(lkk7&Pҁ|ք!fjʤR)bXB044Ly't ӫ9 4@GG|>J\B3 p]=0 #FS__r.r-3F>00 WT"߿jY,VDDļyв Wt:J@` JX,0|@areeeEEE$R 66R:~ ~Z裏&''Kdɒ}5lllJ/D) ӊ(@MԘyDVI>hA Q úM.$ փ͆-uҥ`p`QTzq;#-H$,СȟSJŋ b3))d(ǃKzD"Dh#?UT^spp (=H\<RĘ|;F[r݋/888XTTTXXT*QP=zƍ F||3LV_rЋ͚5YRUVV]|yŊi Ⳉ \WZ Bh$S.PXWWg $QT+;;GydiiiNKTJ$riӦt2,D"iFa]v)ZRz{{嗦W_ Wi_ T>!ҝ`nmm=&;;[$/VvӎclEFݾ}g͡SzΙ [0{0d2'ohhN:9[nnn𤽽N~~~uT*BP*D.EG&jZŒ_I2~ 4 ##k)kFGG OP$rppU\'h4P($hr B@`fy{{Ê,???//믿>zS=944_wUx0 K> Zf͚_~l---DG8 ZT75T#5}Qo{Kɲt!}G1 zD ^,"{FzҨo!$vL#a~&Q)T*aEFj_^׿UWWG~wp>CaeeE@)0[0 M&AQL/3C[-"h8&=x VDC)eTw MZ[[P(1 +fkyxo>|xӧOصkO\.(1%ˑMR,++324iRkkk]]YX3`e$&I$)X,֨p86p8)'SL0cZl>*eJ`YVV=uJ"ΘW ?KJJ}}}=<P( {V[[rJ """.^vmmm99,YrҥGGGQ6*;W̬H=J৶VTfw`0 ǀo`0\]]*++E"Q`` ,// pttt]]]ܱϐc\Dt(L$h4JUXXMfcc{m&D_t @!u:d2F]Βfh0"pаN&,Jhhhkkoomm-((ȩH:n!ӯ ȧ=FѸ\.c#E|pC2 C hkI}}}eee̦&B*Pog 3I&/g0-777Hۋxu[[u;i4Q<䓗/_JYYYYYY|>ΎeBB~ik(!Cp'[XIXcc nnnptx*g___`6Gäh۶m;Q0 44GFFt:ݾ}zzz@ 9t:.>I3Dem󃃃]]]ɅFA_ ' ^cmm .Cda,}̙]]];wJ 27>2e )f͚ 󓒒,{L^m zQ} ``NNN\.*v$hfIHzCBxթS` U*O[[ۿ/--- xWO©3$, 5+\3Z1F(VWWŊCCC* Z[??ROvvvgW^}7 @uJ0ݻ y ΢rnnn5{͛7F.\pE ?X|y{CBB@$SRRfΜi;+ T8'ܘL#LR*/#<hcc3eP RSSQTdff.X`)͛*:ޥ |>_.(2 \r$ FKKKlss/-N=x`\\nook?n!j2 z[[[lZgL%Hc3yùfĊdq y{{9r/_z֭+V,ZH( ¥K"n `:n֭dcc;::_^PP_X y#CV6luxsppx ߿hh4ڤIM7==j(_)S]~~>ua)O 0p8TB ` P`N###v'OZD._g]===>vȸfsssO?D"h ᖛmmmcbb:00zjBRt:?Nx23Kze2 &9&3$ \3tuuks?#񝝝?;vDFGɹvaGGG fO?L>>ظqcAA9BI󭬬Ptttqqqkk#GbccjX,UT1W8g1ϟUQQ</::://o<,;;[,ogfxr]buLٳSRRbK2d0F\co LKKؕ+W.\QQQ[l*m0776W_Aygѱ\]]mll0ِޯ7===Woz' 򊊊0M[3dT]}||{;,E,ab Z$lTK^ZZZD":X,?N7~qqq7Wc5iq`/_r`nnnvvvAARSS᱋!>WPPPQQ ((h-\p23"Z[[['`c2m%<<6!!!&̪̙s)"w޹sJ}ǏkxB1@ Ӵi&O,Frv1үiՑ=R?jIIIpʀVWWP1̄Beˮ]&> E@@y,2jT8a<Ϝ9b̜< W͛x*wXJ4?6eʔg}v/Қ5kf̘1[hч f={|.\ ^ wۀbEEE_$rq%%%J[DrW^y\!, 1>3~R*fqPayǼQXYYM:uٲeK"={nX*OgEE~١Q0!H(rrqqi]RxuJ`0,Y?ᡡ)334OOϗ^ziѢEP팗/_裏Zvûf<`Aɵe˗/w^vvUVfXjQqx{{GFFʪ:Z]YY׮]Xl@ qƅ {96*BX[[po?xbknnHٳ Q0 ,r?Cs|S"Z7rɒ%lB3aa ,? h4vU׮]{G?P.@(˗g̘qAX yrT^cb`Zol[j40p$∈BT*JJJL[3)S*_=Ԯq##44t֭_~D"׿FTo> Lo&RƍԼp'XYY%&&>|yRimm-f)HBٳ0رxWҾkRYYY? RS0zF}̘ҡZRUUUUTT]\.,Y,ڢwppaV ,+66Ν;˖-gn޼?^fBBkǭ۷o? ,شiӜ9s`OǠ%ijԩ:P%D"1WCDbbb_aX[[XUKG3gμ .\l޽{-%={C IFq\ݍ0 1:ԬY 12:;;!?nmmo4m:CsN6mAtZ~-  Ņ,ɹ~:QHN.]>I9agg[&C!ǏoذgϞe0'Od0[͝;^SO۷Ν۾}{dd;Cvy YD[[[Kt:K@/ CK.]t\?| 0^ ւy'88Gp8򞖽=P"D? ҥKJR*;v5)ސð3g544!fj\S{m,醇)3f&(b[lll.nXӣ0EGGâm䓰PWWj*ooשּׁ,ZkY0ĴCƬ݀xBvvvԭ/w/ Xaa!nݪNJJjEEE``NNNCCC%NVm*xSll;E[[ۅ .\`oo * ðFԌ[. Fp(Z`cc)rX,… oܸL}Pe1:E'~璠Gg2++N[n```pppÆ PC3QQQ[ L R UD 솎P(9É^.\yfuu5HCBB6nhTT:t(//SL~L=HGGǶ6NT* ?<;k? !H; IDATk+( EquhVmu{mǭ]ZZ Wa@ @ ~O}M.aUg'\.]Ym۶3[De0#RRRa =`0~ᇼ$YDpوi:Ks쒓oݺETyzzN<@©ɓɻsNQQѤIx 1[XzeeeDD­$^fMT:88PlOkhh(B!V~vv6  =-رc趃_x>BJ+^3++ҥKl8v5kX,njjT*MՂxmmm|>U y/̙_ZZZYYPp8w!aCx~|i ͋Clx:h H"gu/55lbpéܹs'X흔uV8n*++7oޕ+WS^^?駟"rssKNNkkkbɻn;::bqWWWoHH1i!lLJJ3JJJ$Iyy9n|Uaa!0~gddL8={v``ݻw㏷zk)$f0^y商'O6L|A]]+r!9!̔Q(ZSNHOOojjwޅibsʕnrpp {gшVTT/Ns T*O}Wjjjrrrrrr IXaPJv>J󫬬lllG|zFbЌo4uq>hܷo W_}ꩧwuu(wyڡ[kk+ _ Bͩ}ΝW"-qWR566b͘1#33B\vM#V\\ m(i?^{^rΝ;ΝC˗/_iӦ[n}{N8Q[[sn3gLNN>y3>>l7X@@楚^dffJ҂T< {gd2 YYY^GS)a///ܭ?h`0涴\ӧ)>>>66V,dFli4ӬL`Y2l6<9 (<<G ϳg>sVMII0aBaa!XtGC}}Y~ QQQ\.W*Ձٹb tf#-! fƌ!pƍ,.P(ݦQ/R(wyH~~!P݀;cܻ9::k>=h4aQR-]td ,&I$Ju&bl͓&Mə5kqqq߿ljF{xx,]tҥ*%"B|@'AMjs:8Zݵ>fMQkk+PCCCGN. _̙3a6yxxd2P]]kBj/^tnnn+V@whlll,((@H !%ٙF=cnnnFVtq9smmm---cI0o߾}vc5(}R[{L$L&"kfmCKJJ:y$xL&4@ߛЋQLo&%%aoAUvڵ-"NMIdgĥ=?{xݻʎE+kBBl+( FjZmhhء56ke2ƌЛ'`n:υTGEEAeEEܹLEaZ}޽(R(fg^_]]xM::+ E}l zqy^z@1 oF@裏>j9s(RT> G/kiit8U׋bdqlH$bX*vuuyxx@?v$"L]xVٳg[axAM$jB͘1c,tHvКHfI":; vvv8q"ɣM5TVH[h4шJ;88DDDDFF'H"-p"##-%HIуW(HA;***)) </((… SY`?ŋSSSl2|:.ZZZ222qHl'OKMMݹs'PKJJ>k>zaVWWסC X,|>j$8l裑ܨ666_~%(q<쳸_~9T/!Pt:p~Cq$|R R]J%-Vڼy`]8sC5RcIdFP: ,QT[#=<<&LՎ?a*h555Ÿ}lhh1c5>q3otڢ߿cUCHcWTWW B/qpprWUU͛75 h4ZL`,`H<"-wNNN>>>---F!M+FDDD~~~wwNkoo'Sɍf<ɓ't:OLLj;**ڵk˃J|xx3a-DW_}NT*E X3Luuu,͍xjfʉ[F2trpOG5aLR fooo0q򏰵lj`&)##ih:Rd2٭[RSSqSeee"""1 yyy@ 4{Ϡ`_544@QQQhxtNNRT 揋+--j---555DUfF0k"--lii0`HZ[[AgKZaʔ)Κ w-0\dV:iZHt!hkkWWW(Zp@-b a$d HD%?@#NrK}h!l 9D Z[[j5Ųg,՛<*h4L&/` `Fyx  5J*../S*(ޜ9sz=I6Z8vkb Htt4>`n݂d._?L&qFPx9jmf#J8iӦY8| $$,) Etp5tsN'y6]]]a$J39w\T`!4wwYf cGkkkpѥRҏM2z@LA LEWYYi)))0yDvF)--dX~~~ 52C}}}oի/^ V=zLIIr8:::@Օ2rqˋ绸.wYr8 -T*bQTFѨT*5J dTZFG\}(.5Ff\@>*DMlheIc^mnlll:o)[\]]rNExfgg_3##cʕiyy904J쌏H$f&FN>]RRV-Zo߾W'F!VaaaL&Jt\.2R02XСCusݺuFdjsssGGGdd$6D`Ν;~mNuӓfWWWKV^=*EReddwz\\YT*EERgϞ˞ݾ}Z`bǢZnP3}3LD>l^LANF@#H$===Չ`') !d `P( ,dgϞ]p!B>j0=H\oRfE"oj*ܞׯ"Je2".\熢qFZ# xd2D~FcAn;8xNswwtppokko]{f;::bF_~W8eߏS̲ѱB"z|w:=ji;bKKݻwI!r˓&M"h@>l̙ڏ .\f4l"q4TH^0"0tH4񬨨 0TEEd$ɽ{R)Sͳh@Jfy<ɓq"##jkkΝp.<<<33h4* Tn1cFVVܢ?=a8an+M6m߾رcYR\.88??@ غuP(\f `r\V;::ï\ww@\OWZV3g޾}_}'(2 5 lF6RX^x .b7֯_O577:+qѸ|ry/^ddddffoUUU׮]b`G_*ܹSW_}wZf24 ƛԫ7n={www߰aÐc BĨ UUU(_RRqmmm<`aꮮH#HHlj6s )G$FfooR* $2 yb(H`0$d4ᖆc1##*JRY__?sLKd)[bY(b'%M6`dddc&L={>xkݺuoVzzD">v[r999ӧO/((8q0hkŹ Z,NY.\XYYYQQDFFN6(Q/Z5kP#99ѣ& ֭[T*'XQQn??'ھ}?TWW0R)))L4iFŋ/((8$j/j35kYT޽{wŊ @qJb afPB3L4mٲeà #hJd2QH4vqJ$ٓ/͆62Hd~=&);;FaY` ؋$d9Dx+-Kw' ܻw/yO?={=5F+ۀlʐ`ػK KX9RyAȔ)SE`XQ(~)yP(nݺ֓8v bŊoxW}z`` łEDD l!yU{ҥ 4o6zg֗[n&_[FƜF?00InY2yҥ111χ%͈0> V9֎A6OAA4cbbp)u___ `gf?$كBI{{m۶O>eBH-$;sss+**FeL BedH| I1^UyN ۆ<'tؐQmEE( ʬ!}LyTb N $֯_ @d2.] 'y``il!Jnc ۉnx-_om||||@łJ'C̮bGGGuuud4mH̚"""ng4 .]Zv-<**Aa;u1rd2Ҟ9%%#fT '=D|BpWWW`` :^1{ "((HT544888J4:Xss3##i )`d % IDAT=r=<< Щ6)M52ԨT*N'fΜKRA\]rHIl__fTYY#d2"""UPVUUa+UQ-GT vu14d̙ YYYfKyp`QTTW]]]]] )jIēO:?28"EV]@O"{0Өhp#3aR[.֣G^()JpppCC\.7qqq(/HFcmmYF7N/*644{b-W6mڽ{/_Cjiii_Mp~֓?%H$Iggd¶YTUU]Bit:B4f6 3??_~ٳ---hK/4h5$1_Pn۶-!!GXRZѣ C96-HJeoo/B}ڵf:tĢpÚg̘qᦦ&,prr#Փ"""U,4k`(46F0,wUwM///h>a2}}}=== BX"ax̐ C4)gelx4LVU(RP qȈ\1H[qpp"Iwoڴ)---//ggΜٷoP(lDllw}PV``ܹsܹs^xe{-))ϰL4 }prG zK^PP  aĆ^WBahRDcf- 7lnnniiQT$"0F90ڈ*Ch4#:ĉEEEl6l6b<;wO~F6 /zsnܸs!jP$Y7h/59lÞ+K?LG Z3p8qqqbS#6}t>g긹%$$ oĐ KC1owuubX,͛7p)DLFj؇F)ht[kOOOOOO9i6988C_^^n)3  ;#<WTTdi͎ ;C9VH@篋Ud`a豭@III(%VU"##ˆ1+g}l)kNOwƍ322X,f.;00jժ˗/oݺΎoQ(+W+߯Xmҥ_}:t!l_Z[n{ee%3jIdɒ~ EccaBx۶m۵kW[[ۚ5klٲxb^4vuu5{ex1uTDRowAmы(T oǣGCCdxCy]DI*GGa?x#㈉AmEEEfuuuHrF JACRa,9pl2p-PWWWQQpT@ӧO7;LV_~]Plذwcd O88qbllWvرׯO8̙3e2ş}4#-V^}G^ziҤIh4SNMJJںuޏ-Ai "H$QT>b`:>N"¯!YVVԫ,]3g*~\^_ssssss\ElllJeyyy}}P(ľ$??~~0 ~ @vvO?q|}-8lllVs,D6gΜ[nF)++۸q#j &h4%`hnn>}0l .XTTX,:NpŒ3ա-orJ+`0M2ŚlQ+|Id2PXSSt:[B-%%` B&ǏGO< e4^zرK.A… `x P'Oܷog͚eW>([?>q]%lpjD"ikk^iP(Rh4zyy$dZڨ<`ɠ+hNNN޽{wKKB8s |pZ72.\ʂ觠qwp d)sqq P3B)((!DŋmvIyfTT#4tk6tuublbjI2x."ܹsϟ?ݻwŢ t$5k^5N.>$ŊGBBBn߾=00P(222ZZZpD;nAWWjq5kV]]D"_\]]tz{{{sssYYY/dd.\O穧zn޼d3KKKY,Vttt]]ݱcN8>N_dɦMqx+66vĉ+4,DERГę3gE,\4FP kkka`X&LTlL'|'*r8B2e jsrr"\I$|6-[MI( 4-!!X"yގ<=='HH re HI?(DapppMM kub͚5pϝ;gx<^JJ}:~%p8+VHKK;~{VΝ BP %,,lƍ6l [6m~jewtMk4)::틄8ϝ;V-[^^^HNNN-hl P8 Jߟ 6nܘf6WZZ D[JX!U)Jnn.!!!'sA)B̘1ctZD TfBD"D $Bsrrp>::::;;zLP?^;997jS{vZ,,,E2 yzz{mp@`qEEEǏ?uTwww@@,[l9vsVZ4iRyysPקǎpF`?qppHIIIOOp8 6m4!Ns=٠ A{\ Y[rɧXN*zxxxxxXBN@/ = nNs j?Ύ\=j Vu: RDY%E C~~V:u* C:`0Ԑ(b]|9==}ݺu87b,q7oֱOOς ; 2;wiiiǎCr ֭[ϟ={c|}}Rի}xK-D+iqqq\.Wr72 \삂a) |࿰ُch4 a00WDG`/^L&zD9T*/Krr9sbcc̺/m۶wwm۶BkFDD477q֭ .Yqקps(t7 JJ)h 8sz ~+'?Җ"ӇZ&-sqqrpkhhp8z$O0111֣V5 |;;;WWWwww___K eSh)Pikk#j[Ɔ+)ɠB60b4^ΝFN9o޼%KEh@>a„,"AhִQ0x#1$ Tt:=55uӦMK.5_a_`?;;{<ۿNc2_}?[5a\KEcVP {VAA.+ \xEa.a===pmmmcbbF\.d@/j]]dwf/2 cX#OZB*z^?2LƧv J*bHh NJ;vX^^oa|}}mllRVO̶ӧOKR"cHO4ik4F:6d:::BCCSE=իWO:u֤K.mٲ%==X߰a{7QGA KRlii DM~~d JLL<{@ ؼy3_F;;wԩSÅ_P_h0E`0tvvd.N%jb$˵ZY7N~N<UenlFkH"->]`XJ>h)ĶjJJ!Nill!!! Bfɒ%iiiwލ6P01t:FTT _&֠ 2}b0L6mzǷnJP/^\^^~JH?w1/Alllljj=55ܹͭsbxէNމB$:x<^d [ djoozF;88bchbL,N8њ^4+MT:::b'NYl؊-niڦ"|>(Td2^ƆbA. bJim>e4u:va 6L@ Sqtt 8Cά_"dxHHQ`e^|E,[յ z\.4mW^77sL:}파 H=A1%&&R(@R pp8%%%8ĂãhaG TGLBk:N,C<`9zC!ISZZem zzz,M/Zee%]볈`+..ֶ4tww >o)Bz_J=C1\.[3ɓ'cYaaa'OO;Lravᴴߺu_R+Bx͛y_9D/I6&ieVnH$y&H666\~ e)b2& FRQC[EE )zIi>>>F]֦wCխ[ٵ6448IJr,7o޼tRyyH$O MOh [|Pj!FRW:ʕ+Jp A?4?钓'2{C _M>=;;;;;AJLnVj?2$mWWH"z{{]82Nɳ֠@ hmmurrrrrRNNN===yyy .p8p<( _PKx{{cc +33IѴLƾXBdH p{HRl׷ߔr\Zc2lmmM6('?Vmmm5SD"Pnkkc0yyygϞmjjƂp$Iss3d@@D"ill HLL,))k/ޭoӚao+ pecc {HZ ݻ7''g ?bcc233r#z@ fK.Eh QKbbbvv@ @`0e2ҥ)*Y@CZ + $X i4+sqqA% 0Ήp8aaaX-URRP(:::2338Ό3 \@f!R8qbcc#D"#L|Xq,A"RIѦO]oooVV^*9  !bh4X2**޾`0j{k |t:/ h4p z3gĉϟ-wPR$+ pmpMg2bq`` i! ql6Ͷ>ڕ?|x۶m-plٲe˖Yy$$RsNii)c4$z<}`0Ǣ_|RUU Ԝ9spFPrȞ={,]'Onڴa...X*& Dq233 6޹sdfT{`ɓ f-ʟ`8+9}|pVruu 14999AtىQ HFRq`yvq,''Ν;;wD/,%Ikk+J:88@4Ã瓗mFZxj5T J6Bwyծfgg͠FFF~]Q"rOD"E+%z 5 AG ɩJeCCCcc#GEEƆ(1wKK ָT*-//Wa 566jFEDDܸq>FXj20k֬͛7 ]vݺu+55uԩ~B/999 XKK@ 7++ e` EWW#LL5f-??????X\^^mp8|ݻ,GצN s9rR)3](/r)kj`0XQ9{{{C ZZZLlVK*JR$pjjjp,AfQY4iyyyaSR(t&RfΒǔ)S925쌽BCC M R)J{zzz{{mmm9נ@2y„ fILEN r G XL N3 mmmD7n+H<,߸qì~Wj&~KJJ9sH x, ^ ^ZPPP\\ly=3&Mڲe . OѣGw`~mffoۛ Pm%%%p CRYYY(hSNMLLLLL:u*i[PKKK$Bf fdRPqqqtt4[&$2gb1L-L&#~Dee%f X8PZZ:qcǎ\rH QPHRt9psJҒ)SHX,%]]]ыƚod;v,YrnB> ]C(Zm2ꪫ}||HVؠ{v%233 Ftt)SFmƆˣT*95]TTT*H/t:mX__/Bo$yEK@\ CUU`9s?.'>>իJb8gΜF+[fΜ?/]tΝj>l%&&Il`z/rzp{6Dp\hwqq6X,5XFW$,jB@G e5 Ű  8{{{%ar7EV.cj^^^nnnO=Լyi4\ vuժUǏ?tPNNNBBBKK˵kj U6mdϚ5Цc*++CBBqӧ?;{'p܉'Dބ ׬Y_#JΝ;{lss3NollUlb(L~oAIҾ>1 ;;;CK /dX]'O\SSc}}g322Lf[[T*mmmmooJ@fSToNMMz}}}0"(Jr*#88 B/TjdddKK(r ގ̺޽!5B0K񟥼wYې8D`!ɉO6ttt( @␐Hӓr CKKK]]^8,hs=o߾}eeeyzzx\5w\_׮][__QXXyzzܹxL&զZYYYSS?T*o䮫W~WGA=q*8WZZ*7|/޺uknnnb-SNݻw/ZFl5~'7_cccG~X,LF2$CD8Epp\.j0N׵k"##ý._jggWSS5k֬'|.0k ;;_|qUUUIII&($faI2/^(gPAMT./^ -v8њLѠya08T*Dc,%pe$d2|>>{xxb Ø M}{zzP-XHTUUUVV+ʟUgؓ8qp'9sܸq'3LQhdNIIQ(?[p`888xyy+F\\1{lbBRI¦nƍ666~V={,27o>r[o]p!""",,ȑ#ca[4wbo j\x ]6zj>ֆN `S(Q'a'Rv IjtgggXt+ś7o֯_Qww׭[G(SO=e$Q(HH :!@J7oܾ};BO<5Ԍ@pSlT**d2ѵ0jnkk)etPPYiiFb䍀{' V c}w\Sg $ag "nVvh}kuti֎]GպEAQ@{!|Ihǐqs=}_uoA ԕP Ϸ g)U,-- iq#μɬY|>llmm=<<Ⱥg`۪U_{3g޾} Dpߍ!BBBQ/gee}7/_ްa\t:w;w| NT׮]KII0S^^ԄH7XvڵkAWW!Z 2,F%͟h5ѹ̵BɭG"I. TQ`soڜ"?b.\i&hêXn`\% >aDF & tOxN+JR)~%DixѣG/"IHm} ^t{xxtvv544D"AUL)G וP ,n ,hnn'e mpS`0|}}YD`(>LMM 8tŋ9΍7f͚we˖-]u!!!*,,ٳ)?YYYx_>fBP&Af! f$N0G6$2Qd (uiYY=d0&LHJJjmmERDH F+###CܬRz50#Ν;w0NOO&My&0iܺu*883@AXA._laaꫯ> @N;BFR=iv-d~uFXE! C[gF:tлKGˠVVV:x53j*3???++ ðr}G #4u.P ШiBl =BYOiӦ544<~FCo;[ґ?pٳg% \,YC{{7Vu@8pw߅eˎ;&?cƌ^ѡ"PP(ClllL&k-QsO~c$uv/1 p8=s dL'aUvv6Zb={aSejn`6b>dkkk} Fj!i`$ z666Hl񲲲tf,,,M hz1^M/H^ ymvもsUTTҌ~gB;**i^/ -11m:}%n߾?7nȑ#t h4ZqqǏg͚xaÇskמ>}+ QiFsuum>VWWWWWR^^^Vlfff=]*++?~ Qח`ф]iFQgёZַ* Z&i(Y08C D"NjŊ\.W_]h ź} 0 ۻw?d) g9 FFF+š6#xfeeKt"?pDݝV 񓾹\hooҒrmmm*ؘ|-3ЗWDEpU*L&CLLGGGzyy9::fddTTT=٪-^T>Y^^Kacƌ{n]]'\Cd2˻pUƎhѢ'Nlݺ_^I}Zx}G IDAT>kjjz*oΞ]r_R`k s&ɉ"ð25{lrZ3\ iHvuJR,** Ӌ}?d̙/ˁ=zIL_KRa/߳DSd/) ˗I Q\\I^ L0WUUUWW 쬩AU)V-//7T*7{ #waee5zh I333 >|8JDtzxxZ Cmkkkii]]]oMMMlmm}}}́x.Aүk888xyyR{.xyyWVV%NͅBsA0]+ JѴZmii)Az|}})ӧOVy! D 3b;$_F_Ӊsz LMMp'<O' 秥Z yyy&&&z`drXYYQ;(ʜl\a燬iWWWmm-]EgTUU]rE"T*:>qD0t44 T=Spf;3fȐ!(΄-4n(Sߟ %177י!dXaaaM=z "g/FFFSJA!+4 HMMiFFF0ؘd2FJVW@JeEEN~:/)))***.. OA Yjj͛=:fff7oFCBCg)SرcܹcbbO4 u;>iLMMaXTCClw@љo`# xQ>|Fq\$_D,730Jw`///##BLvٙ3gVL!bxŀׯy.*ݻ?hLSZzYo03++ `HtT30VEN,\~}ܸq:ɜVBׇmh-ŗ uDR QLoїWD@www_ >ZOHς@s]v 7|ڣF5kYGx|mmmoooGCvM$߯P(LLL0/!ًB ` ] tӧU*մiӶo+~G:u ԌK^ I}R;AYUTT >6dar dIl>RǠwf͛;::j)Hc85BCp0qss ,..訨wQF]z``˗/266^dܹs!J/]_(˗//]fan`H˗/}' . R^0''3g&&&vvvj4@@n&Uȍ:1Nߝ tNo1,`e6ܶӧO'zzz||+) pzСBƍ5##C,s8U਩8ZWWn |Jl>'TI 0333rZͤ(a_tZ2eOeeeIIIAAApp05͢`s={.]QPPpQt͚5e\.wҤIPAg 'z炈N_3x]]"{{5;u^]O"Hg%w4 xR$_ J~62Ǐç"J/^9y x<4fW3r]]]355-***)))...--mkkCQ!ٟ_珋ꫯ9xhZR]]rg̘eP4M.?~ϷyK/kjj`0'O3е=Nզz!HAޏr;;;H5 YYYxkkk:c@[TT ӿPmҥK`4S C|rvQ__5K.]tj'Lk93ĭD üWTTM[j5J I  Ew"Thkkk`ۙ lllD.PkW<== W@n_V{,8$Cٳg5g͚eiiy֭߹s'** s`׿E")\ #66ԩS_}ڵkðZX)Mx7cjjz̙ZZj G(խÃNwtt|>/ Q"-XL&^QgΜ. d2/ ) d###uuuPZZ*njC!Wz#FMQ顡BeggCHSPP\]N*fgghp}a4:hll|7|S'qp8ONYnxP()rkצMFhKMME>Ӵ+WPQ BDjsss]\\̺B!Kqppn둁cƌ!M2 5$ZZZb1F6m0.;gΜ֢/\KKVXo?ƆbB!Hkڰ_~lْWW>{'ennZSS <.\@ͳ)m)^%-X]\\o5v֬Y!{OdXT*%˺f͚u,fmll Fkooomm]t)lD]ߏ**,dLMM`ZRRxtQʠAb 6 kԨQdQC{{{^^ Ya[[[SҌ{SXXHf0J[_d:҉Ph֐Ou(֬Y#mddtʕDnOāLh&E èOC0@AP3L]QWWWBƿ@qmmɓ'Q^bx<>IPPPVVVMM YV>|(q>oA_0bF34#?''XpsssF6N>}C"(4(:rXvv%K .ެe˖Q䷫z-www`4 !/ԧdX=gjebbBciYUUMKJ:&7Ҟ<l6j~V_BfD1 3YQQQQQmccrцWP@uaaa`GL&^{={tww?~|Μ9dfy]vf SЬ+W(@HƦ@ӕ9 ###hB0 STݫ$3nܸ͚ M=s̬Y,X~:tA B71ae`Bi!!!G---- ri0gW.,,XrepppccP(h4>>>H:XabN_NHH9y򤩩)Yٶ# ͷ(A%$$$99㹺xV㚚@/;zh++?;vx뭷|g#QF?~8ꋯYYY-X ..NTΟ?ʕcǎB]]]ZZڅ *1Yp㱇+Z*++lJ?B8>.?cff&$a1 oeD%ε555``ooQ__vvv i/J*7o<|9ir``Fom@>rss mwW>SLvEJ|իWoܸfQ\.PB$,++K&ZXXեSH$0a46X]]SF\\a2 eyy94塵10V{ƍcǎ6rES E>qS 21e˖Ձ+O?566BVǧ/.2 nL9afff6ydVr@DkkB#:t:G⋗:zꛝ0[XX /\jԃ7l6۷oXrNk&dT*juyyi jmm b2= ?[YYgT*ooT 7233l6`V}wN>_}9!HƳ'\y 1ݘ|\vjP=h@C,_xں_<=JQL>BHfVVV@׮]{7nleܹxW\0ؾ}; {W9իW> `:sEEE `X---8NUUN WJ\.8~… O4,44zi_z@X|OtÇ/\iӦbN GYDB1y嵳RDZ/߂dX ?~j]]] bBBw}WRRnؾ};# ń@Wlkkŋä1}f4LT|c|MMM&&&7oGC8` "11b!8J0 ZMm&z]]]rr1Rq…gްa0_ׄ @n>qݻwo߾СC`= )Dn7&ԩSN ""oU__P(5x<޶m۲ ""⫯-,kqqq W^h~RW_אPTȵG'p@h`qF<_YXXh3gqZg F᝾E"'Oh43f yҩSR)(HS]] =;vرcСC =}qHno IDATqqNp8SLyמIi^nL-(BښWYY똙EEE9 !uN:yf8VE"QFFƔ)S;:aG/t:}ͫW7XVVvM6x"W_@н+Oi\>&0?=dFb2eeex6lO0hb0UUU bǏ 'L R4mٲe_!` {{b$ "_H / D4 bԮ_  `)ѯnܸ1cs)++khh022璐M̙nr;;;fݺueeeާO rZ[[777ݻ˫]* 쫯JII155 hmѣ_=33`P?ݘ̷02 yĉh 3f̽{-ZOmܼy͛eT*ժU>C!Cl۶-11ƍ-BϷGjuNN{Gsvvv?'m{ LR&X,H]ïuƖ: ;:k@h[.H ˧*̙3 DEE-]4** ~f 4 !Qڭ[ڞ[o/,^x͚5͛8q"3aH3H lڴipŒ3͛tݻw`/P1Y ixł1MMMxsuuugg/w莎@.* 9666ǍuܹfcccK\YYYPPc ^:;;Dp"Ec} GX_#?`k+0]!5j:""x}||®\tR`p 777%KK˼>> ?y$a˗/={5kΟ?̙?|߾} ,Xp!s,Y ϟ?ox6ގWxa`ztvvf *(=!>:6+Ԧ|Df`۶m3\'uuu|#*F{{fvCCg:n_Ol0^hnnP{X`-77Z~#?>0 }E{ TUUUUUsJKKBCC[IMMeyȑ#7nHәL&bjii+W9BV[ZZ~(1nݺ+W"<V\iee駟iNAFohhD\ѱJ(FK$[[ۗ^z BBBsrr` B_''G=zHsZ 9@|@C7e6o޼~+W6>|t/]TQQ1~UV@Aw}N,!:ujTTFgggGG 'lϞ=P7nܶmˊcǎݻO>'e`;v@<,,ÃFBH$}U}G}[SSJ}ᜉ'PI2..NΘ1D{lB:nȑ0vxGGjHN>>>iii֖2JJJju/ bŊׯ?W^ 555</!!fCŐFf6}رu}?Aoܸ>x~`޽{9B0Ryy ^?+++KKKy<ޣGOӨ;W_}~ԍ7>쳮Gz T v'Bsqq4iRdd$ބMꊏh2ҥK_y?XreggۼyjufffvvǓ1b㟫nPz 1 c0[lE8::utt۷$N6/otR|||RRRϟ??vؘ:wh4GcF̙3iiiιxL& CF;;;g̘yf +VްaCMM_k.ɽ%,$2|P;v؋G&ք_H$> OJ,t*J,C2XBThii0 0{pH$BΖpb%-[[[!H^8**ܹsuuu$:A`k׮şrl;\rE @)SP`GP&v QSF_XXR| DVVV&IÆ ;ZB߿_$uuu544hܧh@+ On6l؄ ݻ$c899G_'4/Ν;\III||< ;|ի*++J=y`<&H#9kS*EEEr8<<9)xAȑ#ǎ{w:),,DZv̘1X,+++DNHP ~mBT$##C,MqLMM<2Yc0SNMII666AAA>Pg>oCnNt<#XC/"}"Cߣ R,`999...@k FxxxxxxMMMRRRFFFaa! ۾۷o744xxxso0ںzΝ?.\hkk=uԓ'O|``rbzL9:;;;ҥKnZ|@#@ðݻw[nlذ鏵%"##;NSN;v ̀f0$55UPj4AT>$i4 sɷtV&O Z-Ųx!>(--7C`Ν '0ezró#111o RRR.^hB ڊԈp(PZ˕J<!pv`~}Af011h4愪L&+((d~~~G`Jx<ёL4iҤI'NHJJ~P8㓐dB6*9@466XaÆ3 ?p~KK ?޿_"XZZ~3f$$$;v,99yŽ ֈ#233322`G:D-ZsڵkW\\Ç_{5XLfll ((lC4_srrF1|q̘1vAH h۷|M ' JK]<LZF PƏ;9Ǐ%%%GAP }iaaa/&=1 6_qpp`ٍhbgPPW_}% O>}…7778LPrLC_<4>ؤRΝ;wqʕ۶m!### J,Z ɓ'gnill?oذwAoLLc` b|믿0W$UUU9rdTmmmMMMY  ISSE/ݻD"##333'MO?!:Zy{{?~DhUDr>^L&:{\.ommE ooo|-X#/Dtuu0 ІB#ݻw;;;.J***jjj0RX```dddzzVvލ\~0 >}/,--(#Q(NjGЉ'OGESH0]8eƍѣGY,֊+[L./!{,%2؂ܿuvv9ҥKbPTу֥,>oook.(322z-###[[JX :o榧>] pW9r]'*(ÃV``yMM l&0TA1̟h4ɓ333A򍞞 [O ٷo_}}mgE>/|5C^O88@*JJE貲۷o֭[[@6@O0 {˖->|xPPL&xw}̌bTZ&_~8۷U*M|'_~eII jtyЖ!C_~wڵ3fL4LJ-2! $ N:eddjժ7x+d2-,,Ξ=KpJeSS l׮]kD 9qǏǍ`0D"jmll(J=v @#G7z_БW_}u˖-0hZnJOO;w1cӯ^J7oބr˜1c0ڙ!(4-"""<< lM---cǎU}}D"ApE>vvvr8rJzH1>@?B W^YlkE M}ǃ>ӯJPT\ _|E!#33o+((H$xիWGmff6lذz``CAR/`2ׯ_p!/W>s[oejj-q<|H$>`ʔ)`̃AkǜUssskkk/ v;h4.G j(J}S6 Jt:V/uI=qDGGGAAAEE;x.fΜ?}GGVH$)))|>\"2wyXX2fI(dBv //m۶ȑ#??%nzR҇?~% ] "//ʕ+VVV> hҥs ɓ'㷁RݹsGTN8qɒ%iii3))iΜ9xrqqquu+++ `{>888L2b q5p{@tBN?2SNGwX@?7n:;;;;;"/0:uiUdjj:fHqPF1Fdiee+̚5+333))RLQŐ-`r?sLMɄ v͚5kLLy{{X,-  `x!ีҥK~kllHڎ9}Q @#22ĉ aEJBXmQ/'HxIЊH^z%)迴Vb IDAT~^z5T? |> trrh4OL&qZZڛoi+y==)v64~x|-d-^ٲeKuu5?+YP@|ؗa=>~|/ݻJW_%y LP733kZ__aÆzlrO&dbXT4嵵L&fh3ppp s7nܸq--- B⭒U0wwpSSM6ݼyǣGfXJ/KnnnDD/"##wex*h d`p9XVVo rJ^ vwwJVVVcƌ{nvv30:fdЌH;h\PsOtRI&'stt|7?~Ç8;;XZZ"KI0 wީSPhAA ϟo8:+dkk+'BJc #`۸q#׮1@=~7x@^{5 Ł8Y{pp0 )S^Kw)Ĭj (ggg>_]]]YY[m533c02 ݽ#g0/)30|>?##ķc^^8 < `/ 'S=fw5 jC'OgfffffbfbbߢOL&d1ظ"%%%%%b۶m9uf'N1r|Ϟ=tr}QQQ0`@Ǐ;v hѢ%K-CaVZrѣGۇ w}W^^~EڧhD"V|6:wvvv^^^"T*J,BHKw 3Hz6=~xԴf%%%<0D>|Sx…sΩjy>+++vPd`Жx0Adɒ={$%% /_ĉ?'FYPP ̶n:X/$ BH...}i~>rzrf\---?~T*Qḹ#Q`0y;w^z%Nj4h9 ~q8xr322*C|5uԃ޼y `999gΜh@/DOd`C[`Hٳddd$˟f^>7n_]UUpa؈#va`fuCw -[6|ro(7zh'''KKK-+++۶m[CCCkk+H޽K~6eiiiii:%4H⼼Pې3R`0(2H$bA똩)<2ŧd}j|G~ީdB&J'311immdO3/=jԨs544dee1L???6ͅk73౲jhh@ΐswwDhሽ#.]`j?a::;;띝{ >qD1 J766盙A- yLJ5(qLL̵knܸ3% [ZZLMMQS'%%dSO3@C[۵Zrfffτ:99䅃6'Bǡ/闖|rCБao~g>suuruuu`>zh'xkHFL3!,x;$Q||||||T*P(ohhI3!$(ur2V$MLL,,,\\\L^~ׯ߿ٲeM^';vl||>ٳ4zZV,Ѥh$P%@s!s̉755Vaݻ|>$--ƍ0N)gA(q 80bR yի}Z` 2 ~9a``hQسgϊ+ЬQBѣ۷o_'az|-,,^y\Ʀy<@ @| xeffe9rر79 GB!~ aP EU<8t8yxxXYY$v0|ʉn26mZnnnBBٳrww777)y:BPt:]-rIJev/Ν \>ouuu=PA޳ⰰ0.;tЊb2@bãŐI!7sN.P(B!|* oN+'''&^'Nm H$I (X,ʔQF8U9oiip8&L@J%%%YYYOS f@uHHP( BBBRSSϟ?AB999~~~(pΨ( T&A*y)Hdmmp‰'5޾> jjj`HY,*<3}'!J!*@AqE}Qh:um:k\ΌӪL7@, ܑE'$@XfhAQ_prI8${? vttHR+++Hq͛:+U*ZfXnxMM#3*++r9Y-P(8~^b_|xNRVx. bKGG\.Xjy4'111##`/(cP(744TUU f|dj`rT*)ljj/ۏ=z]b0 `˖->/"""N:UQQ!@_{'OXp)X,j|>[r8w}wxx̌M dx ðX;bx pR))) dØ(<&zjr״DlX/JGχକ飈dl!Ł>FRa|>?!!!""bڴiHD=XJYBG vYVVFg͚5y?xő`ii 9-[FPD"ї_~ 3RCCC{C)33wwwWWW^HcT]~f!bc,,,>S_GP 0 c]NSP(͇ͮh4wޱc_WVn ZhZXXHP)JJJ޽{|}}/_o߾׏}<'&vmS(bLJ>>=ׅ@b "ZH$J9< eeed /@ GXRZ-y򺺺lll\\\lmmi4T*=qqrELe{ Xd y~MXkk+%iii6.h4_;4/}` 8߿WZ%ɾ͛7;w0{{{~[~gG {n}69!HZ̙3/))rʡC:rEpz{{գmmmJdggKRkk͛7曛6mڶmۤIڮ]fL 2www:.m,`gY d,_z-BqMxo3ɡƞ:88LRq O>dΝ999& `Ν׿Pri4H[BBBLT*D LnݺpV $6\rp8vQQQፍR<*J&xxxL<9s&pssX---l6{ڵ/{yyikkS(SL! ŋ666#n4޻w+44h$l6!BMRZ[[e2@ eee5662qnP(nnn^^^:U\.ƙR)...ૢR"aD醆j5/0 {avvv___VVVnnn[[ܲeKRRy.&yV/O(U`7pH$H#|UUU͘1w܁/䪋FAV":99{t:l۶m36"" 577CJӧOԞǏqp@+p54R*qFyy7w~"F 齽JRV̞=ۘ/,,dBh9s&BwOqttd=[o^~=yT|Kof趀xw> 6 b꼼;\._WN߿6iaas'O󫨨okkkm_ w^KKKHHֶB{{;1ICV 577d2BALvvv\.դILf___OOLY[[Xĉ< 4iRll,"(,,l̛ЛXz{{{zzC$6tc9@CCCvvk B"> 88x׮]}lP(YmC C<9~~~JVUU ,/ oŅ\.o֭ ***bܹsҋ T`ǎS(dJutttrrŽ}}} v)}'Jrbggu֚TJR-,,|>2NMM}w ֟ bL7eggK$+WEKIIqFYYYqq3=|󰐫Lt 16yyy,[r߾}]]]t;tFnܸheeE bFAȨ~}5p80#]__/addbEGGsGvЗ+'''TP(k({dd˓J- ɁuL&3"""..q޽Xlٱc3b֭[jJnذ!::xTr!=X͛7y]VYY d2ٹs֭[C@999===Љ婺ȀQP.\9r χ9!+RL_tpvԇOh@NO> y<^|||XXqe㫫B!a/R'O,,,,,,$o>Ye ؄֭[&od߾}upppܹ˗/Su Zblݷzd_ZZz+V4Miikג)I}r .4%?==#e+ |~vv68J&Dh!J9sf||l\^QQnX5O~mLjN*&H#!L*++cbb em۶kA#r___h% L_tٳ´ZmVVaK.5CVV࠽DS/ ..~:u|`p*sԩlB%''w&l///CH;RSlff`ٳg#"WHq0I& Bdopޢ"PXXXX[[㸷ƍSY WO0UPP+tHKK0l!P,2XEJJJk ZAP2Ύ|n`Kzd*]]ͧMmiir݃M|$_}Uuu~XB 裏h4'f@yGGG]]z|tB݈@D&)SC`&"mmm:###ϟ/PH ǧرc+V1cƞ={JKK1 4i҄ 'C9τBtR^0^zʕP]0 jOS*2337m^SSvzxqLvXXS}'k֬ɞG PR 60qi$]\O?wrr[nۋ/ןʉ'z H/0Y1A^ZDT*UGf?۷o_ðhrRp_o@4ԚB Ά 9bƉFvvy P\\x…]v{5k֐tαPߢZ@ C ^X2220ݻb"##oNѶlbkkTRR"w-?^zˋbe&CPh! yrHR͛gl۷0 9sKXmhhX![\\d2iO?\"q?:&&%OR->x𠱱QV2L{{'s$rX,3[#HO;w_u3g`fl͛˗/0###/j>N4Z~~~}}k:RyyyD|ҥK.-Yd6l8p? j6Y dOhJ{zzzzzۡm穮a/IDATdį...:0įIX\\ـӧ XYY٢E<==1 KJJzK(`\JD"Hlmm,X[`_JJ NbO? w%,0,??|rl 1%VR)Fnt:|NLMp`9SSS[[[ss-"! c?TUUݺu\a;T*]n陚.0ܗD\N |}}7m ##C(޽{ݻp%i)S__\JaK.`Pr8Xԏa@ T(MMMHHOԩS###(xzz۷ W^yߞ;wnƍ4-*****J\|9###77؁ Br.ce‘É:ݮG:e6f#H2o޼3g$''+m۶s陙L&K.9=UUUoց`N'&&&&&Zܾr.~M]%LLxho0gxxh4 t&Wx@xlq~w}gooh"c{Ξ=B:M. ?Be!"Ϙ>,33Jeffꠠ V[RRBq8q?0,&&&""ٳMMM СCa0N8"PEER666/|E@b+;wXZZ*I{yy999UWW(J&y;vpjjj0 $Bl1 R,*08W`gϞMMM-++q|ڴik׮MIIQ* ѣëWs`s̩' %%%c @ P l:͝;۷a622rŀBD*nٲe t:#$`q]`P(7o^f͌3lmmE"Q||<90+++8wILLݾ}{dd$ blGBB‚ ߿W_A[Q...֭C@J@˗/'a8 1?'8ٽxIENDB`freetype-py-2.5.1/doc/_static/opengl.png0000664000175000017500000023447214664131406020376 0ustar georgeskgeorgeskPNG  IHDRJ#s5WiCCPiccXÕY4]֟s+U{މK"ծ=%"B!U "HCD RE4R}z[o֚;g>{f3\خ{" wrž0A ձ2|N;*# w;dcOpbI %Gڑ'O + `_x`FSP=<Ⱦ`:oCE  cMl0ϞcQ7ezxſ[(Iᡁr%(0;е[VxXI&v;󇱌_og 0f1\(* 7Oaãl8?=?r=LwlF>;ae[@ xهlh #0t@pF5!C24.nhؐ#mv"c/`?czy%} @ x:t[>` ]7R %Stw) Rw!x+L̂n^?za 0c!F쯦gA D>YEs?j갫,ܿ9P(9"JD^3HP*(JS:Ngw%voa ' %|"xuh὇$(WNFVĞ_f7@̏E j@]EcB$E.?Hr/j -ilQXS9ԁ60' /Dpdlp%TZf{ 1L9wA AiB9d9A/ EB P* C%9Bw0 G0"i BaCD"q4D.QG!oH!|HI RitF $dYlCG"KuE@$a[QDT* *AբnzQi2j MDK&h_t4:]A@E1 3F 4b0ØY7,ˆj`-l46v;]QPQR8SSPR\xGAIG)DFiIEKy1=?abTw^R}p8U5;+5qx8^/_#s{'h4R4&4^4447iFh>R к^}LDGI'LGADWJJ7A@/KoIDC!<A!a$DB*p0Ljaa4agfl`d\fb`R`r`a*e`bF2 302gqzįdT,lיr\?Β>=gtfpea*mC*jkk~^0UkS[\WwzD}d%KC -%/kdnnMMﯸ_jvʵׅ Ⱥ ݌<2jݦvԭ |L;::oڵtl[=Oz{}p^}h(('OV+۟s}Uk7o߃ofծF&v϶-Aۡdݫ>_ Np0ͯwA—:@R" %zcC)l( px)j Z3:wHSVif<+}S˟gOWb'$$ d]cTUsՖims^w]̠pX$޴ڧmgd5kCoaepN=]Z]ָpOt%{){PNCXBVCG<";r]b$b~ŕēT1IɁt 0Ҧѥg>JZxl&y'/T:][Z:$ƙ򙊥+>Uԟ56p֣!ahHh1=EO)=~"˥W NaFf|feg7ܛ+xNmaBE%W>}]-4|.rw? 6~olo_jB8!Ph3 Ee =N/O-F#D+J'M`Hp` fJcbe]d$qplG\|/,!'Z+(!,yCj]FK}R*AJ=wo&FKK;JV>@(ӸޤtBRJZFVЎs.YNζ]8\θոgxxyj9^>龮~$:Ҽ퀢 `!CsÜHȟQ1ڱq cEIȺ|pEJjjpsQ3Y7s;K>~yVISE,JP%_LOT :7VjzyNLK \{}J3B&˰@GhgҮ; ='z#ݓO86U<Ty7Zy4zIX8q3K/j넩這و7soޕΟ_hz߶سËk˪+_t]1Y1(@S05lJ'*y nM91T8(B,c,S"sq3lO9?rS T Z+ M/,,/_p[qRiKCUUF7I#OJv]>~WdwϢȒdj9onmpv ݯqr.9"`k;}£<)><>}xHg A!PȭЈ0" ##?GވuC5H@'4%HB'5%b<4|0;U%&m.#HQLYw r|)RNo9Gη=XVuMa_QcQ%Njei9V~siUGIXTA% MW_}tmMfᖽmOu\l}=wz;ܻv}re >Ny825n2l'&ͲԳrrMp5C@|+VةD@:@/L'%3N 4L3'|Pnad @GP4@ phDEqrfvyY@Wj7:%"OQʁACBO}ϷQL1}q, ~Sxvy buf1 mMW+oH4nt޺ۓuw_#óO>s>Y42m"e/l_+k[/ݜ"8HyD ACl{a)"QDE!Ր:Gu rF>gL&̘ZZX$۶٭:(9pFr8Խ'S}I\aABBF""7b:X% $gZKO}nsT9!?$xEZ¢┒2rӳ <4/|{[Ackwn?CmAA#Cs^Ȅe"òz-݄c,w2לO_\OGOXLDIDMk%$禲UfHȴZ˹|B1bKGD oFFsƲ pHYs  ~ vpAg`dIDATxwT\W ?z}5a{<=mm IDcQEQE@9$2BEBBH"XP*6 G^^ܪs}g_M:"#2"Fy[#Ȉ<"# GdD27XF#2"`xDF,#Ȉ|eo<"# GdD27X?r8jpww|[I~/(5q,<]&rJQ ShY ~J>>$zOe3W}RQ6[o|]=E}=j`7ݦV+փןa..FixK?]wg ?$' N~96<||C8&ӆF CU/n7P)Iz^_p4#{6' oU_e`-3 p 몿STwwkWOrRn~i+f"Ʒ KfClcݐW ; xn* 8-qP-z X88/2a^x/!Y"dڣJ\pV=^X8nnNrf^н7xc/w r;_pql,bFQ|Q?NMh ~/)=fѦ7r#c!lI9zVDn9,4ž[d|+&z8KZpg$۵%wrv[1k &DyHX :@{.\CIa妖H^ h3:+%dp4Å$]%+$_c!c0B(GoTI6ql ^q1\%bpX˞8@} !ޜ6ך\b=ܞ<m ӰU|`wwܙy3!;:vرVxџ+[_5rGs_.2Zb7ogW_k>68v]fT;nj=$Aǵd'ߢn#Y"p}$`9CBtTrʹ͐:ń0y>@Wʌ_mz: O+^iXAmlx $Hf3 V9̧ (@o7r=uZ%'VY$hjS.Vh~?8~ ~j2N3a<`3;Nq;>/ƨbPf$N #3O`У-Y TP#]7aIz1,@Tr]W)P"5=f X4Z"y,ljТ.`ObH:房$J|b}!\ = g{̡.UԨnyJb>r. Ms h4PUI8'#}ZY8$"ш0XaFcAk|j$)q7շʰ&d \%h[]/厴b1aQ^\%1{+^PWG)g_ )9UO$soc7u_?>W*Z_ ~qq4ďm/4Mdg^j91ie›蹿yϕL=-+hy1j L"M@$1}Bsi6X$ 1`BGb5ZCfpjK 9GqUQMgUޮx&`XHMЗEaH9Ẻ$BU BNNi%65Fmv&oz$bFRgo8NRYD w8Ɔ.+fpm@1u5^pҶIsZ鏟8H6";OBo?~p@ˀbB{':* I7 K)Vqc?4Gwֿ4 ;-_2wFwZz*Iy-x"YJxDޙ,x+5~1N1=IW=lE<"#2"Öd,ϰջOzy}-b'Gt}ѰPh`Ow ~[{ivSV/滑|(<m;] 6.u 7HCLm#DʻV?tq(fwq4(cBC)^b:_plF0cPpḐG"x>LJj ۪] @ݍqb)5zXqǢXxWwxvN~ Ej>GQ}%^#?DqXYKZ!8; ;'}Qlj==`}R=&|S]J֬aCӊ p1z;y1uT媉:Ľ9n(f t*+O{Yփ 3x*j ّhLO3iB%7.Ko<:S\~b|m&BsnrlBNL  Td(X=gJ%*< Eˑ\VAWKw~5H>Eh?bQ;":noK.;`Aq˔hDsC g񞿋9^ 3mPm]/eUJV{b~5ܧ;W!^4= ̼/ɝx'5yT,?6`὚nuܚ|D5IdQ\LmrYW݋|2?s ;o^ֲ]F} 'ANl ȍQ>D-l l\ƌ3 =&ulp%twA Dr%hZF}q6.x=eRS2'8l~̢K8~EK;O6o+"u>Eso./* \{7|AژuKhlKv[R]UckIcZ8g=&pmozn *'g$\5A0]Oj YP[ܕn摖Xh%Ug冷o4ki;?~O/=èϜeT_c?R<R~De3vY~Sn\ k9/9YLWۑYMu|eאF'G@%K#RVJOSܓ:.N0;#Xd91f[_.&"rm鰗?GdDFduyӋK7i7Y˜xu^xIx/VR_(xmo _cei: Ci57tEA( ^{ K Tgc񠚨هxVfV7 >?;Gp'ŤE{-]M;cuywoF?dF0˗ivlGs*_;W9h(ѳI8"8-o%7 `ܴ >߂N.Yn8/LN`dn2.\| jry Dqoj]u^"awY:;~Ryֶ|# [v`}|s(7bp/'Zt6Q{q+ˣQ:[c:s\aАӟqOoLw=P ufvd\/4Zw-,R)Nlo9p!'{N\ 'vs!h}u!)k+_hn8{fptVG*5h`^"(䄼n{95 Kь 3\VƢQʀvĒcҙF$ѹxZY2zu~( X,WcT ~nr-yr&a:WIuI{+'-b>_[ [;Û@vw׼}FMYO0TŖ/ +}3.B;JhvZOj.%U ɸⵥ38'=CTJ]GND^4W =Q(M/(#˪ħeG\3UL者Ŵ O1ql@A|W,{ <4 V9,P iLNqG)fr׀6WMz:;s?JXQƱ0N.7HP<-W';\f\p'5-@eWh* j82g9SQmF/c$n or6&w=br'Kyi4{'0V,4Kq8.~L ryM\,Zv(NMil-].|p9蜨=,e3G[ eJ)jc6Gݞdz4vdi8_[K'\"p+X廧숗_0KdJP uB;kgeR Rܰ)[; cEmk |>rkSlZϾjvNcc;= @Lg=pf؞ďz%woObA!EÛ }~mn]N9OO㽐Zv&\owG$Xd/#d`YzXG򱆷f?ʹ@5*9WfLXaG?#' &與ҏeg$SWsru"W+i??ooTjiyuFIŮ+oNguDGݩY(FKEȤ_.aBЪ΁,!J+W1e)MFM5,2n&8$1b u)F#;9D1`yX8~o)K:Hyv 5b 6>c|W7$3G"HUUS3k)HrA=U \;q7`Q[p~,?t%F˭wz/S.,4hE\lP&ϧ?.T68n{TyMа>m|?w$DO0f=j$KҘ0թ'iq-;Ӆ["ܭQD{syhu/Cf:ş'bTvs|1H;(:YA8Wa*1hIŭtW@1w3q"[K=6Byl}6s vۤHxי`͓29Nմ,Sr`Sh=#U[N$࿮ЕDIv"tz pdlsҲ_M@~s?*=!SֆmX> Yd;-ʑp2j=O:Gn&)NHmqosY(p{' _=َRxFjv㷾Jh\ɞBg5ԓء%&w+Sb7 /t5FRxmATHײ4!50Cl"͝rTh0>y>'onI;ب "_ 8rpR.Y܁hp ]KXbĤy(hTٺ0y#.>̻9p2Oc ww7ThY_#7ZC WOPDŽm6qÖSEE?GX=lޠl9n[š(VWp:{h>J9 q"dʣ{Yh7@杗f_l_ 7P *bbfc߽iIOD+;^H禤}\z1|V&\BȻ%,(<}%bD@~dk#2"#2lynbo*5s_rz^A=j"fzqx~׆2vsq$\qg7j֛޽s4BƇ]rYzptw W).oo?W>70:§SdH_ܯ|UK{t^2[<}w%J^n> X|DO,g~(.J`V=@A-DNI6q!&`2K 8qhެ` 0B'26Z#rY8{iḽHJoNdI>"g\rz;EE%KBJt£a*wpa.;2?f< c+ˉpˇI[E^XFaPQ+XSZwkc* }.<&hxsk*:˷hc賷[:P|#q\ %;K'OW|3LxAw,X{1YM?y1pZw|l7R1 `E[t'V2 7W`C!fqA,} ?;/⸿Ǯ=ؓ}fV%;1"\$[sažN΅`v3!,{M6KzX"ږ&hjbWݢ`C-{>1\L&p[z1˞/5p~ NXYx0r g-kfs0@iګF-{LI}v.fò8ྻQ7=!ҡ]=̗p߱oW,3㼅rGp- >n ^-e˂K ż{B:):T1RSΩOJ=AZSSl ]9|F^іf̴{il 0(*成6#bU3yu;q=b K 3iVB5Tg݂%qwΣ OY(tBFw-Qcp#b9f&jKf@\vIcf-sQgbB 쉛ͅsy&Zv<=$D Ǟ^1}4ki/]FJ,ah:c#5BW."`?{Y<~l;3K:)[NBD"Ālm:_Iy֕"S'jeO| R@lY.fU t ?SvOIPC uƸb9]rfetS->ֽd&3=ͅ21A9R#]̹hh6i7<I )9\1 T |YI|< nY2j9F 9B㥸O%uz=%Y|mo29/!әeA#+F21xq9Ih4~Ƅˍzaȸh;g1l lhBXl5$m,dV+^J w?ou`5Xʌ7 Qg翭6<4IL0z?c - o{A@JA[.0#OȈp=XˣG>g0y+)*<$B*ZϯdK0K-/ :vO]VQMh!N]ߏ{{b鯓ʣt3#Lu Gizv;KzJs=oki:t},ayLf@c) !PX9qfUL϶NO?]O5MD8U%E'1|i.wBlKp=gplthͲHZ p~VE R/Cޣ5 f}XvhL8\m~Vi?lw]:.{oY\B.:\KƌQfTDx1v{j2;vj+,ǎk5]և{2c;u`xOR|>ͤp4#$Tï⤭Hy?{G W{Xo8ܞ'Bͷ&{_~p&UѾۥBQ%дӗR`dVO0&&'ǿg#Wٻ 1}ф%)Ōaj n$|#ȸq8Bf 0}'S$t-| [/g&e/bܘp}h3+5Wܡ{0?YGzIEv\ϫҊ) ?IjW.vc0Pz+6C (Ń,~5x%3m-5ŤΖ?{n3{6Xqv(?A[WB3k{[RfmY!=Xa4Tg^6EoJi%&E"}m ED;oxIsXEu4'kCj>u=N~'1Ųr3h`-srGV2K&wp'fiфCNzngV}ËALXvgn g+ |Cyb鮑仝 {i}4Mngf;LLX%r .3ʜn |*w|vcuY~p\ u5+ }QAP{q2 v;P9IsՒ8Mwˉ(WWj]Wc?S\{MHϵ9v~ 9sP,\EabD6C3G?2uĞ=Y'F[Фn)‹3-9=OS:r-e"W x[@4wv< G(++9 ;Zsh .pD9U,O`럙9fff$K%nɈ1 u{qmO+ k|繡<,N؇ ԜX9Ѻ54Ï* cF{5ṢɁDGj$H&m兔ki1)@1pq |ù)9TTt8JlHr0Qi`-+Q*i'{ni7^'$_~\,\1GvqKa~|;+ԺS,ԙO##(* L!T6aU֌!8؀C?9=lPya!u}6a^xv̇OKcL,ᝯ+v*4t՝ŗi2mjgxJ>!ua"cTήw.6۾eL|D:.CcN\0W4Ԩ_##d`Yt<m1HZ2/ _wN5o=xDFdD+% ےv&h`AuLsߨ9bD oQf'Goj|Tl}'ɢ_+O,%o%s(;*tY7Qv(&[<_xg{S?w$8r<'W5Y *.E{mZw%:CMկx(6Ԉb)59#p$ 'BPleYIf[{+L2,e[.fak nwT>Zt|P'[v6v/+$/yy@z;Oq>mڽ  nkm'JOe2p[{/'!B*+W82`}9s>) "N*N|hDjFĕ5C 랲ba=48ϯI!q117Ϛ[xV+AyQ~[U9,xhZs^Nh6eylDC8+].[kw;Hmr/[}As}1sZerN"w4pM?u_gb6)Bo}&bУ$*XGN6R(:6u)1U%ﮞ cr8ـIu.Hҏuw0uff>%A˩xy*"Iꤼp`K<,,tʗ2{(w| 8癢6l4Sҙe8Ul `W_Ym1;XfCYkD}3N a+ŷV}>^ˤB6v`R ݽu bt"=|+jw3~np$Dsل~V_B Xh}9%fLqpJ| 8܃;-/ViX9r lw\LPAܖb-Rs21d'u(=.>ZYX}Brx;`ljP %Ngj0}\ y1ZжltxIDT XeJ`' \gRcc=/(Ⱥ/xfJ܂_DO_jA;q!]US wi gˀtF &~W UbԹT5EGvX3c_Mbi+q *0h: BNm`1 iAGaccGj_%QsBluS|M \_ekS?b$. 8ΫihCXvcT Cjn<ξy%q/QblozVyu g"ց_ .±*/B ::4ػy4_3Lx9w\{)e"w71n1UBaU w%^4*N:^|v5O5`&Z]-Fz?&ҫZyv^Zi\%1|"9|>I`Q:kcrI z3mvD)u]"pT࿵l- TG.Zwa ,-^|SDJ{hϖ=$=ނ&)7l,4l4_K`CBrCBY96`mw}ws* #e=IB(w#(qu gSfe5%fxj%3lq̖tv =wHdA3`%{ f7e% u*&{vaژ_ag1ͅewT]C-y3Ey<'1bM( t]8wg"]P>1PMqQ=ֳ*yuc=7ߟΘRڿQ/*=@ԙ#YdoB{.8ba8as9ϝ(@$.w6sh8A{)hۄ-{M`@XK5iаЉ%}o|^K ?CMV2k= M=7ZXN$9BCJ-L*z߿?&Ikma`-I)aOsPOXT9ē _26D o1^ݴs`[pZ)]̥߱!R8*|l6"u̢ĴcK6Zs>sܧq'm&#XI*ɟOL)zbῡ:**5pI $>F uBI>g$ h/(] D3 ,lcB1?-fp [Ţ+9In ;E o=Pl*lw+}޻ {ɮ4/Z %.Na-ҝ6;i,qC$됖#D&UYD}Y\Dt3Š4Ա;*+u'HIg/~\ؐ]*cP _khN;>ױX/oŇZ!91)Y)8|%GX7r|/Kw?br_l%XHjzAi1B}쏓V>ߛw[|Yֺq{,]7\ÓL[Cʸ`7'c/`1Pxuc>ٲWSL7Ђa*#3ׁM=Iq,ԏB˩ڳfY:cAx\/FٲN5ܧ]6sss~V]ܝ2欫f۫1d3oxBBH&vpIwQu(M3@d wܲ?cQNq50 \nh:&qG̓eJ ɓDLJl㰘vRfeITybF}EE{5 I Nxۭ?a ,5cυ !h4bMj=eV^i>c`Cf3<~5ehޏzL7J*7W ,gƛ`? K3ԕ3cY/FnZ͇.E`ݰdϫlwz `~kHKыNl@*s=-sv-1gڳ6'qr?t<.\7q\2Nqo޾D'to؁7URbW"g3A&og2]=N*&+78T᣿,@tEN*$(8iQI]gME/m8ow4|顱k]HɄm{ }j*8X,t*<"JF\3jAK4|xyNװ~^<"#2"Ó{8Wu_& nCm֏W*pk5}x廫Xn1pw7k;1Ⲏ ҟo"4}t'>'SCmu vuVޙ%li||as9Ä 5y=[3$$ӝ뽕gLkƱ:}jo}#({_Owwr!Ɗ2M#E0mM_7pLd\  =ؿ'VNs4nwq*2Kz0R9ƿz5wH/#*b!Fu4KwL'0eVr*t:/s5"ix.68fda-G}MJp^J煱IBɸϝw|,44: ^e-ӴZ:r"eH>{=YZiDk<&,sj; s%M?ٷ;?HhPXNt5[]qOlld|3qϭAt^VXoNPLgr,`cm&pLLbh\o,0'[3w_F'.?~]zxN PL"I18`y\3,.x !$_hQӮUUR)^ 4A1pq⪋{3݈:/۲iFGW4;(J2Sw7[LcKo7\Hq?`YKKO9n̓'4>i-}qhd]uSnhibc3~>a|)iwd![Mε kie 9f,YƄa왛Nh"CsXy0uN>fc`aNVVpdqv3kbТ' >Ӥיocll^$g3ԲWdqp$ 9o1vq/Njq)B܈S ŎWbl\܉Td clPMgfvhr>!-vr9d5.O,V?,+>Q=_hX[dt<8YhW<"ra0Vn%BT\XI_LgjNcֆu"" .! 0o#o4j#d`Y`Gqh0 k%#2"#2`-3XXg.a];f$yTqއNOrRN6X_jL3IC_UXE_2kg+|68v]fT;)i^/wq-ى=}96U,wgO*.n f3$\A+Y+0rʹ͐:.&RfD_h y0[C)wsի<+Lb,u^ YG84󞱞^a>E9z㟼=uZY Q+,4sY)kP+4pWgye?R'0 WMC8cT{1em( qo3S'E'bZ*W}Ϣ()u% ف4 ;8lR̡/Nک0crnG } fLJ(},;GCq(PJ1~h r2rXl#4^ < $+ C( %#]&h`фjC2Xϳ'B="'z!hKR$ +& ̕Pؓp,hXu.OnyJb>r. Ms h4PUI8'#}ZY8$TJi~ -j`M/}LKV5a&c*A]@  "`!KB?=믽5V@1pqoR 堄R Ͼ0R k9-6]%+>sI(6-ワ| qT,ֿfhh^i`% ˛8Z)K91iebrkw\4A3ѲFgMp_ L"M@$1}Bsi6X$ 1`BGb5ZCfpjK 9GqĉtZgA &#{(Y`acC~&ˢ$p] UA*`$ݵف6^mgq_[C=Gmtt#hm7'z ,S ` oSqU;cXG3:p)SW%Qx8 'm[9+dC-}mT!ԩ^V D=3?ӿX=lz\N` V&x"?)|dO,ɤ|́2tOhObqqt/g9sHstg˯{~bk]Έwҵmd&T+d) X/k#d`I[}awrMʾa)&cK>K?} p +ٺC, &D,f7jaZi>F=+olWVnskܼI\~ڷQ\bt\G±:/O 9Zigߵ7*ry⠘gv+ͷ!/ ӳ\OUv9=\O ׎ U[m[ < ;'?XqWy{"5(\\>zC8X]*7\p]D9bTn\\*A#,BbOҪfO-cFa%f@r L{-z!Jd~e8X+,,n^C;4;>gTPOW˖Gg\3`1zn{}z6XYvch89NӤo|5|vNX}'_|*:dWnm7V <&,`+(&Vg~uN SƧ˥쭗^r4Wr?3nи+ibxNUIsDe2m}O1v@ [%Z^#$_'[,nI.~~$ 'YQ,B}TJ!ZJ~v; &7@ݿ|'ꟑm7đ|v <{tI!c0)˵|xޖ|\U4 gYhY%)`%;qg[*tۄcZ Қ>7K:cvnMbn_\5Q7GB)TE1]e#?PIXnж^(SVQɎALO3n,Ty⺄A~fXs?+O^|8ϕ'VoY:!4&&/2_!+`^ {OEvXT0n;JTlw(X.`d88o@$j1X8H.c!~Əc9V+y.<%1T&pCOӍ-L 7.K&},tny+ Z9+]B%̛5NH6Is0-}&'P=-L7v(υ16+L١4pϓJJ"}jc`,g <ɚ-Ҭ} v"}fq|ו?,\F[=8,UBW=FсA_IoMV K!X; ]IR5QgV2h9j1B?v rnC>9X(rDQYp{[w 1v x[fmќ4șDbWLۦ0s/`K|9՞j蹟3BizW'9͕Ӧ x:[5_-S]Ge;i6ǡ\@~ڝąF : p3l#q3P'wxB}Rxj^ _gs(usk'tYJKy10p'/GE>D36zYN;v]b5G8brKh7&"7F9h2 13Sp3πtVױÕ<&MTh1s0R&?i?q\1{,Rz7Xvolw"]#Zd=<+9Όwg9FW-}o,nKv!Ti}$y{ܰ猣-\MA?& I$kjvȞX(}sMWǰM 8~6F},{K7 >?;Gp'ŤE{-]M;ʘa'6[goD[D/_!zCڍʳqΩ|L_Rt'˿F&㴼6z2q.Pk|" :xd097U՗y2.\|  jry Dqoj]u^"awY-efǏY#ږo$wzˮ7?@oXL@Wі#`4N64qey4Jgk,\s!l}q4YUnd3%`]~m~N'։ `~{9>{'@9{5EtU6XR> AӭdupI!X[y0Bd'w}up3㦳:5W䨙D[]8A!'u[LUmN_ϩnXZflĄWEŕ[<.%+2cǤ3IsdX?V3O6[, pقO\Sګf1?7F9<^m9BliPsEU&`W_]<|m%[lqB o(p#i>ߋ~]qb˗󄕾\!yā% ;g'A5ʪ߄d_~wBPXEr*e.x'_L Zh/([ͦ]zeUSԲx&tbڅiwQ86K] pN qlr+\KO+XJk(ׁXLY^3k@[&=𝹟OqyGjXd'DԛSlT(kIRTk3*chAiq>|;Lv:lLwp6y7&)n UL m.c9Ӟe0;]4I;F6+H"{g >Ά $S~jUNux:IK]6jϒ|lvU4GO286QlWXRLjp Qtig4gxbAv80[R%vkgռ˪]^= ў B}[?OΟs9?#syV_#|V7usm/C| *v5ۈ'|ysLX X@B_4Ar IWe \o<8v[s ƌɹVTn7[@:,~C3WWA"Ta Q4/16 Bfk:֭l|Z;&X a#۫߄=.’+?C7H DW#Iu6Kqæn'ͷj%yc:Mv'ia>=+;ˏz8ԛ33ub{?)'Wcp@SJa?}d{ms80Btyeg8vWzpM⑞Evmo<"HFUq$kx`L TRxsaĴ{Oa Uvd3r-`/yk">x(HXvKb0up5'WZ(bq@ӏqFVv_g}[=\}|VW_Otԝb(TL^<7BIJSQf*y4祯Q&M[r%S$`4KodZ"ko*C"/6iZ-⾉alT^ޙm!{9w%Jy {p?<;zpܷo:-cރV.&/i0F[dL>bU _{1Eq3{ .-`2iֶ^`&Ka>xeh1m!XvTu /6H / Ĭ*g_fFhEǿ`},-^,fkTsJ{=Y2PN2wFu3(-PLf#rpW&.̺L mאqk8T v+.N0~b=kLp:p,b\Mbp/1?ej-2sW:U,5psNX31S(ڒݘq\pOb\DLN`N6i':Xg=9+hXC{*LWE6&SVZ-3鷺V(>n&Sdk|ަ[(1چxAێc :y[< 򲚶eTbC~B9|մjˉU0 Y2UmSZ ȗ'zM⤵ %hbx M{G#zb௳y yL<4p=e} 7zEh'!%?g ]eq\k/=RpQNX1ơ*h/ <ٚsDܦ a*7~lv.}B1[o%BqX˭) 52wjn|+g=Eḽ }!  -1kFkh< 0vֽ 1nRvx|<?k'-cK ȼrpCt틓A&jXe2SlPw/zZGJb)iF_7ާ9o 8_Ճ W_##d`I%?ʆ-O~ %=P Ȉ KS؛5u Fgdy^_ĵ̠\: :{Mfw/Xgao|-n6=sw%)6zKOoon± ru9jK».T}~k/| xb&&e3{s}x<&oyx> <$]Nᱯm+Dq.e Pɥ՘qj3^sz(7f~N˖H F+myV4ohE"f>{kifۻ9 p \ _HlL/;H>?3  Bt>Iꂩx80nZL6oW?佬m̸lSQXbClhx9۝c ܝ@v PjF {*/{Q2;ԍV_P/N.d荝5 g 4HG?1`+JLirgiť,Rϑ3`CU Ex9̼N9x,5+pR~?&̖Ohfr)ע0vw`CFl>ߙ<-UsP /Q6SMEg /ب̒*n77keLhЉV8.~^s+si<֤373Zxע'֔smS9|qPLgݝL,0z8*Nػ N cfNQ6 7\Fz鮧W]F_Dc8W6ȣ9o.;,{=gw޻wݵ;*E%JfE( F0a9+(fLPQD1Jq X (CiձO?w7|s1CW}H_c#Xv.yW26BdK0+h!WeMc'|җ5xݷ<ﰽf6f~߱9V4x~c:Kc?ABNtCh\=Y)Vѝحiȇ",fj*MJGF*6PLeQV=]߱ u4G_ǾG vͥ:f=,Z.`%zR ͜ĴwpH7Q¸ =3 S`v!,{I6IEcejH cWݠ`C5}zl505*{Ξ `ZAu儕;s h=@^qֲ3NJ=@i)l3' w?dWOpڝ(bWo:!]]+=c=2+Khw4K0>R,@쭭wYo-ZW'OROכDjxt<;ZgV3p gGAaJTlgɂk ؖ ,pH %kO2pzlh07wGŪtYOﱛW16?, &hhWvKRqgKQ'-RP'es %mTTc x0m83: `8q_**'5./eMݽ.0 *B+m??R_D/$mB{k6cwTӼDž/֊>z*}IYr:(k{X.?mH0|SWnoQHU#Qݝmϼ{#DtSvSU,##m׋^(vs{%s{ҧ#UIpbD{Ɩ<|=7˥WNLuОgJ@ V^c[0yM QV:85kMCA6tiyG{o#zc"i=Z&]~S/فsh>ڇKpM*KXIb)ץ{)Dr_} _H`_X>)gC|%@*ߕx 䏍&I jKjijA}f-Wf[ͮ qa쭫ewΟϬGt+lxv'%+{:jw5pL+d_uF#1BG, `?if>jJ)[cBx"DARvώ'^Iy֕S'ze%426 u&+t _[+S"'`ϠaKQWL Yٯ.w|nVV0y` NO|f$T&Rjdۼ-|,&:c6I[XHəX|z>k'c'E-8mJfxʃ3fЫ),I>Q&wR:GQWCBbl`n0gu\Ee_,'x>Yr{dm3}ujо.'ڝբXUM:Ngo\RZE}1* eRBJ}FCyyU;(aޝ6J6=)&Slkvmo2n$e EドM ?%;*9u.&g<9n4 2/pDž t8K(FY a83#" ~ęɕdK&\n䊜Sz#4=Zb *I;kwNN;>yeτx/Lg9bq I @#tL~K) Cl4# ?1 =GaАvI֣X|j2 Uj5 ?2na6X7e翭6<<8ˤl7)0X.v?/B'eKX'U_ZG?L%e(,pU&pFDfx`a&r4ԁhpM@fV-NNZOD@[6&kq#$vkL :%珋YprK=zeݰ$k=}Xv =X/y~e7 B'QEl~8 wΐX W^x}PMhw!N~GebEn3WIPP]&~'v;KJ3 3Fki:4wy3\]f^Oa;?Epv!$,XWƂ,¨2Uj4j0=݊j&߸<+EcWx5jI pw#9m-ՍBB,Ҟ 8C8 wp{Ʒ:}ko#ODgKu7wgfMS)aCbQ36^l'J({\U*^p#5x`Y*k\ wɕV6v)Uk!Z)83Xxw IGk<;+i5ۏf١Lsw!E¹v?~ N68$K&lG*x=jOaӜ<,p>\^z'V>yZ2r%[vuu'*ăc9I 2>K}5yW0OY .Gtev]i|/*92r]G#3*<1h0RGHqtҲ:Rz^qp7|YX󭧈ʖ6#ʍܿj&|.b}[`ir ӖD7nr'۹09ד4c'%z/0Z{`]FO/!ƝS/_n]!wuKy$o2CmX6\Iץ`'bl.k޲%W1y#D<%{- B{1{Qmk܌yǶq۸Dnc9e:*~ʗrǧEd~ Lbɤjc1yh$ܫt{ S3i\I'!D'M1%3pxT+zCK㰟%o=݄&$gZ!;t|\qO,DE6C#G?75<{NJ8; !tIgsx4nt R[wKEJ<րhN ϴX*PVwr}6i͡}]jwm]W̬@/gr9~jP:Yw/k>f9:X6QSP#=^YX"8 aqPĞΊѭm~0u &z NJ3Jak Rz]ˤ==ܘĺrL< kMis4XV,"u:yn6qd|0Q'p`+9 ܠ(Btbn؅Gq)" `0H&۹:)m柝`.xDKtS@|?(#ϺU&jA)̏2 /@KFZtIs&:L~Uа/330x r˫ qr߫*w#X6Obͅ"X3DW/ِ { p^Kw~8zam]e.WxΑoJwְx,j6'ruNE :z[˖iyB/ Xeby-/>G,M{U/o$Q%UJ㗞nO/lo,IT]8~Gyi3`C &lu-D(gpmsEp+Sg3}a}r.V/fɓw|%2˜oh2ޅ~pf 47ag_z^l%ۜ>/6I.d&noIiӗ@vҶߝo΄)SjW=O:Hn.c:ĉU:% Aךh+‚t7n5{3gi/kӸy;uTΌGnRlhT ~%K_=(S4eKc}-9jg:b42?DN W~2͸qZb'Z/%Gו'Lxgݦx LUN$yA֣p`%+Ӂ%۞_ݰͼh{Rg0cԙtn|50Y-G>G0SѮȌ)_dI>`}u!)wI@CA*^-YJz ^ѱ~\+dׅ']L4n7=h>Ϯy)]#!/4\T 6la0ѻ}!CXE㯬lAAh \XcC5BaW!Etdd Y$ Ey:yɾ*DT2vR&lW+8Ub- J b \4cmCPhibXsw67V+=]e\WŖU>Z pyDsSh-;Ry_z@U'eݰOv/,\ZmqЛZHj0wRq-]( H|ADON|5^dbĕ5CT >uOX1WXX~lq\y$ómJF^߲ LW7s!Nh6>e8.DC8#)[yw8Rl|/[q=A_'ϲr&poc`*ǟ =ŏ:U_sO$,N6kW F=qUҁ'\}L*"Fx,SUQT+$U~įiwx?2El7.݆, Zç w8I#6}Y~~Gq\R8+$XP*Q+O|_o[~np{~~{$D39|_vBXx78rC8XⲞᜑ%(DtZUbڢ) iA#cccGJ_&p\|JO{̛onXWIOE%6.8fi?IQ8jr5$ac+_(FX5 jβ|OdcI[_DtbQ@=B6bjXh  Zdb%q [BG㖮"Q=I⟿DcĚU(MXQ62HtZϔ|Y*WL?=> ^V)ܯ>2̞6otMvcΓĝ*(dQ߲\<#\B"x!{W6hO%b龜{oNiV,~ނǎ'xo!W{ pT^Uuma􇅔_=p7\=λmߨeS\PG&U٬_a㍏Wn}{װmv|[_&Vڙo$N^Es{UZoq-ì\coUW|=p+?"y^JЁ7Iih?:|~c02a^ wS9e̸cvw`*(ߩ#UyU;ٳ-NwDu<m>$]zG'*Z A#x?u"#켴ܸJbx$࿭}w 0(&^]RjWSk [TQdž[SZ\LhG%q)mXOeN[*2<Ø}4<X i90O,-Z|֓Dɓ>=Ιm[37l,4l(7_K`CwsŲ] 4r6ޭvɀ`H9$nN4B!s Wpv<]Ft/1+ K"w?68/ `=3Ѹ0lُvdҗ?Ga6݅egTMC y3E<'Q@:i!V;ZAUΧS y>c-"W\7gwf02֗uk> [;8P,K?JpT 3XlL 5l~&Kܜ`fI'Sȡ :5f#Vr֏l6#f3YsSa).H(}NDh W|cXh 8Sf ? CMV2k.͸ &P/G|2]hɳ71YW_ssFUUb90& ђov7vE\ e]Ɇ34V%~k~(L;A:[gdNn1f.}Yf!!'`6%_2swHWLبUđ,ET2㿊nOZ%fbQcQ5[=p  }y6k2钀T)fX7:pE؏ 9e1NDՖ(]:ŬkdpnOe{[e$50<ř$p]x%  &!g5^HeZc-v,012Xx:K؟ CȑƢVLxOV"Hbpgc X Ex/Gh5Q8Q݋8a&v4uRSr e:QU5]6ѽO9UN>h)RܚƜ2YWz1‰̺%? !YEiAG<4mO?{i mƦHY=0 \nh82ѹf`cCYz_|s1XLEww)szur9xy-rG?;YqFM46 y5MA<|{ sa\ ac Dp2+Z`dto13svwMba醰ZFRnxcic-c{(E嶊|R,vW$[+*a.q""vb1yFgB\;)S0>؇Lk\%vΎi\̦$Dz & 4m S; W/_:X@s URa>!gSƏobf 'oqU=yLr e!G .̀~W \N3ʹ`ugQِKP=]7qJ/3EZB9,5=ǕL%D)h7 )lQ⛘N`oj=D>rtwfȪBpYVXofОTg<zskRQ6˨)녕HFzgHcfg;rU2soSvhϨ__]ÄK3j9@M> G3b'HurHKk]:?i=^~0D4b)fZ~ksm tƗ%o8-Қfډ]\Eo?!ĴHŶJ ‹ATXGE'k4%}\큅rcVEq 4XQf!3/6 BiZ1SV߭3&IE .)=-\&S~gVQPb5+kp؋?X*"m>.*dR4/&\7H";  Q:ӓM\SђNW&X@SF[8XG4` i?m 5fs" p6ѫ7E<M+*[̘2Sy髻(Ğg.xmV`BicrK"zkv*!ٶﳢ7癶%aL(V0Ԟ`Lfx*YX|)+jcapgE&^Ƽm4rW=ّ̽'DnLW2T3Q~$k$")qQ~KkܰEH_8z&ky1dZ$f5[n=w0fXѶF{z\5rE|< %)s'Tʉ8qYnDcYd##m$Fzi߾y s~1mU)j0]R#{In .5 ks~w>qԳ.\V=pۛ% 31+b2q2i{Ch1Ks4u&#Uƛ`-3 ujTQ_' m6Έjw[u1qjwx๽>+;۞bx78ϰ }-5;aO%N8NGK AFxiy"$1 =4ړLwto Ԡ}+j)遵ޡ1${2lX}FEh&*Q}WhX^[dp?P8YhwW#2f0Ԗo!BIL,T_ZIYL>x|;7-u2b" nau~[|ȃ7[K#xޕ ,zb8X*gS&!!{d1v믪Ï'-&s䋣;*M O:2Kh\a$gNxH7 ;ӫL_6O~mݗ廖o)Gߓތ>*fWش_?B\L x&xM+OV(U#„ N~s8Wf><[ΤeIm6g'/TzzyA_pG*/8や!o{0zիپGr |#ibMu`NUU?xM:>C5 `}RRdLz蟭*ˡQg#-SҌo8ٺ0#Uz#ݴ]M/ &le 4Qa4wߍ<~Ȯ`TNvװ-;Ÿn/^G%)tUcU8e:-!Rv&m0B7h[3HxZbZl#xwR*#p}Px2:8,m"+Na 1S]%q\NǺi&Z+ _oQ#pI<Z),e"b4us±HV(K,p~qY NXZ|F:!ҹfb:6m<4S{ fS}6)ÞUUVΦqG8CIvs;=Mx?l!?LÖgF4n7p:6RvرX+r=X,x9YP}vB.Cq(PJQ?2Yl#VJio)mPIF&4LbI:5aeNt+{I.\FIXW}])n`._ƞ3]о.œz޳եENak9RSwx9q«ٸH [8,*RiUʅ=&Y/g;upko1ɚ01pmv) "`!MB?=_kILcKY(J;lH1৬Y]4JsnYnyg$ce87 G GCXxc쨖ı}Q&y?+.x&^V zQ dL?d=zŰxEW:!!{7f;y++}\'m:żru''%An|c]Wlg@˅(Gۘ"[|`1DjMwXX.ljkm /;b\PtVf2-pULi?.nۨ8E`qxlxԖ+ P9ēs`my6;F3Aw`"n?'f0JǑXdr܀x 'e6}>dwS|qI~Jlֆjwb2:rLѠ=w* ;+_XqGwĽŅ/ icKꆝ (2 gX5ӆ2>2 Kϻ1'hU;ҖQVñ+ E9r} L@鵖f [ųn8\reia~Q}f~7XWs> 1<('6ȑb VXc"ހל;&`ٱBkbd4'DC5 =j.+Lr> [vV]W$ `|1J&öuI>+4l}BS^ʅ Xg (Zo'?:+t՜{DD_Jj2΋b?3ըtsa8NTI[R^BnzsӸav/fqIxn~1x׈ثVNϯ`MpU2E"4^Dk#FO/sK岆f_^O%jJrcmv<{<9!kAL$k(/t}fOlz.z2B47ށz~B'{ELs]+AZ|2\7&\mteuJZ(3B-eb}ʏ6nCG聃DD IʹT^.a@޿LDOvKs%wgkͼN<GKK`iIQ±Eez yDvw'E>捖=g urDf?&ml? pi˱-> j%NGRinXv}_Ff%vrFJBepL$kjBMf\Me,S_*ѓ'r\껟|ֿm 跛 ޣvVz99">vR2Xg]=C G[}JOܖ:6.LKxޑ ,[e윘s_e]v2҃ȵ\{!W pU(xp-?H֯dEcppCL4}㰢 Vp5m 'i)qޚԷcb!tI Lwp6y7&\ K*X.AژCYӞe ;P\0 u[=5/ȍE3>-lFgU1+i| qkI63* &,:-OriIh,}M‹u#QָƱf$V'mX$ L,w\|q =V \ez>}P{I+4clȆ`U.^[F,'_trgގ[v%Lm\̒ց(:3 qxyQ|ߥBMu?=vXlz~xfl<CMnneEHXV_Z*y4]\q^I>/fD0!xUg@67|%SˤhޠjI7xī8m w <ߨ!|Lxb#Uo&.}koNv!*ʂ]wa;%*{28ҟ̎tX[Kw YS@-O>`.v>gEq#{8/.-U`*'k6g&2fx27j6Xe+:3W;,lb'+ w2gAUUtOW>TMтS 7YZXvHK=^**O.kQZ1k.C0X=&Za|36vu>hW\"nV@DžH{L?T(VU\&sq5w/r#,så(\#~5:`暙،$|X@[I&~֖ Mp0~wWKy UUl?|ͪ;{ Η:3#pIͥ~D$w}:i-fWV- {SKڻGN\oM@H莋č/7sI_p+}.(О1ODC[B |s~BIPѻݣLD uPF> /Ж-w#i%z궅1nb!ng g["|[qD+c98;z9rلi|X~hiaH(lra e}h*Z֑`IoW@Rq*GKw5N= rVI *2x]< !<'r4` Miզq+G+teai^qypW x}U"Z=NHa  &X]ܘx`&*') o` 픬b 6.9b|sZR么5jwM u{Eᦣdrr-t 3c{EzFtօgVXY:ͼ't<˟Oo v ?adv@h%Ai cgluÖcmRȔEE?X3l^l9n_X JdhL7|Є fy-3Ko/}9zW y7$ v t }_5asROńMƊ N]< "|Ϙ8y{ WْNkvkE̺Ԛc'NwvrT)96pi;{ʼnÏ]+c8h:81@"Ĵ1NK;̝F#,ȺI^Yv^֖N 5S&ben|r;Iǩwrkcϴb;H:*S4lhލ2沼lc<7s"sBa5pmj$?b⽰&p}'b猋oB;Ǖ%j9ՎR bno fm9Vgڵ]q65Q$mXH(VrFD،j1y=XC)j [:.-E>Nfҵn6`B3'bh]#PIm&!Cxb9Ky:b(Ԋٓx8̭~/mQ,x &Htb'pes>5Y²0r#$V &5_,xP s鋍斡LQ9I1$obk<6 .]@F wT8Ճjw>DlnhX9ލgx&FqM)i0ֆѣHQ:8'tϛg[X o7,մp2ЃMֿ:ɫ|E sE9lNJbq (L,g(.H`6֧neEhC8))CL~U$ל]8"g^0%cbڢ9R$!{3weVg(bW3Nr ~nЎ$дW#ϴQjT*4 OL髦Ç)W; /ɡ5d^m4XSQjPEHN k {ǐz8~'GtbS8hr@J&=MyBI`0i ONؑحsu϶Y**ۓqTdz^dpQ,zA&^5 q;'Ϟem1j?R)̱ۘ̊#jGk)a_IA/%FǧsBw!@\8]8$_m؉"\Ty0W>۰Bwrcy=H8'#];']2 gkٮMb 4 8򌻯OF{B*hp#ˤBʂgKu36|1u{pq Jycˆ #iH3T>ǟ5iO1pq=SGGk&p.%!qdĒGZ/5sf9Kl:p+p< NeN-p"Kt"YduJ+) ~ .<#;7֭n:_! 7febt9aNY$w1I#qbʡ X:st?IRpu gcB,B3؅<_O4{ۭbjݷX8.1OS}#(u:b2./87l΋KSl!n%na c ^ÙI8Y$XM?op5qQ-}VՖ?O/1n lQiƱ]( obcBmm~'Fdbr'!Æˢ5xO*5۔9_l.Yh\c3.}:ib.|v"Na4%~?|Hob4|U!51iy3} =XۛɑR1b #Xv.yu(cs*!t̃W8!!{q~v:L('n~0&hw\< [-ߴoe Xz(ߠ,8\m~W6Y{> L}vOQO}55o5ѧo/I?Y:s p3xzgEzɊH„nnΒE>7f1USn'U:=<2 uV7`z.z銧xLM8p}]6"i6䛥?Nh۞p,{r#I534svӊ  ]g# DM .Ds6LJyO8q'E$u Y"ږ&h4>]u !뱩0x֠9{2&i ԝ[BV-l|{Y*Z~:I(9{|P'᧰eG&̜7]=jw,]Ҿ$4Jsv=w#"p ˬ/l[K.[Kٲ sei濵h!*[G\Z1])S}t"ΖVXXUcC' C0`[32H!킔D=7K,G"p=6 t?w}g5R?n2_9ǘ.\=^{-Jŝ- F8H B55SQ-eNsP [r̘,~]xXȗ72'wn6DXtn_H~q,gmgn-%ɪ;,LQQb&F෥ ٌQMX+X%IfB n udyc\K"Y.j\M5_p_S!E#WGuw=uˎ=3OEڭVOUpU\/za̹IdDV% É uJ~[,^i;Az3B{+djXIxn5r2DZIhOԬ5 qçe9~g 9ht}DLl"fΡh.5v/b%͊U\Y}1~_|G@ |c6 B{G Y ~W5&ד?6|')~-cslَj]H__Oo5v.ą1s8v>azadIJ^؝RNpd%k"f{l1T_(Ct9coT*ilq; gZJ=;_H{a2'ZWB L蕕x Ӕظ3]DT)_~mRvOIО=-5F]1).ggbYY1ԋu/89)כBxƞ؞jwVbU]78JrMwHi95Ĝ,gI ) R |i+ +VULbxywڸg+btLɻى)󓏏&:,c7$4<ԑw}縅cb8('ȼ8{V:bJ*P'.H=d*}f|Ȏ$6l7gp'W-p]+rNCh))7N$>aޱ:I8uL>=ξ2YK/`tl?cw -IbT}%k0lҖeU9၅Pn4%Rw[RT892fky?}mۘqӏ黶3a2蔜?.gH/gmuÒ\q!b$C~kdb򤩀_`/|9|2/?-|Z:h,1.=vnP餉6)jt0S2*K'C.~@}Py·7pYWUܞoeŃ[3p=uu #X.J*O9M.랓79s1C6dC*{`D˾0~g j*VrGV ?7e:C^`5l_zA7]8V ݗɷ_%ACw."~d<'^]H\ړ{pgzbn/RV`Y/DHwlLiJ]73lH,qFՋ-$\%cY{nTVglWFLXhqޮZ&1 Y.'q&WDK@, ^ÂxK#Ӟ3j6]:8f2jwM~8dDh\o~V)?lwڙŖ·+kY/_gB//:\KFTzԮDxt;5g5X@g0\cF1 )Ž(Ž+m%T%G>VWFnVhdFg39=&FJ ;.pNZTGJϋcwԐv>>^:@x/+ w^ҦQt]_ўSgnKa/z#<_ϕ&`xVO0\&!%F W 1W1MhBm~`fvjn2_=yw7a|n^s4!Bh)z_&K4r01QnL8:x g;twgE6ՋjƜk.hMTv%B'CͲ>#RVM׳D#滭d9rgW13pChUg%=b>@cY[ŭTgݐB3ϋiŦƃ{J~Cyiv #"N6YʫJiE&GUg~?D;TZMuVQtMqPw~w?'fb,{$ټ3Ӿr/ݑhU̺#\6n,&П|=O3Eo+5M.arZ/dyy;&qzR6&sL62DOp>^kp,V4ĸ3zj8~ԁҭ=X+$nNx)$RfP҆77 #DuYlӖ}[vUd &|dБa9}WAh5&x<6 W }12ubmoV1@_8]^OUvo09`I8T  8&{1=QAcOS}a qy/k>"9d)&pdNQjuEoqiպЄL+c疐" ~Afhff'cUgG1<[L[԰EhNZr 8.^daıb;W/sc|brh)Δ2J6AQQrY7X=(^c`h(5Q. aN$V Ojb&0n~Je&xזe1[SNȠ$ m9ǿG<ַXT˦SϓnDC=5l{;Y&ʝጲ d¼_`Fdg{y)CJdVV89;րڊBow AS9ݝlv՟!m6Ha֌Vz߯/mXK(iBϱ abvay?QKxIr2P4tUAB ;^#W'-\&xٟ-0ꃼlt-Զ|<UL|||jY;z OuXLVZa̷q4B?z3 WV㰳/=/{mNk $V2{i뷌$avTG;iNE7{ugB)5pf+vΞ'Rp71hpv*k}IS`oaArrSj뽙]iܼ:|*jgFY#_A64pIvg iC%/)nֲcץq㱾o53q1쁋r"'+?f8m- ؗ`#ցuœp^lbJ<ֳnSGݺstҔ̻$|b w{/,%Z/X?T^.e}fYe~b4g׼쐗z.ds|Y0Uվu!E,"WVKZ6lq Es b4sQ,污uð+Du"Jg22,W"<K "ƧO'mr /21hʚ*'+}L,  b68.ߗ-eϸȞt/sVVgY\H8{0\τGWI *`/?'Y zRCkqO'B5I #*>&ewuMBS#<׌㊪(Os~m*?4rg?f!,}9!f,qYfpH| 8ܝm3-S`kI~9 p{a"jw2RDЖ=Aܚf;e&&w\&)d5&=3:.^Y縔o:`P)򤄑.Ncv0ct 9c`mm}(483@Zer{ `;wNLgҞcc=xvG~r)b3~y" +Ղwl|p˦):nN~BjF"ӌɢyϦX?YА͇pKS2o 9,ϴܛ;&W)*xoLaUdzt#bԌcCQ*ᢉ!cX3c'ǨMbifkh: F`n1m`Q4ñ#rg/|8.uS'ǽRͷXL7,Hsvפv٢dky4ԟ$y(XtEz pb╯HHmq?,IIsRu5gY>GWo'/y}mjmlpW Ş !bxE1{]_~CO-{28S-~_a!ܣqKWC$~_1fb*&,uwRŨfg: pgJ,+cNZWwbfOEK{^w&AMwXzMW2oY.C gʑRc.!ylG +X4ͧt_ν^ k4+?o[{c+ klȆ^r2_U][?a!Gkϲ0 WOæn7G*vT ?r:ToIU6Cx²m^5z|֗v,W~\Flc0+WXr[54axʏ/|tMi9Oy0+Lx9LC;De"37J$CJwHj44dl]%eϿzIޑ ~, C@&^yO]ȣtG;/-7h<C@oc' GLb  ݜjwCW!-w뷶w=wr2 #i{+mG%Ott%02h+}Q&zċT:Yd`x eE,ݣ%8z.㳏'2݋Cs’OF3 e% U,0y\KKt1XO}L4n8 o#7YcQiMwanӐvd^ `3ITl1zk}Nڄ<1A@V>{))|p{DXzU*׍d~/L+%wݚϢ29<˒:3?;|!҆?pL*±p R?7g(YRŁ7rhhFN{و-͈{C`@X+2njZ( <>|ërHÐjLZp'c34 z1LEZ jLnV=2\QUChfN$%B$~o%7ݍB{dQ W2$}Wo!L͇x_6}VY%[LKob_}V$rY9(3DHk Mi0l\)6mqK|fQ"b?8SVX(?gGzTVs~B#<::hv7Hu #}?k$ x/U.Bs@Jč>lcsNoY̶SD5Q%EN1+=='\CNn]`L jjw+ ^\݉5Hk=: CV5<)?=sX)N4,!MG;AmiD2fq5Kb͸fѢWv +Pî.'1A,jv-siCVU,`}ͽb8}oz/>Ry4LMK4YaE_ϱq,S Ux| ")\J, +DNڽ^,}萞1ܼ}aYF;eY:1Cr w1}q&9\o@W4{I@apǵxgYMRvB !n+g^cl'GP?rU,,U)H8DlX7uCQ"K`Z mNT0{"<"Nɳ nG\/DٲN_g|xe`~t/qNSOo#ZJT-1uUío ,pb'nO8BBHv%rQwQq(:M^29nDBA)'9Rr, s-!fdn;LEtn3ykY/m8z)e׷.;eźO!X*+Jqq1z,:Q}ٻ!e6'T.[R?oPVxoِ 0;꺻/֍fh)&{'JԁX{Ü,U1r[SX 7߇:j|T8U5^ZNɧ}X{֝Qj6OLqNxzG0cߣKj*fip<-?;q:| owœ7:UI(6׿џڪr\aS[n垇qkf`slܫm4iޫ!1?`ʸYqWo p;X|Zƕ>.̀~W \Nʹ`ugQِKP=]7qJ/3EZB9,5=ǕL%D)h7 )lQ⛘N`oj=D>rtwfȪBpYVXofОTg<zskRQ6˨)녕HFzgHcfg;rU2soSvhϨ__]ÄK3j9@M> G3b'HurHKk]:?i=^~0D4b)fZ~ksm tƗ%o8-Қfډ]\Eo?!ĴHŶJ ‹ATXGE'k4%}\큅rcVEq 4XQf!3/6 BiZ1SV߭3&IE .)=-\&S~gVQPb5+kp؋?X*"m>.*dR4/&\7H";  Q:ӓM\SђNW&X@SF[8XG4` i?m 5fs" p6ѫ7E<M+*[̘2Sy髻(Ğg.xmV`BicrK"zkv*!ٶﳢ7癶%aL(V0Ԟ`Lfx*YX|)+jcapgE&^Ƽm4rW=ّ̽'DnLW2T3Q~$k$")qQ~KkܰEH_8z&ky1dZ$f5[n=w0fXѶF{z\5rE|< %)s'Tʉ8qYnDcYd##m$Fzi߾y s~1mU)j0]R#{In .5 ks~w>qԳ.\V=pۛ% 31+b2q2i{Ch1Ks4u&#Uƛ`-3 ujTQ_' m6Έjw[u1qjwx๽>+;۞bx78ϰ }-5;aO%N8NGK AFxiy"$1 =4ړLwto Ԡ}+j)遵ޡ1${2lX}FEh&*Q}WhX^[dp?P8YhwW#2f0Ԗo!BIL,T_ZIYL>x|ܴ4׵~<.x`B nG."li`)Cl`ٴgWqheVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/9%bKGD pHYsaa?itIME :_x IDATx}i]GuuMj4f4,ɒx %'61YRePT⪐*|0&*`;; c[,ɲVK#iY߼y{?xK~t}#*5۷ts~ߡ{W"H@)@̿}>A#μ,)=hg\ 3Z0Vvdh-< 3>2 +sϒ(d暀Ǽga֤׺%"ED8q2 /|D} H$x<{xoPolאZvll6qa~ۆ}evLʚj| qz-]ujiN/J}X7@յwʼՎ~ymОbX'yظ[#;Fךͽ*dﻆ}db~5N\z]T +^dQu窹inRH`(HR~S,111rd 7eldmՅs͗)[}~m K5R2:yun;m .7e9Fi™\ao{uiRʦErZeuw\M-OP>A<3=a_ô!X[ap>c .xjTZC%Q⨴ܟ0WŠQi5s({=W[acETa]%a7d^q1 6D[1/UsM9&NU׿3۲Cqsm|2֎e w%ɗhʲOQ&L3eΛ9~ψ vCcQG͆&n#W`GyĜ a0=_#0Vld2]/<ӄ ܃4Yd3& ɮ0yc30)J9[(cH6=gC7H^q' UD%uPWrךϳfۜi"ݯMÙ=>H~;_;7s}:}mϲ;iq}[:G'(̮}9!-׆:]SDy ˸^)ZKng# DIR)D"o'---hll\xLHR H&(G.DQttt X,ŋ( xrʘ0Wx`*aŅ@*RTi&OJg'z:Vd(ԙ3g(*"B4Ecc1C4EXDssJ&T,Յ hjj L&܌x<(fgg(8… j߾} bѣGq5==M\R ӘQxG2`ÈD"v*ϣX,R bQRBL&\.lJ)ӧOS2D{{;zzzw[-\w^娳S apph*Ě/$ȴ}ybDLlҁS71=_t]Ipi16%eTJd{"jBtēU/z0>>ZEQ,\}}}M`y!F"EEDF,Å 033T*Rd2xWqy5::czz*H H$jhhbXEHEъ>F"b2=0aBbRImiTB6JRHR8}4~iEU*ʚBss3VZnJ%LMM``` .bseǭ-_-"w(2W _IIH4sz:Үy${9PÌ^*yUi 1`zz{RM6!Lwnd~+|E:~8N>t:I\xSSSA6E4UmmmՅ~lذUD"Fu|$Z0d*77@S6)$^u;w333f R J)jmm/^^b1Q(:ë“"hq0^bSd;A;G-O Li#S‚QSSSԄ 6-ڷoڵ e5>ϫl6B Pp577Ws/JU5Fdn^GGȼo^tϟWgϞ7|ry L&Ւ%KdZr%L^XA&Ś:Mȯ:dbS݀Jqɥ!nFϩ2dx[d$Tq3.YfbHWkXRP(7o~:t<USSRH&400z{{` 06m80TZ0{s(IJTaa``@b1DQD"*ŋpΟ?2 <݋^xAe2qe˖aɒ%4<gO\OƏc466ףې~f  M,;hw@_%T]ö$uΥXJ+zSVO<+V`ɒ%01W©Spy;wk]Hli1XfBآ87є;501j~"4f`Æ "dY;v o&:={ॗ^‚ 099 "W_˗܆dr2THlm?+P`߈+WЍo" g^s5Um xgJD֭m݆D |>}"|_K};0P\'xW\q֯_x^zIPgg'b 444 JO q9VT9M`M X!ɽĸ\ydЕUesr =XA/"xlOXT*Q.C6-A-[ W\qFJԙ3ghllL$fggi0lق:#G||Ewm@ߤSut6Uggy+J^u=z_=0==gj*lݺ]]]X`A96ACR-KXUV Ԓ)B0K,eːfqER):a˖-ؼy3P__+W#*@+8Z¾G fC1 |fjJKR+\"NRT zc=W_}U3p9f3'w\>Jx12Uŀ,YB.:tHilܸnXRYe "7!]fn‹X&;dٴD/1?0Nj&0+@|bŰf+UT‰'w^VJ)d2.d^ZeYQΝÅ _Xnھ};-^XW3=ĀU&K;(EJ 65S-,꯲ ܆bF r8Q,1O>$y:s~P,S333d:H fPq.O I'aVf%7G$B(#as2M;vc1am)lcɅj6G1/DCt:FFFfi˖-Xv-ŋI˙ IƘU uI }r ;40Qy͝X ̧zqP_|^w0f4/x˩hZrqd2´6S*R=r9|T%<4#XB]Xݱmd#fSO=;wbtt7nĆ H17QXB-T f+CE6RNKsQH"tҷDp뵜!s/52La ie"W*755Ѷm?pINՓ,K)0:d=CJk*hgR_ױk.\;SSSoJp)Qy(LQ$Iv yl} d{nNsh^/,( W5R)H Ccc$#ޤsE_c ىӑq pbt6[TYE{fy7A{ߏiLMMa/ٍu43KVUp]CI!OW=iAŢJCQsH3TueM_Fu~Yp0w-;|.0ɭ]'EJ[塇/~ \}غukS ]5HsD:J55]/i^|܌}|+moۢS}}|"HӓWVέ;#WqE\|rXf.5I/S4ÇjzzN*ɐ<['I$t(+QoWX8 YX}fn%rZ׺.  \D"*HPTUTZ2ԏ7OS<裴f|F> YvZj.nZ\ 9NQ6g˕;!C! J% }$Z03RDд{, 0 p$R ַꫯ JP*(($a^p Jh=\bƘP .( ||7&~Bp 2$Nм֜c!bq1% [ h}܀sZ4 bb+W_ibbԧڪ˶ QȦ,4 *Ns! 5Zld51QyTv|D?7~je=-{#FXiTL*j#5dpI$r`{ק'xꩧ]]]HR>Bⴌ!ut{<=ה8=>݀sŤu+xN*\ :&6N@:pQKSSSطoz):u MSVzK,Y9oJlOXP2!k.}V}+-@.OsSV`Od`BN Ӽ>fQSg,E${ :uJW'O|#hkk#_ biƐߊUK-Y*+VP@OlnNu|V 5ms"Ld|\›(ACaRDqFJ"U}9Ā #fnW 4ԫ>Ter gvQSW)\ry !H"  [Q:T*l6K\Ne2r&A[s!*uTcc# r+H$h4殥x6J%U*̲[VRP "x͵ay-W-@J4T5өK@pXD 14bݻ?ܤ4OL&Hcccx7(lbvvV΢P(P2DCCZ`-YAWWZZZL֘ =ljPSyb irr'ObzzBd QUR__ɤ!Ub+prpӞo2mHINH(ͮc\^s>d< eYݻxߍ3g[56h+Y`Bx=&^lj'[4E<h4T*7D6E]]b1FЀ~,]^d:Lϟ[oz ###F>Dž hdd/22 Z[[188jnnFTBP@Xħ`e4FoasE/ND%E;E/+|F̝|SSSH$?cy|k_ڵkvZiVE4 SPj/H[F[o{btt6 IDAT h" PW Aƨ^2Fww76nX}.ѣGqLMM!J᭷ž={099& aҥhnn2CP j ͹#q^  MߞbfH&]]]7H$pM7>űB@ $n#p7Mh$)׎T3334>>ܹsµ^-Z&^>_XԵejqH`E  H$jժUpŋqY5==M8z(y?uuuX|D"&҂X,FBAa d&(clT0 QVQNe}|DkM&@1LEٳxW^ye?1^u|ӟ.u`j;1ZZZqbttgϞE?>`hnnFccMihB>3\vhϥR˂ `obT |'No[ܹLB]]:::h"cvve,k/YdS*ֹb+:3_ go %"pzPWWחxcoG,+#۰ċ[S[*YLdz^eqW)X,Fjjj ;vfgg҂[nSyM7SUb />I̲I(6K`شi@:Ʈ]_F{nXd /_FJ^4 ??K"odgb$rLE W owww+տoc˖-_lLTZV]\8s ?Š+|S۽]6}>]Lr6p o^z%>}ǏǾ}P*pWb ƝK6^߱/K_`089F i9@fڵA~e5WH/S0!\Q)7f0(s̚iU4x#F6U]-*>ǼS5Gd,1$pӳ}4MB Z'"BWW&''q);v,(e˖app;B ĔBb]Vb¼܀'NX|9+ՋX \<V^ brr[-}{bpa߿gϞ/} ---UjV獥6uz|A6kg= h3`yk׮{^LNN?|>>c``CCCPJazzR Z!bq+&DZetvv6?T*n~t755azz?я066k_mމ~~'l|yw܁;.\O>Cattoۋ͛7t`0+JzPstQqM7!ΝO?oYyQM@?6r>ڹ+ /5k<-ZdkXـ\YIXtl,aUmQU1KـB&30*ى~G^xN:yjjjR[nEOOO9O!< Fnfrٱa 6w?v,]T\N ڨ$~cffpM7 ѨWpK! Wj6DŃ`hD6|zG`hhCCC( سg:_򗘞Ɩ-[000Prj]..m-dᒓ`ub׮]k+V;v ;w]w݅l6˞amMkoЇ#G:|,z1sqڽ.9p׻毖$JJI!\5-aؼy3x'/cpp/FWW.\|>T*UFCb|\Ry:MGZS Xfb{z!_mmmd2Tp_{wߍ۷eW I :a"|7_&kԧ9Qi&LOO'k$I477cҥXfMʶ"HJu D7ӧ~RoP 7QγH6NT+L&Q*c=t:M_W7 I.6qHvRcm@z|2+dPK1| % r eV1GMwe$P{~[eOss3Nyj޽ϪW_ʕ+qUW@`D1ܚǠuKcW wLjx0"!\Z \P-^z{{NM?/W8~ǬI4?ҥK|$yH҂ 6!#keykx` pj'4l3~iqZ~=֯_O.\P< ãa.j! &nWbʅ%(0ckـ.ĝwމ߿~WW\455!"`[ Rd25U2)L~UϪD"e˖1SPGpq%y:VavvV=#g>cB UNOC+-=_SkWh ÇWK(>ӥŅjч9B;*xccqWԩS_B=קb tvv)r9D"[)bܫʈ,LwNŧ9(MLL6kߛ!*5W)$2)ʴ/;3!3yQ-:kύAby}ygK녫ԇ]Z kc# hDԜ@=gyFG?¢Ep\.麴B b۩lkDQmf400J6%XCl6] tqڵkjll[Yy0 )J^4c8<&J;ʨ6υY1^VZ1!4W$Ew}n::<577dILD2n΃MQﺺT]wipU:;D! @?533Ƈ>!ZjۙQ1 p/èHkCPj.h*hi^g0' "! N/x4Wmei}7#1Pv䴶⮻*'$I6[iQUJ72=/x[oU_O@'K/a``Kc Gam}K@+6?w0:c1>ԕp=$V \U$n`oV5  -5v؁e˖QCC6 Ns}ts_q1.3tYuJ.-mrJTp}Ju ٳsajºb]:pkZAi[7vn@=vU,_v޽]]]hhh(\_R%x\K/nP .T/ML7OZ܀&8rSFe9&Tg.2i+ߛцPwI]ߔrhJ*&ʝB#.5WR bRJ+x}}TV#hN(N8xߜG-u_Ij3wNKMz;ظ9Rqsك9[;咓do[.brJG\v =ySX3̇K-D";v* qh*hSa(m\rG;K˭nϺM\*$^p'fbmZX{4Pw#}sтEP-b$'I](N# ӍH¥' ty*Jhjj‹/ 68Wv1eU7f$!USJ%!z MqsUFOUΥ$Y)r2WC/g+)+.͡G`+%Nc֎0NV2[QF< Tf1ؤ,uJ;pIb8sd2jѢEfJIYN} SPquš5k*%V bƹ3'oe[@e[N6P+eIrDc96wߦ L1}7zŜf ZҢ;4耟6,ʐ76r6*[U:133<|>El6 pU, 22pss3كl޼YI6L"f\sBtӀ2N2 PG*:gk`V,$!NJ̌q7I/RNRŜ`^=XLs/>&%GI p=RSUloΟ?L&\p! 1D`oтsAH$B\Xz5v (q%fY񢚕\\6Lu,)eJ+LemG#+2*;{G r'\7mjHjJ8L(ό)z nZ)ͪX,(aJ'eqP٘:}4J:h4*r@@sqƒ<8N@ XuNH*,r'LdW,!AÁ}\2 kZo@@iB/IBUW"' &buww$v63r ZU 8Ǒd088XEL<-`',>^JYEr9,X *VU7mW.]Q`o]s,}G8$pmS>>kVӠ\5XZjdȍbKg"@oo/cnRy+ۛn !jff/^<;aHgߔ`ѭ#o8@+B+\[ir5"˓xm}*!@*VB2;;t:Ɗ,)Jadd[lTLNkMp?3* $!uToq'vp 1A;&Ja‚goƙHd,\\r].oTq3d!uNh1ͣ8\.'C(n} W&-T! *KϿJ1|Jbp)AJɅ'ʈUPMp|¯H1sK2dI>G|#Za11JG0ɐT&Hr/XEeFb;v,:Nn@ ܀ҫt5e&d"̪-4T3|&5XGjUڕ*% HĆGur>sj' d<8dYĀt-T]LZ2T뗍tmFP,V(h;;;6'ri\m\ Y/,r.W?| CL!% 9Xr7R2+Tn6=}b1@uJnkk3O\슜 lH WAeNd79)] O؀B (rc$\IIҒ WLd۾v !3;"tmJOO}m,R/@lM<_ lw ԛ 'm=ڗMȬW($%a-GvYK=',]p%HΜrZHX,CY hE`333 KRTQw}J_|4=q}w 0}k:,|I=fl|搻'fNEDQ'W%89cXСHp*ZRuߺ6nz8Z\}9@i-ܷ\^ya0I6Q[ހoED#VY/k&1I!q"#I`D%J&UK6my\ $Y* Tf7s1Vm¶ Gqr%f]ȼP5_g%Q4psђ͞$D=#$gL&P+;ZKK7Oe% nU ce8(5z@18|:QH$raKD"hkkٳg zJ_iZJVf;Q{΁FH$(f#brG\btYc3JejU43`0 &ߴq%{ԔB\,و>v&U֫d܊ 7V>̃ŔY6 v>e8Yk3vd` .mQ_\JВD@2k$"jllą N\Vm%@ajדB Ǿd8dI[ð1d돭Kz?[-FV9xRw'b8&PrPb(I$DBSD2ȥsQ IDATQ\6a[iͦg8mVsͭr5UE ڌ )n޹96laɩ64i1Lđ(7ڀV&F*H JI҂Bq]$/ATB2Tȑ#b\6@&"Jl#Dvu8i>v/Fe;PmKc`$}6+ )a5j !n'#bqLOOSb$Dm4<bʹpBzmv gщ0h0wb rv}b8y1KĜpdDX[/ jʀ7\msS,ݰ]E&v֋9v`JWs480==bj-3RCcc#>썾AehZ=\_+ 1خTE?#lt aU&G \dLMMU@[Ae25;;H$W!qj L-  ,q0꺲j4gV0s4L4&̪&&Ti0cQT_z73$P5H)iD"W N6!'xP,ŸX+L4A&d{SN7“dC >n@Nm&ō?s-/11kZ39Yr $2n tAT&[qze-[,UssjllT BlV+fIͱKAFenXPh;A*ɍυjhI̓Ԗ,J ND* ?,=رi\/M ݿ_&A,#.nd }R)Zv-_GVmy64U^`íe5S6=Rnmig71Zq+'!U!c~d#{kS;1@' q{3 .b<|;fR /xyj>sNR͗-/mFS-\8;v D'Բte}}}~ Wa-nKqiۇF۷ϗeN?].9w ӧE)se2l۶ /"^{%N{ۘ¶⟶p]oZh>!+L\kÌWuknȖ%* ɤ*J h΢ yZZZeu˵>ZP/0%YVM0XX(x nn-cs3._Y| .C4[EG_/I2YHH$πM`e@6)N#z-l&ªBP͛)}:_#Z^**#~?03ٓfJ\U?bo \IG.@ C6b_-CCfȸyt$ļ$ĬXFf;8ɔ53^p >L.^*/^:ݻw#V3r|_F0؇A' C ݖ|j_/N-`S /' V0=F hbbx*Acv!l)2Íkv!RZnF?% Uԃg2bNl6ra_2pU2F`2l@ 6A3G\fIـ9.9eeV"egYUs/ TK6 yf =頮N]ŋUX̌# )_Hp5$ ]ŠDԔڸq#6mڤovˬYow3fּ_(V!?&%*ˑW/L3׆}KLU 5ﺉ)$߹X-dZ-1oNFŠ&!"zLMMٳ^:̇1`zz[n͛կ~?|E@-|b.G;Qra [kH/)ØXDB@/^DT* '2Awɳ5K`VMӴuVl߾~ DT*j;,}T-%xs< Ra0}BN2L*;'!Ne3<491Hȓ zX|Ô7*X<vn<2L\nDⳳd2޽L l2 y'yX`!wX4V^;O?4^LOOWQŵjhu \(f@a1o% n hvQ@}e[KaJ|J@K_V{3؇c*m߾GE*5rxOTB:Fww7>cjj _*Li"}j)%(K}҂^TN*Qe_-(9|smq/M^]ȶ{-%RJ`xx]; ,]k,(>яbxկ~###r Eu6˙'xOX 忓$6mڄÇT*9U06w R)\uUAD|.W ̺6Ad5\j DזI:f 5'}|}.ن9}L \Ϡ*^WWJboV{с)%p,Bd\ hM>i\mT*T*R---ؾ}G>N:E_Cرcb* qѐ:h6 -Dn@d4ÓϬrheUMlt>,{e}7d:r.WM^Un`,0k8O`*8V)}UoS|Rl5Pa MMMM)(% JRرc]{Hd$D_~a鿱m.%DJ)*穱7o6:rڵ{9@CCC5ڂ{mrɢ寮mcF<> ۵^.5|ms<7d9wI0Lr8r䈞f Xf pI67V`-.[6f"BX۷oGWWz)|sߏ'OE&`> 7a\i 䪴=5ph6Wg-]ˋ0-[W^ywq`O^$A.q 7`ll ccc8u`x׻ޅa,^01=%9|pl6ڥ|~\|0{hG:fɰ+P(|7lؠ~`ttFk~\h\ Shhh@KK qUW .駟?UVahh}}}ꪫT}}};b~5qr}2U[AbN9r0sG}>B&mO>!ȝK'ߗkre՚ 4k d2 p 7@?վ}m6 -v 5I @ vz6ND>G>G$A"~|\c駟&[7x# 8Tsst%my?v b\l'6m/ENHrA A>:J{h)ɪآRXlYd 6}CwիW l?|$`Cشin݊)8pعs'|IqY[n࠸ӛrTC)1:ۇZUlWȴk\a]3~ps3vw5w`B& E"599#GЪUTss3PW]u.\^{5馛tf - Lq.~s7̹ti)R6e +PJ)iJRbؼyJ$x":uJӧo~SeY kŲe؈ʬ=T @HgG<}}(62;13p1.Tbe%\gs6jY&R.~JNo˼>&J褹{S{{;/ҦMԧ>E_җn:jllTZfvSL{ Ĝ,`2(gPT (cժUDDW\L&qg?ϣ W ZZZAFG\j\8)en=ÍqY^v#5[ PW& b^̊kdS*TgsL%d%ƿOώ` "YDp5P]]_;wOOiffƖZog KFHXb`rrc*===hooGKK aʕkj0I!%;VoWr#WAs=J/_#-B, O1}g0 l>h̝@jL,z( (Jv:Nsmς "G4 )vrs'4q4*ƍd2hŊ*! cttϟ;v dGA& +LbѢEAx@["&9r*XWWbrR!ۻa%VO6 >}Ukc=&,^333]\{)mLlDaǦobBL|]$AWWWgl6t:t:rB(8 . JXp!/_6ף ,ڔ"[lkl{jW)D.qcg}֌>n 8a133|g\W?>fG41$W bw |rR_Ţ@۩uuuhhh P(JDP(S ɓxQ*ގf:::a,ZHg%MܙM.?@."-=bɦ}ֆP=œœЃkZZZ/~?0~;Ă Nm9$ ԗewK+당Xtj-\᫩NKQX,X,V%“$VXUV!(qIn-[ זΚ@p\>֭[d2t:GӘٳgw^LMM۶mƍxD?벵)Y`BHmlHN70)ĸJ(eG?>Lէ?iWͣ2N*Mre&34#3%=e&vkfP*Ql<971ߔdTD",]+WX,fggqE!ĉ /gRGGZf Z[[qF+!J!N#Hh4DQ̹ (܀IEtW1^[Ol@}nllJV--@wۿ=|cC]]2LM9lyHhi"IN0Dx%h4hG̥Uc͚5(J8wvލQشidPWW:(088v rM466V:hfk\ exr[/bbuwuZ[[133kIَmsmqۆlCqaTYIemLSD/c!rkii6\DSN7Goo/ގף`vvDB`xxDBGGG9QS-:0딑b6j%l]Lg-u:ȭ@6a*<;N`![ -P4]OX߫/ UYTXFfQbNd}TaC+=,ϓQ?̙3k'NDb }Ö-[xm*Rsr8q=J\===jժUe3%k]u6s}43HB@ eLW\Sߔq\ᤜ7eWp-DcEY$! Yw$ьFۙsVw3N/J3{^ݻ{g,isD&}WR:o{2_ռ{u*;f腅l'|^$W_X,'؈JKHA"nzFY gzrda]qfKLv ^Z5F#UFrb_)6Rފ5eccR)-DE5U홺@͟?tq?jhhڵkj*ZbEr T*z̞=6V[FȤKriPŭ7L4nG%z HܠTܶ6ڼy3N:E/2% 7oEêJ_yؾ=IQMoVUpVbJq1Fgt/}L <8aƭυPM'd ?[ګdbzr>35g3*"C^vtYHuLIp(BhJ.r٫\.k8}4ߏh"zA*˴g* hiiCIH9fOq O^m@H N7M6?7递>Hb͝;W577ӓO>'OM566b!ʔPheP@w \*Ͷ/l^y 9fgŬ=*HRXr0cǎc=N>MS\h4Jؿ? Z[[2 =sb@"g6x Wٯ + '<葀u5 `ѢE8rx 411Q% vgBN@d+#ɀB""F!)x؍R[r *RF9uP>WDÜ9sՅ^zGpE(JE>}٬Jz9QCk(8@lBٮ۷oHG]!yofDn:dY ^{z),Y_=B|d()؉t(Eyr}LŘ>NGP@4Egg'fϞk~_a׮]X~=n6tww֯__ҒuZF1Pf\֞zD$j@~k4wM6tuuaÆ 5kC;wTMMMLWPIJ0}2|^j_0VҪ/AH+熋G7xq83v&L'j- ;U2TVٳ{n׿gbɒ%*H18qZZZM BχZ7& 9w7~f0ANZ !/o:;;iժUfsɓ'iٔdQ*C I`B?f4I` 9#l:iL$j΁Lʎ'|rbNLLP]]]{N{a˖-444˗S"C:;;I(.xg^G#գo^m=sОi@@0qJiSh.r-ꦛnǏg8$H$TPdny@'K!,A@]($L r1& *6:uR*X,"ϣ/^:ٳO?4pҹsԹs缘i(K :q޹ Eb\adxvލ9s>1\wuؿ?vލ~$Itvvs1舏w‡sP` I&\e9[LX[gB2,yڵkfQ.JHw c\6o p'gp2Uh*3-eohh\.f}}=6l@k֬CoCUX^YBsI65Wf% L^.ʐ7BԲe˰k.z饗܌e˖Uy Қ8ݹ yc !>\bRrf͚UnnW\~ty "= S gd`xLsi !56?iq֪}\.SP@"U(b֭xwA/_FSSVCa/t oz{{ׇkӃ;v ;w֭[Q*puסS10>>^a \\mta(?3Mv2 lNR,1bعs'oswߍիW3=/ z*#1(!~׽ ݓP&Ǐ̙3$/8V\I7piǎػw/&&&P(Pss3hrrbUf;+%iFӟ4@I*{A+@{8/*U[í-aOF"D"%KBs̡n/ ª`x8g&<{yTL\s[ %PL~#;hͣ3g… 0KND*Nc޼ypUWсԻヒSNх T[[ZZZ*%hz$iQrKgTtg*=!EO<)W %Y''!ſ 5l|p>w#RDbqW>zҥKFHJ%\=r$8LD`۾}1&HRI(~3Ywv`GvuuaF#h 7p6mڄAŁ[o!Hٳr!/0kMиtO&YF0Ni_M cRb%`1 } $`7aWcꠠh4իWST–-[cJ5K̆e\J(LՁ\ %{ؕTv0ヒJCN):|s8r>_WhooǺu\鸒g|t*/03Xn&tvvG={o|J n=.@ծ$7& 0muFT*E\Bl022^LNN,\+WĊ+h娫ïkk.TWWW.r./V $jz~&Z\C"B48fϞKb۶mعs'6mڄtc#f/:m/@U,&p/;G -Pڙ$ 6%U'7)T,ìYΝ EQXqiܹsqUW`Xv- axݔH$Tkk+(N##in0 'Ūt v,kXT@~n,zL̐K8DJqI7ϛd2~3կ~oѿv(6eCbtN `CͧWt!MKPXi?S[[ϟ+:u BTB,u]gƁctt'NX,brʧrDUC%` dׂH؄o9KCµOLq5{#T*!К5kpqzEGd*ڀ8*Mq [o h ]-s*ӷ@θF̟?lbd2hooŋ1o̹Mv4.IV\w;*5 lmulc`;MtP ͓XRL'iwׅ)؎v"poA\yoo/|M8p8s y R"9sݍYf!HT*UyGi)l<"W3T7 u-㿮\.cll wu{1-ʩrth2,0H<59|ӎ/f ͸4b,X T&ѣ8z(099K.^Å 099:̞=fϞ:::fiUq؆fmMntt;K/СC^jH)cQ%=ƾ$/6O,T2H`ʜ{Q9r'N˗DpE;w###E$A{{;:;;ىƊ_Wjq9lv 46om^$d/lhhk֬Aoo/^ylܸ]6ύX `ۉR3a\/6@zkl ؤ d#-"[n&3)pYŋ(JpΟ?ÇcppՅD""B< ja5 ei[Z[㗿%n9sW^y%Eݎ[KypgIYf%p/-%$Z&HDdXҥK(qQR3g8tΞ= "j6"s kb||IP񌿜s ,X 7Mڱ0dPD eaAL#plJ9pHs~z!\d]O>`UZ|yQػw/Ν;(ˈD"X` `||f@OwЫX1Ht)˘ĦM#gw܁ÇT*UevX10赁[$`a:].'l"am|ߧ}fq7FFFw^>|8}4z-J%,^W^y%l.y #''Ӻ #;K.h;֦i]֔n:<쳸S/S:V 6oһB]rhV Cd[p5$ܖa;$aƍtGhO>$Ӄe˖!TJ%LNNFw].X'wK;44+V`߾}D#G`pp֭clB𮗾#ԝ&"O`JPl %ڐؑ\eg웡^!"iU?'Xkkjmm%@__;益^zưdɒJ6K u`t_!dJIȶ1e1g*L\bގ+W[okܹs ǹs@PJaƣ:[4wRCJDT*q!lذBw }$)no^ ,q !ݣ%pJRO5@>-{n(CBUBN9߸>dǜ{&0b'NK9UϓB JW<Wݸ:|0mݺU?/RJ5\LLL(/QCu/h]0RVLqI=Q&&&ootQ/nCmܸ(4*FWy)t 8 ĴS~K'M@M{XQ?%f_fc h+id Ls MlL[$$j---n:l޼#L_"!{6E1 H!JL4"޽7tSL&"ax/FVi0 %H;򟀆D- i;=wZRήC]sq%2ߓ(}2`u l~@ =3Ӹk93\.{hݺu??{^z%pbl0][ӫY[6~2yl<dzs^T)n@ڀV*ɄrQ\5tK}%uմ0Ue-Cifp'*YwU]!sqt\,3E犓V~)'_Gjs KW^-\_=][nA""D"A֭@@m=旷It\.Sss3~i&R SNQWW]@ܚھ};E\\r_Nhvyc uKϵ%lmaecP~&9OX,.;aǎ߿TZb1( ,@?N꣕"<N;)Aue*a&m^4f*'(o0U1.hhh}ݧ's,\Pmذb1`*!^Y@%-X,bѢEFGGfdY((){4bIǩiw2V5^\'-+vJW#7) Ԅ/| 7X,F=~mDQ~ ֯OaddW^۷ l~FL){ACnа ]{IlXu 5]X"e49%d]dc{e4l?nD"b=-__o⩧ŋ+5fMJ4:{Unbb{"!7@@ _]b]k?? 蚈;Tb7AX~=cܹxDZ~UL$IM_wux_*+fkHv2vsR)})k[ ;v%z$7I.kĶgdcԾ11KjxO}A2ė%<x嗱uV$IH$돓޷) @yx9(ԷrQ(p1iW5(j&c @ E!95U[%0YCi黡T5l^u)ȅ>eo'aHi T#CmzsXOd8Ii}7ǞKn__ŋxǨ\.#J߮׫UyL5&UarW_}5^}ՀcX?;alqSuEKeN6 Y-4aa >lMD p3m'IS1͵ߤ(3g?0ǑJݻeD"ā*рLk׮܀1aM;l>=9 d鞰\`\B6[ӆ縞 iÑ}[-QV9W1H###M s=n. u2D$AoooeSHRhc L?Ij+vD _u*0y_T}]9O_t~yo4g^>[>( A.^I'>zQa☦jjjR`ttT{P(֨"Lp6wXrFK6DFhX Sj‘?d e/TPBR |P-U.,mIkkח6A/~?>z ?Д\!.CSyTDD|4$̈́sUaPsHX0ܜl$qNQZRьVBB`Fz$E/hC(6fC5.i&1b "EI+;8ګ̿Q,m۶Q:&h@תH@D֘iK5;::PWW;v L4JMq2*n7`l0b9|2P= V"̿ &f@"naaUE<W_W{UY>53MDJ:K fT*T C"5Y8gu!bx fT&RHg6U%A|{<* N6Ɇc rK̆$Kȕ ރ*E={6}ӟW^yL&\Lf)bA0_+`ҥټ"8Y5F,q`!:ڐzavV So{)C]u<WܽMT`pCKbƥ88we@YSBP*fNFJ)n6pB}vDѪLD2=b((Hбp0Yi3ک dssP1iD &aЮP4710'9/ӧqqqEc% לikkCXđ#G*ZM mlƭg,ܒ]'-0?J t="4_EȆq:c[+d$C9&(I}SŽ;<r}"WNS9pZZÁ>qnŢ$T,cj0sK]k4VCH#0qhq3 f^钩@&_[2 N2!ŒpLYb rB$H;Ķm(HLCill:IGKlj!%i 0HjKI'R1Gz;۸]毖 ɕem]~ bhjjJ$.s캞MkDX,B08% M &IцVcV"A9R`qxi^wj -f:"wr K |P|ݺuؽ{74|A&rWW ̙R6y7u7 B&i%Y76n 4c 9I2$Wyeۼ\$ }\[%} (@$H1%nsW\t:ՐM\Z݀: )ҀCEI׎tpԪVU`JE0)p)Оhom'r1?d*a w_.#?Tߖ6J?|"zjبErJUؙ;U.:qx5@*G]3+ 9?i)ǥ3c*Ði`| EB`4;>-ζ>Jk \ ,s]u/d ѤubPWW $<:W B CVՇ0fҥK4U6,h2FJG+ׄL ج֠1[3 'Z0,nR `9%ySQ7p2Ξ=KSHƐm6@UoE*Ngk`2Qٟ<ݏT! [tښ 36^ WJpҪrdCbe@~ѐ4.m0Zr]@q)F =dێ0ٲu6\ 69*͊cVfNGKOL&rlp8j:v<466merU^rҸk `j+k{zz0<2g 0088h]oάB@ZL [ g]&,dLB|-U 5 4'ÂLH{IgV.s1KΟ?CCCTf2fdd000P3&KM _A5%M(43:5eT6Xej[ZxJJ6 In=eqZ7nLd\Үd'X g'13X*<&#P;;Zc:l6[)0s@@hՁ5Cf* ~rT: , \l \%z*5,+0G`Zó0xC҃Pq=O(o.? 9vc@pY*HTC N7)Qbֿ 66^sPHR!g)Ze0R bN=U+쮾3&N"!id_"P0g Q2 ̧3Vw_<dYpZޗl6* vVX5˥}N 9 ˚1D!s"85M uεB\is#rZ `?xL +C.d> dPh:BÀ sr2Dkk+Q.\7͚ F+ 0ԲZ R.APͦ2 bTçj=6qg26I48lVY# WM `:lւqUd2k 16sJ&J8&0O0^p[a4DwOG}u{cކ.% R%aq7Y d9_u _~χ6Gֈ2DW,oGe\H$BS 1BS + >%X MRB?lGZ& q~Z)\7`M5N@&`gk(RPSIoNR ()+`CI-MLLA@͉8/Kv-E$(p C+[#U O?%y0mrHWϒ`Of@@:wzjZ,y 0$ d%_kJg5PaJعb4$R!U<W tP(dbEtRX"M+XN'͐co}oG"X> e^dJ1x/,*$pzS.  <Y¶ɆWXH&W:*e}5)]=hGi*g{N!bL % frdOR>UGZ_C_ۙ\dc(JBy,PzAK2.++_(]k>_v ef ɖ@kA|(^Uyឧ0=Ƨ I&F/ N1E f%~A<;8{!͡<x8h ɨ4Vͥr㸹е<^GEcypR&#[cypAN&<'O*.xUЃ8N@ԩSG2D\b~ dZs#`ll BA[C-udj)&TSDWa d(8jbWg>8%If %C!{ X/_7;R.?v٣sp^0^+h4˗/#l6`Ϥd1D@l"Mh/&tjst)h'l&¶!x/b>n>v~$ wrr{? g2d9rђdt o~d2aE aIڀ RJQ4ťKJ(# S(6Zaw>~rJ 19}+Vujn?Fa8\]sk&&34e_,,Nsa{w܉L&Nġ)05X .\@WWdc%ML4%hu%gB-ZIA]"~X)\ō o.bnQhMC4-СC "X,sqzZnHqq aq B :Ŀ᷹>sm $\~-R7>'X+eCm&u2\%pq땑 ir7/5Nt5 &>d3I(ɨ|>~֢\:~p<"ja׾o.S FHtc10l>r][wf_vU]Ud%Tֆco te\c`"si֬Yl&`M>`3d7vM1'T#dq20I#<\0Uu-a>V<SM̵o@CCrJYj9, =Lӈ 0`SFuiގvoaC垡 *l3Eb|=w``" 㯒As*6\qα:m6,qO CfGAg8~8z-lذ###D"%Ta\F122T*ND"nm4'eHj\QO:Wpq퓩b (_a۰mLm\fd1 AaT U^w}7w'"H4Ykk+4ϟ_s_D/ImmQlY] aUdp&]? 鷭wC9 f>###زe nFLNNtxM\=AX UW]JOvGyL_kz0~Lۘ4UdUQ^o}DhddΜ9C7n  3(bE%Df w,1JLc!.ǶFmht1#C:updCA)R"³>>\{thm.؀(F1>>JX7>nvH$OhbJv[8Sn}LƊ;}dH맄RZ1*j5PI)k?v*V͟i=@=g?Cy sm0*HC%ae/C,ǏGŭފ:ֲds66O7cࠔRCCChjjBCC@2TC:NTN@p@},J7{n:d2ڧӫHm; ,NTդELyTQfT(&A"k/t]n|:OdXˍF5\'/{L<)vիWcɒ%j QW3Z""[ؼys庎8ϳ ?)_E?-['xGGyNB`Ţ^YRɌ@1 ucs(%X^/ ;SE12S.7k 4\=B"*JnA*_ RdI;wW_}ux<^(w\S.Ѐ+WkA__v؁^z \s *_BXX.C|arWv}6LW-xIvRӉn~sÇKH_VSmc IDATXd{Ŋ+ZP*fsµ3usx:66qR)ttt{ oߎ~/"͛oA9l±$e7.@(o.A1R;.7OzIҸL$G!%p{ =>!JIgR~m|Te"ٳg166˗ע hs T*T*P( Jᮻ(z-7ヒl6n 6l`w&zpd@v闁 imڄm31&\ḯ7FOS=܃f͈1/Ǒl2蚔$narFذa2=??Caؼy3ŪM #Nt{~D)T?{~_ĽދVk8-ɦQyoLu +7Ă L~ $xhFsWϟ ҥKpe߿>,.]믿/FwwwA-D"DITR/ɦJ(%aX~kqPaA-%x8lKI@qPsʐIm7s\(zz7SxbK?!vIDF0fph>8 =HӘ 6j&ĭEΫe3S뷮Ht& "d娽6mÇ MMMXtZt)mܸQMMg׫QZJ\5z u_D!:; \-@̿b-A+sU xJ)fc7ΝȀ5#ro,ùst>ϫ\.Gccc*:ƪnI !JСCHRꫯ&?BWWpk*9/fs*V(@E"b1\֮]N<_T[nE{{;nd_ܿD%YJhdSr.,d O\>3FBX\p~E f.H?J n=va2WIRvH!"kg?{J.cp5*i>99陸'OOzɱϤ LbⰽڂTSubb|p=AڷoĿ8VZo:::T$bBT>"|~khV}L5!Ư*N3|x>^NuG02Vܔ= tIAGFkR.WT_غ)mC^7ߌ+VȈ_`#1QRqqQ>(?X,F7nT(2FXDcc?1`kiF\#"DQLNNx7nD\ӧ100 .&r~~+WDKKK%Yr;D>qqNzI\="Ml>cǎ?!FFF~|2"H1..x޽(^wy466Z=Ga@@넺b1e\|D6tvvb||+Vv؁W\qV\nZ'Z**XlZ3¸5m w#l[\K"׷r\.]-[^+pw"cxxl^x<7xXv(r\U'o1!gm.Jj%TjbbHT]]:;;R ǎ /h4J]]]hooDzehڵt] `'-fJ(榪D0*Q@d$0ePMHVuV2eu4Qڲeںu+njooWt $-l2&wfhݻ|Cʷ QX pLLjBhhp=ljb'===XrQ{ꩧF\s5ذaR3cIČU01)gH풡 pv?O  / sϾm۶駟V|V^5k ϫ1FbpU7Qjo\:n466'5k`Woll$GNWu"cQ0ʰ 8UD$UI#І <8qcccxWL]w6l@MMMކE6[J|`8c1ؾ %xacmkY~zoϗpF۷oǓO>X,իf1B2w5q$+r8|0.^x@z'+%PSGCF"B]]֮] 188qlj'p1\|N֭[Q*Յkbʕhjj奅!=a.nRJݶ.\ ;N.^۷cΝ(JH$5k6mڄz"S59#+ͰM(J%<쳸;*'ēլYpUW rqW\`8Ln@F"{D@ѱ whllLye͛%K]tI={CCC_|>(&&&… iŊX|h4uWVE}4t sbTe.B#dPŻȸuӨjLL89PrCCC8<^{5499̙CsUX`" DbjY'5p\Gy e*1bR)ڲe={6>Tzhhz{{1|fi^T 1*)V] '2D2dr#rďP_ep0Ktrr&&&1QOOѨ* (J b׮]x'i }n5w\Nd@}}jX,*.w8 \W`7r)K35 8%!޵~h4J7Soo/._!zo>5>>N^h:zQTRccc}.h)܀.H~ B2ck.JT__={q(1w\d*_x IxLJ/U d2p 넍ܮp̭VV`Na"qW}B1N{TK/^RFGGթSk.X,jmmESS,ꢹs窶6*c8 @5PLE d kz GT?:tH:<(ŋ21!*J4::Z{%ʰHEgeY=թ3g`կ~UT6sΩ#GkYf*S-I&2PM&[F6W>6_̉]cժUXfMVĩSۋa$IٳX hhX LfBGGى\.Ŧuez|y>^e <(yfL-x VS.+\1ῑ}ҍLCCCxꩧ|[__nL5:L9 ' fl%V"j^}=DVrcmmd:5M-J;T ˗/W_X,FbA\.S>ѣGq LLLP( S:Vmmm4Ӧl6\.:{C&5EBSI*Om/˕kO.\O.]8"$R4ytZ[[1gjjj'&&0<< AϩHѥKH.m@ߒ$StSP(P4d2d2ЀJ2׏zR)D"&700PIu6..uaƹCͽ%񂙞z)C_pEhmm|̋<*3& B.K=uWT/JY_٬hW̥RSEʿ*u\.X,V#hv-H HDdx<62Y=hh( ZI-_K֣Y}ӚdeϠ¾}tR̝;Wt~X6qaug^1bqq:os/oP@Pnae[\Ljı*uRҞGWt`ϤHˀ8T}:]/5-/]oJ$JI{”!̟*Z?t#1 WO6 :}L&zT>'?I\p٬W}~`UgӁ W=pN3ŦHUIOgk%P)al, $Ă+$C9he qZӁ9yJع`?Mrg*!@voJ)EtZ /~A;QWW& auڋokSA5     hCs_Ձ9 @L*8ZF#,BPM7RjsIXjИD˻T*!NqlٲEi+)!X\+ 2-@*% QgtKƺq]AHl###+Vk_Zhܐ}ب"A~}>J(LJѿ"ԦR huuu8{,_Wٗ1{fn°^#spߣ@ڇ2c`;cs 7bU8} St1s OY&JF\ڪN΀ҩqY}X@S0@,L I\TD"X,F*~_;3xJJZ z֞HWNl@L@N<(i*J8P8,#!f2i˖-j``> 6lؠJ^? 0{g7Bom={й.8?RruAQ׶jV}K >aG.ɓ'3`ɒ%x+^JnM$\(܀L4RPOm[:0^r`R..20KI#eZ݀B-t`N=7Xv.dVId&!.&nHn@=C3YdAo%L&H$K/a޽twⳟb/8TE3\+TFVS9CQvK0Lvs@Tek[OV1cm\la<B.3%VQyߝ($yxdΟ?-[ //|rn$_魛r'G(݋%/8ؤ{8J N+c24Vh1 iCRgPtj("cX[ޘ .,a"\5']4E:(^z%u|?_~d}km@S5n: ]הsi0ùk)6QVL &O-%$~Nf.m̱+/,kJ,8ߏ_W?>oakOg [zOQ=yeIWd+%tF ׿P@}+Ur5!zm>K` `8OUӰhwf2g ]:7.:)ʨ/ӓm۶'Nqw/E+V Ik԰'F g=P,'-[`6PPk{c`ӥ3X{ctC;BL&'?ó>KG9svkB@@H72μ\܌7O?2,YB˖-S\(M3PRJl.TNb6.LCQ _bp1I+~6` S>q %"W!F /b"!\C?l@Fò#k2d?GQ,sXf'?Iׯ/s4<1uObYXXA}.*>1:wۇG}2-[.\d2IuuuhhhH$&''Q(\.KEkef_}*ݢ:0x Hߥ! hŽ\TJF01i.pꕍMpb446} C2 KR*B.^cǎaΝhii/XbEer瑄y2%5iZdܔ^PKqPD˖-òe˰yf\t صkvލ̚5 ^坶6ttt Ncbbccc >z0 LI/MĤ&@̡飏54Mc4ffabLR–DDWv8vp뭷bժUXbEhc \$2,Q(LN\ TSS\0>>^~ezաCQWWt::::tR5kŢ ]EWWBPb eCv!H(ɬ WLc5ol[Ȏ[W9m6PH7g!j)Ѐb]v^_100ŋ$/0.˖38#QWD‚6xjw*ߎoR|MTqQPsy<6uW?qQ>Gww7m'<9cT"i9uQypFպun:Qرɓ'ӟTEQ N#t+J(HؕA 幒b ⱜFWs%4Vaǁ Q.VJz,SqŋsN\|+Wg?Yu۬44vlr)jb F :N)-˂j,n6vm422'OP(ڵk_ tRjjjRx؈q$W3!HP-98@GJ` \Kr!1ā `$YRAqP=,{2lV mn9zLF}t:F TR)n_z\cꋻ5imIDAT쿢`N &c<A@Fab={b> wޥUz1M0U)LdLPJ&a-d[VvPb*Zp޽>&}uzLr;#r " Rkؘk%p>5)o4[|&4J@"tP(>o h4>k,,,h-K(c~~>L5_GȃcqcRƯgjU18Mx|666"t]|7pzz qbNZܸqE4ho,['d2899?C`j/"z`0Ɔ6ݜhqJ^K`V~)m/!EͣGn#_?F 9,//ۘ+1+۠'޿an i'''x)Q*0??Uᣏ>gK\__޽{p]7z=MBZI'#3dNixL=xe9(4-=ϋR37oT4M<{{{loe,--֭[T*@z;KG(S$TwIeKi2;F"~Nfv2koRnWۦQ xSVZ6^/Lt:x ...F MĐ Aiq!L9}l:eTr90L%u8& cK-:'?33C~ȵ;j4xuJ)eUViffE\iU,)Ev:] ]*0okV*sXRݨԥ!a6O"V+Yf/R-..bjj['OP&~ +DJo@ى:5IXN{tĪ h@Da+ʫ1UVCVb jv/^`kkK={ f|W|\.sLMM)u:Eq5<yX__WoȭmPHD a܍X 7he`uS;g_HjȤdb~Xԉu].e2loocggG=GGG١]8~O "Vjvvr* JR JTJj:8l! f#HJ;Nҭo1}}"Sݽ{w1jYd,s~~?f3J-aS>j( P(@D5y^DR&$X IH-Yn%Hϕŀ42OA^?H4o+$ 5J;[+<^|A4Fqpp~ ',2fggqqq/^Ǹ@EVpaj @>ZZJvH/d_Cd=5" @1z\ET1??Npmbnn+++(Jh6Q077hQnQհëW.RuzFZkoeeJ~/_pyX[[CPō#޼46givggAJ\Ӏ9(F9(R:SJLPbԐ8ghii)a{ PGEG\.JPWWWhZp]~#a+Ǖ Q!LP@qmd2dY*L&CJ%dJ/&l\N@>'AD8Eߏ2 IJ4ݼy3. * QJ)=V8P,52DsPOb3Ve`,mJ3!k=8O& &Ȥm9ϛ6[B1`rR 8P2HcGVSc֡"jZbf:ε.S.IoޏB@CX޻X,X,JB\q2O]2bCgL9<@N AAclYrbY]fN+qöeia AXE .kj@؅:E)31 %\5Á~9b ,גZΤ%{c⓸:r1 ݴi C0|^9lѦc#(ߘVyFt&ł67i>oW.qrom@6L MmaY}>sec#&AtI%k՞F**:#Jƭ6~`7tߴ`ߜ#ȰqaO9F?G0q̘:06 g.V\ŜJ:IVK:anq<Gk=3}̓aH<$&g8Kٰh  &" %ih"z=:m3& % ^M)HOv}H&HuoIy Y깕bn[Ƃ^^IE@ZyD2 IThS b|Փ !X$ |_Uct^#a6Wh ="4<<pl\3C:&5q#UqqK7iw\ lQ02AUN/$i8HcƛP Y3<_Rp4YU9g)> 4Yc@@|bR!J1-$JF _YƑN/B{iX_z?~p,?+0-&dO_콗iNyZ>G&ZԾ7v*݁1m]Rp4o8x߳In$s1~Y!;ގ(ꫯ͛7Ad^i_zor^c5>O?#)IENDB`freetype-py-2.5.1/doc/_static/hello-world.png0000664000175000017500000002077114664131406021335 0ustar georgeskgeorgeskPNG  IHDR c;+. CiCCPICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/9%bKGD pHYsaa?itIME 82Q7IDATxY l"Ȯ F/PQ/D@`k"1H?QT ( 2,JEtF=gNOuWWTwWw?7sr驮tlٲ\ԨQ#wq7oJ5sL I҈#To֭ ֭[U#R)QVRRh@q1DFʴvڂ.@wqm6m/^,I:sr;vvڥ:[l$9OJҠAnסCۮ"QID7 c23dF/nԣ>(׉Zꑟr(dt:hDa„ 9%K:&0rȜ'" " QGALL^b$鯿} 4~=9bo2( . z=ۚ'+W}g}vuϞ=_n{!Hիytv2Ν;m_۶mzEj1jP̈(F@r@g̘p;wl2N;O> Cq~" %A# aUENU*Qm;Ǔ"ɑzY4M%Izh/#FU~}#apk&PCD<~I҆ lc~noܸQԦMw'tgqkݺ5=OUWW۶^}Y>W>}b~J5KdJ',I֭=N:vv$I?gJ^j$ۯ~yOIIm0DJk1U_I_$I͛7{ru<~El=3 mm޼Y۾˗{̎;8eg>fϞmL % D"ʍ;VR'܇Z4w\7ydIRf8aa>K%>%1/h[̓dT?~|%ҥΝxx/ Ds'=GuuPQQkKDmy睒GbҥSN9HF~P/PDp 9R"fʕ+mݺ52+ضYy͚5UV%Iwd:(k&N(I7n\QT4 RUN=z'B{0Vc4hP]ƞ[g Jc됤/ضm)#2&7vmۗ^z5X((۷o5kTVVk]z]pw .]xD͒nuNztz^T ]n3LdZ۞:uj^7fbTS%7޽{!C$NF+++IBg ~iOIz7m/Hi̓rI:ӋCحJaY*?MJJ^vΝ}G{, ,h*믶I&OH쩩ȜZ3Rw{Lҝ/R?n^l_ ]=AL0vi|gشi3ˣ.\ СCm{Μ95ߙw˜9_Il3Om,Y⻝>wMB7v׮]n׸qc6ׯuɢ 橵̬Yl{Ĉ s% i1KRf$Ic*޻hƞFK160(~ޛ([/Ri&\fr{2fҤb}j\:c$I;wnٲebkiet6mjzM1{v'<}AiK~;t`)]L~s'+gct[.)typBI'#)bfL0ixw3ztGJh;&4*H=W) c~#A+.`6oh /жsI0Dv؂ nF܊1`Ϟ=w;7ʕ+%%"}m"o۶ͳ; W:=蒨.c]@"JcLEw?_~mg;`.2kq^D!(F@r)ē(TVҰznZ+qŽyG-俠@"A~b^gƌ+Vj5f^܊H K"0 F;Cd, })vЈOœr)RرcPl_ɡQ(9ɤ3T'w\ҾD" 7 dA&3Ɲt/',*GȃFӺuk6э:$[x2r7 (sWHGAD7 #(A˭zxbҜ 0_}Մ۹UϠA"AB}vڄرö۶mˁ+r:umwbjmݧOy;wd+x˗۶Y@~w_ϿjRf+2{~㎱0 x{Sm۶qj!`qԣ,ѣm4d\ zc>Ynl۬=?zsk"^ZRl=Wt@7hS:5Z]]-)vWTcҫ\LzCXnz>z5qĘ" Y)>s0Ew}h;&TzvfP7aIү͛7$3cw޶ݬY3I޽{=/qFIOK.Z ̌=RXQ(\Dp 9R{[r% V m?~2P RLEпIYg%I;wnNQX՘{ȶ?ct~ QAD!˂F-Zdf@'D{϶̈́SO=5gmݠO5tɮ%e˖I,E"KQ0OL:sX)Ǟ,c/p {l{˖-7|#Iz9qn$GQ=\I҇~T$QFI֯_o7n,"nڙI_/}{$}9oɘɪgq';gFVlO?[A؝'AM 2֕?}}K0cM :{d&'$g>ÒjQH=ʡgyFt'ھ˳͛%ŮOK9dp>(IK}g޼y{3&Oڶz󞸞sӃ^}դ+R%O>9塞LԤI۷~v;w$M:53h>㎱M woذa3}tIСCm_XDjsk̜9@:uiܴ\J}VYFeeeZvmd.s„ }>}H}z: zy7lYKyӦMs΢zݘ궒|@sKx w衇UUU}M7I^x@;`ۦgrO=m| +- 5j+//\M=m}J{j^{m^qɱg].^T?#{i_}Uߩ_m̃ѣG?&Zy-2k)Ǥ/nxzo[RT\~bSRR]vTθ$ϒj& JҎ;<}&o۾CR[tmAtI=dI5LݶW^SM;SڇO>ĶO?t>ظqm;nܸ'v*k1aQ{LT]&G7{lN6.̶gnʰ]pB[o%$9sk)DŽ#ox(D}~g:52>Jҋ)rbSyϞ=irٴd8p`گFIoߞqWcBرc%I'Oj۶$/}͛7/!R qqc#$&cپ]c&+.IڵkW]vYfپ>VG%hԨ$SN8lAWO&j̩=3{Tkjy睒֦M65kI*kC6" հaC~衇$IW\q5jCWRkfVYN֯_/Ikl￟}.)Iݺu$]r%C_3EQtl4pSE+:a`uEGs^^EQ> +(nE;/ ܫWy?h "`'(֟ssקLOR9`p OιwO;Rx9 ιsǀwLgeǵ'uD=\skψ:.8ç~ ;Hǣkk?~<㜛~}]X/GQt}EE>KιƳy(~;Oq"rZ~ۨ.}Q X}Qmh]E/kxGEEDQ[5<ιQy((֍snssn>k(Ll\>).(vߑDUsnss:8~sWQ]ι/;89D%<E_G^m]EZ=8s}9wK~oZK2/ܲ޶o9{sGι@"wν93ιtν!"e[ |jED뷽|9wyyp OoፃÍιzs̿??6uιߦ|{3Ud)en/`p`9^Zz& sVקHu5U? 9e^|Ŧ"zs>3KWJ팢h#8a5(|]ke 0 fv? <IO#! o$~<7x5s?GLr}קjCd48NREQsަo8>oQeZ?+6'З_ D,mc:G{(Q̃% ùEQs_E79r}vPlQs;F$?|n8vXEѩosw79{#DQþ8ף qb}`EQ[Jܟl(C^3%cos#g-{(Aιo foVwL ι?+9{Cu9IyM޴~ w|㫈#__ "snH D }w$ձ=s.EQx$VY [3X~'їsFQtsՅr7A|X:4n){ nhvWIι+&!](iEQjq"22.&֫QeR W/QǶ-/dohkaPtdr0ОA,|#v0Ǎ;?^(?s~8r73iRb=&n oιIhDFjZsn*p%p❥qsh!s_E`o"Aa|䛀;ssz;t4q-.<ݱ(q8phɗi>m0 ^{P7 zcNFD ?v]T␏'3#o'q20Z%.GQ| Qι.g]{S&G5Fô9&v=')|%ιsH<Ts:qν6YDQwz⯂9ws4~vTyQ,xhΗ9.vν9wW%2ι/B/Q_\|;<=798|D\%'s+#:>潍w=dȹ@7A⯅ L\i| MUV>t]~aD$7뫀/^[(9y;طwعxhw >\| (/ !u/uxI<+1,Q= \BwQod@\Ǽ.o |ZۉHwܗ߇ K <=؂|l;TvG#.%{q_G2haC?N~pνhRT)cW"ܕSKXsU-ZQUUbktڎEQrHTWWmiiinjjA83t&;Ms\gr.q/ץ?|LqyO͆O͚971Quu?d"2Sr5"3oGWs 72{q?(5;L/lv.2S̘O+LXl`&c"-Dg2QPUuE]5"nn׮]U?pD9"x|g+NSSӮOsorJe0iH&ן23$> Gh}a|^z)ۡ#?Cq]ׇg:nhI>R3LRLJ7mZgPunO{w6L=q-vSODQ3Z{m^ڿ[3?Nִ{vj:3w73w?iΘSa+N7_]_Owfd̙k4(I}~X9’7sU2{;6 `gro}7R9|-&/:Y4MdLٲGway3lTJlI9d2%FozSϛ/>}N(Uq` >a4hy0N$m\Q&mr%ʕy7m%+X""""")Pb-""""%""""")8jO07OSo~zJdoJ*&Y:mA; ?-u#5cx5W"ܜWg&d2qm zqL3 m.w zpE-Yo-׬E`Cb2!tuKOZ&2 2lokϾ5d5@=ovT1facuOp!Ϥm˗sb2֬!`WUWS]SV~鎵H X@H qx~ĭ9m24s`>1c'ךSʕ&^WrBu;wŽݰkWoϜ VǬ]Ƶa I`"N]_عӯc;uƵɚt{fdzzc^{mwvIsʹmo{ƋN=STSza`,\n[(X5er;|Νt?0㧙_};ն""M<sM|Dص`M3dekm!~d'=@fe&%wIk 2l)Qx#GNv"3yCixײ șh6yԳ牵xmm"-[{`/ &AIk4)̈́20۶>/c*X.)RPjғr+uѯ:.etΧ Lg1~0~Qm6&|uk RDzw 8m h'-0m&^H-|vX۸zg&`by&uGRWk83D:m {*~RlV9ޝ>͡d?5w{RcҘ\Aʸqw;:e_joZ,8|8YpMa -Nj=WWޡv.y'Vw2K+j2.$[ZKm7 ܿ?y{Ϟ0~G c[ֲt),YRw٧"aé~V^@dJ,eE,w͟SHu>2Yl3^JBt#ыa\N|LY^Y_ҥԟE~o#Lr!2߮!^Er YǜMNOLOqgg@o=, lВjkD_rI1v</O<'>D3(Sb=J}~´{_?vvY(9j1_3WǰLVF4+Jh 23<~P>a) D5ǽJˣ7ek(IkN"o&,q#g޾0~p*'`Μw#WH+禑LJp!LE%?qA~+k@m߱]DXr'*2F0#tZD-u&0ozJ..|3v[x&|lrn[Ú9$kIQET """""%""""")Pb-""""Q }b{o56kmǭN=cpxA8p ^߻/)S`py煱y~m<)V{W}N^5莵H X@H R>b⇁xC:/SL\.X?Ra{4,Zya\< +]Ӛo6o&+~ۋ'1~:?`⿳f#X鳉H{gCi&gp//Lo&@bR(IYtkxi2p`e;<`yj;R5ֶڌ[5{M<Ķ&I:f5I5rnן2gU[+Î;kʤ wcZd[1{vf c[\[,7׌*΅Rϙ%r0[ QaIؽ;fkзn Iwareq.}TnLsP"LVJf|уa$*[׭ oڿÙ Ma=Di*2bC;m0isoa|_s05}}d_Fs̶JY2'[f6^M"x9Ƽ H#bb07OR/&~ȐH&aoa\]J.2'y^D;v;\wl0o\vY:ư $; ld؟~Hn ZM/i ;ܿsgCC)v1xٟeuSI݀i56Q_D9ȚvfsdG6~N>fw"6?3e Yn n0*w~7m goW,ؙߴy3wg'>1L*U5벗YJADDDDDRZDDDD$gQ ʶff a) Nf.a95}4;&^j@9k ~[ҏ+c3dY@|q}L9:'[\oxCaߟ,`UlM!G>2x~=k^/׽.KȠ(™҂=ǘV^_|f%9^O5=l? "gĎ^}05c{q"n 4_#Ÿͽ۔\\Ie2ݱIk(IkH/ôe \$ _T@z)}/7_gk__2p|]c{.XU(S[Se <\1~x+Ÿ%Y.nk_z"s.vka|ظ …Rvz76ngUK̈́O\&NjO&VMm\jM_.?X8~SOPnc^L3?j2Z]?F'7;c$3]7zo545LmrL?aO_pcԿhGe 飖H X` GSD0ost_5`9",։MG_SZ\75cR*Qj*1KNʕa針j\Uoe.o/n>NɿW:<9I3]͇hy@9ӓďM}W]:[%&\"l2?z5K.aoqS:Rmۊ5?~2v&GͶX/D$5,;;vR:axkkƾلGÚꆆx\ri7\\l >aw/l7dPH(d IDAT}7+Wjbdb==lUWUWS?v#cdgφիLB>~z7$shlk@H X`5_Z\a'"DƏ|;<ˋ/m|sO4okUUЬY/w3/"6_n?w4>U~/BWm|Ħ>ĄM=ffq*1 w+#OOiδ ]T՟X@H X`^JXfeMN(""BWW1no'M3uc=5SgCsaWCc螗T&;7f2+Xl'_kUL7iX[=Ve93"U+6js(*r^W;sS2MpĺI^vz)[[Z$qG?^g̀eǔâ[/Ϟ\`?55ŋpQ>ttP3*N9^{8i]`9y׀ڦ&jǸDDDDD$JEDDDDR0H)K|_OGGK/'UW9 ==fK.n3k`\_^oGa1*׉o{M!sQc ۶뽽&L^u*ԍ)^_*X@H X`c&.QXvEĈ'IalsRn µ۶ 8TcL vA2Q5XχMdd tZDDDD$JEDDDDRZDDDD$TJ5Wgtzq-B0Vc#4468q"<& L>OG$<FTUEwK˩m]Au}I /65=׫ZbĺĽT$16V9#} (rkn.&ֶ"@yrd!2~ RkN,c?ILabmU2Q)H X@H ^dn(:l@SEd5 ;Ar'_ks5;wФkP=Wp<\n7?3>jRc-""""%""""")a)ȁ>3ߋ\DƱav &+0VӦKPZ쐠?su`A1"pnOdUWG=^ఉGJ |im"cDwEDDDDRZDDDD$JEDDDDR0H|o9};{xp9aNGd2%rPvwQ3ޖ?Xg*No^Sab['O{"V6g?~OS*Xlڿ[6Ss0<'rv旂5@9FȰNٳI.hms*6^ >߅}W5(`3.S*pMۮJ T """""%""""")Pb-""""Aj5#~"g̶'J "D+W =ᶫJ'wy oIc wG>g1鞣84)jm?7<jK}I_~z Zc-""""%""""")Pb-""""Ajgx*aq@(Or7utDƋ]?ٌ[Lw75L낻 o|#^ > )5+,GdTUEӼl=krB /cts zWaҹ`A5Y4Yk(Ik Rcm5~{M @cZ0sfY/f͚x)x۠#<= G?SMRpۊa\R^JL]1~G#,Re{c~f?ƣ//*]FZ8ôlUU~ptZDDDD$JEDDDDRZDDDD$#/??7kH>lE^ܜ_|gtv"c%^ n!<{˗ǓLӧ9xaa?(S\\f K.k}~u1s'M_FH$--4kL~!_^ כu&~>_f~jɀa 4c7ufΤ?{d+7DDDDDRZDDDD$g1(oz_0DͶ_xVO||\tdK ץad,_}m/ٰbWofx|U9:55˗'4#G}phmӦ0ٱN <|BGuu8alfT2%6\WseLϬ_lh}xl2 'O$""""RJEDDDDRZDDDD$)X[SE^jEEh?:##j⟙I`6ėx o8Z ^b\[ 'Ol?qX{kjJ<' :k_qꫫ00鉗^ +w׮0Wg溲`x5\w]7 u˖1o@ۯ~ĵ]G;t>lE-Q3=$ߞ1 0'dh~ɫiѴzkL!'^.MVWSU]x2T/nVcabF1{wPۖzBX,^ N_ яx^b1Jg;/zc. c;qM[ ΐ{ċ_%Nvh\&XWe˨?+_ [bdט Qb=ih\^bh7}/ mk`[x09fiu .V)H X@H F* a |ˋwNS*ܿ^`k%?fW{$ngxx)υ5҄2c?67Kø+^|naSO~2//{\}1J֗˘rL n}Qz]_t<*/~p+ʌR>:@_ v;1lxxi~a [eL?P[Wy鎵H X@H Xfmߗ_ 䗂w[I,f ?IS_Xʎ[ ~59?ƙL[u mݰx}a}{׿>^|v(J=ʨr=mZZ֭;x[`^绩zTd=fkST`i}=?^it{oOOD^i<x=KhEQq]GDDDD$JEDDDDRZDDDD$4hDXŦޒ_xfbe^O Qƍfo3m=۶֭s@0??^ ΍ߴiaZܱl=71=[[5y_xaT{?sD5ֶ =Ѷw喝? kOל 6/r͟UTTV4dE$`;^´fڿ۶c/p*BjMόr?!6;G$/8lQb=Jl?{3id0Fxc0bbe lޜ[Y*nkut]w;yr{`ӦxXvXqf+;66&Xw= ǞyT|Ծx6R0[dc ,6qM8b6 zZ~ >mm5"6jƸcH gf»ܯ!N~8hNFKWW㗛ؖIE(umM \tQ^j<탇*ƻv1$KC,niu;}˽6Ò%xFذ!<޻ Rx{HYeLi5+V[SCThb˔/af̉ٴb>)O 6w>Do퇂k@.kMdd,6痂&~/&J+H* 0_+'k]*sɄU >$zZ[OċS Z0WpC/[uuSviUUa]{/0~x~Я#ef?Gw=J/9/s~\\gkM<0}SRߣ&װ0 NOOO٪k(IkEdƶ6-4ff ֙'t'1޴i/0z^lD|l1i? `VO.V[ul~KW:/={8ʶma|Xqjg xda<|wd!:{K1+ kbm hezT """"" %""""")Pb-""""XA3Uvnd/^yO}ϔEQ'_3ێzU@؝/v"ӓuxGe>y2jIv'?C}vukovRxprž^ $:@4#ety"O)O:pI _b8jŸŽʫ7-Vv͕da}>__{_D}-b/k(Ikz&fIbb;̘<䭟_DFsqhj*nMN/x۶p#f0ݵfe˒C!vO? =a<L2)Vzuߴl[}fli2^_ |Ta.zrx۴ի.xiJ'RX=uޕPBa5 tu3τ;:¸6#F;ԅ ǘ_wDROט_5M!ƣ!sbi/nv:֟*)W]u]56Wb-y$3oM_Csc%\ D<69I޴i `- [o 61M+!dYz}>;sJllfd8a>tq"FꨗX"N} &-Pos?}uM]{]sAb] ?ȸZDDDD$*pz_ue:Qd3Xg s0G? ~8onOuz+[ / W nalMddly[9[||Tb?'N~#+Pr΋?^*;""""")Pb-""""%""""")P綗Q=tD\/^0W!C&;4ޚ5a\_]n7xX:vyg~iil, ^jZv3=4+WS n;7VS_OiD'sa3yqgipi1Pr%QO\&֋M<^V/%rN."a#a|egOI⥰n;v=DpCQN-Tĺ0;{Ea=Լd*!M8iSu8{ 8NT """""%""""")P)!TwJbez̶1: VUuuw3m)O׿n55ֳf%f߲% z{Uc-lU5ט."k'ygxR~KU@3]YuwuF!yǨOQb-RBUU2 ~׻(7nL&TyˡJ7n x#NrVU5mִ޽~}qntP2$ޏ愻~2NjqOw7ĹJADDDDDRZDDDD$JEDDDDRkCYkOs9SS_u87yrwwn o|#:_ fx;&/t"I[W`mwl͓(\2v+Mv5BwEDDDDRZDDDD$JEDDDDRk))&^6۞S.M5"#|y>,Zn+5FtAG[c#̙31mmpNXT\n]/כI+7txE%RVvrd%K`p}qR={EJEJki~Sq%t߮A~b2ksO0jk#ڳP)H*X@ RA%>at}"Sܹp6[ [`sLU }LOO|839"} ̝Kp$p8>h4\[I@Ti>atYisxXfǴ:fX^b:/ y׀9su(Abik#DDDDD$JEDDDDRZDDDD$ 2/O<,IL f%뮭g)Z3g9Y#>~v'8"#R3kk%`h lɆ0:~ݻtZDDDD$JEDDDDRR M$Ʊ8S+ɓ/xUFL&^  [׮)ŹϱN6n0 [UE4\8>AT8>N*G&#,؊t$D&l6^'GE'k3frR T?$DDDDD$JEDDDDRZDDDD$9--rĐ 10!lhs1΅VV %2Q.GδIidkMl/1ιsi냧k4(IkZ*HxJ6X^::mc.>{O)2arؽqX@wGO5yJ9h0>˗ݭk(IkZ*SF=\aU]64AoCs3926$2=\&kGq}a3@g<k 0o`eWL+IL p̘Q\/Gb=0}}CSWӦAc#s(2 k)vZڤ):iӈjjBH X@5RAvϖ$1XXo>[3$6S…pjEFj$p^v[s]hX@H X@5RAv$.IO)?>t6o1כ?n8{ }LCC tćpđ#Q"PAR B'MhsuR߲I|^|g|K:Wgf{}wd]⵵_fh|`y>$8Ӄ:]ˣ#^6dɆwt`L c=Xc ȉvy,_-׾/٬nn;.yohpKV-C XlСC7SKlNAD:]^tԹqXv"8A+1% XaU0Z~U)HԱ :"""""!(dWf@G)>_2 [l5m t,s6_M{V?^nL\Dhls{L311sc}xF qKEUcn~wzp sca/=Ô?؉Nʾ/J6̿>zW7l܈T dXBkc-""""Ij&Ѷ,LaT2Q|i>}xBy=|$^N$C6m6oX Ѱ 0D3'tw[/_.n;AәveB}Ht5ئ'?y#nڴ Mf7Seq;n?+l; o.ލo)] :"""""!PZDDDD$PxXOڶ@oYMqd*-7Xni~l 8`[[pI_v궊v`r{ݻ8.0|t~'NxH/}Ɏ_K q츷x%ouuqsVՠ2x/7^._c%[[3@ʎ] g1Hcbr 0akz{QO5,x/:/|U7{fHSmFZ'dfv3y<[a<cOA{G/>t8}wlVVuuTO1fwk>ڵ۱~w9~W s;g =Sk%~xrGw[WFM%|Q<1uki_>#gTOg!Ԅ%c-""""uEDDDDB0G32Wn;}iwÝ'B5ivu?o˅r[6îeCPpk_}խŮ|ٝhLmf'|kvZx);~܎_yxe/~ũ=6wq7~ڎΞu?縪zx7Q|ʜN}NGWP׶ --VQp}`#ֺ·ucy-?~N#A7/[yo0r O}-{usX@kc-""""9 rxr ]Ol8YnKʁoH)v1X^[PS60u<:'C 5x;xweJctvx&NLq>wߎϝazʎ񏩏W?+VL3vkRޤ/|ېYFxsI޵.زy3ixxO&? :VyB>nr9K_zūWu-?5`yK5ݍ6W)HԱ :"""""!XD5a(>Qn/ UvT-.޾}t Lƾ%e{&Kt7Եknl`fu;wq{w`[jo߰We8ňo|g?vcv?ot̿bOvDTkTAB|@a4t>˭b m縉ڇom=bu*SqAU+"""""!PZDDDD$X`Xg;O.KNФ xJ/޺unInMg3gu?C>x>ib~() +.R78G tZDDDD$X@kZ(φ;}:(=EH7fqS)gT]Hu0@S8QueMv&KWZ(Ncҍ"&7: z??ߨL;DTO<' gH֋B?zP)HԱ :"""""!P,2_7?Vn5Kz>fߗ-s[E$bslr~[~M{N5ճ Sn[cgo jh> ޺oS͉kc-""""uEDDDDB0IAjaWh+ӶMd6Vy7@B^|?y/m֭u_wv46MM>Q};gǎv\2j(WNj?V)ZZJݻrZ_vQldn 6aGq}5Fzr38/yTB%{GV=k_3cs78s^S%""""uEDDDDBH&z:໌ezU_lsK(̖,NQ_3DҺe9[ <t߾>Ur3S|s*IӎWpcutz*T]seuj}4n3ҧ?-wvhhwZ>qE3 Zqaha@ z^/y@f{fاvN5AF(n@r>Xp;^?mrhg':':F_H1]_ Lr]ڌ]hăfzƍ Ա^̢Q%?ʜ7V @A^2QْoZO}ʎmvkݴvkV9I{O1.vy7w11ʬEJfǺX(h?kODuѣYɳԱLrivk2S:mZy⚓+!21,'m,۸MfW)`>qxF|355+4PW7y --v\[ R^T?TS/e혇DWT a 9oo*x`N;^Bm-V<E +aPK8%Ć HzL"o^J(kQ+0.o`)z$"Bܦzvq""?;(q9`TM3(AΞnSiks[n3mb\=J9Lsߑ8;ΥTvfu|uvss3ێwǥ|ΙJc_q8Y5ߏ~X352Dp0mup;qS⠱1f?L~|c8;h;w}rwcLf+1lv6A ;SKDDDD$X@kT`4r:<_}r7xb v59JU -c GZe.J?YK636RL7u! H(-߰kqkTHhy|pvO7o +VIDATFx) ~؎msǕ6q4.d NM.vuy+{߳‰\}/cs(c nv7aHk[`ԸG%mb)b1,[LNb"i2""g(kjkQC?'QͰY_*wiF렧,mv3ʝKAp::ܩ܎EÚ40pŸ?;x͑61:A~shWLrc==vivQRdEc1$Y"Db}` #aP|-+1?:6{ IԡPg>Goh@u N]J^i_LR'[Zq#NR'l˒"""""!_Sǩd2Wno|:iL.zN]t xh<]c '&s /7c~Hܫb=L&q?*f#cE8Qb&J1#٬js?I\S*!NxS(7]; ܩ-t>A(;jTK]/Hx~8΁>bCR-Fb{.H$>nITTT0bĈKg2(..&//jhhhUP?__ e?'% Ofʨ)$`4;?+1 :I_жD"P̛7Ozj}YY\\sC=$XƦMXr_u^ n#?0sLC5q`M}m+JQX 5=i1JgZ$770L@GGx4: )CR 7O?cBF eF{o:چZjkj ୷B"0x`RRRHII!::ˍԈdn 80uZzjCF" 3OG'WG*5hT*ioo撗Zqd2DR|QaQ8990RT[ήمhã/l28f0eedeSPPM&99 O/<QLzRCǹT*E.Zuhسg_|] e|x2xH.p;F_ wϻOOO=grϐ3'ٿ?G&5j9:nHga۷^\.'!.GLb\"kҙG3zh*k*I?Nzf:gϒÆ ݝHS773j{oNii),tz6o #,8f1j!-#=vZ>3xlmnw|KRSS1(JLY IOtitz- JgF'fth|}pqvaׁ][?ٳgxblms:SUU|j20j oYȬ)pwju#pRpX?Ksp~)~-~-))),^ӧ^-QIVyfRSS1 2%o C iT-Sn)ͧ_|yg ga…6nIѰrJx z=QQ,yp GOiD[|wc֭,_!fk2x`^y %0S#]CYR72;… 1Ͷ6.#ә3gXhxzx常 aՕIݻ9{,~~~L<IHHa OOOQ O\jj*&L9z(Ηt*ʰZUUH%RQj/ϗLf&A▎+j*KMmC->8ɝNqE1-"""HLLDrgKK zѣG m޽dgg3sLz zڴmTU"4nݺUTҥKywDtRҼ!4SZZ/(uz<TAovkh54PxpF! 9fإX1bps ['ii?/)))AR/ n׿5w}ŹS5ظc_M233ٲe :cUJo~l۵?~Ǐ /t;J]O gl۶SN=ȡL.yk[+8BaweeeZSN?0W}Hv?+y3摟gRVVfkv֭[UsGd2s< 7s [ح3g׮]Ғynjs`9N_ a|׶6W;gjoogxyz_([堇Iÿ/}yYz5 ʙz=-bڵ O ߷ovd:=£XjaǎY`k9vL,X铦Eo7?>q:_Vkk)vLL>#Gp GqrrOc'SYYɯ~2VdHNx{{ >|qƉjѣYV;***HIHaΔ9}m;Ǘ:nJΞ=kkzL;Ӂ((( 6:f߅GTÍNDhU믿ιslmRSgJKKӄEݰ;?<t:+Vu7q!|x·:*@8p3ƦO>戦O)--w?\7z/1|w>}戢םzDw=Bd2^z%xwE-ۚ^wz ƌCH@Ho7: ,8G}Joksӫq;~!۶mcYD [rQ<ري^rrr?_go5:E"-nn{477ڤngj,^7WOr _x ju+K/uE57ZE q Ə}Hn1cRlrylAAw&80;ށTKܮ٢sE#/aRP5f&#QQ5J' 8u!CPkԨ5jں?-f &邟v VDL.C.wˑdrθ݃Em-%40TTTJu}52 [U7=XFb02f ^T^Ġ^FҬn* 2o5==!C\ϳn:\x^e~Q>qqbȥ"I$pǭB2sLu4~/{d$039g͢ ^t...3eeejt~o]rT*E!CI)Qi&RS0G> ^.^5 M Ԟ%_xb)9uA⊮5H]Mck#rUlEKnXv-:x/xMPFbn.nƕ %..rV:cX!:u~~zj8sgNr2$gb4BPps!&&hbe˖]1J2JKK)--eMzP!\0Ɍ: "Q\]\F/ >.HQM&?ĄP]Wݳ>QD"vKO&##~3ǽf%hj(JJJJ #F`ذa[ojժkj/Sr,[RN>ͩS8uGOs[7c)C֯kLfO?\c=v-).̸g-˶C aƌ1Dm ӻkZ2339y$wf-lٹ Bˆ`Um&R[[˝s$$rhoo詣ܿ7o1116{\]]7nƍ㩧"++;vk.3IH':ܹs̛>Ȱki(,+/>~BCťfȑlڴ{s*M+zLlݺwkmScX. J5k3gD&t#͋/Ȯ]ؿ?uePᅞgzLeeeT*^O NÞ{P5r9gذalڴ g=^k֬//a4OF.Ξ=4Uŝ D&>Bo:mƶnU5رwjP{9jjRHMM4դc4khll5*<<kRXX[?fc^IZDmv fQ^[X,D"b`28qNGlT,6 6a{z^W_58ͻ6c23f aaa$$$n2ŏEGFHRU˥R)nnn 9,3y;vT¯AWbVpD"{{{[>7|D¬DW..BhQF-m- BL6nو ˖-CPٳS[[˹sDive Nf ĉ?6%o f.\ MD _2[TUC%%Q58}B#Gp BCDGX lϊ+HIqx^ Fɛo/k֯a㖍6Lm5l$,,DD8>^K"""x cÖ |.K;ٳg6qiS^nX?W_ߟֲ^[gvQ7׌-:ƪVkM^ˋUةc6OLlݺ))ș9{7}ggg/_NppM!f8;;ƻop&Mu9_|b׋.?_k^C*?([tCşg2)z6WLn̚6f-fh}Y%sqpmgEƿl1ڤ^[gʢ9JXO^Qg]eܸq̞=<> /cn̵lY6LTTıʦ`4(J^|Ea8zB/RdW4zɑ#G.bVV:V22BSK=-QрlŠVdghx饗'(++l[CCCW|Z[[VDEEЀ3!!'҉g᭷DF k[5M FCZj"w?;>=~8бo{UMvqi-Q5(8W mUmM-MMZZ ]ii)jM6 MV)JU\.CxL<<<8㽽'//}&HniWLiy)'NtlGNQ(L8RQt9Suu5!L)ލA]LaWeԣxxx0j([5jW\LRn/567r)));rRRR8WyF[# )8 n[33HNN%yR6j]/>:8F:w^RFvDGG}@tt4odwgjjiÇu̠kD"aVNxj+.p&{]vrԟetF)c nկ'N0ng2h Gyj---رؘX&Exp8* }hTՊ0X( tzF\x%z/sqssw72w\G߿ocߏROw׽q9}4jJz=^Y0jRTVmm0x`ˊZo%R"t 5u5`bccڔn9ud**+p8 J猤^?,lƌChp(< GVgt׼L6ā-Z}O:N&d2)___d2G&ɄR%K:AJ9Fn&;{ݻ;+v=2YVJp`(J,͸"v=2;Lff\ڭ8;; vs?ՙ#1ͻ #XVv(:ǎ&->>vgРA322 Ֆ^Ju,IU/T"8;:-<dO;W~ '-;;VUY])߉ zZZNr;GNXai!7 IUU599446͂ iZ[[5kVGnnn8vjʸD=JP(_ScAxh8GE&,'>߉ըUde#dV#F9lhh%lII`t8S}:SgPcƦjL&j4&DȤRll[y]\OlT&YXim᪯dxvp}QVV]ogKg5PtbF )"dVV}:ӠAƮn,1 ^VHr^!: ll[yF:F)??Ɩ8]129g?3IR$ݎL|CaaMq` a[-rՊ+-:A"Ō(n;b1[̨Dp& jQj3z jz=VZ-mmmRt:Z[n6)--eMCQ1htQ'Nh2bZt:B0{l$ILDXV]FTH(MyM9OL[nBTFM7 h4dee1vX舀>}]j;FRRnn·:FD~IK`MC9{ȐHՓ~'F3PkԔה[AAAFEjj*7nߠUʄD"Js /z-.ӧd$ݔdkSq3UVWԘBx[oL&پc:#HvdHNLFדkkSzmm`QH׾)㤞:uƖ8 :sut%nFդ< i(RqtpiR)CojkSL!!!XV*kŕ!CÐ!v!\L5Lod6A/rAL&o\L{4}tiWIF'{E*2}b?ud2]L> ONzz:--hii!==W>t9T*%88sU簴֙fbXS딃bX9iMeޠVt˔Sٳ֦8ك\.g)6E4CXXVӧ̜LE5TQSAxIem%!^XJ$=+U&M2Bee%RjEUj0rHT&Olt \]] @QQ^^^h4rA}ty[(,-$<8\jnOޠMFe]Ujt,^RoeщEf!Js Nhۅ/:L&_@wy.5}'\Gj2Y$ald41uTQԓ~'VsAk'... 4<&(C"==ݑ:bCσڟsQCb4-8Tͣnz0Q7_4/\LII9}nƧGPrqVqpXV?Rd|x[c.r8J;ҙcillttx<g-E$ˉNk 3i$R)Ǐ)Ǐ#J4;o흋 :, }m(||?J**7 婨a9W%7̜8Tʞ={N ʞ={J̜"~%)&&///<&? #&P[[Kf;̤ #&/Z=rIgH$?:^"dٸsF}>' ՝ٓfڜk% Jô>380w\t:EEE6ǁ9NcԹ&aJw\֙bcc ǴEac ‘'++0 cks M7ݤpssϜ9Cvv6SM!8#iG >>̟?_PvZ:t:“w8];(((@.#l%jcHMCJBCE@H͛/Y߰cۯ%]°AD6f(́L1Nrz}_;ʢzKp;@6mڄl(r|455c9tP$2tPvmp;#,8ʑ8u7o&,8[svt]wiٵoW_sHR1ά\RTwGcc#VỴ=T&lޟqHR\xghii9kO{{;o6---</tL!!!?GjRMׄi1k,kksnh>35y&oOk.3[vlm{)Y""ٽ{͹!ٽ{79a<Г6WL~;|sotP*7իW?ڤ5k7 MU9?0U5Ul۹m+d?Vr [tCΪ߿q'K*O<J?yYpvxH8P(XlZfŊ( ^넇{h_L{߽RMzAуˋA^{[t]rYڋ1(j-;D-?HRg0ib|"Z'f3ӟؿx_bҗIKI}(gaTTUMyoʕ+ٸqMXV6lUp;Y}$440vX' VPWWdž  `J뾒))',( Dש :Y'h5x{{ĨQ;N' @G.3*ݷoӦ{>o>&M$*?==%%%Rp %1ۤ(mU 꾿unt(.#*$4:FMyMUjZn%]/OCC3'$8@Xl7E$3cA&G-+? t91&vP^SbnVQw}m/gyFG{LTСCinnt|KK ;wDRsqrrV؀•8U- >V`4/v}\&YE5޽{u`O= g4NrB)*j\.pRjY̽se˞-+w[oeܸqjM&NNNxxBЉB찝(i<==ER)J\]]1 W"9!Yg 9!ؘX%?%""9spMQ+VlvMUUrgp;Q*rUǂ ؼy3[wm\+ls=pQ֮]Kdd$g&44& VL{L?S2[RU9 HMMew:~*+xX8cN닟+EEE>| 6Rp;1c LWL E;'w-;~TRwqqU̙3Ç`f͚%z ۖw߱c f̺y^WLG&11cɰ!2'x7mیYɡCdddb Fȑ#1bܵ%Z NjRYYIzz:'OɓvrƎ:a*..|GB\5sPn;K](r˛{o{ou:sSY8s 'O:V.sibbb8p 111DFF憳Otjh4h4())Ү.GBrR2IIUk7CP+@YYG^\!#""///VuōVfy%yj4`0hlp<‹iuZ*+.-n`q0YLTTUPVQF"*+8{lmHRJ%?PPQTx{z?(DEDDp%s`mb4/~PtUMƖFQ!;?_Hnb4z&, rggD\\\ okÇgaߑ}^+z▓r5etqv/7:TV-<ѦNd0q6{ $3]QI0[̨5j5m6&#fلld6Ѧm \\&$w_T*p77R)'N0(cc^KC - Hߤ7tu-NL4E5u5|{[f3!!4:m)lx{z 7M2$ r˼yD5v F?|>y="H\٢ tS?@@ŌF!$@VCCc( tLjz'WQF"-Lެ'~P|ǚf]D>ᴵ n'ՍP[Q<;CI& /PP\Gz)l~_1p@[sE:?7Ņͻ6SXVM:ǨԬ`Jg}VTr[y '1o<2)*k+Y}/y m+lI@@ ,l1Uy}/s()))̞= $22YfjQk}ټ;f&"##ylm(3V}LLc FGΡC{?YTw{sB륙r1pMMM]ɄԵ'**sY>Cu%44 t4[UhokEסj>uhZQx~b^KSkz^Mۆ"u  J xg;dt:Suo:F՜;!vZZțdׯa[kjjHKKe`]] .rr26l ==}'\ ֤LF5htOxcK#FQTȊhr3]j[|yq>hj=%{H$q|}}b~Ig|mUWp}t%زe s?P[_kkFդ#/3 H$Lϙ~!>,99̽o.8?ao؉=O4ڎ0vL7|3slھca0x_qF"""XjUU1 vLm6:?y7$$$p& ,[yH=ʈ#Xr%AAAW---(OQ^Bk> wuw׿m1vsw:S|<ϟϫzձvI75fMۆL&v]{QFæMH=J~I>Q"C#mm:B}ڋO>d^4 IDAT.EmmsGwk~גvk;Zo}O~/O<3gΤ^UϊVsNGL#?C{:t(k֬f?9=LZՊT*ElLNNv@h#G0~xQDsqFq%Ѻ:OKK |5|A$wUEըBo!hqU#4P\fۊ Ɖ+&~PsD)ֶV8BgggƍGlll:JEUUQQQ9wG!80 W}ꪈ |yr spssʣ ~HҥK;2'e˖+\6^z%>vIә0z-467}G褹22a` 7{a4b}:9`߾}z뭂9rddtI6=Gp-}ܢ\r sjWӼ_Κ5k`=׼ͺmpOGd'k'駟H=(jo =HHH믿DEEqQx5V[X,ڷxG{*~im'9:I薈3T*?yB4i/"YYYl߾Ͽ{vpmpB=9Hظe#r.\ȓO>Idd߭644pR^t}9S')))yر׳Xz&ȭn%91Dbk3s} ^7K,ZRQQA`͞}IgTT*^z+fb޽l߾~‚XpL~FM} y/gcZ8p > ."Pojdꄩ6i;8;;3o<͛GQQ;v~n:n{3 \of%L:iӨ`„ ,^'|jەȞP{g9 bҥ,Y}vǾC&%1ĸDbpwUtN9ALt*| 8K2c$//A1/ʷ5֊GGuʙ:qvvfΜ9̙3>gG>$ a$%H8= B^QgIL뵨(RRRHNN&66o+[ߓ@c۝3[IHHd2ݘsbbb;:u*|$??g3 <(3Emv#( *5Qc&&L&VfKM}Su$JʹKL2NQǕqH\EPihz?##qThT9>{|MOO,IHH !!UVrhmmz6Pbiln$&*h#*v0E}o/pݫ%)) W\!=%'^׍&@TAFF6lj҂N.zzzi)648ZC㖎gz/v}:8<ϱm8 51}套^bS9===06亘bbbP$$$ؗ.]&zD+WJdbN>Maaimm-.at:Vx160L2::dl6t:A&]J&88J?Fhh-)((7deeI]vPIqz=$%%q. .&3-چZZ ;{;KDdn\Awv\47GNN.Urrc޽oJzƱuV s t:>Nǎ;Dr\L&L&:?O~x< $44to[l4+v裏}~ws?"#9߬.\-)dO{z꿾Jxx8 oeT* '<}&>FW_8 8[k ޳%ܒ[ I.&_N=:n$TUUǜ9ݔ[r(d|vX7/'"00p$YL2>ɓ'Xx4to:$s @Z6|CgYL2>E}}=zdϦCn9>,&'VO\sroBd1*Ncǎ1'aٹݜxa5aG_b%v}< Vk_fM@DDhsY^e21%%%YFRVJ$egmiid2pB1&*IadbN8A~~X1JJJϟ?޽{9&aMs{3tzW;$2jU-%"k>vmml޼񥆆.ULL7ސdtmjjd lL{{;< '\.-Ztk^?θ8zAd?LUh'T9]VcD9rp%vnAOfҭoa@NVCC|=y m|#ϟϯlٲŭ =\',,Lnbf͚Err$xTT  )&(()SV}jN(&o~l6}6$C l $<4\4@bgǢMԲd?6g}{&wߥ_̂y IsɟشiӄbڵZ xvKfQZV… IKKp}YL2GRZZJfj&?N{i)~Qje17.^G}'quăhhOEE 䵟FxXt7IA=GJ|r22 b甖?&y\?OEbݻ={ c?<n7%'JHMM[=PZZ6AAd¾~Pb_ThM]cXغu+ϟ'+-khB&A<{NR,&A-9քncÆ 7&Be4U;wDш68d?+W+yCKK G[QWWFӉtFp#NF&Iﻩijj?A`׮]OBTk(XP@}s:^}/#m.!--cGq ?˵HNN돎bX0 d&ʕ+W>|ÇJnn. ,@}ھ>-dbhhHtlb`ZEl6ArdbfNStl}̫x;z=| ===D̊`yrZ  toݢ֨ DoOXXɢ|_Ը֭[')0jk8s gΜa֬Ydgg}n&ILjtEXVxEsUVZ%:ȑ#^ZRLII&''1۞՝N'Νxi11K-ހj #M;E:K[R @KW K.ҭCׯԇ?x)&*KV~zZ;ZnR%*++$*2y^aEF̑åK8uD̊`deQ]_=ͻ'NV$==}}oZ (HKJ#-)MmkӜ>}4OLYYu 6`9*5vӝ.M6qʕI}Ǵ???ҲJB5PPMW_}L~a-[&i@f򴵵qiP)UAj6>M6qy0 S?8l{=qb2 mm} {㰑 .PUSšC8tMIRRZdFFF$%ܘ 8Njjj8{,TWW=˦'6QTPD‚As禳SJO_xIYČӭc+ٴ;CKUTTq/^ٳb .iiiBZZ)))V(`:멫]v\QOG|ϏAزewӗUO^{No_/=tvwr]=]8'UUU9s/_fϞ=LHHȸ>YV(//N7fppp\̜9hl\ԤTrsEi*T]lYXd=^  )PZ\/5ow1_;FWYFzdfITDA'x<Igw']=]=T_|ַKDaa!˖-eLYY_EMFN8R͙3DZm6I:_/))ảCCL&S%YW6; Q FŊQz-fo`2f n_V5nѝz5ͤƉO? דMFk kI3âyD.IbI~v+?<-bhjiG?x7%K\-&]eKx7eǎeQ رc\R$w:xYr}Wbh\Ko/--Yu[I恥KEkW+l۶ߧby 1[|#</={}ߦ,&}_$&&2)ٮ|$@a6z{.L2 vmmKE^^}dN,X 9۽@̌)8ٹg'm]m̟?5kYxǢECCCE6?Icb8.\Dv}O7 d1GŅ v~ALtt4]]]ݴ;"IgaQXK`` 7ofڵ(JIy YL2ӎagϑ=uBM~PO&MFtl)8%H:{;ƋOv91:(IW,>fa:fEoУSBJJmͥn %y$II*79wwO6l;Cjꝳl6|Mz-m]2/;;_Wz:ľ}8Uy/ʿ,{dLXa2 >vZ ,{=V^=ͻgLDtt4[la˖-qAOٙ2N>ϯ(.,f8n=4jў' ~+Vt:(!4 / /ˁؿ?Oc(JY*Z%ѣagsh~o(iiifs|fh<>>^z^zn֭[)*.ZJqa1 -#ILL_`0xb9qΞS̎]2S3}bNWn]7+'tt+7IqqQyyz{{9N@k׮XTӍ\}:ha0+8לgDGEAFJ$%~f6Py~5X0%U|PQb2eJo~iooB9uhAjRdd2'hfG:;5qIۚinmj-IDATfxdxaaa^K2|J%gΜ_R>-/RcΜ9$&zHFhook7׏Ө5@dx$" :5fEHʎ4S0[tuFkW+jj/'##tZ|f*"y+ߊw8dDD,Z䭟t:줻hKQ 4$1EΊ$(( 6-xsIbHZ0b  y_H),,$??'(v}nrM W2CibQvd1 Oҗc2$nj1?iiicjkkddd0440whj^::H߻ {?UOw7*~VT^Vn7 i)8--8MG q6ՎkB 44ظX"""!)) VKHHYrY] VCu=>4Un2۱l(4=--/((F#ҢLKKsIXkkVuKrK9zO@@hjU8NFcn7 (\.NSa6* sEDNSWMėMC!Q(Rn+f͚T*JGT2`0EFF{!j'<<\l ɤ<~)))Pkk_jj)b(l6mmmC"x0IENDB`freetype-py-2.5.1/doc/tt_name_ids.rst0000664000175000017500000000162314664131406017764 0ustar georgeskgeorgeskTT_NAME_IDS =========== Possible values of the 'name' identifier field in the name records of the TTF 'name' table. These values are platform independent. .. data:: TT_NAME_ID_COPYRIGHT .. data:: TT_NAME_ID_FONT_FAMILY .. data:: TT_NAME_ID_FONT_SUBFAMILY .. data:: TT_NAME_ID_UNIQUE_ID .. data:: TT_NAME_ID_FULL_NAME .. data:: TT_NAME_ID_VERSION_STRING .. data:: TT_NAME_ID_PS_NAME .. data:: TT_NAME_ID_TRADEMARK .. data:: TT_NAME_ID_MANUFACTURER .. data:: TT_NAME_ID_DESIGNER .. data:: TT_NAME_ID_DESCRIPTION .. data:: TT_NAME_ID_VENDOR_URL .. data:: TT_NAME_ID_DESIGNER_URL .. data:: TT_NAME_ID_LICENSE .. data:: TT_NAME_ID_LICENSE_URL .. data:: TT_NAME_ID_PREFERRED_FAMILY .. data:: TT_NAME_ID_PREFERRED_SUBFAMILY .. data:: TT_NAME_ID_MAC_FULL_NAME .. data:: TT_NAME_ID_SAMPLE_TEXT .. data:: TT_NAME_ID_CID_FINDFONT_NAME .. data:: TT_NAME_ID_WWS_FAMILY .. data:: TT_NAME_ID_WWS_SUBFAMILY freetype-py-2.5.1/doc/license.rst0000664000175000017500000000275414664131406017126 0ustar georgeskgeorgeskLicense ======= Copyright (c) 2011-2014, Nicolas P. Rougier - All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the freetype-py Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. freetype-py-2.5.1/doc/stroker.rst0000664000175000017500000000012114664131406017157 0ustar georgeskgeorgesk.. currentmodule:: freetype Stroker ======= .. autoclass:: Stroker :members: freetype-py-2.5.1/doc/ft_load_flags.rst0000664000175000017500000001000714664131406020256 0ustar georgeskgeorgeskFT_LOAD_FLAGS ============= A list of bit-field constants used with FT_Load_Glyph to indicate what kind of operations to perform during glyph loading. .. data:: FT_LOAD_DEFAULT Corresponding to 0, this value is used as the default glyph load operation. In this case, the following happens: 1. FreeType looks for a bitmap for the glyph corresponding to the face's current size. If one is found, the function returns. The bitmap data can be accessed from the glyph slot (see note below). 2. If no embedded bitmap is searched or found, FreeType looks for a scalable outline. If one is found, it is loaded from the font file, scaled to device pixels, then 'hinted' to the pixel grid in order to optimize it. The outline data can be accessed from the glyph slot (see note below). Note that by default, the glyph loader doesn't render outlines into bitmaps. The following flags are used to modify this default behaviour to more specific and useful cases. .. data:: FT_LOAD_NO_SCALE Don't scale the outline glyph loaded, but keep it in font units. This flag implies FT_LOAD_NO_HINTING and FT_LOAD_NO_BITMAP, and unsets FT_LOAD_RENDER. .. data:: FT_LOAD_NO_HINTING Disable hinting. This generally generates 'blurrier' bitmap glyph when the glyph is rendered in any of the anti-aliased modes. See also the note below. This flag is implied by FT_LOAD_NO_SCALE. .. data:: FT_LOAD_RENDER Call FT_Render_Glyph after the glyph is loaded. By default, the glyph is rendered in FT_RENDER_MODE_NORMAL mode. This can be overridden by FT_LOAD_TARGET_XXX or FT_LOAD_MONOCHROME. This flag is unset by FT_LOAD_NO_SCALE. .. data:: FT_LOAD_NO_BITMAP Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag. FT_LOAD_NO_SCALE always sets this flag. .. data:: FT_LOAD_VERTICAL_LAYOUT Load the glyph for vertical text layout. Don't use it as it is problematic currently. .. data:: FT_LOAD_FORCE_AUTOHINT Indicates that the auto-hinter is preferred over the font's native hinter. See also the note below. .. data:: FT_LOAD_CROP_BITMAP Indicates that the font driver should crop the loaded bitmap glyph (i.e., remove all space around its black bits). Not all drivers implement this. .. data:: FT_LOAD_PEDANTIC Indicates that the font driver should perform pedantic verifications during glyph loading. This is mostly used to detect broken glyphs in fonts. By default, FreeType tries to handle broken fonts also. .. data:: FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH Indicates that the font driver should ignore the global advance width defined in the font. By default, that value is used as the advance width for all glyphs when the face has FT_FACE_FLAG_FIXED_WIDTH set. This flag exists for historical reasons (to support buggy CJK fonts). .. data:: FT_LOAD_NO_RECURSE This flag is only used internally. It merely indicates that the font driver should not load composite glyphs recursively. Instead, it should set the 'num_subglyph' and 'subglyphs' values of the glyph slot accordingly, and set 'glyph->format' to FT_GLYPH_FORMAT_COMPOSITE. The description of sub-glyphs is not available to client applications for now. This flag implies FT_LOAD_NO_SCALE and FT_LOAD_IGNORE_TRANSFORM. .. data:: FT_LOAD_IGNORE_TRANSFORM Indicates that the transform matrix set by FT_Set_Transform should be ignored. .. data:: FT_LOAD_MONOCHROME This flag is used with FT_LOAD_RENDER to indicate that you want to render an outline glyph to a 1-bit monochrome bitmap glyph, with 8 pixels packed into each byte of the bitmap data. Note that this has no effect on the hinting algorithm used. You should rather use FT_LOAD_TARGET_MONO so that the monochrome-optimized hinting algorithm is used. .. data:: FT_LOAD_LINEAR_DESIGN Indicates that the 'linearHoriAdvance' and 'linearVertAdvance' fields of FT_GlyphSlotRec should be kept in font units. See FT_GlyphSlotRec for details. .. data:: FT_LOAD_NO_AUTOHINT Disable auto-hinter. See also the note below. freetype-py-2.5.1/doc/bbox.rst0000664000175000017500000000011014664131406016416 0ustar georgeskgeorgesk.. currentmodule:: freetype BBox ==== .. autoclass:: BBox :members: freetype-py-2.5.1/doc/tt_adobe_ids.rst0000664000175000017500000000057514664131406020123 0ustar georgeskgeorgeskTT_ADOBE_IDS ============ A list of valid values for the 'encoding_id' for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! .. data:: TT_ADOBE_ID_STANDARD Adobe standard encoding. .. data:: TT_ADOBE_ID_EXPERT Adobe expert encoding. .. data:: TT_ADOBE_ID_CUSTOM Adobe custom encoding. .. data:: TT_ADOBE_ID_LATIN_1 Adobe Latin 1 encoding. freetype-py-2.5.1/doc/bitmap_glyph.rst0000664000175000017500000000013714664131406020154 0ustar georgeskgeorgesk.. currentmodule:: freetype Bitmap glyph ============ .. autoclass:: BitmapGlyph :members: freetype-py-2.5.1/doc/tt_mac_langids.rst0000664000175000017500000001033514664131406020446 0ustar georgeskgeorgeskTT_MAC_LANGIDS ============== Possible values of the language identifier field in the name records of the TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MACINTOSH. .. data:: TT_MAC_LANGID_LATIN .. data:: TT_MAC_LANGID_MALAY_ARABIC_SCRIPT .. data:: TT_MAC_LANGID_HINDI .. data:: TT_MAC_LANGID_CATALAN .. data:: TT_MAC_LANGID_MARATHI .. data:: TT_MAC_LANGID_ICELANDIC .. data:: TT_MAC_LANGID_ARABIC .. data:: TT_MAC_LANGID_SWAHILI .. data:: TT_MAC_LANGID_KHMER .. data:: TT_MAC_LANGID_UKRAINIAN .. data:: TT_MAC_LANGID_FINNISH .. data:: TT_MAC_LANGID_POLISH .. data:: TT_MAC_LANGID_NEPALI .. data:: TT_MAC_LANGID_UZBEK .. data:: TT_MAC_LANGID_TELUGU .. data:: TT_MAC_LANGID_MALTESE .. data:: TT_MAC_LANGID_AFRIKAANS .. data:: TT_MAC_LANGID_CHEWA .. data:: TT_MAC_LANGID_BASQUE .. data:: TT_MAC_LANGID_CZECH .. data:: TT_MAC_LANGID_ROMANIAN .. data:: TT_MAC_LANGID_QUECHUA .. data:: TT_MAC_LANGID_TAGALOG .. data:: TT_MAC_LANGID_HUNGARIAN .. data:: TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT .. data:: TT_MAC_LANGID_TONGAN .. data:: TT_MAC_LANGID_SUNDANESE .. data:: TT_MAC_LANGID_JAPANESE .. data:: TT_MAC_LANGID_MONGOLIAN .. data:: TT_MAC_LANGID_ALBANIAN .. data:: TT_MAC_LANGID_NORWEGIAN .. data:: TT_MAC_LANGID_SLOVAK .. data:: TT_MAC_LANGID_MALAGASY .. data:: TT_MAC_LANGID_DZONGKHA .. data:: TT_MAC_LANGID_DUTCH .. data:: TT_MAC_LANGID_MALAY_ROMAN_SCRIPT .. data:: TT_MAC_LANGID_SERBIAN .. data:: TT_MAC_LANGID_GERMAN .. data:: TT_MAC_LANGID_SOMALI .. data:: TT_MAC_LANGID_KOREAN .. data:: TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT .. data:: TT_MAC_LANGID_CROATIAN .. data:: TT_MAC_LANGID_TURKISH .. data:: TT_MAC_LANGID_MOLDAVIAN .. data:: TT_MAC_LANGID_LAO .. data:: TT_MAC_LANGID_ORIYA .. data:: TT_MAC_LANGID_BRETON .. data:: TT_MAC_LANGID_PASHTO .. data:: TT_MAC_LANGID_GUARANI .. data:: TT_MAC_LANGID_HEBREW .. data:: TT_MAC_LANGID_SLOVENIAN .. data:: TT_MAC_LANGID_ESTONIAN .. data:: TT_MAC_LANGID_RUNDI .. data:: TT_MAC_LANGID_URDU .. data:: TT_MAC_LANGID_CHINESE_TRADITIONAL .. data:: TT_MAC_LANGID_TATAR .. data:: TT_MAC_LANGID_CHINESE_SIMPLIFIED .. data:: TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT .. data:: TT_MAC_LANGID_SANSKRIT .. data:: TT_MAC_LANGID_KURDISH .. data:: TT_MAC_LANGID_FAEROESE .. data:: TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT .. data:: TT_MAC_LANGID_TIGRINYA .. data:: TT_MAC_LANGID_THAI .. data:: TT_MAC_LANGID_DANISH .. data:: TT_MAC_LANGID_KAZAKH .. data:: TT_MAC_LANGID_YIDDISH .. data:: TT_MAC_LANGID_ESPERANTO .. data:: TT_MAC_LANGID_LITHUANIAN .. data:: TT_MAC_LANGID_FARSI .. data:: TT_MAC_LANGID_LETTISH .. data:: TT_MAC_LANGID_VIETNAMESE .. data:: TT_MAC_LANGID_PORTUGUESE .. data:: TT_MAC_LANGID_IRISH .. data:: TT_MAC_LANGID_WELSH .. data:: TT_MAC_LANGID_PUNJABI .. data:: TT_MAC_LANGID_GREEK .. data:: TT_MAC_LANGID_INUKTITUT .. data:: TT_MAC_LANGID_FRENCH .. data:: TT_MAC_LANGID_GREEK_POLYTONIC .. data:: TT_MAC_LANGID_AZERBAIJANI .. data:: TT_MAC_LANGID_JAVANESE .. data:: TT_MAC_LANGID_SWEDISH .. data:: TT_MAC_LANGID_UIGHUR .. data:: TT_MAC_LANGID_BENGALI .. data:: TT_MAC_LANGID_RUANDA .. data:: TT_MAC_LANGID_SINDHI .. data:: TT_MAC_LANGID_TIBETAN .. data:: TT_MAC_LANGID_ENGLISH .. data:: TT_MAC_LANGID_SAAMISK .. data:: TT_MAC_LANGID_INDONESIAN .. data:: TT_MAC_LANGID_MANX_GAELIC .. data:: TT_MAC_LANGID_BYELORUSSIAN .. data:: TT_MAC_LANGID_BULGARIAN .. data:: TT_MAC_LANGID_GEORGIAN .. data:: TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT .. data:: TT_MAC_LANGID_ITALIAN .. data:: TT_MAC_LANGID_SCOTTISH_GAELIC .. data:: TT_MAC_LANGID_ARMENIAN .. data:: TT_MAC_LANGID_GALLA .. data:: TT_MAC_LANGID_MACEDONIAN .. data:: TT_MAC_LANGID_IRISH_GAELIC .. data:: TT_MAC_LANGID_KIRGHIZ .. data:: TT_MAC_LANGID_TAMIL .. data:: TT_MAC_LANGID_SPANISH .. data:: TT_MAC_LANGID_BURMESE .. data:: TT_MAC_LANGID_KANNADA .. data:: TT_MAC_LANGID_GALICIAN .. data:: TT_MAC_LANGID_FLEMISH .. data:: TT_MAC_LANGID_TAJIKI .. data:: TT_MAC_LANGID_ASSAMESE .. data:: TT_MAC_LANGID_SINHALESE .. data:: TT_MAC_LANGID_GREELANDIC .. data:: TT_MAC_LANGID_AMHARIC .. data:: TT_MAC_LANGID_KASHMIRI .. data:: TT_MAC_LANGID_AYMARA .. data:: TT_MAC_LANGID_GUJARATI .. data:: TT_MAC_LANGID_RUSSIAN .. data:: TT_MAC_LANGID_TURKMEN .. data:: TT_MAC_LANGID_MALAYALAM freetype-py-2.5.1/doc/glyph_slot.rst0000664000175000017500000000013114664131406017653 0ustar georgeskgeorgesk.. currentmodule:: freetype Glyph slot ========== .. autoclass:: GlyphSlot :members: freetype-py-2.5.1/doc/ft_render_modes.rst0000664000175000017500000000263014664131406020634 0ustar georgeskgeorgeskFT_RENDER_MODES =============== An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. For bitmap fonts and embedded bitmaps the 'bitmap->pixel_mode' field in the .. data:: FT_GlyphSlotRec structure gives the format of the returned bitmap. All modes except FT_RENDER_MODE_MONO use 256 levels of opacity. .. data:: FT_RENDER_MODE_NORMAL This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps. .. data:: FT_RENDER_MODE_LIGHT This is equivalent to FT_RENDER_MODE_NORMAL. It is only defined as a separate value because render modes are also used indirectly to define hinting algorithm selectors. See FT_LOAD_TARGET_XXX for details. .. data:: FT_RENDER_MODE_MONO This mode corresponds to 1-bit bitmaps (with 2 levels of opacity). .. data:: FT_RENDER_MODE_LCD This mode corresponds to horizontal RGB and BGR sub-pixel displays like LCD screens. It produces 8-bit bitmaps that are 3 times the width of the original glyph outline in pixels, and which use the FT_PIXEL_MODE_LCD mode. .. data:: FT_RENDER_MODE_LCD_V This mode corresponds to vertical RGB and BGR sub-pixel displays (like PDA screens, rotated LCD displays, etc.). It produces 8-bit bitmaps that are 3 times the height of the original glyph outline in pixels and use the FT_PIXEL_MODE_LCD_V mode. freetype-py-2.5.1/doc/ft_open_modes.rst0000664000175000017500000000073114664131406020316 0ustar georgeskgeorgeskFT_OPEN_MODES ============= A list of bit-field constants used within the 'flags' field of the .. data:: FT_Open_Args structure. .. data:: FT_OPEN_MEMORY This is a memory-based stream. .. data:: FT_OPEN_STREAM Copy the stream from the 'stream' field. .. data:: FT_OPEN_PATHNAME Create a new input stream from a C path name. .. data:: FT_OPEN_DRIVER Use the 'driver' field. .. data:: FT_OPEN_PARAMS Use the 'num_params' and 'params' fields. freetype-py-2.5.1/doc/ft_lcd_filters.rst0000664000175000017500000000212014664131406020452 0ustar georgeskgeorgeskFT_LCD_FILTERS ============== A list of values to identify various types of LCD filters. .. data:: FT_LCD_FILTER_NONE Do not perform filtering. When used with subpixel rendering, this results in sometimes severe color fringes. .. data:: FT_LCD_FILTER_DEFAULT The default filter reduces color fringes considerably, at the cost of a slight blurriness in the output. .. data:: FT_LCD_FILTER_LIGHT The light filter is a variant that produces less blurriness at the cost of slightly more color fringes than the default one. It might be better, depending on taste, your monitor, or your personal vision. .. data:: FT_LCD_FILTER_LEGACY This filter corresponds to the original libXft color filter. It provides high contrast output but can exhibit really bad color fringes if glyphs are not extremely well hinted to the pixel grid. In other words, it only works well if the TrueType bytecode interpreter is enabled and high-quality hinted fonts are used. This filter is only provided for comparison purposes, and might be disabled or stay unsupported in the future. freetype-py-2.5.1/doc/ft_stroker_borders.rst0000664000175000017500000000133314664131406021376 0ustar georgeskgeorgeskFT_STROKER_BORDERS ================== These values are used to select a given stroke border in .. data:: FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder. .. data:: FT_STROKER_BORDER_LEFT Select the left border, relative to the drawing direction. .. data:: FT_STROKER_BORDER_RIGHT Select the right border, relative to the drawing direction. Note Applications are generally interested in the 'inside' and 'outside' borders. However, there is no direct mapping between these and the 'left' and 'right' ones, since this really depends on the glyph's drawing orientation, which varies between font formats. You can however use FT_Outline_GetInsideBorder and FT_Outline_GetOutsideBorder to get these. freetype-py-2.5.1/doc/size_metrics.rst0000664000175000017500000000013714664131406020175 0ustar georgeskgeorgesk.. currentmodule:: freetype Size Metrics ============ .. autoclass:: SizeMetrics :members: freetype-py-2.5.1/doc/ft_glyph_formats.rst0000664000175000017500000000240414664131406021043 0ustar georgeskgeorgeskFT_GLYPH_FORMATS ================ An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format. .. data:: FT_GLYPH_FORMAT_NONE The value 0 is reserved. .. data:: FT_GLYPH_FORMAT_COMPOSITE The glyph image is a composite of several other images. This format is only used with FT_LOAD_NO_RECURSE, and is used to report compound glyphs (like accented characters). .. data:: FT_GLYPH_FORMAT_BITMAP The glyph image is a bitmap, and can be described as an FT_Bitmap. You generally need to access the 'bitmap' field of the FT_GlyphSlotRec structure to read it. .. data:: FT_GLYPH_FORMAT_OUTLINE The glyph image is a vectorial outline made of line segments and Bezier arcs; it can be described as an FT_Outline; you generally want to access the 'outline' field of the FT_GlyphSlotRec structure to read it. .. data:: FT_GLYPH_FORMAT_PLOTTER The glyph image is a vectorial path with no inside and outside contours. Some Type 1 fonts, like those in the Hershey family, contain glyphs in this format. These are described as FT_Outline, but FreeType isn't currently capable of rendering them correctly. freetype-py-2.5.1/doc/tt_apple_ids.rst0000664000175000017500000000120514664131406020141 0ustar georgeskgeorgeskTT_APPLE_IDS ============ A list of valid values for the 'encoding_id' for TT_PLATFORM_APPLE_UNICODE charmaps and name entries. .. data:: TT_APPLE_ID_DEFAULT Unicode version 1.0. .. data:: TT_APPLE_ID_UNICODE_1_1 Unicode 1.1; specifies Hangul characters starting at U+34xx. .. data:: TT_APPLE_ID_ISO_10646 Deprecated (identical to preceding). .. data:: TT_APPLE_ID_UNICODE_2_0 Unicode 2.0 and beyond (UTF-16 BMP only). .. data:: TT_APPLE_ID_UNICODE_32 Unicode 3.1 and beyond, using UTF-32. .. data:: TT_APPLE_ID_VARIANT_SELECTOR From Adobe, not Apple. Not a normal cmap. Specifies variations on a real cmap. freetype-py-2.5.1/doc/ft_glyph_bbox_modes.rst0000664000175000017500000000071714664131406021516 0ustar georgeskgeorgeskFT_GLYPH_BBOX_MODES =================== The mode how the values of FT_Glyph_Get_CBox are returned. .. data:: FT_GLYPH_BBOX_UNSCALED Return unscaled font units. .. data:: FT_GLYPH_BBOX_SUBPIXELS Return unfitted 26.6 coordinates. .. data:: FT_GLYPH_BBOX_GRIDFIT Return grid-fitted 26.6 coordinates. .. data:: FT_GLYPH_BBOX_TRUNCATE Return coordinates in integer pixels. .. data:: FT_GLYPH_BBOX_PIXELS Return grid-fitted pixel coordinates. freetype-py-2.5.1/doc/ft_stroker_linejoins.rst0000664000175000017500000000116314664131406021731 0ustar georgeskgeorgeskFT_STROKER_LINEJOINS ==================== These values determine how two joining lines are rendered in a stroker. .. data:: FT_STROKER_LINEJOIN_ROUND Used to render rounded line joins. Circular arcs are used to join two lines smoothly. .. data:: FT_STROKER_LINEJOIN_BEVEL Used to render beveled line joins; i.e., the two joining lines are extended until they intersect. .. data:: FT_STROKER_LINEJOIN_MITER Same as beveled rendering, except that an additional line break is added if the angle between the two joining lines is too closed (this is useful to avoid unpleasant spikes in beveled rendering). freetype-py-2.5.1/doc/constants.rst0000664000175000017500000000113114664131406017504 0ustar georgeskgeorgeskConstants ========= .. toctree:: :maxdepth: 1 ft_encodings.rst ft_face_flags.rst ft_fstypes.rst ft_glyph_bbox_modes.rst ft_glyph_formats.rst ft_kerning_modes.rst ft_lcd_filters.rst ft_load_flags.rst ft_load_targets.rst ft_open_modes.rst ft_outline_flags.rst ft_pixel_modes.rst ft_render_modes.rst ft_stroker_borders.rst ft_stroker_linecaps.rst ft_stroker_linejoins.rst ft_style_flags.rst tt_adobe_ids.rst tt_apple_ids.rst tt_mac_ids.rst tt_mac_langids.rst tt_ms_ids.rst tt_ms_langids.rst tt_name_ids.rst tt_platforms.rst freetype-py-2.5.1/doc/tt_ms_ids.rst0000664000175000017500000000175214664131406017466 0ustar georgeskgeorgeskTT_MS_IDS ========= A list of valid values for the 'encoding_id' for TT_PLATFORM_MICROSOFT charmaps and name entries. .. data:: TT_MS_ID_SYMBOL_CS Corresponds to Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL. .. data:: TT_MS_ID_UNICODE_CS Corresponds to a Microsoft WGL4 charmap, matching Unicode. See FT_ENCODING_UNICODE. .. data:: TT_MS_ID_SJIS Corresponds to SJIS Japanese encoding. See FT_ENCODING_SJIS. .. data:: TT_MS_ID_PRC Corresponds to Simplified Chinese as used in Mainland China. See FT_ENCODING_PRC. .. data:: TT_MS_ID_BIG_5 Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. See FT_ENCODING_BIG5. .. data:: TT_MS_ID_WANSUNG Corresponds to Korean Wansung encoding. See FT_ENCODING_WANSUNG. .. data:: TT_MS_ID_JOHAB Corresponds to Johab encoding. See FT_ENCODING_JOHAB. .. data:: TT_MS_ID_UCS_4 Corresponds to UCS-4 or UTF-32 charmaps. This has been added to the OpenType specification version 1.4 (mid-2001.) freetype-py-2.5.1/doc/ft_encodings.rst0000664000175000017500000000510714664131406020141 0ustar georgeskgeorgeskFT_ENCODINGS ============ An enumeration used to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function. .. data:: FT_ENCODING_NONE The encoding value 0 is reserved. .. data:: FT_ENCODING_UNICODE Corresponds to the Unicode character set. This value covers all versions of the Unicode repertoire, including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them. For example, if you want to access Unicode value U+1F028 (and the font contains it), use value 0x1F028 as the input value for FT_Get_Char_Index. .. data:: FT_ENCODING_MS_SYMBOL Corresponds to the Microsoft Symbol encoding, used to encode mathematical symbols in the 32..255 character code range. For more information, see 'http://www.ceviz.net/symbol.htm'. .. data:: FT_ENCODING_SJIS Corresponds to Japanese SJIS encoding. More info at at 'http://langsupport.japanreference.com/encoding.shtml'. See note on multi-byte encodings below. .. data:: FT_ENCODING_PRC Corresponds to an encoding system for Simplified Chinese as used used in mainland China. .. data:: FT_ENCODING_BIG5 Corresponds to an encoding system for Traditional Chinese as used in Taiwan and Hong Kong. .. data:: FT_ENCODING_WANSUNG Corresponds to the Korean encoding system known as Wansung. For more information see 'http://www.microsoft.com/typography/unicode/949.txt'. .. data:: FT_ENCODING_JOHAB The Korean standard character set (KS C 5601-1992), which corresponds to MS Windows code page 1361. This character set includes all possible Hangeul character combinations. .. data:: FT_ENCODING_ADOBE_LATIN_1 Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript font. It is limited to 256 character codes. .. data:: FT_ENCODING_ADOBE_STANDARD Corresponds to the Adobe Standard encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. .. data:: FT_ENCODING_ADOBE_EXPERT Corresponds to the Adobe Expert encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. .. data:: FT_ENCODING_ADOBE_CUSTOM Corresponds to a custom encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. .. data:: FT_ENCODING_APPLE_ROMAN Corresponds to the 8-bit Apple roman encoding. Many TrueType and OpenType fonts contain a charmap for this encoding, since older versions of Mac OS are able to use it. .. data:: FT_ENCODING_OLD_LATIN_2 This value is deprecated and was never used nor reported by FreeType. Don't use or test for it. freetype-py-2.5.1/doc/ft_fstypes.rst0000664000175000017500000000262214664131406017664 0ustar georgeskgeorgeskFT_FSTYPES ========== A list of bit flags that inform client applications of embedding and subsetting restrictions associated with a font. .. data:: FT_FSTYPE_INSTALLABLE_EMBEDDING Fonts with no fsType bit set may be embedded and permanently installed on the remote system by an application. .. data:: FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING Fonts that have only this bit set must not be modified, embedded or exchanged in any manner without first obtaining permission of the font software copyright owner. .. data:: FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING If this bit is set, the font may be embedded and temporarily loaded on the remote system. Documents containing Preview & Print fonts must be opened 'read-only'; no edits can be applied to the document. .. data:: FT_FSTYPE_EDITABLE_EMBEDDING If this bit is set, the font may be embedded but must only be installed temporarily on other systems. In contrast to Preview & Print fonts, documents containing editable fonts may be opened for reading, editing is permitted, and changes may be saved. .. data:: FT_FSTYPE_NO_SUBSETTING If this bit is set, the font may not be subsetted prior to embedding. .. data:: FT_FSTYPE_BITMAP_EMBEDDING_ONLY If this bit is set, only bitmaps contained in the font may be embedded; no outline data may be embedded. If there are no bitmaps available in the font, then the font is unembeddable. freetype-py-2.5.1/doc/bitmap.rst0000664000175000017500000000011614664131406016746 0ustar georgeskgeorgesk.. currentmodule:: freetype Bitmap ====== .. autoclass:: Bitmap :members: freetype-py-2.5.1/doc/tt_platforms.rst0000664000175000017500000000265614664131406020223 0ustar georgeskgeorgeskTT_PLATFORMS ============ A list of valid values for the 'platform_id' identifier code in FT_CharMapRec and FT_SfntName structures. .. data:: TT_PLATFORM_APPLE_UNICODE Used by Apple to indicate a Unicode character map and/or name entry. See TT_APPLE_ID_XXX for corresponding 'encoding_id' values. Note that name entries in this format are coded as big-endian UCS-2 character codes only. .. data:: TT_PLATFORM_MACINTOSH Used by Apple to indicate a MacOS-specific charmap and/or name entry. See TT_MAC_ID_XXX for corresponding 'encoding_id' values. Note that most TrueType fonts contain an Apple roman charmap to be usable on MacOS systems (even if they contain a Microsoft charmap as well). .. data:: TT_PLATFORM_ISO This value was used to specify ISO/IEC 10646 charmaps. It is however now deprecated. See TT_ISO_ID_XXX for a list of corresponding 'encoding_id' values. .. data:: TT_PLATFORM_MICROSOFT Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for a list of corresponding 'encoding_id' values. Note that most fonts contain a Unicode charmap using (TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS). .. data:: TT_PLATFORM_CUSTOM Used to indicate application-specific charmaps. .. data:: TT_PLATFORM_ADOBE This value isn't part of any font format specification, but is used by FreeType to report Adobe-specific charmaps in an FT_CharMapRec structure. See TT_ADOBE_ID_XXX. freetype-py-2.5.1/doc/conf.py0000664000175000017500000001642414664131406016250 0ustar georgeskgeorgesk# -*- coding: utf-8 -*- # # Freetype/Python documentation build configuration file, created by # sphinx-quickstart on Wed Nov 9 16:29:54 2011. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Freetype python bindings' copyright = u'2011-2014, Nicolas P. Rougier' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.4.1' # The full version, including alpha/beta/rc tags. release = '0.4.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org on_rtd = os.environ.get('READTHEDOCS', None) == 'True' # only import and set the theme if we're building docs locally if not on_rtd: import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # 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'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'FreetypePythondoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'FreetypePython.tex', u'Freetype Python Documentation', u'Nicolas P. Rougier', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'freetypepython', u'Freetype Python Documentation', [u'Nicolas P. Rougier'], 1) ] freetype-py-2.5.1/doc/glyph.rst0000664000175000017500000000011314664131406016612 0ustar georgeskgeorgesk.. currentmodule:: freetype Glyph ===== .. autoclass:: Glyph :members: freetype-py-2.5.1/doc/Makefile0000664000175000017500000001101614664131406016401 0ustar georgeskgeorgesk# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FreetypePython.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FreetypePython.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/FreetypePython" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FreetypePython" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." freetype-py-2.5.1/setup.py0000664000175000017500000001114214664131406015706 0ustar georgeskgeorgesk# ----------------------------------------------------------------------------- # FreeType high-level python API - copyright 2011 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # ----------------------------------------------------------------------------- import distutils import distutils.dir_util import distutils.file_util import os import subprocess import sys from io import open from os import path from setuptools import setup if os.environ.get("FREETYPEPY_BUNDLE_FT"): print("# Will build and bundle FreeType.") from setuptools import Extension from setuptools.command.build_ext import build_ext from wheel.bdist_wheel import bdist_wheel class BdistWheel(bdist_wheel): def get_tag(self): return ('py3', 'none') + bdist_wheel.get_tag(self)[2:] class SharedLibrary(Extension): """Object that describes the library (filename) and how to make it.""" if sys.platform == "darwin": suffix = ".dylib" elif sys.platform == "win32": suffix = ".dll" else: suffix = ".so" def __init__(self, name, cmd, cwd=".", output_dir=".", env=None): Extension.__init__(self, name, sources=[]) self.cmd = cmd self.cwd = path.normpath(cwd) self.output_dir = path.normpath(output_dir) self.env = env or dict(os.environ) class SharedLibBuildExt(build_ext): """Object representing command to produce and install a shared library.""" # Needed to make setuptools and wheel believe they're looking at an # extension instead of a shared library. def get_ext_filename(self, ext_name): for ext in self.extensions: if isinstance(ext, SharedLibrary): return os.path.join(*ext_name.split('.')) + ext.suffix return build_ext.get_ext_filename(self, ext_name) def build_extension(self, ext): if not isinstance(ext, SharedLibrary): build_ext.build_extension(self, ext) return distutils.log.info("running '{}'".format(ext.cmd)) if not self.dry_run: rv = subprocess.Popen( ext.cmd, cwd=ext.cwd, env=ext.env, shell=True).wait() if rv != 0: sys.exit(rv) lib_name = ext.name.split(".")[-1] + ext.suffix lib_fullpath = path.join(ext.output_dir, lib_name) dest_path = self.get_ext_fullpath(ext.name) distutils.dir_util.mkpath( path.dirname(dest_path), verbose=self.verbose, dry_run=self.dry_run) distutils.file_util.copy_file( lib_fullpath, dest_path, verbose=self.verbose, dry_run=self.dry_run) ext_modules = [ SharedLibrary( "freetype.libfreetype", # package.shared_lib_name cmd='"{}" ./setup-build-freetype.py'.format(sys.executable), output_dir="build/local/lib") ] cmdclass = { 'bdist_wheel': BdistWheel, 'build_ext': SharedLibBuildExt } else: print("# Will use the system-provided FreeType.") ext_modules = [] cmdclass = {} description = open( path.join(path.abspath(path.dirname(__file__)), 'README.rst'), encoding='utf-8').read() setup( name='freetype-py', use_scm_version=True, description='Freetype python bindings', long_description=description, author='Nicolas P. Rougier', author_email='Nicolas.Rougier@inria.fr', url='https://github.com/rougier/freetype-py', python_requires=">=3.7", packages=['freetype', 'freetype.ft_enums', 'freetype.__pyinstaller', 'freetype.__pyinstaller.tests'], ext_modules=ext_modules, zip_safe=False if ext_modules else True, cmdclass=cmdclass, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: X11 Applications', 'Environment :: MacOS X', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: MacOS', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', 'Programming Language :: Python :: 3', 'Topic :: Multimedia :: Graphics', ], keywords=['freetype', 'font'], setup_requires=['setuptools_scm'], entry_points={ "pyinstaller40": [ "hook-dirs = freetype.__pyinstaller:get_hook_dirs", "tests = freetype.__pyinstaller:get_test_dirs", ], }, ) freetype-py-2.5.1/setup.cfg0000664000175000017500000000006314664131406016015 0ustar georgeskgeorgesk[bdist_wheel] universal = 0 [sdist] formats = zip freetype-py-2.5.1/tests/0000775000175000017500000000000014664131406015337 5ustar georgeskgeorgeskfreetype-py-2.5.1/tests/vf_test.py0000664000175000017500000000505114664131406017364 0ustar georgeskgeorgeskimport os import freetype import pytest test_folder = os.path.realpath(os.path.dirname(__file__)) def _ft_ver(): ft_ver_tuple = freetype.version() ft_ver_str = ".".join(['{}'.format(i) for i in ft_ver_tuple]) return ft_ver_tuple, ft_ver_str def test_variable_font_basics(): """ Check that basic VF functionality functions (open a VF font, get VF info) """ ft_vt, ft_vs = _ft_ver() if ft_vt < (2, 8, 1): # note: there is some proto-VF (Multiple Master) support in older # FreeType versions, but not enough to work with here. pytest.skip("Incomplete VF support in FreeType lib {} (need 2.8.1 or later)".format(ft_vs)) return font_path = os.path.join( test_folder, "..", "examples", "SourceSansVariable-Roman.otf") face = freetype.Face(font_path) var_info = face.get_variation_info() assert len(var_info.axes) == 1 assert var_info.axes[0].tag == 'wght' assert len(var_info.instances) == 6 for ii, cv in enumerate((200, 300, 400, 600, 700, 900)): assert var_info.instances[ii].coords == (cv,) def test_vf_axis_get_set(): ft_vt, ft_vs = _ft_ver() if ft_vt < (2, 8, 1): pytest.skip("Incomplete VF support in FreeType lib {} (need 2.8.1 or later)".format(ft_vs)) return font_path = os.path.join( test_folder, "..", "examples", "SourceSansVariable-Roman.otf") face = freetype.Face(font_path) dc_in = (373,) face.set_var_design_coords(dc_in) dcoords = face.get_var_design_coords() assert dcoords[0] == dc_in[0] bc_in = (-0.5,) face.set_var_blend_coords(bc_in) bcoords = face.get_var_blend_coords() assert bcoords[0] == bc_in[0] # try 'reset to defaults' option face.set_var_design_coords(None, reset=True) dcoords = face.get_var_design_coords() vsi = face.get_variation_info() expected = tuple([vsi.axes[i].default for i in range(len(dcoords))]) assert dcoords == expected def test_vf_set_named_instance(): ft_vt, ft_vs = _ft_ver() if ft_vt < (2, 8, 1): pytest.skip("Incomplete VF support in FreeType lib {} (need 2.8.1 or later)".format(ft_vs)) return font_path = os.path.join( test_folder, "..", "examples", "SourceSansVariable-Roman.otf") face = freetype.Face(font_path) vsi = face.get_variation_info() for inst in vsi.instances: face.set_var_named_instance(inst.name) dcoords = face.get_var_design_coords() assert dcoords == inst.coords freetype-py-2.5.1/tests/smoke_test.py0000664000175000017500000000335714664131406020076 0ustar georgeskgeorgeskimport glob import os import freetype import pytest test_folder = os.path.realpath(os.path.dirname(__file__)) def test_load_ft_face(): """A smoke test.""" p = os.path.join(test_folder, "..", "examples", "Vera.ttf") assert freetype.Face(p) def test_load_ft_face_from_memory(): """Another smoke test.""" p = os.path.join(test_folder, "..", "examples", "Vera.ttf") with open(p, mode="rb") as f: assert freetype.Face(f) with open(p, mode="rb") as f: byte_stream = f.read() assert freetype.Face.from_bytes(byte_stream) def test_bundle_version(): module_dir = os.path.dirname(freetype.__file__) shared_object = glob.glob(os.path.join(module_dir, "libfreetype*")) if shared_object: import re p = os.path.join(test_folder, "..", "setup-build-freetype.py") with open(p) as f: m = re.findall(r"freetype-(\d+)\.(\d+)\.?(\d+)?\.tar", f.read()) version = m[0] if not version[2]: version = (int(version[0]), int(version[1]), 0) else: version = (int(version[0]), int(version[1]), int(version[2])) assert freetype.version() == version else: pytest.skip("Not using a bundled FreeType library.") def test_get_ft_face_properties(): p = os.path.join(test_folder, "..", "examples", "Vera.ttf") f = freetype.Face(p) assert f.family_name == b"Bitstream Vera Sans" assert f.get_format() == b"TrueType" assert f.get_glyph_name(20) == b"one" assert f.get_fstype() == ("FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING", 4) assert f.get_first_char() == (32, 3) assert f.is_sfnt assert f.ascender == 1901 assert f.descender == -483 assert f.num_glyphs == 268 assert f.style_name == b"Roman" freetype-py-2.5.1/NOTES.txt0000664000175000017500000000216714664131406015634 0ustar georgeskgeorgeskRelease notes for 0.4.1 ======================= * Fixed a bug in Face.load_char * Added get_format and get_fstype in Face (titusz.pan) Release notes for 0.3.3 ======================= * Fixed a bug in get_kerning * Added test against freetype version for FT_ReferenceFace and FT_Get_FSType_Flags Release notes for 0.3.2 ======================= * Added wordle.py example * Added get_bbox for Outline class * Added get_cbox for Outline and Glyph classes * Added __del__ method to Face class * Set encoding (utf-8) to all source files and examples. * Added test against freetype version for FT_Library_SetLcdFilterWeights. Release notes for 0.3.1 ======================= * Added FT_Stroker bindings (enums, structs and methods) * Added ft-outline and ft-color examples * Fixed first/next char in Face * Pythonic interface has been documented Release notes for 0.3.0 ======================= * Added ftdump.py demo and necessary functions Release notes for 0.2.0 ======================= * Added sfnt functions * Added TT_XXX flags in ft_enums * New examples Release notes for 0.1.1 ======================= * Initial release * Working examples freetype-py-2.5.1/.github/0000775000175000017500000000000014664131406015535 5ustar georgeskgeorgeskfreetype-py-2.5.1/.github/workflows/0000775000175000017500000000000014664131406017572 5ustar georgeskgeorgeskfreetype-py-2.5.1/.github/workflows/ci.yml0000664000175000017500000000672614664131406020723 0ustar georgeskgeorgesk# based on https://github.com/joerick/cibuildwheel/blob/master/examples/github-minimal.yml name: Build on: push: branches: [master] # Sequence of patterns matched against refs/tags tags: - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 pull_request: branches: [master] jobs: build: name: Build wheels on ${{ matrix.os }} ${{ matrix.name }} if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-latest cibw_build: "cp37-*" cibw_archs_linux: "auto64" - os: windows-latest cibw_build: "cp37-*" - os: macos-latest cibw_build: "cp38-macosx_universal2" cibw_archs_macos: "universal2" name: '(universal2)' - os: 'ubuntu-latest' cibw_build: "cp37-manylinux*" cibw_archs_linux: 'aarch64' name: '(manylinux aarch64)' qemu: true - os: 'ubuntu-latest' cibw_build: "cp37-musllinux*" cibw_archs_linux: 'aarch64' name: '(musllinux aarch64)' qemu: true steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # unshallow fetch for setuptools-scm - name: Set up QEMU if: matrix.qemu uses: docker/setup-qemu-action@v3 with: platforms: all - name: Build wheels uses: pypa/cibuildwheel@v2.16.5 env: CIBW_BUILD: ${{ matrix.cibw_build }} CIBW_ARCHS: "auto64" CIBW_ARCHS_MACOS: ${{ matrix.cibw_archs_macos }} CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs_linux }} CIBW_ENVIRONMENT: "FREETYPEPY_BUNDLE_FT=yes PYTHON_ARCH=64" CIBW_MANYLINUX_X86_64_IMAGE: manylinux2010 CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014 CIBW_TEST_COMMAND: "pytest {project}/tests" CIBW_TEST_REQUIRES: "pytest" with: output-dir: dist - name: Upload distributions uses: actions/upload-artifact@v4 with: path: dist name: dist-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.build }}-${{ matrix.name }} publish: name: Publish release to Pypi runs-on: ubuntu-latest needs: [build] if: success() && github.event_name == 'push' && startsWith(github.ref, 'refs/tags') permissions: id-token: write environment: name: pypi url: https://pypi.org/p/freetype-py/ steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # unshallow fetch for setuptools-scm - name: Set up Python 3.9 uses: actions/setup-python@v5 with: python-version: '3.9' - name: Download assets uses: actions/download-artifact@v4 with: merge-multiple: true path: dist pattern: dist-* - name: Build sdist run: | python setup.py sdist - uses: pypa/gh-action-pypi-publish@release/v1 test-pyinstaller: name: Test pyinstaller hook runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python 3.9 uses: actions/setup-python@v5 with: python-version: '3.9' - name: Test pyinstaller hook env: FREETYPEPY_BUNDLE_FT: yes PYTHON_ARCH: 64 run: | pip install pytest psutil pyinstaller>=4 pip install . pytest -v --pyargs freetype.__pyinstaller.tests