PyX-0.14.1/0000755000076500000240000000000012615763300012534 5ustar andrestaff00000000000000PyX-0.14.1/AUTHORS0000644000076500000240000000021712037344757013615 0ustar andrestaff00000000000000Jörg Lehmann Michael Schindler André Wobst PyX-0.14.1/CHANGES0000644000076500000240000013723512615760212013541 0ustar andrestaff000000000000000.14.1 (2015/11/02): - distribution: - upload to PyPI (including old releases) - remove old releases from sourceforge - text module: - fix load_def message parser (reported by Mico Filós) - normpath: - fix intersect with empty normsubpaths (bug #62, thanks to Florent Hivert) 0.14 (2015/04/30): - new svgwriter module: - complete SVG output - SVG font output disabled by default due to missing support by most browsers, fallback by rendering fonts as paths - new svgfile module: - SVG reader - unparsed mode: embedd svg in other svg - parsed mode: supports reading paths (including styles, tranformations, etc.) into a PyX canvas - bitmap module: - using bytes in image type conversions and channel extraction - color module: - fix grey class - fix rgb css binary issue and short code index error - epsfile module: - fix parsing of bounding box - text module: - no end of pages test when no dvi is created at all - add chroot config option needed to use a chrooted TeX installation - graph module: - add xy12axesat feature to graphxyz - canvas module: - fix clipping and transformation applied together - provide _repr_svg_ in canvas for use by IPython - new constructor argument ipython_bboxenlarge - deco module: - remove shortcut for ornaments only to not skip global styles 0.13 (2013/12/20): - Requires at least Python 3.2 - The gallery has been moved to https://sourceforge.net/p/pyx/gallery/, which is a wiki. Contributions are welcome. - filelocator module: - cygwin LaTeX with windows python patch (thanks to Sybren A. Stüvel) - graph styles: - fix numerical instability of line clippings - remove errorbar range checks, as they fail on a reverse axis, which is correct (reported by Néstor Espinoza) - path module: - fix internal name clash when generating a normpath from an empty path (reported by Brendon Higgins) - normpath module: - several stability and precision improvements and bugfixes - cusp removal at normpath construction (and getting rid of invalid results for curvature, rotation, tangent, and trafo methods) - remove curveradius methods as they are invalid for straigt paths - deco module: - apply text trafos to each character in curvedtext (reported by Hans L) - properly apply all textattrs in curvedtext (for example colors or scalings) - canvas module: - layer method takes layer names above or below (instead of an instance), also reorders layer accordingly when layer is already existing - remove the before and after arguments of insert - handle trafo and clip separately in constructor and write methods - allow for one clipping instance only - optimize graphics state stack usage - dvi/dvifile module: - change special handling for transformations and colors to use subcanvases - apply transformations to markers - trafos and styles are no longer canvasitems - style module: - fillrules are now fillstyles and handled within the PS/PDF context - text module: - new texenc setting - major code reorganization and documentation revision (now using autodoc) - font/afmfile module: - parse more AFM files, also some with common inconsistencies (thanks to Markus Schwienbacher for reporting these issues) - color module: - functiongradient has been split into functiongradient_rgb, etc. and the function parameters are now passed directly - lineargradient has been removed for factory functions lineargradient_rgb, etc. that provide linear gradients between colors of a particular color model - bitmap module: - fix jpegimage for progressive jpeg files (thanks to Michael Schindler) - pyxrc: - use APPDATA environment variable to locate the pyxrc on windows - tex, latex, kpsewhich, and locate executables are now customizable in the pyxrc - on the package level: - add pyxinfo to enable output of some useful information - manual: - PyX theme and various sphinx tweaks 0.12.1 (2012/10/26): - graph styles: - fix drawing and clipping of gradient style 0.12 (2012/10/17): - canvas module: - insert method now returns canvas wrapping item if attrs are given - insert method allows specification of position where item is inserted by before and after arguments - new layer method allows creation of separated drawing layers for grouping of drawing operations - writeXXXfile methods now use "page_" and "write_" prefixes for passing the keyword arguments to the page constructor and write method - pipeGS now returns a file handle instead of writing to a file or to stdout - the new method writeGSfile restores the previous pipeGS functionality - support rendering as png for use in IPython notebooks (as suggested by Nikolas Tezak) - document module: - writeXXXfile methods now support writing to stdout when filename is set to "-" - type 1 font modules: - allow font slanting for T1builtinfont instances - improve stripped font compatibility - remove UniqueID lookup from embedded fonts in PostScript output (fixes missing glyph issue with dvips and certain fonts) - allow Type1 font usage without TeX and without AFM font metric - add support for pfm font matrices - epsfile module: - fix race condition while generating bitmap for PDF inclusion - fix file opening for bbox reading when using filelocator (reported by Michael J Gruber) - filelocator module: - fix text mode line ending issue for MS Windows - text module: - fix subprocess call on MS Windows (closefds not functional not also not required at all) - fix pyxgraphics functionality because at least some versions of graphics and friends seem to expect the file extension .def for the driver files (thanks to Michael J Gruber) - deco module: - decorator to put text along a path; based on a patch by Michael J Gruber - dvifile module: - fix for MS Windows: open virtual font files in binary mode - graph modules: - graphs: - uses new canvas layers to stack graph components (fixing bug #1518414, reported by Dominic Ford) - add a flipped option to graphxy to exchange x and y coordinates - add a 1d graph "graphx" (use case: convert a value to a color) - add hiddenaxes layer to the 3d graph - add linkedaxes for the xy-plane in 3d like in 2d (works now properly due to the hiddenaxes feature) - graph styles: - add density style - add gradient style to convert a value to a color using a 1d graph - add a usenames dictionary to the pos style (like rangepos had it already) - graph data: - add a join data provide which adds concatenates several data sources - axis module: - divisor was not properly taken into account in tick handling (axis range extension and range rating) - added the metapost module: - create smooth paths from a series of points - bitmap module: - new fundamental constructor based on arbitrary affine transformations - add ASCIIHexDecode end marker - color module: - add rgbgradient and cmykgradient to force color space - mesh module: - add ASCIIHexDecode end marker - sourceforge.net: - upgrade PyX project page to the Allura platform 0.11.1 (2011/05/20): - canvas: - fix pipeGS (adding support for writing using pycompat.popen) - deco module: - arrow decorator: proper sign of constriction length for positioning reversed arrows - dvi/texfont: - fix exception type - increase designsize deviation to 4 (needs some further investigation) - contrib files: - fixes due to the dvi and font restructuring - setup.py: - fix build process for extension modules - fix download url to allow for easy_install (hopefully) - manual: - converted to sphinx 0.11 (2011/05/15): - font and dvi modules: - major reorganization - TeX mapping files are a property of the writer now By that the pdfwriter now uses pdftex.map instead of psfonts.map (It's also possible to pass a fontmap to a texrunners text method to use different mappings within a single output file) - support for font matrices (afm) for Type1 fonts (using fonts without a metrics is still supported, but properly issues a warning now) - interface for basic TeX-less text output - new PS and PDF writer options: strip_fonts, text_as_path, mesh_as_bitmap, mesh_as_bitmap_resolution - fix for commented out UniqueID - fix rounding of font sizes - fix scaling of VF position increments - new filelocator module - graph modules: - bar style on graphxyz (single datasets only) - graphxyz: - fix position of z4 axis - set correct errorname for z axis (thanks to Axel Freyn) - fix wrong y value usage instead of z value in pos methods - fix unused color range settings in surface style (thanks to Michael J Gruber) - fallbackrange for axes with vanishing range - dokeyitem method (to be called with a plotitem) to alter the key order - doplot() was renamed to doplotitem(), dodata() was renamed to doplot() to have similar naming conventions like for the graph key - axis module: do not divide by None for data.min and/or data.max being None (see patch #2833369) - axis painter: - properly rotate axis titles when ticks are not othorgonal to the axis (reported by Christian Delfosse) - correct namedirection in bar axis painter (reported by rhunger, bug #2028032) - graph.style.arrow: decorator is an parameter of the constructor now (thanks to Axel Freyn) - remove ticks with unset ticklevel and labellevel to prevent rating failures (thanks to Brendon Higgins) - canvas and document modules: - auto-guess output filename from the script filename - add ciecolor flag and input type to the pipeGS method of canvas - pyxrc: - new config options for psfontmaps and pdffontmaps - new config option for formatting of Python warnings - new config section for new filelocator module - text module: - fix two bugs in the read pipe of the texrunner (thanks to Laurence Tratt and Eric Faurot) - fix "<" token handling in mapping file parser (thanks to Matthew West) - fix start message parse error in MiKTeX (thanks to Wojciech Jaskowski) - fix rigid aux file checking (thanks to Clayton E. Myers) - use subprocess module if available - proper error messages when TeX is stopped due to unrecoverable error - style module: - implement style.fillrule - deco module: - added an explicit hatch pattern as an alternative for real postscript patterns - arrow decorator: take into account constriction length when arrow pos < 1 - bitmap module: - add support for transparent bitmaps (in postscript stencil masking only) - path and normpath modules: - remove incorrect zero length line in PDF output for each first moveto path element (thanks to Michael J Gruber) - raise correct normpath exception (thanks to Axel Freyn) - epsfile module: - an ugly way to import EPS in PDF using a bitmap (requires PIL) 0.10 (2007/10/03): - graph modules: - graph module: - graphxyz for 3d graphs with parallel and central projection - doplot method (to be called with a plotitem) to alter the plotitem order etc. - graph styles: - new surface style for 3d graphs (colored surfaces are functional (and useful!) for 2d graphs as well) - new grid style for 3d graphs - new impulses style - optional textdx/textdy columns to the text style added - arrowpos parameter to the arrow style added - bugfix: fromvalue axis range adjustment in histogram style - bugfix: axis range adjustment in range style - axis module: - painter: don't insert axis title twice (thanks to Tim Gray for reporting this problem) - parter: extend the logarithmic parter to calculate automatic partitions for huge ranges (TODO: documentation of the new autoexponent parameter) (suggested by Dominic Ford) - fix: range rating was not taken into account due in the 0.9 release - data module: - list class was renamed to points; deprecation warning added for instance creation, but inheritance from list failes - new values class - new mesh module: - internal helper module for efficient handling of triangular colored meshs - color module: - renamed: palette->gradient, functionpalette->functiongradient, linearpalette->lineargradient - new class palette representing a discrete ordered list of colors - support transparency for filling/stroking in pdf separately - transparency support for postscript as available by means of a proprietary ghostscript extension (for ps2pdf) - renamed method: tostring8bit -> to8bitstring (bug #2932888) - attr module: - add multichangeattr to perform a select on different changeable attributes depending on the selects total number - font modules: - t1font: - add missing glyph traversal in t1seacs updatepath - normpath module: - support zero-length normsubpaths - canvas module: - don't change order of attrs passed to canvas constructor in place - added __truediv__ methods according to PEP 238 0.9 (2006/05/24): - most important changes (to be included in the release notes): - mathtree removal (warning about integer division) - barpos style does not build tuples for nestedbar axes automatically - new deformers for path manipulation (for smoothing, shifting, ... paths) - font modules: - new framework for font handling - own implementation of type1 font stripping (old pdftex code fragments removed) - complete type1 font command representation and glyph path extraction from font programs - t1code extension module (C version of de-/encoding routines used in Type 1 font files) - AFM file parser - graph modules: - data module: - mathtree removal: more flexibility due to true python expressions - default style instantiation bug (reported by Gregory Novak) - style module: - automatic subaxis tuple creation removed in barpos (create tuples in expressions now; subnames argument removed since it became pointless; adujstaxis became independend from selectstyle for all styles now) - remove multiple painting of frompath in histogram and barpos styles - fix missing attribute select when using a bar style once only (reported by Alan Isaac) - fix histograms for negative y-coordinates (reported by Dominic Ford, bug #1492548) - fix histogram to stroke lines to the baseline for steps=0 when two subsequent values are equal - add key method for histogram style (reported by Hagemann, bug #1371554) - implement a changebar style - graph, axis and style module: - support for mutual linking of axes between graphs - new domethods dependency handling - separate axis range calculation from dolayout - axis.parter module: - linear and logarthmic partitioners always need lists now (as it was documented all the time; renamed tickdist/labeldist to tickdists/labeldists; renamed tickpos/labelpos to tickpreexps/labelpreexps) - axis module: - patch to tickpos and vtickpos (reported by Wojciech Smigaj, cf. patch #1286112) - anchoredpathaxis added (suggested by Wojciech Smigaj) - properly handle range rating on inversed axis (reported by Dominic Ford, cf. bug #1461513) - invalidate axis partitions with a single label only by the distance rater - fallback (with warning) to linear partitioner on a small logarithmics scale - painter module: - patch to allow for tickattrs=None (reported by Wojciech Smigaj, cf. patch #1286116) - color module: - transparency support (PDF only) - conversion between colorspaces - nonlinear palettes added - the former palette must now be initialized as linearpalette - remove min and max arguments of palettes - text module: - improve escapestring to handle all ascii characters - correct vshift when text size is modified by a text.size instance - recover from exceptions (reported by Alan Isaac) - handle missing italic angle information in tfm for pdf output (reported by Brett Calcott) - allow for .def and .fd files in texmessage.loaddef (new name for texmessage.loadfd, which was restricted to .fd files) - path module: - correct closepath (do not invalidate currentpoint but set it to the beginning of the current subpath); structural rework of pathitems - calculate real bboxes for Bezier curves - fix intersection due to non-linear parametrization of bezier curves - add rotate methods to path, normpath, normsubpath, and normsubpathitems - add flushskippedline to normsubpath - add arclentoparam to normsubpath and normsubpathitems - path is no longer a canvasitem - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - normpath module: - contains normpath, normsubpath and normpathparam which have originally been in the path module - return "invalid" for certain path operations when the curve "speed" is below a certain threshold - normpath is no longer a canvasitem - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - deformer module: - rewritten smoothed to make use of the subnormpath facilities - rewritten parallel for arbitrary paths - deco module: - add basic text decorator - allow arrows at arbitrary positions along the path - connector module: - boxdists parameter need to be a list/tuple of two items now - changed the orientation of the angle parameters - trafo module: - renamed _apply to apply_pt - introduce _epsilon for checking the singularity of a trafo - epsfile module: - use rectclip instead of clip to remove the clipping path from the PostScript stack, which otherwise might create strange effects for certain PostScript files (reported by Gert Ingold) - dvifile module: - silently ignore TrueType fonts in font mapping files (reported by Gabriel Vasseur) - type1font module: - accept [ and ] as separators in encoding files (reported by Mojca Miklavec, cf. bug #1429524) - canvas module: - remove registerPS/registerPDF in favour of registering resourcing during the outputPS/outputPDF run - move bbox handling to registry - rename outputPS/outputPDF -> processPS/processPDF - remove set method of canvas - add a pipeGS method to directly pass the PyX output to ghostscript - allow file instances as parameter of the writeXXXfile methods (feature request #1419658 by Jason Pratt) - document modules: - allow file instances as parameter of the writeXXXfile methods (feature request #1419658 by Jason Pratt) - style module: - make rellength the default for dash styles - random notes: - switched to subversion on 2006/03/09 0.8.1 (2005/08/13): - deco module: - fix bug in postscript deco code for stroking only attributes - path module: - fix multicurveto._normalized - fix path.paramtoarclen and path.paramtoarclen_pt - remove unused method-local function - fix linestyle rellength in PostScript - correction to the rounding problems in circles (reported by Uwe Fabricius) - epsfile module: - fix a typo - pattern module: - issue a warning when not using a stroke color for patterns - text module: - postpone PDFfontdescriptor information, since it raises an error on certain fonts even when PostScript output was requested (reported by Gert Ingold) - remove spurious spaces when checking for empty texmessages - kpathsea module: - caching in fallback to lower system call bottleneck - canvas module: - add missing writePSfile wrapper - add *args to writeEPSfile and writePDFfile wrappers - writer modules: - writebbox option to write bbox information (disabled by default) even when a paper format is specified (PS and PDF writers only) - use arclen in spring example - add knot example - use pdf graphic files for pdf version of the manual - use PyX to create tipa fallbacks for FAQ - correct description regarding the manual in the README file 0.8 (2005/07/13): - changed requirements to python 2.1 or newer: - nested scopes are needed without fallback solution by the path module (at other places fallback solutions for missing nested scopes are missing as well) - use warning module for warnings - path module: - path parameters and argument handling - the arct to arc/arcn conversion (needed for bbox calculation and for conversion into normpath) has been fixed - document module: new - container classes for document and pages - document.paperformat class (strings are deprecated) - canvas module: - writeEPSfile wraps a canvas in a single page document and performs the output - bbox module: - add _pt methods - pdfwriter module: - completely rewritten: support for fonts and patterns has been added - pswriter module: new - separate PS output from canvas - new signature of outputPS methods: writer and context are passed as additional arguments - color module: - allow selection on zero range palette (reported by Francisco Borges, cf. bug #1116257) - prolog module: removed due to code reorganisation - graph modules: - modifications on __init__.py in graph and axis subdirectories to make "from pyx.graph import *" working as expected - graph styles: - addontop added to stackedbarpos - column -> columnname renaming where appropriate - histogram style added - graph data: - function needs explicit variable definition (implicit variable definition is deprecated) - column names are inherited by data.data() except when copy=0; unused columns are silently ignored now - dynamic function data on a logarithmic axis uses isinstance check now (although it removes the only (mis)use of axis.inverse, it is a temporary solution only) - graph key: - extend graph keys to allow for several columns - axis data handling refactoring: - introcuded an axis positioner (module graph.axis.positioner) - introduced anchoredaxis to make axis data and positioning local to a graph - linkedaxis is a special version of anchoredaxis and is generic (it uses the new linkpainter provided by an axis) - unification of split and bar axes; removed some black magic in baraxis in favor of a nestedbar axis - x linked to x2 etc. is now possible - axis.inverse was removed (the only place it was (mis)used was by a function) - graphxy: - allow to transform axis after layout - [xy]axisat arguments in the constructor to easily move [xy]-axes to a position defined the orthogonal axis - remove axispos (use the axis dictionary now, since it now contains anchored axis instances and those have shortcuts for the axis positioner methods) - dvifile: - tfm->dvi conversion rounding bugfix - fix parsing of empty strings ("") in fontmap files (reported by John Owens, bug #1218983) - text module: - support for halign of boxes and content of boxes (see halign example) - take units xscale into account in parbox - messageparser for replaced fontsizes: Warning -> implemented by texmessage.fontwarning - messageparser for size differences at the end: Warning not Exception -> implemented by texmessage.fontwarning - messageparser for overfull/underfull vbox/hbox: Warning not Exception -> implemented by texmessage.boxwarning - dvicopy flag removed - allow argument of set to be None - rename nomathmode and nophantom to clearmathmode and clearphantom - texmessagepattern for easy creation of simple TeX message parsers - allow long file names in file checking TeX message parsers - no newline removal to not disturbe TeX messages when reporting errors - reworked documentation to use the python documentation standards - style module: - linewidth is no longer a unit.length subclass but expects a such as first argument - epsfile module: - correct EOL handling while reading DSC's (reported by Markus Meyer) - pattern module: new - moved canvas.pattern to its own module together with the new PDFpattern class - add some default patterns: hatched and crosshatched - deformer module: - improve the smoothing deformer - add a parallel deformer - tex module: - the very old tex module finally got removed completely - contrib directory: - a simple converter from dvi to EPS/PS/PDF files (dviconvert.py) has been added - a simple imagine to EPS/PS/PDF converter (imgconvert.py) has been added - a simple dvitype.py has been added - update address of FSF all over the place 0.7.1 (2004/12/15): - canvas module: - EPS header fixed (reported by Russell Lang, cf. bug #1065099) - Makefile fixes: - use CURDIR instead of PWD (reported by David M. Cooke, bug #1070285) - pykpathsea module: - support windows line endings (patch by Hans-Andreas Engel, cf. bug #1071160) - graph modules: - line attributes handling fixed (reported by Andrea Riciputi) - fix typos in predefined symbols (reported by Andrea Riciputi) - cut column name list at the max. number of columns (reported by Arnd Baecker) - examples: - add INDEX and README files to distribution - new errorbar and julia example - faq: - pdf snippets for tipa based phonetic transliterations 0.7 (2004/10/21): - bitmap module: - new module for inclusion of bitmap images - path module: - names of local and member variables now follow the naming convention of having a _pt suffix when containing lengths in points - bbox module: - names of local and member variables now follow the naming convention of having a _pt suffix when containing lengths in points - enlarge was misspelled as enlarged - renamed _bbox -> bbox_pt - new bbox method center, which returns the coordinates of the center of the bbox - enlarge and enlarged do no longer interprete unqualified lengths as being of type visual - unit module: - unit.cm, unit.t_cm, etc. are no longer sub classes but instances of length - never convert implicitly into visual/width, etc. lengths (this is more about usage of the unit module in various other modules) (TODO: update documentation) - support for string initialization removed - support for initialisation with other length removed - lengths can now be divided by other lengths (as suggested by Michael Gruber and Magnus Lie Hetland) - text module: - postpone reading of fontmap files until TeX/LaTeX is started - sign of font number in dvifile (reported by Michael Gruber) - phantom attribute - canvas module: - added new classes page and document for multipage PostScript output - apply deformers (instead of trafos) in draw method - style module: - decrease interval for dotted and dash-dotted lines for better visual appearance - setup.py and distribution: - create siteconfig on install to store positions of the shared data and the global pyxrc - graph modules: - graph style + data reorganization - modularization of the graph styles by separating data handling and drawing tasks - several graph styles can now be combined together - graph data can internally now combine different data sources (by that, some nasty side effects could have been removed) - enum -> num renaming - allow for horizontally and vertically centered graph key alignment and a key background - fix bug that graph was not finished automatically when a bbox was specified manually (reported by David Barton) - path module: - pathel -> pathitem, etc. renaming - methods accepting a parameter value / arc length now also allow the user to pass a tuple (subpath, param) / (subpath, arclen) - normpath constructor no longer accepts a path or normpath as argument but only a list of normsubpaths. Use the new normpath method of the path instead to construct a normpath from a path. - normsubpath can now deal with short (i.e. shorter than epsilon) segments correctly - the intersect and split methods of normpath and normsubpath have been completely rewritten and now take the accuracy epsilon correctly into account. Note that for a closed subpath the split function now returns the segment containing the closing point as first element in the result list (before, it was returned as last element). - normsubpathitems and normsubpath now implement much more methods also provided by path and normpath instances - normpath.append no longer accepts pathitems but only normsubpaths - deformer module: new - moved cycloid and smoothed from deco into deformer - bbox module: - handle "BoundingBox: (atend)" (cf. bug #945621 reported by Jim Boyle) - kpsearch option to search for file using the kpathsea library (contributed by Michael Gruber) - base module: - PSCmd and PSOp are now joined in a new class canvasitem - deco module: - decorated path no longer allows modification of its path - new method excluderange which allows to remove certain parameter ranges from the stroked path - additional canvas provided by decorated path is now called ornaments - constriction=None now indicates an arrowhead without constriction - trafo module: - trafos are now deformers - examples: - a bunch of bargraph examples have been added 0.6.x (????/??/??): - graph/axis module: - fix errorbar range adjustment - fix empty tick lists bug (reported by Marko Vendelin, cf. bug #977323) - graph/style module: - symbolline drawing order in graph key (cf. bug #990687) - graph/data module: - access to builtin list (reported by Marcus Mendenhall, cf. bug #1042458) 0.6.3 (2004/04/27): - graph module: - fix drawing with background - fix insertion of a zero length path when the whole line is outside the valid axis range (reported by Marko Vendelin) - distribution: - include source for faq and manual - distribute the pdf instead of postscript (manual, faq, examples) 0.6.2 (2004/04/07): - graph module: - fixed title=None + graph key issue reported by Gabriel Vasseur - graph.axis.painter.plain -> graph.axis.painter.regular (as it was in parts of the documentation already) - changeable-gridattrs-become-None-bug fixed - graph style cutting outside lines (double-)fixed 0.6.1 (2004/03/31): - fixes missing install of the graph and axis directories introduced in 0.6 - some minor updates to the faq 0.6 (2004/03/30): - graph module: - reorganisation of the graph structure finished (there might be some small pending issues, but the basic restructuring is done with this release): - graph splitted into several modules in pyx/graph and pyx/graph/axis - painters are using the new attribute scheme including changeable attributes - graph styles rewrite - graph data rewrite - axis zeropath feature has been removed - mergelabels removed; linpart doesn't have a label argument anymore - names and texts removed from baraxis - iteration on graph style, when it is used several times in the same graph - symbols + lines -> symbollines; symbols do not allow setting lineattrs, and lines not symbolattrs - manual line clipping (do not include unneeded line segments when the axis range is set manually etc.) - automatic file key titles - graph.data now also includes the old data module - data.list adds (by default) a line number like data.file (thus regular columns are counted from 1) - path: - added new pathels multilineto_pt and multicurveto which allows to specify a list of points and can thus be much more efficient - internal methods return coordinates in pts - arclentoparam returns only parameters not total length - added path.arclength_pt, path.at_pt, path.begin_pt, path.end_pt (and correspondingly for normpath) - complete refactoring of the normpath class: normpaths now consist of normsubpaths which themselves consist of normlines and normcurves This is much more convenient for any routines working with normpaths. - reversing of closed sub paths does not change the first point of the sub path - renamed: arclength -> arclen - renamed: lentopar -> arclentoparam - renamed: glue -> joined - normpath now supports join, the in-place version of joined - path and normpath method raise exception instead of returning None when parameter is out of range - the accuracy epsilon can now only be specified in normpath and normsubpath constructor and no longer in arguments of path and normpath methods - negative parameters are no longer supported in path and normpath methods - path and normpath methods which accept parameter value param now alternatively accept an arc length - deco module: - cycloid decorator - smoothed decorator - arrow heads are no longer stroked (as suggested by Magnus Lie Hetland) - canvas: - writeEPSfile deprecates writetofile - internally, write methods are renamed in outputPS - canvas constructor no longer accepts variable argument list but expects a list of attrs as first argument (defaulting to []) and a texrunner as second argument (defaulting to text.defaulttexrunner) - set, draw, stroke and fill no longer return self, i.e., the canvas, but None - bbox module: - added inplace add (__iadd__), enlarge and transform methods - callers use inplace add where possible now (yielding a considerable speedup) - "undefined" corners of bounding boxes are no longer supported which makes the bounding box operations much more efficient. - connnector module: - renamed _xxx -> xxx_pt - epsfile module: - removed showbbox argument of epsfile class - text module: - default handling of texmessages as in the new attribute scheme - multiple insert bug fixed - made left, right, width, height, depth information available (x length not taking into account box transformations) - ignore tex message "Please type a command or say `\\end'" - added textboxes that are sequentially filled (experimental) - examples: - mandel.py (contributed by Stephen Phillips) - unit module: - length comparision (David Beach) - x-scale for TeX - more unit tests - mathtree module: - switched to the new parser using pythons parser module - data module: - removed, it all lives in the graph.data module now, while before it was splitted into two separate modules - tex module: - not imported by default anymore - obsolete warning when importing this module 0.5.1 (2004/01/22): - distribution: - include missing c-files for optional extension modules - prolog module: - fix unpaired BeginProcSet/EndProcSet in font enconding 0.5 (2004/01/20): - setup.py and distribution: - allow customization of the extension modules built (via setup.cfg) - disable building pykpathsea module by default - more detailed description of install process in INSTALL - provide more information and pointers to other files in README - include example data files in distribution (suggested by Andrea Riciputi) - force dvips to write ps files instead of printing them (suggested by Otto Tronarp) - includ pyxfaq.pdf in distribution - text module: - improved is-readable test for lfs files and pyx.def file - explicitly quit (La)TeX in cleantmp (helps when quitting with C) - showwaitfortex implemented following a suggestion by Fernando Perez (waitfortex is increased to 60 seconds now) - support of TeX extension --ipc for reading dvi results while TeX keeps running - configurable font mapping files (via pyxrc or parameter of the texrunner constructor) - markers to get access to positions within TeX expressions - fix: allow for e-tex in texmessage.start (reported by Andrea Riciputi) - fix: print warning at syntax errors in font mapping file and continue (cf. bug #795271) - remove limitation on number of fonts in dvi file - added native virtual font support - dvicopy support not needed anymore (it is still available, but obsolete and removed from the documentation) - do not include too many glyphs in the eps file - _xxx -> xxx_pt renaming - dvifile module (NEW): - separated from the text module - dvifile class returns standard pyx canvas instances on readpage - graph module: - removed manualpart and partitioners mix keyword - results of the splitting at "=" in graph.function were not stripped - skip title=None in key (cf. bug #821284), properly align a single key entry - another (the last?!) axis redesign: axispos -> class of its own - some axispos name have changed slightly (zeroline -> zeropath etc.) - tick/data-vmin/vmax removed - pathaxis - linkaxis - minor enhancements in exponentionaltexter - axes alongs paths including a set of examples - mixing a partitioner and manual ticks by two distinct keyword arguments now - _xxx -> xxx_pt renaming - part -> parter renaming - canvas module: - stroke, fill, draw, set and insert do no longer accept variable length argument lists but an attribute list as last argument - stroke and fill now support trafos (TODO: documentation) - uppercase version of a4, a3, ... paperformats - config module: - new module for loading PyX configuration information - pyx module: - automatically import main modules into pyx namespace as suggested by Fernando Perez. - path module: - check for sorting of parameter list passed to path.split method - _xxx -> xxx_pt renaming - deco module (NEW): - contains decoratedpath and decorators from canvas module - all predefined decorators are instances now (deco.stroked is thus ok) and attributes have to be passed explicitely, e.g., deco.earrow.small(attrs=color.rgb.red) and deco.stroked([color.rgb.blue]) - style module (NEW): - contains all line- and fillstyles which formerly had been defined in the canvas module - dash now supports relative dash lengths (as suggested by Otto Tronarp) - mathtree module: - fixed incorrect handling of - (for instance -x**2 was not negative) - attrlist module: - contents have been moved to the (obsolete) tex module, which was the only user anyhow, and the module itself was removed - t1strip module: - new fallback solution in pure python - bugfix: pyxadapt.h needs to open files binary under Windows (reported by Gary Pajer) - box module: - _xxx -> xxx_pt renaming - trafo module: - _xxx -> xxx_pt renaming 0.4.1 (2003/09/17): - canvas module: - "in" to "inch" in paperformats - text module: - fix pyx.def hack occuring whenever \ProcessOptions* was used by a package - pykpathsea module: - implement different file formats for Python version of module - t1strip module: - python fallback solution should behave the same way as c extension module (closes SF bug #799182 reported by Marcus Mendenhall) - __init__.py: - added "connector" to __all__ 0.4 (2003/08/22): - graph module: - separate texter out of the axispainter - axis/partitioner/texter/painter/axispos redesign & interfaces - tick.text is renamed to tick.label - ticks and labels are renamed to tickpos/tickdist and labelpos/labeldist in partitioning - ticks can be used in the part to mix a partitioner with some manual ticks -> manualpart and the mix technique is not needed anymore (both things are still available and working, but they will be removed in the future) - _ensurefrac is implemented inside the frac constructor now; initialization is possible by: - a (enum, denom) tuple now (previously there were two arguments) - a string (as before via _ensurefrac) - exponential strings are allowed as well (e.g. "1e10" etc.) - a float (precision is determined by floatprecision -- the number of decimal places) - dense -> density - axis.maxworse - axis interface - text module: - reset() method for the texrunner - automatic restart of a TeX instance with the same preamble (preamble changes are not possible) - texmessage.loadfd for accepting font description loading - don't bail out on width_index == 0, but mark character invalid instead - dvicopy flag - support for specials; pyxgraphics flag - support psfonts.map: font names, font encodings - bugfix \def\ProcessPyXBox -> \long\def\ProcessPyXBox - improved lfs handling - data module: - full documentation via doc strings - connector module: - some preliminary version - box module: - multiple radii (up to two per point) and softnesses - ensurecenter added --- do we always force the creation of a center? - path module: - lentopar methods added including some tests - epsfile module: - new parameter bbox allows to override the bounding box of the eps file bugfixes: - text module: - derive TFMError and DVIError correctly from exceptions.Exception - close files and pipes, if they are no longer used (thanks to Marcus Mendenhall) - remove DeprecationWarning in Python 2.3 (thanks to Marcus Mendenhall) - box module: - correct rounding algorithm (Michael Schindler) - graph module: - refer to the graphs texrunner instead of the defaulttexrunner (cf. #728209) - rounding towards zero bugfix in autolinpart - log axis range rating bugfix - mathtree module: - addarg bugs (#738724) - epsfile module: - fix mixing up of height and width in scale calculation - and various other fixer here and there 0.3.1 (2003/04/04): - text module: - fix bug in dvi rule code where width was height - fix preamble attribute checking bug - fix texmessage.load pattern search instead of pattern match bug - renamed vbox to parbox (was done in 0.3 partially only) - data module: - allow for tuples in arguments of the data class - convenience: exchanged order of named parameters in data.data - graph module: - convenience: allow for part=None in _axis (base of linaxis and logaxis) - examples: - added a latex example (requested) - added a attributechange example (requested) - added back the integral example (requested; prior PyX 0.3 it was part of the user manual) - small change in vector example (allow for the access to the texrunner) - examples included in source distribution - canvas module: - correct arrow template calculation for very short paths 0.3 (2003/03/31): - examples - new easy to use example generation (will hopefully lead to nice examples) - unit box: - new module for handling of convex polygons (taken out of the graph module) - unit helper: - new module containing a collection of helper functions (taken out of the graph module) - moved the attrlist into helper -- as plain functions; attrlist becomes obsolete - text module: - new module: a new and preferable integration of TeX/LaTeX - t1strip module: - strip glyphs from pfa/pfb-fonts - there is a C implementation taken from pdftex - fallback solution via an external program (pfb2pfa) - pykpathsea module: - (partial) C binding to libkpathsea - fallback solution via an external program (kpsewhich) - graph module: - removed some code duplication (various axis painters) - use text module instead of the obsolete tex module - allow for tailing zeros of automatic generated labels - allow for missing data in bar graphs -> skipmissing parameter - remove the support for variables given as keyword arguments in data constructor - use context instead of extern for extern variables and functions - graph keys; titles in data/function/etc. - unit module: - new classes for visual and width lengths, aliases for user length (u_pt = pt) - all length classes have now by default a quantifier 1 (instead of 0), such that, for instance, 5*unit.t_cm() == unit.t_cm(5) - default_unit now has to be set via unit.set. For instance: unit.set(defaultunit="m"). - convert_to is now an internal function, which moreover does not longer accept tuples or lists - bbox module: - new class _bbox (the former bbox) which accepts points in the constructor. This is used for internal purposes. - the bbox constructor now accepts user lengths in the constructor. - new methods height, width, top, bottom, left, right - ll & ur ???, what about ul and lr -> ugly! - enlarge (was enhance) now allows selective enlargement to the left, bottom, right and top - output HiResBoundingBox - never reduce bbox upon output - epsfile module: - new constructor signature, more in line with rest of PyX: epsfile(x, y, filename, **additional_args) - data module: - removed additional column support in addcolumn; removed _addcolumn - line reduction for datafile like the every parameter in gnuplot - canvas module: - new way of PS prolog generation that writes only necessary parts - added support for patterns - canvas.insert() now supports arguments - bbox of canvas can be specified in writetofile command explicitely - writetofile does not return self anymore - arrow template now uses intersection with circle to get size right (as per a suggestion by Michael Schindler) - mathtree module: - added abs function - changed the handling of extern functions and all variables - color module: - gradient renamed to palette - numerous bugfixes: - problem with sizefile on windows (tex module) - allow for strings in graphxy's width and height; allow for width only (graph module) - disable rating for labelattrs equals None (graph module) - defaultstyle selection, when a list of data is provided to the plot function (graph module) - traverse when adding functions as arguments of operators (mathtree module) - allow for extern functions in addcolumn (data module) - just one common place for the version number - fix incorrect exception name MathError (path module) - prevent double return of intersections for closed sub paths - ... 0.2 (2003/01/17): - unit module: - allow division of length by numbers - trafo module: - new transformation: slant - renamed all trafo methods to use the participle (i.e translate->translated) - the name of all trafo subclasses are verbs (i.e. translation->translate) - graph module: - mark class renamed to symbol - (text-)box distance measurement - moved axis partitioning to axis and axis painter - automatic axis partitioning (now officially: general cleanup, distance measurement, documentation) - splitaxis - baraxis, baraxispainter, and bar style - data module: - previously named datafile module - class "_datafile" renamed to class "data" - class sectionfile added - testsuite - mathtree module: - extern variables and functions (support in graph.function, graph.paramfunction and data.data) - testsuite - text module: - deferred to Version 0.3 - running TeX "on the fly" is basically implemented - numerous bugfixes: - transformation bug (#624068, trafo module) - canvas transformations (canvas module???) - textbox alignment (graph module) - return linewidth upon calculation with linewidths (unit module) - allow column number variables with several digits - ... - british and american spellings (color module, graph module) - small logo modifications 0.1 (2002/10/07): - initial release PyX-0.14.1/contrib/0000755000076500000240000000000012615763300014174 5ustar andrestaff00000000000000PyX-0.14.1/contrib/color.cfg0000644000076500000240000000012212037344747015776 0ustar andrestaff00000000000000\DeclareOption{pyx}{\def\Gin@driver{pyx.def} \def\c@lor@namefile{dvipsnam.def}} PyX-0.14.1/contrib/dviconvert.py0000644000076500000240000000450512255044067016737 0ustar andrestaff00000000000000#!/usr/bin/env python # -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 André Wobst # # dviconvert is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # epstopng is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with epstopng; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from optparse import OptionParser from pyx import * from pyx import bbox, version from pyx.dvi import dvifile parser = OptionParser(usage="usage: %prog [-b] [-p paperformat] -o output-file dvi-file", version="%prog " + version.version) parser.add_option("-o", "--output", type="string", dest="output", help="output-file") parser.add_option("-p", "--paperformat", type="string", dest="paperformat", default=None, help="optional paper format string") parser.add_option("-b", "--writebbox", action="store_true", dest="writebbox", default=0, help="Add bouding box information on PS and PDF when a paperformat is defined") (options, args) = parser.parse_args() if len(args) != 1: parser.error("can process a single dvi-file only") if options.paperformat: options.paperformat = getattr(document.paperformat, options.paperformat) df = dvifile.DVIfile(args[0]) d = document.document() while 1: dvipage = df.readpage() if not dvipage: break if options.paperformat: aligntrafo = trafo.translate(unit.t_inch, -unit.t_inch + options.paperformat.height) aligneddvipage = canvas.canvas([aligntrafo]) aligneddvipage.insert(dvipage) p = document.page(aligneddvipage, paperformat=options.paperformat, centered=0) else: p = document.page(dvipage) d.append(p) if options.writebbox: d.writetofile(options.output) else: d.writetofile(options.output, writebbox=1) PyX-0.14.1/contrib/dvitype.py0000644000076500000240000000225312037344747016244 0ustar andrestaff00000000000000#!/usr/bin/env python # -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 André Wobst # # dvitype is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # epstopng is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with epstopng; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from optparse import OptionParser from pyx import version from pyx.dvi import dvifile parser = OptionParser(usage="usage: %prog dvi-file", version="%prog " + version.version) (options, args) = parser.parse_args() if len(args) != 1: parser.error("can process a single dvi-file only") df = dvifile.DVIfile(args[0], debug=True) while df.readpage(): pass PyX-0.14.1/contrib/graphics.cfg0000644000076500000240000000005612037344747016466 0ustar andrestaff00000000000000\DeclareOption{pyx}{\def\Gin@driver{pyx.def}} PyX-0.14.1/contrib/imgconvert.py0000644000076500000240000000353512171007751016727 0ustar andrestaff00000000000000#!/usr/bin/env python # -*- encoding: utf-8 -*- # # # Copyright (C) 2005 André Wobst # # epstopng is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # epstopng is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with epstopng; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from optparse import OptionParser from pyx import * from pyx import version parser = OptionParser(usage="usage: %prog -o output-file [-r resolution] image-file", version="%prog " + version.version) parser.add_option("-o", "--output", type="string", dest="output", help="output-file") parser.add_option("-r", "--resolution", type="string", dest="resolution", default=None, help="resolution of the image in dpi (optional when available in the image data)") (options, args) = parser.parse_args() if len(args) != 1: parser.error("can process a single image-file only") try: im = bitmap.jpegimage(args[0]) except ValueError: from PIL import Image im = Image.open(args[0]) compressmode = "Flate" else: compressmode = None if options.resolution is None: width = None else: width = im.size[0] / float(options.resolution) * unit.inch c = canvas.canvas() c.insert(bitmap.bitmap(0, 0, im, compressmode=compressmode, width=width)) c.writetofile(options.output) PyX-0.14.1/contrib/textboxes.tex0000644000076500000240000003253712037344747016765 0ustar andrestaff00000000000000% Modified \output-routine for the use with PyX % this file makes changes of \hsize and \vsizes possible after % every pagebreak % % Copyright (C) 2004 Michael Schindler % % This file is part of PyX (http://pyx.sourceforge.net/). % % PyX is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % PyX is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with PyX; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA % % \newtoks\lovsizes \newtoks\lohsizes \newtoks\parnos \newtoks\parshapes % % Please note that all four tokenlists have to end with {\relax} % This is needed for correct shortening % %%%%%%%%%% TeX's part %%%%%%%%%% \newif\ifverbose \verbosefalse \newcount\tempcnt \newcount\parno \parno=1 \newcount\myprevgraf \myprevgraf=0 \newcount\showprevgraf \showprevgraf=0 \newcount\outputtype \outputtype=0 \newcount\razor \newcount\leastcost \leastcost=10000000 \newcount\futurecost % % Tools for splitting and merging tokenlists after their first element {{{ % did I learn too much lisp or what? \def\cdr#1{\expandafter\precdr\expandafter#1\the#1@} \def\numcdr#1{\expandafter\prenumcdr\expandafter#1\the#1@} \def\numconcat#1#2{\edef\foo{{\the#1}\the#2}\global#2=\expandafter{\foo}} % \def\precdr#1#2#3@{\ifx#2\relax\relax\global#1={\relax}\else#2\global#1={#3}\fi} \def\prenumcdr#1#2#3@{\ifx\relax#2 0\global#1={\relax}\else#2\global#1={#3}\fi} % }}} % % The output routine {{{ % Documentation {{{ % 1. Question: Who calls the pagebuilder and \output? % Answer: Only \par and $$ (as far as I have read the TeXbook) % % 2. Question: So, all together: What is to be done? % Answer: We have to simulate the work of the linebuilder that makes % paragraphs and math into lines in order to find out, what value \prevgraf % might have at a pagepreak. Then, we change the \hsize and \vsize at the % pagepreak and inform PyX about the value of \prevgraf. % % 3. Question: When is \prevgraf advanced? % Answer: At every line by 1 and at every display math by 3 % % 4. Question: How can we hook into the pagebuilding mechanism to find out % about lines and displays? % Answer: We get into the pagebuilder that splits vertical lists into pages % if we enforce a penalty of less than -10000. There are three built-in % hooks: \interlinepenalty % \predisplaypenalty % \postdisplaypenalty % These are set to values less than -10000 by wrapping \par and $$, the % ones who call the pagebuilder and, therefore, \output % % Unfortunately, we get only "breaks", but we are interested in lines. At % each list, we have one break less than lines. So, we have to add another % call of \output at the end of a paragraph. This is done by an explicit % \penalty % A display math succeeding some text also calls the pagebuilder. We have % to add another line in such situations. This is done in the output % routine while processing \predisplaypenalty. % % 5. Question: Why are there so many \ifnum s in the output routine? % Answer: As explained avove, we have to do different things at different % positions of our text. \interlinepenalty and the \penalty for paragraph % endings have to add a line. \postdisplaypenalty has to add the display % (advances \prevgraf by 3), while \predisplaypenalty may still reside on % the previous page, while the display math has moved to the next one. % Therefore, it does not contribute to the \prevgraf. Nevertheless, if % there was some text before the display math in the same paragraph, we % still have to add the last line of text! % % This is the reason for the whole \outputtype business: % We have to show a \prevgraf value different to \myprevgraf at a situation % where an \interlinepenalty is followed by a \predisplaypenalty which is % followed by a pagebreak. The display is on the next page. % The same can -- of course -- also occur with a \predisplaypenalty % following a \penalty caused by \par % % 6. Question: What the hell does \leastcost do? % Answer: This is a tricky point. We hooked into the pagebuilding mechanism % by changing penalties. In this case, TeX thinks, there is a very good % pagebreak and calls \output. But \output removes the strongly negative % penalty we added. Now, TeX has to reconsider the pagebreak and may come % to the result that some of the lines that have appeared as perfect % pagebreaks are not so perfect... % Therefore, before we re-inject the whole vertical list and remove the % negative penalty by saying % \unvbox255 \advance\outputpenalty by XXXXXX \penalty\outputpenalty % we have to know in advance, what the pagebuilder will think of the % pagebreak in the next run. See the TeXbook, p. 111 for the correct % formula. % % This is the reason for \showprevgraf. We have two counters: % - \myprevgraf counts real lines and displays. This keeps us up-to-date % with the paragraph all the time % - \showprevgraf only counts what will be visible on the current page. It % will be reset to \myprevgraf after the pagebreak. % % 7. Question: What do you do to \deadcycles? % Answer: \deadcycles is advanced every time an \output routine has % re-inserted \box255 into the recent contributions. We have to do this for % every line and display math. Therefore, we are restricted to % \maxdeadcycles lines or displays :-( % To avoid this, we cheat the counting of deadcycles and re-advance % \deadcycles by -1. Please, be careful with this hack! % }}} \def\setshowprevgraf#1{% % \futurecost will be the cost in the next step (TeXBook, p.111) \futurecost=#1 \advance\futurecost by\outputpenalty % redo Knuth's formula for pagebreaking: futurecost (is the penalty), badness and insertpenalties \ifnum\insertpenalties<10000 \ifnum\futurecost<-9999 \else\ifnum\futurecost<10000 \ifnum\badness<10000 \advance\futurecost by\badness \else\ifnum\badness=10000 \futurecost=100000 \else \futurecost=10000000 % infinity \fi\fi \else \futurecost=10000 % this case is not in Knuth's formula !?? \fi\fi \else \futurecost=10000000 % infinity \fi % track the leastcost up to now and % set showprevgraf to the current value of myprevgraf \ifnum\futurecost>\leastcost\else \global\leastcost=\futurecost \global\showprevgraf=\myprevgraf \fi % show some debugging info \inform } \def\inform{\ifverbose\immediate\write16{% \space myprevgraf=\the\myprevgraf \space showprevgraf=\the\showprevgraf \space futurecost=\the\futurecost \space leastcost=\the\leastcost}\fi } % at the end of all input we will need \showprevgraf to be \myprevgraf % \supereject is called by \bye % and explicitly by the textboxes() method \edef\savesupereject{\supereject} \def\supereject{\global\showprevgraf=\myprevgraf\savesupereject} % save whatever someone said to be the output routine % \plainoutput uses \makeheadline and \makefootline \newtoks\saveoutput \def\makeheadline{} \def\makefootline{} \saveoutput=\expandafter{\the\output} \def\linemarker{\PyXMarker{start@\the\parno@\the\myprevgraf}} \output={% \tempcnt=\deadcycles \advance\tempcnt by-1 \deadcycles=\tempcnt% \razor=-50000 \ifnum\outputpenalty>\razor %%%%%%%%%% End of the page %%%%%%%%%% \immediate\write16{PyXVariableBox:page=\the\pageno,par=\the\parno,prevgraf=\the\showprevgraf:}% % reset showprevgraf \global\showprevgraf=\myprevgraf \tempcnt=\deadcycles \advance\tempcnt by 1 \deadcycles=\tempcnt % set the outputtype % \global\outputtype=0 % this has no outputtype!! Otherwise, the outputtype of the last page is lost % e.g. makes % <\interlinepenalty (1)> <\predisplaypenalty (should be 5, not 2)> % after the page has been shipped out, we need a new leastcost \global\leastcost=10000000 % do whatever someone told to be the output routine \the\saveoutput % and change the \hsize and \vsize \cdr\lovsizes \cdr\lohsizes \else\advance\razor by -100000 \ifnum\outputpenalty>\razor %%%%%%%%%% InterLinePenalty: -100000 %%%%%%%%%% \ifverbose\immediate\write16{******** InterLinePenalty ********}\fi \global\advance\myprevgraf by 1 % this will be the cost in the next page break finding: \setshowprevgraf{100000} % set the outputtype \global\outputtype=1 % and re-inject the whole page with the original penalty \unvbox255 \linemarker % \setbox0=\lastbox% % \setbox0=\hbox to \the\wd0{\PyXMarker{start@\the\parno@\the\myprevgraf}% % \unhbox0% % \PyXMarker{end@\the\parno@\the\myprevgraf}}% % \nointerlineskip\box0% \advance\outputpenalty by 100000 \penalty\outputpenalty \else\advance\razor by -100000 \ifnum\outputpenalty>\razor %%%%%%%%%% PreDisplayPenalty: -200000 %%%%%%%%%% \ifverbose\immediate\write16{******** PreDisplayPenalty ********}\fi \ifnum\outputtype=1 \global\advance\myprevgraf by 1 % this is for the last preceding text line \global\outputtype=5 % this will be the cost in the next page break finding: \setshowprevgraf{200000} \else\ifnum\outputtype=4 \global\advance\myprevgraf by 1 % this is for the first line of the current par % which has no interlinepenalty \global\outputtype=2 % this will be the cost in the next page break finding: \setshowprevgraf{200000} \else \global\outputtype=2 \def\linemarker{} \fi\fi % and re-inject the whole page with the original penalty \unvbox255 \linemarker \advance\outputpenalty by 200000 \penalty\outputpenalty \else\advance\razor by -100000 \ifnum\outputpenalty>\razor %%%%%%%%%% PostDisplayPenalty: -300000 %%%%%%%%%% \ifverbose\immediate\write16{******** PostDisplayPenalty ********}\fi \global\advance\myprevgraf by 3 % all prevgraf for the display comes here, not in PreDisplayPenalty % this will be the cost in the next page break finding: \setshowprevgraf{300000} % set the outputtype \global\outputtype=3 % and re-inject the whole page with the original penalty \unvbox255 \linemarker \advance\outputpenalty by 300000 \penalty\outputpenalty \else\advance\razor by -100000 \ifnum\outputpenalty>\razor %%%%%%%%%% end of the paragraph: \penalty-400000 %%%%%%%%%% \ifverbose\immediate\write16{******** Penalty ********}\fi \global\advance\myprevgraf by 1 % this will be the cost in the next page break finding: \setshowprevgraf{400000} \global\outputtype=4 % and re-inject the whole page with the original penalty \unvbox255 \linemarker \advance\outputpenalty by 400000 \penalty\outputpenalty \else %%%%%%%%%% some stuff unknown to us %%%%%%%%%% \immediate\write16{******** VEEEEEEERY negative value of outputpenalty: ERROR? ********}% \unvbox255 \tempcnt=\deadcycles\advance\tempcnt by 1 \deadcycles=\tempcnt \fi\fi\fi\fi\fi} % }}} % % We have to reset certain things at the beginning of {{{ % every paragraph: Hook into it with \everypar \newtoks\saveeverypar \saveeverypar=\expandafter{\the\everypar} \everypar={% \global\advance\parno by 1 \global\myprevgraf=0 \global\showprevgraf=0 % \global\leastcost=10000000 % check if the following paragraph will need a \parshape % if yes, say the first token of \parshapes % if no, restore the parno number into \parnos. % This has to come in \everypar to avoid content after the last \par \tempcnt=\numcdr\parnos \ifnum\tempcnt=\parno \cdr\parshapes \else \numconcat\tempcnt\parnos \fi %PAR--\the\parno--% \the\saveeverypar} % }}} % % \par calls the pagebuilder and \output {{{ % We wrap the \par primitive % - set \interlinepenalty first and reset it afterwards % - call \output another time for the last line of the paragraph \let\savepar\par \def\par{% \ifvmode\savepar\else\ifinner\savepar\else % \global\leastcost=10000000 \advance\interlinepenalty by -100000 \vadjust{\penalty-400000}% \savepar \advance\interlinepenalty by 100000 \fi\fi} % }}} % % $$ also calls the pagebuilder and \output {{{ % We wrap these characters with newly defined commands % \display and \enddisplay % XXX Can $ be redefined to achieve the same result? % - $$ (begin) calls the pagebuilder for the previous text % we have to do similar things as in \par % - $$ (end) calls the pagebuilder for the display math % we have to adjust \predisplaypenalty and \postdisplaypenalty % XXX Has \interdisplaylinepenalty any effect on \prevgraf ? \def\display{% % \global\leastcost=10000000 \global\advance\interlinepenalty by -100000 $$% \global\advance\interlinepenalty by 100000\relax} \def\enddisplay{% % \global\leastcost=10000000 \global\advance\predisplaypenalty by -200000 \global\advance\postdisplaypenalty by -300000 $$% \global\advance\predisplaypenalty by 200000 \global\advance\postdisplaypenalty by 300000\relax} % }}} % % vim:fdm=marker PyX-0.14.1/examples/0000755000076500000240000000000012615763300014352 5ustar andrestaff00000000000000PyX-0.14.1/examples/3dgraphs/0000755000076500000240000000000012615763300016065 5ustar andrestaff00000000000000PyX-0.14.1/examples/3dgraphs/bar.ipynb0000644000076500000240000014600412615761705017710 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Bar graphs in 3d" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nIlKX/wekYOFydZKzvgAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#!/usr/bin/env python\n", "from pyx import *\n", "\n", "g = graph.graphxyz(0, 0, size=5, x=graph.axis.bar(), y=graph.axis.bar(), z=None, z2=graph.axis.lin())\n", "g.plot(graph.data.data(graph.data.points([[1, 1, 1.4], [1, 2, 1.8], [2, 1, -0.5], [2, 2, 0.9]]), xname=1, yname=2, z2=3),\n", " [graph.style.barpos(fromvalue=0, frompathattrs=None), graph.style.bar(barattrs=[style.linejoin.bevel])])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The bar style can also be used in 3d graphs.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/3dgraphs/bar.py0000755000076500000240000000067312515656650017224 0ustar andrestaff00000000000000#!/usr/bin/env python from pyx import * g = graph.graphxyz(0, 0, size=5, x=graph.axis.bar(), y=graph.axis.bar(), z=None, z2=graph.axis.lin()) g.plot(graph.data.data(graph.data.points([[1, 1, 1.4], [1, 2, 1.8], [2, 1, -0.5], [2, 2, 0.9]]), xname=1, yname=2, z2=3), [graph.style.barpos(fromvalue=0, frompathattrs=None), graph.style.bar(barattrs=[style.linejoin.bevel])]) g.writeEPSfile("bar") g.writePDFfile("bar") g.writeSVGfile("bar") PyX-0.14.1/examples/3dgraphs/bar.txt0000644000076500000240000000007712037343664017403 0ustar andrestaff00000000000000Bar graphs in 3d The bar style can also be used in 3d graphs. PyX-0.14.1/examples/3dgraphs/color.dat0000644000076500000240000006516112037344757017717 0ustar andrestaff000000000000000 0 +2.744434246094877e-06 0 1 +2.518061584101027e-06 0 2 +1.759486087349929e-06 0 3 +9.970876191013776e-07 0 4 +3.824133190986796e-06 0 5 +2.975115378597332e-05 0 6 +1.699285851675448e-04 0 7 +6.720788024534639e-04 0 8 +1.792832060948163e-03 0 9 +3.200655253796644e-03 0 10 +3.816618683189747e-03 0 11 +3.032150111960852e-03 0 12 +1.590229109988915e-03 0 13 +5.326214926640671e-04 0 14 +9.904354320939544e-05 0 15 +9.357929797648389e-06 0 16 +9.904354320939544e-05 0 17 +5.326214926640671e-04 0 18 +1.590229109988915e-03 0 19 +3.032150111960852e-03 0 20 +3.816618683189747e-03 0 21 +3.200655253796644e-03 0 22 +1.792832060948163e-03 0 23 +6.720788024534639e-04 0 24 +1.699285851675448e-04 0 25 +2.975115378597332e-05 0 26 +3.824133190986796e-06 0 27 +9.970876191013776e-07 0 28 +1.759486087349929e-06 0 29 +2.518061584101027e-06 0 30 +2.744434246094877e-06 1 0 +1.653567652207974e-06 1 1 +2.080019415431434e-06 1 2 +2.256392327443844e-06 1 3 +2.353042222660531e-06 1 4 +4.658691276947686e-06 1 5 +2.435782462200616e-05 1 6 +1.490972431055931e-04 1 7 +6.377284017517769e-04 1 8 +1.771582235157512e-03 1 9 +3.225933640796166e-03 1 10 +3.906803557194595e-03 1 11 +3.197308254883010e-03 1 12 +1.817291725241250e-03 1 13 +7.630389801230493e-04 1 14 +2.807603469492349e-04 1 15 +1.608446672699473e-04 1 16 +2.807603469492349e-04 1 17 +7.630389801230493e-04 1 18 +1.817291725241250e-03 1 19 +3.197308254883010e-03 1 20 +3.906803557194595e-03 1 21 +3.225933640796166e-03 1 22 +1.771582235157512e-03 1 23 +6.377284017517769e-04 1 24 +1.490972431055931e-04 1 25 +2.435782462200616e-05 1 26 +4.658691276947686e-06 1 27 +2.353042222660531e-06 1 28 +2.256392327443844e-06 1 29 +2.080019415431434e-06 1 30 +1.653567652207974e-06 2 0 +4.903222446513287e-07 2 1 +1.470523991761591e-06 2 2 +2.270477656555739e-06 2 3 +1.893286577894258e-06 2 4 +8.875040369628528e-07 2 5 +1.382699095923903e-05 2 6 +1.323259508158545e-04 2 7 +6.252257214541712e-04 2 8 +1.780184015590029e-03 2 9 +3.259559977840245e-03 2 10 +3.952100806252818e-03 2 11 +3.252471803511440e-03 2 12 +1.899491987795393e-03 2 13 +8.762282695816127e-04 2 14 +4.087748017613867e-04 2 15 +2.912636182938809e-04 2 16 +4.087748017613867e-04 2 17 +8.762282695816127e-04 2 18 +1.899491987795393e-03 2 19 +3.252471803511440e-03 2 20 +3.952100806252818e-03 2 21 +3.259559977840245e-03 2 22 +1.780184015590029e-03 2 23 +6.252257214541712e-04 2 24 +1.323259508158545e-04 2 25 +1.382699095923903e-05 2 26 +8.875040369628528e-07 2 27 +1.893286577894258e-06 2 28 +2.270477656555739e-06 2 29 +1.470523991761591e-06 2 30 +4.903222446513287e-07 3 0 +2.525077324128639e-07 3 1 +1.411976960236152e-06 3 2 +2.585027402357342e-06 3 3 +2.455329005085701e-06 3 4 +1.524299827202244e-06 3 5 +1.730855351620528e-05 3 6 +1.485538901683144e-04 3 7 +6.672169413806638e-04 3 8 +1.845851704536038e-03 3 9 +3.314019707590146e-03 3 10 +3.938097395997995e-03 3 11 +3.137337133297499e-03 3 12 +1.714725940474006e-03 3 13 +6.894032775764756e-04 3 14 +2.562722332523367e-04 3 15 +1.572414788470460e-04 3 16 +2.562722332523367e-04 3 17 +6.894032775764756e-04 3 18 +1.714725940474006e-03 3 19 +3.137337133297499e-03 3 20 +3.938097395997995e-03 3 21 +3.314019707590146e-03 3 22 +1.845851704536038e-03 3 23 +6.672169413806638e-04 3 24 +1.485538901683144e-04 3 25 +1.730855351620528e-05 3 26 +1.524299827202244e-06 3 27 +2.455329005085701e-06 3 28 +2.585027402357342e-06 3 29 +1.411976960236152e-06 3 30 +2.525077324128639e-07 4 0 +1.226989384095427e-06 4 1 +2.143934503008343e-06 4 2 +3.419052137664231e-06 4 3 +5.044497070280032e-06 4 4 +1.019883325351201e-05 4 5 +4.134677767967157e-05 4 6 +2.024165951452637e-04 4 7 +7.595561633249549e-04 4 8 +1.957907998196094e-03 4 9 +3.390836776047649e-03 4 10 +3.907691866900613e-03 4 11 +2.958824680334640e-03 4 12 +1.433416637054468e-03 4 13 +4.183160198044826e-04 4 14 +6.825032672642671e-05 4 15 +1.565122491813854e-05 4 16 +6.825032672642671e-05 4 17 +4.183160198044826e-04 4 18 +1.433416637054468e-03 4 19 +2.958824680334640e-03 4 20 +3.907691866900613e-03 4 21 +3.390836776047649e-03 4 22 +1.957907998196094e-03 4 23 +7.595561633249549e-04 4 24 +2.024165951452637e-04 4 25 +4.134677767967157e-05 4 26 +1.019883325351201e-05 4 27 +5.044497070280032e-06 4 28 +3.419052137664231e-06 4 29 +2.143934503008343e-06 4 30 +1.226989384095427e-06 5 0 +2.307317576927403e-06 5 1 +2.716699175289595e-06 5 2 +3.392503181823541e-06 5 3 +5.499844452398325e-06 5 4 +1.535221942328690e-05 5 5 +6.146497948927013e-05 5 6 +2.527173255797678e-04 5 7 +8.466746072201876e-04 5 8 +2.063200871238251e-03 5 9 +3.474385548526664e-03 5 10 +3.926889486415615e-03 5 11 +2.892497988275950e-03 5 12 +1.312540781600459e-03 5 13 +3.136255923160151e-04 5 14 +2.172446734687579e-05 5 15 +7.019738683128956e-09 5 16 +2.172446734687579e-05 5 17 +3.136255923160151e-04 5 18 +1.312540781600459e-03 5 19 +2.892497988275950e-03 5 20 +3.926889486415615e-03 5 21 +3.474385548526664e-03 5 22 +2.063200871238251e-03 5 23 +8.466746072201876e-04 5 24 +2.527173255797678e-04 5 25 +6.146497948927013e-05 5 26 +1.535221942328690e-05 5 27 +5.499844452398325e-06 5 28 +3.392503181823541e-06 5 29 +2.716699175289595e-06 5 30 +2.307317576927403e-06 6 0 +2.373332825254899e-06 6 1 +2.321653560233388e-06 6 2 +1.822958685202512e-06 6 3 +1.998034295855592e-06 6 4 +1.070244688479249e-05 6 5 +6.062668963464542e-05 6 6 +2.637758074029551e-04 6 7 +8.732926224204041e-04 6 8 +2.104254493353289e-03 6 9 +3.536589556516121e-03 6 10 +4.022793689595565e-03 6 11 +3.021560454986797e-03 6 12 +1.452268740872702e-03 6 13 +4.229684890191378e-04 6 14 +7.183483566560646e-05 6 15 +1.825194993036989e-05 6 16 +7.183483566560646e-05 6 17 +4.229684890191378e-04 6 18 +1.452268740872702e-03 6 19 +3.021560454986797e-03 6 20 +4.022793689595565e-03 6 21 +3.536589556516121e-03 6 22 +2.104254493353289e-03 6 23 +8.732926224204041e-04 6 24 +2.637758074029551e-04 6 25 +6.062668963464542e-05 6 26 +1.070244688479249e-05 6 27 +1.998034295855592e-06 6 28 +1.822958685202512e-06 6 29 +2.321653560233388e-06 6 30 +2.373332825254899e-06 7 0 +1.587195130150310e-06 7 1 +1.713658780206171e-06 7 2 +9.411594223291881e-07 7 3 +6.776789721331578e-08 7 4 +6.860825504386979e-06 7 5 +5.146201467104523e-05 7 6 +2.396166831456199e-04 7 7 +8.264643309087650e-04 7 8 +2.056438818405584e-03 7 9 +3.549963363240440e-03 7 10 +4.156944303260867e-03 7 11 +3.275907813144717e-03 7 12 +1.756915148324869e-03 7 13 +6.844759133332523e-04 7 14 +2.464153674380294e-04 7 15 +1.495346760772398e-04 7 16 +2.464153674380294e-04 7 17 +6.844759133332523e-04 7 18 +1.756915148324869e-03 7 19 +3.275907813144717e-03 7 20 +4.156944303260867e-03 7 21 +3.549963363240440e-03 7 22 +2.056438818405584e-03 7 23 +8.264643309087650e-04 7 24 +2.396166831456199e-04 7 25 +5.146201467104523e-05 7 26 +6.860825504386979e-06 7 27 +6.776789721331578e-08 7 28 +9.411594223291881e-07 7 29 +1.713658780206171e-06 7 30 +1.587195130150310e-06 8 0 +5.842895768532483e-07 8 1 +1.514582924947651e-06 8 2 +1.918239459944766e-06 8 3 +2.478661441644039e-06 8 4 +8.932418369414274e-06 8 5 +4.159804448997610e-05 8 6 +1.917917504088143e-04 8 7 +7.237846411730068e-04 8 8 +1.937637574805104e-03 8 9 +3.510202961653063e-03 8 10 +4.266350475238421e-03 8 11 +3.503586015126449e-03 8 12 +1.998570138710667e-03 8 13 +8.585196678491770e-04 8 14 +3.479814933876024e-04 8 15 +2.236338486521513e-04 8 16 +3.479814933876024e-04 8 17 +8.585196678491770e-04 8 18 +1.998570138710667e-03 8 19 +3.503586015126449e-03 8 20 +4.266350475238421e-03 8 21 +3.510202961653063e-03 8 22 +1.937637574805104e-03 8 23 +7.237846411730068e-04 8 24 +1.917917504088143e-04 8 25 +4.159804448997610e-05 8 26 +8.932418369414274e-06 8 27 +2.478661441644039e-06 8 28 +1.918239459944766e-06 8 29 +1.514582924947651e-06 8 30 +5.842895768532483e-07 9 0 +3.642883870758245e-07 9 1 +2.053202999470949e-06 9 2 +3.837166158545995e-06 9 3 +5.348894469071784e-06 9 4 +7.858828200887174e-06 9 5 +2.145531964264211e-05 9 6 +1.278998893281748e-04 9 7 +6.057443575635683e-04 9 8 +1.807819709990386e-03 9 9 +3.456094204549144e-03 9 10 +4.332932758161096e-03 9 11 +3.623389816823501e-03 9 12 +2.054991941718712e-03 9 13 +8.036014751161785e-04 9 14 +2.166177170601839e-04 9 15 +6.915211547501020e-05 9 16 +2.166177170601839e-04 9 17 +8.036014751161785e-04 9 18 +2.054991941718712e-03 9 19 +3.623389816823501e-03 9 20 +4.332932758161096e-03 9 21 +3.456094204549144e-03 9 22 +1.807819709990386e-03 9 23 +6.057443575635683e-04 9 24 +1.278998893281748e-04 9 25 +2.145531964264211e-05 9 26 +7.858828200887174e-06 9 27 +5.348894469071784e-06 9 28 +3.837166158545995e-06 9 29 +2.053202999470949e-06 9 30 +3.642883870758245e-07 10 0 +2.512490246878957e-06 10 1 +4.396610854841844e-06 10 2 +6.575545000503195e-06 10 3 +7.083439501810090e-06 10 4 +3.470894493160968e-06 10 5 +2.622883261358829e-06 10 6 +8.709326319537562e-05 10 7 +5.447133938049011e-04 10 8 +1.752837291237968e-03 10 9 +3.455315221404786e-03 10 10 +4.398958252080046e-03 10 11 +3.686186997488258e-03 10 12 +2.037578409116048e-03 10 13 +7.234336912109821e-04 10 14 +1.396226098258371e-04 10 15 +7.543732908067557e-06 10 16 +1.396226098258371e-04 10 17 +7.234336912109821e-04 10 18 +2.037578409116048e-03 10 19 +3.686186997488258e-03 10 20 +4.398958252080046e-03 10 21 +3.455315221404786e-03 10 22 +1.752837291237968e-03 10 23 +5.447133938049011e-04 10 24 +8.709326319537562e-05 10 25 +2.622883261358829e-06 10 26 +3.470894493160968e-06 10 27 +7.083439501810090e-06 10 28 +6.575545000503195e-06 10 29 +4.396610854841844e-06 10 30 +2.512490246878957e-06 11 0 +6.815671315359540e-06 11 1 +8.264538431099037e-06 11 2 +1.005401247062773e-05 11 3 +1.059684653758765e-05 11 4 +8.755895107819839e-06 11 5 +1.555038478500510e-05 11 6 +1.170561839376850e-04 11 7 +5.962253896499082e-04 11 8 +1.824100571423304e-03 11 9 +3.550529315318575e-03 11 10 +4.513631727635005e-03 11 11 +3.777400017948165e-03 11 12 +2.069898556039909e-03 11 13 +7.321944395611375e-04 11 14 +1.800591890588128e-04 11 15 +7.252664246864497e-05 11 16 +1.800591890588128e-04 11 17 +7.321944395611375e-04 11 18 +2.069898556039909e-03 11 19 +3.777400017948165e-03 11 20 +4.513631727635005e-03 11 21 +3.550529315318575e-03 11 22 +1.824100571423304e-03 11 23 +5.962253896499082e-04 11 24 +1.170561839376850e-04 11 25 +1.555038478500510e-05 11 26 +8.755895107819839e-06 11 27 +1.059684653758765e-05 11 28 +1.005401247062773e-05 11 29 +8.264538431099037e-06 11 30 +6.815671315359540e-06 12 0 +9.749610156771229e-06 12 1 +1.055180001296198e-05 12 2 +1.180987001645569e-05 12 3 +1.395571025914737e-05 12 4 +2.057271886339045e-05 12 5 +5.026620068793996e-05 12 6 +1.931212798890028e-04 12 7 +7.199830460496915e-04 12 8 +1.978312822663844e-03 12 9 +3.714503821754403e-03 12 10 +4.680865749503483e-03 12 11 +3.932112021941086e-03 12 12 +2.178726369038801e-03 12 13 +7.706810332112831e-04 12 14 +1.501137773096962e-04 12 15 +1.261640298775073e-05 12 16 +1.501137773096962e-04 12 17 +7.706810332112831e-04 12 18 +2.178726369038801e-03 12 19 +3.932112021941086e-03 12 20 +4.680865749503483e-03 12 21 +3.714503821754403e-03 12 22 +1.978312822663844e-03 12 23 +7.199830460496915e-04 12 24 +1.931212798890028e-04 12 25 +5.026620068793996e-05 12 26 +2.057271886339045e-05 12 27 +1.395571025914737e-05 12 28 +1.180987001645569e-05 12 29 +1.055180001296198e-05 12 30 +9.749610156771229e-06 13 0 +8.490623059819040e-06 13 1 +8.799846154170221e-06 13 2 +8.994677966752248e-06 13 3 +1.010871017786102e-05 13 4 +1.870330300271311e-05 13 5 +6.084068161357250e-05 13 6 +2.356274475978317e-04 13 7 +8.098356562680192e-04 13 8 +2.107865874310841e-03 13 9 +3.865318650390775e-03 13 10 +4.852291507897281e-03 13 11 +4.126295330348602e-03 13 12 +2.369155320117100e-03 13 13 +9.147697022767272e-04 13 14 +2.308142003576141e-04 13 15 +6.328836926190641e-05 13 16 +2.308142003576141e-04 13 17 +9.147697022767272e-04 13 18 +2.369155320117100e-03 13 19 +4.126295330348602e-03 13 20 +4.852291507897281e-03 13 21 +3.865318650390775e-03 13 22 +2.107865874310841e-03 13 23 +8.098356562680192e-04 13 24 +2.356274475978317e-04 13 25 +6.084068161357250e-05 13 26 +1.870330300271311e-05 13 27 +1.010871017786102e-05 13 28 +8.994677966752248e-06 13 29 +8.799846154170221e-06 13 30 +8.490623059819040e-06 14 0 +4.687403389656196e-06 14 1 +5.079153114463964e-06 14 2 +4.497918246229313e-06 14 3 +2.774071303358379e-06 14 4 +5.904632068328592e-06 14 5 +4.270413859622926e-05 14 6 +2.207746257698169e-04 14 7 +8.135918874377782e-04 14 8 +2.139508173337537e-03 14 9 +3.927780870116436e-03 14 10 +4.956023042244558e-03 14 11 +4.277097097416137e-03 14 12 +2.546496865618815e-03 14 13 +1.093698356447127e-03 14 14 +4.092148715898557e-04 14 15 +2.440103587145870e-04 14 16 +4.092148715898557e-04 14 17 +1.093698356447127e-03 14 18 +2.546496865618815e-03 14 19 +4.277097097416137e-03 14 20 +4.956023042244558e-03 14 21 +3.927780870116436e-03 14 22 +2.139508173337537e-03 14 23 +8.135918874377782e-04 14 24 +2.207746257698169e-04 14 25 +4.270413859622926e-05 14 26 +5.904632068328592e-06 14 27 +2.774071303358379e-06 14 28 +4.497918246229313e-06 14 29 +5.079153114463964e-06 14 30 +4.687403389656196e-06 15 0 +1.501257749887276e-06 15 1 +2.435756825174617e-06 15 2 +2.411966242960009e-06 15 3 +7.157054724050202e-07 15 4 +1.716069852294603e-06 15 5 +3.013705168409485e-05 15 6 +1.904842036316344e-04 15 7 +7.619892865676402e-04 15 8 +2.077488033630016e-03 15 9 +3.878674705777598e-03 15 10 +4.943717078853101e-03 15 11 +4.303065526353173e-03 15 12 +2.573644579802008e-03 15 13 +1.075135802949144e-03 15 14 +3.350972364282421e-04 15 15 +1.464398667425757e-04 15 16 +3.350972364282421e-04 15 17 +1.075135802949144e-03 15 18 +2.573644579802008e-03 15 19 +4.303065526353173e-03 15 20 +4.943717078853101e-03 15 21 +3.878674705777598e-03 15 22 +2.077488033630016e-03 15 23 +7.619892865676402e-04 15 24 +1.904842036316344e-04 15 25 +3.013705168409485e-05 15 26 +1.716069852294603e-06 15 27 +7.157054724050202e-07 15 28 +2.411966242960009e-06 15 29 +2.435756825174617e-06 15 30 +1.501257749887276e-06 16 0 +2.323571591220434e-07 16 1 +1.393475802039957e-06 16 2 +2.091541786468290e-06 16 3 +2.126752993258124e-06 16 4 +4.835644738161436e-06 16 5 +2.852474621669622e-05 16 6 +1.659548141126014e-04 16 7 +6.933826714206772e-04 16 8 +1.963201825373199e-03 16 9 +3.743280998425761e-03 16 10 +4.819314315173870e-03 16 11 +4.206415709376830e-03 16 12 +2.492191540160578e-03 16 13 +9.778007064550418e-04 16 14 +2.051669934845689e-04 16 15 +7.791777078841276e-08 16 16 +2.051669934845689e-04 16 17 +9.778007064550418e-04 16 18 +2.492191540160578e-03 16 19 +4.206415709376830e-03 16 20 +4.819314315173870e-03 16 21 +3.743280998425761e-03 16 22 +1.963201825373199e-03 16 23 +6.933826714206772e-04 16 24 +1.659548141126014e-04 16 25 +2.852474621669622e-05 16 26 +4.835644738161436e-06 16 27 +2.126752993258124e-06 16 28 +2.091541786468290e-06 16 29 +1.393475802039957e-06 16 30 +2.323571591220434e-07 17 0 +6.534106903077690e-07 17 1 +1.487306123431552e-06 17 2 +1.979172297174789e-06 17 3 +1.976234205687681e-06 17 4 +3.531951296812328e-06 17 5 +2.095624840708503e-05 17 6 +1.382476024308607e-04 17 7 +6.241889811214583e-04 17 8 +1.838277343110348e-03 17 9 +3.567829091690213e-03 17 10 +4.619649049288467e-03 17 11 +4.029180994811406e-03 17 12 +2.389692813180007e-03 17 13 +9.801953064551853e-04 17 14 +3.010360683959697e-04 17 15 +1.339147984653232e-04 17 16 +3.010360683959697e-04 17 17 +9.801953064551853e-04 17 18 +2.389692813180007e-03 17 19 +4.029180994811406e-03 17 20 +4.619649049288467e-03 17 21 +3.567829091690213e-03 17 22 +1.838277343110348e-03 17 23 +6.241889811214583e-04 17 24 +1.382476024308607e-04 17 25 +2.095624840708503e-05 17 26 +3.531951296812328e-06 17 27 +1.976234205687681e-06 17 28 +1.979172297174789e-06 17 29 +1.487306123431552e-06 17 30 +6.534106903077690e-07 18 0 +1.876059361241538e-06 18 1 +2.057784840208347e-06 18 2 +1.777613271338336e-06 18 3 +8.699234969159874e-07 18 4 +1.968652577303025e-07 18 5 +1.208171122223021e-05 18 6 +1.171139379151092e-04 18 7 +5.767959563594669e-04 18 8 +1.740740070141123e-03 18 9 +3.396802527464631e-03 18 10 +4.382735284334756e-03 18 11 +3.786662133385478e-03 18 12 +2.219758764675431e-03 18 13 +9.142867897053784e-04 18 14 +3.110029558942641e-04 18 15 +1.692446500089834e-04 18 16 +3.110029558942641e-04 18 17 +9.142867897053784e-04 18 18 +2.219758764675431e-03 18 19 +3.786662133385478e-03 18 20 +4.382735284334756e-03 18 21 +3.396802527464631e-03 18 22 +1.740740070141123e-03 18 23 +5.767959563594669e-04 18 24 +1.171139379151092e-04 18 25 +1.208171122223021e-05 18 26 +1.968652577303025e-07 18 27 +8.699234969159874e-07 18 28 +1.777613271338336e-06 18 29 +2.057784840208347e-06 18 30 +1.876059361241538e-06 19 0 +3.062840789809967e-06 19 1 +2.527808076843036e-06 19 2 +1.633271973488836e-06 19 3 +9.736235185669393e-07 19 4 +1.380503967706013e-06 19 5 +1.469419689216322e-05 19 6 +1.207048147882760e-04 19 7 +5.719123589096748e-04 19 8 +1.692871022540258e-03 19 9 +3.256428719310688e-03 19 10 +4.139632891211538e-03 19 11 +3.504909208546127e-03 19 12 +1.982724381278589e-03 19 13 +7.402920491410022e-04 19 14 +1.617462685140096e-04 19 15 +2.053330572468854e-05 19 16 +1.617462685140096e-04 19 17 +7.402920491410022e-04 19 18 +1.982724381278589e-03 19 19 +3.504909208546127e-03 19 20 +4.139632891211538e-03 19 21 +3.256428719310688e-03 19 22 +1.692871022540258e-03 19 23 +5.719123589096748e-04 19 24 +1.207048147882760e-04 19 25 +1.469419689216322e-05 19 26 +1.380503967706013e-06 19 27 +9.736235185669393e-07 19 28 +1.633271973488836e-06 19 29 +2.527808076843036e-06 19 30 +3.062840789809967e-06 20 0 +3.965288889790357e-06 20 1 +2.752129060676672e-06 20 2 +1.161841016756794e-06 20 3 +5.701545853936663e-07 20 4 +3.098355792788597e-06 20 5 +2.353023458085338e-05 20 6 +1.431860973840122e-04 20 7 +6.003781224686864e-04 20 8 +1.683390907031591e-03 20 9 +3.145644377756497e-03 20 10 +3.912068929840578e-03 20 11 +3.233033884460954e-03 20 12 +1.771385768497788e-03 20 13 +6.375462234056684e-04 20 14 +1.434980619272460e-04 20 15 +3.195125662258565e-05 20 16 +1.434980619272460e-04 20 17 +6.375462234056684e-04 20 18 +1.771385768497788e-03 20 19 +3.233033884460954e-03 20 20 +3.912068929840578e-03 20 21 +3.145644377756497e-03 20 22 +1.683390907031591e-03 20 23 +6.003781224686864e-04 20 24 +1.431860973840122e-04 20 25 +2.353023458085338e-05 20 26 +3.098355792788597e-06 20 27 +5.701545853936663e-07 20 28 +1.161841016756794e-06 20 29 +2.752129060676672e-06 20 30 +3.965288889790357e-06 21 0 +4.809474577021396e-06 21 1 +3.265902127647575e-06 21 2 +1.153290298311127e-06 21 3 +1.734187798996243e-07 21 4 +4.307226170255345e-06 21 5 +3.268845994111086e-05 21 6 +1.673952798494322e-04 21 7 +6.297509875229867e-04 21 8 +1.674683627968040e-03 21 9 +3.043996694190472e-03 21 10 +3.709176492544443e-03 21 11 +2.997312013828311e-03 21 12 +1.599019952667030e-03 21 13 +5.728662937094130e-04 21 14 +1.609992934304200e-04 21 15 +7.737655471200314e-05 21 16 +1.609992934304200e-04 21 17 +5.728662937094130e-04 21 18 +1.599019952667030e-03 21 19 +2.997312013828311e-03 21 20 +3.709176492544443e-03 21 21 +3.043996694190472e-03 21 22 +1.674683627968040e-03 21 23 +6.297509875229867e-04 21 24 +1.673952798494322e-04 21 25 +3.268845994111086e-05 21 26 +4.307226170255345e-06 21 27 +1.734187798996243e-07 21 28 +1.153290298311127e-06 21 29 +3.265902127647575e-06 21 30 +4.809474577021396e-06 22 0 +5.555042869803733e-06 22 1 +4.420635368354199e-06 22 2 +3.028730507567648e-06 22 3 +3.100707295620601e-06 22 4 +9.243914480592160e-06 22 5 +4.087587045427118e-05 22 6 +1.760607022307088e-04 22 7 +6.247370338825327e-04 22 8 +1.629230426377810e-03 22 9 +2.933474132420932e-03 22 10 +3.538408480595143e-03 22 11 +2.811983434809747e-03 22 12 +1.451910099681378e-03 22 13 +4.768548007400953e-04 22 14 +9.099433778678653e-05 22 15 +1.171746709542609e-05 22 16 +9.099433778678653e-05 22 17 +4.768548007400953e-04 22 18 +1.451910099681378e-03 22 19 +2.811983434809747e-03 22 20 +3.538408480595143e-03 22 21 +2.933474132420932e-03 22 22 +1.629230426377810e-03 22 23 +6.247370338825327e-04 22 24 +1.760607022307088e-04 22 25 +4.087587045427118e-05 22 26 +9.243914480592160e-06 22 27 +3.100707295620601e-06 22 28 +3.028730507567648e-06 22 29 +4.420635368354199e-06 22 30 +5.555042869803733e-06 23 0 +5.404189672356805e-06 23 1 +4.892870830299098e-06 23 2 +4.557607934560358e-06 23 3 +5.537092541242136e-06 23 4 +1.083855203679700e-05 23 5 +3.547085934154473e-05 23 6 +1.510775020427121e-04 23 7 +5.676546615136151e-04 23 8 +1.538572432507774e-03 23 9 +2.819067621052516e-03 23 10 +3.417150766148686e-03 23 11 +2.705429500718680e-03 23 12 +1.374749562040417e-03 23 13 +4.333463453912217e-04 23 14 +7.941771000134053e-05 23 15 +1.479566369747944e-05 23 16 +7.941771000134053e-05 23 17 +4.333463453912217e-04 23 18 +1.374749562040417e-03 23 19 +2.705429500718680e-03 23 20 +3.417150766148686e-03 23 21 +2.819067621052516e-03 23 22 +1.538572432507774e-03 23 23 +5.676546615136151e-04 23 24 +1.510775020427121e-04 23 25 +3.547085934154473e-05 23 26 +1.083855203679700e-05 23 27 +5.537092541242136e-06 23 28 +4.557607934560358e-06 23 29 +4.892870830299098e-06 23 30 +5.404189672356805e-06 24 0 +3.955165536724783e-06 24 1 +3.584741991399201e-06 24 2 +3.508885372422360e-06 24 3 +3.939399145842972e-06 24 4 +4.822757117855054e-06 24 5 +1.528945559383431e-05 24 6 +1.028440676156929e-04 24 7 +4.865196638755525e-04 24 8 +1.440956718322974e-03 24 9 +2.733108955173010e-03 24 10 +3.366008382925306e-03 24 11 +2.697020398631471e-03 24 12 +1.391340841413025e-03 24 13 +4.489266759395228e-04 24 14 +8.931113109195366e-05 24 15 +2.423720573557286e-05 24 16 +8.931113109195366e-05 24 17 +4.489266759395228e-04 24 18 +1.391340841413025e-03 24 19 +2.697020398631471e-03 24 20 +3.366008382925306e-03 24 21 +2.733108955173010e-03 24 22 +1.440956718322974e-03 24 23 +4.865196638755525e-04 24 24 +1.028440676156929e-04 24 25 +1.528945559383431e-05 24 26 +4.822757117855054e-06 24 27 +3.939399145842972e-06 24 28 +3.508885372422360e-06 24 29 +3.584741991399201e-06 24 30 +3.955165536724783e-06 25 0 +2.214633245267957e-06 25 1 +1.585525169790331e-06 25 2 +1.483434350126737e-06 25 3 +1.972238971450125e-06 25 4 +8.239998404110594e-07 25 5 +3.274470653067594e-06 25 6 +7.580088249132948e-05 25 7 +4.457366278418717e-04 25 8 +1.401383271659800e-03 25 9 +2.715854393917418e-03 25 10 +3.391604051034845e-03 25 11 +2.775387360033505e-03 25 12 +1.495302570719864e-03 25 13 +5.208990796590071e-04 25 14 +9.956297062102457e-05 25 15 +4.074204269152465e-06 25 16 +9.956297062102457e-05 25 17 +5.208990796590071e-04 25 18 +1.495302570719864e-03 25 19 +2.775387360033505e-03 25 20 +3.391604051034845e-03 25 21 +2.715854393917418e-03 25 22 +1.401383271659800e-03 25 23 +4.457366278418717e-04 25 24 +7.580088249132948e-05 25 25 +3.274470653067594e-06 25 26 +8.239998404110594e-07 25 27 +1.972238971450125e-06 25 28 +1.483434350126737e-06 25 29 +1.585525169790331e-06 25 30 +2.214633245267957e-06 26 0 +1.270433760442372e-06 26 1 +3.916387056204372e-07 26 2 +2.231233391960010e-07 26 3 +1.503250077270970e-06 26 4 +3.125235105917701e-06 26 5 +1.232580616064923e-05 26 6 +9.755857943602422e-05 26 7 +4.851055857767528e-04 26 8 +1.457115907850736e-03 26 9 +2.782087863624691e-03 26 10 +3.471885190847275e-03 26 11 +2.885556868129979e-03 26 12 +1.636626067410123e-03 26 13 +6.667717289764138e-04 26 14 +2.263997570460314e-04 26 15 +1.189280941020137e-04 26 16 +2.263997570460314e-04 26 17 +6.667717289764138e-04 26 18 +1.636626067410123e-03 26 19 +2.885556868129979e-03 26 20 +3.471885190847275e-03 26 21 +2.782087863624691e-03 26 22 +1.457115907850736e-03 26 23 +4.851055857767528e-04 26 24 +9.755857943602422e-05 26 25 +1.232580616064923e-05 26 26 +3.125235105917701e-06 26 27 +1.503250077270970e-06 26 28 +2.231233391960010e-07 26 29 +3.916387056204372e-07 26 30 +1.270433760442372e-06 27 0 +1.299354594308245e-06 27 1 +5.522911269684502e-07 27 2 +4.619462725569895e-07 27 3 +2.265200690627976e-06 27 4 +8.097778286089136e-06 27 5 +3.240334951419666e-05 27 6 +1.498979407853844e-04 27 7 +5.803392722650569e-04 27 8 +1.582282591448272e-03 27 9 +2.903121917018245e-03 27 10 +3.560888391768400e-03 27 11 +2.942173666034896e-03 27 12 +1.681218578604672e-03 27 13 +7.183020985079531e-04 27 14 +2.890668649459803e-04 27 15 +1.861637286406668e-04 27 16 +2.890668649459803e-04 27 17 +7.183020985079531e-04 27 18 +1.681218578604672e-03 27 19 +2.942173666034896e-03 27 20 +3.560888391768400e-03 27 21 +2.903121917018245e-03 27 22 +1.582282591448272e-03 27 23 +5.803392722650569e-04 27 24 +1.498979407853844e-04 27 25 +3.240334951419666e-05 27 26 +8.097778286089136e-06 27 27 +2.265200690627976e-06 27 28 +4.619462725569895e-07 27 29 +5.522911269684502e-07 27 30 +1.299354594308245e-06 28 0 +2.040365887620211e-06 28 1 +1.650917666586412e-06 28 2 +1.774875725028040e-06 28 3 +3.556606295780957e-06 28 4 +1.121238171560661e-05 28 5 +4.596797846319543e-05 28 6 +1.924256950599667e-04 28 7 +6.695452279961972e-04 28 8 +1.710357891797661e-03 28 9 +3.026685345607163e-03 28 10 +3.623902514336288e-03 28 11 +2.912274546185048e-03 28 12 +1.573517463148064e-03 28 13 +5.814421846018108e-04 28 14 +1.585057189477723e-04 28 15 +6.269150114528087e-05 28 16 +1.585057189477723e-04 28 17 +5.814421846018108e-04 28 18 +1.573517463148064e-03 28 19 +2.912274546185048e-03 28 20 +3.623902514336288e-03 28 21 +3.026685345607163e-03 28 22 +1.710357891797661e-03 28 23 +6.695452279961972e-04 28 24 +1.924256950599667e-04 28 25 +4.596797846319543e-05 28 26 +1.121238171560661e-05 28 27 +3.556606295780957e-06 28 28 +1.774875725028040e-06 28 29 +1.650917666586412e-06 28 30 +2.040365887620211e-06 29 0 +2.889936412548378e-06 29 1 +2.523107656067143e-06 29 2 +2.137256869716177e-06 29 3 +2.408742209727751e-06 29 4 +7.837863399645522e-06 29 5 +4.293412664154757e-05 29 6 +2.012737823483604e-04 29 7 +7.094420933272181e-04 29 8 +1.788723143733490e-03 29 9 +3.116507360268357e-03 29 10 +3.668485365947303e-03 29 11 +2.864609577951840e-03 29 12 +1.444029026933867e-03 29 13 +4.403845160530417e-04 29 14 +6.521201643211877e-05 29 15 +2.389980714464935e-07 29 16 +6.521201643211877e-05 29 17 +4.403845160530417e-04 29 18 +1.444029026933867e-03 29 19 +2.864609577951840e-03 29 20 +3.668485365947303e-03 29 21 +3.116507360268357e-03 29 22 +1.788723143733490e-03 29 23 +7.094420933272181e-04 29 24 +2.012737823483604e-04 29 25 +4.293412664154757e-05 29 26 +7.837863399645522e-06 29 27 +2.408742209727751e-06 29 28 +2.137256869716177e-06 29 29 +2.523107656067143e-06 29 30 +2.889936412548378e-06 30 0 +3.189540008095353e-06 30 1 +2.665276215102024e-06 30 2 +1.538390887473923e-06 30 3 +2.126393704049059e-07 30 4 +2.872410902877456e-06 30 5 +3.332700529158972e-05 30 6 +1.874186897482456e-04 30 7 +7.023315789295831e-04 30 8 +1.808842702438711e-03 30 9 +3.169450767598823e-03 30 10 +3.727981450772813e-03 30 11 +2.895425157778220e-03 30 12 +1.436817970496205e-03 30 13 +4.198892675035715e-04 30 14 +6.131415667355502e-05 30 15 +9.736971670136333e-06 30 16 +6.131415667355502e-05 30 17 +4.198892675035715e-04 30 18 +1.436817970496205e-03 30 19 +2.895425157778220e-03 30 20 +3.727981450772813e-03 30 21 +3.169450767598823e-03 30 22 +1.808842702438711e-03 30 23 +7.023315789295831e-04 30 24 +1.874186897482456e-04 30 25 +3.332700529158972e-05 30 26 +2.872410902877456e-06 30 27 +2.126393704049059e-07 30 28 +1.538390887473923e-06 30 29 +2.665276215102024e-06 30 30 +3.189540008095353e-06 PyX-0.14.1/examples/3dgraphs/color.ipynb0000644000076500000240000212375512615761675020302 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# A colored surface" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nQEBAQEB3+P/A/1LICq/1HAAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#!/usr/bin/env python\n", "from pyx import *\n", "\n", "g = graph.graphxyz(size=4, projector=graph.graphxyz.parallel(170, 45))\n", "g.plot(graph.data.file(\"color.dat\", x=1, y=2, z=3, color=3),\n", " [graph.style.surface(gradient=color.gradient.RedGreen,\n", " gridcolor=color.rgb.black,\n", " backcolor=color.rgb.black)])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To add colors to the surface you need to pass color data to the plot command.\n", "As in this example, you can just reuse the z value. Alternatively you could\n", "pass some independend color data. \n", "\n", "To bring colors instead of black/white to the surface, you need to change the\n", "gradient. Be sure to use the same color space for the gridcolor and the\n", "backcolor too.\n", "\n", " In this example we also modified the projector. By that you can change the\n", "view angle, and you can also (as in this example) use a parallel projection\n", "instead of the default central projection. While the later looks more natural,\n", "a parallel projection keeps lines parallel independend from their depths. An\n", "very simple justification of the parallel projection is the vertical z axis,\n", "which stays vertical in the projection. Also the linear axes have equal\n", "distances between the ticks, which is not true for central projections.\n", "\n", " Skipping the value for the z component will allow you to plot this surface\n", "on a two-dimensional graph as well.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/3dgraphs/color.py0000755000076500000240000000064312515656652017575 0ustar andrestaff00000000000000#!/usr/bin/env python from pyx import * g = graph.graphxyz(size=4, projector=graph.graphxyz.parallel(170, 45)) g.plot(graph.data.file("color.dat", x=1, y=2, z=3, color=3), [graph.style.surface(gradient=color.gradient.RedGreen, gridcolor=color.rgb.black, backcolor=color.rgb.black)]) g.writeEPSfile("color") g.writePDFfile("color") g.writeSVGfile("color") PyX-0.14.1/examples/3dgraphs/color.txt0000644000076500000240000000177612037342027017754 0ustar andrestaff00000000000000A colored surface To add colors to the surface you need to pass color data to the plot command. As in this example, you can just reuse the z value. Alternatively you could pass some independend color data. ... To bring colors instead of black/white to the surface, you need to change the gradient. Be sure to use the same color space for the gridcolor and the backcolor too. ! In this example we also modified the projector. By that you can change the view angle, and you can also (as in this example) use a parallel projection instead of the default central projection. While the later looks more natural, a parallel projection keeps lines parallel independend from their depths. An very simple justification of the parallel projection is the vertical z axis, which stays vertical in the projection. Also the linear axes have equal distances between the ticks, which is not true for central projections. ! Skipping the value for the z component will allow you to plot this surface on a two-dimensional graph as well. PyX-0.14.1/examples/3dgraphs/grid.dat0000644000076500000240000006516112037344757017526 0ustar andrestaff000000000000000 0 +2.744434246094877e-06 0 1 +2.518061584101027e-06 0 2 +1.759486087349929e-06 0 3 +9.970876191013776e-07 0 4 +3.824133190986796e-06 0 5 +2.975115378597332e-05 0 6 +1.699285851675448e-04 0 7 +6.720788024534639e-04 0 8 +1.792832060948163e-03 0 9 +3.200655253796644e-03 0 10 +3.816618683189747e-03 0 11 +3.032150111960852e-03 0 12 +1.590229109988915e-03 0 13 +5.326214926640671e-04 0 14 +9.904354320939544e-05 0 15 +9.357929797648389e-06 0 16 +9.904354320939544e-05 0 17 +5.326214926640671e-04 0 18 +1.590229109988915e-03 0 19 +3.032150111960852e-03 0 20 +3.816618683189747e-03 0 21 +3.200655253796644e-03 0 22 +1.792832060948163e-03 0 23 +6.720788024534639e-04 0 24 +1.699285851675448e-04 0 25 +2.975115378597332e-05 0 26 +3.824133190986796e-06 0 27 +9.970876191013776e-07 0 28 +1.759486087349929e-06 0 29 +2.518061584101027e-06 0 30 +2.744434246094877e-06 1 0 +1.653567652207974e-06 1 1 +2.080019415431434e-06 1 2 +2.256392327443844e-06 1 3 +2.353042222660531e-06 1 4 +4.658691276947686e-06 1 5 +2.435782462200616e-05 1 6 +1.490972431055931e-04 1 7 +6.377284017517769e-04 1 8 +1.771582235157512e-03 1 9 +3.225933640796166e-03 1 10 +3.906803557194595e-03 1 11 +3.197308254883010e-03 1 12 +1.817291725241250e-03 1 13 +7.630389801230493e-04 1 14 +2.807603469492349e-04 1 15 +1.608446672699473e-04 1 16 +2.807603469492349e-04 1 17 +7.630389801230493e-04 1 18 +1.817291725241250e-03 1 19 +3.197308254883010e-03 1 20 +3.906803557194595e-03 1 21 +3.225933640796166e-03 1 22 +1.771582235157512e-03 1 23 +6.377284017517769e-04 1 24 +1.490972431055931e-04 1 25 +2.435782462200616e-05 1 26 +4.658691276947686e-06 1 27 +2.353042222660531e-06 1 28 +2.256392327443844e-06 1 29 +2.080019415431434e-06 1 30 +1.653567652207974e-06 2 0 +4.903222446513287e-07 2 1 +1.470523991761591e-06 2 2 +2.270477656555739e-06 2 3 +1.893286577894258e-06 2 4 +8.875040369628528e-07 2 5 +1.382699095923903e-05 2 6 +1.323259508158545e-04 2 7 +6.252257214541712e-04 2 8 +1.780184015590029e-03 2 9 +3.259559977840245e-03 2 10 +3.952100806252818e-03 2 11 +3.252471803511440e-03 2 12 +1.899491987795393e-03 2 13 +8.762282695816127e-04 2 14 +4.087748017613867e-04 2 15 +2.912636182938809e-04 2 16 +4.087748017613867e-04 2 17 +8.762282695816127e-04 2 18 +1.899491987795393e-03 2 19 +3.252471803511440e-03 2 20 +3.952100806252818e-03 2 21 +3.259559977840245e-03 2 22 +1.780184015590029e-03 2 23 +6.252257214541712e-04 2 24 +1.323259508158545e-04 2 25 +1.382699095923903e-05 2 26 +8.875040369628528e-07 2 27 +1.893286577894258e-06 2 28 +2.270477656555739e-06 2 29 +1.470523991761591e-06 2 30 +4.903222446513287e-07 3 0 +2.525077324128639e-07 3 1 +1.411976960236152e-06 3 2 +2.585027402357342e-06 3 3 +2.455329005085701e-06 3 4 +1.524299827202244e-06 3 5 +1.730855351620528e-05 3 6 +1.485538901683144e-04 3 7 +6.672169413806638e-04 3 8 +1.845851704536038e-03 3 9 +3.314019707590146e-03 3 10 +3.938097395997995e-03 3 11 +3.137337133297499e-03 3 12 +1.714725940474006e-03 3 13 +6.894032775764756e-04 3 14 +2.562722332523367e-04 3 15 +1.572414788470460e-04 3 16 +2.562722332523367e-04 3 17 +6.894032775764756e-04 3 18 +1.714725940474006e-03 3 19 +3.137337133297499e-03 3 20 +3.938097395997995e-03 3 21 +3.314019707590146e-03 3 22 +1.845851704536038e-03 3 23 +6.672169413806638e-04 3 24 +1.485538901683144e-04 3 25 +1.730855351620528e-05 3 26 +1.524299827202244e-06 3 27 +2.455329005085701e-06 3 28 +2.585027402357342e-06 3 29 +1.411976960236152e-06 3 30 +2.525077324128639e-07 4 0 +1.226989384095427e-06 4 1 +2.143934503008343e-06 4 2 +3.419052137664231e-06 4 3 +5.044497070280032e-06 4 4 +1.019883325351201e-05 4 5 +4.134677767967157e-05 4 6 +2.024165951452637e-04 4 7 +7.595561633249549e-04 4 8 +1.957907998196094e-03 4 9 +3.390836776047649e-03 4 10 +3.907691866900613e-03 4 11 +2.958824680334640e-03 4 12 +1.433416637054468e-03 4 13 +4.183160198044826e-04 4 14 +6.825032672642671e-05 4 15 +1.565122491813854e-05 4 16 +6.825032672642671e-05 4 17 +4.183160198044826e-04 4 18 +1.433416637054468e-03 4 19 +2.958824680334640e-03 4 20 +3.907691866900613e-03 4 21 +3.390836776047649e-03 4 22 +1.957907998196094e-03 4 23 +7.595561633249549e-04 4 24 +2.024165951452637e-04 4 25 +4.134677767967157e-05 4 26 +1.019883325351201e-05 4 27 +5.044497070280032e-06 4 28 +3.419052137664231e-06 4 29 +2.143934503008343e-06 4 30 +1.226989384095427e-06 5 0 +2.307317576927403e-06 5 1 +2.716699175289595e-06 5 2 +3.392503181823541e-06 5 3 +5.499844452398325e-06 5 4 +1.535221942328690e-05 5 5 +6.146497948927013e-05 5 6 +2.527173255797678e-04 5 7 +8.466746072201876e-04 5 8 +2.063200871238251e-03 5 9 +3.474385548526664e-03 5 10 +3.926889486415615e-03 5 11 +2.892497988275950e-03 5 12 +1.312540781600459e-03 5 13 +3.136255923160151e-04 5 14 +2.172446734687579e-05 5 15 +7.019738683128956e-09 5 16 +2.172446734687579e-05 5 17 +3.136255923160151e-04 5 18 +1.312540781600459e-03 5 19 +2.892497988275950e-03 5 20 +3.926889486415615e-03 5 21 +3.474385548526664e-03 5 22 +2.063200871238251e-03 5 23 +8.466746072201876e-04 5 24 +2.527173255797678e-04 5 25 +6.146497948927013e-05 5 26 +1.535221942328690e-05 5 27 +5.499844452398325e-06 5 28 +3.392503181823541e-06 5 29 +2.716699175289595e-06 5 30 +2.307317576927403e-06 6 0 +2.373332825254899e-06 6 1 +2.321653560233388e-06 6 2 +1.822958685202512e-06 6 3 +1.998034295855592e-06 6 4 +1.070244688479249e-05 6 5 +6.062668963464542e-05 6 6 +2.637758074029551e-04 6 7 +8.732926224204041e-04 6 8 +2.104254493353289e-03 6 9 +3.536589556516121e-03 6 10 +4.022793689595565e-03 6 11 +3.021560454986797e-03 6 12 +1.452268740872702e-03 6 13 +4.229684890191378e-04 6 14 +7.183483566560646e-05 6 15 +1.825194993036989e-05 6 16 +7.183483566560646e-05 6 17 +4.229684890191378e-04 6 18 +1.452268740872702e-03 6 19 +3.021560454986797e-03 6 20 +4.022793689595565e-03 6 21 +3.536589556516121e-03 6 22 +2.104254493353289e-03 6 23 +8.732926224204041e-04 6 24 +2.637758074029551e-04 6 25 +6.062668963464542e-05 6 26 +1.070244688479249e-05 6 27 +1.998034295855592e-06 6 28 +1.822958685202512e-06 6 29 +2.321653560233388e-06 6 30 +2.373332825254899e-06 7 0 +1.587195130150310e-06 7 1 +1.713658780206171e-06 7 2 +9.411594223291881e-07 7 3 +6.776789721331578e-08 7 4 +6.860825504386979e-06 7 5 +5.146201467104523e-05 7 6 +2.396166831456199e-04 7 7 +8.264643309087650e-04 7 8 +2.056438818405584e-03 7 9 +3.549963363240440e-03 7 10 +4.156944303260867e-03 7 11 +3.275907813144717e-03 7 12 +1.756915148324869e-03 7 13 +6.844759133332523e-04 7 14 +2.464153674380294e-04 7 15 +1.495346760772398e-04 7 16 +2.464153674380294e-04 7 17 +6.844759133332523e-04 7 18 +1.756915148324869e-03 7 19 +3.275907813144717e-03 7 20 +4.156944303260867e-03 7 21 +3.549963363240440e-03 7 22 +2.056438818405584e-03 7 23 +8.264643309087650e-04 7 24 +2.396166831456199e-04 7 25 +5.146201467104523e-05 7 26 +6.860825504386979e-06 7 27 +6.776789721331578e-08 7 28 +9.411594223291881e-07 7 29 +1.713658780206171e-06 7 30 +1.587195130150310e-06 8 0 +5.842895768532483e-07 8 1 +1.514582924947651e-06 8 2 +1.918239459944766e-06 8 3 +2.478661441644039e-06 8 4 +8.932418369414274e-06 8 5 +4.159804448997610e-05 8 6 +1.917917504088143e-04 8 7 +7.237846411730068e-04 8 8 +1.937637574805104e-03 8 9 +3.510202961653063e-03 8 10 +4.266350475238421e-03 8 11 +3.503586015126449e-03 8 12 +1.998570138710667e-03 8 13 +8.585196678491770e-04 8 14 +3.479814933876024e-04 8 15 +2.236338486521513e-04 8 16 +3.479814933876024e-04 8 17 +8.585196678491770e-04 8 18 +1.998570138710667e-03 8 19 +3.503586015126449e-03 8 20 +4.266350475238421e-03 8 21 +3.510202961653063e-03 8 22 +1.937637574805104e-03 8 23 +7.237846411730068e-04 8 24 +1.917917504088143e-04 8 25 +4.159804448997610e-05 8 26 +8.932418369414274e-06 8 27 +2.478661441644039e-06 8 28 +1.918239459944766e-06 8 29 +1.514582924947651e-06 8 30 +5.842895768532483e-07 9 0 +3.642883870758245e-07 9 1 +2.053202999470949e-06 9 2 +3.837166158545995e-06 9 3 +5.348894469071784e-06 9 4 +7.858828200887174e-06 9 5 +2.145531964264211e-05 9 6 +1.278998893281748e-04 9 7 +6.057443575635683e-04 9 8 +1.807819709990386e-03 9 9 +3.456094204549144e-03 9 10 +4.332932758161096e-03 9 11 +3.623389816823501e-03 9 12 +2.054991941718712e-03 9 13 +8.036014751161785e-04 9 14 +2.166177170601839e-04 9 15 +6.915211547501020e-05 9 16 +2.166177170601839e-04 9 17 +8.036014751161785e-04 9 18 +2.054991941718712e-03 9 19 +3.623389816823501e-03 9 20 +4.332932758161096e-03 9 21 +3.456094204549144e-03 9 22 +1.807819709990386e-03 9 23 +6.057443575635683e-04 9 24 +1.278998893281748e-04 9 25 +2.145531964264211e-05 9 26 +7.858828200887174e-06 9 27 +5.348894469071784e-06 9 28 +3.837166158545995e-06 9 29 +2.053202999470949e-06 9 30 +3.642883870758245e-07 10 0 +2.512490246878957e-06 10 1 +4.396610854841844e-06 10 2 +6.575545000503195e-06 10 3 +7.083439501810090e-06 10 4 +3.470894493160968e-06 10 5 +2.622883261358829e-06 10 6 +8.709326319537562e-05 10 7 +5.447133938049011e-04 10 8 +1.752837291237968e-03 10 9 +3.455315221404786e-03 10 10 +4.398958252080046e-03 10 11 +3.686186997488258e-03 10 12 +2.037578409116048e-03 10 13 +7.234336912109821e-04 10 14 +1.396226098258371e-04 10 15 +7.543732908067557e-06 10 16 +1.396226098258371e-04 10 17 +7.234336912109821e-04 10 18 +2.037578409116048e-03 10 19 +3.686186997488258e-03 10 20 +4.398958252080046e-03 10 21 +3.455315221404786e-03 10 22 +1.752837291237968e-03 10 23 +5.447133938049011e-04 10 24 +8.709326319537562e-05 10 25 +2.622883261358829e-06 10 26 +3.470894493160968e-06 10 27 +7.083439501810090e-06 10 28 +6.575545000503195e-06 10 29 +4.396610854841844e-06 10 30 +2.512490246878957e-06 11 0 +6.815671315359540e-06 11 1 +8.264538431099037e-06 11 2 +1.005401247062773e-05 11 3 +1.059684653758765e-05 11 4 +8.755895107819839e-06 11 5 +1.555038478500510e-05 11 6 +1.170561839376850e-04 11 7 +5.962253896499082e-04 11 8 +1.824100571423304e-03 11 9 +3.550529315318575e-03 11 10 +4.513631727635005e-03 11 11 +3.777400017948165e-03 11 12 +2.069898556039909e-03 11 13 +7.321944395611375e-04 11 14 +1.800591890588128e-04 11 15 +7.252664246864497e-05 11 16 +1.800591890588128e-04 11 17 +7.321944395611375e-04 11 18 +2.069898556039909e-03 11 19 +3.777400017948165e-03 11 20 +4.513631727635005e-03 11 21 +3.550529315318575e-03 11 22 +1.824100571423304e-03 11 23 +5.962253896499082e-04 11 24 +1.170561839376850e-04 11 25 +1.555038478500510e-05 11 26 +8.755895107819839e-06 11 27 +1.059684653758765e-05 11 28 +1.005401247062773e-05 11 29 +8.264538431099037e-06 11 30 +6.815671315359540e-06 12 0 +9.749610156771229e-06 12 1 +1.055180001296198e-05 12 2 +1.180987001645569e-05 12 3 +1.395571025914737e-05 12 4 +2.057271886339045e-05 12 5 +5.026620068793996e-05 12 6 +1.931212798890028e-04 12 7 +7.199830460496915e-04 12 8 +1.978312822663844e-03 12 9 +3.714503821754403e-03 12 10 +4.680865749503483e-03 12 11 +3.932112021941086e-03 12 12 +2.178726369038801e-03 12 13 +7.706810332112831e-04 12 14 +1.501137773096962e-04 12 15 +1.261640298775073e-05 12 16 +1.501137773096962e-04 12 17 +7.706810332112831e-04 12 18 +2.178726369038801e-03 12 19 +3.932112021941086e-03 12 20 +4.680865749503483e-03 12 21 +3.714503821754403e-03 12 22 +1.978312822663844e-03 12 23 +7.199830460496915e-04 12 24 +1.931212798890028e-04 12 25 +5.026620068793996e-05 12 26 +2.057271886339045e-05 12 27 +1.395571025914737e-05 12 28 +1.180987001645569e-05 12 29 +1.055180001296198e-05 12 30 +9.749610156771229e-06 13 0 +8.490623059819040e-06 13 1 +8.799846154170221e-06 13 2 +8.994677966752248e-06 13 3 +1.010871017786102e-05 13 4 +1.870330300271311e-05 13 5 +6.084068161357250e-05 13 6 +2.356274475978317e-04 13 7 +8.098356562680192e-04 13 8 +2.107865874310841e-03 13 9 +3.865318650390775e-03 13 10 +4.852291507897281e-03 13 11 +4.126295330348602e-03 13 12 +2.369155320117100e-03 13 13 +9.147697022767272e-04 13 14 +2.308142003576141e-04 13 15 +6.328836926190641e-05 13 16 +2.308142003576141e-04 13 17 +9.147697022767272e-04 13 18 +2.369155320117100e-03 13 19 +4.126295330348602e-03 13 20 +4.852291507897281e-03 13 21 +3.865318650390775e-03 13 22 +2.107865874310841e-03 13 23 +8.098356562680192e-04 13 24 +2.356274475978317e-04 13 25 +6.084068161357250e-05 13 26 +1.870330300271311e-05 13 27 +1.010871017786102e-05 13 28 +8.994677966752248e-06 13 29 +8.799846154170221e-06 13 30 +8.490623059819040e-06 14 0 +4.687403389656196e-06 14 1 +5.079153114463964e-06 14 2 +4.497918246229313e-06 14 3 +2.774071303358379e-06 14 4 +5.904632068328592e-06 14 5 +4.270413859622926e-05 14 6 +2.207746257698169e-04 14 7 +8.135918874377782e-04 14 8 +2.139508173337537e-03 14 9 +3.927780870116436e-03 14 10 +4.956023042244558e-03 14 11 +4.277097097416137e-03 14 12 +2.546496865618815e-03 14 13 +1.093698356447127e-03 14 14 +4.092148715898557e-04 14 15 +2.440103587145870e-04 14 16 +4.092148715898557e-04 14 17 +1.093698356447127e-03 14 18 +2.546496865618815e-03 14 19 +4.277097097416137e-03 14 20 +4.956023042244558e-03 14 21 +3.927780870116436e-03 14 22 +2.139508173337537e-03 14 23 +8.135918874377782e-04 14 24 +2.207746257698169e-04 14 25 +4.270413859622926e-05 14 26 +5.904632068328592e-06 14 27 +2.774071303358379e-06 14 28 +4.497918246229313e-06 14 29 +5.079153114463964e-06 14 30 +4.687403389656196e-06 15 0 +1.501257749887276e-06 15 1 +2.435756825174617e-06 15 2 +2.411966242960009e-06 15 3 +7.157054724050202e-07 15 4 +1.716069852294603e-06 15 5 +3.013705168409485e-05 15 6 +1.904842036316344e-04 15 7 +7.619892865676402e-04 15 8 +2.077488033630016e-03 15 9 +3.878674705777598e-03 15 10 +4.943717078853101e-03 15 11 +4.303065526353173e-03 15 12 +2.573644579802008e-03 15 13 +1.075135802949144e-03 15 14 +3.350972364282421e-04 15 15 +1.464398667425757e-04 15 16 +3.350972364282421e-04 15 17 +1.075135802949144e-03 15 18 +2.573644579802008e-03 15 19 +4.303065526353173e-03 15 20 +4.943717078853101e-03 15 21 +3.878674705777598e-03 15 22 +2.077488033630016e-03 15 23 +7.619892865676402e-04 15 24 +1.904842036316344e-04 15 25 +3.013705168409485e-05 15 26 +1.716069852294603e-06 15 27 +7.157054724050202e-07 15 28 +2.411966242960009e-06 15 29 +2.435756825174617e-06 15 30 +1.501257749887276e-06 16 0 +2.323571591220434e-07 16 1 +1.393475802039957e-06 16 2 +2.091541786468290e-06 16 3 +2.126752993258124e-06 16 4 +4.835644738161436e-06 16 5 +2.852474621669622e-05 16 6 +1.659548141126014e-04 16 7 +6.933826714206772e-04 16 8 +1.963201825373199e-03 16 9 +3.743280998425761e-03 16 10 +4.819314315173870e-03 16 11 +4.206415709376830e-03 16 12 +2.492191540160578e-03 16 13 +9.778007064550418e-04 16 14 +2.051669934845689e-04 16 15 +7.791777078841276e-08 16 16 +2.051669934845689e-04 16 17 +9.778007064550418e-04 16 18 +2.492191540160578e-03 16 19 +4.206415709376830e-03 16 20 +4.819314315173870e-03 16 21 +3.743280998425761e-03 16 22 +1.963201825373199e-03 16 23 +6.933826714206772e-04 16 24 +1.659548141126014e-04 16 25 +2.852474621669622e-05 16 26 +4.835644738161436e-06 16 27 +2.126752993258124e-06 16 28 +2.091541786468290e-06 16 29 +1.393475802039957e-06 16 30 +2.323571591220434e-07 17 0 +6.534106903077690e-07 17 1 +1.487306123431552e-06 17 2 +1.979172297174789e-06 17 3 +1.976234205687681e-06 17 4 +3.531951296812328e-06 17 5 +2.095624840708503e-05 17 6 +1.382476024308607e-04 17 7 +6.241889811214583e-04 17 8 +1.838277343110348e-03 17 9 +3.567829091690213e-03 17 10 +4.619649049288467e-03 17 11 +4.029180994811406e-03 17 12 +2.389692813180007e-03 17 13 +9.801953064551853e-04 17 14 +3.010360683959697e-04 17 15 +1.339147984653232e-04 17 16 +3.010360683959697e-04 17 17 +9.801953064551853e-04 17 18 +2.389692813180007e-03 17 19 +4.029180994811406e-03 17 20 +4.619649049288467e-03 17 21 +3.567829091690213e-03 17 22 +1.838277343110348e-03 17 23 +6.241889811214583e-04 17 24 +1.382476024308607e-04 17 25 +2.095624840708503e-05 17 26 +3.531951296812328e-06 17 27 +1.976234205687681e-06 17 28 +1.979172297174789e-06 17 29 +1.487306123431552e-06 17 30 +6.534106903077690e-07 18 0 +1.876059361241538e-06 18 1 +2.057784840208347e-06 18 2 +1.777613271338336e-06 18 3 +8.699234969159874e-07 18 4 +1.968652577303025e-07 18 5 +1.208171122223021e-05 18 6 +1.171139379151092e-04 18 7 +5.767959563594669e-04 18 8 +1.740740070141123e-03 18 9 +3.396802527464631e-03 18 10 +4.382735284334756e-03 18 11 +3.786662133385478e-03 18 12 +2.219758764675431e-03 18 13 +9.142867897053784e-04 18 14 +3.110029558942641e-04 18 15 +1.692446500089834e-04 18 16 +3.110029558942641e-04 18 17 +9.142867897053784e-04 18 18 +2.219758764675431e-03 18 19 +3.786662133385478e-03 18 20 +4.382735284334756e-03 18 21 +3.396802527464631e-03 18 22 +1.740740070141123e-03 18 23 +5.767959563594669e-04 18 24 +1.171139379151092e-04 18 25 +1.208171122223021e-05 18 26 +1.968652577303025e-07 18 27 +8.699234969159874e-07 18 28 +1.777613271338336e-06 18 29 +2.057784840208347e-06 18 30 +1.876059361241538e-06 19 0 +3.062840789809967e-06 19 1 +2.527808076843036e-06 19 2 +1.633271973488836e-06 19 3 +9.736235185669393e-07 19 4 +1.380503967706013e-06 19 5 +1.469419689216322e-05 19 6 +1.207048147882760e-04 19 7 +5.719123589096748e-04 19 8 +1.692871022540258e-03 19 9 +3.256428719310688e-03 19 10 +4.139632891211538e-03 19 11 +3.504909208546127e-03 19 12 +1.982724381278589e-03 19 13 +7.402920491410022e-04 19 14 +1.617462685140096e-04 19 15 +2.053330572468854e-05 19 16 +1.617462685140096e-04 19 17 +7.402920491410022e-04 19 18 +1.982724381278589e-03 19 19 +3.504909208546127e-03 19 20 +4.139632891211538e-03 19 21 +3.256428719310688e-03 19 22 +1.692871022540258e-03 19 23 +5.719123589096748e-04 19 24 +1.207048147882760e-04 19 25 +1.469419689216322e-05 19 26 +1.380503967706013e-06 19 27 +9.736235185669393e-07 19 28 +1.633271973488836e-06 19 29 +2.527808076843036e-06 19 30 +3.062840789809967e-06 20 0 +3.965288889790357e-06 20 1 +2.752129060676672e-06 20 2 +1.161841016756794e-06 20 3 +5.701545853936663e-07 20 4 +3.098355792788597e-06 20 5 +2.353023458085338e-05 20 6 +1.431860973840122e-04 20 7 +6.003781224686864e-04 20 8 +1.683390907031591e-03 20 9 +3.145644377756497e-03 20 10 +3.912068929840578e-03 20 11 +3.233033884460954e-03 20 12 +1.771385768497788e-03 20 13 +6.375462234056684e-04 20 14 +1.434980619272460e-04 20 15 +3.195125662258565e-05 20 16 +1.434980619272460e-04 20 17 +6.375462234056684e-04 20 18 +1.771385768497788e-03 20 19 +3.233033884460954e-03 20 20 +3.912068929840578e-03 20 21 +3.145644377756497e-03 20 22 +1.683390907031591e-03 20 23 +6.003781224686864e-04 20 24 +1.431860973840122e-04 20 25 +2.353023458085338e-05 20 26 +3.098355792788597e-06 20 27 +5.701545853936663e-07 20 28 +1.161841016756794e-06 20 29 +2.752129060676672e-06 20 30 +3.965288889790357e-06 21 0 +4.809474577021396e-06 21 1 +3.265902127647575e-06 21 2 +1.153290298311127e-06 21 3 +1.734187798996243e-07 21 4 +4.307226170255345e-06 21 5 +3.268845994111086e-05 21 6 +1.673952798494322e-04 21 7 +6.297509875229867e-04 21 8 +1.674683627968040e-03 21 9 +3.043996694190472e-03 21 10 +3.709176492544443e-03 21 11 +2.997312013828311e-03 21 12 +1.599019952667030e-03 21 13 +5.728662937094130e-04 21 14 +1.609992934304200e-04 21 15 +7.737655471200314e-05 21 16 +1.609992934304200e-04 21 17 +5.728662937094130e-04 21 18 +1.599019952667030e-03 21 19 +2.997312013828311e-03 21 20 +3.709176492544443e-03 21 21 +3.043996694190472e-03 21 22 +1.674683627968040e-03 21 23 +6.297509875229867e-04 21 24 +1.673952798494322e-04 21 25 +3.268845994111086e-05 21 26 +4.307226170255345e-06 21 27 +1.734187798996243e-07 21 28 +1.153290298311127e-06 21 29 +3.265902127647575e-06 21 30 +4.809474577021396e-06 22 0 +5.555042869803733e-06 22 1 +4.420635368354199e-06 22 2 +3.028730507567648e-06 22 3 +3.100707295620601e-06 22 4 +9.243914480592160e-06 22 5 +4.087587045427118e-05 22 6 +1.760607022307088e-04 22 7 +6.247370338825327e-04 22 8 +1.629230426377810e-03 22 9 +2.933474132420932e-03 22 10 +3.538408480595143e-03 22 11 +2.811983434809747e-03 22 12 +1.451910099681378e-03 22 13 +4.768548007400953e-04 22 14 +9.099433778678653e-05 22 15 +1.171746709542609e-05 22 16 +9.099433778678653e-05 22 17 +4.768548007400953e-04 22 18 +1.451910099681378e-03 22 19 +2.811983434809747e-03 22 20 +3.538408480595143e-03 22 21 +2.933474132420932e-03 22 22 +1.629230426377810e-03 22 23 +6.247370338825327e-04 22 24 +1.760607022307088e-04 22 25 +4.087587045427118e-05 22 26 +9.243914480592160e-06 22 27 +3.100707295620601e-06 22 28 +3.028730507567648e-06 22 29 +4.420635368354199e-06 22 30 +5.555042869803733e-06 23 0 +5.404189672356805e-06 23 1 +4.892870830299098e-06 23 2 +4.557607934560358e-06 23 3 +5.537092541242136e-06 23 4 +1.083855203679700e-05 23 5 +3.547085934154473e-05 23 6 +1.510775020427121e-04 23 7 +5.676546615136151e-04 23 8 +1.538572432507774e-03 23 9 +2.819067621052516e-03 23 10 +3.417150766148686e-03 23 11 +2.705429500718680e-03 23 12 +1.374749562040417e-03 23 13 +4.333463453912217e-04 23 14 +7.941771000134053e-05 23 15 +1.479566369747944e-05 23 16 +7.941771000134053e-05 23 17 +4.333463453912217e-04 23 18 +1.374749562040417e-03 23 19 +2.705429500718680e-03 23 20 +3.417150766148686e-03 23 21 +2.819067621052516e-03 23 22 +1.538572432507774e-03 23 23 +5.676546615136151e-04 23 24 +1.510775020427121e-04 23 25 +3.547085934154473e-05 23 26 +1.083855203679700e-05 23 27 +5.537092541242136e-06 23 28 +4.557607934560358e-06 23 29 +4.892870830299098e-06 23 30 +5.404189672356805e-06 24 0 +3.955165536724783e-06 24 1 +3.584741991399201e-06 24 2 +3.508885372422360e-06 24 3 +3.939399145842972e-06 24 4 +4.822757117855054e-06 24 5 +1.528945559383431e-05 24 6 +1.028440676156929e-04 24 7 +4.865196638755525e-04 24 8 +1.440956718322974e-03 24 9 +2.733108955173010e-03 24 10 +3.366008382925306e-03 24 11 +2.697020398631471e-03 24 12 +1.391340841413025e-03 24 13 +4.489266759395228e-04 24 14 +8.931113109195366e-05 24 15 +2.423720573557286e-05 24 16 +8.931113109195366e-05 24 17 +4.489266759395228e-04 24 18 +1.391340841413025e-03 24 19 +2.697020398631471e-03 24 20 +3.366008382925306e-03 24 21 +2.733108955173010e-03 24 22 +1.440956718322974e-03 24 23 +4.865196638755525e-04 24 24 +1.028440676156929e-04 24 25 +1.528945559383431e-05 24 26 +4.822757117855054e-06 24 27 +3.939399145842972e-06 24 28 +3.508885372422360e-06 24 29 +3.584741991399201e-06 24 30 +3.955165536724783e-06 25 0 +2.214633245267957e-06 25 1 +1.585525169790331e-06 25 2 +1.483434350126737e-06 25 3 +1.972238971450125e-06 25 4 +8.239998404110594e-07 25 5 +3.274470653067594e-06 25 6 +7.580088249132948e-05 25 7 +4.457366278418717e-04 25 8 +1.401383271659800e-03 25 9 +2.715854393917418e-03 25 10 +3.391604051034845e-03 25 11 +2.775387360033505e-03 25 12 +1.495302570719864e-03 25 13 +5.208990796590071e-04 25 14 +9.956297062102457e-05 25 15 +4.074204269152465e-06 25 16 +9.956297062102457e-05 25 17 +5.208990796590071e-04 25 18 +1.495302570719864e-03 25 19 +2.775387360033505e-03 25 20 +3.391604051034845e-03 25 21 +2.715854393917418e-03 25 22 +1.401383271659800e-03 25 23 +4.457366278418717e-04 25 24 +7.580088249132948e-05 25 25 +3.274470653067594e-06 25 26 +8.239998404110594e-07 25 27 +1.972238971450125e-06 25 28 +1.483434350126737e-06 25 29 +1.585525169790331e-06 25 30 +2.214633245267957e-06 26 0 +1.270433760442372e-06 26 1 +3.916387056204372e-07 26 2 +2.231233391960010e-07 26 3 +1.503250077270970e-06 26 4 +3.125235105917701e-06 26 5 +1.232580616064923e-05 26 6 +9.755857943602422e-05 26 7 +4.851055857767528e-04 26 8 +1.457115907850736e-03 26 9 +2.782087863624691e-03 26 10 +3.471885190847275e-03 26 11 +2.885556868129979e-03 26 12 +1.636626067410123e-03 26 13 +6.667717289764138e-04 26 14 +2.263997570460314e-04 26 15 +1.189280941020137e-04 26 16 +2.263997570460314e-04 26 17 +6.667717289764138e-04 26 18 +1.636626067410123e-03 26 19 +2.885556868129979e-03 26 20 +3.471885190847275e-03 26 21 +2.782087863624691e-03 26 22 +1.457115907850736e-03 26 23 +4.851055857767528e-04 26 24 +9.755857943602422e-05 26 25 +1.232580616064923e-05 26 26 +3.125235105917701e-06 26 27 +1.503250077270970e-06 26 28 +2.231233391960010e-07 26 29 +3.916387056204372e-07 26 30 +1.270433760442372e-06 27 0 +1.299354594308245e-06 27 1 +5.522911269684502e-07 27 2 +4.619462725569895e-07 27 3 +2.265200690627976e-06 27 4 +8.097778286089136e-06 27 5 +3.240334951419666e-05 27 6 +1.498979407853844e-04 27 7 +5.803392722650569e-04 27 8 +1.582282591448272e-03 27 9 +2.903121917018245e-03 27 10 +3.560888391768400e-03 27 11 +2.942173666034896e-03 27 12 +1.681218578604672e-03 27 13 +7.183020985079531e-04 27 14 +2.890668649459803e-04 27 15 +1.861637286406668e-04 27 16 +2.890668649459803e-04 27 17 +7.183020985079531e-04 27 18 +1.681218578604672e-03 27 19 +2.942173666034896e-03 27 20 +3.560888391768400e-03 27 21 +2.903121917018245e-03 27 22 +1.582282591448272e-03 27 23 +5.803392722650569e-04 27 24 +1.498979407853844e-04 27 25 +3.240334951419666e-05 27 26 +8.097778286089136e-06 27 27 +2.265200690627976e-06 27 28 +4.619462725569895e-07 27 29 +5.522911269684502e-07 27 30 +1.299354594308245e-06 28 0 +2.040365887620211e-06 28 1 +1.650917666586412e-06 28 2 +1.774875725028040e-06 28 3 +3.556606295780957e-06 28 4 +1.121238171560661e-05 28 5 +4.596797846319543e-05 28 6 +1.924256950599667e-04 28 7 +6.695452279961972e-04 28 8 +1.710357891797661e-03 28 9 +3.026685345607163e-03 28 10 +3.623902514336288e-03 28 11 +2.912274546185048e-03 28 12 +1.573517463148064e-03 28 13 +5.814421846018108e-04 28 14 +1.585057189477723e-04 28 15 +6.269150114528087e-05 28 16 +1.585057189477723e-04 28 17 +5.814421846018108e-04 28 18 +1.573517463148064e-03 28 19 +2.912274546185048e-03 28 20 +3.623902514336288e-03 28 21 +3.026685345607163e-03 28 22 +1.710357891797661e-03 28 23 +6.695452279961972e-04 28 24 +1.924256950599667e-04 28 25 +4.596797846319543e-05 28 26 +1.121238171560661e-05 28 27 +3.556606295780957e-06 28 28 +1.774875725028040e-06 28 29 +1.650917666586412e-06 28 30 +2.040365887620211e-06 29 0 +2.889936412548378e-06 29 1 +2.523107656067143e-06 29 2 +2.137256869716177e-06 29 3 +2.408742209727751e-06 29 4 +7.837863399645522e-06 29 5 +4.293412664154757e-05 29 6 +2.012737823483604e-04 29 7 +7.094420933272181e-04 29 8 +1.788723143733490e-03 29 9 +3.116507360268357e-03 29 10 +3.668485365947303e-03 29 11 +2.864609577951840e-03 29 12 +1.444029026933867e-03 29 13 +4.403845160530417e-04 29 14 +6.521201643211877e-05 29 15 +2.389980714464935e-07 29 16 +6.521201643211877e-05 29 17 +4.403845160530417e-04 29 18 +1.444029026933867e-03 29 19 +2.864609577951840e-03 29 20 +3.668485365947303e-03 29 21 +3.116507360268357e-03 29 22 +1.788723143733490e-03 29 23 +7.094420933272181e-04 29 24 +2.012737823483604e-04 29 25 +4.293412664154757e-05 29 26 +7.837863399645522e-06 29 27 +2.408742209727751e-06 29 28 +2.137256869716177e-06 29 29 +2.523107656067143e-06 29 30 +2.889936412548378e-06 30 0 +3.189540008095353e-06 30 1 +2.665276215102024e-06 30 2 +1.538390887473923e-06 30 3 +2.126393704049059e-07 30 4 +2.872410902877456e-06 30 5 +3.332700529158972e-05 30 6 +1.874186897482456e-04 30 7 +7.023315789295831e-04 30 8 +1.808842702438711e-03 30 9 +3.169450767598823e-03 30 10 +3.727981450772813e-03 30 11 +2.895425157778220e-03 30 12 +1.436817970496205e-03 30 13 +4.198892675035715e-04 30 14 +6.131415667355502e-05 30 15 +9.736971670136333e-06 30 16 +6.131415667355502e-05 30 17 +4.198892675035715e-04 30 18 +1.436817970496205e-03 30 19 +2.895425157778220e-03 30 20 +3.727981450772813e-03 30 21 +3.169450767598823e-03 30 22 +1.808842702438711e-03 30 23 +7.023315789295831e-04 30 24 +1.874186897482456e-04 30 25 +3.332700529158972e-05 30 26 +2.872410902877456e-06 30 27 +2.126393704049059e-07 30 28 +1.538390887473923e-06 30 29 +2.665276215102024e-06 30 30 +3.189540008095353e-06 PyX-0.14.1/examples/3dgraphs/grid.ipynb0000644000076500000240000042432012615761701020065 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Stroking the grid" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#!/usr/bin/env python\n", "from pyx import *\n", "\n", "g = graph.graphxyz(size=4, z=graph.axis.lin(min=0.001))\n", "g.plot(graph.data.file(\"grid.dat\", x=1, y=2, z=3), [graph.style.grid()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The grid as its created by PyX internally can also be stroked by means of the\n", "grid style. In this example the minimal value of the z axis was changed too. As\n", "lines are cut at graph boundaries properly, this results in a cutted grid. \n", "\n", " The surface style does not support cuts at the graph boundary. It'll always\n", "skip rectangles partially (or fully) outside of the graph.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/3dgraphs/grid.py0000755000076500000240000000035712515656654017410 0ustar andrestaff00000000000000#!/usr/bin/env python from pyx import * g = graph.graphxyz(size=4, z=graph.axis.lin(min=0.001)) g.plot(graph.data.file("grid.dat", x=1, y=2, z=3), [graph.style.grid()]) g.writeEPSfile("grid") g.writePDFfile("grid") g.writeSVGfile("grid") PyX-0.14.1/examples/3dgraphs/grid.txt0000644000076500000240000000061212037342027017547 0ustar andrestaff00000000000000Stroking the grid The grid as its created by PyX internally can also be stroked by means of the grid style. In this example the minimal value of the z axis was changed too. As lines are cut at graph boundaries properly, this results in a cutted grid. ... ! The surface style does not support cuts at the graph boundary. It'll always skip rectangles partially (or fully) outside of the graph. PyX-0.14.1/examples/3dgraphs/README0000644000076500000240000000047312037344757016762 0ustar andrestaff000000000000003d graphs 3d graphs are created by graphxyz instances. They behave quite similar to regular graphs. Various styles can be used on 3d graphs without further adjustment like the symbol, line, and errorbar styles. Beside that the surface and grid styles are available to handle 3d data defined on a rectangular grid. PyX-0.14.1/examples/3dgraphs/surface.dat0000644000076500000240000006516112037344757020231 0ustar andrestaff000000000000000 0 +2.744434246094877e-06 0 1 +2.518061584101027e-06 0 2 +1.759486087349929e-06 0 3 +9.970876191013776e-07 0 4 +3.824133190986796e-06 0 5 +2.975115378597332e-05 0 6 +1.699285851675448e-04 0 7 +6.720788024534639e-04 0 8 +1.792832060948163e-03 0 9 +3.200655253796644e-03 0 10 +3.816618683189747e-03 0 11 +3.032150111960852e-03 0 12 +1.590229109988915e-03 0 13 +5.326214926640671e-04 0 14 +9.904354320939544e-05 0 15 +9.357929797648389e-06 0 16 +9.904354320939544e-05 0 17 +5.326214926640671e-04 0 18 +1.590229109988915e-03 0 19 +3.032150111960852e-03 0 20 +3.816618683189747e-03 0 21 +3.200655253796644e-03 0 22 +1.792832060948163e-03 0 23 +6.720788024534639e-04 0 24 +1.699285851675448e-04 0 25 +2.975115378597332e-05 0 26 +3.824133190986796e-06 0 27 +9.970876191013776e-07 0 28 +1.759486087349929e-06 0 29 +2.518061584101027e-06 0 30 +2.744434246094877e-06 1 0 +1.653567652207974e-06 1 1 +2.080019415431434e-06 1 2 +2.256392327443844e-06 1 3 +2.353042222660531e-06 1 4 +4.658691276947686e-06 1 5 +2.435782462200616e-05 1 6 +1.490972431055931e-04 1 7 +6.377284017517769e-04 1 8 +1.771582235157512e-03 1 9 +3.225933640796166e-03 1 10 +3.906803557194595e-03 1 11 +3.197308254883010e-03 1 12 +1.817291725241250e-03 1 13 +7.630389801230493e-04 1 14 +2.807603469492349e-04 1 15 +1.608446672699473e-04 1 16 +2.807603469492349e-04 1 17 +7.630389801230493e-04 1 18 +1.817291725241250e-03 1 19 +3.197308254883010e-03 1 20 +3.906803557194595e-03 1 21 +3.225933640796166e-03 1 22 +1.771582235157512e-03 1 23 +6.377284017517769e-04 1 24 +1.490972431055931e-04 1 25 +2.435782462200616e-05 1 26 +4.658691276947686e-06 1 27 +2.353042222660531e-06 1 28 +2.256392327443844e-06 1 29 +2.080019415431434e-06 1 30 +1.653567652207974e-06 2 0 +4.903222446513287e-07 2 1 +1.470523991761591e-06 2 2 +2.270477656555739e-06 2 3 +1.893286577894258e-06 2 4 +8.875040369628528e-07 2 5 +1.382699095923903e-05 2 6 +1.323259508158545e-04 2 7 +6.252257214541712e-04 2 8 +1.780184015590029e-03 2 9 +3.259559977840245e-03 2 10 +3.952100806252818e-03 2 11 +3.252471803511440e-03 2 12 +1.899491987795393e-03 2 13 +8.762282695816127e-04 2 14 +4.087748017613867e-04 2 15 +2.912636182938809e-04 2 16 +4.087748017613867e-04 2 17 +8.762282695816127e-04 2 18 +1.899491987795393e-03 2 19 +3.252471803511440e-03 2 20 +3.952100806252818e-03 2 21 +3.259559977840245e-03 2 22 +1.780184015590029e-03 2 23 +6.252257214541712e-04 2 24 +1.323259508158545e-04 2 25 +1.382699095923903e-05 2 26 +8.875040369628528e-07 2 27 +1.893286577894258e-06 2 28 +2.270477656555739e-06 2 29 +1.470523991761591e-06 2 30 +4.903222446513287e-07 3 0 +2.525077324128639e-07 3 1 +1.411976960236152e-06 3 2 +2.585027402357342e-06 3 3 +2.455329005085701e-06 3 4 +1.524299827202244e-06 3 5 +1.730855351620528e-05 3 6 +1.485538901683144e-04 3 7 +6.672169413806638e-04 3 8 +1.845851704536038e-03 3 9 +3.314019707590146e-03 3 10 +3.938097395997995e-03 3 11 +3.137337133297499e-03 3 12 +1.714725940474006e-03 3 13 +6.894032775764756e-04 3 14 +2.562722332523367e-04 3 15 +1.572414788470460e-04 3 16 +2.562722332523367e-04 3 17 +6.894032775764756e-04 3 18 +1.714725940474006e-03 3 19 +3.137337133297499e-03 3 20 +3.938097395997995e-03 3 21 +3.314019707590146e-03 3 22 +1.845851704536038e-03 3 23 +6.672169413806638e-04 3 24 +1.485538901683144e-04 3 25 +1.730855351620528e-05 3 26 +1.524299827202244e-06 3 27 +2.455329005085701e-06 3 28 +2.585027402357342e-06 3 29 +1.411976960236152e-06 3 30 +2.525077324128639e-07 4 0 +1.226989384095427e-06 4 1 +2.143934503008343e-06 4 2 +3.419052137664231e-06 4 3 +5.044497070280032e-06 4 4 +1.019883325351201e-05 4 5 +4.134677767967157e-05 4 6 +2.024165951452637e-04 4 7 +7.595561633249549e-04 4 8 +1.957907998196094e-03 4 9 +3.390836776047649e-03 4 10 +3.907691866900613e-03 4 11 +2.958824680334640e-03 4 12 +1.433416637054468e-03 4 13 +4.183160198044826e-04 4 14 +6.825032672642671e-05 4 15 +1.565122491813854e-05 4 16 +6.825032672642671e-05 4 17 +4.183160198044826e-04 4 18 +1.433416637054468e-03 4 19 +2.958824680334640e-03 4 20 +3.907691866900613e-03 4 21 +3.390836776047649e-03 4 22 +1.957907998196094e-03 4 23 +7.595561633249549e-04 4 24 +2.024165951452637e-04 4 25 +4.134677767967157e-05 4 26 +1.019883325351201e-05 4 27 +5.044497070280032e-06 4 28 +3.419052137664231e-06 4 29 +2.143934503008343e-06 4 30 +1.226989384095427e-06 5 0 +2.307317576927403e-06 5 1 +2.716699175289595e-06 5 2 +3.392503181823541e-06 5 3 +5.499844452398325e-06 5 4 +1.535221942328690e-05 5 5 +6.146497948927013e-05 5 6 +2.527173255797678e-04 5 7 +8.466746072201876e-04 5 8 +2.063200871238251e-03 5 9 +3.474385548526664e-03 5 10 +3.926889486415615e-03 5 11 +2.892497988275950e-03 5 12 +1.312540781600459e-03 5 13 +3.136255923160151e-04 5 14 +2.172446734687579e-05 5 15 +7.019738683128956e-09 5 16 +2.172446734687579e-05 5 17 +3.136255923160151e-04 5 18 +1.312540781600459e-03 5 19 +2.892497988275950e-03 5 20 +3.926889486415615e-03 5 21 +3.474385548526664e-03 5 22 +2.063200871238251e-03 5 23 +8.466746072201876e-04 5 24 +2.527173255797678e-04 5 25 +6.146497948927013e-05 5 26 +1.535221942328690e-05 5 27 +5.499844452398325e-06 5 28 +3.392503181823541e-06 5 29 +2.716699175289595e-06 5 30 +2.307317576927403e-06 6 0 +2.373332825254899e-06 6 1 +2.321653560233388e-06 6 2 +1.822958685202512e-06 6 3 +1.998034295855592e-06 6 4 +1.070244688479249e-05 6 5 +6.062668963464542e-05 6 6 +2.637758074029551e-04 6 7 +8.732926224204041e-04 6 8 +2.104254493353289e-03 6 9 +3.536589556516121e-03 6 10 +4.022793689595565e-03 6 11 +3.021560454986797e-03 6 12 +1.452268740872702e-03 6 13 +4.229684890191378e-04 6 14 +7.183483566560646e-05 6 15 +1.825194993036989e-05 6 16 +7.183483566560646e-05 6 17 +4.229684890191378e-04 6 18 +1.452268740872702e-03 6 19 +3.021560454986797e-03 6 20 +4.022793689595565e-03 6 21 +3.536589556516121e-03 6 22 +2.104254493353289e-03 6 23 +8.732926224204041e-04 6 24 +2.637758074029551e-04 6 25 +6.062668963464542e-05 6 26 +1.070244688479249e-05 6 27 +1.998034295855592e-06 6 28 +1.822958685202512e-06 6 29 +2.321653560233388e-06 6 30 +2.373332825254899e-06 7 0 +1.587195130150310e-06 7 1 +1.713658780206171e-06 7 2 +9.411594223291881e-07 7 3 +6.776789721331578e-08 7 4 +6.860825504386979e-06 7 5 +5.146201467104523e-05 7 6 +2.396166831456199e-04 7 7 +8.264643309087650e-04 7 8 +2.056438818405584e-03 7 9 +3.549963363240440e-03 7 10 +4.156944303260867e-03 7 11 +3.275907813144717e-03 7 12 +1.756915148324869e-03 7 13 +6.844759133332523e-04 7 14 +2.464153674380294e-04 7 15 +1.495346760772398e-04 7 16 +2.464153674380294e-04 7 17 +6.844759133332523e-04 7 18 +1.756915148324869e-03 7 19 +3.275907813144717e-03 7 20 +4.156944303260867e-03 7 21 +3.549963363240440e-03 7 22 +2.056438818405584e-03 7 23 +8.264643309087650e-04 7 24 +2.396166831456199e-04 7 25 +5.146201467104523e-05 7 26 +6.860825504386979e-06 7 27 +6.776789721331578e-08 7 28 +9.411594223291881e-07 7 29 +1.713658780206171e-06 7 30 +1.587195130150310e-06 8 0 +5.842895768532483e-07 8 1 +1.514582924947651e-06 8 2 +1.918239459944766e-06 8 3 +2.478661441644039e-06 8 4 +8.932418369414274e-06 8 5 +4.159804448997610e-05 8 6 +1.917917504088143e-04 8 7 +7.237846411730068e-04 8 8 +1.937637574805104e-03 8 9 +3.510202961653063e-03 8 10 +4.266350475238421e-03 8 11 +3.503586015126449e-03 8 12 +1.998570138710667e-03 8 13 +8.585196678491770e-04 8 14 +3.479814933876024e-04 8 15 +2.236338486521513e-04 8 16 +3.479814933876024e-04 8 17 +8.585196678491770e-04 8 18 +1.998570138710667e-03 8 19 +3.503586015126449e-03 8 20 +4.266350475238421e-03 8 21 +3.510202961653063e-03 8 22 +1.937637574805104e-03 8 23 +7.237846411730068e-04 8 24 +1.917917504088143e-04 8 25 +4.159804448997610e-05 8 26 +8.932418369414274e-06 8 27 +2.478661441644039e-06 8 28 +1.918239459944766e-06 8 29 +1.514582924947651e-06 8 30 +5.842895768532483e-07 9 0 +3.642883870758245e-07 9 1 +2.053202999470949e-06 9 2 +3.837166158545995e-06 9 3 +5.348894469071784e-06 9 4 +7.858828200887174e-06 9 5 +2.145531964264211e-05 9 6 +1.278998893281748e-04 9 7 +6.057443575635683e-04 9 8 +1.807819709990386e-03 9 9 +3.456094204549144e-03 9 10 +4.332932758161096e-03 9 11 +3.623389816823501e-03 9 12 +2.054991941718712e-03 9 13 +8.036014751161785e-04 9 14 +2.166177170601839e-04 9 15 +6.915211547501020e-05 9 16 +2.166177170601839e-04 9 17 +8.036014751161785e-04 9 18 +2.054991941718712e-03 9 19 +3.623389816823501e-03 9 20 +4.332932758161096e-03 9 21 +3.456094204549144e-03 9 22 +1.807819709990386e-03 9 23 +6.057443575635683e-04 9 24 +1.278998893281748e-04 9 25 +2.145531964264211e-05 9 26 +7.858828200887174e-06 9 27 +5.348894469071784e-06 9 28 +3.837166158545995e-06 9 29 +2.053202999470949e-06 9 30 +3.642883870758245e-07 10 0 +2.512490246878957e-06 10 1 +4.396610854841844e-06 10 2 +6.575545000503195e-06 10 3 +7.083439501810090e-06 10 4 +3.470894493160968e-06 10 5 +2.622883261358829e-06 10 6 +8.709326319537562e-05 10 7 +5.447133938049011e-04 10 8 +1.752837291237968e-03 10 9 +3.455315221404786e-03 10 10 +4.398958252080046e-03 10 11 +3.686186997488258e-03 10 12 +2.037578409116048e-03 10 13 +7.234336912109821e-04 10 14 +1.396226098258371e-04 10 15 +7.543732908067557e-06 10 16 +1.396226098258371e-04 10 17 +7.234336912109821e-04 10 18 +2.037578409116048e-03 10 19 +3.686186997488258e-03 10 20 +4.398958252080046e-03 10 21 +3.455315221404786e-03 10 22 +1.752837291237968e-03 10 23 +5.447133938049011e-04 10 24 +8.709326319537562e-05 10 25 +2.622883261358829e-06 10 26 +3.470894493160968e-06 10 27 +7.083439501810090e-06 10 28 +6.575545000503195e-06 10 29 +4.396610854841844e-06 10 30 +2.512490246878957e-06 11 0 +6.815671315359540e-06 11 1 +8.264538431099037e-06 11 2 +1.005401247062773e-05 11 3 +1.059684653758765e-05 11 4 +8.755895107819839e-06 11 5 +1.555038478500510e-05 11 6 +1.170561839376850e-04 11 7 +5.962253896499082e-04 11 8 +1.824100571423304e-03 11 9 +3.550529315318575e-03 11 10 +4.513631727635005e-03 11 11 +3.777400017948165e-03 11 12 +2.069898556039909e-03 11 13 +7.321944395611375e-04 11 14 +1.800591890588128e-04 11 15 +7.252664246864497e-05 11 16 +1.800591890588128e-04 11 17 +7.321944395611375e-04 11 18 +2.069898556039909e-03 11 19 +3.777400017948165e-03 11 20 +4.513631727635005e-03 11 21 +3.550529315318575e-03 11 22 +1.824100571423304e-03 11 23 +5.962253896499082e-04 11 24 +1.170561839376850e-04 11 25 +1.555038478500510e-05 11 26 +8.755895107819839e-06 11 27 +1.059684653758765e-05 11 28 +1.005401247062773e-05 11 29 +8.264538431099037e-06 11 30 +6.815671315359540e-06 12 0 +9.749610156771229e-06 12 1 +1.055180001296198e-05 12 2 +1.180987001645569e-05 12 3 +1.395571025914737e-05 12 4 +2.057271886339045e-05 12 5 +5.026620068793996e-05 12 6 +1.931212798890028e-04 12 7 +7.199830460496915e-04 12 8 +1.978312822663844e-03 12 9 +3.714503821754403e-03 12 10 +4.680865749503483e-03 12 11 +3.932112021941086e-03 12 12 +2.178726369038801e-03 12 13 +7.706810332112831e-04 12 14 +1.501137773096962e-04 12 15 +1.261640298775073e-05 12 16 +1.501137773096962e-04 12 17 +7.706810332112831e-04 12 18 +2.178726369038801e-03 12 19 +3.932112021941086e-03 12 20 +4.680865749503483e-03 12 21 +3.714503821754403e-03 12 22 +1.978312822663844e-03 12 23 +7.199830460496915e-04 12 24 +1.931212798890028e-04 12 25 +5.026620068793996e-05 12 26 +2.057271886339045e-05 12 27 +1.395571025914737e-05 12 28 +1.180987001645569e-05 12 29 +1.055180001296198e-05 12 30 +9.749610156771229e-06 13 0 +8.490623059819040e-06 13 1 +8.799846154170221e-06 13 2 +8.994677966752248e-06 13 3 +1.010871017786102e-05 13 4 +1.870330300271311e-05 13 5 +6.084068161357250e-05 13 6 +2.356274475978317e-04 13 7 +8.098356562680192e-04 13 8 +2.107865874310841e-03 13 9 +3.865318650390775e-03 13 10 +4.852291507897281e-03 13 11 +4.126295330348602e-03 13 12 +2.369155320117100e-03 13 13 +9.147697022767272e-04 13 14 +2.308142003576141e-04 13 15 +6.328836926190641e-05 13 16 +2.308142003576141e-04 13 17 +9.147697022767272e-04 13 18 +2.369155320117100e-03 13 19 +4.126295330348602e-03 13 20 +4.852291507897281e-03 13 21 +3.865318650390775e-03 13 22 +2.107865874310841e-03 13 23 +8.098356562680192e-04 13 24 +2.356274475978317e-04 13 25 +6.084068161357250e-05 13 26 +1.870330300271311e-05 13 27 +1.010871017786102e-05 13 28 +8.994677966752248e-06 13 29 +8.799846154170221e-06 13 30 +8.490623059819040e-06 14 0 +4.687403389656196e-06 14 1 +5.079153114463964e-06 14 2 +4.497918246229313e-06 14 3 +2.774071303358379e-06 14 4 +5.904632068328592e-06 14 5 +4.270413859622926e-05 14 6 +2.207746257698169e-04 14 7 +8.135918874377782e-04 14 8 +2.139508173337537e-03 14 9 +3.927780870116436e-03 14 10 +4.956023042244558e-03 14 11 +4.277097097416137e-03 14 12 +2.546496865618815e-03 14 13 +1.093698356447127e-03 14 14 +4.092148715898557e-04 14 15 +2.440103587145870e-04 14 16 +4.092148715898557e-04 14 17 +1.093698356447127e-03 14 18 +2.546496865618815e-03 14 19 +4.277097097416137e-03 14 20 +4.956023042244558e-03 14 21 +3.927780870116436e-03 14 22 +2.139508173337537e-03 14 23 +8.135918874377782e-04 14 24 +2.207746257698169e-04 14 25 +4.270413859622926e-05 14 26 +5.904632068328592e-06 14 27 +2.774071303358379e-06 14 28 +4.497918246229313e-06 14 29 +5.079153114463964e-06 14 30 +4.687403389656196e-06 15 0 +1.501257749887276e-06 15 1 +2.435756825174617e-06 15 2 +2.411966242960009e-06 15 3 +7.157054724050202e-07 15 4 +1.716069852294603e-06 15 5 +3.013705168409485e-05 15 6 +1.904842036316344e-04 15 7 +7.619892865676402e-04 15 8 +2.077488033630016e-03 15 9 +3.878674705777598e-03 15 10 +4.943717078853101e-03 15 11 +4.303065526353173e-03 15 12 +2.573644579802008e-03 15 13 +1.075135802949144e-03 15 14 +3.350972364282421e-04 15 15 +1.464398667425757e-04 15 16 +3.350972364282421e-04 15 17 +1.075135802949144e-03 15 18 +2.573644579802008e-03 15 19 +4.303065526353173e-03 15 20 +4.943717078853101e-03 15 21 +3.878674705777598e-03 15 22 +2.077488033630016e-03 15 23 +7.619892865676402e-04 15 24 +1.904842036316344e-04 15 25 +3.013705168409485e-05 15 26 +1.716069852294603e-06 15 27 +7.157054724050202e-07 15 28 +2.411966242960009e-06 15 29 +2.435756825174617e-06 15 30 +1.501257749887276e-06 16 0 +2.323571591220434e-07 16 1 +1.393475802039957e-06 16 2 +2.091541786468290e-06 16 3 +2.126752993258124e-06 16 4 +4.835644738161436e-06 16 5 +2.852474621669622e-05 16 6 +1.659548141126014e-04 16 7 +6.933826714206772e-04 16 8 +1.963201825373199e-03 16 9 +3.743280998425761e-03 16 10 +4.819314315173870e-03 16 11 +4.206415709376830e-03 16 12 +2.492191540160578e-03 16 13 +9.778007064550418e-04 16 14 +2.051669934845689e-04 16 15 +7.791777078841276e-08 16 16 +2.051669934845689e-04 16 17 +9.778007064550418e-04 16 18 +2.492191540160578e-03 16 19 +4.206415709376830e-03 16 20 +4.819314315173870e-03 16 21 +3.743280998425761e-03 16 22 +1.963201825373199e-03 16 23 +6.933826714206772e-04 16 24 +1.659548141126014e-04 16 25 +2.852474621669622e-05 16 26 +4.835644738161436e-06 16 27 +2.126752993258124e-06 16 28 +2.091541786468290e-06 16 29 +1.393475802039957e-06 16 30 +2.323571591220434e-07 17 0 +6.534106903077690e-07 17 1 +1.487306123431552e-06 17 2 +1.979172297174789e-06 17 3 +1.976234205687681e-06 17 4 +3.531951296812328e-06 17 5 +2.095624840708503e-05 17 6 +1.382476024308607e-04 17 7 +6.241889811214583e-04 17 8 +1.838277343110348e-03 17 9 +3.567829091690213e-03 17 10 +4.619649049288467e-03 17 11 +4.029180994811406e-03 17 12 +2.389692813180007e-03 17 13 +9.801953064551853e-04 17 14 +3.010360683959697e-04 17 15 +1.339147984653232e-04 17 16 +3.010360683959697e-04 17 17 +9.801953064551853e-04 17 18 +2.389692813180007e-03 17 19 +4.029180994811406e-03 17 20 +4.619649049288467e-03 17 21 +3.567829091690213e-03 17 22 +1.838277343110348e-03 17 23 +6.241889811214583e-04 17 24 +1.382476024308607e-04 17 25 +2.095624840708503e-05 17 26 +3.531951296812328e-06 17 27 +1.976234205687681e-06 17 28 +1.979172297174789e-06 17 29 +1.487306123431552e-06 17 30 +6.534106903077690e-07 18 0 +1.876059361241538e-06 18 1 +2.057784840208347e-06 18 2 +1.777613271338336e-06 18 3 +8.699234969159874e-07 18 4 +1.968652577303025e-07 18 5 +1.208171122223021e-05 18 6 +1.171139379151092e-04 18 7 +5.767959563594669e-04 18 8 +1.740740070141123e-03 18 9 +3.396802527464631e-03 18 10 +4.382735284334756e-03 18 11 +3.786662133385478e-03 18 12 +2.219758764675431e-03 18 13 +9.142867897053784e-04 18 14 +3.110029558942641e-04 18 15 +1.692446500089834e-04 18 16 +3.110029558942641e-04 18 17 +9.142867897053784e-04 18 18 +2.219758764675431e-03 18 19 +3.786662133385478e-03 18 20 +4.382735284334756e-03 18 21 +3.396802527464631e-03 18 22 +1.740740070141123e-03 18 23 +5.767959563594669e-04 18 24 +1.171139379151092e-04 18 25 +1.208171122223021e-05 18 26 +1.968652577303025e-07 18 27 +8.699234969159874e-07 18 28 +1.777613271338336e-06 18 29 +2.057784840208347e-06 18 30 +1.876059361241538e-06 19 0 +3.062840789809967e-06 19 1 +2.527808076843036e-06 19 2 +1.633271973488836e-06 19 3 +9.736235185669393e-07 19 4 +1.380503967706013e-06 19 5 +1.469419689216322e-05 19 6 +1.207048147882760e-04 19 7 +5.719123589096748e-04 19 8 +1.692871022540258e-03 19 9 +3.256428719310688e-03 19 10 +4.139632891211538e-03 19 11 +3.504909208546127e-03 19 12 +1.982724381278589e-03 19 13 +7.402920491410022e-04 19 14 +1.617462685140096e-04 19 15 +2.053330572468854e-05 19 16 +1.617462685140096e-04 19 17 +7.402920491410022e-04 19 18 +1.982724381278589e-03 19 19 +3.504909208546127e-03 19 20 +4.139632891211538e-03 19 21 +3.256428719310688e-03 19 22 +1.692871022540258e-03 19 23 +5.719123589096748e-04 19 24 +1.207048147882760e-04 19 25 +1.469419689216322e-05 19 26 +1.380503967706013e-06 19 27 +9.736235185669393e-07 19 28 +1.633271973488836e-06 19 29 +2.527808076843036e-06 19 30 +3.062840789809967e-06 20 0 +3.965288889790357e-06 20 1 +2.752129060676672e-06 20 2 +1.161841016756794e-06 20 3 +5.701545853936663e-07 20 4 +3.098355792788597e-06 20 5 +2.353023458085338e-05 20 6 +1.431860973840122e-04 20 7 +6.003781224686864e-04 20 8 +1.683390907031591e-03 20 9 +3.145644377756497e-03 20 10 +3.912068929840578e-03 20 11 +3.233033884460954e-03 20 12 +1.771385768497788e-03 20 13 +6.375462234056684e-04 20 14 +1.434980619272460e-04 20 15 +3.195125662258565e-05 20 16 +1.434980619272460e-04 20 17 +6.375462234056684e-04 20 18 +1.771385768497788e-03 20 19 +3.233033884460954e-03 20 20 +3.912068929840578e-03 20 21 +3.145644377756497e-03 20 22 +1.683390907031591e-03 20 23 +6.003781224686864e-04 20 24 +1.431860973840122e-04 20 25 +2.353023458085338e-05 20 26 +3.098355792788597e-06 20 27 +5.701545853936663e-07 20 28 +1.161841016756794e-06 20 29 +2.752129060676672e-06 20 30 +3.965288889790357e-06 21 0 +4.809474577021396e-06 21 1 +3.265902127647575e-06 21 2 +1.153290298311127e-06 21 3 +1.734187798996243e-07 21 4 +4.307226170255345e-06 21 5 +3.268845994111086e-05 21 6 +1.673952798494322e-04 21 7 +6.297509875229867e-04 21 8 +1.674683627968040e-03 21 9 +3.043996694190472e-03 21 10 +3.709176492544443e-03 21 11 +2.997312013828311e-03 21 12 +1.599019952667030e-03 21 13 +5.728662937094130e-04 21 14 +1.609992934304200e-04 21 15 +7.737655471200314e-05 21 16 +1.609992934304200e-04 21 17 +5.728662937094130e-04 21 18 +1.599019952667030e-03 21 19 +2.997312013828311e-03 21 20 +3.709176492544443e-03 21 21 +3.043996694190472e-03 21 22 +1.674683627968040e-03 21 23 +6.297509875229867e-04 21 24 +1.673952798494322e-04 21 25 +3.268845994111086e-05 21 26 +4.307226170255345e-06 21 27 +1.734187798996243e-07 21 28 +1.153290298311127e-06 21 29 +3.265902127647575e-06 21 30 +4.809474577021396e-06 22 0 +5.555042869803733e-06 22 1 +4.420635368354199e-06 22 2 +3.028730507567648e-06 22 3 +3.100707295620601e-06 22 4 +9.243914480592160e-06 22 5 +4.087587045427118e-05 22 6 +1.760607022307088e-04 22 7 +6.247370338825327e-04 22 8 +1.629230426377810e-03 22 9 +2.933474132420932e-03 22 10 +3.538408480595143e-03 22 11 +2.811983434809747e-03 22 12 +1.451910099681378e-03 22 13 +4.768548007400953e-04 22 14 +9.099433778678653e-05 22 15 +1.171746709542609e-05 22 16 +9.099433778678653e-05 22 17 +4.768548007400953e-04 22 18 +1.451910099681378e-03 22 19 +2.811983434809747e-03 22 20 +3.538408480595143e-03 22 21 +2.933474132420932e-03 22 22 +1.629230426377810e-03 22 23 +6.247370338825327e-04 22 24 +1.760607022307088e-04 22 25 +4.087587045427118e-05 22 26 +9.243914480592160e-06 22 27 +3.100707295620601e-06 22 28 +3.028730507567648e-06 22 29 +4.420635368354199e-06 22 30 +5.555042869803733e-06 23 0 +5.404189672356805e-06 23 1 +4.892870830299098e-06 23 2 +4.557607934560358e-06 23 3 +5.537092541242136e-06 23 4 +1.083855203679700e-05 23 5 +3.547085934154473e-05 23 6 +1.510775020427121e-04 23 7 +5.676546615136151e-04 23 8 +1.538572432507774e-03 23 9 +2.819067621052516e-03 23 10 +3.417150766148686e-03 23 11 +2.705429500718680e-03 23 12 +1.374749562040417e-03 23 13 +4.333463453912217e-04 23 14 +7.941771000134053e-05 23 15 +1.479566369747944e-05 23 16 +7.941771000134053e-05 23 17 +4.333463453912217e-04 23 18 +1.374749562040417e-03 23 19 +2.705429500718680e-03 23 20 +3.417150766148686e-03 23 21 +2.819067621052516e-03 23 22 +1.538572432507774e-03 23 23 +5.676546615136151e-04 23 24 +1.510775020427121e-04 23 25 +3.547085934154473e-05 23 26 +1.083855203679700e-05 23 27 +5.537092541242136e-06 23 28 +4.557607934560358e-06 23 29 +4.892870830299098e-06 23 30 +5.404189672356805e-06 24 0 +3.955165536724783e-06 24 1 +3.584741991399201e-06 24 2 +3.508885372422360e-06 24 3 +3.939399145842972e-06 24 4 +4.822757117855054e-06 24 5 +1.528945559383431e-05 24 6 +1.028440676156929e-04 24 7 +4.865196638755525e-04 24 8 +1.440956718322974e-03 24 9 +2.733108955173010e-03 24 10 +3.366008382925306e-03 24 11 +2.697020398631471e-03 24 12 +1.391340841413025e-03 24 13 +4.489266759395228e-04 24 14 +8.931113109195366e-05 24 15 +2.423720573557286e-05 24 16 +8.931113109195366e-05 24 17 +4.489266759395228e-04 24 18 +1.391340841413025e-03 24 19 +2.697020398631471e-03 24 20 +3.366008382925306e-03 24 21 +2.733108955173010e-03 24 22 +1.440956718322974e-03 24 23 +4.865196638755525e-04 24 24 +1.028440676156929e-04 24 25 +1.528945559383431e-05 24 26 +4.822757117855054e-06 24 27 +3.939399145842972e-06 24 28 +3.508885372422360e-06 24 29 +3.584741991399201e-06 24 30 +3.955165536724783e-06 25 0 +2.214633245267957e-06 25 1 +1.585525169790331e-06 25 2 +1.483434350126737e-06 25 3 +1.972238971450125e-06 25 4 +8.239998404110594e-07 25 5 +3.274470653067594e-06 25 6 +7.580088249132948e-05 25 7 +4.457366278418717e-04 25 8 +1.401383271659800e-03 25 9 +2.715854393917418e-03 25 10 +3.391604051034845e-03 25 11 +2.775387360033505e-03 25 12 +1.495302570719864e-03 25 13 +5.208990796590071e-04 25 14 +9.956297062102457e-05 25 15 +4.074204269152465e-06 25 16 +9.956297062102457e-05 25 17 +5.208990796590071e-04 25 18 +1.495302570719864e-03 25 19 +2.775387360033505e-03 25 20 +3.391604051034845e-03 25 21 +2.715854393917418e-03 25 22 +1.401383271659800e-03 25 23 +4.457366278418717e-04 25 24 +7.580088249132948e-05 25 25 +3.274470653067594e-06 25 26 +8.239998404110594e-07 25 27 +1.972238971450125e-06 25 28 +1.483434350126737e-06 25 29 +1.585525169790331e-06 25 30 +2.214633245267957e-06 26 0 +1.270433760442372e-06 26 1 +3.916387056204372e-07 26 2 +2.231233391960010e-07 26 3 +1.503250077270970e-06 26 4 +3.125235105917701e-06 26 5 +1.232580616064923e-05 26 6 +9.755857943602422e-05 26 7 +4.851055857767528e-04 26 8 +1.457115907850736e-03 26 9 +2.782087863624691e-03 26 10 +3.471885190847275e-03 26 11 +2.885556868129979e-03 26 12 +1.636626067410123e-03 26 13 +6.667717289764138e-04 26 14 +2.263997570460314e-04 26 15 +1.189280941020137e-04 26 16 +2.263997570460314e-04 26 17 +6.667717289764138e-04 26 18 +1.636626067410123e-03 26 19 +2.885556868129979e-03 26 20 +3.471885190847275e-03 26 21 +2.782087863624691e-03 26 22 +1.457115907850736e-03 26 23 +4.851055857767528e-04 26 24 +9.755857943602422e-05 26 25 +1.232580616064923e-05 26 26 +3.125235105917701e-06 26 27 +1.503250077270970e-06 26 28 +2.231233391960010e-07 26 29 +3.916387056204372e-07 26 30 +1.270433760442372e-06 27 0 +1.299354594308245e-06 27 1 +5.522911269684502e-07 27 2 +4.619462725569895e-07 27 3 +2.265200690627976e-06 27 4 +8.097778286089136e-06 27 5 +3.240334951419666e-05 27 6 +1.498979407853844e-04 27 7 +5.803392722650569e-04 27 8 +1.582282591448272e-03 27 9 +2.903121917018245e-03 27 10 +3.560888391768400e-03 27 11 +2.942173666034896e-03 27 12 +1.681218578604672e-03 27 13 +7.183020985079531e-04 27 14 +2.890668649459803e-04 27 15 +1.861637286406668e-04 27 16 +2.890668649459803e-04 27 17 +7.183020985079531e-04 27 18 +1.681218578604672e-03 27 19 +2.942173666034896e-03 27 20 +3.560888391768400e-03 27 21 +2.903121917018245e-03 27 22 +1.582282591448272e-03 27 23 +5.803392722650569e-04 27 24 +1.498979407853844e-04 27 25 +3.240334951419666e-05 27 26 +8.097778286089136e-06 27 27 +2.265200690627976e-06 27 28 +4.619462725569895e-07 27 29 +5.522911269684502e-07 27 30 +1.299354594308245e-06 28 0 +2.040365887620211e-06 28 1 +1.650917666586412e-06 28 2 +1.774875725028040e-06 28 3 +3.556606295780957e-06 28 4 +1.121238171560661e-05 28 5 +4.596797846319543e-05 28 6 +1.924256950599667e-04 28 7 +6.695452279961972e-04 28 8 +1.710357891797661e-03 28 9 +3.026685345607163e-03 28 10 +3.623902514336288e-03 28 11 +2.912274546185048e-03 28 12 +1.573517463148064e-03 28 13 +5.814421846018108e-04 28 14 +1.585057189477723e-04 28 15 +6.269150114528087e-05 28 16 +1.585057189477723e-04 28 17 +5.814421846018108e-04 28 18 +1.573517463148064e-03 28 19 +2.912274546185048e-03 28 20 +3.623902514336288e-03 28 21 +3.026685345607163e-03 28 22 +1.710357891797661e-03 28 23 +6.695452279961972e-04 28 24 +1.924256950599667e-04 28 25 +4.596797846319543e-05 28 26 +1.121238171560661e-05 28 27 +3.556606295780957e-06 28 28 +1.774875725028040e-06 28 29 +1.650917666586412e-06 28 30 +2.040365887620211e-06 29 0 +2.889936412548378e-06 29 1 +2.523107656067143e-06 29 2 +2.137256869716177e-06 29 3 +2.408742209727751e-06 29 4 +7.837863399645522e-06 29 5 +4.293412664154757e-05 29 6 +2.012737823483604e-04 29 7 +7.094420933272181e-04 29 8 +1.788723143733490e-03 29 9 +3.116507360268357e-03 29 10 +3.668485365947303e-03 29 11 +2.864609577951840e-03 29 12 +1.444029026933867e-03 29 13 +4.403845160530417e-04 29 14 +6.521201643211877e-05 29 15 +2.389980714464935e-07 29 16 +6.521201643211877e-05 29 17 +4.403845160530417e-04 29 18 +1.444029026933867e-03 29 19 +2.864609577951840e-03 29 20 +3.668485365947303e-03 29 21 +3.116507360268357e-03 29 22 +1.788723143733490e-03 29 23 +7.094420933272181e-04 29 24 +2.012737823483604e-04 29 25 +4.293412664154757e-05 29 26 +7.837863399645522e-06 29 27 +2.408742209727751e-06 29 28 +2.137256869716177e-06 29 29 +2.523107656067143e-06 29 30 +2.889936412548378e-06 30 0 +3.189540008095353e-06 30 1 +2.665276215102024e-06 30 2 +1.538390887473923e-06 30 3 +2.126393704049059e-07 30 4 +2.872410902877456e-06 30 5 +3.332700529158972e-05 30 6 +1.874186897482456e-04 30 7 +7.023315789295831e-04 30 8 +1.808842702438711e-03 30 9 +3.169450767598823e-03 30 10 +3.727981450772813e-03 30 11 +2.895425157778220e-03 30 12 +1.436817970496205e-03 30 13 +4.198892675035715e-04 30 14 +6.131415667355502e-05 30 15 +9.736971670136333e-06 30 16 +6.131415667355502e-05 30 17 +4.198892675035715e-04 30 18 +1.436817970496205e-03 30 19 +2.895425157778220e-03 30 20 +3.727981450772813e-03 30 21 +3.169450767598823e-03 30 22 +1.808842702438711e-03 30 23 +7.023315789295831e-04 30 24 +1.874186897482456e-04 30 25 +3.332700529158972e-05 30 26 +2.872410902877456e-06 30 27 +2.126393704049059e-07 30 28 +1.538390887473923e-06 30 29 +2.665276215102024e-06 30 30 +3.189540008095353e-06 PyX-0.14.1/examples/3dgraphs/surface.ipynb0000644000076500000240000055210512615761666020605 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple 3d surface" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nTM0ogyMiCuP/cGhdbRw4T1YAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#!/usr/bin/env python\n", "from pyx import *\n", "\n", "g = graph.graphxyz(size=4, x2=None, y2=None)\n", "g.plot(graph.data.file(\"surface.dat\", x=1, y=2, z=3), [graph.style.surface()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This first simple example provides data for the x, y and z coordinates. PyX\n", "creates a rectangular grid from the data from the first two coordinates without\n", "relying on a special ordering of the data. A missing point will create a\n", "hole in the surface.\n", "\n", " The surface is plotted using a mesh. In case of a huge number of data points,\n", "you may want to replace the mesh by a bitmap rasterized on a different (i.e.\n", "lower) resolution. This can reduce the file size and may also resolve various\n", "printing problems (unfortunately those are quite common with mesh data). To\n", "enable the mesh by bitmap replacement feature use the option `mesh_as_bitmap`\n", "(together with its `mesh_as_bitmap_resolution` option)::\n", "\n", " g.writeEPSfile(write_mesh_as_bitmap=True)\n", " g.writePDFfile(write_mesh_as_bitmap=True)\n", "\n", " The underlying rectangular grid is created by the gridpos style. By changing\n", "its parameters you can also create the base rectangular grid from others than\n", "the first two coordinates.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/3dgraphs/surface.py0000755000076500000240000000036312517447165020105 0ustar andrestaff00000000000000#!/usr/bin/env python from pyx import * g = graph.graphxyz(size=4, x2=None, y2=None) g.plot(graph.data.file("surface.dat", x=1, y=2, z=3), [graph.style.surface()]) g.writeEPSfile("surface") g.writePDFfile("surface") g.writeSVGfile("surface") PyX-0.14.1/examples/3dgraphs/surface.txt0000644000076500000240000000174712037464541020272 0ustar andrestaff00000000000000Simple 3d surface This first simple example provides data for the x, y and z coordinates. PyX creates a rectangular grid from the data from the first two coordinates without relying on a special ordering of the data. ... A missing point will create a hole in the surface. ! The surface is plotted using a mesh. In case of a huge number of data points, you may want to replace the mesh by a bitmap rasterized on a different (i.e. lower) resolution. This can reduce the file size and may also resolve various printing problems (unfortunately those are quite common with mesh data). To enable the mesh by bitmap replacement feature use the option `mesh_as_bitmap` (together with its `mesh_as_bitmap_resolution` option):: g.writeEPSfile(write_mesh_as_bitmap=True) g.writePDFfile(write_mesh_as_bitmap=True) !! The underlying rectangular grid is created by the gridpos style. By changing its parameters you can also create the base rectangular grid from others than the first two coordinates. PyX-0.14.1/examples/axis/0000755000076500000240000000000012615763300015316 5ustar andrestaff00000000000000PyX-0.14.1/examples/axis/grid.ipynb0000644000076500000240000014145512615761564017332 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Drawing a graph with grid lines" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcMAAAERCAYAAAAHcMz6AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nACAASURBVHic7d1LiGzbeR/w/+dz7OPBvUrqRjgKhlipcxUPnICu62BHAROTVE8cMMShOwGDJzbd\nZBYwonruEKoJhEwSODXNIEkXyTAedA3yGESDrsgELBN0T11pIK5QjlURkiPd6PF5sL7dtXp3vWvv\nvV7/HzSnunp1nbW69q5vvZeoKkITkZ6qLkPng4iIyvRTIf9zERmIyCWA+5D5ICKiskkkLUNVVQmd\nDyIiKlPQliEREVEMGAyJiKh4DIZERFS856EzcCoR+TGAH9m3PwTwAwAfAnjfS/Zl+/fnAfycPf4W\ngG/Y4/cBvFtL+673Gt+116yn/dB+dkhaAPiglvaXAPwEwM+uyVuVtolybErbRDleAPhTAM825C2F\ncvwE7lr64y15i7UczwH8Ktzf/zmA7wH4NoDvN1COdWnbfj8+Za9ZpfXztu69i7Ecvwb3mfQ24XJ8\nBsDn4K4nP23M5fg83PUDuOv/RwDeVdUX2CL5YAjgR7sKGTsR+R8A/pOq/ovQeTlWJmX4IoDfUtWz\n0Hk5hIgMANwB+LcArgF8FcCvABgBGAL4XGpLl0Tkrar+tdD5OEVm98QXQuflFCLyya40OQRDomJ5\ngfBMVef2HFR1AeDKli7dichZagGRqEtBg6HdqH17PAawUNVJyDwF8jUAH4fOBOFjuPciCSLSgwuE\n11UgrFPViYjA0r3qMHun+lboDBCAxO6JUwQNhl7guw6Zjwh8HcA3Q2eC8E249yIVrwFMdlUgLSAO\nRWSsqqnca9/YnYQ6kNo9cbQcukn/X+gMEADgj+DGqqgDInIOoK+qF2t+/OGa564AvBGR6aZWJDWO\n90Q8dsaJHJZW/Dh0BggA8B24GWfUMusefQ0X4Nb5bv0JGy+8BjBuMWv0GO+JeOyMEzkEQ6LSjAAc\n3MKz7tSeiAzbyRZRuhgMiRJircJLADdHvsQELpgSkYfBkCgtVatwccwvW+uwz9Yh0WMMhkRpOcfx\nrcLKDdg6JHqEwZAoEbYud35sq7DitQ77zeSMKH0MhkTpOAcwa+i1pnBjj0QEBkOiJFgrbtDgDk0T\nMBgSPWAwJErDJVwAa4R1tc6s65WoeAyGRGk4R4PB0EzhTrUgKh6DIVHkbOu15akTZ+pUdQpgaGsX\niYrGYEgUvyFcK64NU7hWJ1HRGAyJ4neO9oLhDJxIQ8RgSBQz6yJdNN1FWrGuUq45pOIxGBLFrc0u\n0gq7Sql4DIZEcWtjFmndDJxVSoVjMCSKlG2mvbCzCFtjXaUDziqlkjEYEsWriy7SCrtKqWjPQ2eg\nAS9E5M4eTxvcroootCE2n2bftDmAQUf/F1HrRGSM1TX9bFf6HILhJ6p6FjoTRE2y2Z29Q0+zP8EU\nwBjdBV+iVqnqdfVYRN7uSs9uUqI4NXlCxU42Lrngob9UKgZDojgN0GEwNNyrlIrFYEgUp3Ob5dkl\nLrGgYjEYEkXGuiq7bhXCxif7XGJBJWIwJIrPEG52ZwhcYkFFYjAkik+X6wvruMSCisRgSBQR66Ls\nd7ikoo7jhlQkBkOiuAQZL6xUp2PwFAsqDYMhUVwGCDdeWOG4IRWHwZAoLm0e5LsvjhtScRgMiSJR\nLWlo6yDfA3DckIrDYEgUj5BLKh54W7OxdUjFYDAkikcM44WVGdhVSgVhMCSKR9CZpDULMBhSQRgM\niSIQwfrCOo4bUlEYDIniEFOrkOsNqTgMhkRxiGm8sMLWIRXjpGC4z0Gg22qW9d3xuVs+FSyqlqHh\nekMqxlHBUETORWRkj8c7pmDfi4jWvl7bz0Yi8kZE7kTkHqyFUrkGEY0XVjijlIrx/MjfG6nqK3s8\nE5E3AF5uSDvB4xrvOYBrezyHm7UGAFNb30RUlFDnF+6iqgsR6YtIj/cm5e7gYGg3bv3GWIjIk5qt\ndZFOvMH4IR4HvWWA07yJYhPFYvsNqnFD3qeUtWO6STd1ZT4Z71PVhRcIq6njfg24JyJD+xpzzJAK\n1Ue8wZDrDakIx3aTHmME12XqW1StSREBgFsAZwe+7k+LyBft8ccAvonawH8VgK2lWk3o8QP1ABbM\nvbQ97zWWXj4f0gKYq+rykLT2/LCeFsBnvOcXtdZ0U+VYm7aJclR53JK3FMrxuUDlGAL4N95rn1qO\ndxssxwzAjYjM9ihHk+/He35vUy1v68q8z/uxLm1r5QDwCwA+EJFl6uWoegQTKcdvAvhFe/6rAL4H\nQLBDl8FwqKrX/hN+t6qqzmwiTf/AjYqfAfgte/w1AF+Hq836LdiqNdr3np9hNV45wOrNqtL2vLQL\nrGruftoFXCA4JC02pP0rAP7Gmrw1WY5NaZsoR2VT3lIox88A+P9dlsMqgQsAf73BcnzKy+NJ5bD7\n8pdrzz8px4Yyn1KO9/B4uUm/9hr1Mm8tx5a0bZbjs/bvdzIox7CWNuZy/DqAL9jjP4L7++8MhqKq\nu9I8/gUXzUeqeuY9dw/gutYFuut3BgDuVPU97zkFcLbpdTa89ltV/fRBhYiMiIwBzA4pd2wyKcMQ\nayptLf+fl3AzSa8afM07/15r4PXuAVx1Odu16TKEwHsiHvvEiWPGDOd4Oj7Y85q552uWWmwaZ3zo\nNrXfWaR84RAdIebxwgoX31P2Dg6G1jc88dYZjrBaKgG4pRM7T8m2WuZSRAbWpzwGcHFofogSF/NM\n0socqy4qoiwdNWaoqhNbf1QtlVh4P1sX0OoTZ6q0N9Yi7AO44FomKlBMm3NvMoerrBJl6+gJNBYA\n95rosm1CTAIfBEStsMpk9Ne/Lb7vcfE95YwbdROFk0QwNNyajbLGYEgUTgqTZyr15UpEWWEwJAon\nxmObNmHLkLLGYEgUQLX14IEbTITE45woawyGRGGkNF5YLalaypbzSYlSxmBIFMYAe87Gjgi7Silb\nDIZEYQwQ4RmGO/AEC8oWgyFRGIMEtx7kuCFli8GQqGM27pZaF2l1zA6XV1CWGAyJupfSkoq6+ZqN\n+ImSx2BI1L0UJ89U2FVKWWIwJOpeyi3DBXiCBWWIwZCoeylOnqmwZUhZYjAk6lCqk2cqnERDuWIw\nJOpWyl2kFU6ioewwGBJ1K+XJMxV2lVJ2GAyJupVDy5CTaCg7DIZE3RomPHmmwpYhZed56Aw04IWI\n3NnjqapOguaGaAObPJN6qxCqOvPuOaIoicgYq0rbs13pcwiGn6jqWehMEO0hhy7SylxEBqqaS3ko\nM6p6XT0Wkbe70rOblKg7OUyeqbCrlLLCYEjUnZxahpxEQ1lhMCTqTk7BkC1DygqDIVEHbPLMUlWX\nofPSBJsRy2BI2WAwJOpGTq3CysKCPFHyGAyJupHT5JkKu0opGwyGRN0YAEh9sX3dEgyGlAkGQ6Ju\nZLHgvobjhpQNBkOilolIDwBymTzjYTcpZYPBkKh9OY4XVsF9WQV7opQxGBK1b4j8ukgrbB1SFhgM\nidqX43hhZQEX7ImSxmBI1L6cg+Ec3JaNMsBgSNS+vqpmN2Zo2E1KWWAwJGqRiOQ8XggL8pxAQ8lj\nMCRqV47bsNXNLegTJau1YLjPzVGfks0p2pShHjJcVlHDrlJKXuPBUETORWRkj8cisu0mGYnIGxG5\nE5F7cFYa5aeEliHPNqTkPW/hNUeq+soez0TkDYCXG9LOsao1TzPcoYNoqKq5B8M5gPPQmSA6RaPB\n0LpG6wFtISKDDR8IS1WdNpkHolhYr0jugRCqyjFDSl7T3aSbbohNY4E9ERna15hjhpSZnNcX1s12\nDIkQRa2NbtJDLKoWo4gAwC2As6A5ImpOlnuSbrBAGeOjlKmgSyv8rlNVnQEYHnFy9jsi8ta+vmKT\ncQb2752I3FUJReTSe/7Se368Jq3/GuN1aaua8CFp7fknaQH8xoa8NVmOtWmbLMeWvEVfDgC/22Q5\nAPwjABcByvF+w+/HurT1ciwA9JsqB4APtlxX667BpsrR2Pth7/9NDuVYkzbmcvyhrGLCl+z1n2EH\nUdVdafYmbtxgpKpn3nP3AK4t2PlpBwDuVPU97zkFcFZPu+P/fKuqnz499+HYGzk7pNyxyaQMQ7gJ\nL9cNvd63AbzsemKYiNz592BH/+eTe//E1+u8DE3jPRGPfeJE0y3DOZ6OD/aqi0Hcsgu/xjGpHtjz\ni5QvHKKKuPHvZUEzpLnWkJLWaDC0G38iq3WGIwB+jeLcvqou0qU1dfsAxgAumswPUUAljRf6Zxty\nvSElqfEJNKo6EZG+Na+n/gbFqnpRS3tjLcI+gIuCatGUv6z3JN2gOsGimEoA5aOV2aQWAPe6IQpY\nkExl6gMobQ1tdbYhhzooOdyom6gdJa0xrPBsQ0oWgyFROwYZn2G4CYMhJYvBkKhhNl5eXFehBX8G\nQ0oSgyFR80rsIq1wn1JKEoMhUfP6eLphfSm43pCSxGBI1LyS9+hcYPPG/ETRYjAkat6w4J2Uqg27\niZLCYEjUINuBpdRW4cOG+6HzQXQoBkOiZhW1DdsGc27LRqlhMCRqFoMhu0opQQyGRM3qo8A1hjUM\nhpQcBkOiZrFl6CoD7CalpDAYEjWrV+A2bHVca0jJYTAkaojtvFLsTNKKHcXWswOOiZLAYEjUnJIX\n29exdUhJYTAkag4Ptl1hMKSkMBgSNafoBfc1PMGCksJgSNScoaoyGDo825CS8jx0BhrwU96RMQvO\n5KMQRITjhR5V5VFOFJTdk9UkLtmVPodg+AyrvRBn4JgNhcEu0qdmIjJga5kCGWDVO1FEMPyhql6H\nzgQVj4vtn6p2omEwpM6p6qR6LCK/tys9xwyJmsEP/ac4iYaSwWBI1AwGw6e4vIKSwWBIdCLbaWVp\nO6/QCoMhJYPBkOh0HC9cwyoHS55tSClgMCQ6Hfck3YzrDSkJDIZEp+Oyis0WWC19IooWgyHR6RgM\nN2PLkJLAYEh0ugF3PtqIwZCSwGBIdALbcmwWOh+xskoCgyFFj8GQ6DTsIt2N+5RS9BgMiU7DMwx3\n43pDih6DIdFpuMZwtwVWpwcQRYnBkOg0Q1XlmOF2bBlS9BgMiY7EMwz3Y0c4ccyQosZgSHQ8Tp7Z\n39wqD0RRYjAkOt4AADfn3g+7SilqJwXDfadLi0hvXVrb7X/j90SRG4BrDPfF9YYUtaOCoYici8jI\nHo+3dX+IyDmAcwA9EbkTkUvvxyMReWPP34PjCpQWjhnujy1DitrzI39vpKqv7PFMRN4AeFlPZEe3\nDFT12r5fArgVkakd7zLHalr6lOfBUSp4huHBGAwpage3DK27s/4BsNjQOuzBtf56AGBT0HtY3RRL\nVZ3YFz9UKCVsFR6AZxtS7I7pJt3UlflkvE9V56oqVaCzLtOlty6rJyJD+xpzzJASMgQX2x+Km3ZT\ntLqeTXoJ4Nr7fqGqMwuOMwC3HeeH6FhcVnE4nm1I8VLVg74AjAHc1Z67g9uJY9vvjQBc7kijAPoH\n5ucHAN7a11csLwP7987PK1wwrp6/rJepltZ/jfG6tHDjoQel9f5eD2kt3b/ckLcmy7E2bRPlsK/h\nlrylUI5/570nu8rxZ7BrNcJyfLTH3/iQ92Nd2mPKMQfwJ3uW422tzJdb0nZdjn3fj4+szMmWA+6e\n/mhN2pjL8YdYxYQv2c+XftxY9yX2y3uzMcORqp55z90DuNYN21JZ9yhUdeqNGfTsj/Cel04BnG16\nnQ2v/VZVP31QISIjImMAs0PKHZtMyjCEq9Rd70jXA/DGv3ZjIiJ3/v0ZC/u73avqk8l2a9JGWYZD\nlHRPxG6fOHFMN+kcT8cHe9UbbssuHibT2B9zoapTe8o/CHXipRtYumQvHCoGJ88cQd3cgR7nBlCM\nDg6GdkFPvHWGIzweB6zWFVZLK24B3IuIWstvbK8zh5tdNrB0YwAXpxSGqCMMhsfjEguK0lHrDFV1\nIiJ9a/VNvZYeVPXCe7wAsLErSVVvrEXYB3ChXF5BaeiDO88cq9q0m38/isqxi+6rQHfy1HJrIRKl\nZADgJnQmEjWH9RwRxYQbdRMdzh/3psOwm5SixGBIdAAbGmAX35GsEsEJNBQdBkOiw3DyzOnm+554\nQ9QVBkOiw/TBbdhOxa5Sig6DIdFh2DI8HfcopegwGBIdZsAZ0Cdjy5Ciw2BItCdOnmmGTaJhy5Ci\nwmBItD92kTaHk2goKgyGRPvj5JnmsKuUosJgSLQ/tgybw0k0FBUGQ6L9cfJMc9gypKgwGBLtgZNn\nmlVNouFxThQLBkOi/bCLtHlsHVI0GAyJ9sPJM82rjnMiCo7BkGg/A7CbtGmcREPRYDAk2sHGtfo8\ntqlx7CalaDAYEu3G8cIWVJULTqKhGBx90j2lRUQGeHyO3IItnb0NwWDYlmrccBo6IylYcx8vudyn\nGTkEwxcicmePp6o6CZqbiNhygHP7msNNAFnCjdMMRARwH0ITBsat+uCHdVsWcC1v/n03EJE+gBHc\nfbyAu5er+7hvP58CuOF9vCIiY6y64Z/tSp9DMPxEVc9CZyImVnscw90sNwCuVXW5Jl0fwCWAexGZ\nqOp1tzlNxgDAVehMZGoG90FPNdZ9/BqrysLLLffxOYA7EZmBQREA4H+eicjbXek5ZpgZqw3dwbWS\nX6rqZN0NBLgxG7tgXsLVMO8tkJKxDxps+hvSyTiJZg3r1XkD1xJ8paprK7TAw318A+AVXIvxTkRY\nwTgQg2EmRKQnIvdwrcGXh3QXq+pSVS8ATOBuJK79WuHkmRbZB/yiqnQQICKXAG4BnG0LgnV2H18D\nuABwLiKvOTlpfwyGGbDW3D2AmapeHNuKsQB6BuDWbkhywbD4LqeWcfG9sfvuEi4QHlUJU9W5qr6y\nb+8YEPfDYJg4C4R3cOMEJ4/52Q14BmDMLlMAXGzfBR72i2YCoU9Vr+CuXQbEPTAYJswLhNdNzqL1\nAuItAyKGqspg2K4ZCh83tEA4BnB0z846VkGuhj8YELdgMExUW4GwYgHxBi4gFnkT2d+Y44Uts2ut\n2G5Su85GcC3Cxrvk7fOBAXEHBsME2WSD1gJhxV57CjeYXyIe29SdWYkTt7zlEzdtLp63e5ldplsw\nGCbGLuRbtBwIK9U4pC3ZKA1PquhOqa3D13AT37q6l+f2f1INg2F6bgHMO95p5wrAZYHjh2wZdqe4\nEyxE5BxuA/jONruwSTW9Qiu3WzEYJsQu4KVd0J2xcYwrFFSjtBZ4jzt5dGaGglqGNtTxGmF2NroA\nMOTyqccYDBNhF+4QgbYFU9Up3OLoUmqUbBV2yGZQLgtafD+G2xO48wla9re+ApdPPcJgmABvttlV\n4G3BSuou5WL77hXROgzRPVpnQfgKnFDzgMEwcrUJM0Gn+VsgvoGr1eaOi+27l/3ie7ufxwCCb4pv\nvT0TlDtb/BEGw/i9htt0O4ojbmxDYBQw3sDF9t0roWU4gps9GsW1Vfhs8UdyOMIpW7bzfN820Y7J\nDYDXIjLN8TQHW+8WxYdVSVR1LiL9XLvtvCPTXobOS80F3DFu0QTpENgyjJQ3ThhbIITdMDmfQ8eT\n7cPJuXVYTZqJqgJp+blAwbtNAQyGUfLGCa8intp/DTeZJscxnj7YMgwly/MNrbdhEOsB2v72i6Hz\nEkoUwbDEbZh2iGqccB2rTU6QZ+uQLcNwsgyGcPdJlIGw4s0HKHL8MGgwFJHz6kRmEeGaFzwaJ4z6\nxjE3cIeI5tQ6/MsAFrF1ZZXCuuCzqhxXk81irtx6LuB6fLJ6D/YRegLNyDuEciYibxDf4HJnvHHC\nV7vSxkBVlyJyDdeSzaUl9VmwizS0GYD3QmeiQSME2izjUHZPV+OHRX0WB2sZWs2jXvteFNw6fAfx\njxM+YXuk9gH8Qui8NOQzyCewp2qOfILhb8D1NCRTwbK8Frf+MGQ36aZmeKmzmf4pIh8n3OIGwN8K\nnYmGfBZsGYY2A/Bu6Ew05B/D3R9J8YZpfjdoRjoUupu0CT8jIl+0xx8D+CZqg/BVrczGtqrxrUXV\nArPWaK+Wtue9xrLa/cVPC3d6xPKQtPb8sJb2VwH8VQD/zH7m5+2h0tBAOdambaAccwB/EcAHIuLv\nIpJaOf4egP9rr7EpbymU4yGQNFSOdWlbK4f5SyIy8NL6eVtX5hjL8XcB/B94PWAplQNu/PDrcGsQ\nh7W0MZfjNwH8oj3/Vft3Z8Mvh2D4AsDvA/gIwNfg3rwFHrc8q5p+33t+htXekwOs3qwqbc9Lu8Cq\n68xPu4C70A9JCz+tiACuVfWvNuStyXJsSntyOQB8Ca4W/OWEy/G34a6hbXlLoRyf8vLYRDnWpW27\nHN8H8Nte2n7tNepljrEcfxPuEO5BiuVQ1YWI/AGAfw7g7wP4k0TK8esAvmCPvwLXVf0CO4iq7krT\nCqsVjFT1zHvuHm4Pzr27qUTkLYD/CDyc1ZUMq9ncA/hfAP51SuMKdTYd+3cA/E6q5RCR/wJXw/wH\nofNyChG58++rFInIRwD+QyKzqp+wGaT/BMAXU70fgIfP6T8A8NPeZMck2OfrHVyQ/Ieq+ult6UOO\nGc7xdHywd8yFUwVBEUntvL1bAFMA/zt0Rhry75H2usNfxqplSGF9G2mvNxzB9Zbk4L8isePb/EC4\nbyMpWDCsFm176wxPWpSaWkCsLqxUa74b/GcA/RTXKNmYxMcAPgmdFwLggmFy1xHw0CqcAfhO6Lw0\n6AqJHAh8TCAEAi+6t2n5U/vwPHkmZSoB0S6oc0S472gDbpBm63AI4H+GzgQ9MkuxYgV3/U9CZ6JJ\n3oHAo5iXvx0bCIEItmNT1YWqzppaWxd7QPQ34M5xl5Nq3WGCH2IDrGaeURyS243GKroLDXz2aBus\nTNeI9EDgUwIhEEEwbIMXEKN602yK8R0iOKi3ZSm2Ds8B/LfQmaBHkguGcNd9cusK92W9dzeILCB6\ngXB27ETKLIMh8BAQF4jkTZPHJ9anuLB+b17rMIk9S0XkHG4iE0XEKoy9hK6jqlWY7OzRfdiG3nNE\nskON18iYnDIHI9tgCDwExDkCB8RarSWrsYQtUmod+uvAKC4ptQ6zbhX6qsZG6OEoG3a6hwuEJ322\nZh0MgYc3bQYXEDsf+K31Y+c0c3SXKdI50eIc3IItVkkEw1JahT77bB2ECoj2eV4NO53cyMg+GAIP\nyxcm6DggnjqgmzJN5LzDKlhnPoabsiSCIVyFqohWYc0ZAgREq3zcwU1EbKS3rYhgCDyMY13ABcTW\n18qUHAg9KZx3OARbhdGySlXUp9nYzOmjNgxJnb0/Z3BzBF53MRxla7RHAM6a/JsXEwyBh81gz+AO\nr2ztjfP6sacFB8JUWocMhvGbwrW8YpXdusJDqOrS2/6vtfkZItITkWqv11dN9+YUFQyBh+6w6o27\nb7rGaa3OWwA3NuuqdNG2Du2mPc99dm8GZog0GFqrsF/QxLiNvPkZb5peZ2wzvt/A9bSdtbFGu7hg\nCDzUZK6wWkA6PrU2Y7WWWwCXaLAfO3Ve6zDGbZyG4JKK6NWODYpNMTNI92HzMy4A3Db0udq3z9Ux\nXLdoa5MQiwyGFWsRvLRv3xzz5lkQHMPVWhaq2njzPQM3cF3Twdd71rCLNB3RdZWyVbieDUe9hDuI\n4f6YORoWBF/DzbtYqOrLtj9Xiw6GwEMr8RrAK7g3742NJ2698USkmkH1xn7vVWFLJ/ZmrcMp4hs7\n5GL7dMTYVXoJtgrX8nrfruCGSarGxsZhKWtYnFtL8B7uzMLOPldzONy3EbY36pWIXMPddJcW7PyD\nKytVi2IG92Y1sq9q5m7gaok3MezJarX6RQx5od1UdWathV4M75l12Q5UNcfN9htjrcSZ/b0uAby2\ngFjvkenBHd47g9ucpPO/K4NhjTfGNQEeZob63XtLdoMezk7NrlqHMbSgOV6YnqqrNIZuSY4VHsAa\nDA/3/ZoJNovQjQoGwx0Y+BoVU+vwEq5rnNIxg3vfggZDa+UMS142daoY12QWP2ZI3bGaX/CxQxsP\nnoeuidJhbMLbIIJZpWwVZojBkLoWw8xSdpGmK+isUgvEnHiVIQZD6lQkrUN+mKVrgrCzSkdwG0OH\n7uanhjEYUgjBWofWRTrjh1maQp5xaJM+hlxXmKccguELO9G+kw246XSBW4c8ril9U4TZ0YhjhQmx\ndY13tp/ps13pc5hN+om3SSyl4xpuZumkq4ks3ixArg1L2wRuUXZnS3S420x6/MX6IvJ2V/ocWoaU\noEC70gSflk+ns8rTrOOeILYKM8dgSCF1faJFLAu26XSdzSqtgi5bhXljMKRgrHV4DaD1U7Jt4kzw\nXS6oGbbmsN9RRYqtwgIwGFJQVtvu7doYvQHcVDk/rXez24k08xh3TKFmMRhSDK4BnHz22Sbe5Ad+\noOWl1W52b4F9DHvpUssYDCm4amd7tFfLZzdXhrxN9du6bsYApuxaL0MOSysoD9dwZ0lOm9wcnVPi\ns1dt/t7o0U7Wbd/nMpxysGVIUbAPsis0P5mGrcKMeUt0xk29pnXXv4a7HqkQDIYUDZshuLBJCyfj\nlPhiVGOHG09RP9BrABMe31YWdpNSbK7guktnp0x4sdr9GAB3J8qcqi5F5BoNvN8iMgK7R4vEliFF\nxbq9LgDcnjhLcAzW7otRtf4tmB3FWpYjuOuPCsNgSNGxFuENXEA8eLmFdY8OwLHC0lwBGB3TXWq/\ncwfggrNHy8RgSFFS1RsAcwB3hwREr3Z/xWOaymJB7AoHVqIs7R3cOYVci1ooBkOKlqpe4YCA6NXu\nb9g9WiabhHUDd83s7Ga3a+YeLhByolXBGAwpahYQp3CTaoab0lnX6C1cNxc/1Apm7/8Ebv3htmtm\nBHfNMBASZ5NS/FT1RkTmAF6LSHUwcDWuM4DbMmsJFwjZIiSo6kRElth8zVza97xmCMCJwVBEhvv0\nsVsX16Cetr5rRNO7SFA+7Np5aTX9IVbH98zhukWnwTJHUbJrYupNqPKvmSuOD5LvqGBYbVUEYG4L\npDduoWVpewCWInJnaasuiVF1tI6luYGrwRGt5e1jSrQXdoHSPo5tGY5U9ZU9nonIm9BmvQAABANJ\nREFUGwAv64lsAHugqtf2/RJuptfUWoBzrLoupke2Ct894neoeX8HwJ+CgSoGH4TOAAHgPRGTnXHi\n4Ak01k1VD1qLDWt7enCtvx7wUKvvwXVZAMBSVSf2VXL36F8A8E7oTBDegXsvKDxWcuNQzD1xTMtw\n0+ysJ1PfretUqu+tS3Tp9dX3vNleQ7ixnxKD4uexaiFTOJ+Dey8ovPdDZ4AAFHRPdD2b9BKPD8pc\nVGONIgK4ac7cS5KIiDolquoeuBlX2xapzlR1ZhNmBqr6ELRsYszNttlZtqZnuW0wW0QUwMtDtkMS\nkR8D+JF9+0MAPwDwIR7XLL9s//48gJ+zx98C8A17/D5W3TJV2ne91/iuvWY97Yf2s0PSAqsxnSrt\nLwH4CYCfXZM3f/zn1HJsSttEOV7AjY8825C3FMrxE7hr6Y+35C2FcrwD4L/vyNsh5ViXtu1yfMpe\ns0rr521dmWMsx6/BfSa9Tbgcn4FrHX6vljbmcnwe7voBgO/D3dPvquoLbPHQMjxgxtUMqzG/ytbd\nQaoZo6o69XaF6AG4U9X3asn7OKzL8Fe4ToiIiDbZZ7/aY3agmeNp8OtVrUIReXSumI0JLrx1YAOv\n5Tfx0g0s3UEzrxgIiYhom33ixMHB0Ca4TKqjUuxffxzw3L6qpRW3cNsiqXWDjr3MLUVkYOnG4NEp\nREQUwMOY4cG/6AJYH641d/RMSGsR9gDMC51JSkREgR0dDImIiHLBUyuIiKh4DIZERFQ8BkMiIioe\ngyERERWPwZCIiIqXTTD0drahQETE33idAuF70D1e+/E5NCZkEwzhzknkxRiIbbl3DncSyZ3tdUsd\nst2fqs0wxvtsQUWn47UfrYNiQtenVrSCF19YexziTN3Y69Btag6v/TgdExOSbxnaxbjA0wOHqTu7\nDnGmlh146DY1h9d+ZI6NCTm0DAd2GsbIf9KOmhrCXZgL+3cJt+3b9dOXoWPtOsSZ70Un9j50m5rD\naz9KR8WEpFuGduE9OeXCnp9al9GNnb04VdUzXoCdeDjEme8FFYbXfkCnxIQoW4b7HDQMawav65ev\njouqjoXyms10gH0PfK79zgjuIpsAfC+oHLz2w7K/79ExIcpguM9Bw9UHtTdbaADgXETgfUBfqurV\nhvEU2uGAA58BrD/E2TvRhO9Fuw4+dJuaw2s/CkOcEBOiDIb7qH9Qe7Wyqq++h8etmiHWNJ+pGd4h\nztUhmgOvNsb3on1bD92m9vDaj8OpMSHpMUPANY1tYBRwtYCqVnCJVUGX4Oyu1mw7xNnwvWjZHodu\nUwt47cfn2JiQ7XmGItLz+45FpH/KIcR0PL4X3Wnq0G1qBq/9eOx6L7INhkRERPtKvpuUiIjoVH8O\nBDdmHukr1gIAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from math import pi\n", "from pyx import *\n", "from pyx.graph import axis\n", "\n", "xgridpainter = axis.painter.regular(gridattrs=[])\n", "ygridpainter = axis.painter.regular(gridattrs=[attr.changelist([style.linestyle.dashed, None])])\n", "\n", "g = graph.graphxy(width=10,\n", " x=axis.lin(painter=xgridpainter,\n", " divisor=pi, texter=axis.texter.rational(suffix=r\"\\pi\"), min=-4*pi, max=4*pi),\n", " y=axis.lin(painter=ygridpainter))\n", "\n", "g.plot(graph.data.function(\"y(x)=sin(x)/x\", points=200))\n", "\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The drawing of grid lines is performed by the axis painters of the graph. \n", "In order to turn on a grid, one has to specify in the argument `gridattrs` a\n", "list of attributes defining the way the grid should look like. In order to\n", "enable a grid at the position of the axis ticks and subticks, it is enough to\n", "set `gridattrs` to an empty list. In the example, this is done for the grid\n", "corresponding to the x-axis. If one wants to control the style of the grid\n", "lines or even turn them off selectively for the main or subticks, one can pass\n", "`attr.changelist` instances in the list. The first item of the argument of this\n", "class is then used for the main ticks, the second for the first subticks, and\n", "so on. In the example, it is shown how to change the linestyle of the grid at\n", "the main tick positions and to turn off the grid for the subticks by setting\n", "the correpsonding value in the `attr.changelist` instance to `None`.\n", "\n", " The example also shows a neat trick how to create an axis with axis labels at\n", "fractions of pi. This can be achieved by passing a `divisor` argument to the\n", "axis itself, which means that for the axis handling, all values are divided by\n", "the corresponding value. Then, we automatically put ticks at the position of\n", "rational number by means of `axis.texter.rational` and add the missing factor\n", "pi at the end of the TeX output.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/grid.py0000644000076500000240000000106212515656656016632 0ustar andrestaff00000000000000from math import pi from pyx import * from pyx.graph import axis xgridpainter = axis.painter.regular(gridattrs=[]) ygridpainter = axis.painter.regular(gridattrs=[attr.changelist([style.linestyle.dashed, None])]) g = graph.graphxy(width=10, x=axis.lin(painter=xgridpainter, divisor=pi, texter=axis.texter.rational(suffix=r"\pi"), min=-4*pi, max=4*pi), y=axis.lin(painter=ygridpainter)) g.plot(graph.data.function("y(x)=sin(x)/x", points=200)) g.writeEPSfile() g.writePDFfile() g.writeSVGfile() PyX-0.14.1/examples/axis/grid.txt0000644000076500000240000000254212037346772017017 0ustar andrestaff00000000000000Drawing a graph with grid lines The drawing of grid lines is performed by the axis painters of the graph. ... In order to turn on a grid, one has to specify in the argument `gridattrs` a list of attributes defining the way the grid should look like. In order to enable a grid at the position of the axis ticks and subticks, it is enough to set `gridattrs` to an empty list. In the example, this is done for the grid corresponding to the x-axis. If one wants to control the style of the grid lines or even turn them off selectively for the main or subticks, one can pass `attr.changelist` instances in the list. The first item of the argument of this class is then used for the main ticks, the second for the first subticks, and so on. In the example, it is shown how to change the linestyle of the grid at the main tick positions and to turn off the grid for the subticks by setting the correpsonding value in the `attr.changelist` instance to `None`. ! The example also shows a neat trick how to create an axis with axis labels at fractions of pi. This can be achieved by passing a `divisor` argument to the axis itself, which means that for the axis handling, all values are divided by the corresponding value. Then, we automatically put ticks at the position of rational number by means of `axis.texter.rational` and add the missing factor pi at the end of the TeX output. PyX-0.14.1/examples/axis/link.ipynb0000644000076500000240000015370012615761473017335 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Linking one axis to another one" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\njNzjdgAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "g1 = c.insert(graph.graphxy(width=8))\n", "g1.plot(graph.data.function(\"y(x)=2*exp(-30*x)-exp(-3*x)\", min=0, max=1))\n", "\n", "g2 = c.insert(graph.graphxy(width=8, ypos=g1.height+0.5,\n", " x=graph.axis.linkedaxis(g1.axes[\"x\"])))\n", "g2.plot(graph.data.function(\"y(x)=cos(20*x)*exp(-2*x)\"))\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When plotting two or more related graphs, you sometimes want to have identical\n", "axes. This example demonstrates how to achieve this goal in PyX using a\n", "`linkedaxis`. \n", "\n", "In order to arrange the two graphs, we first create a canvas `c`, in which\n", "we insert the first graph `g1` (the lower panel in the output), which contains the graph of a function.\n", "\n", "In the next graph `g2` (the upper panel in the output), we now refer to the\n", "x-axis of `g1`. We do this by creating a `graph.axis.linkedaxis` instance\n", "passing the x-axis of `g1` as the only argument. The latter is obtained from\n", "the axis dictionary `axes` of the graph.\n", "\n", "Note that for a linked axis, PyX automatically turns off the drawing of the axis\n", "labels, as you can see in the upper panel. If you do not like this behaviour, you\n", "have to pass a different axis painter to the `linkedaxis` constructor.\n", "\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/link.py0000644000076500000240000000064112515656656016644 0ustar andrestaff00000000000000import math from pyx import * c = canvas.canvas() g1 = c.insert(graph.graphxy(width=8)) g1.plot(graph.data.function("y(x)=2*exp(-30*x)-exp(-3*x)", min=0, max=1)) g2 = c.insert(graph.graphxy(width=8, ypos=g1.height+0.5, x=graph.axis.linkedaxis(g1.axes["x"]))) g2.plot(graph.data.function("y(x)=cos(20*x)*exp(-2*x)")) c.writeEPSfile("link") c.writePDFfile("link") c.writeSVGfile("link") PyX-0.14.1/examples/axis/link.txt0000644000076500000240000000157012037344755017026 0ustar andrestaff00000000000000Linking one axis to another one When plotting two or more related graphs, you sometimes want to have identical axes. This example demonstrates how to achieve this goal in PyX using a `linkedaxis`. ... In order to arrange the two graphs, we first create a canvas `c`, in which we insert the first graph `g1` (the lower panel in the output), which contains the graph of a function. In the next graph `g2` (the upper panel in the output), we now refer to the x-axis of `g1`. We do this by creating a `graph.axis.linkedaxis` instance passing the x-axis of `g1` as the only argument. The latter is obtained from the axis dictionary `axes` of the graph. Note that for a linked axis, PyX automatically turns off the drawing of the axis labels, as you can see in the upper panel. If you do not like this behaviour, you have to pass a different axis painter to the `linkedaxis` constructor. PyX-0.14.1/examples/axis/log.ipynb0000644000076500000240000016713512615761467017173 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Logarithmic axes" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nAAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "from pyx import *\n", "from pyx.graph import axis\n", "\n", "# we here use parters and texters which are explained in the examples below\n", "log2parter = axis.parter.log([axis.parter.preexp([axis.tick.rational(1)], 4),\n", " axis.parter.preexp([axis.tick.rational(1)], 2)])\n", "log2texter = axis.texter.exponential(nomantissaexp=r\"{2^{%s}}\",\n", " mantissamax=axis.tick.rational(2))\n", "\n", "g = graph.graphxy(width=10,\n", " x=axis.log(min=1, max=1024),\n", " y=axis.log(min=1, max=1024, parter=log2parter),\n", " y2=axis.log(min=1, max=1024, parter=log2parter, texter=log2texter))\n", "\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Logarithmic axes are quite similar to linear axes and differ only in a very few\n", "properties, namely a non-linear mapping of values to axis positions. They also\n", "have different default partitioners and raters (see below). While the\n", "partitioner really is quite different - it implements a logarithmic positioning\n", "of the ticks - the rater just alters some defaults in favour of using more\n", "subticks to improve the visualization of the logarithmic nature of the axis.\n", "\n", " Besides presenting a standard logarithmic axis, we also show you how to alter\n", "the base used by the logarithmic axis. Since the functionality of a logarithmic\n", "axis is independent of the base, all we need to adjust are the components for\n", "creating ticks (see `log2parter`) and the texts for the labels (see\n", "`log2texter`). More details about the parters and texters components are given\n", "below in the corresponding examples.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/log.py0000644000076500000240000000125012515656656016465 0ustar andrestaff00000000000000import math from pyx import * from pyx.graph import axis # we here use parters and texters which are explained in the examples below log2parter = axis.parter.log([axis.parter.preexp([axis.tick.rational(1)], 4), axis.parter.preexp([axis.tick.rational(1)], 2)]) log2texter = axis.texter.exponential(nomantissaexp=r"{2^{%s}}", mantissamax=axis.tick.rational(2)) g = graph.graphxy(width=10, x=axis.log(min=1, max=1024), y=axis.log(min=1, max=1024, parter=log2parter), y2=axis.log(min=1, max=1024, parter=log2parter, texter=log2texter)) g.writeEPSfile("log") g.writePDFfile("log") g.writeSVGfile("log") PyX-0.14.1/examples/axis/log.txt0000644000076500000240000000161212037343037016637 0ustar andrestaff00000000000000Logarithmic axes Logarithmic axes are quite similar to linear axes and differ only in a very few properties, namely a non-linear mapping of values to axis positions. They also have different default partitioners and raters (see below). ... While the partitioner really is quite different - it implements a logarithmic positioning of the ticks - the rater just alters some defaults in favour of using more subticks to improve the visualization of the logarithmic nature of the axis. ! Besides presenting a standard logarithmic axis, we also show you how to alter the base used by the logarithmic axis. Since the functionality of a logarithmic axis is independent of the base, all we need to adjust are the components for creating ticks (see `log2parter`) and the texts for the labels (see `log2texter`). More details about the parters and texters components are given below in the corresponding examples. PyX-0.14.1/examples/axis/manualticks.ipynb0000644000076500000240000006470712615761537020724 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Manually place ticks at certain positions" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "from pyx import *\n", "\n", "p1 = path.curve(0, 0, 3, 0, 1, 4, 4, 4)\n", "p2 = p1.transformed(trafo.translate(4, 0))\n", "\n", "myticks = [graph.axis.tick.tick(math.pi, label=\"\\pi\", labelattrs=[text.mathmode]),\n", " graph.axis.tick.tick(2*math.pi, label=\"2\\pi\", labelattrs=[text.mathmode])]\n", "\n", "c = canvas.canvas()\n", "c.insert(graph.axis.pathaxis(p1, graph.axis.linear(min=0, max=10)))\n", "c.insert(graph.axis.pathaxis(p2, graph.axis.linear(min=0, max=10, manualticks=myticks)))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ticks can be set manually by passing tick instances to the `manualticks`\n", "argument of the axis instance as shown at the right axis in this example. \n", "\n", "As you can see, the manual ticks are combined with the automatically created\n", "ticks. You could disable any automatic tick creation by setting the `parter`\n", "argument to None. But what's much more interesting is, that the manually and\n", "automatically created ticks are not just merged, but their combination is used\n", "for rating the resulting partition. Therefore, the additional manual ticks lead\n", "to a different set of automatically created ticks in this example.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/manualticks.py0000644000076500000240000000105012515656656020215 0ustar andrestaff00000000000000import math from pyx import * p1 = path.curve(0, 0, 3, 0, 1, 4, 4, 4) p2 = p1.transformed(trafo.translate(4, 0)) myticks = [graph.axis.tick.tick(math.pi, label="\pi", labelattrs=[text.mathmode]), graph.axis.tick.tick(2*math.pi, label="2\pi", labelattrs=[text.mathmode])] c = canvas.canvas() c.insert(graph.axis.pathaxis(p1, graph.axis.linear(min=0, max=10))) c.insert(graph.axis.pathaxis(p2, graph.axis.linear(min=0, max=10, manualticks=myticks))) c.writeEPSfile("manualticks") c.writePDFfile("manualticks") c.writeSVGfile("manualticks") PyX-0.14.1/examples/axis/manualticks.txt0000644000076500000240000000121412037343037020367 0ustar andrestaff00000000000000Manually place ticks at certain positions Ticks can be set manually by passing tick instances to the `manualticks` argument of the axis instance as shown at the right axis in this example. ... As you can see, the manual ticks are combined with the automatically created ticks. You could disable any automatic tick creation by setting the `parter` argument to None. But what's much more interesting is, that the manually and automatically created ticks are not just merged, but their combination is used for rating the resulting partition. Therefore, the additional manual ticks lead to a different set of automatically created ticks in this example. PyX-0.14.1/examples/axis/minimal.ipynb0000644000076500000240000003671112615761501020020 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Minimal example for drawing an isolated axis" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = graph.axis.pathaxis(path.curve(0, 0, 3, 0, 1, 4, 4, 4),\n", " graph.axis.linear(min=0, max=10))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the basic example of how to draw an axis alone -- without the whole\n", "graph. It serves to simplify the following examples. The function\n", "`pathaxis` from the `graph.axis` module takes a path and returns a canvas which\n", "contains the drawn axis.\n", "\n", "In contrast to the typical usecase of graphs containing data, we here have to\n", "provide the range explicitly (using the `min` and `max` arguments). For real\n", "graphs the range of an axis, of course, is adjusted automatically, although you\n", "can still set minimal and/or maximal values to force a certain axis range.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/minimal.py0000644000076500000240000000032712515656656017336 0ustar andrestaff00000000000000from pyx import * c = graph.axis.pathaxis(path.curve(0, 0, 3, 0, 1, 4, 4, 4), graph.axis.linear(min=0, max=10)) c.writeEPSfile("minimal") c.writePDFfile("minimal") c.writeSVGfile("minimal") PyX-0.14.1/examples/axis/minimal.txt0000644000076500000240000000114012037343037017500 0ustar andrestaff00000000000000Minimal example for drawing an isolated axis This is the basic example of how to draw an axis alone -- without the whole graph. It serves to simplify the following examples. ... The function `pathaxis` from the `graph.axis` module takes a path and returns a canvas which contains the drawn axis. In contrast to the typical usecase of graphs containing data, we here have to provide the range explicitly (using the `min` and `max` arguments). For real graphs the range of an axis, of course, is adjusted automatically, although you can still set minimal and/or maximal values to force a certain axis range. PyX-0.14.1/examples/axis/painter.ipynb0000644000076500000240000006260212615761511020033 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Painter: Controlling the visual features of an axis" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKQAAAC5CAYAAACm/ZQEAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAA6QSURBVHic7Z09jytLEYbfuoIIAnwEMeCNEVz5JGQEXgE/YI8Iic6KGCSfn7COiNcBJES7SEC8\nlhAJ0VoEV7qCYEfiDxyji5D4CIqgq+32rD/G45np7pn3kVZre+31nLOvq6qrq6pFVUFIKnwS+wJI\nfxGR9yJyc85rKEjSJgWABxH5KCL3VcQpdNmkCiIyAzBS1Q9nvu4JwDR4aA1gAeBRVVfl59NCkqqs\nAEyqPllExiIyBfDH0o9GAGYAnkXk2dz6aPM6WkhSFRFRVZXg/hROpCMA4+D7+MxfXQC4VtWCgiSV\nEJExgN8B+BzA17HrhuuyBLBQ1cfN+1CQZB/mRt/DWbspjlu9wr7WwfeVfQeA59LzF3BCfBVDfumy\nyyZ9wkR4AyfAQyvi/wL4A5zgVqq6PPE774O7CwBzVS0OPp8Wklg6xn+VWcG51gLA3wD8SlWvKv7e\nEYCPqCBEDy3kQLGYcAYnwlHpxwW2qZmi9DqIyLiKuODc/FXF5wKgIAdHIMT3pR8VAB5xID8YsIRb\nWZ8U2YnfsxcKciAcEeLBBcYBHlFBjHVhDNlzLI67w34hVorruoQWssfYYuUeuzFikkL0UJA9xKzi\nPXZXzUkL0UNB9gARGanq2m6XrWIB4PZUvjAVWFyROSLyHsCTiIxE5AHAA7ZinAN4m4sYAS5qeoGV\neH0XwDfsoaysYggtZOaIyATAW2zFuECLVjEsFdvzs4sLLijIjDF3/Qzga/bQv+ByiuvDr6r9XpPg\n/co/u7ECXojInX1I6r0PXXaemADu7O4awK3dfq+q1y2+705NpD32rKpvg/svVfe7y3CVnSFWQeMT\n3Wu44la/0/K4/1WtXcsU2zIzTyEikzpbh3TZmWGW0YtxBVe8cPYfvkEOxY0HY81jUJAZYTGcd9Mr\nOMvYeLwYEwoyE0yMvtjVu+leiRGgILPAVq3hAiYlMe5LL9Vy1wAFmTxWNvYE90cuL2BSYIXXAhzV\nzYNSkOkTbgXexhKj9U/f2e07CyFglnoR5CFnAM4aJrDzPsxDposJYGZ35+dOjegSs+RjAMUlFUUU\nZKJYfu/J7i7bTHanBAWZILZf/IJt3HiV0CKmVRhDpkk5bhyEGAEKMjlsseB3P+bhmJEhQJedECVX\nXdQtUMgZWsi0mCFw1TEvJBa0kIlgaZMXu/uoqu9iXk8saCHTIdynTjbf2DYUZAJYp6BfyCxSb1Vt\nE7rsCIjIM9we8FxVCxF5ge1ywPXDDCbNU4YWMg7XcK75WUT+hO0w0PmQxQjQQkbF0jwFXJPWFwA+\nHbK7BmghYzPBtmPwz3AW895W3IOEgoyLr+QpVPXHAK7gXPlDvEuKC112JErVPLequoh5PalACxmP\n0DqeJcZzXHp50sSxyRMpQEFGwAS1yTvW+BXPIqKlr/sDz52JyIuIPFm6qYnzZVqDgwLiEE6zrSPI\nBXabq25weHdnhe0I5sfU00qMISMgIh/hiigWqnpWEYV31z495Ac8HWqqEpFpTlPQaCE7xuodfRx3\ndq1jmKe0eHB8IgYdBVPJpkg8+U5Bdo9310UDlmuG0y6/8J2KIgK4lFKy/Tl02R1iDf9+nN3FqZ7y\n1LGKr1GceZhRl3CV3S3hEPqLWhMOTB0rP2di8WqZZHeCKMhu8YJsYqjo3vSNDQ8NB4Yugp9N0Eyo\n0BoUZEeYGLxlalMQm0M0LXZcm6Ucw80HSroSnTFkRwRDRteq+qaB37eT/jnx3Ancyn6V8goboCA7\n45Lc45Cgy+4Aa1Hwucdk47cUoCC7wS9AiqE1/p8LBdkNfnVNMZ6AgmwZyxd6d53SoNEkoSDbx7vr\nNd31aSjI9vHumouZClCQLRJMlQUoyEpQkO3S2N71UKAg28XHj8vUd0hSgYJsATux4FsIBBnvavKC\ngmwYq+KeAPgsePiLSJeTHdzLbomgmOIfcHMf10M5SeES2MLQHt5dP7CYojoUZAuU0j3Z7s5Y+OGb\n0jppDmMM2Q59SffMsO3pHonI2CqXWoMWsh18C0HyBbGHsD34uaquRSTsA5+ceOlF0EK2Qx/SPWvs\nWvpOoIVsmKBdAMg4flTVVTCrcg1srGarHYu0kM2z6QbsQXXPNdyHa2YtGFPUm0VUGeYhG0ZEHuBc\nXVYnuNpRyGu4645m2Wkhm8fHXbm56zGcNbwTkY8i8mBboBsX3faCBmAM2SjBUCcgvwXNh9Igqymc\ni/Zx5BLOgrb6QaMgmyWMH7MSZLm/265/CewkyFufB0SX3SzepWUlxjIlSw/LpT6igzCEgmwW/4fM\nLX6EiEyDeHESPD4SkRncHEpayFzIPH4E3IfoxtI7E7+gUdW1qs7R0cQ0xpDNkW38CGzc8jw4XWwC\nl3+E3e/E6lOQzdGL+BGlqh5fudTVh4wuuzmyjB9tVN/mVIhyMYiqdjpPkoJsgMzjxwls7rkNO73f\nkxDvbOIutw4bwLbdZgCgqhL5cmpjq+kVnLX3I2CWcO0Xh87BaRTGkM3Qi/jRVtNAhIS4hy67GbKM\nH0PKyXCg24S4h4K8kNIfMqtys1PJcDsFrOjyCBEK8nLC6Wa5WcgkkuEhjCEvJ9v4MZVkeAgFeSaW\ns/OFrGvUjB9FZFRKQI/KOcAOiZoMD6HLPp8RXBHui4i8BI+f+8dL5hzr2MnwEOYhL0BEfg3gpwD+\nB+DLcKJcwR39cXQhUDqZIflzrLuCFvIyvmPff28JcZ/Hq2Lt1qq6sC+K0WAMWROLs3YWNGGVdQWy\nOse6KyjI+ly6f53VOdZdQZddH28dayWOw5ylWdZpl0UMHusunNntSRedhcegIOtT+zCkVM6xNvF9\nUNW5pbPu4RLld11eRwgFWYOGxqWkcI71SFULS4zfAXhnVT3RYlnGkPUIhzCdLSKbmzM1Ia4R8Rxr\nSz9N4VJPPvTobO+6DC1kPfyCpnb+MCj1GsNZps636QKLXKjqrX1I7hBRkLSQZ1JK91wkoq5FaBZ5\noqqbcKE0EKuwr2gumxbyfLItN8OJdgVz2csuy83KUJDnsymmiPmHq4PtCr21u2O4D9QYwIPtq/uT\nI6LBvewzERH/Hzbvqs+kC8J2hZhzLRlDnkFp4Htu7nqDT1uFaSabJR7930SXfR7eXRcxVsUN4rsK\ny9zEDkMoyIoELg3I2DoaSwArv01oC5tnRFxdeyjI6vTCXRt+8OjMhDiG2zmK3obBGLI6vXDXVvJ2\nDyfKBVwsOT/+qu6gICtg7rp2MUVijAHc+gWNtbzeweUfaSEzoU/uelUqfVuLSIFtsUhUKMhqeEFm\n7a6Bg9uVKySwoAG4qDmJbav5+LHVQ4O6wooopnZ7hO1gqehQkKcJt9KyF6RtD/rjPhSudWKEYJRK\nTLh1eAKr7B7BtbZmfRC7r7+0otypqi5t92mSyjYoLeQRrKx/0zsd81oaYgRswpARsCk/S6ZIhIua\nPQTn/v3IHoo2yaFhVnAuegnXhusFmUT8CFCQh3gE8HMAP7D7v413Kc1h1e3XwMZKPtthocm031KQ\ne7Cel3/a3X8DeCci31bVKH0vbWBFFG8iD7l6BRc1ezDr4QdJzVX1g4hMcs9B5gAXNfuZBbcXQPf9\nL0OFgixh1tHnHk9OMSPNQkG+JkyEJ1MFMxQoyIBSES6tYwQoyF3usM3J0TpGgII0bFuN1jEyTPsY\nIvIEV3SwBnCVUm5uSNBCYmfgEuCsI8UYCVpIAHaawhhuz/oq9vUMmcFbSCuk8INCkyjBGjKDtpBW\nNf1kd5eqmkyRwVAZrCAt5+h7ktcA3nJlHZ8hu+zQVd9SjGkwSEHaqjrMOfahGrwXDM5l+8JUuB2Z\nAs5VM82TCIOykBY3+i47wLlqijEhBiVIuBW1b/f80JM+mV7RS0GKyMysYfjYPbZiXKQ0YIls6aUg\n4VbPT16UlvzezHbMvb+6z/R2URNYxN8A+KU9vAJwzbgxXXorSAAQkb8A+J7dpRgzoK8u21tIL8b/\nAPgFxZg+vbOQwUGSPmZcAfgMwFf61FfdV3olSBNjmNrZuGmzmOCCJm1647KtcucZu6mdzS6MCXEd\n45B0Up1eWEhL6+w099MS5knWs32sMStMeK/htgNZLJEp2bpsEZlh10Uv4QolKMaMyU6QNh/7CW4l\nDTir+EFVr1nTmD/ZuGxbtMywe0bfCs5FcxBUT0jeQgYW0fdNA66O8dZW0ReL0Q4P2ncY5avnHbtP\nLidZQdqJ92UhruHmNV6paiMnIlj1+A3ciOMnmyt+iJkddP5kZwSeFDE5j6gu2xYmq+CYswmcOMJh\n88D2XL55k9t/lpPcnEAgImsADyLyeOB9VtgOiD/0HHIBUfOQZo2+D+CvcEIsn5VSwM37blSIwftP\n4Fbqb/zvt7NbrvcV7/qjNJq+DrLllYVs+yDG4OSoCYAfYlsAEbKwa2g1hWPxpwTXdgN3jsuhf3sY\na07R0gdlyLTusksC9N/3sYSzhjFd4Xscn16xOetQRADXn8PhAg3SiCBNdBNsjygbwVVt+9v7WMOJ\n8KsA/q6qP2viWupi8ezjscVS6RTVpS1uxsx/NseOIC3I/yaAT+32vkKEUenxqitNL8AVnDv2lmaM\n7TiTKJirLlT10RdflEVm8eaTqr4pvXyMhE7Cyp2yhZwA+Il9XcISToCFfS0PWRE7d+/the9XG4sJ\nw2OHJz52DYTqf7YIXjdBf074SoayIA/Fbl5YZVbB92OLgaPEihnNGj7Ajlkz/MoecCv/AnbouSXp\nJ3D/T3cAWPDbMK/SPm2vsnPHBDmCEylX2A2TzV52KnDfvF2S3Tokw2SfIAscjiUJaZVetDCQ/kCX\nTZKCgiRJQUGSpKAgSVJQkCQpXgmySm8JIW2xSftYIcEYbl96CleKxV0J0imhIJ9VdVN1IyIvPPeP\ndM0nwMZNl3dnCiskIKQzfAx5KG5k3zHpFK6ySVJQkCQpvCD3FePSXZPO8YJc4bUAR6waJ13zCbDp\naVlYK6hvCT3Wn0xIK+zUQwatrwV7jUkM/g9w6lbBW+jg5gAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "mypainter = graph.axis.painter.regular(outerticklength=graph.axis.painter.ticklength.normal,\n", " basepathattrs=[style.linewidth.THick, deco.earrow.large])\n", "\n", "c = graph.axis.pathaxis(path.curve(0, 0, 3, 0, 1, 4, 4, 4),\n", " graph.axis.linear(min=0, max=11, title=\"axis title\", painter=mypainter))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The visual features of an axis (such as ticklengths, linewidths, distances of\n", "the labels, their orientation, text attributes, etc.) are controlled by its\n", "painter. You can modify these attributes by creating a painter explicitly. \n", "\n", "While the axis painter has quite some parameters to adjust the output, here we\n", "only change its width, add an arrow and alter the ticks: By default, ticks are\n", "stroked only towards the inside of the graph (in the path examples there is no\n", "graph but don't mind). The labels and the axis title are plotted outside of the\n", "graph. Futhermore, the axis title (when present as in this example) is rotated\n", "along the axis (without writing it upside down), while the tick labels are not\n", "rotated at all.\n", "\n", "In this example we set an `outerticklength`. Together with the\n", "`innerticklength`, which by default is set to the same value, the ticks are\n", "stroked across the axis. As it is common to sub-components of the axis, you\n", "need to pass the adapted instances (stored in the variable `mypainter` here) to\n", "the axis in its constructor.\n", "\n", " In this example there is no tick at the end due to the axis range. You can\n", "suppress individual ticks by the `manualticks` axis parameter with ticklevel\n", "and labellevel being zero.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/painter.py0000644000076500000240000000067512515656657017361 0ustar andrestaff00000000000000from pyx import * mypainter = graph.axis.painter.regular(outerticklength=graph.axis.painter.ticklength.normal, basepathattrs=[style.linewidth.THick, deco.earrow.large]) c = graph.axis.pathaxis(path.curve(0, 0, 3, 0, 1, 4, 4, 4), graph.axis.linear(min=0, max=11, title="axis title", painter=mypainter)) c.writeEPSfile("painter") c.writePDFfile("painter") c.writeSVGfile("painter") PyX-0.14.1/examples/axis/painter.txt0000644000076500000240000000240512037507716017527 0ustar andrestaff00000000000000Painter: Controlling the visual features of an axis The visual features of an axis (such as ticklengths, linewidths, distances of the labels, their orientation, text attributes, etc.) are controlled by its painter. You can modify these attributes by creating a painter explicitly. ... While the axis painter has quite some parameters to adjust the output, here we only change its width, add an arrow and alter the ticks: By default, ticks are stroked only towards the inside of the graph (in the path examples there is no graph but don't mind). The labels and the axis title are plotted outside of the graph. Futhermore, the axis title (when present as in this example) is rotated along the axis (without writing it upside down), while the tick labels are not rotated at all. In this example we set an `outerticklength`. Together with the `innerticklength`, which by default is set to the same value, the ticks are stroked across the axis. As it is common to sub-components of the axis, you need to pass the adapted instances (stored in the variable `mypainter` here) to the axis in its constructor. ! In this example there is no tick at the end due to the axis range. You can suppress individual ticks by the `manualticks` axis parameter with ticklevel and labellevel being zero. PyX-0.14.1/examples/axis/parter.ipynb0000644000076500000240000005644412615761560017701 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Parter: Control over the partitioning of the axis" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "from pyx import *\n", "\n", "p = path.curve(0, 0, 3, 0, 1, 4, 4, 4)\n", "\n", "myparter = graph.axis.parter.linear([\"1/3\", \"1/6\"])\n", "\n", "c = canvas.canvas()\n", "c.insert(graph.axis.pathaxis(p, graph.axis.linear(min=0, max=1, parter=myparter)))\n", "c.insert(graph.axis.pathaxis(p.transformed(trafo.translate(4, 0)),\n", " graph.axis.linear(min=0, max=1, parter=myparter,\n", " texter=graph.axis.texter.rational())))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the above example, the (default) automatic choice of a good partitioning has\n", "been selected. Here, we show how to gain more control over the ticks, in order\n", "to fix their intervals. \n", "\n", "Partitioners (in the code the short form `parter` is used) take care of\n", "calculating appropriate tick positions for a given axis range. Automatic\n", "partitioners create several tick lists, which are than rated by an axis rater\n", "instance, as explained in the above example. In contrast, manual partitioners\n", "create a single tick list only, which thus doesn't need to be rated at all.\n", "\n", "In this example we create a manual partitioner, which places ticks with a\n", "distance of 1/3 and subticks with a distance of 1/6. We then use this\n", "partitioner at two axis, which are identical except for a texter instance (to\n", "show you another feature of the axes in PyX, namely the rational number\n", "arithmetics used to place ticks). The rational numbers are preserved throughout\n", "the whole process of merging ticks, until the texter finally needs to output\n", "the rational numbers. And at the very end the decimal texter steps into the\n", "problem to create a proper representation for the fractions. The solution is\n", "shown at the left part of the example: the texter marks a period to express the\n", "fraction.\n", "\n", "Alternatively you can use the rational texter to display the values by\n", "fractions directly.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/parter.py0000644000076500000240000000100312515656657017176 0ustar andrestaff00000000000000import math from pyx import * p = path.curve(0, 0, 3, 0, 1, 4, 4, 4) myparter = graph.axis.parter.linear(["1/3", "1/6"]) c = canvas.canvas() c.insert(graph.axis.pathaxis(p, graph.axis.linear(min=0, max=1, parter=myparter))) c.insert(graph.axis.pathaxis(p.transformed(trafo.translate(4, 0)), graph.axis.linear(min=0, max=1, parter=myparter, texter=graph.axis.texter.rational()))) c.writeEPSfile("parter") c.writePDFfile("parter") c.writeSVGfile("parter") PyX-0.14.1/examples/axis/parter.txt0000644000076500000240000000257312037343037017362 0ustar andrestaff00000000000000Parter: Control over the partitioning of the axis In the above example, the (default) automatic choice of a good partitioning has been selected. Here, we show how to gain more control over the ticks, in order to fix their intervals. ... Partitioners (in the code the short form `parter` is used) take care of calculating appropriate tick positions for a given axis range. Automatic partitioners create several tick lists, which are than rated by an axis rater instance, as explained in the above example. In contrast, manual partitioners create a single tick list only, which thus doesn't need to be rated at all. In this example we create a manual partitioner, which places ticks with a distance of 1/3 and subticks with a distance of 1/6. We then use this partitioner at two axis, which are identical except for a texter instance (to show you another feature of the axes in PyX, namely the rational number arithmetics used to place ticks). The rational numbers are preserved throughout the whole process of merging ticks, until the texter finally needs to output the rational numbers. And at the very end the decimal texter steps into the problem to create a proper representation for the fractions. The solution is shown at the left part of the example: the texter marks a period to express the fraction. Alternatively you can use the rational texter to display the values by fractions directly. PyX-0.14.1/examples/axis/rating.ipynb0000644000076500000240000011536512615761553017670 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Rater: How a nicely looking axis partition is chosen" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "p2 = path.curve(0, 0, 3, 0, 1, 4, 4, 4)\n", "p1 = p2.transformed(trafo.translate(-4, 0).scaled(0.75))\n", "p3 = p2.transformed(trafo.scale(1.25).translated(4, 0))\n", "\n", "myaxis = graph.axis.linear(min=0, max=10)\n", "\n", "c = canvas.canvas()\n", "c.insert(graph.axis.pathaxis(p1, myaxis))\n", "c.insert(graph.axis.pathaxis(p2, myaxis))\n", "c.insert(graph.axis.pathaxis(p3, myaxis))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We here demonstrate how an axis actually chooses its partition. \n", "\n", "There are good-looking partitions of an axis and bad-looking ones. The element\n", "which chooses one or the other, is the `rater` of an axis. It asks yet another\n", "element, the `parter` to suggest several partitions and then chooses the best,\n", "according to criteria such as tick distance, number of ticks, subticks, etc.\n", "(The partitioning process itself is explained in a later example).\n", "\n", "In this example we show the influence of the tick distances: Several axes with\n", "the same parameters are plotted on a path which is scaled. Note that the axes\n", "choose the ticks appropriately to the available space.\n", "\n", "The rating mechanism takes into account the number of ticks and subticks, but\n", "also the distances between the labels. Thus, the example in the middle has less\n", "ticks than the right version, because there is more space available at the\n", "larger path. More interestingly more labels are also shown on the very left\n", "path, although it is smaller than the middle one. This is due to the fact, that\n", "there is not enough room for labels with a decimal place on the smaller axis!\n", "\n", " The rating mechanism is configurable and exchangeable by passing rater\n", "instances to the `rater` keyword of the axis constructor. But instead of\n", "reconfiguring the whole rating mechanism, simple adjustments to favour more or\n", "less ticks are easily possible by the axis keyword argument `density`.\n", "\n", " In this example, the same axis instance is used several times. This works\n", "since the axis does not store any data within its own instance. Instead, an\n", "`anchoredaxis` instance is created by the `pathaxis` which embeds the axis in a\n", "proper environment. This way, a place for storing information for this specific\n", "use of the axis instance is provided. When using axes in a graph, the graph\n", "instance takes care of the proper setup of the anchored axes instances.\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/rating.py0000644000076500000240000000066512515656657017202 0ustar andrestaff00000000000000from pyx import * p2 = path.curve(0, 0, 3, 0, 1, 4, 4, 4) p1 = p2.transformed(trafo.translate(-4, 0).scaled(0.75)) p3 = p2.transformed(trafo.scale(1.25).translated(4, 0)) myaxis = graph.axis.linear(min=0, max=10) c = canvas.canvas() c.insert(graph.axis.pathaxis(p1, myaxis)) c.insert(graph.axis.pathaxis(p2, myaxis)) c.insert(graph.axis.pathaxis(p3, myaxis)) c.writeEPSfile("rating") c.writePDFfile("rating") c.writeSVGfile("rating") PyX-0.14.1/examples/axis/rating.txt0000644000076500000240000000363112037343037017345 0ustar andrestaff00000000000000Rater: How a nicely looking axis partition is chosen We here demonstrate how an axis actually chooses its partition. ... There are good-looking partitions of an axis and bad-looking ones. The element which chooses one or the other, is the `rater` of an axis. It asks yet another element, the `parter` to suggest several partitions and then chooses the best, according to criteria such as tick distance, number of ticks, subticks, etc. (The partitioning process itself is explained in a later example). In this example we show the influence of the tick distances: Several axes with the same parameters are plotted on a path which is scaled. Note that the axes choose the ticks appropriately to the available space. The rating mechanism takes into account the number of ticks and subticks, but also the distances between the labels. Thus, the example in the middle has less ticks than the right version, because there is more space available at the larger path. More interestingly more labels are also shown on the very left path, although it is smaller than the middle one. This is due to the fact, that there is not enough room for labels with a decimal place on the smaller axis! ! The rating mechanism is configurable and exchangeable by passing rater instances to the `rater` keyword of the axis constructor. But instead of reconfiguring the whole rating mechanism, simple adjustments to favour more or less ticks are easily possible by the axis keyword argument `density`. !! In this example, the same axis instance is used several times. This works since the axis does not store any data within its own instance. Instead, an `anchoredaxis` instance is created by the `pathaxis` which embeds the axis in a proper environment. This way, a place for storing information for this specific use of the axis instance is provided. When using axes in a graph, the graph instance takes care of the proper setup of the anchored axes instances. PyX-0.14.1/examples/axis/README0000644000076500000240000000167712037344755016220 0ustar andrestaff00000000000000Graph axes This section demonstrates the axis subsystem of the graph module. The axes delegate a lot of tasks to different components like ''painters'' (which control how the baseline of the axis, the ticks and the axis title are drawn), ''texters'' (which create the label strings written on the ticks), ''parters'' (short for partionioners, which take care of determining appropriate tick positions along the axis, and ''raters'' (which adjust the number of ticks to match the available size). In the present section, we will explain various basic aspects of these components. Most of the time, the examples will not show a complete graph but just a single axis. In that case, we will take an axis created along an arbitrary path, partially in order to demonstrate the flexibility of PyX's axis system but also too increase the coolness factor. Of course, in a real-world example, you will use the shown features mostly for simple, boring, straight axes. PyX-0.14.1/examples/axis/texter.ipynb0000644000076500000240000017251212615761526017714 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Texter: Controlling the formatting of tick labels" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoQAAADACAYAAACd4XIcAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nACAASURBVHic7d1PiKTfd9fxz/nxRVHUWANq+PknWBMVVDShRt0oSaAGzCKCkhoEAy4CNQQhWUk1\ngkgkix4NiqCLblDiD8lPupQfuNBF90pFRLpEyE7s2mQRIWGKmIW4Oi7uebrv1FRVd1fVc59/7xcM\nM91d35pnvn37POc599x7zd0FAACA4fpW0xcASJKZ3TZ9DQAA9I2ZXZrZ9LnXkRAC6D0zGzV9DRgW\nxhy6hoQQQK+Z2aWkRdPXgcH53PQFAK9BQgig7+6avgAM0rrpCwBe45umLwD9FNMlk+xTE0m7plDG\n8fnfVeK60G9mlo+zagz+gKQfMrP8pdXYvHD3VbkrRN8ciHXfMrN/LOn/xeerWLdy94uyV4m+2RPr\ndplI+oOSfuXZ92SVMY5lZmOlIFcNzCrgTZWejqsn5F033M3W5zfcmIfBzMbufnT1JJqj8wA4URp7\nYz1VA9dKY2zbauvzK3ff9Tr0yBnG3Hasq8YesQ612Yp11T22tlhHQghJjwNP7r53ei1eM1UanFM9\nDbgquN2JYIcDzGwuaeruH174+rG+HHMjpfFWBcHqZkxih73M7EHSh5fGpmdi3ePvxDq8lJkt3P3T\nga8/F+sex15dsY6EEJIkM5tJmuU36h1B8U5pUN4dShyBQ8zss6R3uyo2O4Ki9OW4oy8Lr2ZmC0lj\nd/+45+vEOtRq+6GkjbGOhBCP4kb9dyX9iKSZCIqoQaz6VdVHFYFxrjTmJBJAnFn0+T1IeltVV6qH\nYBHrUEDEve+T9JtqaaxjUQnyG/Jvk/STkr770ik94AjXkm7NbK0UGMeSlpLetyEoon/cfWNmS0k/\nY2a/Ryne3SndiIl1qE08jMwk/UVJPyjpl9TSWEdCOFDZIJ0r9SosJf2ZNg5S9EesjJtL+n5JPy7p\n2t2XzV4V+iyLdX9J0k9I+o72tCwA55LFuqoC/U/aHutICAcmguNCaaAuJX1q+yBF90WP1kKpGngt\n6Q+xCAR12hHrfpbpYNRtR6x725VYR0I4INFYvVAKjjwho3bRjnClFBw/uft1w5eEAYh+rSoR7MwN\nGd0VFcFLpVh30cVCCyeVDICZzWOF01QpEfxIMog6mdnYzK4k3UtauvtbkkHULYt1Yz3FOpJB1CaL\ndTd6inWdSwYlEsJeM7Opmd0r9TB8dPdWNrKiP8xsFNWZe6U9s0gEUbuIdQ96inUfiHWo045Y967r\nsY6EsKdioN4oTdO9b0PvTPT07Pva9JivoT1iyuQ+Pnzr7hdUZ1C3iHVXenrobTzWod/aHOsiUT3q\nnklC2DNRvr5XmjJpRenazCZxQsX9jq/NordRZnYZP2jPfg3tEt+nW6XemdYER/RXxJUq1r0jEUQJ\n8QDSyliX7a05MrPbuO++/L9nY+r+iG/+Qmkrj71H5DTFzNzdbetz9+7+Lvv4wd3fPvc1tENUfW/i\nQ3pTUUQW61iohCKyBXJSOnGkNYmg9LSfcLbh/1QpNr94URUVwh6IEvGV0qq6D21MBneJAbs9UNfx\n5L/3a2WuDs+Jp9EHpbM16U9F7SLW3egp1pEMonYR6+6VNjJ/37ZkMIwkLarWrKiYj5SOxnsRtp3p\nuPjm3yodf9PWgbrPvj6H0TNfQ8OiQnOpNOZWTV8P+i+LdZwugmKyanSrY11c2+MMXCSxm6qVIqa6\np0r30HX8vlF6oL+QSAg7LQuQy65UBdF90S84E/u7oZCYGbhSaoepvSpoZiPGNmLmbaLUo9q18TCX\nVE0fz5TyhAszm7v7tZkttvMGpow7KgLkg1raL4h+igA5U/eq0eioiHW3KpAMHloAh2HJksHOxbp4\naF9WPy/uvnT3VfwsraPf8KsWHxLCDsoC5EXHe2h2rQocveBraECXAyS6qXSsc/dV/D3juv8utFeX\nY11UA9dRBRxH8leZxxTyWF/36JMQtlW16eX23n09Sgal1Pe4neSNYsAe+hoKiwA5VgcDJLopYt2N\n0ur1rsc6tMy+rcwi1kkdjHWxGHOdbTc3qRb7RS6RJ4df9emTELZUDMSRpNsqKcySwU6trovjpC7j\nz5fV3kjxb7zO9hpcKHoeDn0N9YqHkVn28ZVSMt65AInuiDixK9Y1vpcqeulO6f76uFdflQx28cjD\nqATeSLo3MzczV1r4V5nraeZtox2rj9mHsOUiEVpI+muSflGFmqpLioE8VnqyWb/0a6hH1sB/p9Rn\nMlcHn5bRLfHQOJP005L+uRrcY3DXnqnon6wKvVRKknrbH729UMrMxl/db0kI2y+eYP6+pF+qlocD\ndYpKzZ2kPybph0ol42Y2fa4tIK5tsv26HQGPlaIdk21ndN1krCMhHI6IJ/eSfp+kHxhyzGDKuBsm\nkv4jySAKGkv6o5J+rEQy+NJjCp85mmlhZg/x+Xvt38sS7TVRbI/R9IVgMKq+uh8bcjIosQ9h68UN\nbyLpfdPXgmHIjqO7OOdGrGZ2c2BD4UV2TOGdmT1I+uKYwmgfmGRHM20k3ZjZMgL5Sk9bKSyHHty7\nJh4IiHUoJtvL96yxrquoELZYVEku1cJzE9FrN8r2sDqjndsGveKYwueOZtq4+3X84uelQ2IMVKdB\nNPa927cADr11ozP1qsZivE7PSlAhbLcrpS0XWEyBIqJKMyo8ZfeiYwqfO5pJaRq5eq+pUqAnMWy5\nSPCrWNfo9ytLDJiy7rmqReUcBztE3BlJ2phZdXpY5xZ/khC2VDyl5vsJAbWKKdmFujNl93g0U1hX\n0z5mJqWn/678W4asOlWBWIciItbNdb74cKt0vN0qe8AhIcTp4mljrq0eKqBm1VmxJ/fSZAE3N66m\n4yrHViK3j2aK91plf76LxSVfba2A9ohYN5P07rnXAmdUxbpzxYYPeupfHiv1M3cOCWHLnGP6ZN9N\nkG05sM+5p4pj/H3xXmY22fP+d/p6k9S9xxRmRzMts2OZRpJu3f3N1st3ntmJ5rVpqhjDcc6p4kpV\n3Y4xPVVHWw5YVNI+C0mrE6dPHncqz35diW05sENWzdu3Arhue48pjO1oHpPFQ0czKZuiif9mzVGH\nrVZVefkeoYgs1n2s4b0nStXuTlYHJSqErZIN1lOniq/1dESNlAbphVICyLYc2FbdmBuppLn7xsyu\nzWzh7p+2jimcKY3ZVXY00yh6BBVfW0bvzjSC8kaxOr/svwQvld08WzNVvN3OkGNfxN4491Txo2hZ\nWcUMxq2Zve3aPZaTSlrEzG6UqoNHl7KrKbTsQOtpfHz3klMgMCwxPq7cvfZ+VTO7dfe9TdznOKYw\nEo2R0s9Rp4LxkLRxJeahLUOIm91XV6yLmDN394/x8UjSZ6UtlDo1bqgQtkQM1smBjXtfJL+RxsAc\nZ0GXbTmwbSHpbL00zzg4tmPsnvTkzuay7RcxaNymZFAi6RuAfObhnCb6sv2qanHpXO8yCWF71HFj\nXujLpe9sy4FH1d5ZpW7MPHwgXKqGHi5gn2qD8Tq2NnL3azMbV33Lih7FLu5uwJRxC8RgnR2aTjvy\nfe+z48B2fd0lve3iwMXp4ni4j1RGUEpdsa4ObFnUHyViXdaucnTLS9NYZdwOZ68Obh8HZmYTM/u8\n46XjHZ9Dz8WNmVW4KCZaWEq2KJzqputHkeFxm5lV3bHO3VfuftfVZFBiyrhxNd6YdwUytuVAZSFW\n4aKsmaS7LsQczjDulYVatJq9zUgIm7dQgX4atuVAJXsIYQEGSurEQ0isdl8rm2FBN0Wsa0XVLrY1\nqs48XsfvG6XqZSu2NWLKuEHZJrt1PDFfayvRzLazGUv6QEIwWHN1Z9oOPdCxh5BJF6qYeJHthZWN\niL0Jl9HT/yl6aJfu/r4tyaBEhbBpC0m1HOi+74moIwEZNclWFnPDQ0kzteDG/Jy4cfOz0QPZEZe1\nfj/jYWdfL/61uz+erFS1amVV6FYhIWxIDIzW7cWF3utSUz96INt3sJaH33OJm/SG7ZF6Y66aCi5b\nVtqf3G2Ppbm7f9xe9NkWJITNmasDT8zoj+okEB5CUNhM3XgImUoaZyuLJ5JmZsam1R1TsuDy0lm3\n6qCI7FNTtawazT6EDYgb873SHoCte0pAP5nZlVIFpDU9K+i3Kta5+5umr+W1Yp/Wzh0/hsdYt2rT\nw29sf6M4r30i6bJt+3FSIWzGTKm3gGQQRcTT6UxS7WcWA5nOzYREElttO0OFsGOyWFf0wTf+3kML\nkh7v+bHrR+tO66FC2IDYNZ1VvqhNbEJ+rbSSbRWNz5PqAHbg3GJbjYlS39bS3TcR6963YdsPDEMT\nsS4WsFTbyMyVxn+nHoQkKoTFVc2kJIOo2Tulp+QbM9tI+p2S/l6zl4Q+c/eLuDHOJF2a2UrS/yEZ\nRGFzFawORkV5UrXiRLy9MbNl12YBqRAWFr0N62xPQKBWZvZTkv6Bu3+76WvBMMT02X+Q9C+OrZSY\n2ZSpWrxG9ObduHux1pj4O+8lvakSwK72n1IhLCCmUtZKUyn0caG0Py3pO01fBAbnj+uIbT+iyjiW\ntIrYuWRGBfvErNtUqUVmpjJbzTyKsWnZ9cyUZgE7lQxKJISlrJUG7D+S9O+6VkZG580ktWo1G3qv\nOpnhmFi3iBMdJOku+hB5iMY+VUvCraRvS/pTDV6LVHjK+pw4uq4Ad7929w9KA/Z7TV8PhiN7WqWP\nCyUdtSnwng171zEtB3wlTgK5UErC/muTsS62lunkghKJhLCY6Kn5kbbv1o/emarQFEq2oe9Jr33N\n+6B9osn+2OMR933vRydcEoZhKum7Tf3l2VF512Y2jp+DTiEhLKd4bwOgAuPOzGbVpqtmdnmomnPo\nta95H7Qa5wGjCY3dY+Mhdp0VfCZdnJWhh7CcYpUaQHo6SP0cgcnMbqLtYZfX9Hwdei29Y/3QlaPq\n0BNRnbtroj8/KoE3kkZmj2tLqkWknUKFsICYLp4yXYzCzvnEvHPK7jU9X4deS+9YP2TnZR877nZV\nFpkuxnMaOxc4ehjfuLtlvzr5IEtCWAbTxWhCiXH3mp6vQ6+ld6wfTh1zK339PT+2HxHDQZvCGZAQ\nltHY0wuGKSprrC5GaROdEOtiyu866yVdqKNbeKCMbDEHse5E9BDWrDpo+0D/FVCHoys1Me033/r0\nODYJflQd1QRIX7TGnBTrslWaU6UtPLjR45Dq/GyciISwfiwmQROmko463D1uwF8ke2Y22ZMA3ikF\n5Ny+ad5Dr33N+6CdztaiEGOQRBAvwcb7Z8KUcf2YLkZR2T5wJY77OtjzFVvJTF7wWnrHum+i9H0E\niqj2+qOKfB4khPUjIURpxcbcC3q+ZvHr4GvpHesFFs+hNMbcGZm7N30NvRWVkatsbzWgdmZ2o9R7\ndbZAaWa37r53WqbabkQvaO4+9NrXvA/ag1iHJpjZraRrtnQ7DxLCGkWVY0TzPUoyM5f05pybtJrZ\nqIlNX9EN1YIjYh1KiUVMn93dnn0xXoQp43oxXYyi6tqxn2QQz2DxHEpjzJ0ZCWFN4ullQlM8Cjtp\nHzjgtSLWjQstYgIqFFzOjISwPgxWNIFxh9Jo7EcTiHVnRkJYH7ZgQFFUatAQYh2KYruZepAQ1oen\nF5RGpQZNINahNMZcDUgIa1B4Y2CgQqUGRVGpQUPola4BCWE9eHpBExh3KI0xhybMxLg7OxLCelCp\nQVFUatAQEkIUFZugr9kK6/xICOtBkERp9A+iCcQ6lMaYqwkJ4ZlRqUFDqEqjiFjNTqUGTSHW1YSE\n8Px4ekERZrYws89xdvFfFuMOZTyY2b2kXxRjDuVxj60JCeH58fSCItz9k6S3SuPt16jUoAR3fyPp\no6Q3ItahIKrS9SIhPD/OV0QxWWD8XqMXgkGJLbX+sKjUoCyqgzUiITyj6B/c8PSCwqhKoygqNWgI\nsa5GJITnxd5IaAJPzSiNMYcmTN2dGbiafNP0BXRVrLT7rBQUV/H7REdMF5vZKH/S3v44Pjd1dwIw\nvkClBg05KtYBL2VmV3p68FhJ+t+iOlgrKoRHcveNu5ukT/GpuaS/ouOemhdm9mBmt7F6b1p9wcxm\nZraIP19GAgBUqNSgCYw71MrdP0p6r5QETiT9S0n/q9GL6jkqhCeKqt1dJGrjIys1K0nVvoXLrfdY\nuPu7+POdmT0orSwFJCo1KIyqNEqJ/Xyvpcce/X/b7BX1Gwnh+ZzyxLzZ1RdhZlNJ20F3bWaTWOUH\nTJW2AAFKoTqIJkzd/f1r/yMzu1QasyOlwstI6b66cveL815itzFlfD6nrH4amdk0fl1WJwEomzre\nfv2Rfw96hEoNGsJKTxQVxZFXP4SY2Uxp1u2dpE+RUC7d/T3J4NeoEJ7PKZWadVXxMzNJulHqnQAO\noVKDJlCVRmlTHfEQUs28VQ/PMe3MsbJ7UCE8g1MrNfn0b/QkTqszkYEDqNSgKKrSaMhEpz38zuPe\nOtbXbVgIJITncXSlxswmZvZ5x5fGe96T6WJUqBCiNMYcmnD0tmvRgpUXWPa1Yg0eCeF5nFqpua7+\nkD2BV3svbSeAI/YjBJUaNISqNIo6tn8wM8/++43SGMYO5u5NX0PnRYXv7bE359hn8E5psF5Jush6\nCudKSeCneN2andoRY2FEYzRKMjOP/VeBImKVsI6NdTsOfhjHdjbYQoXwROeo1Lh7tbn1WNKHrZ7C\na0nLeEpakgwiUKlBUWeo1ADHOKl/cPveTDK4HxXCE1GpQROo1KC0Uys1wDGIdeVQITwdT80oikoN\nGnLqSk/gVap9BJu+jqEgITzd0aufgCMdtScXcKxYqTkh1qEwWmMKIiE8AZUaNGQqnppRFrEOTWDc\nFURCeBoqNSiq2lOLs6xRWPFKTXaEJwaIWFceCeFpqNSgNJ6Y0YRi4y42659Lui/x96G16B8sjITw\nSDy9oCEkhCgqjtEclYp17r6K7bY4vnPY6B8sjITweDy9oAkkhChtJsYcyuMeWxgJ4fF4ekFRsQn6\nho1VURjbzaAojuZsBgnh8Xh6QWlUB9EEKoQojTHXABLCI8R2Mzy9oDZmNjazRfRvVUgIUasYc9Ps\n45mkO2IdCmPBZgO+afoCOoobM+o2UmqqvzWzjaT/JOnPsTEwCliY2Y3SDfmPiFiHgliw2RzOMj6C\nmd1L+siARQnRT/MLkn6Hu/9ow5eDAYib8kzSJ6UTSor3rXKG7TDFlkMTd//Y9LUMDRXCVyq9BQPg\n7isz+y1J32v6WjAM7r4xs5Wkz6WTwUgIxvHnS6X2nOuS14BGMV3cECqEr2RmC6WE8KLpa8FwmNln\nSW/p5UIpkYyJWIdSojL94O5vmr6WIWJRyeuxuhhFlWzszxcUPPO60a7Xbh83xvFjnUasQ2mMuQaR\nEL4C08VoSO2LmMxsFtVvmdll9C3ufa1S4B6Z2W1M8VUWZvYQn7+Pa0fHVN9/Yh0Km4r9fRvDlPEr\nMF2MJpSYLjaze3d/l3384O5vd7xuLGle/QxElfCmur5IFquq4JIp7m4i1qG0mE34LOkNcaMZVAif\nsTXlRTkbRZWYLo6kbvv913uqhCOlKuBIkmIbnJHSaRZSOknlOn4R1LuLWIfaRetJdY+diYfIRrHK\n+HlXcWP8N0pVEMrZKKnEnpf7pnW/6v+L8f+4FUgkrJtsf8S8t3Aq6RMBvlvO2RqTrxje464aOzFu\n9o1FVhr300TSjZktJf0JSb/c8PUMGgnhM9z9QySE/1TSv276ejAc8eQ8l9TmFXdzSfm04rpKJMxM\nStPJ7xu4LhxvrjNVB1+ZxK21/+GHh4oecvc7M3sr6W9K+ilJf7XhSxo0EsIXiH3gfr+kf9j0tWBQ\nZpJOmnp9SYXmhPdeKE3xPN7086pSBPtbMxs3sbExjjZTA0l8jBHGycBE7/Fvl/SvmE1oFgnhC1Q9\nVtzUUNh29e3VXlKhiUredr/gwe1iYqp47e7L7LzlkaTbHXuIjcWNvhOy7yvfL5Q0k8TJJA1jUcnL\nzCTRv4Jisj6uEufIrvR1AjjKertm+QKTeEBau3s1rZgfbXadvW4Sr+Ms3O5o1WKS7GEDPRVxgu3c\nWoCE8BlZH1drgiQGodiYi2ma62wfwoW+rExW+w5WN+gbSfdm5mbmkqoTLVaSNmY2idddSvpQ4t+A\n00Wsa9uxYTcv3SwdnUXBpSXYh/AZHLSNJpjZg6T3JafuIokb68Qpw+qJX9KKnqDuiAeBcVtiXcTe\nuaQLqsz9FfusvqNNoXn0ED7v5D4u4DXiRli8j+tcTf1M/XTWXC2p6MbDyVqsLu61iHV3JIPtwJTx\nAdVUBU+nKGwm6VPTF4HhyBaTtCWZnxB3B2Ehpotbg4TwMAYrioqHkDE3QxTWmj7p6nSepq8D9cp2\n7+B73RIkhHtU/VTsjo/C5qI6iIKyh5DGY13E3Q29p4NAwaVl6CHcb6GWPDFjGOJmOHX3VvRxYTDa\n1KIwlTTOVhZPJM3MjNadHqHg0k6sMt4hBuu90tnFPKmiCDO7UqqOsIgJRbQ91sW2Ru9JBvslYt3a\n3dvyIAJRIdxnrhOPDANeI/aAm0l62/S1YFAWamGsi0R1Hh9SIeyR+N4S61qICuGWGKy3SvsitSpI\nor+oDqK0tlcH0U/EuvaiQvi1haQlARKl8MSMhrSyOoj+ik3rp5LeNX0t+BoJYSYGKzdmlHYp6RM3\nZpQSizam7k6sQ0nEuhZj25kvXSodk8RgRW3MbGxml2Y2ihvzhOZq1C3GXLV6d6H2rCzGALRpeyPs\nRoUwMFhRUPXA8SDpV8WNGWXcSboys1+V9H3EOhR2KakV52RjNxaVBDO7Vypls/cgijCzX5D04+4+\nafpaMBxm9huS/jqrdlFKnFk8c/f3TV8L9iMhVJpKUZq2Y7CiiNhm5kFpj7W2nB+LnotYN2bzc5RC\nrOuOwSeEsZCk2mZm3fT1YBjM7EZpY1a2XkARWaxjmxkUQ6zrDnoIpSulhSQkgyjCzGaiSoPyriR9\nJBlEKWa2ELGuMwZdIWT6BKUxfYImEOtQWrbxObGuIwabEDJ9giYwfYLSiHVogpndSloR67qj9/sQ\nmtnUzO6jMlN9biSmT1BYrLQbEyBRSsS6GxHrUJO4v863PreQNCLWdUvvE8LYWmEp6SGelKWUDK7Y\nYgalxD6X7MOF0m6UjuIk1qEuHyXNoy2h6pFeSKI9oWMGM2Ucg/RS0v+U9A1bzKCUbMqOXhoUY2ZX\nSlUabsyoVVaJlqQflPSTxLruGcwqY3dfmtmflfTTkv5k09eDYcjaEy4IkCglpvAmknjwRe3cfWNm\nHyStJf08sa6bhlQhnCo9wVClQTE0VqO0mA25EnuroqA47euOWNddg0gImbJDE5iyQ2kR624kfSDW\noZSIdXJ3eqQ7rPdTxlkyyJQdiokAyZQdiiHWoQkR68Y64yISMxuxKr68Xq8yzp6WL9z9uunrwTBU\nlUGlijRBDbXLWmI+EOtQgpmNYl9VuftZYp2ZTaL/9f7kC8Sr9XbKOAbVQkydoJBYQFL1DDJ1giIi\n1l2KlhgUUnesMzN3dzv3++KwXk4ZEyBRGskgmkCsQ2nEuv7q3ZRxbI55lgAZJfHprs8f+hj9Eyfe\nzPd8rerdIkDirMzscl98iVi3EMkgCsli3R2xrn96kxBG8nar1Mj/7gzJ4EzSTNLIzG63koGFmT3E\n5+8lfZU0onfWki7jwPZHcUTTjaRrAiRqMFZK+h6Z2ficsQ54iYh1t0qxjq1leqgXPYTZvltnGahx\n059X75U1bL+NDThnSosGpHQsFAsHBiAqMhN3f59tOD1WOieWmzLOLsbZg6IKmMW6T+7+qdmrwxBs\nxboPJfa2pIewGZ1OCGOgLpQqeWdbPBJl8XtJb6pkz8xcKSjfmdk0zkjGwERF+N9L+htKDwM8KaNW\nkQT+HUn/TakqyAMIisiKIUWrgiSEzejsopIYqJeSVkrTJmer0kWwfRyMEZA3WRKY9xZOlZ7WqRL2\nXDyA/Iqkvy3pJ3goQCEbSd8v6XeLrYxQwI5iC7FuADqXEMZ07qXSk/KFuy8L/LVzSfnT0bp6Qjcz\nKY7EK3AdaEj0zywkLSV9m5sy6hYzFZdKU3U/WyjWYeCiNWauFOvOWmx5wd89Vxrv1XWs2VeznM5M\nGUciWD2xFOufiURgc2hQxnTyW84N7Z9sP8uV0gMI32PUaivWsak+ishi3Z3SPZZYNzCtqRCa2WRX\nX8xW6XqpWNhR6JpmSk8oy2x16UjSrbu/2Xr5WGklKnoga0nYKPVsMWWCWmWxbi7pWgVjHfot7l+b\nXeMpYt2V0v2LWDdgrUkIJd2a2WMAjOmSuZ4SwdKl66myqWGl1aXLuK7r7HWTeB0/RB0XN+SZ0rgb\nieCIAiLWVNtckQiiDtW2adXOGSM93V8lYh3UroRwKennzOz/6mnwNhIc42nqRmnxSPXptdKq0lVs\nUjxRqh5d6oyHeqO8rRvyUmmajuCI2kSMqR4+Nio8+4HBWUq6MbOV0kLIKtZ1bsV69BZOlR7a1/H7\nRulgAHZ9OMFXPYRZZazY9GdMzf4tSX9B0neUlri3epBGQjhSGoQE8Y6p9ppUCowbpYcP9pRErbIN\n76dKN+TWxzqcl5nNS/aFZrHuZyT9d0nfVUdjXdbGtar+P5rZgj05z2NXhXCq1FRaW0IYSedUaaVw\nFRh/2d1/tK6/89wI4u0SJzd82lfZi6CYjzkpjbv3NE/jGBHHFu6+d4eBPbHuzt2ZVRiuqjWgFgdi\n3Q+3OdZFDN+p+hmrVtpXrVrxb23tv6lrikwZxzevGqAzpYRzpXQDZ7sWnMNKaXzdSV/0A+ZBMR93\nBBGcaqXYIqOyIwEk1qFWexLAzsW6V/58zN39Y/y8da7S2VZnSwhjUI6VBuVo6/eV0gC95skY5xQB\nYaTUbvB74+Oqv7NzQRHtl7WLTCRV5wpXH5MA4uziAXf73lrdbwcV6+L/Rf4gVj144US7EsI/IOmH\ns8UU0x2vkdJAlNI3Zqw0GDfZ759UuBcR3ZQFu0o1praN9XSG9FRpqqD69T8k/Rd9xcD5IgAAA7JJ\nREFUeaIMsFeW2FVeGuuq8bWS9POS/rM6GuvMbNTFXrKuilj3Jjvp6rWxrmpVutNwY91cTz+DG315\n78AJdi0q+STpz0v6de2em19vfZ5FFThJdiKD9BTwtuWBb0MPJ04VqxWrCsugYl38zE2UeiDfNn09\nQxH/3/+ZpN8SsW6nqkBwoB/8i4cYMxt38WGsjTpzUgkA4LzMzN3dnn8lUL9YRVxtIzNXWg3NST2F\ntGkfQgAAMECxDmFS7SVoZhulvRM7uUVOF32r6QsAAACDN5K0iCljxZTxdn85asSUMQAMFFPGaKuY\nPr5y9zdNX8tQUCEEapStJtz39dGhj1/yHgDQQ3PF2csog4QQqIGZzcxsEX++jNWFuyzM7MHMbs3s\nXtnWJ694DwDojYh7LCgpjCljoAZmdu/u77KPH3Zt75GtqpO2zhd96XsAx2LKGG0TMVHuvoyFJmJb\nmTJYZQyc2Z7jlNZmNtmxp9imOp/zhPcAXsXM5ooNkWM/xjXVGDQt4t46i3GTXfER9SAhBM5vX8/f\nV/2BkkZZj+BU6eipzSvfA3iVLPmjRwutENXAG6WYWH16LYmEsBASQqBZj0/DEQRvJHEGLoBBiWlh\nVhQ36KuE0MymAz0fETgon2bb4+61Pzv59K+738XikkN/B4AO4x6LtnpMCKORcyxpFT0lS3qVgCev\n6LG609ebqe7aTmYi6XbHPlvjl74HgG7gHou2yyuEi2xF452ZPUhiRSPweit9nbyNqqpA3BiqVXOP\nSWYkiOuoFI4OvQeAzuEei1b7RmJFI3BO7r4xs2szW7j7p9hTK2/enyklfhdmNo1EcCPpUtKHF74H\n8Og17QxmdrvvRe5O/2oNuMeiC6oKISsagTNy92szG8eNYJnvo+XuH7I/f4qEcCzpQ74P4aH3AHKv\n2TKGpK8R3GPReqwyBmoSCdyzSdyhCsFL3wMAgFNwdB0AAMDAVQnhrkZ1StkA0FNmlm+Kjnpxj0Xr\nVQnhwVWRAID+iJXuM6VTIW5jUQrqwz0WrWfunv6QAsIoW9G45gxBAOiX2Ph87u4X8fFU6YSct/mi\nJpwX91i03WNCKD0GirHSQKWRHQB6Jla130t6UyWAZuaS3lOxqhf3WLTZFwkhAGBYYvr4aseJOQAG\nhFXGADBsc7HpOTB4VAgBYKCil23zmo2tAfQTCSEADFBMFcvdl9HbJvragOFiyhgABiZWFuerXCck\ng8CwUSEEgAGJauC9vtwXb+3ubxu6JAAtQEIIAAAwcP8fwT4K/upplEcAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "from pyx import *\n", "from pyx.graph import axis\n", "\n", "texter1 = axis.texter.decimal(plus=\"+\", minus=\"-\", equalprecision=1)\n", "texter2 = axis.texter.rational()\n", "\n", "class piaxis(axis.linear):\n", "\n", " def __init__(self, divisor=math.pi,\n", " texter=axis.texter.rational(suffix=\"\\pi\"), **kwargs):\n", " axis.linear.__init__(self, divisor=divisor, texter=texter, **kwargs)\n", "\n", "p1 = path.path(path.moveto(0, 0), path.curveto(3, 0, 1, 4, 4, 4))\n", "p2 = p1.transformed(trafo.translate(4, 0))\n", "p3 = p2.transformed(trafo.translate(4, 0))\n", "p4 = p3.transformed(trafo.translate(4, 0))\n", "\n", "c = canvas.canvas()\n", "c.insert(axis.pathaxis(p1, axis.linear(min=0, max=1e2)))\n", "c.insert(axis.pathaxis(p2, axis.linear(min=-0.7, max=0.4, texter=texter1)))\n", "c.insert(axis.pathaxis(p3, axis.linear(min=-0.7, max=0.4, texter=texter2)))\n", "c.insert(axis.pathaxis(p4, piaxis(min=0, max=2*math.pi)))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Texters do the formatting of the tick labels: They create the strings which are\n", "then passed to the painter. You can choose between fractions and decimal\n", "numbers with/without an exponential part. The `texter` should not be mixed\n", "up with the `painter`: The `painter` is afterwards doing the TeXing and finally\n", "creates the labels -- the `texter` prepares the string that is to be processed\n", "by TeX.\n", "\n", "The first example shows the default behavior, which chooses either decimal and\n", "exponential formatting.\n", "\n", "The second example is for special purpose only (because it is ugly), in case\n", "that it is strictly necessary to have the same width of all labels.\n", "\n", "The third example shows how to create fractions instead of decimal numbers.\n", "\n", " At the rightmost axis we also show how to create a special piaxis. Here, some\n", "axis parameters are altered to fit an pi-scaled axis nicely. Futhermore,\n", "instead of just creating a special axis instance by setting the divisor and\n", "texter parameters, a `piaxis` class is created which just alters the defaults\n", "of the linear axis it is based at.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/axis/texter.py0000644000076500000240000000165012515656657017224 0ustar andrestaff00000000000000import math from pyx import * from pyx.graph import axis texter1 = axis.texter.decimal(plus="+", minus="-", equalprecision=1) texter2 = axis.texter.rational() class piaxis(axis.linear): def __init__(self, divisor=math.pi, texter=axis.texter.rational(suffix="\pi"), **kwargs): axis.linear.__init__(self, divisor=divisor, texter=texter, **kwargs) p1 = path.path(path.moveto(0, 0), path.curveto(3, 0, 1, 4, 4, 4)) p2 = p1.transformed(trafo.translate(4, 0)) p3 = p2.transformed(trafo.translate(4, 0)) p4 = p3.transformed(trafo.translate(4, 0)) c = canvas.canvas() c.insert(axis.pathaxis(p1, axis.linear(min=0, max=1e2))) c.insert(axis.pathaxis(p2, axis.linear(min=-0.7, max=0.4, texter=texter1))) c.insert(axis.pathaxis(p3, axis.linear(min=-0.7, max=0.4, texter=texter2))) c.insert(axis.pathaxis(p4, piaxis(min=0, max=2*math.pi))) c.writeEPSfile("texter") c.writePDFfile("texter") c.writeSVGfile("texter") PyX-0.14.1/examples/axis/texter.txt0000644000076500000240000000214012037343037017366 0ustar andrestaff00000000000000Texter: Controlling the formatting of tick labels Texters do the formatting of the tick labels: They create the strings which are then passed to the painter. You can choose between fractions and decimal numbers with/without an exponential part. ... The `texter` should not be mixed up with the `painter`: The `painter` is afterwards doing the TeXing and finally creates the labels -- the `texter` prepares the string that is to be processed by TeX. The first example shows the default behavior, which chooses either decimal and exponential formatting. The second example is for special purpose only (because it is ugly), in case that it is strictly necessary to have the same width of all labels. The third example shows how to create fractions instead of decimal numbers. ! At the rightmost axis we also show how to create a special piaxis. Here, some axis parameters are altered to fit an pi-scaled axis nicely. Futhermore, instead of just creating a special axis instance by setting the divisor and texter parameters, a `piaxis` class is created which just alters the defaults of the linear axis it is based at. PyX-0.14.1/examples/bargraphs/0000755000076500000240000000000012615763300016323 5ustar andrestaff00000000000000PyX-0.14.1/examples/bargraphs/changebar.ipynb0000644000076500000240000010132112615761633021305 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Changing the attributes of the bars" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAVsAAADgCAYAAACttcXvAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAA+GSURBVHic7d1NjFvXecbx53VkaeSPOJQQWy7kWKbkoHUB2zKN1t3UKEAtUiN1imK0K4IgwKhd\nZWXMAEX3HPRjkaJoNUZW3QSapgt1lyFQFN0kgGi5aWA0ccS4RlDLbjyUbVkfVpS3Cx5KV9SQM7wf\nL0XO/wcMwHuHc84h7+XDc8+9c4+5uwAA1bpvuyeYWW27dVs9BwBw28iwNbOGmS1JOrfFr5fN7IKZ\nbZjZOUnNyloIAHPAthtGMDN3dxtatyhp0Jtdd/deRe0DgLmwJ+ff9dx9vdSWAMAcyxu2NTMbDB00\nJa3SuwWA0fKGbdfdO5JkZpJ0RtKJSQows1ckNSRdzay+LOntnG0CgHvB8aHlA5JO5xqz3eo5ko66\ne3enrTGzs5KOSvo4s/qSpP/caRkAcA96eWj5CUkrE/dszawhacPdDwz9qi5px2Er6S1J33b39qRt\nAIBZYWYtSRe3vc52hLVMQQ31hxUITQAYYWTPNl1jW0+PW+oH6pq7d8ysmUK2J6kl6WRIawFgRo0M\nW3cf9F5XtvjdagrbuqSTXIkAAOPlvRpBg6sRAADbyztmCwCYAGELAAEIWwAIQNgCQADCFgACELYA\nEICwBYAAhC0ABCBsASAAYQsAAQhbAAhA2AJAAMIWAAIQtgAQgLAFgACELQAEIGwBIABhCwABck+L\nU4LHJK2a2aakjrvfNdcZAMyiNEdjKy0ek9Q2d59WY1qS2kyBDmCeDbKOYQQACEDYAkAAwhYAAkzz\nBBkwdXZgzw/09L5jhQr5+Ob9+rX+xX9y7Rsj6zFr6Tcf/XN9ft+NQnV98OkH/vMPnylUBqaCsMXu\nttfu1w+PHSxURvuy9Np7C9s+7+++9nk1ny5UlZ7560+KFYBpYRgBAAIQtgAQgLAFgACELQAEIGwB\nIABhCwABCFsACEDYAkAAwhYAAhC2ABCAsAWAANuGrZnVxvyuWW5zAGA+jQxbM2uY2ZKkc1v8btHM\nltPjVpoCAgAwwsi7frl7R1LHzE5v8etld38xPW6b2QVJR6toIADMg4nHbNPQQW9odZfeLQCMlucE\n2ahx2pFjuwCw23E1AgAEmOZMDY9I+ubQFQ1dd1+bVoNw79h72P5hzxf1haLlXH1Tf+Hu3TLaBOxE\nmro862VJ7Txh25Y0PD6bZwjhmqQ3JJ3PrBseC8Zu9Tl97fG/0qEiRVxal66+qe9IImwRqT20/KSU\nr2fb0d3hWnP34Qq2c13S+Rx/h13gvgd17aGCV3F/wp6FKRjOtMHR+7jrbJcG3eF0Le1SKqgnaS1z\nne2ypJWqGg4A82DcdbaDsdO7gtTd18ysnhJ7nTExABgv9wmyFLCELADsAJd+AUAAwhYAAhC2ABCA\nsAWAAIQtAAQgbAEgAGELAAEIWwAIQNgCQADCFgACELYAEICwBYAAhC0ABCBsASDANOcgA1AyM2vq\n4IF1HX3yZqGC/uu/H/QrV/aX1CyIsAXmzx9/5ZJe/5sjhcr43a98WE5jMMAwAgAEIGwBIMA0hxH2\nSTpuZpLUc/fOFNsCAKUxs5qkRlrMPZV5WRYkvSDpoPpzmRG2AOZFTVIzPT4iTTdsP5L0veE51gFg\n1qUJcVckycxaEmO2ABCCsAWAAFxnix0bGvQvhOEj7DaELSbReOJ39N1jf6CDRQrp/JOuSHqwpDYB\nM4GwxUQef1af/GGrWNj+7N90taz2ALOCMVsACEDYAkAAwhYAAhC2ABCAsAWAAIQtAAQgbAEgAGEL\nAAEIWwAIQNgCQADCFgAC5ArbdPenkcsAgDvl7dkum9kFM9sws3O6Pf0DAGALee/61VF/3jBJWnf3\nXkntAYC5lDdse+6+XmpLAGCO5Q3bmpkNhg6aklbp3QLAaHnDtuvuHUkyM0k6I+lEWY0CgHmTK2wH\nQZset9OJsnqavnenHpO0amabmXUdd1/J0yYAuBeY2cbQqmOS2hOHrZk1JG24+4GhX9V1+6TZTrwv\naZmJ/wDME3e/4yjfzFpS/ku/1jIFNdQfViA0AWCEicM2DSH0zKxhZnVJLUknS28ZAMyRXD1bd19N\nD+uSTmbHcAEAd8s9lTkBCwA7x41oACAAYQsAAQhbAAhA2AJAgNwnyADsbrZ34bLqz10rVMgvf7Ff\nH/7vq7vhOn3CFkA+j9f/T9/+4ZFCZXxnRTqzuv3z5gDDCAAQgLAFgACELQAEIGwBIABhCwABCFsA\nCEDYAkAArrOdA+m+wvUSiupxNzegGoTtfFj60yUtP1IrVsj3z+odSU+V0SAAdyJs58RXF6Xfb27/\nvHG+f7actgC4G2O2ABCAsAWAANMcRnhE0jfNrKn+7Lxr2/0BAMyCdNJ6KS2+LKk9zbC9JukNSecl\n9abYDgAoW0/S4LaRT0rT7dlel3R+N9zHEsDu4u63wjYdvTNmCwARCFsACEDYAkAAwhYAAhC2ABCA\nsAWAAIQtAAQgbAEgAGELAAEIWwAIQNgCQADCFgACELYAEICwBYAAhC0ABCBsASBAobAd3BQXADBe\nrrA1s0UzW06PW2bWKLdZADBf8k6Ls+zuL6bHbTO7IOloSW0CgLkzcc82DR0MT9DYpXcLAKPlGUYY\nNU5bK9IQAJhn05xdd5+k42aWXddz986U2lO6NHd8vYSiuu7eLaEcYOako+YyOnMhn6MtLhyY+lTm\nC5JekHQws64raW7C9suH9ZfPPqXmFx7Ur/KWcelT7fnRz9WW9I0SmwbMjr21v9eX/uSxQmXcuLRH\nvR9FfY6Gw/aIlC9s25KGx2fzfOt8JOl77t7O8bcz4YF9Wjj1ig43j+cvo31eeu11LZTXKmDG3Lf3\nfv3e60cKlfFeW3rjtZDPkbuvZJfNrCXlG7Pt6O5wrc1zaAJAUROHrbv3JK1lrrNdlrQy/q8AYHfL\nNWbr7mtmVk8DweucvAGA8XKfIEsBS8gCwA5wIxoACEDYAkAAwhYAAhC2ABCAsAWAAIQtAAQgbAEg\nAGELAAEIWwAIQNgCQADCFgACELYAEICwBYAAhC0ABCBsASAAYQsAAQhbAAhA2AJAgNzT4pTgMUmr\nZrYpqTM8/S8AzCoza0hqpcVjktrTDNv3JS0zBTqAeePuHUknJMnMWhLDCAAQgrAFgACELQAEIGwB\nIABhCwABCFsACEDYAkAAwhYAAhC2ABCAsAWAAIQtAAQgbAEgwDRvRDM16Y48tRKK6rp7t4RyAEyZ\nmdUl1UsoqpduRHOHXRm2v/WI/vmPDutIkTJ6n0lrb2tVEreGBObDkrS0XLwfdvYdSU8Nr92VYStJ\nrReK/X37PWnt7XLaAuBesSipWbCMs1uuZcwWAALkClszq41bBgDcKW/PdtnMLpjZhpmdU/F+NwDM\ntbxjth1Jg7Pw6+7eK6k9ADCX8oZtz93XS20JAMyxvGFbM7PB0EFT0iq9WwAYLW/YdgcX7ZqZJJ1R\nmkkSAHA3c/f+A7Mljf/vifaoacfNzCUdneS/qczsrKSjkj4erHtA+uKCdH2nZYxwaVP6j3FPOLBP\nf/blh/VIkUqu3ZTe7OkHkv59ZD0P66tfelTPLNxfoJ4b0rsf6K3NT/SvY5728m8/r5f2LeSvR5K6\nP9VHlzb1j2Oe8uTDh/Rq7Yj2F6nn4o9147PL+ttxz7H9+tb+51ToFf3qovTZO/qupP8Z+aQH7vu6\nnl04VKQeXfu19O6Nt7R5c+w20vO/8ZIWCl7a/tNffqTNK2O3kQ49+qqOHC60jfTjn9zQ5U/HbiPt\n3f8t1Z8rttf1LkrvvzN+G33uga+r9myxbXTzmnTl3bd0fXP8NtLzL6nYbifpzevStfOZFU9IWrkV\ntjuV/tV1w90PZNa5pBOjwnhEOa9Iaki6mll9QNLmRA2622VJ2/27wdOSHipYjyS9J+nimN8fkvT4\nDNWz3Xv3kPrvXRnOb/P74yXV87b6r2uUWdsX2Eb5RW2jw5J+kVk+IOl03rBddPeVzPIZdz9aQiMB\nYC5NfJ1tGqvtmVkj3bihJelk6S0DgDkycc/21h/evnNWhysRAGC83GELANg5bkQDAAEIWwAIQNgC\nQADCFgACELYAEICwBYAAMxe2EbNCmFn2rmYzX0+mvjJmDh1XfugMHun9a1RYfqXv1xb1Re4LldQ1\nbpuXXeeousre78bVM8lrmpmwTf+xtiTpXMX1LKo/61stzUSxVFE9TaUZLqqsZ8iZij/QYTN4mFlL\n/e1UT4+rcM7MfOjndNmVmNli2u9kZstV7gtmtjR4v8ysVdaX1bjPZ3p9y2XVOaqusjNiu9ekSXPC\n3Wfqp9/kysquS2pllpvq3xinVsXrkNRIjxclbVb8vg12mmaFdSymepaqeM8y9bQkLaXHjareu1RP\nM/NzuqJ9oTW0fLqi11PPvldpeaPkOnyLdeeGli9UVde49WXVkzcnZqZnG6Smfu+sJknev4tZTf0P\ndNlO6vbUQnX1pxqqRDoc7kqq+t+qe+6+ln4qqSttm2V3X5P69+rwzB3oSqynLmnN3bO3Fq1qCqjF\nKodDsvUos595/5aozSqHS9KR1PB71g16vVXJlRMFb645X7x/kx0bLKdDhZ5PcOvICepaT3XU1P9m\nXCm7joyGu68PDuUqFDGDR0NSJ9Uz2MHXfIJ7Ke9Etry0jeqDgK/AuvpDFqtpuap6Rm2LwZdxFUYN\nJc3sjNx5c4KwHW9JFYZg+nZvqNpe7aKk0r8sRoiYwaOpFA7u3jWzTqrnxZLryVpWdQEoSYOQXVI/\n9Kqa329d/aERSbf2PxS3o5xgGGGE1Atcr7A3MzgEXlM/bDcqOItaV/8bN+SubIOgTY/bquYQtaf+\na+qmerqSGhWf+GuW3XMeSNu8pX7gHlX/i7H0fUGS0n5wIp2kWtQM9y7vFZPkBD3bLaQdsZsOvevS\nnYeVJZTfUP8Ez6m0KjvmU2YvtKn+2fpBEDXUHx9U2UMjW83gkZR9iFrZUcBWRow5lmlR/SmnBnWs\npKOCsvcFSbe+EG+9h2ZWyTBZRlt3j2XORchPmhOE7ZD04epmemkNL3/a9obuHMsa7Ixljzve8W2b\n+Rau6sN1q74Uvt2y63L39ha9vp6qC+Gqr33taevwqaonvSHpVBqCWVK1wyNSf7sMv75axQFfuTw5\nMTPDCFtcH1j6tYjp2+mMMtdXKjPGVZYUguvpOr6a+mM+pyo8VM1ei7pYxSG3x87gccrMTqfXdVrS\nStRQSdnSB7Seuc520Fuq6oRVT/3t1FQ/IEo5JzHq85m2y1rmOttlFTwPMqqusjNiTD25coKbh0+R\n3Z7tosoPVygLmsEj7fC3TpRVXE+pw0gj6gnZF9KXe0P9ce+wIZmo7XUv+3+2AfyttDzgoAAAAABJ\nRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.bar())\n", "g.plot(graph.data.file(\"minimal.dat\", xname=0, y=2), [graph.style.changebar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example is equal to the [minimal bar-graph example minimal.html] except for\n", "the used style to draw the bars. \n", "\n", " It is not possible to use the changebar style to change itself on a list of\n", "data as it is shown for the bar style in the [comparing bars example\n", "compare.html].\n", "\n", " We are sorry that a graph key implementation for the changebar style is\n", "currently missing. The implementation of such a graph key needs a major rework\n", "on the whole graph key system. This rework is planned for the near future.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/changebar.py0000644000076500000240000000034612515656657020631 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.bar()) g.plot(graph.data.file("minimal.dat", xname=0, y=2), [graph.style.changebar()]) g.writeEPSfile("changebar") g.writePDFfile("changebar") g.writeSVGfile("changebar") PyX-0.14.1/examples/bargraphs/changebar.txt0000644000076500000240000000104312037342027020771 0ustar andrestaff00000000000000Changing the attributes of the bars This example is equal to the [minimal bar-graph example minimal.html] except for the used style to draw the bars. ... ! It is not possible to use the changebar style to change itself on a list of data as it is shown for the bar style in the [comparing bars example compare.html]. ! We are sorry that a graph key implementation for the changebar style is currently missing. The implementation of such a graph key needs a major rework on the whole graph key system. This rework is planned for the near future. PyX-0.14.1/examples/bargraphs/compare.ipynb0000644000076500000240000011547612615761637021045 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Comparing bars" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.nestedbar())\n", "g.plot([graph.data.file(\"minimal.dat\", xname=\"$0, 0\", y=2),\n", " graph.data.file(\"minimal.dat\", xname=\"$0, 1\", y=3)],\n", " [graph.style.bar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To draw bars side by side to show differences for the same value you basically\n", "need to replace the bar axis by a nestedbar axis and adjust the data to that\n", "nesting. The latter is done by providing a tuple of two values to the\n", "nested bar axis instead of a single value. The first element of the tuple is\n", "used to select a subaxis (in the present case: one out of twelve) of the\n", "nestedbar axis. The second element of the tuple then selects a sub-axis of\n", "that particular bar axis (here: one out of two).\n", "\n", " You can replace `0` and `1` in the values provided to the xname parameter of\n", "the data by other unique hashable objects. Note, however, that this does not\n", "affect the order of the bars of the subaxis. Instead, the order is defined by\n", "the order that data is added to the bar axis. Consequently, when you swap `0`\n", "and `1` in the xname parameter nothing will change in the output. However, this\n", "value becomes relevant if you turn on naming of the sub-axis by using\n", "\n", " graph.axis.bar(defaultsubaxis=graph.axis.bar(dist=0))\n", "\n", "instead of the `graph.axis.nestedbar` instance in the graph constructor.\n", "\n", " You can also use the same values (i.e. objects with the same hash value) for\n", "the subselection of the nested bar axis. Then the bars will overpaint each\n", "other and by proper ordering of the data you can fake stacked bars by that. For\n", "an description of how to do this properly, we refer to the [stacked.html Stack\n", "bars on top of each other].\n", "\n", " Let's suppose you change the values provided to the xname parameter of the\n", "data from `\"$1, 0\"` and `\"$1, 1\"` to `\"0, $1\"` and `\"1, $1\"`, respectively. The\n", "answer is, that all red bars will be shown on one subaxis and all blue bars\n", "will be shown on another subaxis.\n", "\n", " A nested bar axis is totally equivalent to a regular bar axis except for its\n", "default value for the `defaultsubaxis` parameter in the constructor. While this\n", "`defaultsubaxis` parameter is a special instance of a linear axis for the bar\n", "axis, for a nestedbar axis its a special instance of another bar axis. The\n", "nesting of bar axes is not limited to a single level: You can nest bar axes\n", "into each other to any level you want. Providing explicit subaxes for certain\n", "values, the nesting levels can even vary for the differen subaxes. (This is\n", "totally crazy.)\n", "\n", " In PyX versions prior to PyX 0.9 the creation of nested data for the bar axes\n", "was hidden inside the graph styles (with the limitation as we use it here in\n", "this example: adding precisely a single nesting level when passing multiple\n", "data to a single set of styles). In previous versions we didn't had the\n", "possibility to simply generate tuples for data columns. The automatism was\n", "removed completely, which makes *all* the bended sections above possible.\n", "This is a quite incompatible but absolutely necessary change.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/compare.py0000644000076500000240000000045312515656657020344 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.nestedbar()) g.plot([graph.data.file("minimal.dat", xname="$0, 0", y=2), graph.data.file("minimal.dat", xname="$0, 1", y=3)], [graph.style.bar()]) g.writeEPSfile("compare") g.writePDFfile("compare") g.writeSVGfile("compare") PyX-0.14.1/examples/bargraphs/compare.txt0000644000076500000240000000537012037340753020520 0ustar andrestaff00000000000000Comparing bars To draw bars side by side to show differences for the same value you basically need to replace the bar axis by a nestedbar axis and adjust the data to that nesting. ... The latter is done by providing a tuple of two values to the nested bar axis instead of a single value. The first element of the tuple is used to select a subaxis (in the present case: one out of twelve) of the nestedbar axis. The second element of the tuple then selects a sub-axis of that particular bar axis (here: one out of two). ! You can replace `0` and `1` in the values provided to the xname parameter of the data by other unique hashable objects. Note, however, that this does not affect the order of the bars of the subaxis. Instead, the order is defined by the order that data is added to the bar axis. Consequently, when you swap `0` and `1` in the xname parameter nothing will change in the output. However, this value becomes relevant if you turn on naming of the sub-axis by using graph.axis.bar(defaultsubaxis=graph.axis.bar(dist=0)) instead of the `graph.axis.nestedbar` instance in the graph constructor. !! You can also use the same values (i.e. objects with the same hash value) for the subselection of the nested bar axis. Then the bars will overpaint each other and by proper ordering of the data you can fake stacked bars by that. For an description of how to do this properly, we refer to the [stacked.html Stack bars on top of each other]. !! Let's suppose you change the values provided to the xname parameter of the data from `"$1, 0"` and `"$1, 1"` to `"0, $1"` and `"1, $1"`, respectively. The answer is, that all red bars will be shown on one subaxis and all blue bars will be shown on another subaxis. !! A nested bar axis is totally equivalent to a regular bar axis except for its default value for the `defaultsubaxis` parameter in the constructor. While this `defaultsubaxis` parameter is a special instance of a linear axis for the bar axis, for a nestedbar axis its a special instance of another bar axis. The nesting of bar axes is not limited to a single level: You can nest bar axes into each other to any level you want. Providing explicit subaxes for certain values, the nesting levels can even vary for the differen subaxes. (This is totally crazy.) ! In PyX versions prior to PyX 0.9 the creation of nested data for the bar axes was hidden inside the graph styles (with the limitation as we use it here in this example: adding precisely a single nesting level when passing multiple data to a single set of styles). In previous versions we didn't had the possibility to simply generate tuples for data columns. The automatism was removed completely, which makes ''all'' the bended sections above possible. This is a quite incompatible but absolutely necessary change. PyX-0.14.1/examples/bargraphs/errors.ipynb0000644000076500000240000012304012615761652020712 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Skipping the first bar in a stacked bargraph" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nff4fZSpkTH/D+5MAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from random import random\n", "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.bar())\n", "g.plot(graph.data.file(\"minimal.dat\", xname=0, y=2, stack=3,\n", " dy=\"1+random()\", dstack=\"1+random()\",\n", " context={\"random\": random}),\n", " [graph.style.errorbar(),\n", " graph.style.stackedbarpos(\"stack\"),\n", " graph.style.bar([color.rgb.green]),\n", " graph.style.range({\"y\": \"stack\"}),\n", " graph.style.errorbar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows a bar graph, which starts with a stacked bar skipping to\n", "plot the original bar. This is done by using stackedbarpos before plotting\n", "a bar with the bar style. However you can still add errorbars, even to the\n", "lower bound of the bar.\n", "\n", " This example also shows how to handle several errorbars in one plot command\n", "by the usenames argument of the range style.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/errors.py0000644000076500000240000000103112515656657020223 0ustar andrestaff00000000000000from random import random from pyx import * g = graph.graphxy(width=8, x=graph.axis.bar()) g.plot(graph.data.file("minimal.dat", xname=0, y=2, stack=3, dy="1+random()", dstack="1+random()", context={"random": random}), [graph.style.errorbar(), graph.style.stackedbarpos("stack"), graph.style.bar([color.rgb.green]), graph.style.range({"y": "stack"}), graph.style.errorbar()]) g.writeEPSfile("errors") g.writePDFfile("errors") g.writeSVGfile("errors") PyX-0.14.1/examples/bargraphs/errors.txt0000644000076500000240000000065112037340753020403 0ustar andrestaff00000000000000Skipping the first bar in a stacked bargraph This example shows a bar graph, which starts with a stacked bar skipping to plot the original bar. ... This is done by using stackedbarpos before plotting a bar with the bar style. However you can still add errorbars, even to the lower bound of the bar. !! This example also shows how to handle several errorbars in one plot command by the usenames argument of the range style. PyX-0.14.1/examples/bargraphs/fromvalue.ipynb0000644000076500000240000010161312615761642021377 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Changing the starting values of the bars" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.bar())\n", "g.plot(graph.data.file(\"minimal.dat\", xname=0, y=2),\n", " [graph.style.barpos(fromvalue=0), graph.style.bar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To adjust the value the bars are starting at you need to set a `fromvalue` at\n", "the `barpos` style. By default the bars start at the baseline not taking\n", "into account its value at all.\n", "\n", " When setting a `barpos` style explicitely, no other positioning style\n", "instance is needed by the bar style and thus you can set other default values\n", "for the `barpos` style. Note, that as soon as you explicitely set a barpos\n", "style, you can also use other styles requesting a point position at the graph\n", "(since the bar style also initializes a point position). Hence you could for\n", "example replace the bar style in this example by a `graph.style.symbol`\n", "instance.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/fromvalue.py0000644000076500000240000000041012515656657020707 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.bar()) g.plot(graph.data.file("minimal.dat", xname=0, y=2), [graph.style.barpos(fromvalue=0), graph.style.bar()]) g.writeEPSfile("fromvalue") g.writePDFfile("fromvalue") g.writeSVGfile("fromvalue") PyX-0.14.1/examples/bargraphs/fromvalue.txt0000644000076500000240000000126412037342027021064 0ustar andrestaff00000000000000Changing the starting values of the bars To adjust the value the bars are starting at you need to set a `fromvalue` at the `barpos` style. ... By default the bars start at the baseline not taking into account its value at all. !! When setting a `barpos` style explicitely, no other positioning style instance is needed by the bar style and thus you can set other default values for the `barpos` style. Note, that as soon as you explicitely set a barpos style, you can also use other styles requesting a point position at the graph (since the bar style also initializes a point position). Hence you could for example replace the bar style in this example by a `graph.style.symbol` instance. PyX-0.14.1/examples/bargraphs/minimal.dat0000644000076500000240000000033012037344757020450 0ustar andrestaff00000000000000January -5 1 Feburary -4 3 March 0 8 April 3 13 May 7 18 June 10 21 July 12 23 August 12 23 September 8 19 October 4 13 November 0 6 December -4 2 PyX-0.14.1/examples/bargraphs/minimal.ipynb0000644000076500000240000010347612615761623021035 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Minimal bar-graph example" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nFwAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.bar())\n", "g.plot(graph.data.file(\"minimal.dat\", xname=0, y=2), [graph.style.bar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a minimal bar plot you have set an bar axis in the graph constructor and\n", "provide Xname column data (X stands for the bar axis to be used). Here, we\n", "just use column 0 which is automatically filled by `graph.data.file` with the\n", "line number of the corresponding entry. Furthermore, you need to specify the\n", "graph style, since the default graph styles `symbol` and `function` (depending on\n", "the data type) are not appropriate for bar graphs.\n", "\n", "Note that bar graphs differ from other xy-graphs in that they use *discrete\n", "axes* for one graph dimension. However, the only affected components of this\n", "fundamental change are one of the axes, which needs to be come a discrete one,\n", "i.e. a bar axis, and the usage of appropriate graph styles.\n", "\n", " A bar graph is fundamentally different from a graph with a histogram style in\n", "its usage of a *discrete axis* in one graph dimension. A histogram instead is\n", "created using *continuous axes* in all graph dimensions and just drawing the\n", "data in a specific bar-graph-like presentation. In particular, the discreteness\n", "of the bar axis is reflected in the naming of its column name: instead of the\n", "continuous \"X\" it expects an \"Xname\" (where X stands for the bar axis used) as\n", "mentioned above.\n", "\n", " As all axes and graph dimensions in the PyX graph system are treated equally\n", "all you need to modify to get bar graph with horizontal bars is to assign the\n", "bar axis to the y-axis in the graph constructor and change the names of the\n", "data columns to `yname` and `x`.\n", "\n", " By using the bar style you implicitly also select a different positioning\n", "style, namepy `barpos`. This positioning style handles a single-nested axes\n", "with sub-axis values of the range going from 0 to 1.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/minimal.py0000644000076500000240000000033212515656657020340 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.bar()) g.plot(graph.data.file("minimal.dat", xname=0, y=2), [graph.style.bar()]) g.writeEPSfile("minimal") g.writePDFfile("minimal") g.writeSVGfile("minimal") PyX-0.14.1/examples/bargraphs/minimal.txt0000644000076500000240000000330612037340753020515 0ustar andrestaff00000000000000Minimal bar-graph example For a minimal bar plot you have set an bar axis in the graph constructor and provide Xname column data (X stands for the bar axis to be used). ... Here, we just use column 0 which is automatically filled by `graph.data.file` with the line number of the corresponding entry. Furthermore, you need to specify the graph style, since the default graph styles `symbol` and `function` (depending on the data type) are not appropriate for bar graphs. Note that bar graphs differ from other xy-graphs in that they use ''discrete axes'' for one graph dimension. However, the only affected components of this fundamental change are one of the axes, which needs to be come a discrete one, i.e. a bar axis, and the usage of appropriate graph styles. ! A bar graph is fundamentally different from a graph with a histogram style in its usage of a ''discrete axis'' in one graph dimension. A histogram instead is created using ''continuous axes'' in all graph dimensions and just drawing the data in a specific bar-graph-like presentation. In particular, the discreteness of the bar axis is reflected in the naming of its column name: instead of the continuous "X" it expects an "Xname" (where X stands for the bar axis used) as mentioned above. ! As all axes and graph dimensions in the PyX graph system are treated equally all you need to modify to get bar graph with horizontal bars is to assign the bar axis to the y-axis in the graph constructor and change the names of the data columns to `yname` and `x`. !! By using the bar style you implicitly also select a different positioning style, namepy `barpos`. This positioning style handles a single-nested axes with sub-axis values of the range going from 0 to 1. PyX-0.14.1/examples/bargraphs/month.ipynb0000644000076500000240000026262712615761627020544 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Naming bars" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nlgAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "mypainter = graph.axis.painter.bar(nameattrs=[trafo.rotate(45),\n", " text.halign.right],\n", " innerticklength=0.1)\n", "myaxis = graph.axis.bar(painter=mypainter)\n", "\n", "g = graph.graphxy(width=8, x=myaxis)\n", "g.plot(graph.data.file(\"minimal.dat\", xname=1, y=2), [graph.style.bar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To name the bars you just need to use a proper data column (instead of column\n", "0, which is the line number in `data.file` instances). Beside that we show\n", "in this example how to adjust the bar axis painter to properly show the names.\n", "\n", " The internals of a bar axis are quite different from a continuous axis (like\n", "a linear or logarithmic) axis. A bar axis just handles a set of subaxes - one\n", "for each discrete value. The painting of a bar axis can only draw the names for\n", "the subaxes and some ticks between the subaxes. Other axes features known from\n", "continous axes like ticks and labels, partitioners, texters, raters are\n", "non-existent for bar axes.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/month.py0000644000076500000240000000066012515656657020043 0ustar andrestaff00000000000000from pyx import * mypainter = graph.axis.painter.bar(nameattrs=[trafo.rotate(45), text.halign.right], innerticklength=0.1) myaxis = graph.axis.bar(painter=mypainter) g = graph.graphxy(width=8, x=myaxis) g.plot(graph.data.file("minimal.dat", xname=1, y=2), [graph.style.bar()]) g.writeEPSfile("month") g.writePDFfile("month") g.writeSVGfile("month") PyX-0.14.1/examples/bargraphs/month.txt0000644000076500000240000000123112037340753020207 0ustar andrestaff00000000000000Naming bars To name the bars you just need to use a proper data column (instead of column 0, which is the line number in `data.file` instances). ... Beside that we show in this example how to adjust the bar axis painter to properly show the names. ! The internals of a bar axis are quite different from a continuous axis (like a linear or logarithmic) axis. A bar axis just handles a set of subaxes - one for each discrete value. The painting of a bar axis can only draw the names for the subaxes and some ticks between the subaxes. Other axes features known from continous axes like ticks and labels, partitioners, texters, raters are non-existent for bar axes. PyX-0.14.1/examples/bargraphs/README0000644000076500000240000000100312037344757017206 0ustar andrestaff00000000000000Bar graphs In this section we show you the basic features of bar graphs in PyX. All examples shown here use the same data from `minimal.dat` available for download at the first [minimal bar-graph example minimal.html]. Note that bar graphs differ from other xy-graphs in that they use ''discrete axes'' for one graph dimension. However, the only affected components of this fundamental change are one of the axes, which needs to be come a discrete one, i.e. a bar axis, and the usage of appropriate graph styles. PyX-0.14.1/examples/bargraphs/stacked.ipynb0000644000076500000240000031220312615761646021020 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Stack bars on top of each other" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=14, height=6, x=graph.axis.bar())\n", "g.plot(graph.data.file(\"minimal.dat\", xname=0, y=2, stack=3),\n", " [graph.style.bar(),\n", " graph.style.text(\"y\"),\n", " graph.style.stackedbarpos(\"stack\"),\n", " graph.style.bar([color.rgb.green]),\n", " graph.style.text(\"stack\")])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To stack bars on top of each other, you can add stackedbarpos styles and\n", "further bars to the list of styles. The stackbarpos need to get different\n", "column names each time to access the new stack data. This example also adds\n", "text styles to the bars, which just repeat the value column data here, but they\n", "could refer to other columns as well.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bargraphs/stacked.py0000644000076500000240000000061712515656657020336 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=14, height=6, x=graph.axis.bar()) g.plot(graph.data.file("minimal.dat", xname=0, y=2, stack=3), [graph.style.bar(), graph.style.text("y"), graph.style.stackedbarpos("stack"), graph.style.bar([color.rgb.green]), graph.style.text("stack")]) g.writeEPSfile("stacked") g.writePDFfile("stacked") g.writeSVGfile("stacked") PyX-0.14.1/examples/bargraphs/stacked.txt0000644000076500000240000000057212037340753020507 0ustar andrestaff00000000000000Stack bars on top of each other To stack bars on top of each other, you can add stackedbarpos styles and further bars to the list of styles. ... The stackbarpos need to get different column names each time to access the new stack data. This example also adds text styles to the bars, which just repeat the value column data here, but they could refer to other columns as well. PyX-0.14.1/examples/bitmap/0000755000076500000240000000000012615763300015626 5ustar andrestaff00000000000000PyX-0.14.1/examples/bitmap/jpeg.ipynb0000644000076500000240000044134712615761710017636 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Insert JPEG images without and with recompression" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "i = bitmap.jpegimage(\"jpeg.jpg\")\n", "c = canvas.canvas()\n", "c.insert(bitmap.bitmap(0, 0, i, compressmode=None))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the `bitmap.jpegimage` class, PyX allows you to directly insert a\n", "JPEG image into a canvas. It extracts the compressed JPEG data and makes\n", "the data available to a PyX bitmap without recompression (i.e. without loss\n", "of quality). \n", "\n", " Note that you need to set `compressmode` to `None` when creating the\n", "bitmap instance, since the data provided by the image instance `i` is\n", "already compressed. If you forget to do so, PyX will fail and report about\n", "this mistake. (The original source of the problem is that PyX tries to\n", "compress all images using the gzip method by default and you need to\n", "turn off this feature to prevent the data from being double compressed.)\n", "\n", "Since we have some image data in this example, let us also discuss how to use\n", "the [Python Imaging Libary PIL http://www.pythonware.com/products/pil/] to load\n", "the data and write it to the file. The straightforward solution would be to\n", "replace the creation of the `bitmap.jpegimage` instance by:\n", "\n", " import Image\n", " i = Image.open(\"jpeg.jpg\")\n", "\n", "While this works perfectly, it will result in a totally uncompressed\n", "image. The size of the EPS file will for example become almost 1.1MB.\n", "\n", "In a next step, you may turn on the default gzip-based compression by\n", "omitting the 'compressmode=None' (or by setting `compressmode=\"Flate\"`\n", "explicitely). This will reduce the file size down to about 727KB (EPS)\n", "which is still much larger than the version in the above example which\n", "used the JPEG compression. Note that this does not mean that the gzip\n", "based compression method is bad in general - it is just bad compared to\n", "the JPEG method for certain kind of image data like photos.\n", "\n", "Finally, since the image instance is a PIL instance, we can also use\n", "`compressmode=\"DCT\"`, which turns on the lossy JPEG compression method.\n", "This will restore the file size to similar values as we got previously by using\n", "the `bitmap.jpegimage` instance. The file size and quality of the loosy\n", "compression can be adjusted by the `dctquality`, `dctoptimize`, and\n", "`dctprogression` parameters of the `bitmap` constructor. Nevertheless, it is\n", "important to note that you will always get some additional artifacts due\n", "to the recompression by the lossy JPEG compression method. It is also\n", "important to note that the original version shown in this example (using\n", "`bitmap.jpegimage`) does not use the PIL at all.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bitmap/jpeg.jpg0000644000076500000240000011400412516412061017250 0ustar andrestaff00000000000000JFIF,,ExifII*  8(TF1 2K.iPanasonicDMC-LZ1HHVer.1.0 2005:04:07 16:32:56PrintIM0250d  ' ''''^''''"@H"O8'@880220Pdx en9- 9- |\010085 O-n_UIAU.ISO%1515-888 85 IS  2005:04:07 16:32:562005:04:07 16:32:56d = Panasonic !"#$%&0100'() *+,-./012DVEP?DB0?AF`G bGdGfGNGPrGtGzG|G~G@G@BG[ LG8\GvGxGRGVG+TGHlGpG-nG]XGGGGGG[ GGGGGjG?STFFFFFFFFFFFGGFFDD?AEEEDE"J1YYFFF F!FEFAPXFYFYYPYM`YD`LDNDDDDEErEUEEEEEEEEkEdEEERDTDVDXDDDDD]XXX8X%6X8X:X9GE?CM E?ISFFCFF`FbFAEBMPRSTFCCV[ [ A A Y @q @  ]WBCZ       # 0HGT DHT@T 0@P @peTpeTpfT0#>Y #>YF020502140166sr R980100 hp(HHC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222A">!1A"Qa2q#BR3b$Ccr(!1AQ"2a#Rq ?񖹏\&^dB&oRadx|;‘PmQt&^E2 p"qט;,<\F2,:5d ^f ݰwPa qZJM,užd5.`1V;9Iq:NfsȢKg?6;_'=K Dr (MFbdVlf٠"FaPb6%!2JA>[)#YuFQnetKӜ#<%B߿xAlә*?9N+ܣĦ1QKlJjO8b2YUBٓQĆB.̴l)3aHKZ0DɅd' шбuj4,I G\HΠb&* !arx?D%&8 `Ѷ7"-s Y L}4@B!dF&aQtOZqC:"]h@=g+ʁz#^ ۑ(k*МwSܹ ws9K^LrHf2љ1b0 H5)3JI?L5cRT4V@X>8h 1HRD 4XD}fg{&6GU3XTɞ/Nn }m<#S_w$}[C?yg)lb>OK,w5EĪh (zڷ*Ñ HC6(b\W%8@']ߧ6L#Ĭ8t+95 c*^g\kr:фAR54lj$! b :cړ4P٦ur4ej|mA0 n@'e9`x˦in&~YǴ^2\YI "WLz(l:Gh0\~ʚqKWo[8u\Cn2l4o-f!St4``rhtunRʴH_Vd"Ms"S${k*&1rt cQLQ&JIQ]Įc5Hunt\w;Gɒmi0+k5@]wK2@ n."]D0rerV*dObwyKWfVp o1 >\cE`vτB LID:1c\>*ze؎UNν)R ĨF؛X<0`:Z"}znq8 qIUιIO9ΥHV$BP)H;{ajmyȨi]'3[64T "d\ђ+edZ[gb]׊#̃㪟GV)Yُmw5-@ ~E "*ͽ*OwV;3N!sN_H5iRE&< 4c(>Y(^fKl'К# 6ɹV"lTlP:j ^c/&( `IeF7pޤZ,C[9L.c ^Irv6d-SPWxRi3bS'zwdP;u-3 XIRD<7Nz.ԏ9,O5 tM<=å@a>[l+)z:d =Ufۏ~y!h~[DN{a@Z['4LN_jv$Dq'G&;lE[=7j̾ӗ6HVn8ظ5\ Xq-pq8؇j ZFbW}t*~YuPDCau>ڬBN7%~>׳7D NYD;䉔~Ֆ$nʏ;thxV*)?ya&y3>}1N#q s3xܶZGfkDU~|CWV1E׈2BFEq!ٳ$IVb4Jtġ;Tnk$v3 x>'I`+:x`! NWbXkNs>{3˺[O:w޸Ux4R)jW'D [I#qN} I#z 2TWGud8W "Q_8a(3HO[{%âef>J56h'KM2HlTq+krԈh찊ISvIJ<t)h& !cpy+aVQ%s+)gEWgо֠z1T|讫f/QZÞg7w% ~uٽrORw V(a(9$F<#>?_L X*7;ːyXV؄D Ge+TcNq3 P; Wu "[bW~#jI #= ],UPKL\p=f?pTi4A˻p0w7%ZA24cbv% 7 qH>g!mF Gn g/r0y!<ΊZ91kTnJg,s##@B9KKH0aW{ۍ2WX ㉾뉦}O@DQɰ(_̈́% >/ݾ( D'c$P Gi 6u+_{- l(o{}/"Z>m 0 aМY=M{FG@]zW:l.n?yS]oP eE=DT؟+%^Aߙ|\ Z0,qu +v‛(v5~2Jl;Ce3)&ukJD9rhVouhzO$ڲڿim 0l* d^L%1/#R!{V`uw2sHH C`j.s lvUcbX % VF&ބ{}Cz%6b-Ye Gf#3 ,o\#̣RN)Q.%\̉:.Nj;U¹ihdkqcҲ6uos>_T;u>nVzo}@*dDqh/gh;q[ȀNRx=HEUԨ"nK;\)$J)~凧,Խ̴D/mL2>;,2+zAnQ ~y2˳XGyX(eIWQ/Z μRD2O.WDB+-QB{jք8/P_pހfwho"c3v朗$ :aoiav5B)*?'nadMlTBnb :*mBwSGTt?#`h˺$c5/shȊ-s ^Gi+4L^]t+ :2:wɜ/r6Sr9H5qE rL6_&.I%i]R# gs#?d يB-Ds {\s[bm֋t;7j7"pg\&e6c$BM UR?K'0g+ I2Z9_͡CW&8^^%u` ȲVU2j2Vt)Y@Ȍ[p M;=7zUKG;ޟ*n?1Scu\cXaA}0vaZ[O n`҂wΫggf[z0Hs4?ù7Mml|r@FS&W L Ua0,'.&z(V 'rb!qW|= OAkz~%pcw:IiHV'ᶧuwwq2(8P;-A]Tz8sN қ-lĴ>Ogޥԋ[+]ͯ=+aGe۬GӕY!@c)h6K)W9іy{R%&L0$a&wð1X*qw%jHd=Q_eS%[g7e  {"Vee F*a ъŷk~gi԰9\(rB2/1a#-fzC۳DSaıa1GD] ĆГvX׼m0Aw1́ĈnLJȑ A& dM4L`DpՐ X©͡ծ 6Īq8ΛWzoYԼi/oGil*%RآXw|3r;-GٌUKl!0 9SCwhXXZ$-Jĵ%Cv[y9u)x4+G3M"[љ[\zz*__M58.7R]S))ޣ@-K?n!(s>o"rRτIޤMhiV*[=V@^K:w9I2{<@dgR )e{A{NdJrdb X1= ̗t ó~$&@&Ȩ$3!1Ĝ!ư{M19"Ёg+t}1M 0*U?GPey)a:L%" 2aigGQ2dԠ0jnd OTZhKw>WĬouhۍY6WpaYc[u 5u/뚌 #FyEoS9K]Dx:v nOb`37q'CcNd;v{E~G@;^6'ӝuzӟ.0V@c%Zd4[FXP8 OPY ?XKNkoUf?Ǩ.[fK?eSySFk`[-f?æQ$nS2[u]:vΫ*ya:gVSXrF{lEiyg/5Z̡)$9'"{5%vv ''.4V>=\|$M-EcEnTJ}, c^Kz՗̌'{IreI:4Zį%wfX_ˌrC̓Y-k'a굟x%$+$:R}&$R$,zh , YI!)l*`{ܡ,sK}& {KNMK.EWi4~򁽠 ccW y4 W&;5%`Lvl2%;Mg*3p3Ĵsw:Θ=]hόVPycIJ=2,?WXwN#;0=G5Բnޔl9s&9%z-icQS<Ǫy.F̆R2IK2s9<{fםO$q$w7nIGDC OzhgOAز y2f Tzd9fu%UE,Of=Ttd ?_$*(%Y~?0¬7 tq0#tZ[|%Xbs\{/Kd5VnY?OzOK9u:b?c>=Sl͢ίUd??C<[Wc#WSR4AI(DYDƙO>kFHȒJGMGP1 WqSYc 5 [j> nKt'LHe_MO2^v8Ef LML ' 6^E {2LېH i *&XU-0j!KCAudFMa]AI^Ci%AE`:Oz7/2aJþn;4myM]Kqߴ'y ,U| OM阘TvTKPH|?Ncz#b XfbVl~]yK-ȇI%V^S%Dܔ,R3\Elx_/va fs{yUq=7 ,*fJhqIӟf1OI^n2Iǥ;2lN^nyFk+OD}IkAĴTdTOPpeN6$9{: pNxMDDg~|IK*v]̝-ud^$HP>|B =@mdߙ JB557]V5HeS024j1Y9&i|c  c" ǙycژSPd~!;@\z_~Ϭ)R <6ԗ~"->}+`x.zMF\LӵU%Cg1:mwȤNBeY)k{4j?F׷*&@Mod$ fn4j+, v%mB%Iq-Hx"FT|J*rYH LltG.錄aޗY}zzv;Õa%![}_]Iэ~]zl+R o@86b >qGqY0qoHǰ =OP`S90߅>Vj)To6sc׈R䜬<,ʦnCK?Yz'NE76}dۏz(|  %K/LsO'^ez5g*1z=#+` {dIrNdBw$Zù5²0GKxں)v0۲몱2ެWZЯCm)nosO[ud~VNipZLF{[ZtE'LbQO3"c{3WH) TAa3ڛ+@r0:3!W.}įi;l?u%ǰ m\՚ d>`9&wYёGQ{]\dqGH{B?j?Nƿ"OIWj 4׺眺5nUԫ#= 3%fbO=:ΘޤťUh `/#/ÕY2kQޗޣM7{VxtCe ыuz!06#c%tUǩ~ i@R~%tR0jQnmA69r:_̥fYa~`+9c6sz/J5颵W'uL/ӴQ;s.6D5ߘJ&4l9Ckxٖ5Hh gd l;.um}~'!TΙ@7"r= n";a1q'!)mN+/DB*є"|Aι+p6v^]',u3`bj Q,]ֽqk yYb:1;Y^xLk.ne3ČBLFr}T5mÙzשX Etf~{bPF2uvZ܈^aňћY&J%]tN'N+,'+z:yuP[}7Zc w NKR"DբU[ׯd(q0#Oj9M 6z$ɨ֦@ope5 1&*"AA Me$KHAm& c ߂b]5%21l@>3,ͮ|q>pR=/=#$/oc=목N~= uO-yn cp:: .(F6t}' oC[ʎ@Y)h=ŃrԲL@Vĩ*8of_K CF=K?C k8Tk>͏gr?*F><0k,>H#N8B6Q 1_ gbإ^>b"3FSml.$kUKCU]B2-Hu a%B6}_-(݄I/%+h&iIS=3 CCCϹ #[KZ0Ml総ȰhCJ~P}Ș>`^ ĉn7W0]|}%m L}!Z:3˿zX| f2.5+UcZ^}u]~÷_ a,S`䕰I9SKNLg b w̕NM#n6m'H#*- dԍAv1WPU8 q\8׍ }Hn,9]M;TzO:b㺩>2,7;;rXKcڰq̀:cܑ*jofla":ܑ6Z e"6ԃ,WFd!^fKE䄁tJD#D{7!Uh@`f`2^ rۛ7$CS$|4&jaP͉@Mb2b#_79'*UՇh+.Ϊ*s,'^,rq9xf$4/^BgRruOa2ʫɠ݊;]GΣJ6$xPu7b(ZEL.2z-& (oh}DDZ7įa {-{~ӣ*PRЖ7W~}a@@ {` -mlG)XmEK2>Q)X|CZ+4 }|+Ps= 1ݰk*9#s3:h ju (eNڧ28AHmMFmS1S-"MZ\trl.G.ET z9:~3u7Z=j 'տ♍Z?ǝ{E鲃Ȥ}BޣwS21:}AӺmMCW*&|[v_#>pթnTL1- gOoh59̚.ֵُ$⦲7z5ip؊Q̋QbD",ٙ]C4V$€뙲7$W%b7W-3[*$D̋h%[GbdkǏ}Dw;T y`=v%L ⋹;%[%oB$m5\='Fr =q*MXcϴcA>x?~?¼+s@ý=#l{iS(?ޝjϺs쭸2%vU6v +.^B;"ΡciW+Ӟ2쒒~8Âq{z6qEʍq!?N>km#${h)TI3w:؟G[)]j `چgI1|[EJD"2~'ggUT;p~ +x2Co0'gg'9]辥 $ IIBSFdPVD )[=0 hȡ:1^$%OeBRhHjFD;4f%5Y1Aجktш;8+a`* ]h",NLbc*('X^ K屬-[>_'Y;4/pb%U[Iܳ\FSsп_Ms3t>Ge*Χ^S|+Cboi>d/ȖhsqQ-ʒKk0DuU7&td^k*Y%N "`P["{$c !G!Qg;$5- ^ppڕ=c#"BCq8>taYt;Wǹj ڣC[Ԣ2q2,WQ̯AvO*Z׼rA;?x`Қ‰cY8*޼ctM~"ħ>ՈKKjyU]S2E>OOn9'TzLZ宏Q&ϴc&e[ s}4!`YU$j'C]U:6,Up}QɷaQ]ts9GD؞SdG==pU@XmӺz &XfelvOZV~eLGl lYH]gq` 50iRIx&ޣԨ4wn )2+GeWY)B MɖH(-EՆXYkNӖ߇:;z> B< tܛ+gA ??љS%ȽckqKa/JyZ~iRaD[F\l8"QUe=@iM4c%7⸰LL4$9x%KAh/l^8Tkv\e$PQQ+\iGWSSxXgdI ٣5t aR ]_cX53( .Ƣĕ b`w1ܓ!-Q% N0"~S y' /W|JKGsg= عo <[l+em^9Kr>os7uhf]hi :3G\uTC]KV?yHFvA-lC̱ޕ~z~QPxyL1'Ly#z8Z?K}bn g<?n\NR3>91rnѕ2?=R_/oBrI q'R~FQmɞ[tEsrXƦcbm}ɖN膟*=J$R 3}!]B︊bUdщa{V?Pߒ{)b0Rl&ug U^#3?lcq-K$Lh[ŻΣgޗR^omK #;X= z2}yC#&;Vǚm~lLP+DKy(6S{tW yhA̧Nk<ڑkՎ4~'\-XӣOۑIp|ANӯN;Ir7O{;ԒՃ#OӔNF8ΧѬ¶Dm}~.j與VjG.rqXdęopll_iㆭ.^Wƺ©[c^ *`:nN9)F铎IJ3{Uӭ=}^ƼԄ?<^WNfHskDC߉'6_\\;Ρk騭m ix|Hư9$ID1s9#EvG?PJր4LJ]U06|4G:R^E)~?:|:6hqR1SJ\ V+1TE }SѲUuu,Kz~mطkTݭYJ'*=ұеOuwXuWJ-޾-IIhhJtu,Χ/{_۸>{K]:jI7e2>OC},*6q,FQNNuDNŸe33GnI?@"YUSPy95JKEKzs+b\$jLl"B,-;{FT4k":s@C \;A<!:]2{zGǵ҂n<}?WjvTK0O{_G%r;8oSy  fOdwY,>\++`?Mͷ4I4dEaI]u*3jyS%tF2K?GNJ]E%6F؉mgeM\% }/LO*Tj[ާū0o)IGiK {#ɝ*2~ӔtJcbU]~DjUyym]1:N+rW`bW6$qr T(8,,4G_;L]bydf:-p=Ho 1ϙ5$wE "y@A!kGWUVV(.t%-9yOj8=K+)\@:NH99Evl9*bu<`>(~Q9+.;貳Ud211Cw9sH(Uт0&A'r,uM"9?dafǰ |azO7&F"tcv=/?)rZ_A̪wu>rzo'奄" w/TadQgzi2tOA}+5rjڒgu[*yv4e*wua>wKؠG9|nd|tcҰ{Zda𻞲1> 2yeI8x5N=H>!ź,Ҭ񚨥8_(gb29L쮡RGTRYcŘ~wΗT#0{D0,21QIկo:B8kC&Yt ig?ә;5²#E~!}&z5V[dj QNLVC{u%!l F:t^O2b84FM#?u ʼr -(z}uՏ?X{krVű=0u[k%u8iEi͉gq2F>NL>B* }w_.V%Do3 ~(zoJL .Wʣw3ꞕx܃9A'Ak_TΞ0ڭlFR>a,FNPt+ĩan1&9&$MahCޓE]=[ӿx֕e7c;3Ŝ+<eFMoGԘ}s 5%w> go`>ˊg?_0BnA8bIh<syF@wM'M:fݜF4ZXf`#Vwũ+D^u> P,00r2Rzܞ_M7ҽ>zS/b6O8q: qɯdԡsZj$g9CS]Ry2 Qg{Vt;lkߘgoi$E⠲uLYV"'ea! sξ5d,,tD Tro9@ W6;'4K_jH읟yܖ0.D4X7ӃE~׻>o]HQN`}hwEo;&r?=XӯgDq+Ajμu~h ;sN⎍a"/0`[]nIJg$wXi}ĠnKz{7fۚ ?goOޛZ q2ծbT?,Z@%;.^@V<*x|~U&q=ם?]FWub+:SMV/o%^/H~Md$gŔAXylTP^eè ,uXQW,m7=Gr{n3fJQV̋,:$@ ir=֗lI`hPt;u y D;6DFRgiYci, |:9(y#naK?K8dZ2~ka2"⾔~.OZl V2S[p_,W蘣/[yƆk]ؖ'd4sڊNª߆:i-Kw"{λ!f/m볮pe'&ĜyYAб>[ºa^|?ReRC}6zuo4O1zR!i?ga־Vn1]35Rq:=b3b@!L0q $:{bR ܼ{l\m2YܬU y/M#;O%\a~"~۬滎?%͇-YNiȨ=#ߍϜqfo*ڏ"Z':]J>R!~wތ+ x= EXľ*߷`;O)V^D. :刽l> L5 O/XpU> }nVNs(#_"'ڇ|>S[]hK4uaX_O[c%= ms'|;5TzNs<ܴꞠУCEǁE:J]0+*||xa6)i+bON2358ل雮<n;[^е۱Jen?hT$N=FU`yaX%ɦzmx1m}$8+_MEmyKFsy%Q;HJA,@ lm3[R!Mlu yhYu,J,8;w?zԭWzeQv'ՊկjDuұM8?Ğ\ᖋSgzuf XTAȩ&&ՖYAܴe hW2Ѽt(5 1![X}yh hU&®PA3`Cd7o$ d:{kq{lv&NqNn{g\-A"TDJXޠ׏,r+FMQ5=%`;Nɥ=?E߃ dQU&F|l++n #[x#Yc`a;*Ea&N1K/5q10ɐN{3vgAӬ`t`HJG2~+rԨ_g_~H;CGzEzlO_lgS}yOoR[>2+CL;؋V 9Fn98dЅU`M]E}yDٗK@`LTja> #tW7u45CS3;.fE@3w3i5w "<_cD(Lܛ$ь"wcVDfѐ Mryt2XAsTթMbWKD؋.5e32S]D^cT/2dtzy2Qu5|EMrY1cWMf/ĺE9}3@|05֥)WE>q ,^Tk@hGbwE!Ase#`}Q#2zuL)\ʺJԞEXƞIܿ IR|F1K C@D_u|y/:|­_g[l}'b㛲C0c/?:JbAcP}W(Pyf 3{`2-!)RX$hl [!$ p-xE'} W] > yh/D ˠk(3ч5O΀TNA]o庿X^gDq9dJV!u߶y&9nEgBhțG Y&):?jlFaݍzmd 4AzZ0GG7:`S7CC;dMägez{qqƒIzss1miC;\:gEϼb{9=9c7uZ1>-1kRH1)oXh3իZ{:ߘNw8o@F+ IÄLW9. L76&mN[F +DR 7_uCUcm7'~UH-#s?ϋy̖&Γ'bd$bue/Px2=חf"YVrzWVE,ƪZsV%il 9ޢ6tNQ5ZWJszlC_q93 O"nnz>5MhEшt@y lx;#hh`?3JI>>'.9úZN)S='T?@6Ogul|dF2ީ]IˍxЙѯS5y딑2bG'$XLL2s Xm'rǬz~QJg!I8At8#Δ؝ySL踹 }ccK[۹O|ƈĞfA 2*ڪ>q*뤣ڡW @GoZ"YnG|hT1 {NClC˭ eeؕ`eS(2qT%e~%T4G2M4`ͻ}N*bdP^ϙfvQtxL/- t@\Xfׅe6.ξs'_˺wy'p-?}(F)<}O68hҳ:R~e ҏlD^f褒s=ɝQ؝i-7_s״U. ݠ gj*)oȶ{HZ಺dX"7p,+du&"(@j; ^90 {Xl#HZUb~#TQE9VKkbe~2LZqҼj/j2$ɷi,駳^MLj&4mé؋R49I"Wq[=ۨ S{qXՕf銁S_ D42 ЍBcJ&$:F X_ί%SHFK*[B!RCKɱ!Ț+4pӛ]*}vMd0 `rΓqԯRņwMU|N`9;9'w#٥eG7WlHC"" lNS] R:RV,:g텗e.9F"j>Y"`/PXh?3n`LJ;0k6;Q"T MDY:+b%Y bAӘ:ΥX4+F;&C%]/ip)mK Gxy%g"v? b6cw/>L,ecQ1`u "S1Ї2zeثy-ڦט+nkʇg9/ܠseWR,'|J7= (#pz }Q{FL50ܱ@I@dM@Ijor$Mw{Һ-:Y}d!"RQVSt̴3+w=; b/^M0 'aّc龡VױRX>!/:c(g6hLSfu8J)Ig7ZʟH$KZsXU7k[7DD0V 2AMm1lVR Xan+M7h 5?yh:l>&bR/x_<[3*c7\Auivn&H ATwG)+7[ ^ 8n$Ia<b|O53âlMlQ$p5%d̎V[n6ωn Olbĭ "u_Ӄ@MYWn10N3!jҒEj+}AՄI4bO{3@oi IJ)pjlIWX4=,SuO;R;v}2H{srIGeZWXa%Xo1NLjM]r9L;?`]^ؙLJ%tJ_Enb+Ov$RDfMl ;Q/`}Mܲ>ӏ{H7BWBvD]3XrfRZ2·tۜ3^^93H;9Ώd#:ݒ>N`d2#nQtgT<;,ߐI3?&56Vx3ɝ\"U _Kaߙt!ְ/X)Di gy!,_FG%m12 nSå2g2/_2&Cbp.vx]7XitȬsZnazU5ڣshMŚO.;`G z>I❣T]u݉AVGs,"w1&Uې):?1S_뭾r5#OLKW2#ozM5:b{OOWmW ;,SqJu4tWczrVeY7#&qR} D1sM::VPɪu2!ί[uv<  \ȣ5&K|M=YGv6:۲Tsk6˙d>!Wx8 bեg|N/Z}&c/哒QoGE~ hNs:1 y]2pUg`SKLmd- μ~Ui٧*UǰίI h_sQmv3t Is9r)OrѱIA#g!5$9ɑLrW~\bg@g2sLs7l;1 6Q?QےtGP|[\p طRZ4V vIrI1R6,vGsgr4H}n߼m3 42mv $w"4f#,YI_Y'qjN<@{,jӠ(ԨctasܩS2ƏHɉEZ&P||n5WRILs9~YɌ#ٹ*'MGI:ꘋN~r5I`Qaք-$2LtY.Br]s _vXU,`9OX99"vs3 fJ Rkf'c0*?lb ^#lfFs˒%!G YљG)[3Gyei2[;c"Mm+o{&+A",EdɳQf;;wcZ&Rh X+6$a0Mn%&AK48P)1:"~.m„Lx 7w9k@1+P~iAoGvhE's-k$zSkI)fw{w~LR˹gdq(7ekD͚$ZD 4X_jFY?CK7+k1y1,3ԕ\+G[L䒢> SBO0݃UqfМV [((,%DX;"kUVGãy1U;#i]K[oq73l1ѬSP`Y莍W@*ڰő;2Z ܴrhBQhiϛ8wXxPnUC*A"[5by1WjS"V+'&Za ) &촱I2D K@3p£>A`? hHrbuVeNe.ef7[D[s3)L~Jc]bU3n8ۈ縦u#DI]Uv[@۳~AM^B_JnK̨LKg;W-Gvɖ}+"$BA5mUh %& Л4DƌWaЍvh]ųᾏ:2rp[v;mɟm39bzd1s[ҊQݒޫߡ+,vO3<r`I|G;3@ou&@kpnh,$h6L'" i|^ AɡXbu1lX:.T7?y|Nc4XAsa3 ܃%GSe>X |a@kl+&>gERcK=cbQ!-0x#L8Z8"2d^fs$BY!x\f ,٪k?]`Se:Є^RbFVJ_x!ji.F`2dqI$_3gɒCcL|'\82DDyɒe8e?2duc貧`{L;bPZ̻&ˢYu_9 dȱI|/'XT!ɓ)vR ɒ&M}G#$&ɒY@Z 2Z ɓ# 2d >&L̙ɐ6{4ɑ^| E>Ddɛ# %2dYM}LHY#2LЛ~2Pdɑ2t~iW$̟]d( Tɓ&GPyX-0.14.1/examples/bitmap/jpeg.py0000644000076500000240000000030112516430616017120 0ustar andrestaff00000000000000from pyx import * i = bitmap.jpegimage("jpeg.jpg") c = canvas.canvas() c.insert(bitmap.bitmap(0, 0, i, compressmode=None)) c.writeEPSfile("jpeg") c.writePDFfile("jpeg") c.writeSVGfile("jpeg") PyX-0.14.1/examples/bitmap/jpeg.txt0000644000076500000240000000453012037343037017315 0ustar andrestaff00000000000000Insert JPEG images without and with recompression With the `bitmap.jpegimage` class, PyX allows you to directly insert a JPEG image into a canvas. It extracts the compressed JPEG data and makes the data available to a PyX bitmap without recompression (i.e. without loss of quality). ... ! Note that you need to set `compressmode` to `None` when creating the bitmap instance, since the data provided by the image instance `i` is already compressed. If you forget to do so, PyX will fail and report about this mistake. (The original source of the problem is that PyX tries to compress all images using the gzip method by default and you need to turn off this feature to prevent the data from being double compressed.) Since we have some image data in this example, let us also discuss how to use the [Python Imaging Libary PIL http://www.pythonware.com/products/pil/] to load the data and write it to the file. The straightforward solution would be to replace the creation of the `bitmap.jpegimage` instance by: import Image i = Image.open("jpeg.jpg") While this works perfectly, it will result in a totally uncompressed image. The size of the EPS file will for example become almost 1.1MB. In a next step, you may turn on the default gzip-based compression by omitting the 'compressmode=None' (or by setting `compressmode="Flate"` explicitely). This will reduce the file size down to about 727KB (EPS) which is still much larger than the version in the above example which used the JPEG compression. Note that this does not mean that the gzip based compression method is bad in general - it is just bad compared to the JPEG method for certain kind of image data like photos. Finally, since the image instance is a PIL instance, we can also use `compressmode="DCT"`, which turns on the lossy JPEG compression method. This will restore the file size to similar values as we got previously by using the `bitmap.jpegimage` instance. The file size and quality of the loosy compression can be adjusted by the `dctquality`, `dctoptimize`, and `dctprogression` parameters of the `bitmap` constructor. Nevertheless, it is important to note that you will always get some additional artifacts due to the recompression by the lossy JPEG compression method. It is also important to note that the original version shown in this example (using `bitmap.jpegimage`) does not use the PIL at all. PyX-0.14.1/examples/bitmap/minimal.ipynb0000644000076500000240000000675512615761706020344 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Store bitmap data using PyX" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAADIAAABKCAYAAAD5TgcdAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAC0SURBVGiB7dqxDcMwDAXRz0CDcf+llCIjUEAOxL1ehg8sLFuue282+Pz7Bl45SVJVo7E8mGpN\nL7BmIobQGEJjCI0hNIbQGEKzJuQk82141WwX/uLlbs1EDKExhMYQGkNoDKExhMYQmvKgB8YQGkNo\nDKE5SdLdo4dJd49u4sH6WjMRQ2gMoTGExhAaQ2gMoTGE5vdda/i77Gz1/AL3xvcRHENoDKExhMYQ\nGkNoDKFZE7LmnP0LbzMfiDWM7GAAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "image_bw = bitmap.image(2, 2, \"L\", b\"\\0\\377\\377\\0\")\n", "image_rgb = bitmap.image(3, 2, \"RGB\", b\"\\77\\77\\77\\177\\177\\177\\277\\277\\277\"\n", " b\"\\377\\0\\0\\0\\377\\0\\0\\0\\377\")\n", "bitmap_bw = bitmap.bitmap(0, 1, image_bw, height=0.8)\n", "bitmap_rgb = bitmap.bitmap(0, 0, image_rgb, height=0.8)\n", "\n", "c = canvas.canvas()\n", "c.insert(bitmap_bw)\n", "c.insert(bitmap_rgb)\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While the main purpose of PyX is to create vector graphics, it is also possible\n", "to store bitmap data in the PyX output. In this example, we show how to\n", "create a simple data structure containing the bitmap data and how such data\n", "can then be transformed into an object which can be inserted into a PyX canvas.\n", "\n", "The first step of providing the bitmap data is creating an `image` instance.\n", "You need to specify the size of your data (in pixels) followed by strings\n", "describing the type of the bitmap and the bitmap data itself.\n", "\n", " The bitmap functionality currently uses a fixed color depth of 8 bits per\n", "color. The pixels are listed row by row, one after the other starting at the\n", "upper left corner of the image.\n", "\n", "Once the image data has been prepared, a `bitmap` instance can be created and\n", "inserted into a PyX canvas for later output.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bitmap/minimal.py0000644000076500000240000000071712517447632017643 0ustar andrestaff00000000000000from pyx import * image_bw = bitmap.image(2, 2, "L", b"\0\377\377\0") image_rgb = bitmap.image(3, 2, "RGB", b"\77\77\77\177\177\177\277\277\277" b"\377\0\0\0\377\0\0\0\377") bitmap_bw = bitmap.bitmap(0, 1, image_bw, height=0.8) bitmap_rgb = bitmap.bitmap(0, 0, image_rgb, height=0.8) c = canvas.canvas() c.insert(bitmap_bw) c.insert(bitmap_rgb) c.writeEPSfile("minimal") c.writePDFfile("minimal") c.writeSVGfile("minimal") PyX-0.14.1/examples/bitmap/minimal.txt0000644000076500000240000000154112037340753020017 0ustar andrestaff00000000000000Store bitmap data using PyX While the main purpose of PyX is to create vector graphics, it is also possible to store bitmap data in the PyX output. In this example, we show how to create a simple data structure containing the bitmap data ... and how such data can then be transformed into an object which can be inserted into a PyX canvas. The first step of providing the bitmap data is creating an `image` instance. You need to specify the size of your data (in pixels) followed by strings describing the type of the bitmap and the bitmap data itself. ! The bitmap functionality currently uses a fixed color depth of 8 bits per color. The pixels are listed row by row, one after the other starting at the upper left corner of the image. Once the image data has been prepared, a `bitmap` instance can be created and inserted into a PyX canvas for later output. PyX-0.14.1/examples/bitmap/pil.ipynb0000644000076500000240000000511312615761707017466 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using image instances from the PIL" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGEAAAAiCAYAAABPyrdhAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAB8SURBVGiB7dvBDQMxDMTAdXD9t+yUYT5mGpAEvnXuveOtb9t2ztMST6e/PX337vyebsC2TYQA\nEQJECBAhQIQAEQJECBAhQIQAEQJECBAhQIQAEQJECBAhQIQAEQJECBAhQIQAEQJECBAhQIQAEQJE\nCBAhQIQAEQKOJ5H3/pMiCz/dwhYZAAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "from PIL import Image\n", "\n", "im = Image.new(\"RGB\", (3, 1))\n", "im.putpixel((0, 0), (255, 0, 0))\n", "im.putpixel((1, 0), (0, 255, 0))\n", "im.putpixel((2, 0), (0, 0, 255))\n", "\n", "c = canvas.canvas()\n", "c.insert(bitmap.bitmap(0, 0, im, height=0.8))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use image instances from the [Python Image Library\n", "http://www.pythonware.com/products/pil] to create bitmaps. You then have an\n", "easy access to all the bitmap formats available in PIL, you may also use PIL\n", "features to create/load/modify bitmaps etc. In order to create an image\n", "pixel by pixel, the PIL is not necessary (by the way, it is slow to use\n", "putpixel for that).\n", "\n", " Using PIL image instances you can also pass indexed images\n", "to PyX's `bitmap` class.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/bitmap/pil.py0000644000076500000240000000045712515656657017011 0ustar andrestaff00000000000000from pyx import * from PIL import Image im = Image.new("RGB", (3, 1)) im.putpixel((0, 0), (255, 0, 0)) im.putpixel((1, 0), (0, 255, 0)) im.putpixel((2, 0), (0, 0, 255)) c = canvas.canvas() c.insert(bitmap.bitmap(0, 0, im, height=0.8)) c.writeEPSfile("pil") c.writePDFfile("pil") c.writeSVGfile("pil") PyX-0.14.1/examples/bitmap/pil.txt0000644000076500000240000000077012037340753017160 0ustar andrestaff00000000000000Using image instances from the PIL You can use image instances from the [Python Image Library http://www.pythonware.com/products/pil] to create bitmaps. You then have an easy access to all the bitmap formats available in PIL, you may also use PIL features to create/load/modify bitmaps etc. ... In order to create an image pixel by pixel, the PIL is not necessary (by the way, it is slow to use putpixel for that). !! Using PIL image instances you can also pass indexed images to PyX's `bitmap` class. PyX-0.14.1/examples/bitmap/README0000644000076500000240000000020312037344757016512 0ustar andrestaff00000000000000Bitmaps Although PyX creates scaleable vector graphics, you can embed bitmap data into your output by means of the bitmap module. PyX-0.14.1/examples/drawing/0000755000076500000240000000000012615763300016005 5ustar andrestaff00000000000000PyX-0.14.1/examples/drawing/arrow.ipynb0000644000076500000240000001776712615761354020233 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Adding an arrow when stroking a path" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "c.stroke(path.curve(0, 0, 0, 4, 2, 4, 3, 3),\n", " [style.linewidth.THICK, style.linestyle.dashed, color.rgb.blue,\n", " deco.earrow([deco.stroked([color.rgb.red, style.linejoin.round]),\n", " deco.filled([color.rgb.green])], size=1)])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The example shows how to use an arrow decorator instance to add an arrow to a\n", "path when it is stroked. Instead of using a default arrow instance, we create a\n", "highly customized arrow head. \n", "\n", "Apart from setting arrow specific features like the arrow size, a list of\n", "styles and decorators can be passed to the arrow. In this example, the arrow is\n", "stroked in red with round corners. In addition, the arrow is filled in green.\n", "\n", " Note that style properties are inherited from the outer towards the inner\n", "decorators. In this example, the linewidth is also used when stroking the arrow\n", "head. We could for example also skip the color.rgb.green value in the\n", "`deco.filled` decorator and the arrow would be filled in blue.\n", "\n", " To continue removing the deco.filled features, it is equivalent to write\n", "`deco.filled([])`, `deco.filled()` and `deco.filled`. This is due to the fact that\n", "`deco.filled` already is an instance, which can be *modified by call*. An empty\n", "list does not really modify it. But you could even skip `deco.filled` completely\n", "and the arrow would still be filled with blue color. The reason is that the\n", "arrow is implemented in a way that it always *merges* the `filled` decorator. This\n", "step in the evaluation of the attributes is transparent to other settings: if\n", "we would replace the `deco.filled([color.rgb.green])` by `color.rgb.green`, we\n", "would still get a filled green arrow. You could then remove the `color.rgb.red`\n", "in `deco.stroked` inside of the arrow instance and the line would become green as\n", "well. Note that the order of the attributes is not important for this style\n", "delegation feature.\n", "\n", " Since we have learned that the arrow decorators always fill the arrow head by\n", "default, the question is now whether and how such a feature can be removed. This\n", "is done by *clear* instances available as a `clear` class attribute. Hence in case\n", "of `deco.filled`, it is available as `deco.filled.clear`. When you add this\n", "attribute to the earrow call, the arrowhead will not be filled anymore and you\n", "will notice that the blue line is not stroked inside the arrowhead.\n", "\n", " You might also have noticed, that the dashed linestyle is not used when\n", "stroking the arrowhead. This is similar to the default `filled` feature of the\n", "arrowhead: The arrowhead merges a `style.linestyle.normal` to ensure a solid\n", "line. Instead of manually setting `style.linestyle.dashed` in the arrowhead, you\n", "could use `style.linestyle.clear` to restore the linestyle setting of the path.\n", "\n", " The arrow head is a so-called ornament. Beside attaching stroke and fill\n", "styles during the process of converting a path into a decorated path, any\n", "number of ornaments can be added to the decorated path. When adding ornaments,\n", "parts of the path can also be marked as not-to-be-stroked. While this is taken\n", "into account in a final stroke operation, different decorators do not see this\n", "information such that decorators always commute.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/arrow.py0000644000076500000240000000056312515656657017534 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.stroke(path.curve(0, 0, 0, 4, 2, 4, 3, 3), [style.linewidth.THICK, style.linestyle.dashed, color.rgb.blue, deco.earrow([deco.stroked([color.rgb.red, style.linejoin.round]), deco.filled([color.rgb.green])], size=1)]) c.writeEPSfile("arrow") c.writePDFfile("arrow") c.writeSVGfile("arrow") PyX-0.14.1/examples/drawing/arrow.txt0000644000076500000240000000560612037337703017711 0ustar andrestaff00000000000000Adding an arrow when stroking a path The example shows how to use an arrow decorator instance to add an arrow to a path when it is stroked. Instead of using a default arrow instance, we create a highly customized arrow head. ... Apart from setting arrow specific features like the arrow size, a list of styles and decorators can be passed to the arrow. In this example, the arrow is stroked in red with round corners. In addition, the arrow is filled in green. ! Note that style properties are inherited from the outer towards the inner decorators. In this example, the linewidth is also used when stroking the arrow head. We could for example also skip the color.rgb.green value in the `deco.filled` decorator and the arrow would be filled in blue. ! To continue removing the deco.filled features, it is equivalent to write `deco.filled([])`, `deco.filled()` and `deco.filled`. This is due to the fact that `deco.filled` already is an instance, which can be ''modified by call''. An empty list does not really modify it. But you could even skip `deco.filled` completely and the arrow would still be filled with blue color. The reason is that the arrow is implemented in a way that it always ''merges'' the `filled` decorator. This step in the evaluation of the attributes is transparent to other settings: if we would replace the `deco.filled([color.rgb.green])` by `color.rgb.green`, we would still get a filled green arrow. You could then remove the `color.rgb.red` in `deco.stroked` inside of the arrow instance and the line would become green as well. Note that the order of the attributes is not important for this style delegation feature. ! Since we have learned that the arrow decorators always fill the arrow head by default, the question is now whether and how such a feature can be removed. This is done by ''clear'' instances available as a `clear` class attribute. Hence in case of `deco.filled`, it is available as `deco.filled.clear`. When you add this attribute to the earrow call, the arrowhead will not be filled anymore and you will notice that the blue line is not stroked inside the arrowhead. ! You might also have noticed, that the dashed linestyle is not used when stroking the arrowhead. This is similar to the default `filled` feature of the arrowhead: The arrowhead merges a `style.linestyle.normal` to ensure a solid line. Instead of manually setting `style.linestyle.dashed` in the arrowhead, you could use `style.linestyle.clear` to restore the linestyle setting of the path. !! The arrow head is a so-called ornament. Beside attaching stroke and fill styles during the process of converting a path into a decorated path, any number of ornaments can be added to the decorated path. When adding ornaments, parts of the path can also be marked as not-to-be-stroked. While this is taken into account in a final stroke operation, different decorators do not see this information such that decorators always commute. PyX-0.14.1/examples/drawing/metapost.ipynb0000644000076500000240000003046012615761351020713 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Creating paths with MetaPost-like parameters" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "from pyx.metapost.path import beginknot, endknot, smoothknot, tensioncurve\n", "\n", "p1, p2, p3, p4, p5 = (0, 0), (2, 1.33), (1.3, 3), (0.33, 2.33), (1, 1.67)\n", "openpath = metapost.path.path([\n", " beginknot(*p1), tensioncurve(), smoothknot(*p2), tensioncurve(),\n", " smoothknot(*p3), tensioncurve(), smoothknot(*p4), tensioncurve(),\n", " endknot(*p5)])\n", "closedpath = metapost.path.path([\n", " smoothknot(*p1), tensioncurve(), smoothknot(*p2), tensioncurve(),\n", " smoothknot(*p3), tensioncurve(), smoothknot(*p4), tensioncurve(),\n", " smoothknot(*p5), tensioncurve()])\n", "c = canvas.canvas()\n", "for p in [p1, p2, p3, p4, p5]:\n", " c.fill(path.circle(p[0], p[1], 0.05), [color.rgb.red])\n", " c.fill(path.circle(p[0], p[1], 0.05), [color.rgb.red, trafo.translate(2, 0)])\n", "c.stroke(openpath)\n", "c.stroke(closedpath, [trafo.translate(2, 0)])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some simple paths are created by prescribing five points on the path. The\n", "curves between them are automatically chosen such that the result looks smooth. \n", "\n", "Instead of constructing paths from their path elements, where all control\n", "points must be given explicitly, we here specify only five points which must\n", "lie on the path. The remaining control points are then internally determined by\n", "the constraint that the curve should look smooth.\n", "\n", "In the first curve, the geometrical constraints are the following. The three\n", "interior points have a continuous tangent and a continuous curvature. The two\n", "end points demand a curvature not too different from that at their neighbor\n", "(second/fourth point).\n", "\n", "For the closed curve, all points are of the continuous type.\n", "\n", " The algorithm for calculating the curves comes from MetaPost. In the syntax\n", "of MetaPost, the above example corresponds to the commands\n", "\n", " draw((0,0)..(2,1.33)..(1.3,3)..(0.33,2.33)..(1,1.67));\n", " draw((0,0)..(2,1.33)..(1.3,3)..(0.33,2.33)..(1,1.67)..cycle);\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/metapost.py0000644000076500000240000000161512515656657020235 0ustar andrestaff00000000000000from pyx import * from pyx.metapost.path import beginknot, endknot, smoothknot, tensioncurve p1, p2, p3, p4, p5 = (0, 0), (2, 1.33), (1.3, 3), (0.33, 2.33), (1, 1.67) openpath = metapost.path.path([ beginknot(*p1), tensioncurve(), smoothknot(*p2), tensioncurve(), smoothknot(*p3), tensioncurve(), smoothknot(*p4), tensioncurve(), endknot(*p5)]) closedpath = metapost.path.path([ smoothknot(*p1), tensioncurve(), smoothknot(*p2), tensioncurve(), smoothknot(*p3), tensioncurve(), smoothknot(*p4), tensioncurve(), smoothknot(*p5), tensioncurve()]) c = canvas.canvas() for p in [p1, p2, p3, p4, p5]: c.fill(path.circle(p[0], p[1], 0.05), [color.rgb.red]) c.fill(path.circle(p[0], p[1], 0.05), [color.rgb.red, trafo.translate(2, 0)]) c.stroke(openpath) c.stroke(closedpath, [trafo.translate(2, 0)]) c.writeEPSfile("metapost") c.writePDFfile("metapost") c.writeSVGfile("metapost") PyX-0.14.1/examples/drawing/metapost.txt0000644000076500000240000000205012037344755020406 0ustar andrestaff00000000000000Creating paths with MetaPost-like parameters Some simple paths are created by prescribing five points on the path. The curves between them are automatically chosen such that the result looks smooth. ... Instead of constructing paths from their path elements, where all control points must be given explicitly, we here specify only five points which must lie on the path. The remaining control points are then internally determined by the constraint that the curve should look smooth. In the first curve, the geometrical constraints are the following. The three interior points have a continuous tangent and a continuous curvature. The two end points demand a curvature not too different from that at their neighbor (second/fourth point). For the closed curve, all points are of the continuous type. ! The algorithm for calculating the curves comes from MetaPost. In the syntax of MetaPost, the above example corresponds to the commands draw((0,0)..(2,1.33)..(1.3,3)..(0.33,2.33)..(1,1.67)); draw((0,0)..(2,1.33)..(1.3,3)..(0.33,2.33)..(1,1.67)..cycle); PyX-0.14.1/examples/drawing/path.ipynb0000644000076500000240000001010112615761347020006 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Basic paths" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHkAAABSCAYAAABwkXu8AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAMUSURBVHic7d3RcdpAFIXhczM0QAu4BLsEKIGUgEswJdgloBJCCVBCKMGUEEo4ftDiiASQEFfS\nDvd8M0wSR8ZyfnaxNNLGSEIe2wgAzOx96B2pUZDcD70TXTOzKYADyZ3n847Sr1MAS88ndjQHMAHw\nMJHNbILy33wK4Bnl91f9++Nvd+mxJblu/QXTdL0hiRwfAN4BTIfeD6fvZQHgNwC2ePwBsAIwufXr\n/mj96pDGzGxqZhuUkZ5bPs0Y5Yvk08xWZjZu+omK3CEzG5vZCsAG5dTs5Rh70WTjUf0m0kYaaRu0\nH7l1xgBWZjYhefXnKY3kDpjZM4BPdBe46i3NFhcpsrM0gn+hHGl9WVwLrcj+NvjnkKgni0vv0Yrs\nKJ1U6mOKvmSVTqicUGQn6QTH29D7gTP7oMh+cjk1PDWzefUDiuwgTZHz2g37c/KCU2QfOQUGgEk6\njAOgyF5yiwxU9kmR75RGTJ/HxE0psqMcRzFQmbIV+X5DnPhoagwosoccp+qjCaDIHhQ5gCFPYzai\nyPdzveiuC4p8v8PQO3DFHlBkD4ocQM6XCh8ARfaQ63vy/niRviLfKV30nuOU/X0xviL7aH93Q3e+\nZxhF9pFb5H31thpFdkByC2A79H5UfFT/oMh+Puo36cWOZFH9gCI7SaO5qN2we//dTaHIvpYY9pDq\nI73YTiiyI5IHAD8xzCFVcemeKEV2llZEmKHf0DtcWURAkTuQzjTN0M8pz4LkS5pFzlLkjqTQL+j2\n0GpJ8rVuI0XuEMkDyRmAV/iO6i2AJ5KNDtsUuQckC5JPKI+l74m9BTAjObtlNaTjSgPjc3fDZSLn\na6hukn76XaZLZef4u/rPNWuUcbdtl7kyklrHa2DpxvVqbNe1vIxake/h6T05AEUOQJEDUOQAFDkA\nRQ5AkQNQ5AAUOQBFDkCRA1DkABQ5AEUOQJEDUOQAFDkARQ5AkQNQ5AAUOQBFDkCRA1DkABQ5AEUO\nQJEDUOQAFDkARQ5AkQNQ5AAUOQBFDkCRA1DkABQ5gBGA4xJP2f93dHKzNclCSzwF8AUp8P6jWaaY\nlgAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "c.stroke(path.line(0, 0, 3, 0))\n", "c.stroke(path.rect(0, 1, 1, 1))\n", "c.fill(path.circle(2.5, 1.5, 0.5))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This first path example demonstrates how to create a canvas, how to draw some\n", "simple geometric objects onto it and how to write the result into a PostScript\n", "or PDF file. \n", "\n", "First we import all top-level symbols of the PyX package by the usual Python\n", "import statement. In the further examples we will always use this form of the\n", "import statement to make the PyX package available to our scripts.\n", "\n", "Now we can create a canvas instance `c`, onto which our basic paths are drawn.\n", "The later is done by passing some path instances (a line, a rectangle and a\n", "circle) to the `strokes` or `fill` methods of the canvas instance we just\n", "created and stored in the variable `c`. Finally, we call the `writeEPSfile` and\n", "`writePDFfile` methods of the canvas to create an EPS and a PDF file of our\n", "drawing. While typically you will only create either a PostScript or a PDF\n", "file, in our examples we always create both output formats to have them both\n", "available for download.\n", "\n", "This example, in addition, shows some basics of the PyX coordinate system. The\n", "first coordinate (often referred to as `x`) goes horizontally from left to right\n", "and the second coordinate (`y`) goes vertically from the bottom to the top. The\n", "default unit is `1 cm`. The boundary of the resulting image is calculated\n", "automatically.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/path.py0000644000076500000240000000031712515656657017333 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.stroke(path.line(0, 0, 3, 0)) c.stroke(path.rect(0, 1, 1, 1)) c.fill(path.circle(2.5, 1.5, 0.5)) c.writeEPSfile("path") c.writePDFfile("path") c.writeSVGfile("path") PyX-0.14.1/examples/drawing/path.txt0000644000076500000240000000242612037337703017510 0ustar andrestaff00000000000000Basic paths This first path example demonstrates how to create a canvas, how to draw some simple geometric objects onto it and how to write the result into a PostScript or PDF file. ... First we import all top-level symbols of the PyX package by the usual Python import statement. In the further examples we will always use this form of the import statement to make the PyX package available to our scripts. Now we can create a canvas instance `c`, onto which our basic paths are drawn. The later is done by passing some path instances (a line, a rectangle and a circle) to the `strokes` or `fill` methods of the canvas instance we just created and stored in the variable `c`. Finally, we call the `writeEPSfile` and `writePDFfile` methods of the canvas to create an EPS and a PDF file of our drawing. While typically you will only create either a PostScript or a PDF file, in our examples we always create both output formats to have them both available for download. This example, in addition, shows some basics of the PyX coordinate system. The first coordinate (often referred to as `x`) goes horizontally from left to right and the second coordinate (`y`) goes vertically from the bottom to the top. The default unit is `1 cm`. The boundary of the resulting image is calculated automatically. PyX-0.14.1/examples/drawing/pathitem.ipynb0000644000076500000240000001301012615761350020661 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Constructing paths from pathitems" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMsAAAAuCAYAAACGcu0CAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAGPSURBVHic7d1BbQJRFIXhcwkGsICFsUAl1EIttBKKBSwgASzUAhYq4XZRSCeEoackcN9L/y9h\nwe7kJX94w2YiM3USETu1a5uZm+oRJxExSHqv3nGD8nOMiBdJz5UbbjE/+74qWeH5qB5wZqG2z2tK\nC+e4VIdnN6seAPRiHhG9XCWG0dZD9VUC/89c0mv1CNNKPz/de0nEgofiGgaYzh/wxzaSPh81ZMKg\nDh8EJa2rB+j736Zl9Yg/OkjaVo/QxG3rWizbzNzfaYzl+IzSXSyZ+Va94fjXdnexNHJ2F2PhGgaY\niAUwEQtgIhbARCyAiVgAE7EAJmIBTMQCmIgFMBELYCIWwEQsgIlYABOxACZiAUzEApiIBTARC2Ai\nFsBELICJWAATsQAmYgFMxAKYiAUwEQtgIhbARCyAiVgAE7EApmvvZxki4mFDJiyqB9wiIlp4p0yP\nZ7do5OwuuhZLLy9mbdGuekCnBjV8dlzDABOxAKZZZsbpUz3mF+vR1qfqMZm5H51b+R7cH78sgIlY\nANMXF9BLgZnMHPQAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "rect1 = path.path(path.moveto(0, 0), path.lineto(1, 0),\n", " path.moveto(1, 0), path.lineto(1, 1),\n", " path.moveto(1, 1), path.lineto(0, 1),\n", " path.moveto(0, 1), path.lineto(0, 0))\n", "rect2 = path.path(path.moveto(2, 0), path.lineto(3, 0),\n", " path.lineto(3, 1), path.lineto(2, 1),\n", " path.lineto(2, 0))\n", "rect3 = path.path(path.moveto(4, 0), path.lineto(5, 0),\n", " path.lineto(5, 1), path.lineto(4, 1),\n", " path.closepath())\n", "\n", "c.stroke(rect1, [style.linewidth.THICK])\n", "c.stroke(rect2, [style.linewidth.THICK])\n", "c.stroke(rect3, [style.linewidth.THICK])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, some simple paths are constructed out of pathitems, which are\n", "the basic building blocks of paths. While we only use `moveto`, `lineto` and\n", "`closepath` instances, we can already see some features of paths in PyX. \n", "\n", "In the first path instance `rect1`, we alternatingly use `moveto` and `lineto`\n", "pathitem instances. A `moveto` instance sets an internal *current point*,\n", "while a `lineto` instance additionally creates a straight line connecting the\n", "old and the new *current point*. Due to the intermediate `moveto`\n", "instances, we generate a path which contains 4 separate subpaths. When\n", "stroking this path with a thick linewidth in order to show the details, the\n", "corners of the result exhibits that the individual lines are not connected.\n", "\n", "In the second case `rect2`, we skip the intermediate `moveto` instances. The\n", "default join method between pathitems within a single subpath is to miter them.\n", "This results in a different rendering except for the start and end point of the\n", "path.\n", "\n", "In order to get rid of the ragged effect at the corners, we close the path as\n", "shown by `rect3`. Here, one can (and should) skip the last connecting line since\n", "a `closepath` pathitem implicitly adds a straight connection line between the\n", "first and the last point of the subpath.\n", "\n", " PyX resembles the full PostScript path model. The whole PostScript path\n", "construction functionality is available by means of pathitems and the resulting\n", "PostScript code will make use of the corresponding PostScript operators. For\n", "PDF output, where some of the PostScript features are not available (all forms\n", "of arcs are missing in PDF), proper replacement code is generated automatically.\n", "\n", " You might ask why you should skip the last straight connection line of\n", "finite length when closing a path. This is not a question of reducing the file\n", "size but increasing the rendering stability of the drawing. The problem is that\n", "in case of rounding errors a very short connection line might mistakenly be\n", "inserted when rendering a `closepath`. Depending on the linejoin setting, this\n", "can create a major visual defect.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/pathitem.py0000644000076500000240000000137712515656657020221 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() rect1 = path.path(path.moveto(0, 0), path.lineto(1, 0), path.moveto(1, 0), path.lineto(1, 1), path.moveto(1, 1), path.lineto(0, 1), path.moveto(0, 1), path.lineto(0, 0)) rect2 = path.path(path.moveto(2, 0), path.lineto(3, 0), path.lineto(3, 1), path.lineto(2, 1), path.lineto(2, 0)) rect3 = path.path(path.moveto(4, 0), path.lineto(5, 0), path.lineto(5, 1), path.lineto(4, 1), path.closepath()) c.stroke(rect1, [style.linewidth.THICK]) c.stroke(rect2, [style.linewidth.THICK]) c.stroke(rect3, [style.linewidth.THICK]) c.writeEPSfile("pathitem") c.writePDFfile("pathitem") c.writeSVGfile("pathitem") PyX-0.14.1/examples/drawing/pathitem.txt0000644000076500000240000000412312037337703020363 0ustar andrestaff00000000000000Constructing paths from pathitems In this example, some simple paths are constructed out of pathitems, which are the basic building blocks of paths. While we only use `moveto`, `lineto` and `closepath` instances, we can already see some features of paths in PyX. ... In the first path instance `rect1`, we alternatingly use `moveto` and `lineto` pathitem instances. A `moveto` instance sets an internal ''current point'', while a `lineto` instance additionally creates a straight line connecting the old and the new ''current point''. Due to the intermediate `moveto` instances, we generate a path which contains 4 separate subpaths. When stroking this path with a thick linewidth in order to show the details, the corners of the result exhibits that the individual lines are not connected. In the second case `rect2`, we skip the intermediate `moveto` instances. The default join method between pathitems within a single subpath is to miter them. This results in a different rendering except for the start and end point of the path. In order to get rid of the ragged effect at the corners, we close the path as shown by `rect3`. Here, one can (and should) skip the last connecting line since a `closepath` pathitem implicitly adds a straight connection line between the first and the last point of the subpath. ! PyX resembles the full PostScript path model. The whole PostScript path construction functionality is available by means of pathitems and the resulting PostScript code will make use of the corresponding PostScript operators. For PDF output, where some of the PostScript features are not available (all forms of arcs are missing in PDF), proper replacement code is generated automatically. !! You might ask why you should skip the last straight connection line of finite length when closing a path. This is not a question of reducing the file size but increasing the rendering stability of the drawing. The problem is that in case of rounding errors a very short connection line might mistakenly be inserted when rendering a `closepath`. Depending on the linejoin setting, this can create a major visual defect. PyX-0.14.1/examples/drawing/README0000644000076500000240000000027112037344755016674 0ustar andrestaff00000000000000Basic drawing In this first section we demonstrate basic drawing features of PyX. The goal is to present some of the basic concepts of the PyX package like canvases, paths and styles. PyX-0.14.1/examples/drawing/strokefill.ipynb0000644000076500000240000001032612615761353021236 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Stroke and fill paths at the same time" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAACoAAAAqCAYAAADFw8lbAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAACHSURBVFiF7c5BDcJAAETRWVIDtYCFasAKFqiEegILWKiV5UDKpYe9/GSX5P9kkjm+UpNrknvG\n7jXlC330lrS6HOf2TEodbyfo6AmlE0onlE4onVA6oXRC6YTSCaUTSieUTiidUDqhdELphNIJpfsb\n6HSc5d2T0e4H3daejHalJnOSpTek0f4Bh14tVvHGaYQAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "c.stroke(path.rect(0, 0, 1, 1), [style.linewidth.Thick,\n", " color.rgb.red,\n", " deco.filled([color.rgb.green])])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to stroke and fill a path, you could call the `fill` and `stroke`\n", "methods of a canvas instance one after the other. However, such a solution is\n", "not optimal since the path would be written into the output file twice.\n", "Instead, you can use the `filled` decorator within a `stroke` method call as an\n", "additional attribute. \n", "\n", "In the example code, the filled decorator is called to pass additional\n", "styles, which will then only be used for the fill operation. Other styles\n", "passed in the second argument of the `stroke` method are used for both, the\n", "stroke and the fill operation. Here we set a linewidth, which only affects the\n", "stroke operation.\n", "\n", "A complementary functionality exists as well: you can use a `deco.stroked`\n", "instance to add a stroke operation within a `fill` method call.\n", "\n", " The `filled` and `stroked` are pre-defined instances, but they accept a\n", "*modify by call* operation. This is a common feature of decorators and other\n", "attributes.\n", "\n", " Internally, the `stroke` and the `fill` methods are implemented by adding either\n", "`deco.stroked` or `deco.filled` to the list passed as the second parameter to the\n", "`stroke` or `fill` method of a canvas. This whole construction is then evaluated by\n", "the `draw` method of the canvas instance. The draw method is really the basic\n", "operation to output a path. It transforms a path into a so-called decorated\n", "path. The mere path itself is a pure mathematical object without any information\n", "about how it should be drawn and which styles should be applied.\n", "Output-specific properties like dashing or the linewidth are not attached to\n", "the path at all. In contrast, the decorated path attaches styles and the two output\n", "operations stroke and fill to the mathematical path object. A symmetric stroke\n", "and fill operation therefore looks like\n", "\n", " c.draw(p, l1 + [deco.stroked(l2), deco.filled(l3)])\n", "\n", "where `c` is the canvas instance, `p` is the path to be stroked and filled, `l1` is\n", "a list of styles used for both stroking and filling, `l2` are additional styles\n", "used for stroking, and `l3` are additional styles used for filling.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/strokefill.py0000644000076500000240000000045012515656657020553 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.stroke(path.rect(0, 0, 1, 1), [style.linewidth.Thick, color.rgb.red, deco.filled([color.rgb.green])]) c.writeEPSfile("strokefill") c.writePDFfile("strokefill") c.writeSVGfile("strokefill") PyX-0.14.1/examples/drawing/strokefill.txt0000644000076500000240000000410512037337703020726 0ustar andrestaff00000000000000Stroke and fill paths at the same time In order to stroke and fill a path, you could call the `fill` and `stroke` methods of a canvas instance one after the other. However, such a solution is not optimal since the path would be written into the output file twice. Instead, you can use the `filled` decorator within a `stroke` method call as an additional attribute. ... In the example code, the filled decorator is called to pass additional styles, which will then only be used for the fill operation. Other styles passed in the second argument of the `stroke` method are used for both, the stroke and the fill operation. Here we set a linewidth, which only affects the stroke operation. A complementary functionality exists as well: you can use a `deco.stroked` instance to add a stroke operation within a `fill` method call. ! The `filled` and `stroked` are pre-defined instances, but they accept a ''modify by call'' operation. This is a common feature of decorators and other attributes. !! Internally, the `stroke` and the `fill` methods are implemented by adding either `deco.stroked` or `deco.filled` to the list passed as the second parameter to the `stroke` or `fill` method of a canvas. This whole construction is then evaluated by the `draw` method of the canvas instance. The draw method is really the basic operation to output a path. It transforms a path into a so-called decorated path. The mere path itself is a pure mathematical object without any information about how it should be drawn and which styles should be applied. Output-specific properties like dashing or the linewidth are not attached to the path at all. In contrast, the decorated path attaches styles and the two output operations stroke and fill to the mathematical path object. A symmetric stroke and fill operation therefore looks like c.draw(p, l1 + [deco.stroked(l2), deco.filled(l3)]) where `c` is the canvas instance, `p` is the path to be stroked and filled, `l1` is a list of styles used for both stroking and filling, `l2` are additional styles used for stroking, and `l3` are additional styles used for filling. PyX-0.14.1/examples/drawing/style.ipynb0000644000076500000240000001072512615761352020222 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Stroke and fill attributes" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKUAAAB7CAYAAAAVH0CFAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAJ6SURBVHic7d3LTRxBGIXRWxYJkAIpOIWJBafgEOwQPCkQAoQAKUwKE8LvBX7wkrzwNHMtnyP1\nokGqKZU+qVW96Fozk1/WukpynW3sM3M4+ahrXSe5Ovm4ySEz+5OPuuUaz3zeZNzt1vguM3ev/joz\nv69kN8lsdO2e/dapruR2o/nebjTf7dZ4i/luu8Zf3vq9DxvUD39FlNQRJXVESZ2LF/fHJK93Q6dx\n3Gjch39s3C3XeCtbrcWbb2PWs1dCUMDjmzqipI4oqSNK6oiSOqKkjiipI0rqiJI6oqSOKKkjSuqI\nkjqipI4oqSNK6oiSOqKkjiipI0rqiJI6oqSOKKkjSuqIkjqipI4oqSNK6oiSOqKkzrPvU66syyQf\nzzQX/l+Hye+TQy6SZGXtknzLNsdSwB+trGOS/WQ+r0x2SW7PPSn44evK5D4e2RRZmfi+NFXsvqnz\nIcnNuScBTxxXJldJ7pNcnns2kOTTmpmf7ye/5HHDY9PDezvk8aye/WTunKNDHRsd6oiSOqKkjiip\nI0rqiJI6oqSOKKkjSuqIkjqipI4oqSNK6oiSOqKkjiipI0rqiJI6oqSOKKkjSuqIkjqipI4oqSNK\n6oiSOqKkjiipI0rqiJI6oqSOKKkjSuqIkjrPz2Zc+ZjHb5/De7qZyf7nzcWLf14m2b3vfCAPT288\nvqkjSuqIkjqipI4oqSNK6oiSOqKkjiipI0rqiJI6oqSOKKkjSuqIkjqipI4oqSNK6oiSOqKkjiip\nI0rqiJI6oqSOKKkjSuqIkjqipI4oqSNK6oiSOqKkjiipI0rqiJI6oqSOKKnz8nSIY5K7c0yE/9rh\n6c2amXNNBN70HRdp1KuC0k96AAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "c.stroke(path.line(0, 0, 4, 0),\n", " [style.linewidth.THICK, style.linestyle.dashed, color.rgb.red])\n", "c.stroke(path.line(0, -1, 4, -1),\n", " [style.linewidth(0.2), style.linecap.round, color.rgb.green])\n", "c.fill(path.rect(0, -3, 4, 1), [color.rgb.blue])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The previous example anticipated a simple case of setting an attribute when\n", "stroking paths. This example shows a few more use-cases.\n", "\n", "Attributes can be passed in a list as the second optional argument of the\n", "`stroke` or `fill` methods of a canvas instance. The attributes themselves are\n", "instances of certain attribute classes. A full list is available in the manual.\n", "\n", "In general, some useful attribute instances are predefined as class attributes\n", "of the corresponding attribute class. In the given example, the\n", "`style.linewidth.THICK`, `style.linestyle.dashed`, `style.linecap.round`,\n", "`color.rgb.red`, `color.rgb.green`, and `color.rgb.blue` are just some examples of\n", "this type of attribute instances. In contrast, `style.linewidth(0.2)` creates a\n", "new style instance for the given parameters.\n", "\n", " The linewidth instance created by `style.linewidth(0.2)` is different from the\n", "predefined linewidth instances in PyX in its use of *user* units. In the example\n", "*Adding and joining paths* of section *Path features*, the linewidth is\n", "scaled independently of the *user* units, but if you try to double all linewidth\n", "by\n", "\n", " unit.set(wscale=2)\n", "\n", "in the beginning of the script, our self-defined linewidth will not be scaled.\n", "To obtain the proper scaling behaviour it would be necessary to attach the\n", "*width* unit by using\n", "\n", " style.linewidth(0.2*unit.w_cm)\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing/style.py0000644000076500000240000000056212515656657017541 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.stroke(path.line(0, 0, 4, 0), [style.linewidth.THICK, style.linestyle.dashed, color.rgb.red]) c.stroke(path.line(0, -1, 4, -1), [style.linewidth(0.2), style.linecap.round, color.rgb.green]) c.fill(path.rect(0, -3, 4, 1), [color.rgb.blue]) c.writeEPSfile("style") c.writePDFfile("style") c.writeSVGfile("style") PyX-0.14.1/examples/drawing/style.txt0000644000076500000240000000256012037337703017713 0ustar andrestaff00000000000000Stroke and fill attributes The previous example anticipated a simple case of setting an attribute when stroking paths. This example shows a few more use-cases. Attributes can be passed in a list as the second optional argument of the `stroke` or `fill` methods of a canvas instance. ... The attributes themselves are instances of certain attribute classes. A full list is available in the manual. In general, some useful attribute instances are predefined as class attributes of the corresponding attribute class. In the given example, the `style.linewidth.THICK`, `style.linestyle.dashed`, `style.linecap.round`, `color.rgb.red`, `color.rgb.green`, and `color.rgb.blue` are just some examples of this type of attribute instances. In contrast, `style.linewidth(0.2)` creates a new style instance for the given parameters. !! The linewidth instance created by `style.linewidth(0.2)` is different from the predefined linewidth instances in PyX in its use of ''user'' units. In the example ''Adding and joining paths'' of section ''Path features'', the linewidth is scaled independently of the ''user'' units, but if you try to double all linewidth by unit.set(wscale=2) in the beginning of the script, our self-defined linewidth will not be scaled. To obtain the proper scaling behaviour it would be necessary to attach the ''width'' unit by using style.linewidth(0.2*unit.w_cm) PyX-0.14.1/examples/drawing2/0000755000076500000240000000000012615763300016067 5ustar andrestaff00000000000000PyX-0.14.1/examples/drawing2/clipping.ipynb0000644000076500000240000001703412615761366020756 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Clipping a canvas" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "clippath = path.circle(0, 0, 1)\n", "drawpath = path.line(-2, -2, 1.2, 2)\n", "\n", "cl = canvas.canvas([canvas.clip(clippath)])\n", "cl.stroke(drawpath, [color.rgb.red, style.linewidth(1.0)])\n", "\n", "c = canvas.canvas()\n", "c.stroke(drawpath, [style.linewidth(1.0)])\n", "c.insert(cl)\n", "c.stroke(clippath)\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows how drawing on a canvas can be clipped to a predefined\n", "region. The thick line is drawn two times, first in black onto an ordinary\n", "canvas, the second time in red onto a canvas which is clipped to the indicated\n", "circle. \n", "\n", "The clipping property of a canvas must be specified on creation with an\n", "instance of `canvas.clip`, which takes a path as an argument. Note that this\n", "way of clipping will probably be removed in future releases of PyX. Instead, it\n", "will become part of the [box concept ../../roadmap.html].\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing2/clipping.py0000644000076500000240000000056212515656657020270 0ustar andrestaff00000000000000from pyx import * clippath = path.circle(0, 0, 1) drawpath = path.line(-2, -2, 1.2, 2) cl = canvas.canvas([canvas.clip(clippath)]) cl.stroke(drawpath, [color.rgb.red, style.linewidth(1.0)]) c = canvas.canvas() c.stroke(drawpath, [style.linewidth(1.0)]) c.insert(cl) c.stroke(clippath) c.writeEPSfile("clipping") c.writePDFfile("clipping") c.writeSVGfile("clipping") PyX-0.14.1/examples/drawing2/clipping.txt0000644000076500000240000000104312037344757020444 0ustar andrestaff00000000000000Clipping a canvas This example shows how drawing on a canvas can be clipped to a predefined region. The thick line is drawn two times, first in black onto an ordinary canvas, the second time in red onto a canvas which is clipped to the indicated circle. ... The clipping property of a canvas must be specified on creation with an instance of `canvas.clip`, which takes a path as an argument. Note that this way of clipping will probably be removed in future releases of PyX. Instead, it will become part of the [box concept ../../roadmap.html]. PyX-0.14.1/examples/drawing2/ellipse.ipynb0000644000076500000240000003332412615761362020602 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Applying transformations on a path or canvas: Drawing an ellipse" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "circ = path.circle(0, 0, 1)\n", "\n", "# variant 1: use trafo as a deformer\n", "c.stroke(circ, [style.linewidth.THIck, \n", " trafo.scale(sx=2, sy=0.9), trafo.rotate(45), trafo.translate(1, 0)])\n", "\n", "# variant 2: transform a subcanvas\n", "sc = canvas.canvas()\n", "sc.stroke(circ, [style.linewidth.THIck])\n", "c.insert(sc, [trafo.scale(sx=2, sy=0.9), trafo.rotate(45), trafo.translate(5, 0)])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "PyX does not directly provide a path corresponding to an ellipse. This example\n", "shows two ways how to draw an ellipse using affine transformations. \n", "\n", "In order to create an ellipse, we best start from a unit circle centered around\n", "the point of origin of the coordinate system (here: `circ`). In variant 1, we\n", "tell PyX to apply a couple of affine transformations before stroking this\n", "circle on the canvas `c`. These affine transformations are contained in the\n", "`trafo` module. We first use `trafo.scale` to apply a non-uniform scaling,\n", "namely by a factor of 2 in x-direction and a factor of 0.9 in y-direction.\n", "Doing so, we define the two principle axes of the ellipse. In a next step, we\n", "rotate with `trafo.rotate` the ellipse by an angle of 45 degrees in the\n", "mathematical positive direction, i.e. counter-clockwise. Last, we shift the\n", "origin of the ellipse to the desired point by applying a `trafo.translate`\n", "operation.\n", "\n", " Note that the order of the transformations matters. If you, for instance, would\n", "first translate the ellipse, the later scaling would also affect the distance\n", "by which you have shifted the ellipse. PyX applies the transformations one after\n", "the other, from left to right, so the example shown above does the correct thing.\n", "\n", " You can also treat transformations as mathematical objects (they are\n", "represented by two-dimensional matrices together with an offset vector) and\n", "multiply them using the `*` operator. Note, however, that mathematically,\n", "transformations are applied from right to left, such that variant 1\n", "would need to be written as\n", "\n", " c.stroke(circ, [trafo.translate(1,0) * trafo.rotate(45) * trafo.scale(sx=2, sy=1.5)])\n", "\n", " PyX also provides some convenience methods for applying certain\n", "transformations with a given point as the origin. These allow one to write variant 1\n", "in yet another form\n", "\n", " c.stroke(circ, [trafo.scale(sx=2, sy=1.5, x=1, y=0), trafo.rotate(45, x=1, y=0)])\n", "\n", "where we have started already from a circle centered around the desired point 1,0.\n", "\n", "When telling the stroke method to apply a number of transformations, we use\n", "that a transformation is a so-called deformer. Deformers take an original path,\n", "do some operation on it and return the modified version. PyX thus internally\n", "converts the circle into a path representing the ellipse. Alternatively, we can\n", "also let the PostScript or PDF interpreter do the same transformation. This is what\n", "is shown in variant 2. There, we first stroke the circle on a new canvas `sc`.\n", "When inserting this canvas in the original canvas `c`, we again pass a set of\n", "transformations as arguments. Since PyX cannot deform an entire canvas, it just\n", "writes these transformations into the output file. If you compare the resulting\n", "output (the right ellipse) with the one of variant 1, you will notice a\n", "difference, though: when transforming a whole canvas, the lineshape is\n", "transformed as well. Often, this is not the intended result, so you better\n", "transform individual objects when stroking or filling them.\n", "\n", " When you look at the EPS or PDF output generated by the example, you will\n", "notice that the bounding box is too large. The reason for this artefact lies in\n", "the way PyX calculates the bounding box for a transformed canvas: It simply\n", "applies the transformation to the bounding box of the canvas and takes the\n", "bounding box of this new object. While this certainly yields a bounding box of\n", "the canvas, it does not necessarily yield a minimal one. To see this, you just\n", "have to consider the two extreme cases of a circle, which is rotationally\n", "invariant, and a square, which only posseses a discrete rotational symmetry.\n", "Whereas the minimal bounding box of the circle does not change under rotations\n", "around its center, the same is not true for the square. When you rotate a\n", "circle by applying a deformer (as in variant 1), PyX will thus calculate the\n", "correct bounding box. On the other hand, when you insert the circle into a\n", "canvas and afterwards transform this canvas (as in variant 2), PyX cannot\n", "distinguish between a circle and a square anymore and calculates a too large\n", "bounding box.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing2/ellipse.py0000644000076500000240000000075212515656657020121 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() circ = path.circle(0, 0, 1) # variant 1: use trafo as a deformer c.stroke(circ, [style.linewidth.THIck, trafo.scale(sx=2, sy=0.9), trafo.rotate(45), trafo.translate(1, 0)]) # variant 2: transform a subcanvas sc = canvas.canvas() sc.stroke(circ, [style.linewidth.THIck]) c.insert(sc, [trafo.scale(sx=2, sy=0.9), trafo.rotate(45), trafo.translate(5, 0)]) c.writeEPSfile("ellipse") c.writePDFfile("ellipse") c.writeSVGfile("ellipse") PyX-0.14.1/examples/drawing2/ellipse.txt0000644000076500000240000001006112037344757020274 0ustar andrestaff00000000000000Applying transformations on a path or canvas: Drawing an ellipse PyX does not directly provide a path corresponding to an ellipse. This example shows two ways how to draw an ellipse using affine transformations. ... In order to create an ellipse, we best start from a unit circle centered around the point of origin of the coordinate system (here: `circ`). In variant 1, we tell PyX to apply a couple of affine transformations before stroking this circle on the canvas `c`. These affine transformations are contained in the `trafo` module. We first use `trafo.scale` to apply a non-uniform scaling, namely by a factor of 2 in x-direction and a factor of 0.9 in y-direction. Doing so, we define the two principle axes of the ellipse. In a next step, we rotate with `trafo.rotate` the ellipse by an angle of 45 degrees in the mathematical positive direction, i.e. counter-clockwise. Last, we shift the origin of the ellipse to the desired point by applying a `trafo.translate` operation. ! Note that the order of the transformations matters. If you, for instance, would first translate the ellipse, the later scaling would also affect the distance by which you have shifted the ellipse. PyX applies the transformations one after the other, from left to right, so the example shown above does the correct thing. ! You can also treat transformations as mathematical objects (they are represented by two-dimensional matrices together with an offset vector) and multiply them using the `*` operator. Note, however, that mathematically, transformations are applied from right to left, such that variant 1 would need to be written as c.stroke(circ, [trafo.translate(1,0) * trafo.rotate(45) * trafo.scale(sx=2, sy=1.5)]) ! PyX also provides some convenience methods for applying certain transformations with a given point as the origin. These allow one to write variant 1 in yet another form c.stroke(circ, [trafo.scale(sx=2, sy=1.5, x=1, y=0), trafo.rotate(45, x=1, y=0)]) where we have started already from a circle centered around the desired point 1,0. When telling the stroke method to apply a number of transformations, we use that a transformation is a so-called deformer. Deformers take an original path, do some operation on it and return the modified version. PyX thus internally converts the circle into a path representing the ellipse. Alternatively, we can also let the PostScript or PDF interpreter do the same transformation. This is what is shown in variant 2. There, we first stroke the circle on a new canvas `sc`. When inserting this canvas in the original canvas `c`, we again pass a set of transformations as arguments. Since PyX cannot deform an entire canvas, it just writes these transformations into the output file. If you compare the resulting output (the right ellipse) with the one of variant 1, you will notice a difference, though: when transforming a whole canvas, the lineshape is transformed as well. Often, this is not the intended result, so you better transform individual objects when stroking or filling them. !! When you look at the EPS or PDF output generated by the example, you will notice that the bounding box is too large. The reason for this artefact lies in the way PyX calculates the bounding box for a transformed canvas: It simply applies the transformation to the bounding box of the canvas and takes the bounding box of this new object. While this certainly yields a bounding box of the canvas, it does not necessarily yield a minimal one. To see this, you just have to consider the two extreme cases of a circle, which is rotationally invariant, and a square, which only posseses a discrete rotational symmetry. Whereas the minimal bounding box of the circle does not change under rotations around its center, the same is not true for the square. When you rotate a circle by applying a deformer (as in variant 1), PyX will thus calculate the correct bounding box. On the other hand, when you insert the circle into a canvas and afterwards transform this canvas (as in variant 2), PyX cannot distinguish between a circle and a square anymore and calculates a too large bounding box. PyX-0.14.1/examples/drawing2/insert.ipynb0000644000076500000240000004115212615761363020450 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Inserting transformed canvases into canvases" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from math import sin, cos, radians\n", "from pyx import *\n", "\n", "angle = 10\n", "factor = 1.0 / (cos(radians(angle)) + sin(radians(angle)))\n", "\n", "cc = canvas.canvas()\n", "cc.stroke(path.rect(-2, -2, 4, 4))\n", "\n", "c = canvas.canvas()\n", "for i in range(10):\n", " c.insert(cc, [trafo.rotate(i*angle), trafo.scale(factor**i)])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similar to the drawing of paths onto canvases, it is also possible to insert\n", "one canvas into another. You may specify additional transformations which are\n", "applied to the canvas which is inserted. \n", "\n", "The example code shows how a canvas `cc` containing a square can be inserted\n", "several times into another canvas `c`. The applied transformation first rotates\n", "the square around the origin and then performs a scaling. Note that not only\n", "the size of the square gets scaled, but everything that is drawn on the canvas,\n", "also the linewidth of the square.\n", "\n", "In geometrical operations, it is often necessary to perform calculations. This\n", "is conveniently done by importing the mathematics capability of Python. In the\n", "example, we calculate the scaling factor from the rotation angle such that the\n", "corners of the rotated smaller square reside on the sides of the larger square.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing2/insert.py0000644000076500000240000000055312515656657017767 0ustar andrestaff00000000000000from math import sin, cos, radians from pyx import * angle = 10 factor = 1.0 / (cos(radians(angle)) + sin(radians(angle))) cc = canvas.canvas() cc.stroke(path.rect(-2, -2, 4, 4)) c = canvas.canvas() for i in range(10): c.insert(cc, [trafo.rotate(i*angle), trafo.scale(factor**i)]) c.writeEPSfile("insert") c.writePDFfile("insert") c.writeSVGfile("insert") PyX-0.14.1/examples/drawing2/insert.txt0000644000076500000240000000162112037344757020145 0ustar andrestaff00000000000000Inserting transformed canvases into canvases Similar to the drawing of paths onto canvases, it is also possible to insert one canvas into another. You may specify additional transformations which are applied to the canvas which is inserted. ... The example code shows how a canvas `cc` containing a square can be inserted several times into another canvas `c`. The applied transformation first rotates the square around the origin and then performs a scaling. Note that not only the size of the square gets scaled, but everything that is drawn on the canvas, also the linewidth of the square. In geometrical operations, it is often necessary to perform calculations. This is conveniently done by importing the mathematics capability of Python. In the example, we calculate the scaling factor from the rotation angle such that the corners of the rotated smaller square reside on the sides of the larger square. PyX-0.14.1/examples/drawing2/parallel.ipynb0000644000076500000240000001442312615761365020743 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Paths with constant distance" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "p = path.line(0, 0, 2, 2)\n", "p.append(path.curveto(2, 0, 3, 0, 4, 0))\n", "c.stroke(p)\n", "c.stroke(p, [deformer.parallel(0.2), color.rgb.blue])\n", "c.stroke(p, [deformer.parallel(-0.2), color.rgb.red])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows how to use the `deformer.parallel` class. It provides the\n", "path which has always constant (signed) distance to an original path. \n", "\n", "The correct geometrical solution to the \"constant distance\" problem is that a\n", "corner of the original curve gets surrounded by an arc. As an alternative, you\n", "can make the deformer deviate from the strict geometrical interpretation with\n", "the argument `sharpoutercorners=1`. The resulting parallel path will then\n", "exhibit corners with the same angle as the original path does.\n", "\n", " The parallel deformer tries to find the parallel path which consists of as\n", "few path elements as possible. This is a striking feature of the parallel\n", "deformer, resulting in small EPS and PDF files, as well as in paths which can\n", "be processed further in PyX. In the example, the parallel curves for the curved\n", "right part of the original path consists of a single Bézier curve only.\n", "\n", " Note that the order of the deformer attributes is not arbitrary, since the\n", "deforming operations do not commute. If you want first to smooth and then get\n", "the parallel curve to the smoothed curve, you have to say\n", "\n", " [deformer.smoothed(radius), deformer.parallel(dist)]\n", "\n", "since the stroke attributes are evaluated from left to right.\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing2/parallel.py0000644000076500000240000000046312515656657020257 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() p = path.line(0, 0, 2, 2) p.append(path.curveto(2, 0, 3, 0, 4, 0)) c.stroke(p) c.stroke(p, [deformer.parallel(0.2), color.rgb.blue]) c.stroke(p, [deformer.parallel(-0.2), color.rgb.red]) c.writeEPSfile("parallel") c.writePDFfile("parallel") c.writeSVGfile("parallel") PyX-0.14.1/examples/drawing2/parallel.txt0000644000076500000240000000237212171044076020427 0ustar andrestaff00000000000000Paths with constant distance This example shows how to use the `deformer.parallel` class. It provides the path which has always constant (signed) distance to an original path. ... The correct geometrical solution to the "constant distance" problem is that a corner of the original curve gets surrounded by an arc. As an alternative, you can make the deformer deviate from the strict geometrical interpretation with the argument `sharpoutercorners=1`. The resulting parallel path will then exhibit corners with the same angle as the original path does. !! The parallel deformer tries to find the parallel path which consists of as few path elements as possible. This is a striking feature of the parallel deformer, resulting in small EPS and PDF files, as well as in paths which can be processed further in PyX. In the example, the parallel curves for the curved right part of the original path consists of a single Bézier curve only. ! Note that the order of the deformer attributes is not arbitrary, since the deforming operations do not commute. If you want first to smooth and then get the parallel curve to the smoothed curve, you have to say [deformer.smoothed(radius), deformer.parallel(dist)] since the stroke attributes are evaluated from left to right. PyX-0.14.1/examples/drawing2/README0000644000076500000240000000047212037344757016763 0ustar andrestaff00000000000000More drawing In this section we demonstrate more drawing features of PyX. The goal is to present the various attributes that can be used for stroking and filling paths in a canvas. Or, they are useful when one canvas is inserted into another one. In many cases, there are several ways to achieve the same result. PyX-0.14.1/examples/drawing2/smoothed.ipynb0000644000076500000240000001361012615761364020765 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Smoothing paths" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "p = path.line(0, 0, 2, 2)\n", "p.append(path.curveto(2, 0, 3, 0, 4, 0))\n", "c.stroke(p)\n", "c.stroke(p, [deformer.smoothed(1.0), color.rgb.blue])\n", "c.stroke(p, [deformer.smoothed(2.0), color.rgb.red])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows how to use the `deformer` class. A deformer takes an\n", "original path and return a modified one, which is here a smoothed variant. The\n", "deformer can be used like any other attribute when stroking or filling a path.\n", "\n", "Here, we show the use of `deformer.smoothed`, which smoothes away corners in\n", "the original path. It operates on the `pathitem`s of the original path and\n", "cuts out pieces of a given length (`1.0` in the example) surrounding a corner\n", "and replaces them by a smooth curve. This new curve is determined to be\n", "*geometrically smooth*, exhibiting the same tangents and curvatures as the\n", "original path at the connection points. Alltogether, the smoothing is performed\n", "not in a strictly *geometrical* sense but also depends on the\n", "parameterization of the path. If you try to smooth a path consisting of many\n", "short path elements, nothing will really change.\n", "\n", " In all deformers, the deformed path can be accessed directly by\n", "\n", " ps = deformer.smoothed(1.0).deform(p)\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/drawing2/smoothed.py0000644000076500000240000000046212515656657020304 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() p = path.line(0, 0, 2, 2) p.append(path.curveto(2, 0, 3, 0, 4, 0)) c.stroke(p) c.stroke(p, [deformer.smoothed(1.0), color.rgb.blue]) c.stroke(p, [deformer.smoothed(2.0), color.rgb.red]) c.writeEPSfile("smoothed") c.writePDFfile("smoothed") c.writeSVGfile("smoothed") PyX-0.14.1/examples/drawing2/smoothed.txt0000644000076500000240000000176312037344757020472 0ustar andrestaff00000000000000Smoothing paths This example shows how to use the `deformer` class. A deformer takes an original path and return a modified one, which is here a smoothed variant. The deformer can be used like any other attribute when stroking or filling a path. Here, we show the use of `deformer.smoothed`, which smoothes away corners in the original path. ... It operates on the `pathitem`s of the original path and cuts out pieces of a given length (`1.0` in the example) surrounding a corner and replaces them by a smooth curve. This new curve is determined to be ''geometrically smooth'', exhibiting the same tangents and curvatures as the original path at the connection points. Alltogether, the smoothing is performed not in a strictly ''geometrical'' sense but also depends on the parameterization of the path. If you try to smooth a path consisting of many short path elements, nothing will really change. ! In all deformers, the deformed path can be accessed directly by ps = deformer.smoothed(1.0).deform(p) PyX-0.14.1/examples/graphs/0000755000076500000240000000000012615763300015636 5ustar andrestaff00000000000000PyX-0.14.1/examples/graphs/axis.ipynb0000644000076500000240000016324412615761454017667 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using a logarithmic axis and defining the axis range and its label" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8,\n", " x=graph.axis.log(min=1e-1, max=1e4, title=r\"$x$-axis\"),\n", " y=graph.axis.lin(max=5, title=r\"$y$-axis\"))\n", "g.plot(graph.data.function(\"y(x)=tan(log(1/x))**2\"))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sometimes, you have to visualize rather pathological funtions containing\n", "divergencies and/or varying over a large parameter range. This is best done\n", "using an appropriate axis. Here, we show a simple example how to do\n", "this with PyX. \n", "\n", "In order to change the properties of the graph axes, we have to create\n", "appropriate instances of an axis class and pass them as keyword arguments to\n", "the `graph.graphxy` constructor. A number of predefined axes is contained in\n", "the `graph.axis` module. Here, we use a linear (abbreviated as\n", "`graph.axis.lin`) and a logarithmic (abbreviated as `graph.axis.log`) axis. In\n", "both cases, we pass a minimal and maximal value for the axis range. Whereas for\n", "the x-axis this is not strictly necessary (we could as well tell the\n", "`graph.data.function` instance to emit data in a certain x-range), it is\n", "important for the y-axis because the function diverges for certain x values. If\n", "we do not set the y range manually, we would obtain a rather compressed display\n", "of the function in the y-direction, which, moreover, would strongly depend on\n", "the sampling points choosen by PyX along the x-direction. Since the function only\n", "diverges towards positive y-values, we only need to set the maximal value of\n", "the y-axis (using the `max`-argument). Of course, you can also fix the lower end\n", "of the axis range by providing a `min`-argument. In order to introduce the\n", "`title` keyword, we give names to the axes.\n", "\n", " Note how PyX changes the way the x-axis is drawn. Instead of simple decimal\n", "numbers, an exponential notation is used. This happens automatically by\n", "default, if at least one of the values to be shown becomes 10,000 or bigger\n", "smaller than 0.001. This behaviour can be altered by using a different axis\n", "texter.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/axis.py0000644000076500000240000000046012515656657017173 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.log(min=1e-1, max=1e4, title=r"$x$-axis"), y=graph.axis.lin(max=5, title=r"$y$-axis")) g.plot(graph.data.function("y(x)=tan(log(1/x))**2")) g.writeEPSfile("axis") g.writePDFfile("axis") g.writeSVGfile("axis") PyX-0.14.1/examples/graphs/axis.txt0000644000076500000240000000341212037344751017346 0ustar andrestaff00000000000000Using a logarithmic axis and defining the axis range and its label Sometimes, you have to visualize rather pathological funtions containing divergencies and/or varying over a large parameter range. This is best done using an appropriate axis. Here, we show a simple example how to do this with PyX. ... In order to change the properties of the graph axes, we have to create appropriate instances of an axis class and pass them as keyword arguments to the `graph.graphxy` constructor. A number of predefined axes is contained in the `graph.axis` module. Here, we use a linear (abbreviated as `graph.axis.lin`) and a logarithmic (abbreviated as `graph.axis.log`) axis. In both cases, we pass a minimal and maximal value for the axis range. Whereas for the x-axis this is not strictly necessary (we could as well tell the `graph.data.function` instance to emit data in a certain x-range), it is important for the y-axis because the function diverges for certain x values. If we do not set the y range manually, we would obtain a rather compressed display of the function in the y-direction, which, moreover, would strongly depend on the sampling points choosen by PyX along the x-direction. Since the function only diverges towards positive y-values, we only need to set the maximal value of the y-axis (using the `max`-argument). Of course, you can also fix the lower end of the axis range by providing a `min`-argument. In order to introduce the `title` keyword, we give names to the axes. ! Note how PyX changes the way the x-axis is drawn. Instead of simple decimal numbers, an exponential notation is used. This happens automatically by default, if at least one of the values to be shown becomes 10,000 or bigger smaller than 0.001. This behaviour can be altered by using a different axis texter. PyX-0.14.1/examples/graphs/change.ipynb0000644000076500000240000020300012615761460020126 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting more than one data set and adding a graph key" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8,\n", " x=graph.axis.linear(min=0, max=2),\n", " y=graph.axis.linear(min=0, max=2),\n", " key=graph.key.key(pos=\"br\", dist=0.1))\n", "g.plot([graph.data.function(\"x(y)=y**4\", title=r\"$x = y^4$\"),\n", " graph.data.function(\"x(y)=y**2\", title=r\"$x = y^2$\"),\n", " graph.data.function(\"x(y)=y\", title=r\"$x = y$\"),\n", " graph.data.function(\"y(x)=x**2\", title=r\"$y = x^2$\"),\n", " graph.data.function(\"y(x)=x**4\", title=r\"$y = x^4$\")],\n", " [graph.style.line([color.gradient.Rainbow])])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example we demonstrate how to plot more than one data set in a graph.\n", "Furthermore, adding a graph key labelling the data is explained. \n", "\n", "In order to display more than one data set, we pass a list of data sets to the\n", "`plot` method of the graph. In the present case, we contruct this list out of\n", "three lists of `graph.data.function` instances. For each data set we also\n", "set a title using the corresponding keyword argument of the data class.\n", "\n", "For a more colorful output, we pass the `color.gradient.Rainbow` color gradient\n", "to the `graph.style.line` class. PyX then automatically chooses color spanning\n", "the whole range of the rainbow gradient.\n", "\n", " If you look at the output, you will notice that not only the colors are\n", "cycled through, but also the line style changes. The reason for this behavior\n", "is that the default line attributes of the `graph.style.line` style contain an\n", "`attr.changelist` comprising a couple of different line styles. When you pass\n", "additional line attributes, these are appended to the default attributes (this\n", "is generally the case in PyX). Consequently, you get a change of both the\n", "color and the line style. If you only want to change the color, either\n", "pass the desired line style explicitly, i.e., use\n", " graph.style.line([style.linestyle.solid, color.gradient.Rainbow])\n", "or clear a previous setting of the line style using the `clear` attribute\n", "of the corresponding class:\n", " graph.style.line([style.linestyle.clear, color.gradient.Rainbow])\n", "\n", " It is also possible to call the `plot` method several times. Note that the\n", "changing of the styles is also performed when the style instances are used on\n", "several plot commands within the same graph as long as the same set of style\n", "instances are passed at the `plot` method calls.\n", "\n", "Finally, when plotting more than one data set you might want to label them in\n", "your graph. We already have passed titles identifying each data set, so we only\n", "have to add a graph key. This is done by passing a `graph.key.key` instance as\n", "the `key` keyword argument to the graph. Usually, you only need to specify the\n", "position of the key using the `pos` argument of the `graph.key.key`\n", "constructor. The syntax should be self-explaining; here we use `br` to put\n", "the key at the bottom-right position of the graph. In order to save some\n", "space, we furthermore decreases the distance between the key entries a little\n", "bit by passing a value of 0.1 to the `dist` argument.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/change.py0000644000076500000240000000120312515656657017450 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.linear(min=0, max=2), y=graph.axis.linear(min=0, max=2), key=graph.key.key(pos="br", dist=0.1)) g.plot([graph.data.function("x(y)=y**4", title=r"$x = y^4$"), graph.data.function("x(y)=y**2", title=r"$x = y^2$"), graph.data.function("x(y)=y", title=r"$x = y$"), graph.data.function("y(x)=x**2", title=r"$y = x^2$"), graph.data.function("y(x)=x**4", title=r"$y = x^4$")], [graph.style.line([color.gradient.Rainbow])]) g.writeEPSfile("change") g.writePDFfile("change") g.writeSVGfile("change") PyX-0.14.1/examples/graphs/change.txt0000644000076500000240000000466212037344751017637 0ustar andrestaff00000000000000Plotting more than one data set and adding a graph key In this example we demonstrate how to plot more than one data set in a graph. Furthermore, adding a graph key labelling the data is explained. ... In order to display more than one data set, we pass a list of data sets to the `plot` method of the graph. In the present case, we contruct this list out of three lists of `graph.data.function` instances. For each data set we also set a title using the corresponding keyword argument of the data class. For a more colorful output, we pass the `color.gradient.Rainbow` color gradient to the `graph.style.line` class. PyX then automatically chooses color spanning the whole range of the rainbow gradient. ! If you look at the output, you will notice that not only the colors are cycled through, but also the line style changes. The reason for this behavior is that the default line attributes of the `graph.style.line` style contain an `attr.changelist` comprising a couple of different line styles. When you pass additional line attributes, these are appended to the default attributes (this is generally the case in PyX). Consequently, you get a change of both the color and the line style. If you only want to change the color, either pass the desired line style explicitly, i.e., use graph.style.line([style.linestyle.solid, color.gradient.Rainbow]) or clear a previous setting of the line style using the `clear` attribute of the corresponding class: graph.style.line([style.linestyle.clear, color.gradient.Rainbow]) !! It is also possible to call the `plot` method several times. Note that the changing of the styles is also performed when the style instances are used on several plot commands within the same graph as long as the same set of style instances are passed at the `plot` method calls. Finally, when plotting more than one data set you might want to label them in your graph. We already have passed titles identifying each data set, so we only have to add a graph key. This is done by passing a `graph.key.key` instance as the `key` keyword argument to the graph. Usually, you only need to specify the position of the key using the `pos` argument of the `graph.key.key` constructor. The syntax should be self-explaining; here we use `br` to put the key at the bottom-right position of the graph. In order to save some space, we furthermore decreases the distance between the key entries a little bit by passing a value of 0.1 to the `dist` argument. PyX-0.14.1/examples/graphs/function.ipynb0000644000076500000240000013255512615761441020545 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting a function graph" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8)\n", "g.plot(graph.data.function(\"y(x)=sin(x)/x\", min=-15, max=15))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we explain how to plot the graph of a real-valued mathematical function of\n", "a single real parameter. \n", "\n", "As in the previous example, we first create a `graph.graphxy` instance passing\n", "the width as argument. We then pass a `graph.data.function` instance to the\n", "`plot` method of the graph. As first argument, we pass the function in the form\n", "\"y(x) = f(x)\". Here, the left-hand side of the equation defines which parameter\n", "is independent (here: `x`) and which one is dependent (here: `y`). We also need\n", "to inform PyX about the range of the independent variable. This is done by passing\n", "the parameters `min` and `max`.\n", "\n", " In order to increase the resolution of the function graph, you can use the\n", "parameter `points` of the `graph.data.function` class to increase the number of\n", "sampling points from its default value of `100`.\n", "\n", "Note that the default graph style for function data is `graph.style.line` since\n", "PyX assumes a continuous x-range. \n", "\n", " You only need to pass the `min` and `max` parameters to the\n", "`graph.data.function` class, if PyX cannot figure out an axis range by itself.\n", "Thus, an alternative way to achieve the above result would look like\n", " g = graph.graphxy(width=8, x=graph.axis.linear(min=-15, max=15))\n", " g.plot(graph.data.function(\"y(x)=sin(x)/x\"))\n", "Here, we explicitely define an x-axis range by passing an appropriate\n", "argument to the `x` parameter of the `graph.graphxy` class.\n", "\n", " For PyX it does not matter, whether you plot a function of a parameter `x` or\n", "a parameter `y`. Thus, you may as well write\n", " g.plot(graph.data.function(\"x(y)=sin(y)/y\", min=-15, max=15))\n", "to obtain a plot where the y-coordinate is the independent one.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/function.py0000644000076500000240000000027512515656657020060 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.function("y(x)=sin(x)/x", min=-15, max=15)) g.writeEPSfile("function") g.writePDFfile("function") g.writeSVGfile("function") PyX-0.14.1/examples/graphs/function.txt0000644000076500000240000000322612037344751020232 0ustar andrestaff00000000000000Plotting a function graph Here, we explain how to plot the graph of a real-valued mathematical function of a single real parameter. ... As in the previous example, we first create a `graph.graphxy` instance passing the width as argument. We then pass a `graph.data.function` instance to the `plot` method of the graph. As first argument, we pass the function in the form "y(x) = f(x)". Here, the left-hand side of the equation defines which parameter is independent (here: `x`) and which one is dependent (here: `y`). We also need to inform PyX about the range of the independent variable. This is done by passing the parameters `min` and `max`. ! In order to increase the resolution of the function graph, you can use the parameter `points` of the `graph.data.function` class to increase the number of sampling points from its default value of `100`. Note that the default graph style for function data is `graph.style.line` since PyX assumes a continuous x-range. ! You only need to pass the `min` and `max` parameters to the `graph.data.function` class, if PyX cannot figure out an axis range by itself. Thus, an alternative way to achieve the above result would look like g = graph.graphxy(width=8, x=graph.axis.linear(min=-15, max=15)) g.plot(graph.data.function("y(x)=sin(x)/x")) Here, we explicitely define an x-axis range by passing an appropriate argument to the `x` parameter of the `graph.graphxy` class. ! For PyX it does not matter, whether you plot a function of a parameter `x` or a parameter `y`. Thus, you may as well write g.plot(graph.data.function("x(y)=sin(y)/y", min=-15, max=15)) to obtain a plot where the y-coordinate is the independent one. PyX-0.14.1/examples/graphs/join.dat0000644000076500000240000000213412037346772017277 0ustar andrestaff000000000000000 -0.0416523 0.00370405 -0.0120944 0.0344828 0.0758855 0.144363 0.203587 0.0689655 0.105887 0.259478 0.3624 0.103448 0.170788 0.360286 0.542374 0.137931 0.20317 0.407522 0.704534 0.172414 0.311803 0.481457 0.80502 0.206897 0.338232 0.594614 0.821449 0.241379 0.302589 0.612485 0.906532 0.275862 0.335894 0.59561 0.898951 0.310345 0.286523 0.537869 0.842022 0.344828 0.241982 0.471199 0.78992 0.37931 0.201726 0.391884 0.645232 0.413793 0.115665 0.282956 0.499897 0.448276 0.126654 0.176257 0.328663 0.482759 0.066533 0.0198417 0.110219 0.517241 -0.0331831 -0.0761098 -0.141317 0.551724 -0.0927296 -0.219183 -0.241559 0.586207 -0.179708 -0.270902 -0.460771 0.62069 -0.162048 -0.456294 -0.575559 0.655172 -0.20805 -0.530463 -0.780346 0.689655 -0.242298 -0.528865 -0.822735 0.724138 -0.315267 -0.588264 -0.905236 0.758621 -0.305853 -0.643168 -0.903536 0.793103 -0.291477 -0.592055 -0.857436 0.827586 -0.289402 -0.484567 -0.76292 0.862069 -0.270358 -0.430461 -0.675236 0.896552 -0.231194 -0.328504 -0.512663 0.931034 -0.17519 -0.221731 -0.330941 0.965517 -0.0567209 -0.0880629 -0.200636 1 0.0449826 -0.0469508 0.0426738 PyX-0.14.1/examples/graphs/join.ipynb0000644000076500000240000023005412615761463017654 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Joing multiple datasets for grouping in the graph key" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, key=graph.key.key())\n", "\n", "As = [0.3, 0.6, 0.9]\n", "\n", "d = [graph.data.join([graph.data.function(\"y_a(x_a)=A*sin(2*pi*x_a)\", context=dict(A=A)),\n", " graph.data.file(\"join.dat\", x_b=1, y_b=i+2)],\n", " title=r\"$A=%g$\" % A)\n", " for i, A in enumerate(As)]\n", "\n", "attrs = [color.gradient.RedBlue]\n", "\n", "g.plot(d,\n", " [graph.style.pos(usenames=dict(x=\"x_a\", y=\"y_a\")),\n", " graph.style.line(attrs),\n", " graph.style.pos(usenames=dict(x=\"x_b\", y=\"y_b\")),\n", " graph.style.symbol(graph.style.symbol.changesquare, symbolattrs=attrs, size=0.1)])\n", "\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to group datasets in the graph key, e.g., to compare simulation\n", "results with measurement data or some approximate results with results from\n", "a more detailed calculation, you can pass a list of datasets to the\n", "`graph.data.join` class.\n", "\n", "When doing so, you have to assign unique names to the corresponding datasets.\n", "In the example, we have used `x_a` and `y_a` as well as `x_b` and\n", "`y_b` as names. Subsequently, one has to tell the graph style which data\n", "columns—identified by the given name—it has to plot. This can be done\n", "by inserting `graph.style.pos` instances before the respective graph style. By\n", "passing a dictionary to the `usenames` argument, one specifies the\n", "mapping from the data columns to the corresponding graph axes `x`, `y`, `x2`,\n", "and so on.\n", "\n", " When using the standard names `x`, `y`, etc. for the data columns, as is done\n", "in most cases, PyX does insert the `graph.style.pos` instance mapping those\n", "data columns to the axis with the same name, automatically.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/join.py0000755000076500000240000000122312515656657017167 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, key=graph.key.key()) As = [0.3, 0.6, 0.9] d = [graph.data.join([graph.data.function("y_a(x_a)=A*sin(2*pi*x_a)", context=dict(A=A)), graph.data.file("join.dat", x_b=1, y_b=i+2)], title=r"$A=%g$" % A) for i, A in enumerate(As)] attrs = [color.gradient.RedBlue] g.plot(d, [graph.style.pos(usenames=dict(x="x_a", y="y_a")), graph.style.line(attrs), graph.style.pos(usenames=dict(x="x_b", y="y_b")), graph.style.symbol(graph.style.symbol.changesquare, symbolattrs=attrs, size=0.1)]) g.writeEPSfile() g.writePDFfile() g.writeSVGfile() PyX-0.14.1/examples/graphs/join.txt0000644000076500000240000000203012037346772017341 0ustar andrestaff00000000000000Joing multiple datasets for grouping in the graph key If you want to group datasets in the graph key, e.g., to compare simulation results with measurement data ... or some approximate results with results from a more detailed calculation, you can pass a list of datasets to the `graph.data.join` class. When doing so, you have to assign unique names to the corresponding datasets. In the example, we have used `x_a` and `y_a` as well as `x_b` and `y_b` as names. Subsequently, one has to tell the graph style which data columns—identified by the given name—it has to plot. This can be done by inserting `graph.style.pos` instances before the respective graph style. By passing a dictionary to the `usenames` argument, one specifies the mapping from the data columns to the corresponding graph axes `x`, `y`, `x2`, and so on. ! When using the standard names `x`, `y`, etc. for the data columns, as is done in most cases, PyX does insert the `graph.style.pos` instance mapping those data columns to the axis with the same name, automatically. PyX-0.14.1/examples/graphs/lissajous.ipynb0000644000076500000240000011744312615761450020733 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting a parametric function" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nRK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from math import pi\n", "from pyx import *\n", "\n", "g = graph.graphxy(width=8)\n", "g.plot(graph.data.paramfunction(\"k\", 0, 2*pi, \"x, y = sin(2*k), cos(3*k)\"))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows how to use a `paramfunction` as a data source for a graph.\n", "`paramfunction` defines a parameter variable name given as a string in the first\n", "argument, a minimal and a maximal value given as the second and third argument\n", "and an expression string as forth argument. This expression string assigns a\n", "tuple of expressions to a tuple of data names. As usual the styles will decide\n", "what those data names are responsible for.\n", "\n", " Like for the function, you can also access external data and functions in your\n", "expression. Suppose we want to provide the data for this example by means of\n", "the following python function:\n", "\n", " def lissajousdata(k):\n", " return sin(2*k), cos(3*k)\n", "\n", "Then we would need to modify the plot command to:\n", "\n", " g.plot(graph.data.paramfunction(\"t\", min, max, \"x, y = f(t)\",\n", " context={\"f\": lissajousdata}))\n", "\n", "Note, that `t` and `f` in the string expression stand for `k` and `lissajousdata`\n", "respectively. You can also use the same names in the expression if you like.\n", "\n", " When you try this, you will notice, that you need to add `sin` and `cos` to the\n", "list of imported symbols from the math module. While this should be expected,\n", "it is more interesting to note, that it was not necessary to import those\n", "functions before. The reason is, that the string expressions are evaluated in\n", "a certain context. This context does not only contain the symbols given in the\n", "`context` keyword argument, but in addition some standard mathematical functions\n", "(and constants) including `sin` and `cos`. See the reference manual for a complete\n", "list.\n", "\n", "For the common case of plotting a parametric function providing data for `x` and\n", "`y` by means of an external function, there is a special `paramfunctionxy` which\n", "directly calls the external function instead of using a context in a string\n", "expression. A `lambda` expression could serve to provide the data inline, which\n", "results in:\n", "\n", " g.plot(graph.data.paramfunctionxy(lambda k: (sin(2*k), cos(3*k)), 0, 2*pi))\n", "\n", "Note that the external expression is provided in the first argument here.\n", "Since the system just need to call the function, the parameter variable name\n", "does not have to be provided to `paramfunctionxy`.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/lissajous.py0000644000076500000240000000034212515656657020242 0ustar andrestaff00000000000000from math import pi from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.paramfunction("k", 0, 2*pi, "x, y = sin(2*k), cos(3*k)")) g.writeEPSfile("lissajous") g.writePDFfile("lissajous") g.writeSVGfile("lissajous") PyX-0.14.1/examples/graphs/lissajous.txt0000644000076500000240000000430612037344752020422 0ustar andrestaff00000000000000Plotting a parametric function This example shows how to use a `paramfunction` as a data source for a graph. `paramfunction` defines a parameter variable name given as a string in the first argument, a minimal and a maximal value given as the second and third argument and an expression string as forth argument. ... This expression string assigns a tuple of expressions to a tuple of data names. As usual the styles will decide what those data names are responsible for. ! Like for the function, you can also access external data and functions in your expression. Suppose we want to provide the data for this example by means of the following python function: def lissajousdata(k): return sin(2*k), cos(3*k) Then we would need to modify the plot command to: g.plot(graph.data.paramfunction("t", min, max, "x, y = f(t)", context={"f": lissajousdata})) Note, that `t` and `f` in the string expression stand for `k` and `lissajousdata` respectively. You can also use the same names in the expression if you like. ! When you try this, you will notice, that you need to add `sin` and `cos` to the list of imported symbols from the math module. While this should be expected, it is more interesting to note, that it was not necessary to import those functions before. The reason is, that the string expressions are evaluated in a certain context. This context does not only contain the symbols given in the `context` keyword argument, but in addition some standard mathematical functions (and constants) including `sin` and `cos`. See the reference manual for a complete list. For the common case of plotting a parametric function providing data for `x` and `y` by means of an external function, there is a special `paramfunctionxy` which directly calls the external function instead of using a context in a string expression. A `lambda` expression could serve to provide the data inline, which results in: g.plot(graph.data.paramfunctionxy(lambda k: (sin(2*k), cos(3*k)), 0, 2*pi)) Note that the external expression is provided in the first argument here. Since the system just need to call the function, the parameter variable name does not have to be provided to `paramfunctionxy`. PyX-0.14.1/examples/graphs/minimal.dat0000644000076500000240000000004412037344752017760 0ustar andrestaff000000000000001 2 2 3 3 8 4 13 5 18 6 21 PyX-0.14.1/examples/graphs/minimal.ipynb0000644000076500000240000007546712615761435020361 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting data contained in a file" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nvWtVm/8H5K9otd0nyioAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8)\n", "g.plot(graph.data.file(\"minimal.dat\", x=1, y=2))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example shows how to draw a graph representing data stored in a file. \n", "We assume that the data is arranged in the file `minimal.dat` in a whitespace-separated\n", "two-column form:\n", " # minimal.dat\n", " 1 2\n", " 2 3\n", " 3 8\n", " 4 13\n", " 5 18\n", " 6 21\n", "\n", "The first step is to create an instance of the `graphxy` class which can be\n", "found in the `graph` module. By convention, we call it `g`. The constructor\n", "expects at least some information about the desired size of the graph. Here, we\n", "specify a width of 8 cm.\n", "\n", " If we only specify one dimension of the graph size, PyX calculates the other\n", "automatically, assuming a ratio corresponding to the golden ratio.\n", "\n", "Next, we add some data to the yet empty graph. In order to do so, we first\n", "create a `graph.data.file` instance, which reads the file with the name given\n", "as the first argument, i.e., in the present case, `\"minimal.dat\"`. In addition,\n", "we have to specify, how the data is organized in the file. To this end, we use\n", "the keyword arguments `x=1` and `y=2`, which tell PyX that the first (second)\n", "column of the file contains the x (y) values. The `graph.data.file` instance is\n", "then directly passed to the `plot` method of the graph `g`.\n", "\n", " Note that PyX by default ignores comments starting by a # sign when reading\n", "in the data from the file.\n", "\n", " The previous statement is actually not completely correct, as PyX\n", "uses the last comment preceding the actual data to give names to the columns.\n", "Thus, for a file looking like\n", " # my data (this line is ignored by PyX, but not the following)\n", " # x y\n", " 1 2\n", " \n", "you wouldn't need to label the columns in the `graph.data.file` call at all.\n", "\n", "Finally, we write the graph to an EPS and PDF file. Here, we use that every\n", "graph is (by inheritance) an instance of the `canvas` class, as well, such that\n", "we can directly write it into a file.\n", "\n", " Of course, you can also insert a graph into another canvas and write this\n", "canvas later to a file. This way, you can, for instance, easily arrange more\n", "than one graph on a page. Later examples will make use of this fact.\n", "\n", "In PyX, the way data is plotted in a graph is defined by a so-called graph\n", "style. A couple of standard graph styles are contained in the module\n", "`graph.style`. Depending on the data source, PyX chooses a default style. Here,\n", "we are taking the data from a file and PyX assumes that the values represent a\n", "discrete set of data points. Hence, it chooses the symbol style\n", "`graph.style.symbol` to plot the data. To override this default behaviour, you\n", "can pass a list of styles as second argument to the `plot` method. For instance,\n", "to have PyX drawing a line through the data points, you can use\n", "\n", " g.plot(graph.data.file(\"minimal.dat\", x=1, y=2), [graph.style.line()])\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/minimal.py0000644000076500000240000000025512515656657017657 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.file("minimal.dat", x=1, y=2)) g.writeEPSfile("minimal") g.writePDFfile("minimal") g.writeSVGfile("minimal") PyX-0.14.1/examples/graphs/minimal.txt0000644000076500000240000000527412037344751020040 0ustar andrestaff00000000000000Plotting data contained in a file This example shows how to draw a graph representing data stored in a file. ... We assume that the data is arranged in the file `minimal.dat` in a whitespace-separated two-column form: # minimal.dat 1 2 2 3 3 8 4 13 5 18 6 21 The first step is to create an instance of the `graphxy` class which can be found in the `graph` module. By convention, we call it `g`. The constructor expects at least some information about the desired size of the graph. Here, we specify a width of 8 cm. ! If we only specify one dimension of the graph size, PyX calculates the other automatically, assuming a ratio corresponding to the golden ratio. Next, we add some data to the yet empty graph. In order to do so, we first create a `graph.data.file` instance, which reads the file with the name given as the first argument, i.e., in the present case, `"minimal.dat"`. In addition, we have to specify, how the data is organized in the file. To this end, we use the keyword arguments `x=1` and `y=2`, which tell PyX that the first (second) column of the file contains the x (y) values. The `graph.data.file` instance is then directly passed to the `plot` method of the graph `g`. ! Note that PyX by default ignores comments starting by a # sign when reading in the data from the file. !! The previous statement is actually not completely correct, as PyX uses the last comment preceding the actual data to give names to the columns. Thus, for a file looking like # my data (this line is ignored by PyX, but not the following) # x y 1 2 ... you wouldn't need to label the columns in the `graph.data.file` call at all. Finally, we write the graph to an EPS and PDF file. Here, we use that every graph is (by inheritance) an instance of the `canvas` class, as well, such that we can directly write it into a file. ! Of course, you can also insert a graph into another canvas and write this canvas later to a file. This way, you can, for instance, easily arrange more than one graph on a page. Later examples will make use of this fact. In PyX, the way data is plotted in a graph is defined by a so-called graph style. A couple of standard graph styles are contained in the module `graph.style`. Depending on the data source, PyX chooses a default style. Here, we are taking the data from a file and PyX assumes that the values represent a discrete set of data points. Hence, it chooses the symbol style `graph.style.symbol` to plot the data. To override this default behaviour, you can pass a list of styles as second argument to the `plot` method. For instance, to have PyX drawing a line through the data points, you can use g.plot(graph.data.file("minimal.dat", x=1, y=2), [graph.style.line()]) PyX-0.14.1/examples/graphs/points.ipynb0000644000076500000240000007437612615761444020245 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting data contained in one or more lists" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nB/fcu2a9Dv4fhpL+ZCRrcfoAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# suggested by Chris Spencer\n", "\n", "from pyx import *\n", "\n", "g = graph.graphxy(width=8)\n", "# either provide lists of the individual coordinates\n", "g.plot(graph.data.values(x=list(range(10)), y=list(range(10))))\n", "# or provide one list containing the whole points\n", "g.plot(graph.data.points(list(zip(range(10), range(10))), x=1, y=2))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we explain how to plot data which has been calculated before and which is\n", "available in a list. \n", "\n", "The procedure is quite the same as for plotting a data file or a function in\n", "the above examples. It differs in that we use an instance of\n", "`graph.data.values` or `graph.data.points` in the `plot` method of the graph.\n", "The choice of one or the other variant depends on convenience and how the data\n", "has been generated: In `graph.data.values` the coordinate values are provided\n", "as individual lists. Alternatively, `graph.data.points` takes a list of data\n", "points which come as coordinate tuples. You will then have to say something\n", "like `x=1, y=2` to specify which entry in your tuples is to be used on which\n", "axis.\n", "\n", "Similarly to the plotting of a data file, the default plotting style here are\n", "symbols.\n", "\n", "Caution: This feature has been renamed/introduced between versions 0.9 and\n", "0.10. In versions 0.9 and before the functionality of `graph.data.points` was\n", "provided by `graph.data.list`.\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphs/points.py0000644000076500000240000000060312522164247017525 0ustar andrestaff00000000000000# suggested by Chris Spencer from pyx import * g = graph.graphxy(width=8) # either provide lists of the individual coordinates g.plot(graph.data.values(x=list(range(10)), y=list(range(10)))) # or provide one list containing the whole points g.plot(graph.data.points(list(zip(range(10), range(10))), x=1, y=2)) g.writeEPSfile("points") g.writePDFfile("points") g.writeSVGfile("points") PyX-0.14.1/examples/graphs/points.txt0000644000076500000240000000201312037344752017713 0ustar andrestaff00000000000000Plotting data contained in one or more lists Here, we explain how to plot data which has been calculated before and which is available in a list. ... The procedure is quite the same as for plotting a data file or a function in the above examples. It differs in that we use an instance of `graph.data.values` or `graph.data.points` in the `plot` method of the graph. The choice of one or the other variant depends on convenience and how the data has been generated: In `graph.data.values` the coordinate values are provided as individual lists. Alternatively, `graph.data.points` takes a list of data points which come as coordinate tuples. You will then have to say something like `x=1, y=2` to specify which entry in your tuples is to be used on which axis. Similarly to the plotting of a data file, the default plotting style here are symbols. Caution: This feature has been renamed/introduced between versions 0.9 and 0.10. In versions 0.9 and before the functionality of `graph.data.points` was provided by `graph.data.list`. PyX-0.14.1/examples/graphs/README0000644000076500000240000000233412037344752016524 0ustar andrestaff00000000000000Basic plotting One of PyX's major strengths are its graph-plotting capabilities. PyX offers you a flexible system which, while providing sensible defaults, allows you to customize almost every aspect of the graph output. Such a flexibility comes at a price, though: you need to learn at least a little bit about the different components playing together in order to produce a graph. In this section, we try to give you a gentle introduction to one component after the other by by demonstrating how to plot various kind of data (from a file, a function mapping x values to y values, a parametric function). Furthermore, we explain how to do simple modifications to the axes of the graph and show how to add a graph key. After having gone through the introductory examples you should be able to freely go through the following sections of the examples, which examples will be devoted to a more detailed explanation of PyX's graph-plotting facilities. In particular, you might want to learn about the customization of the graph axes (see section [ Graph axes ../axis/index.html]), about further available graph styles (see section [Graph styles ../styles/index.html]) and about bar graphs (see section [Bar graphs ../bargraphs/index.html]). PyX-0.14.1/examples/graphstyles/0000755000076500000240000000000012615763300016717 5ustar andrestaff00000000000000PyX-0.14.1/examples/graphstyles/cal.ipynb0000644000076500000240000700721312615761620020536 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Making a calendar graph" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nEBEREdEV+W+tkO6alVM6JQAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import calendar\n", "from pyx import *\n", "\n", "class daystyle(graph.style._style):\n", "\n", " def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames):\n", " # register the new column names\n", " usecolumnnames = [\"day\", \"month\", \"weekday\", \"note\"]\n", " for columnname in usecolumnnames:\n", " if columnname not in columnnames:\n", " raise ValueError(\"column '%s' missing\" % columnname)\n", " return usecolumnnames\n", "\n", " def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data):\n", " # adjust axes ranges\n", " if columnname == \"month\":\n", " graph.axes[\"x\"].adjustaxis([(x, 0) for x in data])\n", " graph.axes[\"x\"].adjustaxis([(x, 1) for x in data])\n", " if columnname == \"day\":\n", " graph.axes[\"y\"].adjustaxis([(x, 0) for x in data])\n", " graph.axes[\"y\"].adjustaxis([(x, 1) for x in data])\n", "\n", " def drawpoint(self, privatedata, sharedata, graph, point):\n", " # draw a single day\n", " x1_pt, y1_pt = graph.pos_pt((point[\"month\"], 0), (point[\"day\"], 0))\n", " x2_pt, y2_pt = graph.pos_pt((point[\"month\"], 1), (point[\"day\"], 1))\n", " p = path.rect_pt(x1_pt, y1_pt, x2_pt - x1_pt, y2_pt - y1_pt)\n", " if point[\"weekday\"] == calendar.day_abbr[-1]:\n", " graph.stroke(p, [deco.filled([color.gray(0.8)])])\n", " else:\n", " graph.stroke(p)\n", " graph.text_pt(x1_pt+3, y2_pt-3,\n", " \"%i %s\" % (point[\"day\"], point[\"weekday\"]),\n", " [text.valign.top])\n", " if point[\"note\"]:\n", " graph.text_pt(x1_pt+3, y1_pt+3, point[\"note\"], [text.size.tiny])\n", "\n", "# create calendar data\n", "year = 2015\n", "notes = {1: {17: r\"\\PyX{} 0.2 (2003)\", 20: r\"\\PyX{} 0.5 (2004)\", 22: r\"\\PyX{} 0.5.1 (2004)\"},\n", " 3: {30: r\"\\PyX{} 0.6 (2004)\", 31: r\"\\PyX{} 0.3 ('03), \\PyX{} 0.6.1 ('04)\"},\n", " 4: {4: r\"\\PyX{} 0.3.1 (2003)\", 7: r\"\\PyX{} 0.6.2 (2004)\", 27: r\"\\PyX{} 0.6.3 (2004)\", 30: r\"\\PyX{} 0.14 (2015)\"},\n", " 5: {5: r\"\\PyX{} 0.11 (2011)\", 20: r\"\\PyX{} 0.11.1 (2011)\", 24: r\"\\PyX{} 0.9 (2006)\"},\n", " 7: {13: r\"\\PyX{} 0.8 (2005)\"},\n", " 8: {13: r\"\\PyX{} 0.8.1 (2005)\", 22: r\"\\PyX{} 0.4 (2003)\"},\n", " 9: {17: r\"\\PyX{} 0.4.1 (2003)\"},\n", " 10: {3: r\"\\PyX{} 0.10 (2007)\", 7: r\"\\PyX{} 0.1 (2002)\", 12: r\"\\PyX{} 0.12 (2012)\",\n", " 21: r\"\\PyX{} 0.7 (2004)\", 26: r\"\\PyX{} 0.12.1 (2012)\"},\n", " 11: {2: r\"\\PyX{} 0.14.1 (2015)\"},\n", " 12: {15: r\"\\PyX{} 0.7.1 (2004)\", 20: r\"\\PyX{} 0.13 (2013)\"}}\n", "d = graph.data.points([(day,\n", " calendar.month_name[month],\n", " calendar.day_abbr[calendar.weekday(year, month, day)],\n", " notes.get(month, {}).get(day))\n", " for month in range(1, 13)\n", " for day in range(1, calendar.monthrange(year, month)[1]+1)],\n", " day=1, month=2, weekday=3, note=4)\n", "\n", "# create the calendar\n", "g = graph.graphxy(width=40, x2=graph.axis.bar(dist=0, linkpainter=None),\n", " y=graph.axis.bar(dist=0, reverse=1, painter=None))\n", "g.plot(d, [daystyle()])\n", "\n", "# we could write the full calendar by\n", "# g.writeEPSfile(\"cal\", paperformat=document.paperformat.A3, rotated=1)\n", "\n", "# instead we clip the result to show only a small part\n", "clip = canvas.clip(g.bbox().enlarged(0.1, bottom=-17, right=-25).path())\n", "gc = canvas.canvas([clip])\n", "gc.insert(g)\n", "# and add some dots at the clipped parts\n", "gcbb = gc.bbox()\n", "c = canvas.canvas()\n", "c.insert(gc)\n", "c.text(gcbb.right()+0.5, gcbb.center()[1], r\"\\dots\")\n", "c.text(gcbb.center()[0], gcbb.bottom()-0.5, r\"\\dots\")\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " In this example we create a calendar graph style. The style uses bar axes\n", "for both graph coordinates and it is a simple and minimal example in the sense\n", "that it does not make use of other styles for positioning.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/cal.py0000644000076500000240000000701412615761267020044 0ustar andrestaff00000000000000import calendar from pyx import * class daystyle(graph.style._style): def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): # register the new column names usecolumnnames = ["day", "month", "weekday", "note"] for columnname in usecolumnnames: if columnname not in columnnames: raise ValueError("column '%s' missing" % columnname) return usecolumnnames def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): # adjust axes ranges if columnname == "month": graph.axes["x"].adjustaxis([(x, 0) for x in data]) graph.axes["x"].adjustaxis([(x, 1) for x in data]) if columnname == "day": graph.axes["y"].adjustaxis([(x, 0) for x in data]) graph.axes["y"].adjustaxis([(x, 1) for x in data]) def drawpoint(self, privatedata, sharedata, graph, point): # draw a single day x1_pt, y1_pt = graph.pos_pt((point["month"], 0), (point["day"], 0)) x2_pt, y2_pt = graph.pos_pt((point["month"], 1), (point["day"], 1)) p = path.rect_pt(x1_pt, y1_pt, x2_pt - x1_pt, y2_pt - y1_pt) if point["weekday"] == calendar.day_abbr[-1]: graph.stroke(p, [deco.filled([color.gray(0.8)])]) else: graph.stroke(p) graph.text_pt(x1_pt+3, y2_pt-3, "%i %s" % (point["day"], point["weekday"]), [text.valign.top]) if point["note"]: graph.text_pt(x1_pt+3, y1_pt+3, point["note"], [text.size.tiny]) # create calendar data year = 2015 notes = {1: {17: r"\PyX{} 0.2 (2003)", 20: r"\PyX{} 0.5 (2004)", 22: r"\PyX{} 0.5.1 (2004)"}, 3: {30: r"\PyX{} 0.6 (2004)", 31: r"\PyX{} 0.3 ('03), \PyX{} 0.6.1 ('04)"}, 4: {4: r"\PyX{} 0.3.1 (2003)", 7: r"\PyX{} 0.6.2 (2004)", 27: r"\PyX{} 0.6.3 (2004)", 30: r"\PyX{} 0.14 (2015)"}, 5: {5: r"\PyX{} 0.11 (2011)", 20: r"\PyX{} 0.11.1 (2011)", 24: r"\PyX{} 0.9 (2006)"}, 7: {13: r"\PyX{} 0.8 (2005)"}, 8: {13: r"\PyX{} 0.8.1 (2005)", 22: r"\PyX{} 0.4 (2003)"}, 9: {17: r"\PyX{} 0.4.1 (2003)"}, 10: {3: r"\PyX{} 0.10 (2007)", 7: r"\PyX{} 0.1 (2002)", 12: r"\PyX{} 0.12 (2012)", 21: r"\PyX{} 0.7 (2004)", 26: r"\PyX{} 0.12.1 (2012)"}, 11: {2: r"\PyX{} 0.14.1 (2015)"}, 12: {15: r"\PyX{} 0.7.1 (2004)", 20: r"\PyX{} 0.13 (2013)"}} d = graph.data.points([(day, calendar.month_name[month], calendar.day_abbr[calendar.weekday(year, month, day)], notes.get(month, {}).get(day)) for month in range(1, 13) for day in range(1, calendar.monthrange(year, month)[1]+1)], day=1, month=2, weekday=3, note=4) # create the calendar g = graph.graphxy(width=40, x2=graph.axis.bar(dist=0, linkpainter=None), y=graph.axis.bar(dist=0, reverse=1, painter=None)) g.plot(d, [daystyle()]) # we could write the full calendar by # g.writeEPSfile("cal", paperformat=document.paperformat.A3, rotated=1) # instead we clip the result to show only a small part clip = canvas.clip(g.bbox().enlarged(0.1, bottom=-17, right=-25).path()) gc = canvas.canvas([clip]) gc.insert(g) # and add some dots at the clipped parts gcbb = gc.bbox() c = canvas.canvas() c.insert(gc) c.text(gcbb.right()+0.5, gcbb.center()[1], r"\dots") c.text(gcbb.center()[0], gcbb.bottom()-0.5, r"\dots") c.writeEPSfile("cal") c.writePDFfile("cal") c.writeSVGfile("cal") PyX-0.14.1/examples/graphstyles/cal.txt0000644000076500000240000000036012037340752020216 0ustar andrestaff00000000000000Making a calendar graph !! In this example we create a calendar graph style. The style uses bar axes for both graph coordinates and it is a simple and minimal example in the sense that it does not make use of other styles for positioning. PyX-0.14.1/examples/graphstyles/changesymbol.ipynb0000644000076500000240000123262612615761610022453 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Add functionality to existing graph styles" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import random\n", "from pyx import *\n", "\n", "# introduce a new symbol style where size and color are given by some data\n", "class changesymbol(graph.style.symbol):\n", "\n", " def __init__(self, sizecolumnname=\"size\", colorcolumnname=\"color\",\n", " gradient=color.gradient.Rainbow,\n", " symbol=graph.style.symbol.circle,\n", " symbolattrs=[deco.filled, deco.stroked([color.gray.black])],\n", " **kwargs):\n", " # add some configuration parameters and modify some other\n", " self.sizecolumnname = sizecolumnname\n", " self.colorcolumnname = colorcolumnname\n", " self.gradient = gradient\n", " graph.style.symbol.__init__(self, symbol=symbol, symbolattrs=symbolattrs, **kwargs)\n", "\n", " def columnnames(self, privatedata, sharedata, agraph, columnnames, dataaxisnames):\n", " # register the new column names\n", " if self.sizecolumnname not in columnnames:\n", " raise ValueError(\"column '%s' missing\" % self.sizecolumnname)\n", " if self.colorcolumnname not in columnnames:\n", " raise ValueError(\"column '%s' missing\" % self.colorcolumnname)\n", " return ([self.sizecolumnname, self.colorcolumnname] +\n", " graph.style.symbol.columnnames(self, privatedata, sharedata, agraph,\n", " columnnames, dataaxisnames))\n", "\n", " def drawpoint(self, privatedata, sharedata, graph, point):\n", " # replace the original drawpoint method by a slightly revised one\n", " if sharedata.vposvalid and privatedata.symbolattrs is not None:\n", " x_pt, y_pt = graph.vpos_pt(*sharedata.vpos)\n", " color = self.gradient.getcolor(point[self.colorcolumnname])\n", " privatedata.symbol(privatedata.symbolcanvas, x_pt, y_pt,\n", " privatedata.size_pt*point[self.sizecolumnname],\n", " privatedata.symbolattrs + [color])\n", "\n", "g = graph.graphxy(width=10)\n", "g.plot(graph.data.points([[random.random() for i in range(4)]\n", " for i in range(1000)],\n", " x=1, y=2, size=3, color=4),\n", " [changesymbol()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " In this example demonstrate how graph styles can be modified to add further\n", "functionality to them. Here we create changesymbol styles based on PyX's\n", "symbol style. For that two additional column names are introduced that way,\n", "that they can be modified in the constructor of the style. The column names are\n", "then registered by the adjusted version of the `columnnames` method. After that\n", "we only need to replace the drawpoint method by a modified version, which\n", "implements the additional functionality. This new created style can than be\n", "used like any other graph style.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/changesymbol.py0000644000076500000240000000423012515656701021750 0ustar andrestaff00000000000000import random from pyx import * # introduce a new symbol style where size and color are given by some data class changesymbol(graph.style.symbol): def __init__(self, sizecolumnname="size", colorcolumnname="color", gradient=color.gradient.Rainbow, symbol=graph.style.symbol.circle, symbolattrs=[deco.filled, deco.stroked([color.gray.black])], **kwargs): # add some configuration parameters and modify some other self.sizecolumnname = sizecolumnname self.colorcolumnname = colorcolumnname self.gradient = gradient graph.style.symbol.__init__(self, symbol=symbol, symbolattrs=symbolattrs, **kwargs) def columnnames(self, privatedata, sharedata, agraph, columnnames, dataaxisnames): # register the new column names if self.sizecolumnname not in columnnames: raise ValueError("column '%s' missing" % self.sizecolumnname) if self.colorcolumnname not in columnnames: raise ValueError("column '%s' missing" % self.colorcolumnname) return ([self.sizecolumnname, self.colorcolumnname] + graph.style.symbol.columnnames(self, privatedata, sharedata, agraph, columnnames, dataaxisnames)) def drawpoint(self, privatedata, sharedata, graph, point): # replace the original drawpoint method by a slightly revised one if sharedata.vposvalid and privatedata.symbolattrs is not None: x_pt, y_pt = graph.vpos_pt(*sharedata.vpos) color = self.gradient.getcolor(point[self.colorcolumnname]) privatedata.symbol(privatedata.symbolcanvas, x_pt, y_pt, privatedata.size_pt*point[self.sizecolumnname], privatedata.symbolattrs + [color]) g = graph.graphxy(width=10) g.plot(graph.data.points([[random.random() for i in range(4)] for i in range(1000)], x=1, y=2, size=3, color=4), [changesymbol()]) g.writeEPSfile("changesymbol") g.writePDFfile("changesymbol") g.writeSVGfile("changesymbol") PyX-0.14.1/examples/graphstyles/changesymbol.txt0000644000076500000240000000115212037340752022132 0ustar andrestaff00000000000000Add functionality to existing graph styles ! In this example demonstrate how graph styles can be modified to add further functionality to them. ... Here we create changesymbol styles based on PyX's symbol style. For that two additional column names are introduced that way, that they can be modified in the constructor of the style. The column names are then registered by the adjusted version of the `columnnames` method. After that we only need to replace the drawpoint method by a modified version, which implements the additional functionality. This new created style can than be used like any other graph style. PyX-0.14.1/examples/graphstyles/density.ipynb0000644000076500000240000021335412615761600021452 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Drawing a density plot" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "# Mandelbrot calculation contributed by Stephen Phillips\n", "\n", "# Mandelbrot parameters\n", "re_min = -2\n", "re_max = 0.5\n", "im_min = -1.25\n", "im_max = 1.25\n", "gridx = 100\n", "gridy = 100\n", "max_iter = 10\n", "\n", "# Set-up\n", "re_step = (re_max - re_min) / gridx\n", "im_step = (im_max - im_min) / gridy\n", "d = []\n", "\n", "# Compute fractal\n", "for re_index in range(gridx):\n", " re = re_min + re_step * (re_index + 0.5)\n", " for im_index in range(gridy):\n", " im = im_min + im_step * (im_index + 0.5)\n", " c = complex(re, im)\n", " n = 0\n", " z = complex(0, 0)\n", " while n < max_iter and abs(z) < 2:\n", " z = (z * z) + c\n", " n += 1\n", " d.append([re, im, n])\n", "\n", "# Plot graph\n", "g = graph.graphxy(height=8, width=8,\n", " x=graph.axis.linear(min=re_min, max=re_max, title=r\"$\\Re(c)$\"),\n", " y=graph.axis.linear(min=im_min, max=im_max, title=r'$\\Im(c)$'))\n", "g.plot(graph.data.points(d, x=1, y=2, color=3, title=\"iterations\"),\n", " [graph.style.density(gradient=color.rgbgradient.Rainbow)])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2 dimensional plots where the value of each point is represented by a color can\n", "be created by the density style. The data points have to be spaced\n", "equidistantly in each dimension with the possible exception of missing data.\n", "\n", "For data which is not equidistantly spaced but still arranged in a grid,\n", "`graph.style.surface` can be used, which also provides a smooth representation\n", "by means of a color interpolation between the mesh moints. Finally, for\n", "completely unstructured data, `graph.style.rect` can be used.\n", "\n", "The plot is encoded in an efficient way using a bitmap. Unfortunately, this\n", "means, that the HSB color space cannot be used (due to limitations of the\n", "bitmap color spaces in PostScript and PDF). Some of the predefined gradients in\n", "PyX, e.g. `color.gradient.Rainbow`, cannot be used here. As a workaround, PyX\n", "provides those gradients in other color spaces as shown in the example.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/density.py0000644000076500000240000000202712515656701020756 0ustar andrestaff00000000000000from pyx import * # Mandelbrot calculation contributed by Stephen Phillips # Mandelbrot parameters re_min = -2 re_max = 0.5 im_min = -1.25 im_max = 1.25 gridx = 100 gridy = 100 max_iter = 10 # Set-up re_step = (re_max - re_min) / gridx im_step = (im_max - im_min) / gridy d = [] # Compute fractal for re_index in range(gridx): re = re_min + re_step * (re_index + 0.5) for im_index in range(gridy): im = im_min + im_step * (im_index + 0.5) c = complex(re, im) n = 0 z = complex(0, 0) while n < max_iter and abs(z) < 2: z = (z * z) + c n += 1 d.append([re, im, n]) # Plot graph g = graph.graphxy(height=8, width=8, x=graph.axis.linear(min=re_min, max=re_max, title=r"$\Re(c)$"), y=graph.axis.linear(min=im_min, max=im_max, title=r'$\Im(c)$')) g.plot(graph.data.points(d, x=1, y=2, color=3, title="iterations"), [graph.style.density(gradient=color.rgbgradient.Rainbow)]) g.writeEPSfile() g.writePDFfile() g.writeSVGfile() PyX-0.14.1/examples/graphstyles/density.txt0000644000076500000240000000163112037346772021150 0ustar andrestaff00000000000000Drawing a density plot 2 dimensional plots where the value of each point is represented by a color can be created by the density style. ... The data points have to be spaced equidistantly in each dimension with the possible exception of missing data. For data which is not equidistantly spaced but still arranged in a grid, `graph.style.surface` can be used, which also provides a smooth representation by means of a color interpolation between the mesh moints. Finally, for completely unstructured data, `graph.style.rect` can be used. !The plot is encoded in an efficient way using a bitmap. Unfortunately, this means, that the HSB color space cannot be used (due to limitations of the bitmap color spaces in PostScript and PDF). Some of the predefined gradients in PyX, e.g. `color.gradient.Rainbow`, cannot be used here. As a workaround, PyX provides those gradients in other color spaces as shown in the example. PyX-0.14.1/examples/graphstyles/errorbar.dat0000644000076500000240000000010212037344757021231 0ustar andrestaff000000000000001 2 0.7 2 3 0.9 3 8 0.8 4 13 1.2 5 18 1.1 6 21 1.3 PyX-0.14.1/examples/graphstyles/errorbar.ipynb0000644000076500000240000007671012615761570021622 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Combining several graph styles" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8)\n", "g.plot(graph.data.file(\"errorbar.dat\", x=1, y=2, dy=3),\n", " [graph.style.symbol(), graph.style.errorbar()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example several graph styles are applied one after the other to stroke\n", "symbols and errorbars for the given data. This can be achieved by passing a\n", "list of graph styles as the second parameter to the graph style. \n", "\n", "When you do set the second argument in the graphs plot command, default graph\n", "styles are used to plot the data. The default for the graph styles depend is a\n", "property of the data instance passed in the first argument of the plot command.\n", "While the list and file data instances use a `graph.style.symbol` instance by\n", "default, for functions and parametric functions a `graph.style.line` instance\n", "is used.\n", "\n", "The style instances parse the column names for appropriate entries to generate\n", "the corresponding output. In this case, the `x` and `y` values are used by\n", "both, the symbol and the errorbar style, whereas `dy` is used by the\n", "`errorbar` style only.\n", "\n", " You could also provide data for `ymin` and `ymax` to the errorbar style\n", "instead of `dy`. The errorbar style can also draw errorbars in x-direction\n", "using `dx` or `xmin` and `xmax`. You can add errorbars in both graph directions\n", "at the same time.\n", "\n", " The `x` and `y` data is not used by the symbol style nor the errorbar style\n", "directly (except for calculating the minimal and maximal value in y-direction\n", "by the errorbar due to the parametrization by `y` and `dy`). Instead a\n", "positioning style is inserted implicitly (a instance of graph.style.pos) as a\n", "position information is needed by the symbol and errorbar styles. By that the\n", "styles don't need to perform certain operations several times. Additionally the\n", "styles can also be used on graphs, which behave different in their positioning\n", "properties like bar graphs where you can use the same styles by just using a\n", "different positioning style.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/errorbar.py0000644000076500000240000000035612515656701021120 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.file("errorbar.dat", x=1, y=2, dy=3), [graph.style.symbol(), graph.style.errorbar()]) g.writeEPSfile("errorbar") g.writePDFfile("errorbar") g.writeSVGfile("errorbar") PyX-0.14.1/examples/graphstyles/errorbar.txt0000644000076500000240000000341412037340752021300 0ustar andrestaff00000000000000Combining several graph styles In this example several graph styles are applied one after the other to stroke symbols and errorbars for the given data. This can be achieved by passing a list of graph styles as the second parameter to the graph style. ... When you do set the second argument in the graphs plot command, default graph styles are used to plot the data. The default for the graph styles depend is a property of the data instance passed in the first argument of the plot command. While the list and file data instances use a `graph.style.symbol` instance by default, for functions and parametric functions a `graph.style.line` instance is used. The style instances parse the column names for appropriate entries to generate the corresponding output. In this case, the `x` and `y` values are used by both, the symbol and the errorbar style, whereas `dy` is used by the `errorbar` style only. ! You could also provide data for `ymin` and `ymax` to the errorbar style instead of `dy`. The errorbar style can also draw errorbars in x-direction using `dx` or `xmin` and `xmax`. You can add errorbars in both graph directions at the same time. !! The `x` and `y` data is not used by the symbol style nor the errorbar style directly (except for calculating the minimal and maximal value in y-direction by the errorbar due to the parametrization by `y` and `dy`). Instead a positioning style is inserted implicitly (a instance of graph.style.pos) as a position information is needed by the symbol and errorbar styles. By that the styles don't need to perform certain operations several times. Additionally the styles can also be used on graphs, which behave different in their positioning properties like bar graphs where you can use the same styles by just using a different positioning style. PyX-0.14.1/examples/graphstyles/histogram.ipynb0000644000076500000240000006514412615761573022003 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Creating a histogram" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWkAAADgCAYAAADBs5fqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAyKSURBVHic7d2/biPXFcfx3wlsBEb8BxQCJMAWCbjrKkBih9vbBfcRqLyB3Lqj/AbcR1i+QVaP\nQDbuxcJFkEqDuDDsBIaZKlueFLzUzo4oiRzNcM5cfT+AYGo44r3cIX+8PHM919xdAICYfnWshsxs\ncKy2ACAXrYe0mY3M7EzSZdttAUBu7FjlDjNzd7ejNAYAmThauQMAcDhCGgACe6/rDuzDzL6W9H5l\n84+SfuqgOwDQhA8lfVrZduLu35Q39KImbWb/lfTPyuZ/Sfr+of2q+Is2wf/vhh+36neSfi/pu5bb\nkaQvJH2bUTsco/jtcIz284mkzyrb/uzuvylv6EtI/+zuv226TzvamUlauvuy5XbGksbuft5mO6mt\nhbu/yKgdjlH8djhG9du5kXXUpAEgsNZr0mmO9DDdnkkq3H3edrs1zSWtu+5Ew1ofZRwZxyg+jlGD\nWg/pUiCHfyG6e9F1H5rm7quu+9AkjlF8HKNmHa0m/RDHqgcBQJd2ZR01aQAIjJAGgMAIaQAIjJAG\ngMAIaQAIjJAGgMAIaQAIjJAGgMAIaQAIjJAGgMAIaQAIjJAGgMAIaQAIrBdrHAI5M7NF131owXlu\nl2DtCiENBJDTpXjT4h6DrvuRC8odABAYIQ0AgRHSABBYX2rST0onV1bHWMIdAI4hLdY9Sb8+q97f\nl5D+IacTKwCwlRbrnku7Z/pQ7gCAwAhpAAiMkAaAwAhpAAiMkAaAwAhpAAiMkAaAwAhpAAiMkAaA\nwAhpAAiMkAaAwAhpAAiMkAaAwAhpAAiMkAaAwAhpAAjsQSFtZuM99hnc9TsA4Ha1QtrMJmY2Tbdn\nZja6Y/epmV2Z2cLMLiXdG+wAgI26y2dN3f15ur00sytJT2/ZdyWpSLcv3H1ds00AeHQODulU4qgG\nbWFmI3df7fiTtbtf1OodADxydUbSt5Urbqs1D0q167Gkl4ymAWA/x1gtvNiOsM1Mkl5LYuVvANhD\n6yFdLoG4+zKdQBy6e3HX31WcmNmssm3p7stmegmgYZN9Zn/1SOHu8yYf0MyGks4qm59U96sT0ktJ\n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\nMzWzq3R8LpWOV5+l/yN7ImlYXswg9P9xaGaX7v689PuVuz/tsk9NyeFaJmlUdubu5+n3saTXkp66\n+7rTzj2Ambmk5+6+Sh9Cr9z9pOt+PVT6sDmTdF69SmXfpOOyHT1f9Pn1Jr17yYw0GF1sX3NhR9Lp\nDV/9hy9yGE1nZKDNiGYgSemNP5DU92N0KqlIt4eSVh32pRHpA7XQzfdUX63dfZ5+ev2c0vtnur2m\nUVpy8HpQEDakdfvXlyxqTzlILybbvknS6Gbd91Gau1+4+zq9ecaSzrvuUwNGfT8uFYO0xuE4lUL7\nnAsjSav0XCbp+VyfO2j9Knh4VM6UR6ApfWMbKY9R9ERSTgEtbUoDK0kyM2lTZnvRaY/qG2vzja1w\n98LMVto8n+dS7JE0eiSd4L3I5TK0pVXuV5IWfR2ppRHZuu8lgaptQKfbS0njHs9cWWtzjApJSv8d\nbU/wRg7pXZ/8vXyj5C6N1LYnPYY9frNsZ9+8Km3qe519rE2AzdLJqZGkSZ9neKRj9MuOu/r6urvz\n21rkcsdKN0N5kFldrffSm70ojWxG7n7RZZ8eaKR3z4dsw7nYsW941W82pW88fX8fXT+vVJoq+vqc\n3H2545vaWim8w46k09ezeWme9FQZ1DvN7Gw7BzKNbno7BzeNmF9LujQzT1PXZvf8WWgp1C7SaG2g\nTZ39q+1X0b5K33C2x6bXI+k0IFinYzTU5jV32nG3HuorM3uVjtMrbaZJbk7IR54nLV0HwXVRvev+\n4HFIo7OBeN2FVTpGqxxq7rdl3f8B+cTIa+Lw1EIAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "d = graph.data.points([(1, 0.3),\n", " (2, -0.7),\n", " (3, -0.3),\n", " (4, 0.8),\n", " (5, 0.5)], x=1, y=2)\n", "\n", "g = graph.graphxy(width=8)\n", "g.plot(d, [graph.style.histogram()])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Styles can alter the way data is presented in arbitrary ways. Here the\n", "histogram style is used to generate a histogram. By default the histogram\n", "draws a box for each histogram value, but you can set the `step` parameter of\n", "the histogram style to use steps instead.\n", "\n", " In this basic use-case the histogram is calculated out of equal-spaced\n", "x-values automatically. You can also use errorbar like data in one graph\n", "dimension to generate histograms with different widths of the histogram boxes.\n", "\n", " Note that a histogram is very different from a bar graph in that it uses\n", "regular axes (like the default linear axes in this example) in both graph\n", "dimensions. Instead, bar graphs use a discrete axis.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/histogram.py0000644000076500000240000000053512515656701021276 0ustar andrestaff00000000000000from pyx import * d = graph.data.points([(1, 0.3), (2, -0.7), (3, -0.3), (4, 0.8), (5, 0.5)], x=1, y=2) g = graph.graphxy(width=8) g.plot(d, [graph.style.histogram()]) g.writeEPSfile("histogram") g.writePDFfile("histogram") g.writeSVGfile("histogram") PyX-0.14.1/examples/graphstyles/histogram.txt0000644000076500000240000000132012037340752021451 0ustar andrestaff00000000000000Creating a histogram Styles can alter the way data is presented in arbitrary ways. Here the histogram style is used to generate a histogram. ... By default the histogram draws a box for each histogram value, but you can set the `step` parameter of the histogram style to use steps instead. ! In this basic use-case the histogram is calculated out of equal-spaced x-values automatically. You can also use errorbar like data in one graph dimension to generate histograms with different widths of the histogram boxes. ! Note that a histogram is very different from a bar graph in that it uses regular axes (like the default linear axes in this example) in both graph dimensions. Instead, bar graphs use a discrete axis. PyX-0.14.1/examples/graphstyles/README0000644000076500000240000000024612037344757017612 0ustar andrestaff00000000000000Graph styles The component architecture of the graph system make graphs highly customizeable. A typical case are personalized graph styles as shown in this section. PyX-0.14.1/examples/graphstyles/usesymbol.ipynb0000644000076500000240000015507512615761603022025 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using the functionality of existing graph styles" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "# colors and symbols to use (alternatingly)\n", "colors = [color.rgb.red, color.rgb.green, color.rgb.blue, color.gray.black]\n", "symbols = [graph.style._diamondsymbol, graph.style._trianglesymbol, graph.style._circlesymbol]\n", "\n", "# create the graph styles to be used below\n", "symbol = graph.style.symbol(symbol=attr.changelist(symbols),\n", " symbolattrs=[deco.stroked.clear,\n", " attr.changelist([deco.filled([cc]) for cc in colors])])\n", "line = graph.style.line(lineattrs=[attr.changelist(colors),\n", " attr.changelist([style.linestyle.solid])])\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.linear(min=0, max=1))\n", "g.plot([graph.data.function(\"y(x) = x**%d\" % i, points=8) for i in range(1, 7)],\n", " styles=[line, symbol])\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example demonstrates how linestyles, symboltypes, colors, and other\n", "decorations can be changed in existing graph styles. We make use of the\n", "`changelist` feature as an argument when using a style. Generally, all items in\n", "the attribute lists can be iterable `changelists`. If the end of such a list is\n", "reached, the changelist restarts from its beginning (see e.g. the colors which\n", "are used several times).\n", "\n", "The `attr.stroked.clear' in the symbol deletes the default property of the\n", "symbols, which says to stroke the symbol outline.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/graphstyles/usesymbol.py0000644000076500000240000000157512515656701021330 0ustar andrestaff00000000000000from pyx import * # colors and symbols to use (alternatingly) colors = [color.rgb.red, color.rgb.green, color.rgb.blue, color.gray.black] symbols = [graph.style._diamondsymbol, graph.style._trianglesymbol, graph.style._circlesymbol] # create the graph styles to be used below symbol = graph.style.symbol(symbol=attr.changelist(symbols), symbolattrs=[deco.stroked.clear, attr.changelist([deco.filled([cc]) for cc in colors])]) line = graph.style.line(lineattrs=[attr.changelist(colors), attr.changelist([style.linestyle.solid])]) g = graph.graphxy(width=8, x=graph.axis.linear(min=0, max=1)) g.plot([graph.data.function("y(x) = x**%d" % i, points=8) for i in range(1, 7)], styles=[line, symbol]) g.writeEPSfile("usesymbol") g.writePDFfile("usesymbol") g.writeSVGfile("usesymbol") PyX-0.14.1/examples/graphstyles/usesymbol.txt0000644000076500000240000000111512037344757021511 0ustar andrestaff00000000000000Using the functionality of existing graph styles This example demonstrates how linestyles, symboltypes, colors, and other decorations can be changed in existing graph styles. ... We make use of the `changelist` feature as an argument when using a style. Generally, all items in the attribute lists can be iterable `changelists`. If the end of such a list is reached, the changelist restarts from its beginning (see e.g. the colors which are used several times). The `attr.stroked.clear' in the symbol deletes the default property of the symbols, which says to stroke the symbol outline. PyX-0.14.1/examples/hello.ipynb0000644000076500000240000002747312615761346016545 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Hello, world!" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFIAAAAPCAYAAAB3PJiyAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAJbSURBVFiF7Ze9bhNBFIW/E6VIgUS2owMZIdGB5IYKBWl7KsMb+BWcR0ga+vgV3EDNNlClIAUd\nEsIKHVVMQUN1KHxXmmxm4iU4yEQcyfLOzLk/c3fm+Fq2+Y8/xzaApBqok/kGmAPjlGx7v+Qo8dHY\nbrrjdSe+DqzKUdIYGABT23NJB8DC9mGXuwUQThpgEkaN7XkUrg5OsYiJDxL+ufEmYlWOtqexNoip\nIVDluFsZ43lnanG1NG8Meu3/QiH7QlIlaXhF22s/pdcU46S0cKVChlaMgUrSkaTscc/YjUN3kDRp\nn3vanUWsWtLb+Axi/EXS5LIYwfsQcxNJZ4VYI0kHwW81MkVW77czjrpvssqsD2y/iHHFUlsv1dBW\n2Fs7oImNNRk5OQfbU0kDlkLfSAIYhd1c0tT24YoYjaQGqGzvS7pwuiLGge37ydwooRSveU4jm/ST\nMa6BRbyxmoL4ZlCz7ARSLOh0BpdgBrSbGgB1Ii+z341R6CTGGfsUxat94UT2xOJvtzS2TyS1pwZg\nyrKwVa4duSbMS7fnKhrZ0GkXegp7w7J9SFEB09ClPj9cM+AovmeRR3pjijF6+CZ43RuWjoelPGUb\nSa+AZ8Bj4Bg4Bb7H+GE8fwPehd0jYDd4u7G2AzyJ9eP4Tsdfw24n+PfC70fgefDerNjobWAv4b0E\nXgM/E04pxt0kn0+ZuTTHdm87Ee801vfCX1sHaJv1KGSx0VyBB8DnNdk9Bd73sL0F/Mg8ryu3rv0d\nli+lhBPbC23Kf21JI9uz1czNxEYUUtLQdvEX8V/ARhTyJuAXXCgUSWuwh0sAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "c.text(0, 0, \"Hello, world!\")\n", "c.stroke(path.line(0, 0, 2, 0))\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As it is good practice to say \"Hello, world!\" in the first example, let's\n", "discuss how to do that in PyX.\n", "\n", "At first we import the PyX modules. Most PyX programs will start with a line\n", "like that. In order to produce some output we create a canvas instance `c`.\n", "Such an instance provides some useful methods to output some text at a certain\n", "position and for directly stroking a path, for which we use a `line` instance\n", "from the `path` module here. Once this is done, we write an EPS file and a PDF\n", "file containing all items inserted into the canvas instance. Since we did not\n", "pass a filename as argument to the write methods, the resulting files will just\n", "be named as the Python script - minus the extension, of course.\n", "\n", "This rather minimal example is quite useful for debugging your setup. In case\n", "of problems with your installation, you can add a `pyxinfo()` call immediately\n", "after the import. PyX will then write various information to `stderr`, which is\n", "quite helpful for yourself or when asking for help on the mailing list.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/hello.py0000644000076500000240000000023012520413527016020 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.text(0, 0, "Hello, world!") c.stroke(path.line(0, 0, 2, 0)) c.writeEPSfile() c.writePDFfile() c.writeSVGfile() PyX-0.14.1/examples/hello.txt0000644000076500000240000000202212255060660016211 0ustar andrestaff00000000000000Hello, world! As it is good practice to say "Hello, world!" in the first example, let's discuss how to do that in PyX. At first we import the PyX modules. Most PyX programs will start with a line like that. In order to produce some output we create a canvas instance `c`. Such an instance provides some useful methods to output some text at a certain position and for directly stroking a path, for which we use a `line` instance from the `path` module here. Once this is done, we write an EPS file and a PDF file containing all items inserted into the canvas instance. Since we did not pass a filename as argument to the write methods, the resulting files will just be named as the Python script - minus the extension, of course. This rather minimal example is quite useful for debugging your setup. In case of problems with your installation, you can add a `pyxinfo()` call immediately after the import. PyX will then write various information to `stderr`, which is quite helpful for yourself or when asking for help on the mailing list. PyX-0.14.1/examples/path/0000755000076500000240000000000012615763300015306 5ustar andrestaff00000000000000PyX-0.14.1/examples/path/addjoin.ipynb0000644000076500000240000001036112615761355017772 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Adding and joining paths" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAM0AAAAvCAYAAABAME7gAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAGGSURBVHic7d3RbcJAEEXRN5EboBa34JSQFtICKcE1pAVKgBZoIS1QwuQDEm2QEH4EMba4R9oP\nJCQPhisW8bHKTP0sSYOknPEa23krl6RxBvfjP2sovHfbGbz+m9eLAFiIBjB1ETE2j1dlk0zTn827\ny8xd2TR4Sp2kdfUQhuG0WkSDh2J7BpiIBjB1E55Tuf3pNf/fWZccJO0Lr3++jV2Sr9OqsNLxc3fR\n1Wgy8/Vu45giYqvlvvn74nuXVde+g01mflRcOCIGHf9HuojtGWAiGsBENICJaAAT0QAmogFMRAOY\niAYwEQ1gIhrARDSAiWgAE9EAJqIBTEQDmIgGMBENYCIawEQ0gIloABPRACaiAUxEA5iIBjARDWAi\nGsBENICJaAAT0QAmogFMV4/aWPiRDZUG7t3N1hEx22Mt+aYBTEQDmIgGMHWS2iPueklj0SxTfEra\nNI+rzmWUjrO055G+SXovmgUP1GXm7xsfEZWzTHFo562UmX8OUz2d1YgnwPYMMBENYPoGR1+AUfr2\n1LQAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "unit.set(wscale=10)\n", "\n", "c = canvas.canvas()\n", "\n", "c.stroke(path.line(0, 0, 1, 0) +\n", " path.line(1, 0, 1, 1) +\n", " path.line(1, 1, 0, 1) +\n", " path.line(0, 1, 0, 0))\n", "\n", "c.stroke(path.line(2, 0, 3, 0) <<\n", " path.line(3, 0, 3, 1) <<\n", " path.line(3, 1, 2, 1) <<\n", " path.line(2, 1, 2, 0))\n", "\n", "p = path.line(4, 0, 5, 0) << path.line(5, 0, 5, 1) << path.line(5, 1, 4, 1)\n", "p.append(path.closepath())\n", "c.stroke(p)\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result of this example looks the same as the [*pathitem*\n", "../drawing/pathitem.html] example from the *Basic drawing* section. However, we\n", "are using a different approach to construct the paths in this example: we add\n", "and join paths. When *adding* two paths, the resulting path just contains\n", "all the subpaths from the first and the second path as its subpaths. The\n", "*join* operation between two paths is similar but it combines the last\n", "subpath from the first path and continues it by the first subpath of the second\n", "path. Thus, *join* does not increase the number of subpaths like the *add*\n", "operation.\n", "\n", " A similar result in terms of the line thickness could be achieved by setting a\n", "different scale for the linewidth by\n", "\n", " unit.set(wscale=10)\n", "\n", "immediately after the import statement. The unit system of PyX is aware of\n", "several length types (unscaleable *true* coordinates `t`, regular *user* coordinates\n", "`u`, *visual* coordinates `v` for arrows, symbols and other small visual components,\n", "line *widths* `w` and the ``text`` sizes `x`). The length types can be scaled\n", "independent of each other (except for *true* coordinates, which cannot be scaled at all).\n", "\n", " Note that joining two paths might insert a line connecting the first and the\n", "second path. For example, we could skip the second line when constructing\n", "`rect2` in our example above without any change in the result.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/path/addjoin.py0000644000076500000240000000101212515656701017267 0ustar andrestaff00000000000000from pyx import * unit.set(wscale=10) c = canvas.canvas() c.stroke(path.line(0, 0, 1, 0) + path.line(1, 0, 1, 1) + path.line(1, 1, 0, 1) + path.line(0, 1, 0, 0)) c.stroke(path.line(2, 0, 3, 0) << path.line(3, 0, 3, 1) << path.line(3, 1, 2, 1) << path.line(2, 1, 2, 0)) p = path.line(4, 0, 5, 0) << path.line(5, 0, 5, 1) << path.line(5, 1, 4, 1) p.append(path.closepath()) c.stroke(p) c.writeEPSfile("addjoin") c.writePDFfile("addjoin") c.writeSVGfile("addjoin") PyX-0.14.1/examples/path/addjoin.txt0000644000076500000240000000262612037340745017467 0ustar andrestaff00000000000000Adding and joining paths The result of this example looks the same as the [''pathitem'' ../drawing/pathitem.html] example from the ''Basic drawing'' section. However, we are using a different approach to construct the paths in this example: we add and join paths. ... When ''adding'' two paths, the resulting path just contains all the subpaths from the first and the second path as its subpaths. The ''join'' operation between two paths is similar but it combines the last subpath from the first path and continues it by the first subpath of the second path. Thus, ''join'' does not increase the number of subpaths like the ''add'' operation. ! A similar result in terms of the line thickness could be achieved by setting a different scale for the linewidth by unit.set(wscale=10) immediately after the import statement. The unit system of PyX is aware of several length types (unscaleable ''true'' coordinates `t`, regular ''user'' coordinates `u`, ''visual'' coordinates `v` for arrows, symbols and other small visual components, line ''widths'' `w` and the ``text`` sizes `x`). The length types can be scaled independent of each other (except for ''true'' coordinates, which cannot be scaled at all). ! Note that joining two paths might insert a line connecting the first and the second path. For example, we could skip the second line when constructing `rect2` in our example above without any change in the result. PyX-0.14.1/examples/path/arclen.ipynb0000644000076500000240000000601112615761356017624 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Arc length of a path" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAF4AAAAqCAYAAAA6Yey5AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAJBSURBVGiB7ZvLbdtAFEXPDdIAW1A22VsliCXIJcglyCU4JVglmCVEJcjrrMwObC+8zOJlMc8Q\nw8QwKInkzJAHIPgBJA4OHi6HnBmZGTOnIekKqM3stetvv/bQnmyQtACaW+H7Kz/eA7fAY+f/nis+\nIGnDUeq76EfglaPYPYCZ7c++35TFSyqALbAmyK1w0afERxcmGTWezRuC8Aoozawesg2TEu9xsibE\nyA741ndlf0T24ltxUgM7M6vGbRV8GbsBfSJpDTwReiClmZUxSIeMK17SHaHKSzPr3N3rm+zEe9/7\ngRAry7Ey/DOyihqPlgNQmdl1rNIho4qPPVraJC8+lWhpk3TU+ItQEtHSJtmK95ehLYlES5skxbv0\nOxKVDglGTQ7SITHxuUiHhMSnnultksh4l74hoe7iZ0QvXtI9YVSozEU6RB41uUqHiMXnLB0iFZ+7\ndIhQvEt/H7jIUjpE9nB16ZjZ9dht6ZsoKl5SIekAYGY3Y7dnCEYX74PRPwlzWSYhHUYW3/isu5+S\ndBgx4yVtCZ8AbmIZ+R+SwcV7tNwTJhUth57BFQuDRk0jWmozm6x0GLDipx4tbXoXP0fL/+ktaiQt\nfMrFE3O0/MPFxUta+RvowS8tzez20vdJnYstTGgMVhTAD8KUi2y/tZzLWeIbU6A3hGUqu0ssU5kC\nnR6uklZ+uCJU9powwX/O7478VfHezy44rmpbNM7huBir9m2OkxORmSHpF/AdePbrb75/AX43zmfO\npzKz3aRX/Y3JHyzFCqvXriwrAAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1)\n", "p2 = path.line(0, 0, p1.arclen(), 0)\n", "c.stroke(p1)\n", "c.stroke(p2)\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example we use the `arclen` method of the path instance `p1` to get the\n", "arc length and create a straight line `p2` with the same arc length. \n", "\n", " While here we use the return value of the arc length as a parameter to a path\n", "constructor, you might be interested in what kind of object the return value of\n", "the `arclen` method call really is: It is a PyX length in true coordinates,\n", "since the path already analyses the PyX units and the return value thus needs\n", "to be fixed and can not be scaled anymore. Printing the result of the `arclen`\n", "method call of path `p1` would show you:\n", "\n", " (0.023110 t + 0.000000 u + 0.000000 v + 0.000000 w + 0.000000 x) m\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/path/arclen.py0000644000076500000240000000033312515656701017130 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1) p2 = path.line(0, 0, p1.arclen(), 0) c.stroke(p1) c.stroke(p2) c.writeEPSfile("arclen") c.writePDFfile("arclen") c.writeSVGfile("arclen") PyX-0.14.1/examples/path/arclen.txt0000644000076500000240000000125012037337703017313 0ustar andrestaff00000000000000Arc length of a path In this example we use the `arclen` method of the path instance `p1` to get the arc length and create a straight line `p2` with the same arc length. ... ! While here we use the return value of the arc length as a parameter to a path constructor, you might be interested in what kind of object the return value of the `arclen` method call really is: It is a PyX length in true coordinates, since the path already analyses the PyX units and the return value thus needs to be fixed and can not be scaled anymore. Printing the result of the `arclen` method call of path `p1` would show you: (0.023110 t + 0.000000 u + 0.000000 v + 0.000000 w + 0.000000 x) m PyX-0.14.1/examples/path/at.ipynb0000644000076500000240000001475612615761357017004 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Positions along a path" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMwAAAAyCAYAAAAQujSbAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAUYSURBVHic7Z2/buNGEIe/ORyQKoXqXBBA9waRgRRpUtCPIPdp5CJNOt8j2I8gvcABdpMmQACr\nSZfi1KW1cMgDHItUqSbFDs01Tcp/RIvc9XyAcbZoyntc/Ti/meXuiqriOM7jeDt0A3JBRBZAAUyA\nNbBS1XLYVjl9Ix5h9kNEJsA1MGsc2gDHLpq8eDN0AzLgjPtiwV47P3BbnBfGI8yeiMgNMO06rqpy\nwOY4L4C5CFS19BzmiYhIYd9W/3aKxTk89uGu8kkI1vjiIWvc0q8zQj46A7bACbDxCNOBJfFTartV\nACWhA7b2/RY4Bb7veJutqr5/4aY6xo58cgscqWppwigIfTuJfndD3ae3X6q6jd/II0xEdHdaEC7Y\nGrgASlXddJxTApcdb7l6iXY6nZzTnk9Ogd9E5B1BFGtC33T2axceYQARmRKS9zlwRQjh291n3Tl/\nQeisSfTyhap+6LWhzk5E5At3+6DJsaqu9/obr1kwIjInRJMptVCeVQa26HQb3r2cfHhEZOeHuY8C\nzKsTTIvtulJVt04ZICKfge86DveST76qcRhL+Koy8ImqHrtY0kdEZlbe/7zj13qxx69GMCJyDiwJ\nPvb0qcmeM05E5IxQGfugqj8Ryr+xHS6BU1W96uXv5W7JLKG/xErAnlvkgVnrJbVb2DaOFwD7JvlN\nso4wltR/IuQpJy6WPBCRGaFft6p61FbRVNV132KBjMdhzILNCRbM7VcmWL8uCFGld0E8RHaCaViw\nI48qeWAWrBogfj9Uv2ZlyaJQ7RYsI6xfbwjjW4NOmcgmwtho+xluwbLCxFJVwQYfAshCMNGjKS6W\njDCxXNJjWXhfkheMiyVPIrGcjKlfk8lhRGQuIjcioiLyRUSWIvIrLpbssJvgNSMTCyQycGmjuW3T\nff8DfhzbRXWez9gdw+gjjJUTzzoOf0U9Q85JnLGLBRIQDPVU0S5cMBmQglggg6Sfuw/aOQliYlkQ\nBpofPXFvCFIQTDXXuivKjPZu5DyM5afVI0yjv/mlkvT/BfzQcmijqkeHbo/TDyKyJFjuJMQCCeQw\ndlH/AX6mjiYlYRGD46Ha5exHimKBkUcYu6io6unQbXH6I1WxwEgjjIhMROQTuFhyI2WxwAgFEy3G\ntnGx5EXlGEhULDAywUSP569dLPkgItPYMaQqFhiRYBqLGfgCeJnQmCae/E1w8HGYxmIGox+4ch5H\n9EhTwchH75/CoBHmMYsZOOkRTfqakJFYYEDBuAVLF8tJCls/oXlsQZjHsko9X2nj4JbMLVi6RH03\nj15bE7b8KKlXzx/dPJa+OFiEsbGVc9yCpcwlkViMAviT0K+QmQVr8uKCsXVvl4RVPypP6xYsMSwv\n6ZpK8Q74mKMFa3LPkkVbl93bfekpmJedE6zXigHXknJ6oRlZmgxecT0Et//JaNGBafTamuBHH/VB\nb9lKYjWW1T6c52P9+s3Q7RgDb+F2tciqDBhTEETU+lSwnVd9zah38Dr2/CRdos2hqr5dAH8A/wJf\nd5z2Km6MVYRZ0D1BqxCRX4Bv7ef4QlaTu6qNUt12JYJZ73jXtHjX4LhfS6yaaTZ72fJ2Fzkn+jGi\nqojINbvnxv8O/E10IV0Y6WFVyjPu7hR8Z+fgh5yBCa3KTUuC7T74ouBDUQmmupBd7L2ZpjM8IjLx\nG91+VGXlXWLYuljywMWyP2/gdpemi5bjJWELNMdxaExRNn9aUCd+K692OU7NqOf0O87Y+B8Hp2pC\nM/hItAAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "def mark(x, y):\n", " return path.circle(x, y, 0.1)\n", "\n", "c = canvas.canvas()\n", "\n", "p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1)\n", "c.stroke(p1)\n", "c.fill(mark(*p1.atbegin()))\n", "c.fill(mark(*p1.at(0.5*p1.arclen())))\n", "c.fill(mark(*p1.atend()))\n", "\n", "p2 = path.curve(3, 0, 4, 0, 4, 1, 5, 1)\n", "c.stroke(p2)\n", "c.fill(mark(*p2.at(p2.begin()+0.5)))\n", "c.fill(mark(*p2.at(p2.end()-0.5)))\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several methods to access certain positions at a path. At first there\n", "are `atbegin` and `atend` methods, which return a coordinate tuple. \n", "\n", " In this example, we have defined a small helper function `mark` to which we\n", "can pass the return value of the `at` methods. We do this by transforming\n", "the sequence in to positional argument of the function call. This Python\n", "language feature is available by the `*` syntax in the call.\n", "\n", " The coordinates returned by the `at` methods are PyX lengths in the\n", "unscaleable true units similar to the return value of the `arclen` method.\n", "\n", "For the left path `p1`, we also show how to use the `at` method,\n", "which can be used to get the coordinates of a certain point of the path\n", "depending on the arc length along the path.\n", "\n", "A different use of the `at` function is shown for the right path `p2`: It is\n", "also possible to pass parametrization instances of the path to the `at` method.\n", "In the shown case we first fetch such parametrization instances for the\n", "beginning and the end of the path by the `begin` and `end` methods. Note that\n", "the `atbegin` method is equal to call `at` with the result value of the `begin`\n", "method (except for optimizations: atbegin is faster than the two calls).\n", "Similar `atend` could be rewritten using the result value of `end`. As shown in\n", "the example you can use the parametrization instances to add and substract arc\n", "lengths from selected point.\n", "\n", " The `at` method of a path instance can not only handle a single value, in\n", "which case it returns a single result tuple. You can also pass a list to the\n", "method and the return value will contain a list of coordinate tuples. You\n", "should bear in mind that passing a list is much more efficient than multiple\n", "calls of the method performing single conversions at each time.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/path/at.py0000644000076500000240000000065212515656701016274 0ustar andrestaff00000000000000from pyx import * def mark(x, y): return path.circle(x, y, 0.1) c = canvas.canvas() p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1) c.stroke(p1) c.fill(mark(*p1.atbegin())) c.fill(mark(*p1.at(0.5*p1.arclen()))) c.fill(mark(*p1.atend())) p2 = path.curve(3, 0, 4, 0, 4, 1, 5, 1) c.stroke(p2) c.fill(mark(*p2.at(p2.begin()+0.5))) c.fill(mark(*p2.at(p2.end()-0.5))) c.writeEPSfile("at") c.writePDFfile("at") c.writeSVGfile("at") PyX-0.14.1/examples/path/at.txt0000644000076500000240000000342712037340745016463 0ustar andrestaff00000000000000Positions along a path There are several methods to access certain positions at a path. At first there are `atbegin` and `atend` methods, which return a coordinate tuple. ... ! In this example, we have defined a small helper function `mark` to which we can pass the return value of the `at...` methods. We do this by transforming the sequence in to positional argument of the function call. This Python language feature is available by the `*` syntax in the call. ! The coordinates returned by the `at...` methods are PyX lengths in the unscaleable true units similar to the return value of the `arclen` method. For the left path `p1`, we also show how to use the `at` method, which can be used to get the coordinates of a certain point of the path depending on the arc length along the path. A different use of the `at` function is shown for the right path `p2`: It is also possible to pass parametrization instances of the path to the `at` method. In the shown case we first fetch such parametrization instances for the beginning and the end of the path by the `begin` and `end` methods. Note that the `atbegin` method is equal to call `at` with the result value of the `begin` method (except for optimizations: atbegin is faster than the two calls). Similar `atend` could be rewritten using the result value of `end`. As shown in the example you can use the parametrization instances to add and substract arc lengths from selected point. ! The `at` method of a path instance can not only handle a single value, in which case it returns a single result tuple. You can also pass a list to the method and the return value will contain a list of coordinate tuples. You should bear in mind that passing a list is much more efficient than multiple calls of the method performing single conversions at each time. PyX-0.14.1/examples/path/intersect.ipynb0000644000076500000240000001145012615761361020357 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Intersection points between paths" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFIAAAAqCAYAAAAgXQw3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAASASURBVGiB3ZuxiyRFFIe/EkUMDCoRAz2kRREM+1gwM+gzVZC+VKNZjAwMejPTFg7MDmYTMR3/\nhBnMPXpSBaVHuEDBoIdD8TgDfwZVPdN7u+zOTPebufFB0ezSU/3q6/eqXtV77STxLIvDpcBCaHlo\nXS6JC7ohLZ8/tC5didBSIInXDJgBicMBzIFF/N/cHK5zSdSlbb6jm496nAFzd2iLdLiCAKyF1sKa\nC80793nWcNvBEO8/E1r0U8SNOv224ObAMl6J+oE0u/R7SQdpiAQxjS3dsQ+PKBA1oti6D/CCUlAL\nJoJckAn89rocBmKBaBClwUtJQDloChKoBl18DqSCsaCJ16S/DvsF6ONgq12t8Ib+S568+BdFqQix\n26aCkWAaLbDYxfIODhKRD2mFVz4DeU5+eESVimkmfCNPo5JCNYl+5Y0fBbnN+PYDMYnz2OBW+BTI\nbGWB45HeKT9Ug9eYkRJqgcZ2Y9wPyOlOi0EPkF/6z/V6/YLeyu533Xti9ezneoUMm0QVIbxB6Cvr\nZwGLhAUVt3l3+RvL0wm/jO+BX4Wb8+t+3EuMLbF16d6r4kYN8r956XFBZ7EpCzHJBapsx2oLci8u\nHSG28WAKKmPYI3wj/njlEQ9vfXqUIBElYroHgImgigH1leEMIosRw2Dhzj5BNuYuHQLrRtxs9fHF\nmnmHyaGFwyXAUn33v9c+xI2AAriDtMkiMifs003EatVOsVwhA8QSuLshRKI+6Y137SiWIG2scQ1x\nU0sEIHpHYqITtiAvHzX1lR0hdmTucCbufTyuvf2ceJWYuffgIDsLzXCn1wHiCLjdAyIcE0iGtkbn\nxgSId1Dvl3NUIIeTADFlGIgQ8iwmeR4LkDOGeOvDQwTDsGxwkO3cGJNVu4kNRAjhj0lYZuXau89F\nAaJneIhwTBYZZcEu27EAEaS7BhABMnFFKnUAsQI5Y5tdhHMe5yoApFMLhWLxgdm29fCu7ZwHpsDc\nCmKU4wPZWXCuhxlqZypgZgwRwlRjdxpleB6ZIypplZS6mEEMeeXGKj16hS71UR7sSoIHJz9x74vH\nnSxefcKDj+JpdjVEhcMGEH08ZLZNBZt1jAp8Ixov0kogpVSqSfQzb39jDbADcmJZlLAPkA1I5BNR\npSoo1eCVMzFN1D8FcTW9HCVIUNK6s6fRe5PX9En5alvtEOpw7CHuxaXbZhX+LBMWlJxR8yYfnH7M\nt6MnLHK77ENX4vZ0ApyLXsdum8vgbyfUF47/5OV/Soq1FaaVqJOQrL/18GtDS8ziCm0+L1587nAA\nR3ElrgWjjO/fX82TbfONuP/Z7/zrlohsYIA+plzrofu2B7mueG1iSHNhAHGuLGPR5xRUgHzXaoaI\n7Ybub5e2XQ25WyWOMsIJTQ6cA+douxx2nMeK2McZoWZ82z7a2vMcOJXRgcRGulwAGbZsbdF7W8Hf\n/g3r4vRFbN/R85QmwshZF8HPu62FG+/rfvHQ3jsjLCoH/XwkgHRuQhhM+0a7VfxL+iWctlPoMrCU\n9ZcFlwA/K3Lwz0P+L/IfoB36FegyxBkAAAAASUVORK5CYII=\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1)\n", "p2 = path.circle(1, 0.5, 0.5)\n", "\n", "(a1, a2), (b1, b2) = p1.intersect(p2)\n", "\n", "x1, y1 = p1.at(a1)\n", "x2, y2 = p1.at(a2)\n", "\n", "c = canvas.canvas()\n", "c.fill(path.circle(x1, y1, 0.1), [color.rgb.blue])\n", "c.fill(path.circle(x2, y2, 0.1), [color.rgb.blue])\n", "c.stroke(p1, [color.rgb.red])\n", "c.stroke(p2, [color.rgb.green])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `intersect` method of a path allows for the calculation of intersection\n", "points between this path and the second path passed to the `intersect` method. \n", "The return value of the intersect method is a tuple of two lists, where each\n", "list contains parametrization instances for the intersection points. The first\n", "list are the parameters for the path the `intersect` method was called for. The\n", "second list are the parameter values for the path passed to the `intersect`\n", "method. Thus we can calculate the first intersection point `x1, y1` by\n", "\n", " x1, y1 = p1.at(a1)\n", "\n", "as done in the example or alternatively by\n", "\n", " x1, y1 = p2.at(b1)\n", "\n", " When several intersections between two paths occur, the order of the\n", "intersection points is defined by the order in which the points are passed when\n", "walking along the first path.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/path/intersect.py0000644000076500000240000000066412515656701017673 0ustar andrestaff00000000000000from pyx import * p1 = path.curve(0, 0, 1, 0, 1, 1, 2, 1) p2 = path.circle(1, 0.5, 0.5) (a1, a2), (b1, b2) = p1.intersect(p2) x1, y1 = p1.at(a1) x2, y2 = p1.at(a2) c = canvas.canvas() c.fill(path.circle(x1, y1, 0.1), [color.rgb.blue]) c.fill(path.circle(x2, y2, 0.1), [color.rgb.blue]) c.stroke(p1, [color.rgb.red]) c.stroke(p2, [color.rgb.green]) c.writeEPSfile("intersect") c.writePDFfile("intersect") c.writeSVGfile("intersect") PyX-0.14.1/examples/path/intersect.txt0000644000076500000240000000152312037337703020052 0ustar andrestaff00000000000000Intersection points between paths The `intersect` method of a path allows for the calculation of intersection points between this path and the second path passed to the `intersect` method. ... The return value of the intersect method is a tuple of two lists, where each list contains parametrization instances for the intersection points. The first list are the parameters for the path the `intersect` method was called for. The second list are the parameter values for the path passed to the `intersect` method. Thus we can calculate the first intersection point `x1, y1` by x1, y1 = p1.at(a1) as done in the example or alternatively by x1, y1 = p2.at(b1) ! When several intersections between two paths occur, the order of the intersection points is defined by the order in which the points are passed when walking along the first path. PyX-0.14.1/examples/path/README0000644000076500000240000000031512037344755016174 0ustar andrestaff00000000000000Path features In this section we demonstrate the capabilities of paths in PyX. The goal is to give an overview of those operations that are intrinsic to paths and do not affect their drawing on a canvas. PyX-0.14.1/examples/path/split.ipynb0000644000076500000240000001031312615761360017506 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Splitting paths" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFIAAAAqCAYAAAAgXQw3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAAL4SURBVGiB7ZpNaxNBGMd/j+ataRCGKj0oRXITjzkU9CBK/AJCes6p/QgVEbx4SD+ASHqpJy85\n1JuHFqkH8dLiG+ItaBEpaFkPSUzS6uNhk5JKsDTZzc6k/Ydh97I7M7/8Z+eZmUdUlVMNr1jUDXBC\nIvnOXfdqAK9zv4xqVU4d2ZFIFijgQ+oFBVA9KKrVfo+fOtJ3WwEfXAXVrUFec6JACmKAggoVfHh5\nYB3VhaFfrqonoqAU4m2+oOjD+6wq5IN9vwWdDBmgmdlmA/V/F7/xGMUEX48FnQ2rXP3IvXSdZgfi\nJkouvD/Mgg4H3ymyl77yDkXlDx5KKfw6Leh4wBAXJxr86rhwDSU7inrPDD1bWSJBchMteQ+U9hK0\ngbuK3lb6x32BK2oHBeTCUncySTVZDWMyOao4v7IRpAzMp1o0mkmKilaiaIfTAXmmISukKWZqfKpl\nuK6od/RT4chZR2YaslJPU4zt83Y/xq0oIYKDjhTEGI/ndcOsLRDBMUcKYjI1XtUyXEnssdGOc8cG\niIA74U8vxMkGT1pxvWkLRHDEkb0QgWUlgN2agGU9SEFysd+82D/LOSyFCJYP7X8gLtkKESyetQXJ\nJdu8bCWYBBYUXY66Tf+TlY50DSJYCFKQeWDTJYhgGcgOxHKyTR2YcwUiWPSN7IXYSnBDGew0LypZ\n4UjXIYIFjuxug7kMESJ2ZKYhK8D8+R9UXYYIEa1sBMkZj0eeYTbV4kMzyQ2b1s2DaOSOFKQEbHqG\nWaAyDhBhhCAFycf35Q2wmNijhh/ezI0DRCD8wy8U03s4deE7T6M4nHL68EuQPFAGslO7/NydoqDo\nemgVRqhQhrYgphPWrAHZa695tjtFdlwhAsEP7ZltiqkmdRSd3uFzmPk2NpXgHCmSRaQ8WeNBM0ka\nWNqZ1svqcGx4HA3/jTyc8bokigHQUaWKWKLjg/RzrbslB2yh7uzShKX+IH2XGXxQ/bQOeAyYbz2O\n8kGKLHI4m3/r4KpjEjCHLOtPEV3RXzP2fBzz7m+OAAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "p = path.curve(0, 0, 1, 0, 1, 1, 2, 1)\n", "p1, p2, p3 = p.split([0.5, p.end()-0.5])\n", "\n", "c = canvas.canvas()\n", "c.stroke(p, [style.linewidth.Thin, color.rgb.red])\n", "c.stroke(p2, [style.linewidth.Thick, color.rgb.green])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example we use the `split` method of a path to split it into several\n", "paths. Similar to the `at` method you can pass a list of numbers to the split\n", "method (or PyX length instances) to specify the splitting point by the arc\n", "length or you can use parametrization instances like the one returned by\n", "the `end` method, where you can substract a length to conventiently express a\n", "certain location measured from the end of the path.\n", "\n", "For a single splitting point, you can also pass the parameter directly instead\n", "of warpping this single value into a list. Note, however, that the return value\n", "of the `split` method is always a list; splitting a non-closed path at one\n", "point still yields two segments.\n", "\n", " When splitting at the beginning or the end of the path, one segment may\n", "be empty. Still PyX returns a corresponding path of length 0.\n", "\n", " When splitting at non-closed subpaths the result of the split method\n", "will be a list containing one path more than the number of splitting\n", "points. However, for a closed subpath a splitting at a single point\n", "will open the subpath but return a single path only. Consider a circle\n", "which you split at a single value: The result will still be a circle,\n", "but the path will not be closed anymore.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/path/split.py0000644000076500000240000000045212515656701017021 0ustar andrestaff00000000000000from pyx import * p = path.curve(0, 0, 1, 0, 1, 1, 2, 1) p1, p2, p3 = p.split([0.5, p.end()-0.5]) c = canvas.canvas() c.stroke(p, [style.linewidth.Thin, color.rgb.red]) c.stroke(p2, [style.linewidth.Thick, color.rgb.green]) c.writeEPSfile("split") c.writePDFfile("split") c.writeSVGfile("split") PyX-0.14.1/examples/path/split.txt0000644000076500000240000000234212037337703017205 0ustar andrestaff00000000000000Splitting paths In this example we use the `split` method of a path to split it into several paths. Similar to the `at` method you can pass a list of numbers to the split method (or PyX length instances) to specify the splitting point by the arc length ... or you can use parametrization instances like the one returned by the `end` method, where you can substract a length to conventiently express a certain location measured from the end of the path. For a single splitting point, you can also pass the parameter directly instead of warpping this single value into a list. Note, however, that the return value of the `split` method is always a list; splitting a non-closed path at one point still yields two segments. ! When splitting at the beginning or the end of the path, one segment may be empty. Still PyX returns a corresponding path of length 0. ! When splitting at non-closed subpaths the result of the split method will be a list containing one path more than the number of splitting points. However, for a closed subpath a splitting at a single point will open the subpath but return a single path only. Consider a circle which you split at a single value: The result will still be a circle, but the path will not be closed anymore. PyX-0.14.1/examples/README0000644000076500000240000000172212037344757015245 0ustar andrestaff00000000000000PyX examples The following examples are part of the PyX release __version__. For each PyX example the source code and the corresponding output are shown. You can take a guided tour through all examples by the ''prev'' and ''next'' links on the upper right. All the examples and their descriptions are included in the source distribution of PyX in the examples subdirectory. ! Some paragraphs (like the one you're just reading) are marked with a ''dangerous bend sign''. Some people will recognize this classification from the TeXbook by D.E. Knuth and we use it at the PyX example pages for the same purpose. The bend marks parts of the description, which require some experiences with PyX. On the other hand, those parts can savely be ignored by PyX beginners. !! There are even some paragraphs marked as ''doubly dangerous''. The explanations given in those paragraphs provide some deeper insights of what's really going on, but are not important for the average PyX user. PyX-0.14.1/examples/splitgraphs/0000755000076500000240000000000012615763300016712 5ustar andrestaff00000000000000PyX-0.14.1/examples/splitgraphs/minimal.ipynb0000644000076500000240000011037612615761656021427 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Minimal split-axis example" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n9rHirgZvOwAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.split())\n", "g.plot(graph.data.points([((0, 0.1), 0.1),\n", " ((0, 0.5), 0.2),\n", " ((0, 0.9), 0.3),\n", " ((1, 101), 0.7),\n", " ((1, 105), 0.8),\n", " ((1, 109), 0.9)], x=1, y=2))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This minimal example creates a split-axis by two simple modifications. \n", "First a splitaxis instance is passed to the graph constructor and secondly the\n", "data provided for this axis is modified to contain a tuple of two items. The\n", "first item is used as a dictionary key to identify the subaxis, to which the\n", "presented data belongs to. The second item in the tuple is used as the value on\n", "this subaxis.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/splitgraphs/minimal.py0000644000076500000240000000064012515656701020717 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.split()) g.plot(graph.data.points([((0, 0.1), 0.1), ((0, 0.5), 0.2), ((0, 0.9), 0.3), ((1, 101), 0.7), ((1, 105), 0.8), ((1, 109), 0.9)], x=1, y=2)) g.writeEPSfile("minimal") g.writePDFfile("minimal") g.writeSVGfile("minimal") PyX-0.14.1/examples/splitgraphs/minimal.txt0000644000076500000240000000065612037340745021112 0ustar andrestaff00000000000000Minimal split-axis example This minimal example creates a split-axis by two simple modifications. ... First a splitaxis instance is passed to the graph constructor and secondly the data provided for this axis is modified to contain a tuple of two items. The first item is used as a dictionary key to identify the subaxis, to which the presented data belongs to. The second item in the tuple is used as the value on this subaxis. PyX-0.14.1/examples/splitgraphs/README0000644000076500000240000000123312037344755017600 0ustar andrestaff00000000000000Split axes Split axes can be used to build axes containing axis breaks. While split axes work exactly like bar axes (they even share the same code except for the painter), their usage differs. A split axes has a tuple as its data value. The first value of the tuple identifies a sub-axis (for example by a unique integer) and the second is the value to be passed to the sub-axis. (For a bar axis, internally this is basically the same, but there the styles take care of the wrapping of the data into those tuples.) !! Note: Currently the graph styles are not aware of axis breaks. A generic notification mechanism for graph styles should be added at a later point. PyX-0.14.1/examples/splitgraphs/splitatvalue.ipynb0000644000076500000240000012411712615761661022510 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Split axis at certain values" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "pf = graph.data.paramfunction\n", "\n", "g = graph.graphxy(width=8, x=graph.axis.split())\n", "g.plot(pf(\"k\", -1, 1,\n", " \"x, y = splitatvalue(k, -0.9, 0.9), k**100\",\n", " points=1000))\n", "g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A typical use-case for a split axis is to use some special positions on the\n", "axis to mark the axis breaks. For that the `splitatvalue` function is\n", "available in all places, where expressions are evaluated in the `graph.data`\n", "classes. Here we create a special parametric function where split positions for\n", "the x axis are added by the `splitatvalue` function and the y function is a\n", "simple polynomial of high order. Note that you can set several split positions\n", "by additional parameters of the `splitatvalue` function. In that case\n", "the `splitatvalue` function marks odd regions to be a \"None\", by which those\n", "data values are ignored by the `splitaxis` instance.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/splitgraphs/splitatvalue.py0000644000076500000240000000044512515656701022011 0ustar andrestaff00000000000000from pyx import * pf = graph.data.paramfunction g = graph.graphxy(width=8, x=graph.axis.split()) g.plot(pf("k", -1, 1, "x, y = splitatvalue(k, -0.9, 0.9), k**100", points=1000)) g.writeEPSfile("splitatvalue") g.writePDFfile("splitatvalue") g.writeSVGfile("splitatvalue") PyX-0.14.1/examples/splitgraphs/splitatvalue.txt0000644000076500000240000000126412037340745022175 0ustar andrestaff00000000000000Split axis at certain values A typical use-case for a split axis is to use some special positions on the axis to mark the axis breaks. ... For that the `splitatvalue` function is available in all places, where expressions are evaluated in the `graph.data` classes. Here we create a special parametric function where split positions for the x axis are added by the `splitatvalue` function and the y function is a simple polynomial of high order. Note that you can set several split positions by additional parameters of the `splitatvalue` function. In that case the `splitatvalue` function marks odd regions to be a "None", by which those data values are ignored by the `splitaxis` instance. PyX-0.14.1/examples/text/0000755000076500000240000000000012615763300015336 5ustar andrestaff00000000000000PyX-0.14.1/examples/text/color.ipynb0000644000076500000240000007730712615761410017535 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using the same color in PyX and in LaTeX" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "unit.set(uscale=2, xscale=2)\n", "\n", "col = color.cmyk.PineGreen\n", "\n", "text.set(text.LatexRunner)\n", "text.preamble(r\"\\usepackage{color}\")\n", "text.preamble(r\"\\definecolor{COL}{cmyk}{%g,%g,%g,%g}\" % (col.c, col.m, col.y, col.k))\n", "\n", "c = canvas.canvas()\n", "c.text(0, 0, r\"\\textcolor{COL}{Text} and outline have the same color\")\n", "c.stroke(path.rect(-0.2, -0.2, 6.2, 0.6), [col])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " This example shows three different methods how to use a color defined in PyX\n", "also in LaTeX. In the example code, we first define a cmyk color `col`,\n", "which is then used to define a color `COL` in LaTeX. The latter is then used in\n", "a LaTeX expression.\n", "\n", " The same behavior can be achieved by two different methods in `c.text`,\n", "\n", " r\"\\textcolor[named]{PineGreen}{Text} and outline \"\n", " r\"\\textcolor[pyx]{color.cmyk.PineGreen}{Text} and outline \"\n", "\n", "They are not as elegant as the above shown, since we need to insert the color\n", "definition `PineGreen` explicitly. The first alternative makes use of the\n", "`named` color model of color.sty. All colors of this model are predefined also\n", "in PyX. The other alternative allows to use PyX colors directly.\n", "\n", " Note that no graphics driver has been used for the color.sty LaTeX package.\n", "PyX performs a hack to enforce the use of its own LaTeX driver file pyx.def. In\n", "case that you have installed the three files `pyx.def`, `color.cfg`, and\n", "`graphics.cfg` from the PyX distribution somewhere in the LaTeX search path, it is\n", "possible to use\n", "\n", " text.set(mode=\"latex\", pyxgraphics=0)\n", " text.preamble(r\"\\usepackage[pyx]{color}\")\n", "\n", "which is the more aesthetic variant.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/color.py0000644000076500000240000000066712515656701017044 0ustar andrestaff00000000000000from pyx import * unit.set(uscale=2, xscale=2) col = color.cmyk.PineGreen text.set(text.LatexRunner) text.preamble(r"\usepackage{color}") text.preamble(r"\definecolor{COL}{cmyk}{%g,%g,%g,%g}" % (col.c, col.m, col.y, col.k)) c = canvas.canvas() c.text(0, 0, r"\textcolor{COL}{Text} and outline have the same color") c.stroke(path.rect(-0.2, -0.2, 6.2, 0.6), [col]) c.writeEPSfile("color") c.writePDFfile("color") c.writeSVGfile("color") PyX-0.14.1/examples/text/color.txt0000644000076500000240000000234512037344751017224 0ustar andrestaff00000000000000Using the same color in PyX and in LaTeX ! This example shows three different methods how to use a color defined in PyX also in LaTeX.... In the example code, we first define a cmyk color `col`, which is then used to define a color `COL` in LaTeX. The latter is then used in a LaTeX expression. ! The same behavior can be achieved by two different methods in `c.text`, r"\textcolor[named]{PineGreen}{Text} and outline ..." r"\textcolor[pyx]{color.cmyk.PineGreen}{Text} and outline ..." They are not as elegant as the above shown, since we need to insert the color definition `PineGreen` explicitly. The first alternative makes use of the `named` color model of color.sty. All colors of this model are predefined also in PyX. The other alternative allows to use PyX colors directly. !! Note that no graphics driver has been used for the color.sty LaTeX package. PyX performs a hack to enforce the use of its own LaTeX driver file pyx.def. In case that you have installed the three files `pyx.def`, `color.cfg`, and `graphics.cfg` from the PyX distribution somewhere in the LaTeX search path, it is possible to use text.set(mode="latex", pyxgraphics=0) text.preamble(r"\usepackage[pyx]{color}") which is the more aesthetic variant. PyX-0.14.1/examples/text/font.ipynb0000644000076500000240000002707712615761401017364 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Customize fonts" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " L\n", " A\n", " T\n", " E\n", " X\n", " d\n", " o\n", " e\n", " s\n", " n\n", " \n", " t\n", " n\n", " e\n", " e\n", " d\n", " t\n", " o\n", " l\n", " o\n", " o\n", " k\n", " l\n", " i\n", " k\n", " e\n", " L\n", " A\n", " T\n", " E\n", " X\n", " a\n", " l\n", " l\n", " t\n", " h\n", " e\n", " t\n", " i\n", " m\n", " e\n", " .\n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "text.set(text.LatexRunner)\n", "text.preamble(r\"\\usepackage{times}\")\n", "\n", "c = canvas.canvas()\n", "c.text(0, 0, r\"\\LaTeX{} doesn't need to look like \\LaTeX{} all the time.\")\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In LaTeX, there are nice packages allowing to switch fonts. Hence, for a simple\n", "example we change the mode of the default texrunner instance to LaTeX and use\n", "the `preamble` method to load the `times` package. \n", "\n", " In general, it is also favourable to employ LaTeX when using your own Type1\n", "fonts. Still you can also use different fonts in plain TeX if you are familiar\n", "with the topic. However, LaTeX's NFSS (new font selection scheme) is preferable\n", "for the ordinary user and has great advantages in daily use. All you need to do\n", "is to integrate the fonts into your LaTeX system. PyX and LaTeX both require\n", "a font map file containing the specification and the names of the font files.\n", "Probably you will need to create your own LaTeX font adaptation, where the\n", "`fontinst` utility is of great help. Try your favorite search engine on that\n", "topic to learn more about it and find some step by step guides. As soon as\n", "your LaTeX system is configured to use your fonts, they will also be available\n", "to PyX.\n", "\n", " The `times` package loads the Times New Roman and the Helvetica fonts, which\n", "are part of any valid Acrobat Reader and Ghostscript installation. These fonts\n", "are therefore not explicitly included in the output of PyX. This behaviour is\n", "<> from LaTeX, where these standard 35 fonts usually are not contained in the\n", "standard font-map file `psfonts.map`.\n", "If you say in the PyX configuration file\n", "\n", " psfontmaps = psfonts.map download35.map\n", " pdffontmaps = pdftex.map download35.map\n", "\n", "then PyX finds the corresponding fonts in the map-file and includes the fonts\n", "in the output EPS and PDF files.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/font.py0000644000076500000240000000037012516154337016662 0ustar andrestaff00000000000000from pyx import * text.set(text.LatexRunner) text.preamble(r"\usepackage{times}") c = canvas.canvas() c.text(0, 0, r"\LaTeX{} doesn't need to look like \LaTeX{} all the time.") c.writeEPSfile("font") c.writePDFfile("font") c.writeSVGfile("font") PyX-0.14.1/examples/text/font.txt0000644000076500000240000000311612037344751017051 0ustar andrestaff00000000000000Customize fonts In LaTeX, there are nice packages allowing to switch fonts. Hence, for a simple example we change the mode of the default texrunner instance to LaTeX and use the `preamble` method to load the `times` package. ... !! In general, it is also favourable to employ LaTeX when using your own Type1 fonts. Still you can also use different fonts in plain TeX if you are familiar with the topic. However, LaTeX's NFSS (new font selection scheme) is preferable for the ordinary user and has great advantages in daily use. All you need to do is to integrate the fonts into your LaTeX system. PyX and LaTeX both require a font map file containing the specification and the names of the font files. Probably you will need to create your own LaTeX font adaptation, where the `fontinst` utility is of great help. Try your favorite search engine on that topic to learn more about it and find some step by step guides. As soon as your LaTeX system is configured to use your fonts, they will also be available to PyX. !! The `times` package loads the Times New Roman and the Helvetica fonts, which are part of any valid Acrobat Reader and Ghostscript installation. These fonts are therefore not explicitly included in the output of PyX. This behaviour is <> from LaTeX, where these standard 35 fonts usually are not contained in the standard font-map file `psfonts.map`. If you say in the PyX configuration file psfontmaps = psfonts.map download35.map pdffontmaps = pdftex.map download35.map then PyX finds the corresponding fonts in the map-file and includes the fonts in the output EPS and PDF files. PyX-0.14.1/examples/text/halign.ipynb0000644000076500000240000046470712615761372017674 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Horizontal alignment" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "c.stroke(path.line(-5, 0, -5, 5))\n", "c.stroke(path.line(0, 0, 0, 5))\n", "c.stroke(path.line(5, 0, 5, 5))\n", "\n", "c.text(-5, 5, r\"boxleft\", [text.halign.boxleft])\n", "c.text(0, 5, r\"boxcenter\", [text.halign.boxcenter])\n", "c.text(5, 5, r\"boxright\", [text.halign.boxright])\n", "\n", "c.text(0, 4, r\"boxcenter and flushleft\",\n", " [text.parbox(3), text.halign.boxcenter, text.halign.flushleft])\n", "c.text(0, 3, r\"boxcenter and flushcenter\",\n", " [text.parbox(3), text.halign.boxcenter, text.halign.flushcenter])\n", "c.text(0, 2, r\"boxcenter and flushright\",\n", " [text.parbox(3), text.halign.boxcenter, text.halign.flushright])\n", "\n", "c.text(-5, 0, r\"left: boxleft and flushleft\",\n", " [text.parbox(3), text.halign.left])\n", "c.text(0, 0, r\"center: boxcenter and flushcenter\",\n", " [text.parbox(3), text.halign.center])\n", "c.text(5, 0, r\"right: boxright and flushright\",\n", " [text.parbox(3), text.halign.right])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The example shows the result of the different text attributes for horizontal\n", "alignment. We first need to emphasize, that PyX distinguishes between the\n", "alignment of the text box and the alignment of the material within the text\n", "box. The first line in the output shows the effect of the box alignment\n", "created by `boxleft`, `boxcenter` and `boxright` leading to left, center, and right\n", "alignment of the text box with respect to the dotted lines. \n", "\n", "The middle part shows the examples for centering a box, but aligning the\n", "content differently inside the box, namely at the left box boundary by\n", "`flushleft`, at the center by `flushcenter` and at the right box boundary by\n", "`flushright`. Note, that such an alignment of material is available only\n", "when you create a parbox in TeX. This is easily done by means of the `parbox`\n", "attribute, where you have to specify the width of the box.\n", "\n", "At the bottom, you can see combinations of `boxleft` and `flushleft`, `boxcenter` and\n", "`flushcenter`, and `boxright` and `boxcenter` in action. These combinations are\n", "available by the attributes `left`, `center` and `right` to shortcut the setting of\n", "both corresponding attributes. You can use these shortcuts for box alignment as\n", "well, when you do not create a parbox.\n", "\n", " Note that the alignment features are implemented in such a way, that they work\n", "in both, TeX and LaTeX mode. Furthermore, you can always influence the\n", "alignment of the box contents by appropriate TeX and LaTeX commands as well.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/halign.py0000644000076500000240000000173312515656701017163 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.stroke(path.line(-5, 0, -5, 5)) c.stroke(path.line(0, 0, 0, 5)) c.stroke(path.line(5, 0, 5, 5)) c.text(-5, 5, r"boxleft", [text.halign.boxleft]) c.text(0, 5, r"boxcenter", [text.halign.boxcenter]) c.text(5, 5, r"boxright", [text.halign.boxright]) c.text(0, 4, r"boxcenter and flushleft", [text.parbox(3), text.halign.boxcenter, text.halign.flushleft]) c.text(0, 3, r"boxcenter and flushcenter", [text.parbox(3), text.halign.boxcenter, text.halign.flushcenter]) c.text(0, 2, r"boxcenter and flushright", [text.parbox(3), text.halign.boxcenter, text.halign.flushright]) c.text(-5, 0, r"left: boxleft and flushleft", [text.parbox(3), text.halign.left]) c.text(0, 0, r"center: boxcenter and flushcenter", [text.parbox(3), text.halign.center]) c.text(5, 0, r"right: boxright and flushright", [text.parbox(3), text.halign.right]) c.writeEPSfile("halign") c.writePDFfile("halign") c.writeSVGfile("halign") PyX-0.14.1/examples/text/halign.txt0000644000076500000240000000273612037344751017354 0ustar andrestaff00000000000000Horizontal alignment The example shows the result of the different text attributes for horizontal alignment. We first need to emphasize, that PyX distinguishes between the alignment of the text box and the alignment of the material within the text box. The first line in the output shows the effect of the box alignment created by `boxleft`, `boxcenter` and `boxright` leading to left, center, and right alignment of the text box with respect to the dotted lines. ... The middle part shows the examples for centering a box, but aligning the content differently inside the box, namely at the left box boundary by `flushleft`, at the center by `flushcenter` and at the right box boundary by `flushright`. Note, that such an alignment of material is available only when you create a parbox in TeX. This is easily done by means of the `parbox` attribute, where you have to specify the width of the box. At the bottom, you can see combinations of `boxleft` and `flushleft`, `boxcenter` and `flushcenter`, and `boxright` and `boxcenter` in action. These combinations are available by the attributes `left`, `center` and `right` to shortcut the setting of both corresponding attributes. You can use these shortcuts for box alignment as well, when you do not create a parbox. !! Note that the alignment features are implemented in such a way, that they work in both, TeX and LaTeX mode. Furthermore, you can always influence the alignment of the box contents by appropriate TeX and LaTeX commands as well. PyX-0.14.1/examples/text/marker.ipynb0000644000076500000240000005056112615761405017675 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using markers" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\ngg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "unit.set(xscale=3)\n", "\n", "c = canvas.canvas()\n", "t = c.text(0, 0, r\"Here\\PyXMarker{id} is a marker.\")\n", "center = t.marker(\"id\")\n", "c.stroke(path.circle(center[0], center[1], 1), [color.rgb.red])\n", "c.stroke(path.line(center[0]-1, center[1], center[0]+1, center[1]), [color.rgb.red])\n", "c.stroke(path.line(center[0], center[1]-1, center[0], center[1]+1), [color.rgb.red])\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The example shows how to obtain specific coordinates in a (La)TeX text. This\n", "allows to mark specific portions of text, setting arrows, braces and many\n", "more. A marker can be set with the command `\\PyXMarker` which takes the\n", "name of the marker as an argument (`id` in the example code). The position of\n", "the marker can then be obtained from the textbox, which is returned by the\n", "`canvas.text` method.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/marker.py0000644000076500000240000000067412515656701017205 0ustar andrestaff00000000000000from pyx import * unit.set(xscale=3) c = canvas.canvas() t = c.text(0, 0, r"Here\PyXMarker{id} is a marker.") center = t.marker("id") c.stroke(path.circle(center[0], center[1], 1), [color.rgb.red]) c.stroke(path.line(center[0]-1, center[1], center[0]+1, center[1]), [color.rgb.red]) c.stroke(path.line(center[0], center[1]-1, center[0], center[1]+1), [color.rgb.red]) c.writeEPSfile("marker") c.writePDFfile("marker") c.writeSVGfile("marker") PyX-0.14.1/examples/text/marker.txt0000644000076500000240000000064012037344751017363 0ustar andrestaff00000000000000Using markers The example shows how to obtain specific coordinates in a (La)TeX text. This allows to mark specific portions of text, setting arrows, braces and many more. A marker can be set with the command `\PyXMarker`... which takes the name of the marker as an argument (`id` in the example code). The position of the marker can then be obtained from the textbox, which is returned by the `canvas.text` method. PyX-0.14.1/examples/text/README0000644000076500000240000000101512037344751016216 0ustar andrestaff00000000000000Creating text One of the major features of PyX is to use the TeX typesetting engine to create text. PyX will start a single TeX or LaTeX instance as soon as text needs to be typeset. It passes the texts to this instance and directly reads the typeset information (dvi file) as created by the TeX interpreter. By this seamless and as far as we know unique integration, all advanced features of the TeX typesetting system like its high quality paragraph builder or the highly advanced math mode become available to PyX users. PyX-0.14.1/examples/text/texrunner.ipynb0000644000076500000240000006743212615761415020454 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Running and controlling TeX" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAAA3CAYAAADUvc6fAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI\nWXMAAA9hAAAPYQGoP6dpAAAAHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xNeq0bM4A\nAARRSURBVHic7ZzBceM4EEVfbzkBbdUmwA1gD5wQtCFwApiDHIIVwB40IVi3vVoh2CFYIYxCGIXQ\ne0BDwtAERVKEtVDhV7FKItFAAx/4bB30RVUpyBcPACKyAOoLbffWZgm8qepbVyMRqYCjqh7HJDIl\nTkSWls8JqroOn6nqeuj8usbuGGOrqgcRWQGV3YuuR3LYCVwCG6Cy7+/Axj5XwDNuMbB2G1Wl6wJ+\n9D1PELcE1Oce3H8CfoydX2SMheX33Lr33h73s68H47H2O9dw2om229a0dnoP/g7jR2BqHODy9J/t\nxB2BvZ2gq+anqkcReQReROS7jbUCvobj3gKewN4kbAKLIR12TcgWce/7mjMugkZVtyJyBBogKm+B\nRP4lIl0yu1XVg6q+icgWeDbCD7cmDyAmGa9E5AwnRc+4hVkCL8AikKpQnmqclPl30EuPDI6OCyW0\nI0dPzE+fX2x+NhcN23GW1qZDSqP5fPb12xXE79S9uE8Fgn0Pd3uD26lHVd0Du0hfk+K6YCdqq6q+\nsNji5K4PR8vjF2lV1UfOhYp/vgOWVnTdHFMJHCpnO5zkvIvIhh4pmyPOJHADVK0FXhmxgyAidSCn\nb+F9nKRvcafz5ph8AgfioKq/A76AeEkZp6p7Vf1iJ29l99aq+qcOLPPtXd/glAVTgNN9Vd0B33Gb\n5GngfJIhNYFPIrIwOVsz/OROjQsxqOgKERQ0XfL4hCPOS+mj5VkF8U2kEEqGh/BL8OO0AhZevvzu\n9SV58Nm3bUTEdxM+Bydfe9yCxn78t/sdE9fY503waEkH6bH5+efBPI9BzD/AHzbOASef+D5wPy38\nRvNt9l35JkHKColzdVrTqgRTxF2R54dKNni2umWVeel66OB0zs3hq7tRO3Jq3Nyw997/otqMISmB\nOaBHhrH7g3/C3AJiMlGQKVJXoQWJUQjMHIXAzFEIzByFwMxRCMwchcDMUQjMHIXAzFEIzByFwMxR\nCMwchcDMUQjMHIXAzFEIzByFwMxRCMwchcDMUQjMHIXAzFEIzByFwMxRCMwchcDMUQjMHFn7xAzo\n0//f76KPyzXjX+ND08rTY7gXTfD3qix9Ygb025vvHOOPWb+ePiZ50dyNT8wMuGb8q9dPJ3rR3KtP\nTBT+L9Ht8foWaQAuxdbAt56/X0/3ookc5yx8YoK4V8unsXzqLgnl7B/j28Xy9t875zlAUj+sH4m8\naLL2iQni9pbPjn4LkBWuUNnhTs2q1c+HfLrmORFJvGjuyicGTotfd8mVOuuSSkS8jcil10Kyd/Jc\nXjR35RPTBxFZiMgr5xN4s4JpTi+au/OJ8YWPfjRICOWy3f7TMLcXTdY+MQFqk0Vwi/PY7hf41+bU\n4DbEwdpWkfGj82xvgmAevesHCbxohlQ6Uy8+wScGqzJtohfNV8fmMuNaJPGiuRufGIu5KLVjc0mN\na71osvaJCeTtKCLLmLTdGim9aIpPTOb4D/zgpGjd/o1MAAAAAElFTkSuQmCC\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "# Set properties of the defaulttexrunner, e.g. switch to LaTeX.\n", "text.set(text.LatexRunner)\n", "\n", "c = canvas.canvas()\n", "# The canvas, by default, uses the default_runner from the text module.\n", "# This can be changed by the canvas method settexrunner.\n", "c.text(0, 0, r\"This is \\LaTeX.\")\n", "\n", "# If you want to use another texrunner temporarily, you can just insert\n", "# a text box manually\n", "plaintex = text.TexRunner() # plain TeX runner\n", "c.insert(plaintex.text(0, -1, r\"This is plain \\TeX.\"))\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Usually, all you will ever need is a single `texrunner` instance which\n", "controls a single running TeX or LaTeX instance at a time. To make life easy to\n", "our users, such an instance is created automatically upon startup and its\n", "called the `defaulttexrunner`. Whenever you use the function shortcuts like\n", "`text.text()` and in particular `text.set()`, you are accessing this\n", "`defaulttexrunner` instance. Also, the shortcut method `text` of any canvas\n", "instance uses this `defaulttexrunner` by default.\n", "\n", " However, it is possible to create several texrunner instances. In this\n", "example, we are using two of them. To make it a little more interesting, we\n", "instruct the `defaulttexrunner` to use LaTeX, while keeping TeX for the\n", "`plaintexrunner` instance. It is you turn to try expressions valid in TeX or\n", "LaTeX only at the different `texrunner` instances.\n", "\n", " Note that you do not have to worry about mixing the results of different\n", "texrunners into a single output. Even the embedded fonts in the output are\n", "shared. You can, by the way, also restart a `texrunner` instance including the\n", "`defaulttexrunner` and change its configuration on that occasion.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/texrunner.py0000644000076500000240000000107712515656701017754 0ustar andrestaff00000000000000from pyx import * # Set properties of the defaulttexrunner, e.g. switch to LaTeX. text.set(text.LatexRunner) c = canvas.canvas() # The canvas, by default, uses the default_runner from the text module. # This can be changed by the canvas method settexrunner. c.text(0, 0, r"This is \LaTeX.") # If you want to use another texrunner temporarily, you can just insert # a text box manually plaintex = text.TexRunner() # plain TeX runner c.insert(plaintex.text(0, -1, r"This is plain \TeX.")) c.writeEPSfile("texrunner") c.writePDFfile("texrunner") c.writeSVGfile("texrunner") PyX-0.14.1/examples/text/texrunner.txt0000644000076500000240000000223212037344751020133 0ustar andrestaff00000000000000Running and controlling TeX ! Usually, all you will ever need is a single `texrunner` instance which controls a single running TeX or LaTeX instance at a time. To make life easy to our users..., such an instance is created automatically upon startup and its called the `defaulttexrunner`. Whenever you use the function shortcuts like `text.text()` and in particular `text.set()`, you are accessing this `defaulttexrunner` instance. Also, the shortcut method `text` of any canvas instance uses this `defaulttexrunner` by default. !! However, it is possible to create several texrunner instances. In this example, we are using two of them. To make it a little more interesting, we instruct the `defaulttexrunner` to use LaTeX, while keeping TeX for the `plaintexrunner` instance. It is you turn to try expressions valid in TeX or LaTeX only at the different `texrunner` instances. !! Note that you do not have to worry about mixing the results of different texrunners into a single output. Even the embedded fonts in the output are shared. You can, by the way, also restart a `texrunner` instance including the `defaulttexrunner` and change its configuration on that occasion. PyX-0.14.1/examples/text/textalongpath.ipynb0000644000076500000240000005563212615761431021301 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Text along path" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n41bkQgAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "p = path.path(path.moveto(-2, 0), path.curveto(-1, 0, -1, 1, 0, 1), path.curveto(1, 1, 1, 0, 2, 0))\n", "\n", "c.stroke(p, [deco.curvedtext(\"\\PyX{} is fun!\"),\n", " deco.curvedtext(\"left\", textattrs=[text.halign.left, text.vshift.mathaxis], arclenfrombegin=0.5, exclude=0.1),\n", " deco.curvedtext(\"right\", textattrs=[text.halign.right, text.vshift.mathaxis], arclenfromend=0.5, exclude=0.1)])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to set text along a given path, you can use the `curvedtext()`\n", "decorator. The example shows a few useful parameter settings for this\n", "decorator.\n", "\n", " To output just the curved text, but not the path, you can use the\n", "draw method of the canvas instead of the stroke method. By that the\n", "path is omitted in the output completely. In contrast, if you set the\n", "linewidth to zero instead, the path will still be visible, as those\n", "lines will be rendered as the thinnest available linewidth on the\n", "output device according to the PostScript and PDF specification.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/textalongpath.py0000644000076500000240000000102712515656701020577 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() p = path.path(path.moveto(-2, 0), path.curveto(-1, 0, -1, 1, 0, 1), path.curveto(1, 1, 1, 0, 2, 0)) c.stroke(p, [deco.curvedtext("\PyX{} is fun!"), deco.curvedtext("left", textattrs=[text.halign.left, text.vshift.mathaxis], arclenfrombegin=0.5, exclude=0.1), deco.curvedtext("right", textattrs=[text.halign.right, text.vshift.mathaxis], arclenfromend=0.5, exclude=0.1)]) c.writeEPSfile("textalongpath") c.writePDFfile("textalongpath") c.writeSVGfile("textalongpath") PyX-0.14.1/examples/text/textalongpath.txt0000644000076500000240000000110012041740003020735 0ustar andrestaff00000000000000Text along path In order to set text along a given path, you can use the `curvedtext()` decorator. The example shows a few useful parameter settings for this decorator. ! To output just the curved text, but not the path, you can use the draw method of the canvas instead of the stroke method. By that the path is omitted in the output completely. In contrast, if you set the linewidth to zero instead, the path will still be visible, as those lines will be rendered as the thinnest available linewidth on the output device according to the PostScript and PDF specification. PyX-0.14.1/examples/text/textbox.ipynb0000644000076500000240000003271612615761421020111 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Enlarge the surrounding of a textbox" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "unit.set(xscale=3)\n", "\n", "tbox = text.text(0, 0, r\"Boxed text\")\n", "tpath = tbox.bbox().enlarged(3*unit.x_pt).path()\n", "\n", "c = canvas.canvas()\n", "c.draw(tpath, [deco.filled([color.cmyk.Yellow]), deco.stroked()])\n", "c.insert(tbox)\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " This example introduces the concept of the `textbox`, which is a canvas-like\n", "structure containing the text and its surrounding path and reference point. We\n", "demonstrate how to enlarge the surrounding box a little and use it as a\n", "decoration of the path. \n", "\n", " The `textbox` is a specialized version of the [`box` concept\n", "../../roadmap.html] which has been introduced into PyX in a preliminary\n", "version. In the example, we obtain the bounding box (this is a `bbox` instance,\n", "not to be mixed up with the `box`) and enlarge it a bit. We then draw the path\n", "of the bounding box.\n", "\n", " In future releases of PyX, the boxes will have generic support for enlarging.\n", "The syntax will then be\n", "\n", " tpath = tbox.enlarged(3*unit.x_pt).path()\n", "\n", " An alternative, geometrically different approach to enlarging the textbox path\n", "is via an appropriate transformation, such as\n", "\n", " tbox = text.text(0, 0, r\"Boxed text\", [text.halign.boxcenter, text.valign.middle])\n", " tpath = tbox.path().transformed(trafo.scale(1.5, 1.5, 0, 0))\n", "\n", "\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/textbox.py0000644000076500000240000000046112515656701017413 0ustar andrestaff00000000000000from pyx import * unit.set(xscale=3) tbox = text.text(0, 0, r"Boxed text") tpath = tbox.bbox().enlarged(3*unit.x_pt).path() c = canvas.canvas() c.draw(tpath, [deco.filled([color.cmyk.Yellow]), deco.stroked()]) c.insert(tbox) c.writeEPSfile("textbox") c.writePDFfile("textbox") c.writeSVGfile("textbox") PyX-0.14.1/examples/text/textbox.txt0000644000076500000240000000202712037344751017600 0ustar andrestaff00000000000000Enlarge the surrounding of a textbox ! This example introduces the concept of the `textbox`, which is a canvas-like structure containing the text and its surrounding path and reference point. We demonstrate how to enlarge the surrounding box a little and use it as a decoration of the path. ... ! The `textbox` is a specialized version of the [`box` concept ../../roadmap.html] which has been introduced into PyX in a preliminary version. In the example, we obtain the bounding box (this is a `bbox` instance, not to be mixed up with the `box`) and enlarge it a bit. We then draw the path of the bounding box. ! In future releases of PyX, the boxes will have generic support for enlarging. The syntax will then be tpath = tbox.enlarged(3*unit.x_pt).path() ! An alternative, geometrically different approach to enlarging the textbox path is via an appropriate transformation, such as tbox = text.text(0, 0, r"Boxed text", [text.halign.boxcenter, text.valign.middle]) tpath = tbox.path().transformed(trafo.scale(1.5, 1.5, 0, 0)) PyX-0.14.1/examples/text/valign.ipynb0000644000076500000240000027362112615761375017706 0ustar andrestaff00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vertical alignment" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nNQAAAABJRU5ErkJggg==\n", "image/svg+xml": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pyx import *\n", "\n", "c = canvas.canvas()\n", "\n", "# apply global TeX setting\n", "text.preamble(r\"\\parindent=0pt\")\n", "w = 1.2 # an appropriate parbox width for spam & eggs\n", "\n", "# vertical alignments by margins\n", "c.stroke(path.line(0, 4, 8, 4), [style.linewidth.THin])\n", "c.text(0, 4, r\"spam \\& eggs\", [text.parbox(w), text.valign.top])\n", "c.text(3, 4, r\"spam \\& eggs\", [text.parbox(w), text.valign.middle])\n", "c.text(6, 4, r\"spam \\& eggs\", [text.parbox(w), text.valign.bottom])\n", "\n", "# vertical alignments by baselines\n", "c.stroke(path.line(0, 2, 8, 2), [style.linewidth.THin])\n", "c.text(0, 2, r\"spam \\& eggs\", [text.parbox(w, baseline=text.parbox.top)])\n", "c.text(3, 2, r\"spam \\& eggs\", [text.parbox(w, baseline=text.parbox.middle)])\n", "c.text(6, 2, r\"spam \\& eggs\", [text.parbox(w, baseline=text.parbox.bottom)])\n", "\n", "# vertical shifts\n", "c.stroke(path.line(0, 0, 8, 0), [style.linewidth.THin])\n", "c.text(0, 0, r\"x=0\", [text.mathmode, text.vshift.topzero])\n", "c.text(2, 0, r\"x=0\", [text.mathmode, text.vshift.middlezero])\n", "c.text(4, 0, r\"x=0\", [text.mathmode, text.vshift.bottomzero])\n", "c.text(6, 0, r\"x=0\", [text.mathmode, text.vshift.mathaxis])\n", "\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The example demonstrates the effect of several text attributes for vertical\n", "alignment.\n", "\n", "In the first line of the output, the extent of the whole text box is taken into\n", "account by various versions of valign. While in this case, the valign attributes\n", "are combined with a parbox each, the valign technique also perfectly works for\n", "single line text. \n", "\n", "In contrast, in the second line of the output a parbox is shown with different\n", "values for the baseline. Note that by default, text is vertically aligned at\n", "its baseline, that is, the line the letters are typed upon. For a parbox\n", "containing several lines, there are several choices. PyX allows you to use the\n", "top-most baseline (which is, by the way, the default when skipping the baseline\n", "keyword argument of the parbox completely), and the bottom-most baseline in\n", "your paragraph. Additionally you can also use the position just in the middle\n", "of these two cases. Since the alignment along a baseline does not depend on the\n", "size of the characters in your output, it is preferable to valign in most\n", "use-cases.\n", "\n", "In the last line of the output, the text.vshift is used to create some vertical\n", "shift of the output corresponding to certain criteria. The universal case is\n", "to use a certain fraction of a character height (or the height of any TeX\n", "expression). For `vshift.topzero` the full height of the character `0` is used,\n", "for `vshift.middlezero` half of the height of the character `0` is used and for\n", "`vshift.bottomzero`, no shift will be done at all and the usual alignment at the\n", "baseline will take place. Another interesting vertical shift value is the\n", "`vshift.mathaxis`, which shifts the material by the height of the mathematical\n", "axis. This axis is used by TeX to vertically align the mathematical operators\n", "and the equal sign but also brackets and objects like the sum and integral\n", "symbols. This shift typically is a little less in height as compared to\n", "`vshift.middlezero` and fits well in various cases to visually center a single\n", "line output in vertical direction. It is also useful to align text, although\n", "the value of the shift is based on the configuration of the mathematical mode.\n", "This means that the alignment might not be suitable for cases, where the\n", "text mode of TeX was reconfigured without also adapting the math mode configuration.\n", "\n", " Please don't get confused by the additional text.mathmode attribute in this\n", "vshift example, which leads the text to be rendered in TeX's mathematical mode.\n", "The `text.mathmode` attribute is by the way similar but not identical (due to the\n", "use of `\\displaystyle`) to encapsulating your expression in TeX's mathmode\n", "delimiters `$`.\n" ] } ], "metadata": { "language": "python" }, "nbformat": 4, "nbformat_minor": 0 }PyX-0.14.1/examples/text/valign.py0000644000076500000240000000220712515656704017201 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() # apply global TeX setting text.preamble(r"\parindent=0pt") w = 1.2 # an appropriate parbox width for spam & eggs # vertical alignments by margins c.stroke(path.line(0, 4, 8, 4), [style.linewidth.THin]) c.text(0, 4, r"spam \& eggs", [text.parbox(w), text.valign.top]) c.text(3, 4, r"spam \& eggs", [text.parbox(w), text.valign.middle]) c.text(6, 4, r"spam \& eggs", [text.parbox(w), text.valign.bottom]) # vertical alignments by baselines c.stroke(path.line(0, 2, 8, 2), [style.linewidth.THin]) c.text(0, 2, r"spam \& eggs", [text.parbox(w, baseline=text.parbox.top)]) c.text(3, 2, r"spam \& eggs", [text.parbox(w, baseline=text.parbox.middle)]) c.text(6, 2, r"spam \& eggs", [text.parbox(w, baseline=text.parbox.bottom)]) # vertical shifts c.stroke(path.line(0, 0, 8, 0), [style.linewidth.THin]) c.text(0, 0, r"x=0", [text.mathmode, text.vshift.topzero]) c.text(2, 0, r"x=0", [text.mathmode, text.vshift.middlezero]) c.text(4, 0, r"x=0", [text.mathmode, text.vshift.bottomzero]) c.text(6, 0, r"x=0", [text.mathmode, text.vshift.mathaxis]) c.writeEPSfile("valign") c.writePDFfile("valign") c.writeSVGfile("valign") PyX-0.14.1/examples/text/valign.txt0000644000076500000240000000513612037344751017367 0ustar andrestaff00000000000000Vertical alignment The example demonstrates the effect of several text attributes for vertical alignment. In the first line of the output, the extent of the whole text box is taken into account by various versions of valign. While in this case, the valign attributes are combined with a parbox each, the valign technique also perfectly works for single line text. ... In contrast, in the second line of the output a parbox is shown with different values for the baseline. Note that by default, text is vertically aligned at its baseline, that is, the line the letters are typed upon. For a parbox containing several lines, there are several choices. PyX allows you to use the top-most baseline (which is, by the way, the default when skipping the baseline keyword argument of the parbox completely), and the bottom-most baseline in your paragraph. Additionally you can also use the position just in the middle of these two cases. Since the alignment along a baseline does not depend on the size of the characters in your output, it is preferable to valign in most use-cases. In the last line of the output, the text.vshift is used to create some vertical shift of the output corresponding to certain criteria. The universal case is to use a certain fraction of a character height (or the height of any TeX expression). For `vshift.topzero` the full height of the character `0` is used, for `vshift.middlezero` half of the height of the character `0` is used and for `vshift.bottomzero`, no shift will be done at all and the usual alignment at the baseline will take place. Another interesting vertical shift value is the `vshift.mathaxis`, which shifts the material by the height of the mathematical axis. This axis is used by TeX to vertically align the mathematical operators and the equal sign but also brackets and objects like the sum and integral symbols. This shift typically is a little less in height as compared to `vshift.middlezero` and fits well in various cases to visually center a single line output in vertical direction. It is also useful to align text, although the value of the shift is based on the configuration of the mathematical mode. This means that the alignment might not be suitable for cases, where the text mode of TeX was reconfigured without also adapting the math mode configuration. ! Please don't get confused by the additional text.mathmode attribute in this vshift example, which leads the text to be rendered in TeX's mathematical mode. The `text.mathmode` attribute is by the way similar but not identical (due to the use of `\displaystyle`) to encapsulating your expression in TeX's mathmode delimiters `$`. PyX-0.14.1/faq/0000755000076500000240000000000012615763300013303 5ustar andrestaff00000000000000PyX-0.14.1/faq/conf.py0000644000076500000240000001665712255047666014633 0ustar andrestaff00000000000000# -*- coding: utf-8 -*- # # pyxfaq documentation build configuration file, created by # sphinx-quickstart on Sun Jun 12 16:54:07 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 sys.path.insert(0, '..') import pyx.version # 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.todo'] # 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 = 'pyxfaq' copyright = '2011, Gert-Ludwig Ingold' # 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 = '.'.join(pyx.version.version.split('.')[:1]) # The full version, including alpha/beta/rc tags. release = pyx.version.version # 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 = pyx.version.date # 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 = 'pyx' # 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 = {'sidebarwidth': 200} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['../manual/theme'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'PyX FAQ' # 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 = [] # 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 = {} html_sidebars = { '**': ['localtoc.html', 'sourcelink.html', 'searchbox.html'] } # 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 = False # 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 = 'pyxfaqdoc' todo_include_todos = True # gli # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). latex_paper_size = 'a4' # 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', 'pyxfaq.tex', 'Some frequently and not so frequently asked questions about PyX', 'Gert-Ludwig Ingold', '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 = r''' \hypersetup{pdftitle={%s}, pdfauthor={Gert-Ludwig Ingold }, pdfsubject={FAQ for PyX}, pdfkeywords={PyX, graphics, tipps and tricks, FAQ}} \DeclareUnicodeCharacter{028F}{{\fontsize{7}{7}\selectfont Y}} ''' % latex_documents[0][2] # 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', 'pyxfaq', 'pyxfaq Documentation', ['Gert-Ludwig Ingold'], 1) ] PyX-0.14.1/faq/general_aspects_plotting.rst0000644000076500000240000000217012037344747021124 0ustar andrestaff00000000000000==================================== General aspects of plotting with PyX ==================================== How do I generate multipage output? =================================== With versions 0.8 and higher it is possible to produce multipage output, i.e. a Postscript or PDF file containing more than one page. In order to achieve this, one creates pages by drawing on a canvas as usual and appends them in the desired order to a document from which Postscript or PDF output is produced. The following example serves as an illustration:: from pyx import * d = document.document() for i in range(3): c = canvas.canvas() c.text(0, 0, "page %i" % (i+1)) d.append(document.page(c, paperformat=document.paperformat.A4, margin=3*unit.t\_cm, fittosize=1)) d.writePSfile("multipage") Here, ``d`` is the document into which pages are inserted by means of the ``append`` method. When converting from a canvas to a document page, the page properties like the paperformat are specified. In the last line, output is produced from document ``d``. PyX-0.14.1/faq/general_aspects_pyx.rst0000644000076500000240000002133112615760612020077 0ustar andrestaff00000000000000====================== General aspects of PyX ====================== The name of the game ==================== Originally, the name PyX was constructed as a combination of **P**\ ostscript, i.e. the first output format supported by PyX, P\ **y**\ thon, i.e. the language in which PyX is written, and Te\ **X**, i.e. the program which PyX uses for typesetting purposes. Actually, the title of this question is a tribute to TeX because it is taken from the first chapter of the TeX book [#texbook]_ where the origin of the name TeX and its pronunciation are explained. Despite the ties between TeX and PyX, their pronunciation is quite different. According to the developers of PyX, it should be pronounced as [pʏks]. Please do not pronounce it as [pʏx] or [pʏç]. .. _where_do_I_get_PyX: Where do I get the latest version of PyX? ========================================= The current release of PyX (as well as older ones) is freely available from `http://pyx.sourceforge.net `_ where also a subversion repository with the latest patches can be found. In addition, PyX is registered on the Python Package Index at `https://pypi.python.org/pypi/PyX `_ and can be installed by ``easy_install`` and ``pip``. As PyX is hosted on PyPI, it can be directly downloaded and installed by ``pip``. Please see the `pip documentation `_ for details. Possibly older versions of PyX are also available as package for various Linux distributions: see, for instance, `http://packages.debian.org/testing/python-pyx `_ for information on the PyX package in Debian GNU/Linux or `http://packages.ubuntu.com/raring/python-pyx `_ for Ubuntu. PyX has no dependencies on other Python packages. How can I determine the version of PyX running on my machine? ============================================================= Start a python session (usually by typing ``python`` at the system prompt) and then type the following two commands (``>>>`` is the python prompt) >>> import pyx >>> pyx.__version__ Note that there are two underscores before and after ``version``. How can I access older versions of PyX? ======================================= There are reasons which might make it necessary to use older versions of PyX. If you are using Python 2 you will need PyX version 0.12.1 or earlier (see :ref:`python_requirements`). Furthermore, as at present it is not guaranteed that PyX is backward compatible, it may be desirable to access an older version of PyX instead of adapting older code to a more recent version of PyX. In order to do that, one needs the corresponding PyX package (see :ref:`where_do_I_get_PyX` if you need to download it), which should be unpacked below a directory, e.g. ``/home/xyz/Python``, where you want to keep the various PyX versions. This will result in a subdirectory with a name like ``PyX-0.14`` which contains the contents of the corresponding package. You can then ask Python to first look in the appropriate directory before looking for the current version of PyX by inserting the following code (appropriately modified according to your needs) at the beginning of your program before importing the PyX module:: import sys sys.path.insert(0, "/home/xyz/Python/PyX-0.14") Including appropriate lines even if the current version of PyX is used, might turn out to be helpful when the current version has become an old version (unless you have no difficulties determining the PyX version by looking at your code). If your operating system supports path expansion, you might use as an alternative:: import sys, os sys.path.insert(0, os.path.expanduser("~/Python/PyX-0.14")) which will expand the tilde to your home directory. Does PyX run under my favorite operating system? ================================================ Yes, if you have installed Python (:ref:`what_is_python`) and TeX (:ref:`what_is_tex`). Both are available for a large variety of operating systems so chances are pretty good that you will get PyX to work on your system. .. _python_requirements: Under which versions of Python will PyX run? ============================================ Starting with version 0.13, PyX requires Python 3.2 or higher. If you still need to run PyX with Python 2, you should use version 0.12.1 which is designed to run with Python 2.3 up to 2.7. The version of your Python interpreter can be determined by calling it with the option ``-V``. Alternatively, you can simply start the interpreter and take a look at the startup message. Note that there may be different versions of Python installed on your system at the same time. The default Python version need not be the same for all users. Does PyX provide a GUI to view the produced image? ================================================== No, PyX itself does not provide a means to view the produced image. The result of a PyX run is an EPS (= Encapsulated PostScript) file, a PS (= PostScript) file, a PDF (= Portable Document Format) file or a SVG (= Scalable Vector Graphics) file, which can be viewed, printed or imported into other applications. There are several means of viewing PS and EPS files. A common way would be to use ``ghostview`` which provides a user interface to the PostScript interpreter ``ghostscript``. More information about this software, which is available for a variety of platforms, can be found at `http://www.cs.wisc.edu/~ghost/ `_. If you do not own a printer which is capable of printing PostScript files directly, ``ghostscript`` may also be useful to translate PS and EPS files produced by PyX into something your printer will understand. PDF files can be viewed by means of the ``Adobe Reader ®`` available from `http://www.adobe.com/products/acrobat/readstep2.html `_. On systems running X11, ``xpdf`` might be an alternative. It is available from `http://www.foolabs.com/xpdf/ `_. SVG files can be viewed by webbrowsers like Firefox available at `https://www.mozilla.org/en-US/firefox `_ or Chrome available at `https://www.google.com/chrome/ `_. If you want to do interactive development of a PyX graphics, you might consider to use an IPython notebook (see :ref:`pyx_ipython_notebook`). .. _pyx_ipython_notebook: Will I be able to embed PyX graphics output into an IPython notebook? ===================================================================== Yes, PyX canvas object and objects inheriting from the canvas class, in particular graphs and text, can be embedded into an IPython notebook. Suppose you have a canvas object called ``c`` on which you have done some drawing. Then entering ``c`` in an IPython notebook cell and executing that cell will automatically produce a SVG representation and embed it into the notebook. (Alternatively, also PNG is available by means of ghostscript, but the default display_order of IPython prefers SVG over PNG.) For more information on IPython and working with its notebooks see `http://www.ipython.org/ `_. I am a Gnuplot user and want to try PyX. Where can I get some help? =================================================================== There exists a tutorial by Titus Winters which explains how to perform standard Gnuplot tasks with \PyX. The tutorial can be found at `http://www.cs.ucr.edu/~titus/pyxTutorial/ `_. Where can I get help if my question is not answered in this FAQ? ================================================================ The PyX sources contain a reference manual which is also available online at `http://pyx.sourceforge.net/manual/ `_. Furthermore, there exists a set of examples demonstrating various features of PyX, which is available in the sources or can be browsed at `http://pyx.sourceforge.net/examples.html `_. If the feature you are looking for is among them, using the appropriate part of the example code or adapting it for your purposes may help. There is also a user discussion list about PyX which you can subscribe to at `http://lists.sourceforge.net/lists/listinfo/pyx-user `_. The archive of the discussion list is available at `http://sourceforge.net/mailarchive/forum.php?forum_name=pyx-user `_. Finally, it might be worth checking `http://pyx.sourceforge.net/pyxfaq.pdf `_ for an updated version of this FAQ. .. [#texbook] D.Knuth, *The TeX book* (Addison-Wesley, 1984) PyX-0.14.1/faq/index.rst0000644000076500000240000000142412037344747015155 0ustar andrestaff00000000000000.. pyxfaq documentation master file, created by sphinx-quickstart on Sun Jun 12 16:54:07 2011. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Some frequently and not so frequently asked questions about PyX =============================================================== .. topic:: Acknowledgements The following persons have in one way or the other, e.g. by asking good questions or providing answers, contributed to this FAQ: Walter Brisken, Alejandro Gaita-Arinyo, Pierre Joyot, Jörg Lehmann, John Owens, Michael Schindler, Gerhard Schmid, André Wobst. .. toctree:: :maxdepth: -1 general_aspects_pyx python general_aspects_plotting plotting_graphs other_plotting tex_latex PyX-0.14.1/faq/Makefile0000644000076500000240000000153212171063276014746 0ustar andrestaff00000000000000# Makefile for Sphinx documentation # PYTHON ?= python3 # 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 all html latexpdf all: html latexpdf @echo "Done." clean: -rm -rf $(BUILDDIR)/* *.eps *.pdf *.png html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 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." PyX-0.14.1/faq/other_plotting.rst0000644000076500000240000000204612037344747017110 0ustar andrestaff00000000000000==================== Other plotting tasks ==================== How can I rotate text? ====================== Text can be written at an arbitrary angle by specifying the appropriate transformation as an attribute. The command :: c.text(0, 0, "Text", [trafo.rotate(60)]) will write at an angle of 60 degrees relative to the horizontal axis. If no pivot is specified (like in this example), the text is rotated around the reference point given in the first two arguments of ``text``. In the following example, the pivot coincides with the center of the text:: c.text(0, 0, "Text", [text.halign.center,text.valign.middle,trafo.rotate(60)]) How can I clip a canvas? ======================== In order to use only a part of a larger canvas, one may want to clip it. This can be done by creating a clipping object which is used when creating a canvas instance:: clippath = path.circle(0.,0.,1.) clipobject = canvas.clip(clippath) c = canvas.canvas([clipobject]) In this example, the clipping path used to define the clipping object is a circle. PyX-0.14.1/faq/plotting_graphs.rst0000644000076500000240000004027612037344747017262 0ustar andrestaff00000000000000================== Plotting of graphs ================== General aspects =============== .. _mingraphdata: How do I generate a graph from data as simply as possible? ---------------------------------------------------------- Suppose that you have a data file ``x.dat`` containing values for ``x`` and ``y`` in two columns. Then the following code will do the job:: from pyx import * g = graph.graphxy(width=10) g.plot(graph.data.file("x.dat", x=1, y=2)) g.writeEPSfile("x") ``graphxy`` creates a canvas (called ``g`` in this example) onto which the graph will be drawn and it sets the default behavior including the axis. There is, however, no default value for the width of the graph. In ``plot`` you have to specify the name of the data file and the columns from which the data should be taken. Finally, ``writeEPSfile`` will generate the postscript file ``x.eps`` which you can view or print. A minimal example is also provided in the PyX distribution as ``examples/graphs/minimal.py``. .. _mingraphfunc: How do I generate a graph of a function as simply as possible? -------------------------------------------------------------- The following example will draw a parabola:: from pyx import * g = graph.graphxy(width=10, x=graph.axis.linear(min=-2, max=2) ) g.plot(graph.data.function("y(x)=x**2")) g.writeEPSfile("x") Most of the code has been explained in :ref:`mingraphdata`. The main difference is that here you need to specify minimum and maximum for the ``x``-axis so that PyX knows in which range to evaluate the function. Another, slightly more complex, example is also provided in the PyX distribution as ``examples/graphs/piaxis.py``. How can I stack graphs? ----------------------- PyX always needs a canvas to draw on. One possibility therefore consists in creating a new canvas with :: c = canvas.canvas() and inserting the graphs into this canvas with ``c.insert(…)``. Here, ``…`` has to be replaced by the name of the graph. Alternatively, the canvas created with ``graph.graphxy`` for one of the graphs can be used to insert the other graphs even if they will be positioned outside the first graph. The second issue to address is positioning of the graphs. By specifying ``xpos`` and ``ypos`` when calling ``graphxy`` you can define the position of a graph. Later on, the position and size of a graph ``g`` can be referred to as ``g.xpos`` ``g.ypos`` ``g.width`` and ``g.height`` even if for example the height has never been specified explicitly but is only defined by a PyX default. The following example shows how to put graph ``gupper`` above graph ``glower`` on a canvas ``c``:: from pyx import * from graph import graphxy c = canvas.canvas() glower = graphxy(width=10) glower.plot(...) c.insert(glower) gupper = graphxy(width=10, ypos=glower.ypos+glower.height+2) gupper.plot(...) c.insert(gupper) c.writeEPSfile(...) where ``…`` has to be replaced by the appropriate information like data and symbol specifications and the name of the output file. Here, ``c.insert`` is used to actually insert the subcanvasses for the graphs into the main canvas ``c`` and ``c.writeEPSfile`` in the last line requests to write the contents of this canvas to a file. How can I plot grid data? ------------------------- PyX offers support for plotting three-dimensional data as two-dimensional color plots or grey-scale plots and of vector fields by providing ways to plot rectangles and arrows in graphs. We start by considering the task of creating a two-dimensional color plot by plotting a number of filled rectangles. One first needs to create a data set which consists of five entries per data point. These are the lower left corner (*x*\ :sub:`min`, *y*\ :sub:`min`) and the upper right corner (*x*\ :sub:`max`, *y*\ :sub:`max`) of the triangle and a value between 0 and 1 determining the color via a PyX color palette. The following code gives an idea of how to proceed:: g.plot(graph.data.file("datafile.dat", xmin=1, xmax=2, ymin=3, ymax=4, color=5), [graph.style.rect(color.palette.ReverseRainbow)] ) g.dodata() Here, we assume that the data are stored in ``datafile.dat`` and the columns contain *x*\ :sub:`min`, *x* :sub:`max`, *y*\ :sub:`min`, *y*\ :sub:`max`, and the color value in this order. The columns are numbered from 1, since the 0th column contains the line number. To determine the color, we use the ``ReverseRainbow`` palette. The last line instructs PyX to plot the rectangles before plotting the axes. Otherwise, the axes might be covered partially by the rectangles and, in particular, the ticks might not be visible. Gray-scale plots can easily be generated by specifying the palette ``Gray`` or ``ReverseGray`` (cf. appendix C of the manual for a list of predefined palettes). At first sight, it seems surprising that plotting of grid data requires the specification of four coordinates for the rectangle. The reason is that this allows to draw rectangles of varying sizes which may help to reduce the size of the postscript file by combining rectangles of the same color in horizontal or vertical direction. For example, it may be sufficient to plot a grey-scale image in a small number of grey shades and then combining rectangles may be appropriate. Note, though, that this step is part of the data creation and not preformed by PyX. Another advantage of fully specifying each rectangle is that it is straightforward to leave parts of the graph blank. The same ideas as for the color plot can be applied to plot vector fields where each data point is represented by an arrow. In this case a data point is specified by the position of the arrow, its size and its direction as indicated in the following code snippet:: g.plot(graph.data.file("datafile.dat"), x=1, y=2, size=3, angle=4), [graph.style.arrow()] ) Complete code examples can be found in ``examples/graphs/mandel.py`` and ``examples/graphs/arrows.py`` . .. _problemcoord: How can I access points in problem coordinates of a graph? ---------------------------------------------------------- Sometimes it may be necessary to add graphical elements to a graph in addition to the data or function(s) which have been plotted as described in :ref:`mingraphdata` and :ref:`mingraphfunc`. For a graph instance ``g`` the positioning can easily be done in canvas coordinates by making use of the origin (``g.xpos``, ``g.ypos``) and the width (``g.width``) and height (``g.height``) of the graph. Occasionally, it may be more convenient to specify the position of the additional material in terms of problem coordinates. However, this requires that the mapping from problem coordinates to canvas coordinates is known. By default this is not the case before the content of the canvas is written to the output which is too late for our purpose. One therefore needs to explicitly instruct PyX to determine this mapping. One possibility is to ask PyX to finish the graph by means of ``g.finish()``. Now, problem coordinates can be used to insert additional material which will end up in front of the graph. If this is not desired, one should only fix the layout of the graph by means of ``g.dolayout()``. Then, the additional material can be put onto the canvas before the graph is drawn and it will therefore appear behind the graph. The conversion of problem coordinates (``px``, ``py``) to canvas coordinates (``x``, ``y``) is performed as follows:: x, y = g.pos(px, py) By default, the problem coordinates will refer to the ranges of the *x* and *y* axes. If several axes with different ranges exist, the instances of the desired axes should be passed to the ``pos`` method by means of the keyword arguments ``xaxis`` and ``yaxis``. We remark that the drawing of lines parallel to one of the axes at specific problem coordinates can also be done by adapting the method described in :ref:`zeroline`. I would like a key for only some of my data sets. How do I do that? ------------------------------------------------------------------- .. todo:: This still needs to be answered. Axis properties =============== How do I specify the tick increment? ------------------------------------ In the partition of a linear axis, the increments associated with ticks, subticks etc. can be specified as argument of ``parter.linear``. In the following example, ticks will be drawn at even values while subticks will be drawn at all integers:: from pyx.graph import axis tg = graph.graphxy(width=10, x=axis.linear(min=1, max=10, parter=axis.parter.linear(tickdists=[2,1])) ) .. _zeroline: How do I plot the zero line? ---------------------------- PyX releases before 0.6 offered the possibility to stroke a zero line by specifying ``zeropathattrs`` in the painter constructor. In more recent releases, one proceeds as follows. First one has to fix the layout information of the graph by means of the ``finish`` or ``dolayout`` method (see :ref:`problemcoord` for a more detailed explanation). Then, the ``xgridpath`` or ``ygridpath`` method of a graph will return a grid path parallel to the *y* or *x* axis, respectively, at the specified *y* value. As an example, a zero line in *x* direction can be drawn as follows:: g.finish() g.stroke(g.ygridpath(0)) How can I add grid lines to a graph? ------------------------------------ Specifying ``gridattrs`` for the painter of an axis will generate grid lines orthogonal to this axis. At least an empty list is needed like in :: g = graph.graphxy(width=10, x=graph.axis.linear(painter=graph.axis.painter.regular(gridattrs=[])), y=graph.axis.linear() ) where grid lines in vertical direction are drawn in default style. Occassionally, one might want to draw grid lines corresponding to ticks and subticks in a different style. This can be achieved by specifiying changeable attributes using ``changelist``. The following code :: my_xpainter = graph.axis.painter.regular(gridattrs= [attr.changelist([style.linestyle.solid, style.linestyle.dashed])] ) my_ypainter = graph.axis.painter.regular(gridattrs= [attr.changelist([color.rgb.red, color.rgb.blue])] ) g = graph.graphxy(width=10, x=graph.axis.linear(painter=my_xpainter), y=graph.axis.linear(painter=my_ypainter) ) will create vertical solid and dashed grid lines for ticks and subticks, respectively. The horizontal grid lines will be red for ticks and blue for subticks. The changeable attributes are applied in a cyclic manner. Therefore, in this example grid lines at subsubticks would be plotted in the same style as for ticks. If this is not desired, the list of attributes should be extended by an appropriate third style. The keyword ``None`` will switch off the respective level of grid lines in case you want to draw them only e.g. for ticks but not subticks. Data properties =============== How do I choose the symbol and its attributes? ---------------------------------------------- Suppose a graph called ``g`` has been initialized, e.g. by using ``graph.graphxy``. Then, data and the style of their representation in the graph are defined by calling ``g.plot`` like in the following example in which filled circles are requested:: g.plot(graph.data.file("test.dat"), [graph.style.symbol(graph.style.symbol.circle, symbolattrs=[deco.filled])] ) As another example, if the linewidth of the symbol is too thin for your purposes, you could use something like:: [graph.style.symbol(graph.style.symbol.plus, symbolattrs=[style.linewidth.Thick])] How do I choose the color of the symbols? ----------------------------------------- Colors are not properties of the symbol as such and can therefore not be specified in ``symbolattrs`` directly. The color is rather related to the plotting of the symbol as defined by ``deco.stroked`` or ``deco.filled``. With :: graph.style.symbol(graph.style.symbol.circle, symbolattrs=[deco.stroked([color.rgb.red]), deco.filled([color.rgb.green])] ) you will obtain a circle filled in green with a red borderline. How do I choose the line style? ------------------------------- If you do not want to use symbols, you can set the line style as in this example :: g.plot(graph.data.file("test.dat"), [graph.style.line([style.linewidth.Thin])] ) where the linewidth is set. If you also want to use symbols, you can combine the symbol and the line style as in :: g.plot(graph.data.file("test.dat"), [graph.style.line(lineattrs=[style.linewidth.Thin, style.linestyle.dashed]), graph.style.symbol(graph.style.symbolline.circle, symbolattrs=[deco.filled]) ] ) to plot the symbols on top of a thin, dashed line. You may alter the order of the styles to plot the line on top of the symbols. How can I change the color of symbols or lines according to a palette? ---------------------------------------------------------------------- If several data sets should be plotted in different colors, one can specify in ``symbolattrs`` and/or ``lineattrs`` a palette like ``color.palette.Rainbow``. Equidistant colors are chosen spanning the palette from one end to the other. For example, for three data sets the colors are chosen from the palette at 0, 0.5, and 1. For the rainbow palette, this would correspond to red, green, and blue, respectively. In the following example, symbols vary in form and change their color according to the rainbow palette at the same time as the connecting lines:: mystyle = [graph.style.symbol(graph.style.symbol.changecircle, symbolattrs=[color.palette.Rainbow]), graph.style.line(lineattrs=[color.palette.Rainbow])] See question :ref:`changelist` for a more complete example demonstrating how to use this style definition and for a comment on the necessity of defining ``mystyle`` (you are of course free to choose a different name). .. _changelist: How can I specify changing colors (or other attributes) for symbols or lines? ----------------------------------------------------------------------------- In ``symbolattrs`` and/or ``lineattrs`` so-called changelist can be used. As an example :: mystyle = graph.style.symbol(symbolattrs= [attr.changelist([color.rgb.red, color.rgb.green])]) g.plot(graph.data.file("x.dat", x=1, y=2), [mystyle]) g.plot(graph.data.file("y.dat", x=1, y=2), [mystyle]) g.plot(graph.data.file("z.dat", x=1, y=2), [mystyle]) will switch between red and green symbols each time a new data set is plotted. Several changelists can be specified. They are cycled independently and need not be of the same length. It should be noted that the definition of ``mystyle`` in this example ensures that there is only one instance of the definition of ``symbolattrs``. Putting an explicit definition of ``symbolattrs`` in each call to ``plot`` would not lead to the desired result because each time a new instance would be created which then starts with the first item in the changelist. It may be necessary to repeat attributes in order that several changelists cooperate to produce the desired result. A common situation is that one would like to cycle through a list of symbols which should be used in alternating colors. This can be achieved with the following code:: mystyle = graph.style.symbol( graph.style.symbol.changetriangletwice, symbolattrs=[attr.changelist([color.rgb.red, color.rgb.green])]) which will produce a red triangle, a green triangle, a red circle, a green circle and so on for diamond and square because ``changetriangletwice`` lists each symbol twice. If instead of changing between colors one would like to change between filled and open symbols, one can make use of a predefined changelist :: mystyle = graph.style.symbol( graph.style.symbol.changetriangletwice, symbolattrs=[graph.style.symbol.changefilledstroked]) PyX-0.14.1/faq/python.rst0000644000076500000240000000536312171330402015353 0ustar andrestaff00000000000000====== Python ====== .. _what_is_python: What is Python? =============== From `www.python.org `_: Python is an *interpreted, interactive, object-oriented* programming language. It is often compared to Tcl, Perl, Scheme or Java. Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface. The Python implementation is portable: it runs on many brands of UNIX, on Windows, OS/2, Mac, Amiga, and many other platforms. If your favorite system isn't listed here, it may still be supported, if there's a C compiler for it. Ask around on `comp.lang.python `_ – or just try compiling Python yourself. The Python implementation is `copyrighted `_ but **freely usable and distributable, even for commercial use**. Where can I learn more about Python? ==================================== The place to start is `www.python.org `_ where you will find plenty of information on Python including tutorials. What do I need to import in order to use PyX? ============================================= It is recommended to begin your Python code with:: from pyx import * when using PyX. This allows you for example to write simply ``graph.graphxy`` instead of ``pyx.graph.graphxy``. The following modules will be loaded: ``attr``, ``box``, ``bitmap``, ``canvas``, ``color``, ``connector``, ``deco``, ``deformer``, ``document``, ``epsfile``, ``graph``, ``path``, ``pattern``, ``style``, ``trafo``, ``text``, and ``unit``. For convenience, you might import specific objects of a module like in:: from graph import graphxy which allows you to write ``graphxy()`` instead of ``graph.graphxy()``. All code segments in this document assume that the import line mentioned in the first code snippet is present. What is a raw string and why should I know about it when using PyX? =================================================================== The backslash serves in standard Python strings to start an escape sequence. For example ``\n`` corresponds to a newline character. On the other hand, TeX and LaTeX, which do the typesetting in PyX, use the backslash to indicate the start of a command. In order to avoid the standard interpretation, the string should be marked as a raw string by prepending it by an ``r`` like in:: c.text(0, 0, r"$\alpha\beta\gamma$") PyX-0.14.1/faq/tex_latex.rst0000644000076500000240000003260712255042736016045 0ustar andrestaff00000000000000============= TeX and LaTeX ============= General aspects =============== .. _what_is_tex: What is TeX/LaTeX and why do I need it? --------------------------------------- TeX is a high quality typesetting system developed by Donald E. Knuth which is available for a wide variety of operating systems. LaTeX is a macro package originally developed by Leslie Lamport which makes life with TeX easier, in particular for complex typesetting tasks. The current version of LaTeX is referred to as LaTeX2e and offers e.g. improved font selection as compared to the long outdated LaTeX 2.09 which should no longer be used. All typesetting tasks in PyX are ultimately handed over to TeX (which is the default) or LaTeX, so that PyX cannot do without it. On the other hand, the capabilities of TeX and LaTeX can be used for complex tasks where both graphics and typesetting are needed. .. _intro_tex_latex: I don't know anything about TeX and LaTeX. Where can I read something about it? -------------------------------------------------------------------------------- Take a look at CTAN (cf. :ref:`ctan`) where in `CTAN:info `_ you may be able to find some useful information. There exists for example “A Gentle Introduction to TeX” by M. Doob (`CTAN:gentle/gentle.pdf `_) and “The Not So Short Introduction to LaTeX2e” (`CTAN:info/lshort/english/lshort.pdf `_) by T. Oetiker et al. The latter has been translated into a variety of languages among them korean (which you will not be able to read unless you have appropriate fonts installed) and mongolian. Of course, it is likely that these documents will go way beyond what you will need for generating graphics with PyX so you don't have to read all of it (unless you want to use TeX or LaTeX for typesetting which can be highly recommended). There exists also a number of FAQs on TeX at `CTAN:help `_. .. _ctan: What is CTAN? ------------- CTAN is the *Comprehensive TeX Archive Network* where you will find almost everything related to TeX and friends. The main CTAN server is `www.ctan.org `_ but there exists a large number of mirrors around the world. You can help to reduce the load on the main server by using `mirror.ctan.org `_ which will redirect you to a mirror nearby. A list of known mirrors is available at `http://mirror.ctan.org/README.mirrors `_. In this FAQ, ``CTAN:`` refers to the root of the CTAN tree, e.g. `http://www.ctan.org/tex-archive/ `_. The links to CTAN in this document point to the main server but you might consider using a server closer to you in order to reduce traffic load. Is there support for ConTeXt? ----------------------------- No, and as far as I know there no plans to provide it in the near future. Given the close ties between ConTeXt and MetaPost, ConTeXt users probably prefer to stick with the latter anyway. TeX and LaTeX commands useful for PyX ===================================== How do I get a specific symbol with TeX or LaTeX? ------------------------------------------------- A list of mathematical symbols together with the appropriate command name can be found at `CTAN:info/symbols/math/symbols.pdf `_. A comprehensive list containing almost 6000 symbols for use with LaTeX can be obtained from `CTAN:info/symbols/comprehensive/symbols-a4.pdf `_. In some cases it might be necessary to install fonts or packages available from CTAN (cf. :ref:`ctan`). TeX and LaTeX errors ==================== .. _undefined_usepackage: Undefined control sequence ``\usepackage`` ------------------------------------------ The command ``\usepackage`` is specific to LaTeX. Since by default PyX uses TeX, you have to specify the correct mode:: text.set(mode="latex") Undefined control sequence ``\frac`` The command ``\frac`` is only available in LaTeX. The equivalent to ``\frac{a}{b}`` in TeX is ``{a \over b}``. As an alternative you may ask for the LaTeX mode as explained in :ref:`undefined_usepackage`. Missing ``$`` inserted ---------------------- You have specified TeX- or LaTeX-code which is only valid in math mode. Typical examples are greek symbols, sub- and superscripts or fractions. On the PyX level, you can specify math mode for the whole string by using ``text.mathmode`` as in :: c.text(0, 0, r"{\alpha}", text.mathmode) Keep also in mind that the standard Python interpretation of the backslash as introducing escape sequences needs to be prevented. On the TeX/LaTeX level you should enclose the commands requiring math mode in ``$``'s. As an example, ``$\alpha_i^j$`` will produce a greek letter alpha with a subscript i and a superscript j. The dollar sign thus allows you to specify math mode also for substrings. There exist other ways to specify math mode in TeX and LaTeX which are particularly useful for more complex typesetting tasks. To learn more about it, you should consult the documentation :ref:`intro_tex_latex`. Why do environments like ``itemize`` or ``eqnarray`` seem not to work? ---------------------------------------------------------------------- An itemize environment might result in a LaTeX error complaining about a ``missing \item`` or an eqnarray might lead to a LaTeX message ``missing \endgroup inserted`` even though the syntax appears to be correct. The TeXnical reason is that in PyX text is typeset in left-right mode (LR mode) which does not allow linebreaks to occur. There are two ways out. If the text material should go in a box of given width, a parbox can be used like in the following example:: text.set(mode="latex") c = canvas.canvas() w = 2 c.text(0, 0, r"\begin{itemize}\item a\item b\end{itemize}", [text.parbox(w)]) Occasionally, one would like to have the box in which the text appears to be as small as possible. Then the ``fancybox`` package developed by Timothy Van Zandt is useful which provides several environments like ``Bitemize`` and ``Beqnarray`` which can be processed in LR mode. The relevant part of the code could look like:: text.set(mode="latex") text.preamble(r"\usepackage{fancybox}") c = canvas.canvas() c.text(0, 0, r"\begin{Bitemize}\item a\item b\end{Bitemize}") Other environments provided by the ``fancybox`` package include ``Bcenter``, ``Bflushleft``, ``Bflushright``, ``Benumerate``, and ``Bdescription``. For more details, the documentation of the package should be consulted. .. _fontshape_undefined: Font shape ``OT1/xyz/m/n`` undefined ------------------------------------ You have asked to use font ``xyz`` which is not available. Make sure that you have this font available in Type1 format, i.e. there should be a file ``xyz.pfb`` somewhere. If your TeX system is TDS compliant (TDS=TeX directory structure, cf. `CTAN:tds/draft-standard/tds/tds.pdf `_) you should take a look at the subdirectories of ``$TEXMF/fonts/type1``. File ``…`` is not available or not readable ------------------------------------------- Such an error message might already occur when running the example file ``hello.py`` included in the PyX distribution. Usually, the error occurs due to an overly restrictive umask setting applied when unpacking the ``tar.gz`` sources. This may render the file mentioned in the error message unreadable because the python distutil installation package doesn't change the file permissions back to readable for everyone. If the file exists, the problem can be solved by changing the permissions to allow read access. No information for font ``cmr10`` found in font mapping file ------------------------------------------------------------ Such an error message can already be encountered by simply running the example file ``hello.py`` included in the PyX distribution. The likely reason is that the TeX system does not find the cmr fonts in Type1 format. PyX depends on these fonts as it does not work with the traditional pk fonts which are stored as bitmaps. Therefore, the first thing to make sure is that the cmr Type1 fonts are installed. In some TeX installations, the command ``kpsewhich cmr10.pfb`` will return the appropriate path if the cmr fonts exist in the binary Type1 format (extension ``pfb``) required by PyX. If the command does not work but the TeX system is TDS compliant (:ref:`fontshape_undefined`), a look should be taken at ``$TEXMF/fonts/type1/bluesky/cm`` where ``$TEXMF`` is the root of the ``texmf`` tree. If the Type1 fonts do not exist on the system, they may be obtained from the CTAN (cf. :ref:`ctan`) at `CTAN:fonts/cm/ps-type1/bluesky `_). See the ``README`` for information about who produced these fonts and why they are freely available. If the Type1 fonts exist, the next step is to take a look at ``psfonts.map``. There may be several files with this name on the system, so it is important to find out which one TeX is actually using. ``kpsewhich psfonts.map`` might give this information. The most likely problem is that this file does not contain a line telling TeX what to do if it encounters a request for font ``cmr10``, i.e. the following line may be missing :: cmr10 CMR10 `_ and its subdirectories as well as at the web page `http://home.vr-web.de/was/fonts.html `_ of Walter Schmidt. It is not unlikely that somebody has already done most of the work for you and created the files needed for the font to work properly with LaTeX. But remember: we are talking about commercial fonts here, so do not expect to find the fonts themselves for free. If none of these cases applies, you should spend some time reading manuals about font installation, e.g. `CTAN:macros/latex/doc/fntguide.pdf `_ (of course, I do not expect font wizards to read the last few lines). Can I use a TrueType font with PyX? ----------------------------------- Not directly as PyX only knows how to handle Type1 fonts (although it is possible to get LaTeX to work with TrueType fonts). However, you may use ``ttf2pt1`` (from `ttf2pt1.sourceforge.net `_) to convert a TrueType font into a Type1 font which you then install in your TeX system (cf. :ref:`other_font`). You will loose hinting information in the conversion process but this should not really matter on output devices with not too low resolution. PyX-0.14.1/INSTALL0000644000076500000240000000465312615760433013601 0ustar andrestaff00000000000000Installation ============ Prerequisites ------------- PyX requires Python 3.2 or newer and a TeX installation (including Type1 fonts). Try to start 'python', 'tex' and 'kpsewhich cmr10.pfb' (the latter should issue a full path of the requested Type1 font). Local usage without C extension modules --------------------------------------- PyX can be run without any installation. To test your environment copy the file hello.py from the examples directory to the main pyx directory (where the subdirectory pyx containing the modules is located) and type 'python hello.py'. For debugging, you can call the pyxinfo() method immediately after the import to get some details written to stderr. Installation procedure ---------------------- The installation of PyX is pretty straightforward if you have installed the Python distutils package. First, you have to decide which C extension modules you want to build. This can be done by setting the respective flags in the setup.cfg config file. By default no C extension modules are built and appropriate fallbacks will be used instead. The build_t1code option enables building of an extension module, which enables faster coding/decoding of Type 1 fonts. The only requisites for building this module are the Python header files and a C compiler. Note that the C compiler has to suit the Python distribution you are using. The second extension module pykpathsea provides Python binding for the kpathsea library, which enables fast searching for files in the TeX/LaTeX directory hierarchy. You will need the header files of this library, which unfortunately are not included in many standard TeX distributions. Note that the fallback, which uses the kpsewhich program, works equally well, although it is not as efficient as using the library directly. If you want to build the C extension module, you may also have to specify the location of the kpathsea header files and of the library itself in the setup.cfg file. After you have adapted the setup.cfg file to your needs, you can either build the extension modules locally by running python setup.py build_ext -i or install PyX system wide by using python setup.py install or an appropriate variant thereof. Installation by easy_install or pip ----------------------------------- PyX can be installed via easy_install and pip straightforwardly. It can be run as an zipped egg. As PyX is hosted on PyPI, it can be directly downloaded and installed by pip. PyX-0.14.1/LICENSE0000644000076500000240000003545112037344757013562 0ustar andrestaff00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS PyX-0.14.1/manual/0000755000076500000240000000000012615763300014011 5ustar andrestaff00000000000000PyX-0.14.1/manual/arrows.py0000755000076500000240000000223312255047563015711 0ustar andrestaff00000000000000from pyx import * text.set(text.LatexRunner) text.preamble(r"\renewcommand{\familydefault}{\ttdefault}") c = canvas.canvas() # positioning is quite ugly ... but it works at the moment x = 0 y = 0 dx = 6 dy = -0.65 length = 1.2 def drawdeco(name, showpath=0, default=0): global x,y p = path.path(path.moveto(x + 0.1, y+0.1 ), path.rlineto(length/2.0, 0.3), path.rlineto(length/2.0, -0.3)) c.stroke(p, [style.linewidth.THIck, eval("deco."+name)]) if showpath: c.stroke(p, [style.linewidth.Thin, color.gray.white]) if default: name = name + r"\rm\quad (default)" c.text(x + 1.5, y + 0.15, name, [text.size.footnotesize]) y += dy if y < -16: y = 0 x += dx drawdeco("earrow.Small") drawdeco("earrow.small") drawdeco("earrow.normal") drawdeco("earrow.large") drawdeco("earrow.Large") y += dy drawdeco("barrow.normal") y += dy drawdeco("earrow.Large([deco.filled([color.rgb.red]), style.linewidth.normal])") drawdeco("earrow.normal(constriction=None)") drawdeco("earrow.Large([style.linejoin.round])") drawdeco("earrow.Large([deco.stroked.clear])") c.writePDFfile() PyX-0.14.1/manual/arrows.rst0000644000076500000240000000030212037344751016056 0ustar andrestaff00000000000000 .. _arrows: ******************************* Appendix: Arrows in deco module ******************************* .. _fig_arrows: .. figure:: arrows.* :align: center Arrows in deco module PyX-0.14.1/manual/axis.rst0000644000076500000240000011161012037344751015512 0ustar andrestaff00000000000000 .. module:: graph.axis **** Axes **** Component architecture ====================== Axes are a fundamental component of graphs although there might be applications outside of the graph system. Internally axes are constructed out of components, which handle different tasks axes need to fulfill: axis Implements the conversion of a data value to a graph coordinate of range [0:1]. It does also handle the proper usage of the components in complicated tasks (*i.e.* combine the partitioner, texter, painter and rater to find the best partitioning). An anchoredaxis is a container to combine an axis with an positioner and provide a storage area for all kind of axis data. That way axis instances are reusable (they do not store any data locally). The anchoredaxis and the positioner are created by a graph corresponding to its geometry. tick Ticks are plotted along the axis. They might be labeled with text as well. partitioner, we use "parter" as a short form Creates one or several choices of tick lists suitable to a certain axis range. texter Creates labels for ticks when they are not set manually. painter Responsible for painting the axis. rater Calculate ratings, which can be used to select the best suitable partitioning. positioner Defines the position of an axis. The names above map directly to modules which are provided in the directory :file:`graph/axis` except for the anchoredaxis, which is part of the axis module as well. Sometimes it might be convenient to import the axis directory directly rather than to access iit through the graph. This would look like:: from pyx import * graph.axis.painter() # and the like from pyx.graph import axis axis.painter() # this is shorter ... In most cases different implementations are available through different classes, which can be combined in various ways. There are various axis examples distributed with PyX, where you can see some of the features of the axis with a few lines of code each. Hence we can here directly come to the reference of the available components. .. module:: graph.axis.axis Module :mod:`graph.axis.axis`: Axes =================================== The following classes are part of the module :mod:`graph.axis.axis`. However, there is a shortcut to access those classes via ``graph.axis`` directly. Instances of the following classes can be passed to the *\*\*axes* keyword arguments of a graph. Those instances should only be used once. .. class:: linear(min=None, max=None, reverse=0, divisor=None, title=None, parter=parter.autolinear(), manualticks=[], density=1, maxworse=2, rater=rater.linear(), texter=texter.mixed(), painter=painter.regular(), linkpainter=painter.linked(), fallbackrange=None) This class provides a linear axis. *min* and *max* define the axis range. When not set, they are adjusted automatically by the data to be plotted in the graph. Note, that some data might want to access the range of an axis (*e.g.* the :class:`function` class when no range was provided there) or you need to specify a range when using the axis without plugging it into a graph (*e.g.* when drawing an axis along a path). In cases where the data provides a range of zero (e.g. a when plotting a constant function), then a *fallbackrange* can be set to guarantee a minimal range of the axis. *reverse* can be set to indicate a reversed axis starting with bigger values first. Alternatively you can fix the axis range by *min* and *max* accordingly. When divisor is set, it is taken to divide all data range and position informations while creating ticks. You can create ticks not taking into account a factor by that. *title* is the title of the axis. *parter* is a partitioner instance, which creates suitable ticks for the axis range. Those ticks are merged with ticks manually given by *manualticks* before proceeding with rating, painting *etc.* Manually placed ticks win against those created by the partitioner. For automatic partitioners, which are able to calculate several possible tick lists for a given axis range, the *density* is a (linear) factor to favour more or less ticks. It should not be stressed to much (its likely, that the result would be unappropriate or not at all valid in terms of rating label distances). But within a range of say 0.5 to 2 (even bigger for large graphs) it can help to get less or more ticks than the default would lead to. *maxworse* is the number of trials with more and less ticks when a better rating was already found. *rater* is a rater instance, which rates the ticks and the label distances for being best suitable. It also takes into account *density*. The rater is only needed, when the partitioner creates several tick lists. *texter* is a texter instance. It creates labels for those ticks, which claim to have a label, but do not have a label string set already. Ticks created by partitioners typically receive their label strings by texters. The *painter* is finally used to construct the output. Note, that usually several output constructions are needed, since the rater is also used to rate the distances between the labels for an optimum. The *linkedpainter* is used as the axis painter, when automatic link axes are created by the :meth:`createlinked` method. .. class:: lin(...) This class is an abbreviation of :class:`linear` described above. .. class:: logarithmic(min=None, max=None, reverse=0, divisor=None, title=None, parter=parter.autologarithmic(), manualticks=[], density=1, maxworse=2, rater=rater.logarithmic(), texter=texter.mixed(), painter=painter.regular(), linkpainter=painter.linked(), fallbackrange=None) This class provides a logarithmic axis. All parameters work like :class:`linear`. Only two parameters have a different default: *parter* and *rater*. Furthermore and most importantly, the mapping between data and graph coordinates is logarithmic. .. class:: log(...) This class is an abbreviation of :class:`logarithmic` described above. .. class:: bar(subaxes=None, defaultsubaxis=linear(painter=None, linkpainter=None, parter=None, texter=None), dist=0.5, firstdist=None, lastdist=None, title=None, reverse=0, painter=painter.bar(), linkpainter=painter.linkedbar()) This class provides an axis suitable for a bar style. It handles a discrete set of values and maps them to distinct ranges in graph coordinates. For that, the axis gets a tuple of two values. The first item is taken to be one of the discrete values valid on this axis. The discrete values can be any hashable type and the order of the subaxes is defined by the order the data is received or the inverse of that when *reverse* is set. The second item is passed to the corresponding subaxis. The result of the conversion done by the subaxis is mapped to the graph coordinate range reserved for this subaxis. This range is defined by a size attribute of the subaxis, which can be added to any axis. (see the sized linear axes described below for some axes already having a size argument). When no size information is available for a subaxis, a size value of 1 is used. The baraxis itself calculates its size by suming up the sizes of its subaxes plus *firstdist*, *lastdist* and *dist* times the number of subaxes minus 1. *subaxes* should be a list or a dictionary mapping a discrete value of the bar axis to the corresponding subaxis. When no subaxes are set or data is received for an unknown discrete axis value, instances of defaultsubaxis are used as the subaxis for this discrete value. *dist* is used as the spacing between the ranges for each distinct value. It is measured in the same units as the subaxis results, thus the default value of ``0.5`` means half the width between the distinct values as the width for each distinct value. *firstdist* and *lastdist* are used before the first and after the last value. When set to ``None``, half of *dist* is used. *title* is the title of the split axes and *painter* is a specialized painter for an bar axis and *linkpainter* is used as the painter, when automatic link axes are created by the :meth:`createlinked` method. .. class:: nestedbar(subaxes=None, defaultsubaxis=bar(dist=0, painter=None, linkpainter=None), dist=0.5, firstdist=None, lastdist=None, title=None, reverse=0, painter=painter.bar(), linkpainter=painter.linkedbar()) This class is identical to the bar axis except for the different default value for defaultsubaxis. .. class:: split(subaxes=None, defaultsubaxis=linear(), dist=0.5, firstdist=0, lastdist=0, title=None, reverse=0, painter=painter.split(), linkpainter=painter.linkedsplit()) This class is identical to the bar axis except for the different default value for defaultsubaxis, firstdist, lastdist, painter, and linkedpainter. Sometimes you want to alter the default size of 1 of the subaxes. For that you have to add a size attribute to the axis data. The two classes :class:`sizedlinear` and :class:`autosizedlinear` do that for linear axes. Their short names are :class:`sizedlin` and :class:`autosizedlin`. :class:`sizedlinear` extends the usual linear axis by an first argument *size*. :class:`autosizedlinear` creates the size out of its data range automatically but sets an :class:`autolinear` parter with *extendtick* being ``None`` in order to disable automatic range modifications while painting the axis. The :mod:`axis` module also contains classes implementing so called anchored axes, which combine an axis with an positioner and a storage place for axis related data. Since these features are not interesting for the average PyX user, we'll not go into all the details of their parameters and except for some handy axis position methods: .. class:: anchoredaxis() .. method:: anchoredaxis.basepath(x1=None, x2=None) Returns a path instance for the base path. *x1* and *x2* define the axis range, the base path should cover. For ``None`` the beginning and end of the path is taken, which might cover a longer range, when the axis is embedded as a subaxis. For that case, a ``None`` value extends the range to the point of the middle between two subaxes or the beginning or end of the whole axis, when the subaxis is the first or last of the subaxes. .. method:: anchoredaxis.vbasepath(v1=None, v2=None) Like :meth:`basepath` but in graph coordinates. .. method:: anchoredaxis.gridpath(x) Returns a path instance for the grid path at position *x*. Might return ``None`` when no grid path is available. .. method:: anchoredaxis.vgridpath(v) Like :meth:`gridpath` but in graph coordinates. .. method:: anchoredaxis.tickpoint(x) Returns the position of *x* as a tuple ``(x, y)``. .. method:: anchoredaxis.vtickpoint(v) Like :meth:`tickpoint` but in graph coordinates. .. method:: anchoredaxis.tickdirection(x) Returns the direction of a tick at *x* as a tuple ``(dx, dy)``. The tick direction points inside of the graph. .. method:: anchoredaxis.vtickdirection(v) Like :meth:`tickdirection` but in graph coordinates. .. method:: anchoredaxis.vtickdirection(v) Like :meth:`tickdirection` but in graph coordinates. However, there are two anchored axes implementations :class:`linkedaxis` and :class:`anchoredpathaxis` which are available to the user to create special forms of anchored axes. .. class:: linkedaxis(linkedaxis=None, errorname="manual-linked", painter=_marker) This class implements an anchored axis to be passed to a graph constructor to manually link the axis to another anchored axis instance *linkedaxis*. Note that you can skip setting the value of *linkedaxis* in the constructor, but set it later on by the :meth:`setlinkedaxis` method described below. *errorname* is printed within error messages when the data is used and some problem occurs. *painter* is used for painting the linked axis instead of the *linkedpainter* provided by the *linkedaxis*. .. method:: linkedaxis.setlinkedaxis(linkedaxis) This method can be used to set the *linkedaxis* after constructing the axis. By that you can create several graph instances with cycled linked axes. .. class:: anchoredpathaxis(path, axis, direction=1) This class implements an anchored axis the path *path*. *direction* defines the direction of the ticks. Allowed values are ``1`` (left) and ``-1`` (right). The :class:`anchoredpathaxis` contains as any anchored axis after calling its :meth:`create` method the painted axis in the :attr:`canvas` member attribute. The function :func:`pathaxis` has the same signature like the :class:`anchoredpathaxis` class, but immediately creates the axis and returns the painted axis. .. module:: graph.axis.tick Module :mod:`graph.axis.tick`: Axes ticks ========================================= The following classes are part of the module :mod:`graph.axis.tick`. .. class:: rational(x, power=1, floatprecision=10) This class implements a rational number with infinite precision. For that it stores two integers, the numerator ``num`` and a denominator ``denom``. Note that the implementation of rational number arithmetics is not at all complete and designed for its special use case of axis partitioning in PyX preventing any roundoff errors. *x* is the value of the rational created by a conversion from one of the following input values: * A float. It is converted to a rational with finite precision determined by *floatprecision*. * A string, which is parsed to a rational number with full precision. It is also allowed to provide a fraction like ``"1/3"``. * A sequence of two integers. Those integers are taken as numerator and denominator of the rational. * An instance defining instance variables ``num`` and ``denom`` like :class:`rational` itself. *power* is an integer to calculate ``x**power``. This is useful at certain places in partitioners. .. class:: tick(x, ticklevel=0, labellevel=0, label=None, labelattrs=[], power=1, floatprecision=10) This class implements ticks based on rational numbers. Instances of this class can be passed to the ``manualticks`` parameter of a regular axis. The parameters *x*, *power*, and *floatprecision* share its meaning with :class:`rational`. A tick has a tick level (*i.e.* markers at the axis path) and a label lavel (*e.i.* place text at the axis path), *ticklevel* and *labellevel*. These are non-negative integers or *None*. A value of ``0`` means a regular tick or label, ``1`` stands for a subtick or sublabel, ``2`` for subsubtick or subsublabel and so on. ``None`` means omitting the tick or label. *label* is the text of the label. When not set, it can be created automatically by a texter. *labelattrs* are the attributes for the labels. .. module:: graph.axis.parter Module :mod:`graph.axis.parter`: Axes partitioners ================================================== The following classes are part of the module :mod:`graph.axis.parter`. Instances of the classes can be passed to the parter keyword argument of regular axes. .. class:: linear(tickdists=None, labeldists=None, extendtick=0, extendlabel=None, epsilon=1e-10) Instances of this class creates equally spaced tick lists. The distances between the ticks, subticks, subsubticks *etc.* starting from a tick at zero are given as first, second, third *etc.* item of the list *tickdists*. For a tick position, the lowest level wins, *i.e.* for ``[2, 1]`` even numbers will have ticks whereas subticks are placed at odd integer. The items of *tickdists* might be strings, floats or tuples as described for the *pos* parameter of class :class:`tick`. *labeldists* works equally for placing labels. When *labeldists* is kept ``None``, labels will be placed at each tick position, but sublabels *etc.* will not be used. This copy behaviour is also available *vice versa* and can be disabled by an empty list. *extendtick* can be set to a tick level for including the next tick of that level when the data exceeds the range covered by the ticks by more than *epsilon*. *epsilon* is taken relative to the axis range. *extendtick* is disabled when set to ``None`` or for fixed range axes. *extendlabel* works similar to *extendtick* but for labels. .. class:: lin(...) This class is an abbreviation of :class:`linear` described above. .. class:: autolinear(variants=defaultvariants, extendtick=0, epsilon=1e-10) Instances of this class creates equally spaced tick lists, where the distance between the ticks is adjusted to the range of the axis automatically. Variants are a list of possible choices for *tickdists* of :class:`linear`. Further variants are build out of these by multiplying or dividing all the values by multiples of ``10``. *variants* should be ordered that way, that the number of ticks for a given range will decrease, hence the distances between the ticks should increase within the *variants* list. *extendtick* and *epsilon* have the same meaning as in :class:`linear`. .. attribute:: autolinear.defaultvariants ``[[tick.rational((1, 1)), tick.rational((1, 2))], [tick.rational((2, 1)), tick.rational((1, 1))], [tick.rational((5, 2)), tick.rational((5, 4))], [tick.rational((5, 1)), tick.rational((5, 2))]]`` .. class:: autolin(...) This class is an abbreviation of :class:`autolinear` described above. .. class:: preexp(pres, exp) This is a storage class defining positions of ticks on a logarithmic scale. It contains a list *pres* of positions :math:`p_i` and *exp*, a multiplicator :math:`m`. Valid tick positions are defined by :math:`p_im^n` for any integer :math:`n`. .. class:: logarithmic(tickpreexps=None, labelpreexps=None, extendtick=0, extendlabel=None, epsilon=1e-10) Instances of this class creates tick lists suitable to logarithmic axes. The positions of the ticks, subticks, subsubticks *etc.* are defined by the first, second, third *etc.* item of the list *tickpreexps*, which are all :class:`preexp` instances. *labelpreexps* works equally for placing labels. When *labelpreexps* is kept ``None``, labels will be placed at each tick position, but sublabels *etc.* will not be used. This copy behaviour is also available *vice versa* and can be disabled by an empty list. *extendtick*, *extendlabel* and *epsilon* have the same meaning as in :class:`linear`. Some :class:`preexp` instances for the use in :class:`logarithmic` are available as instance variables (should be used read-only): .. attribute:: logarithmic.pre1exp5 ``preexp([tick.rational((1, 1))], 100000)`` .. attribute:: logarithmic.pre1exp4 ``preexp([tick.rational((1, 1))], 10000)`` .. attribute:: logarithmic.pre1exp3 ``preexp([tick.rational((1, 1))], 1000)`` .. attribute:: logarithmic.pre1exp2 ``preexp([tick.rational((1, 1))], 100)`` .. attribute:: logarithmic.pre1exp ``preexp([tick.rational((1, 1))], 10)`` .. attribute:: logarithmic.pre125exp ``preexp([tick.rational((1, 1)), tick.rational((2, 1)), tick.rational((5, 1))], 10)`` .. attribute:: logarithmic.pre1to9exp ``preexp([tick.rational((1, 1)) for x in range(1, 10)], 10)`` .. class:: log(...) This class is an abbreviation of :class:`logarithmic` described above. .. class:: autologarithmic(variants=defaultvariants, extendtick=0, extendlabel=None, epsilon=1e-10) Instances of this class creates tick lists suitable to logarithmic axes, where the distance between the ticks is adjusted to the range of the axis automatically. Variants are a list of tuples with possible choices for *tickpreexps* and *labelpreexps* of :class:`logarithmic`. *variants* should be ordered that way, that the number of ticks for a given range will decrease within the *variants* list. *extendtick*, *extendlabel* and *epsilon* have the same meaning as in :class:`linear`. .. attribute:: autologarithmic.defaultvariants ``[([log.pre1exp, log.pre1to9exp], [log.pre1exp, log.pre125exp]), ([log.pre1exp, log.pre1to9exp], None), ([log.pre1exp2, log.pre1exp], None), ([log.pre1exp3, log.pre1exp], None), ([log.pre1exp4, log.pre1exp], None), ([log.pre1exp5, log.pre1exp], None)]`` .. class:: autolog(...) This class is an abbreviation of :class:`autologarithmic` described above. .. module:: graph.axis.texter Module :mod:`graph.axis.texter`: Axes texter ============================================ The following classes are part of the module :mod:`graph.axis.texter`. Instances of the classes can be passed to the texter keyword argument of regular axes. Texters are used to define the label text for ticks, which request to have a label, but for which no label text has been specified so far. A typical case are ticks created by partitioners described above. .. class:: decimal(prefix="", infix="", suffix="", equalprecision=0, decimalsep=".", thousandsep="", thousandthpartsep="", plus="", minus="-", period=r"\\overline{%s}", labelattrs=[text.mathmode]) Instances of this class create decimal formatted labels. The strings *prefix*, *infix*, and *suffix* are added to the label at the beginning, immediately after the plus or minus, and at the end, respectively. *decimalsep*, *thousandsep*, and *thousandthpartsep* are strings used to separate integer from fractional part and three-digit groups in the integer and fractional part. The strings *plus* and *minus* are inserted in front of the unsigned value for non-negative and negative numbers, respectively. The format string *period* should generate a period. It must contain one string insert operators ``%s`` for the period. *labelattrs* is a list of attributes to be added to the label attributes given in the painter. It should be used to setup TeX features like ``text.mathmode``. Text format options like ``text.size`` should instead be set at the painter. .. class:: exponential(plus="", minus="-", mantissaexp=r"{{%s}\\cdot10^{%s}}", skipexp0=r"{%s}", skipexp1=None, nomantissaexp=r"{10^{%s}}", minusnomantissaexp=r"{-10^{%s}}", mantissamin=tick.rational((1, 1)), mantissamax=tick.rational((10L, 1)), skipmantissa1=0, skipallmantissa1=1, mantissatexter=decimal()) Instances of this class create decimal formatted labels with an exponential. The strings *plus* and *minus* are inserted in front of the unsigned value of the exponent. The format string *mantissaexp* should generate the exponent. It must contain two string insert operators ``%s``, the first for the mantissa and the second for the exponent. An alternative to the default is ``r"{{%s}{\rm e}{%s}}"``. The format string *skipexp0* is used to skip exponent ``0`` and must contain one string insert operator ``%s`` for the mantissa. ``None`` turns off the special handling of exponent ``0``. The format string *skipexp1* is similar to *skipexp0*, but for exponent ``1``. The format string *nomantissaexp* is used to skip the mantissa ``1`` and must contain one string insert operator ``%s`` for the exponent. ``None`` turns off the special handling of mantissa ``1``. The format string *minusnomantissaexp* is similar to *nomantissaexp*, but for mantissa ``-1``. The :class:`tick.rational` instances *mantissamin*< *mantissamax* are minimum (including) and maximum (excluding) of the mantissa. The boolean *skipmantissa1* enables the skipping of any mantissa equals ``1`` and ``-1``, when *minusnomantissaexp* is set. When the boolean *skipallmantissa1* is set, a mantissa equals ``1`` is skipped only, when all mantissa values are ``1``. Skipping of a mantissa is stronger than the skipping of an exponent. *mantissatexter* is a texter instance for the mantissa. .. class:: mixed(smallestdecimal=tick.rational((1, 1000)), biggestdecimal=tick.rational((9999, 1)), equaldecision=1, decimal=decimal(), exponential=exponential()) Instances of this class create decimal formatted labels with an exponential, when the unsigned values are small or large compared to *1*. The rational instances *smallestdecimal* and *biggestdecimal* are the smallest and biggest decimal values, where the decimal texter should be used. The sign of the value is ignored here. For a tick at zero the decimal texter is considered best as well. *equaldecision* is a boolean to indicate whether the decision for the decimal or exponential texter should be done globally for all ticks. *decimal* and *exponential* are a decimal and an exponential texter instance, respectively. .. class:: rational(prefix="", infix="", suffix="", numprefix="", numinfix="", numsuffix="", denomprefix="", denominfix="", denomsuffix="", plus="", minus="-", minuspos=0, over=r"%s\\over%s", equaldenom=0, skip1=1, skipnum0=1, skipnum1=1, skipdenom1=1, labelattrs=[text.mathmode]) Instances of this class create labels formated as fractions. The strings *prefix*, *infix*, and *suffix* are added to the label at the beginning, immediately after the plus or minus, and at the end, respectively. The strings *numprefix*, *numinfix*, and *numsuffix* are added to the labels numerator accordingly whereas *denomprefix*, *denominfix*, and *denomsuffix* do the same for the denominator. The strings *plus* and *minus* are inserted in front of the unsigned value. The position of the sign is defined by *minuspos* with values ``1`` (at the numerator), ``0`` (in front of the fraction), and ``-1`` (at the denominator). The format string *over* should generate the fraction. It must contain two string insert operators ``%s``, the first for the numerator and the second for the denominator. An alternative to the default is ``"{{%s}/{%s}}"``. Usually, the numerator and denominator are canceled, while, when *equaldenom* is set, the least common multiple of all denominators is used. The boolean *skip1* indicates, that only the prefix, plus or minus, the infix and the suffix should be printed, when the value is ``1`` or ``-1`` and at least one of *prefix*, *infix* and *suffix* is present. The boolean *skipnum0* indicates, that only a ``0`` is printed when the numerator is zero. *skipnum1* is like *skip1* but for the numerator. *skipdenom1* skips the denominator, when it is ``1`` taking into account *denomprefix*, *denominfix*, *denomsuffix* *minuspos* and the sign of the number. *labelattrs* has the same meaning as for *decimal*. .. module:: graph.axis.painter Module :mod:`graph.axis.painter`: Axes painter ============================================== The following classes are part of the module :mod:`graph.axis.painter`. Instances of the painter classes can be passed to the painter keyword argument of regular axes. .. class:: rotatetext(direction, epsilon=1e-10) This helper class is used in direction arguments of the painters below to prevent axis labels and titles being written upside down. In those cases the text will be rotated by 180 degrees. *direction* is an angle to be used relative to the tick direction. *epsilon* is the value by which 90 degrees can be exceeded before an 180 degree rotation is performed. The following two class variables are initialized for the most common applications: .. attribute:: rotatetext.parallel ``rotatetext(90)`` .. attribute:: rotatetext.orthogonal ``rotatetext(180)`` .. class:: ticklength(initial, factor) This helper class provides changeable PyX lengths starting from an initial value *initial* multiplied by *factor* again and again. The resulting lengths are thus a geometric series. There are some class variables initialized with suitable values for tick stroking. They are named ``ticklength.SHORT``, ``ticklength.SHORt``, …, ``ticklength.short``, ``ticklength.normal``, ``ticklength.long``, …, ``ticklength.LONG``. ``ticklength.normal`` is initialized with a length of ``0.12`` and the reciprocal of the golden mean as ``factor`` whereas the others have a modified initial value obtained by multiplication with or division by appropriate multiples of :math:`\sqrt{2}`. .. class:: regular(innerticklength=ticklength.normal, outerticklength=None, tickattrs=[], gridattrs=None, basepathattrs=[], labeldist="0.3 cm", labelattrs=[], labeldirection=None, labelhequalize=0, labelvequalize=1, titledist="0.3 cm", titleattrs=[], titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) Instances of this class are painters for regular axes like linear and logarithmic axes. *innerticklength* and *outerticklength* are visual PyX lengths of the ticks, subticks, subsubticks *etc.* plotted along the axis inside and outside of the graph. Provide changeable attributes to modify the lengths of ticks compared to subticks *etc.* ``None`` turns off the ticks inside and outside the graph, respectively. *tickattrs* and *gridattrs* are changeable stroke attributes for the ticks and the grid, where ``None`` turns off the feature. *basepathattrs* are stroke attributes for the axis or ``None`` to turn it off. *basepathattrs* is merged with ``[style.linecap.square]``. *labeldist* is the distance of the labels from the axis base path as a visual PyX length. *labelattrs* is a list of text attributes for the labels. It is merged with ``[text.halign.center, text.vshift.mathaxis]``. *labeldirection* is an instance of *rotatetext* to rotate the labels relative to the axis tick direction or ``None``. The boolean values *labelhequalize* and *labelvequalize* force an equal alignment of all labels for straight vertical and horizontal axes, respectively. *titledist* is the distance of the title from the rest of the axis as a visual PyX length. *titleattrs* is a list of text attributes for the title. It is merged with ``[text.halign.center, text.vshift.mathaxis]``. *titledirection* is an instance of *rotatetext* to rotate the title relative to the axis tick direction or ``None``. *titlepos* is the position of the title in graph coordinates. *texrunner* is the texrunner instance to create axis text like the axis title or labels. When not set the texrunner of the graph instance is taken to create the text. .. class:: linked(innerticklength=ticklength.short, outerticklength=None, tickattrs=[], gridattrs=None, basepathattrs=[], labeldist="0.3 cm", labelattrs=None, labeldirection=None, labelhequalize=0, labelvequalize=1, titledist="0.3 cm", titleattrs=None, titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) This class is identical to :class:`regular` up to the default values of *labelattrs* and *titleattrs*. By turning off those features, this painter is suitable for linked axes. .. class:: bar(innerticklength=None, outerticklength=None, tickattrs=[], basepathattrs=[], namedist="0.3 cm", nameattrs=[], namedirection=None, namepos=0.5, namehequalize=0, namevequalize=1, titledist="0.3 cm", titleattrs=[], titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) Instances of this class are suitable painters for bar axes. *innerticklength* and *outerticklength* are visual PyX lengths to mark the different bar regions along the axis inside and outside of the graph. ``None`` turns off the ticks inside and outside the graph, respectively. *tickattrs* are stroke attributes for the ticks or ``None`` to turn all ticks off. The parameters with prefix *name* are identical to their *label* counterparts in :class:`regular`. All other parameters have the same meaning as in :class:`regular`. .. class:: linkedbar(innerticklength=None, outerticklength=None, tickattrs=[], basepathattrs=[], namedist="0.3 cm", nameattrs=None, namedirection=None, namepos=0.5, namehequalize=0, namevequalize=1, titledist="0.3 cm", titleattrs=None, titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) This class is identical to :class:`bar` up to the default values of *nameattrs* and *titleattrs*. By turning off those features, this painter is suitable for linked bar axes. .. class:: split(breaklinesdist="0.05 cm", breaklineslength="0.5 cm", breaklinesangle=-60, titledist="0.3 cm", titleattrs=[], titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) Instances of this class are suitable painters for split axes. *breaklinesdist* and *breaklineslength* are the distance between axes break markers in visual PyX lengths. *breaklinesangle* is the angle of the axis break marker with respect to the base path of the axis. All other parameters have the same meaning as in :class:`regular`. .. class:: linkedsplit(breaklinesdist="0.05 cm", breaklineslength="0.5 cm", breaklinesangle=-60, titledist="0.3 cm", titleattrs=None, titledirection=rotatetext.parallel, titlepos=0.5, texrunner=None) This class is identical to :class:`split` up to the default value of *titleattrs*. By turning off this feature, this painter is suitable for linked split axes. .. module:: graph.axis.rater Module :mod:`graph.axis.rater`: Axes rater ========================================== The rating of axes is implemented in :mod:`graph.axis.rater`. When an axis partitioning scheme returns several partitioning possibilities, the partitions need to be rated by a positive number. The axis partitioning rated lowest is considered best. The rating consists of two steps. The first takes into account only the number of ticks, subticks, labels and so on in comparison to optimal numbers. Additionally, the extension of the axis range by ticks and labels is taken into account. This rating leads to a preselection of possible partitions. In the second step, after the layout of preferred partitionings has been calculated, the distance of the labels in a partition is taken into account as well at a smaller weight factor by default. Thereby partitions with overlapping labels will be rejected completely. Exceptionally sparse or dense labels will receive a bad rating as well. .. class:: cube(opt, left=None, right=None, weight=1) Instances of this class provide a number rater. *opt* is the optimal value. When not provided, *left* is set to ``0`` and *right* is set to ``3*opt``. Weight is a multiplicator to the result. The rater calculates ``width*((x-opt)/(other-opt))**3`` to rate the value ``x``, where ``other`` is *left* (``x``<*opt*) or *right* (``x``>*opt*). .. class:: distance(opt, weight=0.1) Instances of this class provide a rater for a list of numbers. The purpose is to rate the distance between label boxes. *opt* is the optimal value. The rater calculates the sum of ``weight*(opt/x-1)`` (``x``<*opt*) or ``weight*(x/opt-1)`` (``x``>*opt*) for all elements ``x`` of the list. It returns this value divided by the number of elements in the list. .. class:: rater(ticks, labels, range, distance) Instances of this class are raters for axes partitionings. *ticks* and *labels* are both lists of number rater instances, where the first items are used for the number of ticks and labels, the second items are used for the number of subticks (including the ticks) and sublabels (including the labels) and so on until the end of the list is reached or no corresponding ticks are available. *range* is a number rater instance which rates the range of the ticks relative to the range of the data. *distance* is an distance rater instance. .. class:: linear(ticks=[cube(4), cube(10, weight=0.5)], labels=[cube(4)], range=cube(1, weight=2), distance=distance("1 cm")) This class is suitable to rate partitionings of linear axes. It is equal to :class:`rater` but defines predefined values for the arguments. .. class:: lin(...) This class is an abbreviation of :class:`linear` described above. .. class:: logarithmic(ticks=[cube(5, right=20), cube(20, right=100, weight=0.5)], labels=[cube(5, right=20), cube(5, right=20, weight=0.5)], range=cube(1, weight=2), distance=distance("1 cm")) This class is suitable to rate partitionings of logarithmic axes. It is equal to :class:`rater` but defines predefined values for the arguments. .. class:: log(...) This class is an abbreviation of :class:`logarithmic` described above. .. module:: graph.axis.positioners Module :mod:`graph.axis.positioner`: Axes positioners ===================================================== The position of an axis is defined by an instance of a class providing the following methods: .. class:: positioner() .. method:: positioner.vbasepath(v1=None, v2=None) Returns a path instance for the base path. *v1* and *v2* define the axis range in graph coordinates the base path should cover. .. method:: positioner.vgridpath(v) Returns a path instance for the grid path at position *v* in graph coordinates. The method might return ``None`` when no grid path is available (for an axis along a path for example). .. method:: positioner.vtickpoint_pt(v) Returns the position of *v* in graph coordinates as a tuple ``(x, y)`` in points. .. method:: positioner.vtickdirection(v) Returns the direction of a tick at *v* in graph coordinates as a tuple ``(dx, dy)``. The tick direction points inside of the graph. The module contains several implementations of those positioners, but since the positioner instances are created by graphs etc. as needed, the details are not interesting for the average PyX user. PyX-0.14.1/manual/bbox.rst0000644000076500000240000001221112037344751015475 0ustar andrestaff00000000000000 .. _bbox_module: .. module:: bbox ****************** Module :mod:`bbox` ****************** The :mod:`bbox`` module contains the definition of the :class:`bbox` class representing bounding boxes of graphical elements like paths, canvases, etc. used in PyX. Usually, you obtain ``bbox`` instances as return values of the corresponding ``bbox())`` method, but you may also construct a bounding box by yourself. :class:`bbox` constructor ========================= The ``bbox`` constructor accepts the following keyword arguments +---------+-----------------------------------------------+ | keyword | description | +=========+===============================================+ | ``llx`` | ``None`` (default) for :math:`-\infty` or | | | :math:`x`\ -position of the lower left corner | | | of the bbox (in user units) | +---------+-----------------------------------------------+ | ``lly`` | ``None`` (default) for :math:`-\infty` or | | | :math:`y`\ -position of the lower left corner | | | of the bbox (in user units) | +---------+-----------------------------------------------+ | ``urx`` | ``None`` (default) for :math:`\infty` or | | | :math:`x`\ -position of the upper right | | | corner of the bbox (in user units) | +---------+-----------------------------------------------+ | ``ury`` | ``None`` (default) for :math:`\infty` or | | | :math:`y`\ -position of the upper right | | | corner of the bbox (in user units) | +---------+-----------------------------------------------+ :class:`bbox` methods ===================== +-------------------------------------------+-----------------------------------------------+ | ``bbox`` method | function | +===========================================+===============================================+ | ``intersects(other)`` | returns ``1`` if the ``bbox`` instance and | | | ``other`` intersect with each other. | +-------------------------------------------+-----------------------------------------------+ | ``transformed(self, trafo)`` | returns ``self`` transformed by | | | transformation ``trafo``. | +-------------------------------------------+-----------------------------------------------+ | ``enlarged(all=0, bottom=None, left=None, | return the bounding box enlarged by the given | | top=None, right=None)`` | amount (in visual units). ``all`` is the | | | default for all other directions, which is | | | used whenever ``None`` is given for the | | | corresponding direction. | +-------------------------------------------+-----------------------------------------------+ | ``path()`` or ``rect()`` | return the ``path`` corresponding to the | | | bounding box rectangle. | +-------------------------------------------+-----------------------------------------------+ | ``height()`` | returns the height of the bounding box (in | | | PyX lengths). | +-------------------------------------------+-----------------------------------------------+ | ``width()`` | returns the width of the bounding box (in PyX | | | lengths). | +-------------------------------------------+-----------------------------------------------+ | ``top()`` | returns the :math:`y`\ -position of the top | | | of the bounding box (in PyX lengths). | +-------------------------------------------+-----------------------------------------------+ | ``bottom()`` | returns the :math:`y`\ -position of the | | | bottom of the bounding box (in PyX lengths). | +-------------------------------------------+-----------------------------------------------+ | ``left()`` | returns the :math:`x`\ -position of the left | | | side of the bounding box (in PyX lengths). | +-------------------------------------------+-----------------------------------------------+ | ``right()`` | returns the :math:`x`\ -position of the right | | | side of the bounding box (in PyX lengths). | +-------------------------------------------+-----------------------------------------------+ Furthermore, two bounding boxes can be added (giving the bounding box enclosing both) and multiplied (giving the intersection of both bounding boxes). PyX-0.14.1/manual/bitmap.py0000644000076500000240000000062312171066303015634 0ustar andrestaff00000000000000from pyx import * image_bw = bitmap.image(2, 2, "L", b"\0\377\377\0") image_rgb = bitmap.image(3, 2, "RGB", b"\77\77\77\177\177\177\277\277\277" b"\377\0\0\0\377\0\0\0\377") bitmap_bw = bitmap.bitmap(0, 1, image_bw, height=0.8) bitmap_rgb = bitmap.bitmap(0, 0, image_rgb, height=0.8) c = canvas.canvas() c.insert(bitmap_bw) c.insert(bitmap_rgb) c.writePDFfile() PyX-0.14.1/manual/bitmap.rst0000644000076500000240000001416212037344751016026 0ustar andrestaff00000000000000 ******* Bitmaps ******* Introduction ============ PyX focuses on the creation of scaleable vector graphics. However, PyX also allows for the output of bitmap images. Still, the support for creation and handling of bitmap images is quite limited. On the other hand the interfaces are built that way, that its trivial to combine PyX with the "Python Image Library", also known as "PIL". The creation of a bitmap can be performed out of some unpacked binary data by first creating image instances:: from pyx import * image_bw = bitmap.image(2, 2, "L", "\0\377\377\0") image_rgb = bitmap.image(3, 2, "RGB", "\77\77\77\177\177\177\277\277\277" "\377\0\0\0\377\0\0\0\377") Now ``image_bw`` is a :math:`2\times2` grayscale image. The bitmap data is provided by a string, which contains two black (``"\0" == chr(0)``) and two white (``"\377" == chr(255)``) pixels. Currently the values per (colour) channel is fixed to 8 bits. The coloured image ``image_rgb`` has :math:`3\times2` pixels containing a row of 3 different gray values and a row of the three colours red, green, and blue. The images can then be wrapped into ``bitmap`` instances by:: bitmap_bw = bitmap.bitmap(0, 1, image_bw, height=0.8) bitmap_rgb = bitmap.bitmap(0, 0, image_rgb, height=0.8) When constructing a ``bitmap`` instance you have to specify a certain position by the first two arguments fixing the bitmaps lower left corner. Some optional arguments control further properties. Since in this example there is no information about the dpi-value of the images, we have to specify at least a ``width`` or a ``height`` of the bitmap. The bitmaps are now to be inserted into a canvas:: c = canvas.canvas() c.insert(bitmap_bw) c.insert(bitmap_rgb) c.writeEPSfile("bitmap") Figure :ref:`fig_bitmap` shows the resulting output. .. _fig_bitmap: .. figure:: bitmap.* :align: center An introductory bitmap example. .. module:: bitmap Bitmap :mod:`module`: Bitmap support ==================================== .. class:: image(width, height, mode, data, compressed=None) This class is a container for image data. *width* and *height* are the size of the image in pixel. *mode* is one of ``"L"``, ``" RGB"`` or ``"CMYK"`` for grayscale, rgb, or cmyk colours, respectively. *data* is the bitmap data as a string, where each single character represents a colour value with ordinal range ``0`` to ``255``. Each pixel is described by the appropriate number of colour components according to *mode*. The pixels are listed row by row one after the other starting at the upper left corner of the image. *compressed* might be set to ``" Flate"`` or ``"DCT"`` to provide already compressed data. Note that those data will be passed to PostScript without further checks, *i.e.* this option is for experts only. .. class:: jpegimage(file) This class is specialized to read data from a JPEG/JFIF-file. *file* is either an open file handle (it only has to provide a :meth:`read` method; the file should be opened in binary mode) or a string. In the latter case :class:`jpegimage` will try to open a file named like *file* for reading. The contents of the file is checked for some JPEG/JFIF format markers in order to identify the size and dpi resolution of the image for further usage. These checks will typically fail for invalid data. The data are not uncompressed, but directly inserted into the output stream (for invalid data the result will be invalid PostScript). Thus there is no quality loss by recompressing the data as it would occur when recompressing the uncompressed stream with the lossy jpeg compression method. .. class:: bitmap(xpos, ypos, image, width=None, height=None, ratio=None, storedata=0, maxstrlen=4093, compressmode="Flate", flatecompresslevel=6, dctquality=75, dctoptimize=1, dctprogression=0) *xpos* and *ypos* are the position of the lower left corner of the image. This position might be modified by some additional transformations when inserting the bitmap into a canvas. *image* is an instance of :class:`image` or :class:`jpegimage` but it can also be an image instance from the "Python Image Library". *width*, *height*, and *ratio* adjust the size of the image. At least *width* or *height* needs to be given, when no dpi information is available from *image*. *storedata* is a flag indicating, that the (still compressed) image data should be put into the printers memory instead of writing it as a stream into the PostScript file. While this feature consumes memory of the PostScript interpreter, it allows for multiple usage of the image without including the image data several times in the PostScript file. *maxstrlen* defines a maximal string length when *storedata* is enabled. Since the data must be kept in the PostScript interpreters memory, it is stored in strings. While most interpreters do not allow for an arbitrary string length (a common limit is 65535 characters), a limit for the string length is set. When more data need to be stored, a list of strings will be used. Note that lists are also subject to some implementation limits. Since a typical value is 65535 entries, in combination a huge amount of memory can be used. Valid values for *compressmode* currently are ``"Flate"`` (zlib compression), ``"DCT"`` (jpeg compression), or ``None`` (disabling the compression). The zlib compression makes use of the zlib module as it is part of the standard Python distribution. The jpeg compression is available for those *image* instances only, which support the creation of a jpeg-compressed stream, *e.g.* images from the "Python Image Library" with jpeg support installed. The compression must be disabled when the image data is already compressed. *flatecompresslevel* is a parameter of the zlib compression. *dctquality*, *dctoptimize*, and *dctprogression* are parameters of the jpeg compression. Note, that the progression feature of the jpeg compression should be turned off in order to produce valid PostScript. Also the optimization feature is known to produce errors on certain printers. PyX-0.14.1/manual/box.rst0000644000076500000240000001047612037344751015346 0ustar andrestaff00000000000000 .. module:: box ************************************** Module :mod:`box`: Convex box handling ************************************** This module has a quite internal character, but might still be useful from the users point of view. It might also get further enhanced to cover a broader range of standard arranging problems. In the context of this module a box is a convex polygon having optionally a center coordinate, which plays an important role for the box alignment. The center might not at all be central, but it should be within the box. The convexity is necessary in order to keep the problems to be solved by this module quite a bit easier and unambiguous. Directions (for the alignment etc.) are usually provided as pairs (dx, dy) within this module. It is required, that at least one of these two numbers is unequal to zero. No further assumptions are taken. Polygon ======= A polygon is the most general case of a box. It is an instance of the class ``polygon``. The constructor takes a list of points (which are (x, y) tuples) in the keyword argument ``corners`` and optionally another (x, y) tuple as the keyword argument ``center``. The corners have to be ordered counterclockwise. In the following list some methods of this ``polygon`` class are explained: ``path(centerradius=None, bezierradius=None, beziersoftness=1)``: returns a path of the box; the center might be marked by a small circle of radius ``centerradius``; the corners might be rounded using the parameters ``bezierradius`` and ``beziersoftness``. For each corner of the box there may be one value for beziersoftness and two bezierradii. For convenience, it is not necessary to specify the whole list (for beziersoftness) and the whole list of lists (bezierradius) here. You may give a single value and/or a 2-tuple instead. ``transform(*trafos)``: performs a list of transformations to the box ``reltransform(*trafos)``: performs a list of transformations to the box relative to the box center .. _fig_boxalign: .. figure:: boxalign.* :align: center circle and line alignment examples (equal direction and distance) ``circlealignvector(a, dx, dy)``: returns a vector (a tuple (x, y)) to align the box at a circle with radius ``a`` in the direction (``dx``, ``dy``); see figure :ref:`fig_boxalign` ``linealignvector(a, dx, dy)``: as above, but align at a line with distance ``a`` ``circlealign(a, dx, dy)``: as circlealignvector, but perform the alignment instead of returning the vector ``linealign(a, dx, dy)``: as linealignvector, but perform the alignment instead of returning the vector ``extent(dx, dy)``: extent of the box in the direction (``dx``, ``dy``) ``pointdistance(x, y)``: distance of the point (``x``, ``y``) to the box; the point must be outside of the box ``boxdistance(other)``: distance of the box to the box ``other``; when the boxes are overlapping, ``BoxCrossError`` is raised ``bbox()``: returns a bounding box instance appropriate to the box Functions working on a box list =============================== ``circlealignequal(boxes, a, dx, dy)``: Performs a circle alignment of the boxes ``boxes`` using the parameters ``a``, ``dx``, and ``dy`` as in the ``circlealign`` method. For the length of the alignment vector its largest value is taken for all cases. ``linealignequal(boxes, a, dx, dy)``: as above, but performing a line alignment ``tile(boxes, a, dx, dy)``: tiles the boxes ``boxes`` with a distance ``a`` between the boxes (in addition the maximal box extent in the given direction (``dx``, ``dy``) is taken into account) Rectangular boxes ================= For easier creation of rectangular boxes, the module provides the specialized class ``rect``. Its constructor first takes four parameters, namely the x, y position and the box width and height. Additionally, for the definition of the position of the center, two keyword arguments are available. The parameter ``relcenter`` takes a tuple containing a relative x, y position of the center (they are relative to the box extent, thus values between ``0`` and ``1`` should be used). The parameter ``abscenter`` takes a tuple containing the x and y position of the center. This values are measured with respect to the lower left corner of the box. By default, the center of the rectangular box is set to this lower left corner. PyX-0.14.1/manual/boxalign.py0000644000076500000240000000144512037344751016175 0ustar andrestaff00000000000000import math from pyx import * c = canvas.canvas() t1 = text.text(0, 0, "circle align", [text.halign.center, text.size.huge]) x, y = t1.circlealignvector(1, 1, 1) t1.circlealign(1, 1, 1) c.stroke(path.path(path.arc(0, 0, 1, -30, 120)), [style.linestyle.dashed]) c.stroke(t1.path(centerradius=0.05), [style.linewidth.THin]) c.stroke(path.line(0, 0, x, y), [deco.earrow.normal]) c.insert(t1) t2 = text.text(5, 0, "line align", [text.halign.center, text.size.huge]) x, y = t2.linealignvector(1, 1, 1) t2.linealign(1, 1, 1) c.stroke(path.line(5 + 1.5 * math.sqrt(2), -0.5 * math.sqrt(2), 5 - 0.5 * math.sqrt(2), 1.5 * math.sqrt(2)), [style.linestyle.dashed]) c.stroke(t2.path(centerradius=0.05), [style.linewidth.THin]) c.stroke(path.line(5, 0, 5 + x, y), [deco.earrow.normal]) c.insert(t2) c.writePDFfile() PyX-0.14.1/manual/canvas.rst0000644000076500000240000001642212520510552016015 0ustar andrestaff00000000000000 .. module:: canvas ==================== Module :mod:`canvas` ==================== .. sectionauthor:: Jörg Lehmann In addition it contains the class ``canvas.clip`` which allows clipping of the output. Class :class:`canvas` --------------------- This is the basic class of the canvas module. Instances of this class collect visual elements like paths, other canvases, TeX or LaTeX elements. A canvas may also be embedded in another one using its ``insert`` method. This may be useful when you want to apply a transformation on a whole set of operations. .. class:: canvas(attrs=[], texrunner=None, ipython_bboxenlarge=1*unit.t_pt) Construct a new canvas, applying the given *attrs*, which can be instances of :class:`trafo.trafo`, :class:`canvas.clip`, :class:`style.strokestyle` or :class:`style.fillstyle`. The *texrunner* argument can be used to specify the texrunner instance used for the :meth:`text` method of the canvas. If not specified, it defaults to *text.defaulttexrunner*. *ipython_bboxenlarge* defines the `bboxenlarge` :class:`document.page` for IPython's `_repr_png_` and `_repr_svg_`. Paths can be drawn on the canvas using one of the following methods: .. method:: canvas.draw(path, attrs) Draws *path* on the canvas applying the given *attrs*. Depending on the *attrs* the path will be filled, stroked, ornamented, or a combination thereof. For the common first two cases the following two convenience functions are provided. .. method:: canvas.fill(path, attrs=[]) Fills the given *path* on the canvas applying the given *attrs*. .. method:: canvas.stroke(path, attrs=[]) Strokes the given *path* on the canvas applying the given *attrs*. Arbitrary allowed elements like other :class:`canvas` instances can be inserted in the canvas using .. method:: canvas.insert(item, attrs=[]) Inserts an instance of :class:`base.canvasitem` into the canvas. If *attrs* are present, *item* is inserted into a new :class:`canvas` instance with *attrs* as arguments passed to its constructor. Then this :class:`canvas` instance is inserted itself into the canvas. Text output on the canvas is possible using .. method:: canvas.text(x, y, text, attrs=[]) Inserts *text* at position (*x*, *y*) into the canvas applying *attrs*. This is a shortcut for ``insert(texrunner.text(x, y, text, attrs))``. To group drawing operations, layers can be used: .. method:: canvas.layer( name, above=None, below=None) This method creates or gets a layer with name *name*. A layer is a canvas itself and can be used to combine drawing operations for ordering purposes, i.e., what is above and below each other. The layer name *name* is a dotted string, where dots are used to form a hierarchy of layer groups. When inserting a layer, it is put on top of its layer group except when another layer instance of this group is specified by means of the parameters *above* or *below*. The :class:`canvas` class provides access to the total geometrical size of its element: .. method:: canvas.bbox() Returns the bounding box enclosing all elements of the canvas (see Sect. :mod:`bbox`). A canvas also allows to set its TeX runner: .. method:: canvas.settexrunner(texrunner) Sets a new *texrunner* for the canvas. The contents of the canvas can be written to a file using the following convenience methods, which wrap the canvas into a single page document. .. method:: canvas.writeEPSfile(file, **kwargs) Writes the canvas to *file* using the EPS format. *file* either has to provide a write method or it is used as a string containing the filename (the extension ``.eps`` is appended automatically, if it is not present). This method constructs a single page document, passing *kwargs* to the :class:`document.page` constructor for all *kwargs* starting with ``page_`` (without this prefix) and calls the :meth:`writeEPSfile` method of this :class:`document.document` instance passing the *file* and all *kwargs* starting with ``write_`` (without this prefix). .. method:: canvas.writePSfile(file, *args, **kwargs) Similar to :meth:`writeEPSfile` but using the PS format. .. method:: canvas.writePDFfile(file, *args, **kwargs) Similar to :meth:`writeEPSfile` but using the PDF format. .. method:: canvas.writeSVGfile(file, *args, **kwargs) Similar to :meth:`writeEPSfile` but using the SVG format. .. method:: canvas.writetofile(filename, *args, **kwargs) Determine the file type (EPS, PS, PDF, or SVG) from the file extension of *filename* and call the corresponding write method with the given arguments *arg* and *kwargs*. .. method:: canvas.pipeGS(device, resolution=100, gs="gs", gsoptions=[], textalphabits=4, graphicsalphabits=4, ciecolor=False, input="eps", **kwargs) This method pipes the content of a canvas to the ghostscript interpreter to generate other output formats. The output is returned by means of a python BytesIO object. *device* specifies a ghostscript output device by a string. Depending on the ghostscript configuration ``"png16"``, ``"png16m"``, ``"png256"``, ``"png48"``, ``"pngalpha"``, ``"pnggray"``, ``"pngmono"``, ``"jpeg"``, and ``"jpeggray"`` might be available among others. See the output of ``gs --help`` and the ghostscript documentation for more information. *resolution* specifies the resolution in dpi (dots per inch). *gs* is the name of the ghostscript executable. *gsoptions* is a list of additional options passed to the ghostscript interpreter. *textalphabits* and *graphicsalphabits* are convenient parameters to set the ``TextAlphaBits`` and ``GraphicsAlphaBits`` options of ghostscript. The addition of these options can be skipped by setting their values to ``None``. *ciecolor* adds the ``-dUseCIEColor`` flag to improve the CMYK to RGB color conversion. *input* can be either ``"eps"`` or ``"pdf"`` to select the input type to be passed to ghostscript (note slightly different features available in the different input types regarding e.g. :mod:`epsfile` inclusion and transparency). *kwargs* are passed to the :meth:`writeEPSfile` method (not counting the *file* parameter), which is used to generate the input for ghostscript. By that you gain access to the :class:`document.page` constructor arguments. .. method:: canvas.writeGSfile(filename=None, device=None, **kwargs) This method is similar to pipeGS, but the content is written into the file *filename*. If filename is None it is auto-guessed from the script name. If filename is "-", the output is written to stdout. In both cases, a device needs to be specified to define the format (and the file suffix in case the filename is created from the script name). If device is None, but a filename with suffix is given, PNG files will be written using the png16m device and JPG files using the jpeg device. All other arguments are identical to those of the :meth:`canvas.pipeGS`. For more information about the possible arguments of the :class:`document.page` constructor, we refer to Sect. :mod:`document`. Class :class:`clip` --------------------- In addition the canvas module contains the class ``canvas.clip`` which allows for clipping of the output by passing a clipping instance to the attrs parameter of the canvas constructor. PyX-0.14.1/manual/color.py0000755000076500000240000000037212171066315015505 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() c.fill(path.rect(0, 0, 7, 3), [color.gray(0.8)]) c.fill(path.rect(1, 1, 1, 1), [color.rgb.red]) c.fill(path.rect(3, 1, 1, 1), [color.rgb.green]) c.fill(path.rect(5, 1, 1, 1), [color.rgb.blue]) c.writePDFfile() PyX-0.14.1/manual/color.rst0000644000076500000240000001045512177005275015671 0ustar andrestaff00000000000000 .. module:: color ******************* Module :mod:`color` ******************* Color models ============ PostScript provides different color models. They are available to PyX by different color classes, which just pass the colors down to the PostScript level. This implies, that there are no conversion routines between different color models available. However, some color model conversion routines are included in Python's standard library in the module ``colorsym``. Furthermore also the comparison of colors within a color model is not supported, but might be added in future versions at least for checking color identity and for ordering gray colors. There is a class for each of the supported color models, namely ``gray``, ``rgb``, ``cmyk``, and ``hsb``. The constructors take variables appropriate for the color model. Additionally, a list of named colors is given in appendix :ref:`colorname`. Example ======= :: from pyx import * c = canvas.canvas() c.fill(path.rect(0, 0, 7, 3), [color.gray(0.8)]) c.fill(path.rect(1, 1, 1, 1), [color.rgb.red]) c.fill(path.rect(3, 1, 1, 1), [color.rgb.green]) c.fill(path.rect(5, 1, 1, 1), [color.rgb.blue]) c.writeEPSfile("color") The file ``color.eps`` is created and looks like: .. _fig_color: .. figure:: color.* :align: center Color example Color gradients =============== The color module provides a class :class:`gradient` for continous transitions between colors. A list of named gradients is available in appendix :ref:`gradientname`. Note that all predefined non-gray gradients are defined in the RGB color space, except for `gradient.Rainbow`, `gradient.ReverseRainbow`, `gradient.Hue`, and `gradient.ReverseHue`, which are naturally defined in the HSB color space. Converted RGB and CMYK versions of these latter gradients are also defined under the names `rgbgradient.Rainbow` and `cmykgradient.Rainbow`, etc. .. class:: gradient() This class defines the methods for the ``gradient``. .. function:: getcolor(parameter) Returns the color that corresponds to *parameter* (must be between *min* and *max*). .. function:: select(index, n_indices) When a total number of *n_indices* different colors is needed from the gradient, this method returns the *index*-th color. .. class:: functiongradient_cmyk(f_c, f_m, f_y, f_k) .. class:: functiongradient_gray(f_gray) .. class:: functiongradient_hsb(f_g, f_s, f_b) .. class:: functiongradient_rgb(f_r, f_g, f_b) This class provides an arbitray transition between colors of the same color model. The functions *f_c*, etc. map the values [0, 1] to the respective components of the color model. .. function:: lineargradient_cmyk(mincolor, maxcolor) .. function:: lineargradient_gray(mincolor, maxcolor) .. function:: lineargradient_hsb(mincolor, maxcolor) .. function:: lineargradient_rgb(mincolor, maxcolor) These factory functors for the corresponding *functiongradient_* classes provide a linear transition between two given instances of the same color class. The linear interpolation is performed on the color components of the specific color model. *mincolor* and *maxcolor* must be colors of the corresponding color class. .. class:: class rgbgradient(gradient) This class takes an arbitrary gradient and converts it into one in the RGB color model. This is useful for instance in bitmap output, where only certain color models are supported in Postscript/PDF. .. class:: class cmykgradient(gradient) This class takes an arbitrary gradient and converts it into one in the CMYK color mode. This is useful for instance in bitmap output, where only certain color models are supported in Postscript/PDF. Transparency ============ .. class:: transparency(value) Instances of this class will make drawing operations (stroking, filling) to become partially transparent. *value* defines the transparency factor in the range ``0`` (opaque) to ``1`` (transparent). Transparency is available in PDF output only since it is not supported by PostScript. However, for certain ghostscript devices (for example the pdf backend as used by ps2pdf) proprietary PostScript extension allows for transparency in PostScript code too. PyX creates such PostScript proprietary code, but issues a warning when doing so. PyX-0.14.1/manual/colorname.py0000755000076500000240000000316412255047625016356 0ustar andrestaff00000000000000#!/usr/bin/env python import imp, re import pyx from pyx import * text.set(text.LatexRunner) text.preamble(r"\renewcommand{\familydefault}{\ttdefault}") c = canvas.canvas() # positioning is quite ugly ... but it works at the moment x = 0 y = 0 dx = 4.8 dy = -0.65 lastmodel = 0 # we could use (gray|rgb|cmyk).__dict__ to get the instances, but we # would loose the ordering ... instead we just parse the file: # TODO: code something along the lines of c.l.p post cbs38g$2kp$04$1@news.t-online.com p = re.compile("(?P(?P[a-z]+)\\.(?P[a-z]+)) += (?P=model)\\([0-9\\., ]+\\)\n", re.IGNORECASE) lines = imp.find_module("color", pyx.__path__)[0].readlines() for line in lines: # we yet don't use a file iterator m = p.match(line) if m: if lastmodel and (m.group("model") != lastmodel): y += dy myc = pyx.color.__dict__[m.group("model")].__dict__[m.group("name")] c.stroke(path.line(x + 0.1, y + 0.1, x + 0.4, y + 0.4), [myc]) c.stroke(path.line(x + 0.4, y + 0.1, x + 0.1, y + 0.4), [myc]) c.fill(path.rect(x + 0.5, y, 1, 0.5), [myc]) c.stroke(path.line(x + 0.6, y + 0.1, x + 0.9, y + 0.4), [color.gray.black]) c.stroke(path.line(x + 0.9, y + 0.1, x + 0.6, y + 0.4), [color.gray.black]) c.stroke(path.line(x + 1.1, y + 0.1, x + 1.4, y + 0.4), [color.gray.white]) c.stroke(path.line(x + 1.4, y + 0.1, x + 1.1, y + 0.4), [color.gray.white]) c.text(x + 1.7, y + 0.15, m.group("id"), [text.size.footnotesize]) y += dy lastmodel = m.group("model") if y < -16.5: y = 0 x += dx c.writePDFfile() PyX-0.14.1/manual/colorname.rst0000644000076500000240000000024712037344751016530 0ustar andrestaff00000000000000 .. _colorname: ********************** Appendix: Named colors ********************** .. _fig_colorname: .. figure:: colorname.* :align: center Names colors PyX-0.14.1/manual/conf.py0000644000076500000240000002306712534606642015325 0ustar andrestaff00000000000000# -*- coding: utf-8 -*- # # PyX documentation build configuration file, created by # sphinx-quickstart on Thu May 19 17:32:57 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 sys.path.insert(0, '../pyx') sys.path.insert(0, '..') import pyx.version # 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.mathjax', 'sphinx.ext.todo', '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 = 'manual' # General information about the project. project = 'PyX' copyright = pyx.version.date.split('/')[0] + ', Jörg Lehmann, Michael Schindler, André Wobst' # 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 = '.'.join(pyx.version.version.split('.')[:1]) # The full version, including alpha/beta/rc tags. release = pyx.version.version # 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 = pyx.version.date # 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 = 'pyx' # 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 = {'sidebarwidth': 200} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['theme'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'PyX %s Manual' % release # 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 = [] # 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 = {} html_sidebars = { '**': ['localtoc.html', 'sourcelink.html', 'searchbox.html'] } # 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 = 'PyXdoc' todo_include_todos = True # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). latex_paper_size = 'a4' # 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 = [ ('manual', 'manual.tex', 'PyX Manual', 'Jörg Lehmann, Michael Schindler, André Wobst', '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 = r''' \hypersetup{pdftitle={PyX Manual}, pdfauthor={Joerg Lehmann , Michael Schindler , Andre Wobst }, pdfsubject={PyX Manual}, pdfkeywords={PyX, graphics, manual}} ''' # 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 = [ ('manual', 'pyx', 'PyX Manual', ['Jörg Lehmann, Michael Schindler, André Wobst'], 1) ] # -- Other options ------------------------------------------------------------ mathjax_path = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default' todo_include_todos = True autoclass_content = 'both' autodoc_member_order = 'bysource' # -- unprocessed function signature extractor ---------------------------------- # This feature is not robust. It does not parse the code properly, removes # comments and whitespace doubtfully, requires '):' without space for # termination, etc. import inspect def function_signature_lines(lines): # extract the lines of the function definition removing comments # and stripping spaces for line in lines: code = line.split("#", 1)[0].strip() yield code if code.endswith("):"): break def unprocessed_function_signature(app, what, name, obj, options, sig, retann): # extract the unprocessed signature from the source if what not in ["class", "method", "staticmethod", "function"]: return if what == "class": # get the constructor (code copied from autodoc) obj = getattr(obj, "__init__", None) if obj is None or obj is object.__init__ or not \ (inspect.ismethod(obj) or inspect.isfunction(obj)): return elif hasattr(obj, '__wrapped__'): obj = obj.__wrapped__ src, line = inspect.findsource(obj) code = " ".join(function_signature_lines(src[line:])).split("(", 1)[1][:-2] if code.startswith("self, "): code = code[6:] elif code == "self": code = "" return "({})".format(code), retann def remove_default_constructor_docstring(app, what, name, obj, options, lines): # remove default constructor docstring, i.e. when no own constructor is defined for i, line in enumerate(lines): lines[i] = line.replace("x.__init__(...) initializes x; see help(type(x)) for signature", "") def setup(app): app.connect('autodoc-process-signature', unprocessed_function_signature) app.connect('autodoc-process-docstring', remove_default_constructor_docstring) PyX-0.14.1/manual/connector.py0000755000076500000240000001155012171066365016366 0ustar andrestaff00000000000000from math import * from pyx import * try: from math import radians, degrees except ImportError: # fallback implementation for Python 2.1 def radians(x): return x*pi/180 def degrees(x): return x*180/pi startbox = box.polygon(corners=[[0,-0.6], [0.5,0.1], [-0.25,0.1]]) endbox = box.polygon(corners=[[4.5,3.9], [5.5,4.0], [5.2,3.4]]) # the arc connector <<< c1 = canvas.canvas() for b in [startbox, endbox]: c1.stroke(b.path(), [style.linewidth.Thick, style.linejoin.round]) c1.fill(path.circle_pt(b.center[0], b.center[1], 2)) absangle = degrees(atan2(endbox.center[1] - startbox.center[1], endbox.center[0] - startbox.center[0])) relangle = 60 len = 2 # the direct connection direct = path.line_pt(startbox.center[0], startbox.center[1], endbox.center[0], endbox.center[1]) c1.stroke(direct, [style.linestyle.dashed]) # the arc connector l = connector.arc(startbox, endbox, relangle=relangle, boxdists=[0.0,0.0]) c1.stroke(l, [style.linewidth.Thick, color.rgb.red, deco.earrow.Large]) # the relangle parameter comp1 = path.path(path.moveto(*direct.atbegin()), path.rlineto(len*cos(radians(absangle + relangle)), len*sin(radians(absangle + relangle)))) c1.stroke(comp1) ang = path.path(path.arc(direct.atbegin()[0], direct.atbegin()[1], 0.8*len, absangle, absangle+relangle)) c1.stroke(ang, [deco.earrow.large]) pos = ang.at(0.5*ang.arclen()) c1.text(pos[0], pos[1], r"~relangle", [text.halign.left]) # the bulge parameter bulge = 0.5 * direct.arclen() * tan(0.5*radians(relangle)) bul = path.path(path.moveto(*direct.at(0.5*direct.arclen())), path.rlineto(bulge * cos(radians(absangle+90)), bulge * sin(radians(absangle+90)))) c1.stroke(bul, [deco.earrow.large]) pos = bul.at(0.5*bul.arclen()) c1.text(pos[0], pos[1], r"~(rel)bulge", [text.halign.left]) # >>> # the curve connector <<< c2 = canvas.canvas() for b in [startbox, endbox]: c2.stroke(b.path(), [style.linewidth.Thick, style.linejoin.round]) c2.fill(path.circle_pt(b.center[0], b.center[1], 2)) absangle = degrees(atan2(endbox.center[1] - startbox.center[1], endbox.center[0] - startbox.center[0])) relangle1 = 60 relangle2 = 30 absbulge = 0 relbulge = 0.5 len = 2 # the direct connection direct = path.line_pt(startbox.center[0], startbox.center[1], endbox.center[0], endbox.center[1]) c2.stroke(direct, [style.linestyle.dashed]) # the arc connector l = connector.curve(startbox, endbox, relangle1=relangle1, relangle2=relangle2, absbulge=absbulge, relbulge=relbulge, boxdists=[0.0,0.0]) #l = connector.curve(startbox, endbox, absangle1=absangle+relangle1, absangle2=absangle+relangle2, absbulge=absbulge, relbulge=relbulge, boxdists=[0.0,0.0]) c2.stroke(l, [style.linewidth.Thick, color.rgb.red, deco.earrow.Large]) # the relangle parameters # relangle1 c2.stroke(path.path(path.moveto(*direct.atbegin()), path.rlineto(len*cos(radians(absangle + relangle1)), len*sin(radians(absangle + relangle1))))) ang = path.path(path.arc(direct.atbegin()[0], direct.atbegin()[1], 0.8*len, absangle, absangle+relangle1)) c2.stroke(ang, [deco.earrow.large]) pos = ang.at(0.5*ang.arclen()) c2.text(pos[0], pos[1], r"~relangle1", [text.halign.left]) # absangle1 c2.stroke(path.path(path.moveto(*direct.atbegin()), path.rlineto(len, 0))) ang = path.path(path.arc(direct.atbegin()[0], direct.atbegin()[1], 0.5*len, 0, absangle+relangle1)) c2.stroke(ang, [deco.earrow.large]) pos = ang.at(0.2*ang.arclen()) c2.text(pos[0], pos[1], r"~absangle1", [text.halign.left]) # relangle2 c2.stroke(path.path(path.moveto(*direct.atend()), path.rlineto(len*cos(radians(absangle)), len*sin(radians(absangle))))) c2.stroke(path.path(path.moveto(*direct.atend()), path.rlineto(len*cos(radians(absangle + relangle2)), len*sin(radians(absangle + relangle2))))) ang = path.path(path.arc(direct.atend()[0], direct.atend()[1], 0.8*len, absangle, absangle+relangle2)) c2.stroke(ang, [deco.earrow.large]) pos = ang.at(0.5*ang.arclen()) c2.text(pos[0], pos[1], r"~relangle2", [text.halign.left]) # the bulge parameter bulge = absbulge + direct.arclen() * relbulge bul = path.path(path.moveto(*direct.atbegin()), path.rlineto(bulge * cos(radians(absangle+relangle1)), bulge * sin(radians(absangle+relangle1)))) c2.stroke(bul, [deco.earrow.large]) pos = bul.at(0.7*bul.arclen()) c2.text(pos[0], pos[1], r"~(rel)bulge", [text.halign.left]) bul = path.path(path.moveto(*direct.atend()), path.rlineto(-bulge * cos(radians(absangle+relangle2)), -bulge * sin(radians(absangle+relangle2)))) c2.stroke(bul, [deco.earrow.large]) pos = bul.at(0.7*bul.arclen()) c2.text(pos[0], pos[1], r"~(rel)bulge", [text.halign.left, text.vshift(1)]) # >>> # write everything c1.insert(c2, [trafo.translate(6.5, 0)]) c1.writePDFfile() # vim:foldmethod=marker:foldmarker=<<<,>>> PyX-0.14.1/manual/connector.rst0000644000076500000240000000610612037344751016543 0ustar andrestaff00000000000000 .. module:: connector *********************** Module :mod:`connector` *********************** This module provides classes for connecting two :class:`box`\ -instances with lines, arcs or curves. All constructors of the following connector-classes take two :class:`box`\ -instances as the two first arguments. They return a connecting path from the first to the second box. The overall geometry of the path is such that is starts/ends at the boxes' centers. It is then cut by the boxes' outlines. The resulting :class:`connector` will additionally be shortened by lengths given in the *boxdists* (a list of two lengths, default ``[0,0]``). Angle keywords can be either absolute or relative. The absolute angles refer to the angle between x-axis and the running tangent of the connector, while the relative angles are between the direct connecting line of the box-centers and the running tangent (see figure. :ref:`fig_connector`). The bulge-keywords parameterize the deviation of the connector from the connecting line. It has different meanings for different connectors (see figure. :ref:`fig_connector`). Class :class:`line` =================== The constructor of the :class:`line` class accepts only boxes and the *boxdists*. Class :class:`arc` ================== The constructor takes either the *relangle* or a combination of *relbulge* and *absbulge*. The "bulge" is meant to be a hint for the greatest distance between the connecting arc and the straight connection between the box-centers. (Default: ``relangle=45``, ``relbulge=None``, ``absbulge=None``) Note that the bulge-keywords override the angle-keyword. If both *relbulge* and *absbulge* are given, they will be added. Class :class:`curve` ==================== The constructor takes both angle- and bulge-keywords. Here, the bulges are used as distances between the control points of the cubic Beziér-curve. For the signs of the angle- and bulge-keywords refer to figure :ref:`fig_connector`. *absangle1* or *relangle1* --- *absangle2* or *relangle2*, where the absolute angle overrides the relative if both are given. (Default: ``relangle1=45``, ``relangle2=45``, ``absangle1=None``, ``absangle2=None``) *absbulge* and *relbulge*, where they will be added if both are given. --- (Default: ``absbulge=None``, ``relbulge=0.39``; these default values produce output similar to the defaults of :class:`arc`.) .. _fig_connector: .. figure:: connector.* :align: center The angle-parameters of the connector.arc (left panel) and the connector.curve (right panel) classes. Class :class:`twolines` ======================= This class returns two connected straight lines. There is a vast variety of combinations for angle- and length-keywords. The user has to make sure to provide a non-ambiguous set of keywords: *absangle1* or *relangle1* for the first angle, --- *relangleM* for the middle angle and --- *absangle2* or *relangle2* for the ending angle. Again, the absolute angle overrides the relative if both are given. (Default: all five angles are ``None``) *length1* and *length2* for the lengths of the connecting lines. (Default: ``None``) PyX-0.14.1/manual/deformer.rst0000644000076500000240000001335412037344751016357 0ustar andrestaff00000000000000 .. module:: deformer ====================================== Module :mod:`deformer`: Path deformers ====================================== The :mod:`deformer` module provides techniques to generate modulated paths. All classes in the :mod:`deformer` module can be used as attributes when drawing/stroking paths onto a canvas. Alternatively new paths can be created by deforming an existing path by means of the :meth:`deform` method. All classes of the :mod:`deformer` module provide the following methods: .. class:: deformer() .. method:: deformer.__call__((specific parameters for the class)) Returns a deformer with modified parameters .. method:: deformer.deform(path) Returns the deformed normpath on the basis of the *path*. This method allows using the deformers outside of a drawing call. The deformer classes are the following: .. class:: cycloid(radius, halfloops=10, skipfirst=1*unit.t_cm, skiplast=1*unit.t_cm, curvesperhloop=3, sign=1, turnangle=45) This deformer creates a cycloid around a path. The outcome looks similar to a 3D spring stretched along the original path. *radius*: the radius of the cycloid (this is the radius of the 3D spring) *halfloops*: the number of half-loops of the cycloid *skipfirst* and *skiplast*: the lengths on the original path not to be bent to a cycloid *curvesperhloop*: the number of Bezier curves to approximate a half-loop *sign*: for ``sign>=0`` the cycloid starts to the left of the path, whereas for ``sign<0`` it starts to the right. *turnangle*: the angle of perspective on the 3D spring. At ``turnangle=0`` results in a sinusoidal curve, whereas for ``turnangle=90`` one essentially obtains a circle. .. class:: smoothed(radius, softness=1, obeycurv=0, relskipthres=0.01) This deformer creates a smoothed variant of the original path. The smoothing is done on the basis of the corners of the original path, not on a global scope! Therefore, the result might not be what one would draw by hand. At each corner (or wherever two path elements meet) a piece of twice the *radius* is taken out of the original path and replaced by a curve. This curve is determined by the tangent directions and the curvatures at its endpoints. Both are taken from the original path, and therefore, the new curve fits into the gap in a *geometrically smooth* way. Path elements that are shorter than *radius* :math:`\times` *relskipthres* are ignored. The new curve smoothing the corner consists either of one or of two Bezier curves, depending on the surrounding path elements. If there are straight lines before and after the new curve, then two Bezier curves are used. This optimises the bending of curves in rectangular boxes or polygons. Here, the curves have an additional degree of freedom that can be set with *softness* :math:`\in(0,1]`. If one of the concerned path elements is curved, only one Bezier curve is used that is (not always uniquely) determined by its geometrical constraints. There are, nevertheless, some *caveats*: A curve that strictly obeys the sign and magnitude of the curvature might not look very smooth in some cases. Especially when connecting a curved with a straight piece, the smoothed path contains unwanted overshootings. To prevent this, the parameter default *obeycurv=0* releases the curvature constraints a little: The curvature may then change its sign (still looks smooth for human eyes) or, in more extreme cases, even its magnitude (does not look so smooth). If you really need a geometrically smooth path on the basis of Bezier curves, then set *obeycurv=1*. .. class:: parallel(distance, relerr=0.05, sharpoutercorners=0, dointersection=1, checkdistanceparams=[0.5], lookforcurvatures=11) This deformer creates a parallel curve to a given path. The result is similar to what is usually referred to as the *set with constant distance* to the set of points on the path. It differs in one important respect, because the *distance* parameter in the deformer is a signed distance. The resulting parallel normpath is constructed on the level of the original pathitems. For each of them a parallel pathitem is constructed. Then, they are connected by circular arcs (or by sharp edges) around the corners of the original path. Later, everything that is nearer to the original path than distance is cut away. There are some caveats: * When the original path is too curved then the parallel path would contain points with infinte curvature. The resulting path stops at such points and leaves the too strongly curved piece out. * When the original path contains on or more self-intersections, then the resulting parallel path is not continuous in the parameterisation of the original path. This may result in the surprising behaviour that a piece that corresponding to a "later" parameter value is followed by an "earlier" one. The parameters are the following: *distance* is the minimal (signed) distance between the original and the parallel paths. *relerr* is the allowed relative error in the distance. *sharpoutercorners* connects the parallel pathitems by a wegde made of straight lines, instead of taking circular arcs. This preserves the angle of the original corners. *dointersection* is a boolean for performing the last step, the intersection step, in the path construction. Setting this to 0 gives the full parallel path, which can be favourable for self-intersecting paths. *checkdistanceparams* is a list of parameter values in the interval (0,1) where the distance is checked on each parallel pathitem. *lookforcurvatures* is the number of points per normpathitem where its curvature is checked for critical values. PyX-0.14.1/manual/document.rst0000644000076500000240000001325112520251157016360 0ustar andrestaff00000000000000 .. module:: document ====================== Module :mod:`document` ====================== .. sectionauthor:: Jörg Lehmann The document module contains two classes: :class:`document` and :class:`page`. A :class:`document` consists of one or several :class:`page`\ s. Class :class:`page` ------------------- A :class:`page` is a thin wrapper around a :class:`canvas`, which defines some additional properties of the page. .. class:: page(canvas, pagename=None, paperformat=None, rotated=0, centered=1, fittosize=0, margin=1 * unit.t_cm, bboxenlarge=1 * unit.t_pt, bbox=None) Construct a new :class:`page` from the given :class:`canvas` instance. A string *pagename* and the *paperformat* can be defined. See below, for a list of known paper formats. If *rotated* is set, the output is rotated by 90 degrees on the page. If *centered* is set, the output is centered on the given paperformat. If *fittosize* is set, the output is scaled to fill the full page except for a given *margin*. Normally, the bounding box of the canvas is calculated automatically from the bounding box of its elements. Alternatively, you may specify the *bbox* manually. In any case, the bounding box is enlarged on all sides by *bboxenlarge*. Class :class:`document` ----------------------- .. class:: document(pages=[]) Construct a :class:`document` consisting of a given list of *pages*. A :class:`document` can be written to a file using one of the following methods: .. method:: document.writeEPSfile(file, title=None, strip_fonts=True, text_as_path=False, mesh_as_bitmap=False, mesh_as_bitmap_resolution=300) Write a single page :class:`document` to an EPS file or to stdout if *file* is set to *-*. *title* is used as the document title, *strip_fonts* enabled font stripping (removal of unused glyphs), *text_as_path* converts all text to paths instead of using fonts in the output, *mesh_as_bitmap* converts meshs (like 3d surface plots) to bitmaps (to reduce complexity in the output) and *mesh_as_bitmap_resolution* is the resolution of this conversion in dots per inch. .. method:: document.writePSfile(file, writebbox=False, title=None, strip_fonts=True, text_as_path=False, mesh_as_bitmap=False, mesh_as_bitmap_resolution=300) Write :class:`document` to a PS file or to to stdout if *file* is set to *-*. *writebbox* add the page bounding boxes to the output. All other parameters are identical to the :meth:`writeEPSfile` method. .. method:: document.writePDFfile(file, title=None, author=None, subject=None, keywords=None, fullscreen=False, writebbox=False, compress=True, compresslevel=6, strip_fonts=True, text_as_path=False, mesh_as_bitmap=False, mesh_as_bitmap_resolution=300) Write :class:`document` to a PDF file or to stdout if *file* is set to *-*. *author*, *subject*, and *keywords* are used for the document author, subject, and keyword information, respectively. *fullscreen* enabled fullscreen mode when the document is opened, *writebbox* enables writing of the crop box to each page, *compress* enables output stream compression and *compresslevel* sets the compress level to be used (from 1 to 9). All other parameters are identical to the :meth:`writeEPSfile`. .. method:: document.writeSVGfile(file, text_as_path=True, mesh_as_bitmap_resolution=300) Write :class:`document` to a SVG file or to stdout if *file* is set to *-*. The *text_as_path* and *mesh_as_bitmap_resolution* have the same meaning as in :meth:`writeEPSfile`. However, not the different default for *text_as_path* due to the missing SVG font support by current browsers. In addition, there is no *mesh_as_bitmap* flag, as meshs are always stored using bitmaps in SVG. .. method:: document.writetofile(filename, *args, **kwargs) Determine the file type (EPS, PS, PDF, or SVG) from the file extension of *filename* and call the corresponding write method with the given arguments *arg* and *kwargs*. Class :class:`paperformat` -------------------------- .. class:: paperformat(width, height, name=None) Define a :class:`paperformat` with the given *width* and *height* and the optional *name*. Predefined paperformats are listed in the following table +--------------------------------------+--------+----------+---------+ | instance | name | width | height | +======================================+========+==========+=========+ | :const:`document.paperformat.A0` | A0 | 840 mm | 1188 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A0b` | | 910 mm | 1370 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A1` | A1 | 594 mm | 840 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A2` | A2 | 420 mm | 594 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A3` | A3 | 297 mm | 420 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A4` | A4 | 210 mm | 297 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.A5` | A5 | 148.5 mm | 210 mm | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.Letter` | Letter | 8.5 inch | 11 inch | +--------------------------------------+--------+----------+---------+ | :const:`document.paperformat.Legal` | Legal | 8.5 inch | 14 inch | +--------------------------------------+--------+----------+---------+ PyX-0.14.1/manual/epsfile.rst0000644000076500000240000000653712037344751016210 0ustar andrestaff00000000000000 .. module:: epsfile ***************************************** Module :mod:`epsfile`: EPS file inclusion ***************************************** With the help of the ``epsfile.epsfile`` class, you can easily embed another EPS file in your canvas, thereby scaling, aligning the content at discretion. The most simple example looks like :: from pyx import * c = canvas.canvas() c.insert(epsfile.epsfile(0, 0, "file.eps")) c.writeEPSfile("output") All relevant parameters are passed to the ``epsfile.epsfile`` constructor. They are summarized in the following table: +---------------------+-----------------------------------------------+ | argument name | description | +=====================+===============================================+ | ``x`` | :math:`x`\ -coordinate of position. | +---------------------+-----------------------------------------------+ | ``y`` | :math:`y`\ -coordinate of position. | +---------------------+-----------------------------------------------+ | ``filename`` | Name of the EPS file (including a possible | | | extension). | +---------------------+-----------------------------------------------+ | ``width=None`` | Desired width of EPS graphics or ``None`` for | | | original width. Cannot be combined with scale | | | specification. | +---------------------+-----------------------------------------------+ | ``height=None`` | Desired height of EPS graphics or ``None`` | | | for original height. Cannot be combined with | | | scale specification. | +---------------------+-----------------------------------------------+ | ``scale=None`` | Scaling factor for EPS graphics or ``None`` | | | for no scaling. Cannot be combined with width | | | or height specification. | +---------------------+-----------------------------------------------+ | ``align="bl"`` | Alignment of EPS graphics. The first | | | character specifies the vertical alignment: | | | ``b`` for bottom, ``c`` for center, and ``t`` | | | for top. The second character fixes the | | | horizontal alignment: ``l`` for left, ``c`` | | | for center ``r`` for right. | +---------------------+-----------------------------------------------+ | ``clip=1`` | Clip to bounding box of EPS file? | +---------------------+-----------------------------------------------+ | ``translatebbox=1`` | Use lower left corner of bounding box of EPS | | | file? Set to :math:`0` with care. | +---------------------+-----------------------------------------------+ | ``bbox=None`` | If given, use ``bbox`` instance instead of | | | bounding box of EPS file. | +---------------------+-----------------------------------------------+ | ``kpsearch=0`` | Search for file using the kpathsea library. | +---------------------+-----------------------------------------------+ .. _epsfile: PyX-0.14.1/manual/gradientname.py0000755000076500000240000000356012255047651017034 0ustar andrestaff00000000000000# WARNING: THIS IS REALLY OLD CODE. IT COULD PROBABLY BE DONE USING GRAPHX NOWADAYS. # HOWEVER, WE DON'T CARE. JUST DON'T TAKE THIS CODE TOO SERIOUSLY. import sys, imp, re sys.path[:0] = [".."] import pyx from pyx import * text.set(text.LatexRunner) text.preamble(r"\renewcommand{\familydefault}{\ttdefault}") c = canvas.canvas() # data to be plotted pf = graph.data.paramfunction("k", 0, 1, "color, xmin, xmax, ymin, ymax= k, k, 1, 0, 1") # positioning is quite ugly ... but it works at the moment y = 0 dy = -0.65 # we could use gradient.__dict__ to get the instances, but we # would loose the ordering ... instead we just parse the file: # see comment in colorname.py p = re.compile("(?Pgradient\\.(?P[a-z]+)) += [a-z]*gradient_[a-z]+\\(", re.IGNORECASE) lines = imp.find_module("color", pyx.__path__)[0].readlines() firstgraph = None for line in lines: # we yet don't use a file iterator m = p.match(line) if m: if firstgraph is None: xaxis = graph.axis.lin( parter=graph.axis.parter.lin(tickdists=["0.5","0.1"], labeldists=["1"]), painter=graph.axis.painter.regular( innerticklength=None, outerticklength=graph.axis.painter.ticklength.normal), linkpainter=graph.axis.painter.regular(innerticklength=None, labelattrs=None)) firstgraph = g = graph.graphxy(ypos=y, width=10, height=0.5, x2=xaxis, y=graph.axis.lin(parter=None)) else: g = graph.graphxy(ypos=y, width=10, height=0.5, x2=graph.axis.linkedaxis(firstgraph.axes["x2"]), y=graph.axis.lin(parter=None)) g.plot(pf, [graph.style.rect(gradient=getattr(pyx.color.gradient, m.group("name")), keygraph=None)]) g.doplot() g.finish() c.insert(g) c.text(10.2, y + 0.15, m.group("id"), [text.size.footnotesize]) y += dy c.writePDFfile() PyX-0.14.1/manual/gradientname.rst0000644000076500000240000000027312067125674017212 0ustar andrestaff00000000000000 .. _gradientname: ************************* Appendix: Named gradients ************************* .. _fig_gradientname: .. figure:: gradientname.* :align: center Named gradients PyX-0.14.1/manual/graph.dat0000644000076500000240000000004412037344751015605 0ustar andrestaff000000000000001 2 2 3 3 8 4 13 5 18 6 21 PyX-0.14.1/manual/graph.py0000755000076500000240000000015512171066400015462 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.file("graph.dat", x=1, y=2)) g.writePDFfile() PyX-0.14.1/manual/graph.rst0000644000076500000240000014321712520246733015655 0ustar andrestaff00000000000000 .. module:: graph ****** Graphs ****** Introduction ============ PyX can be used for data and function plotting. At present x-y-graphs and x-y-z-graphs are supported only. However, the component architecture of the graph system described in section :ref:`graph_components` allows for additional graph geometries while reusing most of the existing components. Creating a graph splits into two basic steps. First you have to create a graph instance. The most simple form would look like:: from pyx import * g = graph.graphxy(width=8) The graph instance ``g`` created in this example can then be used to actually plot something into the graph. Suppose you have some data in a file :file:`graph.dat` you want to plot. The content of the file could look like: .. include:: graph.dat :literal: To plot these data into the graph ``g`` you must perform:: g.plot(graph.data.file("graph.dat", x=1, y=2)) The method :meth:`plot` takes the data to be plotted and optionally a list of graph styles to be used to plot the data. When no styles are provided, a default style defined by the data instance is used. For data read from a file by an instance of :class:`graph.data.file`, the default are symbols. When instantiating :class:`graph.data.file`, you not only specify the file name, but also a mapping from columns to axis names and other information the styles might make use of (*e.g.* data for error bars to be used by the errorbar style). While the graph is already created by that, we still need to perform a write of the result into a file. Since the graph instance is a canvas, we can just call its :meth:`writeEPSfile` method. :: g.writeEPSfile("graph") The result :file:`graph.eps` is shown in figure :ref:`fig_graph`. .. _fig_graph: .. figure:: graph.* :align: center A minimalistic plot for the data from file :file:`graph.dat`. Instead of plotting data from a file, other data source are available as well. For example function data is created and placed into :meth:`plot` by the following line:: g.plot(graph.data.function("y(x)=x**2")) You can plot different data in a single graph by calling :meth:`plot` several times before writing the output to a file. Note that a calling :meth:`plot` will fail once a graph was forced to "finish" itself. This happens automatically, when the graph is written to a file. Thus it is not an option to call :meth:`plot` after writing the output. The topic of the finalization of a graph is addressed in more detail in section :mod:`graph.graph`. As you can see in figure :ref:`fig_graph2`, a function is plotted as a line by default. .. _fig_graph2: .. figure:: graph2.* :align: center Plotting data from a file together with a function. While the axes ranges got adjusted automatically in the previous example, they might be fixed by keyword options in axes constructors. Plotting only a function will need such a setting at least in the variable coordinate. The following code also shows how to set a logathmic axis in y-direction: .. include:: graph3.py :literal: The result is shown in figure :ref:`fig_graph3`. .. _fig_graph3: .. figure:: graph3.* :align: center Plotting a function for a given axis range and use a logarithmic y-axis. .. _graph_components: Component architecture ====================== Creating a graph involves a variety of tasks, which thus can be separated into components without significant additional costs. This structure manifests itself also in the PyX source, where there are different modules for the different tasks. They interact by some well-defined interfaces. They certainly have to be completed and stabilized in their details, but the basic structure came up in the continuous development quite clearly. The basic parts of a graph are: graph Defines the geometry of the graph by means of graph coordinates with range [0:1]. Keeps lists of plotted data, axes *etc.* data Produces or prepares data to be plotted in graphs. style Performs the plotting of the data into the graph. It gets data, converts them via the axes into graph coordinates and uses the graph to finally plot the data with respect to the graph geometry methods. key Responsible for the graph keys. axis Creates axes for the graph, which take care of the mapping from data values to graph coordinates. Because axes are also responsible for creating ticks and labels, showing up in the graph themselves and other things, this task is splitted into several independent subtasks. Axes are discussed separately in chapter :mod:`axis`. .. module:: graph.graph Module :mod:`graph.graph`: Graph geometry ========================================= The classes :class:`graphxy` and :class:`graphxyz` are part of the module :mod:`graph.graph`. However, there are shortcuts to access the classes via ``graph.graphxy`` and ``graph.graphxyz``, respectively. .. class:: graphxy(xpos=0, ypos=0, width=None, height=None, ratio=goldenmean, key=None, backgroundattrs=None, axesdist=0.8*unit.v_cm, xaxisat=None, yaxisat=None, **axes) This class provides an x-y-graph. A graph instance is also a fully functional canvas. The position of the graph on its own canvas is specified by *xpos* and *ypos*. The size of the graph is specified by *width*, *height*, and *ratio*. These parameters define the size of the graph area not taking into account the additional space needed for the axes. Note that you have to specify at least *width* or *height*. *ratio* will be used as the ratio between *width* and *height* when only one of these is provided. *key* can be set to a :class:`graph.key.key` instance to create an automatic graph key. ``None`` omits the graph key. *backgroundattrs* is a list of attributes for drawing the background of the graph. Allowed are decorators, strokestyles, and fillstyles. ``None`` disables background drawing. *axisdist* is the distance between axes drawn at the same side of a graph. *xaxisat* and *yaxisat* specify a value at the y and x axis, where the corresponding axis should be moved to. It's a shortcut for corresonding calls of :meth:`axisatv` described below. Moving an axis by *xaxisat* or *yaxisat* disables the automatic creation of a linked axis at the opposite side of the graph. *\*\*axes* receives axes instances. Allowed keywords (axes names) are ``x``, ``x2``, ``x3``, *etc.* and ``y``, ``y2``, ``y3``, *etc.* When not providing an ``x`` or ``y`` axis, linear axes instances will be used automatically. When not providing a ``x2`` or ``y2`` axis, linked axes to the ``x`` and ``y`` axes are created automatically and *vice versa*. As an exception, a linked axis is not created automatically when the axis is placed at a specific position by *xaxisat* or *yaxisat*. You can disable the automatic creation of axes by setting the linked axes to ``None``. The even numbered axes are plotted at the top (``x`` axes) and right (``y`` axes) while the others are plotted at the bottom (``x`` axes) and left (``y`` axes) in ascending order each. Some instance attributes might be useful for outside read-access. Those are: .. attribute:: graphxy.axes A dictionary mapping axes names to the :class:`anchoredaxis` instances. To actually plot something into the graph, the following instance method :meth:`plot` is provided: .. method:: graphxy.plot(data, styles=None) Adds *data* to the list of data to be plotted. Sets *styles* to be used for plotting the data. When *styles* is ``None``, the default styles for the data as provided by *data* is used. *data* should be an instance of any of the data described in section :mod:`graph.data`. When the same combination of styles (*i.e.* the same references) are used several times within the same graph instance, the styles are kindly asked by the graph to iterate their appearance. Its up to the styles how this is performed. Instead of calling the plot method several times with different *data* but the same style, you can use a list (or something iterateable) for *data*. While a graph instance only collects data initially, at a certain point it must create the whole plot. Once this is done, further calls of :meth:`plot` will fail. Usually you do not need to take care about the finalization of the graph, because it happens automatically once you write the plot into a file. However, sometimes position methods (described below) are nice to be accessible. For that, at least the layout of the graph must have been finished. However, the drawing order is based on canvas layers and thus the order in which the :meth:`do`\ -methods are called will not alter the output. Multiple calls to any of the :meth:`do`\ -methods have no effect (only the first call counts). The orginal order in which the :meth:`do`\ -methods are called is: .. method:: graphxy.dolayout() Fixes the layout of the graph. As part of this work, the ranges of the axes are fitted to the data when the axes ranges are allowed to adjust themselves to the data ranges. The other :meth:`do`\ -methods ensure, that this method is always called first. .. method:: graphxy.dobackground() Draws the background. .. method:: graphxy.doaxes() Inserts the axes. .. method:: graphxy.doplotitem(plotitem) Plots the plotitem as returned by the graphs plot method. .. method:: graphxy.doplot() Plots all (remaining) plotitems. .. method:: graphxy.dokeyitem() Inserts a plotitem in the graph key as returned by the graphs plot method. .. method:: graphxy.dokey() Inserts the graph key. .. method:: graphxy.finish() Finishes the graph by calling all pending :meth:`do`\ -methods. This is done automatically, when the output is created. The graph provides some methods to access its geometry: .. method:: graphxy.pos(x, y, xaxis=None, yaxis=None) Returns the given point at *x* and *y* as a tuple ``(xpos, ypos)`` at the graph canvas. *x* and *y* are anchoredaxis instances for the two axes *xaxis* and *yaxis*. When *xaxis* or *yaxis* are ``None``, the axes with names ``x`` and ``y`` are used. This method fails if called before :meth:`dolayout`. .. method:: graphxy.vpos(vx, vy) Returns the given point at *vx* and *vy* as a tuple ``(xpos, ypos)`` at the graph canvas. *vx* and *vy* are graph coordinates with range [0:1]. .. method:: graphxy.vgeodesic(vx1, vy1, vx2, vy2) Returns the geodesic between points *vx1*, *vy1* and *vx2*, *vy2* as a path. All parameters are in graph coordinates with range [0:1]. For :class:`graphxy` this is a straight line. .. method:: graphxy.vgeodesic_el(vx1, vy1, vx2, vy2) Like :meth:`vgeodesic` but this method returns the path element to connect the two points. .. index:: single: xbasepath()@xbasepath() (graphxy method) single: xvbasepath()@xvbasepath() (graphxy method) single: xgridpath()@xgridpath() (graphxy method) single: xvgridpath()@xvgridpath() (graphxy method) single: xtickpoint()@xtickpoint() (graphxy method) single: xvtickpoint()@xvtickpoint() (graphxy method) single: xtickdirection()@xtickdirection() (graphxy method) single: xvtickdirection()@xvtickdirection() (graphxy method) single: ybasepath()@ybasepath() (graphxy method) single: yvbasepath()@yvbasepath() (graphxy method) single: ygridpath()@ygridpath() (graphxy method) single: yvgridpath()@yvgridpath() (graphxy method) single: ytickpoint()@ytickpoint() (graphxy method) single: yvtickpoint()@yvtickpoint() (graphxy method) single: ytickdirection()@ytickdirection() (graphxy method) single: yvtickdirection()@yvtickdirection() (graphxy method) Further geometry information is available by the :attr:`axes` instance variable, with is a dictionary mapping axis names to :class:`anchoredaxis` instances. Shortcuts to the anchoredaxis positioner methods for the ``x``\ - and ``y``\ -axis become available after :meth:`dolayout` as :class:`graphxy` methods ``Xbasepath``, ``Xvbasepath``, ``Xgridpath``, ``Xvgridpath``, ``Xtickpoint``, ``Xvtickpoint``, ``Xtickdirection``, and ``Xvtickdirection`` where the prefix ``X`` stands for ``x`` and ``y``. .. method:: graphxy.axistrafo(axis, t) This method can be used to apply a transformation *t* to an :class:`anchoredaxis` instance *axis* to modify the axis position and the like. This method fails when called on a not yet finished axis, i.e. it should be used after :meth:`dolayout`. .. method:: graphxy.axisatv(axis, v) This method calls :meth:`axistrafo` with a transformation to move the axis *axis* to a graph position *v* (in graph coordinates). The class :class:`graphxyz` is very similar to the :class:`graphxy` class, except for its additional dimension. In the following documentation only the differences to the :class:`graphxy` class are described. .. class:: graphxyz(xpos=0, ypos=0, size=None, xscale=1, yscale=1, zscale=1/goldenmean, xy12axesat=None, xy12axesatname="z", projector=central(10, -30, 30), key=None, **axes) This class provides an x-y-z-graph. The position of the graph on its own canvas is specified by *xpos* and *ypos*. The size of the graph is specified by *size* and the length factors *xscale*, *yscale*, and *zscale*. The final size of the graph depends on the projector *projector*, which is called with ``x``, ``y``, and ``z`` values up to *xscale*, *yscale*, and *zscale* respectively and scaling the result by *size*. For a parallel projector changing *size* is thus identical to changing *xscale*, *yscale*, and *zscale* by the same factor. For the central projector the projectors internal distance would also need to be changed by this factor. Thus *size* changes the size of the whole graph without changing the projection. *xy12axesat* moves the xy-plane of the axes ``x``, ``x2``, ``y``, ``y2`` to the given value at the axis *xy12axesatname*. *projector* defines the conversion of 3d coordinates to 2d coordinates. It can be an instance of :class:`central` or :class:`parallel` described below. *\*\*axes* receives axes instances as for :class:`graphxy`. The graphxyz allows for 4 axes per graph dimension ``x``, ``x2``, ``x3``, ``x4``, ``y``, ``y2``, ``y3``, ``y4``, ``z``, ``z2``, ``z3``, and ``z4``. The x-y-plane is the horizontal plane at the bottom and the ``x``, ``x2``, ``y``, and ``y2`` axes are placed at the boundary of this plane with ``x`` and ``y`` always being in front. ``x3``, ``x4``, ``y3``, and ``y4`` are handled similar, but for the top plane of the graph. The ``z`` axis is placed at the origin of the ``x`` and ``y`` dimension, whereas ``z2`` is placed at the final point of the ``x`` dimension, ``z3`` at the final point of the ``y`` dimension and ``z4`` at the final point of the ``x`` and ``y`` dimension together. .. attribute:: graphxyz.central The central attribute of the graphxyz is the :class:`central` class. See the class description below. .. attribute:: graphxyz.parallel The parallel attribute of the graphxyz is the :class:`parallel` class. See the class description below. Regarding the 3d to 2d transformation the methods :meth:`pos`, :meth:`vpos`, :meth:`vgeodesic`, and :meth:`vgeodesic_el` are available as for class :class:`graphxy` and just take an additional argument for the dimension. Note that a similar transformation method (3d to 2d) is available as part of the projector as well already, but only the graph acknowledges its size, the scaling and the internal tranformation of the graph coordinates to the scaled coordinates. As the projector also implements a :meth:`zindex` and a :meth:`angle` method, those are also available at the graph level in the graph coordinate variant (i.e. having an additional v in its name and using values from 0 to 1 per dimension). .. method:: graphxyz.vzindex(vx, vy, vz) The depths of the point defined by *vx*, *vy*, and *vz* scaled to a range [-1:1] where 1 is closest to the viewer. All arguments passed to the method are in graph coordinates with range [0:1]. .. method:: graphxyz.vangle(vx1, vy1, vz1, vx2, vy2, vz2, vx3, vy3, vz3) The cosine of the angle of the view ray thru point ``(vx1, vy1, vz1)`` and the plane defined by the points ``(vx1, vy1, vz1)``, ``(vx2, vy2, vz2)``, and ``(vx3, vy3, vz3)``. All arguments passed to the method are in graph coordinates with range [0:1]. There are two projector classes :class:`central` and :class:`parallel`: .. class:: central(distance, phi, theta, anglefactor=math.pi/180) Instances of this class implement a central projection for the given parameters. *distance* is the distance of the viewer from the origin. Note that the :class:`graphxyz` class uses the range ``-xscale`` to ``xscale``, ``-yscale`` to ``yscale``, and ``-zscale`` to ``zscale`` for the coordinates ``x``, ``y``, and ``z``. As those scales are of the order of one (by default), the distance should be of the order of 10 to give nice results. Smaller distances increase the central projection character while for huge distances the central projection becomes identical to the parallel projection. ``phi`` is the angle of the viewer in the x-y-plane and ``theta`` is the angle of the viewer to the x-y-plane. The standard notation for spheric coordinates are used. The angles are multiplied by *anglefactor* which is initialized to do a degree in radiant transformation such that you can specify ``phi`` and ``theta`` in degree while the internal computation is always done in radiants. .. class:: parallel(phi, theta, anglefactor=math.pi/180) Instances of this class implement a parallel projection for the given parameters. There is no distance for that transformation (compared to the central projection). All other parameters are identical to the :class:`central` class. .. module:: graph.data Module :mod:`graph.data`: Graph data ==================================== The following classes provide data for the :meth:`plot` method of a graph. The classes are implemented in :mod:`graph.data`. .. class:: file(filename, commentpattern=defaultcommentpattern, columnpattern=defaultcolumnpattern, stringpattern=defaultstringpattern, skiphead=0, skiptail=0, every=1, title=notitle, context={}, copy=1, replacedollar=1, columncallback="__column__", **columns) This class reads data from a file and makes them available to the graph system. *filename* is the name of the file to be read. The data should be organized in columns. The arguments *commentpattern*, *columnpattern*, and *stringpattern* are responsible for identifying the data in each line of the file. Lines matching *commentpattern* are ignored except for the column name search of the last non- empty comment line before the data. By default a line starting with one of the characters ``'#'``, ``'%'``, or ``'!'`` as well as an empty line is treated as a comment. A non-comment line is analysed by repeatedly matching *stringpattern* and, whenever the stringpattern does not match, by *columnpattern*. When the *stringpattern* matches, the result is taken as the value for the next column without further transformations. When *columnpattern* matches, it is tried to convert the result to a float. When this fails the result is taken as a string as well. By default, you can write strings with spaces surrounded by ``'"'`` immediately surrounded by spaces or begin/end of line in the data file. Otherwise ``'"'`` is not taken to be special. *skiphead* and *skiptail* are numbers of data lines to be ignored at the beginning and end of the file while *every* selects only every *every* line from the data. *title* is the title of the data to be used in the graph key. A default title is constructed out of *filename* and *\*\*columns*. You may set *title* to ``None`` to disable the title. Finally, *columns* define columns out of the existing columns from the file by a column number or a mathematical expression (see below). When *copy* is set the names of the columns in the file (file column names) and the freshly created columns having the names of the dictionary key (data column names) are passed as data to the graph styles. The data columns may hide file columns when names are equal. For unset *copy* the file columns are not available to the graph styles. File column names occur when the data file contains a comment line immediately in front of the data (except for empty or empty comment lines). This line will be parsed skipping the matched comment identifier as if the line would be regular data, but it will not be converted to floats even if it would be possible to convert the items. The result is taken as file column names, *i.e.* a string representation for the columns in the file. The values of *\*\*columns* can refer to column numbers in the file starting at ``1``. The column ``0`` is also available and contains the line number starting from ``1`` not counting comment lines, but lines skipped by *skiphead*, *skiptail*, and *every*. Furthermore values of *\*\*columns* can be strings: file column names or complex mathematical expressions. To refer to columns within mathematical expressions you can also use file column names when they are valid variable identifiers. Equal named items in context will then be hidden. Alternatively columns can be access by the syntax ``$`` when *replacedollar* is set. They will be translated into function calls to *columncallback*, which is a function to access column data by index or name. *context* allows for accessing external variables and functions when evaluating mathematical expressions for columns. Additionally to the identifiers in *context*, the file column names, the *columncallback* function and the functions shown in the table "builtins in math expressions" at the end of the section are available. Example:: graph.data.file("test.dat", a=1, b="B", c="2*B+$3") with :file:`test.dat` looking like:: # A B C 1.234 1 2 5.678 3 4 The columns with name ``"a"``, ``"b"``, ``"c"`` will become ``"[1.234, 5.678]"``, ``"[1.0, 3.0]"``, and ``"[4.0, 10.0]"``, respectively. The columns ``"A"``, ``"B"``, ``"C"`` will be available as well, since *copy* is enabled by default. When creating several data instances accessing the same file, the file is read only once. There is an inherent caching of the file contents. For the sake of completeness we list the default patterns: .. attribute:: file.defaultcommentpattern ``re.compile(r"(#+|!+|%+)\s*")`` .. attribute:: file.defaultcolumnpattern ``re.compile(r"\"(.*?)\"(\s+|$)")`` .. attribute:: file.defaultstringpattern ``re.compile(r"(.*?)(\s+|$)")`` .. class:: function(expression, title=notitle, min=None, max=None, points=100, context={}) This class creates graph data from a function. *expression* is the mathematical expression of the function. It must also contain the result variable name including the variable the function depends on by assignment. A typical example looks like ``"y(x)=sin(x)"``. *title* is the title of the data to be used in the graph key. By default *expression* is used. You may set *title* to ``None`` to disable the title. *min* and *max* give the range of the variable. If not set, the range spans the whole axis range. The axis range might be set explicitly or implicitly by ranges of other data. *points* is the number of points for which the function is calculated. The points are choosen linearly in terms of graph coordinates. *context* allows for accessing external variables and functions. Additionally to the identifiers in *context*, the variable name and the functions shown in the table "builtins in math expressions" at the end of the section are available. .. class:: paramfunction(varname, min, max, expression, title=notitle, points=100, context={}) This class creates graph data from a parametric function. *varname* is the parameter of the function. *min* and *max* give the range for that variable. *points* is the number of points for which the function is calculated. The points are choosen lineary in terms of the parameter. *expression* is the mathematical expression for the parametric function. It contains an assignment of a tuple of functions to a tuple of variables. A typical example looks like ``"x, y = cos(k), sin(k)"``. *title* is the title of the data to be used in the graph key. By default *expression* is used. You may set *title* to ``None`` to disable the title. *context* allows for accessing external variables and functions. Additionally to the identifiers in *context*, *varname* and the functions shown in the table "builtins in math expressions" at the end of the section are available. .. class:: values(title="user provided values", **columns) This class creates graph data from externally provided data. Each column is a list of values to be used for that column. *title* is the title of the data to be used in the graph key. .. class:: points(data, title="user provided points", addlinenumbers=1, **columns) This class creates graph data from externally provided data. *data* is a list of lines, where each line is a list of data values for the columns. *title* is the title of the data to be used in the graph key. The keywords of *\*\*columns* become the data column names. The values are the column numbers starting from one, when *addlinenumbers* is turned on (the zeroth column is added to contain a line number in that case), while the column numbers starts from zero, when *addlinenumbers* is switched off. .. class:: data(data, title=notitle, context=, copy=1, replacedollar=1, columncallback="__column__", **columns) This class provides graph data out of other graph data. *data* is the source of the data. All other parameters work like the equally called parameters in :class:`graph.data.file`. Indeed, the latter is built on top of this class by reading the file and caching its contents in a :class:`graph.data.list` instance. .. class:: conffile(filename, title=notitle, context=, copy=1, replacedollar=1, columncallback="__column__", **columns) This class reads data from a config file with the file name *filename*. The format of a config file is described within the documentation of the :mod:`ConfigParser` module of the Python Standard Library. Each section of the config file becomes a data line. The options in a section are the columns. The name of the options will be used as file column names. All other parameters work as in *graph.data.file* and *graph.data.data* since they all use the same code. .. class:: cbdfile(filename, minrank=None, maxrank=None, title=notitle, context=, copy=1, replacedollar=1, columncallback="__column__", **columns) This is an experimental class to read map data from cbd-files. See ``_ for some world-map data. The builtins in math expressions are listed in the following table: +------------------+--------------------------------------------+ | name | value | +==================+============================================+ | ``neg`` | ``lambda x: -x`` | +------------------+--------------------------------------------+ | ``abs`` | ``lambda x: x < 0 and -x or x`` | +------------------+--------------------------------------------+ | ``sgn`` | ``lambda x: x < 0 and -1 or 1`` | +------------------+--------------------------------------------+ | ``sqrt`` | ``math.sqrt`` | +------------------+--------------------------------------------+ | ``exp`` | ``math.exp`` | +------------------+--------------------------------------------+ | ``log`` | ``math.log`` | +------------------+--------------------------------------------+ | ``sin`` | ``math.sin`` | +------------------+--------------------------------------------+ | ``cos`` | ``math.cos`` | +------------------+--------------------------------------------+ | ``tan`` | ``math.tan`` | +------------------+--------------------------------------------+ | ``asin`` | ``math.asin`` | +------------------+--------------------------------------------+ | ``acos`` | ``math.acos`` | +------------------+--------------------------------------------+ | ``atan`` | ``math.atan`` | +------------------+--------------------------------------------+ | ``sind`` | ``lambda x: math.sin(math.pi/180*x)`` | +------------------+--------------------------------------------+ | ``cosd`` | ``lambda x: math.cos(math.pi/180*x)`` | +------------------+--------------------------------------------+ | ``tand`` | ``lambda x: math.tan(math.pi/180*x)`` | +------------------+--------------------------------------------+ | ``asind`` | ``lambda x: 180/math.pi*math.asin(x)`` | +------------------+--------------------------------------------+ | ``acosd`` | ``lambda x: 180/math.pi*math.acos(x)`` | +------------------+--------------------------------------------+ | ``atand`` | ``lambda x: 180/math.pi*math.atan(x)`` | +------------------+--------------------------------------------+ | ``norm`` | ``lambda x, y: math.hypot(x, y)`` | +------------------+--------------------------------------------+ | ``splitatvalue`` | see the ``splitatvalue`` description below | +------------------+--------------------------------------------+ | ``pi`` | ``math.pi`` | +------------------+--------------------------------------------+ | ``e`` | ``math.e`` | +------------------+--------------------------------------------+ ``math`` refers to Pythons :mod:`math` module. The ``splitatvalue`` function is defined as: .. function:: splitatvalue(value, *splitpoints) This method returns a tuple ``(section, value)``. The section is calculated by comparing *value* with the values of splitpoints. If *splitpoints* contains only a single item, ``section`` is ``0`` when value is lower or equal this item and ``1`` else. For multiple splitpoints, ``section`` is ``0`` when its lower or equal the first item, ``None`` when its bigger than the first item but lower or equal the second item, ``1`` when its even bigger the second item, but lower or equal the third item. It continues to alter between ``None`` and ``2``, ``3``, etc. .. module:: graph.style Module :mod:`graph.style`: Graph styles ======================================= Please note that we are talking about graph styles here. Those are responsible for plotting symbols, lines, bars and whatever else into a graph. Do not mix it up with path styles like the line width, the line style (solid, dashed, dotted *etc.*) and others. The following classes provide styles to be used at the :meth:`plot` method of a graph. The plot method accepts a list of styles. By that you can combine several styles at the very same time. Some of the styles below are hidden styles. Those do not create any output, but they perform internal data handling and thus help on modularization of the styles. Usually, a visible style will depend on data provided by one or more hidden styles but most of the time it is not necessary to specify the hidden styles manually. The hidden styles register themself to be the default for providing certain internal data. .. class:: pos(usenames={}, epsilon=1e-10) This class is a hidden style providing a position in the graph. It needs a data column for each graph dimension. For that the column names need to be equal to an axis name, or a name translation from axis names to column names need to be given by *usenames*. Data points are considered to be out of graph when their position in graph coordinates exceeds the range [0:1] by more than *epsilon*. .. class:: range(usenames={}, epsilon=1e-10) This class is a hidden style providing an errorbar range. It needs data column names constructed out of a axis name ``X`` for each dimension errorbar data should be provided as follows: +-----------+---------------------------+ | data name | description | +===========+===========================+ | ``Xmin`` | minimal value | +-----------+---------------------------+ | ``Xmax`` | maximal value | +-----------+---------------------------+ | ``dX`` | minimal and maximal delta | +-----------+---------------------------+ | ``dXmin`` | minimal delta | +-----------+---------------------------+ | ``dXmax`` | maximal delta | +-----------+---------------------------+ When delta data are provided the style will also read column data for the axis name ``X`` itself. *usenames* allows to insert a translation dictionary from axis names to the identifiers ``X``. *epsilon* is a comparison precision when checking for invalid errorbar ranges. .. class:: symbol(symbol=changecross, size=0.2*unit.v_cm, symbolattrs=[]) This class is a style for plotting symbols in a graph. *symbol* refers to a (changeable) symbol function with the prototype ``symbol(c, x_pt, y_pt, size_pt, attrs)`` and draws the symbol into the canvas ``c`` at the position ``(x_pt, y_pt)`` with size ``size_pt`` and attributes ``attrs``. Some predefined symbols are available in member variables listed below. The symbol is drawn at size *size* using *symbolattrs*. *symbolattrs* is merged with ``defaultsymbolattrs`` which is a list containing the decorator :class:`deco.stroked`. An instance of :class:`symbol` is the default style for all graph data classes described in section :mod:`graph.data` except for :class:`function` and :class:`paramfunction`. The class :class:`symbol` provides some symbol functions as member variables, namely: .. attribute:: symbol.cross A cross. Should be used for stroking only. .. attribute:: symbol.plus A plus. Should be used for stroking only. .. attribute:: symbol.square A square. Might be stroked or filled or both. .. attribute:: symbol.triangle A triangle. Might be stroked or filled or both. .. attribute:: symbol.circle A circle. Might be stroked or filled or both. .. attribute:: symbol.diamond A diamond. Might be stroked or filled or both. :class:`symbol` provides some changeable symbol functions as member variables, namely: .. attribute:: symbol.changecross attr.changelist([cross, plus, square, triangle, circle, diamond]) .. attribute:: symbol.changeplus attr.changelist([plus, square, triangle, circle, diamond, cross]) .. attribute:: symbol.changesquare attr.changelist([square, triangle, circle, diamond, cross, plus]) .. attribute:: symbol.changetriangle attr.changelist([triangle, circle, diamond, cross, plus, square]) .. attribute:: symbol.changecircle attr.changelist([circle, diamond, cross, plus, square, triangle]) .. attribute:: symbol.changediamond attr.changelist([diamond, cross, plus, square, triangle, circle]) .. attribute:: symbol.changesquaretwice attr.changelist([square, square, triangle, triangle, circle, circle, diamond, diamond]) .. attribute:: symbol.changetriangletwice attr.changelist([triangle, triangle, circle, circle, diamond, diamond, square, square]) .. attribute:: symbol.changecircletwice attr.changelist([circle, circle, diamond, diamond, square, square, triangle, triangle]) .. attribute:: symbol.changediamondtwice attr.changelist([diamond, diamond, square, square, triangle, triangle, circle, circle]) The class :class:`symbol` provides two changeable decorators for alternated filling and stroking. Those are especially useful in combination with the :meth:`change`\ -\ :meth:`twice`\ -symbol methods above. They are: .. attribute:: symbol.changestrokedfilled attr.changelist([deco.stroked, deco.filled]) .. attribute:: symbol.changefilledstroked attr.changelist([deco.filled, deco.stroked]) .. class:: line(lineattrs=[], epsilon=1e-10) This class is a style to stroke lines in a graph. *lineattrs* is merged with ``defaultlineattrs`` which is a list containing the member variable ``changelinestyle`` as described below. An instance of :class:`line` is the default style of the graph data classes :class:`function` and :class:`paramfunction` described in section :mod:`graph.data`. *epsilon* is a precision in graph coordinates for line clipping. The class :class:`line` provides a changeable line style. Its definition is: .. attribute:: line.changelinestyle attr.changelist([style.linestyle.solid, style.linestyle.dashed, style.linestyle.dotted, style.linestyle.dashdotted]) .. class:: impulses(lineattrs=[], fromvalue=0, frompathattrs=[], valueaxisindex=1) This class is a style to plot impulses. *lineattrs* is merged with ``defaultlineattrs`` which is a list containing the member variable ``changelinestyle`` of the :class:`line` class. *fromvalue* is the baseline value of the impulses. When set to ``None``, the impulses will start at the baseline. When fromvalue is set, *frompathattrs* are the stroke attributes used to show the impulses baseline path. .. class:: errorbar(size=0.1*unit.v_cm, errorbarattrs=[], epsilon=1e-10) This class is a style to stroke errorbars in a graph. *size* is the size of the caps of the errorbars and *errorbarattrs* are the stroke attributes. Errorbars and error caps are considered to be out of the graph when their position in graph coordinates exceeds the range [0:1] by more that *epsilon*. Out of graph caps are omitted and the errorbars are cut to the valid graph range. .. class:: text(textname="text", dxname=None, dyname=None, dxunit=0.3*unit.v_cm, dyunit=0.3*unit.v_cm, textdx=0*unit.v_cm, textdy=0.3*unit.v_cm, textattrs=[]) This class is a style to stroke text in a graph. The text to be written has to be provided in the data column named ``textname``. *textdx* and *textdy* are the position of the text with respect to the position in the graph. Alternatively you can specify a ``dxname`` and a ``dyname`` and provide appropriate data in those columns to be taken in units of *dxunit* and *dyunit* to specify the position of the text for each point separately. *textattrs* are text attributes for the output of the text. Those attributes are merged with the default attributes ``textmodule.halign.center`` and ``textmodule.vshift.mathaxis``. .. class:: arrow(linelength=0.25*unit.v_cm, arrowsize=0.15*unit.v_cm, lineattrs=[], arrowattrs=[], arrowpos=0.5, epsilon=1e-10, decorator=deco.earrow) This class is a style to plot short lines with arrows into a two-dimensional graph to a given graph position. The arrow parameters are defined by two additional data columns named ``size`` and ``angle`` define the size and angle for each arrow. ``size`` is taken as a factor to *arrowsize* and *linelength*, the size of the arrow and the length of the line the arrow is plotted at. ``angle`` is the angle the arrow points to with respect to a horizontal line. The ``angle`` is taken in degrees and used in mathematically positive sense. *lineattrs* and *arrowattrs* are styles for the arrow line and arrow head, respectively. *arrowpos* defines the position of the arrow line with respect to the position at the graph. The default ``0.5`` means centered at the graph position, whereas ``0`` and ``1`` creates the arrows to start or end at the graph position, respectively. *epsilon* is used as a cutoff for short arrows in order to prevent numerical instabilities. *decorator* defines the decorator to be added to the line. .. class:: rect(colorname="color", gradient=color.gradient.Grey, coloraxis=None, keygraph=_autokeygraph) This class is a style to plot colored rectangles into a two-dimensional graph. The size of the rectangles is taken from the data provided by the :class:`range` style. The additional data column named *colorname* specifies the color of the rectangle defined by *gradient*. The translation of the data values to the gradient is done by the *coloraxis*, which is set to be a linear axis if not provided by *coloraxis*. A key graph, a graphx instance, is generated automatically to indicate the color scale if not provided by *keygraph*. If a *keygraph* is given, its ``x`` axis defines the color conversion and *coloraxis* is ignored. .. class:: histogram(lineattrs=[], steps=0, fromvalue=0, frompathattrs=[], fillable=0, rectkey=0, autohistogramaxisindex=0, autohistogrampointpos=0.5, epsilon=1e-10) This class is a style to plot histograms. *lineattrs* is merged with ``defaultlineattrs`` which is ``[deco.stroked]``. When *steps* is set, the histrogram is plotted as steps instead of the default being a boxed histogram. *fromvalue* is the baseline value of the histogram. When set to ``None``, the histogram will start at the baseline. When fromvalue is set, *frompathattrs* are the stroke attributes used to show the histogram baseline path. The *fillable* flag changes the stoke line of the histogram to make it fillable properly. This is important on non-steped histograms or on histograms, which hit the graph boundary. *rectkey* can be set to generate a rectanglar area instead of a line in the graph key. In the most general case, a histogram is defined by a range specification (like for an errorbar) in one graph dimension (say, along the x-axis) and a value for the other graph dimension. This allows for the widths of the histogram boxes being variable. Often, however, all histogram bin ranges are equally sized, and instead of passing the range, the position of the bin along the x-axis fully specifies the histogram - assuming that there are at least two bins. This common case is supported via two parameters: *autohistogramaxisindex*, which defines the index of the independent histogram axis (in the case just described this would be ``0`` designating the x axis). *autohistogrampointpos*, defines the relative position of the center of the histogram bin: ``0.5`` means that the bin is centered at the values passed to the style, ``0`` (``1``) means that the bin is aligned at the right-(left-)hand side. XXX describe, how to specify general histograms with varying bin widths Positions of the histograms are considered to be out of graph when they exceed the graph coordinate range [0:1] by more than *epsilon*. .. class:: barpos(fromvalue=None, frompathattrs=[], epsilon=1e-10) This class is a hidden style providing position information in a bar graph. Those graphs need to contain a specialized axis, namely a bar axis. The data column for this bar axis is named ``Xname`` where ``X`` is an axis name. In the other graph dimension the data column name must be equal to an axis name. To plot several bars in a single graph side by side, you need to have a nested bar axis and provide a tuple as data for nested bar axis. The bars start at *fromvalue* when provided. The *fromvalue* is marked by a gridline stroked using *frompathattrs*. Thus this hidden style might actually create some output. The value of a bar axis is considered to be out of graph when its position in graph coordinates exceeds the range [0:1] by more than *epsilon*. .. class:: stackedbarpos(stackname, addontop=0, epsilon=1e-10) This class is a hidden style providing position information in a bar graph by stacking a new bar on top of another bar. The value of the new bar is taken from the data column named *stackname*. When *addontop* is set, the values is taken relative to the previous top of the bar. .. class:: bar(barattrs=[], epsilon=1e-10, gradient=color.gradient.RedBlack) This class draws bars in a bar graph. The bars are filled using *barattrs*. *barattrs* is merged with ``defaultbarattrs`` which is a list containing ``[color.gradient.Rainbow, deco.stroked([color.grey.black])]``. The bar style has limited support for 3d graphs: Occlusion does not work properly on stacked bars or multiple dataset. *epsilon* is used in 3d to prevent numerical instabilities on bars without hight. When *gradient* is not ``None`` it is used to calculate a lighting coloring taking into account the angle between the view ray and the bar and the distance between viewer and bar. The precise conversion is defined in the :meth:`lighting` method. .. class:: changebar(barattrs=[]) This style works like the :class:`bar` style, but instead of the *barattrs* to be changed on subsequent data instances the *barattrs* are changed for each value within a single data instance. In the result the style can't be applied to several data instances and does not support 3d. The style raises an error instead. .. class:: gridpos(index1=0, index2=1, gridlines1=1, gridlines2=1, gridattrs=[], epsilon=1e-10) This class is a hidden style providing rectangular grid information out of graph positions for graph dimensions *index1* and *index2*. Data points are considered to be out of graph when their position in graph coordinates exceeds the range [0:1] by more than *epsilon*. Data points are merged to a single graph coordinate value when their difference in graph coordinates is below *epsilon*. .. class:: grid(gridlines1=1, gridlines2=1, gridattrs=[], epsilon=1e-10) Strokes a rectangular grid in the first grid direction, when *gridlines1* is set and in the second grid direction, when *gridlines2* is set. *gridattrs* is merged with ``defaultgridattrs`` which is a list containing the member variable ``changelinestyle`` of the :class:`line` class. *epsilon* is a precision in graph coordinates for line clipping. .. class:: surface(gridlines1=0.05, gridlines2=0.05, gridcolor=None, backcolor=color.gray.black, **kwargs) Draws a surface of a rectangular grid. Each rectangle is divided into 4 triangles. If a *gridcolor* is set, the rectangular grid is marked by small stripes of the relative (compared to each rectangle) size of *gridlines1* and *gridlines2* for the first and second grid direction, respectively. *backcolor* is used to fill triangles shown from the back. If *backcolor* is set to ``None``, back sides are not drawn differently from the front sides. The surface is encoded using a single mesh. While this is quite space efficient, it has the following implications: * All colors must use the same color space. * HSB colors are not allowed, whereas Gray, RGB, and CMYK are allowed. You can convert HSB colors into a different color space by means of :class:`rgbgradient` and class:`cmykgradient` before passing it to the surface style. * The grid itself is also constructed out of triangles. The grid is transformed along with the triangles thus looking quite different from a stroked grid (as done by the grid style). * Occlusion is handled by proper painting order. * Color changes are continuous (in the selected color space) for each triangle. Further arguments are identical to the :class:`graph.style.rect` style. However, if no *colorname* column exists, the surface style falls back to a lighting coloring taking into account the angle between the view ray and the triangle and the distance between viewer and triangle. The precise conversion is defined in the :meth:`lighting` method. .. class:: density(epsilon=1e-10, **kwargs): Density plots can be created by the density style. It is similar to a surface plot in 2d, but it does not use a mesh, but a bitmap representation instead. Due to that difference, the file size is smaller and no color interpolation takes place. Furthermore the style can be used with equidistantly spaced data only (after conversion by the axis, so logarithmic raw data and such are possible using proper axes). Further arguments are identical to the :class:`graph.style.rect` style. .. module:: graph.key Module :mod:`graph.key`: Graph keys =================================== The following class provides a key, whose instances can be passed to the constructor keyword argument ``key`` of a graph. The class is implemented in :mod:`graph.key`. .. class:: key(dist=0.2*unit.v_cm, pos="tr", hpos=None, vpos=None, hinside=1, vinside=1, hdist=0.6*unit.v_cm, vdist=0.4*unit.v_cm, symbolwidth=0.5*unit.v_cm, symbolheight=0.25*unit.v_cm, symbolspace=0.2*unit.v_cm, textattrs=[], columns=1, columndist=0.5*unit.v_cm, border=0.3*unit.v_cm, keyattrs=None) This class writes the title of the data in a plot together with a small illustration of the style. The style is responsible for its illustration. *dist* is a visual length and a distance between the key entries. *pos* is the position of the key with respect to the graph. Allowed values are combinations of ``"t"`` (top), ``"m"`` (middle) and ``"b"`` (bottom) with ``"l"`` (left), ``"c"`` (center) and ``"r"`` (right). Alternatively, you may use *hpos* and *vpos* to specify the relative position using the range [0:1]. *hdist* and *vdist* are the distances from the specified corner of the graph. *hinside* and *vinside* are numbers to be set to 0 or 1 to define whether the key should be placed horizontally and vertically inside of the graph or not. *symbolwidth* and *symbolheight* are passed to the style to control the size of the style illustration. *symbolspace* is the space between the illustration and the text. *textattrs* are attributes for the text creation. They are merged with ``[text.vshift.mathaxis]``. *columns* is a number of columns of the graph key and *columndist* is the distance between those columns. When *keyattrs* is set to contain some draw attributes, the graph key is enlarged by *border* and the key area is drawn using *keyattrs*. PyX-0.14.1/manual/graph2.py0000755000076500000240000000022612171066401015544 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8) g.plot(graph.data.file("graph.dat", x=1, y=2)) g.plot(graph.data.function("y(x)=x**2")) g.writePDFfile() PyX-0.14.1/manual/graph3.py0000644000076500000240000000030412171066402015540 0ustar andrestaff00000000000000from pyx import * g = graph.graphxy(width=8, x=graph.axis.linear(min=-5, max=5), y=graph.axis.logarithmic()) g.plot(graph.data.function("y(x)=exp(x)")) g.writePDFfile() PyX-0.14.1/manual/graphics.rst0000644000076500000240000004512412520247016016345 0ustar andrestaff00000000000000 .. _graphics: ************** Basic graphics ************** .. sectionauthor:: Jörg Lehmann Introduction ============ The path module allows one to construct PostScript-like *paths*, which are one of the main building blocks for the generation of drawings. A PostScript path is an arbitrary shape consisting of straight lines, arc segments and cubic Bézier curves. Such a path does not have to be connected but may also comprise several disconnected segments, which will be called *subpaths* in the following. .. todo:: example for paths and subpaths (figure) Usually, a path is constructed by passing a list of the path primitives :class:`moveto`, :class:`lineto`, :class:`curveto`, etc., to the constructor of the :class:`path` class. The following code snippet, for instance, defines a path *p* that consists of a straight line from the point :math:`(0, 0)` to the point :math:`(1, 1)` :: from pyx import * p = path.path(path.moveto(0, 0), path.lineto(1, 1)) Equivalently, one can also use the predefined :class:`path` subclass :class:`line` and write :: p = path.line(0, 0, 1, 1) While already some geometrical operations can be performed with this path (see next section), another PyX object is needed in order to actually being able to draw the path, namely an instance of the :class:`canvas` class. By convention, we use the name *c* for this instance:: c = canvas.canvas() In order to draw the path on the canvas, we use the :meth:`stroke` method of the :class:`canvas` class, i.e., :: c.stroke(p) c.writeEPSfile("line") To complete the example, we have added a :meth:`writeEPSfile` call, which writes the contents of the canvas to the file :file:`line.eps`. Note that an extension :file:`.eps` is added automatically, if not already present in the given filename. Similarly, if you want to generate a PDF or SVG file instead, use :: c.writePDFfile("line") or c.writeSVGfile("line") As a second example, let us define a path which consists of more than one subpath:: cross = path.path(path.moveto(0, 0), path.rlineto(1, 1), path.moveto(1, 0), path.rlineto(-1, 1)) The first subpath is again a straight line from :math:`(0, 0)` to :math:`(1, 1)`, with the only difference that we now have used the :class:`rlineto` class, whose arguments count relative from the last point in the path. The second :class:`moveto` instance opens a new subpath starting at the point :math:`(1, 0)` and ending at :math:`(0, 1)`. Note that although both lines intersect at the point :math:`(1/2, 1/2)`, they count as disconnected subpaths. The general rule is that each occurrence of a :class:`moveto` instance opens a new subpath. This means that if one wants to draw a rectangle, one should not use :: rect1 = path.path(path.moveto(0, 0), path.lineto(0, 1), path.moveto(0, 1), path.lineto(1, 1), path.moveto(1, 1), path.lineto(1, 0), path.moveto(1, 0), path.lineto(0, 0)) which would construct a rectangle out of four disconnected subpaths (see Fig. :ref:`fig_rects` a). In a better solution (see Fig. :ref:`fig_rects` b), the pen is not lifted between the first and the last point: .. _fig_rects: .. figure:: rects.* :align: center Rectangle example Rectangle consisting of (a) four separate lines, (b) one open path, and (c) one closed path. (d) Filling a path always closes it automatically. :: rect2 = path.path(path.moveto(0, 0), path.lineto(0, 1), path.lineto(1, 1), path.lineto(1, 0), path.lineto(0, 0)) However, as one can see in the lower left corner of Fig. :ref:`fig_rects` b, the rectangle is still incomplete. It needs to be closed, which can be done explicitly by using for the last straight line of the rectangle (from the point :math:`(0, 1)` back to the origin at :math:`(0, 0)`) the :class:`closepath` directive:: rect3 = path.path(path.moveto(0, 0), path.lineto(0, 1), path.lineto(1, 1), path.lineto(1, 0), path.closepath()) The :class:`closepath` directive adds a straight line from the current point to the first point of the current subpath and furthermore *closes* the sub path, i.e., it joins the beginning and the end of the line segment. This results in the intended rectangle shown in Fig. :ref:`fig_rects` c. Note that filling the path implicitly closes every open subpath, as is shown for a single subpath in Fig. :ref:`fig_rects` d), which results from :: c.stroke(rect2, [deco.filled([color.grey(0.5)])]) Here, we supply as second argument of the :meth:`stroke` method a list which in the present case only consists of a single element, namely the so called decorator :class:`deco.filled`. As its name says, this decorator specifies that the path is not only being stroked but also filled with the given color. More information about decorators, styles and other attributes which can be passed as elements of the list can be found in Sect. :ref:`graphics_attributes`. More details on the available path elements can be found in Sect. :ref:`path_pathitem`. To conclude this section, we should not forget to mention that rectangles are, of course, predefined in PyX, so above we could have as well written :: rect2 = path.rect(0, 0, 1, 1) Here, the first two arguments specify the origin of the rectangle while the second two arguments define its width and height, respectively. For more details on the predefined paths, we refer the reader to Sect. :ref:`path_predefined`. Path operations =============== Often, one wants to perform geometrical operations with a path before placing it on a canvas by stroking or filling it. For instance, one might want to intersect one path with another one, split the paths at the intersection points, and then join the segments together in a new way. PyX supports such tasks by means of a number of path methods, which we will introduce in the following. Suppose you want to draw the radii to the intersection points of a circle with a straight line. This task can be done using the following code which results in Fig. :ref:`fig_radii` .. include:: radii.py :literal: .. _fig_radii: .. figure:: radii.* :align: center Example: Intersection of circle with line yielding two radii Here, the basic elements, a circle around the point :math:`(0, 0)` with radius :math:`2` and a straight line, are defined. Then, passing the *line*, to the :meth:`intersect` method of *circle*, we obtain a tuple of parameter values of the intersection points. The first element of the tuple is a list of parameter values for the path whose :meth:`intersect` method has been called, the second element is the corresponding list for the path passed as argument to this method. In the present example, we only need one list of parameter values, namely *isects_circle*. Using the :meth:`at` path method to obtain the point corresponding to the parameter value, we draw the radii for the different intersection points. Another powerful feature of PyX is its ability to split paths at a given set of parameters. For instance, in order to fill in the previous example the segment of the circle delimited by the straight line (cf. Fig. :ref:`fig_radii2`), one first has to construct a path corresponding to the outline of this segment. The following code snippet yields this *segment* :: arc1, arc2 = circle.split(isects_circle) if arc1.arclen() < arc2.arclen(): arc = arc1 else: arc = arc2 isects_line.sort() line1, line2, line3 = line.split(isects_line) segment = line2 << arc .. _fig_radii2: .. figure:: radii2.* :align: center Example: Intersection of circle with line yielding radii and circle segment Here, we first split the circle using the :meth:`split` method passing the list of parameters obtained above. Since the circle is closed, this yields two arc segments. We then use the :meth:`arclen`, which returns the arc length of the path, to find the shorter of the two arcs. Before splitting the line, we have to take into account that the :meth:`split` method only accepts a sorted list of parameters. Finally, we join the straight line and the arc segment. For this, we make use of the ``<<`` operator, which not only adds the paths (which could be done using ``line2 + arc``), but also joins the last subpath of *line2* and the first one of *arc*. Thus, *segment* consists of only a single subpath and filling works as expected. An important issue when operating on paths is the parametrisation used. Internally, PyX uses a parametrisation which uses an interval of length :math:`1` for each path element of a path. For instance, for a simple straight line, the possible parameter values range from :math:`0` to :math:`1`, corresponding to the first and last point, respectively, of the line. Appending another straight line, would extend this range to a maximal value of :math:`2`. However, the situation becomes more complicated if more complex objects like a circle are involved. Then, one could be tempted to assume that again the parameter value ranges from :math:`0` to :math:`1`, because the predefined circle consists just of one :class:`arc` together with a :class:`closepath` element. However, this is not the case: the actual range is much larger. The reason for this behaviour lies in the internal path handling of PyX: Before performing any non-trivial geometrical operation on a path, it will automatically be converted into an instance of the :class:`normpath` class (see also Sect. :class:`path.normpath`). These so generated paths are already separated in their subpaths and only contain straight lines and Bézier curve segments. XXX explain normpathparams and things like p.begin(), p.end()-1, A more geometrical way of accessing a point on the path is to use the arc length of the path segment from the first point of the path to the given point. Thus, all PyX path methods that accept a parameter value also allow the user to pass an arc length. For instance, :: from math import pi r = 2 pt1 = path.circle(0, 0, r).at(r*pi) pt2 = path.circle(0, 0, r).at(r*3*pi/2) c.stroke(path.path(path.moveto(*pt1), path.lineto(*pt2))) will draw a straight line from a point at angle :math:`180` degrees (in radians :math:`\pi`) to another point at angle :math:`270` degrees (in radians :math:`3\pi/2`) on a circle with radius :math:`r=2`. Note however, that the mapping from an arc length to a point is in general discontinuous at the beginning and the end of a subpath, and thus PyX does not guarantee any particular result for this boundary case. More information on the available path methods can be found in Sect. :ref:`postscript_like_paths`. .. _graphics_attributes: Attributes: Styles and Decorations ================================== Attributes define properties of a given object when it is being used. Typically, there are different kinds of attributes which are usually orthogonal to each other, while for one type of attribute, several choices are possible. An example is the stroking of a path. There, linewidth and linestyle are different kind of attributes. The linewidth might be thin, normal, thick, etc., and the linestyle might be solid, dashed etc. Attributes always occur in lists passed as an optional keyword argument to a method or a function. Usually, attributes are the first keyword argument, so one can just pass the list without specifying the keyword. Again, for the path example, a typical call looks like :: c.stroke(path, [style.linewidth.Thick, style.linestyle.dashed]) Here, we also encounter another feature of PyX's attribute system. For many attributes useful default values are stored as member variables of the actual attribute. For instance, ``style.linewidth.Thick`` is equivalent to ``style.linewidth(0.04, type="w", unit="cm")``, that is :math:`0.04` width cm (see Sect. :ref:`module_unit` for more information about PyX's unit system). Another important feature of PyX attributes is what is call attributed merging. A trivial example is the following:: # the following two lines are equivalent c.stroke(path, [style.linewidth.Thick, style.linewidth.thin]) c.stroke(path, [style.linewidth.thin]) Here, the ``style.linewidth.thin`` attribute overrides the preceding ``style.linewidth.Thick`` declaration. This is especially important in more complex cases where PyX defines default attributes for a certain operation. When calling the corresponding methods with an attribute list, this list is appended to the list of defaults. This way, the user can easily override certain defaults, while leaving the other default values intact. In addition, every attribute kind defines a special clear attribute, which allows to selectively delete a default value. For path stroking this looks like :: # the following two lines are equivalent c.stroke(path, [style.linewidth.Thick, style.linewidth.clear]) c.stroke(path) The clear attribute is also provided by the base classes of the various styles. For instance, :class:`style.strokestyle.clear` clears all strokestyle subclasses i.e. :class:`style.linewidth` and :class:`style.linestyle`. Since all attributes derive from :class:`attr.attr`, you can remove all defaults using ``attr.clear``. An overview over the most important attribute types provided by PyX is given in the following table. +----------------------------+---------------------------------+------------------------------------+ | Attribute category | description | examples | +============================+=================================+====================================+ | :class:`deco.deco` | decorator specifying the way | :class:`deco.stroked`, | | | the path is drawn | :class:`deco.filled`, | | | | :class:`deco.arrow`, | | | | :class:`deco.text` | +----------------------------+---------------------------------+------------------------------------+ | :class:`style.strokestyle` | style used for path stroking | :class:`style.linecap`, | | | | :class:`style.linejoin`, | | | | :class:`style.miterlimit`, | | | | :class:`style.dash`, | | | | :class:`style.linestyle`, | | | | :class:`style.linewidth`, | | | | :class:`color.color` | +----------------------------+---------------------------------+------------------------------------+ | :class:`style.fillstyle` | style used for path filling | :class:`color.color`, | | | | :class:`pattern.pattern` | +----------------------------+---------------------------------+------------------------------------+ | :class:`style.filltype` | type of path filling | ``style.fillrule.nonzero_winding`` | | | | (default), | | | | ``style.fillrule.even_odd`` | +----------------------------+---------------------------------+------------------------------------+ | :class:`deformer.deformer` | operations changing the shape | :class:`deformer.cycloid`, | | | of the path | :class:`deformer.smoothed` | +----------------------------+---------------------------------+------------------------------------+ | :class:`text.textattr` | attributes used for typesetting | :class:`text.halign`, | | | | :class:`text.valign`, | | | | :class:`text.mathmode`, | | | | :class:`text.phantom`, | | | | :class:`text.size`, | | | | :class:`text.parbox` | +----------------------------+---------------------------------+------------------------------------+ | :class:`trafo.trafo` | transformations applied when | :class:`trafo.mirror`, | | | drawing object | :class:`trafo.rotate`, | | | | :class:`trafo.scale`, | | | | :class:`trafo.slant`, | | | | :class:`trafo.translate` | +----------------------------+---------------------------------+------------------------------------+ .. todo:: specify which classes in the table are in fact instances Note that operations usually allow for certain attribute categories only. For example when stroking a path, text attributes are not allowed, while stroke attributes and decorators are. Some attributes might belong to several attribute categories like colours, which are both, stroke and fill attributes. Last, we discuss another important feature of PyX's attribute system. In order to allow the easy customisation of predefined attributes, it is possible to create a modified attribute by calling of an attribute instance, thereby specifying new parameters. A typical example is to modify the way a path is stroked or filled by constructing appropriate :class:`deco.stroked` or :class:`deco.filled` instances. For instance, the code :: c.stroke(path, [deco.filled([color.rgb.green])]) draws a path filled in green with a black outline. Here, ``deco.filled`` is already an instance which is modified to fill with the given color. Note that an equivalent version would be :: c.draw(path, [deco.stroked, deco.filled([color.rgb.green])]) In particular, you can see that :class:`deco.stroked` is already an attribute instance, since otherwise you were not allowed to pass it as a parameter to the draw method. Another example where the modification of a decorator is useful are arrows. For instance, the following code draws an arrow head with a more acute angle (compared to the default value of :math:`45` degrees):: c.stroke(path, [deco.earrow(angle=30)]) .. todo:: changeable attributes PyX-0.14.1/manual/intro.rst0000644000076500000240000000474512037344751015713 0ustar andrestaff00000000000000 .. _intro: ************ Introduction ************ PyX is a Python package for the creation of vector graphics. As such it readily allows one to generate encapsulated PostScript files by providing an abstraction of the PostScript graphics model. Based on this layer and in combination with the full power of the Python language itself, the user can just code any complexity of the figure wanted. PyX distinguishes itself from other similar solutions by its TeX/LaTeX interface that enables one to make direct use of the famous high quality typesetting of these programs. A major part of PyX on top of the already described basis is the provision of high level functionality for complex tasks like 2d plots in publication-ready quality. Organisation of the PyX package =============================== The PyX package is split into several modules, which can be categorised in the following groups +----------------------------------+------------------------------------------+ | Functionality | Modules | +==================================+==========================================+ | basic graphics functionality | :mod:`canvas`, :mod:`path`, :mod:`deco`, | | | :mod:`style`, :mod:`color`, and | | | :mod:`connector` | +----------------------------------+------------------------------------------+ | text output via TeX/LaTeX | :mod:`text` and :mod:`box` | +----------------------------------+------------------------------------------+ | linear transformations and units | :mod:`trafo` and :mod:`unit` | +----------------------------------+------------------------------------------+ | graph plotting functionality | :mod:`graph` (including submodules) and | | | :mod:`graph.axis` (including submodules) | +----------------------------------+------------------------------------------+ | EPS file inclusion | :mod:`epsfile` | +----------------------------------+------------------------------------------+ These modules (and some other less import ones) are imported into the module namespace by using :: from pyx import * at the beginning of the Python program. However, in order to prevent namespace pollution, you may also simply use ``import pyx``. Throughout this manual, we shall always assume the presence of the above given import line. PyX-0.14.1/manual/Makefile0000644000076500000240000000216112220544407015446 0ustar andrestaff00000000000000# Makefile for Sphinx documentation # PYTHON ?= python3 GS ?= gs # 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 all html latexpdf figs all: html latexpdf @echo "Done." clean: -rm -rf $(BUILDDIR)/* *.pdf *.png html: figs $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." latexpdf: figs $(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." figs: $(patsubst %.py, %.png, $(filter-out conf.py,$(wildcard *.py))) %.pdf: %.py export PYTHONPATH=$(CURDIR)/.. ; $(PYTHON) $^ %.png: %.pdf $(GS) -r100 -dNOPAUSE -dQUIET -dBATCH -sDEVICE=pngalpha -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sOutputFile=$@ $^ PyX-0.14.1/manual/manual.rst0000644000076500000240000000116712520511266016022 0ustar andrestaff00000000000000 ************** PyX Manual ************** .. topic:: Abstract PyX is a Python package for the creation of PostScript, PDF, and SVG files. It combines an abstraction of the PostScript drawing model with a TeX/LaTeX interface. Complex tasks like 2d and 3d plots in publication-ready quality are built out of these primitives. .. toctree:: intro graphics path metapost deformer canvas document text graph axis box connector epsfile svgfile bitmap bbox color pattern unit trafo colorname gradientname pathstyles arrows PyX-0.14.1/manual/metapost.rst0000644000076500000240000001151612037344751016406 0ustar andrestaff00000000000000.. module:: metapost.path =========================== Module :mod:`metapost.path` =========================== .. sectionauthor:: Michael Schindler The :mod:`metapost` subpackage provides some of the path functionality of the MetaPost program. The :mod:`metapost.path` presents the path construction facility of MetaPost. Similarly to the :mod:`normpath`, there is a short length *epsilon* (always in Postscript points pt) used as accuracy of numerical operations, such as calculating angles from short path elements, or for omitting such short path elements, etc. The default value is :math:`10^{-5}` and can be changed using the module function :func:`metapost.set`. Class :class:`path` --- MetaPost-like paths ------------------------------------------- .. class:: path(pathitems, epsilon=None) This class represents a MetaPost-like path which is created from the given list of knots and curves/lines. It can find an optimal way through given points. At points (knots), you can either specify a given tangent direction (angle in degrees) or a certain *curlyness* (relative to the curvature at the other end of a curve), or nothing. In the latter case, both the tangent and the *mock* curvature (an approximation to the real curvature, introduced by J. D. Hobby in MetaPost) will be continuous. The shape of the cubic Bezier curves between two points is controlled by its *tension*, unless you choose to set the control points manually. All possible path items are described below. They are either :ref:`knots` or :ref:`links`. Note that there is no explicit `closepath` class. Whether the path is open or closed depends on the type of knots used, begin endpoints or not. Note also that the number of knots and links must be equal for closed paths, and that you cannot create a path comprising closed subpaths. The *epsilon* argument governs the accuracy of the calculations implied in creating the path (see above). The value *None* means fallback to the default epsilon of the module. Instances of the class :class:`path` inherit all properties of the Postscript paths in :mod:`path`. .. _knots: Knots ----- .. class:: beginknot(x, y, curl=1, angle=None) The first knot, starting an open path at the coordinates (*x*, *y*). The properties of the curve in that point can either be given by its curlyness (default) or the angle of its tangent vector (in degrees). The *curl* parameter is (as in MetaPost) the ratio of the curvatures at this point and at the other point of the curve connecting it. .. class:: startknot(x, y, curl=1, angle=None) Synonym for :class:`beginknot`. .. class:: endknot(x, y, curl=1, angle=None) The last knot of an open path. Curlyness and angle are the same as in :class:`beginknot`. .. class:: smoothknot(x, y) This knot is the standard knot of MetaPost. It guarantees continuous tangent vectors and *mock curvatures* of the two curves it connects. Note: If one of the links is a line, the knot is changed to a :class:`roughknot` with either a specified angle (if the *keepangles* parameter is set in the line) or with *curl=1*. .. class:: roughknot(x, y, left_curl=1, right_curl=None, left_angle=None, right_angle=None) This knot is a possibly non-smooth knot, connecting two curves or lines. At each side of the knot (left/right) you can specify either the curlyness or the tangent angle. Note: If one of the links is a line with the *keepangles* parameter set, the angles will be set eplicitly, regardless of any curlyness set. .. class:: knot(x, y) Synonym for :class:`smoothknot`. .. _links: Links ----- .. class:: line(keepangles=False) A straight line which corresponds to the MetaPost command "--". The option *keepangles* will guarantee a continuous tangent. (The curvature may become discontinuous, however.) This behavior is achieved by turning adjacent knots into roughknots with specified angles. Note that a smoothknot and a roughknot with given curlyness do behave differently near a line. .. class:: tensioncurve(ltension=1, latleast=False, rtension=None, ratleast=None) The standard type of curve in MetaPost. It corresponds to the MetaPost command ".." or to "..." if the *atleast* parameters are set to True. The tension parameters indicate the tensions at the beginning (l) and the end (r) of the curve. Set the parameters (l/r)atleast to True if you want to avoid inflection points. .. class:: controlcurve(lcontrol, rcontrol) A cubic Bezier curve which has its control points explicity set, similar to the :class:`path.curveto` class of the Postscript paths. The control points at the beginning (l) and the end (r) must be coordinate pairs (x, y). .. class:: curve(ltension=1, latleast=False, rtension=None, ratleast=None) Synonym for :class:`tensioncurve`. PyX-0.14.1/manual/path.rst0000644000076500000240000003404412151151002015465 0ustar andrestaff00000000000000 .. module:: path ================== Module :mod:`path` ================== .. sectionauthor:: Jörg Lehmann The :mod:`path` module defines several important classes which are documented in the present section. .. _postscript_like_paths: Class :class:`path` --- PostScript-like paths --------------------------------------------- .. class:: path(*pathitems) This class represents a PostScript like path consisting of the path elements *pathitems*. All possible path items are described in Sect. :ref:`path_pathitem`. Note that there are restrictions on the first path element and likewise on each path element after a :class:`closepath` directive. In both cases, no current point is defined and the path element has to be an instance of one of the following classes: :class:`moveto`, :class:`arc`, and :class:`arcn`. Instances of the class :class:`path` provide the following methods (in alphabetic order): .. method:: path.append(pathitem) Appends a *pathitem* to the end of the path. .. method:: path.arclen() Returns the total arc length of the path. [#normpathconvert]_ .. method:: path.arclentoparam(lengths) Returns the parameter value(s) corresponding to the arc length(s) *lengths*. [#normpathconvert]_ .. method:: path.at(params) Returns the coordinates (as 2-tuple) of the path point(s) corresponding to the parameter value(s) *params*. [#normpathconvert]_ [#value_or_list]_ .. method:: path.atbegin() Returns the coordinates (as 2-tuple) of the first point of the path. [#normpathconvert]_ .. method:: path.atend() Returns the coordinates (as 2-tuple) of the end point of the path. [#normpathconvert]_ .. method:: path.bbox() Returns the bounding box of the path. .. method:: path.begin() Returns the parameter value (a :class:`normpathparam` instance) of the first point in the path. .. method:: path.curveradius(params) Returns the curvature radius/radii (or None if infinite) at parameter value(s) *params*. [#value_or_list]_ This is the inverse of the curvature at this parameter. Note that this radius can be negative or positive, depending on the sign of the curvature. [#normpathconvert]_ .. method:: path.end() Returns the parameter value (a :class:`normpathparam` instance) of the last point in the path. .. method:: path.extend(pathitems) Appends the list *pathitems* to the end of the path. .. method:: path.intersect(opath) Returns a tuple consisting of two lists of parameter values corresponding to the intersection points of the path with the other path *opath*, respectively. [#normpathconvert]_ For intersection points which are not farther apart then *epsilon* (defaulting to :math:`10^{-5}` PostScript points), only one is returned. .. method:: path.joined(opath) Appends *opath* to the end of the path, thereby merging the last subpath (which must not be closed) of the path with the first sub path of *opath* and returns the resulting new path. [#normpathconvert]_ Instead of using the :meth:`joined` method, you can also join two paths together with help of the ``<<`` operator, for instance ``p = p1 << p2``. .. method:: path.normpath(epsilon=None) Returns the equivalent :class:`normpath`. For the conversion and for later calculations with this :class:`normpath` an accuracy of *epsilon* is used. If *epsilon* is *None*, the global *epsilon* of the :mod:`path` module is used. .. method:: path.paramtoarclen(params) Returns the arc length(s) corresponding to the parameter value(s) *params*. [#value_or_list]_ [#normpathconvert]_ .. method:: path.range() Returns the maximal parameter value *param* that is allowed in the path methods. .. method:: path.reversed() Returns the reversed path. [#normpathconvert]_ .. method:: path.rotation(params) Returns a transformation or a list of transformations, which rotate the x-direction to the tangent vector and the y-direction to the normal vector at the parameter value(s) *params*. [#value_or_list]_ [#normpathconvert]_ .. method:: path.split(params) Splits the path at the parameter values *params*, which have to be sorted in ascending order, and returns a corresponding list of :class:`normpath` instances. [#normpathconvert]_ .. method:: path.tangent(params, length=1) Return a :class:`line` instance or a list of :class:`line` instances, corresponding to the tangent vectors at the parameter value(s) *params*. [#value_or_list]_ The tangent vector will be scaled to the length *length*. [#normpathconvert]_ .. method:: path.trafo(params) Returns a transformation or a list of tranformations, which translate the origin to a point on the path corresponding to parameter value(s) *params* and rotate the x-direction to the tangent vector and the y-direction to the normal vector. [#normpathconvert]_ .. method:: path.transformed(trafo) Returns the path transformed according to the linear transformation *trafo*. Here, ``trafo`` must be an instance of the :class:`trafo.trafo` class. [#normpathconvert]_ .. [#normpathconvert] This method requires a prior conversion of the path into a :class:`normpath` instance. This is done automatically (using the precision *epsilon* set globally using :meth:`path.set`). If you need a different *epsilon* for a normpath, you also can perform the conversion manually. .. [#value_or_list] In these methods, *params* may either be a single value or a list. In the latter case, the result of the method will be a list consisting of the results for each parameter. The parameter itself may either be a length (or a number which is then interpreted as a user length) or an instance of the class :class:`normpathparam`. In the former case, the length refers to the arc length along the path. .. _path_pathitem: Path elements ------------- The class :class:`pathitem` is the superclass of all PostScript path construction primitives. It is never used directly, but only by instantiating its subclasses, which correspond one by one to the PostScript primitives. Except for the path elements ending in ``_pt``, all coordinates passed to the path elements can be given as number (in which case they are interpreted as user units with the currently set default type) or in PyX lengths. The following operation move the current point and open a new subpath: .. class:: moveto(x, y) Path element which sets the current point to the absolute coordinates (*x*, *y*). This operation opens a new subpath. .. class:: rmoveto(dx, dy) Path element which moves the current point by (*dx*, *dy*). This operation opens a new subpath. Drawing a straight line can be accomplished using: .. class:: lineto(x, y) Path element which appends a straight line from the current point to the point with absolute coordinates (*x*, *y*), which becomes the new current point. .. class:: rlineto(dx, dy) Path element which appends a straight line from the current point to the point with relative coordinates (*dx*, *dy*), which becomes the new current point. For the construction of arc segments, the following three operations are available: .. class:: arc(x, y, r, angle1, angle2) Path element which appends an arc segment in counterclockwise direction with absolute coordinates (*x*, *y*) of the center and radius *r* from *angle1* to *angle2* (in degrees). If before the operation, the current point is defined, a straight line from the current point to the beginning of the arc segment is prepended. Otherwise, a subpath, which thus is the first one in the path, is opened. After the operation, the current point is at the end of the arc segment. .. class:: arcn(x, y, r, angle1, angle2) Same as :class:`arc` but in clockwise direction. .. class:: arct(x1, y1, x2, y2, r) Path element consisting of a line followed by an arc of radius *r*. The arc is part of the circle inscribed to the angle at *x1*, *y1* given by lines in the directions to the current point and to *x2*, *y2*. The initial line connects the current point to the point where the circle touches the line through the current point and *x1*, *y1*. The arc then continues to the point where the circle touches the line through *x1*, *y1* and *x2*, *y2*. Bézier curves can be constructed using: .. class:: curveto(x1, y1, x2, y2, x3, y3) Path element which appends a Bézier curve with the current point as first control point and the other control points (*x1*, *y1*), (*x2*, *y2*), and (*x3*, *y3*). .. class:: rcurveto(dx1, dy1, dx2, dy2, dx3, dy3) Path element which appends a Bézier curve with the current point as first control point and the other control points defined relative to the current point by the coordinates (*dx1*, *dy1*), (*dx2*, *dy2*), and (*dx3*, *dy3*). Note that when calculating the bounding box (see Sect. :mod:`bbox`) of Bézier curves, PyX uses for performance reasons the so-called control box, i.e., the smallest rectangle enclosing the four control points of the Bézier curve. In general, this is not the smallest rectangle enclosing the Bézier curve. Finally, an open subpath can be closed using: .. class:: closepath() Path element which closes the current subpath. For performance reasons, two non-PostScript path elements are defined, which perform multiple identical operations: .. class:: multilineto_pt(points_pt) Path element which appends straight line segments starting from the current point and going through the list of points given in the *points_pt* argument. All coordinates have to be given in PostScript points. .. class:: multicurveto_pt(points_pt) Path element which appends Bézier curve segments starting from the current point. *points_pt* is a sequence of 6-tuples containing the coordinates of the two control points and the end point of a multicurveto segment. .. _path_normpath: Class :class:`normpath` ----------------------- The :class:`normpath` class is used internally for all non-trivial path operations, cf. footnote [#normpathconvert]_ in Sect. :ref:`postscript_like_paths`. It represents a path as a list of subpaths, which are instances of the class :class:`normsubpath`. These :class:`normsubpath`\ s themselves consist of a list of :class:`normsubpathitems` which are either straight lines (:class:`normline`) or Bézier curves (:class:`normcurve`). A given path ``p`` can easily be converted to the corresponding :class:`normpath` ``np`` by:: np = p.normpath() Additionally, the accuracy that is used in all :class:`normpath` calculations can be specified by means of the argument *epsilon*, which defaults to :math:`10^{-5}`, where units of PostScript points are understood. This default value can also be changed using the module function :func:`path.set`. To construct a :class:`normpath` from a list of :class:`normsubpath` instances, they are passed to the :class:`normpath` constructor: .. class:: normpath(normsubpaths=[]) Construct a :class:`normpath` consisting of *subnormpaths*, which is a list of :class:`subnormpath` instances. Instances of :class:`normpath` offer all methods of regular :class:`path` instances, which also have the same semantics. An exception are the methods :meth:`append` and :meth:`extend`. While they allow for adding of instances of :class:`subnormpath` to the :class:`normpath` instance, they also keep the functionality of a regular path and allow for regular path elements to be appended. The latter are converted to the proper normpath representation during addition. In addition to the :class:`path` methods, a :class:`normpath` instance also offers the following methods, which operate on the instance itself, i.e., modify it in place. .. method:: normpath.join(other) Join *other*, which has to be a :class:`path` instance, to the :class:`normpath` instance. .. method:: normpath.reverse() Reverses the :class:`normpath` instance. .. method:: normpath.transform(trafo) Transforms the :class:`normpath` instance according to the linear transformation *trafo*. Finally, we remark that the sum of a :class:`normpath` and a :class:`path` always yields a :class:`normpath`. Class :class:`normsubpath` -------------------------- .. class:: normsubpath(normsubpathitems=[], closed=0, epsilon=1e-5) Construct a :class:`normsubpath` consisting of *normsubpathitems*, which is a list of :class:`normsubpathitem` instances. If *closed* is set, the :class:`normsubpath` will be closed, thereby appending a straight line segment from the first to the last point, if it is not already present. All calculations with the :class:`normsubpath` are performed with an accuracy of *epsilon* (in units of PostScript points). Most :class:`normsubpath` methods behave like the ones of a :class:`path`. Exceptions are: .. method:: normsubpath.append(anormsubpathitem) Append the *normsubpathitem* to the end of the :class:`normsubpath` instance. This is only possible if the :class:`normsubpath` is not closed, otherwise an :exc:`NormpathException` is raised. .. method:: normsubpath.extend(normsubpathitems) Extend the :class:`normsubpath` instances by *normsubpathitems*, which has to be a list of :class:`normsubpathitem` instances. This is only possible if the :class:`normsubpath` is not closed, otherwise an :exc:`NormpathException` is raised. .. method:: normsubpath.close() Close the :class:`normsubpath` instance by appending a straight line segment from the first to the last point, if not already present. .. _path_predefined: Predefined paths ---------------- For convenience, some often used paths are already predefined. All of them are subclasses of the :class:`path` class. .. class:: line(x0, y0, x1, y1) A straight line from the point (*x0*, *y0*) to the point (*x1*, *y1*). .. class:: curve(x0, y0, x1, y1, x2, y2, x3, y3) A Bézier curve with control points (*x0*, *y0*), :math:`\dots`, (*x3*, *y3*).\ .. class:: rect(x, y, w, h) A closed rectangle with lower left point (*x*, *y*), width *w*, and height *h*. .. class:: circle(x, y, r) A closed circle with center (*x*, *y*) and radius *r*. PyX-0.14.1/manual/pathstyles.py0000755000076500000240000000401512255047656016577 0ustar andrestaff00000000000000from pyx import * text.set(text.LatexRunner) text.preamble(r"\renewcommand{\familydefault}{\ttdefault}") c = canvas.canvas() # positioning is quite ugly ... but it works at the moment x = 0 y = 0 dx = 6 dy = -0.65 length = 0.8 def drawstyle(name, showpath=0, default=0): global x,y p = path.path(path.moveto(x + 0.1, y+0.1 ), path.rlineto(length/2.0, 0.3), path.rlineto(length/2.0, -0.3)) c.stroke(p, [style.linewidth.THIck, eval("style."+name)]) if showpath: c.stroke(p, [style.linewidth.Thin, color.gray.white]) if default: name = name + r"\rm\quad (default)" c.text(x + 1.5, y + 0.15, name, [text.size.footnotesize]) y += dy if y < -16: y = 0 x += dx drawstyle("linecap.butt", showpath=1, default=1) drawstyle("linecap.round", showpath=1) drawstyle("linecap.square", showpath=1) y += dy drawstyle("linejoin.miter", showpath=1, default=1) drawstyle("linejoin.round", showpath=1) drawstyle("linejoin.bevel", showpath=1) y += dy drawstyle("linestyle.solid", default=1) drawstyle("linestyle.dashed") drawstyle("linestyle.dotted") drawstyle("linestyle.dashdotted") y += dy drawstyle("linewidth.THIN") drawstyle("linewidth.THIn") drawstyle("linewidth.THin") drawstyle("linewidth.Thin") drawstyle("linewidth.thin") drawstyle("linewidth.normal", default=1) drawstyle("linewidth.thick") drawstyle("linewidth.Thick") drawstyle("linewidth.THick") drawstyle("linewidth.THIck") drawstyle("linewidth.THICk") drawstyle("linewidth.THICK") drawstyle("miterlimit.lessthan180deg", showpath=1) drawstyle("miterlimit.lessthan90deg", showpath=1) drawstyle("miterlimit.lessthan60deg", showpath=1) drawstyle("miterlimit.lessthan45deg", showpath=1) drawstyle("miterlimit.lessthan11deg", showpath=1, default=1) y += dy drawstyle("dash((1, 1, 2, 2, 3, 3), 0)") drawstyle("dash((1, 1, 2, 2, 3, 3), 1)") drawstyle("dash((1, 2, 3), 2)") drawstyle("dash((1, 2, 3), 3)") drawstyle("dash((1, 2, 3), 4)") drawstyle("dash((1, 2, 3), rellengths=1)") c.writePDFfile() PyX-0.14.1/manual/pathstyles.rst0000644000076500000240000000027012037344751016745 0ustar andrestaff00000000000000 .. module:: style .. _pathstyles: ********************* Appendix: path styles ********************* .. _fig_pathstyles: .. figure:: pathstyles.* :align: center path styles PyX-0.14.1/manual/pattern.rst0000644000076500000240000000672612037346772016243 0ustar andrestaff00000000000000 .. module:: pattern ********************* Module :mod:`pattern` ********************* .. sectionauthor:: Jörg Lehmann This module contains the :class:`pattern.pattern` class, whichs allows the definition of PostScript Tiling patterns (cf. Sect. 4.9 of the PostScript Language Reference Manual) which may then be used to fill paths. In addition, a number of predefined hatch patterns are included. Class :class:`pattern` ====================== The classes :class:`pattern.pattern` and :class:`canvas.canvas` differ only in their constructor and in the absence of a :meth:`writeEPSfile` method in the former. The :class:`pattern` constructor accepts the following keyword arguments: +-----------------+-----------------------------------------------+ | keyword | description | +=================+===============================================+ | ``painttype`` | ``1`` (default) for coloured patterns or | | | ``2`` for uncoloured patterns | +-----------------+-----------------------------------------------+ | ``tilingtype`` | ``1`` (default) for constant spacing tilings | | | (patterns are spaced constantly by a multiple | | | of a device pixel), ``2`` for undistorted | | | pattern cell, whereby the spacing may vary by | | | as much as one device pixel, or ``3`` for | | | constant spacing and faster tiling which | | | behaves as tiling type ``1`` but with | | | additional distortion allowed to permit a | | | more efficient implementation. | +-----------------+-----------------------------------------------+ | ``xstep`` | desired horizontal spacing between pattern | | | cells, use ``None`` (default) for automatic | | | calculation from pattern bounding box. | +-----------------+-----------------------------------------------+ | ``ystep`` | desired vertical spacing between pattern | | | cells, use ``None`` (default) for automatic | | | calculation from pattern bounding box. | +-----------------+-----------------------------------------------+ | ``bbox`` | bounding box of pattern. Use ``None`` for an | | | automatic determination of the bounding box | | | (including an enlargement by ``bboxenlarge`` | | | pts on each side.) | +-----------------+-----------------------------------------------+ | ``trafo`` | additional transformation applied to pattern | | | or ``None`` (default). This may be used to | | | rotate the pattern or to shift its phase (by | | | a translation). | +-----------------+-----------------------------------------------+ | ``bboxenlarge`` | enlargement when using the automatic bounding | | | box determination; default is 5 pts. | +-----------------+-----------------------------------------------+ After you have created a pattern instance, you define the pattern shape by drawing in it like in an ordinary canvas. To use the pattern, you simply pass the pattern instance to a :meth:`stroke`, :meth:`fill`, :meth:`draw` or :meth:`set` method of the canvas, just like you would do with a colour, etc. PyX-0.14.1/manual/pyx.sty0000644000076500000240000000006512037344751015376 0ustar andrestaff00000000000000\def\PyX{P\kern-.3em\lower.5ex\hbox{Y}\kern-.18em X} PyX-0.14.1/manual/radii.py0000644000076500000240000000055512171066410015453 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() circle = path.circle(0, 0, 2) line = path.line(-3, 1, 3, 2) c.stroke(circle, [style.linewidth.Thick]) c.stroke(line, [style.linewidth.Thick]) isects_circle, isects_line = circle.intersect(line) for isect in isects_circle: isectx, isecty = circle.at(isect) c.stroke(path.line(0, 0, isectx, isecty)) c.writePDFfile() PyX-0.14.1/manual/radii2.py0000644000076500000240000000104712171066411015533 0ustar andrestaff00000000000000from pyx import * c = canvas.canvas() circle = path.circle(0, 0, 2) line = path.line(-3, 1, 3, 2) isects_circle, isects_line = circle.intersect(line) arc1, arc2 = circle.split(isects_circle) arc = arc1.arclen() {%- endblock %} {%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} {%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} {%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and (sidebars != []) %} {%- set url_root = pathto('', 1) %} {# XXX necessary? #} {%- if url_root == '#' %}{% set url_root = '' %}{% endif %} {%- if not embedded and docstitle %} {%- set titlesuffix = " — "|safe + docstitle|e %} {%- else %} {%- set titlesuffix = "" %} {%- endif %} {%- macro relbar() %} {%- endmacro %} {%- macro sidebar() %} {%- if render_sidebar %}
{%- for sidebartemplate in sidebars %} {%- macro thissidebar() %}{%- include sidebartemplate -%}{% endmacro -%} {% if thissidebar()|length %}
{{ thissidebar() }}
{% endif %} {%- endfor %}
{%- endif %} {%- endmacro %} {%- macro script() %} {%- for scriptfile in script_files %} {%- endfor %} {%- endmacro %} {%- macro css() %} {%- for cssfile in css_files %} {%- endfor %} {%- endmacro %} {{ metatags }} {%- block htmltitle %} {{ title|striptags|e }}{{ titlesuffix }} {%- endblock %} {{ css() }} {%- if not embedded %} {{ script() }} {%- if use_opensearch %} {%- endif %} {%- if favicon %} {%- endif %} {%- endif %} {%- block linktags %} {%- if hasdoc('about') %} {%- endif %} {%- if hasdoc('genindex') %} {%- endif %} {%- if hasdoc('search') %} {%- endif %} {%- if hasdoc('copyright') %} {%- endif %} {%- if parents %} {%- endif %} {%- if next %} {%- endif %} {%- if prev %} {%- endif %} {%- endblock %} {%- block extrahead %} {% endblock %} {%- block header %}{% endblock %}
{%- block relbar1 %}{{ relbar() }}{% endblock %}
{%- block content %} {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
{%- block document %}
{%- if render_sidebar %}
{%- endif %}
{% block body %} {% endblock %}
{%- if render_sidebar %}
{%- endif %}
{%- endblock %} {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
{%- endblock %}
{%- block relbar2 %}{{ relbar() }}{% endblock %}
{%- block footer %} {%- endblock %} PyX-0.14.1/manual/theme/pyx/static/0000755000076500000240000000000012615763300017222 5ustar andrestaff00000000000000PyX-0.14.1/manual/theme/pyx/static/navbg.png0000644000076500000240000000017712205571654021036 0ustar andrestaff00000000000000PNG  IHDRCztEXtSoftwareAdobe ImageReadyqe<PLTEo'IDATxb`& PdvlIENDB`PyX-0.14.1/manual/theme/pyx/static/pyx.css0000644000076500000240000001056112255042611020552 0ustar andrestaff00000000000000/* * default.css_t * ~~~~~~~~~~~~~ * * Sphinx stylesheet -- default theme. * * :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: verdana,helvetica,sans-serif; font-size: 100%; background-color: #eed; color: #000; margin: 0; padding: 0; } div.document { background-image: url(navbg.png); background-repeat: repeat-y; background-color: #ffe; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 200px; border-left: 1px solid #88a; } div.body { background-color: #ffe; color: #333; padding: 0 20px 30px 20px; } div.footer { color: #333; width: 100%; padding: 9px 0 9px 0; text-align: center; font-size: 75%; } div.footer a { color: #333; text-decoration: underline; } div.related { background-color: #eed; line-height: 30px; color: #333; } div.relatedtop { border-bottom: 1px solid #88a; } div.relatedbottom { border-top: 1px solid #88a; border-bottom: 1px solid #88a; } div.related a { color: #a33; } div.sphinxsidebar { font-size: 10pt; } div.sphinxsidebar h3 { color: #333; margin: 0 0 10px 0; border-bottom: 1px solid #88a; padding: 0; font-size: 13pt; } div.sphinxsidebar h3 a { color: #333; } div.sphinxsidebar h4 { font-family: verdana,helvetica,sans-serif; color: #333; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { color: #333; } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 0; padding: 0; color: #333; } div.sphinxsidebar a { color: #a33; } div.sphinxsidebar input { border: 1px solid #a33; font-family: sans-serif; font-size: 1em; } p.logo { text-align:center; } div.sidebarbox { width: 140px; margin-top: 20px; margin-left: 9px; padding: 10px; border: 1px dashed #88a; background-color: #dcf; } /* -- hyperlink styles ------------------------------------------------------ */ a { color: #a33; text-decoration: none; } a:visited { color: #a33; text-decoration: none; } a:hover { text-decoration: underline; } /* -- body styles ----------------------------------------------------------- */ div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: verdana,helvetica,sans-serif; background-color: #ffe; font-weight: bolder; color: #333; border-bottom: 1px solid #88a; margin: 20px 0px 10px 0px; padding: 3px 0; } div.body h1 { margin-top: 0; font-size: 150%; } div.body h2 { font-size: 130%; } div.body h3 { font-size: 120%; } div.body h4 { font-size: 110%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 90%; } a.headerlink { color: #a33; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #a33; color: white; } div.body p, div.body dd, div.body li { text-align: justify; line-height: 130%; } div.admonition p.admonition-title + p { display: inline; } div.admonition p { margin-bottom: 5px; } div.admonition pre { margin-bottom: 5px; } div.admonition ul, div.admonition ol { margin-bottom: 5px; } div.note { background-color: #eed; border: 1px solid #88a; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eed; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 5px; background-color: #ffe; color: #333; line-height: 120%; border: 1px solid #ac9; border-left: none; border-right: none; } tt { background-color: #eed; padding: 0 1px 0 1px; font-size: 1.2em; } th { } .warning tt { background: #efc2c2; } .note tt { background: #d6d6d6; } .viewcode-back { font-family: verdana,helvetica,sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } div.sphinxsidebar #searchbox input[type="text"] { width: 100px; } PyX-0.14.1/manual/theme/pyx/theme.conf0000644000076500000240000000010712205421651017675 0ustar andrestaff00000000000000[theme] inherit = default stylesheet = pyx.css pygments_style = sphinx PyX-0.14.1/manual/trafo.rst0000644000076500000240000000732512037542415015665 0ustar andrestaff00000000000000 .. module:: trafo ******************************************* Module :mod:`trafo`: Linear transformations ******************************************* With the ``trafo`` module PyX supports linear transformations, which can then be applied to canvases, Bézier paths and other objects. It consists of the main class ``trafo`` representing a general linear transformation and subclasses thereof, which provide special operations like translation, rotation, scaling, and mirroring. Class :class:`trafo` ==================== The ``trafo`` class represents a general linear transformation, which is defined for a vector :math:`\vec{x}` as .. math:: \vec{x}' = \mathsf{A}\, \vec{x} + \vec{b}\ , where :math:`\mathsf{A}` is the transformation matrix and :math:`\vec{b}` the translation vector. The transformation matrix must not be singular, *i.e.* we require :math:`\det \mathsf{A} \ne 0`. Multiple ``trafo`` instances can be multiplied, corresponding to a consecutive application of the respective transformation. Note that ``trafo1*trafo2`` means that ``trafo1`` is applied after ``trafo2``, *i.e.* the new transformation is given by :math:`\mathsf{A} = \mathsf{A}_1 \mathsf{A}_2` and :math:`\vec{b} = \mathsf{A}_1 \vec{b}_2 + \vec{b}_1`. Use the ``trafo`` methods described below, if you prefer thinking the other way round. The inverse of a transformation can be obtained via the ``trafo`` method ``inverse()``, defined by the inverse :math:`\mathsf{A}^{-1}` of the transformation matrix and the translation vector :math:`-\mathsf{A}^{-1}\vec{b}`. .. class:: trafo(matrix=((1,0),(0,1)), vector=(0,0)) create new ``trafo`` instance with transformation ``matrix`` and ``vector`` .. method:: apply(x, y) apply ``trafo`` to point vector :math:`(\mathtt{x}, \mathtt{y})`. .. method:: inverse() returns inverse transformation of ``trafo``. .. method:: mirrored(angle) returns ``trafo`` followed by mirroring at line through :math:`(0,0)` with direction ``angle`` in degrees. .. method:: rotated(angle, x=None, y=None) returns ``trafo`` followed by rotation by ``angle`` degrees around point :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. method:: scaled(sx, sy=None, x=None, y=None) returns ``trafo`` followed by scaling with scaling factor ``sx`` in :math:`x`\ -direction, ``sy`` in :math:`y`\ -direction (:math:`\mathtt{sy}=\mathtt{sx}`, if not given) with scaling center :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. method:: slanted(a, angle=0, x=None, y=None) returns ``trafo`` followed by slant by ``angle`` around point :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. method:: translated(x, y) returns ``trafo`` followed by translation by vector :math:`(\mathtt{x}, \mathtt{y})`. Subclasses of :class:`trafo` ============================ The ``trafo`` module provides a number of subclasses of the ``trafo`` class, each of which corresponds to one ``trafo`` method. .. class:: mirror(angle) mirroring at line through :math:`(0,0)` with direction ``angle`` in degrees. .. class:: rotate(angle, x=None, y=None) rotation by ``angle`` degrees around point :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. class:: scale(sx, sy=None, x=None, y=None) scaling with scaling factor ``sx`` in :math:`x`\ -direction, ``sy`` in :math:`y`\ -direction (:math:`\mathtt{sy}=\mathtt{sx}`, if not given) with scaling center :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. class:: slant(a, angle=0, x=None, y=None) slant by ``angle`` around point :math:`(\mathtt{x}, \mathtt{y})`, or :math:`(0,0)`, if not given. .. class:: translate(x, y) translation by vector :math:`(\mathtt{x}, \mathtt{y})`. PyX-0.14.1/manual/unit.rst0000644000076500000240000001532712037344751015535 0ustar andrestaff00000000000000 .. module:: unit .. _module_unit: ****************** Module :mod:`unit` ****************** .. sectionauthor:: Jörg Lehmann With the ``unit`` module PyX makes available classes and functions for the specification and manipulation of lengths. As usual, lengths consist of a number together with a measurement unit, e.g., 1 cm, 50 points, 0.42 inch. In addition, lengths in PyX are composed of the five types "true", "user", "visual", "width", and "TeX", e.g., 1 user cm, 50 true points, 0.42 visual + 0.2 width inch. As their names indicate, they serve different purposes. True lengths are not scalable and are mainly used for return values of PyX functions. The other length types can be rescaled by the user and differ with respect to the type of object they are applied to: user length: used for lengths of graphical objects like positions etc. visual length: used for sizes of visual elements, like arrows, graph symbols, axis ticks, etc. width length: used for line widths TeX length: used for all TeX and LaTeX output When not specified otherwise, all types of lengths are interpreted in terms of a default unit, which, by default, is 1 cm. You may change this default unit by using the module level function .. function:: set(uscale=None, vscale=None, wscale=None, xscale=None, defaultunit=None) When *uscale*, *vscale*, *wscale*, or *xscale* is not `None`, the corresponding scaling factor(s) is redefined to the given number. When *defaultunit* is not `None`, the default unit is set to the given value, which has to be one of ``"cm"``, ``"mm"``, ``"inch"``, or ``"pt"``. For instance, if you only want thicker lines for a publication version of your figure, you can just rescale all width lengths using :: unit.set(wscale=2) Or suppose, you are used to specify length in imperial units. In this, admittedly rather unfortunate case, just use :: unit.set(defaultunit="inch") at the beginning of your program. Class :class:`length` ===================== .. class:: length(f, type="u", unit=None) The constructor of the :class:`length` class expects as its first argument a number *f*, which represents the prefactor of the given length. By default this length is interpreted as a user length (``type="u"``) in units of the current default unit (see :func:`set` function of the :mod:`unit` module). Optionally, a different *type* may be specified, namely ``"u"`` for user lengths, ``"v"`` for visual lengths, ``"w"`` for width lengths, ``"x"`` for TeX length, and ``"t"`` for true lengths. Furthermore, a different unit may be specified using the *unit* argument. Allowed values are ``"cm"``, ``"mm"``, ``"inch"``, and ``"pt"``. Instances of the :class:`length` class support addition and substraction either by another :class:`length` or by a number which is then interpeted as being a user length in default units, multiplication by a number and division either by another :class:`length` in which case a float is returned or by a number in which case a :class:`length` instance is returned. When two lengths are compared, they are first converted to meters (using the currently set scaling), and then the resulting values are compared. Predefined length instances =========================== A number of ``length`` instances are already predefined, which only differ in there values for ``type`` and ``unit``. They are summarized in the following table +-----------------+--------+--------+ | name | type | unit | +=================+========+========+ | :const:`m` | user | m | +-----------------+--------+--------+ | :const:`cm` | user | cm | +-----------------+--------+--------+ | :const:`mm` | user | mm | +-----------------+--------+--------+ | :const:`inch` | user | inch | +-----------------+--------+--------+ | :const:`pt` | user | points | +-----------------+--------+--------+ | :const:`t_m` | true | m | +-----------------+--------+--------+ | :const:`t_cm` | true | cm | +-----------------+--------+--------+ | :const:`t_mm` | true | mm | +-----------------+--------+--------+ | :const:`t_inch` | true | inch | +-----------------+--------+--------+ | :const:`t_pt` | true | points | +-----------------+--------+--------+ | :const:`u_m` | user | m | +-----------------+--------+--------+ | :const:`u_cm` | user | cm | +-----------------+--------+--------+ | :const:`u_mm` | user | mm | +-----------------+--------+--------+ | :const:`u_inch` | user | inch | +-----------------+--------+--------+ | :const:`u_pt` | user | points | +-----------------+--------+--------+ | :const:`v_m` | visual | m | +-----------------+--------+--------+ | :const:`v_cm` | visual | cm | +-----------------+--------+--------+ | :const:`v_mm` | visual | mm | +-----------------+--------+--------+ | :const:`v_inch` | visual | inch | +-----------------+--------+--------+ | :const:`v_pt` | visual | points | +-----------------+--------+--------+ | :const:`w_m` | width | m | +-----------------+--------+--------+ | :const:`w_cm` | width | cm | +-----------------+--------+--------+ | :const:`w_mm` | width | mm | +-----------------+--------+--------+ | :const:`w_inch` | width | inch | +-----------------+--------+--------+ | :const:`w_pt` | width | points | +-----------------+--------+--------+ | :const:`x_m` | TeX | m | +-----------------+--------+--------+ | :const:`x_cm` | TeX | cm | +-----------------+--------+--------+ | :const:`x_mm` | TeX | mm | +-----------------+--------+--------+ | :const:`x_inch` | TeX | inch | +-----------------+--------+--------+ | :const:`x_pt` | TeX | points | +-----------------+--------+--------+ Thus, in order to specify, e.g., a length of 5 width points, just use ``5*unit.w_pt``. Conversion functions ==================== If you want to know the value of a PyX length in certain units, you may use the predefined conversion functions which are given in the following table +---------------+--------------------------+ | function | result | +===============+==========================+ | ``tom(l)`` | ``l`` in units of m | +---------------+--------------------------+ | ``tocm(l)`` | ``l`` in units of cm | +---------------+--------------------------+ | ``tomm(l)`` | ``l`` in units of mm | +---------------+--------------------------+ | ``toinch(l)`` | ``l`` in units of inch | +---------------+--------------------------+ | ``topt(l)`` | ``l`` in units of points | +---------------+--------------------------+ If ``l`` is not yet a ``length`` instance but a number, it first is interpreted as a user length in the default units. PyX-0.14.1/PKG-INFO0000644000076500000240000000205312615763300013631 0ustar andrestaff00000000000000Metadata-Version: 1.1 Name: PyX Version: 0.14.1 Summary: Python package for the generation of PostScript, PDF, and SVG files Home-page: http://pyx.sourceforge.net/ Author: Jörg Lehmann, André Wobst Author-email: pyx-devel@lists.sourceforge.net License: GPL Description: PyX is a Python package for the creation of PostScript, PDF, and SVG files. It combines an abstraction of the PostScript drawing model with a TeX/LaTeX interface. Complex tasks like 2d and 3d plots in publication-ready quality are built out of these primitives. Platform: OS independent Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: Intended Audience :: End Users/Desktop Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Multimedia :: Graphics Classifier: Topic :: Scientific/Engineering :: Visualization Classifier: Topic :: Software Development :: Libraries :: Python Modules PyX-0.14.1/pyx/0000755000076500000240000000000012615763300013354 5ustar andrestaff00000000000000PyX-0.14.1/pyx/__init__.py0000644000076500000240000000564312506455767015513 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2005 Jörg Lehmann # Copyright (C) 2002-2006 André Wobst # Copyright (C) 2006 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """Python graphics package PyX is a Python package for the creation of PostScript and PDF files. It combines an abstraction of the PostScript drawing model with a TeX/LaTeX interface. Complex tasks like 2d and 3d plots in publication-ready quality are built out of these primitives. """ from . import version __version__ = version.version import sys if sys.hexversion < 0x03020000: sys.stderr.write("PyX {} requires Python 3.2 or higher.\n".format(__version__)) sys.exit() del sys __all__ = ["attr", "box", "bitmap", "canvas", "color", "connector", "deco", "deformer", "document", "epsfile", "svgfile", "graph", "mesh", "metapost", "path", "pattern", "pdfextra", "style", "trafo", "text", "unit"] import importlib # automatically import main modules into pyx namespace for module in __all__: importlib.import_module('.' + module, package='pyx') def pyxinfo(): """Make PyX a little verbose (for information or debugging) This function enables info level on the ``"pyx"`` logger. It also adds some general information about the Python interpreter, the PyX installation, and the PyX configuration to the logger. """ import logging, os, sys from . import config logging.lastResort.setLevel(logging.INFO) logger = logging.getLogger("pyx") logger.setLevel(logging.INFO) logger.info("Platform name is: {}".format(os.name)) logger.info("Python executable: {}".format(sys.executable)) logger.info("Python version: %s", sys.version) logger.info("PyX comes from: %s", __file__) logger.info("PyX version: %s", __version__) logger.info("pyxrc %s %s %s", "is" if os.path.isfile(config.user_pyxrc) else "would be" ,"loaded from:", config.user_pyxrc) logger.info("pykpathsea: %s", "available" if config.has_pykpathsea else "not available") logger.info("file locators in use: %s", ", ".join(method.__class__.__name__ for method in config.methods)) __all__.append("__version__") __all__.append("pyxinfo") PyX-0.14.1/pyx/attr.py0000644000076500000240000002032312234411502014667 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2003-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2003-2013 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # # some helper functions for the attribute handling # def mergeattrs(attrs): """perform merging of the attribute list attrs as defined by the merge methods of the attributes""" newattrs = [] for a in attrs: # XXX Do we really need this test? if isinstance(a, attr): newattrs = a.merge(newattrs) else: raise TypeError("only instances of class attr.attr are allowed") return newattrs def getattrs(attrs, getclasses): """return all attributes in the attribute list attrs, which are instances of one of the classes in getclasses""" return [attr for attr in attrs if isinstance(attr, tuple(getclasses))] def checkattrs(attrs, allowedclasses): """check whether only attributes which are instances of classes in allowedclasses are present in the attribute list attrs; if not it raises a TypeError""" if len(attrs) != len(getattrs(attrs, allowedclasses)): for attr1, attr2 in zip(attrs, getattrs(attrs, allowedclasses)): if attr1 is not attr2: raise TypeError("instance %r not allowed" % attr1) else: raise TypeError("instance %r not allowed" % attrs[len(getattrs(attrs, allowedclasses))]) def refineattrs(attrs, defaults, allowedclasses, allow_none=True): """combine the typical handling for attribues passed to a function in a single call""" # TODO the whole attribute handling needs some major documentation if allow_none and attrs is None: return None checkattrs(attrs, allowedclasses) return mergeattrs(defaults + attrs) # # attr class and simple descendants # class attr: """ attr is the base class of all attributes, i.e., colors, decorators, styles, text attributes and trafos""" def merge(self, attrs): """merge self into list of attrs self may either be appended to attrs or inserted at a proper position immediately before a dependent attribute. Attributes of the same type should be removed, if redundant. Note that it is safe to modify attrs.""" attrs.append(self) return attrs class exclusiveattr(attr): """an attribute which swallows all but the last of the same type (specified by the exlusiveclass argument to the constructor) in an attribute list""" def __init__(self, exclusiveclass): self.exclusiveclass = exclusiveclass def merge(self, attrs): attrs = [attr for attr in attrs if not isinstance(attr, self.exclusiveclass)] attrs.append(self) return attrs class sortbeforeattr(attr): """an attribute which places itself previous to all attributes given in the beforetheclasses argument to the constructor""" def __init__(self, beforetheclasses): self.beforetheclasses = tuple(beforetheclasses) def merge(self, attrs): first = True result = [] for attr in attrs: if first and isinstance(attr, self.beforetheclasses): result.append(self) first = False result.append(attr) if first: result.append(self) return result class sortbeforeexclusiveattr(attr): """an attribute which swallows all but the last of the same type (specified by the exlusiveclass argument to the constructor) in an attribute list and places itself previous to all attributes given in the beforetheclasses argument to the constructor""" def __init__(self, exclusiveclass, beforetheclasses): self.exclusiveclass = exclusiveclass self.beforetheclasses = tuple(beforetheclasses) def merge(self, attrs): first = 1 result = [] for attr in attrs: if first and isinstance(attr, self.beforetheclasses): result.append(self) first = 0 if not isinstance(attr, self.exclusiveclass): result.append(attr) if first: result.append(self) return result class clearclass(attr): """a special attribute which allows to remove all predecessing attributes of the same type in an attribute list""" def __init__(self, clearclass): self.clearclass = clearclass def merge(self, attrs): return [attr for attr in attrs if not isinstance(attr, self.clearclass)] class _clear(attr): """a special attribute which removes all predecessing attributes in an attribute list""" def merge(self, attrs): return [] # we define the attribute "clear", an instance of "_clear", # which can be used to remove all predecessing attributes # in an attribute list clear = _clear() # # changeable attrs # def selectattrs(attrs, index, total): """performs select calls for all changeable attributes and returns the resulting attribute list - attrs should be a list containing attributes and changeable attributes - index should be an unsigned integer - total should be a positive number - valid sections fullfill 0<=index # Copyright (C) 2002-2007 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from . import attr class canvasitem: """Base class for everything which can be inserted into a canvas""" def bbox(self): """return bounding box of canvasitem""" raise NotImplementedError() def requiretextregion(self): """indicates whether a canvasitem needs to be part of a PDF text region""" return False def processPS(self, file, writer, context, registry, bbox): """process canvasitem by writing the corresponding PS code to file and by updating context, registry as well as bbox - the PS code corresponding to the canvasitem has to be written in the stream file, which provides a write(string) method - writer is the PSwriter used for the output - context is an instance of pswriter.context which is used for keeping track of the graphics state (current linewidth, colorspace and font, etc.) - registry is used for tracking resources needed by the canvasitem - bbox has to be updated to include the bounding box of the canvasitem """ raise NotImplementedError() def processPDF(self, file, writer, context, registry, bbox): """process canvasitem by writing the corresponding PDF code to file and by updating context, registry as well as bbox - the PDF code corresponding to the canvasitem has to be written in the stream file, which provides a write(string) method - writer is the PDFwriter used for the output, which contains properties like whether streamcompression is used - context is an instance of pdfwriter.context which is used for keeping track of the graphics state, in particular for the emulation of PS behaviour regarding fill and stroke styles, for keeping track of the currently selected font as well as of text regions. - registry is used for tracking resources needed by the canvasitem - bbox has to be updated to include the bounding box of the canvasitem """ raise NotImplementedError() class deformer(attr.attr): def deform(self, basepath): raise NotImplementedError() PyX-0.14.1/pyx/bbox.py0000644000076500000240000003007212507071714014663 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from . import unit # # classes representing bounding boxes # class bbox_pt: """class for bounding boxes This variant requires points in the constructor, and is used for internal purposes. A bbox for which llx_pt is None represents an empty bbox, i.e., one containing no points. """ def __init__(self, llx_pt, lly_pt, urx_pt, ury_pt): self.llx_pt = llx_pt self.lly_pt = lly_pt self.urx_pt = urx_pt self.ury_pt = ury_pt def __bool__(self): return self.llx_pt is not None def __add__(self, other): """join two bboxes""" if self.llx_pt is not None: if other.llx_pt is not None: return bbox_pt(min(self.llx_pt, other.llx_pt), min(self.lly_pt, other.lly_pt), max(self.urx_pt, other.urx_pt), max(self.ury_pt, other.ury_pt)) else: return bbox_pt(self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) else: return bbox_pt(other.llx_pt, other.lly_pt, other.urx_pt, other.ury_pt) def __iadd__(self, other): """join two bboxes inplace""" if self.llx_pt is not None: if other.llx_pt is not None: self.llx_pt = min(self.llx_pt, other.llx_pt) self.lly_pt = min(self.lly_pt, other.lly_pt) self.urx_pt = max(self.urx_pt, other.urx_pt) self.ury_pt = max(self.ury_pt, other.ury_pt) else: self.llx_pt = other.llx_pt self.lly_pt = other.lly_pt self.urx_pt = other.urx_pt self.ury_pt = other.ury_pt return self def __mul__(self, other): """return intersection of two bboxes""" if self.llx_pt is not None and other.llx_pt is not None: return bbox_pt(max(self.llx_pt, other.llx_pt), max(self.lly_pt, other.lly_pt), min(self.urx_pt, other.urx_pt), min(self.ury_pt, other.ury_pt)) else: return empty() def __imul__(self, other): """intersect two bboxes in place""" if self.llx_pt is not None and other.llx_pt is not None: self.llx_pt = max(self.llx_pt, other.llx_pt) self.lly_pt = max(self.lly_pt, other.lly_pt) self.urx_pt = min(self.urx_pt, other.urx_pt) self.ury_pt = min(self.ury_pt, other.ury_pt) elif other.llx_pt is None: self.llx_pt = None return self def copy(self): return bbox_pt(self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) def set(self, other): self.llx_pt = other.llx_pt self.lly_pt = other.lly_pt self.urx_pt = other.urx_pt self.ury_pt = other.ury_pt def lowrestuple_pt(self): if self.llx_pt is None: raise ValueError("Cannot return low-res tuple for empty bbox") return (math.floor(self.llx_pt), math.floor(self.lly_pt), math.ceil(self.urx_pt), math.ceil(self.ury_pt)) def highrestuple_pt(self): if self.llx_pt is None: raise ValueError("Cannot return high-res tuple for empty bbox") return (self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) def intersects(self, other): """check, if two bboxes intersect eachother""" if self.llx_pt is None or other.llx_pt is None: return 0 else: return not (self.llx_pt > other.urx_pt or self.lly_pt > other.ury_pt or self.urx_pt < other.llx_pt or self.ury_pt < other.lly_pt) def includepoint_pt(self, x_pt, y_pt): if self.llx_pt is None: self.llx_pt = self.urx_pt = x_pt self.lly_pt = self.ury_pt = y_pt else: self.llx_pt = min(self.llx_pt, x_pt) self.lly_pt = min(self.lly_pt, y_pt) self.urx_pt = max(self.urx_pt, x_pt) self.ury_pt = max(self.ury_pt, y_pt) def transform(self, trafo): """transform bbox in place by trafo""" if self.llx_pt is None: return # we have to transform all four corner points of the bbox llx_pt, lly_pt = trafo.apply_pt(self.llx_pt, self.lly_pt) lrx_pt, lry_pt = trafo.apply_pt(self.urx_pt, self.lly_pt) urx_pt, ury_pt = trafo.apply_pt(self.urx_pt, self.ury_pt) ulx_pt, uly_pt = trafo.apply_pt(self.llx_pt, self.ury_pt) # Now, by sorting, we obtain the lower left and upper right corner # of the new bounding box. self.llx_pt = min(llx_pt, lrx_pt, urx_pt, ulx_pt) self.lly_pt = min(lly_pt, lry_pt, ury_pt, uly_pt) self.urx_pt = max(llx_pt, lrx_pt, urx_pt, ulx_pt) self.ury_pt = max(lly_pt, lry_pt, ury_pt, uly_pt) def transformed(self, trafo): """return bbox transformed by trafo""" if self.llx_pt is None: return empty() # we have to transform all four corner points of the bbox llx_pt, lly_pt = trafo.apply_pt(self.llx_pt, self.lly_pt) lrx_pt, lry_pt = trafo.apply_pt(self.urx_pt, self.lly_pt) urx_pt, ury_pt = trafo.apply_pt(self.urx_pt, self.ury_pt) ulx_pt, uly_pt = trafo.apply_pt(self.llx_pt, self.ury_pt) # Now, by sorting, we obtain the lower left and upper right corner # of the new bounding box. return bbox_pt(min(llx_pt, lrx_pt, urx_pt, ulx_pt), min(lly_pt, lry_pt, ury_pt, uly_pt), max(llx_pt, lrx_pt, urx_pt, ulx_pt), max(lly_pt, lry_pt, ury_pt, uly_pt)) def enlarge_pt(self, all_pt=0, bottom_pt=None, left_pt=None, top_pt=None, right_pt=None): """enlarge bbox in place by the given amounts in pts all is used, if bottom, left, top and/or right are not given. """ if self.llx_pt is None: return if bottom_pt is None: bottom_pt = all_pt if left_pt is None: left_pt = all_pt if top_pt is None: top_pt = all_pt if right_pt is None: right_pt = all_pt self.llx_pt -= left_pt self.lly_pt -= bottom_pt self.urx_pt += right_pt self.ury_pt += top_pt def enlarged_pt(self, all_pt=0, bottom_pt=None, left_pt=None, top_pt=None, right_pt=None): """return bbox enlarged by the given amounts in pts all is used, if bottom, left, top and/or right are not given. """ if self.llx_pt is None: return empty() if bottom_pt is None: bottom_pt = all_pt if left_pt is None: left_pt = all_pt if top_pt is None: top_pt = all_pt if right_pt is None: right_pt = all_pt return bbox_pt(self.llx_pt-left_pt, self.lly_pt-bottom_pt, self.urx_pt+right_pt, self.ury_pt+top_pt) def enlarge(self, all=0, bottom=None, left=None, top=None, right=None): """enlarge bbox in place all is used, if bottom, left, top and/or right are not given. """ if self.llx_pt is None: return bottom_pt = left_pt = top_pt = right_pt = unit.topt(all) if bottom is not None: bottom_pt = unit.topt(bottom) if left is not None: left_pt = unit.topt(left) if top is not None: top_pt = unit.topt(top) if right is not None: right_pt = unit.topt(right) self.llx_pt -= left_pt self.lly_pt -= bottom_pt self.urx_pt += right_pt self.ury_pt += top_pt def enlarged(self, all=0, bottom=None, left=None, top=None, right=None): """return bbox enlarged all is used, if bottom, left, top and/or right are not given. """ if self.llx_pt is None: return empty() bottom_pt = left_pt = top_pt = right_pt = unit.topt(all) if bottom is not None: bottom_pt = unit.topt(bottom) if left is not None: left_pt = unit.topt(left) if top is not None: top_pt = unit.topt(top) if right is not None: right_pt = unit.topt(right) return bbox_pt(self.llx_pt-left_pt, self.lly_pt-bottom_pt, self.urx_pt+right_pt, self.ury_pt+top_pt) def rect(self): """return rectangle corresponding to bbox""" from . import path if self.llx_pt is None: raise ValueError("Cannot return path for empty bbox") return path.rect_pt(self.llx_pt, self.lly_pt, self.urx_pt-self.llx_pt, self.ury_pt-self.lly_pt) path = rect def height_pt(self): """return height of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return heigth of empty bbox") return self.ury_pt-self.lly_pt def width_pt(self): """return width of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return width of empty bbox") return self.urx_pt-self.llx_pt def top_pt(self): """return top coordinate of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return top coordinate of empty bbox") return self.ury_pt def bottom_pt(self): """return bottom coordinate of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return bottom coordinate of empty bbox") return self.lly_pt def left_pt(self): """return left coordinate of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return left coordinate of empty bbox") return self.llx_pt def right_pt(self): """return right coordinate of bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return right coordinate of empty bbox") return self.urx_pt def center_pt(self): """return coordinates of the center of the bbox in pts""" if self.llx_pt is None: raise ValueError("Cannot return center coordinates of empty bbox") return 0.5 * (self.llx_pt+self.urx_pt), 0.5 * (self.lly_pt+self.ury_pt) def height(self): """return height of bbox""" return self.height_pt() * unit.t_pt def width(self): """return width of bbox""" return self.width_pt() * unit.t_pt def top(self): """return top coordinate of bbox""" return self.ury_pt * unit.t_pt def bottom(self): """return bottom coordinate of bbox""" return self.lly_pt * unit.t_pt def left(self): """return left coordinate of bbox""" return self.llx_pt * unit.t_pt def right(self): """return right coordinate of bbox""" return self.urx_pt * unit.t_pt def center(self): """return coordinates of the center of the bbox""" centerx_pt, centery_pt = self.center_pt() return centerx_pt * unit.t_pt, centery_pt * unit.t_pt class bbox(bbox_pt): """class for bounding boxes""" def __init__(self, llx_pt, lly_pt, urx_pt, ury_pt): llx_pt = unit.topt(llx_pt) lly_pt = unit.topt(lly_pt) urx_pt = unit.topt(urx_pt) ury_pt = unit.topt(ury_pt) bbox_pt.__init__(self, llx_pt, lly_pt, urx_pt, ury_pt) class empty(bbox_pt): """empty bounding box, i.e., one containing no point""" def __init__(self): bbox_pt.__init__(self, None, None, None, None) PyX-0.14.1/pyx/bitmap.py0000644000076500000240000006270712535570011015212 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2004-2015 André Wobst # Copyright (C) 2011 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import binascii, logging, struct, io try: import zlib haszlib = True except: haszlib = False from . import bbox, baseclasses, pswriter, pdfwriter, trafo, unit logger = logging.getLogger("pyx") devicenames = {"L": "/DeviceGray", "RGB": "/DeviceRGB", "CMYK": "/DeviceCMYK"} decodestrings = {"L": "[0 1]", "RGB": "[0 1 0 1 0 1]", "CMYK": "[0 1 0 1 0 1 0 1]", "P": "[0 255]"} def ascii85lines(datalen): if datalen < 4: return 1 return (datalen + 56)/60 def ascii85stream(file, data): """Encodes the string data in ASCII85 and writes it to the stream file. The number of lines written to the stream is known just from the length of the data by means of the ascii85lines function. Note that the tailing newline character of the last line is not added by this function, but it is taken into account in the ascii85lines function.""" i = 3 # go on smoothly in case of data length equals zero l = 0 l = [None, None, None, None] for i in range(len(data)): c = data[i] l[i%4] = c if i%4 == 3: if i%60 == 3 and i != 3: file.write("\n") if l: # instead of # l[3], c5 = divmod(256*256*256*l[0]+256*256*l[1]+256*l[2]+l[3], 85) # l[2], c4 = divmod(l[3], 85) # we have to avoid number > 2**31 by l[3], c5 = divmod(256*256*l[0]+256*256*l[1]+256*l[2]+l[3], 85) l[2], c4 = divmod(256*256*3*l[0]+l[3], 85) l[1], c3 = divmod(l[2], 85) c1 , c2 = divmod(l[1], 85) file.write_bytes(struct.pack("BBBBB", c1+33, c2+33, c3+33, c4+33, c5+33)) else: file.write("z") if i%4 != 3: for j in range((i%4) + 1, 4): l[j] = 0 l[3], c5 = divmod(256*256*l[0]+256*256*l[1]+256*l[2]+l[3], 85) l[2], c4 = divmod(256*256*3*l[0]+l[3], 85) l[1], c3 = divmod(l[2], 85) c1 , c2 = divmod(l[1], 85) file.write_bytes(struct.pack("BBBB", c1+33, c2+33, c3+33, c4+33)[:(i%4)+2]) _asciihexlinelength = 64 def asciihexlines(datalen): return (datalen*2 + _asciihexlinelength - 1) / _asciihexlinelength def asciihexstream(file, data): hexdata = binascii.b2a_hex(data) for i in range((len(hexdata)-1)/_asciihexlinelength + 1): file.write(hexdata[i*_asciihexlinelength: i*_asciihexlinelength+_asciihexlinelength]) file.write("\n") class palette: def __init__(self, mode, data): self.mode = mode self.data = data def getdata(self): return self.mode, self.data class image: def __init__(self, width, height, mode, data, compressed=None, palette=None): if width <= 0 or height <= 0: raise ValueError("valid image size") if mode not in ["L", "RGB", "CMYK", "LA", "RGBA", "CMYKA", "AL", "ARGB", "ACMYK", "P"]: raise ValueError("invalid mode") if compressed is None and len(mode)*width*height != len(data): raise ValueError("wrong size of uncompressed data") self.size = width, height self.mode = mode self.data = data self.compressed = compressed self.palette = palette def split(self): if self.compressed is not None: raise RuntimeError("cannot extract bands from compressed image") bands = len(self.mode) width, height = self.size return [image(width, height, "L", bytes(self.data[band::bands])) for band in range(bands)] def tobytes(self, *args): if len(args): raise RuntimeError("encoding not supported in this implementation") return self.data def convert(self, model): raise RuntimeError("color model conversion not supported in this implementation") def save(self, file, format=None, **attrs): if format != "png": raise RuntimeError("Uncompressed image can be output as PNG only.", format, file) if not haszlib: raise ValueError("PNG output not available due to missing zlib module.") try: pngmode, bytesperpixel = {"L": (0, 1), "LA": (4, 2), "RGB": (2, 3), "RGBA": (6, 4), "P": (3, 1)}[self.mode] except KeyError: raise RuntimeError("Unsupported mode '%s' for PNG output." % self.mode) width, height = self.size assert len(self.data) == width*height*bytesperpixel # inject filter byte to each scanline data = b"".join(b"\x00" + self.data[bytesperpixel*width*pos:bytesperpixel*width*(pos+1)] for pos in range(0, height)) chunk=lambda name, data=b"": struct.pack("!I", len(data)) + name + data + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(name + data)) file.write(b"\x89PNG\r\n\x1a\n") file.write(chunk(b"IHDR", struct.pack("!2I5B", width, height, 8, pngmode, 0, 0, 0))) if self.mode == "P": palettemode, palettedata = self.palette.getdata() if palettemode == "L": palettemode = "RGB" palettedata = b"".join(bytes([x, x, x]) for x in palettedata) if palettemode != "RGB": raise RuntimeError("Unsupported palette mode '%s' for PNG output." % palettemode) file.write(chunk(b"PLTE", palettedata)) file.write(chunk(b"IDAT", zlib.compress(data, 9))) file.write(chunk(b"IEND")) class jpegimage(image): def __init__(self, file): try: data = file.read() except: with open(file, "rb") as f: data = f.read() pos = 0 nestinglevel = 0 try: while True: if data[pos] == 0o377 and data[pos+1] not in [0, 0o377]: # print("marker: 0x%02x \\%03o" % (data[pos+1], data[pos+1])) if data[pos+1] == 0o330: if not nestinglevel: begin = pos nestinglevel += 1 elif not nestinglevel: raise ValueError("begin marker expected") elif data[pos+1] == 0o331: nestinglevel -= 1 if not nestinglevel: end = pos + 2 break elif data[pos+1] in [0o300, 0o302]: l, bits, height, width, components = struct.unpack(">HBHHB", data[pos+2:pos+10]) if bits != 8: raise ValueError("implementation limited to 8 bit per component only") try: mode = {1: "L", 3: "RGB", 4: "CMYK"}[components] except KeyError: raise ValueError("invalid number of components") pos += l+1 elif data[pos+1] == 0o340: l, id, major, minor, dpikind, xdpi, ydpi = struct.unpack(">H5sBBBHH", data[pos+2:pos+16]) if dpikind == 1: self.info = {"dpi": (xdpi, ydpi)} elif dpikind == 2: self.info = {"dpi": (xdpi*2.54, ydpi*2.45)} # else do not provide dpi information pos += l+1 pos += 1 except IndexError: raise ValueError("end marker expected") image.__init__(self, width, height, mode, data[begin:end], compressed="DCT") def save(self, file, format=None, **attrs): if format != "jpeg": raise RuntimeError("JPG image can be output as JPG only.") file.write(self.data) class PSimagedata(pswriter.PSresource): def __init__(self, name, data, singlestring, maxstrlen): pswriter.PSresource.__init__(self, "imagedata", name) self.data = data self.singlestring = singlestring self.maxstrlen = maxstrlen def output(self, file, writer, registry): file.write("%%%%BeginRessource: %s\n" % self.id) if self.singlestring: file.write("%%%%BeginData: %i ASCII Lines\n" "<~" % ascii85lines(len(self.data))) ascii85stream(file, self.data) file.write("~>\n" "%%EndData\n") else: datalen = len(self.data) tailpos = datalen - datalen % self.maxstrlen file.write("%%%%BeginData: %i ASCII Lines\n" % ((tailpos/self.maxstrlen) * ascii85lines(self.maxstrlen) + ascii85lines(datalen-tailpos))) file.write("[ ") for i in range(0, tailpos, self.maxstrlen): file.write("<~") ascii85stream(file, self.data[i: i+self.maxstrlen]) file.write("~>\n") if datalen != tailpos: file.write("<~") ascii85stream(file, self.data[tailpos:]) file.write("~>") file.write("]\n" "%%EndData\n") file.write("/%s exch def\n" % self.id) file.write("%%EndRessource\n") class PDFimagepalettedata(pdfwriter.PDFobject): def __init__(self, name, data): pdfwriter.PDFobject.__init__(self, "imagepalettedata", name) self.data = data def write(self, file, writer, registry): file.write("<<\n" "/Length %d\n" % len(self.data)) file.write(">>\n" "stream\n") file.write(self.data) file.write("\n" "endstream\n") class PDFimage(pdfwriter.PDFobject): def __init__(self, name, width, height, palettemode, palettedata, mode, bitspercomponent, compressmode, data, smask, registry, addresource=True): pdfwriter.PDFobject.__init__(self, "image", name) if addresource: if palettedata is not None: procset = "ImageI" elif mode == "L": procset = "ImageB" else: procset = "ImageC" registry.addresource("XObject", name, self, procset=procset) if palettedata is not None: # note that acrobat wants a palette to be an object (which clearly is a bug) self.PDFpalettedata = PDFimagepalettedata(name, palettedata) registry.add(self.PDFpalettedata) self.name = name self.width = width self.height = height self.palettemode = palettemode self.palettedata = palettedata self.mode = mode self.bitspercomponent = bitspercomponent self.compressmode = compressmode self.data = data self.smask = smask def write(self, file, writer, registry): file.write("<<\n" "/Type /XObject\n" "/Subtype /Image\n" "/Width %d\n" % self.width) file.write("/Height %d\n" % self.height) if self.palettedata is not None: file.write("/ColorSpace [ /Indexed %s %i\n" % (devicenames[self.palettemode], len(self.palettedata)/3-1)) file.write("%d 0 R\n" % registry.getrefno(self.PDFpalettedata)) file.write("]\n") else: file.write("/ColorSpace %s\n" % devicenames[self.mode]) if self.smask: file.write("/SMask %d 0 R\n" % registry.getrefno(self.smask)) file.write("/BitsPerComponent %d\n" % self.bitspercomponent) file.write("/Length %d\n" % len(self.data)) if self.compressmode: file.write("/Filter /%sDecode\n" % self.compressmode) file.write(">>\n" "stream\n") file.write_bytes(self.data) file.write("\n" "endstream\n") class bitmap_trafo(baseclasses.canvasitem): def __init__(self, trafo, image, PSstoreimage=0, PSmaxstrlen=4093, PSbinexpand=1, compressmode="Flate", flatecompresslevel=6, dctquality=75, dctoptimize=0, dctprogression=0): self.pdftrafo = trafo self.image = image self.imagewidth, self.imageheight = image.size self.PSstoreimage = PSstoreimage self.PSmaxstrlen = PSmaxstrlen self.PSbinexpand = PSbinexpand self.compressmode = compressmode self.flatecompresslevel = flatecompresslevel self.dctquality = dctquality self.dctoptimize = dctoptimize self.dctprogression = dctprogression try: self.imagecompressed = image.compressed except: self.imagecompressed = None if self.compressmode not in [None, "Flate", "DCT"]: raise ValueError("invalid compressmode '%s'" % self.compressmode) if self.imagecompressed not in [None, "Flate", "DCT"]: raise ValueError("invalid compressed image '%s'" % self.imagecompressed) if self.compressmode is not None and self.imagecompressed is not None: raise ValueError("compression of a compressed image not supported") if not haszlib and self.compressmode == "Flate": logger.warning("zlib module not available, disable compression") self.compressmode = None def imagedata(self, interleavealpha): """ Returns a tuple (mode, data, alpha, palettemode, palettedata) where mode does not contain the alpha channel anymore. If there is an alpha channel, for interleavealpha == False it is returned as a band in alpha itself. For interleavealpha == True alpha will be True and the channel is interleaved in front of each pixel in data. """ alpha = palettemode = palettedata = None data = self.image mode = data.mode if mode.startswith("A"): mode = mode[1:] if interleavealpha: alpha = True else: bands = data.split() alpha = bands[0] data = image(self.imagewidth, self.imageheight, mode, b"".join([bytes(values) for values in zip(*[band.tobytes() for band in bands[1:]])]), palette=data.palette) if mode.endswith("A"): bands = data.split() mode = mode[:-1] if interleavealpha: alpha = True bands = list(bands[-1:]) + list(bands[:-1]) data = image(self.imagewidth, self.imageheight, "A%s" % mode, b"".join([bytes(values) for values in zip(*[band.tobytes() for band in bands])]), palette=data.palette) else: alpha = bands[-1] data = image(self.imagewidth, self.imageheight, mode, b"".join([bytes(values) for values in zip(*[band.tobytes() for band in bands[:-1]])]), palette=data.palette) if mode == "P": palettemode, palettedata = data.palette.getdata() if palettemode not in ["L", "RGB", "CMYK"]: logger.warning("image with invalid palette mode '%s' converted to rgb image" % palettemode) data = data.convert("RGB") mode = "RGB" palettemode = None palettedata = None elif len(mode) == 1: if mode != "L": logger.warning("specific single channel image mode not natively supported, converted to regular grayscale") data = data.convert("L") mode = "L" elif mode not in ["CMYK", "RGB"]: logger.warning("image with invalid mode converted to rgb") data = data.convert("RGB") mode = "RGB" if self.compressmode == "Flate": data = zlib.compress(data.tobytes(), self.flatecompresslevel) elif self.compressmode == "DCT": data = data.tobytes("jpeg", mode, self.dctquality, self.dctoptimize, self.dctprogression) else: data = data.tobytes() if alpha and not interleavealpha: # we might want a separate alphacompressmode if self.compressmode == "Flate": alpha = zlib.compress(alpha.tobytes(), self.flatecompresslevel) elif self.compressmode == "DCT": alpha = alpha.tobytes("jpeg", mode, self.dctquality, self.dctoptimize, self.dctprogression) else: alpha = alpha.tobytes() return mode, data, alpha, palettemode, palettedata def bbox(self): bb = bbox.empty() bb.includepoint_pt(*self.pdftrafo.apply_pt(0.0, 0.0)) bb.includepoint_pt(*self.pdftrafo.apply_pt(0.0, 1.0)) bb.includepoint_pt(*self.pdftrafo.apply_pt(1.0, 0.0)) bb.includepoint_pt(*self.pdftrafo.apply_pt(1.0, 1.0)) return bb def processPS(self, file, writer, context, registry, bbox): mode, data, alpha, palettemode, palettedata = self.imagedata(True) pstrafo = trafo.translate_pt(0, -1.0).scaled(self.imagewidth, -self.imageheight)*self.pdftrafo.inverse() PSsinglestring = self.PSstoreimage and len(data) < self.PSmaxstrlen if PSsinglestring: PSimagename = "image-%d-%s-singlestring" % (id(self.image), self.compressmode) else: PSimagename = "image-%d-%s-stringarray" % (id(self.image), self.compressmode) if self.PSstoreimage and not PSsinglestring: registry.add(pswriter.PSdefinition("imagedataaccess", b"{ /imagedataindex load " # get list index b"dup 1 add /imagedataindex exch store " # store increased index b"/imagedataid load exch get }")) # select string from array if self.PSstoreimage: registry.add(PSimagedata(PSimagename, data, PSsinglestring, self.PSmaxstrlen)) bbox += self.bbox() file.write("gsave\n") if palettedata is not None: file.write("[ /Indexed %s %i\n" % (devicenames[palettemode], len(palettedata)/3-1)) file.write("%%%%BeginData: %i ASCII Lines\n" % ascii85lines(len(palettedata))) file.write("<~") ascii85stream(file, palettedata) file.write("~>\n" "%%EndData\n") file.write("] setcolorspace\n") else: file.write("%s setcolorspace\n" % devicenames[mode]) if self.PSstoreimage and not PSsinglestring: file.write("/imagedataindex 0 store\n" # not use the stack since interpreters differ in their stack usage "/imagedataid %s store\n" % PSimagename) file.write("<<\n") if alpha: file.write("/ImageType 3\n" "/DataDict\n" "<<\n") file.write("/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % pstrafo) file.write("/Decode %s\n" % decodestrings[mode]) file.write("/DataSource ") if self.PSstoreimage: if PSsinglestring: file.write("/%s load" % PSimagename) else: file.write("/imagedataaccess load") # some printers do not allow for inline code here -> we store it in a resource else: if self.PSbinexpand == 2: file.write("currentfile /ASCIIHexDecode filter") else: file.write("currentfile /ASCII85Decode filter") if self.compressmode or self.imagecompressed: file.write(" /%sDecode filter" % (self.compressmode or self.imagecompressed)) file.write("\n") file.write(">>\n") if alpha: file.write("/MaskDict\n" "<<\n" "/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % pstrafo) file.write("/Decode [1 0]\n" ">>\n" "/InterleaveType 1\n" ">>\n") if self.PSstoreimage: file.write("image\n") else: if self.PSbinexpand == 2: file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (asciihexlines(len(data)) + 1)) asciihexstream(file, data) file.write(">\n") else: # the datasource is currentstream (plus some filters) file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (ascii85lines(len(data)) + 1)) ascii85stream(file, data) file.write("~>\n") file.write("%%EndData\n") file.write("grestore\n") def processPDF(self, file, writer, context, registry, bbox): mode, data, alpha, palettemode, palettedata = self.imagedata(False) name = "image-%d-%s" % (id(self.image), self.compressmode or self.imagecompressed) if alpha: alpha = PDFimage("%s-smask" % name, self.imagewidth, self.imageheight, None, None, "L", 8, self.compressmode, alpha, None, registry, addresource=False) registry.add(alpha) registry.add(PDFimage(name, self.imagewidth, self.imageheight, palettemode, palettedata, mode, 8, self.compressmode or self.imagecompressed, data, alpha, registry)) bbox += self.bbox() file.write("q\n") self.pdftrafo.processPDF(file, writer, context, registry) file.write("/%s Do\n" % name) file.write("Q\n") def processSVG(self, xml, writer, context, registry, bbox): if self.compressmode == "Flate": f = io.BytesIO() self.image.save(f, "png") inlinedata = "data:image/png;base64," + binascii.b2a_base64(f.getvalue()).decode('ascii').replace("\n", "") elif self.compressmode == "DCT" or self.imagecompressed == "DCT": f = io.BytesIO() self.image.save(f, "jpeg") inlinedata = "data:image/jpeg;base64," + binascii.b2a_base64(f.getvalue()).decode('ascii').replace("\n", "") else: raise ValueError("SVG cannot store uncompressed image data.") attrs = {"preserveAspectRatio": "none", "x": "0", "y": "-1", "width": "1", "height": "1", "xlink:href": inlinedata} self.pdftrafo.processSVGattrs(attrs, writer, context, registry) xml.startSVGElement("image", attrs) xml.endSVGElement("image") class bitmap_pt(bitmap_trafo): def __init__(self, xpos_pt, ypos_pt, image, width_pt=None, height_pt=None, ratio=None, **kwargs): imagewidth, imageheight = image.size if width_pt is not None or height_pt is not None: if width_pt is None: if ratio is None: width_pt = height_pt * imagewidth / float(imageheight) else: width_pt = ratio * height_pt elif height_pt is None: if ratio is None: height_pt = width_pt * imageheight / float(imagewidth) else: height_pt = (1.0/ratio) * width_pt elif ratio is not None: raise ValueError("can't specify a ratio when setting width_pt and height_pt") else: if ratio is not None: raise ValueError("must specify width_pt or height_pt to set a ratio") widthdpi, heightdpi = image.info["dpi"] # fails when no dpi information available width_pt = 72.0 * imagewidth / float(widthdpi) height_pt = 72.0 * imageheight / float(heightdpi) bitmap_trafo.__init__(self, trafo.trafo_pt(((float(width_pt), 0.0), (0.0, float(height_pt))), (float(xpos_pt), float(ypos_pt))), image, **kwargs) class bitmap(bitmap_pt): def __init__(self, xpos, ypos, image, width=None, height=None, **kwargs): xpos_pt = unit.topt(xpos) ypos_pt = unit.topt(ypos) if width is not None: width_pt = unit.topt(width) else: width_pt = None if height is not None: height_pt = unit.topt(height) else: height_pt = None bitmap_pt.__init__(self, xpos_pt, ypos_pt, image, width_pt=width_pt, height_pt=height_pt, **kwargs) PyX-0.14.1/pyx/box.py0000644000076500000240000003207112233504466014523 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import types, math from . import bbox, path, unit, trafo class _marker: pass class BoxCrossError(Exception): pass class polygon_pt: def __init__(self, corners=None, center=None): self.corners = corners self.center = center if self.center is None: self._ensurecenter() def _ensurecenter(self): if self.center is None: self.center = 0, 0 for corn in self.corners: self.center = self.center[0] + corn[0], self.center[1] + corn[1] self.center = self.center[0]/len(self.corners), self.center[1]/len(self.corners) def path(self, centerradius=None, bezierradius=None, beziersoftness=None): pathitems = [] if centerradius is not None and self.center is not None: r = unit.topt(centerradius) pathitems.append(path.arc_pt(self.center[0], self.center[1], r, 0, 360)) pathitems.append(path.closepath()) if bezierradius is not None or beziersoftness is not None: raise ValueError("smooth functionality removed; apply smooth deformer on path") pathitems.append(path.moveto_pt(self.corners[0][0], self.corners[0][1])) for x, y in self.corners[1:]: pathitems.append(path.lineto_pt(x, y)) pathitems.append(path.closepath()) return path.path(*pathitems) def transform(self, *trafos): for trafo in trafos: if self.center is not None: self.center = trafo.apply_pt(*self.center) self.corners = [trafo.apply_pt(*point) for point in self.corners] def reltransform(self, *trafos): if self.center is not None: trafos = ([trafo.translate_pt(-self.center[0], -self.center[1])] + list(trafos) + [trafo.translate_pt(self.center[0], self.center[1])]) self.transform(*trafos) def successivepointnumbers(self): return [i and (i - 1, i) or (len(self.corners) - 1, 0) for i in range(len(self.corners))] def successivepoints(self): return [(self.corners[i], self.corners[j]) for i, j in self.successivepointnumbers()] def circlealignlinevector_pt(self, a, dx, dy, ex, ey, fx, fy, epsilon=1e-10): cx, cy = self.center gx, gy = ex - fx, ey - fy # direction vector if gx*gx + gy*gy < epsilon: # zero line length return None # no solution -> return None rsplit = (dx*gx + dy*gy) * 1.0 / (gx*gx + gy*gy) bx, by = dx - gx * rsplit, dy - gy * rsplit if bx*bx + by*by < epsilon: # zero projection return None # no solution -> return None if bx*gy - by*gx < 0: # half space return None # no solution -> return None sfactor = math.sqrt((dx*dx + dy*dy) / (bx*bx + by*by)) bx, by = a * bx * sfactor, a * by * sfactor alpha = ((bx+cx-ex)*dy - (by+cy-ey)*dx) * 1.0 / (gy*dx - gx*dy) if alpha > 0 - epsilon and alpha < 1 + epsilon: beta = ((ex-bx-cx)*gy - (ey-by-cy)*gx) * 1.0 / (gx*dy - gy*dx) return beta*dx, beta*dy # valid solution -> return align tuple # crossing point at the line, but outside a valid range if alpha < 0: return 0 # crossing point outside e return 1 # crossing point outside f def linealignlinevector_pt(self, a, dx, dy, ex, ey, fx, fy, epsilon=1e-10): cx, cy = self.center gx, gy = ex - fx, ey - fy # direction vector if gx*gx + gy*gy < epsilon: # zero line length return None # no solution -> return None if gy*dx - gx*dy < -epsilon: # half space return None # no solution -> return None if dx*gx + dy*gy > epsilon or dx*gx + dy*gy < -epsilon: if dx*gx + dy*gy < 0: # angle bigger 90 degree return 0 # use point e return 1 # use point f # a and g are othorgonal alpha = ((a*dx+cx-ex)*dy - (a*dy+cy-ey)*dx) * 1.0 / (gy*dx - gx*dy) if alpha > 0 - epsilon and alpha < 1 + epsilon: beta = ((ex-a*dx-cx)*gy - (ey-a*dy-cy)*gx) * 1.0 / (gx*dy - gy*dx) return beta*dx, beta*dy # valid solution -> return align tuple # crossing point at the line, but outside a valid range if alpha < 0: return 0 # crossing point outside e return 1 # crossing point outside f def circlealignpointvector_pt(self, a, dx, dy, px, py, epsilon=1e-10): if a*a < epsilon: return None cx, cy = self.center p = 2 * ((px-cx)*dx + (py-cy)*dy) q = ((px-cx)*(px-cx) + (py-cy)*(py-cy) - a*a) if p*p/4 - q < 0: return None if a > 0: alpha = - p / 2 + math.sqrt(p*p/4 - q) else: alpha = - p / 2 - math.sqrt(p*p/4 - q) return alpha*dx, alpha*dy def linealignpointvector_pt(self, a, dx, dy, px, py): cx, cy = self.center beta = (a*dx+cx-px)*dy - (a*dy+cy-py)*dx return a*dx - beta*dy - px + cx, a*dy + beta*dx - py + cy def alignvector_pt(self, a, dx, dy, alignlinevector, alignpointvector): n = math.hypot(dx, dy) dx, dy = dx / n, dy / n linevectors = list(map(lambda ps, self=self, a=a, dx=dx, dy=dy, alignlinevector=alignlinevector: alignlinevector(a, dx, dy, *(ps[0] + ps[1])), self.successivepoints())) for linevector in linevectors: if type(linevector) is tuple: return linevector for i, j in self.successivepointnumbers(): l1, l2 = linevectors[i], linevectors[j] if (l1 is not None or l2 is not None) and (l1 == 1 or l1 is None) and (l2 == 0 or l2 is None): return alignpointvector(a, dx, dy, *self.successivepoints()[j][0]) return a*dx, a*dy def circlealignvector_pt(self, a, dx, dy): return self.alignvector_pt(a, dx, dy, self.circlealignlinevector_pt, self.circlealignpointvector_pt) def linealignvector_pt(self, a, dx, dy): return self.alignvector_pt(a, dx, dy, self.linealignlinevector_pt, self.linealignpointvector_pt) def circlealignvector(self, a, dx, dy): ndx, ndy = self.circlealignvector_pt(unit.topt(a), dx, dy) return ndx * unit.t_pt, ndy * unit.t_pt def linealignvector(self, a, dx, dy): ndx, ndy = self.linealignvector_pt(unit.topt(a), dx, dy) return ndx * unit.t_pt, ndy * unit.t_pt def circlealign_pt(self, *args): self.transform(trafo.translate_pt(*self.circlealignvector_pt(*args))) return self def linealign_pt(self, *args): self.transform(trafo.translate_pt(*self.linealignvector_pt(*args))) return self def circlealign(self, *args): self.transform(trafo.translate(*self.circlealignvector(*args))) return self def linealign(self, *args): self.transform(trafo.translate(*self.linealignvector(*args))) return self def extent_pt(self, dx, dy): n = math.hypot(dx, dy) dx, dy = dx / n, dy / n oldcenter = self.center if self.center is None: self.center = 0, 0 x1, y1 = self.linealignvector_pt(0, dx, dy) x2, y2 = self.linealignvector_pt(0, -dx, -dy) self.center = oldcenter return (x1-x2)*dx + (y1-y2)*dy def extent(self, dx, dy): return self.extent_pt(dx, dy) * unit.t_pt def pointdistance_pt(self, x, y): result = None for p1, p2 in self.successivepoints(): gx, gy = p2[0] - p1[0], p2[1] - p1[1] if gx * gx + gy * gy < 1e-10: dx, dy = p1[0] - x, p1[1] - y else: a = (gx * (x - p1[0]) + gy * (y - p1[1])) / (gx * gx + gy * gy) if a < 0: dx, dy = p1[0] - x, p1[1] - y elif a > 1: dx, dy = p2[0] - x, p2[1] - y else: dx, dy = x - p1[0] - a * gx, y - p1[1] - a * gy new = math.hypot(dx, dy) if result is None or new < result: result = new return result def pointdistance(self, x, y): return self.pointdistance_pt(unit.topt(x), unit.topt(y)) * unit.t_pt def boxdistance_pt(self, other, epsilon=1e-10): # XXX: boxes crossing and distance calculation is O(N^2) for p1, p2 in self.successivepoints(): for p3, p4 in other.successivepoints(): a = (p4[1] - p3[1]) * (p3[0] - p1[0]) - (p4[0] - p3[0]) * (p3[1] - p1[1]) b = (p2[1] - p1[1]) * (p3[0] - p1[0]) - (p2[0] - p1[0]) * (p3[1] - p1[1]) c = (p2[0] - p1[0]) * (p4[1] - p3[1]) - (p2[1] - p1[1]) * (p4[0] - p3[0]) if (abs(c) > 1e-10 and a / c > -epsilon and a / c < 1 + epsilon and b / c > -epsilon and b / c < 1 + epsilon): raise BoxCrossError result = None for x, y in other.corners: new = self.pointdistance_pt(x, y) if result is None or new < result: result = new for x, y in self.corners: new = other.pointdistance_pt(x, y) if result is None or new < result: result = new return result def boxdistance(self, other): return self.boxdistance_pt(other) * unit.t_pt def bbox(self): return bbox.bbox_pt(min([x[0] for x in self.corners]), min([x[1] for x in self.corners]), max([x[0] for x in self.corners]), max([x[1] for x in self.corners])) def genericalignequal_pt(method, polygons, a, dx, dy): vec = None for p in polygons: v = method(p, a, dx, dy) if vec is None or vec[0] * dx + vec[1] * dy < v[0] * dx + v[1] * dy: vec = v for p in polygons: p.transform(trafo.translate_pt(*vec)) def circlealignequal_pt(polygons, *args): genericalignequal_pt(polygon_pt.circlealignvector_pt, polygons, *args) def linealignequal_pt(polygons, *args): genericalignequal_pt(polygon_pt.linealignvector_pt, polygons, *args) def circlealignequal(polygons, a, *args): circlealignequal_pt(polygons, unit.topt(a), *args) def linealignequal(polygons, a, *args): linealignequal_pt(polygons, unit.topt(a), *args) def tile_pt(polygons, a, dx, dy): maxextent = polygons[0].extent_pt(dx, dy) for p in polygons[1:]: extent = p.extent_pt(dx, dy) if extent > maxextent: maxextent = extent delta = maxextent + a d = 0 for p in polygons: p.transform(trafo.translate_pt(d*dx, d*dy)) d += delta return delta def tile(polygons, a, dx, dy): return tile_pt(polygons, unit.topt(a), dx, dy) * unit.t_pt class polygon(polygon_pt): def __init__(self, corners=None, center=None, **args): corners = [[unit.topt(x) for x in corner] for corner in corners] if center is not None: center = unit.topt(center[0]), unit.topt(center[1]) polygon_pt.__init__(self, corners=corners, center=center, **args) class rect_pt(polygon_pt): def __init__(self, x_pt, y_pt, width_pt, height_pt, relcenter=(0, 0), abscenter_pt=(0, 0), corners=_marker, center=_marker, **args): if corners != _marker or center != _marker: raise ValueError polygon_pt.__init__(self, corners=((x_pt, y_pt), (x_pt + width_pt, y_pt), (x_pt + width_pt, y_pt + height_pt), (x_pt, y_pt + height_pt)), center=(x_pt + relcenter[0] * width_pt + abscenter_pt[0], y_pt + relcenter[1] * height_pt + abscenter_pt[1]), **args) class rect(rect_pt): def __init__(self, x, y, width, height, relcenter=(0, 0), abscenter=(0, 0), **args): rect_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(width), unit.topt(height), relcenter=relcenter, abscenter_pt=(unit.topt(abscenter[0]), unit.topt(abscenter[1])), **args) PyX-0.14.1/pyx/canvas.py0000644000076500000240000004634312520510206015201 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """The canvas module provides a PostScript canvas class and related classes A canvas holds a collection of all elements and corresponding attributes to be displayed. """ import io, logging, os, sys, string, tempfile from . import attr, baseclasses, config, document, style, trafo, svgwriter, unit from . import bbox as bboxmodule logger = logging.getLogger("pyx") def _wrappedindocument(method): def wrappedindocument(self, file=None, **kwargs): page_kwargs = {} write_kwargs = {} for name, value in list(kwargs.items()): if name.startswith("page_"): page_kwargs[name[5:]] = value elif name.startswith("write_"): write_kwargs[name[6:]] = value else: logger.warning("implicit page keyword argument passing is deprecated; keyword argument '%s' of %s method should be changed to 'page_%s'" % (name, method.__name__, name)) page_kwargs[name] = value d = document.document([document.page(self, **page_kwargs)]) self.__name__ = method.__name__ self.__doc__ = method.__doc__ return method(d, file, **write_kwargs) return wrappedindocument # # clipping class # class SVGclippath(svgwriter.SVGresource): def __init__(self, path): self.svgid = "clippath%d" % id(path) super().__init__("clip-path", self.svgid) self.path = path def output(self, xml, writer, registry): xml.startSVGElement("clipPath", {"id": self.svgid}) # TODO: clip-rule missing (defaults to nonzero) xml.startSVGElement("path", {"d": self.path.returnSVGdata()}) xml.endSVGElement("path") xml.endSVGElement("clipPath") class clip(attr.attr): """class for use in canvas constructor which clips to a path""" def __init__(self, path): """construct a clip instance for a given path""" self.path = path def processPS(self, file, writer, context, registry): file.write("newpath\n") self.path.outputPS(file, writer) file.write("clip\n") def processPDF(self, file, writer, context, registry): self.path.outputPDF(file, writer) file.write("W n\n") def processSVGattrs(self, attrs, writer, context, registry): clippath = SVGclippath(self.path) registry.add(clippath) attrs["clip-path"] = "url(#%s)" % clippath.svgid # # general canvas class # class canvas(baseclasses.canvasitem): """a canvas holds a collection of canvasitems""" def __init__(self, attrs=None, texrunner=None, ipython_bboxenlarge=1*unit.t_pt): """construct a canvas The canvas can be modfied by supplying a list of attrs, which have to be instances of one of the following classes: - trafo.trafo (leading to a global transformation of the canvas) - canvas.clip (clips the canvas) - style.strokestyle, style.fillstyle (sets some global attributes of the canvas) Note that, while the first two properties are fixed for the whole canvas, the last one can be changed via canvas.set(). The texrunner instance used for the text method can be specified using the texrunner argument. It defaults to text.defaulttexrunner """ self.items = [] self.trafo = trafo.identity self.clip = None self.layers = {} if attrs is None: attrs = [] if texrunner is not None: self.texrunner = texrunner else: # prevent cyclic imports from . import text self.texrunner = text.defaulttexrunner self.ipython_bboxenlarge = ipython_bboxenlarge attr.checkattrs(attrs, [trafo.trafo_pt, clip, style.style]) attrs = attr.mergeattrs(attrs) self.modifies_state = bool(attrs) self.styles = attr.getattrs(attrs, [style.style]) # trafos (and one possible clip operation) are applied from left to # right in the attrs list -> reverse for calculating total trafo for aattr in reversed(attr.getattrs(attrs, [trafo.trafo_pt, clip])): if isinstance(aattr, trafo.trafo_pt): self.trafo = self.trafo * aattr else: if self.clip is not None: raise ValueError("single clipping allowed only") self.clip = clip(aattr.path.transformed(self.trafo)) def __len__(self): return len(self.items) def __getitem__(self, i): return self.items[i] def _repr_png_(self): """ Automatically represent as PNG graphic when evaluated in IPython notebook. """ return self.pipeGS(device="png16m", page_bboxenlarge=self.ipython_bboxenlarge).getvalue() def _repr_svg_(self): """ Automatically represent as SVG graphic when evaluated in IPython notebook. """ f = io.BytesIO() self.writeSVGfile(f, page_bboxenlarge=self.ipython_bboxenlarge) return f.getvalue().decode("utf-8") def bbox(self): """returns bounding box of canvas Note that this bounding box doesn't take into account the linewidths, so is less accurate than the one used when writing the output to a file. """ obbox = bboxmodule.empty() for cmd in self.items: obbox += cmd.bbox() # transform according to our global transformation and # intersect with clipping bounding box (which has already been # transformed in canvas.__init__()) obbox.transform(self.trafo) if self.clip is not None: obbox *= self.clip.path.bbox() return obbox def processPS(self, file, writer, context, registry, bbox): context = context() if self.items: if self.modifies_state: file.write("gsave\n") for attr in self.styles: attr.processPS(file, writer, context, registry) if self.clip is not None: self.clip.processPS(file, writer, context, registry) if self.trafo is not trafo.identity: self.trafo.processPS(file, writer, context, registry) nbbox = bboxmodule.empty() for item in self.items: item.processPS(file, writer, context, registry, nbbox) # update bounding bbox nbbox.transform(self.trafo) if self.clip is not None: nbbox *= self.clip.path.bbox() bbox += nbbox if self.modifies_state: file.write("grestore\n") def processPDF(self, file, writer, context, registry, bbox): context = context() textregion = False context.trafo = context.trafo * self.trafo if self.items: if self.modifies_state: file.write("q\n") # gsave for attr in self.styles: if isinstance(attr, style.fillstyle): context.fillstyles.append(attr) attr.processPDF(file, writer, context, registry) if self.clip is not None: self.clip.processPDF(file, writer, context, registry) if self.trafo is not trafo.identity: self.trafo.processPDF(file, writer, context, registry) nbbox = bboxmodule.empty() for item in self.items: if not writer.text_as_path: if item.requiretextregion(): if not textregion: file.write("BT\n") textregion = True else: if textregion: file.write("ET\n") textregion = False context.selectedfont = None item.processPDF(file, writer, context, registry, nbbox) if textregion: file.write("ET\n") textregion = False context.selectedfont = None # update bounding bbox nbbox.transform(self.trafo) if self.clip is not None: nbbox *= self.clip.path.bbox() bbox += nbbox if self.modifies_state: file.write("Q\n") # grestore def processSVG(self, xml, writer, context, registry, bbox): if self.items: if self.modifies_state: context = context() attrs = {} for attr in self.styles: attr.processSVGattrs(attrs, writer, context, registry) if self.clip is not None: self.clip.processSVGattrs(attrs, writer, context, registry) if self.trafo is not trafo.identity: # trafo needs to be applied after clipping # thus write g and start anew xml.startSVGElement("g", attrs) attrs = {} self.trafo.processSVGattrs(attrs, writer, context, registry) elif self.trafo is not trafo.identity: self.trafo.processSVGattrs(attrs, writer, context, registry) xml.startSVGElement("g", attrs) nbbox = bboxmodule.empty() for item in self.items: item.processSVG(xml, writer, context, registry, nbbox) # update bounding bbox nbbox.transform(self.trafo) if self.clip is not None: nbbox *= self.clip.path.bbox() bbox += nbbox if self.modifies_state: xml.endSVGElement("g") if self.clip is not None and self.trafo is not trafo.identity: xml.endSVGElement("g") def layer(self, name, above=None, below=None): """create or get a layer with name A layer is a canvas itself and can be used to combine drawing operations for ordering purposes, i.e., what is above and below each other. The layer name is a dotted string, where dots are used to form a hierarchy of layer groups. When inserting a layer, it is put on top of its layer group except when another layer of this group is specified by means of the parameters above or below. """ if above is not None and below is not None: raise ValueError("above and below cannot be specified at the same time") try: group, layer = name.split(".", 1) except ValueError: if name in self.layers: if above is not None or below is not None: # remove for repositioning self.items.remove(self.layers[name]) else: # create new layer self.layers[name] = canvas(texrunner=self.texrunner) if above is None and below is None: self.items.append(self.layers[name]) # (re)position layer if above is not None: self.items.insert(self.items.index(self.layers[above])+1, self.layers[name]) elif below is not None: self.items.insert(self.items.index(self.layers[below]), self.layers[name]) return self.layers[name] else: if not group in self.layers: self.layers[group] = self.insert(canvas(texrunner=self.texrunner)) if above is not None: abovegroup, above = above.split(".", 1) assert abovegroup == group if below is not None: belowgroup, below = below.split(".", 1) assert belowgroup == group return self.layers[group].layer(layer, above=above, below=below) def insert(self, item, attrs=None): """insert item in the canvas. If attrs are passed, a canvas containing the item is inserted applying attrs. If replace is not None, the new item is positioned accordingly in the canvas. returns the item, possibly wrapped in a canvas """ if not isinstance(item, baseclasses.canvasitem): raise ValueError("only instances of baseclasses.canvasitem can be inserted into a canvas") if attrs: sc = canvas(attrs) sc.insert(item) item = sc self.items.append(item) return item def draw(self, path, attrs): """draw path on canvas using the style given by args The argument attrs consists of PathStyles, which modify the appearance of the path, PathDecos, which add some new visual elements to the path, or trafos, which are applied before drawing the path. """ from . import deco attrs = attr.mergeattrs(attrs) attr.checkattrs(attrs, [deco.deco, baseclasses.deformer, style.style]) for adeformer in attr.getattrs(attrs, [baseclasses.deformer]): path = adeformer.deform(path) styles = attr.getattrs(attrs, [style.style]) dp = deco.decoratedpath(path, styles=styles) # add path decorations and modify path accordingly for adeco in attr.getattrs(attrs, [deco.deco]): adeco.decorate(dp, self.texrunner) self.insert(dp) def stroke(self, path, attrs=[]): """stroke path on canvas using the style given by args The argument attrs consists of PathStyles, which modify the appearance of the path, PathDecos, which add some new visual elements to the path, or trafos, which are applied before drawing the path. """ from . import deco self.draw(path, [deco.stroked]+list(attrs)) def fill(self, path, attrs=[]): """fill path on canvas using the style given by args The argument attrs consists of PathStyles, which modify the appearance of the path, PathDecos, which add some new visual elements to the path, or trafos, which are applied before drawing the path. """ from . import deco self.draw(path, [deco.filled]+list(attrs)) def settexrunner(self, texrunner): """sets the texrunner to be used to within the text and text_pt methods""" self.texrunner = texrunner def text(self, x, y, atext, *args, **kwargs): """insert a text into the canvas inserts a textbox created by self.texrunner.text into the canvas returns the inserted textbox""" return self.insert(self.texrunner.text(x, y, atext, *args, **kwargs)) def text_pt(self, x, y, atext, *args): """insert a text into the canvas inserts a textbox created by self.texrunner.text_pt into the canvas returns the inserted textbox""" return self.insert(self.texrunner.text_pt(x, y, atext, *args)) writeEPSfile = _wrappedindocument(document.document.writeEPSfile) writePSfile = _wrappedindocument(document.document.writePSfile) writePDFfile = _wrappedindocument(document.document.writePDFfile) writeSVGfile = _wrappedindocument(document.document.writeSVGfile) writetofile = _wrappedindocument(document.document.writetofile) def _gscmd(self, device, filename, resolution=100, gs="gs", gsoptions=[], textalphabits=4, graphicsalphabits=4, ciecolor=False, **kwargs): cmd = [gs, "-dEPSCrop", "-dNOPAUSE", "-dQUIET", "-dBATCH", "-r%d" % resolution, "-sDEVICE=%s" % device, "-sOutputFile=%s" % filename] if textalphabits is not None: cmd.append("-dTextAlphaBits=%i" % textalphabits) if graphicsalphabits is not None: cmd.append("-dGraphicsAlphaBits=%i" % graphicsalphabits) if ciecolor: cmd.append("-dUseCIEColor") cmd.extend(gsoptions) return cmd, kwargs def writeGSfile(self, filename=None, device=None, input="eps", **kwargs): """ convert EPS or PDF output to a file via Ghostscript If filename is None it is auto-guessed from the script name. If filename is "-", the output is written to stdout. In both cases, a device needs to be specified to define the format. If device is None, but a filename with suffix is given, PNG files will be written using the png16m device and JPG files using the jpeg device. """ if filename is None: if not sys.argv[0].endswith(".py"): raise RuntimeError("could not auto-guess filename") if device.startswith("png"): filename = sys.argv[0][:-2] + "png" elif device.startswith("jpeg"): filename = sys.argv[0][:-2] + "jpg" else: filename = sys.argv[0][:-2] + device if device is None: if filename.endswith(".png"): device = "png16m" elif filename.endswith(".jpg"): device = "jpeg" else: raise RuntimeError("could not auto-guess device") cmd, kwargs = self._gscmd(device, filename, **kwargs) if input == "eps": cmd.append("-") p = config.Popen(cmd, stdin=config.PIPE) self.writeEPSfile(p.stdin, **kwargs) p.stdin.close() p.wait() elif input == "pdf": # PDF files need to be accesible by random access and thus we need to create # a temporary file with tempfile.NamedTemporaryFile("wb", delete=False) as f: self.writePDFfile(f, **kwargs) fname = f.name cmd.append(fname) config.Popen(cmd).wait() os.unlink(fname) else: raise RuntimeError("input 'eps' or 'pdf' expected") def pipeGS(self, device, input="eps", **kwargs): """ returns a BytesIO instance with the Ghostscript output of the EPS or PDF """ cmd, kwargs = self._gscmd(device, "-", **kwargs) with tempfile.NamedTemporaryFile("wb", delete=False) as f: if input == "eps": self.writeEPSfile(f, **kwargs) elif input == "pdf": self.writePDFfile(f, **kwargs) else: raise RuntimeError("input 'eps' or 'pdf' expected") fname = f.name cmd.append(fname) p = config.Popen(cmd, stdout=config.PIPE) data, error = p.communicate() os.unlink(fname) if error: raise ValueError("error received while waiting for ghostscript") return io.BytesIO(data) PyX-0.14.1/pyx/color.py0000644000076500000240000005235112517520131015044 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004, 2006, 2013 Jörg Lehmann # Copyright (C) 2003-2006 Michael Schindler # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import binascii, colorsys, logging, math, struct from . import attr, style, pdfwriter logger = logging.getLogger("pyx") # device-dependent (nonlinear) functions for color conversion # UCRx : [0,1] -> [-1, 1] UnderColorRemoval (removes black from c, y, m) # BG : [0,1] -> [0, 1] BlackGeneration (generate the black from the nominal k-value) # as long as we have no further knowledge we define them linearly with constants 1 def _UCRc(x): return x def _UCRm(x): return x def _UCRy(x): return x def _BG(x): return x def set(UCRc=None, UCRm=None, UCRy=None, BG=None): global _UCRc global _UCRm global _UCRy global _BG if UCRc is not None: _UCRc = UCRc if UCRm is not None: _UCRm = UCRm if UCRy is not None: _UCRy = UCRy if BG is not None: _BG = BG class color(attr.exclusiveattr, style.strokestyle, style.fillstyle): """base class for all colors""" def __init__(self): super().__init__(color) def processSVGattrs(self, attrs, writer, context, registry): if context.strokeattr: context.strokecolor = self.rgb().tohexstring() if context.fillattr: context.fillcolor = self.rgb().tohexstring() clear = attr.clearclass(color) class gray(color): """grey tones""" def __init__(self, g=0.0): super().__init__() if g<0 or g>1: raise ValueError("Value g out of range [0,1]") self.g = g def processPS(self, file, writer, context, registry): file.write("%f setgray\n" % self.g) def processPDF(self, file, writer, context, registry): if context.strokeattr: file.write("%f G\n" % self.g) if context.fillattr: file.write("%f g\n" % self.g) def cmyk(self): return cmyk(0, 0, 0, 1 - self.g) def gray(self): return gray(self.g) grey = gray def hsb(self): return hsb(0, 0, self.g) def rgb(self): return rgb(self.g, self.g, self.g) def colorspacestring(self): return "/DeviceGray" def to8bitbytes(self): return bytes((int(self.g*255),)) gray.black = gray(0.0) gray.white = gray(1.0) grey = gray class rgb(color): """rgb colors""" def __init__(self, r=0.0, g=0.0, b=0.0): super().__init__() if r<0 or r>1: raise ValueError("Value r out of range [0,1]") if g<0 or g>1: raise ValueError("Value g out of range [0,1]") if b<0 or b>1: raise ValueError("Value b out of range [0,1]") self.r = r self.g = g self.b = b def processPS(self, file, writer, context, registry): file.write("%f %f %f setrgbcolor\n" % (self.r, self.g, self.b)) def processPDF(self, file, writer, context, registry): if context.strokeattr: file.write("%f %f %f RG\n" % (self.r, self.g, self.b)) if context.fillattr: file.write("%f %f %f rg\n" % (self.r, self.g, self.b)) def cmyk(self): # conversion to cmy c, m, y = 1 - self.r, 1 - self.g, 1 - self.b # conversion from cmy to cmyk with device-dependent functions k = min([c, m, y]) return cmyk(min(1, max(0, c - _UCRc(k))), min(1, max(0, m - _UCRm(k))), min(1, max(0, y - _UCRy(k))), _BG(k)) def gray(self): return gray(0.3*self.r + 0.59*self.g + 0.11*self.b) grey = gray def hsb(self): h, s, b = colorsys.rgb_to_hsv(self.r, self.g, self.b) return hsb(h, s, b) def rgb(self): return rgb(self.r, self.g, self.b) def colorspacestring(self): return "/DeviceRGB" def to8bitbytes(self): return struct.pack("BBB", int(self.r*255), int(self.g*255), int(self.b*255)) def tohexstring(self, cssstrip=1, addhash=1): hexstring = binascii.b2a_hex(self.to8bitbytes()).decode('ascii') if cssstrip and hexstring[0] == hexstring[1] and hexstring[2] == hexstring[3] and hexstring[4] == hexstring[5]: hexstring = "".join([hexstring[0], hexstring[2], hexstring[4]]) if addhash: hexstring = "#" + hexstring return hexstring def rgbfromhexstring(hexstring): hexstring = hexstring.strip().lstrip("#") if len(hexstring) == 3: hexstring = "".join([hexstring[0], hexstring[0], hexstring[1], hexstring[1], hexstring[2], hexstring[2]]) elif len(hexstring) != 6: raise ValueError("3 or 6 digit hex number expected (with optional leading hash character)") return rgb(*[value/255.0 for value in struct.unpack("BBB", binascii.a2b_hex(hexstring))]) rgb.red = rgb(1, 0, 0) rgb.green = rgb(0, 1, 0) rgb.blue = rgb(0, 0, 1) rgb.white = rgb(1, 1, 1) rgb.black = rgb(0, 0, 0) class hsb(color): """hsb colors""" def __init__(self, h=0.0, s=0.0, b=0.0): super().__init__() if h<0 or h>1: raise ValueError("Value h out of range [0,1]") if s<0 or s>1: raise ValueError("Value s out of range [0,1]") if b<0 or b>1: raise ValueError("Value b out of range [0,1]") self.h = h self.s = s self.b = b def processPS(self, file, writer, context, registry): file.write("%f %f %f sethsbcolor\n" % (self.h, self.s, self.b)) def processPDF(self, file, writer, context, registry): self.rgb().processPDF(file, writer, context, registry) def cmyk(self): return self.rgb().cmyk() def gray(self): return self.rgb().gray() grey = gray def hsb(self): return hsb(self.h, self.s, self.b) def rgb(self): r, g, b = colorsys.hsv_to_rgb(self.h, self.s, self.b) return rgb(r, g, b) def colorspacestring(self): raise RuntimeError("colorspace string not available for hsb colors") class cmyk(color): """cmyk colors""" def __init__(self, c=0.0, m=0.0, y=0.0, k=0.0): super().__init__() if c<0 or c>1: raise ValueError("Value c out of range [0,1]") if m<0 or m>1: raise ValueError("Value m out of range [0,1]") if y<0 or y>1: raise ValueError("Value y out of range [0,1]") if k<0 or k>1: raise ValueError("Value k out of range [0,1]") self.c = c self.m = m self.y = y self.k = k def processPS(self, file, writer, context, registry): file.write("%f %f %f %f setcmykcolor\n" % (self.c, self.m, self.y, self.k)) def processPDF(self, file, writer, context, registry): if context.strokeattr: file.write("%f %f %f %f K\n" % (self.c, self.m, self.y, self.k)) if context.fillattr: file.write("%f %f %f %f k\n" % (self.c, self.m, self.y, self.k)) def cmyk(self): return cmyk(self.c, self.m, self.y, self.k) def gray(self): return gray(1 - min([1, 0.3*self.c + 0.59*self.m + 0.11*self.y + self.k])) grey = gray def hsb(self): return self.rgb().hsb() def rgb(self): # conversion to cmy: c = min(1, self.c + self.k) m = min(1, self.m + self.k) y = min(1, self.y + self.k) # conversion from cmy to rgb: return rgb(1 - c, 1 - m, 1 - y) def colorspacestring(self): return "/DeviceCMYK" def to8bitbytes(self): return struct.pack("BBBB", int(self.c*255), int(self.m*255), int(self.y*255), int(self.k*255)) cmyk.GreenYellow = cmyk(0.15, 0, 0.69, 0) cmyk.Yellow = cmyk(0, 0, 1, 0) cmyk.Goldenrod = cmyk(0, 0.10, 0.84, 0) cmyk.Dandelion = cmyk(0, 0.29, 0.84, 0) cmyk.Apricot = cmyk(0, 0.32, 0.52, 0) cmyk.Peach = cmyk(0, 0.50, 0.70, 0) cmyk.Melon = cmyk(0, 0.46, 0.50, 0) cmyk.YellowOrange = cmyk(0, 0.42, 1, 0) cmyk.Orange = cmyk(0, 0.61, 0.87, 0) cmyk.BurntOrange = cmyk(0, 0.51, 1, 0) cmyk.Bittersweet = cmyk(0, 0.75, 1, 0.24) cmyk.RedOrange = cmyk(0, 0.77, 0.87, 0) cmyk.Mahogany = cmyk(0, 0.85, 0.87, 0.35) cmyk.Maroon = cmyk(0, 0.87, 0.68, 0.32) cmyk.BrickRed = cmyk(0, 0.89, 0.94, 0.28) cmyk.Red = cmyk(0, 1, 1, 0) cmyk.OrangeRed = cmyk(0, 1, 0.50, 0) cmyk.RubineRed = cmyk(0, 1, 0.13, 0) cmyk.WildStrawberry = cmyk(0, 0.96, 0.39, 0) cmyk.Salmon = cmyk(0, 0.53, 0.38, 0) cmyk.CarnationPink = cmyk(0, 0.63, 0, 0) cmyk.Magenta = cmyk(0, 1, 0, 0) cmyk.VioletRed = cmyk(0, 0.81, 0, 0) cmyk.Rhodamine = cmyk(0, 0.82, 0, 0) cmyk.Mulberry = cmyk(0.34, 0.90, 0, 0.02) cmyk.RedViolet = cmyk(0.07, 0.90, 0, 0.34) cmyk.Fuchsia = cmyk(0.47, 0.91, 0, 0.08) cmyk.Lavender = cmyk(0, 0.48, 0, 0) cmyk.Thistle = cmyk(0.12, 0.59, 0, 0) cmyk.Orchid = cmyk(0.32, 0.64, 0, 0) cmyk.DarkOrchid = cmyk(0.40, 0.80, 0.20, 0) cmyk.Purple = cmyk(0.45, 0.86, 0, 0) cmyk.Plum = cmyk(0.50, 1, 0, 0) cmyk.Violet = cmyk(0.79, 0.88, 0, 0) cmyk.RoyalPurple = cmyk(0.75, 0.90, 0, 0) cmyk.BlueViolet = cmyk(0.86, 0.91, 0, 0.04) cmyk.Periwinkle = cmyk(0.57, 0.55, 0, 0) cmyk.CadetBlue = cmyk(0.62, 0.57, 0.23, 0) cmyk.CornflowerBlue = cmyk(0.65, 0.13, 0, 0) cmyk.MidnightBlue = cmyk(0.98, 0.13, 0, 0.43) cmyk.NavyBlue = cmyk(0.94, 0.54, 0, 0) cmyk.RoyalBlue = cmyk(1, 0.50, 0, 0) cmyk.Blue = cmyk(1, 1, 0, 0) cmyk.Cerulean = cmyk(0.94, 0.11, 0, 0) cmyk.Cyan = cmyk(1, 0, 0, 0) cmyk.ProcessBlue = cmyk(0.96, 0, 0, 0) cmyk.SkyBlue = cmyk(0.62, 0, 0.12, 0) cmyk.Turquoise = cmyk(0.85, 0, 0.20, 0) cmyk.TealBlue = cmyk(0.86, 0, 0.34, 0.02) cmyk.Aquamarine = cmyk(0.82, 0, 0.30, 0) cmyk.BlueGreen = cmyk(0.85, 0, 0.33, 0) cmyk.Emerald = cmyk(1, 0, 0.50, 0) cmyk.JungleGreen = cmyk(0.99, 0, 0.52, 0) cmyk.SeaGreen = cmyk(0.69, 0, 0.50, 0) cmyk.Green = cmyk(1, 0, 1, 0) cmyk.ForestGreen = cmyk(0.91, 0, 0.88, 0.12) cmyk.PineGreen = cmyk(0.92, 0, 0.59, 0.25) cmyk.LimeGreen = cmyk(0.50, 0, 1, 0) cmyk.YellowGreen = cmyk(0.44, 0, 0.74, 0) cmyk.SpringGreen = cmyk(0.26, 0, 0.76, 0) cmyk.OliveGreen = cmyk(0.64, 0, 0.95, 0.40) cmyk.RawSienna = cmyk(0, 0.72, 1, 0.45) cmyk.Sepia = cmyk(0, 0.83, 1, 0.70) cmyk.Brown = cmyk(0, 0.81, 1, 0.60) cmyk.Tan = cmyk(0.14, 0.42, 0.56, 0) cmyk.Gray = cmyk(0, 0, 0, 0.50) cmyk.Grey = cmyk.Gray cmyk.Black = cmyk(0, 0, 0, 1) cmyk.White = cmyk(0, 0, 0, 0) cmyk.white = cmyk.White cmyk.black = cmyk.Black class palette(attr.changelist): """color palettes A color palette is a discrete, ordered list of colors""" palette.clear = attr.clearclass(palette) # # gradients # class gradient(attr.changeattr): """base class for color gradients A gradient is a continuous collection of colors with a single parameter ranging from 0 to 1 to address them""" def getcolor(self, param): """return color corresponding to param""" pass def select(self, index, n_indices): """return a color corresponding to an index out of n_indices""" if n_indices == 1: param = 0 else: param = index / (n_indices - 1.0) return self.getcolor(param) gradient.clear = attr.clearclass(gradient) # # gradient with arbitrary non-linear dependency # class functiongradient_gray(gradient): """arbitrary non-linear gradients of gray colors f_gray: a function mapping [0,1] to the gray value """ def __init__(self, f_gray): super().__init__() self.f_gray = f_gray def getcolor(self, param): return gray(self.f_gray(param)) class functiongradient_cmyk(gradient): """arbitrary non-linear gradients of cmyk colors f_c: a function mapping [0,1] to the c component f_m: a function mapping [0,1] to the m component f_y: a function mapping [0,1] to the y component f_k: a function mapping [0,1] to the k component """ def __init__(self, f_c, f_m, f_y, f_k): super().__init__() self.f_c = f_c self.f_m = f_m self.f_y = f_y self.f_k = f_k def getcolor(self, param): return cmyk(self.f_c(param), self.f_m(param), self.f_y(param), self.f_k(param)) class functiongradient_hsb(gradient): """arbitrary non-linear gradients of hsb colors f_h: a function mapping [0,1] to the h component f_s: a function mapping [0,1] to the s component f_b: a function mapping [0,1] to the b component """ def __init__(self, f_h, f_s, f_b): super().__init__() self.f_h = f_h self.f_s = f_s self.f_b = f_b def getcolor(self, param): return hsb(self.f_h(param), self.f_s(param), self.f_b(param)) class functiongradient_rgb(gradient): """arbitrary non-linear gradients of rgb colors f_r: a function mapping [0,1] to the r component f_g: a function mapping [0,1] to the b component f_b: a function mapping [0,1] to the b component """ def __init__(self, f_r, f_g, f_b): super().__init__() self.f_r = f_r self.f_g = f_g self.f_b = f_b def getcolor(self, param): return rgb(self.f_r(param), self.f_g(param), self.f_b(param)) # # factory functions for gradients interpolating linearly between two colors # def lineargradient_cmyk(mincolor, maxcolor): return functiongradient_cmyk(lambda x:maxcolor.c * x + mincolor.c * (1-x), lambda x:maxcolor.m * x + mincolor.m * (1-x), lambda x:maxcolor.y * x + mincolor.y * (1-x), lambda x:maxcolor.k * x + mincolor.k * (1-x)) def lineargradient_gray(mincolor, maxcolor): return functiongradient_gray(lambda x:maxcolor.g * x + mincolor.g * (1-x)) def lineargradient_hsb(mincolor, maxcolor): return functiongradient_hsb(lambda x:maxcolor.h * x + mincolor.h * (1-x), lambda x:maxcolor.s * x + mincolor.s * (1-x), lambda x:maxcolor.b * x + mincolor.b * (1-x)) def lineargradient_rgb(mincolor, maxcolor): return functiongradient_rgb(lambda x:maxcolor.r * x + mincolor.r * (1-x), lambda x:maxcolor.g * x + mincolor.g * (1-x), lambda x:maxcolor.b * x + mincolor.b * (1-x)) # # gradients converted into other color spaces # class rgbgradient(gradient): "a gradient, which takes another gradient and returns rgb colors" def __init__(self, gradient): super().__init__() self.gradient = gradient def getcolor(self, param): return self.gradient.getcolor(param).rgb() class cmykgradient(gradient): "a gradient, which takes another gradient and returns cmyk colors" def __init__(self, gradient): super().__init__() self.gradient = gradient def getcolor(self, param): return self.gradient.getcolor(param).cmyk() gradient.Gray = lineargradient_gray(gray.white, gray.black) gradient.Grey = gradient.Gray gradient.ReverseGray = lineargradient_gray(gray.black, gray.white) gradient.ReverseGrey = gradient.ReverseGray gradient.BlackYellow = functiongradient_rgb( # compare this with reversegray above f_r=lambda x: 2*x*(1-x)**5 + 3.5*x**2*(1-x)**3 + 2.1*x*x*(1-x)**2 + 3.0*x**3*(1-x)**2 + x**0.5*(1-(1-x)**2), f_g=lambda x: 1.5*x**2*(1-x)**3 - 0.8*x**3*(1-x)**2 + 2.0*x**4*(1-x) + x**4, f_b=lambda x: 5*x*(1-x)**5 - 0.5*x**2*(1-x)**3 + 0.3*x*x*(1-x)**2 + 5*x**3*(1-x)**2 + 0.5*x**6) gradient.YellowBlack = functiongradient_rgb( f_r=lambda x: 2*(1-x)*x**5 + 3.5*(1-x)**2*x**3 + 2.1*(1-x)*(1-x)*x**2 + 3.0*(1-x)**3*x**2 + (1-x)**0.5*(1-x**2), f_g=lambda x: 1.5*(1-x)**2*x**3 - 0.8*(1-x)**3*x**2 + 2.0*(1-x)**4*x + (1-x)**4, f_b=lambda x: 5*(1-x)*x**5 - 0.5*(1-x)**2*x**3 + 0.3*(1-x)*(1-x)*x**2 + 5*(1-x)**3*x**2 + 0.5*(1-x)**6) gradient.RedGreen = lineargradient_rgb(rgb.red, rgb.green) gradient.RedBlue = lineargradient_rgb(rgb.red, rgb.blue) gradient.GreenRed = lineargradient_rgb(rgb.green, rgb.red) gradient.GreenBlue = lineargradient_rgb(rgb.green, rgb.blue) gradient.BlueRed = lineargradient_rgb(rgb.blue, rgb.red) gradient.BlueGreen = lineargradient_rgb(rgb.blue, rgb.green) gradient.RedBlack = lineargradient_rgb(rgb.red, rgb.black) gradient.BlackRed = lineargradient_rgb(rgb.black, rgb.red) gradient.RedWhite = lineargradient_rgb(rgb.red, rgb.white) gradient.WhiteRed = lineargradient_rgb(rgb.white, rgb.red) gradient.GreenBlack = lineargradient_rgb(rgb.green, rgb.black) gradient.BlackGreen = lineargradient_rgb(rgb.black, rgb.green) gradient.GreenWhite = lineargradient_rgb(rgb.green, rgb.white) gradient.WhiteGreen = lineargradient_rgb(rgb.white, rgb.green) gradient.BlueBlack = lineargradient_rgb(rgb.blue, rgb.black) gradient.BlackBlue = lineargradient_rgb(rgb.black, rgb.blue) gradient.BlueWhite = lineargradient_rgb(rgb.blue, rgb.white) gradient.WhiteBlue = lineargradient_rgb(rgb.white, rgb.blue) gradient.Rainbow = lineargradient_hsb(hsb(0, 1, 1), hsb(2.0/3.0, 1, 1)) gradient.ReverseRainbow = lineargradient_hsb(hsb(2.0/3.0, 1, 1), hsb(0, 1, 1)) gradient.Hue = lineargradient_hsb(hsb(0, 1, 1), hsb(1, 1, 1)) gradient.ReverseHue = lineargradient_hsb(hsb(1, 1, 1), hsb(0, 1, 1)) rgbgradient.Rainbow = rgbgradient(gradient.Rainbow) rgbgradient.ReverseRainbow = rgbgradient(gradient.ReverseRainbow) rgbgradient.Hue = rgbgradient(gradient.Hue) rgbgradient.ReverseHue = rgbgradient(gradient.ReverseHue) cmykgradient.Rainbow = cmykgradient(gradient.Rainbow) cmykgradient.ReverseRainbow = cmykgradient(gradient.ReverseRainbow) cmykgradient.Hue = cmykgradient(gradient.Hue) cmykgradient.ReverseHue = cmykgradient(gradient.ReverseHue) def jet_r(x): if x < 0.38: return 0 elif x < 0.62: return (x-0.38)/(0.62-0.38) elif x < 0.87: return 1 else: return 0.5 + 0.5*(1-x)/(1-0.87) def jet_g(x): if x < 0.13: return 0 elif x < 0.38: return (x-0.13)/(0.38-0.13) elif x < 0.62: return 1 elif x < 0.87: return (0.87-x)/(0.87-0.62) else: return 0 def jet_b(x): if x < 0.13: return 0.5 + 0.5*x/0.13 elif x < 0.38: return 1 elif x < 0.62: return 1-(x-0.38)/(0.62-0.38) else: return 0 gradient.Jet = functiongradient_rgb(f_r=jet_r, f_g=jet_g, f_b=jet_b) gradient.ReverseJet = functiongradient_rgb(f_r=lambda x: jet_r(1-x), f_g=lambda x: jet_g(1-x), f_b=lambda x: jet_b(1-x)) cmykgradient.Jet = cmykgradient(gradient.Jet) cmykgradient.ReverseJet = cmykgradient(gradient.ReverseJet) class PDFextgstate(pdfwriter.PDFobject): def __init__(self, name, extgstate, registry): pdfwriter.PDFobject.__init__(self, "extgstate", name) registry.addresource("ExtGState", name, self) self.name = name self.extgstate = extgstate def write(self, file, writer, registry): file.write("%s\n" % self.extgstate) class transparency(attr.exclusiveattr, style.strokestyle, style.fillstyle): def __init__(self, value): self.value = 1-value attr.exclusiveattr.__init__(self, transparency) def processPS(self, file, writer, context, registry): logger.warning("Transparency not available in PostScript, proprietary ghostscript extension code inserted.") file.write("%f .setshapealpha\n" % self.value) def processPDF(self, file, writer, context, registry): if context.strokeattr and context.fillattr: registry.add(PDFextgstate("Transparency-%f" % self.value, "<< /Type /ExtGState /CA %f /ca %f >>" % (self.value, self.value), registry)) file.write("/Transparency-%f gs\n" % self.value) elif context.strokeattr: registry.add(PDFextgstate("Transparency-Stroke-%f" % self.value, "<< /Type /ExtGState /CA %f >>" % self.value, registry)) file.write("/Transparency-Stroke-%f gs\n" % self.value) elif context.fillattr: registry.add(PDFextgstate("Transparency-Fill-%f" % self.value, "<< /Type /ExtGState /ca %f >>" % self.value, registry)) file.write("/Transparency-Fill-%f gs\n" % self.value) def processSVGattrs(self, attrs, writer, context, registry): if context.strokeattr: context.strokeopacity = self.value if context.fillattr: context.fillopacity = self.value PyX-0.14.1/pyx/config.py0000644000076500000240000003405512400436454015201 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2003-2011 Jörg Lehmann # Copyright (C) 2003-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import configparser, io, logging, os, pkgutil, subprocess, shutil logger = logging.getLogger("pyx") logger_execute = logging.getLogger("pyx.execute") logger_filelocator = logging.getLogger("pyx.filelocator") builtinopen = open try: import pykpathsea as pykpathsea_module has_pykpathsea = True except ImportError: has_pykpathsea = False # Locators implement an open method which returns a list of functions # by searching for a file according to a specific rule. Each of the functions # returned can be called (multiple times) and return an open file. The # opening of the file might fail with a IOError which indicates, that the # file could not be found at the given location. # names is a list of kpsewhich format names to be used for searching where as # extensions is a list of file extensions to be tried (including the dot). Note # that the list of file extenions should include an empty string to not add # an extension at all. locator_classes = {} class local: """locates files in the current directory""" def openers(self, filename, names, extensions): return [lambda extension=extension: builtinopen(filename+extension, "rb") for extension in extensions] locator_classes["local"] = local class internal: """locates files within the PyX data tree""" def openers(self, filename, names, extensions): for extension in extensions: full_filename = filename+extension dir = os.path.splitext(full_filename)[1][1:] try: data = pkgutil.get_data("pyx", "data/%s/%s" % (dir, full_filename)) except IOError: pass else: if data: return [lambda: io.BytesIO(data)] return [] locator_classes["internal"] = internal class recursivedir: """locates files by searching recursively in a list of directories""" def __init__(self): self.dirs = getlist("filelocator", "recursivedir") self.full_filenames = {} def openers(self, filename, names, extensions): for extension in extensions: if filename+extension in self.full_filenames: return [lambda: builtinopen(self.full_filenames[filename+extension], "rb")] while self.dirs: dir = self.dirs.pop(0) for item in os.listdir(dir): full_item = os.path.join(dir, item) if os.path.isdir(full_item): self.dirs.insert(0, full_item) else: self.full_filenames[item] = full_item for extension in extensions: if filename+extension in self.full_filenames: return [lambda: builtinopen(self.full_filenames[filename+extension], "rb")] return [] locator_classes["recursivedir"] = recursivedir class ls_R: """locates files by searching a list of ls-R files""" def __init__(self): self.ls_Rs = getlist("filelocator", "ls-R") self.full_filenames = {} def openers(self, filename, names, extensions): while self.ls_Rs and not any([filename+extension in self.full_filenames for extension in extensions]): lsr = self.ls_Rs.pop(0) base_dir = os.path.dirname(lsr) dir = None first = True with builtinopen(lsr, "r", encoding="ascii", errors="surrogateescape") as lsrfile: for line in lsrfile: line = line.rstrip() if first and line.startswith("%"): continue first = False if line.endswith(":"): dir = os.path.join(base_dir, line[:-1]) elif line: self.full_filenames[line] = os.path.join(dir, line) for extension in extensions: if filename+extension in self.full_filenames: def _opener(): try: return builtinopen(self.full_filenames[filename+extension], "rb") except IOError: logger.warning("'%s' should be available at '%s' according to the ls-R file, " "but the file is not available at this location; " "update your ls-R file" % (filename, self.full_filenames[filename+extension])) return [_opener] return [] locator_classes["ls-R"] = ls_R class pykpathsea: """locate files by pykpathsea (a C extension module wrapping libkpathsea)""" def openers(self, filename, names, extensions): if not has_pykpathsea: return [] for name in names: full_filename = pykpathsea_module.find_file(filename, name) if full_filename: break else: return [] def _opener(): try: return builtinopen(full_filename, "rb") except IOError: logger.warning("'%s' should be available at '%s' according to libkpathsea, " "but the file is not available at this location; " "update your kpsewhich database" % (filename, full_filename)) return [_opener] locator_classes["pykpathsea"] = pykpathsea # class libkpathsea: # """locate files by libkpathsea using ctypes""" # # def openers(self, filename, names, extensions): # raise NotImplemented # # locator_classes["libpathsea"] = libkpathsea def Popen(cmd, *args, **kwargs): try: cmd + "" except: pass else: raise ValueError("pyx.config.Popen must not be used with a string cmd") info = "PyX executes {} with args {}".format(cmd[0], cmd[1:]) try: shutil.which except: pass else: info += " located at {}".format(shutil.which(cmd[0])) logger_execute.info(info) return subprocess.Popen(cmd, *args, **kwargs) PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT def fix_cygwin(full_filename): # detect cygwin result on windows python if os.name == "nt" and full_filename.startswith("/"): with Popen(['cygpath', '-w', full_filename], stdout=subprocess.PIPE).stdout as output: return io.TextIOWrapper(output, encoding="ascii", errors="surrogateescape").readline().rstrip() return full_filename class kpsewhich: """locate files using the kpsewhich executable""" def __init__(self): self.kpsewhich = get("filelocator", "kpsewhich", "kpsewhich") def openers(self, filename, names, extensions): full_filename = None for name in names: try: with Popen([self.kpsewhich, '--format', name, filename], stdout=subprocess.PIPE).stdout as output: with io.TextIOWrapper(output, encoding="ascii", errors="surrogateescape") as text_output: full_filename = text_output.readline().rstrip() except OSError: return [] if full_filename: break else: return [] full_filename = fix_cygwin(full_filename) def _opener(): try: return builtinopen(full_filename, "rb") except IOError: logger.warning("'%s' should be available at '%s' according to kpsewhich, " "but the file is not available at this location; " "update your kpsewhich database" % (filename, full_filename)) return [_opener] locator_classes["kpsewhich"] = kpsewhich class locate: """locate files using a locate executable""" def __init__(self): self.locate = get("filelocator", "locate", "locate") def openers(self, filename, names, extensions): full_filename = None for extension in extensions: with Popen([self.locate, filename+extension], stdout=subprocess.PIPE).stdout as output: with io.TextIOWrapper(output, encoding="ascii", errors="surrogateescape") as text_output: for line in text_output: line = line.rstrip() if os.path.basename(line) == filename+extension: full_filename = line break if full_filename: break else: return [] full_filename = fix_cygwin(full_filename) def _opener(): try: return builtinopen(full_filename, "rb") except IOError: logger.warning("'%s' should be available at '%s' according to the locate, " "but the file is not available at this location; " "update your locate database" % (filename+extension, full_filename)) return [_opener] locator_classes["locate"] = locate class _marker: pass config = configparser.ConfigParser() config.read_string(locator_classes["internal"]().openers("pyxrc", [], [""])[0]().read().decode("utf-8"), source="(internal pyxrc)") if os.name == "nt": user_pyxrc = os.path.join(os.environ['APPDATA'], "pyxrc") else: user_pyxrc = os.path.expanduser("~/.pyxrc") config.read(user_pyxrc, encoding="utf-8") if os.environ.get('PYXRC'): config.read(os.environ['PYXRC'], encoding="utf-8") def get(section, option, default=_marker): if default is _marker: return config.get(section, option) else: try: return config.get(section, option) except configparser.Error: return default def getint(section, option, default=_marker): if default is _marker: return config.getint(section, option) else: try: return config.getint(section, option) except configparser.Error: return default def getfloat(section, option, default=_marker): if default is _marker: return config.getfloat(section, option) else: try: return config.getfloat(section, option) except configparser.Error: return default def getboolean(section, option, default=_marker): if default is _marker: return config.getboolean(section, option) else: try: return config.getboolean(section, option) except configparser.Error: return default def getlist(section, option, default=_marker): if default is _marker: l = config.get(section, option).split() else: try: l = config.get(section, option).split() except configparser.Error: return default if space: l = [item.replace(space, " ") for item in l] return l space = get("general", "space", "SPACE") methods = [locator_classes[method]() for method in getlist("filelocator", "methods", ["local", "internal", "pykpathsea", "kpsewhich"])] opener_cache = {} def open(filename, formats, ascii=False): """returns an open file searched according the list of formats""" # When using an empty list of formats, the names list is empty # and the extensions list contains an empty string only. For that # case some locators (notably local and internal) return an open # function for the requested file whereas other locators might not # return anything (like pykpathsea and kpsewhich). # This is useful for files not to be searched in the latex # installation at all (like lfs files). extensions = set([""]) for format in formats: for extension in format.extensions: extensions.add(extension) names = tuple([format.name for format in formats]) if (filename, names) in opener_cache: file = opener_cache[(filename, names)]() else: for method in methods: openers = method.openers(filename, names, extensions) for opener in openers: try: file = opener() except EnvironmentError: file = None if file: info = "PyX filelocator found {} by method {}".format(filename, method.__class__.__name__) if hasattr(file, "name"): info += " at {}".format(file.name) logger_filelocator.info(info) opener_cache[(filename, names)] = opener break # break two loops here else: continue break else: logger_filelocator.info("PyX filelocator failed to find {} of type {} and extensions {}".format(filename, names, extensions)) raise IOError("Could not locate the file '%s'." % filename) if ascii: return io.TextIOWrapper(file, encoding="ascii", errors="surrogateescape") else: return file class format: def __init__(self, name, extensions): self.name = name self.extensions = extensions format.tfm = format("tfm", [".tfm"]) format.afm = format("afm", [".afm"]) format.fontmap = format("map", []) format.pict = format("graphic/figure", [".eps", ".epsi"]) format.tex_ps_header = format("PostScript header", [".pro"]) # contains also: enc files format.type1 = format("type1 fonts", [".pfa", ".pfb"]) format.vf = format("vf", [".vf"]) format.dvips_config = format("dvips config", []) PyX-0.14.1/pyx/connector.py0000644000076500000240000004000612177540640015723 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2003-2006 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from math import degrees, radians, pi, sin, cos, atan2, tan, hypot, acos, sqrt from . import path, unit, mathutils, normpath ######################### ## helpers ######################### class connector_pt(normpath.normpath): def omitends(self, box1, box2): """intersects a path with the boxes' paths""" # cut off the start of self # XXX how can decoration of this box1.path() be handled? sp = self.intersect(box1.path())[0] if sp: self.normsubpaths = self.split(sp[-1:])[1].normsubpaths # cut off the end of self sp = self.intersect(box2.path())[0] if sp: self.normsubpaths = self.split(sp[:1])[0].normsubpaths def shortenpath(self, dists): """shortens a path by the given distances""" # XXX later, this should be done by extended boxes instead of intersecting with circles # cut off the start of self center = self.atbegin_pt() cutpath = path.circle_pt(center[0], center[1], dists[0]) try: cutpath = cutpath.normpath() except normpath.NormpathException: pass else: sp = self.intersect(cutpath)[0] self.normsubpaths = self.split(sp[-1:])[1].normsubpaths # cut off the end of self center = self.atend_pt() cutpath = path.circle_pt(center[0], center[1], dists[1]) try: cutpath = cutpath.normpath() except normpath.NormpathException: pass else: sp = self.intersect(cutpath)[0] if sp: self.normsubpaths = self.split(sp[:1])[0].normsubpaths ################ ## classes ################ class line_pt(connector_pt): def __init__(self, box1, box2, boxdists=[0,0]): self.box1 = box1 self.box2 = box2 connector_pt.__init__(self, [path.normsubpath([path.normline_pt(self.box1.center[0], self.box1.center[1], self.box2.center[0], self.box2.center[1])], closed=0)]) self.omitends(box1, box2) self.shortenpath(boxdists) class arc_pt(connector_pt): def __init__(self, box1, box2, relangle=45, absbulge=None, relbulge=None, boxdists=[0,0]): # the deviation of arc from the straight line can be specified: # 1. By an angle between a straight line and the arc # This angle is measured at the centers of the box. # 2. By the largest normal distance between line and arc: absbulge # or, equivalently, by the bulge relative to the length of the # straight line from center to center. # Only one can be used. self.box1 = box1 self.box2 = box2 tangent = (self.box2.center[0] - self.box1.center[0], self.box2.center[1] - self.box1.center[1]) distance = hypot(*tangent) tangent = tangent[0] / distance, tangent[1] / distance if relbulge is not None or absbulge is not None: # usage of bulge overrides the relangle parameter bulge = 0 if absbulge is not None: bulge += absbulge if relbulge is not None: bulge += relbulge*distance else: # otherwise use relangle, which should be present bulge = 0.5 * distance * math.tan(0.5*radians(relangle)) if abs(bulge) < normpath._epsilon: # fallback solution for too straight arcs connector_pt.__init__(self, [path.normsubpath([path.normline_pt(*(self.box1.center+self.box2.center))], closed=0)]) else: radius = abs(0.5 * (bulge + 0.25 * distance**2 / bulge)) centerdist = mathutils.sign(bulge) * (radius - abs(bulge)) center = (0.5 * (self.box1.center[0] + self.box2.center[0]) + tangent[1]*centerdist, 0.5 * (self.box1.center[1] + self.box2.center[1]) - tangent[0]*centerdist) angle1 = atan2(self.box1.center[1] - center[1], self.box1.center[0] - center[0]) angle2 = atan2(self.box2.center[1] - center[1], self.box2.center[0] - center[0]) if bulge > 0: connectorpath = path.path(path.moveto_pt(*self.box1.center), path.arcn_pt(center[0], center[1], radius, degrees(angle1), degrees(angle2))) connector_pt.__init__(self, connectorpath.normpath().normsubpaths) else: connectorpath = path.path(path.moveto_pt(*self.box1.center), path.arc_pt(center[0], center[1], radius, degrees(angle1), degrees(angle2))) connector_pt.__init__(self, connectorpath.normpath().normsubpaths) self.omitends(box1, box2) self.shortenpath(boxdists) class curve_pt(connector_pt): def __init__(self, box1, box2, relangle1=45, relangle2=45, absangle1=None, absangle2=None, absbulge=0, relbulge=0.39, boxdists=[0,0]): # The deviation of the curve from a straight line can be specified: # A. By an angle at each center # These angles are either absolute angles with origin at the positive x-axis # or the relative angle with origin at the straight connection line # B. By the (expected) largest normal distance between line and arc: absbulge # and/or by the (expected) bulge relative to the length of the # straight line from center to center. # Here, we need both informations. # # a curve with relbulge=0.39 and relangle1,2=45 leads # approximately to the arc with angle=45 self.box1 = box1 self.box2 = box2 rel = (self.box2.center[0] - self.box1.center[0], self.box2.center[1] - self.box1.center[1]) distance = hypot(*rel) # absolute angle of the straight connection dangle = atan2(rel[1], rel[0]) # calculate the armlength and absolute angles for the control points: # absolute and relative bulges are added bulge = abs(distance*relbulge + absbulge) if absangle1 is not None: angle1 = radians(absangle1) else: angle1 = dangle + radians(relangle1) if absangle2 is not None: angle2 = radians(absangle2) else: angle2 = dangle + radians(relangle2) # get the control points control1 = (cos(angle1), sin(angle1)) control2 = (cos(angle2), sin(angle2)) control1 = (self.box1.center[0] + control1[0] * bulge, self.box1.center[1] + control1[1] * bulge) control2 = (self.box2.center[0] - control2[0] * bulge, self.box2.center[1] - control2[1] * bulge) connector_pt.__init__(self, [path.normsubpath([path.normcurve_pt(*(self.box1.center + control1 + control2 + self.box2.center))], 0)]) self.omitends(box1, box2) self.shortenpath(boxdists) class twolines_pt(connector_pt): def __init__(self, box1, box2, absangle1=None, absangle2=None, relangle1=None, relangle2=None, relangleM=None, length1=None, length2=None, bezierradius=None, beziersoftness=1, arcradius=None, boxdists=[0,0]): # The connection with two lines can be done in the following ways: # 1. an angle at each box-center # 2. two armlengths (if they are long enough) # 3. angle and armlength at the same box # 4. angle and armlength at different boxes # 5. one armlength and the angle between the arms # # Angles at the box-centers can be relative or absolute # The angle in the middle is always relative # lengths are always absolute self.box1 = box1 self.box2 = box2 begin = self.box1.center end = self.box2.center rel = (self.box2.center[0] - self.box1.center[0], self.box2.center[1] - self.box1.center[1]) distance = hypot(*rel) dangle = atan2(rel[1], rel[0]) # find out what arguments are given: if relangle1 is not None: relangle1 = radians(relangle1) if relangle2 is not None: relangle2 = radians(relangle2) if relangleM is not None: relangleM = radians(relangleM) # absangle has priority over relangle: if absangle1 is not None: relangle1 = dangle - radians(absangle1) if absangle2 is not None: relangle2 = math.pi - dangle + radians(absangle2) # check integrity of arguments no_angles, no_lengths=0,0 for anangle in (relangle1, relangle2, relangleM): if anangle is not None: no_angles += 1 for alength in (length1, length2): if alength is not None: no_lengths += 1 if no_angles + no_lengths != 2: raise NotImplementedError("Please specify exactly two angles or lengths") # calculate necessary angles and armlengths # always length1 and relangle1 # the case with two given angles # use the "sine-theorem" for calculating length1 if no_angles == 2: if relangle1 is None: relangle1 = math.pi - relangle2 - relangleM elif relangle2 is None: relangle2 = math.pi - relangle1 - relangleM elif relangleM is None: relangleM = math.pi - relangle1 - relangle2 length1 = distance * abs(sin(relangle2)/sin(relangleM)) middle = self._middle_a(begin, dangle, length1, relangle1) # the case with two given lengths # uses the "cosine-theorem" for calculating length1 elif no_lengths == 2: relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1)) middle = self._middle_a(begin, dangle, length1, relangle1) # the case with one length and one angle else: if relangle1 is not None: if length1 is not None: middle = self._middle_a(begin, dangle, length1, relangle1) elif length2 is not None: length1 = self._missinglength(length2, distance, relangle1) middle = self._middle_a(begin, dangle, length1, relangle1) elif relangle2 is not None: if length1 is not None: length2 = self._missinglength(length1, distance, relangle2) middle = self._middle_b(end, dangle, length2, relangle2) elif length2 is not None: middle = self._middle_b(end, dangle, length2, relangle2) elif relangleM is not None: if length1 is not None: length2 = self._missinglength(distance, length1, relangleM) relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1)) middle = self._middle_a(begin, dangle, length1, relangle1) elif length2 is not None: length1 = self._missinglength(distance, length2, relangleM) relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1)) middle = self._middle_a(begin, dangle, length1, relangle1) else: raise NotImplementedError("I found a strange combination of arguments") connectorpath = path.path(path.moveto_pt(*self.box1.center), path.lineto_pt(*middle), path.lineto_pt(*self.box2.center)) connector_pt.__init__(self, connectorpath.normpath().normsubpaths) self.omitends(box1, box2) self.shortenpath(boxdists) def _middle_a(self, begin, dangle, length1, angle1): a = dangle - angle1 dir = cos(a), sin(a) return begin[0] + length1*dir[0], begin[1] + length1*dir[1] def _middle_b(self, end, dangle, length2, angle2): # a = -math.pi + dangle + angle2 return self._middle_a(end, -math.pi+dangle, length2, -angle2) def _missinglength(self, lenA, lenB, angleA): # calculate lenC, where side A and angleA are opposite tmp1 = lenB * cos(angleA) tmp2 = sqrt(tmp1**2 - lenB**2 + lenA**2) if tmp1 > tmp2: return tmp1 - tmp2 return tmp1 + tmp2 class line(line_pt): """a line is the straight connector between the centers of two boxes""" def __init__(self, box1, box2, boxdists=(0,0)): line_pt.__init__(self, box1, box2, boxdists=list(map(unit.topt, boxdists))) class curve(curve_pt): """a curve is the curved connector between the centers of two boxes. The constructor needs both angle and bulge""" def __init__(self, box1, box2, relangle1=45, relangle2=45, absangle1=None, absangle2=None, absbulge=0, relbulge=0.39, boxdists=[0,0]): curve_pt.__init__(self, box1, box2, relangle1=relangle1, relangle2=relangle2, absangle1=absangle1, absangle2=absangle2, absbulge=unit.topt(absbulge), relbulge=relbulge, boxdists=list(map(unit.topt, boxdists))) class arc(arc_pt): """an arc is a round connector between the centers of two boxes. The constructor gets either an angle in (-pi,pi) or a bulge parameter in (-distance, distance) (relbulge and absbulge are added)""" def __init__(self, box1, box2, relangle=45, absbulge=None, relbulge=None, boxdists=[0,0]): if absbulge is not None: absbulge = unit.topt(absbulge) arc_pt.__init__(self, box1, box2, relangle=relangle, absbulge=absbulge, relbulge=relbulge, boxdists=list(map(unit.topt, boxdists))) class twolines(twolines_pt): """a twolines is a connector consisting of two straight lines. The construcor takes a combination of angles and lengths: either two angles (relative or absolute) or two lenghts or one length and one angle""" def __init__(self, box1, box2, absangle1=None, absangle2=None, relangle1=None, relangle2=None, relangleM=None, length1=None, length2=None, bezierradius=None, beziersoftness=1, arcradius=None, boxdists=[0,0]): if length1 is not None: length1 = unit.topt(length1) if length2 is not None: length2 = unit.topt(length2) if bezierradius is not None: bezierradius = unit.topt(bezierradius) if arcradius is not None: arcradius = unit.topt(arcradius) twolines_pt.__init__(self, box1, box2, absangle1=absangle1, absangle2=absangle2, relangle1=relangle1, relangle2=relangle2, relangleM=relangleM, length1=length1, length2=length2, bezierradius=bezierradius, beziersoftness=1, arcradius=arcradius, boxdists=list(map(unit.topt, boxdists))) PyX-0.14.1/pyx/data/0000755000076500000240000000000012615763300014265 5ustar andrestaff00000000000000PyX-0.14.1/pyx/data/afm/0000755000076500000240000000000012615763300015030 5ustar andrestaff00000000000000PyX-0.14.1/pyx/data/afm/Courier-Bold.afm0000644000076500000240000003647312037547555020032 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Mon Jun 23 16:28:00 1997 Comment UniqueID 43048 Comment VMusage 41139 52164 FontName Courier-Bold FullName Courier Bold FamilyName Courier Weight Bold ItalicAngle 0 IsFixedPitch true CharacterSet ExtendedRoman FontBBox -113 -250 749 801 UnderlinePosition -100 UnderlineThickness 50 Version 003.000 Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. EncodingScheme AdobeStandardEncoding CapHeight 562 XHeight 439 Ascender 629 Descender -157 StdHW 84 StdVW 106 StartCharMetrics 315 C 32 ; WX 600 ; N space ; B 0 0 0 0 ; C 33 ; WX 600 ; N exclam ; B 202 -15 398 572 ; C 34 ; WX 600 ; N quotedbl ; B 135 277 465 562 ; C 35 ; WX 600 ; N numbersign ; B 56 -45 544 651 ; C 36 ; WX 600 ; N dollar ; B 82 -126 519 666 ; C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ; C 38 ; WX 600 ; N ampersand ; B 36 -15 546 543 ; C 39 ; WX 600 ; N quoteright ; B 171 277 423 562 ; C 40 ; WX 600 ; N parenleft ; B 219 -102 461 616 ; C 41 ; WX 600 ; N parenright ; B 139 -102 381 616 ; C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ; C 43 ; WX 600 ; N plus ; B 71 39 529 478 ; C 44 ; WX 600 ; N comma ; B 123 -111 393 174 ; C 45 ; WX 600 ; N hyphen ; B 100 203 500 313 ; C 46 ; WX 600 ; N period ; B 192 -15 408 171 ; C 47 ; WX 600 ; N slash ; B 98 -77 502 626 ; C 48 ; WX 600 ; N zero ; B 87 -15 513 616 ; C 49 ; WX 600 ; N one ; B 81 0 539 616 ; C 50 ; WX 600 ; N two ; B 61 0 499 616 ; C 51 ; WX 600 ; N three ; B 63 -15 501 616 ; C 52 ; WX 600 ; N four ; B 53 0 507 616 ; C 53 ; WX 600 ; N five ; B 70 -15 521 601 ; C 54 ; WX 600 ; N six ; B 90 -15 521 616 ; C 55 ; WX 600 ; N seven ; B 55 0 494 601 ; C 56 ; WX 600 ; N eight ; B 83 -15 517 616 ; C 57 ; WX 600 ; N nine ; B 79 -15 510 616 ; C 58 ; WX 600 ; N colon ; B 191 -15 407 425 ; C 59 ; WX 600 ; N semicolon ; B 123 -111 408 425 ; C 60 ; WX 600 ; N less ; B 66 15 523 501 ; C 61 ; WX 600 ; N equal ; B 71 118 529 398 ; C 62 ; WX 600 ; N greater ; B 77 15 534 501 ; C 63 ; WX 600 ; N question ; B 98 -14 501 580 ; C 64 ; WX 600 ; N at ; B 16 -15 584 616 ; C 65 ; WX 600 ; N A ; B -9 0 609 562 ; C 66 ; WX 600 ; N B ; B 30 0 573 562 ; C 67 ; WX 600 ; N C ; B 22 -18 560 580 ; C 68 ; WX 600 ; N D ; B 30 0 594 562 ; C 69 ; WX 600 ; N E ; B 25 0 560 562 ; C 70 ; WX 600 ; N F ; B 39 0 570 562 ; C 71 ; WX 600 ; N G ; B 22 -18 594 580 ; C 72 ; WX 600 ; N H ; B 20 0 580 562 ; C 73 ; WX 600 ; N I ; B 77 0 523 562 ; C 74 ; WX 600 ; N J ; B 37 -18 601 562 ; C 75 ; WX 600 ; N K ; B 21 0 599 562 ; C 76 ; WX 600 ; N L ; B 39 0 578 562 ; C 77 ; WX 600 ; N M ; B -2 0 602 562 ; C 78 ; WX 600 ; N N ; B 8 -12 610 562 ; C 79 ; WX 600 ; N O ; B 22 -18 578 580 ; C 80 ; WX 600 ; N P ; B 48 0 559 562 ; C 81 ; WX 600 ; N Q ; B 32 -138 578 580 ; C 82 ; WX 600 ; N R ; B 24 0 599 562 ; C 83 ; WX 600 ; N S ; B 47 -22 553 582 ; C 84 ; WX 600 ; N T ; B 21 0 579 562 ; C 85 ; WX 600 ; N U ; B 4 -18 596 562 ; C 86 ; WX 600 ; N V ; B -13 0 613 562 ; C 87 ; WX 600 ; N W ; B -18 0 618 562 ; C 88 ; WX 600 ; N X ; B 12 0 588 562 ; C 89 ; WX 600 ; N Y ; B 12 0 589 562 ; C 90 ; WX 600 ; N Z ; B 62 0 539 562 ; C 91 ; WX 600 ; N bracketleft ; B 245 -102 475 616 ; C 92 ; WX 600 ; N backslash ; B 99 -77 503 626 ; C 93 ; WX 600 ; N bracketright ; B 125 -102 355 616 ; C 94 ; WX 600 ; N asciicircum ; B 108 250 492 616 ; C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ; C 96 ; WX 600 ; N quoteleft ; B 178 277 428 562 ; C 97 ; WX 600 ; N a ; B 35 -15 570 454 ; C 98 ; WX 600 ; N b ; B 0 -15 584 626 ; C 99 ; WX 600 ; N c ; B 40 -15 545 459 ; C 100 ; WX 600 ; N d ; B 20 -15 591 626 ; C 101 ; WX 600 ; N e ; B 40 -15 563 454 ; C 102 ; WX 600 ; N f ; B 83 0 547 626 ; L i fi ; L l fl ; C 103 ; WX 600 ; N g ; B 30 -146 580 454 ; C 104 ; WX 600 ; N h ; B 5 0 592 626 ; C 105 ; WX 600 ; N i ; B 77 0 523 658 ; C 106 ; WX 600 ; N j ; B 63 -146 440 658 ; C 107 ; WX 600 ; N k ; B 20 0 585 626 ; C 108 ; WX 600 ; N l ; B 77 0 523 626 ; C 109 ; WX 600 ; N m ; B -22 0 626 454 ; C 110 ; WX 600 ; N n ; B 18 0 592 454 ; C 111 ; WX 600 ; N o ; B 30 -15 570 454 ; C 112 ; WX 600 ; N p ; B -1 -142 570 454 ; C 113 ; WX 600 ; N q ; B 20 -142 591 454 ; C 114 ; WX 600 ; N r ; B 47 0 580 454 ; C 115 ; WX 600 ; N s ; B 68 -17 535 459 ; C 116 ; WX 600 ; N t ; B 47 -15 532 562 ; C 117 ; WX 600 ; N u ; B -1 -15 569 439 ; C 118 ; WX 600 ; N v ; B -1 0 601 439 ; C 119 ; WX 600 ; N w ; B -18 0 618 439 ; C 120 ; WX 600 ; N x ; B 6 0 594 439 ; C 121 ; WX 600 ; N y ; B -4 -142 601 439 ; C 122 ; WX 600 ; N z ; B 81 0 520 439 ; C 123 ; WX 600 ; N braceleft ; B 160 -102 464 616 ; C 124 ; WX 600 ; N bar ; B 255 -250 345 750 ; C 125 ; WX 600 ; N braceright ; B 136 -102 440 616 ; C 126 ; WX 600 ; N asciitilde ; B 71 153 530 356 ; C 161 ; WX 600 ; N exclamdown ; B 202 -146 398 449 ; C 162 ; WX 600 ; N cent ; B 66 -49 518 614 ; C 163 ; WX 600 ; N sterling ; B 72 -28 558 611 ; C 164 ; WX 600 ; N fraction ; B 25 -60 576 661 ; C 165 ; WX 600 ; N yen ; B 10 0 590 562 ; C 166 ; WX 600 ; N florin ; B -30 -131 572 616 ; C 167 ; WX 600 ; N section ; B 83 -70 517 580 ; C 168 ; WX 600 ; N currency ; B 54 49 546 517 ; C 169 ; WX 600 ; N quotesingle ; B 227 277 373 562 ; C 170 ; WX 600 ; N quotedblleft ; B 71 277 535 562 ; C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ; C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ; C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ; C 174 ; WX 600 ; N fi ; B 12 0 593 626 ; C 175 ; WX 600 ; N fl ; B 12 0 593 626 ; C 177 ; WX 600 ; N endash ; B 65 203 535 313 ; C 178 ; WX 600 ; N dagger ; B 106 -70 494 580 ; C 179 ; WX 600 ; N daggerdbl ; B 106 -70 494 580 ; C 180 ; WX 600 ; N periodcentered ; B 196 165 404 351 ; C 182 ; WX 600 ; N paragraph ; B 6 -70 576 580 ; C 183 ; WX 600 ; N bullet ; B 140 132 460 430 ; C 184 ; WX 600 ; N quotesinglbase ; B 175 -142 427 143 ; C 185 ; WX 600 ; N quotedblbase ; B 65 -142 529 143 ; C 186 ; WX 600 ; N quotedblright ; B 61 277 525 562 ; C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ; C 188 ; WX 600 ; N ellipsis ; B 26 -15 574 116 ; C 189 ; WX 600 ; N perthousand ; B -113 -15 713 616 ; C 191 ; WX 600 ; N questiondown ; B 99 -146 502 449 ; C 193 ; WX 600 ; N grave ; B 132 508 395 661 ; C 194 ; WX 600 ; N acute ; B 205 508 468 661 ; C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ; C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ; C 197 ; WX 600 ; N macron ; B 88 505 512 585 ; C 198 ; WX 600 ; N breve ; B 83 468 517 631 ; C 199 ; WX 600 ; N dotaccent ; B 230 498 370 638 ; C 200 ; WX 600 ; N dieresis ; B 128 498 472 638 ; C 202 ; WX 600 ; N ring ; B 198 481 402 678 ; C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ; C 205 ; WX 600 ; N hungarumlaut ; B 68 488 588 661 ; C 206 ; WX 600 ; N ogonek ; B 169 -199 400 0 ; C 207 ; WX 600 ; N caron ; B 103 493 497 667 ; C 208 ; WX 600 ; N emdash ; B -10 203 610 313 ; C 225 ; WX 600 ; N AE ; B -29 0 602 562 ; C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ; C 232 ; WX 600 ; N Lslash ; B 39 0 578 562 ; C 233 ; WX 600 ; N Oslash ; B 22 -22 578 584 ; C 234 ; WX 600 ; N OE ; B -25 0 595 562 ; C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ; C 241 ; WX 600 ; N ae ; B -4 -15 601 454 ; C 245 ; WX 600 ; N dotlessi ; B 77 0 523 439 ; C 248 ; WX 600 ; N lslash ; B 77 0 523 626 ; C 249 ; WX 600 ; N oslash ; B 30 -24 570 463 ; C 250 ; WX 600 ; N oe ; B -18 -15 611 454 ; C 251 ; WX 600 ; N germandbls ; B 22 -15 596 626 ; C -1 ; WX 600 ; N Idieresis ; B 77 0 523 761 ; C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ; C -1 ; WX 600 ; N abreve ; B 35 -15 570 661 ; C -1 ; WX 600 ; N uhungarumlaut ; B -1 -15 628 661 ; C -1 ; WX 600 ; N ecaron ; B 40 -15 563 667 ; C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 761 ; C -1 ; WX 600 ; N divide ; B 71 16 529 500 ; C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ; C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ; C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ; C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ; C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ; C -1 ; WX 600 ; N scommaaccent ; B 68 -250 535 459 ; C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ; C -1 ; WX 600 ; N Uring ; B 4 -18 596 801 ; C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 761 ; C -1 ; WX 600 ; N aogonek ; B 35 -199 586 454 ; C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ; C -1 ; WX 600 ; N uogonek ; B -1 -199 585 439 ; C -1 ; WX 600 ; N Edieresis ; B 25 0 560 761 ; C -1 ; WX 600 ; N Dcroat ; B 30 0 594 562 ; C -1 ; WX 600 ; N commaaccent ; B 205 -250 397 -57 ; C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ; C -1 ; WX 600 ; N Emacron ; B 25 0 560 708 ; C -1 ; WX 600 ; N ccaron ; B 40 -15 545 667 ; C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ; C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 610 562 ; C -1 ; WX 600 ; N lacute ; B 77 0 523 801 ; C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ; C -1 ; WX 600 ; N Tcommaaccent ; B 21 -250 579 562 ; C -1 ; WX 600 ; N Cacute ; B 22 -18 560 784 ; C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ; C -1 ; WX 600 ; N Edotaccent ; B 25 0 560 761 ; C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ; C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ; C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ; C -1 ; WX 600 ; N lozenge ; B 66 0 534 740 ; C -1 ; WX 600 ; N Rcaron ; B 24 0 599 790 ; C -1 ; WX 600 ; N Gcommaaccent ; B 22 -250 594 580 ; C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ; C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ; C -1 ; WX 600 ; N Amacron ; B -9 0 609 708 ; C -1 ; WX 600 ; N rcaron ; B 47 0 580 667 ; C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ; C -1 ; WX 600 ; N Zdotaccent ; B 62 0 539 761 ; C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ; C -1 ; WX 600 ; N Omacron ; B 22 -18 578 708 ; C -1 ; WX 600 ; N Racute ; B 24 0 599 784 ; C -1 ; WX 600 ; N Sacute ; B 47 -22 553 784 ; C -1 ; WX 600 ; N dcaron ; B 20 -15 727 626 ; C -1 ; WX 600 ; N Umacron ; B 4 -18 596 708 ; C -1 ; WX 600 ; N uring ; B -1 -15 569 678 ; C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ; C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ; C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ; C -1 ; WX 600 ; N Abreve ; B -9 0 609 784 ; C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ; C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ; C -1 ; WX 600 ; N Tcaron ; B 21 0 579 790 ; C -1 ; WX 600 ; N partialdiff ; B 63 -38 537 728 ; C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 638 ; C -1 ; WX 600 ; N Nacute ; B 8 -12 610 784 ; C -1 ; WX 600 ; N icircumflex ; B 73 0 523 657 ; C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ; C -1 ; WX 600 ; N adieresis ; B 35 -15 570 638 ; C -1 ; WX 600 ; N edieresis ; B 40 -15 563 638 ; C -1 ; WX 600 ; N cacute ; B 40 -15 545 661 ; C -1 ; WX 600 ; N nacute ; B 18 0 592 661 ; C -1 ; WX 600 ; N umacron ; B -1 -15 569 585 ; C -1 ; WX 600 ; N Ncaron ; B 8 -12 610 790 ; C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ; C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ; C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ; C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ; C -1 ; WX 600 ; N Gbreve ; B 22 -18 594 784 ; C -1 ; WX 600 ; N Idotaccent ; B 77 0 523 761 ; C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ; C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ; C -1 ; WX 600 ; N racute ; B 47 0 580 661 ; C -1 ; WX 600 ; N omacron ; B 30 -15 570 585 ; C -1 ; WX 600 ; N Zacute ; B 62 0 539 784 ; C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ; C -1 ; WX 600 ; N greaterequal ; B 26 0 523 696 ; C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ; C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ; C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 523 626 ; C -1 ; WX 600 ; N tcaron ; B 47 -15 532 703 ; C -1 ; WX 600 ; N eogonek ; B 40 -199 563 454 ; C -1 ; WX 600 ; N Uogonek ; B 4 -199 596 562 ; C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ; C -1 ; WX 600 ; N Adieresis ; B -9 0 609 761 ; C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ; C -1 ; WX 600 ; N zacute ; B 81 0 520 661 ; C -1 ; WX 600 ; N iogonek ; B 77 -199 523 658 ; C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ; C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ; C -1 ; WX 600 ; N amacron ; B 35 -15 570 585 ; C -1 ; WX 600 ; N sacute ; B 68 -17 535 661 ; C -1 ; WX 600 ; N idieresis ; B 77 0 523 618 ; C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ; C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ; C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ; C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ; C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ; C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 761 ; C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ; C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ; C -1 ; WX 600 ; N ohungarumlaut ; B 30 -15 668 661 ; C -1 ; WX 600 ; N Eogonek ; B 25 -199 576 562 ; C -1 ; WX 600 ; N dcroat ; B 20 -15 591 626 ; C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ; C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ; C -1 ; WX 600 ; N lcaron ; B 77 0 597 626 ; C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 599 562 ; C -1 ; WX 600 ; N Lacute ; B 39 0 578 784 ; C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ; C -1 ; WX 600 ; N edotaccent ; B 40 -15 563 638 ; C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ; C -1 ; WX 600 ; N Imacron ; B 77 0 523 708 ; C -1 ; WX 600 ; N Lcaron ; B 39 0 637 562 ; C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ; C -1 ; WX 600 ; N lessequal ; B 26 0 523 696 ; C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ; C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ; C -1 ; WX 600 ; N Uhungarumlaut ; B 4 -18 638 784 ; C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ; C -1 ; WX 600 ; N emacron ; B 40 -15 563 585 ; C -1 ; WX 600 ; N gbreve ; B 30 -146 580 661 ; C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ; C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ; C -1 ; WX 600 ; N Scommaaccent ; B 47 -250 553 582 ; C -1 ; WX 600 ; N Ohungarumlaut ; B 22 -18 628 784 ; C -1 ; WX 600 ; N degree ; B 86 243 474 616 ; C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ; C -1 ; WX 600 ; N Ccaron ; B 22 -18 560 790 ; C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ; C -1 ; WX 600 ; N radical ; B -19 -104 473 778 ; C -1 ; WX 600 ; N Dcaron ; B 30 0 594 790 ; C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 580 454 ; C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ; C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ; C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 599 562 ; C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 578 562 ; C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ; C -1 ; WX 600 ; N Aogonek ; B -9 -199 625 562 ; C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ; C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ; C -1 ; WX 600 ; N zdotaccent ; B 81 0 520 638 ; C -1 ; WX 600 ; N Ecaron ; B 25 0 560 790 ; C -1 ; WX 600 ; N Iogonek ; B 77 -199 523 562 ; C -1 ; WX 600 ; N kcommaaccent ; B 20 -250 585 626 ; C -1 ; WX 600 ; N minus ; B 71 203 529 313 ; C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ; C -1 ; WX 600 ; N ncaron ; B 18 0 592 667 ; C -1 ; WX 600 ; N tcommaaccent ; B 47 -250 532 562 ; C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ; C -1 ; WX 600 ; N odieresis ; B 30 -15 570 638 ; C -1 ; WX 600 ; N udieresis ; B -1 -15 569 638 ; C -1 ; WX 600 ; N notequal ; B 12 -47 537 563 ; C -1 ; WX 600 ; N gcommaaccent ; B 30 -146 580 714 ; C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ; C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ; C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 592 454 ; C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ; C -1 ; WX 600 ; N imacron ; B 77 0 523 585 ; C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/afm/Courier-BoldOblique.afm0000644000076500000240000003657512037547555021356 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Mon Jun 23 16:28:46 1997 Comment UniqueID 43049 Comment VMusage 17529 79244 FontName Courier-BoldOblique FullName Courier Bold Oblique FamilyName Courier Weight Bold ItalicAngle -12 IsFixedPitch true CharacterSet ExtendedRoman FontBBox -57 -250 869 801 UnderlinePosition -100 UnderlineThickness 50 Version 003.000 Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. EncodingScheme AdobeStandardEncoding CapHeight 562 XHeight 439 Ascender 629 Descender -157 StdHW 84 StdVW 106 StartCharMetrics 315 C 32 ; WX 600 ; N space ; B 0 0 0 0 ; C 33 ; WX 600 ; N exclam ; B 215 -15 495 572 ; C 34 ; WX 600 ; N quotedbl ; B 211 277 585 562 ; C 35 ; WX 600 ; N numbersign ; B 88 -45 641 651 ; C 36 ; WX 600 ; N dollar ; B 87 -126 630 666 ; C 37 ; WX 600 ; N percent ; B 101 -15 625 616 ; C 38 ; WX 600 ; N ampersand ; B 61 -15 595 543 ; C 39 ; WX 600 ; N quoteright ; B 229 277 543 562 ; C 40 ; WX 600 ; N parenleft ; B 265 -102 592 616 ; C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ; C 42 ; WX 600 ; N asterisk ; B 179 219 598 601 ; C 43 ; WX 600 ; N plus ; B 114 39 596 478 ; C 44 ; WX 600 ; N comma ; B 99 -111 430 174 ; C 45 ; WX 600 ; N hyphen ; B 143 203 567 313 ; C 46 ; WX 600 ; N period ; B 206 -15 427 171 ; C 47 ; WX 600 ; N slash ; B 90 -77 626 626 ; C 48 ; WX 600 ; N zero ; B 135 -15 593 616 ; C 49 ; WX 600 ; N one ; B 93 0 562 616 ; C 50 ; WX 600 ; N two ; B 61 0 594 616 ; C 51 ; WX 600 ; N three ; B 71 -15 571 616 ; C 52 ; WX 600 ; N four ; B 81 0 559 616 ; C 53 ; WX 600 ; N five ; B 77 -15 621 601 ; C 54 ; WX 600 ; N six ; B 135 -15 652 616 ; C 55 ; WX 600 ; N seven ; B 147 0 622 601 ; C 56 ; WX 600 ; N eight ; B 115 -15 604 616 ; C 57 ; WX 600 ; N nine ; B 75 -15 592 616 ; C 58 ; WX 600 ; N colon ; B 205 -15 480 425 ; C 59 ; WX 600 ; N semicolon ; B 99 -111 481 425 ; C 60 ; WX 600 ; N less ; B 120 15 613 501 ; C 61 ; WX 600 ; N equal ; B 96 118 614 398 ; C 62 ; WX 600 ; N greater ; B 97 15 589 501 ; C 63 ; WX 600 ; N question ; B 183 -14 592 580 ; C 64 ; WX 600 ; N at ; B 65 -15 642 616 ; C 65 ; WX 600 ; N A ; B -9 0 632 562 ; C 66 ; WX 600 ; N B ; B 30 0 630 562 ; C 67 ; WX 600 ; N C ; B 74 -18 675 580 ; C 68 ; WX 600 ; N D ; B 30 0 664 562 ; C 69 ; WX 600 ; N E ; B 25 0 670 562 ; C 70 ; WX 600 ; N F ; B 39 0 684 562 ; C 71 ; WX 600 ; N G ; B 74 -18 675 580 ; C 72 ; WX 600 ; N H ; B 20 0 700 562 ; C 73 ; WX 600 ; N I ; B 77 0 643 562 ; C 74 ; WX 600 ; N J ; B 58 -18 721 562 ; C 75 ; WX 600 ; N K ; B 21 0 692 562 ; C 76 ; WX 600 ; N L ; B 39 0 636 562 ; C 77 ; WX 600 ; N M ; B -2 0 722 562 ; C 78 ; WX 600 ; N N ; B 8 -12 730 562 ; C 79 ; WX 600 ; N O ; B 74 -18 645 580 ; C 80 ; WX 600 ; N P ; B 48 0 643 562 ; C 81 ; WX 600 ; N Q ; B 83 -138 636 580 ; C 82 ; WX 600 ; N R ; B 24 0 617 562 ; C 83 ; WX 600 ; N S ; B 54 -22 673 582 ; C 84 ; WX 600 ; N T ; B 86 0 679 562 ; C 85 ; WX 600 ; N U ; B 101 -18 716 562 ; C 86 ; WX 600 ; N V ; B 84 0 733 562 ; C 87 ; WX 600 ; N W ; B 79 0 738 562 ; C 88 ; WX 600 ; N X ; B 12 0 690 562 ; C 89 ; WX 600 ; N Y ; B 109 0 709 562 ; C 90 ; WX 600 ; N Z ; B 62 0 637 562 ; C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ; C 92 ; WX 600 ; N backslash ; B 222 -77 496 626 ; C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ; C 94 ; WX 600 ; N asciicircum ; B 171 250 556 616 ; C 95 ; WX 600 ; N underscore ; B -27 -125 585 -75 ; C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ; C 97 ; WX 600 ; N a ; B 61 -15 593 454 ; C 98 ; WX 600 ; N b ; B 13 -15 636 626 ; C 99 ; WX 600 ; N c ; B 81 -15 631 459 ; C 100 ; WX 600 ; N d ; B 60 -15 645 626 ; C 101 ; WX 600 ; N e ; B 81 -15 605 454 ; C 102 ; WX 600 ; N f ; B 83 0 677 626 ; L i fi ; L l fl ; C 103 ; WX 600 ; N g ; B 40 -146 674 454 ; C 104 ; WX 600 ; N h ; B 18 0 615 626 ; C 105 ; WX 600 ; N i ; B 77 0 546 658 ; C 106 ; WX 600 ; N j ; B 36 -146 580 658 ; C 107 ; WX 600 ; N k ; B 33 0 643 626 ; C 108 ; WX 600 ; N l ; B 77 0 546 626 ; C 109 ; WX 600 ; N m ; B -22 0 649 454 ; C 110 ; WX 600 ; N n ; B 18 0 615 454 ; C 111 ; WX 600 ; N o ; B 71 -15 622 454 ; C 112 ; WX 600 ; N p ; B -32 -142 622 454 ; C 113 ; WX 600 ; N q ; B 60 -142 685 454 ; C 114 ; WX 600 ; N r ; B 47 0 655 454 ; C 115 ; WX 600 ; N s ; B 66 -17 608 459 ; C 116 ; WX 600 ; N t ; B 118 -15 567 562 ; C 117 ; WX 600 ; N u ; B 70 -15 592 439 ; C 118 ; WX 600 ; N v ; B 70 0 695 439 ; C 119 ; WX 600 ; N w ; B 53 0 712 439 ; C 120 ; WX 600 ; N x ; B 6 0 671 439 ; C 121 ; WX 600 ; N y ; B -21 -142 695 439 ; C 122 ; WX 600 ; N z ; B 81 0 614 439 ; C 123 ; WX 600 ; N braceleft ; B 203 -102 595 616 ; C 124 ; WX 600 ; N bar ; B 201 -250 505 750 ; C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ; C 126 ; WX 600 ; N asciitilde ; B 120 153 590 356 ; C 161 ; WX 600 ; N exclamdown ; B 196 -146 477 449 ; C 162 ; WX 600 ; N cent ; B 121 -49 605 614 ; C 163 ; WX 600 ; N sterling ; B 106 -28 650 611 ; C 164 ; WX 600 ; N fraction ; B 22 -60 708 661 ; C 165 ; WX 600 ; N yen ; B 98 0 710 562 ; C 166 ; WX 600 ; N florin ; B -57 -131 702 616 ; C 167 ; WX 600 ; N section ; B 74 -70 620 580 ; C 168 ; WX 600 ; N currency ; B 77 49 644 517 ; C 169 ; WX 600 ; N quotesingle ; B 303 277 493 562 ; C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ; C 171 ; WX 600 ; N guillemotleft ; B 62 70 639 446 ; C 172 ; WX 600 ; N guilsinglleft ; B 195 70 545 446 ; C 173 ; WX 600 ; N guilsinglright ; B 165 70 514 446 ; C 174 ; WX 600 ; N fi ; B 12 0 644 626 ; C 175 ; WX 600 ; N fl ; B 12 0 644 626 ; C 177 ; WX 600 ; N endash ; B 108 203 602 313 ; C 178 ; WX 600 ; N dagger ; B 175 -70 586 580 ; C 179 ; WX 600 ; N daggerdbl ; B 121 -70 587 580 ; C 180 ; WX 600 ; N periodcentered ; B 248 165 461 351 ; C 182 ; WX 600 ; N paragraph ; B 61 -70 700 580 ; C 183 ; WX 600 ; N bullet ; B 196 132 523 430 ; C 184 ; WX 600 ; N quotesinglbase ; B 144 -142 458 143 ; C 185 ; WX 600 ; N quotedblbase ; B 34 -142 560 143 ; C 186 ; WX 600 ; N quotedblright ; B 119 277 645 562 ; C 187 ; WX 600 ; N guillemotright ; B 71 70 647 446 ; C 188 ; WX 600 ; N ellipsis ; B 35 -15 587 116 ; C 189 ; WX 600 ; N perthousand ; B -45 -15 743 616 ; C 191 ; WX 600 ; N questiondown ; B 100 -146 509 449 ; C 193 ; WX 600 ; N grave ; B 272 508 503 661 ; C 194 ; WX 600 ; N acute ; B 312 508 609 661 ; C 195 ; WX 600 ; N circumflex ; B 212 483 607 657 ; C 196 ; WX 600 ; N tilde ; B 199 493 643 636 ; C 197 ; WX 600 ; N macron ; B 195 505 637 585 ; C 198 ; WX 600 ; N breve ; B 217 468 652 631 ; C 199 ; WX 600 ; N dotaccent ; B 348 498 493 638 ; C 200 ; WX 600 ; N dieresis ; B 246 498 595 638 ; C 202 ; WX 600 ; N ring ; B 319 481 528 678 ; C 203 ; WX 600 ; N cedilla ; B 168 -206 368 0 ; C 205 ; WX 600 ; N hungarumlaut ; B 171 488 729 661 ; C 206 ; WX 600 ; N ogonek ; B 143 -199 367 0 ; C 207 ; WX 600 ; N caron ; B 238 493 633 667 ; C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ; C 225 ; WX 600 ; N AE ; B -29 0 708 562 ; C 227 ; WX 600 ; N ordfeminine ; B 188 196 526 580 ; C 232 ; WX 600 ; N Lslash ; B 39 0 636 562 ; C 233 ; WX 600 ; N Oslash ; B 48 -22 673 584 ; C 234 ; WX 600 ; N OE ; B 26 0 701 562 ; C 235 ; WX 600 ; N ordmasculine ; B 188 196 543 580 ; C 241 ; WX 600 ; N ae ; B 21 -15 652 454 ; C 245 ; WX 600 ; N dotlessi ; B 77 0 546 439 ; C 248 ; WX 600 ; N lslash ; B 77 0 587 626 ; C 249 ; WX 600 ; N oslash ; B 54 -24 638 463 ; C 250 ; WX 600 ; N oe ; B 18 -15 662 454 ; C 251 ; WX 600 ; N germandbls ; B 22 -15 629 626 ; C -1 ; WX 600 ; N Idieresis ; B 77 0 643 761 ; C -1 ; WX 600 ; N eacute ; B 81 -15 609 661 ; C -1 ; WX 600 ; N abreve ; B 61 -15 658 661 ; C -1 ; WX 600 ; N uhungarumlaut ; B 70 -15 769 661 ; C -1 ; WX 600 ; N ecaron ; B 81 -15 633 667 ; C -1 ; WX 600 ; N Ydieresis ; B 109 0 709 761 ; C -1 ; WX 600 ; N divide ; B 114 16 596 500 ; C -1 ; WX 600 ; N Yacute ; B 109 0 709 784 ; C -1 ; WX 600 ; N Acircumflex ; B -9 0 632 780 ; C -1 ; WX 600 ; N aacute ; B 61 -15 609 661 ; C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 716 780 ; C -1 ; WX 600 ; N yacute ; B -21 -142 695 661 ; C -1 ; WX 600 ; N scommaaccent ; B 66 -250 608 459 ; C -1 ; WX 600 ; N ecircumflex ; B 81 -15 607 657 ; C -1 ; WX 600 ; N Uring ; B 101 -18 716 801 ; C -1 ; WX 600 ; N Udieresis ; B 101 -18 716 761 ; C -1 ; WX 600 ; N aogonek ; B 61 -199 593 454 ; C -1 ; WX 600 ; N Uacute ; B 101 -18 716 784 ; C -1 ; WX 600 ; N uogonek ; B 70 -199 592 439 ; C -1 ; WX 600 ; N Edieresis ; B 25 0 670 761 ; C -1 ; WX 600 ; N Dcroat ; B 30 0 664 562 ; C -1 ; WX 600 ; N commaaccent ; B 151 -250 385 -57 ; C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ; C -1 ; WX 600 ; N Emacron ; B 25 0 670 708 ; C -1 ; WX 600 ; N ccaron ; B 81 -15 633 667 ; C -1 ; WX 600 ; N aring ; B 61 -15 593 678 ; C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 730 562 ; C -1 ; WX 600 ; N lacute ; B 77 0 639 801 ; C -1 ; WX 600 ; N agrave ; B 61 -15 593 661 ; C -1 ; WX 600 ; N Tcommaaccent ; B 86 -250 679 562 ; C -1 ; WX 600 ; N Cacute ; B 74 -18 675 784 ; C -1 ; WX 600 ; N atilde ; B 61 -15 643 636 ; C -1 ; WX 600 ; N Edotaccent ; B 25 0 670 761 ; C -1 ; WX 600 ; N scaron ; B 66 -17 633 667 ; C -1 ; WX 600 ; N scedilla ; B 66 -206 608 459 ; C -1 ; WX 600 ; N iacute ; B 77 0 609 661 ; C -1 ; WX 600 ; N lozenge ; B 145 0 614 740 ; C -1 ; WX 600 ; N Rcaron ; B 24 0 659 790 ; C -1 ; WX 600 ; N Gcommaaccent ; B 74 -250 675 580 ; C -1 ; WX 600 ; N ucircumflex ; B 70 -15 597 657 ; C -1 ; WX 600 ; N acircumflex ; B 61 -15 607 657 ; C -1 ; WX 600 ; N Amacron ; B -9 0 633 708 ; C -1 ; WX 600 ; N rcaron ; B 47 0 655 667 ; C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ; C -1 ; WX 600 ; N Zdotaccent ; B 62 0 637 761 ; C -1 ; WX 600 ; N Thorn ; B 48 0 620 562 ; C -1 ; WX 600 ; N Omacron ; B 74 -18 663 708 ; C -1 ; WX 600 ; N Racute ; B 24 0 665 784 ; C -1 ; WX 600 ; N Sacute ; B 54 -22 673 784 ; C -1 ; WX 600 ; N dcaron ; B 60 -15 861 626 ; C -1 ; WX 600 ; N Umacron ; B 101 -18 716 708 ; C -1 ; WX 600 ; N uring ; B 70 -15 592 678 ; C -1 ; WX 600 ; N threesuperior ; B 193 222 526 616 ; C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ; C -1 ; WX 600 ; N Agrave ; B -9 0 632 784 ; C -1 ; WX 600 ; N Abreve ; B -9 0 684 784 ; C -1 ; WX 600 ; N multiply ; B 104 39 606 478 ; C -1 ; WX 600 ; N uacute ; B 70 -15 599 661 ; C -1 ; WX 600 ; N Tcaron ; B 86 0 679 790 ; C -1 ; WX 600 ; N partialdiff ; B 91 -38 627 728 ; C -1 ; WX 600 ; N ydieresis ; B -21 -142 695 638 ; C -1 ; WX 600 ; N Nacute ; B 8 -12 730 784 ; C -1 ; WX 600 ; N icircumflex ; B 77 0 577 657 ; C -1 ; WX 600 ; N Ecircumflex ; B 25 0 670 780 ; C -1 ; WX 600 ; N adieresis ; B 61 -15 595 638 ; C -1 ; WX 600 ; N edieresis ; B 81 -15 605 638 ; C -1 ; WX 600 ; N cacute ; B 81 -15 649 661 ; C -1 ; WX 600 ; N nacute ; B 18 0 639 661 ; C -1 ; WX 600 ; N umacron ; B 70 -15 637 585 ; C -1 ; WX 600 ; N Ncaron ; B 8 -12 730 790 ; C -1 ; WX 600 ; N Iacute ; B 77 0 643 784 ; C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ; C -1 ; WX 600 ; N brokenbar ; B 217 -175 489 675 ; C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ; C -1 ; WX 600 ; N Gbreve ; B 74 -18 684 784 ; C -1 ; WX 600 ; N Idotaccent ; B 77 0 643 761 ; C -1 ; WX 600 ; N summation ; B 15 -10 672 706 ; C -1 ; WX 600 ; N Egrave ; B 25 0 670 784 ; C -1 ; WX 600 ; N racute ; B 47 0 655 661 ; C -1 ; WX 600 ; N omacron ; B 71 -15 637 585 ; C -1 ; WX 600 ; N Zacute ; B 62 0 665 784 ; C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ; C -1 ; WX 600 ; N greaterequal ; B 26 0 627 696 ; C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ; C -1 ; WX 600 ; N Ccedilla ; B 74 -206 675 580 ; C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 546 626 ; C -1 ; WX 600 ; N tcaron ; B 118 -15 627 703 ; C -1 ; WX 600 ; N eogonek ; B 81 -199 605 454 ; C -1 ; WX 600 ; N Uogonek ; B 101 -199 716 562 ; C -1 ; WX 600 ; N Aacute ; B -9 0 655 784 ; C -1 ; WX 600 ; N Adieresis ; B -9 0 632 761 ; C -1 ; WX 600 ; N egrave ; B 81 -15 605 661 ; C -1 ; WX 600 ; N zacute ; B 81 0 614 661 ; C -1 ; WX 600 ; N iogonek ; B 77 -199 546 658 ; C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ; C -1 ; WX 600 ; N oacute ; B 71 -15 649 661 ; C -1 ; WX 600 ; N amacron ; B 61 -15 637 585 ; C -1 ; WX 600 ; N sacute ; B 66 -17 609 661 ; C -1 ; WX 600 ; N idieresis ; B 77 0 561 618 ; C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ; C -1 ; WX 600 ; N Ugrave ; B 101 -18 716 784 ; C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ; C -1 ; WX 600 ; N thorn ; B -32 -142 622 626 ; C -1 ; WX 600 ; N twosuperior ; B 191 230 542 616 ; C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 761 ; C -1 ; WX 600 ; N mu ; B 49 -142 592 439 ; C -1 ; WX 600 ; N igrave ; B 77 0 546 661 ; C -1 ; WX 600 ; N ohungarumlaut ; B 71 -15 809 661 ; C -1 ; WX 600 ; N Eogonek ; B 25 -199 670 562 ; C -1 ; WX 600 ; N dcroat ; B 60 -15 712 626 ; C -1 ; WX 600 ; N threequarters ; B 8 -60 699 661 ; C -1 ; WX 600 ; N Scedilla ; B 54 -206 673 582 ; C -1 ; WX 600 ; N lcaron ; B 77 0 731 626 ; C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 692 562 ; C -1 ; WX 600 ; N Lacute ; B 39 0 636 784 ; C -1 ; WX 600 ; N trademark ; B 86 230 869 562 ; C -1 ; WX 600 ; N edotaccent ; B 81 -15 605 638 ; C -1 ; WX 600 ; N Igrave ; B 77 0 643 784 ; C -1 ; WX 600 ; N Imacron ; B 77 0 663 708 ; C -1 ; WX 600 ; N Lcaron ; B 39 0 757 562 ; C -1 ; WX 600 ; N onehalf ; B 22 -60 716 661 ; C -1 ; WX 600 ; N lessequal ; B 26 0 671 696 ; C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ; C -1 ; WX 600 ; N ntilde ; B 18 0 643 636 ; C -1 ; WX 600 ; N Uhungarumlaut ; B 101 -18 805 784 ; C -1 ; WX 600 ; N Eacute ; B 25 0 670 784 ; C -1 ; WX 600 ; N emacron ; B 81 -15 637 585 ; C -1 ; WX 600 ; N gbreve ; B 40 -146 674 661 ; C -1 ; WX 600 ; N onequarter ; B 13 -60 707 661 ; C -1 ; WX 600 ; N Scaron ; B 54 -22 689 790 ; C -1 ; WX 600 ; N Scommaaccent ; B 54 -250 673 582 ; C -1 ; WX 600 ; N Ohungarumlaut ; B 74 -18 795 784 ; C -1 ; WX 600 ; N degree ; B 173 243 570 616 ; C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ; C -1 ; WX 600 ; N Ccaron ; B 74 -18 689 790 ; C -1 ; WX 600 ; N ugrave ; B 70 -15 592 661 ; C -1 ; WX 600 ; N radical ; B 67 -104 635 778 ; C -1 ; WX 600 ; N Dcaron ; B 30 0 664 790 ; C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 655 454 ; C -1 ; WX 600 ; N Ntilde ; B 8 -12 730 759 ; C -1 ; WX 600 ; N otilde ; B 71 -15 643 636 ; C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 617 562 ; C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 636 562 ; C -1 ; WX 600 ; N Atilde ; B -9 0 669 759 ; C -1 ; WX 600 ; N Aogonek ; B -9 -199 632 562 ; C -1 ; WX 600 ; N Aring ; B -9 0 632 801 ; C -1 ; WX 600 ; N Otilde ; B 74 -18 669 759 ; C -1 ; WX 600 ; N zdotaccent ; B 81 0 614 638 ; C -1 ; WX 600 ; N Ecaron ; B 25 0 670 790 ; C -1 ; WX 600 ; N Iogonek ; B 77 -199 643 562 ; C -1 ; WX 600 ; N kcommaaccent ; B 33 -250 643 626 ; C -1 ; WX 600 ; N minus ; B 114 203 596 313 ; C -1 ; WX 600 ; N Icircumflex ; B 77 0 643 780 ; C -1 ; WX 600 ; N ncaron ; B 18 0 633 667 ; C -1 ; WX 600 ; N tcommaaccent ; B 118 -250 567 562 ; C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ; C -1 ; WX 600 ; N odieresis ; B 71 -15 622 638 ; C -1 ; WX 600 ; N udieresis ; B 70 -15 595 638 ; C -1 ; WX 600 ; N notequal ; B 30 -47 626 563 ; C -1 ; WX 600 ; N gcommaaccent ; B 40 -146 674 714 ; C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ; C -1 ; WX 600 ; N zcaron ; B 81 0 643 667 ; C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 615 454 ; C -1 ; WX 600 ; N onesuperior ; B 212 230 514 616 ; C -1 ; WX 600 ; N imacron ; B 77 0 575 585 ; C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/afm/Courier-Oblique.afm0000644000076500000240000003664712037547555020555 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 17:37:52 1997 Comment UniqueID 43051 Comment VMusage 16248 75829 FontName Courier-Oblique FullName Courier Oblique FamilyName Courier Weight Medium ItalicAngle -12 IsFixedPitch true CharacterSet ExtendedRoman FontBBox -27 -250 849 805 UnderlinePosition -100 UnderlineThickness 50 Version 003.000 Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. EncodingScheme AdobeStandardEncoding CapHeight 562 XHeight 426 Ascender 629 Descender -157 StdHW 51 StdVW 51 StartCharMetrics 315 C 32 ; WX 600 ; N space ; B 0 0 0 0 ; C 33 ; WX 600 ; N exclam ; B 243 -15 464 572 ; C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ; C 35 ; WX 600 ; N numbersign ; B 133 -32 596 639 ; C 36 ; WX 600 ; N dollar ; B 108 -126 596 662 ; C 37 ; WX 600 ; N percent ; B 134 -15 599 622 ; C 38 ; WX 600 ; N ampersand ; B 87 -15 580 543 ; C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ; C 40 ; WX 600 ; N parenleft ; B 313 -108 572 622 ; C 41 ; WX 600 ; N parenright ; B 137 -108 396 622 ; C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ; C 43 ; WX 600 ; N plus ; B 129 44 580 470 ; C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ; C 45 ; WX 600 ; N hyphen ; B 152 231 558 285 ; C 46 ; WX 600 ; N period ; B 238 -15 382 109 ; C 47 ; WX 600 ; N slash ; B 112 -80 604 629 ; C 48 ; WX 600 ; N zero ; B 154 -15 575 622 ; C 49 ; WX 600 ; N one ; B 98 0 515 622 ; C 50 ; WX 600 ; N two ; B 70 0 568 622 ; C 51 ; WX 600 ; N three ; B 82 -15 538 622 ; C 52 ; WX 600 ; N four ; B 108 0 541 622 ; C 53 ; WX 600 ; N five ; B 99 -15 589 607 ; C 54 ; WX 600 ; N six ; B 155 -15 629 622 ; C 55 ; WX 600 ; N seven ; B 182 0 612 607 ; C 56 ; WX 600 ; N eight ; B 132 -15 588 622 ; C 57 ; WX 600 ; N nine ; B 93 -15 574 622 ; C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ; C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ; C 60 ; WX 600 ; N less ; B 96 42 610 472 ; C 61 ; WX 600 ; N equal ; B 109 138 600 376 ; C 62 ; WX 600 ; N greater ; B 85 42 599 472 ; C 63 ; WX 600 ; N question ; B 222 -15 583 572 ; C 64 ; WX 600 ; N at ; B 127 -15 582 622 ; C 65 ; WX 600 ; N A ; B 3 0 607 562 ; C 66 ; WX 600 ; N B ; B 43 0 616 562 ; C 67 ; WX 600 ; N C ; B 93 -18 655 580 ; C 68 ; WX 600 ; N D ; B 43 0 645 562 ; C 69 ; WX 600 ; N E ; B 53 0 660 562 ; C 70 ; WX 600 ; N F ; B 53 0 660 562 ; C 71 ; WX 600 ; N G ; B 83 -18 645 580 ; C 72 ; WX 600 ; N H ; B 32 0 687 562 ; C 73 ; WX 600 ; N I ; B 96 0 623 562 ; C 74 ; WX 600 ; N J ; B 52 -18 685 562 ; C 75 ; WX 600 ; N K ; B 38 0 671 562 ; C 76 ; WX 600 ; N L ; B 47 0 607 562 ; C 77 ; WX 600 ; N M ; B 4 0 715 562 ; C 78 ; WX 600 ; N N ; B 7 -13 712 562 ; C 79 ; WX 600 ; N O ; B 94 -18 625 580 ; C 80 ; WX 600 ; N P ; B 79 0 644 562 ; C 81 ; WX 600 ; N Q ; B 95 -138 625 580 ; C 82 ; WX 600 ; N R ; B 38 0 598 562 ; C 83 ; WX 600 ; N S ; B 76 -20 650 580 ; C 84 ; WX 600 ; N T ; B 108 0 665 562 ; C 85 ; WX 600 ; N U ; B 125 -18 702 562 ; C 86 ; WX 600 ; N V ; B 105 -13 723 562 ; C 87 ; WX 600 ; N W ; B 106 -13 722 562 ; C 88 ; WX 600 ; N X ; B 23 0 675 562 ; C 89 ; WX 600 ; N Y ; B 133 0 695 562 ; C 90 ; WX 600 ; N Z ; B 86 0 610 562 ; C 91 ; WX 600 ; N bracketleft ; B 246 -108 574 622 ; C 92 ; WX 600 ; N backslash ; B 249 -80 468 629 ; C 93 ; WX 600 ; N bracketright ; B 135 -108 463 622 ; C 94 ; WX 600 ; N asciicircum ; B 175 354 587 622 ; C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ; C 96 ; WX 600 ; N quoteleft ; B 343 328 457 562 ; C 97 ; WX 600 ; N a ; B 76 -15 569 441 ; C 98 ; WX 600 ; N b ; B 29 -15 625 629 ; C 99 ; WX 600 ; N c ; B 106 -15 608 441 ; C 100 ; WX 600 ; N d ; B 85 -15 640 629 ; C 101 ; WX 600 ; N e ; B 106 -15 598 441 ; C 102 ; WX 600 ; N f ; B 114 0 662 629 ; L i fi ; L l fl ; C 103 ; WX 600 ; N g ; B 61 -157 657 441 ; C 104 ; WX 600 ; N h ; B 33 0 592 629 ; C 105 ; WX 600 ; N i ; B 95 0 515 657 ; C 106 ; WX 600 ; N j ; B 52 -157 550 657 ; C 107 ; WX 600 ; N k ; B 58 0 633 629 ; C 108 ; WX 600 ; N l ; B 95 0 515 629 ; C 109 ; WX 600 ; N m ; B -5 0 615 441 ; C 110 ; WX 600 ; N n ; B 26 0 585 441 ; C 111 ; WX 600 ; N o ; B 102 -15 588 441 ; C 112 ; WX 600 ; N p ; B -24 -157 605 441 ; C 113 ; WX 600 ; N q ; B 85 -157 682 441 ; C 114 ; WX 600 ; N r ; B 60 0 636 441 ; C 115 ; WX 600 ; N s ; B 78 -15 584 441 ; C 116 ; WX 600 ; N t ; B 167 -15 561 561 ; C 117 ; WX 600 ; N u ; B 101 -15 572 426 ; C 118 ; WX 600 ; N v ; B 90 -10 681 426 ; C 119 ; WX 600 ; N w ; B 76 -10 695 426 ; C 120 ; WX 600 ; N x ; B 20 0 655 426 ; C 121 ; WX 600 ; N y ; B -4 -157 683 426 ; C 122 ; WX 600 ; N z ; B 99 0 593 426 ; C 123 ; WX 600 ; N braceleft ; B 233 -108 569 622 ; C 124 ; WX 600 ; N bar ; B 222 -250 485 750 ; C 125 ; WX 600 ; N braceright ; B 140 -108 477 622 ; C 126 ; WX 600 ; N asciitilde ; B 116 197 600 320 ; C 161 ; WX 600 ; N exclamdown ; B 225 -157 445 430 ; C 162 ; WX 600 ; N cent ; B 151 -49 588 614 ; C 163 ; WX 600 ; N sterling ; B 124 -21 621 611 ; C 164 ; WX 600 ; N fraction ; B 84 -57 646 665 ; C 165 ; WX 600 ; N yen ; B 120 0 693 562 ; C 166 ; WX 600 ; N florin ; B -26 -143 671 622 ; C 167 ; WX 600 ; N section ; B 104 -78 590 580 ; C 168 ; WX 600 ; N currency ; B 94 58 628 506 ; C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ; C 170 ; WX 600 ; N quotedblleft ; B 262 328 541 562 ; C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ; C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ; C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ; C 174 ; WX 600 ; N fi ; B 3 0 619 629 ; C 175 ; WX 600 ; N fl ; B 3 0 619 629 ; C 177 ; WX 600 ; N endash ; B 124 231 586 285 ; C 178 ; WX 600 ; N dagger ; B 217 -78 546 580 ; C 179 ; WX 600 ; N daggerdbl ; B 163 -78 546 580 ; C 180 ; WX 600 ; N periodcentered ; B 275 189 434 327 ; C 182 ; WX 600 ; N paragraph ; B 100 -78 630 562 ; C 183 ; WX 600 ; N bullet ; B 224 130 485 383 ; C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ; C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ; C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ; C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ; C 188 ; WX 600 ; N ellipsis ; B 46 -15 575 111 ; C 189 ; WX 600 ; N perthousand ; B 59 -15 627 622 ; C 191 ; WX 600 ; N questiondown ; B 105 -157 466 430 ; C 193 ; WX 600 ; N grave ; B 294 497 484 672 ; C 194 ; WX 600 ; N acute ; B 348 497 612 672 ; C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ; C 196 ; WX 600 ; N tilde ; B 212 489 629 606 ; C 197 ; WX 600 ; N macron ; B 232 525 600 565 ; C 198 ; WX 600 ; N breve ; B 279 501 576 609 ; C 199 ; WX 600 ; N dotaccent ; B 373 537 478 640 ; C 200 ; WX 600 ; N dieresis ; B 272 537 579 640 ; C 202 ; WX 600 ; N ring ; B 332 463 500 627 ; C 203 ; WX 600 ; N cedilla ; B 197 -151 344 10 ; C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ; C 206 ; WX 600 ; N ogonek ; B 189 -172 377 4 ; C 207 ; WX 600 ; N caron ; B 262 492 614 669 ; C 208 ; WX 600 ; N emdash ; B 49 231 661 285 ; C 225 ; WX 600 ; N AE ; B 3 0 655 562 ; C 227 ; WX 600 ; N ordfeminine ; B 209 249 512 580 ; C 232 ; WX 600 ; N Lslash ; B 47 0 607 562 ; C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ; C 234 ; WX 600 ; N OE ; B 59 0 672 562 ; C 235 ; WX 600 ; N ordmasculine ; B 210 249 535 580 ; C 241 ; WX 600 ; N ae ; B 41 -15 626 441 ; C 245 ; WX 600 ; N dotlessi ; B 95 0 515 426 ; C 248 ; WX 600 ; N lslash ; B 95 0 587 629 ; C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ; C 250 ; WX 600 ; N oe ; B 54 -15 615 441 ; C 251 ; WX 600 ; N germandbls ; B 48 -15 617 629 ; C -1 ; WX 600 ; N Idieresis ; B 96 0 623 753 ; C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ; C -1 ; WX 600 ; N abreve ; B 76 -15 576 609 ; C -1 ; WX 600 ; N uhungarumlaut ; B 101 -15 723 672 ; C -1 ; WX 600 ; N ecaron ; B 106 -15 614 669 ; C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 753 ; C -1 ; WX 600 ; N divide ; B 136 48 573 467 ; C -1 ; WX 600 ; N Yacute ; B 133 0 695 805 ; C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 787 ; C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ; C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 787 ; C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ; C -1 ; WX 600 ; N scommaaccent ; B 78 -250 584 441 ; C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ; C -1 ; WX 600 ; N Uring ; B 125 -18 702 760 ; C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 753 ; C -1 ; WX 600 ; N aogonek ; B 76 -172 569 441 ; C -1 ; WX 600 ; N Uacute ; B 125 -18 702 805 ; C -1 ; WX 600 ; N uogonek ; B 101 -172 572 426 ; C -1 ; WX 600 ; N Edieresis ; B 53 0 660 753 ; C -1 ; WX 600 ; N Dcroat ; B 43 0 645 562 ; C -1 ; WX 600 ; N commaaccent ; B 145 -250 323 -58 ; C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ; C -1 ; WX 600 ; N Emacron ; B 53 0 660 698 ; C -1 ; WX 600 ; N ccaron ; B 106 -15 614 669 ; C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ; C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 712 562 ; C -1 ; WX 600 ; N lacute ; B 95 0 640 805 ; C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ; C -1 ; WX 600 ; N Tcommaaccent ; B 108 -250 665 562 ; C -1 ; WX 600 ; N Cacute ; B 93 -18 655 805 ; C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ; C -1 ; WX 600 ; N Edotaccent ; B 53 0 660 753 ; C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ; C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ; C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ; C -1 ; WX 600 ; N lozenge ; B 94 0 519 706 ; C -1 ; WX 600 ; N Rcaron ; B 38 0 642 802 ; C -1 ; WX 600 ; N Gcommaaccent ; B 83 -250 645 580 ; C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ; C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ; C -1 ; WX 600 ; N Amacron ; B 3 0 607 698 ; C -1 ; WX 600 ; N rcaron ; B 60 0 636 669 ; C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ; C -1 ; WX 600 ; N Zdotaccent ; B 86 0 610 753 ; C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ; C -1 ; WX 600 ; N Omacron ; B 94 -18 628 698 ; C -1 ; WX 600 ; N Racute ; B 38 0 670 805 ; C -1 ; WX 600 ; N Sacute ; B 76 -20 650 805 ; C -1 ; WX 600 ; N dcaron ; B 85 -15 849 629 ; C -1 ; WX 600 ; N Umacron ; B 125 -18 702 698 ; C -1 ; WX 600 ; N uring ; B 101 -15 572 627 ; C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ; C -1 ; WX 600 ; N Ograve ; B 94 -18 625 805 ; C -1 ; WX 600 ; N Agrave ; B 3 0 607 805 ; C -1 ; WX 600 ; N Abreve ; B 3 0 607 732 ; C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ; C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ; C -1 ; WX 600 ; N Tcaron ; B 108 0 665 802 ; C -1 ; WX 600 ; N partialdiff ; B 45 -38 546 710 ; C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 620 ; C -1 ; WX 600 ; N Nacute ; B 7 -13 712 805 ; C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ; C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 787 ; C -1 ; WX 600 ; N adieresis ; B 76 -15 575 620 ; C -1 ; WX 600 ; N edieresis ; B 106 -15 598 620 ; C -1 ; WX 600 ; N cacute ; B 106 -15 612 672 ; C -1 ; WX 600 ; N nacute ; B 26 0 602 672 ; C -1 ; WX 600 ; N umacron ; B 101 -15 600 565 ; C -1 ; WX 600 ; N Ncaron ; B 7 -13 712 802 ; C -1 ; WX 600 ; N Iacute ; B 96 0 640 805 ; C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ; C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ; C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ; C -1 ; WX 600 ; N Gbreve ; B 83 -18 645 732 ; C -1 ; WX 600 ; N Idotaccent ; B 96 0 623 753 ; C -1 ; WX 600 ; N summation ; B 15 -10 670 706 ; C -1 ; WX 600 ; N Egrave ; B 53 0 660 805 ; C -1 ; WX 600 ; N racute ; B 60 0 636 672 ; C -1 ; WX 600 ; N omacron ; B 102 -15 600 565 ; C -1 ; WX 600 ; N Zacute ; B 86 0 670 805 ; C -1 ; WX 600 ; N Zcaron ; B 86 0 642 802 ; C -1 ; WX 600 ; N greaterequal ; B 98 0 594 710 ; C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ; C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ; C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 515 629 ; C -1 ; WX 600 ; N tcaron ; B 167 -15 587 717 ; C -1 ; WX 600 ; N eogonek ; B 106 -172 598 441 ; C -1 ; WX 600 ; N Uogonek ; B 124 -172 702 562 ; C -1 ; WX 600 ; N Aacute ; B 3 0 660 805 ; C -1 ; WX 600 ; N Adieresis ; B 3 0 607 753 ; C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ; C -1 ; WX 600 ; N zacute ; B 99 0 612 672 ; C -1 ; WX 600 ; N iogonek ; B 95 -172 515 657 ; C -1 ; WX 600 ; N Oacute ; B 94 -18 640 805 ; C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ; C -1 ; WX 600 ; N amacron ; B 76 -15 600 565 ; C -1 ; WX 600 ; N sacute ; B 78 -15 612 672 ; C -1 ; WX 600 ; N idieresis ; B 95 0 545 620 ; C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 787 ; C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 805 ; C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ; C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ; C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ; C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 753 ; C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ; C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ; C -1 ; WX 600 ; N ohungarumlaut ; B 102 -15 723 672 ; C -1 ; WX 600 ; N Eogonek ; B 53 -172 660 562 ; C -1 ; WX 600 ; N dcroat ; B 85 -15 704 629 ; C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ; C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ; C -1 ; WX 600 ; N lcaron ; B 95 0 667 629 ; C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 671 562 ; C -1 ; WX 600 ; N Lacute ; B 47 0 607 805 ; C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ; C -1 ; WX 600 ; N edotaccent ; B 106 -15 598 620 ; C -1 ; WX 600 ; N Igrave ; B 96 0 623 805 ; C -1 ; WX 600 ; N Imacron ; B 96 0 628 698 ; C -1 ; WX 600 ; N Lcaron ; B 47 0 632 562 ; C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ; C -1 ; WX 600 ; N lessequal ; B 98 0 645 710 ; C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ; C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ; C -1 ; WX 600 ; N Uhungarumlaut ; B 125 -18 761 805 ; C -1 ; WX 600 ; N Eacute ; B 53 0 670 805 ; C -1 ; WX 600 ; N emacron ; B 106 -15 600 565 ; C -1 ; WX 600 ; N gbreve ; B 61 -157 657 609 ; C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ; C -1 ; WX 600 ; N Scaron ; B 76 -20 672 802 ; C -1 ; WX 600 ; N Scommaaccent ; B 76 -250 650 580 ; C -1 ; WX 600 ; N Ohungarumlaut ; B 94 -18 751 805 ; C -1 ; WX 600 ; N degree ; B 214 269 576 622 ; C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ; C -1 ; WX 600 ; N Ccaron ; B 93 -18 672 802 ; C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ; C -1 ; WX 600 ; N radical ; B 85 -15 765 792 ; C -1 ; WX 600 ; N Dcaron ; B 43 0 645 802 ; C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 636 441 ; C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 729 ; C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ; C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 598 562 ; C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 607 562 ; C -1 ; WX 600 ; N Atilde ; B 3 0 655 729 ; C -1 ; WX 600 ; N Aogonek ; B 3 -172 607 562 ; C -1 ; WX 600 ; N Aring ; B 3 0 607 750 ; C -1 ; WX 600 ; N Otilde ; B 94 -18 655 729 ; C -1 ; WX 600 ; N zdotaccent ; B 99 0 593 620 ; C -1 ; WX 600 ; N Ecaron ; B 53 0 660 802 ; C -1 ; WX 600 ; N Iogonek ; B 96 -172 623 562 ; C -1 ; WX 600 ; N kcommaaccent ; B 58 -250 633 629 ; C -1 ; WX 600 ; N minus ; B 129 232 580 283 ; C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 787 ; C -1 ; WX 600 ; N ncaron ; B 26 0 614 669 ; C -1 ; WX 600 ; N tcommaaccent ; B 165 -250 561 561 ; C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ; C -1 ; WX 600 ; N odieresis ; B 102 -15 588 620 ; C -1 ; WX 600 ; N udieresis ; B 101 -15 575 620 ; C -1 ; WX 600 ; N notequal ; B 43 -16 621 529 ; C -1 ; WX 600 ; N gcommaaccent ; B 61 -157 657 708 ; C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ; C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ; C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 585 441 ; C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ; C -1 ; WX 600 ; N imacron ; B 95 0 543 565 ; C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/afm/Courier.afm0000644000076500000240000003647512037547555017156 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 17:27:09 1997 Comment UniqueID 43050 Comment VMusage 39754 50779 FontName Courier FullName Courier FamilyName Courier Weight Medium ItalicAngle 0 IsFixedPitch true CharacterSet ExtendedRoman FontBBox -23 -250 715 805 UnderlinePosition -100 UnderlineThickness 50 Version 003.000 Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. EncodingScheme AdobeStandardEncoding CapHeight 562 XHeight 426 Ascender 629 Descender -157 StdHW 51 StdVW 51 StartCharMetrics 315 C 32 ; WX 600 ; N space ; B 0 0 0 0 ; C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ; C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ; C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ; C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ; C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ; C 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ; C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ; C 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ; C 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ; C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ; C 43 ; WX 600 ; N plus ; B 80 44 520 470 ; C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ; C 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ; C 46 ; WX 600 ; N period ; B 229 -15 371 109 ; C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ; C 48 ; WX 600 ; N zero ; B 106 -15 494 622 ; C 49 ; WX 600 ; N one ; B 96 0 505 622 ; C 50 ; WX 600 ; N two ; B 70 0 471 622 ; C 51 ; WX 600 ; N three ; B 75 -15 466 622 ; C 52 ; WX 600 ; N four ; B 78 0 500 622 ; C 53 ; WX 600 ; N five ; B 92 -15 497 607 ; C 54 ; WX 600 ; N six ; B 111 -15 497 622 ; C 55 ; WX 600 ; N seven ; B 82 0 483 607 ; C 56 ; WX 600 ; N eight ; B 102 -15 498 622 ; C 57 ; WX 600 ; N nine ; B 96 -15 489 622 ; C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ; C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ; C 60 ; WX 600 ; N less ; B 41 42 519 472 ; C 61 ; WX 600 ; N equal ; B 80 138 520 376 ; C 62 ; WX 600 ; N greater ; B 66 42 544 472 ; C 63 ; WX 600 ; N question ; B 129 -15 492 572 ; C 64 ; WX 600 ; N at ; B 77 -15 533 622 ; C 65 ; WX 600 ; N A ; B 3 0 597 562 ; C 66 ; WX 600 ; N B ; B 43 0 559 562 ; C 67 ; WX 600 ; N C ; B 41 -18 540 580 ; C 68 ; WX 600 ; N D ; B 43 0 574 562 ; C 69 ; WX 600 ; N E ; B 53 0 550 562 ; C 70 ; WX 600 ; N F ; B 53 0 545 562 ; C 71 ; WX 600 ; N G ; B 31 -18 575 580 ; C 72 ; WX 600 ; N H ; B 32 0 568 562 ; C 73 ; WX 600 ; N I ; B 96 0 504 562 ; C 74 ; WX 600 ; N J ; B 34 -18 566 562 ; C 75 ; WX 600 ; N K ; B 38 0 582 562 ; C 76 ; WX 600 ; N L ; B 47 0 554 562 ; C 77 ; WX 600 ; N M ; B 4 0 596 562 ; C 78 ; WX 600 ; N N ; B 7 -13 593 562 ; C 79 ; WX 600 ; N O ; B 43 -18 557 580 ; C 80 ; WX 600 ; N P ; B 79 0 558 562 ; C 81 ; WX 600 ; N Q ; B 43 -138 557 580 ; C 82 ; WX 600 ; N R ; B 38 0 588 562 ; C 83 ; WX 600 ; N S ; B 72 -20 529 580 ; C 84 ; WX 600 ; N T ; B 38 0 563 562 ; C 85 ; WX 600 ; N U ; B 17 -18 583 562 ; C 86 ; WX 600 ; N V ; B -4 -13 604 562 ; C 87 ; WX 600 ; N W ; B -3 -13 603 562 ; C 88 ; WX 600 ; N X ; B 23 0 577 562 ; C 89 ; WX 600 ; N Y ; B 24 0 576 562 ; C 90 ; WX 600 ; N Z ; B 86 0 514 562 ; C 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ; C 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ; C 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ; C 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ; C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ; C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ; C 97 ; WX 600 ; N a ; B 53 -15 559 441 ; C 98 ; WX 600 ; N b ; B 14 -15 575 629 ; C 99 ; WX 600 ; N c ; B 66 -15 529 441 ; C 100 ; WX 600 ; N d ; B 45 -15 591 629 ; C 101 ; WX 600 ; N e ; B 66 -15 548 441 ; C 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ; C 103 ; WX 600 ; N g ; B 45 -157 566 441 ; C 104 ; WX 600 ; N h ; B 18 0 582 629 ; C 105 ; WX 600 ; N i ; B 95 0 505 657 ; C 106 ; WX 600 ; N j ; B 82 -157 410 657 ; C 107 ; WX 600 ; N k ; B 43 0 580 629 ; C 108 ; WX 600 ; N l ; B 95 0 505 629 ; C 109 ; WX 600 ; N m ; B -5 0 605 441 ; C 110 ; WX 600 ; N n ; B 26 0 575 441 ; C 111 ; WX 600 ; N o ; B 62 -15 538 441 ; C 112 ; WX 600 ; N p ; B 9 -157 555 441 ; C 113 ; WX 600 ; N q ; B 45 -157 591 441 ; C 114 ; WX 600 ; N r ; B 60 0 559 441 ; C 115 ; WX 600 ; N s ; B 80 -15 513 441 ; C 116 ; WX 600 ; N t ; B 87 -15 530 561 ; C 117 ; WX 600 ; N u ; B 21 -15 562 426 ; C 118 ; WX 600 ; N v ; B 10 -10 590 426 ; C 119 ; WX 600 ; N w ; B -4 -10 604 426 ; C 120 ; WX 600 ; N x ; B 20 0 580 426 ; C 121 ; WX 600 ; N y ; B 7 -157 592 426 ; C 122 ; WX 600 ; N z ; B 99 0 502 426 ; C 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ; C 124 ; WX 600 ; N bar ; B 275 -250 326 750 ; C 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ; C 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ; C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ; C 162 ; WX 600 ; N cent ; B 96 -49 500 614 ; C 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ; C 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ; C 165 ; WX 600 ; N yen ; B 26 0 574 562 ; C 166 ; WX 600 ; N florin ; B 4 -143 539 622 ; C 167 ; WX 600 ; N section ; B 113 -78 488 580 ; C 168 ; WX 600 ; N currency ; B 73 58 527 506 ; C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ; C 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ; C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ; C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ; C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ; C 174 ; WX 600 ; N fi ; B 3 0 597 629 ; C 175 ; WX 600 ; N fl ; B 3 0 597 629 ; C 177 ; WX 600 ; N endash ; B 75 231 525 285 ; C 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ; C 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ; C 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ; C 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ; C 183 ; WX 600 ; N bullet ; B 172 130 428 383 ; C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ; C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ; C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ; C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ; C 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ; C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ; C 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ; C 193 ; WX 600 ; N grave ; B 151 497 378 672 ; C 194 ; WX 600 ; N acute ; B 242 497 469 672 ; C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ; C 196 ; WX 600 ; N tilde ; B 105 489 503 606 ; C 197 ; WX 600 ; N macron ; B 120 525 480 565 ; C 198 ; WX 600 ; N breve ; B 153 501 447 609 ; C 199 ; WX 600 ; N dotaccent ; B 249 537 352 640 ; C 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ; C 202 ; WX 600 ; N ring ; B 218 463 382 627 ; C 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ; C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ; C 206 ; WX 600 ; N ogonek ; B 211 -172 407 4 ; C 207 ; WX 600 ; N caron ; B 124 492 476 669 ; C 208 ; WX 600 ; N emdash ; B 0 231 600 285 ; C 225 ; WX 600 ; N AE ; B 3 0 550 562 ; C 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ; C 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ; C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ; C 234 ; WX 600 ; N OE ; B 7 0 567 562 ; C 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ; C 241 ; WX 600 ; N ae ; B 19 -15 570 441 ; C 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ; C 248 ; WX 600 ; N lslash ; B 95 0 505 629 ; C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ; C 250 ; WX 600 ; N oe ; B 19 -15 559 441 ; C 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ; C -1 ; WX 600 ; N Idieresis ; B 96 0 504 753 ; C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ; C -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ; C -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ; C -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ; C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ; C -1 ; WX 600 ; N divide ; B 87 48 513 467 ; C -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ; C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ; C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ; C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ; C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ; C -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ; C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ; C -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ; C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ; C -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ; C -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ; C -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ; C -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ; C -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ; C -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ; C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ; C -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ; C -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ; C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ; C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ; C -1 ; WX 600 ; N lacute ; B 95 0 505 805 ; C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ; C -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ; C -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ; C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ; C -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ; C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ; C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ; C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ; C -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ; C -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ; C -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ; C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ; C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ; C -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ; C -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ; C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ; C -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ; C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ; C -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ; C -1 ; WX 600 ; N Racute ; B 38 0 588 805 ; C -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ; C -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ; C -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ; C -1 ; WX 600 ; N uring ; B 21 -15 562 627 ; C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ; C -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ; C -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ; C -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ; C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ; C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ; C -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ; C -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ; C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ; C -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ; C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ; C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ; C -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ; C -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ; C -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ; C -1 ; WX 600 ; N nacute ; B 26 0 575 672 ; C -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ; C -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ; C -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ; C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ; C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ; C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ; C -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ; C -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ; C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ; C -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ; C -1 ; WX 600 ; N racute ; B 60 0 559 672 ; C -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ; C -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ; C -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ; C -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ; C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ; C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ; C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ; C -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ; C -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ; C -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ; C -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ; C -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ; C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ; C -1 ; WX 600 ; N zacute ; B 99 0 502 672 ; C -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ; C -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ; C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ; C -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ; C -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ; C -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ; C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ; C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ; C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ; C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ; C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ; C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ; C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ; C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ; C -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ; C -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ; C -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ; C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ; C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ; C -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ; C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ; C -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ; C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ; C -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ; C -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ; C -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ; C -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ; C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ; C -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ; C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ; C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ; C -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ; C -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ; C -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ; C -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ; C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ; C -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ; C -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ; C -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ; C -1 ; WX 600 ; N degree ; B 123 269 477 622 ; C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ; C -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ; C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ; C -1 ; WX 600 ; N radical ; B 3 -15 597 792 ; C -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ; C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ; C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ; C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ; C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ; C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ; C -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ; C -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ; C -1 ; WX 600 ; N Aring ; B 3 0 597 750 ; C -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ; C -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ; C -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ; C -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ; C -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ; C -1 ; WX 600 ; N minus ; B 80 232 520 283 ; C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ; C -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ; C -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ; C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ; C -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ; C -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ; C -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ; C -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ; C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ; C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ; C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ; C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ; C -1 ; WX 600 ; N imacron ; B 95 0 505 565 ; C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/afm/Helvetica-Bold.afm0000644000076500000240000021464012037547555020320 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:43:52 1997 Comment UniqueID 43052 Comment VMusage 37169 48194 FontName Helvetica-Bold FullName Helvetica Bold FamilyName Helvetica Weight Bold ItalicAngle 0 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -170 -228 1003 962 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 718 XHeight 532 Ascender 718 Descender -207 StdHW 118 StdVW 140 StartCharMetrics 315 C 32 ; WX 278 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 90 0 244 718 ; C 34 ; WX 474 ; N quotedbl ; B 98 447 376 718 ; C 35 ; WX 556 ; N numbersign ; B 18 0 538 698 ; C 36 ; WX 556 ; N dollar ; B 30 -115 523 775 ; C 37 ; WX 889 ; N percent ; B 28 -19 861 710 ; C 38 ; WX 722 ; N ampersand ; B 54 -19 701 718 ; C 39 ; WX 278 ; N quoteright ; B 69 445 209 718 ; C 40 ; WX 333 ; N parenleft ; B 35 -208 314 734 ; C 41 ; WX 333 ; N parenright ; B 19 -208 298 734 ; C 42 ; WX 389 ; N asterisk ; B 27 387 362 718 ; C 43 ; WX 584 ; N plus ; B 40 0 544 506 ; C 44 ; WX 278 ; N comma ; B 64 -168 214 146 ; C 45 ; WX 333 ; N hyphen ; B 27 215 306 345 ; C 46 ; WX 278 ; N period ; B 64 0 214 146 ; C 47 ; WX 278 ; N slash ; B -33 -19 311 737 ; C 48 ; WX 556 ; N zero ; B 32 -19 524 710 ; C 49 ; WX 556 ; N one ; B 69 0 378 710 ; C 50 ; WX 556 ; N two ; B 26 0 511 710 ; C 51 ; WX 556 ; N three ; B 27 -19 516 710 ; C 52 ; WX 556 ; N four ; B 27 0 526 710 ; C 53 ; WX 556 ; N five ; B 27 -19 516 698 ; C 54 ; WX 556 ; N six ; B 31 -19 520 710 ; C 55 ; WX 556 ; N seven ; B 25 0 528 698 ; C 56 ; WX 556 ; N eight ; B 32 -19 524 710 ; C 57 ; WX 556 ; N nine ; B 30 -19 522 710 ; C 58 ; WX 333 ; N colon ; B 92 0 242 512 ; C 59 ; WX 333 ; N semicolon ; B 92 -168 242 512 ; C 60 ; WX 584 ; N less ; B 38 -8 546 514 ; C 61 ; WX 584 ; N equal ; B 40 87 544 419 ; C 62 ; WX 584 ; N greater ; B 38 -8 546 514 ; C 63 ; WX 611 ; N question ; B 60 0 556 727 ; C 64 ; WX 975 ; N at ; B 118 -19 856 737 ; C 65 ; WX 722 ; N A ; B 20 0 702 718 ; C 66 ; WX 722 ; N B ; B 76 0 669 718 ; C 67 ; WX 722 ; N C ; B 44 -19 684 737 ; C 68 ; WX 722 ; N D ; B 76 0 685 718 ; C 69 ; WX 667 ; N E ; B 76 0 621 718 ; C 70 ; WX 611 ; N F ; B 76 0 587 718 ; C 71 ; WX 778 ; N G ; B 44 -19 713 737 ; C 72 ; WX 722 ; N H ; B 71 0 651 718 ; C 73 ; WX 278 ; N I ; B 64 0 214 718 ; C 74 ; WX 556 ; N J ; B 22 -18 484 718 ; C 75 ; WX 722 ; N K ; B 87 0 722 718 ; C 76 ; WX 611 ; N L ; B 76 0 583 718 ; C 77 ; WX 833 ; N M ; B 69 0 765 718 ; C 78 ; WX 722 ; N N ; B 69 0 654 718 ; C 79 ; WX 778 ; N O ; B 44 -19 734 737 ; C 80 ; WX 667 ; N P ; B 76 0 627 718 ; C 81 ; WX 778 ; N Q ; B 44 -52 737 737 ; C 82 ; WX 722 ; N R ; B 76 0 677 718 ; C 83 ; WX 667 ; N S ; B 39 -19 629 737 ; C 84 ; WX 611 ; N T ; B 14 0 598 718 ; C 85 ; WX 722 ; N U ; B 72 -19 651 718 ; C 86 ; WX 667 ; N V ; B 19 0 648 718 ; C 87 ; WX 944 ; N W ; B 16 0 929 718 ; C 88 ; WX 667 ; N X ; B 14 0 653 718 ; C 89 ; WX 667 ; N Y ; B 15 0 653 718 ; C 90 ; WX 611 ; N Z ; B 25 0 586 718 ; C 91 ; WX 333 ; N bracketleft ; B 63 -196 309 722 ; C 92 ; WX 278 ; N backslash ; B -33 -19 311 737 ; C 93 ; WX 333 ; N bracketright ; B 24 -196 270 722 ; C 94 ; WX 584 ; N asciicircum ; B 62 323 522 698 ; C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ; C 96 ; WX 278 ; N quoteleft ; B 69 454 209 727 ; C 97 ; WX 556 ; N a ; B 29 -14 527 546 ; C 98 ; WX 611 ; N b ; B 61 -14 578 718 ; C 99 ; WX 556 ; N c ; B 34 -14 524 546 ; C 100 ; WX 611 ; N d ; B 34 -14 551 718 ; C 101 ; WX 556 ; N e ; B 23 -14 528 546 ; C 102 ; WX 333 ; N f ; B 10 0 318 727 ; L i fi ; L l fl ; C 103 ; WX 611 ; N g ; B 40 -217 553 546 ; C 104 ; WX 611 ; N h ; B 65 0 546 718 ; C 105 ; WX 278 ; N i ; B 69 0 209 725 ; C 106 ; WX 278 ; N j ; B 3 -214 209 725 ; C 107 ; WX 556 ; N k ; B 69 0 562 718 ; C 108 ; WX 278 ; N l ; B 69 0 209 718 ; C 109 ; WX 889 ; N m ; B 64 0 826 546 ; C 110 ; WX 611 ; N n ; B 65 0 546 546 ; C 111 ; WX 611 ; N o ; B 34 -14 578 546 ; C 112 ; WX 611 ; N p ; B 62 -207 578 546 ; C 113 ; WX 611 ; N q ; B 34 -207 552 546 ; C 114 ; WX 389 ; N r ; B 64 0 373 546 ; C 115 ; WX 556 ; N s ; B 30 -14 519 546 ; C 116 ; WX 333 ; N t ; B 10 -6 309 676 ; C 117 ; WX 611 ; N u ; B 66 -14 545 532 ; C 118 ; WX 556 ; N v ; B 13 0 543 532 ; C 119 ; WX 778 ; N w ; B 10 0 769 532 ; C 120 ; WX 556 ; N x ; B 15 0 541 532 ; C 121 ; WX 556 ; N y ; B 10 -214 539 532 ; C 122 ; WX 500 ; N z ; B 20 0 480 532 ; C 123 ; WX 389 ; N braceleft ; B 48 -196 365 722 ; C 124 ; WX 280 ; N bar ; B 84 -225 196 775 ; C 125 ; WX 389 ; N braceright ; B 24 -196 341 722 ; C 126 ; WX 584 ; N asciitilde ; B 61 163 523 343 ; C 161 ; WX 333 ; N exclamdown ; B 90 -186 244 532 ; C 162 ; WX 556 ; N cent ; B 34 -118 524 628 ; C 163 ; WX 556 ; N sterling ; B 28 -16 541 718 ; C 164 ; WX 167 ; N fraction ; B -170 -19 336 710 ; C 165 ; WX 556 ; N yen ; B -9 0 565 698 ; C 166 ; WX 556 ; N florin ; B -10 -210 516 737 ; C 167 ; WX 556 ; N section ; B 34 -184 522 727 ; C 168 ; WX 556 ; N currency ; B -3 76 559 636 ; C 169 ; WX 238 ; N quotesingle ; B 70 447 168 718 ; C 170 ; WX 500 ; N quotedblleft ; B 64 454 436 727 ; C 171 ; WX 556 ; N guillemotleft ; B 88 76 468 484 ; C 172 ; WX 333 ; N guilsinglleft ; B 83 76 250 484 ; C 173 ; WX 333 ; N guilsinglright ; B 83 76 250 484 ; C 174 ; WX 611 ; N fi ; B 10 0 542 727 ; C 175 ; WX 611 ; N fl ; B 10 0 542 727 ; C 177 ; WX 556 ; N endash ; B 0 227 556 333 ; C 178 ; WX 556 ; N dagger ; B 36 -171 520 718 ; C 179 ; WX 556 ; N daggerdbl ; B 36 -171 520 718 ; C 180 ; WX 278 ; N periodcentered ; B 58 172 220 334 ; C 182 ; WX 556 ; N paragraph ; B -8 -191 539 700 ; C 183 ; WX 350 ; N bullet ; B 10 194 340 524 ; C 184 ; WX 278 ; N quotesinglbase ; B 69 -146 209 127 ; C 185 ; WX 500 ; N quotedblbase ; B 64 -146 436 127 ; C 186 ; WX 500 ; N quotedblright ; B 64 445 436 718 ; C 187 ; WX 556 ; N guillemotright ; B 88 76 468 484 ; C 188 ; WX 1000 ; N ellipsis ; B 92 0 908 146 ; C 189 ; WX 1000 ; N perthousand ; B -3 -19 1003 710 ; C 191 ; WX 611 ; N questiondown ; B 55 -195 551 532 ; C 193 ; WX 333 ; N grave ; B -23 604 225 750 ; C 194 ; WX 333 ; N acute ; B 108 604 356 750 ; C 195 ; WX 333 ; N circumflex ; B -10 604 343 750 ; C 196 ; WX 333 ; N tilde ; B -17 610 350 737 ; C 197 ; WX 333 ; N macron ; B -6 604 339 678 ; C 198 ; WX 333 ; N breve ; B -2 604 335 750 ; C 199 ; WX 333 ; N dotaccent ; B 104 614 230 729 ; C 200 ; WX 333 ; N dieresis ; B 6 614 327 729 ; C 202 ; WX 333 ; N ring ; B 59 568 275 776 ; C 203 ; WX 333 ; N cedilla ; B 6 -228 245 0 ; C 205 ; WX 333 ; N hungarumlaut ; B 9 604 486 750 ; C 206 ; WX 333 ; N ogonek ; B 71 -228 304 0 ; C 207 ; WX 333 ; N caron ; B -10 604 343 750 ; C 208 ; WX 1000 ; N emdash ; B 0 227 1000 333 ; C 225 ; WX 1000 ; N AE ; B 5 0 954 718 ; C 227 ; WX 370 ; N ordfeminine ; B 22 401 347 737 ; C 232 ; WX 611 ; N Lslash ; B -20 0 583 718 ; C 233 ; WX 778 ; N Oslash ; B 33 -27 744 745 ; C 234 ; WX 1000 ; N OE ; B 37 -19 961 737 ; C 235 ; WX 365 ; N ordmasculine ; B 6 401 360 737 ; C 241 ; WX 889 ; N ae ; B 29 -14 858 546 ; C 245 ; WX 278 ; N dotlessi ; B 69 0 209 532 ; C 248 ; WX 278 ; N lslash ; B -18 0 296 718 ; C 249 ; WX 611 ; N oslash ; B 22 -29 589 560 ; C 250 ; WX 944 ; N oe ; B 34 -14 912 546 ; C 251 ; WX 611 ; N germandbls ; B 69 -14 579 731 ; C -1 ; WX 278 ; N Idieresis ; B -21 0 300 915 ; C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ; C -1 ; WX 556 ; N abreve ; B 29 -14 527 750 ; C -1 ; WX 611 ; N uhungarumlaut ; B 66 -14 625 750 ; C -1 ; WX 556 ; N ecaron ; B 23 -14 528 750 ; C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ; C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ; C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ; C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ; C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ; C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ; C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ; C -1 ; WX 556 ; N scommaaccent ; B 30 -228 519 546 ; C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ; C -1 ; WX 722 ; N Uring ; B 72 -19 651 962 ; C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ; C -1 ; WX 556 ; N aogonek ; B 29 -224 545 546 ; C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ; C -1 ; WX 611 ; N uogonek ; B 66 -228 545 532 ; C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ; C -1 ; WX 722 ; N Dcroat ; B -5 0 685 718 ; C -1 ; WX 250 ; N commaaccent ; B 64 -228 199 -50 ; C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ; C -1 ; WX 667 ; N Emacron ; B 76 0 621 864 ; C -1 ; WX 556 ; N ccaron ; B 34 -14 524 750 ; C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ; C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 654 718 ; C -1 ; WX 278 ; N lacute ; B 69 0 329 936 ; C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ; C -1 ; WX 611 ; N Tcommaaccent ; B 14 -228 598 718 ; C -1 ; WX 722 ; N Cacute ; B 44 -19 684 936 ; C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ; C -1 ; WX 667 ; N Edotaccent ; B 76 0 621 915 ; C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ; C -1 ; WX 556 ; N scedilla ; B 30 -228 519 546 ; C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ; C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ; C -1 ; WX 722 ; N Rcaron ; B 76 0 677 936 ; C -1 ; WX 778 ; N Gcommaaccent ; B 44 -228 713 737 ; C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ; C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ; C -1 ; WX 722 ; N Amacron ; B 20 0 702 864 ; C -1 ; WX 389 ; N rcaron ; B 18 0 373 750 ; C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ; C -1 ; WX 611 ; N Zdotaccent ; B 25 0 586 915 ; C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ; C -1 ; WX 778 ; N Omacron ; B 44 -19 734 864 ; C -1 ; WX 722 ; N Racute ; B 76 0 677 936 ; C -1 ; WX 667 ; N Sacute ; B 39 -19 629 936 ; C -1 ; WX 743 ; N dcaron ; B 34 -14 750 718 ; C -1 ; WX 722 ; N Umacron ; B 72 -19 651 864 ; C -1 ; WX 611 ; N uring ; B 66 -14 545 776 ; C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ; C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ; C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ; C -1 ; WX 722 ; N Abreve ; B 20 0 702 936 ; C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ; C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ; C -1 ; WX 611 ; N Tcaron ; B 14 0 598 936 ; C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ; C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ; C -1 ; WX 722 ; N Nacute ; B 69 0 654 936 ; C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ; C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ; C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ; C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ; C -1 ; WX 556 ; N cacute ; B 34 -14 524 750 ; C -1 ; WX 611 ; N nacute ; B 65 0 546 750 ; C -1 ; WX 611 ; N umacron ; B 66 -14 545 678 ; C -1 ; WX 722 ; N Ncaron ; B 69 0 654 936 ; C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ; C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ; C -1 ; WX 280 ; N brokenbar ; B 84 -150 196 700 ; C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ; C -1 ; WX 778 ; N Gbreve ; B 44 -19 713 936 ; C -1 ; WX 278 ; N Idotaccent ; B 64 0 214 915 ; C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ; C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ; C -1 ; WX 389 ; N racute ; B 64 0 384 750 ; C -1 ; WX 611 ; N omacron ; B 34 -14 578 678 ; C -1 ; WX 611 ; N Zacute ; B 25 0 586 936 ; C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ; C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ; C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ; C -1 ; WX 278 ; N lcommaaccent ; B 69 -228 213 718 ; C -1 ; WX 389 ; N tcaron ; B 10 -6 421 878 ; C -1 ; WX 556 ; N eogonek ; B 23 -228 528 546 ; C -1 ; WX 722 ; N Uogonek ; B 72 -228 651 718 ; C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ; C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ; C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ; C -1 ; WX 500 ; N zacute ; B 20 0 480 750 ; C -1 ; WX 278 ; N iogonek ; B 16 -224 249 725 ; C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ; C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ; C -1 ; WX 556 ; N amacron ; B 29 -14 527 678 ; C -1 ; WX 556 ; N sacute ; B 30 -14 519 750 ; C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ; C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ; C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ; C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ; C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ; C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ; C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ; C -1 ; WX 611 ; N ohungarumlaut ; B 34 -14 625 750 ; C -1 ; WX 667 ; N Eogonek ; B 76 -224 639 718 ; C -1 ; WX 611 ; N dcroat ; B 34 -14 650 718 ; C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ; C -1 ; WX 667 ; N Scedilla ; B 39 -228 629 737 ; C -1 ; WX 400 ; N lcaron ; B 69 0 408 718 ; C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 722 718 ; C -1 ; WX 611 ; N Lacute ; B 76 0 583 936 ; C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ; C -1 ; WX 556 ; N edotaccent ; B 23 -14 528 729 ; C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ; C -1 ; WX 278 ; N Imacron ; B -33 0 312 864 ; C -1 ; WX 611 ; N Lcaron ; B 76 0 583 718 ; C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ; C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ; C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ; C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 72 -19 681 936 ; C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ; C -1 ; WX 556 ; N emacron ; B 23 -14 528 678 ; C -1 ; WX 611 ; N gbreve ; B 40 -217 553 750 ; C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ; C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ; C -1 ; WX 667 ; N Scommaaccent ; B 39 -228 629 737 ; C -1 ; WX 778 ; N Ohungarumlaut ; B 44 -19 734 936 ; C -1 ; WX 400 ; N degree ; B 57 426 343 712 ; C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ; C -1 ; WX 722 ; N Ccaron ; B 44 -19 684 936 ; C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ; C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ; C -1 ; WX 722 ; N Dcaron ; B 76 0 685 936 ; C -1 ; WX 389 ; N rcommaaccent ; B 64 -228 373 546 ; C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ; C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ; C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 677 718 ; C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 583 718 ; C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ; C -1 ; WX 722 ; N Aogonek ; B 20 -224 742 718 ; C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ; C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ; C -1 ; WX 500 ; N zdotaccent ; B 20 0 480 729 ; C -1 ; WX 667 ; N Ecaron ; B 76 0 621 936 ; C -1 ; WX 278 ; N Iogonek ; B -11 -228 222 718 ; C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 562 718 ; C -1 ; WX 584 ; N minus ; B 40 197 544 309 ; C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ; C -1 ; WX 611 ; N ncaron ; B 65 0 546 750 ; C -1 ; WX 333 ; N tcommaaccent ; B 10 -228 309 676 ; C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ; C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ; C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ; C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ; C -1 ; WX 611 ; N gcommaaccent ; B 40 -217 553 850 ; C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ; C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ; C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 546 546 ; C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ; C -1 ; WX 278 ; N imacron ; B -8 0 285 678 ; C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2481 KPX A C -40 KPX A Cacute -40 KPX A Ccaron -40 KPX A Ccedilla -40 KPX A G -50 KPX A Gbreve -50 KPX A Gcommaaccent -50 KPX A O -40 KPX A Oacute -40 KPX A Ocircumflex -40 KPX A Odieresis -40 KPX A Ograve -40 KPX A Ohungarumlaut -40 KPX A Omacron -40 KPX A Oslash -40 KPX A Otilde -40 KPX A Q -40 KPX A T -90 KPX A Tcaron -90 KPX A Tcommaaccent -90 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -80 KPX A W -60 KPX A Y -110 KPX A Yacute -110 KPX A Ydieresis -110 KPX A u -30 KPX A uacute -30 KPX A ucircumflex -30 KPX A udieresis -30 KPX A ugrave -30 KPX A uhungarumlaut -30 KPX A umacron -30 KPX A uogonek -30 KPX A uring -30 KPX A v -40 KPX A w -30 KPX A y -30 KPX A yacute -30 KPX A ydieresis -30 KPX Aacute C -40 KPX Aacute Cacute -40 KPX Aacute Ccaron -40 KPX Aacute Ccedilla -40 KPX Aacute G -50 KPX Aacute Gbreve -50 KPX Aacute Gcommaaccent -50 KPX Aacute O -40 KPX Aacute Oacute -40 KPX Aacute Ocircumflex -40 KPX Aacute Odieresis -40 KPX Aacute Ograve -40 KPX Aacute Ohungarumlaut -40 KPX Aacute Omacron -40 KPX Aacute Oslash -40 KPX Aacute Otilde -40 KPX Aacute Q -40 KPX Aacute T -90 KPX Aacute Tcaron -90 KPX Aacute Tcommaaccent -90 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -80 KPX Aacute W -60 KPX Aacute Y -110 KPX Aacute Yacute -110 KPX Aacute Ydieresis -110 KPX Aacute u -30 KPX Aacute uacute -30 KPX Aacute ucircumflex -30 KPX Aacute udieresis -30 KPX Aacute ugrave -30 KPX Aacute uhungarumlaut -30 KPX Aacute umacron -30 KPX Aacute uogonek -30 KPX Aacute uring -30 KPX Aacute v -40 KPX Aacute w -30 KPX Aacute y -30 KPX Aacute yacute -30 KPX Aacute ydieresis -30 KPX Abreve C -40 KPX Abreve Cacute -40 KPX Abreve Ccaron -40 KPX Abreve Ccedilla -40 KPX Abreve G -50 KPX Abreve Gbreve -50 KPX Abreve Gcommaaccent -50 KPX Abreve O -40 KPX Abreve Oacute -40 KPX Abreve Ocircumflex -40 KPX Abreve Odieresis -40 KPX Abreve Ograve -40 KPX Abreve Ohungarumlaut -40 KPX Abreve Omacron -40 KPX Abreve Oslash -40 KPX Abreve Otilde -40 KPX Abreve Q -40 KPX Abreve T -90 KPX Abreve Tcaron -90 KPX Abreve Tcommaaccent -90 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -80 KPX Abreve W -60 KPX Abreve Y -110 KPX Abreve Yacute -110 KPX Abreve Ydieresis -110 KPX Abreve u -30 KPX Abreve uacute -30 KPX Abreve ucircumflex -30 KPX Abreve udieresis -30 KPX Abreve ugrave -30 KPX Abreve uhungarumlaut -30 KPX Abreve umacron -30 KPX Abreve uogonek -30 KPX Abreve uring -30 KPX Abreve v -40 KPX Abreve w -30 KPX Abreve y -30 KPX Abreve yacute -30 KPX Abreve ydieresis -30 KPX Acircumflex C -40 KPX Acircumflex Cacute -40 KPX Acircumflex Ccaron -40 KPX Acircumflex Ccedilla -40 KPX Acircumflex G -50 KPX Acircumflex Gbreve -50 KPX Acircumflex Gcommaaccent -50 KPX Acircumflex O -40 KPX Acircumflex Oacute -40 KPX Acircumflex Ocircumflex -40 KPX Acircumflex Odieresis -40 KPX Acircumflex Ograve -40 KPX Acircumflex Ohungarumlaut -40 KPX Acircumflex Omacron -40 KPX Acircumflex Oslash -40 KPX Acircumflex Otilde -40 KPX Acircumflex Q -40 KPX Acircumflex T -90 KPX Acircumflex Tcaron -90 KPX Acircumflex Tcommaaccent -90 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -80 KPX Acircumflex W -60 KPX Acircumflex Y -110 KPX Acircumflex Yacute -110 KPX Acircumflex Ydieresis -110 KPX Acircumflex u -30 KPX Acircumflex uacute -30 KPX Acircumflex ucircumflex -30 KPX Acircumflex udieresis -30 KPX Acircumflex ugrave -30 KPX Acircumflex uhungarumlaut -30 KPX Acircumflex umacron -30 KPX Acircumflex uogonek -30 KPX Acircumflex uring -30 KPX Acircumflex v -40 KPX Acircumflex w -30 KPX Acircumflex y -30 KPX Acircumflex yacute -30 KPX Acircumflex ydieresis -30 KPX Adieresis C -40 KPX Adieresis Cacute -40 KPX Adieresis Ccaron -40 KPX Adieresis Ccedilla -40 KPX Adieresis G -50 KPX Adieresis Gbreve -50 KPX Adieresis Gcommaaccent -50 KPX Adieresis O -40 KPX Adieresis Oacute -40 KPX Adieresis Ocircumflex -40 KPX Adieresis Odieresis -40 KPX Adieresis Ograve -40 KPX Adieresis Ohungarumlaut -40 KPX Adieresis Omacron -40 KPX Adieresis Oslash -40 KPX Adieresis Otilde -40 KPX Adieresis Q -40 KPX Adieresis T -90 KPX Adieresis Tcaron -90 KPX Adieresis Tcommaaccent -90 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -80 KPX Adieresis W -60 KPX Adieresis Y -110 KPX Adieresis Yacute -110 KPX Adieresis Ydieresis -110 KPX Adieresis u -30 KPX Adieresis uacute -30 KPX Adieresis ucircumflex -30 KPX Adieresis udieresis -30 KPX Adieresis ugrave -30 KPX Adieresis uhungarumlaut -30 KPX Adieresis umacron -30 KPX Adieresis uogonek -30 KPX Adieresis uring -30 KPX Adieresis v -40 KPX Adieresis w -30 KPX Adieresis y -30 KPX Adieresis yacute -30 KPX Adieresis ydieresis -30 KPX Agrave C -40 KPX Agrave Cacute -40 KPX Agrave Ccaron -40 KPX Agrave Ccedilla -40 KPX Agrave G -50 KPX Agrave Gbreve -50 KPX Agrave Gcommaaccent -50 KPX Agrave O -40 KPX Agrave Oacute -40 KPX Agrave Ocircumflex -40 KPX Agrave Odieresis -40 KPX Agrave Ograve -40 KPX Agrave Ohungarumlaut -40 KPX Agrave Omacron -40 KPX Agrave Oslash -40 KPX Agrave Otilde -40 KPX Agrave Q -40 KPX Agrave T -90 KPX Agrave Tcaron -90 KPX Agrave Tcommaaccent -90 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -80 KPX Agrave W -60 KPX Agrave Y -110 KPX Agrave Yacute -110 KPX Agrave Ydieresis -110 KPX Agrave u -30 KPX Agrave uacute -30 KPX Agrave ucircumflex -30 KPX Agrave udieresis -30 KPX Agrave ugrave -30 KPX Agrave uhungarumlaut -30 KPX Agrave umacron -30 KPX Agrave uogonek -30 KPX Agrave uring -30 KPX Agrave v -40 KPX Agrave w -30 KPX Agrave y -30 KPX Agrave yacute -30 KPX Agrave ydieresis -30 KPX Amacron C -40 KPX Amacron Cacute -40 KPX Amacron Ccaron -40 KPX Amacron Ccedilla -40 KPX Amacron G -50 KPX Amacron Gbreve -50 KPX Amacron Gcommaaccent -50 KPX Amacron O -40 KPX Amacron Oacute -40 KPX Amacron Ocircumflex -40 KPX Amacron Odieresis -40 KPX Amacron Ograve -40 KPX Amacron Ohungarumlaut -40 KPX Amacron Omacron -40 KPX Amacron Oslash -40 KPX Amacron Otilde -40 KPX Amacron Q -40 KPX Amacron T -90 KPX Amacron Tcaron -90 KPX Amacron Tcommaaccent -90 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -80 KPX Amacron W -60 KPX Amacron Y -110 KPX Amacron Yacute -110 KPX Amacron Ydieresis -110 KPX Amacron u -30 KPX Amacron uacute -30 KPX Amacron ucircumflex -30 KPX Amacron udieresis -30 KPX Amacron ugrave -30 KPX Amacron uhungarumlaut -30 KPX Amacron umacron -30 KPX Amacron uogonek -30 KPX Amacron uring -30 KPX Amacron v -40 KPX Amacron w -30 KPX Amacron y -30 KPX Amacron yacute -30 KPX Amacron ydieresis -30 KPX Aogonek C -40 KPX Aogonek Cacute -40 KPX Aogonek Ccaron -40 KPX Aogonek Ccedilla -40 KPX Aogonek G -50 KPX Aogonek Gbreve -50 KPX Aogonek Gcommaaccent -50 KPX Aogonek O -40 KPX Aogonek Oacute -40 KPX Aogonek Ocircumflex -40 KPX Aogonek Odieresis -40 KPX Aogonek Ograve -40 KPX Aogonek Ohungarumlaut -40 KPX Aogonek Omacron -40 KPX Aogonek Oslash -40 KPX Aogonek Otilde -40 KPX Aogonek Q -40 KPX Aogonek T -90 KPX Aogonek Tcaron -90 KPX Aogonek Tcommaaccent -90 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -80 KPX Aogonek W -60 KPX Aogonek Y -110 KPX Aogonek Yacute -110 KPX Aogonek Ydieresis -110 KPX Aogonek u -30 KPX Aogonek uacute -30 KPX Aogonek ucircumflex -30 KPX Aogonek udieresis -30 KPX Aogonek ugrave -30 KPX Aogonek uhungarumlaut -30 KPX Aogonek umacron -30 KPX Aogonek uogonek -30 KPX Aogonek uring -30 KPX Aogonek v -40 KPX Aogonek w -30 KPX Aogonek y -30 KPX Aogonek yacute -30 KPX Aogonek ydieresis -30 KPX Aring C -40 KPX Aring Cacute -40 KPX Aring Ccaron -40 KPX Aring Ccedilla -40 KPX Aring G -50 KPX Aring Gbreve -50 KPX Aring Gcommaaccent -50 KPX Aring O -40 KPX Aring Oacute -40 KPX Aring Ocircumflex -40 KPX Aring Odieresis -40 KPX Aring Ograve -40 KPX Aring Ohungarumlaut -40 KPX Aring Omacron -40 KPX Aring Oslash -40 KPX Aring Otilde -40 KPX Aring Q -40 KPX Aring T -90 KPX Aring Tcaron -90 KPX Aring Tcommaaccent -90 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -80 KPX Aring W -60 KPX Aring Y -110 KPX Aring Yacute -110 KPX Aring Ydieresis -110 KPX Aring u -30 KPX Aring uacute -30 KPX Aring ucircumflex -30 KPX Aring udieresis -30 KPX Aring ugrave -30 KPX Aring uhungarumlaut -30 KPX Aring umacron -30 KPX Aring uogonek -30 KPX Aring uring -30 KPX Aring v -40 KPX Aring w -30 KPX Aring y -30 KPX Aring yacute -30 KPX Aring ydieresis -30 KPX Atilde C -40 KPX Atilde Cacute -40 KPX Atilde Ccaron -40 KPX Atilde Ccedilla -40 KPX Atilde G -50 KPX Atilde Gbreve -50 KPX Atilde Gcommaaccent -50 KPX Atilde O -40 KPX Atilde Oacute -40 KPX Atilde Ocircumflex -40 KPX Atilde Odieresis -40 KPX Atilde Ograve -40 KPX Atilde Ohungarumlaut -40 KPX Atilde Omacron -40 KPX Atilde Oslash -40 KPX Atilde Otilde -40 KPX Atilde Q -40 KPX Atilde T -90 KPX Atilde Tcaron -90 KPX Atilde Tcommaaccent -90 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -80 KPX Atilde W -60 KPX Atilde Y -110 KPX Atilde Yacute -110 KPX Atilde Ydieresis -110 KPX Atilde u -30 KPX Atilde uacute -30 KPX Atilde ucircumflex -30 KPX Atilde udieresis -30 KPX Atilde ugrave -30 KPX Atilde uhungarumlaut -30 KPX Atilde umacron -30 KPX Atilde uogonek -30 KPX Atilde uring -30 KPX Atilde v -40 KPX Atilde w -30 KPX Atilde y -30 KPX Atilde yacute -30 KPX Atilde ydieresis -30 KPX B A -30 KPX B Aacute -30 KPX B Abreve -30 KPX B Acircumflex -30 KPX B Adieresis -30 KPX B Agrave -30 KPX B Amacron -30 KPX B Aogonek -30 KPX B Aring -30 KPX B Atilde -30 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -40 KPX D Aacute -40 KPX D Abreve -40 KPX D Acircumflex -40 KPX D Adieresis -40 KPX D Agrave -40 KPX D Amacron -40 KPX D Aogonek -40 KPX D Aring -40 KPX D Atilde -40 KPX D V -40 KPX D W -40 KPX D Y -70 KPX D Yacute -70 KPX D Ydieresis -70 KPX D comma -30 KPX D period -30 KPX Dcaron A -40 KPX Dcaron Aacute -40 KPX Dcaron Abreve -40 KPX Dcaron Acircumflex -40 KPX Dcaron Adieresis -40 KPX Dcaron Agrave -40 KPX Dcaron Amacron -40 KPX Dcaron Aogonek -40 KPX Dcaron Aring -40 KPX Dcaron Atilde -40 KPX Dcaron V -40 KPX Dcaron W -40 KPX Dcaron Y -70 KPX Dcaron Yacute -70 KPX Dcaron Ydieresis -70 KPX Dcaron comma -30 KPX Dcaron period -30 KPX Dcroat A -40 KPX Dcroat Aacute -40 KPX Dcroat Abreve -40 KPX Dcroat Acircumflex -40 KPX Dcroat Adieresis -40 KPX Dcroat Agrave -40 KPX Dcroat Amacron -40 KPX Dcroat Aogonek -40 KPX Dcroat Aring -40 KPX Dcroat Atilde -40 KPX Dcroat V -40 KPX Dcroat W -40 KPX Dcroat Y -70 KPX Dcroat Yacute -70 KPX Dcroat Ydieresis -70 KPX Dcroat comma -30 KPX Dcroat period -30 KPX F A -80 KPX F Aacute -80 KPX F Abreve -80 KPX F Acircumflex -80 KPX F Adieresis -80 KPX F Agrave -80 KPX F Amacron -80 KPX F Aogonek -80 KPX F Aring -80 KPX F Atilde -80 KPX F a -20 KPX F aacute -20 KPX F abreve -20 KPX F acircumflex -20 KPX F adieresis -20 KPX F agrave -20 KPX F amacron -20 KPX F aogonek -20 KPX F aring -20 KPX F atilde -20 KPX F comma -100 KPX F period -100 KPX J A -20 KPX J Aacute -20 KPX J Abreve -20 KPX J Acircumflex -20 KPX J Adieresis -20 KPX J Agrave -20 KPX J Amacron -20 KPX J Aogonek -20 KPX J Aring -20 KPX J Atilde -20 KPX J comma -20 KPX J period -20 KPX J u -20 KPX J uacute -20 KPX J ucircumflex -20 KPX J udieresis -20 KPX J ugrave -20 KPX J uhungarumlaut -20 KPX J umacron -20 KPX J uogonek -20 KPX J uring -20 KPX K O -30 KPX K Oacute -30 KPX K Ocircumflex -30 KPX K Odieresis -30 KPX K Ograve -30 KPX K Ohungarumlaut -30 KPX K Omacron -30 KPX K Oslash -30 KPX K Otilde -30 KPX K e -15 KPX K eacute -15 KPX K ecaron -15 KPX K ecircumflex -15 KPX K edieresis -15 KPX K edotaccent -15 KPX K egrave -15 KPX K emacron -15 KPX K eogonek -15 KPX K o -35 KPX K oacute -35 KPX K ocircumflex -35 KPX K odieresis -35 KPX K ograve -35 KPX K ohungarumlaut -35 KPX K omacron -35 KPX K oslash -35 KPX K otilde -35 KPX K u -30 KPX K uacute -30 KPX K ucircumflex -30 KPX K udieresis -30 KPX K ugrave -30 KPX K uhungarumlaut -30 KPX K umacron -30 KPX K uogonek -30 KPX K uring -30 KPX K y -40 KPX K yacute -40 KPX K ydieresis -40 KPX Kcommaaccent O -30 KPX Kcommaaccent Oacute -30 KPX Kcommaaccent Ocircumflex -30 KPX Kcommaaccent Odieresis -30 KPX Kcommaaccent Ograve -30 KPX Kcommaaccent Ohungarumlaut -30 KPX Kcommaaccent Omacron -30 KPX Kcommaaccent Oslash -30 KPX Kcommaaccent Otilde -30 KPX Kcommaaccent e -15 KPX Kcommaaccent eacute -15 KPX Kcommaaccent ecaron -15 KPX Kcommaaccent ecircumflex -15 KPX Kcommaaccent edieresis -15 KPX Kcommaaccent edotaccent -15 KPX Kcommaaccent egrave -15 KPX Kcommaaccent emacron -15 KPX Kcommaaccent eogonek -15 KPX Kcommaaccent o -35 KPX Kcommaaccent oacute -35 KPX Kcommaaccent ocircumflex -35 KPX Kcommaaccent odieresis -35 KPX Kcommaaccent ograve -35 KPX Kcommaaccent ohungarumlaut -35 KPX Kcommaaccent omacron -35 KPX Kcommaaccent oslash -35 KPX Kcommaaccent otilde -35 KPX Kcommaaccent u -30 KPX Kcommaaccent uacute -30 KPX Kcommaaccent ucircumflex -30 KPX Kcommaaccent udieresis -30 KPX Kcommaaccent ugrave -30 KPX Kcommaaccent uhungarumlaut -30 KPX Kcommaaccent umacron -30 KPX Kcommaaccent uogonek -30 KPX Kcommaaccent uring -30 KPX Kcommaaccent y -40 KPX Kcommaaccent yacute -40 KPX Kcommaaccent ydieresis -40 KPX L T -90 KPX L Tcaron -90 KPX L Tcommaaccent -90 KPX L V -110 KPX L W -80 KPX L Y -120 KPX L Yacute -120 KPX L Ydieresis -120 KPX L quotedblright -140 KPX L quoteright -140 KPX L y -30 KPX L yacute -30 KPX L ydieresis -30 KPX Lacute T -90 KPX Lacute Tcaron -90 KPX Lacute Tcommaaccent -90 KPX Lacute V -110 KPX Lacute W -80 KPX Lacute Y -120 KPX Lacute Yacute -120 KPX Lacute Ydieresis -120 KPX Lacute quotedblright -140 KPX Lacute quoteright -140 KPX Lacute y -30 KPX Lacute yacute -30 KPX Lacute ydieresis -30 KPX Lcommaaccent T -90 KPX Lcommaaccent Tcaron -90 KPX Lcommaaccent Tcommaaccent -90 KPX Lcommaaccent V -110 KPX Lcommaaccent W -80 KPX Lcommaaccent Y -120 KPX Lcommaaccent Yacute -120 KPX Lcommaaccent Ydieresis -120 KPX Lcommaaccent quotedblright -140 KPX Lcommaaccent quoteright -140 KPX Lcommaaccent y -30 KPX Lcommaaccent yacute -30 KPX Lcommaaccent ydieresis -30 KPX Lslash T -90 KPX Lslash Tcaron -90 KPX Lslash Tcommaaccent -90 KPX Lslash V -110 KPX Lslash W -80 KPX Lslash Y -120 KPX Lslash Yacute -120 KPX Lslash Ydieresis -120 KPX Lslash quotedblright -140 KPX Lslash quoteright -140 KPX Lslash y -30 KPX Lslash yacute -30 KPX Lslash ydieresis -30 KPX O A -50 KPX O Aacute -50 KPX O Abreve -50 KPX O Acircumflex -50 KPX O Adieresis -50 KPX O Agrave -50 KPX O Amacron -50 KPX O Aogonek -50 KPX O Aring -50 KPX O Atilde -50 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -50 KPX O X -50 KPX O Y -70 KPX O Yacute -70 KPX O Ydieresis -70 KPX O comma -40 KPX O period -40 KPX Oacute A -50 KPX Oacute Aacute -50 KPX Oacute Abreve -50 KPX Oacute Acircumflex -50 KPX Oacute Adieresis -50 KPX Oacute Agrave -50 KPX Oacute Amacron -50 KPX Oacute Aogonek -50 KPX Oacute Aring -50 KPX Oacute Atilde -50 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -50 KPX Oacute X -50 KPX Oacute Y -70 KPX Oacute Yacute -70 KPX Oacute Ydieresis -70 KPX Oacute comma -40 KPX Oacute period -40 KPX Ocircumflex A -50 KPX Ocircumflex Aacute -50 KPX Ocircumflex Abreve -50 KPX Ocircumflex Acircumflex -50 KPX Ocircumflex Adieresis -50 KPX Ocircumflex Agrave -50 KPX Ocircumflex Amacron -50 KPX Ocircumflex Aogonek -50 KPX Ocircumflex Aring -50 KPX Ocircumflex Atilde -50 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -50 KPX Ocircumflex X -50 KPX Ocircumflex Y -70 KPX Ocircumflex Yacute -70 KPX Ocircumflex Ydieresis -70 KPX Ocircumflex comma -40 KPX Ocircumflex period -40 KPX Odieresis A -50 KPX Odieresis Aacute -50 KPX Odieresis Abreve -50 KPX Odieresis Acircumflex -50 KPX Odieresis Adieresis -50 KPX Odieresis Agrave -50 KPX Odieresis Amacron -50 KPX Odieresis Aogonek -50 KPX Odieresis Aring -50 KPX Odieresis Atilde -50 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -50 KPX Odieresis X -50 KPX Odieresis Y -70 KPX Odieresis Yacute -70 KPX Odieresis Ydieresis -70 KPX Odieresis comma -40 KPX Odieresis period -40 KPX Ograve A -50 KPX Ograve Aacute -50 KPX Ograve Abreve -50 KPX Ograve Acircumflex -50 KPX Ograve Adieresis -50 KPX Ograve Agrave -50 KPX Ograve Amacron -50 KPX Ograve Aogonek -50 KPX Ograve Aring -50 KPX Ograve Atilde -50 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -50 KPX Ograve X -50 KPX Ograve Y -70 KPX Ograve Yacute -70 KPX Ograve Ydieresis -70 KPX Ograve comma -40 KPX Ograve period -40 KPX Ohungarumlaut A -50 KPX Ohungarumlaut Aacute -50 KPX Ohungarumlaut Abreve -50 KPX Ohungarumlaut Acircumflex -50 KPX Ohungarumlaut Adieresis -50 KPX Ohungarumlaut Agrave -50 KPX Ohungarumlaut Amacron -50 KPX Ohungarumlaut Aogonek -50 KPX Ohungarumlaut Aring -50 KPX Ohungarumlaut Atilde -50 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -50 KPX Ohungarumlaut X -50 KPX Ohungarumlaut Y -70 KPX Ohungarumlaut Yacute -70 KPX Ohungarumlaut Ydieresis -70 KPX Ohungarumlaut comma -40 KPX Ohungarumlaut period -40 KPX Omacron A -50 KPX Omacron Aacute -50 KPX Omacron Abreve -50 KPX Omacron Acircumflex -50 KPX Omacron Adieresis -50 KPX Omacron Agrave -50 KPX Omacron Amacron -50 KPX Omacron Aogonek -50 KPX Omacron Aring -50 KPX Omacron Atilde -50 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -50 KPX Omacron X -50 KPX Omacron Y -70 KPX Omacron Yacute -70 KPX Omacron Ydieresis -70 KPX Omacron comma -40 KPX Omacron period -40 KPX Oslash A -50 KPX Oslash Aacute -50 KPX Oslash Abreve -50 KPX Oslash Acircumflex -50 KPX Oslash Adieresis -50 KPX Oslash Agrave -50 KPX Oslash Amacron -50 KPX Oslash Aogonek -50 KPX Oslash Aring -50 KPX Oslash Atilde -50 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -50 KPX Oslash X -50 KPX Oslash Y -70 KPX Oslash Yacute -70 KPX Oslash Ydieresis -70 KPX Oslash comma -40 KPX Oslash period -40 KPX Otilde A -50 KPX Otilde Aacute -50 KPX Otilde Abreve -50 KPX Otilde Acircumflex -50 KPX Otilde Adieresis -50 KPX Otilde Agrave -50 KPX Otilde Amacron -50 KPX Otilde Aogonek -50 KPX Otilde Aring -50 KPX Otilde Atilde -50 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -50 KPX Otilde X -50 KPX Otilde Y -70 KPX Otilde Yacute -70 KPX Otilde Ydieresis -70 KPX Otilde comma -40 KPX Otilde period -40 KPX P A -100 KPX P Aacute -100 KPX P Abreve -100 KPX P Acircumflex -100 KPX P Adieresis -100 KPX P Agrave -100 KPX P Amacron -100 KPX P Aogonek -100 KPX P Aring -100 KPX P Atilde -100 KPX P a -30 KPX P aacute -30 KPX P abreve -30 KPX P acircumflex -30 KPX P adieresis -30 KPX P agrave -30 KPX P amacron -30 KPX P aogonek -30 KPX P aring -30 KPX P atilde -30 KPX P comma -120 KPX P e -30 KPX P eacute -30 KPX P ecaron -30 KPX P ecircumflex -30 KPX P edieresis -30 KPX P edotaccent -30 KPX P egrave -30 KPX P emacron -30 KPX P eogonek -30 KPX P o -40 KPX P oacute -40 KPX P ocircumflex -40 KPX P odieresis -40 KPX P ograve -40 KPX P ohungarumlaut -40 KPX P omacron -40 KPX P oslash -40 KPX P otilde -40 KPX P period -120 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX Q comma 20 KPX Q period 20 KPX R O -20 KPX R Oacute -20 KPX R Ocircumflex -20 KPX R Odieresis -20 KPX R Ograve -20 KPX R Ohungarumlaut -20 KPX R Omacron -20 KPX R Oslash -20 KPX R Otilde -20 KPX R T -20 KPX R Tcaron -20 KPX R Tcommaaccent -20 KPX R U -20 KPX R Uacute -20 KPX R Ucircumflex -20 KPX R Udieresis -20 KPX R Ugrave -20 KPX R Uhungarumlaut -20 KPX R Umacron -20 KPX R Uogonek -20 KPX R Uring -20 KPX R V -50 KPX R W -40 KPX R Y -50 KPX R Yacute -50 KPX R Ydieresis -50 KPX Racute O -20 KPX Racute Oacute -20 KPX Racute Ocircumflex -20 KPX Racute Odieresis -20 KPX Racute Ograve -20 KPX Racute Ohungarumlaut -20 KPX Racute Omacron -20 KPX Racute Oslash -20 KPX Racute Otilde -20 KPX Racute T -20 KPX Racute Tcaron -20 KPX Racute Tcommaaccent -20 KPX Racute U -20 KPX Racute Uacute -20 KPX Racute Ucircumflex -20 KPX Racute Udieresis -20 KPX Racute Ugrave -20 KPX Racute Uhungarumlaut -20 KPX Racute Umacron -20 KPX Racute Uogonek -20 KPX Racute Uring -20 KPX Racute V -50 KPX Racute W -40 KPX Racute Y -50 KPX Racute Yacute -50 KPX Racute Ydieresis -50 KPX Rcaron O -20 KPX Rcaron Oacute -20 KPX Rcaron Ocircumflex -20 KPX Rcaron Odieresis -20 KPX Rcaron Ograve -20 KPX Rcaron Ohungarumlaut -20 KPX Rcaron Omacron -20 KPX Rcaron Oslash -20 KPX Rcaron Otilde -20 KPX Rcaron T -20 KPX Rcaron Tcaron -20 KPX Rcaron Tcommaaccent -20 KPX Rcaron U -20 KPX Rcaron Uacute -20 KPX Rcaron Ucircumflex -20 KPX Rcaron Udieresis -20 KPX Rcaron Ugrave -20 KPX Rcaron Uhungarumlaut -20 KPX Rcaron Umacron -20 KPX Rcaron Uogonek -20 KPX Rcaron Uring -20 KPX Rcaron V -50 KPX Rcaron W -40 KPX Rcaron Y -50 KPX Rcaron Yacute -50 KPX Rcaron Ydieresis -50 KPX Rcommaaccent O -20 KPX Rcommaaccent Oacute -20 KPX Rcommaaccent Ocircumflex -20 KPX Rcommaaccent Odieresis -20 KPX Rcommaaccent Ograve -20 KPX Rcommaaccent Ohungarumlaut -20 KPX Rcommaaccent Omacron -20 KPX Rcommaaccent Oslash -20 KPX Rcommaaccent Otilde -20 KPX Rcommaaccent T -20 KPX Rcommaaccent Tcaron -20 KPX Rcommaaccent Tcommaaccent -20 KPX Rcommaaccent U -20 KPX Rcommaaccent Uacute -20 KPX Rcommaaccent Ucircumflex -20 KPX Rcommaaccent Udieresis -20 KPX Rcommaaccent Ugrave -20 KPX Rcommaaccent Uhungarumlaut -20 KPX Rcommaaccent Umacron -20 KPX Rcommaaccent Uogonek -20 KPX Rcommaaccent Uring -20 KPX Rcommaaccent V -50 KPX Rcommaaccent W -40 KPX Rcommaaccent Y -50 KPX Rcommaaccent Yacute -50 KPX Rcommaaccent Ydieresis -50 KPX T A -90 KPX T Aacute -90 KPX T Abreve -90 KPX T Acircumflex -90 KPX T Adieresis -90 KPX T Agrave -90 KPX T Amacron -90 KPX T Aogonek -90 KPX T Aring -90 KPX T Atilde -90 KPX T O -40 KPX T Oacute -40 KPX T Ocircumflex -40 KPX T Odieresis -40 KPX T Ograve -40 KPX T Ohungarumlaut -40 KPX T Omacron -40 KPX T Oslash -40 KPX T Otilde -40 KPX T a -80 KPX T aacute -80 KPX T abreve -80 KPX T acircumflex -80 KPX T adieresis -80 KPX T agrave -80 KPX T amacron -80 KPX T aogonek -80 KPX T aring -80 KPX T atilde -80 KPX T colon -40 KPX T comma -80 KPX T e -60 KPX T eacute -60 KPX T ecaron -60 KPX T ecircumflex -60 KPX T edieresis -60 KPX T edotaccent -60 KPX T egrave -60 KPX T emacron -60 KPX T eogonek -60 KPX T hyphen -120 KPX T o -80 KPX T oacute -80 KPX T ocircumflex -80 KPX T odieresis -80 KPX T ograve -80 KPX T ohungarumlaut -80 KPX T omacron -80 KPX T oslash -80 KPX T otilde -80 KPX T period -80 KPX T r -80 KPX T racute -80 KPX T rcommaaccent -80 KPX T semicolon -40 KPX T u -90 KPX T uacute -90 KPX T ucircumflex -90 KPX T udieresis -90 KPX T ugrave -90 KPX T uhungarumlaut -90 KPX T umacron -90 KPX T uogonek -90 KPX T uring -90 KPX T w -60 KPX T y -60 KPX T yacute -60 KPX T ydieresis -60 KPX Tcaron A -90 KPX Tcaron Aacute -90 KPX Tcaron Abreve -90 KPX Tcaron Acircumflex -90 KPX Tcaron Adieresis -90 KPX Tcaron Agrave -90 KPX Tcaron Amacron -90 KPX Tcaron Aogonek -90 KPX Tcaron Aring -90 KPX Tcaron Atilde -90 KPX Tcaron O -40 KPX Tcaron Oacute -40 KPX Tcaron Ocircumflex -40 KPX Tcaron Odieresis -40 KPX Tcaron Ograve -40 KPX Tcaron Ohungarumlaut -40 KPX Tcaron Omacron -40 KPX Tcaron Oslash -40 KPX Tcaron Otilde -40 KPX Tcaron a -80 KPX Tcaron aacute -80 KPX Tcaron abreve -80 KPX Tcaron acircumflex -80 KPX Tcaron adieresis -80 KPX Tcaron agrave -80 KPX Tcaron amacron -80 KPX Tcaron aogonek -80 KPX Tcaron aring -80 KPX Tcaron atilde -80 KPX Tcaron colon -40 KPX Tcaron comma -80 KPX Tcaron e -60 KPX Tcaron eacute -60 KPX Tcaron ecaron -60 KPX Tcaron ecircumflex -60 KPX Tcaron edieresis -60 KPX Tcaron edotaccent -60 KPX Tcaron egrave -60 KPX Tcaron emacron -60 KPX Tcaron eogonek -60 KPX Tcaron hyphen -120 KPX Tcaron o -80 KPX Tcaron oacute -80 KPX Tcaron ocircumflex -80 KPX Tcaron odieresis -80 KPX Tcaron ograve -80 KPX Tcaron ohungarumlaut -80 KPX Tcaron omacron -80 KPX Tcaron oslash -80 KPX Tcaron otilde -80 KPX Tcaron period -80 KPX Tcaron r -80 KPX Tcaron racute -80 KPX Tcaron rcommaaccent -80 KPX Tcaron semicolon -40 KPX Tcaron u -90 KPX Tcaron uacute -90 KPX Tcaron ucircumflex -90 KPX Tcaron udieresis -90 KPX Tcaron ugrave -90 KPX Tcaron uhungarumlaut -90 KPX Tcaron umacron -90 KPX Tcaron uogonek -90 KPX Tcaron uring -90 KPX Tcaron w -60 KPX Tcaron y -60 KPX Tcaron yacute -60 KPX Tcaron ydieresis -60 KPX Tcommaaccent A -90 KPX Tcommaaccent Aacute -90 KPX Tcommaaccent Abreve -90 KPX Tcommaaccent Acircumflex -90 KPX Tcommaaccent Adieresis -90 KPX Tcommaaccent Agrave -90 KPX Tcommaaccent Amacron -90 KPX Tcommaaccent Aogonek -90 KPX Tcommaaccent Aring -90 KPX Tcommaaccent Atilde -90 KPX Tcommaaccent O -40 KPX Tcommaaccent Oacute -40 KPX Tcommaaccent Ocircumflex -40 KPX Tcommaaccent Odieresis -40 KPX Tcommaaccent Ograve -40 KPX Tcommaaccent Ohungarumlaut -40 KPX Tcommaaccent Omacron -40 KPX Tcommaaccent Oslash -40 KPX Tcommaaccent Otilde -40 KPX Tcommaaccent a -80 KPX Tcommaaccent aacute -80 KPX Tcommaaccent abreve -80 KPX Tcommaaccent acircumflex -80 KPX Tcommaaccent adieresis -80 KPX Tcommaaccent agrave -80 KPX Tcommaaccent amacron -80 KPX Tcommaaccent aogonek -80 KPX Tcommaaccent aring -80 KPX Tcommaaccent atilde -80 KPX Tcommaaccent colon -40 KPX Tcommaaccent comma -80 KPX Tcommaaccent e -60 KPX Tcommaaccent eacute -60 KPX Tcommaaccent ecaron -60 KPX Tcommaaccent ecircumflex -60 KPX Tcommaaccent edieresis -60 KPX Tcommaaccent edotaccent -60 KPX Tcommaaccent egrave -60 KPX Tcommaaccent emacron -60 KPX Tcommaaccent eogonek -60 KPX Tcommaaccent hyphen -120 KPX Tcommaaccent o -80 KPX Tcommaaccent oacute -80 KPX Tcommaaccent ocircumflex -80 KPX Tcommaaccent odieresis -80 KPX Tcommaaccent ograve -80 KPX Tcommaaccent ohungarumlaut -80 KPX Tcommaaccent omacron -80 KPX Tcommaaccent oslash -80 KPX Tcommaaccent otilde -80 KPX Tcommaaccent period -80 KPX Tcommaaccent r -80 KPX Tcommaaccent racute -80 KPX Tcommaaccent rcommaaccent -80 KPX Tcommaaccent semicolon -40 KPX Tcommaaccent u -90 KPX Tcommaaccent uacute -90 KPX Tcommaaccent ucircumflex -90 KPX Tcommaaccent udieresis -90 KPX Tcommaaccent ugrave -90 KPX Tcommaaccent uhungarumlaut -90 KPX Tcommaaccent umacron -90 KPX Tcommaaccent uogonek -90 KPX Tcommaaccent uring -90 KPX Tcommaaccent w -60 KPX Tcommaaccent y -60 KPX Tcommaaccent yacute -60 KPX Tcommaaccent ydieresis -60 KPX U A -50 KPX U Aacute -50 KPX U Abreve -50 KPX U Acircumflex -50 KPX U Adieresis -50 KPX U Agrave -50 KPX U Amacron -50 KPX U Aogonek -50 KPX U Aring -50 KPX U Atilde -50 KPX U comma -30 KPX U period -30 KPX Uacute A -50 KPX Uacute Aacute -50 KPX Uacute Abreve -50 KPX Uacute Acircumflex -50 KPX Uacute Adieresis -50 KPX Uacute Agrave -50 KPX Uacute Amacron -50 KPX Uacute Aogonek -50 KPX Uacute Aring -50 KPX Uacute Atilde -50 KPX Uacute comma -30 KPX Uacute period -30 KPX Ucircumflex A -50 KPX Ucircumflex Aacute -50 KPX Ucircumflex Abreve -50 KPX Ucircumflex Acircumflex -50 KPX Ucircumflex Adieresis -50 KPX Ucircumflex Agrave -50 KPX Ucircumflex Amacron -50 KPX Ucircumflex Aogonek -50 KPX Ucircumflex Aring -50 KPX Ucircumflex Atilde -50 KPX Ucircumflex comma -30 KPX Ucircumflex period -30 KPX Udieresis A -50 KPX Udieresis Aacute -50 KPX Udieresis Abreve -50 KPX Udieresis Acircumflex -50 KPX Udieresis Adieresis -50 KPX Udieresis Agrave -50 KPX Udieresis Amacron -50 KPX Udieresis Aogonek -50 KPX Udieresis Aring -50 KPX Udieresis Atilde -50 KPX Udieresis comma -30 KPX Udieresis period -30 KPX Ugrave A -50 KPX Ugrave Aacute -50 KPX Ugrave Abreve -50 KPX Ugrave Acircumflex -50 KPX Ugrave Adieresis -50 KPX Ugrave Agrave -50 KPX Ugrave Amacron -50 KPX Ugrave Aogonek -50 KPX Ugrave Aring -50 KPX Ugrave Atilde -50 KPX Ugrave comma -30 KPX Ugrave period -30 KPX Uhungarumlaut A -50 KPX Uhungarumlaut Aacute -50 KPX Uhungarumlaut Abreve -50 KPX Uhungarumlaut Acircumflex -50 KPX Uhungarumlaut Adieresis -50 KPX Uhungarumlaut Agrave -50 KPX Uhungarumlaut Amacron -50 KPX Uhungarumlaut Aogonek -50 KPX Uhungarumlaut Aring -50 KPX Uhungarumlaut Atilde -50 KPX Uhungarumlaut comma -30 KPX Uhungarumlaut period -30 KPX Umacron A -50 KPX Umacron Aacute -50 KPX Umacron Abreve -50 KPX Umacron Acircumflex -50 KPX Umacron Adieresis -50 KPX Umacron Agrave -50 KPX Umacron Amacron -50 KPX Umacron Aogonek -50 KPX Umacron Aring -50 KPX Umacron Atilde -50 KPX Umacron comma -30 KPX Umacron period -30 KPX Uogonek A -50 KPX Uogonek Aacute -50 KPX Uogonek Abreve -50 KPX Uogonek Acircumflex -50 KPX Uogonek Adieresis -50 KPX Uogonek Agrave -50 KPX Uogonek Amacron -50 KPX Uogonek Aogonek -50 KPX Uogonek Aring -50 KPX Uogonek Atilde -50 KPX Uogonek comma -30 KPX Uogonek period -30 KPX Uring A -50 KPX Uring Aacute -50 KPX Uring Abreve -50 KPX Uring Acircumflex -50 KPX Uring Adieresis -50 KPX Uring Agrave -50 KPX Uring Amacron -50 KPX Uring Aogonek -50 KPX Uring Aring -50 KPX Uring Atilde -50 KPX Uring comma -30 KPX Uring period -30 KPX V A -80 KPX V Aacute -80 KPX V Abreve -80 KPX V Acircumflex -80 KPX V Adieresis -80 KPX V Agrave -80 KPX V Amacron -80 KPX V Aogonek -80 KPX V Aring -80 KPX V Atilde -80 KPX V G -50 KPX V Gbreve -50 KPX V Gcommaaccent -50 KPX V O -50 KPX V Oacute -50 KPX V Ocircumflex -50 KPX V Odieresis -50 KPX V Ograve -50 KPX V Ohungarumlaut -50 KPX V Omacron -50 KPX V Oslash -50 KPX V Otilde -50 KPX V a -60 KPX V aacute -60 KPX V abreve -60 KPX V acircumflex -60 KPX V adieresis -60 KPX V agrave -60 KPX V amacron -60 KPX V aogonek -60 KPX V aring -60 KPX V atilde -60 KPX V colon -40 KPX V comma -120 KPX V e -50 KPX V eacute -50 KPX V ecaron -50 KPX V ecircumflex -50 KPX V edieresis -50 KPX V edotaccent -50 KPX V egrave -50 KPX V emacron -50 KPX V eogonek -50 KPX V hyphen -80 KPX V o -90 KPX V oacute -90 KPX V ocircumflex -90 KPX V odieresis -90 KPX V ograve -90 KPX V ohungarumlaut -90 KPX V omacron -90 KPX V oslash -90 KPX V otilde -90 KPX V period -120 KPX V semicolon -40 KPX V u -60 KPX V uacute -60 KPX V ucircumflex -60 KPX V udieresis -60 KPX V ugrave -60 KPX V uhungarumlaut -60 KPX V umacron -60 KPX V uogonek -60 KPX V uring -60 KPX W A -60 KPX W Aacute -60 KPX W Abreve -60 KPX W Acircumflex -60 KPX W Adieresis -60 KPX W Agrave -60 KPX W Amacron -60 KPX W Aogonek -60 KPX W Aring -60 KPX W Atilde -60 KPX W O -20 KPX W Oacute -20 KPX W Ocircumflex -20 KPX W Odieresis -20 KPX W Ograve -20 KPX W Ohungarumlaut -20 KPX W Omacron -20 KPX W Oslash -20 KPX W Otilde -20 KPX W a -40 KPX W aacute -40 KPX W abreve -40 KPX W acircumflex -40 KPX W adieresis -40 KPX W agrave -40 KPX W amacron -40 KPX W aogonek -40 KPX W aring -40 KPX W atilde -40 KPX W colon -10 KPX W comma -80 KPX W e -35 KPX W eacute -35 KPX W ecaron -35 KPX W ecircumflex -35 KPX W edieresis -35 KPX W edotaccent -35 KPX W egrave -35 KPX W emacron -35 KPX W eogonek -35 KPX W hyphen -40 KPX W o -60 KPX W oacute -60 KPX W ocircumflex -60 KPX W odieresis -60 KPX W ograve -60 KPX W ohungarumlaut -60 KPX W omacron -60 KPX W oslash -60 KPX W otilde -60 KPX W period -80 KPX W semicolon -10 KPX W u -45 KPX W uacute -45 KPX W ucircumflex -45 KPX W udieresis -45 KPX W ugrave -45 KPX W uhungarumlaut -45 KPX W umacron -45 KPX W uogonek -45 KPX W uring -45 KPX W y -20 KPX W yacute -20 KPX W ydieresis -20 KPX Y A -110 KPX Y Aacute -110 KPX Y Abreve -110 KPX Y Acircumflex -110 KPX Y Adieresis -110 KPX Y Agrave -110 KPX Y Amacron -110 KPX Y Aogonek -110 KPX Y Aring -110 KPX Y Atilde -110 KPX Y O -70 KPX Y Oacute -70 KPX Y Ocircumflex -70 KPX Y Odieresis -70 KPX Y Ograve -70 KPX Y Ohungarumlaut -70 KPX Y Omacron -70 KPX Y Oslash -70 KPX Y Otilde -70 KPX Y a -90 KPX Y aacute -90 KPX Y abreve -90 KPX Y acircumflex -90 KPX Y adieresis -90 KPX Y agrave -90 KPX Y amacron -90 KPX Y aogonek -90 KPX Y aring -90 KPX Y atilde -90 KPX Y colon -50 KPX Y comma -100 KPX Y e -80 KPX Y eacute -80 KPX Y ecaron -80 KPX Y ecircumflex -80 KPX Y edieresis -80 KPX Y edotaccent -80 KPX Y egrave -80 KPX Y emacron -80 KPX Y eogonek -80 KPX Y o -100 KPX Y oacute -100 KPX Y ocircumflex -100 KPX Y odieresis -100 KPX Y ograve -100 KPX Y ohungarumlaut -100 KPX Y omacron -100 KPX Y oslash -100 KPX Y otilde -100 KPX Y period -100 KPX Y semicolon -50 KPX Y u -100 KPX Y uacute -100 KPX Y ucircumflex -100 KPX Y udieresis -100 KPX Y ugrave -100 KPX Y uhungarumlaut -100 KPX Y umacron -100 KPX Y uogonek -100 KPX Y uring -100 KPX Yacute A -110 KPX Yacute Aacute -110 KPX Yacute Abreve -110 KPX Yacute Acircumflex -110 KPX Yacute Adieresis -110 KPX Yacute Agrave -110 KPX Yacute Amacron -110 KPX Yacute Aogonek -110 KPX Yacute Aring -110 KPX Yacute Atilde -110 KPX Yacute O -70 KPX Yacute Oacute -70 KPX Yacute Ocircumflex -70 KPX Yacute Odieresis -70 KPX Yacute Ograve -70 KPX Yacute Ohungarumlaut -70 KPX Yacute Omacron -70 KPX Yacute Oslash -70 KPX Yacute Otilde -70 KPX Yacute a -90 KPX Yacute aacute -90 KPX Yacute abreve -90 KPX Yacute acircumflex -90 KPX Yacute adieresis -90 KPX Yacute agrave -90 KPX Yacute amacron -90 KPX Yacute aogonek -90 KPX Yacute aring -90 KPX Yacute atilde -90 KPX Yacute colon -50 KPX Yacute comma -100 KPX Yacute e -80 KPX Yacute eacute -80 KPX Yacute ecaron -80 KPX Yacute ecircumflex -80 KPX Yacute edieresis -80 KPX Yacute edotaccent -80 KPX Yacute egrave -80 KPX Yacute emacron -80 KPX Yacute eogonek -80 KPX Yacute o -100 KPX Yacute oacute -100 KPX Yacute ocircumflex -100 KPX Yacute odieresis -100 KPX Yacute ograve -100 KPX Yacute ohungarumlaut -100 KPX Yacute omacron -100 KPX Yacute oslash -100 KPX Yacute otilde -100 KPX Yacute period -100 KPX Yacute semicolon -50 KPX Yacute u -100 KPX Yacute uacute -100 KPX Yacute ucircumflex -100 KPX Yacute udieresis -100 KPX Yacute ugrave -100 KPX Yacute uhungarumlaut -100 KPX Yacute umacron -100 KPX Yacute uogonek -100 KPX Yacute uring -100 KPX Ydieresis A -110 KPX Ydieresis Aacute -110 KPX Ydieresis Abreve -110 KPX Ydieresis Acircumflex -110 KPX Ydieresis Adieresis -110 KPX Ydieresis Agrave -110 KPX Ydieresis Amacron -110 KPX Ydieresis Aogonek -110 KPX Ydieresis Aring -110 KPX Ydieresis Atilde -110 KPX Ydieresis O -70 KPX Ydieresis Oacute -70 KPX Ydieresis Ocircumflex -70 KPX Ydieresis Odieresis -70 KPX Ydieresis Ograve -70 KPX Ydieresis Ohungarumlaut -70 KPX Ydieresis Omacron -70 KPX Ydieresis Oslash -70 KPX Ydieresis Otilde -70 KPX Ydieresis a -90 KPX Ydieresis aacute -90 KPX Ydieresis abreve -90 KPX Ydieresis acircumflex -90 KPX Ydieresis adieresis -90 KPX Ydieresis agrave -90 KPX Ydieresis amacron -90 KPX Ydieresis aogonek -90 KPX Ydieresis aring -90 KPX Ydieresis atilde -90 KPX Ydieresis colon -50 KPX Ydieresis comma -100 KPX Ydieresis e -80 KPX Ydieresis eacute -80 KPX Ydieresis ecaron -80 KPX Ydieresis ecircumflex -80 KPX Ydieresis edieresis -80 KPX Ydieresis edotaccent -80 KPX Ydieresis egrave -80 KPX Ydieresis emacron -80 KPX Ydieresis eogonek -80 KPX Ydieresis o -100 KPX Ydieresis oacute -100 KPX Ydieresis ocircumflex -100 KPX Ydieresis odieresis -100 KPX Ydieresis ograve -100 KPX Ydieresis ohungarumlaut -100 KPX Ydieresis omacron -100 KPX Ydieresis oslash -100 KPX Ydieresis otilde -100 KPX Ydieresis period -100 KPX Ydieresis semicolon -50 KPX Ydieresis u -100 KPX Ydieresis uacute -100 KPX Ydieresis ucircumflex -100 KPX Ydieresis udieresis -100 KPX Ydieresis ugrave -100 KPX Ydieresis uhungarumlaut -100 KPX Ydieresis umacron -100 KPX Ydieresis uogonek -100 KPX Ydieresis uring -100 KPX a g -10 KPX a gbreve -10 KPX a gcommaaccent -10 KPX a v -15 KPX a w -15 KPX a y -20 KPX a yacute -20 KPX a ydieresis -20 KPX aacute g -10 KPX aacute gbreve -10 KPX aacute gcommaaccent -10 KPX aacute v -15 KPX aacute w -15 KPX aacute y -20 KPX aacute yacute -20 KPX aacute ydieresis -20 KPX abreve g -10 KPX abreve gbreve -10 KPX abreve gcommaaccent -10 KPX abreve v -15 KPX abreve w -15 KPX abreve y -20 KPX abreve yacute -20 KPX abreve ydieresis -20 KPX acircumflex g -10 KPX acircumflex gbreve -10 KPX acircumflex gcommaaccent -10 KPX acircumflex v -15 KPX acircumflex w -15 KPX acircumflex y -20 KPX acircumflex yacute -20 KPX acircumflex ydieresis -20 KPX adieresis g -10 KPX adieresis gbreve -10 KPX adieresis gcommaaccent -10 KPX adieresis v -15 KPX adieresis w -15 KPX adieresis y -20 KPX adieresis yacute -20 KPX adieresis ydieresis -20 KPX agrave g -10 KPX agrave gbreve -10 KPX agrave gcommaaccent -10 KPX agrave v -15 KPX agrave w -15 KPX agrave y -20 KPX agrave yacute -20 KPX agrave ydieresis -20 KPX amacron g -10 KPX amacron gbreve -10 KPX amacron gcommaaccent -10 KPX amacron v -15 KPX amacron w -15 KPX amacron y -20 KPX amacron yacute -20 KPX amacron ydieresis -20 KPX aogonek g -10 KPX aogonek gbreve -10 KPX aogonek gcommaaccent -10 KPX aogonek v -15 KPX aogonek w -15 KPX aogonek y -20 KPX aogonek yacute -20 KPX aogonek ydieresis -20 KPX aring g -10 KPX aring gbreve -10 KPX aring gcommaaccent -10 KPX aring v -15 KPX aring w -15 KPX aring y -20 KPX aring yacute -20 KPX aring ydieresis -20 KPX atilde g -10 KPX atilde gbreve -10 KPX atilde gcommaaccent -10 KPX atilde v -15 KPX atilde w -15 KPX atilde y -20 KPX atilde yacute -20 KPX atilde ydieresis -20 KPX b l -10 KPX b lacute -10 KPX b lcommaaccent -10 KPX b lslash -10 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -20 KPX b y -20 KPX b yacute -20 KPX b ydieresis -20 KPX c h -10 KPX c k -20 KPX c kcommaaccent -20 KPX c l -20 KPX c lacute -20 KPX c lcommaaccent -20 KPX c lslash -20 KPX c y -10 KPX c yacute -10 KPX c ydieresis -10 KPX cacute h -10 KPX cacute k -20 KPX cacute kcommaaccent -20 KPX cacute l -20 KPX cacute lacute -20 KPX cacute lcommaaccent -20 KPX cacute lslash -20 KPX cacute y -10 KPX cacute yacute -10 KPX cacute ydieresis -10 KPX ccaron h -10 KPX ccaron k -20 KPX ccaron kcommaaccent -20 KPX ccaron l -20 KPX ccaron lacute -20 KPX ccaron lcommaaccent -20 KPX ccaron lslash -20 KPX ccaron y -10 KPX ccaron yacute -10 KPX ccaron ydieresis -10 KPX ccedilla h -10 KPX ccedilla k -20 KPX ccedilla kcommaaccent -20 KPX ccedilla l -20 KPX ccedilla lacute -20 KPX ccedilla lcommaaccent -20 KPX ccedilla lslash -20 KPX ccedilla y -10 KPX ccedilla yacute -10 KPX ccedilla ydieresis -10 KPX colon space -40 KPX comma quotedblright -120 KPX comma quoteright -120 KPX comma space -40 KPX d d -10 KPX d dcroat -10 KPX d v -15 KPX d w -15 KPX d y -15 KPX d yacute -15 KPX d ydieresis -15 KPX dcroat d -10 KPX dcroat dcroat -10 KPX dcroat v -15 KPX dcroat w -15 KPX dcroat y -15 KPX dcroat yacute -15 KPX dcroat ydieresis -15 KPX e comma 10 KPX e period 20 KPX e v -15 KPX e w -15 KPX e x -15 KPX e y -15 KPX e yacute -15 KPX e ydieresis -15 KPX eacute comma 10 KPX eacute period 20 KPX eacute v -15 KPX eacute w -15 KPX eacute x -15 KPX eacute y -15 KPX eacute yacute -15 KPX eacute ydieresis -15 KPX ecaron comma 10 KPX ecaron period 20 KPX ecaron v -15 KPX ecaron w -15 KPX ecaron x -15 KPX ecaron y -15 KPX ecaron yacute -15 KPX ecaron ydieresis -15 KPX ecircumflex comma 10 KPX ecircumflex period 20 KPX ecircumflex v -15 KPX ecircumflex w -15 KPX ecircumflex x -15 KPX ecircumflex y -15 KPX ecircumflex yacute -15 KPX ecircumflex ydieresis -15 KPX edieresis comma 10 KPX edieresis period 20 KPX edieresis v -15 KPX edieresis w -15 KPX edieresis x -15 KPX edieresis y -15 KPX edieresis yacute -15 KPX edieresis ydieresis -15 KPX edotaccent comma 10 KPX edotaccent period 20 KPX edotaccent v -15 KPX edotaccent w -15 KPX edotaccent x -15 KPX edotaccent y -15 KPX edotaccent yacute -15 KPX edotaccent ydieresis -15 KPX egrave comma 10 KPX egrave period 20 KPX egrave v -15 KPX egrave w -15 KPX egrave x -15 KPX egrave y -15 KPX egrave yacute -15 KPX egrave ydieresis -15 KPX emacron comma 10 KPX emacron period 20 KPX emacron v -15 KPX emacron w -15 KPX emacron x -15 KPX emacron y -15 KPX emacron yacute -15 KPX emacron ydieresis -15 KPX eogonek comma 10 KPX eogonek period 20 KPX eogonek v -15 KPX eogonek w -15 KPX eogonek x -15 KPX eogonek y -15 KPX eogonek yacute -15 KPX eogonek ydieresis -15 KPX f comma -10 KPX f e -10 KPX f eacute -10 KPX f ecaron -10 KPX f ecircumflex -10 KPX f edieresis -10 KPX f edotaccent -10 KPX f egrave -10 KPX f emacron -10 KPX f eogonek -10 KPX f o -20 KPX f oacute -20 KPX f ocircumflex -20 KPX f odieresis -20 KPX f ograve -20 KPX f ohungarumlaut -20 KPX f omacron -20 KPX f oslash -20 KPX f otilde -20 KPX f period -10 KPX f quotedblright 30 KPX f quoteright 30 KPX g e 10 KPX g eacute 10 KPX g ecaron 10 KPX g ecircumflex 10 KPX g edieresis 10 KPX g edotaccent 10 KPX g egrave 10 KPX g emacron 10 KPX g eogonek 10 KPX g g -10 KPX g gbreve -10 KPX g gcommaaccent -10 KPX gbreve e 10 KPX gbreve eacute 10 KPX gbreve ecaron 10 KPX gbreve ecircumflex 10 KPX gbreve edieresis 10 KPX gbreve edotaccent 10 KPX gbreve egrave 10 KPX gbreve emacron 10 KPX gbreve eogonek 10 KPX gbreve g -10 KPX gbreve gbreve -10 KPX gbreve gcommaaccent -10 KPX gcommaaccent e 10 KPX gcommaaccent eacute 10 KPX gcommaaccent ecaron 10 KPX gcommaaccent ecircumflex 10 KPX gcommaaccent edieresis 10 KPX gcommaaccent edotaccent 10 KPX gcommaaccent egrave 10 KPX gcommaaccent emacron 10 KPX gcommaaccent eogonek 10 KPX gcommaaccent g -10 KPX gcommaaccent gbreve -10 KPX gcommaaccent gcommaaccent -10 KPX h y -20 KPX h yacute -20 KPX h ydieresis -20 KPX k o -15 KPX k oacute -15 KPX k ocircumflex -15 KPX k odieresis -15 KPX k ograve -15 KPX k ohungarumlaut -15 KPX k omacron -15 KPX k oslash -15 KPX k otilde -15 KPX kcommaaccent o -15 KPX kcommaaccent oacute -15 KPX kcommaaccent ocircumflex -15 KPX kcommaaccent odieresis -15 KPX kcommaaccent ograve -15 KPX kcommaaccent ohungarumlaut -15 KPX kcommaaccent omacron -15 KPX kcommaaccent oslash -15 KPX kcommaaccent otilde -15 KPX l w -15 KPX l y -15 KPX l yacute -15 KPX l ydieresis -15 KPX lacute w -15 KPX lacute y -15 KPX lacute yacute -15 KPX lacute ydieresis -15 KPX lcommaaccent w -15 KPX lcommaaccent y -15 KPX lcommaaccent yacute -15 KPX lcommaaccent ydieresis -15 KPX lslash w -15 KPX lslash y -15 KPX lslash yacute -15 KPX lslash ydieresis -15 KPX m u -20 KPX m uacute -20 KPX m ucircumflex -20 KPX m udieresis -20 KPX m ugrave -20 KPX m uhungarumlaut -20 KPX m umacron -20 KPX m uogonek -20 KPX m uring -20 KPX m y -30 KPX m yacute -30 KPX m ydieresis -30 KPX n u -10 KPX n uacute -10 KPX n ucircumflex -10 KPX n udieresis -10 KPX n ugrave -10 KPX n uhungarumlaut -10 KPX n umacron -10 KPX n uogonek -10 KPX n uring -10 KPX n v -40 KPX n y -20 KPX n yacute -20 KPX n ydieresis -20 KPX nacute u -10 KPX nacute uacute -10 KPX nacute ucircumflex -10 KPX nacute udieresis -10 KPX nacute ugrave -10 KPX nacute uhungarumlaut -10 KPX nacute umacron -10 KPX nacute uogonek -10 KPX nacute uring -10 KPX nacute v -40 KPX nacute y -20 KPX nacute yacute -20 KPX nacute ydieresis -20 KPX ncaron u -10 KPX ncaron uacute -10 KPX ncaron ucircumflex -10 KPX ncaron udieresis -10 KPX ncaron ugrave -10 KPX ncaron uhungarumlaut -10 KPX ncaron umacron -10 KPX ncaron uogonek -10 KPX ncaron uring -10 KPX ncaron v -40 KPX ncaron y -20 KPX ncaron yacute -20 KPX ncaron ydieresis -20 KPX ncommaaccent u -10 KPX ncommaaccent uacute -10 KPX ncommaaccent ucircumflex -10 KPX ncommaaccent udieresis -10 KPX ncommaaccent ugrave -10 KPX ncommaaccent uhungarumlaut -10 KPX ncommaaccent umacron -10 KPX ncommaaccent uogonek -10 KPX ncommaaccent uring -10 KPX ncommaaccent v -40 KPX ncommaaccent y -20 KPX ncommaaccent yacute -20 KPX ncommaaccent ydieresis -20 KPX ntilde u -10 KPX ntilde uacute -10 KPX ntilde ucircumflex -10 KPX ntilde udieresis -10 KPX ntilde ugrave -10 KPX ntilde uhungarumlaut -10 KPX ntilde umacron -10 KPX ntilde uogonek -10 KPX ntilde uring -10 KPX ntilde v -40 KPX ntilde y -20 KPX ntilde yacute -20 KPX ntilde ydieresis -20 KPX o v -20 KPX o w -15 KPX o x -30 KPX o y -20 KPX o yacute -20 KPX o ydieresis -20 KPX oacute v -20 KPX oacute w -15 KPX oacute x -30 KPX oacute y -20 KPX oacute yacute -20 KPX oacute ydieresis -20 KPX ocircumflex v -20 KPX ocircumflex w -15 KPX ocircumflex x -30 KPX ocircumflex y -20 KPX ocircumflex yacute -20 KPX ocircumflex ydieresis -20 KPX odieresis v -20 KPX odieresis w -15 KPX odieresis x -30 KPX odieresis y -20 KPX odieresis yacute -20 KPX odieresis ydieresis -20 KPX ograve v -20 KPX ograve w -15 KPX ograve x -30 KPX ograve y -20 KPX ograve yacute -20 KPX ograve ydieresis -20 KPX ohungarumlaut v -20 KPX ohungarumlaut w -15 KPX ohungarumlaut x -30 KPX ohungarumlaut y -20 KPX ohungarumlaut yacute -20 KPX ohungarumlaut ydieresis -20 KPX omacron v -20 KPX omacron w -15 KPX omacron x -30 KPX omacron y -20 KPX omacron yacute -20 KPX omacron ydieresis -20 KPX oslash v -20 KPX oslash w -15 KPX oslash x -30 KPX oslash y -20 KPX oslash yacute -20 KPX oslash ydieresis -20 KPX otilde v -20 KPX otilde w -15 KPX otilde x -30 KPX otilde y -20 KPX otilde yacute -20 KPX otilde ydieresis -20 KPX p y -15 KPX p yacute -15 KPX p ydieresis -15 KPX period quotedblright -120 KPX period quoteright -120 KPX period space -40 KPX quotedblright space -80 KPX quoteleft quoteleft -46 KPX quoteright d -80 KPX quoteright dcroat -80 KPX quoteright l -20 KPX quoteright lacute -20 KPX quoteright lcommaaccent -20 KPX quoteright lslash -20 KPX quoteright quoteright -46 KPX quoteright r -40 KPX quoteright racute -40 KPX quoteright rcaron -40 KPX quoteright rcommaaccent -40 KPX quoteright s -60 KPX quoteright sacute -60 KPX quoteright scaron -60 KPX quoteright scedilla -60 KPX quoteright scommaaccent -60 KPX quoteright space -80 KPX quoteright v -20 KPX r c -20 KPX r cacute -20 KPX r ccaron -20 KPX r ccedilla -20 KPX r comma -60 KPX r d -20 KPX r dcroat -20 KPX r g -15 KPX r gbreve -15 KPX r gcommaaccent -15 KPX r hyphen -20 KPX r o -20 KPX r oacute -20 KPX r ocircumflex -20 KPX r odieresis -20 KPX r ograve -20 KPX r ohungarumlaut -20 KPX r omacron -20 KPX r oslash -20 KPX r otilde -20 KPX r period -60 KPX r q -20 KPX r s -15 KPX r sacute -15 KPX r scaron -15 KPX r scedilla -15 KPX r scommaaccent -15 KPX r t 20 KPX r tcommaaccent 20 KPX r v 10 KPX r y 10 KPX r yacute 10 KPX r ydieresis 10 KPX racute c -20 KPX racute cacute -20 KPX racute ccaron -20 KPX racute ccedilla -20 KPX racute comma -60 KPX racute d -20 KPX racute dcroat -20 KPX racute g -15 KPX racute gbreve -15 KPX racute gcommaaccent -15 KPX racute hyphen -20 KPX racute o -20 KPX racute oacute -20 KPX racute ocircumflex -20 KPX racute odieresis -20 KPX racute ograve -20 KPX racute ohungarumlaut -20 KPX racute omacron -20 KPX racute oslash -20 KPX racute otilde -20 KPX racute period -60 KPX racute q -20 KPX racute s -15 KPX racute sacute -15 KPX racute scaron -15 KPX racute scedilla -15 KPX racute scommaaccent -15 KPX racute t 20 KPX racute tcommaaccent 20 KPX racute v 10 KPX racute y 10 KPX racute yacute 10 KPX racute ydieresis 10 KPX rcaron c -20 KPX rcaron cacute -20 KPX rcaron ccaron -20 KPX rcaron ccedilla -20 KPX rcaron comma -60 KPX rcaron d -20 KPX rcaron dcroat -20 KPX rcaron g -15 KPX rcaron gbreve -15 KPX rcaron gcommaaccent -15 KPX rcaron hyphen -20 KPX rcaron o -20 KPX rcaron oacute -20 KPX rcaron ocircumflex -20 KPX rcaron odieresis -20 KPX rcaron ograve -20 KPX rcaron ohungarumlaut -20 KPX rcaron omacron -20 KPX rcaron oslash -20 KPX rcaron otilde -20 KPX rcaron period -60 KPX rcaron q -20 KPX rcaron s -15 KPX rcaron sacute -15 KPX rcaron scaron -15 KPX rcaron scedilla -15 KPX rcaron scommaaccent -15 KPX rcaron t 20 KPX rcaron tcommaaccent 20 KPX rcaron v 10 KPX rcaron y 10 KPX rcaron yacute 10 KPX rcaron ydieresis 10 KPX rcommaaccent c -20 KPX rcommaaccent cacute -20 KPX rcommaaccent ccaron -20 KPX rcommaaccent ccedilla -20 KPX rcommaaccent comma -60 KPX rcommaaccent d -20 KPX rcommaaccent dcroat -20 KPX rcommaaccent g -15 KPX rcommaaccent gbreve -15 KPX rcommaaccent gcommaaccent -15 KPX rcommaaccent hyphen -20 KPX rcommaaccent o -20 KPX rcommaaccent oacute -20 KPX rcommaaccent ocircumflex -20 KPX rcommaaccent odieresis -20 KPX rcommaaccent ograve -20 KPX rcommaaccent ohungarumlaut -20 KPX rcommaaccent omacron -20 KPX rcommaaccent oslash -20 KPX rcommaaccent otilde -20 KPX rcommaaccent period -60 KPX rcommaaccent q -20 KPX rcommaaccent s -15 KPX rcommaaccent sacute -15 KPX rcommaaccent scaron -15 KPX rcommaaccent scedilla -15 KPX rcommaaccent scommaaccent -15 KPX rcommaaccent t 20 KPX rcommaaccent tcommaaccent 20 KPX rcommaaccent v 10 KPX rcommaaccent y 10 KPX rcommaaccent yacute 10 KPX rcommaaccent ydieresis 10 KPX s w -15 KPX sacute w -15 KPX scaron w -15 KPX scedilla w -15 KPX scommaaccent w -15 KPX semicolon space -40 KPX space T -100 KPX space Tcaron -100 KPX space Tcommaaccent -100 KPX space V -80 KPX space W -80 KPX space Y -120 KPX space Yacute -120 KPX space Ydieresis -120 KPX space quotedblleft -80 KPX space quoteleft -60 KPX v a -20 KPX v aacute -20 KPX v abreve -20 KPX v acircumflex -20 KPX v adieresis -20 KPX v agrave -20 KPX v amacron -20 KPX v aogonek -20 KPX v aring -20 KPX v atilde -20 KPX v comma -80 KPX v o -30 KPX v oacute -30 KPX v ocircumflex -30 KPX v odieresis -30 KPX v ograve -30 KPX v ohungarumlaut -30 KPX v omacron -30 KPX v oslash -30 KPX v otilde -30 KPX v period -80 KPX w comma -40 KPX w o -20 KPX w oacute -20 KPX w ocircumflex -20 KPX w odieresis -20 KPX w ograve -20 KPX w ohungarumlaut -20 KPX w omacron -20 KPX w oslash -20 KPX w otilde -20 KPX w period -40 KPX x e -10 KPX x eacute -10 KPX x ecaron -10 KPX x ecircumflex -10 KPX x edieresis -10 KPX x edotaccent -10 KPX x egrave -10 KPX x emacron -10 KPX x eogonek -10 KPX y a -30 KPX y aacute -30 KPX y abreve -30 KPX y acircumflex -30 KPX y adieresis -30 KPX y agrave -30 KPX y amacron -30 KPX y aogonek -30 KPX y aring -30 KPX y atilde -30 KPX y comma -80 KPX y e -10 KPX y eacute -10 KPX y ecaron -10 KPX y ecircumflex -10 KPX y edieresis -10 KPX y edotaccent -10 KPX y egrave -10 KPX y emacron -10 KPX y eogonek -10 KPX y o -25 KPX y oacute -25 KPX y ocircumflex -25 KPX y odieresis -25 KPX y ograve -25 KPX y ohungarumlaut -25 KPX y omacron -25 KPX y oslash -25 KPX y otilde -25 KPX y period -80 KPX yacute a -30 KPX yacute aacute -30 KPX yacute abreve -30 KPX yacute acircumflex -30 KPX yacute adieresis -30 KPX yacute agrave -30 KPX yacute amacron -30 KPX yacute aogonek -30 KPX yacute aring -30 KPX yacute atilde -30 KPX yacute comma -80 KPX yacute e -10 KPX yacute eacute -10 KPX yacute ecaron -10 KPX yacute ecircumflex -10 KPX yacute edieresis -10 KPX yacute edotaccent -10 KPX yacute egrave -10 KPX yacute emacron -10 KPX yacute eogonek -10 KPX yacute o -25 KPX yacute oacute -25 KPX yacute ocircumflex -25 KPX yacute odieresis -25 KPX yacute ograve -25 KPX yacute ohungarumlaut -25 KPX yacute omacron -25 KPX yacute oslash -25 KPX yacute otilde -25 KPX yacute period -80 KPX ydieresis a -30 KPX ydieresis aacute -30 KPX ydieresis abreve -30 KPX ydieresis acircumflex -30 KPX ydieresis adieresis -30 KPX ydieresis agrave -30 KPX ydieresis amacron -30 KPX ydieresis aogonek -30 KPX ydieresis aring -30 KPX ydieresis atilde -30 KPX ydieresis comma -80 KPX ydieresis e -10 KPX ydieresis eacute -10 KPX ydieresis ecaron -10 KPX ydieresis ecircumflex -10 KPX ydieresis edieresis -10 KPX ydieresis edotaccent -10 KPX ydieresis egrave -10 KPX ydieresis emacron -10 KPX ydieresis eogonek -10 KPX ydieresis o -25 KPX ydieresis oacute -25 KPX ydieresis ocircumflex -25 KPX ydieresis odieresis -25 KPX ydieresis ograve -25 KPX ydieresis ohungarumlaut -25 KPX ydieresis omacron -25 KPX ydieresis oslash -25 KPX ydieresis otilde -25 KPX ydieresis period -80 KPX z e 10 KPX z eacute 10 KPX z ecaron 10 KPX z ecircumflex 10 KPX z edieresis 10 KPX z edotaccent 10 KPX z egrave 10 KPX z emacron 10 KPX z eogonek 10 KPX zacute e 10 KPX zacute eacute 10 KPX zacute ecaron 10 KPX zacute ecircumflex 10 KPX zacute edieresis 10 KPX zacute edotaccent 10 KPX zacute egrave 10 KPX zacute emacron 10 KPX zacute eogonek 10 KPX zcaron e 10 KPX zcaron eacute 10 KPX zcaron ecaron 10 KPX zcaron ecircumflex 10 KPX zcaron edieresis 10 KPX zcaron edotaccent 10 KPX zcaron egrave 10 KPX zcaron emacron 10 KPX zcaron eogonek 10 KPX zdotaccent e 10 KPX zdotaccent eacute 10 KPX zdotaccent ecaron 10 KPX zdotaccent ecircumflex 10 KPX zdotaccent edieresis 10 KPX zdotaccent edotaccent 10 KPX zdotaccent egrave 10 KPX zdotaccent emacron 10 KPX zdotaccent eogonek 10 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Helvetica-BoldOblique.afm0000644000076500000240000021500012037547555021630 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:45:12 1997 Comment UniqueID 43053 Comment VMusage 14482 68586 FontName Helvetica-BoldOblique FullName Helvetica Bold Oblique FamilyName Helvetica Weight Bold ItalicAngle -12 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -174 -228 1114 962 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 718 XHeight 532 Ascender 718 Descender -207 StdHW 118 StdVW 140 StartCharMetrics 315 C 32 ; WX 278 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 94 0 397 718 ; C 34 ; WX 474 ; N quotedbl ; B 193 447 529 718 ; C 35 ; WX 556 ; N numbersign ; B 60 0 644 698 ; C 36 ; WX 556 ; N dollar ; B 67 -115 622 775 ; C 37 ; WX 889 ; N percent ; B 136 -19 901 710 ; C 38 ; WX 722 ; N ampersand ; B 89 -19 732 718 ; C 39 ; WX 278 ; N quoteright ; B 167 445 362 718 ; C 40 ; WX 333 ; N parenleft ; B 76 -208 470 734 ; C 41 ; WX 333 ; N parenright ; B -25 -208 369 734 ; C 42 ; WX 389 ; N asterisk ; B 146 387 481 718 ; C 43 ; WX 584 ; N plus ; B 82 0 610 506 ; C 44 ; WX 278 ; N comma ; B 28 -168 245 146 ; C 45 ; WX 333 ; N hyphen ; B 73 215 379 345 ; C 46 ; WX 278 ; N period ; B 64 0 245 146 ; C 47 ; WX 278 ; N slash ; B -37 -19 468 737 ; C 48 ; WX 556 ; N zero ; B 86 -19 617 710 ; C 49 ; WX 556 ; N one ; B 173 0 529 710 ; C 50 ; WX 556 ; N two ; B 26 0 619 710 ; C 51 ; WX 556 ; N three ; B 65 -19 608 710 ; C 52 ; WX 556 ; N four ; B 60 0 598 710 ; C 53 ; WX 556 ; N five ; B 64 -19 636 698 ; C 54 ; WX 556 ; N six ; B 85 -19 619 710 ; C 55 ; WX 556 ; N seven ; B 125 0 676 698 ; C 56 ; WX 556 ; N eight ; B 69 -19 616 710 ; C 57 ; WX 556 ; N nine ; B 78 -19 615 710 ; C 58 ; WX 333 ; N colon ; B 92 0 351 512 ; C 59 ; WX 333 ; N semicolon ; B 56 -168 351 512 ; C 60 ; WX 584 ; N less ; B 82 -8 655 514 ; C 61 ; WX 584 ; N equal ; B 58 87 633 419 ; C 62 ; WX 584 ; N greater ; B 36 -8 609 514 ; C 63 ; WX 611 ; N question ; B 165 0 671 727 ; C 64 ; WX 975 ; N at ; B 186 -19 954 737 ; C 65 ; WX 722 ; N A ; B 20 0 702 718 ; C 66 ; WX 722 ; N B ; B 76 0 764 718 ; C 67 ; WX 722 ; N C ; B 107 -19 789 737 ; C 68 ; WX 722 ; N D ; B 76 0 777 718 ; C 69 ; WX 667 ; N E ; B 76 0 757 718 ; C 70 ; WX 611 ; N F ; B 76 0 740 718 ; C 71 ; WX 778 ; N G ; B 108 -19 817 737 ; C 72 ; WX 722 ; N H ; B 71 0 804 718 ; C 73 ; WX 278 ; N I ; B 64 0 367 718 ; C 74 ; WX 556 ; N J ; B 60 -18 637 718 ; C 75 ; WX 722 ; N K ; B 87 0 858 718 ; C 76 ; WX 611 ; N L ; B 76 0 611 718 ; C 77 ; WX 833 ; N M ; B 69 0 918 718 ; C 78 ; WX 722 ; N N ; B 69 0 807 718 ; C 79 ; WX 778 ; N O ; B 107 -19 823 737 ; C 80 ; WX 667 ; N P ; B 76 0 738 718 ; C 81 ; WX 778 ; N Q ; B 107 -52 823 737 ; C 82 ; WX 722 ; N R ; B 76 0 778 718 ; C 83 ; WX 667 ; N S ; B 81 -19 718 737 ; C 84 ; WX 611 ; N T ; B 140 0 751 718 ; C 85 ; WX 722 ; N U ; B 116 -19 804 718 ; C 86 ; WX 667 ; N V ; B 172 0 801 718 ; C 87 ; WX 944 ; N W ; B 169 0 1082 718 ; C 88 ; WX 667 ; N X ; B 14 0 791 718 ; C 89 ; WX 667 ; N Y ; B 168 0 806 718 ; C 90 ; WX 611 ; N Z ; B 25 0 737 718 ; C 91 ; WX 333 ; N bracketleft ; B 21 -196 462 722 ; C 92 ; WX 278 ; N backslash ; B 124 -19 307 737 ; C 93 ; WX 333 ; N bracketright ; B -18 -196 423 722 ; C 94 ; WX 584 ; N asciicircum ; B 131 323 591 698 ; C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ; C 96 ; WX 278 ; N quoteleft ; B 165 454 361 727 ; C 97 ; WX 556 ; N a ; B 55 -14 583 546 ; C 98 ; WX 611 ; N b ; B 61 -14 645 718 ; C 99 ; WX 556 ; N c ; B 79 -14 599 546 ; C 100 ; WX 611 ; N d ; B 82 -14 704 718 ; C 101 ; WX 556 ; N e ; B 70 -14 593 546 ; C 102 ; WX 333 ; N f ; B 87 0 469 727 ; L i fi ; L l fl ; C 103 ; WX 611 ; N g ; B 38 -217 666 546 ; C 104 ; WX 611 ; N h ; B 65 0 629 718 ; C 105 ; WX 278 ; N i ; B 69 0 363 725 ; C 106 ; WX 278 ; N j ; B -42 -214 363 725 ; C 107 ; WX 556 ; N k ; B 69 0 670 718 ; C 108 ; WX 278 ; N l ; B 69 0 362 718 ; C 109 ; WX 889 ; N m ; B 64 0 909 546 ; C 110 ; WX 611 ; N n ; B 65 0 629 546 ; C 111 ; WX 611 ; N o ; B 82 -14 643 546 ; C 112 ; WX 611 ; N p ; B 18 -207 645 546 ; C 113 ; WX 611 ; N q ; B 80 -207 665 546 ; C 114 ; WX 389 ; N r ; B 64 0 489 546 ; C 115 ; WX 556 ; N s ; B 63 -14 584 546 ; C 116 ; WX 333 ; N t ; B 100 -6 422 676 ; C 117 ; WX 611 ; N u ; B 98 -14 658 532 ; C 118 ; WX 556 ; N v ; B 126 0 656 532 ; C 119 ; WX 778 ; N w ; B 123 0 882 532 ; C 120 ; WX 556 ; N x ; B 15 0 648 532 ; C 121 ; WX 556 ; N y ; B 42 -214 652 532 ; C 122 ; WX 500 ; N z ; B 20 0 583 532 ; C 123 ; WX 389 ; N braceleft ; B 94 -196 518 722 ; C 124 ; WX 280 ; N bar ; B 36 -225 361 775 ; C 125 ; WX 389 ; N braceright ; B -18 -196 407 722 ; C 126 ; WX 584 ; N asciitilde ; B 115 163 577 343 ; C 161 ; WX 333 ; N exclamdown ; B 50 -186 353 532 ; C 162 ; WX 556 ; N cent ; B 79 -118 599 628 ; C 163 ; WX 556 ; N sterling ; B 50 -16 635 718 ; C 164 ; WX 167 ; N fraction ; B -174 -19 487 710 ; C 165 ; WX 556 ; N yen ; B 60 0 713 698 ; C 166 ; WX 556 ; N florin ; B -50 -210 669 737 ; C 167 ; WX 556 ; N section ; B 61 -184 598 727 ; C 168 ; WX 556 ; N currency ; B 27 76 680 636 ; C 169 ; WX 238 ; N quotesingle ; B 165 447 321 718 ; C 170 ; WX 500 ; N quotedblleft ; B 160 454 588 727 ; C 171 ; WX 556 ; N guillemotleft ; B 135 76 571 484 ; C 172 ; WX 333 ; N guilsinglleft ; B 130 76 353 484 ; C 173 ; WX 333 ; N guilsinglright ; B 99 76 322 484 ; C 174 ; WX 611 ; N fi ; B 87 0 696 727 ; C 175 ; WX 611 ; N fl ; B 87 0 695 727 ; C 177 ; WX 556 ; N endash ; B 48 227 627 333 ; C 178 ; WX 556 ; N dagger ; B 118 -171 626 718 ; C 179 ; WX 556 ; N daggerdbl ; B 46 -171 628 718 ; C 180 ; WX 278 ; N periodcentered ; B 110 172 276 334 ; C 182 ; WX 556 ; N paragraph ; B 98 -191 688 700 ; C 183 ; WX 350 ; N bullet ; B 83 194 420 524 ; C 184 ; WX 278 ; N quotesinglbase ; B 41 -146 236 127 ; C 185 ; WX 500 ; N quotedblbase ; B 36 -146 463 127 ; C 186 ; WX 500 ; N quotedblright ; B 162 445 589 718 ; C 187 ; WX 556 ; N guillemotright ; B 104 76 540 484 ; C 188 ; WX 1000 ; N ellipsis ; B 92 0 939 146 ; C 189 ; WX 1000 ; N perthousand ; B 76 -19 1038 710 ; C 191 ; WX 611 ; N questiondown ; B 53 -195 559 532 ; C 193 ; WX 333 ; N grave ; B 136 604 353 750 ; C 194 ; WX 333 ; N acute ; B 236 604 515 750 ; C 195 ; WX 333 ; N circumflex ; B 118 604 471 750 ; C 196 ; WX 333 ; N tilde ; B 113 610 507 737 ; C 197 ; WX 333 ; N macron ; B 122 604 483 678 ; C 198 ; WX 333 ; N breve ; B 156 604 494 750 ; C 199 ; WX 333 ; N dotaccent ; B 235 614 385 729 ; C 200 ; WX 333 ; N dieresis ; B 137 614 482 729 ; C 202 ; WX 333 ; N ring ; B 200 568 420 776 ; C 203 ; WX 333 ; N cedilla ; B -37 -228 220 0 ; C 205 ; WX 333 ; N hungarumlaut ; B 137 604 645 750 ; C 206 ; WX 333 ; N ogonek ; B 41 -228 264 0 ; C 207 ; WX 333 ; N caron ; B 149 604 502 750 ; C 208 ; WX 1000 ; N emdash ; B 48 227 1071 333 ; C 225 ; WX 1000 ; N AE ; B 5 0 1100 718 ; C 227 ; WX 370 ; N ordfeminine ; B 125 401 465 737 ; C 232 ; WX 611 ; N Lslash ; B 34 0 611 718 ; C 233 ; WX 778 ; N Oslash ; B 35 -27 894 745 ; C 234 ; WX 1000 ; N OE ; B 99 -19 1114 737 ; C 235 ; WX 365 ; N ordmasculine ; B 123 401 485 737 ; C 241 ; WX 889 ; N ae ; B 56 -14 923 546 ; C 245 ; WX 278 ; N dotlessi ; B 69 0 322 532 ; C 248 ; WX 278 ; N lslash ; B 40 0 407 718 ; C 249 ; WX 611 ; N oslash ; B 22 -29 701 560 ; C 250 ; WX 944 ; N oe ; B 82 -14 977 546 ; C 251 ; WX 611 ; N germandbls ; B 69 -14 657 731 ; C -1 ; WX 278 ; N Idieresis ; B 64 0 494 915 ; C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ; C -1 ; WX 556 ; N abreve ; B 55 -14 606 750 ; C -1 ; WX 611 ; N uhungarumlaut ; B 98 -14 784 750 ; C -1 ; WX 556 ; N ecaron ; B 70 -14 614 750 ; C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ; C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ; C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ; C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ; C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ; C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ; C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ; C -1 ; WX 556 ; N scommaaccent ; B 63 -228 584 546 ; C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ; C -1 ; WX 722 ; N Uring ; B 116 -19 804 962 ; C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ; C -1 ; WX 556 ; N aogonek ; B 55 -224 583 546 ; C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ; C -1 ; WX 611 ; N uogonek ; B 98 -228 658 532 ; C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ; C -1 ; WX 722 ; N Dcroat ; B 62 0 777 718 ; C -1 ; WX 250 ; N commaaccent ; B 16 -228 188 -50 ; C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ; C -1 ; WX 667 ; N Emacron ; B 76 0 757 864 ; C -1 ; WX 556 ; N ccaron ; B 79 -14 614 750 ; C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ; C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 807 718 ; C -1 ; WX 278 ; N lacute ; B 69 0 528 936 ; C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ; C -1 ; WX 611 ; N Tcommaaccent ; B 140 -228 751 718 ; C -1 ; WX 722 ; N Cacute ; B 107 -19 789 936 ; C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ; C -1 ; WX 667 ; N Edotaccent ; B 76 0 757 915 ; C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ; C -1 ; WX 556 ; N scedilla ; B 63 -228 584 546 ; C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ; C -1 ; WX 494 ; N lozenge ; B 90 0 564 745 ; C -1 ; WX 722 ; N Rcaron ; B 76 0 778 936 ; C -1 ; WX 778 ; N Gcommaaccent ; B 108 -228 817 737 ; C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ; C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ; C -1 ; WX 722 ; N Amacron ; B 20 0 718 864 ; C -1 ; WX 389 ; N rcaron ; B 64 0 530 750 ; C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ; C -1 ; WX 611 ; N Zdotaccent ; B 25 0 737 915 ; C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ; C -1 ; WX 778 ; N Omacron ; B 107 -19 823 864 ; C -1 ; WX 722 ; N Racute ; B 76 0 778 936 ; C -1 ; WX 667 ; N Sacute ; B 81 -19 722 936 ; C -1 ; WX 743 ; N dcaron ; B 82 -14 903 718 ; C -1 ; WX 722 ; N Umacron ; B 116 -19 804 864 ; C -1 ; WX 611 ; N uring ; B 98 -14 658 776 ; C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ; C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ; C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ; C -1 ; WX 722 ; N Abreve ; B 20 0 729 936 ; C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ; C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ; C -1 ; WX 611 ; N Tcaron ; B 140 0 751 936 ; C -1 ; WX 494 ; N partialdiff ; B 43 -21 585 750 ; C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ; C -1 ; WX 722 ; N Nacute ; B 69 0 807 936 ; C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ; C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ; C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ; C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ; C -1 ; WX 556 ; N cacute ; B 79 -14 627 750 ; C -1 ; WX 611 ; N nacute ; B 65 0 654 750 ; C -1 ; WX 611 ; N umacron ; B 98 -14 658 678 ; C -1 ; WX 722 ; N Ncaron ; B 69 0 807 936 ; C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ; C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ; C -1 ; WX 280 ; N brokenbar ; B 52 -150 345 700 ; C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ; C -1 ; WX 778 ; N Gbreve ; B 108 -19 817 936 ; C -1 ; WX 278 ; N Idotaccent ; B 64 0 397 915 ; C -1 ; WX 600 ; N summation ; B 14 -10 670 706 ; C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ; C -1 ; WX 389 ; N racute ; B 64 0 543 750 ; C -1 ; WX 611 ; N omacron ; B 82 -14 643 678 ; C -1 ; WX 611 ; N Zacute ; B 25 0 737 936 ; C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 629 704 ; C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ; C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ; C -1 ; WX 278 ; N lcommaaccent ; B 30 -228 362 718 ; C -1 ; WX 389 ; N tcaron ; B 100 -6 608 878 ; C -1 ; WX 556 ; N eogonek ; B 70 -228 593 546 ; C -1 ; WX 722 ; N Uogonek ; B 116 -228 804 718 ; C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ; C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ; C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ; C -1 ; WX 500 ; N zacute ; B 20 0 599 750 ; C -1 ; WX 278 ; N iogonek ; B -14 -224 363 725 ; C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ; C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ; C -1 ; WX 556 ; N amacron ; B 55 -14 595 678 ; C -1 ; WX 556 ; N sacute ; B 63 -14 627 750 ; C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ; C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ; C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ; C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ; C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ; C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ; C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ; C -1 ; WX 611 ; N ohungarumlaut ; B 82 -14 784 750 ; C -1 ; WX 667 ; N Eogonek ; B 76 -224 757 718 ; C -1 ; WX 611 ; N dcroat ; B 82 -14 789 718 ; C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ; C -1 ; WX 667 ; N Scedilla ; B 81 -228 718 737 ; C -1 ; WX 400 ; N lcaron ; B 69 0 561 718 ; C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 858 718 ; C -1 ; WX 611 ; N Lacute ; B 76 0 611 936 ; C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ; C -1 ; WX 556 ; N edotaccent ; B 70 -14 593 729 ; C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ; C -1 ; WX 278 ; N Imacron ; B 64 0 496 864 ; C -1 ; WX 611 ; N Lcaron ; B 76 0 643 718 ; C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ; C -1 ; WX 549 ; N lessequal ; B 29 0 676 704 ; C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ; C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 116 -19 880 936 ; C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ; C -1 ; WX 556 ; N emacron ; B 70 -14 595 678 ; C -1 ; WX 611 ; N gbreve ; B 38 -217 666 750 ; C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ; C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ; C -1 ; WX 667 ; N Scommaaccent ; B 81 -228 718 737 ; C -1 ; WX 778 ; N Ohungarumlaut ; B 107 -19 908 936 ; C -1 ; WX 400 ; N degree ; B 175 426 467 712 ; C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ; C -1 ; WX 722 ; N Ccaron ; B 107 -19 789 936 ; C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ; C -1 ; WX 549 ; N radical ; B 112 -46 689 850 ; C -1 ; WX 722 ; N Dcaron ; B 76 0 777 936 ; C -1 ; WX 389 ; N rcommaaccent ; B 26 -228 489 546 ; C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ; C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ; C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 778 718 ; C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 611 718 ; C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ; C -1 ; WX 722 ; N Aogonek ; B 20 -224 702 718 ; C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ; C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ; C -1 ; WX 500 ; N zdotaccent ; B 20 0 583 729 ; C -1 ; WX 667 ; N Ecaron ; B 76 0 757 936 ; C -1 ; WX 278 ; N Iogonek ; B -41 -228 367 718 ; C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 670 718 ; C -1 ; WX 584 ; N minus ; B 82 197 610 309 ; C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ; C -1 ; WX 611 ; N ncaron ; B 65 0 641 750 ; C -1 ; WX 333 ; N tcommaaccent ; B 58 -228 422 676 ; C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ; C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ; C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ; C -1 ; WX 549 ; N notequal ; B 32 -49 630 570 ; C -1 ; WX 611 ; N gcommaaccent ; B 38 -217 666 850 ; C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ; C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ; C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 629 546 ; C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ; C -1 ; WX 278 ; N imacron ; B 69 0 429 678 ; C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2481 KPX A C -40 KPX A Cacute -40 KPX A Ccaron -40 KPX A Ccedilla -40 KPX A G -50 KPX A Gbreve -50 KPX A Gcommaaccent -50 KPX A O -40 KPX A Oacute -40 KPX A Ocircumflex -40 KPX A Odieresis -40 KPX A Ograve -40 KPX A Ohungarumlaut -40 KPX A Omacron -40 KPX A Oslash -40 KPX A Otilde -40 KPX A Q -40 KPX A T -90 KPX A Tcaron -90 KPX A Tcommaaccent -90 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -80 KPX A W -60 KPX A Y -110 KPX A Yacute -110 KPX A Ydieresis -110 KPX A u -30 KPX A uacute -30 KPX A ucircumflex -30 KPX A udieresis -30 KPX A ugrave -30 KPX A uhungarumlaut -30 KPX A umacron -30 KPX A uogonek -30 KPX A uring -30 KPX A v -40 KPX A w -30 KPX A y -30 KPX A yacute -30 KPX A ydieresis -30 KPX Aacute C -40 KPX Aacute Cacute -40 KPX Aacute Ccaron -40 KPX Aacute Ccedilla -40 KPX Aacute G -50 KPX Aacute Gbreve -50 KPX Aacute Gcommaaccent -50 KPX Aacute O -40 KPX Aacute Oacute -40 KPX Aacute Ocircumflex -40 KPX Aacute Odieresis -40 KPX Aacute Ograve -40 KPX Aacute Ohungarumlaut -40 KPX Aacute Omacron -40 KPX Aacute Oslash -40 KPX Aacute Otilde -40 KPX Aacute Q -40 KPX Aacute T -90 KPX Aacute Tcaron -90 KPX Aacute Tcommaaccent -90 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -80 KPX Aacute W -60 KPX Aacute Y -110 KPX Aacute Yacute -110 KPX Aacute Ydieresis -110 KPX Aacute u -30 KPX Aacute uacute -30 KPX Aacute ucircumflex -30 KPX Aacute udieresis -30 KPX Aacute ugrave -30 KPX Aacute uhungarumlaut -30 KPX Aacute umacron -30 KPX Aacute uogonek -30 KPX Aacute uring -30 KPX Aacute v -40 KPX Aacute w -30 KPX Aacute y -30 KPX Aacute yacute -30 KPX Aacute ydieresis -30 KPX Abreve C -40 KPX Abreve Cacute -40 KPX Abreve Ccaron -40 KPX Abreve Ccedilla -40 KPX Abreve G -50 KPX Abreve Gbreve -50 KPX Abreve Gcommaaccent -50 KPX Abreve O -40 KPX Abreve Oacute -40 KPX Abreve Ocircumflex -40 KPX Abreve Odieresis -40 KPX Abreve Ograve -40 KPX Abreve Ohungarumlaut -40 KPX Abreve Omacron -40 KPX Abreve Oslash -40 KPX Abreve Otilde -40 KPX Abreve Q -40 KPX Abreve T -90 KPX Abreve Tcaron -90 KPX Abreve Tcommaaccent -90 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -80 KPX Abreve W -60 KPX Abreve Y -110 KPX Abreve Yacute -110 KPX Abreve Ydieresis -110 KPX Abreve u -30 KPX Abreve uacute -30 KPX Abreve ucircumflex -30 KPX Abreve udieresis -30 KPX Abreve ugrave -30 KPX Abreve uhungarumlaut -30 KPX Abreve umacron -30 KPX Abreve uogonek -30 KPX Abreve uring -30 KPX Abreve v -40 KPX Abreve w -30 KPX Abreve y -30 KPX Abreve yacute -30 KPX Abreve ydieresis -30 KPX Acircumflex C -40 KPX Acircumflex Cacute -40 KPX Acircumflex Ccaron -40 KPX Acircumflex Ccedilla -40 KPX Acircumflex G -50 KPX Acircumflex Gbreve -50 KPX Acircumflex Gcommaaccent -50 KPX Acircumflex O -40 KPX Acircumflex Oacute -40 KPX Acircumflex Ocircumflex -40 KPX Acircumflex Odieresis -40 KPX Acircumflex Ograve -40 KPX Acircumflex Ohungarumlaut -40 KPX Acircumflex Omacron -40 KPX Acircumflex Oslash -40 KPX Acircumflex Otilde -40 KPX Acircumflex Q -40 KPX Acircumflex T -90 KPX Acircumflex Tcaron -90 KPX Acircumflex Tcommaaccent -90 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -80 KPX Acircumflex W -60 KPX Acircumflex Y -110 KPX Acircumflex Yacute -110 KPX Acircumflex Ydieresis -110 KPX Acircumflex u -30 KPX Acircumflex uacute -30 KPX Acircumflex ucircumflex -30 KPX Acircumflex udieresis -30 KPX Acircumflex ugrave -30 KPX Acircumflex uhungarumlaut -30 KPX Acircumflex umacron -30 KPX Acircumflex uogonek -30 KPX Acircumflex uring -30 KPX Acircumflex v -40 KPX Acircumflex w -30 KPX Acircumflex y -30 KPX Acircumflex yacute -30 KPX Acircumflex ydieresis -30 KPX Adieresis C -40 KPX Adieresis Cacute -40 KPX Adieresis Ccaron -40 KPX Adieresis Ccedilla -40 KPX Adieresis G -50 KPX Adieresis Gbreve -50 KPX Adieresis Gcommaaccent -50 KPX Adieresis O -40 KPX Adieresis Oacute -40 KPX Adieresis Ocircumflex -40 KPX Adieresis Odieresis -40 KPX Adieresis Ograve -40 KPX Adieresis Ohungarumlaut -40 KPX Adieresis Omacron -40 KPX Adieresis Oslash -40 KPX Adieresis Otilde -40 KPX Adieresis Q -40 KPX Adieresis T -90 KPX Adieresis Tcaron -90 KPX Adieresis Tcommaaccent -90 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -80 KPX Adieresis W -60 KPX Adieresis Y -110 KPX Adieresis Yacute -110 KPX Adieresis Ydieresis -110 KPX Adieresis u -30 KPX Adieresis uacute -30 KPX Adieresis ucircumflex -30 KPX Adieresis udieresis -30 KPX Adieresis ugrave -30 KPX Adieresis uhungarumlaut -30 KPX Adieresis umacron -30 KPX Adieresis uogonek -30 KPX Adieresis uring -30 KPX Adieresis v -40 KPX Adieresis w -30 KPX Adieresis y -30 KPX Adieresis yacute -30 KPX Adieresis ydieresis -30 KPX Agrave C -40 KPX Agrave Cacute -40 KPX Agrave Ccaron -40 KPX Agrave Ccedilla -40 KPX Agrave G -50 KPX Agrave Gbreve -50 KPX Agrave Gcommaaccent -50 KPX Agrave O -40 KPX Agrave Oacute -40 KPX Agrave Ocircumflex -40 KPX Agrave Odieresis -40 KPX Agrave Ograve -40 KPX Agrave Ohungarumlaut -40 KPX Agrave Omacron -40 KPX Agrave Oslash -40 KPX Agrave Otilde -40 KPX Agrave Q -40 KPX Agrave T -90 KPX Agrave Tcaron -90 KPX Agrave Tcommaaccent -90 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -80 KPX Agrave W -60 KPX Agrave Y -110 KPX Agrave Yacute -110 KPX Agrave Ydieresis -110 KPX Agrave u -30 KPX Agrave uacute -30 KPX Agrave ucircumflex -30 KPX Agrave udieresis -30 KPX Agrave ugrave -30 KPX Agrave uhungarumlaut -30 KPX Agrave umacron -30 KPX Agrave uogonek -30 KPX Agrave uring -30 KPX Agrave v -40 KPX Agrave w -30 KPX Agrave y -30 KPX Agrave yacute -30 KPX Agrave ydieresis -30 KPX Amacron C -40 KPX Amacron Cacute -40 KPX Amacron Ccaron -40 KPX Amacron Ccedilla -40 KPX Amacron G -50 KPX Amacron Gbreve -50 KPX Amacron Gcommaaccent -50 KPX Amacron O -40 KPX Amacron Oacute -40 KPX Amacron Ocircumflex -40 KPX Amacron Odieresis -40 KPX Amacron Ograve -40 KPX Amacron Ohungarumlaut -40 KPX Amacron Omacron -40 KPX Amacron Oslash -40 KPX Amacron Otilde -40 KPX Amacron Q -40 KPX Amacron T -90 KPX Amacron Tcaron -90 KPX Amacron Tcommaaccent -90 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -80 KPX Amacron W -60 KPX Amacron Y -110 KPX Amacron Yacute -110 KPX Amacron Ydieresis -110 KPX Amacron u -30 KPX Amacron uacute -30 KPX Amacron ucircumflex -30 KPX Amacron udieresis -30 KPX Amacron ugrave -30 KPX Amacron uhungarumlaut -30 KPX Amacron umacron -30 KPX Amacron uogonek -30 KPX Amacron uring -30 KPX Amacron v -40 KPX Amacron w -30 KPX Amacron y -30 KPX Amacron yacute -30 KPX Amacron ydieresis -30 KPX Aogonek C -40 KPX Aogonek Cacute -40 KPX Aogonek Ccaron -40 KPX Aogonek Ccedilla -40 KPX Aogonek G -50 KPX Aogonek Gbreve -50 KPX Aogonek Gcommaaccent -50 KPX Aogonek O -40 KPX Aogonek Oacute -40 KPX Aogonek Ocircumflex -40 KPX Aogonek Odieresis -40 KPX Aogonek Ograve -40 KPX Aogonek Ohungarumlaut -40 KPX Aogonek Omacron -40 KPX Aogonek Oslash -40 KPX Aogonek Otilde -40 KPX Aogonek Q -40 KPX Aogonek T -90 KPX Aogonek Tcaron -90 KPX Aogonek Tcommaaccent -90 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -80 KPX Aogonek W -60 KPX Aogonek Y -110 KPX Aogonek Yacute -110 KPX Aogonek Ydieresis -110 KPX Aogonek u -30 KPX Aogonek uacute -30 KPX Aogonek ucircumflex -30 KPX Aogonek udieresis -30 KPX Aogonek ugrave -30 KPX Aogonek uhungarumlaut -30 KPX Aogonek umacron -30 KPX Aogonek uogonek -30 KPX Aogonek uring -30 KPX Aogonek v -40 KPX Aogonek w -30 KPX Aogonek y -30 KPX Aogonek yacute -30 KPX Aogonek ydieresis -30 KPX Aring C -40 KPX Aring Cacute -40 KPX Aring Ccaron -40 KPX Aring Ccedilla -40 KPX Aring G -50 KPX Aring Gbreve -50 KPX Aring Gcommaaccent -50 KPX Aring O -40 KPX Aring Oacute -40 KPX Aring Ocircumflex -40 KPX Aring Odieresis -40 KPX Aring Ograve -40 KPX Aring Ohungarumlaut -40 KPX Aring Omacron -40 KPX Aring Oslash -40 KPX Aring Otilde -40 KPX Aring Q -40 KPX Aring T -90 KPX Aring Tcaron -90 KPX Aring Tcommaaccent -90 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -80 KPX Aring W -60 KPX Aring Y -110 KPX Aring Yacute -110 KPX Aring Ydieresis -110 KPX Aring u -30 KPX Aring uacute -30 KPX Aring ucircumflex -30 KPX Aring udieresis -30 KPX Aring ugrave -30 KPX Aring uhungarumlaut -30 KPX Aring umacron -30 KPX Aring uogonek -30 KPX Aring uring -30 KPX Aring v -40 KPX Aring w -30 KPX Aring y -30 KPX Aring yacute -30 KPX Aring ydieresis -30 KPX Atilde C -40 KPX Atilde Cacute -40 KPX Atilde Ccaron -40 KPX Atilde Ccedilla -40 KPX Atilde G -50 KPX Atilde Gbreve -50 KPX Atilde Gcommaaccent -50 KPX Atilde O -40 KPX Atilde Oacute -40 KPX Atilde Ocircumflex -40 KPX Atilde Odieresis -40 KPX Atilde Ograve -40 KPX Atilde Ohungarumlaut -40 KPX Atilde Omacron -40 KPX Atilde Oslash -40 KPX Atilde Otilde -40 KPX Atilde Q -40 KPX Atilde T -90 KPX Atilde Tcaron -90 KPX Atilde Tcommaaccent -90 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -80 KPX Atilde W -60 KPX Atilde Y -110 KPX Atilde Yacute -110 KPX Atilde Ydieresis -110 KPX Atilde u -30 KPX Atilde uacute -30 KPX Atilde ucircumflex -30 KPX Atilde udieresis -30 KPX Atilde ugrave -30 KPX Atilde uhungarumlaut -30 KPX Atilde umacron -30 KPX Atilde uogonek -30 KPX Atilde uring -30 KPX Atilde v -40 KPX Atilde w -30 KPX Atilde y -30 KPX Atilde yacute -30 KPX Atilde ydieresis -30 KPX B A -30 KPX B Aacute -30 KPX B Abreve -30 KPX B Acircumflex -30 KPX B Adieresis -30 KPX B Agrave -30 KPX B Amacron -30 KPX B Aogonek -30 KPX B Aring -30 KPX B Atilde -30 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -40 KPX D Aacute -40 KPX D Abreve -40 KPX D Acircumflex -40 KPX D Adieresis -40 KPX D Agrave -40 KPX D Amacron -40 KPX D Aogonek -40 KPX D Aring -40 KPX D Atilde -40 KPX D V -40 KPX D W -40 KPX D Y -70 KPX D Yacute -70 KPX D Ydieresis -70 KPX D comma -30 KPX D period -30 KPX Dcaron A -40 KPX Dcaron Aacute -40 KPX Dcaron Abreve -40 KPX Dcaron Acircumflex -40 KPX Dcaron Adieresis -40 KPX Dcaron Agrave -40 KPX Dcaron Amacron -40 KPX Dcaron Aogonek -40 KPX Dcaron Aring -40 KPX Dcaron Atilde -40 KPX Dcaron V -40 KPX Dcaron W -40 KPX Dcaron Y -70 KPX Dcaron Yacute -70 KPX Dcaron Ydieresis -70 KPX Dcaron comma -30 KPX Dcaron period -30 KPX Dcroat A -40 KPX Dcroat Aacute -40 KPX Dcroat Abreve -40 KPX Dcroat Acircumflex -40 KPX Dcroat Adieresis -40 KPX Dcroat Agrave -40 KPX Dcroat Amacron -40 KPX Dcroat Aogonek -40 KPX Dcroat Aring -40 KPX Dcroat Atilde -40 KPX Dcroat V -40 KPX Dcroat W -40 KPX Dcroat Y -70 KPX Dcroat Yacute -70 KPX Dcroat Ydieresis -70 KPX Dcroat comma -30 KPX Dcroat period -30 KPX F A -80 KPX F Aacute -80 KPX F Abreve -80 KPX F Acircumflex -80 KPX F Adieresis -80 KPX F Agrave -80 KPX F Amacron -80 KPX F Aogonek -80 KPX F Aring -80 KPX F Atilde -80 KPX F a -20 KPX F aacute -20 KPX F abreve -20 KPX F acircumflex -20 KPX F adieresis -20 KPX F agrave -20 KPX F amacron -20 KPX F aogonek -20 KPX F aring -20 KPX F atilde -20 KPX F comma -100 KPX F period -100 KPX J A -20 KPX J Aacute -20 KPX J Abreve -20 KPX J Acircumflex -20 KPX J Adieresis -20 KPX J Agrave -20 KPX J Amacron -20 KPX J Aogonek -20 KPX J Aring -20 KPX J Atilde -20 KPX J comma -20 KPX J period -20 KPX J u -20 KPX J uacute -20 KPX J ucircumflex -20 KPX J udieresis -20 KPX J ugrave -20 KPX J uhungarumlaut -20 KPX J umacron -20 KPX J uogonek -20 KPX J uring -20 KPX K O -30 KPX K Oacute -30 KPX K Ocircumflex -30 KPX K Odieresis -30 KPX K Ograve -30 KPX K Ohungarumlaut -30 KPX K Omacron -30 KPX K Oslash -30 KPX K Otilde -30 KPX K e -15 KPX K eacute -15 KPX K ecaron -15 KPX K ecircumflex -15 KPX K edieresis -15 KPX K edotaccent -15 KPX K egrave -15 KPX K emacron -15 KPX K eogonek -15 KPX K o -35 KPX K oacute -35 KPX K ocircumflex -35 KPX K odieresis -35 KPX K ograve -35 KPX K ohungarumlaut -35 KPX K omacron -35 KPX K oslash -35 KPX K otilde -35 KPX K u -30 KPX K uacute -30 KPX K ucircumflex -30 KPX K udieresis -30 KPX K ugrave -30 KPX K uhungarumlaut -30 KPX K umacron -30 KPX K uogonek -30 KPX K uring -30 KPX K y -40 KPX K yacute -40 KPX K ydieresis -40 KPX Kcommaaccent O -30 KPX Kcommaaccent Oacute -30 KPX Kcommaaccent Ocircumflex -30 KPX Kcommaaccent Odieresis -30 KPX Kcommaaccent Ograve -30 KPX Kcommaaccent Ohungarumlaut -30 KPX Kcommaaccent Omacron -30 KPX Kcommaaccent Oslash -30 KPX Kcommaaccent Otilde -30 KPX Kcommaaccent e -15 KPX Kcommaaccent eacute -15 KPX Kcommaaccent ecaron -15 KPX Kcommaaccent ecircumflex -15 KPX Kcommaaccent edieresis -15 KPX Kcommaaccent edotaccent -15 KPX Kcommaaccent egrave -15 KPX Kcommaaccent emacron -15 KPX Kcommaaccent eogonek -15 KPX Kcommaaccent o -35 KPX Kcommaaccent oacute -35 KPX Kcommaaccent ocircumflex -35 KPX Kcommaaccent odieresis -35 KPX Kcommaaccent ograve -35 KPX Kcommaaccent ohungarumlaut -35 KPX Kcommaaccent omacron -35 KPX Kcommaaccent oslash -35 KPX Kcommaaccent otilde -35 KPX Kcommaaccent u -30 KPX Kcommaaccent uacute -30 KPX Kcommaaccent ucircumflex -30 KPX Kcommaaccent udieresis -30 KPX Kcommaaccent ugrave -30 KPX Kcommaaccent uhungarumlaut -30 KPX Kcommaaccent umacron -30 KPX Kcommaaccent uogonek -30 KPX Kcommaaccent uring -30 KPX Kcommaaccent y -40 KPX Kcommaaccent yacute -40 KPX Kcommaaccent ydieresis -40 KPX L T -90 KPX L Tcaron -90 KPX L Tcommaaccent -90 KPX L V -110 KPX L W -80 KPX L Y -120 KPX L Yacute -120 KPX L Ydieresis -120 KPX L quotedblright -140 KPX L quoteright -140 KPX L y -30 KPX L yacute -30 KPX L ydieresis -30 KPX Lacute T -90 KPX Lacute Tcaron -90 KPX Lacute Tcommaaccent -90 KPX Lacute V -110 KPX Lacute W -80 KPX Lacute Y -120 KPX Lacute Yacute -120 KPX Lacute Ydieresis -120 KPX Lacute quotedblright -140 KPX Lacute quoteright -140 KPX Lacute y -30 KPX Lacute yacute -30 KPX Lacute ydieresis -30 KPX Lcommaaccent T -90 KPX Lcommaaccent Tcaron -90 KPX Lcommaaccent Tcommaaccent -90 KPX Lcommaaccent V -110 KPX Lcommaaccent W -80 KPX Lcommaaccent Y -120 KPX Lcommaaccent Yacute -120 KPX Lcommaaccent Ydieresis -120 KPX Lcommaaccent quotedblright -140 KPX Lcommaaccent quoteright -140 KPX Lcommaaccent y -30 KPX Lcommaaccent yacute -30 KPX Lcommaaccent ydieresis -30 KPX Lslash T -90 KPX Lslash Tcaron -90 KPX Lslash Tcommaaccent -90 KPX Lslash V -110 KPX Lslash W -80 KPX Lslash Y -120 KPX Lslash Yacute -120 KPX Lslash Ydieresis -120 KPX Lslash quotedblright -140 KPX Lslash quoteright -140 KPX Lslash y -30 KPX Lslash yacute -30 KPX Lslash ydieresis -30 KPX O A -50 KPX O Aacute -50 KPX O Abreve -50 KPX O Acircumflex -50 KPX O Adieresis -50 KPX O Agrave -50 KPX O Amacron -50 KPX O Aogonek -50 KPX O Aring -50 KPX O Atilde -50 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -50 KPX O X -50 KPX O Y -70 KPX O Yacute -70 KPX O Ydieresis -70 KPX O comma -40 KPX O period -40 KPX Oacute A -50 KPX Oacute Aacute -50 KPX Oacute Abreve -50 KPX Oacute Acircumflex -50 KPX Oacute Adieresis -50 KPX Oacute Agrave -50 KPX Oacute Amacron -50 KPX Oacute Aogonek -50 KPX Oacute Aring -50 KPX Oacute Atilde -50 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -50 KPX Oacute X -50 KPX Oacute Y -70 KPX Oacute Yacute -70 KPX Oacute Ydieresis -70 KPX Oacute comma -40 KPX Oacute period -40 KPX Ocircumflex A -50 KPX Ocircumflex Aacute -50 KPX Ocircumflex Abreve -50 KPX Ocircumflex Acircumflex -50 KPX Ocircumflex Adieresis -50 KPX Ocircumflex Agrave -50 KPX Ocircumflex Amacron -50 KPX Ocircumflex Aogonek -50 KPX Ocircumflex Aring -50 KPX Ocircumflex Atilde -50 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -50 KPX Ocircumflex X -50 KPX Ocircumflex Y -70 KPX Ocircumflex Yacute -70 KPX Ocircumflex Ydieresis -70 KPX Ocircumflex comma -40 KPX Ocircumflex period -40 KPX Odieresis A -50 KPX Odieresis Aacute -50 KPX Odieresis Abreve -50 KPX Odieresis Acircumflex -50 KPX Odieresis Adieresis -50 KPX Odieresis Agrave -50 KPX Odieresis Amacron -50 KPX Odieresis Aogonek -50 KPX Odieresis Aring -50 KPX Odieresis Atilde -50 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -50 KPX Odieresis X -50 KPX Odieresis Y -70 KPX Odieresis Yacute -70 KPX Odieresis Ydieresis -70 KPX Odieresis comma -40 KPX Odieresis period -40 KPX Ograve A -50 KPX Ograve Aacute -50 KPX Ograve Abreve -50 KPX Ograve Acircumflex -50 KPX Ograve Adieresis -50 KPX Ograve Agrave -50 KPX Ograve Amacron -50 KPX Ograve Aogonek -50 KPX Ograve Aring -50 KPX Ograve Atilde -50 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -50 KPX Ograve X -50 KPX Ograve Y -70 KPX Ograve Yacute -70 KPX Ograve Ydieresis -70 KPX Ograve comma -40 KPX Ograve period -40 KPX Ohungarumlaut A -50 KPX Ohungarumlaut Aacute -50 KPX Ohungarumlaut Abreve -50 KPX Ohungarumlaut Acircumflex -50 KPX Ohungarumlaut Adieresis -50 KPX Ohungarumlaut Agrave -50 KPX Ohungarumlaut Amacron -50 KPX Ohungarumlaut Aogonek -50 KPX Ohungarumlaut Aring -50 KPX Ohungarumlaut Atilde -50 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -50 KPX Ohungarumlaut X -50 KPX Ohungarumlaut Y -70 KPX Ohungarumlaut Yacute -70 KPX Ohungarumlaut Ydieresis -70 KPX Ohungarumlaut comma -40 KPX Ohungarumlaut period -40 KPX Omacron A -50 KPX Omacron Aacute -50 KPX Omacron Abreve -50 KPX Omacron Acircumflex -50 KPX Omacron Adieresis -50 KPX Omacron Agrave -50 KPX Omacron Amacron -50 KPX Omacron Aogonek -50 KPX Omacron Aring -50 KPX Omacron Atilde -50 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -50 KPX Omacron X -50 KPX Omacron Y -70 KPX Omacron Yacute -70 KPX Omacron Ydieresis -70 KPX Omacron comma -40 KPX Omacron period -40 KPX Oslash A -50 KPX Oslash Aacute -50 KPX Oslash Abreve -50 KPX Oslash Acircumflex -50 KPX Oslash Adieresis -50 KPX Oslash Agrave -50 KPX Oslash Amacron -50 KPX Oslash Aogonek -50 KPX Oslash Aring -50 KPX Oslash Atilde -50 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -50 KPX Oslash X -50 KPX Oslash Y -70 KPX Oslash Yacute -70 KPX Oslash Ydieresis -70 KPX Oslash comma -40 KPX Oslash period -40 KPX Otilde A -50 KPX Otilde Aacute -50 KPX Otilde Abreve -50 KPX Otilde Acircumflex -50 KPX Otilde Adieresis -50 KPX Otilde Agrave -50 KPX Otilde Amacron -50 KPX Otilde Aogonek -50 KPX Otilde Aring -50 KPX Otilde Atilde -50 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -50 KPX Otilde X -50 KPX Otilde Y -70 KPX Otilde Yacute -70 KPX Otilde Ydieresis -70 KPX Otilde comma -40 KPX Otilde period -40 KPX P A -100 KPX P Aacute -100 KPX P Abreve -100 KPX P Acircumflex -100 KPX P Adieresis -100 KPX P Agrave -100 KPX P Amacron -100 KPX P Aogonek -100 KPX P Aring -100 KPX P Atilde -100 KPX P a -30 KPX P aacute -30 KPX P abreve -30 KPX P acircumflex -30 KPX P adieresis -30 KPX P agrave -30 KPX P amacron -30 KPX P aogonek -30 KPX P aring -30 KPX P atilde -30 KPX P comma -120 KPX P e -30 KPX P eacute -30 KPX P ecaron -30 KPX P ecircumflex -30 KPX P edieresis -30 KPX P edotaccent -30 KPX P egrave -30 KPX P emacron -30 KPX P eogonek -30 KPX P o -40 KPX P oacute -40 KPX P ocircumflex -40 KPX P odieresis -40 KPX P ograve -40 KPX P ohungarumlaut -40 KPX P omacron -40 KPX P oslash -40 KPX P otilde -40 KPX P period -120 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX Q comma 20 KPX Q period 20 KPX R O -20 KPX R Oacute -20 KPX R Ocircumflex -20 KPX R Odieresis -20 KPX R Ograve -20 KPX R Ohungarumlaut -20 KPX R Omacron -20 KPX R Oslash -20 KPX R Otilde -20 KPX R T -20 KPX R Tcaron -20 KPX R Tcommaaccent -20 KPX R U -20 KPX R Uacute -20 KPX R Ucircumflex -20 KPX R Udieresis -20 KPX R Ugrave -20 KPX R Uhungarumlaut -20 KPX R Umacron -20 KPX R Uogonek -20 KPX R Uring -20 KPX R V -50 KPX R W -40 KPX R Y -50 KPX R Yacute -50 KPX R Ydieresis -50 KPX Racute O -20 KPX Racute Oacute -20 KPX Racute Ocircumflex -20 KPX Racute Odieresis -20 KPX Racute Ograve -20 KPX Racute Ohungarumlaut -20 KPX Racute Omacron -20 KPX Racute Oslash -20 KPX Racute Otilde -20 KPX Racute T -20 KPX Racute Tcaron -20 KPX Racute Tcommaaccent -20 KPX Racute U -20 KPX Racute Uacute -20 KPX Racute Ucircumflex -20 KPX Racute Udieresis -20 KPX Racute Ugrave -20 KPX Racute Uhungarumlaut -20 KPX Racute Umacron -20 KPX Racute Uogonek -20 KPX Racute Uring -20 KPX Racute V -50 KPX Racute W -40 KPX Racute Y -50 KPX Racute Yacute -50 KPX Racute Ydieresis -50 KPX Rcaron O -20 KPX Rcaron Oacute -20 KPX Rcaron Ocircumflex -20 KPX Rcaron Odieresis -20 KPX Rcaron Ograve -20 KPX Rcaron Ohungarumlaut -20 KPX Rcaron Omacron -20 KPX Rcaron Oslash -20 KPX Rcaron Otilde -20 KPX Rcaron T -20 KPX Rcaron Tcaron -20 KPX Rcaron Tcommaaccent -20 KPX Rcaron U -20 KPX Rcaron Uacute -20 KPX Rcaron Ucircumflex -20 KPX Rcaron Udieresis -20 KPX Rcaron Ugrave -20 KPX Rcaron Uhungarumlaut -20 KPX Rcaron Umacron -20 KPX Rcaron Uogonek -20 KPX Rcaron Uring -20 KPX Rcaron V -50 KPX Rcaron W -40 KPX Rcaron Y -50 KPX Rcaron Yacute -50 KPX Rcaron Ydieresis -50 KPX Rcommaaccent O -20 KPX Rcommaaccent Oacute -20 KPX Rcommaaccent Ocircumflex -20 KPX Rcommaaccent Odieresis -20 KPX Rcommaaccent Ograve -20 KPX Rcommaaccent Ohungarumlaut -20 KPX Rcommaaccent Omacron -20 KPX Rcommaaccent Oslash -20 KPX Rcommaaccent Otilde -20 KPX Rcommaaccent T -20 KPX Rcommaaccent Tcaron -20 KPX Rcommaaccent Tcommaaccent -20 KPX Rcommaaccent U -20 KPX Rcommaaccent Uacute -20 KPX Rcommaaccent Ucircumflex -20 KPX Rcommaaccent Udieresis -20 KPX Rcommaaccent Ugrave -20 KPX Rcommaaccent Uhungarumlaut -20 KPX Rcommaaccent Umacron -20 KPX Rcommaaccent Uogonek -20 KPX Rcommaaccent Uring -20 KPX Rcommaaccent V -50 KPX Rcommaaccent W -40 KPX Rcommaaccent Y -50 KPX Rcommaaccent Yacute -50 KPX Rcommaaccent Ydieresis -50 KPX T A -90 KPX T Aacute -90 KPX T Abreve -90 KPX T Acircumflex -90 KPX T Adieresis -90 KPX T Agrave -90 KPX T Amacron -90 KPX T Aogonek -90 KPX T Aring -90 KPX T Atilde -90 KPX T O -40 KPX T Oacute -40 KPX T Ocircumflex -40 KPX T Odieresis -40 KPX T Ograve -40 KPX T Ohungarumlaut -40 KPX T Omacron -40 KPX T Oslash -40 KPX T Otilde -40 KPX T a -80 KPX T aacute -80 KPX T abreve -80 KPX T acircumflex -80 KPX T adieresis -80 KPX T agrave -80 KPX T amacron -80 KPX T aogonek -80 KPX T aring -80 KPX T atilde -80 KPX T colon -40 KPX T comma -80 KPX T e -60 KPX T eacute -60 KPX T ecaron -60 KPX T ecircumflex -60 KPX T edieresis -60 KPX T edotaccent -60 KPX T egrave -60 KPX T emacron -60 KPX T eogonek -60 KPX T hyphen -120 KPX T o -80 KPX T oacute -80 KPX T ocircumflex -80 KPX T odieresis -80 KPX T ograve -80 KPX T ohungarumlaut -80 KPX T omacron -80 KPX T oslash -80 KPX T otilde -80 KPX T period -80 KPX T r -80 KPX T racute -80 KPX T rcommaaccent -80 KPX T semicolon -40 KPX T u -90 KPX T uacute -90 KPX T ucircumflex -90 KPX T udieresis -90 KPX T ugrave -90 KPX T uhungarumlaut -90 KPX T umacron -90 KPX T uogonek -90 KPX T uring -90 KPX T w -60 KPX T y -60 KPX T yacute -60 KPX T ydieresis -60 KPX Tcaron A -90 KPX Tcaron Aacute -90 KPX Tcaron Abreve -90 KPX Tcaron Acircumflex -90 KPX Tcaron Adieresis -90 KPX Tcaron Agrave -90 KPX Tcaron Amacron -90 KPX Tcaron Aogonek -90 KPX Tcaron Aring -90 KPX Tcaron Atilde -90 KPX Tcaron O -40 KPX Tcaron Oacute -40 KPX Tcaron Ocircumflex -40 KPX Tcaron Odieresis -40 KPX Tcaron Ograve -40 KPX Tcaron Ohungarumlaut -40 KPX Tcaron Omacron -40 KPX Tcaron Oslash -40 KPX Tcaron Otilde -40 KPX Tcaron a -80 KPX Tcaron aacute -80 KPX Tcaron abreve -80 KPX Tcaron acircumflex -80 KPX Tcaron adieresis -80 KPX Tcaron agrave -80 KPX Tcaron amacron -80 KPX Tcaron aogonek -80 KPX Tcaron aring -80 KPX Tcaron atilde -80 KPX Tcaron colon -40 KPX Tcaron comma -80 KPX Tcaron e -60 KPX Tcaron eacute -60 KPX Tcaron ecaron -60 KPX Tcaron ecircumflex -60 KPX Tcaron edieresis -60 KPX Tcaron edotaccent -60 KPX Tcaron egrave -60 KPX Tcaron emacron -60 KPX Tcaron eogonek -60 KPX Tcaron hyphen -120 KPX Tcaron o -80 KPX Tcaron oacute -80 KPX Tcaron ocircumflex -80 KPX Tcaron odieresis -80 KPX Tcaron ograve -80 KPX Tcaron ohungarumlaut -80 KPX Tcaron omacron -80 KPX Tcaron oslash -80 KPX Tcaron otilde -80 KPX Tcaron period -80 KPX Tcaron r -80 KPX Tcaron racute -80 KPX Tcaron rcommaaccent -80 KPX Tcaron semicolon -40 KPX Tcaron u -90 KPX Tcaron uacute -90 KPX Tcaron ucircumflex -90 KPX Tcaron udieresis -90 KPX Tcaron ugrave -90 KPX Tcaron uhungarumlaut -90 KPX Tcaron umacron -90 KPX Tcaron uogonek -90 KPX Tcaron uring -90 KPX Tcaron w -60 KPX Tcaron y -60 KPX Tcaron yacute -60 KPX Tcaron ydieresis -60 KPX Tcommaaccent A -90 KPX Tcommaaccent Aacute -90 KPX Tcommaaccent Abreve -90 KPX Tcommaaccent Acircumflex -90 KPX Tcommaaccent Adieresis -90 KPX Tcommaaccent Agrave -90 KPX Tcommaaccent Amacron -90 KPX Tcommaaccent Aogonek -90 KPX Tcommaaccent Aring -90 KPX Tcommaaccent Atilde -90 KPX Tcommaaccent O -40 KPX Tcommaaccent Oacute -40 KPX Tcommaaccent Ocircumflex -40 KPX Tcommaaccent Odieresis -40 KPX Tcommaaccent Ograve -40 KPX Tcommaaccent Ohungarumlaut -40 KPX Tcommaaccent Omacron -40 KPX Tcommaaccent Oslash -40 KPX Tcommaaccent Otilde -40 KPX Tcommaaccent a -80 KPX Tcommaaccent aacute -80 KPX Tcommaaccent abreve -80 KPX Tcommaaccent acircumflex -80 KPX Tcommaaccent adieresis -80 KPX Tcommaaccent agrave -80 KPX Tcommaaccent amacron -80 KPX Tcommaaccent aogonek -80 KPX Tcommaaccent aring -80 KPX Tcommaaccent atilde -80 KPX Tcommaaccent colon -40 KPX Tcommaaccent comma -80 KPX Tcommaaccent e -60 KPX Tcommaaccent eacute -60 KPX Tcommaaccent ecaron -60 KPX Tcommaaccent ecircumflex -60 KPX Tcommaaccent edieresis -60 KPX Tcommaaccent edotaccent -60 KPX Tcommaaccent egrave -60 KPX Tcommaaccent emacron -60 KPX Tcommaaccent eogonek -60 KPX Tcommaaccent hyphen -120 KPX Tcommaaccent o -80 KPX Tcommaaccent oacute -80 KPX Tcommaaccent ocircumflex -80 KPX Tcommaaccent odieresis -80 KPX Tcommaaccent ograve -80 KPX Tcommaaccent ohungarumlaut -80 KPX Tcommaaccent omacron -80 KPX Tcommaaccent oslash -80 KPX Tcommaaccent otilde -80 KPX Tcommaaccent period -80 KPX Tcommaaccent r -80 KPX Tcommaaccent racute -80 KPX Tcommaaccent rcommaaccent -80 KPX Tcommaaccent semicolon -40 KPX Tcommaaccent u -90 KPX Tcommaaccent uacute -90 KPX Tcommaaccent ucircumflex -90 KPX Tcommaaccent udieresis -90 KPX Tcommaaccent ugrave -90 KPX Tcommaaccent uhungarumlaut -90 KPX Tcommaaccent umacron -90 KPX Tcommaaccent uogonek -90 KPX Tcommaaccent uring -90 KPX Tcommaaccent w -60 KPX Tcommaaccent y -60 KPX Tcommaaccent yacute -60 KPX Tcommaaccent ydieresis -60 KPX U A -50 KPX U Aacute -50 KPX U Abreve -50 KPX U Acircumflex -50 KPX U Adieresis -50 KPX U Agrave -50 KPX U Amacron -50 KPX U Aogonek -50 KPX U Aring -50 KPX U Atilde -50 KPX U comma -30 KPX U period -30 KPX Uacute A -50 KPX Uacute Aacute -50 KPX Uacute Abreve -50 KPX Uacute Acircumflex -50 KPX Uacute Adieresis -50 KPX Uacute Agrave -50 KPX Uacute Amacron -50 KPX Uacute Aogonek -50 KPX Uacute Aring -50 KPX Uacute Atilde -50 KPX Uacute comma -30 KPX Uacute period -30 KPX Ucircumflex A -50 KPX Ucircumflex Aacute -50 KPX Ucircumflex Abreve -50 KPX Ucircumflex Acircumflex -50 KPX Ucircumflex Adieresis -50 KPX Ucircumflex Agrave -50 KPX Ucircumflex Amacron -50 KPX Ucircumflex Aogonek -50 KPX Ucircumflex Aring -50 KPX Ucircumflex Atilde -50 KPX Ucircumflex comma -30 KPX Ucircumflex period -30 KPX Udieresis A -50 KPX Udieresis Aacute -50 KPX Udieresis Abreve -50 KPX Udieresis Acircumflex -50 KPX Udieresis Adieresis -50 KPX Udieresis Agrave -50 KPX Udieresis Amacron -50 KPX Udieresis Aogonek -50 KPX Udieresis Aring -50 KPX Udieresis Atilde -50 KPX Udieresis comma -30 KPX Udieresis period -30 KPX Ugrave A -50 KPX Ugrave Aacute -50 KPX Ugrave Abreve -50 KPX Ugrave Acircumflex -50 KPX Ugrave Adieresis -50 KPX Ugrave Agrave -50 KPX Ugrave Amacron -50 KPX Ugrave Aogonek -50 KPX Ugrave Aring -50 KPX Ugrave Atilde -50 KPX Ugrave comma -30 KPX Ugrave period -30 KPX Uhungarumlaut A -50 KPX Uhungarumlaut Aacute -50 KPX Uhungarumlaut Abreve -50 KPX Uhungarumlaut Acircumflex -50 KPX Uhungarumlaut Adieresis -50 KPX Uhungarumlaut Agrave -50 KPX Uhungarumlaut Amacron -50 KPX Uhungarumlaut Aogonek -50 KPX Uhungarumlaut Aring -50 KPX Uhungarumlaut Atilde -50 KPX Uhungarumlaut comma -30 KPX Uhungarumlaut period -30 KPX Umacron A -50 KPX Umacron Aacute -50 KPX Umacron Abreve -50 KPX Umacron Acircumflex -50 KPX Umacron Adieresis -50 KPX Umacron Agrave -50 KPX Umacron Amacron -50 KPX Umacron Aogonek -50 KPX Umacron Aring -50 KPX Umacron Atilde -50 KPX Umacron comma -30 KPX Umacron period -30 KPX Uogonek A -50 KPX Uogonek Aacute -50 KPX Uogonek Abreve -50 KPX Uogonek Acircumflex -50 KPX Uogonek Adieresis -50 KPX Uogonek Agrave -50 KPX Uogonek Amacron -50 KPX Uogonek Aogonek -50 KPX Uogonek Aring -50 KPX Uogonek Atilde -50 KPX Uogonek comma -30 KPX Uogonek period -30 KPX Uring A -50 KPX Uring Aacute -50 KPX Uring Abreve -50 KPX Uring Acircumflex -50 KPX Uring Adieresis -50 KPX Uring Agrave -50 KPX Uring Amacron -50 KPX Uring Aogonek -50 KPX Uring Aring -50 KPX Uring Atilde -50 KPX Uring comma -30 KPX Uring period -30 KPX V A -80 KPX V Aacute -80 KPX V Abreve -80 KPX V Acircumflex -80 KPX V Adieresis -80 KPX V Agrave -80 KPX V Amacron -80 KPX V Aogonek -80 KPX V Aring -80 KPX V Atilde -80 KPX V G -50 KPX V Gbreve -50 KPX V Gcommaaccent -50 KPX V O -50 KPX V Oacute -50 KPX V Ocircumflex -50 KPX V Odieresis -50 KPX V Ograve -50 KPX V Ohungarumlaut -50 KPX V Omacron -50 KPX V Oslash -50 KPX V Otilde -50 KPX V a -60 KPX V aacute -60 KPX V abreve -60 KPX V acircumflex -60 KPX V adieresis -60 KPX V agrave -60 KPX V amacron -60 KPX V aogonek -60 KPX V aring -60 KPX V atilde -60 KPX V colon -40 KPX V comma -120 KPX V e -50 KPX V eacute -50 KPX V ecaron -50 KPX V ecircumflex -50 KPX V edieresis -50 KPX V edotaccent -50 KPX V egrave -50 KPX V emacron -50 KPX V eogonek -50 KPX V hyphen -80 KPX V o -90 KPX V oacute -90 KPX V ocircumflex -90 KPX V odieresis -90 KPX V ograve -90 KPX V ohungarumlaut -90 KPX V omacron -90 KPX V oslash -90 KPX V otilde -90 KPX V period -120 KPX V semicolon -40 KPX V u -60 KPX V uacute -60 KPX V ucircumflex -60 KPX V udieresis -60 KPX V ugrave -60 KPX V uhungarumlaut -60 KPX V umacron -60 KPX V uogonek -60 KPX V uring -60 KPX W A -60 KPX W Aacute -60 KPX W Abreve -60 KPX W Acircumflex -60 KPX W Adieresis -60 KPX W Agrave -60 KPX W Amacron -60 KPX W Aogonek -60 KPX W Aring -60 KPX W Atilde -60 KPX W O -20 KPX W Oacute -20 KPX W Ocircumflex -20 KPX W Odieresis -20 KPX W Ograve -20 KPX W Ohungarumlaut -20 KPX W Omacron -20 KPX W Oslash -20 KPX W Otilde -20 KPX W a -40 KPX W aacute -40 KPX W abreve -40 KPX W acircumflex -40 KPX W adieresis -40 KPX W agrave -40 KPX W amacron -40 KPX W aogonek -40 KPX W aring -40 KPX W atilde -40 KPX W colon -10 KPX W comma -80 KPX W e -35 KPX W eacute -35 KPX W ecaron -35 KPX W ecircumflex -35 KPX W edieresis -35 KPX W edotaccent -35 KPX W egrave -35 KPX W emacron -35 KPX W eogonek -35 KPX W hyphen -40 KPX W o -60 KPX W oacute -60 KPX W ocircumflex -60 KPX W odieresis -60 KPX W ograve -60 KPX W ohungarumlaut -60 KPX W omacron -60 KPX W oslash -60 KPX W otilde -60 KPX W period -80 KPX W semicolon -10 KPX W u -45 KPX W uacute -45 KPX W ucircumflex -45 KPX W udieresis -45 KPX W ugrave -45 KPX W uhungarumlaut -45 KPX W umacron -45 KPX W uogonek -45 KPX W uring -45 KPX W y -20 KPX W yacute -20 KPX W ydieresis -20 KPX Y A -110 KPX Y Aacute -110 KPX Y Abreve -110 KPX Y Acircumflex -110 KPX Y Adieresis -110 KPX Y Agrave -110 KPX Y Amacron -110 KPX Y Aogonek -110 KPX Y Aring -110 KPX Y Atilde -110 KPX Y O -70 KPX Y Oacute -70 KPX Y Ocircumflex -70 KPX Y Odieresis -70 KPX Y Ograve -70 KPX Y Ohungarumlaut -70 KPX Y Omacron -70 KPX Y Oslash -70 KPX Y Otilde -70 KPX Y a -90 KPX Y aacute -90 KPX Y abreve -90 KPX Y acircumflex -90 KPX Y adieresis -90 KPX Y agrave -90 KPX Y amacron -90 KPX Y aogonek -90 KPX Y aring -90 KPX Y atilde -90 KPX Y colon -50 KPX Y comma -100 KPX Y e -80 KPX Y eacute -80 KPX Y ecaron -80 KPX Y ecircumflex -80 KPX Y edieresis -80 KPX Y edotaccent -80 KPX Y egrave -80 KPX Y emacron -80 KPX Y eogonek -80 KPX Y o -100 KPX Y oacute -100 KPX Y ocircumflex -100 KPX Y odieresis -100 KPX Y ograve -100 KPX Y ohungarumlaut -100 KPX Y omacron -100 KPX Y oslash -100 KPX Y otilde -100 KPX Y period -100 KPX Y semicolon -50 KPX Y u -100 KPX Y uacute -100 KPX Y ucircumflex -100 KPX Y udieresis -100 KPX Y ugrave -100 KPX Y uhungarumlaut -100 KPX Y umacron -100 KPX Y uogonek -100 KPX Y uring -100 KPX Yacute A -110 KPX Yacute Aacute -110 KPX Yacute Abreve -110 KPX Yacute Acircumflex -110 KPX Yacute Adieresis -110 KPX Yacute Agrave -110 KPX Yacute Amacron -110 KPX Yacute Aogonek -110 KPX Yacute Aring -110 KPX Yacute Atilde -110 KPX Yacute O -70 KPX Yacute Oacute -70 KPX Yacute Ocircumflex -70 KPX Yacute Odieresis -70 KPX Yacute Ograve -70 KPX Yacute Ohungarumlaut -70 KPX Yacute Omacron -70 KPX Yacute Oslash -70 KPX Yacute Otilde -70 KPX Yacute a -90 KPX Yacute aacute -90 KPX Yacute abreve -90 KPX Yacute acircumflex -90 KPX Yacute adieresis -90 KPX Yacute agrave -90 KPX Yacute amacron -90 KPX Yacute aogonek -90 KPX Yacute aring -90 KPX Yacute atilde -90 KPX Yacute colon -50 KPX Yacute comma -100 KPX Yacute e -80 KPX Yacute eacute -80 KPX Yacute ecaron -80 KPX Yacute ecircumflex -80 KPX Yacute edieresis -80 KPX Yacute edotaccent -80 KPX Yacute egrave -80 KPX Yacute emacron -80 KPX Yacute eogonek -80 KPX Yacute o -100 KPX Yacute oacute -100 KPX Yacute ocircumflex -100 KPX Yacute odieresis -100 KPX Yacute ograve -100 KPX Yacute ohungarumlaut -100 KPX Yacute omacron -100 KPX Yacute oslash -100 KPX Yacute otilde -100 KPX Yacute period -100 KPX Yacute semicolon -50 KPX Yacute u -100 KPX Yacute uacute -100 KPX Yacute ucircumflex -100 KPX Yacute udieresis -100 KPX Yacute ugrave -100 KPX Yacute uhungarumlaut -100 KPX Yacute umacron -100 KPX Yacute uogonek -100 KPX Yacute uring -100 KPX Ydieresis A -110 KPX Ydieresis Aacute -110 KPX Ydieresis Abreve -110 KPX Ydieresis Acircumflex -110 KPX Ydieresis Adieresis -110 KPX Ydieresis Agrave -110 KPX Ydieresis Amacron -110 KPX Ydieresis Aogonek -110 KPX Ydieresis Aring -110 KPX Ydieresis Atilde -110 KPX Ydieresis O -70 KPX Ydieresis Oacute -70 KPX Ydieresis Ocircumflex -70 KPX Ydieresis Odieresis -70 KPX Ydieresis Ograve -70 KPX Ydieresis Ohungarumlaut -70 KPX Ydieresis Omacron -70 KPX Ydieresis Oslash -70 KPX Ydieresis Otilde -70 KPX Ydieresis a -90 KPX Ydieresis aacute -90 KPX Ydieresis abreve -90 KPX Ydieresis acircumflex -90 KPX Ydieresis adieresis -90 KPX Ydieresis agrave -90 KPX Ydieresis amacron -90 KPX Ydieresis aogonek -90 KPX Ydieresis aring -90 KPX Ydieresis atilde -90 KPX Ydieresis colon -50 KPX Ydieresis comma -100 KPX Ydieresis e -80 KPX Ydieresis eacute -80 KPX Ydieresis ecaron -80 KPX Ydieresis ecircumflex -80 KPX Ydieresis edieresis -80 KPX Ydieresis edotaccent -80 KPX Ydieresis egrave -80 KPX Ydieresis emacron -80 KPX Ydieresis eogonek -80 KPX Ydieresis o -100 KPX Ydieresis oacute -100 KPX Ydieresis ocircumflex -100 KPX Ydieresis odieresis -100 KPX Ydieresis ograve -100 KPX Ydieresis ohungarumlaut -100 KPX Ydieresis omacron -100 KPX Ydieresis oslash -100 KPX Ydieresis otilde -100 KPX Ydieresis period -100 KPX Ydieresis semicolon -50 KPX Ydieresis u -100 KPX Ydieresis uacute -100 KPX Ydieresis ucircumflex -100 KPX Ydieresis udieresis -100 KPX Ydieresis ugrave -100 KPX Ydieresis uhungarumlaut -100 KPX Ydieresis umacron -100 KPX Ydieresis uogonek -100 KPX Ydieresis uring -100 KPX a g -10 KPX a gbreve -10 KPX a gcommaaccent -10 KPX a v -15 KPX a w -15 KPX a y -20 KPX a yacute -20 KPX a ydieresis -20 KPX aacute g -10 KPX aacute gbreve -10 KPX aacute gcommaaccent -10 KPX aacute v -15 KPX aacute w -15 KPX aacute y -20 KPX aacute yacute -20 KPX aacute ydieresis -20 KPX abreve g -10 KPX abreve gbreve -10 KPX abreve gcommaaccent -10 KPX abreve v -15 KPX abreve w -15 KPX abreve y -20 KPX abreve yacute -20 KPX abreve ydieresis -20 KPX acircumflex g -10 KPX acircumflex gbreve -10 KPX acircumflex gcommaaccent -10 KPX acircumflex v -15 KPX acircumflex w -15 KPX acircumflex y -20 KPX acircumflex yacute -20 KPX acircumflex ydieresis -20 KPX adieresis g -10 KPX adieresis gbreve -10 KPX adieresis gcommaaccent -10 KPX adieresis v -15 KPX adieresis w -15 KPX adieresis y -20 KPX adieresis yacute -20 KPX adieresis ydieresis -20 KPX agrave g -10 KPX agrave gbreve -10 KPX agrave gcommaaccent -10 KPX agrave v -15 KPX agrave w -15 KPX agrave y -20 KPX agrave yacute -20 KPX agrave ydieresis -20 KPX amacron g -10 KPX amacron gbreve -10 KPX amacron gcommaaccent -10 KPX amacron v -15 KPX amacron w -15 KPX amacron y -20 KPX amacron yacute -20 KPX amacron ydieresis -20 KPX aogonek g -10 KPX aogonek gbreve -10 KPX aogonek gcommaaccent -10 KPX aogonek v -15 KPX aogonek w -15 KPX aogonek y -20 KPX aogonek yacute -20 KPX aogonek ydieresis -20 KPX aring g -10 KPX aring gbreve -10 KPX aring gcommaaccent -10 KPX aring v -15 KPX aring w -15 KPX aring y -20 KPX aring yacute -20 KPX aring ydieresis -20 KPX atilde g -10 KPX atilde gbreve -10 KPX atilde gcommaaccent -10 KPX atilde v -15 KPX atilde w -15 KPX atilde y -20 KPX atilde yacute -20 KPX atilde ydieresis -20 KPX b l -10 KPX b lacute -10 KPX b lcommaaccent -10 KPX b lslash -10 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -20 KPX b y -20 KPX b yacute -20 KPX b ydieresis -20 KPX c h -10 KPX c k -20 KPX c kcommaaccent -20 KPX c l -20 KPX c lacute -20 KPX c lcommaaccent -20 KPX c lslash -20 KPX c y -10 KPX c yacute -10 KPX c ydieresis -10 KPX cacute h -10 KPX cacute k -20 KPX cacute kcommaaccent -20 KPX cacute l -20 KPX cacute lacute -20 KPX cacute lcommaaccent -20 KPX cacute lslash -20 KPX cacute y -10 KPX cacute yacute -10 KPX cacute ydieresis -10 KPX ccaron h -10 KPX ccaron k -20 KPX ccaron kcommaaccent -20 KPX ccaron l -20 KPX ccaron lacute -20 KPX ccaron lcommaaccent -20 KPX ccaron lslash -20 KPX ccaron y -10 KPX ccaron yacute -10 KPX ccaron ydieresis -10 KPX ccedilla h -10 KPX ccedilla k -20 KPX ccedilla kcommaaccent -20 KPX ccedilla l -20 KPX ccedilla lacute -20 KPX ccedilla lcommaaccent -20 KPX ccedilla lslash -20 KPX ccedilla y -10 KPX ccedilla yacute -10 KPX ccedilla ydieresis -10 KPX colon space -40 KPX comma quotedblright -120 KPX comma quoteright -120 KPX comma space -40 KPX d d -10 KPX d dcroat -10 KPX d v -15 KPX d w -15 KPX d y -15 KPX d yacute -15 KPX d ydieresis -15 KPX dcroat d -10 KPX dcroat dcroat -10 KPX dcroat v -15 KPX dcroat w -15 KPX dcroat y -15 KPX dcroat yacute -15 KPX dcroat ydieresis -15 KPX e comma 10 KPX e period 20 KPX e v -15 KPX e w -15 KPX e x -15 KPX e y -15 KPX e yacute -15 KPX e ydieresis -15 KPX eacute comma 10 KPX eacute period 20 KPX eacute v -15 KPX eacute w -15 KPX eacute x -15 KPX eacute y -15 KPX eacute yacute -15 KPX eacute ydieresis -15 KPX ecaron comma 10 KPX ecaron period 20 KPX ecaron v -15 KPX ecaron w -15 KPX ecaron x -15 KPX ecaron y -15 KPX ecaron yacute -15 KPX ecaron ydieresis -15 KPX ecircumflex comma 10 KPX ecircumflex period 20 KPX ecircumflex v -15 KPX ecircumflex w -15 KPX ecircumflex x -15 KPX ecircumflex y -15 KPX ecircumflex yacute -15 KPX ecircumflex ydieresis -15 KPX edieresis comma 10 KPX edieresis period 20 KPX edieresis v -15 KPX edieresis w -15 KPX edieresis x -15 KPX edieresis y -15 KPX edieresis yacute -15 KPX edieresis ydieresis -15 KPX edotaccent comma 10 KPX edotaccent period 20 KPX edotaccent v -15 KPX edotaccent w -15 KPX edotaccent x -15 KPX edotaccent y -15 KPX edotaccent yacute -15 KPX edotaccent ydieresis -15 KPX egrave comma 10 KPX egrave period 20 KPX egrave v -15 KPX egrave w -15 KPX egrave x -15 KPX egrave y -15 KPX egrave yacute -15 KPX egrave ydieresis -15 KPX emacron comma 10 KPX emacron period 20 KPX emacron v -15 KPX emacron w -15 KPX emacron x -15 KPX emacron y -15 KPX emacron yacute -15 KPX emacron ydieresis -15 KPX eogonek comma 10 KPX eogonek period 20 KPX eogonek v -15 KPX eogonek w -15 KPX eogonek x -15 KPX eogonek y -15 KPX eogonek yacute -15 KPX eogonek ydieresis -15 KPX f comma -10 KPX f e -10 KPX f eacute -10 KPX f ecaron -10 KPX f ecircumflex -10 KPX f edieresis -10 KPX f edotaccent -10 KPX f egrave -10 KPX f emacron -10 KPX f eogonek -10 KPX f o -20 KPX f oacute -20 KPX f ocircumflex -20 KPX f odieresis -20 KPX f ograve -20 KPX f ohungarumlaut -20 KPX f omacron -20 KPX f oslash -20 KPX f otilde -20 KPX f period -10 KPX f quotedblright 30 KPX f quoteright 30 KPX g e 10 KPX g eacute 10 KPX g ecaron 10 KPX g ecircumflex 10 KPX g edieresis 10 KPX g edotaccent 10 KPX g egrave 10 KPX g emacron 10 KPX g eogonek 10 KPX g g -10 KPX g gbreve -10 KPX g gcommaaccent -10 KPX gbreve e 10 KPX gbreve eacute 10 KPX gbreve ecaron 10 KPX gbreve ecircumflex 10 KPX gbreve edieresis 10 KPX gbreve edotaccent 10 KPX gbreve egrave 10 KPX gbreve emacron 10 KPX gbreve eogonek 10 KPX gbreve g -10 KPX gbreve gbreve -10 KPX gbreve gcommaaccent -10 KPX gcommaaccent e 10 KPX gcommaaccent eacute 10 KPX gcommaaccent ecaron 10 KPX gcommaaccent ecircumflex 10 KPX gcommaaccent edieresis 10 KPX gcommaaccent edotaccent 10 KPX gcommaaccent egrave 10 KPX gcommaaccent emacron 10 KPX gcommaaccent eogonek 10 KPX gcommaaccent g -10 KPX gcommaaccent gbreve -10 KPX gcommaaccent gcommaaccent -10 KPX h y -20 KPX h yacute -20 KPX h ydieresis -20 KPX k o -15 KPX k oacute -15 KPX k ocircumflex -15 KPX k odieresis -15 KPX k ograve -15 KPX k ohungarumlaut -15 KPX k omacron -15 KPX k oslash -15 KPX k otilde -15 KPX kcommaaccent o -15 KPX kcommaaccent oacute -15 KPX kcommaaccent ocircumflex -15 KPX kcommaaccent odieresis -15 KPX kcommaaccent ograve -15 KPX kcommaaccent ohungarumlaut -15 KPX kcommaaccent omacron -15 KPX kcommaaccent oslash -15 KPX kcommaaccent otilde -15 KPX l w -15 KPX l y -15 KPX l yacute -15 KPX l ydieresis -15 KPX lacute w -15 KPX lacute y -15 KPX lacute yacute -15 KPX lacute ydieresis -15 KPX lcommaaccent w -15 KPX lcommaaccent y -15 KPX lcommaaccent yacute -15 KPX lcommaaccent ydieresis -15 KPX lslash w -15 KPX lslash y -15 KPX lslash yacute -15 KPX lslash ydieresis -15 KPX m u -20 KPX m uacute -20 KPX m ucircumflex -20 KPX m udieresis -20 KPX m ugrave -20 KPX m uhungarumlaut -20 KPX m umacron -20 KPX m uogonek -20 KPX m uring -20 KPX m y -30 KPX m yacute -30 KPX m ydieresis -30 KPX n u -10 KPX n uacute -10 KPX n ucircumflex -10 KPX n udieresis -10 KPX n ugrave -10 KPX n uhungarumlaut -10 KPX n umacron -10 KPX n uogonek -10 KPX n uring -10 KPX n v -40 KPX n y -20 KPX n yacute -20 KPX n ydieresis -20 KPX nacute u -10 KPX nacute uacute -10 KPX nacute ucircumflex -10 KPX nacute udieresis -10 KPX nacute ugrave -10 KPX nacute uhungarumlaut -10 KPX nacute umacron -10 KPX nacute uogonek -10 KPX nacute uring -10 KPX nacute v -40 KPX nacute y -20 KPX nacute yacute -20 KPX nacute ydieresis -20 KPX ncaron u -10 KPX ncaron uacute -10 KPX ncaron ucircumflex -10 KPX ncaron udieresis -10 KPX ncaron ugrave -10 KPX ncaron uhungarumlaut -10 KPX ncaron umacron -10 KPX ncaron uogonek -10 KPX ncaron uring -10 KPX ncaron v -40 KPX ncaron y -20 KPX ncaron yacute -20 KPX ncaron ydieresis -20 KPX ncommaaccent u -10 KPX ncommaaccent uacute -10 KPX ncommaaccent ucircumflex -10 KPX ncommaaccent udieresis -10 KPX ncommaaccent ugrave -10 KPX ncommaaccent uhungarumlaut -10 KPX ncommaaccent umacron -10 KPX ncommaaccent uogonek -10 KPX ncommaaccent uring -10 KPX ncommaaccent v -40 KPX ncommaaccent y -20 KPX ncommaaccent yacute -20 KPX ncommaaccent ydieresis -20 KPX ntilde u -10 KPX ntilde uacute -10 KPX ntilde ucircumflex -10 KPX ntilde udieresis -10 KPX ntilde ugrave -10 KPX ntilde uhungarumlaut -10 KPX ntilde umacron -10 KPX ntilde uogonek -10 KPX ntilde uring -10 KPX ntilde v -40 KPX ntilde y -20 KPX ntilde yacute -20 KPX ntilde ydieresis -20 KPX o v -20 KPX o w -15 KPX o x -30 KPX o y -20 KPX o yacute -20 KPX o ydieresis -20 KPX oacute v -20 KPX oacute w -15 KPX oacute x -30 KPX oacute y -20 KPX oacute yacute -20 KPX oacute ydieresis -20 KPX ocircumflex v -20 KPX ocircumflex w -15 KPX ocircumflex x -30 KPX ocircumflex y -20 KPX ocircumflex yacute -20 KPX ocircumflex ydieresis -20 KPX odieresis v -20 KPX odieresis w -15 KPX odieresis x -30 KPX odieresis y -20 KPX odieresis yacute -20 KPX odieresis ydieresis -20 KPX ograve v -20 KPX ograve w -15 KPX ograve x -30 KPX ograve y -20 KPX ograve yacute -20 KPX ograve ydieresis -20 KPX ohungarumlaut v -20 KPX ohungarumlaut w -15 KPX ohungarumlaut x -30 KPX ohungarumlaut y -20 KPX ohungarumlaut yacute -20 KPX ohungarumlaut ydieresis -20 KPX omacron v -20 KPX omacron w -15 KPX omacron x -30 KPX omacron y -20 KPX omacron yacute -20 KPX omacron ydieresis -20 KPX oslash v -20 KPX oslash w -15 KPX oslash x -30 KPX oslash y -20 KPX oslash yacute -20 KPX oslash ydieresis -20 KPX otilde v -20 KPX otilde w -15 KPX otilde x -30 KPX otilde y -20 KPX otilde yacute -20 KPX otilde ydieresis -20 KPX p y -15 KPX p yacute -15 KPX p ydieresis -15 KPX period quotedblright -120 KPX period quoteright -120 KPX period space -40 KPX quotedblright space -80 KPX quoteleft quoteleft -46 KPX quoteright d -80 KPX quoteright dcroat -80 KPX quoteright l -20 KPX quoteright lacute -20 KPX quoteright lcommaaccent -20 KPX quoteright lslash -20 KPX quoteright quoteright -46 KPX quoteright r -40 KPX quoteright racute -40 KPX quoteright rcaron -40 KPX quoteright rcommaaccent -40 KPX quoteright s -60 KPX quoteright sacute -60 KPX quoteright scaron -60 KPX quoteright scedilla -60 KPX quoteright scommaaccent -60 KPX quoteright space -80 KPX quoteright v -20 KPX r c -20 KPX r cacute -20 KPX r ccaron -20 KPX r ccedilla -20 KPX r comma -60 KPX r d -20 KPX r dcroat -20 KPX r g -15 KPX r gbreve -15 KPX r gcommaaccent -15 KPX r hyphen -20 KPX r o -20 KPX r oacute -20 KPX r ocircumflex -20 KPX r odieresis -20 KPX r ograve -20 KPX r ohungarumlaut -20 KPX r omacron -20 KPX r oslash -20 KPX r otilde -20 KPX r period -60 KPX r q -20 KPX r s -15 KPX r sacute -15 KPX r scaron -15 KPX r scedilla -15 KPX r scommaaccent -15 KPX r t 20 KPX r tcommaaccent 20 KPX r v 10 KPX r y 10 KPX r yacute 10 KPX r ydieresis 10 KPX racute c -20 KPX racute cacute -20 KPX racute ccaron -20 KPX racute ccedilla -20 KPX racute comma -60 KPX racute d -20 KPX racute dcroat -20 KPX racute g -15 KPX racute gbreve -15 KPX racute gcommaaccent -15 KPX racute hyphen -20 KPX racute o -20 KPX racute oacute -20 KPX racute ocircumflex -20 KPX racute odieresis -20 KPX racute ograve -20 KPX racute ohungarumlaut -20 KPX racute omacron -20 KPX racute oslash -20 KPX racute otilde -20 KPX racute period -60 KPX racute q -20 KPX racute s -15 KPX racute sacute -15 KPX racute scaron -15 KPX racute scedilla -15 KPX racute scommaaccent -15 KPX racute t 20 KPX racute tcommaaccent 20 KPX racute v 10 KPX racute y 10 KPX racute yacute 10 KPX racute ydieresis 10 KPX rcaron c -20 KPX rcaron cacute -20 KPX rcaron ccaron -20 KPX rcaron ccedilla -20 KPX rcaron comma -60 KPX rcaron d -20 KPX rcaron dcroat -20 KPX rcaron g -15 KPX rcaron gbreve -15 KPX rcaron gcommaaccent -15 KPX rcaron hyphen -20 KPX rcaron o -20 KPX rcaron oacute -20 KPX rcaron ocircumflex -20 KPX rcaron odieresis -20 KPX rcaron ograve -20 KPX rcaron ohungarumlaut -20 KPX rcaron omacron -20 KPX rcaron oslash -20 KPX rcaron otilde -20 KPX rcaron period -60 KPX rcaron q -20 KPX rcaron s -15 KPX rcaron sacute -15 KPX rcaron scaron -15 KPX rcaron scedilla -15 KPX rcaron scommaaccent -15 KPX rcaron t 20 KPX rcaron tcommaaccent 20 KPX rcaron v 10 KPX rcaron y 10 KPX rcaron yacute 10 KPX rcaron ydieresis 10 KPX rcommaaccent c -20 KPX rcommaaccent cacute -20 KPX rcommaaccent ccaron -20 KPX rcommaaccent ccedilla -20 KPX rcommaaccent comma -60 KPX rcommaaccent d -20 KPX rcommaaccent dcroat -20 KPX rcommaaccent g -15 KPX rcommaaccent gbreve -15 KPX rcommaaccent gcommaaccent -15 KPX rcommaaccent hyphen -20 KPX rcommaaccent o -20 KPX rcommaaccent oacute -20 KPX rcommaaccent ocircumflex -20 KPX rcommaaccent odieresis -20 KPX rcommaaccent ograve -20 KPX rcommaaccent ohungarumlaut -20 KPX rcommaaccent omacron -20 KPX rcommaaccent oslash -20 KPX rcommaaccent otilde -20 KPX rcommaaccent period -60 KPX rcommaaccent q -20 KPX rcommaaccent s -15 KPX rcommaaccent sacute -15 KPX rcommaaccent scaron -15 KPX rcommaaccent scedilla -15 KPX rcommaaccent scommaaccent -15 KPX rcommaaccent t 20 KPX rcommaaccent tcommaaccent 20 KPX rcommaaccent v 10 KPX rcommaaccent y 10 KPX rcommaaccent yacute 10 KPX rcommaaccent ydieresis 10 KPX s w -15 KPX sacute w -15 KPX scaron w -15 KPX scedilla w -15 KPX scommaaccent w -15 KPX semicolon space -40 KPX space T -100 KPX space Tcaron -100 KPX space Tcommaaccent -100 KPX space V -80 KPX space W -80 KPX space Y -120 KPX space Yacute -120 KPX space Ydieresis -120 KPX space quotedblleft -80 KPX space quoteleft -60 KPX v a -20 KPX v aacute -20 KPX v abreve -20 KPX v acircumflex -20 KPX v adieresis -20 KPX v agrave -20 KPX v amacron -20 KPX v aogonek -20 KPX v aring -20 KPX v atilde -20 KPX v comma -80 KPX v o -30 KPX v oacute -30 KPX v ocircumflex -30 KPX v odieresis -30 KPX v ograve -30 KPX v ohungarumlaut -30 KPX v omacron -30 KPX v oslash -30 KPX v otilde -30 KPX v period -80 KPX w comma -40 KPX w o -20 KPX w oacute -20 KPX w ocircumflex -20 KPX w odieresis -20 KPX w ograve -20 KPX w ohungarumlaut -20 KPX w omacron -20 KPX w oslash -20 KPX w otilde -20 KPX w period -40 KPX x e -10 KPX x eacute -10 KPX x ecaron -10 KPX x ecircumflex -10 KPX x edieresis -10 KPX x edotaccent -10 KPX x egrave -10 KPX x emacron -10 KPX x eogonek -10 KPX y a -30 KPX y aacute -30 KPX y abreve -30 KPX y acircumflex -30 KPX y adieresis -30 KPX y agrave -30 KPX y amacron -30 KPX y aogonek -30 KPX y aring -30 KPX y atilde -30 KPX y comma -80 KPX y e -10 KPX y eacute -10 KPX y ecaron -10 KPX y ecircumflex -10 KPX y edieresis -10 KPX y edotaccent -10 KPX y egrave -10 KPX y emacron -10 KPX y eogonek -10 KPX y o -25 KPX y oacute -25 KPX y ocircumflex -25 KPX y odieresis -25 KPX y ograve -25 KPX y ohungarumlaut -25 KPX y omacron -25 KPX y oslash -25 KPX y otilde -25 KPX y period -80 KPX yacute a -30 KPX yacute aacute -30 KPX yacute abreve -30 KPX yacute acircumflex -30 KPX yacute adieresis -30 KPX yacute agrave -30 KPX yacute amacron -30 KPX yacute aogonek -30 KPX yacute aring -30 KPX yacute atilde -30 KPX yacute comma -80 KPX yacute e -10 KPX yacute eacute -10 KPX yacute ecaron -10 KPX yacute ecircumflex -10 KPX yacute edieresis -10 KPX yacute edotaccent -10 KPX yacute egrave -10 KPX yacute emacron -10 KPX yacute eogonek -10 KPX yacute o -25 KPX yacute oacute -25 KPX yacute ocircumflex -25 KPX yacute odieresis -25 KPX yacute ograve -25 KPX yacute ohungarumlaut -25 KPX yacute omacron -25 KPX yacute oslash -25 KPX yacute otilde -25 KPX yacute period -80 KPX ydieresis a -30 KPX ydieresis aacute -30 KPX ydieresis abreve -30 KPX ydieresis acircumflex -30 KPX ydieresis adieresis -30 KPX ydieresis agrave -30 KPX ydieresis amacron -30 KPX ydieresis aogonek -30 KPX ydieresis aring -30 KPX ydieresis atilde -30 KPX ydieresis comma -80 KPX ydieresis e -10 KPX ydieresis eacute -10 KPX ydieresis ecaron -10 KPX ydieresis ecircumflex -10 KPX ydieresis edieresis -10 KPX ydieresis edotaccent -10 KPX ydieresis egrave -10 KPX ydieresis emacron -10 KPX ydieresis eogonek -10 KPX ydieresis o -25 KPX ydieresis oacute -25 KPX ydieresis ocircumflex -25 KPX ydieresis odieresis -25 KPX ydieresis ograve -25 KPX ydieresis ohungarumlaut -25 KPX ydieresis omacron -25 KPX ydieresis oslash -25 KPX ydieresis otilde -25 KPX ydieresis period -80 KPX z e 10 KPX z eacute 10 KPX z ecaron 10 KPX z ecircumflex 10 KPX z edieresis 10 KPX z edotaccent 10 KPX z egrave 10 KPX z emacron 10 KPX z eogonek 10 KPX zacute e 10 KPX zacute eacute 10 KPX zacute ecaron 10 KPX zacute ecircumflex 10 KPX zacute edieresis 10 KPX zacute edotaccent 10 KPX zacute egrave 10 KPX zacute emacron 10 KPX zacute eogonek 10 KPX zcaron e 10 KPX zcaron eacute 10 KPX zcaron ecaron 10 KPX zcaron ecircumflex 10 KPX zcaron edieresis 10 KPX zcaron edotaccent 10 KPX zcaron egrave 10 KPX zcaron emacron 10 KPX zcaron eogonek 10 KPX zdotaccent e 10 KPX zdotaccent eacute 10 KPX zdotaccent ecaron 10 KPX zdotaccent ecircumflex 10 KPX zdotaccent edieresis 10 KPX zdotaccent edotaccent 10 KPX zdotaccent egrave 10 KPX zdotaccent emacron 10 KPX zdotaccent eogonek 10 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Helvetica-Oblique.afm0000644000076500000240000022720312037547555021037 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:44:31 1997 Comment UniqueID 43055 Comment VMusage 14960 69346 FontName Helvetica-Oblique FullName Helvetica Oblique FamilyName Helvetica Weight Medium ItalicAngle -12 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -170 -225 1116 931 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 718 XHeight 523 Ascender 718 Descender -207 StdHW 76 StdVW 88 StartCharMetrics 315 C 32 ; WX 278 ; N space ; B 0 0 0 0 ; C 33 ; WX 278 ; N exclam ; B 90 0 340 718 ; C 34 ; WX 355 ; N quotedbl ; B 168 463 438 718 ; C 35 ; WX 556 ; N numbersign ; B 73 0 631 688 ; C 36 ; WX 556 ; N dollar ; B 69 -115 617 775 ; C 37 ; WX 889 ; N percent ; B 147 -19 889 703 ; C 38 ; WX 667 ; N ampersand ; B 77 -15 647 718 ; C 39 ; WX 222 ; N quoteright ; B 151 463 310 718 ; C 40 ; WX 333 ; N parenleft ; B 108 -207 454 733 ; C 41 ; WX 333 ; N parenright ; B -9 -207 337 733 ; C 42 ; WX 389 ; N asterisk ; B 165 431 475 718 ; C 43 ; WX 584 ; N plus ; B 85 0 606 505 ; C 44 ; WX 278 ; N comma ; B 56 -147 214 106 ; C 45 ; WX 333 ; N hyphen ; B 93 232 357 322 ; C 46 ; WX 278 ; N period ; B 87 0 214 106 ; C 47 ; WX 278 ; N slash ; B -21 -19 452 737 ; C 48 ; WX 556 ; N zero ; B 93 -19 608 703 ; C 49 ; WX 556 ; N one ; B 207 0 508 703 ; C 50 ; WX 556 ; N two ; B 26 0 617 703 ; C 51 ; WX 556 ; N three ; B 75 -19 610 703 ; C 52 ; WX 556 ; N four ; B 61 0 576 703 ; C 53 ; WX 556 ; N five ; B 68 -19 621 688 ; C 54 ; WX 556 ; N six ; B 91 -19 615 703 ; C 55 ; WX 556 ; N seven ; B 137 0 669 688 ; C 56 ; WX 556 ; N eight ; B 74 -19 607 703 ; C 57 ; WX 556 ; N nine ; B 82 -19 609 703 ; C 58 ; WX 278 ; N colon ; B 87 0 301 516 ; C 59 ; WX 278 ; N semicolon ; B 56 -147 301 516 ; C 60 ; WX 584 ; N less ; B 94 11 641 495 ; C 61 ; WX 584 ; N equal ; B 63 115 628 390 ; C 62 ; WX 584 ; N greater ; B 50 11 597 495 ; C 63 ; WX 556 ; N question ; B 161 0 610 727 ; C 64 ; WX 1015 ; N at ; B 215 -19 965 737 ; C 65 ; WX 667 ; N A ; B 14 0 654 718 ; C 66 ; WX 667 ; N B ; B 74 0 712 718 ; C 67 ; WX 722 ; N C ; B 108 -19 782 737 ; C 68 ; WX 722 ; N D ; B 81 0 764 718 ; C 69 ; WX 667 ; N E ; B 86 0 762 718 ; C 70 ; WX 611 ; N F ; B 86 0 736 718 ; C 71 ; WX 778 ; N G ; B 111 -19 799 737 ; C 72 ; WX 722 ; N H ; B 77 0 799 718 ; C 73 ; WX 278 ; N I ; B 91 0 341 718 ; C 74 ; WX 500 ; N J ; B 47 -19 581 718 ; C 75 ; WX 667 ; N K ; B 76 0 808 718 ; C 76 ; WX 556 ; N L ; B 76 0 555 718 ; C 77 ; WX 833 ; N M ; B 73 0 914 718 ; C 78 ; WX 722 ; N N ; B 76 0 799 718 ; C 79 ; WX 778 ; N O ; B 105 -19 826 737 ; C 80 ; WX 667 ; N P ; B 86 0 737 718 ; C 81 ; WX 778 ; N Q ; B 105 -56 826 737 ; C 82 ; WX 722 ; N R ; B 88 0 773 718 ; C 83 ; WX 667 ; N S ; B 90 -19 713 737 ; C 84 ; WX 611 ; N T ; B 148 0 750 718 ; C 85 ; WX 722 ; N U ; B 123 -19 797 718 ; C 86 ; WX 667 ; N V ; B 173 0 800 718 ; C 87 ; WX 944 ; N W ; B 169 0 1081 718 ; C 88 ; WX 667 ; N X ; B 19 0 790 718 ; C 89 ; WX 667 ; N Y ; B 167 0 806 718 ; C 90 ; WX 611 ; N Z ; B 23 0 741 718 ; C 91 ; WX 278 ; N bracketleft ; B 21 -196 403 722 ; C 92 ; WX 278 ; N backslash ; B 140 -19 291 737 ; C 93 ; WX 278 ; N bracketright ; B -14 -196 368 722 ; C 94 ; WX 469 ; N asciicircum ; B 42 264 539 688 ; C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ; C 96 ; WX 222 ; N quoteleft ; B 165 470 323 725 ; C 97 ; WX 556 ; N a ; B 61 -15 559 538 ; C 98 ; WX 556 ; N b ; B 58 -15 584 718 ; C 99 ; WX 500 ; N c ; B 74 -15 553 538 ; C 100 ; WX 556 ; N d ; B 84 -15 652 718 ; C 101 ; WX 556 ; N e ; B 84 -15 578 538 ; C 102 ; WX 278 ; N f ; B 86 0 416 728 ; L i fi ; L l fl ; C 103 ; WX 556 ; N g ; B 42 -220 610 538 ; C 104 ; WX 556 ; N h ; B 65 0 573 718 ; C 105 ; WX 222 ; N i ; B 67 0 308 718 ; C 106 ; WX 222 ; N j ; B -60 -210 308 718 ; C 107 ; WX 500 ; N k ; B 67 0 600 718 ; C 108 ; WX 222 ; N l ; B 67 0 308 718 ; C 109 ; WX 833 ; N m ; B 65 0 852 538 ; C 110 ; WX 556 ; N n ; B 65 0 573 538 ; C 111 ; WX 556 ; N o ; B 83 -14 585 538 ; C 112 ; WX 556 ; N p ; B 14 -207 584 538 ; C 113 ; WX 556 ; N q ; B 84 -207 605 538 ; C 114 ; WX 333 ; N r ; B 77 0 446 538 ; C 115 ; WX 500 ; N s ; B 63 -15 529 538 ; C 116 ; WX 278 ; N t ; B 102 -7 368 669 ; C 117 ; WX 556 ; N u ; B 94 -15 600 523 ; C 118 ; WX 500 ; N v ; B 119 0 603 523 ; C 119 ; WX 722 ; N w ; B 125 0 820 523 ; C 120 ; WX 500 ; N x ; B 11 0 594 523 ; C 121 ; WX 500 ; N y ; B 15 -214 600 523 ; C 122 ; WX 500 ; N z ; B 31 0 571 523 ; C 123 ; WX 334 ; N braceleft ; B 92 -196 445 722 ; C 124 ; WX 260 ; N bar ; B 46 -225 332 775 ; C 125 ; WX 334 ; N braceright ; B 0 -196 354 722 ; C 126 ; WX 584 ; N asciitilde ; B 111 180 580 326 ; C 161 ; WX 333 ; N exclamdown ; B 77 -195 326 523 ; C 162 ; WX 556 ; N cent ; B 95 -115 584 623 ; C 163 ; WX 556 ; N sterling ; B 49 -16 634 718 ; C 164 ; WX 167 ; N fraction ; B -170 -19 482 703 ; C 165 ; WX 556 ; N yen ; B 81 0 699 688 ; C 166 ; WX 556 ; N florin ; B -52 -207 654 737 ; C 167 ; WX 556 ; N section ; B 76 -191 584 737 ; C 168 ; WX 556 ; N currency ; B 60 99 646 603 ; C 169 ; WX 191 ; N quotesingle ; B 157 463 285 718 ; C 170 ; WX 333 ; N quotedblleft ; B 138 470 461 725 ; C 171 ; WX 556 ; N guillemotleft ; B 146 108 554 446 ; C 172 ; WX 333 ; N guilsinglleft ; B 137 108 340 446 ; C 173 ; WX 333 ; N guilsinglright ; B 111 108 314 446 ; C 174 ; WX 500 ; N fi ; B 86 0 587 728 ; C 175 ; WX 500 ; N fl ; B 86 0 585 728 ; C 177 ; WX 556 ; N endash ; B 51 240 623 313 ; C 178 ; WX 556 ; N dagger ; B 135 -159 622 718 ; C 179 ; WX 556 ; N daggerdbl ; B 52 -159 623 718 ; C 180 ; WX 278 ; N periodcentered ; B 129 190 257 315 ; C 182 ; WX 537 ; N paragraph ; B 126 -173 650 718 ; C 183 ; WX 350 ; N bullet ; B 91 202 413 517 ; C 184 ; WX 222 ; N quotesinglbase ; B 21 -149 180 106 ; C 185 ; WX 333 ; N quotedblbase ; B -6 -149 318 106 ; C 186 ; WX 333 ; N quotedblright ; B 124 463 448 718 ; C 187 ; WX 556 ; N guillemotright ; B 120 108 528 446 ; C 188 ; WX 1000 ; N ellipsis ; B 115 0 908 106 ; C 189 ; WX 1000 ; N perthousand ; B 88 -19 1029 703 ; C 191 ; WX 611 ; N questiondown ; B 85 -201 534 525 ; C 193 ; WX 333 ; N grave ; B 170 593 337 734 ; C 194 ; WX 333 ; N acute ; B 248 593 475 734 ; C 195 ; WX 333 ; N circumflex ; B 147 593 438 734 ; C 196 ; WX 333 ; N tilde ; B 125 606 490 722 ; C 197 ; WX 333 ; N macron ; B 143 627 468 684 ; C 198 ; WX 333 ; N breve ; B 167 595 476 731 ; C 199 ; WX 333 ; N dotaccent ; B 249 604 362 706 ; C 200 ; WX 333 ; N dieresis ; B 168 604 443 706 ; C 202 ; WX 333 ; N ring ; B 214 572 402 756 ; C 203 ; WX 333 ; N cedilla ; B 2 -225 232 0 ; C 205 ; WX 333 ; N hungarumlaut ; B 157 593 565 734 ; C 206 ; WX 333 ; N ogonek ; B 43 -225 249 0 ; C 207 ; WX 333 ; N caron ; B 177 593 468 734 ; C 208 ; WX 1000 ; N emdash ; B 51 240 1067 313 ; C 225 ; WX 1000 ; N AE ; B 8 0 1097 718 ; C 227 ; WX 370 ; N ordfeminine ; B 127 405 449 737 ; C 232 ; WX 556 ; N Lslash ; B 41 0 555 718 ; C 233 ; WX 778 ; N Oslash ; B 43 -19 890 737 ; C 234 ; WX 1000 ; N OE ; B 98 -19 1116 737 ; C 235 ; WX 365 ; N ordmasculine ; B 141 405 468 737 ; C 241 ; WX 889 ; N ae ; B 61 -15 909 538 ; C 245 ; WX 278 ; N dotlessi ; B 95 0 294 523 ; C 248 ; WX 222 ; N lslash ; B 41 0 347 718 ; C 249 ; WX 611 ; N oslash ; B 29 -22 647 545 ; C 250 ; WX 944 ; N oe ; B 83 -15 964 538 ; C 251 ; WX 611 ; N germandbls ; B 67 -15 658 728 ; C -1 ; WX 278 ; N Idieresis ; B 91 0 458 901 ; C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ; C -1 ; WX 556 ; N abreve ; B 61 -15 578 731 ; C -1 ; WX 556 ; N uhungarumlaut ; B 94 -15 677 734 ; C -1 ; WX 556 ; N ecaron ; B 84 -15 580 734 ; C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ; C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ; C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ; C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ; C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ; C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ; C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ; C -1 ; WX 500 ; N scommaaccent ; B 63 -225 529 538 ; C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ; C -1 ; WX 722 ; N Uring ; B 123 -19 797 931 ; C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ; C -1 ; WX 556 ; N aogonek ; B 61 -220 559 538 ; C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ; C -1 ; WX 556 ; N uogonek ; B 94 -225 600 523 ; C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ; C -1 ; WX 722 ; N Dcroat ; B 69 0 764 718 ; C -1 ; WX 250 ; N commaaccent ; B 39 -225 172 -40 ; C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ; C -1 ; WX 667 ; N Emacron ; B 86 0 762 879 ; C -1 ; WX 500 ; N ccaron ; B 74 -15 553 734 ; C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ; C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 799 718 ; C -1 ; WX 222 ; N lacute ; B 67 0 461 929 ; C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ; C -1 ; WX 611 ; N Tcommaaccent ; B 148 -225 750 718 ; C -1 ; WX 722 ; N Cacute ; B 108 -19 782 929 ; C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ; C -1 ; WX 667 ; N Edotaccent ; B 86 0 762 901 ; C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ; C -1 ; WX 500 ; N scedilla ; B 63 -225 529 538 ; C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ; C -1 ; WX 471 ; N lozenge ; B 88 0 540 728 ; C -1 ; WX 722 ; N Rcaron ; B 88 0 773 929 ; C -1 ; WX 778 ; N Gcommaaccent ; B 111 -225 799 737 ; C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ; C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ; C -1 ; WX 667 ; N Amacron ; B 14 0 677 879 ; C -1 ; WX 333 ; N rcaron ; B 77 0 508 734 ; C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ; C -1 ; WX 611 ; N Zdotaccent ; B 23 0 741 901 ; C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ; C -1 ; WX 778 ; N Omacron ; B 105 -19 826 879 ; C -1 ; WX 722 ; N Racute ; B 88 0 773 929 ; C -1 ; WX 667 ; N Sacute ; B 90 -19 713 929 ; C -1 ; WX 643 ; N dcaron ; B 84 -15 808 718 ; C -1 ; WX 722 ; N Umacron ; B 123 -19 797 879 ; C -1 ; WX 556 ; N uring ; B 94 -15 600 756 ; C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ; C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ; C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ; C -1 ; WX 667 ; N Abreve ; B 14 0 685 926 ; C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ; C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ; C -1 ; WX 611 ; N Tcaron ; B 148 0 750 929 ; C -1 ; WX 476 ; N partialdiff ; B 41 -38 550 714 ; C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ; C -1 ; WX 722 ; N Nacute ; B 76 0 799 929 ; C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ; C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ; C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ; C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ; C -1 ; WX 500 ; N cacute ; B 74 -15 559 734 ; C -1 ; WX 556 ; N nacute ; B 65 0 587 734 ; C -1 ; WX 556 ; N umacron ; B 94 -15 600 684 ; C -1 ; WX 722 ; N Ncaron ; B 76 0 799 929 ; C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ; C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ; C -1 ; WX 260 ; N brokenbar ; B 62 -150 316 700 ; C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ; C -1 ; WX 778 ; N Gbreve ; B 111 -19 799 926 ; C -1 ; WX 278 ; N Idotaccent ; B 91 0 377 901 ; C -1 ; WX 600 ; N summation ; B 15 -10 671 706 ; C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ; C -1 ; WX 333 ; N racute ; B 77 0 475 734 ; C -1 ; WX 556 ; N omacron ; B 83 -14 585 684 ; C -1 ; WX 611 ; N Zacute ; B 23 0 741 929 ; C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 620 674 ; C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ; C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ; C -1 ; WX 222 ; N lcommaaccent ; B 25 -225 308 718 ; C -1 ; WX 317 ; N tcaron ; B 102 -7 501 808 ; C -1 ; WX 556 ; N eogonek ; B 84 -225 578 538 ; C -1 ; WX 722 ; N Uogonek ; B 123 -225 797 718 ; C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ; C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ; C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ; C -1 ; WX 500 ; N zacute ; B 31 0 571 734 ; C -1 ; WX 222 ; N iogonek ; B -61 -225 308 718 ; C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ; C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ; C -1 ; WX 556 ; N amacron ; B 61 -15 580 684 ; C -1 ; WX 500 ; N sacute ; B 63 -15 559 734 ; C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ; C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ; C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ; C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ; C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ; C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ; C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ; C -1 ; WX 556 ; N ohungarumlaut ; B 83 -14 677 734 ; C -1 ; WX 667 ; N Eogonek ; B 86 -220 762 718 ; C -1 ; WX 556 ; N dcroat ; B 84 -15 689 718 ; C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ; C -1 ; WX 667 ; N Scedilla ; B 90 -225 713 737 ; C -1 ; WX 299 ; N lcaron ; B 67 0 464 718 ; C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 808 718 ; C -1 ; WX 556 ; N Lacute ; B 76 0 555 929 ; C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ; C -1 ; WX 556 ; N edotaccent ; B 84 -15 578 706 ; C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ; C -1 ; WX 278 ; N Imacron ; B 91 0 483 879 ; C -1 ; WX 556 ; N Lcaron ; B 76 0 570 718 ; C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ; C -1 ; WX 549 ; N lessequal ; B 26 0 666 674 ; C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ; C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 123 -19 801 929 ; C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ; C -1 ; WX 556 ; N emacron ; B 84 -15 580 684 ; C -1 ; WX 556 ; N gbreve ; B 42 -220 610 731 ; C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ; C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ; C -1 ; WX 667 ; N Scommaaccent ; B 90 -225 713 737 ; C -1 ; WX 778 ; N Ohungarumlaut ; B 105 -19 829 929 ; C -1 ; WX 400 ; N degree ; B 169 411 468 703 ; C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ; C -1 ; WX 722 ; N Ccaron ; B 108 -19 782 929 ; C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ; C -1 ; WX 453 ; N radical ; B 79 -80 617 762 ; C -1 ; WX 722 ; N Dcaron ; B 81 0 764 929 ; C -1 ; WX 333 ; N rcommaaccent ; B 30 -225 446 538 ; C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ; C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ; C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 773 718 ; C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 555 718 ; C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ; C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ; C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ; C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ; C -1 ; WX 500 ; N zdotaccent ; B 31 0 571 706 ; C -1 ; WX 667 ; N Ecaron ; B 86 0 762 929 ; C -1 ; WX 278 ; N Iogonek ; B -33 -225 341 718 ; C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 600 718 ; C -1 ; WX 584 ; N minus ; B 85 216 606 289 ; C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ; C -1 ; WX 556 ; N ncaron ; B 65 0 580 734 ; C -1 ; WX 278 ; N tcommaaccent ; B 63 -225 368 669 ; C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ; C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ; C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ; C -1 ; WX 549 ; N notequal ; B 34 -35 623 551 ; C -1 ; WX 556 ; N gcommaaccent ; B 42 -220 610 822 ; C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ; C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ; C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 573 538 ; C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ; C -1 ; WX 278 ; N imacron ; B 95 0 417 684 ; C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2705 KPX A C -30 KPX A Cacute -30 KPX A Ccaron -30 KPX A Ccedilla -30 KPX A G -30 KPX A Gbreve -30 KPX A Gcommaaccent -30 KPX A O -30 KPX A Oacute -30 KPX A Ocircumflex -30 KPX A Odieresis -30 KPX A Ograve -30 KPX A Ohungarumlaut -30 KPX A Omacron -30 KPX A Oslash -30 KPX A Otilde -30 KPX A Q -30 KPX A T -120 KPX A Tcaron -120 KPX A Tcommaaccent -120 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -70 KPX A W -50 KPX A Y -100 KPX A Yacute -100 KPX A Ydieresis -100 KPX A u -30 KPX A uacute -30 KPX A ucircumflex -30 KPX A udieresis -30 KPX A ugrave -30 KPX A uhungarumlaut -30 KPX A umacron -30 KPX A uogonek -30 KPX A uring -30 KPX A v -40 KPX A w -40 KPX A y -40 KPX A yacute -40 KPX A ydieresis -40 KPX Aacute C -30 KPX Aacute Cacute -30 KPX Aacute Ccaron -30 KPX Aacute Ccedilla -30 KPX Aacute G -30 KPX Aacute Gbreve -30 KPX Aacute Gcommaaccent -30 KPX Aacute O -30 KPX Aacute Oacute -30 KPX Aacute Ocircumflex -30 KPX Aacute Odieresis -30 KPX Aacute Ograve -30 KPX Aacute Ohungarumlaut -30 KPX Aacute Omacron -30 KPX Aacute Oslash -30 KPX Aacute Otilde -30 KPX Aacute Q -30 KPX Aacute T -120 KPX Aacute Tcaron -120 KPX Aacute Tcommaaccent -120 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -70 KPX Aacute W -50 KPX Aacute Y -100 KPX Aacute Yacute -100 KPX Aacute Ydieresis -100 KPX Aacute u -30 KPX Aacute uacute -30 KPX Aacute ucircumflex -30 KPX Aacute udieresis -30 KPX Aacute ugrave -30 KPX Aacute uhungarumlaut -30 KPX Aacute umacron -30 KPX Aacute uogonek -30 KPX Aacute uring -30 KPX Aacute v -40 KPX Aacute w -40 KPX Aacute y -40 KPX Aacute yacute -40 KPX Aacute ydieresis -40 KPX Abreve C -30 KPX Abreve Cacute -30 KPX Abreve Ccaron -30 KPX Abreve Ccedilla -30 KPX Abreve G -30 KPX Abreve Gbreve -30 KPX Abreve Gcommaaccent -30 KPX Abreve O -30 KPX Abreve Oacute -30 KPX Abreve Ocircumflex -30 KPX Abreve Odieresis -30 KPX Abreve Ograve -30 KPX Abreve Ohungarumlaut -30 KPX Abreve Omacron -30 KPX Abreve Oslash -30 KPX Abreve Otilde -30 KPX Abreve Q -30 KPX Abreve T -120 KPX Abreve Tcaron -120 KPX Abreve Tcommaaccent -120 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -70 KPX Abreve W -50 KPX Abreve Y -100 KPX Abreve Yacute -100 KPX Abreve Ydieresis -100 KPX Abreve u -30 KPX Abreve uacute -30 KPX Abreve ucircumflex -30 KPX Abreve udieresis -30 KPX Abreve ugrave -30 KPX Abreve uhungarumlaut -30 KPX Abreve umacron -30 KPX Abreve uogonek -30 KPX Abreve uring -30 KPX Abreve v -40 KPX Abreve w -40 KPX Abreve y -40 KPX Abreve yacute -40 KPX Abreve ydieresis -40 KPX Acircumflex C -30 KPX Acircumflex Cacute -30 KPX Acircumflex Ccaron -30 KPX Acircumflex Ccedilla -30 KPX Acircumflex G -30 KPX Acircumflex Gbreve -30 KPX Acircumflex Gcommaaccent -30 KPX Acircumflex O -30 KPX Acircumflex Oacute -30 KPX Acircumflex Ocircumflex -30 KPX Acircumflex Odieresis -30 KPX Acircumflex Ograve -30 KPX Acircumflex Ohungarumlaut -30 KPX Acircumflex Omacron -30 KPX Acircumflex Oslash -30 KPX Acircumflex Otilde -30 KPX Acircumflex Q -30 KPX Acircumflex T -120 KPX Acircumflex Tcaron -120 KPX Acircumflex Tcommaaccent -120 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -70 KPX Acircumflex W -50 KPX Acircumflex Y -100 KPX Acircumflex Yacute -100 KPX Acircumflex Ydieresis -100 KPX Acircumflex u -30 KPX Acircumflex uacute -30 KPX Acircumflex ucircumflex -30 KPX Acircumflex udieresis -30 KPX Acircumflex ugrave -30 KPX Acircumflex uhungarumlaut -30 KPX Acircumflex umacron -30 KPX Acircumflex uogonek -30 KPX Acircumflex uring -30 KPX Acircumflex v -40 KPX Acircumflex w -40 KPX Acircumflex y -40 KPX Acircumflex yacute -40 KPX Acircumflex ydieresis -40 KPX Adieresis C -30 KPX Adieresis Cacute -30 KPX Adieresis Ccaron -30 KPX Adieresis Ccedilla -30 KPX Adieresis G -30 KPX Adieresis Gbreve -30 KPX Adieresis Gcommaaccent -30 KPX Adieresis O -30 KPX Adieresis Oacute -30 KPX Adieresis Ocircumflex -30 KPX Adieresis Odieresis -30 KPX Adieresis Ograve -30 KPX Adieresis Ohungarumlaut -30 KPX Adieresis Omacron -30 KPX Adieresis Oslash -30 KPX Adieresis Otilde -30 KPX Adieresis Q -30 KPX Adieresis T -120 KPX Adieresis Tcaron -120 KPX Adieresis Tcommaaccent -120 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -70 KPX Adieresis W -50 KPX Adieresis Y -100 KPX Adieresis Yacute -100 KPX Adieresis Ydieresis -100 KPX Adieresis u -30 KPX Adieresis uacute -30 KPX Adieresis ucircumflex -30 KPX Adieresis udieresis -30 KPX Adieresis ugrave -30 KPX Adieresis uhungarumlaut -30 KPX Adieresis umacron -30 KPX Adieresis uogonek -30 KPX Adieresis uring -30 KPX Adieresis v -40 KPX Adieresis w -40 KPX Adieresis y -40 KPX Adieresis yacute -40 KPX Adieresis ydieresis -40 KPX Agrave C -30 KPX Agrave Cacute -30 KPX Agrave Ccaron -30 KPX Agrave Ccedilla -30 KPX Agrave G -30 KPX Agrave Gbreve -30 KPX Agrave Gcommaaccent -30 KPX Agrave O -30 KPX Agrave Oacute -30 KPX Agrave Ocircumflex -30 KPX Agrave Odieresis -30 KPX Agrave Ograve -30 KPX Agrave Ohungarumlaut -30 KPX Agrave Omacron -30 KPX Agrave Oslash -30 KPX Agrave Otilde -30 KPX Agrave Q -30 KPX Agrave T -120 KPX Agrave Tcaron -120 KPX Agrave Tcommaaccent -120 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -70 KPX Agrave W -50 KPX Agrave Y -100 KPX Agrave Yacute -100 KPX Agrave Ydieresis -100 KPX Agrave u -30 KPX Agrave uacute -30 KPX Agrave ucircumflex -30 KPX Agrave udieresis -30 KPX Agrave ugrave -30 KPX Agrave uhungarumlaut -30 KPX Agrave umacron -30 KPX Agrave uogonek -30 KPX Agrave uring -30 KPX Agrave v -40 KPX Agrave w -40 KPX Agrave y -40 KPX Agrave yacute -40 KPX Agrave ydieresis -40 KPX Amacron C -30 KPX Amacron Cacute -30 KPX Amacron Ccaron -30 KPX Amacron Ccedilla -30 KPX Amacron G -30 KPX Amacron Gbreve -30 KPX Amacron Gcommaaccent -30 KPX Amacron O -30 KPX Amacron Oacute -30 KPX Amacron Ocircumflex -30 KPX Amacron Odieresis -30 KPX Amacron Ograve -30 KPX Amacron Ohungarumlaut -30 KPX Amacron Omacron -30 KPX Amacron Oslash -30 KPX Amacron Otilde -30 KPX Amacron Q -30 KPX Amacron T -120 KPX Amacron Tcaron -120 KPX Amacron Tcommaaccent -120 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -70 KPX Amacron W -50 KPX Amacron Y -100 KPX Amacron Yacute -100 KPX Amacron Ydieresis -100 KPX Amacron u -30 KPX Amacron uacute -30 KPX Amacron ucircumflex -30 KPX Amacron udieresis -30 KPX Amacron ugrave -30 KPX Amacron uhungarumlaut -30 KPX Amacron umacron -30 KPX Amacron uogonek -30 KPX Amacron uring -30 KPX Amacron v -40 KPX Amacron w -40 KPX Amacron y -40 KPX Amacron yacute -40 KPX Amacron ydieresis -40 KPX Aogonek C -30 KPX Aogonek Cacute -30 KPX Aogonek Ccaron -30 KPX Aogonek Ccedilla -30 KPX Aogonek G -30 KPX Aogonek Gbreve -30 KPX Aogonek Gcommaaccent -30 KPX Aogonek O -30 KPX Aogonek Oacute -30 KPX Aogonek Ocircumflex -30 KPX Aogonek Odieresis -30 KPX Aogonek Ograve -30 KPX Aogonek Ohungarumlaut -30 KPX Aogonek Omacron -30 KPX Aogonek Oslash -30 KPX Aogonek Otilde -30 KPX Aogonek Q -30 KPX Aogonek T -120 KPX Aogonek Tcaron -120 KPX Aogonek Tcommaaccent -120 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -70 KPX Aogonek W -50 KPX Aogonek Y -100 KPX Aogonek Yacute -100 KPX Aogonek Ydieresis -100 KPX Aogonek u -30 KPX Aogonek uacute -30 KPX Aogonek ucircumflex -30 KPX Aogonek udieresis -30 KPX Aogonek ugrave -30 KPX Aogonek uhungarumlaut -30 KPX Aogonek umacron -30 KPX Aogonek uogonek -30 KPX Aogonek uring -30 KPX Aogonek v -40 KPX Aogonek w -40 KPX Aogonek y -40 KPX Aogonek yacute -40 KPX Aogonek ydieresis -40 KPX Aring C -30 KPX Aring Cacute -30 KPX Aring Ccaron -30 KPX Aring Ccedilla -30 KPX Aring G -30 KPX Aring Gbreve -30 KPX Aring Gcommaaccent -30 KPX Aring O -30 KPX Aring Oacute -30 KPX Aring Ocircumflex -30 KPX Aring Odieresis -30 KPX Aring Ograve -30 KPX Aring Ohungarumlaut -30 KPX Aring Omacron -30 KPX Aring Oslash -30 KPX Aring Otilde -30 KPX Aring Q -30 KPX Aring T -120 KPX Aring Tcaron -120 KPX Aring Tcommaaccent -120 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -70 KPX Aring W -50 KPX Aring Y -100 KPX Aring Yacute -100 KPX Aring Ydieresis -100 KPX Aring u -30 KPX Aring uacute -30 KPX Aring ucircumflex -30 KPX Aring udieresis -30 KPX Aring ugrave -30 KPX Aring uhungarumlaut -30 KPX Aring umacron -30 KPX Aring uogonek -30 KPX Aring uring -30 KPX Aring v -40 KPX Aring w -40 KPX Aring y -40 KPX Aring yacute -40 KPX Aring ydieresis -40 KPX Atilde C -30 KPX Atilde Cacute -30 KPX Atilde Ccaron -30 KPX Atilde Ccedilla -30 KPX Atilde G -30 KPX Atilde Gbreve -30 KPX Atilde Gcommaaccent -30 KPX Atilde O -30 KPX Atilde Oacute -30 KPX Atilde Ocircumflex -30 KPX Atilde Odieresis -30 KPX Atilde Ograve -30 KPX Atilde Ohungarumlaut -30 KPX Atilde Omacron -30 KPX Atilde Oslash -30 KPX Atilde Otilde -30 KPX Atilde Q -30 KPX Atilde T -120 KPX Atilde Tcaron -120 KPX Atilde Tcommaaccent -120 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -70 KPX Atilde W -50 KPX Atilde Y -100 KPX Atilde Yacute -100 KPX Atilde Ydieresis -100 KPX Atilde u -30 KPX Atilde uacute -30 KPX Atilde ucircumflex -30 KPX Atilde udieresis -30 KPX Atilde ugrave -30 KPX Atilde uhungarumlaut -30 KPX Atilde umacron -30 KPX Atilde uogonek -30 KPX Atilde uring -30 KPX Atilde v -40 KPX Atilde w -40 KPX Atilde y -40 KPX Atilde yacute -40 KPX Atilde ydieresis -40 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX B comma -20 KPX B period -20 KPX C comma -30 KPX C period -30 KPX Cacute comma -30 KPX Cacute period -30 KPX Ccaron comma -30 KPX Ccaron period -30 KPX Ccedilla comma -30 KPX Ccedilla period -30 KPX D A -40 KPX D Aacute -40 KPX D Abreve -40 KPX D Acircumflex -40 KPX D Adieresis -40 KPX D Agrave -40 KPX D Amacron -40 KPX D Aogonek -40 KPX D Aring -40 KPX D Atilde -40 KPX D V -70 KPX D W -40 KPX D Y -90 KPX D Yacute -90 KPX D Ydieresis -90 KPX D comma -70 KPX D period -70 KPX Dcaron A -40 KPX Dcaron Aacute -40 KPX Dcaron Abreve -40 KPX Dcaron Acircumflex -40 KPX Dcaron Adieresis -40 KPX Dcaron Agrave -40 KPX Dcaron Amacron -40 KPX Dcaron Aogonek -40 KPX Dcaron Aring -40 KPX Dcaron Atilde -40 KPX Dcaron V -70 KPX Dcaron W -40 KPX Dcaron Y -90 KPX Dcaron Yacute -90 KPX Dcaron Ydieresis -90 KPX Dcaron comma -70 KPX Dcaron period -70 KPX Dcroat A -40 KPX Dcroat Aacute -40 KPX Dcroat Abreve -40 KPX Dcroat Acircumflex -40 KPX Dcroat Adieresis -40 KPX Dcroat Agrave -40 KPX Dcroat Amacron -40 KPX Dcroat Aogonek -40 KPX Dcroat Aring -40 KPX Dcroat Atilde -40 KPX Dcroat V -70 KPX Dcroat W -40 KPX Dcroat Y -90 KPX Dcroat Yacute -90 KPX Dcroat Ydieresis -90 KPX Dcroat comma -70 KPX Dcroat period -70 KPX F A -80 KPX F Aacute -80 KPX F Abreve -80 KPX F Acircumflex -80 KPX F Adieresis -80 KPX F Agrave -80 KPX F Amacron -80 KPX F Aogonek -80 KPX F Aring -80 KPX F Atilde -80 KPX F a -50 KPX F aacute -50 KPX F abreve -50 KPX F acircumflex -50 KPX F adieresis -50 KPX F agrave -50 KPX F amacron -50 KPX F aogonek -50 KPX F aring -50 KPX F atilde -50 KPX F comma -150 KPX F e -30 KPX F eacute -30 KPX F ecaron -30 KPX F ecircumflex -30 KPX F edieresis -30 KPX F edotaccent -30 KPX F egrave -30 KPX F emacron -30 KPX F eogonek -30 KPX F o -30 KPX F oacute -30 KPX F ocircumflex -30 KPX F odieresis -30 KPX F ograve -30 KPX F ohungarumlaut -30 KPX F omacron -30 KPX F oslash -30 KPX F otilde -30 KPX F period -150 KPX F r -45 KPX F racute -45 KPX F rcaron -45 KPX F rcommaaccent -45 KPX J A -20 KPX J Aacute -20 KPX J Abreve -20 KPX J Acircumflex -20 KPX J Adieresis -20 KPX J Agrave -20 KPX J Amacron -20 KPX J Aogonek -20 KPX J Aring -20 KPX J Atilde -20 KPX J a -20 KPX J aacute -20 KPX J abreve -20 KPX J acircumflex -20 KPX J adieresis -20 KPX J agrave -20 KPX J amacron -20 KPX J aogonek -20 KPX J aring -20 KPX J atilde -20 KPX J comma -30 KPX J period -30 KPX J u -20 KPX J uacute -20 KPX J ucircumflex -20 KPX J udieresis -20 KPX J ugrave -20 KPX J uhungarumlaut -20 KPX J umacron -20 KPX J uogonek -20 KPX J uring -20 KPX K O -50 KPX K Oacute -50 KPX K Ocircumflex -50 KPX K Odieresis -50 KPX K Ograve -50 KPX K Ohungarumlaut -50 KPX K Omacron -50 KPX K Oslash -50 KPX K Otilde -50 KPX K e -40 KPX K eacute -40 KPX K ecaron -40 KPX K ecircumflex -40 KPX K edieresis -40 KPX K edotaccent -40 KPX K egrave -40 KPX K emacron -40 KPX K eogonek -40 KPX K o -40 KPX K oacute -40 KPX K ocircumflex -40 KPX K odieresis -40 KPX K ograve -40 KPX K ohungarumlaut -40 KPX K omacron -40 KPX K oslash -40 KPX K otilde -40 KPX K u -30 KPX K uacute -30 KPX K ucircumflex -30 KPX K udieresis -30 KPX K ugrave -30 KPX K uhungarumlaut -30 KPX K umacron -30 KPX K uogonek -30 KPX K uring -30 KPX K y -50 KPX K yacute -50 KPX K ydieresis -50 KPX Kcommaaccent O -50 KPX Kcommaaccent Oacute -50 KPX Kcommaaccent Ocircumflex -50 KPX Kcommaaccent Odieresis -50 KPX Kcommaaccent Ograve -50 KPX Kcommaaccent Ohungarumlaut -50 KPX Kcommaaccent Omacron -50 KPX Kcommaaccent Oslash -50 KPX Kcommaaccent Otilde -50 KPX Kcommaaccent e -40 KPX Kcommaaccent eacute -40 KPX Kcommaaccent ecaron -40 KPX Kcommaaccent ecircumflex -40 KPX Kcommaaccent edieresis -40 KPX Kcommaaccent edotaccent -40 KPX Kcommaaccent egrave -40 KPX Kcommaaccent emacron -40 KPX Kcommaaccent eogonek -40 KPX Kcommaaccent o -40 KPX Kcommaaccent oacute -40 KPX Kcommaaccent ocircumflex -40 KPX Kcommaaccent odieresis -40 KPX Kcommaaccent ograve -40 KPX Kcommaaccent ohungarumlaut -40 KPX Kcommaaccent omacron -40 KPX Kcommaaccent oslash -40 KPX Kcommaaccent otilde -40 KPX Kcommaaccent u -30 KPX Kcommaaccent uacute -30 KPX Kcommaaccent ucircumflex -30 KPX Kcommaaccent udieresis -30 KPX Kcommaaccent ugrave -30 KPX Kcommaaccent uhungarumlaut -30 KPX Kcommaaccent umacron -30 KPX Kcommaaccent uogonek -30 KPX Kcommaaccent uring -30 KPX Kcommaaccent y -50 KPX Kcommaaccent yacute -50 KPX Kcommaaccent ydieresis -50 KPX L T -110 KPX L Tcaron -110 KPX L Tcommaaccent -110 KPX L V -110 KPX L W -70 KPX L Y -140 KPX L Yacute -140 KPX L Ydieresis -140 KPX L quotedblright -140 KPX L quoteright -160 KPX L y -30 KPX L yacute -30 KPX L ydieresis -30 KPX Lacute T -110 KPX Lacute Tcaron -110 KPX Lacute Tcommaaccent -110 KPX Lacute V -110 KPX Lacute W -70 KPX Lacute Y -140 KPX Lacute Yacute -140 KPX Lacute Ydieresis -140 KPX Lacute quotedblright -140 KPX Lacute quoteright -160 KPX Lacute y -30 KPX Lacute yacute -30 KPX Lacute ydieresis -30 KPX Lcaron T -110 KPX Lcaron Tcaron -110 KPX Lcaron Tcommaaccent -110 KPX Lcaron V -110 KPX Lcaron W -70 KPX Lcaron Y -140 KPX Lcaron Yacute -140 KPX Lcaron Ydieresis -140 KPX Lcaron quotedblright -140 KPX Lcaron quoteright -160 KPX Lcaron y -30 KPX Lcaron yacute -30 KPX Lcaron ydieresis -30 KPX Lcommaaccent T -110 KPX Lcommaaccent Tcaron -110 KPX Lcommaaccent Tcommaaccent -110 KPX Lcommaaccent V -110 KPX Lcommaaccent W -70 KPX Lcommaaccent Y -140 KPX Lcommaaccent Yacute -140 KPX Lcommaaccent Ydieresis -140 KPX Lcommaaccent quotedblright -140 KPX Lcommaaccent quoteright -160 KPX Lcommaaccent y -30 KPX Lcommaaccent yacute -30 KPX Lcommaaccent ydieresis -30 KPX Lslash T -110 KPX Lslash Tcaron -110 KPX Lslash Tcommaaccent -110 KPX Lslash V -110 KPX Lslash W -70 KPX Lslash Y -140 KPX Lslash Yacute -140 KPX Lslash Ydieresis -140 KPX Lslash quotedblright -140 KPX Lslash quoteright -160 KPX Lslash y -30 KPX Lslash yacute -30 KPX Lslash ydieresis -30 KPX O A -20 KPX O Aacute -20 KPX O Abreve -20 KPX O Acircumflex -20 KPX O Adieresis -20 KPX O Agrave -20 KPX O Amacron -20 KPX O Aogonek -20 KPX O Aring -20 KPX O Atilde -20 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -30 KPX O X -60 KPX O Y -70 KPX O Yacute -70 KPX O Ydieresis -70 KPX O comma -40 KPX O period -40 KPX Oacute A -20 KPX Oacute Aacute -20 KPX Oacute Abreve -20 KPX Oacute Acircumflex -20 KPX Oacute Adieresis -20 KPX Oacute Agrave -20 KPX Oacute Amacron -20 KPX Oacute Aogonek -20 KPX Oacute Aring -20 KPX Oacute Atilde -20 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -30 KPX Oacute X -60 KPX Oacute Y -70 KPX Oacute Yacute -70 KPX Oacute Ydieresis -70 KPX Oacute comma -40 KPX Oacute period -40 KPX Ocircumflex A -20 KPX Ocircumflex Aacute -20 KPX Ocircumflex Abreve -20 KPX Ocircumflex Acircumflex -20 KPX Ocircumflex Adieresis -20 KPX Ocircumflex Agrave -20 KPX Ocircumflex Amacron -20 KPX Ocircumflex Aogonek -20 KPX Ocircumflex Aring -20 KPX Ocircumflex Atilde -20 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -30 KPX Ocircumflex X -60 KPX Ocircumflex Y -70 KPX Ocircumflex Yacute -70 KPX Ocircumflex Ydieresis -70 KPX Ocircumflex comma -40 KPX Ocircumflex period -40 KPX Odieresis A -20 KPX Odieresis Aacute -20 KPX Odieresis Abreve -20 KPX Odieresis Acircumflex -20 KPX Odieresis Adieresis -20 KPX Odieresis Agrave -20 KPX Odieresis Amacron -20 KPX Odieresis Aogonek -20 KPX Odieresis Aring -20 KPX Odieresis Atilde -20 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -30 KPX Odieresis X -60 KPX Odieresis Y -70 KPX Odieresis Yacute -70 KPX Odieresis Ydieresis -70 KPX Odieresis comma -40 KPX Odieresis period -40 KPX Ograve A -20 KPX Ograve Aacute -20 KPX Ograve Abreve -20 KPX Ograve Acircumflex -20 KPX Ograve Adieresis -20 KPX Ograve Agrave -20 KPX Ograve Amacron -20 KPX Ograve Aogonek -20 KPX Ograve Aring -20 KPX Ograve Atilde -20 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -30 KPX Ograve X -60 KPX Ograve Y -70 KPX Ograve Yacute -70 KPX Ograve Ydieresis -70 KPX Ograve comma -40 KPX Ograve period -40 KPX Ohungarumlaut A -20 KPX Ohungarumlaut Aacute -20 KPX Ohungarumlaut Abreve -20 KPX Ohungarumlaut Acircumflex -20 KPX Ohungarumlaut Adieresis -20 KPX Ohungarumlaut Agrave -20 KPX Ohungarumlaut Amacron -20 KPX Ohungarumlaut Aogonek -20 KPX Ohungarumlaut Aring -20 KPX Ohungarumlaut Atilde -20 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -30 KPX Ohungarumlaut X -60 KPX Ohungarumlaut Y -70 KPX Ohungarumlaut Yacute -70 KPX Ohungarumlaut Ydieresis -70 KPX Ohungarumlaut comma -40 KPX Ohungarumlaut period -40 KPX Omacron A -20 KPX Omacron Aacute -20 KPX Omacron Abreve -20 KPX Omacron Acircumflex -20 KPX Omacron Adieresis -20 KPX Omacron Agrave -20 KPX Omacron Amacron -20 KPX Omacron Aogonek -20 KPX Omacron Aring -20 KPX Omacron Atilde -20 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -30 KPX Omacron X -60 KPX Omacron Y -70 KPX Omacron Yacute -70 KPX Omacron Ydieresis -70 KPX Omacron comma -40 KPX Omacron period -40 KPX Oslash A -20 KPX Oslash Aacute -20 KPX Oslash Abreve -20 KPX Oslash Acircumflex -20 KPX Oslash Adieresis -20 KPX Oslash Agrave -20 KPX Oslash Amacron -20 KPX Oslash Aogonek -20 KPX Oslash Aring -20 KPX Oslash Atilde -20 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -30 KPX Oslash X -60 KPX Oslash Y -70 KPX Oslash Yacute -70 KPX Oslash Ydieresis -70 KPX Oslash comma -40 KPX Oslash period -40 KPX Otilde A -20 KPX Otilde Aacute -20 KPX Otilde Abreve -20 KPX Otilde Acircumflex -20 KPX Otilde Adieresis -20 KPX Otilde Agrave -20 KPX Otilde Amacron -20 KPX Otilde Aogonek -20 KPX Otilde Aring -20 KPX Otilde Atilde -20 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -30 KPX Otilde X -60 KPX Otilde Y -70 KPX Otilde Yacute -70 KPX Otilde Ydieresis -70 KPX Otilde comma -40 KPX Otilde period -40 KPX P A -120 KPX P Aacute -120 KPX P Abreve -120 KPX P Acircumflex -120 KPX P Adieresis -120 KPX P Agrave -120 KPX P Amacron -120 KPX P Aogonek -120 KPX P Aring -120 KPX P Atilde -120 KPX P a -40 KPX P aacute -40 KPX P abreve -40 KPX P acircumflex -40 KPX P adieresis -40 KPX P agrave -40 KPX P amacron -40 KPX P aogonek -40 KPX P aring -40 KPX P atilde -40 KPX P comma -180 KPX P e -50 KPX P eacute -50 KPX P ecaron -50 KPX P ecircumflex -50 KPX P edieresis -50 KPX P edotaccent -50 KPX P egrave -50 KPX P emacron -50 KPX P eogonek -50 KPX P o -50 KPX P oacute -50 KPX P ocircumflex -50 KPX P odieresis -50 KPX P ograve -50 KPX P ohungarumlaut -50 KPX P omacron -50 KPX P oslash -50 KPX P otilde -50 KPX P period -180 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX R O -20 KPX R Oacute -20 KPX R Ocircumflex -20 KPX R Odieresis -20 KPX R Ograve -20 KPX R Ohungarumlaut -20 KPX R Omacron -20 KPX R Oslash -20 KPX R Otilde -20 KPX R T -30 KPX R Tcaron -30 KPX R Tcommaaccent -30 KPX R U -40 KPX R Uacute -40 KPX R Ucircumflex -40 KPX R Udieresis -40 KPX R Ugrave -40 KPX R Uhungarumlaut -40 KPX R Umacron -40 KPX R Uogonek -40 KPX R Uring -40 KPX R V -50 KPX R W -30 KPX R Y -50 KPX R Yacute -50 KPX R Ydieresis -50 KPX Racute O -20 KPX Racute Oacute -20 KPX Racute Ocircumflex -20 KPX Racute Odieresis -20 KPX Racute Ograve -20 KPX Racute Ohungarumlaut -20 KPX Racute Omacron -20 KPX Racute Oslash -20 KPX Racute Otilde -20 KPX Racute T -30 KPX Racute Tcaron -30 KPX Racute Tcommaaccent -30 KPX Racute U -40 KPX Racute Uacute -40 KPX Racute Ucircumflex -40 KPX Racute Udieresis -40 KPX Racute Ugrave -40 KPX Racute Uhungarumlaut -40 KPX Racute Umacron -40 KPX Racute Uogonek -40 KPX Racute Uring -40 KPX Racute V -50 KPX Racute W -30 KPX Racute Y -50 KPX Racute Yacute -50 KPX Racute Ydieresis -50 KPX Rcaron O -20 KPX Rcaron Oacute -20 KPX Rcaron Ocircumflex -20 KPX Rcaron Odieresis -20 KPX Rcaron Ograve -20 KPX Rcaron Ohungarumlaut -20 KPX Rcaron Omacron -20 KPX Rcaron Oslash -20 KPX Rcaron Otilde -20 KPX Rcaron T -30 KPX Rcaron Tcaron -30 KPX Rcaron Tcommaaccent -30 KPX Rcaron U -40 KPX Rcaron Uacute -40 KPX Rcaron Ucircumflex -40 KPX Rcaron Udieresis -40 KPX Rcaron Ugrave -40 KPX Rcaron Uhungarumlaut -40 KPX Rcaron Umacron -40 KPX Rcaron Uogonek -40 KPX Rcaron Uring -40 KPX Rcaron V -50 KPX Rcaron W -30 KPX Rcaron Y -50 KPX Rcaron Yacute -50 KPX Rcaron Ydieresis -50 KPX Rcommaaccent O -20 KPX Rcommaaccent Oacute -20 KPX Rcommaaccent Ocircumflex -20 KPX Rcommaaccent Odieresis -20 KPX Rcommaaccent Ograve -20 KPX Rcommaaccent Ohungarumlaut -20 KPX Rcommaaccent Omacron -20 KPX Rcommaaccent Oslash -20 KPX Rcommaaccent Otilde -20 KPX Rcommaaccent T -30 KPX Rcommaaccent Tcaron -30 KPX Rcommaaccent Tcommaaccent -30 KPX Rcommaaccent U -40 KPX Rcommaaccent Uacute -40 KPX Rcommaaccent Ucircumflex -40 KPX Rcommaaccent Udieresis -40 KPX Rcommaaccent Ugrave -40 KPX Rcommaaccent Uhungarumlaut -40 KPX Rcommaaccent Umacron -40 KPX Rcommaaccent Uogonek -40 KPX Rcommaaccent Uring -40 KPX Rcommaaccent V -50 KPX Rcommaaccent W -30 KPX Rcommaaccent Y -50 KPX Rcommaaccent Yacute -50 KPX Rcommaaccent Ydieresis -50 KPX S comma -20 KPX S period -20 KPX Sacute comma -20 KPX Sacute period -20 KPX Scaron comma -20 KPX Scaron period -20 KPX Scedilla comma -20 KPX Scedilla period -20 KPX Scommaaccent comma -20 KPX Scommaaccent period -20 KPX T A -120 KPX T Aacute -120 KPX T Abreve -120 KPX T Acircumflex -120 KPX T Adieresis -120 KPX T Agrave -120 KPX T Amacron -120 KPX T Aogonek -120 KPX T Aring -120 KPX T Atilde -120 KPX T O -40 KPX T Oacute -40 KPX T Ocircumflex -40 KPX T Odieresis -40 KPX T Ograve -40 KPX T Ohungarumlaut -40 KPX T Omacron -40 KPX T Oslash -40 KPX T Otilde -40 KPX T a -120 KPX T aacute -120 KPX T abreve -60 KPX T acircumflex -120 KPX T adieresis -120 KPX T agrave -120 KPX T amacron -60 KPX T aogonek -120 KPX T aring -120 KPX T atilde -60 KPX T colon -20 KPX T comma -120 KPX T e -120 KPX T eacute -120 KPX T ecaron -120 KPX T ecircumflex -120 KPX T edieresis -120 KPX T edotaccent -120 KPX T egrave -60 KPX T emacron -60 KPX T eogonek -120 KPX T hyphen -140 KPX T o -120 KPX T oacute -120 KPX T ocircumflex -120 KPX T odieresis -120 KPX T ograve -120 KPX T ohungarumlaut -120 KPX T omacron -60 KPX T oslash -120 KPX T otilde -60 KPX T period -120 KPX T r -120 KPX T racute -120 KPX T rcaron -120 KPX T rcommaaccent -120 KPX T semicolon -20 KPX T u -120 KPX T uacute -120 KPX T ucircumflex -120 KPX T udieresis -120 KPX T ugrave -120 KPX T uhungarumlaut -120 KPX T umacron -60 KPX T uogonek -120 KPX T uring -120 KPX T w -120 KPX T y -120 KPX T yacute -120 KPX T ydieresis -60 KPX Tcaron A -120 KPX Tcaron Aacute -120 KPX Tcaron Abreve -120 KPX Tcaron Acircumflex -120 KPX Tcaron Adieresis -120 KPX Tcaron Agrave -120 KPX Tcaron Amacron -120 KPX Tcaron Aogonek -120 KPX Tcaron Aring -120 KPX Tcaron Atilde -120 KPX Tcaron O -40 KPX Tcaron Oacute -40 KPX Tcaron Ocircumflex -40 KPX Tcaron Odieresis -40 KPX Tcaron Ograve -40 KPX Tcaron Ohungarumlaut -40 KPX Tcaron Omacron -40 KPX Tcaron Oslash -40 KPX Tcaron Otilde -40 KPX Tcaron a -120 KPX Tcaron aacute -120 KPX Tcaron abreve -60 KPX Tcaron acircumflex -120 KPX Tcaron adieresis -120 KPX Tcaron agrave -120 KPX Tcaron amacron -60 KPX Tcaron aogonek -120 KPX Tcaron aring -120 KPX Tcaron atilde -60 KPX Tcaron colon -20 KPX Tcaron comma -120 KPX Tcaron e -120 KPX Tcaron eacute -120 KPX Tcaron ecaron -120 KPX Tcaron ecircumflex -120 KPX Tcaron edieresis -120 KPX Tcaron edotaccent -120 KPX Tcaron egrave -60 KPX Tcaron emacron -60 KPX Tcaron eogonek -120 KPX Tcaron hyphen -140 KPX Tcaron o -120 KPX Tcaron oacute -120 KPX Tcaron ocircumflex -120 KPX Tcaron odieresis -120 KPX Tcaron ograve -120 KPX Tcaron ohungarumlaut -120 KPX Tcaron omacron -60 KPX Tcaron oslash -120 KPX Tcaron otilde -60 KPX Tcaron period -120 KPX Tcaron r -120 KPX Tcaron racute -120 KPX Tcaron rcaron -120 KPX Tcaron rcommaaccent -120 KPX Tcaron semicolon -20 KPX Tcaron u -120 KPX Tcaron uacute -120 KPX Tcaron ucircumflex -120 KPX Tcaron udieresis -120 KPX Tcaron ugrave -120 KPX Tcaron uhungarumlaut -120 KPX Tcaron umacron -60 KPX Tcaron uogonek -120 KPX Tcaron uring -120 KPX Tcaron w -120 KPX Tcaron y -120 KPX Tcaron yacute -120 KPX Tcaron ydieresis -60 KPX Tcommaaccent A -120 KPX Tcommaaccent Aacute -120 KPX Tcommaaccent Abreve -120 KPX Tcommaaccent Acircumflex -120 KPX Tcommaaccent Adieresis -120 KPX Tcommaaccent Agrave -120 KPX Tcommaaccent Amacron -120 KPX Tcommaaccent Aogonek -120 KPX Tcommaaccent Aring -120 KPX Tcommaaccent Atilde -120 KPX Tcommaaccent O -40 KPX Tcommaaccent Oacute -40 KPX Tcommaaccent Ocircumflex -40 KPX Tcommaaccent Odieresis -40 KPX Tcommaaccent Ograve -40 KPX Tcommaaccent Ohungarumlaut -40 KPX Tcommaaccent Omacron -40 KPX Tcommaaccent Oslash -40 KPX Tcommaaccent Otilde -40 KPX Tcommaaccent a -120 KPX Tcommaaccent aacute -120 KPX Tcommaaccent abreve -60 KPX Tcommaaccent acircumflex -120 KPX Tcommaaccent adieresis -120 KPX Tcommaaccent agrave -120 KPX Tcommaaccent amacron -60 KPX Tcommaaccent aogonek -120 KPX Tcommaaccent aring -120 KPX Tcommaaccent atilde -60 KPX Tcommaaccent colon -20 KPX Tcommaaccent comma -120 KPX Tcommaaccent e -120 KPX Tcommaaccent eacute -120 KPX Tcommaaccent ecaron -120 KPX Tcommaaccent ecircumflex -120 KPX Tcommaaccent edieresis -120 KPX Tcommaaccent edotaccent -120 KPX Tcommaaccent egrave -60 KPX Tcommaaccent emacron -60 KPX Tcommaaccent eogonek -120 KPX Tcommaaccent hyphen -140 KPX Tcommaaccent o -120 KPX Tcommaaccent oacute -120 KPX Tcommaaccent ocircumflex -120 KPX Tcommaaccent odieresis -120 KPX Tcommaaccent ograve -120 KPX Tcommaaccent ohungarumlaut -120 KPX Tcommaaccent omacron -60 KPX Tcommaaccent oslash -120 KPX Tcommaaccent otilde -60 KPX Tcommaaccent period -120 KPX Tcommaaccent r -120 KPX Tcommaaccent racute -120 KPX Tcommaaccent rcaron -120 KPX Tcommaaccent rcommaaccent -120 KPX Tcommaaccent semicolon -20 KPX Tcommaaccent u -120 KPX Tcommaaccent uacute -120 KPX Tcommaaccent ucircumflex -120 KPX Tcommaaccent udieresis -120 KPX Tcommaaccent ugrave -120 KPX Tcommaaccent uhungarumlaut -120 KPX Tcommaaccent umacron -60 KPX Tcommaaccent uogonek -120 KPX Tcommaaccent uring -120 KPX Tcommaaccent w -120 KPX Tcommaaccent y -120 KPX Tcommaaccent yacute -120 KPX Tcommaaccent ydieresis -60 KPX U A -40 KPX U Aacute -40 KPX U Abreve -40 KPX U Acircumflex -40 KPX U Adieresis -40 KPX U Agrave -40 KPX U Amacron -40 KPX U Aogonek -40 KPX U Aring -40 KPX U Atilde -40 KPX U comma -40 KPX U period -40 KPX Uacute A -40 KPX Uacute Aacute -40 KPX Uacute Abreve -40 KPX Uacute Acircumflex -40 KPX Uacute Adieresis -40 KPX Uacute Agrave -40 KPX Uacute Amacron -40 KPX Uacute Aogonek -40 KPX Uacute Aring -40 KPX Uacute Atilde -40 KPX Uacute comma -40 KPX Uacute period -40 KPX Ucircumflex A -40 KPX Ucircumflex Aacute -40 KPX Ucircumflex Abreve -40 KPX Ucircumflex Acircumflex -40 KPX Ucircumflex Adieresis -40 KPX Ucircumflex Agrave -40 KPX Ucircumflex Amacron -40 KPX Ucircumflex Aogonek -40 KPX Ucircumflex Aring -40 KPX Ucircumflex Atilde -40 KPX Ucircumflex comma -40 KPX Ucircumflex period -40 KPX Udieresis A -40 KPX Udieresis Aacute -40 KPX Udieresis Abreve -40 KPX Udieresis Acircumflex -40 KPX Udieresis Adieresis -40 KPX Udieresis Agrave -40 KPX Udieresis Amacron -40 KPX Udieresis Aogonek -40 KPX Udieresis Aring -40 KPX Udieresis Atilde -40 KPX Udieresis comma -40 KPX Udieresis period -40 KPX Ugrave A -40 KPX Ugrave Aacute -40 KPX Ugrave Abreve -40 KPX Ugrave Acircumflex -40 KPX Ugrave Adieresis -40 KPX Ugrave Agrave -40 KPX Ugrave Amacron -40 KPX Ugrave Aogonek -40 KPX Ugrave Aring -40 KPX Ugrave Atilde -40 KPX Ugrave comma -40 KPX Ugrave period -40 KPX Uhungarumlaut A -40 KPX Uhungarumlaut Aacute -40 KPX Uhungarumlaut Abreve -40 KPX Uhungarumlaut Acircumflex -40 KPX Uhungarumlaut Adieresis -40 KPX Uhungarumlaut Agrave -40 KPX Uhungarumlaut Amacron -40 KPX Uhungarumlaut Aogonek -40 KPX Uhungarumlaut Aring -40 KPX Uhungarumlaut Atilde -40 KPX Uhungarumlaut comma -40 KPX Uhungarumlaut period -40 KPX Umacron A -40 KPX Umacron Aacute -40 KPX Umacron Abreve -40 KPX Umacron Acircumflex -40 KPX Umacron Adieresis -40 KPX Umacron Agrave -40 KPX Umacron Amacron -40 KPX Umacron Aogonek -40 KPX Umacron Aring -40 KPX Umacron Atilde -40 KPX Umacron comma -40 KPX Umacron period -40 KPX Uogonek A -40 KPX Uogonek Aacute -40 KPX Uogonek Abreve -40 KPX Uogonek Acircumflex -40 KPX Uogonek Adieresis -40 KPX Uogonek Agrave -40 KPX Uogonek Amacron -40 KPX Uogonek Aogonek -40 KPX Uogonek Aring -40 KPX Uogonek Atilde -40 KPX Uogonek comma -40 KPX Uogonek period -40 KPX Uring A -40 KPX Uring Aacute -40 KPX Uring Abreve -40 KPX Uring Acircumflex -40 KPX Uring Adieresis -40 KPX Uring Agrave -40 KPX Uring Amacron -40 KPX Uring Aogonek -40 KPX Uring Aring -40 KPX Uring Atilde -40 KPX Uring comma -40 KPX Uring period -40 KPX V A -80 KPX V Aacute -80 KPX V Abreve -80 KPX V Acircumflex -80 KPX V Adieresis -80 KPX V Agrave -80 KPX V Amacron -80 KPX V Aogonek -80 KPX V Aring -80 KPX V Atilde -80 KPX V G -40 KPX V Gbreve -40 KPX V Gcommaaccent -40 KPX V O -40 KPX V Oacute -40 KPX V Ocircumflex -40 KPX V Odieresis -40 KPX V Ograve -40 KPX V Ohungarumlaut -40 KPX V Omacron -40 KPX V Oslash -40 KPX V Otilde -40 KPX V a -70 KPX V aacute -70 KPX V abreve -70 KPX V acircumflex -70 KPX V adieresis -70 KPX V agrave -70 KPX V amacron -70 KPX V aogonek -70 KPX V aring -70 KPX V atilde -70 KPX V colon -40 KPX V comma -125 KPX V e -80 KPX V eacute -80 KPX V ecaron -80 KPX V ecircumflex -80 KPX V edieresis -80 KPX V edotaccent -80 KPX V egrave -80 KPX V emacron -80 KPX V eogonek -80 KPX V hyphen -80 KPX V o -80 KPX V oacute -80 KPX V ocircumflex -80 KPX V odieresis -80 KPX V ograve -80 KPX V ohungarumlaut -80 KPX V omacron -80 KPX V oslash -80 KPX V otilde -80 KPX V period -125 KPX V semicolon -40 KPX V u -70 KPX V uacute -70 KPX V ucircumflex -70 KPX V udieresis -70 KPX V ugrave -70 KPX V uhungarumlaut -70 KPX V umacron -70 KPX V uogonek -70 KPX V uring -70 KPX W A -50 KPX W Aacute -50 KPX W Abreve -50 KPX W Acircumflex -50 KPX W Adieresis -50 KPX W Agrave -50 KPX W Amacron -50 KPX W Aogonek -50 KPX W Aring -50 KPX W Atilde -50 KPX W O -20 KPX W Oacute -20 KPX W Ocircumflex -20 KPX W Odieresis -20 KPX W Ograve -20 KPX W Ohungarumlaut -20 KPX W Omacron -20 KPX W Oslash -20 KPX W Otilde -20 KPX W a -40 KPX W aacute -40 KPX W abreve -40 KPX W acircumflex -40 KPX W adieresis -40 KPX W agrave -40 KPX W amacron -40 KPX W aogonek -40 KPX W aring -40 KPX W atilde -40 KPX W comma -80 KPX W e -30 KPX W eacute -30 KPX W ecaron -30 KPX W ecircumflex -30 KPX W edieresis -30 KPX W edotaccent -30 KPX W egrave -30 KPX W emacron -30 KPX W eogonek -30 KPX W hyphen -40 KPX W o -30 KPX W oacute -30 KPX W ocircumflex -30 KPX W odieresis -30 KPX W ograve -30 KPX W ohungarumlaut -30 KPX W omacron -30 KPX W oslash -30 KPX W otilde -30 KPX W period -80 KPX W u -30 KPX W uacute -30 KPX W ucircumflex -30 KPX W udieresis -30 KPX W ugrave -30 KPX W uhungarumlaut -30 KPX W umacron -30 KPX W uogonek -30 KPX W uring -30 KPX W y -20 KPX W yacute -20 KPX W ydieresis -20 KPX Y A -110 KPX Y Aacute -110 KPX Y Abreve -110 KPX Y Acircumflex -110 KPX Y Adieresis -110 KPX Y Agrave -110 KPX Y Amacron -110 KPX Y Aogonek -110 KPX Y Aring -110 KPX Y Atilde -110 KPX Y O -85 KPX Y Oacute -85 KPX Y Ocircumflex -85 KPX Y Odieresis -85 KPX Y Ograve -85 KPX Y Ohungarumlaut -85 KPX Y Omacron -85 KPX Y Oslash -85 KPX Y Otilde -85 KPX Y a -140 KPX Y aacute -140 KPX Y abreve -70 KPX Y acircumflex -140 KPX Y adieresis -140 KPX Y agrave -140 KPX Y amacron -70 KPX Y aogonek -140 KPX Y aring -140 KPX Y atilde -140 KPX Y colon -60 KPX Y comma -140 KPX Y e -140 KPX Y eacute -140 KPX Y ecaron -140 KPX Y ecircumflex -140 KPX Y edieresis -140 KPX Y edotaccent -140 KPX Y egrave -140 KPX Y emacron -70 KPX Y eogonek -140 KPX Y hyphen -140 KPX Y i -20 KPX Y iacute -20 KPX Y iogonek -20 KPX Y o -140 KPX Y oacute -140 KPX Y ocircumflex -140 KPX Y odieresis -140 KPX Y ograve -140 KPX Y ohungarumlaut -140 KPX Y omacron -140 KPX Y oslash -140 KPX Y otilde -140 KPX Y period -140 KPX Y semicolon -60 KPX Y u -110 KPX Y uacute -110 KPX Y ucircumflex -110 KPX Y udieresis -110 KPX Y ugrave -110 KPX Y uhungarumlaut -110 KPX Y umacron -110 KPX Y uogonek -110 KPX Y uring -110 KPX Yacute A -110 KPX Yacute Aacute -110 KPX Yacute Abreve -110 KPX Yacute Acircumflex -110 KPX Yacute Adieresis -110 KPX Yacute Agrave -110 KPX Yacute Amacron -110 KPX Yacute Aogonek -110 KPX Yacute Aring -110 KPX Yacute Atilde -110 KPX Yacute O -85 KPX Yacute Oacute -85 KPX Yacute Ocircumflex -85 KPX Yacute Odieresis -85 KPX Yacute Ograve -85 KPX Yacute Ohungarumlaut -85 KPX Yacute Omacron -85 KPX Yacute Oslash -85 KPX Yacute Otilde -85 KPX Yacute a -140 KPX Yacute aacute -140 KPX Yacute abreve -70 KPX Yacute acircumflex -140 KPX Yacute adieresis -140 KPX Yacute agrave -140 KPX Yacute amacron -70 KPX Yacute aogonek -140 KPX Yacute aring -140 KPX Yacute atilde -70 KPX Yacute colon -60 KPX Yacute comma -140 KPX Yacute e -140 KPX Yacute eacute -140 KPX Yacute ecaron -140 KPX Yacute ecircumflex -140 KPX Yacute edieresis -140 KPX Yacute edotaccent -140 KPX Yacute egrave -140 KPX Yacute emacron -70 KPX Yacute eogonek -140 KPX Yacute hyphen -140 KPX Yacute i -20 KPX Yacute iacute -20 KPX Yacute iogonek -20 KPX Yacute o -140 KPX Yacute oacute -140 KPX Yacute ocircumflex -140 KPX Yacute odieresis -140 KPX Yacute ograve -140 KPX Yacute ohungarumlaut -140 KPX Yacute omacron -70 KPX Yacute oslash -140 KPX Yacute otilde -140 KPX Yacute period -140 KPX Yacute semicolon -60 KPX Yacute u -110 KPX Yacute uacute -110 KPX Yacute ucircumflex -110 KPX Yacute udieresis -110 KPX Yacute ugrave -110 KPX Yacute uhungarumlaut -110 KPX Yacute umacron -110 KPX Yacute uogonek -110 KPX Yacute uring -110 KPX Ydieresis A -110 KPX Ydieresis Aacute -110 KPX Ydieresis Abreve -110 KPX Ydieresis Acircumflex -110 KPX Ydieresis Adieresis -110 KPX Ydieresis Agrave -110 KPX Ydieresis Amacron -110 KPX Ydieresis Aogonek -110 KPX Ydieresis Aring -110 KPX Ydieresis Atilde -110 KPX Ydieresis O -85 KPX Ydieresis Oacute -85 KPX Ydieresis Ocircumflex -85 KPX Ydieresis Odieresis -85 KPX Ydieresis Ograve -85 KPX Ydieresis Ohungarumlaut -85 KPX Ydieresis Omacron -85 KPX Ydieresis Oslash -85 KPX Ydieresis Otilde -85 KPX Ydieresis a -140 KPX Ydieresis aacute -140 KPX Ydieresis abreve -70 KPX Ydieresis acircumflex -140 KPX Ydieresis adieresis -140 KPX Ydieresis agrave -140 KPX Ydieresis amacron -70 KPX Ydieresis aogonek -140 KPX Ydieresis aring -140 KPX Ydieresis atilde -70 KPX Ydieresis colon -60 KPX Ydieresis comma -140 KPX Ydieresis e -140 KPX Ydieresis eacute -140 KPX Ydieresis ecaron -140 KPX Ydieresis ecircumflex -140 KPX Ydieresis edieresis -140 KPX Ydieresis edotaccent -140 KPX Ydieresis egrave -140 KPX Ydieresis emacron -70 KPX Ydieresis eogonek -140 KPX Ydieresis hyphen -140 KPX Ydieresis i -20 KPX Ydieresis iacute -20 KPX Ydieresis iogonek -20 KPX Ydieresis o -140 KPX Ydieresis oacute -140 KPX Ydieresis ocircumflex -140 KPX Ydieresis odieresis -140 KPX Ydieresis ograve -140 KPX Ydieresis ohungarumlaut -140 KPX Ydieresis omacron -140 KPX Ydieresis oslash -140 KPX Ydieresis otilde -140 KPX Ydieresis period -140 KPX Ydieresis semicolon -60 KPX Ydieresis u -110 KPX Ydieresis uacute -110 KPX Ydieresis ucircumflex -110 KPX Ydieresis udieresis -110 KPX Ydieresis ugrave -110 KPX Ydieresis uhungarumlaut -110 KPX Ydieresis umacron -110 KPX Ydieresis uogonek -110 KPX Ydieresis uring -110 KPX a v -20 KPX a w -20 KPX a y -30 KPX a yacute -30 KPX a ydieresis -30 KPX aacute v -20 KPX aacute w -20 KPX aacute y -30 KPX aacute yacute -30 KPX aacute ydieresis -30 KPX abreve v -20 KPX abreve w -20 KPX abreve y -30 KPX abreve yacute -30 KPX abreve ydieresis -30 KPX acircumflex v -20 KPX acircumflex w -20 KPX acircumflex y -30 KPX acircumflex yacute -30 KPX acircumflex ydieresis -30 KPX adieresis v -20 KPX adieresis w -20 KPX adieresis y -30 KPX adieresis yacute -30 KPX adieresis ydieresis -30 KPX agrave v -20 KPX agrave w -20 KPX agrave y -30 KPX agrave yacute -30 KPX agrave ydieresis -30 KPX amacron v -20 KPX amacron w -20 KPX amacron y -30 KPX amacron yacute -30 KPX amacron ydieresis -30 KPX aogonek v -20 KPX aogonek w -20 KPX aogonek y -30 KPX aogonek yacute -30 KPX aogonek ydieresis -30 KPX aring v -20 KPX aring w -20 KPX aring y -30 KPX aring yacute -30 KPX aring ydieresis -30 KPX atilde v -20 KPX atilde w -20 KPX atilde y -30 KPX atilde yacute -30 KPX atilde ydieresis -30 KPX b b -10 KPX b comma -40 KPX b l -20 KPX b lacute -20 KPX b lcommaaccent -20 KPX b lslash -20 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -20 KPX b y -20 KPX b yacute -20 KPX b ydieresis -20 KPX c comma -15 KPX c k -20 KPX c kcommaaccent -20 KPX cacute comma -15 KPX cacute k -20 KPX cacute kcommaaccent -20 KPX ccaron comma -15 KPX ccaron k -20 KPX ccaron kcommaaccent -20 KPX ccedilla comma -15 KPX ccedilla k -20 KPX ccedilla kcommaaccent -20 KPX colon space -50 KPX comma quotedblright -100 KPX comma quoteright -100 KPX e comma -15 KPX e period -15 KPX e v -30 KPX e w -20 KPX e x -30 KPX e y -20 KPX e yacute -20 KPX e ydieresis -20 KPX eacute comma -15 KPX eacute period -15 KPX eacute v -30 KPX eacute w -20 KPX eacute x -30 KPX eacute y -20 KPX eacute yacute -20 KPX eacute ydieresis -20 KPX ecaron comma -15 KPX ecaron period -15 KPX ecaron v -30 KPX ecaron w -20 KPX ecaron x -30 KPX ecaron y -20 KPX ecaron yacute -20 KPX ecaron ydieresis -20 KPX ecircumflex comma -15 KPX ecircumflex period -15 KPX ecircumflex v -30 KPX ecircumflex w -20 KPX ecircumflex x -30 KPX ecircumflex y -20 KPX ecircumflex yacute -20 KPX ecircumflex ydieresis -20 KPX edieresis comma -15 KPX edieresis period -15 KPX edieresis v -30 KPX edieresis w -20 KPX edieresis x -30 KPX edieresis y -20 KPX edieresis yacute -20 KPX edieresis ydieresis -20 KPX edotaccent comma -15 KPX edotaccent period -15 KPX edotaccent v -30 KPX edotaccent w -20 KPX edotaccent x -30 KPX edotaccent y -20 KPX edotaccent yacute -20 KPX edotaccent ydieresis -20 KPX egrave comma -15 KPX egrave period -15 KPX egrave v -30 KPX egrave w -20 KPX egrave x -30 KPX egrave y -20 KPX egrave yacute -20 KPX egrave ydieresis -20 KPX emacron comma -15 KPX emacron period -15 KPX emacron v -30 KPX emacron w -20 KPX emacron x -30 KPX emacron y -20 KPX emacron yacute -20 KPX emacron ydieresis -20 KPX eogonek comma -15 KPX eogonek period -15 KPX eogonek v -30 KPX eogonek w -20 KPX eogonek x -30 KPX eogonek y -20 KPX eogonek yacute -20 KPX eogonek ydieresis -20 KPX f a -30 KPX f aacute -30 KPX f abreve -30 KPX f acircumflex -30 KPX f adieresis -30 KPX f agrave -30 KPX f amacron -30 KPX f aogonek -30 KPX f aring -30 KPX f atilde -30 KPX f comma -30 KPX f dotlessi -28 KPX f e -30 KPX f eacute -30 KPX f ecaron -30 KPX f ecircumflex -30 KPX f edieresis -30 KPX f edotaccent -30 KPX f egrave -30 KPX f emacron -30 KPX f eogonek -30 KPX f o -30 KPX f oacute -30 KPX f ocircumflex -30 KPX f odieresis -30 KPX f ograve -30 KPX f ohungarumlaut -30 KPX f omacron -30 KPX f oslash -30 KPX f otilde -30 KPX f period -30 KPX f quotedblright 60 KPX f quoteright 50 KPX g r -10 KPX g racute -10 KPX g rcaron -10 KPX g rcommaaccent -10 KPX gbreve r -10 KPX gbreve racute -10 KPX gbreve rcaron -10 KPX gbreve rcommaaccent -10 KPX gcommaaccent r -10 KPX gcommaaccent racute -10 KPX gcommaaccent rcaron -10 KPX gcommaaccent rcommaaccent -10 KPX h y -30 KPX h yacute -30 KPX h ydieresis -30 KPX k e -20 KPX k eacute -20 KPX k ecaron -20 KPX k ecircumflex -20 KPX k edieresis -20 KPX k edotaccent -20 KPX k egrave -20 KPX k emacron -20 KPX k eogonek -20 KPX k o -20 KPX k oacute -20 KPX k ocircumflex -20 KPX k odieresis -20 KPX k ograve -20 KPX k ohungarumlaut -20 KPX k omacron -20 KPX k oslash -20 KPX k otilde -20 KPX kcommaaccent e -20 KPX kcommaaccent eacute -20 KPX kcommaaccent ecaron -20 KPX kcommaaccent ecircumflex -20 KPX kcommaaccent edieresis -20 KPX kcommaaccent edotaccent -20 KPX kcommaaccent egrave -20 KPX kcommaaccent emacron -20 KPX kcommaaccent eogonek -20 KPX kcommaaccent o -20 KPX kcommaaccent oacute -20 KPX kcommaaccent ocircumflex -20 KPX kcommaaccent odieresis -20 KPX kcommaaccent ograve -20 KPX kcommaaccent ohungarumlaut -20 KPX kcommaaccent omacron -20 KPX kcommaaccent oslash -20 KPX kcommaaccent otilde -20 KPX m u -10 KPX m uacute -10 KPX m ucircumflex -10 KPX m udieresis -10 KPX m ugrave -10 KPX m uhungarumlaut -10 KPX m umacron -10 KPX m uogonek -10 KPX m uring -10 KPX m y -15 KPX m yacute -15 KPX m ydieresis -15 KPX n u -10 KPX n uacute -10 KPX n ucircumflex -10 KPX n udieresis -10 KPX n ugrave -10 KPX n uhungarumlaut -10 KPX n umacron -10 KPX n uogonek -10 KPX n uring -10 KPX n v -20 KPX n y -15 KPX n yacute -15 KPX n ydieresis -15 KPX nacute u -10 KPX nacute uacute -10 KPX nacute ucircumflex -10 KPX nacute udieresis -10 KPX nacute ugrave -10 KPX nacute uhungarumlaut -10 KPX nacute umacron -10 KPX nacute uogonek -10 KPX nacute uring -10 KPX nacute v -20 KPX nacute y -15 KPX nacute yacute -15 KPX nacute ydieresis -15 KPX ncaron u -10 KPX ncaron uacute -10 KPX ncaron ucircumflex -10 KPX ncaron udieresis -10 KPX ncaron ugrave -10 KPX ncaron uhungarumlaut -10 KPX ncaron umacron -10 KPX ncaron uogonek -10 KPX ncaron uring -10 KPX ncaron v -20 KPX ncaron y -15 KPX ncaron yacute -15 KPX ncaron ydieresis -15 KPX ncommaaccent u -10 KPX ncommaaccent uacute -10 KPX ncommaaccent ucircumflex -10 KPX ncommaaccent udieresis -10 KPX ncommaaccent ugrave -10 KPX ncommaaccent uhungarumlaut -10 KPX ncommaaccent umacron -10 KPX ncommaaccent uogonek -10 KPX ncommaaccent uring -10 KPX ncommaaccent v -20 KPX ncommaaccent y -15 KPX ncommaaccent yacute -15 KPX ncommaaccent ydieresis -15 KPX ntilde u -10 KPX ntilde uacute -10 KPX ntilde ucircumflex -10 KPX ntilde udieresis -10 KPX ntilde ugrave -10 KPX ntilde uhungarumlaut -10 KPX ntilde umacron -10 KPX ntilde uogonek -10 KPX ntilde uring -10 KPX ntilde v -20 KPX ntilde y -15 KPX ntilde yacute -15 KPX ntilde ydieresis -15 KPX o comma -40 KPX o period -40 KPX o v -15 KPX o w -15 KPX o x -30 KPX o y -30 KPX o yacute -30 KPX o ydieresis -30 KPX oacute comma -40 KPX oacute period -40 KPX oacute v -15 KPX oacute w -15 KPX oacute x -30 KPX oacute y -30 KPX oacute yacute -30 KPX oacute ydieresis -30 KPX ocircumflex comma -40 KPX ocircumflex period -40 KPX ocircumflex v -15 KPX ocircumflex w -15 KPX ocircumflex x -30 KPX ocircumflex y -30 KPX ocircumflex yacute -30 KPX ocircumflex ydieresis -30 KPX odieresis comma -40 KPX odieresis period -40 KPX odieresis v -15 KPX odieresis w -15 KPX odieresis x -30 KPX odieresis y -30 KPX odieresis yacute -30 KPX odieresis ydieresis -30 KPX ograve comma -40 KPX ograve period -40 KPX ograve v -15 KPX ograve w -15 KPX ograve x -30 KPX ograve y -30 KPX ograve yacute -30 KPX ograve ydieresis -30 KPX ohungarumlaut comma -40 KPX ohungarumlaut period -40 KPX ohungarumlaut v -15 KPX ohungarumlaut w -15 KPX ohungarumlaut x -30 KPX ohungarumlaut y -30 KPX ohungarumlaut yacute -30 KPX ohungarumlaut ydieresis -30 KPX omacron comma -40 KPX omacron period -40 KPX omacron v -15 KPX omacron w -15 KPX omacron x -30 KPX omacron y -30 KPX omacron yacute -30 KPX omacron ydieresis -30 KPX oslash a -55 KPX oslash aacute -55 KPX oslash abreve -55 KPX oslash acircumflex -55 KPX oslash adieresis -55 KPX oslash agrave -55 KPX oslash amacron -55 KPX oslash aogonek -55 KPX oslash aring -55 KPX oslash atilde -55 KPX oslash b -55 KPX oslash c -55 KPX oslash cacute -55 KPX oslash ccaron -55 KPX oslash ccedilla -55 KPX oslash comma -95 KPX oslash d -55 KPX oslash dcroat -55 KPX oslash e -55 KPX oslash eacute -55 KPX oslash ecaron -55 KPX oslash ecircumflex -55 KPX oslash edieresis -55 KPX oslash edotaccent -55 KPX oslash egrave -55 KPX oslash emacron -55 KPX oslash eogonek -55 KPX oslash f -55 KPX oslash g -55 KPX oslash gbreve -55 KPX oslash gcommaaccent -55 KPX oslash h -55 KPX oslash i -55 KPX oslash iacute -55 KPX oslash icircumflex -55 KPX oslash idieresis -55 KPX oslash igrave -55 KPX oslash imacron -55 KPX oslash iogonek -55 KPX oslash j -55 KPX oslash k -55 KPX oslash kcommaaccent -55 KPX oslash l -55 KPX oslash lacute -55 KPX oslash lcommaaccent -55 KPX oslash lslash -55 KPX oslash m -55 KPX oslash n -55 KPX oslash nacute -55 KPX oslash ncaron -55 KPX oslash ncommaaccent -55 KPX oslash ntilde -55 KPX oslash o -55 KPX oslash oacute -55 KPX oslash ocircumflex -55 KPX oslash odieresis -55 KPX oslash ograve -55 KPX oslash ohungarumlaut -55 KPX oslash omacron -55 KPX oslash oslash -55 KPX oslash otilde -55 KPX oslash p -55 KPX oslash period -95 KPX oslash q -55 KPX oslash r -55 KPX oslash racute -55 KPX oslash rcaron -55 KPX oslash rcommaaccent -55 KPX oslash s -55 KPX oslash sacute -55 KPX oslash scaron -55 KPX oslash scedilla -55 KPX oslash scommaaccent -55 KPX oslash t -55 KPX oslash tcommaaccent -55 KPX oslash u -55 KPX oslash uacute -55 KPX oslash ucircumflex -55 KPX oslash udieresis -55 KPX oslash ugrave -55 KPX oslash uhungarumlaut -55 KPX oslash umacron -55 KPX oslash uogonek -55 KPX oslash uring -55 KPX oslash v -70 KPX oslash w -70 KPX oslash x -85 KPX oslash y -70 KPX oslash yacute -70 KPX oslash ydieresis -70 KPX oslash z -55 KPX oslash zacute -55 KPX oslash zcaron -55 KPX oslash zdotaccent -55 KPX otilde comma -40 KPX otilde period -40 KPX otilde v -15 KPX otilde w -15 KPX otilde x -30 KPX otilde y -30 KPX otilde yacute -30 KPX otilde ydieresis -30 KPX p comma -35 KPX p period -35 KPX p y -30 KPX p yacute -30 KPX p ydieresis -30 KPX period quotedblright -100 KPX period quoteright -100 KPX period space -60 KPX quotedblright space -40 KPX quoteleft quoteleft -57 KPX quoteright d -50 KPX quoteright dcroat -50 KPX quoteright quoteright -57 KPX quoteright r -50 KPX quoteright racute -50 KPX quoteright rcaron -50 KPX quoteright rcommaaccent -50 KPX quoteright s -50 KPX quoteright sacute -50 KPX quoteright scaron -50 KPX quoteright scedilla -50 KPX quoteright scommaaccent -50 KPX quoteright space -70 KPX r a -10 KPX r aacute -10 KPX r abreve -10 KPX r acircumflex -10 KPX r adieresis -10 KPX r agrave -10 KPX r amacron -10 KPX r aogonek -10 KPX r aring -10 KPX r atilde -10 KPX r colon 30 KPX r comma -50 KPX r i 15 KPX r iacute 15 KPX r icircumflex 15 KPX r idieresis 15 KPX r igrave 15 KPX r imacron 15 KPX r iogonek 15 KPX r k 15 KPX r kcommaaccent 15 KPX r l 15 KPX r lacute 15 KPX r lcommaaccent 15 KPX r lslash 15 KPX r m 25 KPX r n 25 KPX r nacute 25 KPX r ncaron 25 KPX r ncommaaccent 25 KPX r ntilde 25 KPX r p 30 KPX r period -50 KPX r semicolon 30 KPX r t 40 KPX r tcommaaccent 40 KPX r u 15 KPX r uacute 15 KPX r ucircumflex 15 KPX r udieresis 15 KPX r ugrave 15 KPX r uhungarumlaut 15 KPX r umacron 15 KPX r uogonek 15 KPX r uring 15 KPX r v 30 KPX r y 30 KPX r yacute 30 KPX r ydieresis 30 KPX racute a -10 KPX racute aacute -10 KPX racute abreve -10 KPX racute acircumflex -10 KPX racute adieresis -10 KPX racute agrave -10 KPX racute amacron -10 KPX racute aogonek -10 KPX racute aring -10 KPX racute atilde -10 KPX racute colon 30 KPX racute comma -50 KPX racute i 15 KPX racute iacute 15 KPX racute icircumflex 15 KPX racute idieresis 15 KPX racute igrave 15 KPX racute imacron 15 KPX racute iogonek 15 KPX racute k 15 KPX racute kcommaaccent 15 KPX racute l 15 KPX racute lacute 15 KPX racute lcommaaccent 15 KPX racute lslash 15 KPX racute m 25 KPX racute n 25 KPX racute nacute 25 KPX racute ncaron 25 KPX racute ncommaaccent 25 KPX racute ntilde 25 KPX racute p 30 KPX racute period -50 KPX racute semicolon 30 KPX racute t 40 KPX racute tcommaaccent 40 KPX racute u 15 KPX racute uacute 15 KPX racute ucircumflex 15 KPX racute udieresis 15 KPX racute ugrave 15 KPX racute uhungarumlaut 15 KPX racute umacron 15 KPX racute uogonek 15 KPX racute uring 15 KPX racute v 30 KPX racute y 30 KPX racute yacute 30 KPX racute ydieresis 30 KPX rcaron a -10 KPX rcaron aacute -10 KPX rcaron abreve -10 KPX rcaron acircumflex -10 KPX rcaron adieresis -10 KPX rcaron agrave -10 KPX rcaron amacron -10 KPX rcaron aogonek -10 KPX rcaron aring -10 KPX rcaron atilde -10 KPX rcaron colon 30 KPX rcaron comma -50 KPX rcaron i 15 KPX rcaron iacute 15 KPX rcaron icircumflex 15 KPX rcaron idieresis 15 KPX rcaron igrave 15 KPX rcaron imacron 15 KPX rcaron iogonek 15 KPX rcaron k 15 KPX rcaron kcommaaccent 15 KPX rcaron l 15 KPX rcaron lacute 15 KPX rcaron lcommaaccent 15 KPX rcaron lslash 15 KPX rcaron m 25 KPX rcaron n 25 KPX rcaron nacute 25 KPX rcaron ncaron 25 KPX rcaron ncommaaccent 25 KPX rcaron ntilde 25 KPX rcaron p 30 KPX rcaron period -50 KPX rcaron semicolon 30 KPX rcaron t 40 KPX rcaron tcommaaccent 40 KPX rcaron u 15 KPX rcaron uacute 15 KPX rcaron ucircumflex 15 KPX rcaron udieresis 15 KPX rcaron ugrave 15 KPX rcaron uhungarumlaut 15 KPX rcaron umacron 15 KPX rcaron uogonek 15 KPX rcaron uring 15 KPX rcaron v 30 KPX rcaron y 30 KPX rcaron yacute 30 KPX rcaron ydieresis 30 KPX rcommaaccent a -10 KPX rcommaaccent aacute -10 KPX rcommaaccent abreve -10 KPX rcommaaccent acircumflex -10 KPX rcommaaccent adieresis -10 KPX rcommaaccent agrave -10 KPX rcommaaccent amacron -10 KPX rcommaaccent aogonek -10 KPX rcommaaccent aring -10 KPX rcommaaccent atilde -10 KPX rcommaaccent colon 30 KPX rcommaaccent comma -50 KPX rcommaaccent i 15 KPX rcommaaccent iacute 15 KPX rcommaaccent icircumflex 15 KPX rcommaaccent idieresis 15 KPX rcommaaccent igrave 15 KPX rcommaaccent imacron 15 KPX rcommaaccent iogonek 15 KPX rcommaaccent k 15 KPX rcommaaccent kcommaaccent 15 KPX rcommaaccent l 15 KPX rcommaaccent lacute 15 KPX rcommaaccent lcommaaccent 15 KPX rcommaaccent lslash 15 KPX rcommaaccent m 25 KPX rcommaaccent n 25 KPX rcommaaccent nacute 25 KPX rcommaaccent ncaron 25 KPX rcommaaccent ncommaaccent 25 KPX rcommaaccent ntilde 25 KPX rcommaaccent p 30 KPX rcommaaccent period -50 KPX rcommaaccent semicolon 30 KPX rcommaaccent t 40 KPX rcommaaccent tcommaaccent 40 KPX rcommaaccent u 15 KPX rcommaaccent uacute 15 KPX rcommaaccent ucircumflex 15 KPX rcommaaccent udieresis 15 KPX rcommaaccent ugrave 15 KPX rcommaaccent uhungarumlaut 15 KPX rcommaaccent umacron 15 KPX rcommaaccent uogonek 15 KPX rcommaaccent uring 15 KPX rcommaaccent v 30 KPX rcommaaccent y 30 KPX rcommaaccent yacute 30 KPX rcommaaccent ydieresis 30 KPX s comma -15 KPX s period -15 KPX s w -30 KPX sacute comma -15 KPX sacute period -15 KPX sacute w -30 KPX scaron comma -15 KPX scaron period -15 KPX scaron w -30 KPX scedilla comma -15 KPX scedilla period -15 KPX scedilla w -30 KPX scommaaccent comma -15 KPX scommaaccent period -15 KPX scommaaccent w -30 KPX semicolon space -50 KPX space T -50 KPX space Tcaron -50 KPX space Tcommaaccent -50 KPX space V -50 KPX space W -40 KPX space Y -90 KPX space Yacute -90 KPX space Ydieresis -90 KPX space quotedblleft -30 KPX space quoteleft -60 KPX v a -25 KPX v aacute -25 KPX v abreve -25 KPX v acircumflex -25 KPX v adieresis -25 KPX v agrave -25 KPX v amacron -25 KPX v aogonek -25 KPX v aring -25 KPX v atilde -25 KPX v comma -80 KPX v e -25 KPX v eacute -25 KPX v ecaron -25 KPX v ecircumflex -25 KPX v edieresis -25 KPX v edotaccent -25 KPX v egrave -25 KPX v emacron -25 KPX v eogonek -25 KPX v o -25 KPX v oacute -25 KPX v ocircumflex -25 KPX v odieresis -25 KPX v ograve -25 KPX v ohungarumlaut -25 KPX v omacron -25 KPX v oslash -25 KPX v otilde -25 KPX v period -80 KPX w a -15 KPX w aacute -15 KPX w abreve -15 KPX w acircumflex -15 KPX w adieresis -15 KPX w agrave -15 KPX w amacron -15 KPX w aogonek -15 KPX w aring -15 KPX w atilde -15 KPX w comma -60 KPX w e -10 KPX w eacute -10 KPX w ecaron -10 KPX w ecircumflex -10 KPX w edieresis -10 KPX w edotaccent -10 KPX w egrave -10 KPX w emacron -10 KPX w eogonek -10 KPX w o -10 KPX w oacute -10 KPX w ocircumflex -10 KPX w odieresis -10 KPX w ograve -10 KPX w ohungarumlaut -10 KPX w omacron -10 KPX w oslash -10 KPX w otilde -10 KPX w period -60 KPX x e -30 KPX x eacute -30 KPX x ecaron -30 KPX x ecircumflex -30 KPX x edieresis -30 KPX x edotaccent -30 KPX x egrave -30 KPX x emacron -30 KPX x eogonek -30 KPX y a -20 KPX y aacute -20 KPX y abreve -20 KPX y acircumflex -20 KPX y adieresis -20 KPX y agrave -20 KPX y amacron -20 KPX y aogonek -20 KPX y aring -20 KPX y atilde -20 KPX y comma -100 KPX y e -20 KPX y eacute -20 KPX y ecaron -20 KPX y ecircumflex -20 KPX y edieresis -20 KPX y edotaccent -20 KPX y egrave -20 KPX y emacron -20 KPX y eogonek -20 KPX y o -20 KPX y oacute -20 KPX y ocircumflex -20 KPX y odieresis -20 KPX y ograve -20 KPX y ohungarumlaut -20 KPX y omacron -20 KPX y oslash -20 KPX y otilde -20 KPX y period -100 KPX yacute a -20 KPX yacute aacute -20 KPX yacute abreve -20 KPX yacute acircumflex -20 KPX yacute adieresis -20 KPX yacute agrave -20 KPX yacute amacron -20 KPX yacute aogonek -20 KPX yacute aring -20 KPX yacute atilde -20 KPX yacute comma -100 KPX yacute e -20 KPX yacute eacute -20 KPX yacute ecaron -20 KPX yacute ecircumflex -20 KPX yacute edieresis -20 KPX yacute edotaccent -20 KPX yacute egrave -20 KPX yacute emacron -20 KPX yacute eogonek -20 KPX yacute o -20 KPX yacute oacute -20 KPX yacute ocircumflex -20 KPX yacute odieresis -20 KPX yacute ograve -20 KPX yacute ohungarumlaut -20 KPX yacute omacron -20 KPX yacute oslash -20 KPX yacute otilde -20 KPX yacute period -100 KPX ydieresis a -20 KPX ydieresis aacute -20 KPX ydieresis abreve -20 KPX ydieresis acircumflex -20 KPX ydieresis adieresis -20 KPX ydieresis agrave -20 KPX ydieresis amacron -20 KPX ydieresis aogonek -20 KPX ydieresis aring -20 KPX ydieresis atilde -20 KPX ydieresis comma -100 KPX ydieresis e -20 KPX ydieresis eacute -20 KPX ydieresis ecaron -20 KPX ydieresis ecircumflex -20 KPX ydieresis edieresis -20 KPX ydieresis edotaccent -20 KPX ydieresis egrave -20 KPX ydieresis emacron -20 KPX ydieresis eogonek -20 KPX ydieresis o -20 KPX ydieresis oacute -20 KPX ydieresis ocircumflex -20 KPX ydieresis odieresis -20 KPX ydieresis ograve -20 KPX ydieresis ohungarumlaut -20 KPX ydieresis omacron -20 KPX ydieresis oslash -20 KPX ydieresis otilde -20 KPX ydieresis period -100 KPX z e -15 KPX z eacute -15 KPX z ecaron -15 KPX z ecircumflex -15 KPX z edieresis -15 KPX z edotaccent -15 KPX z egrave -15 KPX z emacron -15 KPX z eogonek -15 KPX z o -15 KPX z oacute -15 KPX z ocircumflex -15 KPX z odieresis -15 KPX z ograve -15 KPX z ohungarumlaut -15 KPX z omacron -15 KPX z oslash -15 KPX z otilde -15 KPX zacute e -15 KPX zacute eacute -15 KPX zacute ecaron -15 KPX zacute ecircumflex -15 KPX zacute edieresis -15 KPX zacute edotaccent -15 KPX zacute egrave -15 KPX zacute emacron -15 KPX zacute eogonek -15 KPX zacute o -15 KPX zacute oacute -15 KPX zacute ocircumflex -15 KPX zacute odieresis -15 KPX zacute ograve -15 KPX zacute ohungarumlaut -15 KPX zacute omacron -15 KPX zacute oslash -15 KPX zacute otilde -15 KPX zcaron e -15 KPX zcaron eacute -15 KPX zcaron ecaron -15 KPX zcaron ecircumflex -15 KPX zcaron edieresis -15 KPX zcaron edotaccent -15 KPX zcaron egrave -15 KPX zcaron emacron -15 KPX zcaron eogonek -15 KPX zcaron o -15 KPX zcaron oacute -15 KPX zcaron ocircumflex -15 KPX zcaron odieresis -15 KPX zcaron ograve -15 KPX zcaron ohungarumlaut -15 KPX zcaron omacron -15 KPX zcaron oslash -15 KPX zcaron otilde -15 KPX zdotaccent e -15 KPX zdotaccent eacute -15 KPX zdotaccent ecaron -15 KPX zdotaccent ecircumflex -15 KPX zdotaccent edieresis -15 KPX zdotaccent edotaccent -15 KPX zdotaccent egrave -15 KPX zdotaccent emacron -15 KPX zdotaccent eogonek -15 KPX zdotaccent o -15 KPX zdotaccent oacute -15 KPX zdotaccent ocircumflex -15 KPX zdotaccent odieresis -15 KPX zdotaccent ograve -15 KPX zdotaccent ohungarumlaut -15 KPX zdotaccent omacron -15 KPX zdotaccent oslash -15 KPX zdotaccent otilde -15 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Helvetica.afm0000644000076500000240000022703712037547555017446 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:38:23 1997 Comment UniqueID 43054 Comment VMusage 37069 48094 FontName Helvetica FullName Helvetica FamilyName Helvetica Weight Medium ItalicAngle 0 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -166 -225 1000 931 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 718 XHeight 523 Ascender 718 Descender -207 StdHW 76 StdVW 88 StartCharMetrics 315 C 32 ; WX 278 ; N space ; B 0 0 0 0 ; C 33 ; WX 278 ; N exclam ; B 90 0 187 718 ; C 34 ; WX 355 ; N quotedbl ; B 70 463 285 718 ; C 35 ; WX 556 ; N numbersign ; B 28 0 529 688 ; C 36 ; WX 556 ; N dollar ; B 32 -115 520 775 ; C 37 ; WX 889 ; N percent ; B 39 -19 850 703 ; C 38 ; WX 667 ; N ampersand ; B 44 -15 645 718 ; C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ; C 40 ; WX 333 ; N parenleft ; B 68 -207 299 733 ; C 41 ; WX 333 ; N parenright ; B 34 -207 265 733 ; C 42 ; WX 389 ; N asterisk ; B 39 431 349 718 ; C 43 ; WX 584 ; N plus ; B 39 0 545 505 ; C 44 ; WX 278 ; N comma ; B 87 -147 191 106 ; C 45 ; WX 333 ; N hyphen ; B 44 232 289 322 ; C 46 ; WX 278 ; N period ; B 87 0 191 106 ; C 47 ; WX 278 ; N slash ; B -17 -19 295 737 ; C 48 ; WX 556 ; N zero ; B 37 -19 519 703 ; C 49 ; WX 556 ; N one ; B 101 0 359 703 ; C 50 ; WX 556 ; N two ; B 26 0 507 703 ; C 51 ; WX 556 ; N three ; B 34 -19 522 703 ; C 52 ; WX 556 ; N four ; B 25 0 523 703 ; C 53 ; WX 556 ; N five ; B 32 -19 514 688 ; C 54 ; WX 556 ; N six ; B 38 -19 518 703 ; C 55 ; WX 556 ; N seven ; B 37 0 523 688 ; C 56 ; WX 556 ; N eight ; B 38 -19 517 703 ; C 57 ; WX 556 ; N nine ; B 42 -19 514 703 ; C 58 ; WX 278 ; N colon ; B 87 0 191 516 ; C 59 ; WX 278 ; N semicolon ; B 87 -147 191 516 ; C 60 ; WX 584 ; N less ; B 48 11 536 495 ; C 61 ; WX 584 ; N equal ; B 39 115 545 390 ; C 62 ; WX 584 ; N greater ; B 48 11 536 495 ; C 63 ; WX 556 ; N question ; B 56 0 492 727 ; C 64 ; WX 1015 ; N at ; B 147 -19 868 737 ; C 65 ; WX 667 ; N A ; B 14 0 654 718 ; C 66 ; WX 667 ; N B ; B 74 0 627 718 ; C 67 ; WX 722 ; N C ; B 44 -19 681 737 ; C 68 ; WX 722 ; N D ; B 81 0 674 718 ; C 69 ; WX 667 ; N E ; B 86 0 616 718 ; C 70 ; WX 611 ; N F ; B 86 0 583 718 ; C 71 ; WX 778 ; N G ; B 48 -19 704 737 ; C 72 ; WX 722 ; N H ; B 77 0 646 718 ; C 73 ; WX 278 ; N I ; B 91 0 188 718 ; C 74 ; WX 500 ; N J ; B 17 -19 428 718 ; C 75 ; WX 667 ; N K ; B 76 0 663 718 ; C 76 ; WX 556 ; N L ; B 76 0 537 718 ; C 77 ; WX 833 ; N M ; B 73 0 761 718 ; C 78 ; WX 722 ; N N ; B 76 0 646 718 ; C 79 ; WX 778 ; N O ; B 39 -19 739 737 ; C 80 ; WX 667 ; N P ; B 86 0 622 718 ; C 81 ; WX 778 ; N Q ; B 39 -56 739 737 ; C 82 ; WX 722 ; N R ; B 88 0 684 718 ; C 83 ; WX 667 ; N S ; B 49 -19 620 737 ; C 84 ; WX 611 ; N T ; B 14 0 597 718 ; C 85 ; WX 722 ; N U ; B 79 -19 644 718 ; C 86 ; WX 667 ; N V ; B 20 0 647 718 ; C 87 ; WX 944 ; N W ; B 16 0 928 718 ; C 88 ; WX 667 ; N X ; B 19 0 648 718 ; C 89 ; WX 667 ; N Y ; B 14 0 653 718 ; C 90 ; WX 611 ; N Z ; B 23 0 588 718 ; C 91 ; WX 278 ; N bracketleft ; B 63 -196 250 722 ; C 92 ; WX 278 ; N backslash ; B -17 -19 295 737 ; C 93 ; WX 278 ; N bracketright ; B 28 -196 215 722 ; C 94 ; WX 469 ; N asciicircum ; B -14 264 483 688 ; C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ; C 96 ; WX 222 ; N quoteleft ; B 65 470 169 725 ; C 97 ; WX 556 ; N a ; B 36 -15 530 538 ; C 98 ; WX 556 ; N b ; B 58 -15 517 718 ; C 99 ; WX 500 ; N c ; B 30 -15 477 538 ; C 100 ; WX 556 ; N d ; B 35 -15 499 718 ; C 101 ; WX 556 ; N e ; B 40 -15 516 538 ; C 102 ; WX 278 ; N f ; B 14 0 262 728 ; L i fi ; L l fl ; C 103 ; WX 556 ; N g ; B 40 -220 499 538 ; C 104 ; WX 556 ; N h ; B 65 0 491 718 ; C 105 ; WX 222 ; N i ; B 67 0 155 718 ; C 106 ; WX 222 ; N j ; B -16 -210 155 718 ; C 107 ; WX 500 ; N k ; B 67 0 501 718 ; C 108 ; WX 222 ; N l ; B 67 0 155 718 ; C 109 ; WX 833 ; N m ; B 65 0 769 538 ; C 110 ; WX 556 ; N n ; B 65 0 491 538 ; C 111 ; WX 556 ; N o ; B 35 -14 521 538 ; C 112 ; WX 556 ; N p ; B 58 -207 517 538 ; C 113 ; WX 556 ; N q ; B 35 -207 494 538 ; C 114 ; WX 333 ; N r ; B 77 0 332 538 ; C 115 ; WX 500 ; N s ; B 32 -15 464 538 ; C 116 ; WX 278 ; N t ; B 14 -7 257 669 ; C 117 ; WX 556 ; N u ; B 68 -15 489 523 ; C 118 ; WX 500 ; N v ; B 8 0 492 523 ; C 119 ; WX 722 ; N w ; B 14 0 709 523 ; C 120 ; WX 500 ; N x ; B 11 0 490 523 ; C 121 ; WX 500 ; N y ; B 11 -214 489 523 ; C 122 ; WX 500 ; N z ; B 31 0 469 523 ; C 123 ; WX 334 ; N braceleft ; B 42 -196 292 722 ; C 124 ; WX 260 ; N bar ; B 94 -225 167 775 ; C 125 ; WX 334 ; N braceright ; B 42 -196 292 722 ; C 126 ; WX 584 ; N asciitilde ; B 61 180 523 326 ; C 161 ; WX 333 ; N exclamdown ; B 118 -195 215 523 ; C 162 ; WX 556 ; N cent ; B 51 -115 513 623 ; C 163 ; WX 556 ; N sterling ; B 33 -16 539 718 ; C 164 ; WX 167 ; N fraction ; B -166 -19 333 703 ; C 165 ; WX 556 ; N yen ; B 3 0 553 688 ; C 166 ; WX 556 ; N florin ; B -11 -207 501 737 ; C 167 ; WX 556 ; N section ; B 43 -191 512 737 ; C 168 ; WX 556 ; N currency ; B 28 99 528 603 ; C 169 ; WX 191 ; N quotesingle ; B 59 463 132 718 ; C 170 ; WX 333 ; N quotedblleft ; B 38 470 307 725 ; C 171 ; WX 556 ; N guillemotleft ; B 97 108 459 446 ; C 172 ; WX 333 ; N guilsinglleft ; B 88 108 245 446 ; C 173 ; WX 333 ; N guilsinglright ; B 88 108 245 446 ; C 174 ; WX 500 ; N fi ; B 14 0 434 728 ; C 175 ; WX 500 ; N fl ; B 14 0 432 728 ; C 177 ; WX 556 ; N endash ; B 0 240 556 313 ; C 178 ; WX 556 ; N dagger ; B 43 -159 514 718 ; C 179 ; WX 556 ; N daggerdbl ; B 43 -159 514 718 ; C 180 ; WX 278 ; N periodcentered ; B 77 190 202 315 ; C 182 ; WX 537 ; N paragraph ; B 18 -173 497 718 ; C 183 ; WX 350 ; N bullet ; B 18 202 333 517 ; C 184 ; WX 222 ; N quotesinglbase ; B 53 -149 157 106 ; C 185 ; WX 333 ; N quotedblbase ; B 26 -149 295 106 ; C 186 ; WX 333 ; N quotedblright ; B 26 463 295 718 ; C 187 ; WX 556 ; N guillemotright ; B 97 108 459 446 ; C 188 ; WX 1000 ; N ellipsis ; B 115 0 885 106 ; C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 703 ; C 191 ; WX 611 ; N questiondown ; B 91 -201 527 525 ; C 193 ; WX 333 ; N grave ; B 14 593 211 734 ; C 194 ; WX 333 ; N acute ; B 122 593 319 734 ; C 195 ; WX 333 ; N circumflex ; B 21 593 312 734 ; C 196 ; WX 333 ; N tilde ; B -4 606 337 722 ; C 197 ; WX 333 ; N macron ; B 10 627 323 684 ; C 198 ; WX 333 ; N breve ; B 13 595 321 731 ; C 199 ; WX 333 ; N dotaccent ; B 121 604 212 706 ; C 200 ; WX 333 ; N dieresis ; B 40 604 293 706 ; C 202 ; WX 333 ; N ring ; B 75 572 259 756 ; C 203 ; WX 333 ; N cedilla ; B 45 -225 259 0 ; C 205 ; WX 333 ; N hungarumlaut ; B 31 593 409 734 ; C 206 ; WX 333 ; N ogonek ; B 73 -225 287 0 ; C 207 ; WX 333 ; N caron ; B 21 593 312 734 ; C 208 ; WX 1000 ; N emdash ; B 0 240 1000 313 ; C 225 ; WX 1000 ; N AE ; B 8 0 951 718 ; C 227 ; WX 370 ; N ordfeminine ; B 24 405 346 737 ; C 232 ; WX 556 ; N Lslash ; B -20 0 537 718 ; C 233 ; WX 778 ; N Oslash ; B 39 -19 740 737 ; C 234 ; WX 1000 ; N OE ; B 36 -19 965 737 ; C 235 ; WX 365 ; N ordmasculine ; B 25 405 341 737 ; C 241 ; WX 889 ; N ae ; B 36 -15 847 538 ; C 245 ; WX 278 ; N dotlessi ; B 95 0 183 523 ; C 248 ; WX 222 ; N lslash ; B -20 0 242 718 ; C 249 ; WX 611 ; N oslash ; B 28 -22 537 545 ; C 250 ; WX 944 ; N oe ; B 35 -15 902 538 ; C 251 ; WX 611 ; N germandbls ; B 67 -15 571 728 ; C -1 ; WX 278 ; N Idieresis ; B 13 0 266 901 ; C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ; C -1 ; WX 556 ; N abreve ; B 36 -15 530 731 ; C -1 ; WX 556 ; N uhungarumlaut ; B 68 -15 521 734 ; C -1 ; WX 556 ; N ecaron ; B 40 -15 516 734 ; C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ; C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ; C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ; C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ; C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ; C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ; C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ; C -1 ; WX 500 ; N scommaaccent ; B 32 -225 464 538 ; C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ; C -1 ; WX 722 ; N Uring ; B 79 -19 644 931 ; C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ; C -1 ; WX 556 ; N aogonek ; B 36 -220 547 538 ; C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ; C -1 ; WX 556 ; N uogonek ; B 68 -225 519 523 ; C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ; C -1 ; WX 722 ; N Dcroat ; B 0 0 674 718 ; C -1 ; WX 250 ; N commaaccent ; B 87 -225 181 -40 ; C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ; C -1 ; WX 667 ; N Emacron ; B 86 0 616 879 ; C -1 ; WX 500 ; N ccaron ; B 30 -15 477 734 ; C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ; C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 646 718 ; C -1 ; WX 222 ; N lacute ; B 67 0 264 929 ; C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ; C -1 ; WX 611 ; N Tcommaaccent ; B 14 -225 597 718 ; C -1 ; WX 722 ; N Cacute ; B 44 -19 681 929 ; C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ; C -1 ; WX 667 ; N Edotaccent ; B 86 0 616 901 ; C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ; C -1 ; WX 500 ; N scedilla ; B 32 -225 464 538 ; C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ; C -1 ; WX 471 ; N lozenge ; B 10 0 462 728 ; C -1 ; WX 722 ; N Rcaron ; B 88 0 684 929 ; C -1 ; WX 778 ; N Gcommaaccent ; B 48 -225 704 737 ; C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ; C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ; C -1 ; WX 667 ; N Amacron ; B 14 0 654 879 ; C -1 ; WX 333 ; N rcaron ; B 61 0 352 734 ; C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ; C -1 ; WX 611 ; N Zdotaccent ; B 23 0 588 901 ; C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ; C -1 ; WX 778 ; N Omacron ; B 39 -19 739 879 ; C -1 ; WX 722 ; N Racute ; B 88 0 684 929 ; C -1 ; WX 667 ; N Sacute ; B 49 -19 620 929 ; C -1 ; WX 643 ; N dcaron ; B 35 -15 655 718 ; C -1 ; WX 722 ; N Umacron ; B 79 -19 644 879 ; C -1 ; WX 556 ; N uring ; B 68 -15 489 756 ; C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ; C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ; C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ; C -1 ; WX 667 ; N Abreve ; B 14 0 654 926 ; C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ; C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ; C -1 ; WX 611 ; N Tcaron ; B 14 0 597 929 ; C -1 ; WX 476 ; N partialdiff ; B 13 -38 463 714 ; C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ; C -1 ; WX 722 ; N Nacute ; B 76 0 646 929 ; C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ; C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ; C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ; C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ; C -1 ; WX 500 ; N cacute ; B 30 -15 477 734 ; C -1 ; WX 556 ; N nacute ; B 65 0 491 734 ; C -1 ; WX 556 ; N umacron ; B 68 -15 489 684 ; C -1 ; WX 722 ; N Ncaron ; B 76 0 646 929 ; C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ; C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ; C -1 ; WX 260 ; N brokenbar ; B 94 -150 167 700 ; C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ; C -1 ; WX 778 ; N Gbreve ; B 48 -19 704 926 ; C -1 ; WX 278 ; N Idotaccent ; B 91 0 188 901 ; C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ; C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ; C -1 ; WX 333 ; N racute ; B 77 0 332 734 ; C -1 ; WX 556 ; N omacron ; B 35 -14 521 684 ; C -1 ; WX 611 ; N Zacute ; B 23 0 588 929 ; C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 674 ; C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ; C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ; C -1 ; WX 222 ; N lcommaaccent ; B 67 -225 167 718 ; C -1 ; WX 317 ; N tcaron ; B 14 -7 329 808 ; C -1 ; WX 556 ; N eogonek ; B 40 -225 516 538 ; C -1 ; WX 722 ; N Uogonek ; B 79 -225 644 718 ; C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ; C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ; C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ; C -1 ; WX 500 ; N zacute ; B 31 0 469 734 ; C -1 ; WX 222 ; N iogonek ; B -31 -225 183 718 ; C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ; C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ; C -1 ; WX 556 ; N amacron ; B 36 -15 530 684 ; C -1 ; WX 500 ; N sacute ; B 32 -15 464 734 ; C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ; C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ; C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ; C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ; C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ; C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ; C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ; C -1 ; WX 556 ; N ohungarumlaut ; B 35 -14 521 734 ; C -1 ; WX 667 ; N Eogonek ; B 86 -220 633 718 ; C -1 ; WX 556 ; N dcroat ; B 35 -15 550 718 ; C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ; C -1 ; WX 667 ; N Scedilla ; B 49 -225 620 737 ; C -1 ; WX 299 ; N lcaron ; B 67 0 311 718 ; C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 663 718 ; C -1 ; WX 556 ; N Lacute ; B 76 0 537 929 ; C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ; C -1 ; WX 556 ; N edotaccent ; B 40 -15 516 706 ; C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ; C -1 ; WX 278 ; N Imacron ; B -17 0 296 879 ; C -1 ; WX 556 ; N Lcaron ; B 76 0 537 718 ; C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ; C -1 ; WX 549 ; N lessequal ; B 26 0 523 674 ; C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ; C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 79 -19 644 929 ; C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ; C -1 ; WX 556 ; N emacron ; B 40 -15 516 684 ; C -1 ; WX 556 ; N gbreve ; B 40 -220 499 731 ; C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ; C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ; C -1 ; WX 667 ; N Scommaaccent ; B 49 -225 620 737 ; C -1 ; WX 778 ; N Ohungarumlaut ; B 39 -19 739 929 ; C -1 ; WX 400 ; N degree ; B 54 411 346 703 ; C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ; C -1 ; WX 722 ; N Ccaron ; B 44 -19 681 929 ; C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ; C -1 ; WX 453 ; N radical ; B -4 -80 458 762 ; C -1 ; WX 722 ; N Dcaron ; B 81 0 674 929 ; C -1 ; WX 333 ; N rcommaaccent ; B 77 -225 332 538 ; C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ; C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ; C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 684 718 ; C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 537 718 ; C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ; C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ; C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ; C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ; C -1 ; WX 500 ; N zdotaccent ; B 31 0 469 706 ; C -1 ; WX 667 ; N Ecaron ; B 86 0 616 929 ; C -1 ; WX 278 ; N Iogonek ; B -3 -225 211 718 ; C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 501 718 ; C -1 ; WX 584 ; N minus ; B 39 216 545 289 ; C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ; C -1 ; WX 556 ; N ncaron ; B 65 0 491 734 ; C -1 ; WX 278 ; N tcommaaccent ; B 14 -225 257 669 ; C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ; C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ; C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ; C -1 ; WX 549 ; N notequal ; B 12 -35 537 551 ; C -1 ; WX 556 ; N gcommaaccent ; B 40 -220 499 822 ; C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ; C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ; C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 491 538 ; C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ; C -1 ; WX 278 ; N imacron ; B 5 0 272 684 ; C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2705 KPX A C -30 KPX A Cacute -30 KPX A Ccaron -30 KPX A Ccedilla -30 KPX A G -30 KPX A Gbreve -30 KPX A Gcommaaccent -30 KPX A O -30 KPX A Oacute -30 KPX A Ocircumflex -30 KPX A Odieresis -30 KPX A Ograve -30 KPX A Ohungarumlaut -30 KPX A Omacron -30 KPX A Oslash -30 KPX A Otilde -30 KPX A Q -30 KPX A T -120 KPX A Tcaron -120 KPX A Tcommaaccent -120 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -70 KPX A W -50 KPX A Y -100 KPX A Yacute -100 KPX A Ydieresis -100 KPX A u -30 KPX A uacute -30 KPX A ucircumflex -30 KPX A udieresis -30 KPX A ugrave -30 KPX A uhungarumlaut -30 KPX A umacron -30 KPX A uogonek -30 KPX A uring -30 KPX A v -40 KPX A w -40 KPX A y -40 KPX A yacute -40 KPX A ydieresis -40 KPX Aacute C -30 KPX Aacute Cacute -30 KPX Aacute Ccaron -30 KPX Aacute Ccedilla -30 KPX Aacute G -30 KPX Aacute Gbreve -30 KPX Aacute Gcommaaccent -30 KPX Aacute O -30 KPX Aacute Oacute -30 KPX Aacute Ocircumflex -30 KPX Aacute Odieresis -30 KPX Aacute Ograve -30 KPX Aacute Ohungarumlaut -30 KPX Aacute Omacron -30 KPX Aacute Oslash -30 KPX Aacute Otilde -30 KPX Aacute Q -30 KPX Aacute T -120 KPX Aacute Tcaron -120 KPX Aacute Tcommaaccent -120 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -70 KPX Aacute W -50 KPX Aacute Y -100 KPX Aacute Yacute -100 KPX Aacute Ydieresis -100 KPX Aacute u -30 KPX Aacute uacute -30 KPX Aacute ucircumflex -30 KPX Aacute udieresis -30 KPX Aacute ugrave -30 KPX Aacute uhungarumlaut -30 KPX Aacute umacron -30 KPX Aacute uogonek -30 KPX Aacute uring -30 KPX Aacute v -40 KPX Aacute w -40 KPX Aacute y -40 KPX Aacute yacute -40 KPX Aacute ydieresis -40 KPX Abreve C -30 KPX Abreve Cacute -30 KPX Abreve Ccaron -30 KPX Abreve Ccedilla -30 KPX Abreve G -30 KPX Abreve Gbreve -30 KPX Abreve Gcommaaccent -30 KPX Abreve O -30 KPX Abreve Oacute -30 KPX Abreve Ocircumflex -30 KPX Abreve Odieresis -30 KPX Abreve Ograve -30 KPX Abreve Ohungarumlaut -30 KPX Abreve Omacron -30 KPX Abreve Oslash -30 KPX Abreve Otilde -30 KPX Abreve Q -30 KPX Abreve T -120 KPX Abreve Tcaron -120 KPX Abreve Tcommaaccent -120 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -70 KPX Abreve W -50 KPX Abreve Y -100 KPX Abreve Yacute -100 KPX Abreve Ydieresis -100 KPX Abreve u -30 KPX Abreve uacute -30 KPX Abreve ucircumflex -30 KPX Abreve udieresis -30 KPX Abreve ugrave -30 KPX Abreve uhungarumlaut -30 KPX Abreve umacron -30 KPX Abreve uogonek -30 KPX Abreve uring -30 KPX Abreve v -40 KPX Abreve w -40 KPX Abreve y -40 KPX Abreve yacute -40 KPX Abreve ydieresis -40 KPX Acircumflex C -30 KPX Acircumflex Cacute -30 KPX Acircumflex Ccaron -30 KPX Acircumflex Ccedilla -30 KPX Acircumflex G -30 KPX Acircumflex Gbreve -30 KPX Acircumflex Gcommaaccent -30 KPX Acircumflex O -30 KPX Acircumflex Oacute -30 KPX Acircumflex Ocircumflex -30 KPX Acircumflex Odieresis -30 KPX Acircumflex Ograve -30 KPX Acircumflex Ohungarumlaut -30 KPX Acircumflex Omacron -30 KPX Acircumflex Oslash -30 KPX Acircumflex Otilde -30 KPX Acircumflex Q -30 KPX Acircumflex T -120 KPX Acircumflex Tcaron -120 KPX Acircumflex Tcommaaccent -120 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -70 KPX Acircumflex W -50 KPX Acircumflex Y -100 KPX Acircumflex Yacute -100 KPX Acircumflex Ydieresis -100 KPX Acircumflex u -30 KPX Acircumflex uacute -30 KPX Acircumflex ucircumflex -30 KPX Acircumflex udieresis -30 KPX Acircumflex ugrave -30 KPX Acircumflex uhungarumlaut -30 KPX Acircumflex umacron -30 KPX Acircumflex uogonek -30 KPX Acircumflex uring -30 KPX Acircumflex v -40 KPX Acircumflex w -40 KPX Acircumflex y -40 KPX Acircumflex yacute -40 KPX Acircumflex ydieresis -40 KPX Adieresis C -30 KPX Adieresis Cacute -30 KPX Adieresis Ccaron -30 KPX Adieresis Ccedilla -30 KPX Adieresis G -30 KPX Adieresis Gbreve -30 KPX Adieresis Gcommaaccent -30 KPX Adieresis O -30 KPX Adieresis Oacute -30 KPX Adieresis Ocircumflex -30 KPX Adieresis Odieresis -30 KPX Adieresis Ograve -30 KPX Adieresis Ohungarumlaut -30 KPX Adieresis Omacron -30 KPX Adieresis Oslash -30 KPX Adieresis Otilde -30 KPX Adieresis Q -30 KPX Adieresis T -120 KPX Adieresis Tcaron -120 KPX Adieresis Tcommaaccent -120 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -70 KPX Adieresis W -50 KPX Adieresis Y -100 KPX Adieresis Yacute -100 KPX Adieresis Ydieresis -100 KPX Adieresis u -30 KPX Adieresis uacute -30 KPX Adieresis ucircumflex -30 KPX Adieresis udieresis -30 KPX Adieresis ugrave -30 KPX Adieresis uhungarumlaut -30 KPX Adieresis umacron -30 KPX Adieresis uogonek -30 KPX Adieresis uring -30 KPX Adieresis v -40 KPX Adieresis w -40 KPX Adieresis y -40 KPX Adieresis yacute -40 KPX Adieresis ydieresis -40 KPX Agrave C -30 KPX Agrave Cacute -30 KPX Agrave Ccaron -30 KPX Agrave Ccedilla -30 KPX Agrave G -30 KPX Agrave Gbreve -30 KPX Agrave Gcommaaccent -30 KPX Agrave O -30 KPX Agrave Oacute -30 KPX Agrave Ocircumflex -30 KPX Agrave Odieresis -30 KPX Agrave Ograve -30 KPX Agrave Ohungarumlaut -30 KPX Agrave Omacron -30 KPX Agrave Oslash -30 KPX Agrave Otilde -30 KPX Agrave Q -30 KPX Agrave T -120 KPX Agrave Tcaron -120 KPX Agrave Tcommaaccent -120 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -70 KPX Agrave W -50 KPX Agrave Y -100 KPX Agrave Yacute -100 KPX Agrave Ydieresis -100 KPX Agrave u -30 KPX Agrave uacute -30 KPX Agrave ucircumflex -30 KPX Agrave udieresis -30 KPX Agrave ugrave -30 KPX Agrave uhungarumlaut -30 KPX Agrave umacron -30 KPX Agrave uogonek -30 KPX Agrave uring -30 KPX Agrave v -40 KPX Agrave w -40 KPX Agrave y -40 KPX Agrave yacute -40 KPX Agrave ydieresis -40 KPX Amacron C -30 KPX Amacron Cacute -30 KPX Amacron Ccaron -30 KPX Amacron Ccedilla -30 KPX Amacron G -30 KPX Amacron Gbreve -30 KPX Amacron Gcommaaccent -30 KPX Amacron O -30 KPX Amacron Oacute -30 KPX Amacron Ocircumflex -30 KPX Amacron Odieresis -30 KPX Amacron Ograve -30 KPX Amacron Ohungarumlaut -30 KPX Amacron Omacron -30 KPX Amacron Oslash -30 KPX Amacron Otilde -30 KPX Amacron Q -30 KPX Amacron T -120 KPX Amacron Tcaron -120 KPX Amacron Tcommaaccent -120 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -70 KPX Amacron W -50 KPX Amacron Y -100 KPX Amacron Yacute -100 KPX Amacron Ydieresis -100 KPX Amacron u -30 KPX Amacron uacute -30 KPX Amacron ucircumflex -30 KPX Amacron udieresis -30 KPX Amacron ugrave -30 KPX Amacron uhungarumlaut -30 KPX Amacron umacron -30 KPX Amacron uogonek -30 KPX Amacron uring -30 KPX Amacron v -40 KPX Amacron w -40 KPX Amacron y -40 KPX Amacron yacute -40 KPX Amacron ydieresis -40 KPX Aogonek C -30 KPX Aogonek Cacute -30 KPX Aogonek Ccaron -30 KPX Aogonek Ccedilla -30 KPX Aogonek G -30 KPX Aogonek Gbreve -30 KPX Aogonek Gcommaaccent -30 KPX Aogonek O -30 KPX Aogonek Oacute -30 KPX Aogonek Ocircumflex -30 KPX Aogonek Odieresis -30 KPX Aogonek Ograve -30 KPX Aogonek Ohungarumlaut -30 KPX Aogonek Omacron -30 KPX Aogonek Oslash -30 KPX Aogonek Otilde -30 KPX Aogonek Q -30 KPX Aogonek T -120 KPX Aogonek Tcaron -120 KPX Aogonek Tcommaaccent -120 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -70 KPX Aogonek W -50 KPX Aogonek Y -100 KPX Aogonek Yacute -100 KPX Aogonek Ydieresis -100 KPX Aogonek u -30 KPX Aogonek uacute -30 KPX Aogonek ucircumflex -30 KPX Aogonek udieresis -30 KPX Aogonek ugrave -30 KPX Aogonek uhungarumlaut -30 KPX Aogonek umacron -30 KPX Aogonek uogonek -30 KPX Aogonek uring -30 KPX Aogonek v -40 KPX Aogonek w -40 KPX Aogonek y -40 KPX Aogonek yacute -40 KPX Aogonek ydieresis -40 KPX Aring C -30 KPX Aring Cacute -30 KPX Aring Ccaron -30 KPX Aring Ccedilla -30 KPX Aring G -30 KPX Aring Gbreve -30 KPX Aring Gcommaaccent -30 KPX Aring O -30 KPX Aring Oacute -30 KPX Aring Ocircumflex -30 KPX Aring Odieresis -30 KPX Aring Ograve -30 KPX Aring Ohungarumlaut -30 KPX Aring Omacron -30 KPX Aring Oslash -30 KPX Aring Otilde -30 KPX Aring Q -30 KPX Aring T -120 KPX Aring Tcaron -120 KPX Aring Tcommaaccent -120 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -70 KPX Aring W -50 KPX Aring Y -100 KPX Aring Yacute -100 KPX Aring Ydieresis -100 KPX Aring u -30 KPX Aring uacute -30 KPX Aring ucircumflex -30 KPX Aring udieresis -30 KPX Aring ugrave -30 KPX Aring uhungarumlaut -30 KPX Aring umacron -30 KPX Aring uogonek -30 KPX Aring uring -30 KPX Aring v -40 KPX Aring w -40 KPX Aring y -40 KPX Aring yacute -40 KPX Aring ydieresis -40 KPX Atilde C -30 KPX Atilde Cacute -30 KPX Atilde Ccaron -30 KPX Atilde Ccedilla -30 KPX Atilde G -30 KPX Atilde Gbreve -30 KPX Atilde Gcommaaccent -30 KPX Atilde O -30 KPX Atilde Oacute -30 KPX Atilde Ocircumflex -30 KPX Atilde Odieresis -30 KPX Atilde Ograve -30 KPX Atilde Ohungarumlaut -30 KPX Atilde Omacron -30 KPX Atilde Oslash -30 KPX Atilde Otilde -30 KPX Atilde Q -30 KPX Atilde T -120 KPX Atilde Tcaron -120 KPX Atilde Tcommaaccent -120 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -70 KPX Atilde W -50 KPX Atilde Y -100 KPX Atilde Yacute -100 KPX Atilde Ydieresis -100 KPX Atilde u -30 KPX Atilde uacute -30 KPX Atilde ucircumflex -30 KPX Atilde udieresis -30 KPX Atilde ugrave -30 KPX Atilde uhungarumlaut -30 KPX Atilde umacron -30 KPX Atilde uogonek -30 KPX Atilde uring -30 KPX Atilde v -40 KPX Atilde w -40 KPX Atilde y -40 KPX Atilde yacute -40 KPX Atilde ydieresis -40 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX B comma -20 KPX B period -20 KPX C comma -30 KPX C period -30 KPX Cacute comma -30 KPX Cacute period -30 KPX Ccaron comma -30 KPX Ccaron period -30 KPX Ccedilla comma -30 KPX Ccedilla period -30 KPX D A -40 KPX D Aacute -40 KPX D Abreve -40 KPX D Acircumflex -40 KPX D Adieresis -40 KPX D Agrave -40 KPX D Amacron -40 KPX D Aogonek -40 KPX D Aring -40 KPX D Atilde -40 KPX D V -70 KPX D W -40 KPX D Y -90 KPX D Yacute -90 KPX D Ydieresis -90 KPX D comma -70 KPX D period -70 KPX Dcaron A -40 KPX Dcaron Aacute -40 KPX Dcaron Abreve -40 KPX Dcaron Acircumflex -40 KPX Dcaron Adieresis -40 KPX Dcaron Agrave -40 KPX Dcaron Amacron -40 KPX Dcaron Aogonek -40 KPX Dcaron Aring -40 KPX Dcaron Atilde -40 KPX Dcaron V -70 KPX Dcaron W -40 KPX Dcaron Y -90 KPX Dcaron Yacute -90 KPX Dcaron Ydieresis -90 KPX Dcaron comma -70 KPX Dcaron period -70 KPX Dcroat A -40 KPX Dcroat Aacute -40 KPX Dcroat Abreve -40 KPX Dcroat Acircumflex -40 KPX Dcroat Adieresis -40 KPX Dcroat Agrave -40 KPX Dcroat Amacron -40 KPX Dcroat Aogonek -40 KPX Dcroat Aring -40 KPX Dcroat Atilde -40 KPX Dcroat V -70 KPX Dcroat W -40 KPX Dcroat Y -90 KPX Dcroat Yacute -90 KPX Dcroat Ydieresis -90 KPX Dcroat comma -70 KPX Dcroat period -70 KPX F A -80 KPX F Aacute -80 KPX F Abreve -80 KPX F Acircumflex -80 KPX F Adieresis -80 KPX F Agrave -80 KPX F Amacron -80 KPX F Aogonek -80 KPX F Aring -80 KPX F Atilde -80 KPX F a -50 KPX F aacute -50 KPX F abreve -50 KPX F acircumflex -50 KPX F adieresis -50 KPX F agrave -50 KPX F amacron -50 KPX F aogonek -50 KPX F aring -50 KPX F atilde -50 KPX F comma -150 KPX F e -30 KPX F eacute -30 KPX F ecaron -30 KPX F ecircumflex -30 KPX F edieresis -30 KPX F edotaccent -30 KPX F egrave -30 KPX F emacron -30 KPX F eogonek -30 KPX F o -30 KPX F oacute -30 KPX F ocircumflex -30 KPX F odieresis -30 KPX F ograve -30 KPX F ohungarumlaut -30 KPX F omacron -30 KPX F oslash -30 KPX F otilde -30 KPX F period -150 KPX F r -45 KPX F racute -45 KPX F rcaron -45 KPX F rcommaaccent -45 KPX J A -20 KPX J Aacute -20 KPX J Abreve -20 KPX J Acircumflex -20 KPX J Adieresis -20 KPX J Agrave -20 KPX J Amacron -20 KPX J Aogonek -20 KPX J Aring -20 KPX J Atilde -20 KPX J a -20 KPX J aacute -20 KPX J abreve -20 KPX J acircumflex -20 KPX J adieresis -20 KPX J agrave -20 KPX J amacron -20 KPX J aogonek -20 KPX J aring -20 KPX J atilde -20 KPX J comma -30 KPX J period -30 KPX J u -20 KPX J uacute -20 KPX J ucircumflex -20 KPX J udieresis -20 KPX J ugrave -20 KPX J uhungarumlaut -20 KPX J umacron -20 KPX J uogonek -20 KPX J uring -20 KPX K O -50 KPX K Oacute -50 KPX K Ocircumflex -50 KPX K Odieresis -50 KPX K Ograve -50 KPX K Ohungarumlaut -50 KPX K Omacron -50 KPX K Oslash -50 KPX K Otilde -50 KPX K e -40 KPX K eacute -40 KPX K ecaron -40 KPX K ecircumflex -40 KPX K edieresis -40 KPX K edotaccent -40 KPX K egrave -40 KPX K emacron -40 KPX K eogonek -40 KPX K o -40 KPX K oacute -40 KPX K ocircumflex -40 KPX K odieresis -40 KPX K ograve -40 KPX K ohungarumlaut -40 KPX K omacron -40 KPX K oslash -40 KPX K otilde -40 KPX K u -30 KPX K uacute -30 KPX K ucircumflex -30 KPX K udieresis -30 KPX K ugrave -30 KPX K uhungarumlaut -30 KPX K umacron -30 KPX K uogonek -30 KPX K uring -30 KPX K y -50 KPX K yacute -50 KPX K ydieresis -50 KPX Kcommaaccent O -50 KPX Kcommaaccent Oacute -50 KPX Kcommaaccent Ocircumflex -50 KPX Kcommaaccent Odieresis -50 KPX Kcommaaccent Ograve -50 KPX Kcommaaccent Ohungarumlaut -50 KPX Kcommaaccent Omacron -50 KPX Kcommaaccent Oslash -50 KPX Kcommaaccent Otilde -50 KPX Kcommaaccent e -40 KPX Kcommaaccent eacute -40 KPX Kcommaaccent ecaron -40 KPX Kcommaaccent ecircumflex -40 KPX Kcommaaccent edieresis -40 KPX Kcommaaccent edotaccent -40 KPX Kcommaaccent egrave -40 KPX Kcommaaccent emacron -40 KPX Kcommaaccent eogonek -40 KPX Kcommaaccent o -40 KPX Kcommaaccent oacute -40 KPX Kcommaaccent ocircumflex -40 KPX Kcommaaccent odieresis -40 KPX Kcommaaccent ograve -40 KPX Kcommaaccent ohungarumlaut -40 KPX Kcommaaccent omacron -40 KPX Kcommaaccent oslash -40 KPX Kcommaaccent otilde -40 KPX Kcommaaccent u -30 KPX Kcommaaccent uacute -30 KPX Kcommaaccent ucircumflex -30 KPX Kcommaaccent udieresis -30 KPX Kcommaaccent ugrave -30 KPX Kcommaaccent uhungarumlaut -30 KPX Kcommaaccent umacron -30 KPX Kcommaaccent uogonek -30 KPX Kcommaaccent uring -30 KPX Kcommaaccent y -50 KPX Kcommaaccent yacute -50 KPX Kcommaaccent ydieresis -50 KPX L T -110 KPX L Tcaron -110 KPX L Tcommaaccent -110 KPX L V -110 KPX L W -70 KPX L Y -140 KPX L Yacute -140 KPX L Ydieresis -140 KPX L quotedblright -140 KPX L quoteright -160 KPX L y -30 KPX L yacute -30 KPX L ydieresis -30 KPX Lacute T -110 KPX Lacute Tcaron -110 KPX Lacute Tcommaaccent -110 KPX Lacute V -110 KPX Lacute W -70 KPX Lacute Y -140 KPX Lacute Yacute -140 KPX Lacute Ydieresis -140 KPX Lacute quotedblright -140 KPX Lacute quoteright -160 KPX Lacute y -30 KPX Lacute yacute -30 KPX Lacute ydieresis -30 KPX Lcaron T -110 KPX Lcaron Tcaron -110 KPX Lcaron Tcommaaccent -110 KPX Lcaron V -110 KPX Lcaron W -70 KPX Lcaron Y -140 KPX Lcaron Yacute -140 KPX Lcaron Ydieresis -140 KPX Lcaron quotedblright -140 KPX Lcaron quoteright -160 KPX Lcaron y -30 KPX Lcaron yacute -30 KPX Lcaron ydieresis -30 KPX Lcommaaccent T -110 KPX Lcommaaccent Tcaron -110 KPX Lcommaaccent Tcommaaccent -110 KPX Lcommaaccent V -110 KPX Lcommaaccent W -70 KPX Lcommaaccent Y -140 KPX Lcommaaccent Yacute -140 KPX Lcommaaccent Ydieresis -140 KPX Lcommaaccent quotedblright -140 KPX Lcommaaccent quoteright -160 KPX Lcommaaccent y -30 KPX Lcommaaccent yacute -30 KPX Lcommaaccent ydieresis -30 KPX Lslash T -110 KPX Lslash Tcaron -110 KPX Lslash Tcommaaccent -110 KPX Lslash V -110 KPX Lslash W -70 KPX Lslash Y -140 KPX Lslash Yacute -140 KPX Lslash Ydieresis -140 KPX Lslash quotedblright -140 KPX Lslash quoteright -160 KPX Lslash y -30 KPX Lslash yacute -30 KPX Lslash ydieresis -30 KPX O A -20 KPX O Aacute -20 KPX O Abreve -20 KPX O Acircumflex -20 KPX O Adieresis -20 KPX O Agrave -20 KPX O Amacron -20 KPX O Aogonek -20 KPX O Aring -20 KPX O Atilde -20 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -30 KPX O X -60 KPX O Y -70 KPX O Yacute -70 KPX O Ydieresis -70 KPX O comma -40 KPX O period -40 KPX Oacute A -20 KPX Oacute Aacute -20 KPX Oacute Abreve -20 KPX Oacute Acircumflex -20 KPX Oacute Adieresis -20 KPX Oacute Agrave -20 KPX Oacute Amacron -20 KPX Oacute Aogonek -20 KPX Oacute Aring -20 KPX Oacute Atilde -20 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -30 KPX Oacute X -60 KPX Oacute Y -70 KPX Oacute Yacute -70 KPX Oacute Ydieresis -70 KPX Oacute comma -40 KPX Oacute period -40 KPX Ocircumflex A -20 KPX Ocircumflex Aacute -20 KPX Ocircumflex Abreve -20 KPX Ocircumflex Acircumflex -20 KPX Ocircumflex Adieresis -20 KPX Ocircumflex Agrave -20 KPX Ocircumflex Amacron -20 KPX Ocircumflex Aogonek -20 KPX Ocircumflex Aring -20 KPX Ocircumflex Atilde -20 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -30 KPX Ocircumflex X -60 KPX Ocircumflex Y -70 KPX Ocircumflex Yacute -70 KPX Ocircumflex Ydieresis -70 KPX Ocircumflex comma -40 KPX Ocircumflex period -40 KPX Odieresis A -20 KPX Odieresis Aacute -20 KPX Odieresis Abreve -20 KPX Odieresis Acircumflex -20 KPX Odieresis Adieresis -20 KPX Odieresis Agrave -20 KPX Odieresis Amacron -20 KPX Odieresis Aogonek -20 KPX Odieresis Aring -20 KPX Odieresis Atilde -20 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -30 KPX Odieresis X -60 KPX Odieresis Y -70 KPX Odieresis Yacute -70 KPX Odieresis Ydieresis -70 KPX Odieresis comma -40 KPX Odieresis period -40 KPX Ograve A -20 KPX Ograve Aacute -20 KPX Ograve Abreve -20 KPX Ograve Acircumflex -20 KPX Ograve Adieresis -20 KPX Ograve Agrave -20 KPX Ograve Amacron -20 KPX Ograve Aogonek -20 KPX Ograve Aring -20 KPX Ograve Atilde -20 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -30 KPX Ograve X -60 KPX Ograve Y -70 KPX Ograve Yacute -70 KPX Ograve Ydieresis -70 KPX Ograve comma -40 KPX Ograve period -40 KPX Ohungarumlaut A -20 KPX Ohungarumlaut Aacute -20 KPX Ohungarumlaut Abreve -20 KPX Ohungarumlaut Acircumflex -20 KPX Ohungarumlaut Adieresis -20 KPX Ohungarumlaut Agrave -20 KPX Ohungarumlaut Amacron -20 KPX Ohungarumlaut Aogonek -20 KPX Ohungarumlaut Aring -20 KPX Ohungarumlaut Atilde -20 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -30 KPX Ohungarumlaut X -60 KPX Ohungarumlaut Y -70 KPX Ohungarumlaut Yacute -70 KPX Ohungarumlaut Ydieresis -70 KPX Ohungarumlaut comma -40 KPX Ohungarumlaut period -40 KPX Omacron A -20 KPX Omacron Aacute -20 KPX Omacron Abreve -20 KPX Omacron Acircumflex -20 KPX Omacron Adieresis -20 KPX Omacron Agrave -20 KPX Omacron Amacron -20 KPX Omacron Aogonek -20 KPX Omacron Aring -20 KPX Omacron Atilde -20 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -30 KPX Omacron X -60 KPX Omacron Y -70 KPX Omacron Yacute -70 KPX Omacron Ydieresis -70 KPX Omacron comma -40 KPX Omacron period -40 KPX Oslash A -20 KPX Oslash Aacute -20 KPX Oslash Abreve -20 KPX Oslash Acircumflex -20 KPX Oslash Adieresis -20 KPX Oslash Agrave -20 KPX Oslash Amacron -20 KPX Oslash Aogonek -20 KPX Oslash Aring -20 KPX Oslash Atilde -20 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -30 KPX Oslash X -60 KPX Oslash Y -70 KPX Oslash Yacute -70 KPX Oslash Ydieresis -70 KPX Oslash comma -40 KPX Oslash period -40 KPX Otilde A -20 KPX Otilde Aacute -20 KPX Otilde Abreve -20 KPX Otilde Acircumflex -20 KPX Otilde Adieresis -20 KPX Otilde Agrave -20 KPX Otilde Amacron -20 KPX Otilde Aogonek -20 KPX Otilde Aring -20 KPX Otilde Atilde -20 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -30 KPX Otilde X -60 KPX Otilde Y -70 KPX Otilde Yacute -70 KPX Otilde Ydieresis -70 KPX Otilde comma -40 KPX Otilde period -40 KPX P A -120 KPX P Aacute -120 KPX P Abreve -120 KPX P Acircumflex -120 KPX P Adieresis -120 KPX P Agrave -120 KPX P Amacron -120 KPX P Aogonek -120 KPX P Aring -120 KPX P Atilde -120 KPX P a -40 KPX P aacute -40 KPX P abreve -40 KPX P acircumflex -40 KPX P adieresis -40 KPX P agrave -40 KPX P amacron -40 KPX P aogonek -40 KPX P aring -40 KPX P atilde -40 KPX P comma -180 KPX P e -50 KPX P eacute -50 KPX P ecaron -50 KPX P ecircumflex -50 KPX P edieresis -50 KPX P edotaccent -50 KPX P egrave -50 KPX P emacron -50 KPX P eogonek -50 KPX P o -50 KPX P oacute -50 KPX P ocircumflex -50 KPX P odieresis -50 KPX P ograve -50 KPX P ohungarumlaut -50 KPX P omacron -50 KPX P oslash -50 KPX P otilde -50 KPX P period -180 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX R O -20 KPX R Oacute -20 KPX R Ocircumflex -20 KPX R Odieresis -20 KPX R Ograve -20 KPX R Ohungarumlaut -20 KPX R Omacron -20 KPX R Oslash -20 KPX R Otilde -20 KPX R T -30 KPX R Tcaron -30 KPX R Tcommaaccent -30 KPX R U -40 KPX R Uacute -40 KPX R Ucircumflex -40 KPX R Udieresis -40 KPX R Ugrave -40 KPX R Uhungarumlaut -40 KPX R Umacron -40 KPX R Uogonek -40 KPX R Uring -40 KPX R V -50 KPX R W -30 KPX R Y -50 KPX R Yacute -50 KPX R Ydieresis -50 KPX Racute O -20 KPX Racute Oacute -20 KPX Racute Ocircumflex -20 KPX Racute Odieresis -20 KPX Racute Ograve -20 KPX Racute Ohungarumlaut -20 KPX Racute Omacron -20 KPX Racute Oslash -20 KPX Racute Otilde -20 KPX Racute T -30 KPX Racute Tcaron -30 KPX Racute Tcommaaccent -30 KPX Racute U -40 KPX Racute Uacute -40 KPX Racute Ucircumflex -40 KPX Racute Udieresis -40 KPX Racute Ugrave -40 KPX Racute Uhungarumlaut -40 KPX Racute Umacron -40 KPX Racute Uogonek -40 KPX Racute Uring -40 KPX Racute V -50 KPX Racute W -30 KPX Racute Y -50 KPX Racute Yacute -50 KPX Racute Ydieresis -50 KPX Rcaron O -20 KPX Rcaron Oacute -20 KPX Rcaron Ocircumflex -20 KPX Rcaron Odieresis -20 KPX Rcaron Ograve -20 KPX Rcaron Ohungarumlaut -20 KPX Rcaron Omacron -20 KPX Rcaron Oslash -20 KPX Rcaron Otilde -20 KPX Rcaron T -30 KPX Rcaron Tcaron -30 KPX Rcaron Tcommaaccent -30 KPX Rcaron U -40 KPX Rcaron Uacute -40 KPX Rcaron Ucircumflex -40 KPX Rcaron Udieresis -40 KPX Rcaron Ugrave -40 KPX Rcaron Uhungarumlaut -40 KPX Rcaron Umacron -40 KPX Rcaron Uogonek -40 KPX Rcaron Uring -40 KPX Rcaron V -50 KPX Rcaron W -30 KPX Rcaron Y -50 KPX Rcaron Yacute -50 KPX Rcaron Ydieresis -50 KPX Rcommaaccent O -20 KPX Rcommaaccent Oacute -20 KPX Rcommaaccent Ocircumflex -20 KPX Rcommaaccent Odieresis -20 KPX Rcommaaccent Ograve -20 KPX Rcommaaccent Ohungarumlaut -20 KPX Rcommaaccent Omacron -20 KPX Rcommaaccent Oslash -20 KPX Rcommaaccent Otilde -20 KPX Rcommaaccent T -30 KPX Rcommaaccent Tcaron -30 KPX Rcommaaccent Tcommaaccent -30 KPX Rcommaaccent U -40 KPX Rcommaaccent Uacute -40 KPX Rcommaaccent Ucircumflex -40 KPX Rcommaaccent Udieresis -40 KPX Rcommaaccent Ugrave -40 KPX Rcommaaccent Uhungarumlaut -40 KPX Rcommaaccent Umacron -40 KPX Rcommaaccent Uogonek -40 KPX Rcommaaccent Uring -40 KPX Rcommaaccent V -50 KPX Rcommaaccent W -30 KPX Rcommaaccent Y -50 KPX Rcommaaccent Yacute -50 KPX Rcommaaccent Ydieresis -50 KPX S comma -20 KPX S period -20 KPX Sacute comma -20 KPX Sacute period -20 KPX Scaron comma -20 KPX Scaron period -20 KPX Scedilla comma -20 KPX Scedilla period -20 KPX Scommaaccent comma -20 KPX Scommaaccent period -20 KPX T A -120 KPX T Aacute -120 KPX T Abreve -120 KPX T Acircumflex -120 KPX T Adieresis -120 KPX T Agrave -120 KPX T Amacron -120 KPX T Aogonek -120 KPX T Aring -120 KPX T Atilde -120 KPX T O -40 KPX T Oacute -40 KPX T Ocircumflex -40 KPX T Odieresis -40 KPX T Ograve -40 KPX T Ohungarumlaut -40 KPX T Omacron -40 KPX T Oslash -40 KPX T Otilde -40 KPX T a -120 KPX T aacute -120 KPX T abreve -60 KPX T acircumflex -120 KPX T adieresis -120 KPX T agrave -120 KPX T amacron -60 KPX T aogonek -120 KPX T aring -120 KPX T atilde -60 KPX T colon -20 KPX T comma -120 KPX T e -120 KPX T eacute -120 KPX T ecaron -120 KPX T ecircumflex -120 KPX T edieresis -120 KPX T edotaccent -120 KPX T egrave -60 KPX T emacron -60 KPX T eogonek -120 KPX T hyphen -140 KPX T o -120 KPX T oacute -120 KPX T ocircumflex -120 KPX T odieresis -120 KPX T ograve -120 KPX T ohungarumlaut -120 KPX T omacron -60 KPX T oslash -120 KPX T otilde -60 KPX T period -120 KPX T r -120 KPX T racute -120 KPX T rcaron -120 KPX T rcommaaccent -120 KPX T semicolon -20 KPX T u -120 KPX T uacute -120 KPX T ucircumflex -120 KPX T udieresis -120 KPX T ugrave -120 KPX T uhungarumlaut -120 KPX T umacron -60 KPX T uogonek -120 KPX T uring -120 KPX T w -120 KPX T y -120 KPX T yacute -120 KPX T ydieresis -60 KPX Tcaron A -120 KPX Tcaron Aacute -120 KPX Tcaron Abreve -120 KPX Tcaron Acircumflex -120 KPX Tcaron Adieresis -120 KPX Tcaron Agrave -120 KPX Tcaron Amacron -120 KPX Tcaron Aogonek -120 KPX Tcaron Aring -120 KPX Tcaron Atilde -120 KPX Tcaron O -40 KPX Tcaron Oacute -40 KPX Tcaron Ocircumflex -40 KPX Tcaron Odieresis -40 KPX Tcaron Ograve -40 KPX Tcaron Ohungarumlaut -40 KPX Tcaron Omacron -40 KPX Tcaron Oslash -40 KPX Tcaron Otilde -40 KPX Tcaron a -120 KPX Tcaron aacute -120 KPX Tcaron abreve -60 KPX Tcaron acircumflex -120 KPX Tcaron adieresis -120 KPX Tcaron agrave -120 KPX Tcaron amacron -60 KPX Tcaron aogonek -120 KPX Tcaron aring -120 KPX Tcaron atilde -60 KPX Tcaron colon -20 KPX Tcaron comma -120 KPX Tcaron e -120 KPX Tcaron eacute -120 KPX Tcaron ecaron -120 KPX Tcaron ecircumflex -120 KPX Tcaron edieresis -120 KPX Tcaron edotaccent -120 KPX Tcaron egrave -60 KPX Tcaron emacron -60 KPX Tcaron eogonek -120 KPX Tcaron hyphen -140 KPX Tcaron o -120 KPX Tcaron oacute -120 KPX Tcaron ocircumflex -120 KPX Tcaron odieresis -120 KPX Tcaron ograve -120 KPX Tcaron ohungarumlaut -120 KPX Tcaron omacron -60 KPX Tcaron oslash -120 KPX Tcaron otilde -60 KPX Tcaron period -120 KPX Tcaron r -120 KPX Tcaron racute -120 KPX Tcaron rcaron -120 KPX Tcaron rcommaaccent -120 KPX Tcaron semicolon -20 KPX Tcaron u -120 KPX Tcaron uacute -120 KPX Tcaron ucircumflex -120 KPX Tcaron udieresis -120 KPX Tcaron ugrave -120 KPX Tcaron uhungarumlaut -120 KPX Tcaron umacron -60 KPX Tcaron uogonek -120 KPX Tcaron uring -120 KPX Tcaron w -120 KPX Tcaron y -120 KPX Tcaron yacute -120 KPX Tcaron ydieresis -60 KPX Tcommaaccent A -120 KPX Tcommaaccent Aacute -120 KPX Tcommaaccent Abreve -120 KPX Tcommaaccent Acircumflex -120 KPX Tcommaaccent Adieresis -120 KPX Tcommaaccent Agrave -120 KPX Tcommaaccent Amacron -120 KPX Tcommaaccent Aogonek -120 KPX Tcommaaccent Aring -120 KPX Tcommaaccent Atilde -120 KPX Tcommaaccent O -40 KPX Tcommaaccent Oacute -40 KPX Tcommaaccent Ocircumflex -40 KPX Tcommaaccent Odieresis -40 KPX Tcommaaccent Ograve -40 KPX Tcommaaccent Ohungarumlaut -40 KPX Tcommaaccent Omacron -40 KPX Tcommaaccent Oslash -40 KPX Tcommaaccent Otilde -40 KPX Tcommaaccent a -120 KPX Tcommaaccent aacute -120 KPX Tcommaaccent abreve -60 KPX Tcommaaccent acircumflex -120 KPX Tcommaaccent adieresis -120 KPX Tcommaaccent agrave -120 KPX Tcommaaccent amacron -60 KPX Tcommaaccent aogonek -120 KPX Tcommaaccent aring -120 KPX Tcommaaccent atilde -60 KPX Tcommaaccent colon -20 KPX Tcommaaccent comma -120 KPX Tcommaaccent e -120 KPX Tcommaaccent eacute -120 KPX Tcommaaccent ecaron -120 KPX Tcommaaccent ecircumflex -120 KPX Tcommaaccent edieresis -120 KPX Tcommaaccent edotaccent -120 KPX Tcommaaccent egrave -60 KPX Tcommaaccent emacron -60 KPX Tcommaaccent eogonek -120 KPX Tcommaaccent hyphen -140 KPX Tcommaaccent o -120 KPX Tcommaaccent oacute -120 KPX Tcommaaccent ocircumflex -120 KPX Tcommaaccent odieresis -120 KPX Tcommaaccent ograve -120 KPX Tcommaaccent ohungarumlaut -120 KPX Tcommaaccent omacron -60 KPX Tcommaaccent oslash -120 KPX Tcommaaccent otilde -60 KPX Tcommaaccent period -120 KPX Tcommaaccent r -120 KPX Tcommaaccent racute -120 KPX Tcommaaccent rcaron -120 KPX Tcommaaccent rcommaaccent -120 KPX Tcommaaccent semicolon -20 KPX Tcommaaccent u -120 KPX Tcommaaccent uacute -120 KPX Tcommaaccent ucircumflex -120 KPX Tcommaaccent udieresis -120 KPX Tcommaaccent ugrave -120 KPX Tcommaaccent uhungarumlaut -120 KPX Tcommaaccent umacron -60 KPX Tcommaaccent uogonek -120 KPX Tcommaaccent uring -120 KPX Tcommaaccent w -120 KPX Tcommaaccent y -120 KPX Tcommaaccent yacute -120 KPX Tcommaaccent ydieresis -60 KPX U A -40 KPX U Aacute -40 KPX U Abreve -40 KPX U Acircumflex -40 KPX U Adieresis -40 KPX U Agrave -40 KPX U Amacron -40 KPX U Aogonek -40 KPX U Aring -40 KPX U Atilde -40 KPX U comma -40 KPX U period -40 KPX Uacute A -40 KPX Uacute Aacute -40 KPX Uacute Abreve -40 KPX Uacute Acircumflex -40 KPX Uacute Adieresis -40 KPX Uacute Agrave -40 KPX Uacute Amacron -40 KPX Uacute Aogonek -40 KPX Uacute Aring -40 KPX Uacute Atilde -40 KPX Uacute comma -40 KPX Uacute period -40 KPX Ucircumflex A -40 KPX Ucircumflex Aacute -40 KPX Ucircumflex Abreve -40 KPX Ucircumflex Acircumflex -40 KPX Ucircumflex Adieresis -40 KPX Ucircumflex Agrave -40 KPX Ucircumflex Amacron -40 KPX Ucircumflex Aogonek -40 KPX Ucircumflex Aring -40 KPX Ucircumflex Atilde -40 KPX Ucircumflex comma -40 KPX Ucircumflex period -40 KPX Udieresis A -40 KPX Udieresis Aacute -40 KPX Udieresis Abreve -40 KPX Udieresis Acircumflex -40 KPX Udieresis Adieresis -40 KPX Udieresis Agrave -40 KPX Udieresis Amacron -40 KPX Udieresis Aogonek -40 KPX Udieresis Aring -40 KPX Udieresis Atilde -40 KPX Udieresis comma -40 KPX Udieresis period -40 KPX Ugrave A -40 KPX Ugrave Aacute -40 KPX Ugrave Abreve -40 KPX Ugrave Acircumflex -40 KPX Ugrave Adieresis -40 KPX Ugrave Agrave -40 KPX Ugrave Amacron -40 KPX Ugrave Aogonek -40 KPX Ugrave Aring -40 KPX Ugrave Atilde -40 KPX Ugrave comma -40 KPX Ugrave period -40 KPX Uhungarumlaut A -40 KPX Uhungarumlaut Aacute -40 KPX Uhungarumlaut Abreve -40 KPX Uhungarumlaut Acircumflex -40 KPX Uhungarumlaut Adieresis -40 KPX Uhungarumlaut Agrave -40 KPX Uhungarumlaut Amacron -40 KPX Uhungarumlaut Aogonek -40 KPX Uhungarumlaut Aring -40 KPX Uhungarumlaut Atilde -40 KPX Uhungarumlaut comma -40 KPX Uhungarumlaut period -40 KPX Umacron A -40 KPX Umacron Aacute -40 KPX Umacron Abreve -40 KPX Umacron Acircumflex -40 KPX Umacron Adieresis -40 KPX Umacron Agrave -40 KPX Umacron Amacron -40 KPX Umacron Aogonek -40 KPX Umacron Aring -40 KPX Umacron Atilde -40 KPX Umacron comma -40 KPX Umacron period -40 KPX Uogonek A -40 KPX Uogonek Aacute -40 KPX Uogonek Abreve -40 KPX Uogonek Acircumflex -40 KPX Uogonek Adieresis -40 KPX Uogonek Agrave -40 KPX Uogonek Amacron -40 KPX Uogonek Aogonek -40 KPX Uogonek Aring -40 KPX Uogonek Atilde -40 KPX Uogonek comma -40 KPX Uogonek period -40 KPX Uring A -40 KPX Uring Aacute -40 KPX Uring Abreve -40 KPX Uring Acircumflex -40 KPX Uring Adieresis -40 KPX Uring Agrave -40 KPX Uring Amacron -40 KPX Uring Aogonek -40 KPX Uring Aring -40 KPX Uring Atilde -40 KPX Uring comma -40 KPX Uring period -40 KPX V A -80 KPX V Aacute -80 KPX V Abreve -80 KPX V Acircumflex -80 KPX V Adieresis -80 KPX V Agrave -80 KPX V Amacron -80 KPX V Aogonek -80 KPX V Aring -80 KPX V Atilde -80 KPX V G -40 KPX V Gbreve -40 KPX V Gcommaaccent -40 KPX V O -40 KPX V Oacute -40 KPX V Ocircumflex -40 KPX V Odieresis -40 KPX V Ograve -40 KPX V Ohungarumlaut -40 KPX V Omacron -40 KPX V Oslash -40 KPX V Otilde -40 KPX V a -70 KPX V aacute -70 KPX V abreve -70 KPX V acircumflex -70 KPX V adieresis -70 KPX V agrave -70 KPX V amacron -70 KPX V aogonek -70 KPX V aring -70 KPX V atilde -70 KPX V colon -40 KPX V comma -125 KPX V e -80 KPX V eacute -80 KPX V ecaron -80 KPX V ecircumflex -80 KPX V edieresis -80 KPX V edotaccent -80 KPX V egrave -80 KPX V emacron -80 KPX V eogonek -80 KPX V hyphen -80 KPX V o -80 KPX V oacute -80 KPX V ocircumflex -80 KPX V odieresis -80 KPX V ograve -80 KPX V ohungarumlaut -80 KPX V omacron -80 KPX V oslash -80 KPX V otilde -80 KPX V period -125 KPX V semicolon -40 KPX V u -70 KPX V uacute -70 KPX V ucircumflex -70 KPX V udieresis -70 KPX V ugrave -70 KPX V uhungarumlaut -70 KPX V umacron -70 KPX V uogonek -70 KPX V uring -70 KPX W A -50 KPX W Aacute -50 KPX W Abreve -50 KPX W Acircumflex -50 KPX W Adieresis -50 KPX W Agrave -50 KPX W Amacron -50 KPX W Aogonek -50 KPX W Aring -50 KPX W Atilde -50 KPX W O -20 KPX W Oacute -20 KPX W Ocircumflex -20 KPX W Odieresis -20 KPX W Ograve -20 KPX W Ohungarumlaut -20 KPX W Omacron -20 KPX W Oslash -20 KPX W Otilde -20 KPX W a -40 KPX W aacute -40 KPX W abreve -40 KPX W acircumflex -40 KPX W adieresis -40 KPX W agrave -40 KPX W amacron -40 KPX W aogonek -40 KPX W aring -40 KPX W atilde -40 KPX W comma -80 KPX W e -30 KPX W eacute -30 KPX W ecaron -30 KPX W ecircumflex -30 KPX W edieresis -30 KPX W edotaccent -30 KPX W egrave -30 KPX W emacron -30 KPX W eogonek -30 KPX W hyphen -40 KPX W o -30 KPX W oacute -30 KPX W ocircumflex -30 KPX W odieresis -30 KPX W ograve -30 KPX W ohungarumlaut -30 KPX W omacron -30 KPX W oslash -30 KPX W otilde -30 KPX W period -80 KPX W u -30 KPX W uacute -30 KPX W ucircumflex -30 KPX W udieresis -30 KPX W ugrave -30 KPX W uhungarumlaut -30 KPX W umacron -30 KPX W uogonek -30 KPX W uring -30 KPX W y -20 KPX W yacute -20 KPX W ydieresis -20 KPX Y A -110 KPX Y Aacute -110 KPX Y Abreve -110 KPX Y Acircumflex -110 KPX Y Adieresis -110 KPX Y Agrave -110 KPX Y Amacron -110 KPX Y Aogonek -110 KPX Y Aring -110 KPX Y Atilde -110 KPX Y O -85 KPX Y Oacute -85 KPX Y Ocircumflex -85 KPX Y Odieresis -85 KPX Y Ograve -85 KPX Y Ohungarumlaut -85 KPX Y Omacron -85 KPX Y Oslash -85 KPX Y Otilde -85 KPX Y a -140 KPX Y aacute -140 KPX Y abreve -70 KPX Y acircumflex -140 KPX Y adieresis -140 KPX Y agrave -140 KPX Y amacron -70 KPX Y aogonek -140 KPX Y aring -140 KPX Y atilde -140 KPX Y colon -60 KPX Y comma -140 KPX Y e -140 KPX Y eacute -140 KPX Y ecaron -140 KPX Y ecircumflex -140 KPX Y edieresis -140 KPX Y edotaccent -140 KPX Y egrave -140 KPX Y emacron -70 KPX Y eogonek -140 KPX Y hyphen -140 KPX Y i -20 KPX Y iacute -20 KPX Y iogonek -20 KPX Y o -140 KPX Y oacute -140 KPX Y ocircumflex -140 KPX Y odieresis -140 KPX Y ograve -140 KPX Y ohungarumlaut -140 KPX Y omacron -140 KPX Y oslash -140 KPX Y otilde -140 KPX Y period -140 KPX Y semicolon -60 KPX Y u -110 KPX Y uacute -110 KPX Y ucircumflex -110 KPX Y udieresis -110 KPX Y ugrave -110 KPX Y uhungarumlaut -110 KPX Y umacron -110 KPX Y uogonek -110 KPX Y uring -110 KPX Yacute A -110 KPX Yacute Aacute -110 KPX Yacute Abreve -110 KPX Yacute Acircumflex -110 KPX Yacute Adieresis -110 KPX Yacute Agrave -110 KPX Yacute Amacron -110 KPX Yacute Aogonek -110 KPX Yacute Aring -110 KPX Yacute Atilde -110 KPX Yacute O -85 KPX Yacute Oacute -85 KPX Yacute Ocircumflex -85 KPX Yacute Odieresis -85 KPX Yacute Ograve -85 KPX Yacute Ohungarumlaut -85 KPX Yacute Omacron -85 KPX Yacute Oslash -85 KPX Yacute Otilde -85 KPX Yacute a -140 KPX Yacute aacute -140 KPX Yacute abreve -70 KPX Yacute acircumflex -140 KPX Yacute adieresis -140 KPX Yacute agrave -140 KPX Yacute amacron -70 KPX Yacute aogonek -140 KPX Yacute aring -140 KPX Yacute atilde -70 KPX Yacute colon -60 KPX Yacute comma -140 KPX Yacute e -140 KPX Yacute eacute -140 KPX Yacute ecaron -140 KPX Yacute ecircumflex -140 KPX Yacute edieresis -140 KPX Yacute edotaccent -140 KPX Yacute egrave -140 KPX Yacute emacron -70 KPX Yacute eogonek -140 KPX Yacute hyphen -140 KPX Yacute i -20 KPX Yacute iacute -20 KPX Yacute iogonek -20 KPX Yacute o -140 KPX Yacute oacute -140 KPX Yacute ocircumflex -140 KPX Yacute odieresis -140 KPX Yacute ograve -140 KPX Yacute ohungarumlaut -140 KPX Yacute omacron -70 KPX Yacute oslash -140 KPX Yacute otilde -140 KPX Yacute period -140 KPX Yacute semicolon -60 KPX Yacute u -110 KPX Yacute uacute -110 KPX Yacute ucircumflex -110 KPX Yacute udieresis -110 KPX Yacute ugrave -110 KPX Yacute uhungarumlaut -110 KPX Yacute umacron -110 KPX Yacute uogonek -110 KPX Yacute uring -110 KPX Ydieresis A -110 KPX Ydieresis Aacute -110 KPX Ydieresis Abreve -110 KPX Ydieresis Acircumflex -110 KPX Ydieresis Adieresis -110 KPX Ydieresis Agrave -110 KPX Ydieresis Amacron -110 KPX Ydieresis Aogonek -110 KPX Ydieresis Aring -110 KPX Ydieresis Atilde -110 KPX Ydieresis O -85 KPX Ydieresis Oacute -85 KPX Ydieresis Ocircumflex -85 KPX Ydieresis Odieresis -85 KPX Ydieresis Ograve -85 KPX Ydieresis Ohungarumlaut -85 KPX Ydieresis Omacron -85 KPX Ydieresis Oslash -85 KPX Ydieresis Otilde -85 KPX Ydieresis a -140 KPX Ydieresis aacute -140 KPX Ydieresis abreve -70 KPX Ydieresis acircumflex -140 KPX Ydieresis adieresis -140 KPX Ydieresis agrave -140 KPX Ydieresis amacron -70 KPX Ydieresis aogonek -140 KPX Ydieresis aring -140 KPX Ydieresis atilde -70 KPX Ydieresis colon -60 KPX Ydieresis comma -140 KPX Ydieresis e -140 KPX Ydieresis eacute -140 KPX Ydieresis ecaron -140 KPX Ydieresis ecircumflex -140 KPX Ydieresis edieresis -140 KPX Ydieresis edotaccent -140 KPX Ydieresis egrave -140 KPX Ydieresis emacron -70 KPX Ydieresis eogonek -140 KPX Ydieresis hyphen -140 KPX Ydieresis i -20 KPX Ydieresis iacute -20 KPX Ydieresis iogonek -20 KPX Ydieresis o -140 KPX Ydieresis oacute -140 KPX Ydieresis ocircumflex -140 KPX Ydieresis odieresis -140 KPX Ydieresis ograve -140 KPX Ydieresis ohungarumlaut -140 KPX Ydieresis omacron -140 KPX Ydieresis oslash -140 KPX Ydieresis otilde -140 KPX Ydieresis period -140 KPX Ydieresis semicolon -60 KPX Ydieresis u -110 KPX Ydieresis uacute -110 KPX Ydieresis ucircumflex -110 KPX Ydieresis udieresis -110 KPX Ydieresis ugrave -110 KPX Ydieresis uhungarumlaut -110 KPX Ydieresis umacron -110 KPX Ydieresis uogonek -110 KPX Ydieresis uring -110 KPX a v -20 KPX a w -20 KPX a y -30 KPX a yacute -30 KPX a ydieresis -30 KPX aacute v -20 KPX aacute w -20 KPX aacute y -30 KPX aacute yacute -30 KPX aacute ydieresis -30 KPX abreve v -20 KPX abreve w -20 KPX abreve y -30 KPX abreve yacute -30 KPX abreve ydieresis -30 KPX acircumflex v -20 KPX acircumflex w -20 KPX acircumflex y -30 KPX acircumflex yacute -30 KPX acircumflex ydieresis -30 KPX adieresis v -20 KPX adieresis w -20 KPX adieresis y -30 KPX adieresis yacute -30 KPX adieresis ydieresis -30 KPX agrave v -20 KPX agrave w -20 KPX agrave y -30 KPX agrave yacute -30 KPX agrave ydieresis -30 KPX amacron v -20 KPX amacron w -20 KPX amacron y -30 KPX amacron yacute -30 KPX amacron ydieresis -30 KPX aogonek v -20 KPX aogonek w -20 KPX aogonek y -30 KPX aogonek yacute -30 KPX aogonek ydieresis -30 KPX aring v -20 KPX aring w -20 KPX aring y -30 KPX aring yacute -30 KPX aring ydieresis -30 KPX atilde v -20 KPX atilde w -20 KPX atilde y -30 KPX atilde yacute -30 KPX atilde ydieresis -30 KPX b b -10 KPX b comma -40 KPX b l -20 KPX b lacute -20 KPX b lcommaaccent -20 KPX b lslash -20 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -20 KPX b y -20 KPX b yacute -20 KPX b ydieresis -20 KPX c comma -15 KPX c k -20 KPX c kcommaaccent -20 KPX cacute comma -15 KPX cacute k -20 KPX cacute kcommaaccent -20 KPX ccaron comma -15 KPX ccaron k -20 KPX ccaron kcommaaccent -20 KPX ccedilla comma -15 KPX ccedilla k -20 KPX ccedilla kcommaaccent -20 KPX colon space -50 KPX comma quotedblright -100 KPX comma quoteright -100 KPX e comma -15 KPX e period -15 KPX e v -30 KPX e w -20 KPX e x -30 KPX e y -20 KPX e yacute -20 KPX e ydieresis -20 KPX eacute comma -15 KPX eacute period -15 KPX eacute v -30 KPX eacute w -20 KPX eacute x -30 KPX eacute y -20 KPX eacute yacute -20 KPX eacute ydieresis -20 KPX ecaron comma -15 KPX ecaron period -15 KPX ecaron v -30 KPX ecaron w -20 KPX ecaron x -30 KPX ecaron y -20 KPX ecaron yacute -20 KPX ecaron ydieresis -20 KPX ecircumflex comma -15 KPX ecircumflex period -15 KPX ecircumflex v -30 KPX ecircumflex w -20 KPX ecircumflex x -30 KPX ecircumflex y -20 KPX ecircumflex yacute -20 KPX ecircumflex ydieresis -20 KPX edieresis comma -15 KPX edieresis period -15 KPX edieresis v -30 KPX edieresis w -20 KPX edieresis x -30 KPX edieresis y -20 KPX edieresis yacute -20 KPX edieresis ydieresis -20 KPX edotaccent comma -15 KPX edotaccent period -15 KPX edotaccent v -30 KPX edotaccent w -20 KPX edotaccent x -30 KPX edotaccent y -20 KPX edotaccent yacute -20 KPX edotaccent ydieresis -20 KPX egrave comma -15 KPX egrave period -15 KPX egrave v -30 KPX egrave w -20 KPX egrave x -30 KPX egrave y -20 KPX egrave yacute -20 KPX egrave ydieresis -20 KPX emacron comma -15 KPX emacron period -15 KPX emacron v -30 KPX emacron w -20 KPX emacron x -30 KPX emacron y -20 KPX emacron yacute -20 KPX emacron ydieresis -20 KPX eogonek comma -15 KPX eogonek period -15 KPX eogonek v -30 KPX eogonek w -20 KPX eogonek x -30 KPX eogonek y -20 KPX eogonek yacute -20 KPX eogonek ydieresis -20 KPX f a -30 KPX f aacute -30 KPX f abreve -30 KPX f acircumflex -30 KPX f adieresis -30 KPX f agrave -30 KPX f amacron -30 KPX f aogonek -30 KPX f aring -30 KPX f atilde -30 KPX f comma -30 KPX f dotlessi -28 KPX f e -30 KPX f eacute -30 KPX f ecaron -30 KPX f ecircumflex -30 KPX f edieresis -30 KPX f edotaccent -30 KPX f egrave -30 KPX f emacron -30 KPX f eogonek -30 KPX f o -30 KPX f oacute -30 KPX f ocircumflex -30 KPX f odieresis -30 KPX f ograve -30 KPX f ohungarumlaut -30 KPX f omacron -30 KPX f oslash -30 KPX f otilde -30 KPX f period -30 KPX f quotedblright 60 KPX f quoteright 50 KPX g r -10 KPX g racute -10 KPX g rcaron -10 KPX g rcommaaccent -10 KPX gbreve r -10 KPX gbreve racute -10 KPX gbreve rcaron -10 KPX gbreve rcommaaccent -10 KPX gcommaaccent r -10 KPX gcommaaccent racute -10 KPX gcommaaccent rcaron -10 KPX gcommaaccent rcommaaccent -10 KPX h y -30 KPX h yacute -30 KPX h ydieresis -30 KPX k e -20 KPX k eacute -20 KPX k ecaron -20 KPX k ecircumflex -20 KPX k edieresis -20 KPX k edotaccent -20 KPX k egrave -20 KPX k emacron -20 KPX k eogonek -20 KPX k o -20 KPX k oacute -20 KPX k ocircumflex -20 KPX k odieresis -20 KPX k ograve -20 KPX k ohungarumlaut -20 KPX k omacron -20 KPX k oslash -20 KPX k otilde -20 KPX kcommaaccent e -20 KPX kcommaaccent eacute -20 KPX kcommaaccent ecaron -20 KPX kcommaaccent ecircumflex -20 KPX kcommaaccent edieresis -20 KPX kcommaaccent edotaccent -20 KPX kcommaaccent egrave -20 KPX kcommaaccent emacron -20 KPX kcommaaccent eogonek -20 KPX kcommaaccent o -20 KPX kcommaaccent oacute -20 KPX kcommaaccent ocircumflex -20 KPX kcommaaccent odieresis -20 KPX kcommaaccent ograve -20 KPX kcommaaccent ohungarumlaut -20 KPX kcommaaccent omacron -20 KPX kcommaaccent oslash -20 KPX kcommaaccent otilde -20 KPX m u -10 KPX m uacute -10 KPX m ucircumflex -10 KPX m udieresis -10 KPX m ugrave -10 KPX m uhungarumlaut -10 KPX m umacron -10 KPX m uogonek -10 KPX m uring -10 KPX m y -15 KPX m yacute -15 KPX m ydieresis -15 KPX n u -10 KPX n uacute -10 KPX n ucircumflex -10 KPX n udieresis -10 KPX n ugrave -10 KPX n uhungarumlaut -10 KPX n umacron -10 KPX n uogonek -10 KPX n uring -10 KPX n v -20 KPX n y -15 KPX n yacute -15 KPX n ydieresis -15 KPX nacute u -10 KPX nacute uacute -10 KPX nacute ucircumflex -10 KPX nacute udieresis -10 KPX nacute ugrave -10 KPX nacute uhungarumlaut -10 KPX nacute umacron -10 KPX nacute uogonek -10 KPX nacute uring -10 KPX nacute v -20 KPX nacute y -15 KPX nacute yacute -15 KPX nacute ydieresis -15 KPX ncaron u -10 KPX ncaron uacute -10 KPX ncaron ucircumflex -10 KPX ncaron udieresis -10 KPX ncaron ugrave -10 KPX ncaron uhungarumlaut -10 KPX ncaron umacron -10 KPX ncaron uogonek -10 KPX ncaron uring -10 KPX ncaron v -20 KPX ncaron y -15 KPX ncaron yacute -15 KPX ncaron ydieresis -15 KPX ncommaaccent u -10 KPX ncommaaccent uacute -10 KPX ncommaaccent ucircumflex -10 KPX ncommaaccent udieresis -10 KPX ncommaaccent ugrave -10 KPX ncommaaccent uhungarumlaut -10 KPX ncommaaccent umacron -10 KPX ncommaaccent uogonek -10 KPX ncommaaccent uring -10 KPX ncommaaccent v -20 KPX ncommaaccent y -15 KPX ncommaaccent yacute -15 KPX ncommaaccent ydieresis -15 KPX ntilde u -10 KPX ntilde uacute -10 KPX ntilde ucircumflex -10 KPX ntilde udieresis -10 KPX ntilde ugrave -10 KPX ntilde uhungarumlaut -10 KPX ntilde umacron -10 KPX ntilde uogonek -10 KPX ntilde uring -10 KPX ntilde v -20 KPX ntilde y -15 KPX ntilde yacute -15 KPX ntilde ydieresis -15 KPX o comma -40 KPX o period -40 KPX o v -15 KPX o w -15 KPX o x -30 KPX o y -30 KPX o yacute -30 KPX o ydieresis -30 KPX oacute comma -40 KPX oacute period -40 KPX oacute v -15 KPX oacute w -15 KPX oacute x -30 KPX oacute y -30 KPX oacute yacute -30 KPX oacute ydieresis -30 KPX ocircumflex comma -40 KPX ocircumflex period -40 KPX ocircumflex v -15 KPX ocircumflex w -15 KPX ocircumflex x -30 KPX ocircumflex y -30 KPX ocircumflex yacute -30 KPX ocircumflex ydieresis -30 KPX odieresis comma -40 KPX odieresis period -40 KPX odieresis v -15 KPX odieresis w -15 KPX odieresis x -30 KPX odieresis y -30 KPX odieresis yacute -30 KPX odieresis ydieresis -30 KPX ograve comma -40 KPX ograve period -40 KPX ograve v -15 KPX ograve w -15 KPX ograve x -30 KPX ograve y -30 KPX ograve yacute -30 KPX ograve ydieresis -30 KPX ohungarumlaut comma -40 KPX ohungarumlaut period -40 KPX ohungarumlaut v -15 KPX ohungarumlaut w -15 KPX ohungarumlaut x -30 KPX ohungarumlaut y -30 KPX ohungarumlaut yacute -30 KPX ohungarumlaut ydieresis -30 KPX omacron comma -40 KPX omacron period -40 KPX omacron v -15 KPX omacron w -15 KPX omacron x -30 KPX omacron y -30 KPX omacron yacute -30 KPX omacron ydieresis -30 KPX oslash a -55 KPX oslash aacute -55 KPX oslash abreve -55 KPX oslash acircumflex -55 KPX oslash adieresis -55 KPX oslash agrave -55 KPX oslash amacron -55 KPX oslash aogonek -55 KPX oslash aring -55 KPX oslash atilde -55 KPX oslash b -55 KPX oslash c -55 KPX oslash cacute -55 KPX oslash ccaron -55 KPX oslash ccedilla -55 KPX oslash comma -95 KPX oslash d -55 KPX oslash dcroat -55 KPX oslash e -55 KPX oslash eacute -55 KPX oslash ecaron -55 KPX oslash ecircumflex -55 KPX oslash edieresis -55 KPX oslash edotaccent -55 KPX oslash egrave -55 KPX oslash emacron -55 KPX oslash eogonek -55 KPX oslash f -55 KPX oslash g -55 KPX oslash gbreve -55 KPX oslash gcommaaccent -55 KPX oslash h -55 KPX oslash i -55 KPX oslash iacute -55 KPX oslash icircumflex -55 KPX oslash idieresis -55 KPX oslash igrave -55 KPX oslash imacron -55 KPX oslash iogonek -55 KPX oslash j -55 KPX oslash k -55 KPX oslash kcommaaccent -55 KPX oslash l -55 KPX oslash lacute -55 KPX oslash lcommaaccent -55 KPX oslash lslash -55 KPX oslash m -55 KPX oslash n -55 KPX oslash nacute -55 KPX oslash ncaron -55 KPX oslash ncommaaccent -55 KPX oslash ntilde -55 KPX oslash o -55 KPX oslash oacute -55 KPX oslash ocircumflex -55 KPX oslash odieresis -55 KPX oslash ograve -55 KPX oslash ohungarumlaut -55 KPX oslash omacron -55 KPX oslash oslash -55 KPX oslash otilde -55 KPX oslash p -55 KPX oslash period -95 KPX oslash q -55 KPX oslash r -55 KPX oslash racute -55 KPX oslash rcaron -55 KPX oslash rcommaaccent -55 KPX oslash s -55 KPX oslash sacute -55 KPX oslash scaron -55 KPX oslash scedilla -55 KPX oslash scommaaccent -55 KPX oslash t -55 KPX oslash tcommaaccent -55 KPX oslash u -55 KPX oslash uacute -55 KPX oslash ucircumflex -55 KPX oslash udieresis -55 KPX oslash ugrave -55 KPX oslash uhungarumlaut -55 KPX oslash umacron -55 KPX oslash uogonek -55 KPX oslash uring -55 KPX oslash v -70 KPX oslash w -70 KPX oslash x -85 KPX oslash y -70 KPX oslash yacute -70 KPX oslash ydieresis -70 KPX oslash z -55 KPX oslash zacute -55 KPX oslash zcaron -55 KPX oslash zdotaccent -55 KPX otilde comma -40 KPX otilde period -40 KPX otilde v -15 KPX otilde w -15 KPX otilde x -30 KPX otilde y -30 KPX otilde yacute -30 KPX otilde ydieresis -30 KPX p comma -35 KPX p period -35 KPX p y -30 KPX p yacute -30 KPX p ydieresis -30 KPX period quotedblright -100 KPX period quoteright -100 KPX period space -60 KPX quotedblright space -40 KPX quoteleft quoteleft -57 KPX quoteright d -50 KPX quoteright dcroat -50 KPX quoteright quoteright -57 KPX quoteright r -50 KPX quoteright racute -50 KPX quoteright rcaron -50 KPX quoteright rcommaaccent -50 KPX quoteright s -50 KPX quoteright sacute -50 KPX quoteright scaron -50 KPX quoteright scedilla -50 KPX quoteright scommaaccent -50 KPX quoteright space -70 KPX r a -10 KPX r aacute -10 KPX r abreve -10 KPX r acircumflex -10 KPX r adieresis -10 KPX r agrave -10 KPX r amacron -10 KPX r aogonek -10 KPX r aring -10 KPX r atilde -10 KPX r colon 30 KPX r comma -50 KPX r i 15 KPX r iacute 15 KPX r icircumflex 15 KPX r idieresis 15 KPX r igrave 15 KPX r imacron 15 KPX r iogonek 15 KPX r k 15 KPX r kcommaaccent 15 KPX r l 15 KPX r lacute 15 KPX r lcommaaccent 15 KPX r lslash 15 KPX r m 25 KPX r n 25 KPX r nacute 25 KPX r ncaron 25 KPX r ncommaaccent 25 KPX r ntilde 25 KPX r p 30 KPX r period -50 KPX r semicolon 30 KPX r t 40 KPX r tcommaaccent 40 KPX r u 15 KPX r uacute 15 KPX r ucircumflex 15 KPX r udieresis 15 KPX r ugrave 15 KPX r uhungarumlaut 15 KPX r umacron 15 KPX r uogonek 15 KPX r uring 15 KPX r v 30 KPX r y 30 KPX r yacute 30 KPX r ydieresis 30 KPX racute a -10 KPX racute aacute -10 KPX racute abreve -10 KPX racute acircumflex -10 KPX racute adieresis -10 KPX racute agrave -10 KPX racute amacron -10 KPX racute aogonek -10 KPX racute aring -10 KPX racute atilde -10 KPX racute colon 30 KPX racute comma -50 KPX racute i 15 KPX racute iacute 15 KPX racute icircumflex 15 KPX racute idieresis 15 KPX racute igrave 15 KPX racute imacron 15 KPX racute iogonek 15 KPX racute k 15 KPX racute kcommaaccent 15 KPX racute l 15 KPX racute lacute 15 KPX racute lcommaaccent 15 KPX racute lslash 15 KPX racute m 25 KPX racute n 25 KPX racute nacute 25 KPX racute ncaron 25 KPX racute ncommaaccent 25 KPX racute ntilde 25 KPX racute p 30 KPX racute period -50 KPX racute semicolon 30 KPX racute t 40 KPX racute tcommaaccent 40 KPX racute u 15 KPX racute uacute 15 KPX racute ucircumflex 15 KPX racute udieresis 15 KPX racute ugrave 15 KPX racute uhungarumlaut 15 KPX racute umacron 15 KPX racute uogonek 15 KPX racute uring 15 KPX racute v 30 KPX racute y 30 KPX racute yacute 30 KPX racute ydieresis 30 KPX rcaron a -10 KPX rcaron aacute -10 KPX rcaron abreve -10 KPX rcaron acircumflex -10 KPX rcaron adieresis -10 KPX rcaron agrave -10 KPX rcaron amacron -10 KPX rcaron aogonek -10 KPX rcaron aring -10 KPX rcaron atilde -10 KPX rcaron colon 30 KPX rcaron comma -50 KPX rcaron i 15 KPX rcaron iacute 15 KPX rcaron icircumflex 15 KPX rcaron idieresis 15 KPX rcaron igrave 15 KPX rcaron imacron 15 KPX rcaron iogonek 15 KPX rcaron k 15 KPX rcaron kcommaaccent 15 KPX rcaron l 15 KPX rcaron lacute 15 KPX rcaron lcommaaccent 15 KPX rcaron lslash 15 KPX rcaron m 25 KPX rcaron n 25 KPX rcaron nacute 25 KPX rcaron ncaron 25 KPX rcaron ncommaaccent 25 KPX rcaron ntilde 25 KPX rcaron p 30 KPX rcaron period -50 KPX rcaron semicolon 30 KPX rcaron t 40 KPX rcaron tcommaaccent 40 KPX rcaron u 15 KPX rcaron uacute 15 KPX rcaron ucircumflex 15 KPX rcaron udieresis 15 KPX rcaron ugrave 15 KPX rcaron uhungarumlaut 15 KPX rcaron umacron 15 KPX rcaron uogonek 15 KPX rcaron uring 15 KPX rcaron v 30 KPX rcaron y 30 KPX rcaron yacute 30 KPX rcaron ydieresis 30 KPX rcommaaccent a -10 KPX rcommaaccent aacute -10 KPX rcommaaccent abreve -10 KPX rcommaaccent acircumflex -10 KPX rcommaaccent adieresis -10 KPX rcommaaccent agrave -10 KPX rcommaaccent amacron -10 KPX rcommaaccent aogonek -10 KPX rcommaaccent aring -10 KPX rcommaaccent atilde -10 KPX rcommaaccent colon 30 KPX rcommaaccent comma -50 KPX rcommaaccent i 15 KPX rcommaaccent iacute 15 KPX rcommaaccent icircumflex 15 KPX rcommaaccent idieresis 15 KPX rcommaaccent igrave 15 KPX rcommaaccent imacron 15 KPX rcommaaccent iogonek 15 KPX rcommaaccent k 15 KPX rcommaaccent kcommaaccent 15 KPX rcommaaccent l 15 KPX rcommaaccent lacute 15 KPX rcommaaccent lcommaaccent 15 KPX rcommaaccent lslash 15 KPX rcommaaccent m 25 KPX rcommaaccent n 25 KPX rcommaaccent nacute 25 KPX rcommaaccent ncaron 25 KPX rcommaaccent ncommaaccent 25 KPX rcommaaccent ntilde 25 KPX rcommaaccent p 30 KPX rcommaaccent period -50 KPX rcommaaccent semicolon 30 KPX rcommaaccent t 40 KPX rcommaaccent tcommaaccent 40 KPX rcommaaccent u 15 KPX rcommaaccent uacute 15 KPX rcommaaccent ucircumflex 15 KPX rcommaaccent udieresis 15 KPX rcommaaccent ugrave 15 KPX rcommaaccent uhungarumlaut 15 KPX rcommaaccent umacron 15 KPX rcommaaccent uogonek 15 KPX rcommaaccent uring 15 KPX rcommaaccent v 30 KPX rcommaaccent y 30 KPX rcommaaccent yacute 30 KPX rcommaaccent ydieresis 30 KPX s comma -15 KPX s period -15 KPX s w -30 KPX sacute comma -15 KPX sacute period -15 KPX sacute w -30 KPX scaron comma -15 KPX scaron period -15 KPX scaron w -30 KPX scedilla comma -15 KPX scedilla period -15 KPX scedilla w -30 KPX scommaaccent comma -15 KPX scommaaccent period -15 KPX scommaaccent w -30 KPX semicolon space -50 KPX space T -50 KPX space Tcaron -50 KPX space Tcommaaccent -50 KPX space V -50 KPX space W -40 KPX space Y -90 KPX space Yacute -90 KPX space Ydieresis -90 KPX space quotedblleft -30 KPX space quoteleft -60 KPX v a -25 KPX v aacute -25 KPX v abreve -25 KPX v acircumflex -25 KPX v adieresis -25 KPX v agrave -25 KPX v amacron -25 KPX v aogonek -25 KPX v aring -25 KPX v atilde -25 KPX v comma -80 KPX v e -25 KPX v eacute -25 KPX v ecaron -25 KPX v ecircumflex -25 KPX v edieresis -25 KPX v edotaccent -25 KPX v egrave -25 KPX v emacron -25 KPX v eogonek -25 KPX v o -25 KPX v oacute -25 KPX v ocircumflex -25 KPX v odieresis -25 KPX v ograve -25 KPX v ohungarumlaut -25 KPX v omacron -25 KPX v oslash -25 KPX v otilde -25 KPX v period -80 KPX w a -15 KPX w aacute -15 KPX w abreve -15 KPX w acircumflex -15 KPX w adieresis -15 KPX w agrave -15 KPX w amacron -15 KPX w aogonek -15 KPX w aring -15 KPX w atilde -15 KPX w comma -60 KPX w e -10 KPX w eacute -10 KPX w ecaron -10 KPX w ecircumflex -10 KPX w edieresis -10 KPX w edotaccent -10 KPX w egrave -10 KPX w emacron -10 KPX w eogonek -10 KPX w o -10 KPX w oacute -10 KPX w ocircumflex -10 KPX w odieresis -10 KPX w ograve -10 KPX w ohungarumlaut -10 KPX w omacron -10 KPX w oslash -10 KPX w otilde -10 KPX w period -60 KPX x e -30 KPX x eacute -30 KPX x ecaron -30 KPX x ecircumflex -30 KPX x edieresis -30 KPX x edotaccent -30 KPX x egrave -30 KPX x emacron -30 KPX x eogonek -30 KPX y a -20 KPX y aacute -20 KPX y abreve -20 KPX y acircumflex -20 KPX y adieresis -20 KPX y agrave -20 KPX y amacron -20 KPX y aogonek -20 KPX y aring -20 KPX y atilde -20 KPX y comma -100 KPX y e -20 KPX y eacute -20 KPX y ecaron -20 KPX y ecircumflex -20 KPX y edieresis -20 KPX y edotaccent -20 KPX y egrave -20 KPX y emacron -20 KPX y eogonek -20 KPX y o -20 KPX y oacute -20 KPX y ocircumflex -20 KPX y odieresis -20 KPX y ograve -20 KPX y ohungarumlaut -20 KPX y omacron -20 KPX y oslash -20 KPX y otilde -20 KPX y period -100 KPX yacute a -20 KPX yacute aacute -20 KPX yacute abreve -20 KPX yacute acircumflex -20 KPX yacute adieresis -20 KPX yacute agrave -20 KPX yacute amacron -20 KPX yacute aogonek -20 KPX yacute aring -20 KPX yacute atilde -20 KPX yacute comma -100 KPX yacute e -20 KPX yacute eacute -20 KPX yacute ecaron -20 KPX yacute ecircumflex -20 KPX yacute edieresis -20 KPX yacute edotaccent -20 KPX yacute egrave -20 KPX yacute emacron -20 KPX yacute eogonek -20 KPX yacute o -20 KPX yacute oacute -20 KPX yacute ocircumflex -20 KPX yacute odieresis -20 KPX yacute ograve -20 KPX yacute ohungarumlaut -20 KPX yacute omacron -20 KPX yacute oslash -20 KPX yacute otilde -20 KPX yacute period -100 KPX ydieresis a -20 KPX ydieresis aacute -20 KPX ydieresis abreve -20 KPX ydieresis acircumflex -20 KPX ydieresis adieresis -20 KPX ydieresis agrave -20 KPX ydieresis amacron -20 KPX ydieresis aogonek -20 KPX ydieresis aring -20 KPX ydieresis atilde -20 KPX ydieresis comma -100 KPX ydieresis e -20 KPX ydieresis eacute -20 KPX ydieresis ecaron -20 KPX ydieresis ecircumflex -20 KPX ydieresis edieresis -20 KPX ydieresis edotaccent -20 KPX ydieresis egrave -20 KPX ydieresis emacron -20 KPX ydieresis eogonek -20 KPX ydieresis o -20 KPX ydieresis oacute -20 KPX ydieresis ocircumflex -20 KPX ydieresis odieresis -20 KPX ydieresis ograve -20 KPX ydieresis ohungarumlaut -20 KPX ydieresis omacron -20 KPX ydieresis oslash -20 KPX ydieresis otilde -20 KPX ydieresis period -100 KPX z e -15 KPX z eacute -15 KPX z ecaron -15 KPX z ecircumflex -15 KPX z edieresis -15 KPX z edotaccent -15 KPX z egrave -15 KPX z emacron -15 KPX z eogonek -15 KPX z o -15 KPX z oacute -15 KPX z ocircumflex -15 KPX z odieresis -15 KPX z ograve -15 KPX z ohungarumlaut -15 KPX z omacron -15 KPX z oslash -15 KPX z otilde -15 KPX zacute e -15 KPX zacute eacute -15 KPX zacute ecaron -15 KPX zacute ecircumflex -15 KPX zacute edieresis -15 KPX zacute edotaccent -15 KPX zacute egrave -15 KPX zacute emacron -15 KPX zacute eogonek -15 KPX zacute o -15 KPX zacute oacute -15 KPX zacute ocircumflex -15 KPX zacute odieresis -15 KPX zacute ograve -15 KPX zacute ohungarumlaut -15 KPX zacute omacron -15 KPX zacute oslash -15 KPX zacute otilde -15 KPX zcaron e -15 KPX zcaron eacute -15 KPX zcaron ecaron -15 KPX zcaron ecircumflex -15 KPX zcaron edieresis -15 KPX zcaron edotaccent -15 KPX zcaron egrave -15 KPX zcaron emacron -15 KPX zcaron eogonek -15 KPX zcaron o -15 KPX zcaron oacute -15 KPX zcaron ocircumflex -15 KPX zcaron odieresis -15 KPX zcaron ograve -15 KPX zcaron ohungarumlaut -15 KPX zcaron omacron -15 KPX zcaron oslash -15 KPX zcaron otilde -15 KPX zdotaccent e -15 KPX zdotaccent eacute -15 KPX zdotaccent ecaron -15 KPX zdotaccent ecircumflex -15 KPX zdotaccent edieresis -15 KPX zdotaccent edotaccent -15 KPX zdotaccent egrave -15 KPX zdotaccent emacron -15 KPX zdotaccent eogonek -15 KPX zdotaccent o -15 KPX zdotaccent oacute -15 KPX zdotaccent ocircumflex -15 KPX zdotaccent odieresis -15 KPX zdotaccent ograve -15 KPX zdotaccent ohungarumlaut -15 KPX zdotaccent omacron -15 KPX zdotaccent oslash -15 KPX zdotaccent otilde -15 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/MustRead.html0000644000076500000240000000165112037547555017457 0ustar andrestaff00000000000000 Core 14 AFM Files - ReadMe or
This file and the 14 PostScript(R) AFM files it accompanies may be used, copied, and distributed for any purpose and without charge, with or without modification, provided that all copyright notices are retained; that the AFM files are not distributed without this file; that all modifications to this file or any of the AFM files are prominently noted in the modified file(s); and that this paragraph is not modified. Adobe Systems has no responsibility or obligation to support the use of the AFM files. Col
PyX-0.14.1/pyx/data/afm/Symbol.afm0000644000076500000240000002334112037547555016777 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved. Comment Creation Date: Thu May 1 15:12:25 1997 Comment UniqueID 43064 Comment VMusage 30820 39997 FontName Symbol FullName Symbol FamilyName Symbol Weight Medium ItalicAngle 0 IsFixedPitch false CharacterSet Special FontBBox -180 -293 1090 1010 UnderlinePosition -100 UnderlineThickness 50 Version 001.008 Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved. EncodingScheme FontSpecific StdHW 92 StdVW 85 StartCharMetrics 190 C 32 ; WX 250 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ; C 34 ; WX 713 ; N universal ; B 31 0 681 705 ; C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ; C 36 ; WX 549 ; N existential ; B 25 0 478 707 ; C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ; C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ; C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ; C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ; C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ; C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ; C 43 ; WX 549 ; N plus ; B 10 0 539 533 ; C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ; C 45 ; WX 549 ; N minus ; B 11 233 535 288 ; C 46 ; WX 250 ; N period ; B 69 -17 181 95 ; C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ; C 48 ; WX 500 ; N zero ; B 24 -14 476 685 ; C 49 ; WX 500 ; N one ; B 117 0 390 673 ; C 50 ; WX 500 ; N two ; B 25 0 475 685 ; C 51 ; WX 500 ; N three ; B 43 -14 435 685 ; C 52 ; WX 500 ; N four ; B 15 0 469 685 ; C 53 ; WX 500 ; N five ; B 32 -14 445 690 ; C 54 ; WX 500 ; N six ; B 34 -14 468 685 ; C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ; C 56 ; WX 500 ; N eight ; B 56 -14 445 685 ; C 57 ; WX 500 ; N nine ; B 30 -18 459 685 ; C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ; C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ; C 60 ; WX 549 ; N less ; B 26 0 523 522 ; C 61 ; WX 549 ; N equal ; B 11 141 537 390 ; C 62 ; WX 549 ; N greater ; B 26 0 523 522 ; C 63 ; WX 444 ; N question ; B 70 -17 412 686 ; C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ; C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ; C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ; C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ; C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ; C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ; C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ; C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ; C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ; C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ; C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ; C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ; C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ; C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ; C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ; C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ; C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ; C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ; C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ; C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ; C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ; C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ; C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ; C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ; C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ; C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ; C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ; C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ; C 92 ; WX 863 ; N therefore ; B 163 0 701 487 ; C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ; C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ; C 95 ; WX 500 ; N underscore ; B -2 -125 502 -75 ; C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ; C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ; C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ; C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ; C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ; C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ; C 102 ; WX 521 ; N phi ; B 28 -224 492 673 ; C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ; C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ; C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ; C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ; C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ; C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ; C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ; C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ; C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ; C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ; C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ; C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ; C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ; C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ; C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ; C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ; C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ; C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ; C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ; C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ; C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ; C 124 ; WX 200 ; N bar ; B 65 -293 135 707 ; C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ; C 126 ; WX 549 ; N similar ; B 17 203 529 307 ; C 160 ; WX 750 ; N Euro ; B 20 -12 714 685 ; C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ; C 162 ; WX 247 ; N minute ; B 27 459 228 735 ; C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ; C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ; C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ; C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ; C 167 ; WX 753 ; N club ; B 86 -26 660 533 ; C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ; C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ; C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ; C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ; C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ; C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ; C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ; C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ; C 176 ; WX 400 ; N degree ; B 50 385 350 685 ; C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ; C 178 ; WX 411 ; N second ; B 20 459 413 737 ; C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ; C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ; C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ; C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ; C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ; C 184 ; WX 549 ; N divide ; B 10 71 536 456 ; C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ; C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ; C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ; C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ; C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ; C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ; C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ; C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ; C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ; C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ; C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ; C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ; C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ; C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ; C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ; C 200 ; WX 768 ; N union ; B 40 -17 732 492 ; C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ; C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ; C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ; C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ; C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ; C 206 ; WX 713 ; N element ; B 45 0 505 468 ; C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ; C 208 ; WX 768 ; N angle ; B 26 0 738 673 ; C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ; C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ; C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ; C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ; C 213 ; WX 823 ; N product ; B 25 -101 803 751 ; C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ; C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ; C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ; C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ; C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ; C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ; C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ; C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ; C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ; C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ; C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ; C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ; C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ; C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ; C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ; C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ; C 230 ; WX 384 ; N parenlefttp ; B 24 -293 436 926 ; C 231 ; WX 384 ; N parenleftex ; B 24 -85 108 925 ; C 232 ; WX 384 ; N parenleftbt ; B 24 -293 436 926 ; C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 349 926 ; C 234 ; WX 384 ; N bracketleftex ; B 0 -79 77 925 ; C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 349 926 ; C 236 ; WX 494 ; N bracelefttp ; B 209 -85 445 925 ; C 237 ; WX 494 ; N braceleftmid ; B 20 -85 284 935 ; C 238 ; WX 494 ; N braceleftbt ; B 209 -75 445 935 ; C 239 ; WX 494 ; N braceex ; B 209 -85 284 935 ; C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ; C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ; C 243 ; WX 686 ; N integraltp ; B 308 -88 675 920 ; C 244 ; WX 686 ; N integralex ; B 308 -88 378 975 ; C 245 ; WX 686 ; N integralbt ; B 11 -87 378 921 ; C 246 ; WX 384 ; N parenrighttp ; B 54 -293 466 926 ; C 247 ; WX 384 ; N parenrightex ; B 382 -85 466 925 ; C 248 ; WX 384 ; N parenrightbt ; B 54 -293 466 926 ; C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 371 926 ; C 250 ; WX 384 ; N bracketrightex ; B 294 -79 371 925 ; C 251 ; WX 384 ; N bracketrightbt ; B 22 -80 371 926 ; C 252 ; WX 494 ; N bracerighttp ; B 48 -85 284 925 ; C 253 ; WX 494 ; N bracerightmid ; B 209 -85 473 935 ; C 254 ; WX 494 ; N bracerightbt ; B 48 -75 284 935 ; C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/afm/Times-Bold.afm0000644000076500000240000020242712037547555017475 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:52:56 1997 Comment UniqueID 43065 Comment VMusage 41636 52661 FontName Times-Bold FullName Times Bold FamilyName Times Weight Bold ItalicAngle 0 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -168 -218 1000 935 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 676 XHeight 461 Ascender 683 Descender -217 StdHW 44 StdVW 139 StartCharMetrics 315 C 32 ; WX 250 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 81 -13 251 691 ; C 34 ; WX 555 ; N quotedbl ; B 83 404 472 691 ; C 35 ; WX 500 ; N numbersign ; B 4 0 496 700 ; C 36 ; WX 500 ; N dollar ; B 29 -99 472 750 ; C 37 ; WX 1000 ; N percent ; B 124 -14 877 692 ; C 38 ; WX 833 ; N ampersand ; B 62 -16 787 691 ; C 39 ; WX 333 ; N quoteright ; B 79 356 263 691 ; C 40 ; WX 333 ; N parenleft ; B 46 -168 306 694 ; C 41 ; WX 333 ; N parenright ; B 27 -168 287 694 ; C 42 ; WX 500 ; N asterisk ; B 56 255 447 691 ; C 43 ; WX 570 ; N plus ; B 33 0 537 506 ; C 44 ; WX 250 ; N comma ; B 39 -180 223 155 ; C 45 ; WX 333 ; N hyphen ; B 44 171 287 287 ; C 46 ; WX 250 ; N period ; B 41 -13 210 156 ; C 47 ; WX 278 ; N slash ; B -24 -19 302 691 ; C 48 ; WX 500 ; N zero ; B 24 -13 476 688 ; C 49 ; WX 500 ; N one ; B 65 0 442 688 ; C 50 ; WX 500 ; N two ; B 17 0 478 688 ; C 51 ; WX 500 ; N three ; B 16 -14 468 688 ; C 52 ; WX 500 ; N four ; B 19 0 475 688 ; C 53 ; WX 500 ; N five ; B 22 -8 470 676 ; C 54 ; WX 500 ; N six ; B 28 -13 475 688 ; C 55 ; WX 500 ; N seven ; B 17 0 477 676 ; C 56 ; WX 500 ; N eight ; B 28 -13 472 688 ; C 57 ; WX 500 ; N nine ; B 26 -13 473 688 ; C 58 ; WX 333 ; N colon ; B 82 -13 251 472 ; C 59 ; WX 333 ; N semicolon ; B 82 -180 266 472 ; C 60 ; WX 570 ; N less ; B 31 -8 539 514 ; C 61 ; WX 570 ; N equal ; B 33 107 537 399 ; C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ; C 63 ; WX 500 ; N question ; B 57 -13 445 689 ; C 64 ; WX 930 ; N at ; B 108 -19 822 691 ; C 65 ; WX 722 ; N A ; B 9 0 689 690 ; C 66 ; WX 667 ; N B ; B 16 0 619 676 ; C 67 ; WX 722 ; N C ; B 49 -19 687 691 ; C 68 ; WX 722 ; N D ; B 14 0 690 676 ; C 69 ; WX 667 ; N E ; B 16 0 641 676 ; C 70 ; WX 611 ; N F ; B 16 0 583 676 ; C 71 ; WX 778 ; N G ; B 37 -19 755 691 ; C 72 ; WX 778 ; N H ; B 21 0 759 676 ; C 73 ; WX 389 ; N I ; B 20 0 370 676 ; C 74 ; WX 500 ; N J ; B 3 -96 479 676 ; C 75 ; WX 778 ; N K ; B 30 0 769 676 ; C 76 ; WX 667 ; N L ; B 19 0 638 676 ; C 77 ; WX 944 ; N M ; B 14 0 921 676 ; C 78 ; WX 722 ; N N ; B 16 -18 701 676 ; C 79 ; WX 778 ; N O ; B 35 -19 743 691 ; C 80 ; WX 611 ; N P ; B 16 0 600 676 ; C 81 ; WX 778 ; N Q ; B 35 -176 743 691 ; C 82 ; WX 722 ; N R ; B 26 0 715 676 ; C 83 ; WX 556 ; N S ; B 35 -19 513 692 ; C 84 ; WX 667 ; N T ; B 31 0 636 676 ; C 85 ; WX 722 ; N U ; B 16 -19 701 676 ; C 86 ; WX 722 ; N V ; B 16 -18 701 676 ; C 87 ; WX 1000 ; N W ; B 19 -15 981 676 ; C 88 ; WX 722 ; N X ; B 16 0 699 676 ; C 89 ; WX 722 ; N Y ; B 15 0 699 676 ; C 90 ; WX 667 ; N Z ; B 28 0 634 676 ; C 91 ; WX 333 ; N bracketleft ; B 67 -149 301 678 ; C 92 ; WX 278 ; N backslash ; B -25 -19 303 691 ; C 93 ; WX 333 ; N bracketright ; B 32 -149 266 678 ; C 94 ; WX 581 ; N asciicircum ; B 73 311 509 676 ; C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; C 96 ; WX 333 ; N quoteleft ; B 70 356 254 691 ; C 97 ; WX 500 ; N a ; B 25 -14 488 473 ; C 98 ; WX 556 ; N b ; B 17 -14 521 676 ; C 99 ; WX 444 ; N c ; B 25 -14 430 473 ; C 100 ; WX 556 ; N d ; B 25 -14 534 676 ; C 101 ; WX 444 ; N e ; B 25 -14 426 473 ; C 102 ; WX 333 ; N f ; B 14 0 389 691 ; L i fi ; L l fl ; C 103 ; WX 500 ; N g ; B 28 -206 483 473 ; C 104 ; WX 556 ; N h ; B 16 0 534 676 ; C 105 ; WX 278 ; N i ; B 16 0 255 691 ; C 106 ; WX 333 ; N j ; B -57 -203 263 691 ; C 107 ; WX 556 ; N k ; B 22 0 543 676 ; C 108 ; WX 278 ; N l ; B 16 0 255 676 ; C 109 ; WX 833 ; N m ; B 16 0 814 473 ; C 110 ; WX 556 ; N n ; B 21 0 539 473 ; C 111 ; WX 500 ; N o ; B 25 -14 476 473 ; C 112 ; WX 556 ; N p ; B 19 -205 524 473 ; C 113 ; WX 556 ; N q ; B 34 -205 536 473 ; C 114 ; WX 444 ; N r ; B 29 0 434 473 ; C 115 ; WX 389 ; N s ; B 25 -14 361 473 ; C 116 ; WX 333 ; N t ; B 20 -12 332 630 ; C 117 ; WX 556 ; N u ; B 16 -14 537 461 ; C 118 ; WX 500 ; N v ; B 21 -14 485 461 ; C 119 ; WX 722 ; N w ; B 23 -14 707 461 ; C 120 ; WX 500 ; N x ; B 12 0 484 461 ; C 121 ; WX 500 ; N y ; B 16 -205 480 461 ; C 122 ; WX 444 ; N z ; B 21 0 420 461 ; C 123 ; WX 394 ; N braceleft ; B 22 -175 340 698 ; C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ; C 125 ; WX 394 ; N braceright ; B 54 -175 372 698 ; C 126 ; WX 520 ; N asciitilde ; B 29 173 491 333 ; C 161 ; WX 333 ; N exclamdown ; B 82 -203 252 501 ; C 162 ; WX 500 ; N cent ; B 53 -140 458 588 ; C 163 ; WX 500 ; N sterling ; B 21 -14 477 684 ; C 164 ; WX 167 ; N fraction ; B -168 -12 329 688 ; C 165 ; WX 500 ; N yen ; B -64 0 547 676 ; C 166 ; WX 500 ; N florin ; B 0 -155 498 706 ; C 167 ; WX 500 ; N section ; B 57 -132 443 691 ; C 168 ; WX 500 ; N currency ; B -26 61 526 613 ; C 169 ; WX 278 ; N quotesingle ; B 75 404 204 691 ; C 170 ; WX 500 ; N quotedblleft ; B 32 356 486 691 ; C 171 ; WX 500 ; N guillemotleft ; B 23 36 473 415 ; C 172 ; WX 333 ; N guilsinglleft ; B 51 36 305 415 ; C 173 ; WX 333 ; N guilsinglright ; B 28 36 282 415 ; C 174 ; WX 556 ; N fi ; B 14 0 536 691 ; C 175 ; WX 556 ; N fl ; B 14 0 536 691 ; C 177 ; WX 500 ; N endash ; B 0 181 500 271 ; C 178 ; WX 500 ; N dagger ; B 47 -134 453 691 ; C 179 ; WX 500 ; N daggerdbl ; B 45 -132 456 691 ; C 180 ; WX 250 ; N periodcentered ; B 41 248 210 417 ; C 182 ; WX 540 ; N paragraph ; B 0 -186 519 676 ; C 183 ; WX 350 ; N bullet ; B 35 198 315 478 ; C 184 ; WX 333 ; N quotesinglbase ; B 79 -180 263 155 ; C 185 ; WX 500 ; N quotedblbase ; B 14 -180 468 155 ; C 186 ; WX 500 ; N quotedblright ; B 14 356 468 691 ; C 187 ; WX 500 ; N guillemotright ; B 27 36 477 415 ; C 188 ; WX 1000 ; N ellipsis ; B 82 -13 917 156 ; C 189 ; WX 1000 ; N perthousand ; B 7 -29 995 706 ; C 191 ; WX 500 ; N questiondown ; B 55 -201 443 501 ; C 193 ; WX 333 ; N grave ; B 8 528 246 713 ; C 194 ; WX 333 ; N acute ; B 86 528 324 713 ; C 195 ; WX 333 ; N circumflex ; B -2 528 335 704 ; C 196 ; WX 333 ; N tilde ; B -16 547 349 674 ; C 197 ; WX 333 ; N macron ; B 1 565 331 637 ; C 198 ; WX 333 ; N breve ; B 15 528 318 691 ; C 199 ; WX 333 ; N dotaccent ; B 103 536 258 691 ; C 200 ; WX 333 ; N dieresis ; B -2 537 335 667 ; C 202 ; WX 333 ; N ring ; B 60 527 273 740 ; C 203 ; WX 333 ; N cedilla ; B 68 -218 294 0 ; C 205 ; WX 333 ; N hungarumlaut ; B -13 528 425 713 ; C 206 ; WX 333 ; N ogonek ; B 90 -193 319 24 ; C 207 ; WX 333 ; N caron ; B -2 528 335 704 ; C 208 ; WX 1000 ; N emdash ; B 0 181 1000 271 ; C 225 ; WX 1000 ; N AE ; B 4 0 951 676 ; C 227 ; WX 300 ; N ordfeminine ; B -1 397 301 688 ; C 232 ; WX 667 ; N Lslash ; B 19 0 638 676 ; C 233 ; WX 778 ; N Oslash ; B 35 -74 743 737 ; C 234 ; WX 1000 ; N OE ; B 22 -5 981 684 ; C 235 ; WX 330 ; N ordmasculine ; B 18 397 312 688 ; C 241 ; WX 722 ; N ae ; B 33 -14 693 473 ; C 245 ; WX 278 ; N dotlessi ; B 16 0 255 461 ; C 248 ; WX 278 ; N lslash ; B -22 0 303 676 ; C 249 ; WX 500 ; N oslash ; B 25 -92 476 549 ; C 250 ; WX 722 ; N oe ; B 22 -14 696 473 ; C 251 ; WX 556 ; N germandbls ; B 19 -12 517 691 ; C -1 ; WX 389 ; N Idieresis ; B 20 0 370 877 ; C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ; C -1 ; WX 500 ; N abreve ; B 25 -14 488 691 ; C -1 ; WX 556 ; N uhungarumlaut ; B 16 -14 557 713 ; C -1 ; WX 444 ; N ecaron ; B 25 -14 426 704 ; C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ; C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ; C -1 ; WX 722 ; N Yacute ; B 15 0 699 923 ; C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ; C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ; C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ; C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ; C -1 ; WX 389 ; N scommaaccent ; B 25 -218 361 473 ; C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ; C -1 ; WX 722 ; N Uring ; B 16 -19 701 935 ; C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ; C -1 ; WX 500 ; N aogonek ; B 25 -193 504 473 ; C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ; C -1 ; WX 556 ; N uogonek ; B 16 -193 539 461 ; C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ; C -1 ; WX 722 ; N Dcroat ; B 6 0 690 676 ; C -1 ; WX 250 ; N commaaccent ; B 47 -218 203 -50 ; C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ; C -1 ; WX 667 ; N Emacron ; B 16 0 641 847 ; C -1 ; WX 444 ; N ccaron ; B 25 -14 430 704 ; C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ; C -1 ; WX 722 ; N Ncommaaccent ; B 16 -188 701 676 ; C -1 ; WX 278 ; N lacute ; B 16 0 297 923 ; C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ; C -1 ; WX 667 ; N Tcommaaccent ; B 31 -218 636 676 ; C -1 ; WX 722 ; N Cacute ; B 49 -19 687 923 ; C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ; C -1 ; WX 667 ; N Edotaccent ; B 16 0 641 901 ; C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ; C -1 ; WX 389 ; N scedilla ; B 25 -218 361 473 ; C -1 ; WX 278 ; N iacute ; B 16 0 289 713 ; C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ; C -1 ; WX 722 ; N Rcaron ; B 26 0 715 914 ; C -1 ; WX 778 ; N Gcommaaccent ; B 37 -218 755 691 ; C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ; C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ; C -1 ; WX 722 ; N Amacron ; B 9 0 689 847 ; C -1 ; WX 444 ; N rcaron ; B 29 0 434 704 ; C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ; C -1 ; WX 667 ; N Zdotaccent ; B 28 0 634 901 ; C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ; C -1 ; WX 778 ; N Omacron ; B 35 -19 743 847 ; C -1 ; WX 722 ; N Racute ; B 26 0 715 923 ; C -1 ; WX 556 ; N Sacute ; B 35 -19 513 923 ; C -1 ; WX 672 ; N dcaron ; B 25 -14 681 682 ; C -1 ; WX 722 ; N Umacron ; B 16 -19 701 847 ; C -1 ; WX 556 ; N uring ; B 16 -14 537 740 ; C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ; C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ; C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ; C -1 ; WX 722 ; N Abreve ; B 9 0 689 901 ; C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ; C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ; C -1 ; WX 667 ; N Tcaron ; B 31 0 636 914 ; C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ; C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ; C -1 ; WX 722 ; N Nacute ; B 16 -18 701 923 ; C -1 ; WX 278 ; N icircumflex ; B -37 0 300 704 ; C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ; C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ; C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ; C -1 ; WX 444 ; N cacute ; B 25 -14 430 713 ; C -1 ; WX 556 ; N nacute ; B 21 0 539 713 ; C -1 ; WX 556 ; N umacron ; B 16 -14 537 637 ; C -1 ; WX 722 ; N Ncaron ; B 16 -18 701 914 ; C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ; C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ; C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ; C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ; C -1 ; WX 778 ; N Gbreve ; B 37 -19 755 901 ; C -1 ; WX 389 ; N Idotaccent ; B 20 0 370 901 ; C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ; C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ; C -1 ; WX 444 ; N racute ; B 29 0 434 713 ; C -1 ; WX 500 ; N omacron ; B 25 -14 476 637 ; C -1 ; WX 667 ; N Zacute ; B 28 0 634 923 ; C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ; C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ; C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ; C -1 ; WX 278 ; N lcommaaccent ; B 16 -218 255 676 ; C -1 ; WX 416 ; N tcaron ; B 20 -12 425 815 ; C -1 ; WX 444 ; N eogonek ; B 25 -193 426 473 ; C -1 ; WX 722 ; N Uogonek ; B 16 -193 701 676 ; C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ; C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ; C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ; C -1 ; WX 444 ; N zacute ; B 21 0 420 713 ; C -1 ; WX 278 ; N iogonek ; B 16 -193 274 691 ; C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ; C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ; C -1 ; WX 500 ; N amacron ; B 25 -14 488 637 ; C -1 ; WX 389 ; N sacute ; B 25 -14 361 713 ; C -1 ; WX 278 ; N idieresis ; B -37 0 300 667 ; C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ; C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ; C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ; C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ; C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ; C -1 ; WX 278 ; N igrave ; B -27 0 255 713 ; C -1 ; WX 500 ; N ohungarumlaut ; B 25 -14 529 713 ; C -1 ; WX 667 ; N Eogonek ; B 16 -193 644 676 ; C -1 ; WX 556 ; N dcroat ; B 25 -14 534 676 ; C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ; C -1 ; WX 556 ; N Scedilla ; B 35 -218 513 692 ; C -1 ; WX 394 ; N lcaron ; B 16 0 412 682 ; C -1 ; WX 778 ; N Kcommaaccent ; B 30 -218 769 676 ; C -1 ; WX 667 ; N Lacute ; B 19 0 638 923 ; C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ; C -1 ; WX 444 ; N edotaccent ; B 25 -14 426 691 ; C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ; C -1 ; WX 389 ; N Imacron ; B 20 0 370 847 ; C -1 ; WX 667 ; N Lcaron ; B 19 0 652 682 ; C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ; C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ; C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ; C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 16 -19 701 923 ; C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ; C -1 ; WX 444 ; N emacron ; B 25 -14 426 637 ; C -1 ; WX 500 ; N gbreve ; B 28 -206 483 691 ; C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ; C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ; C -1 ; WX 556 ; N Scommaaccent ; B 35 -218 513 692 ; C -1 ; WX 778 ; N Ohungarumlaut ; B 35 -19 743 923 ; C -1 ; WX 400 ; N degree ; B 57 402 343 688 ; C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ; C -1 ; WX 722 ; N Ccaron ; B 49 -19 687 914 ; C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ; C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ; C -1 ; WX 722 ; N Dcaron ; B 14 0 690 914 ; C -1 ; WX 444 ; N rcommaaccent ; B 29 -218 434 473 ; C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ; C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ; C -1 ; WX 722 ; N Rcommaaccent ; B 26 -218 715 676 ; C -1 ; WX 667 ; N Lcommaaccent ; B 19 -218 638 676 ; C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ; C -1 ; WX 722 ; N Aogonek ; B 9 -193 699 690 ; C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ; C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ; C -1 ; WX 444 ; N zdotaccent ; B 21 0 420 691 ; C -1 ; WX 667 ; N Ecaron ; B 16 0 641 914 ; C -1 ; WX 389 ; N Iogonek ; B 20 -193 370 676 ; C -1 ; WX 556 ; N kcommaaccent ; B 22 -218 543 676 ; C -1 ; WX 570 ; N minus ; B 33 209 537 297 ; C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ; C -1 ; WX 556 ; N ncaron ; B 21 0 539 704 ; C -1 ; WX 333 ; N tcommaaccent ; B 20 -218 332 630 ; C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ; C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ; C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ; C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ; C -1 ; WX 500 ; N gcommaaccent ; B 28 -206 483 829 ; C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ; C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ; C -1 ; WX 556 ; N ncommaaccent ; B 21 -218 539 473 ; C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ; C -1 ; WX 278 ; N imacron ; B -8 0 272 637 ; C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2242 KPX A C -55 KPX A Cacute -55 KPX A Ccaron -55 KPX A Ccedilla -55 KPX A G -55 KPX A Gbreve -55 KPX A Gcommaaccent -55 KPX A O -45 KPX A Oacute -45 KPX A Ocircumflex -45 KPX A Odieresis -45 KPX A Ograve -45 KPX A Ohungarumlaut -45 KPX A Omacron -45 KPX A Oslash -45 KPX A Otilde -45 KPX A Q -45 KPX A T -95 KPX A Tcaron -95 KPX A Tcommaaccent -95 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -145 KPX A W -130 KPX A Y -100 KPX A Yacute -100 KPX A Ydieresis -100 KPX A p -25 KPX A quoteright -74 KPX A u -50 KPX A uacute -50 KPX A ucircumflex -50 KPX A udieresis -50 KPX A ugrave -50 KPX A uhungarumlaut -50 KPX A umacron -50 KPX A uogonek -50 KPX A uring -50 KPX A v -100 KPX A w -90 KPX A y -74 KPX A yacute -74 KPX A ydieresis -74 KPX Aacute C -55 KPX Aacute Cacute -55 KPX Aacute Ccaron -55 KPX Aacute Ccedilla -55 KPX Aacute G -55 KPX Aacute Gbreve -55 KPX Aacute Gcommaaccent -55 KPX Aacute O -45 KPX Aacute Oacute -45 KPX Aacute Ocircumflex -45 KPX Aacute Odieresis -45 KPX Aacute Ograve -45 KPX Aacute Ohungarumlaut -45 KPX Aacute Omacron -45 KPX Aacute Oslash -45 KPX Aacute Otilde -45 KPX Aacute Q -45 KPX Aacute T -95 KPX Aacute Tcaron -95 KPX Aacute Tcommaaccent -95 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -145 KPX Aacute W -130 KPX Aacute Y -100 KPX Aacute Yacute -100 KPX Aacute Ydieresis -100 KPX Aacute p -25 KPX Aacute quoteright -74 KPX Aacute u -50 KPX Aacute uacute -50 KPX Aacute ucircumflex -50 KPX Aacute udieresis -50 KPX Aacute ugrave -50 KPX Aacute uhungarumlaut -50 KPX Aacute umacron -50 KPX Aacute uogonek -50 KPX Aacute uring -50 KPX Aacute v -100 KPX Aacute w -90 KPX Aacute y -74 KPX Aacute yacute -74 KPX Aacute ydieresis -74 KPX Abreve C -55 KPX Abreve Cacute -55 KPX Abreve Ccaron -55 KPX Abreve Ccedilla -55 KPX Abreve G -55 KPX Abreve Gbreve -55 KPX Abreve Gcommaaccent -55 KPX Abreve O -45 KPX Abreve Oacute -45 KPX Abreve Ocircumflex -45 KPX Abreve Odieresis -45 KPX Abreve Ograve -45 KPX Abreve Ohungarumlaut -45 KPX Abreve Omacron -45 KPX Abreve Oslash -45 KPX Abreve Otilde -45 KPX Abreve Q -45 KPX Abreve T -95 KPX Abreve Tcaron -95 KPX Abreve Tcommaaccent -95 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -145 KPX Abreve W -130 KPX Abreve Y -100 KPX Abreve Yacute -100 KPX Abreve Ydieresis -100 KPX Abreve p -25 KPX Abreve quoteright -74 KPX Abreve u -50 KPX Abreve uacute -50 KPX Abreve ucircumflex -50 KPX Abreve udieresis -50 KPX Abreve ugrave -50 KPX Abreve uhungarumlaut -50 KPX Abreve umacron -50 KPX Abreve uogonek -50 KPX Abreve uring -50 KPX Abreve v -100 KPX Abreve w -90 KPX Abreve y -74 KPX Abreve yacute -74 KPX Abreve ydieresis -74 KPX Acircumflex C -55 KPX Acircumflex Cacute -55 KPX Acircumflex Ccaron -55 KPX Acircumflex Ccedilla -55 KPX Acircumflex G -55 KPX Acircumflex Gbreve -55 KPX Acircumflex Gcommaaccent -55 KPX Acircumflex O -45 KPX Acircumflex Oacute -45 KPX Acircumflex Ocircumflex -45 KPX Acircumflex Odieresis -45 KPX Acircumflex Ograve -45 KPX Acircumflex Ohungarumlaut -45 KPX Acircumflex Omacron -45 KPX Acircumflex Oslash -45 KPX Acircumflex Otilde -45 KPX Acircumflex Q -45 KPX Acircumflex T -95 KPX Acircumflex Tcaron -95 KPX Acircumflex Tcommaaccent -95 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -145 KPX Acircumflex W -130 KPX Acircumflex Y -100 KPX Acircumflex Yacute -100 KPX Acircumflex Ydieresis -100 KPX Acircumflex p -25 KPX Acircumflex quoteright -74 KPX Acircumflex u -50 KPX Acircumflex uacute -50 KPX Acircumflex ucircumflex -50 KPX Acircumflex udieresis -50 KPX Acircumflex ugrave -50 KPX Acircumflex uhungarumlaut -50 KPX Acircumflex umacron -50 KPX Acircumflex uogonek -50 KPX Acircumflex uring -50 KPX Acircumflex v -100 KPX Acircumflex w -90 KPX Acircumflex y -74 KPX Acircumflex yacute -74 KPX Acircumflex ydieresis -74 KPX Adieresis C -55 KPX Adieresis Cacute -55 KPX Adieresis Ccaron -55 KPX Adieresis Ccedilla -55 KPX Adieresis G -55 KPX Adieresis Gbreve -55 KPX Adieresis Gcommaaccent -55 KPX Adieresis O -45 KPX Adieresis Oacute -45 KPX Adieresis Ocircumflex -45 KPX Adieresis Odieresis -45 KPX Adieresis Ograve -45 KPX Adieresis Ohungarumlaut -45 KPX Adieresis Omacron -45 KPX Adieresis Oslash -45 KPX Adieresis Otilde -45 KPX Adieresis Q -45 KPX Adieresis T -95 KPX Adieresis Tcaron -95 KPX Adieresis Tcommaaccent -95 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -145 KPX Adieresis W -130 KPX Adieresis Y -100 KPX Adieresis Yacute -100 KPX Adieresis Ydieresis -100 KPX Adieresis p -25 KPX Adieresis quoteright -74 KPX Adieresis u -50 KPX Adieresis uacute -50 KPX Adieresis ucircumflex -50 KPX Adieresis udieresis -50 KPX Adieresis ugrave -50 KPX Adieresis uhungarumlaut -50 KPX Adieresis umacron -50 KPX Adieresis uogonek -50 KPX Adieresis uring -50 KPX Adieresis v -100 KPX Adieresis w -90 KPX Adieresis y -74 KPX Adieresis yacute -74 KPX Adieresis ydieresis -74 KPX Agrave C -55 KPX Agrave Cacute -55 KPX Agrave Ccaron -55 KPX Agrave Ccedilla -55 KPX Agrave G -55 KPX Agrave Gbreve -55 KPX Agrave Gcommaaccent -55 KPX Agrave O -45 KPX Agrave Oacute -45 KPX Agrave Ocircumflex -45 KPX Agrave Odieresis -45 KPX Agrave Ograve -45 KPX Agrave Ohungarumlaut -45 KPX Agrave Omacron -45 KPX Agrave Oslash -45 KPX Agrave Otilde -45 KPX Agrave Q -45 KPX Agrave T -95 KPX Agrave Tcaron -95 KPX Agrave Tcommaaccent -95 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -145 KPX Agrave W -130 KPX Agrave Y -100 KPX Agrave Yacute -100 KPX Agrave Ydieresis -100 KPX Agrave p -25 KPX Agrave quoteright -74 KPX Agrave u -50 KPX Agrave uacute -50 KPX Agrave ucircumflex -50 KPX Agrave udieresis -50 KPX Agrave ugrave -50 KPX Agrave uhungarumlaut -50 KPX Agrave umacron -50 KPX Agrave uogonek -50 KPX Agrave uring -50 KPX Agrave v -100 KPX Agrave w -90 KPX Agrave y -74 KPX Agrave yacute -74 KPX Agrave ydieresis -74 KPX Amacron C -55 KPX Amacron Cacute -55 KPX Amacron Ccaron -55 KPX Amacron Ccedilla -55 KPX Amacron G -55 KPX Amacron Gbreve -55 KPX Amacron Gcommaaccent -55 KPX Amacron O -45 KPX Amacron Oacute -45 KPX Amacron Ocircumflex -45 KPX Amacron Odieresis -45 KPX Amacron Ograve -45 KPX Amacron Ohungarumlaut -45 KPX Amacron Omacron -45 KPX Amacron Oslash -45 KPX Amacron Otilde -45 KPX Amacron Q -45 KPX Amacron T -95 KPX Amacron Tcaron -95 KPX Amacron Tcommaaccent -95 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -145 KPX Amacron W -130 KPX Amacron Y -100 KPX Amacron Yacute -100 KPX Amacron Ydieresis -100 KPX Amacron p -25 KPX Amacron quoteright -74 KPX Amacron u -50 KPX Amacron uacute -50 KPX Amacron ucircumflex -50 KPX Amacron udieresis -50 KPX Amacron ugrave -50 KPX Amacron uhungarumlaut -50 KPX Amacron umacron -50 KPX Amacron uogonek -50 KPX Amacron uring -50 KPX Amacron v -100 KPX Amacron w -90 KPX Amacron y -74 KPX Amacron yacute -74 KPX Amacron ydieresis -74 KPX Aogonek C -55 KPX Aogonek Cacute -55 KPX Aogonek Ccaron -55 KPX Aogonek Ccedilla -55 KPX Aogonek G -55 KPX Aogonek Gbreve -55 KPX Aogonek Gcommaaccent -55 KPX Aogonek O -45 KPX Aogonek Oacute -45 KPX Aogonek Ocircumflex -45 KPX Aogonek Odieresis -45 KPX Aogonek Ograve -45 KPX Aogonek Ohungarumlaut -45 KPX Aogonek Omacron -45 KPX Aogonek Oslash -45 KPX Aogonek Otilde -45 KPX Aogonek Q -45 KPX Aogonek T -95 KPX Aogonek Tcaron -95 KPX Aogonek Tcommaaccent -95 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -145 KPX Aogonek W -130 KPX Aogonek Y -100 KPX Aogonek Yacute -100 KPX Aogonek Ydieresis -100 KPX Aogonek p -25 KPX Aogonek quoteright -74 KPX Aogonek u -50 KPX Aogonek uacute -50 KPX Aogonek ucircumflex -50 KPX Aogonek udieresis -50 KPX Aogonek ugrave -50 KPX Aogonek uhungarumlaut -50 KPX Aogonek umacron -50 KPX Aogonek uogonek -50 KPX Aogonek uring -50 KPX Aogonek v -100 KPX Aogonek w -90 KPX Aogonek y -34 KPX Aogonek yacute -34 KPX Aogonek ydieresis -34 KPX Aring C -55 KPX Aring Cacute -55 KPX Aring Ccaron -55 KPX Aring Ccedilla -55 KPX Aring G -55 KPX Aring Gbreve -55 KPX Aring Gcommaaccent -55 KPX Aring O -45 KPX Aring Oacute -45 KPX Aring Ocircumflex -45 KPX Aring Odieresis -45 KPX Aring Ograve -45 KPX Aring Ohungarumlaut -45 KPX Aring Omacron -45 KPX Aring Oslash -45 KPX Aring Otilde -45 KPX Aring Q -45 KPX Aring T -95 KPX Aring Tcaron -95 KPX Aring Tcommaaccent -95 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -145 KPX Aring W -130 KPX Aring Y -100 KPX Aring Yacute -100 KPX Aring Ydieresis -100 KPX Aring p -25 KPX Aring quoteright -74 KPX Aring u -50 KPX Aring uacute -50 KPX Aring ucircumflex -50 KPX Aring udieresis -50 KPX Aring ugrave -50 KPX Aring uhungarumlaut -50 KPX Aring umacron -50 KPX Aring uogonek -50 KPX Aring uring -50 KPX Aring v -100 KPX Aring w -90 KPX Aring y -74 KPX Aring yacute -74 KPX Aring ydieresis -74 KPX Atilde C -55 KPX Atilde Cacute -55 KPX Atilde Ccaron -55 KPX Atilde Ccedilla -55 KPX Atilde G -55 KPX Atilde Gbreve -55 KPX Atilde Gcommaaccent -55 KPX Atilde O -45 KPX Atilde Oacute -45 KPX Atilde Ocircumflex -45 KPX Atilde Odieresis -45 KPX Atilde Ograve -45 KPX Atilde Ohungarumlaut -45 KPX Atilde Omacron -45 KPX Atilde Oslash -45 KPX Atilde Otilde -45 KPX Atilde Q -45 KPX Atilde T -95 KPX Atilde Tcaron -95 KPX Atilde Tcommaaccent -95 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -145 KPX Atilde W -130 KPX Atilde Y -100 KPX Atilde Yacute -100 KPX Atilde Ydieresis -100 KPX Atilde p -25 KPX Atilde quoteright -74 KPX Atilde u -50 KPX Atilde uacute -50 KPX Atilde ucircumflex -50 KPX Atilde udieresis -50 KPX Atilde ugrave -50 KPX Atilde uhungarumlaut -50 KPX Atilde umacron -50 KPX Atilde uogonek -50 KPX Atilde uring -50 KPX Atilde v -100 KPX Atilde w -90 KPX Atilde y -74 KPX Atilde yacute -74 KPX Atilde ydieresis -74 KPX B A -30 KPX B Aacute -30 KPX B Abreve -30 KPX B Acircumflex -30 KPX B Adieresis -30 KPX B Agrave -30 KPX B Amacron -30 KPX B Aogonek -30 KPX B Aring -30 KPX B Atilde -30 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -35 KPX D Aacute -35 KPX D Abreve -35 KPX D Acircumflex -35 KPX D Adieresis -35 KPX D Agrave -35 KPX D Amacron -35 KPX D Aogonek -35 KPX D Aring -35 KPX D Atilde -35 KPX D V -40 KPX D W -40 KPX D Y -40 KPX D Yacute -40 KPX D Ydieresis -40 KPX D period -20 KPX Dcaron A -35 KPX Dcaron Aacute -35 KPX Dcaron Abreve -35 KPX Dcaron Acircumflex -35 KPX Dcaron Adieresis -35 KPX Dcaron Agrave -35 KPX Dcaron Amacron -35 KPX Dcaron Aogonek -35 KPX Dcaron Aring -35 KPX Dcaron Atilde -35 KPX Dcaron V -40 KPX Dcaron W -40 KPX Dcaron Y -40 KPX Dcaron Yacute -40 KPX Dcaron Ydieresis -40 KPX Dcaron period -20 KPX Dcroat A -35 KPX Dcroat Aacute -35 KPX Dcroat Abreve -35 KPX Dcroat Acircumflex -35 KPX Dcroat Adieresis -35 KPX Dcroat Agrave -35 KPX Dcroat Amacron -35 KPX Dcroat Aogonek -35 KPX Dcroat Aring -35 KPX Dcroat Atilde -35 KPX Dcroat V -40 KPX Dcroat W -40 KPX Dcroat Y -40 KPX Dcroat Yacute -40 KPX Dcroat Ydieresis -40 KPX Dcroat period -20 KPX F A -90 KPX F Aacute -90 KPX F Abreve -90 KPX F Acircumflex -90 KPX F Adieresis -90 KPX F Agrave -90 KPX F Amacron -90 KPX F Aogonek -90 KPX F Aring -90 KPX F Atilde -90 KPX F a -25 KPX F aacute -25 KPX F abreve -25 KPX F acircumflex -25 KPX F adieresis -25 KPX F agrave -25 KPX F amacron -25 KPX F aogonek -25 KPX F aring -25 KPX F atilde -25 KPX F comma -92 KPX F e -25 KPX F eacute -25 KPX F ecaron -25 KPX F ecircumflex -25 KPX F edieresis -25 KPX F edotaccent -25 KPX F egrave -25 KPX F emacron -25 KPX F eogonek -25 KPX F o -25 KPX F oacute -25 KPX F ocircumflex -25 KPX F odieresis -25 KPX F ograve -25 KPX F ohungarumlaut -25 KPX F omacron -25 KPX F oslash -25 KPX F otilde -25 KPX F period -110 KPX J A -30 KPX J Aacute -30 KPX J Abreve -30 KPX J Acircumflex -30 KPX J Adieresis -30 KPX J Agrave -30 KPX J Amacron -30 KPX J Aogonek -30 KPX J Aring -30 KPX J Atilde -30 KPX J a -15 KPX J aacute -15 KPX J abreve -15 KPX J acircumflex -15 KPX J adieresis -15 KPX J agrave -15 KPX J amacron -15 KPX J aogonek -15 KPX J aring -15 KPX J atilde -15 KPX J e -15 KPX J eacute -15 KPX J ecaron -15 KPX J ecircumflex -15 KPX J edieresis -15 KPX J edotaccent -15 KPX J egrave -15 KPX J emacron -15 KPX J eogonek -15 KPX J o -15 KPX J oacute -15 KPX J ocircumflex -15 KPX J odieresis -15 KPX J ograve -15 KPX J ohungarumlaut -15 KPX J omacron -15 KPX J oslash -15 KPX J otilde -15 KPX J period -20 KPX J u -15 KPX J uacute -15 KPX J ucircumflex -15 KPX J udieresis -15 KPX J ugrave -15 KPX J uhungarumlaut -15 KPX J umacron -15 KPX J uogonek -15 KPX J uring -15 KPX K O -30 KPX K Oacute -30 KPX K Ocircumflex -30 KPX K Odieresis -30 KPX K Ograve -30 KPX K Ohungarumlaut -30 KPX K Omacron -30 KPX K Oslash -30 KPX K Otilde -30 KPX K e -25 KPX K eacute -25 KPX K ecaron -25 KPX K ecircumflex -25 KPX K edieresis -25 KPX K edotaccent -25 KPX K egrave -25 KPX K emacron -25 KPX K eogonek -25 KPX K o -25 KPX K oacute -25 KPX K ocircumflex -25 KPX K odieresis -25 KPX K ograve -25 KPX K ohungarumlaut -25 KPX K omacron -25 KPX K oslash -25 KPX K otilde -25 KPX K u -15 KPX K uacute -15 KPX K ucircumflex -15 KPX K udieresis -15 KPX K ugrave -15 KPX K uhungarumlaut -15 KPX K umacron -15 KPX K uogonek -15 KPX K uring -15 KPX K y -45 KPX K yacute -45 KPX K ydieresis -45 KPX Kcommaaccent O -30 KPX Kcommaaccent Oacute -30 KPX Kcommaaccent Ocircumflex -30 KPX Kcommaaccent Odieresis -30 KPX Kcommaaccent Ograve -30 KPX Kcommaaccent Ohungarumlaut -30 KPX Kcommaaccent Omacron -30 KPX Kcommaaccent Oslash -30 KPX Kcommaaccent Otilde -30 KPX Kcommaaccent e -25 KPX Kcommaaccent eacute -25 KPX Kcommaaccent ecaron -25 KPX Kcommaaccent ecircumflex -25 KPX Kcommaaccent edieresis -25 KPX Kcommaaccent edotaccent -25 KPX Kcommaaccent egrave -25 KPX Kcommaaccent emacron -25 KPX Kcommaaccent eogonek -25 KPX Kcommaaccent o -25 KPX Kcommaaccent oacute -25 KPX Kcommaaccent ocircumflex -25 KPX Kcommaaccent odieresis -25 KPX Kcommaaccent ograve -25 KPX Kcommaaccent ohungarumlaut -25 KPX Kcommaaccent omacron -25 KPX Kcommaaccent oslash -25 KPX Kcommaaccent otilde -25 KPX Kcommaaccent u -15 KPX Kcommaaccent uacute -15 KPX Kcommaaccent ucircumflex -15 KPX Kcommaaccent udieresis -15 KPX Kcommaaccent ugrave -15 KPX Kcommaaccent uhungarumlaut -15 KPX Kcommaaccent umacron -15 KPX Kcommaaccent uogonek -15 KPX Kcommaaccent uring -15 KPX Kcommaaccent y -45 KPX Kcommaaccent yacute -45 KPX Kcommaaccent ydieresis -45 KPX L T -92 KPX L Tcaron -92 KPX L Tcommaaccent -92 KPX L V -92 KPX L W -92 KPX L Y -92 KPX L Yacute -92 KPX L Ydieresis -92 KPX L quotedblright -20 KPX L quoteright -110 KPX L y -55 KPX L yacute -55 KPX L ydieresis -55 KPX Lacute T -92 KPX Lacute Tcaron -92 KPX Lacute Tcommaaccent -92 KPX Lacute V -92 KPX Lacute W -92 KPX Lacute Y -92 KPX Lacute Yacute -92 KPX Lacute Ydieresis -92 KPX Lacute quotedblright -20 KPX Lacute quoteright -110 KPX Lacute y -55 KPX Lacute yacute -55 KPX Lacute ydieresis -55 KPX Lcommaaccent T -92 KPX Lcommaaccent Tcaron -92 KPX Lcommaaccent Tcommaaccent -92 KPX Lcommaaccent V -92 KPX Lcommaaccent W -92 KPX Lcommaaccent Y -92 KPX Lcommaaccent Yacute -92 KPX Lcommaaccent Ydieresis -92 KPX Lcommaaccent quotedblright -20 KPX Lcommaaccent quoteright -110 KPX Lcommaaccent y -55 KPX Lcommaaccent yacute -55 KPX Lcommaaccent ydieresis -55 KPX Lslash T -92 KPX Lslash Tcaron -92 KPX Lslash Tcommaaccent -92 KPX Lslash V -92 KPX Lslash W -92 KPX Lslash Y -92 KPX Lslash Yacute -92 KPX Lslash Ydieresis -92 KPX Lslash quotedblright -20 KPX Lslash quoteright -110 KPX Lslash y -55 KPX Lslash yacute -55 KPX Lslash ydieresis -55 KPX N A -20 KPX N Aacute -20 KPX N Abreve -20 KPX N Acircumflex -20 KPX N Adieresis -20 KPX N Agrave -20 KPX N Amacron -20 KPX N Aogonek -20 KPX N Aring -20 KPX N Atilde -20 KPX Nacute A -20 KPX Nacute Aacute -20 KPX Nacute Abreve -20 KPX Nacute Acircumflex -20 KPX Nacute Adieresis -20 KPX Nacute Agrave -20 KPX Nacute Amacron -20 KPX Nacute Aogonek -20 KPX Nacute Aring -20 KPX Nacute Atilde -20 KPX Ncaron A -20 KPX Ncaron Aacute -20 KPX Ncaron Abreve -20 KPX Ncaron Acircumflex -20 KPX Ncaron Adieresis -20 KPX Ncaron Agrave -20 KPX Ncaron Amacron -20 KPX Ncaron Aogonek -20 KPX Ncaron Aring -20 KPX Ncaron Atilde -20 KPX Ncommaaccent A -20 KPX Ncommaaccent Aacute -20 KPX Ncommaaccent Abreve -20 KPX Ncommaaccent Acircumflex -20 KPX Ncommaaccent Adieresis -20 KPX Ncommaaccent Agrave -20 KPX Ncommaaccent Amacron -20 KPX Ncommaaccent Aogonek -20 KPX Ncommaaccent Aring -20 KPX Ncommaaccent Atilde -20 KPX Ntilde A -20 KPX Ntilde Aacute -20 KPX Ntilde Abreve -20 KPX Ntilde Acircumflex -20 KPX Ntilde Adieresis -20 KPX Ntilde Agrave -20 KPX Ntilde Amacron -20 KPX Ntilde Aogonek -20 KPX Ntilde Aring -20 KPX Ntilde Atilde -20 KPX O A -40 KPX O Aacute -40 KPX O Abreve -40 KPX O Acircumflex -40 KPX O Adieresis -40 KPX O Agrave -40 KPX O Amacron -40 KPX O Aogonek -40 KPX O Aring -40 KPX O Atilde -40 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -50 KPX O X -40 KPX O Y -50 KPX O Yacute -50 KPX O Ydieresis -50 KPX Oacute A -40 KPX Oacute Aacute -40 KPX Oacute Abreve -40 KPX Oacute Acircumflex -40 KPX Oacute Adieresis -40 KPX Oacute Agrave -40 KPX Oacute Amacron -40 KPX Oacute Aogonek -40 KPX Oacute Aring -40 KPX Oacute Atilde -40 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -50 KPX Oacute X -40 KPX Oacute Y -50 KPX Oacute Yacute -50 KPX Oacute Ydieresis -50 KPX Ocircumflex A -40 KPX Ocircumflex Aacute -40 KPX Ocircumflex Abreve -40 KPX Ocircumflex Acircumflex -40 KPX Ocircumflex Adieresis -40 KPX Ocircumflex Agrave -40 KPX Ocircumflex Amacron -40 KPX Ocircumflex Aogonek -40 KPX Ocircumflex Aring -40 KPX Ocircumflex Atilde -40 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -50 KPX Ocircumflex X -40 KPX Ocircumflex Y -50 KPX Ocircumflex Yacute -50 KPX Ocircumflex Ydieresis -50 KPX Odieresis A -40 KPX Odieresis Aacute -40 KPX Odieresis Abreve -40 KPX Odieresis Acircumflex -40 KPX Odieresis Adieresis -40 KPX Odieresis Agrave -40 KPX Odieresis Amacron -40 KPX Odieresis Aogonek -40 KPX Odieresis Aring -40 KPX Odieresis Atilde -40 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -50 KPX Odieresis X -40 KPX Odieresis Y -50 KPX Odieresis Yacute -50 KPX Odieresis Ydieresis -50 KPX Ograve A -40 KPX Ograve Aacute -40 KPX Ograve Abreve -40 KPX Ograve Acircumflex -40 KPX Ograve Adieresis -40 KPX Ograve Agrave -40 KPX Ograve Amacron -40 KPX Ograve Aogonek -40 KPX Ograve Aring -40 KPX Ograve Atilde -40 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -50 KPX Ograve X -40 KPX Ograve Y -50 KPX Ograve Yacute -50 KPX Ograve Ydieresis -50 KPX Ohungarumlaut A -40 KPX Ohungarumlaut Aacute -40 KPX Ohungarumlaut Abreve -40 KPX Ohungarumlaut Acircumflex -40 KPX Ohungarumlaut Adieresis -40 KPX Ohungarumlaut Agrave -40 KPX Ohungarumlaut Amacron -40 KPX Ohungarumlaut Aogonek -40 KPX Ohungarumlaut Aring -40 KPX Ohungarumlaut Atilde -40 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -50 KPX Ohungarumlaut X -40 KPX Ohungarumlaut Y -50 KPX Ohungarumlaut Yacute -50 KPX Ohungarumlaut Ydieresis -50 KPX Omacron A -40 KPX Omacron Aacute -40 KPX Omacron Abreve -40 KPX Omacron Acircumflex -40 KPX Omacron Adieresis -40 KPX Omacron Agrave -40 KPX Omacron Amacron -40 KPX Omacron Aogonek -40 KPX Omacron Aring -40 KPX Omacron Atilde -40 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -50 KPX Omacron X -40 KPX Omacron Y -50 KPX Omacron Yacute -50 KPX Omacron Ydieresis -50 KPX Oslash A -40 KPX Oslash Aacute -40 KPX Oslash Abreve -40 KPX Oslash Acircumflex -40 KPX Oslash Adieresis -40 KPX Oslash Agrave -40 KPX Oslash Amacron -40 KPX Oslash Aogonek -40 KPX Oslash Aring -40 KPX Oslash Atilde -40 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -50 KPX Oslash X -40 KPX Oslash Y -50 KPX Oslash Yacute -50 KPX Oslash Ydieresis -50 KPX Otilde A -40 KPX Otilde Aacute -40 KPX Otilde Abreve -40 KPX Otilde Acircumflex -40 KPX Otilde Adieresis -40 KPX Otilde Agrave -40 KPX Otilde Amacron -40 KPX Otilde Aogonek -40 KPX Otilde Aring -40 KPX Otilde Atilde -40 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -50 KPX Otilde X -40 KPX Otilde Y -50 KPX Otilde Yacute -50 KPX Otilde Ydieresis -50 KPX P A -74 KPX P Aacute -74 KPX P Abreve -74 KPX P Acircumflex -74 KPX P Adieresis -74 KPX P Agrave -74 KPX P Amacron -74 KPX P Aogonek -74 KPX P Aring -74 KPX P Atilde -74 KPX P a -10 KPX P aacute -10 KPX P abreve -10 KPX P acircumflex -10 KPX P adieresis -10 KPX P agrave -10 KPX P amacron -10 KPX P aogonek -10 KPX P aring -10 KPX P atilde -10 KPX P comma -92 KPX P e -20 KPX P eacute -20 KPX P ecaron -20 KPX P ecircumflex -20 KPX P edieresis -20 KPX P edotaccent -20 KPX P egrave -20 KPX P emacron -20 KPX P eogonek -20 KPX P o -20 KPX P oacute -20 KPX P ocircumflex -20 KPX P odieresis -20 KPX P ograve -20 KPX P ohungarumlaut -20 KPX P omacron -20 KPX P oslash -20 KPX P otilde -20 KPX P period -110 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX Q period -20 KPX R O -30 KPX R Oacute -30 KPX R Ocircumflex -30 KPX R Odieresis -30 KPX R Ograve -30 KPX R Ohungarumlaut -30 KPX R Omacron -30 KPX R Oslash -30 KPX R Otilde -30 KPX R T -40 KPX R Tcaron -40 KPX R Tcommaaccent -40 KPX R U -30 KPX R Uacute -30 KPX R Ucircumflex -30 KPX R Udieresis -30 KPX R Ugrave -30 KPX R Uhungarumlaut -30 KPX R Umacron -30 KPX R Uogonek -30 KPX R Uring -30 KPX R V -55 KPX R W -35 KPX R Y -35 KPX R Yacute -35 KPX R Ydieresis -35 KPX Racute O -30 KPX Racute Oacute -30 KPX Racute Ocircumflex -30 KPX Racute Odieresis -30 KPX Racute Ograve -30 KPX Racute Ohungarumlaut -30 KPX Racute Omacron -30 KPX Racute Oslash -30 KPX Racute Otilde -30 KPX Racute T -40 KPX Racute Tcaron -40 KPX Racute Tcommaaccent -40 KPX Racute U -30 KPX Racute Uacute -30 KPX Racute Ucircumflex -30 KPX Racute Udieresis -30 KPX Racute Ugrave -30 KPX Racute Uhungarumlaut -30 KPX Racute Umacron -30 KPX Racute Uogonek -30 KPX Racute Uring -30 KPX Racute V -55 KPX Racute W -35 KPX Racute Y -35 KPX Racute Yacute -35 KPX Racute Ydieresis -35 KPX Rcaron O -30 KPX Rcaron Oacute -30 KPX Rcaron Ocircumflex -30 KPX Rcaron Odieresis -30 KPX Rcaron Ograve -30 KPX Rcaron Ohungarumlaut -30 KPX Rcaron Omacron -30 KPX Rcaron Oslash -30 KPX Rcaron Otilde -30 KPX Rcaron T -40 KPX Rcaron Tcaron -40 KPX Rcaron Tcommaaccent -40 KPX Rcaron U -30 KPX Rcaron Uacute -30 KPX Rcaron Ucircumflex -30 KPX Rcaron Udieresis -30 KPX Rcaron Ugrave -30 KPX Rcaron Uhungarumlaut -30 KPX Rcaron Umacron -30 KPX Rcaron Uogonek -30 KPX Rcaron Uring -30 KPX Rcaron V -55 KPX Rcaron W -35 KPX Rcaron Y -35 KPX Rcaron Yacute -35 KPX Rcaron Ydieresis -35 KPX Rcommaaccent O -30 KPX Rcommaaccent Oacute -30 KPX Rcommaaccent Ocircumflex -30 KPX Rcommaaccent Odieresis -30 KPX Rcommaaccent Ograve -30 KPX Rcommaaccent Ohungarumlaut -30 KPX Rcommaaccent Omacron -30 KPX Rcommaaccent Oslash -30 KPX Rcommaaccent Otilde -30 KPX Rcommaaccent T -40 KPX Rcommaaccent Tcaron -40 KPX Rcommaaccent Tcommaaccent -40 KPX Rcommaaccent U -30 KPX Rcommaaccent Uacute -30 KPX Rcommaaccent Ucircumflex -30 KPX Rcommaaccent Udieresis -30 KPX Rcommaaccent Ugrave -30 KPX Rcommaaccent Uhungarumlaut -30 KPX Rcommaaccent Umacron -30 KPX Rcommaaccent Uogonek -30 KPX Rcommaaccent Uring -30 KPX Rcommaaccent V -55 KPX Rcommaaccent W -35 KPX Rcommaaccent Y -35 KPX Rcommaaccent Yacute -35 KPX Rcommaaccent Ydieresis -35 KPX T A -90 KPX T Aacute -90 KPX T Abreve -90 KPX T Acircumflex -90 KPX T Adieresis -90 KPX T Agrave -90 KPX T Amacron -90 KPX T Aogonek -90 KPX T Aring -90 KPX T Atilde -90 KPX T O -18 KPX T Oacute -18 KPX T Ocircumflex -18 KPX T Odieresis -18 KPX T Ograve -18 KPX T Ohungarumlaut -18 KPX T Omacron -18 KPX T Oslash -18 KPX T Otilde -18 KPX T a -92 KPX T aacute -92 KPX T abreve -52 KPX T acircumflex -52 KPX T adieresis -52 KPX T agrave -52 KPX T amacron -52 KPX T aogonek -92 KPX T aring -92 KPX T atilde -52 KPX T colon -74 KPX T comma -74 KPX T e -92 KPX T eacute -92 KPX T ecaron -92 KPX T ecircumflex -92 KPX T edieresis -52 KPX T edotaccent -92 KPX T egrave -52 KPX T emacron -52 KPX T eogonek -92 KPX T hyphen -92 KPX T i -18 KPX T iacute -18 KPX T iogonek -18 KPX T o -92 KPX T oacute -92 KPX T ocircumflex -92 KPX T odieresis -92 KPX T ograve -92 KPX T ohungarumlaut -92 KPX T omacron -92 KPX T oslash -92 KPX T otilde -92 KPX T period -90 KPX T r -74 KPX T racute -74 KPX T rcaron -74 KPX T rcommaaccent -74 KPX T semicolon -74 KPX T u -92 KPX T uacute -92 KPX T ucircumflex -92 KPX T udieresis -92 KPX T ugrave -92 KPX T uhungarumlaut -92 KPX T umacron -92 KPX T uogonek -92 KPX T uring -92 KPX T w -74 KPX T y -34 KPX T yacute -34 KPX T ydieresis -34 KPX Tcaron A -90 KPX Tcaron Aacute -90 KPX Tcaron Abreve -90 KPX Tcaron Acircumflex -90 KPX Tcaron Adieresis -90 KPX Tcaron Agrave -90 KPX Tcaron Amacron -90 KPX Tcaron Aogonek -90 KPX Tcaron Aring -90 KPX Tcaron Atilde -90 KPX Tcaron O -18 KPX Tcaron Oacute -18 KPX Tcaron Ocircumflex -18 KPX Tcaron Odieresis -18 KPX Tcaron Ograve -18 KPX Tcaron Ohungarumlaut -18 KPX Tcaron Omacron -18 KPX Tcaron Oslash -18 KPX Tcaron Otilde -18 KPX Tcaron a -92 KPX Tcaron aacute -92 KPX Tcaron abreve -52 KPX Tcaron acircumflex -52 KPX Tcaron adieresis -52 KPX Tcaron agrave -52 KPX Tcaron amacron -52 KPX Tcaron aogonek -92 KPX Tcaron aring -92 KPX Tcaron atilde -52 KPX Tcaron colon -74 KPX Tcaron comma -74 KPX Tcaron e -92 KPX Tcaron eacute -92 KPX Tcaron ecaron -92 KPX Tcaron ecircumflex -92 KPX Tcaron edieresis -52 KPX Tcaron edotaccent -92 KPX Tcaron egrave -52 KPX Tcaron emacron -52 KPX Tcaron eogonek -92 KPX Tcaron hyphen -92 KPX Tcaron i -18 KPX Tcaron iacute -18 KPX Tcaron iogonek -18 KPX Tcaron o -92 KPX Tcaron oacute -92 KPX Tcaron ocircumflex -92 KPX Tcaron odieresis -92 KPX Tcaron ograve -92 KPX Tcaron ohungarumlaut -92 KPX Tcaron omacron -92 KPX Tcaron oslash -92 KPX Tcaron otilde -92 KPX Tcaron period -90 KPX Tcaron r -74 KPX Tcaron racute -74 KPX Tcaron rcaron -74 KPX Tcaron rcommaaccent -74 KPX Tcaron semicolon -74 KPX Tcaron u -92 KPX Tcaron uacute -92 KPX Tcaron ucircumflex -92 KPX Tcaron udieresis -92 KPX Tcaron ugrave -92 KPX Tcaron uhungarumlaut -92 KPX Tcaron umacron -92 KPX Tcaron uogonek -92 KPX Tcaron uring -92 KPX Tcaron w -74 KPX Tcaron y -34 KPX Tcaron yacute -34 KPX Tcaron ydieresis -34 KPX Tcommaaccent A -90 KPX Tcommaaccent Aacute -90 KPX Tcommaaccent Abreve -90 KPX Tcommaaccent Acircumflex -90 KPX Tcommaaccent Adieresis -90 KPX Tcommaaccent Agrave -90 KPX Tcommaaccent Amacron -90 KPX Tcommaaccent Aogonek -90 KPX Tcommaaccent Aring -90 KPX Tcommaaccent Atilde -90 KPX Tcommaaccent O -18 KPX Tcommaaccent Oacute -18 KPX Tcommaaccent Ocircumflex -18 KPX Tcommaaccent Odieresis -18 KPX Tcommaaccent Ograve -18 KPX Tcommaaccent Ohungarumlaut -18 KPX Tcommaaccent Omacron -18 KPX Tcommaaccent Oslash -18 KPX Tcommaaccent Otilde -18 KPX Tcommaaccent a -92 KPX Tcommaaccent aacute -92 KPX Tcommaaccent abreve -52 KPX Tcommaaccent acircumflex -52 KPX Tcommaaccent adieresis -52 KPX Tcommaaccent agrave -52 KPX Tcommaaccent amacron -52 KPX Tcommaaccent aogonek -92 KPX Tcommaaccent aring -92 KPX Tcommaaccent atilde -52 KPX Tcommaaccent colon -74 KPX Tcommaaccent comma -74 KPX Tcommaaccent e -92 KPX Tcommaaccent eacute -92 KPX Tcommaaccent ecaron -92 KPX Tcommaaccent ecircumflex -92 KPX Tcommaaccent edieresis -52 KPX Tcommaaccent edotaccent -92 KPX Tcommaaccent egrave -52 KPX Tcommaaccent emacron -52 KPX Tcommaaccent eogonek -92 KPX Tcommaaccent hyphen -92 KPX Tcommaaccent i -18 KPX Tcommaaccent iacute -18 KPX Tcommaaccent iogonek -18 KPX Tcommaaccent o -92 KPX Tcommaaccent oacute -92 KPX Tcommaaccent ocircumflex -92 KPX Tcommaaccent odieresis -92 KPX Tcommaaccent ograve -92 KPX Tcommaaccent ohungarumlaut -92 KPX Tcommaaccent omacron -92 KPX Tcommaaccent oslash -92 KPX Tcommaaccent otilde -92 KPX Tcommaaccent period -90 KPX Tcommaaccent r -74 KPX Tcommaaccent racute -74 KPX Tcommaaccent rcaron -74 KPX Tcommaaccent rcommaaccent -74 KPX Tcommaaccent semicolon -74 KPX Tcommaaccent u -92 KPX Tcommaaccent uacute -92 KPX Tcommaaccent ucircumflex -92 KPX Tcommaaccent udieresis -92 KPX Tcommaaccent ugrave -92 KPX Tcommaaccent uhungarumlaut -92 KPX Tcommaaccent umacron -92 KPX Tcommaaccent uogonek -92 KPX Tcommaaccent uring -92 KPX Tcommaaccent w -74 KPX Tcommaaccent y -34 KPX Tcommaaccent yacute -34 KPX Tcommaaccent ydieresis -34 KPX U A -60 KPX U Aacute -60 KPX U Abreve -60 KPX U Acircumflex -60 KPX U Adieresis -60 KPX U Agrave -60 KPX U Amacron -60 KPX U Aogonek -60 KPX U Aring -60 KPX U Atilde -60 KPX U comma -50 KPX U period -50 KPX Uacute A -60 KPX Uacute Aacute -60 KPX Uacute Abreve -60 KPX Uacute Acircumflex -60 KPX Uacute Adieresis -60 KPX Uacute Agrave -60 KPX Uacute Amacron -60 KPX Uacute Aogonek -60 KPX Uacute Aring -60 KPX Uacute Atilde -60 KPX Uacute comma -50 KPX Uacute period -50 KPX Ucircumflex A -60 KPX Ucircumflex Aacute -60 KPX Ucircumflex Abreve -60 KPX Ucircumflex Acircumflex -60 KPX Ucircumflex Adieresis -60 KPX Ucircumflex Agrave -60 KPX Ucircumflex Amacron -60 KPX Ucircumflex Aogonek -60 KPX Ucircumflex Aring -60 KPX Ucircumflex Atilde -60 KPX Ucircumflex comma -50 KPX Ucircumflex period -50 KPX Udieresis A -60 KPX Udieresis Aacute -60 KPX Udieresis Abreve -60 KPX Udieresis Acircumflex -60 KPX Udieresis Adieresis -60 KPX Udieresis Agrave -60 KPX Udieresis Amacron -60 KPX Udieresis Aogonek -60 KPX Udieresis Aring -60 KPX Udieresis Atilde -60 KPX Udieresis comma -50 KPX Udieresis period -50 KPX Ugrave A -60 KPX Ugrave Aacute -60 KPX Ugrave Abreve -60 KPX Ugrave Acircumflex -60 KPX Ugrave Adieresis -60 KPX Ugrave Agrave -60 KPX Ugrave Amacron -60 KPX Ugrave Aogonek -60 KPX Ugrave Aring -60 KPX Ugrave Atilde -60 KPX Ugrave comma -50 KPX Ugrave period -50 KPX Uhungarumlaut A -60 KPX Uhungarumlaut Aacute -60 KPX Uhungarumlaut Abreve -60 KPX Uhungarumlaut Acircumflex -60 KPX Uhungarumlaut Adieresis -60 KPX Uhungarumlaut Agrave -60 KPX Uhungarumlaut Amacron -60 KPX Uhungarumlaut Aogonek -60 KPX Uhungarumlaut Aring -60 KPX Uhungarumlaut Atilde -60 KPX Uhungarumlaut comma -50 KPX Uhungarumlaut period -50 KPX Umacron A -60 KPX Umacron Aacute -60 KPX Umacron Abreve -60 KPX Umacron Acircumflex -60 KPX Umacron Adieresis -60 KPX Umacron Agrave -60 KPX Umacron Amacron -60 KPX Umacron Aogonek -60 KPX Umacron Aring -60 KPX Umacron Atilde -60 KPX Umacron comma -50 KPX Umacron period -50 KPX Uogonek A -60 KPX Uogonek Aacute -60 KPX Uogonek Abreve -60 KPX Uogonek Acircumflex -60 KPX Uogonek Adieresis -60 KPX Uogonek Agrave -60 KPX Uogonek Amacron -60 KPX Uogonek Aogonek -60 KPX Uogonek Aring -60 KPX Uogonek Atilde -60 KPX Uogonek comma -50 KPX Uogonek period -50 KPX Uring A -60 KPX Uring Aacute -60 KPX Uring Abreve -60 KPX Uring Acircumflex -60 KPX Uring Adieresis -60 KPX Uring Agrave -60 KPX Uring Amacron -60 KPX Uring Aogonek -60 KPX Uring Aring -60 KPX Uring Atilde -60 KPX Uring comma -50 KPX Uring period -50 KPX V A -135 KPX V Aacute -135 KPX V Abreve -135 KPX V Acircumflex -135 KPX V Adieresis -135 KPX V Agrave -135 KPX V Amacron -135 KPX V Aogonek -135 KPX V Aring -135 KPX V Atilde -135 KPX V G -30 KPX V Gbreve -30 KPX V Gcommaaccent -30 KPX V O -45 KPX V Oacute -45 KPX V Ocircumflex -45 KPX V Odieresis -45 KPX V Ograve -45 KPX V Ohungarumlaut -45 KPX V Omacron -45 KPX V Oslash -45 KPX V Otilde -45 KPX V a -92 KPX V aacute -92 KPX V abreve -92 KPX V acircumflex -92 KPX V adieresis -92 KPX V agrave -92 KPX V amacron -92 KPX V aogonek -92 KPX V aring -92 KPX V atilde -92 KPX V colon -92 KPX V comma -129 KPX V e -100 KPX V eacute -100 KPX V ecaron -100 KPX V ecircumflex -100 KPX V edieresis -100 KPX V edotaccent -100 KPX V egrave -100 KPX V emacron -100 KPX V eogonek -100 KPX V hyphen -74 KPX V i -37 KPX V iacute -37 KPX V icircumflex -37 KPX V idieresis -37 KPX V igrave -37 KPX V imacron -37 KPX V iogonek -37 KPX V o -100 KPX V oacute -100 KPX V ocircumflex -100 KPX V odieresis -100 KPX V ograve -100 KPX V ohungarumlaut -100 KPX V omacron -100 KPX V oslash -100 KPX V otilde -100 KPX V period -145 KPX V semicolon -92 KPX V u -92 KPX V uacute -92 KPX V ucircumflex -92 KPX V udieresis -92 KPX V ugrave -92 KPX V uhungarumlaut -92 KPX V umacron -92 KPX V uogonek -92 KPX V uring -92 KPX W A -120 KPX W Aacute -120 KPX W Abreve -120 KPX W Acircumflex -120 KPX W Adieresis -120 KPX W Agrave -120 KPX W Amacron -120 KPX W Aogonek -120 KPX W Aring -120 KPX W Atilde -120 KPX W O -10 KPX W Oacute -10 KPX W Ocircumflex -10 KPX W Odieresis -10 KPX W Ograve -10 KPX W Ohungarumlaut -10 KPX W Omacron -10 KPX W Oslash -10 KPX W Otilde -10 KPX W a -65 KPX W aacute -65 KPX W abreve -65 KPX W acircumflex -65 KPX W adieresis -65 KPX W agrave -65 KPX W amacron -65 KPX W aogonek -65 KPX W aring -65 KPX W atilde -65 KPX W colon -55 KPX W comma -92 KPX W e -65 KPX W eacute -65 KPX W ecaron -65 KPX W ecircumflex -65 KPX W edieresis -65 KPX W edotaccent -65 KPX W egrave -65 KPX W emacron -65 KPX W eogonek -65 KPX W hyphen -37 KPX W i -18 KPX W iacute -18 KPX W iogonek -18 KPX W o -75 KPX W oacute -75 KPX W ocircumflex -75 KPX W odieresis -75 KPX W ograve -75 KPX W ohungarumlaut -75 KPX W omacron -75 KPX W oslash -75 KPX W otilde -75 KPX W period -92 KPX W semicolon -55 KPX W u -50 KPX W uacute -50 KPX W ucircumflex -50 KPX W udieresis -50 KPX W ugrave -50 KPX W uhungarumlaut -50 KPX W umacron -50 KPX W uogonek -50 KPX W uring -50 KPX W y -60 KPX W yacute -60 KPX W ydieresis -60 KPX Y A -110 KPX Y Aacute -110 KPX Y Abreve -110 KPX Y Acircumflex -110 KPX Y Adieresis -110 KPX Y Agrave -110 KPX Y Amacron -110 KPX Y Aogonek -110 KPX Y Aring -110 KPX Y Atilde -110 KPX Y O -35 KPX Y Oacute -35 KPX Y Ocircumflex -35 KPX Y Odieresis -35 KPX Y Ograve -35 KPX Y Ohungarumlaut -35 KPX Y Omacron -35 KPX Y Oslash -35 KPX Y Otilde -35 KPX Y a -85 KPX Y aacute -85 KPX Y abreve -85 KPX Y acircumflex -85 KPX Y adieresis -85 KPX Y agrave -85 KPX Y amacron -85 KPX Y aogonek -85 KPX Y aring -85 KPX Y atilde -85 KPX Y colon -92 KPX Y comma -92 KPX Y e -111 KPX Y eacute -111 KPX Y ecaron -111 KPX Y ecircumflex -111 KPX Y edieresis -71 KPX Y edotaccent -111 KPX Y egrave -71 KPX Y emacron -71 KPX Y eogonek -111 KPX Y hyphen -92 KPX Y i -37 KPX Y iacute -37 KPX Y iogonek -37 KPX Y o -111 KPX Y oacute -111 KPX Y ocircumflex -111 KPX Y odieresis -111 KPX Y ograve -111 KPX Y ohungarumlaut -111 KPX Y omacron -111 KPX Y oslash -111 KPX Y otilde -111 KPX Y period -92 KPX Y semicolon -92 KPX Y u -92 KPX Y uacute -92 KPX Y ucircumflex -92 KPX Y udieresis -92 KPX Y ugrave -92 KPX Y uhungarumlaut -92 KPX Y umacron -92 KPX Y uogonek -92 KPX Y uring -92 KPX Yacute A -110 KPX Yacute Aacute -110 KPX Yacute Abreve -110 KPX Yacute Acircumflex -110 KPX Yacute Adieresis -110 KPX Yacute Agrave -110 KPX Yacute Amacron -110 KPX Yacute Aogonek -110 KPX Yacute Aring -110 KPX Yacute Atilde -110 KPX Yacute O -35 KPX Yacute Oacute -35 KPX Yacute Ocircumflex -35 KPX Yacute Odieresis -35 KPX Yacute Ograve -35 KPX Yacute Ohungarumlaut -35 KPX Yacute Omacron -35 KPX Yacute Oslash -35 KPX Yacute Otilde -35 KPX Yacute a -85 KPX Yacute aacute -85 KPX Yacute abreve -85 KPX Yacute acircumflex -85 KPX Yacute adieresis -85 KPX Yacute agrave -85 KPX Yacute amacron -85 KPX Yacute aogonek -85 KPX Yacute aring -85 KPX Yacute atilde -85 KPX Yacute colon -92 KPX Yacute comma -92 KPX Yacute e -111 KPX Yacute eacute -111 KPX Yacute ecaron -111 KPX Yacute ecircumflex -111 KPX Yacute edieresis -71 KPX Yacute edotaccent -111 KPX Yacute egrave -71 KPX Yacute emacron -71 KPX Yacute eogonek -111 KPX Yacute hyphen -92 KPX Yacute i -37 KPX Yacute iacute -37 KPX Yacute iogonek -37 KPX Yacute o -111 KPX Yacute oacute -111 KPX Yacute ocircumflex -111 KPX Yacute odieresis -111 KPX Yacute ograve -111 KPX Yacute ohungarumlaut -111 KPX Yacute omacron -111 KPX Yacute oslash -111 KPX Yacute otilde -111 KPX Yacute period -92 KPX Yacute semicolon -92 KPX Yacute u -92 KPX Yacute uacute -92 KPX Yacute ucircumflex -92 KPX Yacute udieresis -92 KPX Yacute ugrave -92 KPX Yacute uhungarumlaut -92 KPX Yacute umacron -92 KPX Yacute uogonek -92 KPX Yacute uring -92 KPX Ydieresis A -110 KPX Ydieresis Aacute -110 KPX Ydieresis Abreve -110 KPX Ydieresis Acircumflex -110 KPX Ydieresis Adieresis -110 KPX Ydieresis Agrave -110 KPX Ydieresis Amacron -110 KPX Ydieresis Aogonek -110 KPX Ydieresis Aring -110 KPX Ydieresis Atilde -110 KPX Ydieresis O -35 KPX Ydieresis Oacute -35 KPX Ydieresis Ocircumflex -35 KPX Ydieresis Odieresis -35 KPX Ydieresis Ograve -35 KPX Ydieresis Ohungarumlaut -35 KPX Ydieresis Omacron -35 KPX Ydieresis Oslash -35 KPX Ydieresis Otilde -35 KPX Ydieresis a -85 KPX Ydieresis aacute -85 KPX Ydieresis abreve -85 KPX Ydieresis acircumflex -85 KPX Ydieresis adieresis -85 KPX Ydieresis agrave -85 KPX Ydieresis amacron -85 KPX Ydieresis aogonek -85 KPX Ydieresis aring -85 KPX Ydieresis atilde -85 KPX Ydieresis colon -92 KPX Ydieresis comma -92 KPX Ydieresis e -111 KPX Ydieresis eacute -111 KPX Ydieresis ecaron -111 KPX Ydieresis ecircumflex -111 KPX Ydieresis edieresis -71 KPX Ydieresis edotaccent -111 KPX Ydieresis egrave -71 KPX Ydieresis emacron -71 KPX Ydieresis eogonek -111 KPX Ydieresis hyphen -92 KPX Ydieresis i -37 KPX Ydieresis iacute -37 KPX Ydieresis iogonek -37 KPX Ydieresis o -111 KPX Ydieresis oacute -111 KPX Ydieresis ocircumflex -111 KPX Ydieresis odieresis -111 KPX Ydieresis ograve -111 KPX Ydieresis ohungarumlaut -111 KPX Ydieresis omacron -111 KPX Ydieresis oslash -111 KPX Ydieresis otilde -111 KPX Ydieresis period -92 KPX Ydieresis semicolon -92 KPX Ydieresis u -92 KPX Ydieresis uacute -92 KPX Ydieresis ucircumflex -92 KPX Ydieresis udieresis -92 KPX Ydieresis ugrave -92 KPX Ydieresis uhungarumlaut -92 KPX Ydieresis umacron -92 KPX Ydieresis uogonek -92 KPX Ydieresis uring -92 KPX a v -25 KPX aacute v -25 KPX abreve v -25 KPX acircumflex v -25 KPX adieresis v -25 KPX agrave v -25 KPX amacron v -25 KPX aogonek v -25 KPX aring v -25 KPX atilde v -25 KPX b b -10 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -15 KPX comma quotedblright -45 KPX comma quoteright -55 KPX d w -15 KPX dcroat w -15 KPX e v -15 KPX eacute v -15 KPX ecaron v -15 KPX ecircumflex v -15 KPX edieresis v -15 KPX edotaccent v -15 KPX egrave v -15 KPX emacron v -15 KPX eogonek v -15 KPX f comma -15 KPX f dotlessi -35 KPX f i -25 KPX f o -25 KPX f oacute -25 KPX f ocircumflex -25 KPX f odieresis -25 KPX f ograve -25 KPX f ohungarumlaut -25 KPX f omacron -25 KPX f oslash -25 KPX f otilde -25 KPX f period -15 KPX f quotedblright 50 KPX f quoteright 55 KPX g period -15 KPX gbreve period -15 KPX gcommaaccent period -15 KPX h y -15 KPX h yacute -15 KPX h ydieresis -15 KPX i v -10 KPX iacute v -10 KPX icircumflex v -10 KPX idieresis v -10 KPX igrave v -10 KPX imacron v -10 KPX iogonek v -10 KPX k e -10 KPX k eacute -10 KPX k ecaron -10 KPX k ecircumflex -10 KPX k edieresis -10 KPX k edotaccent -10 KPX k egrave -10 KPX k emacron -10 KPX k eogonek -10 KPX k o -15 KPX k oacute -15 KPX k ocircumflex -15 KPX k odieresis -15 KPX k ograve -15 KPX k ohungarumlaut -15 KPX k omacron -15 KPX k oslash -15 KPX k otilde -15 KPX k y -15 KPX k yacute -15 KPX k ydieresis -15 KPX kcommaaccent e -10 KPX kcommaaccent eacute -10 KPX kcommaaccent ecaron -10 KPX kcommaaccent ecircumflex -10 KPX kcommaaccent edieresis -10 KPX kcommaaccent edotaccent -10 KPX kcommaaccent egrave -10 KPX kcommaaccent emacron -10 KPX kcommaaccent eogonek -10 KPX kcommaaccent o -15 KPX kcommaaccent oacute -15 KPX kcommaaccent ocircumflex -15 KPX kcommaaccent odieresis -15 KPX kcommaaccent ograve -15 KPX kcommaaccent ohungarumlaut -15 KPX kcommaaccent omacron -15 KPX kcommaaccent oslash -15 KPX kcommaaccent otilde -15 KPX kcommaaccent y -15 KPX kcommaaccent yacute -15 KPX kcommaaccent ydieresis -15 KPX n v -40 KPX nacute v -40 KPX ncaron v -40 KPX ncommaaccent v -40 KPX ntilde v -40 KPX o v -10 KPX o w -10 KPX oacute v -10 KPX oacute w -10 KPX ocircumflex v -10 KPX ocircumflex w -10 KPX odieresis v -10 KPX odieresis w -10 KPX ograve v -10 KPX ograve w -10 KPX ohungarumlaut v -10 KPX ohungarumlaut w -10 KPX omacron v -10 KPX omacron w -10 KPX oslash v -10 KPX oslash w -10 KPX otilde v -10 KPX otilde w -10 KPX period quotedblright -55 KPX period quoteright -55 KPX quotedblleft A -10 KPX quotedblleft Aacute -10 KPX quotedblleft Abreve -10 KPX quotedblleft Acircumflex -10 KPX quotedblleft Adieresis -10 KPX quotedblleft Agrave -10 KPX quotedblleft Amacron -10 KPX quotedblleft Aogonek -10 KPX quotedblleft Aring -10 KPX quotedblleft Atilde -10 KPX quoteleft A -10 KPX quoteleft Aacute -10 KPX quoteleft Abreve -10 KPX quoteleft Acircumflex -10 KPX quoteleft Adieresis -10 KPX quoteleft Agrave -10 KPX quoteleft Amacron -10 KPX quoteleft Aogonek -10 KPX quoteleft Aring -10 KPX quoteleft Atilde -10 KPX quoteleft quoteleft -63 KPX quoteright d -20 KPX quoteright dcroat -20 KPX quoteright quoteright -63 KPX quoteright r -20 KPX quoteright racute -20 KPX quoteright rcaron -20 KPX quoteright rcommaaccent -20 KPX quoteright s -37 KPX quoteright sacute -37 KPX quoteright scaron -37 KPX quoteright scedilla -37 KPX quoteright scommaaccent -37 KPX quoteright space -74 KPX quoteright v -20 KPX r c -18 KPX r cacute -18 KPX r ccaron -18 KPX r ccedilla -18 KPX r comma -92 KPX r e -18 KPX r eacute -18 KPX r ecaron -18 KPX r ecircumflex -18 KPX r edieresis -18 KPX r edotaccent -18 KPX r egrave -18 KPX r emacron -18 KPX r eogonek -18 KPX r g -10 KPX r gbreve -10 KPX r gcommaaccent -10 KPX r hyphen -37 KPX r n -15 KPX r nacute -15 KPX r ncaron -15 KPX r ncommaaccent -15 KPX r ntilde -15 KPX r o -18 KPX r oacute -18 KPX r ocircumflex -18 KPX r odieresis -18 KPX r ograve -18 KPX r ohungarumlaut -18 KPX r omacron -18 KPX r oslash -18 KPX r otilde -18 KPX r p -10 KPX r period -100 KPX r q -18 KPX r v -10 KPX racute c -18 KPX racute cacute -18 KPX racute ccaron -18 KPX racute ccedilla -18 KPX racute comma -92 KPX racute e -18 KPX racute eacute -18 KPX racute ecaron -18 KPX racute ecircumflex -18 KPX racute edieresis -18 KPX racute edotaccent -18 KPX racute egrave -18 KPX racute emacron -18 KPX racute eogonek -18 KPX racute g -10 KPX racute gbreve -10 KPX racute gcommaaccent -10 KPX racute hyphen -37 KPX racute n -15 KPX racute nacute -15 KPX racute ncaron -15 KPX racute ncommaaccent -15 KPX racute ntilde -15 KPX racute o -18 KPX racute oacute -18 KPX racute ocircumflex -18 KPX racute odieresis -18 KPX racute ograve -18 KPX racute ohungarumlaut -18 KPX racute omacron -18 KPX racute oslash -18 KPX racute otilde -18 KPX racute p -10 KPX racute period -100 KPX racute q -18 KPX racute v -10 KPX rcaron c -18 KPX rcaron cacute -18 KPX rcaron ccaron -18 KPX rcaron ccedilla -18 KPX rcaron comma -92 KPX rcaron e -18 KPX rcaron eacute -18 KPX rcaron ecaron -18 KPX rcaron ecircumflex -18 KPX rcaron edieresis -18 KPX rcaron edotaccent -18 KPX rcaron egrave -18 KPX rcaron emacron -18 KPX rcaron eogonek -18 KPX rcaron g -10 KPX rcaron gbreve -10 KPX rcaron gcommaaccent -10 KPX rcaron hyphen -37 KPX rcaron n -15 KPX rcaron nacute -15 KPX rcaron ncaron -15 KPX rcaron ncommaaccent -15 KPX rcaron ntilde -15 KPX rcaron o -18 KPX rcaron oacute -18 KPX rcaron ocircumflex -18 KPX rcaron odieresis -18 KPX rcaron ograve -18 KPX rcaron ohungarumlaut -18 KPX rcaron omacron -18 KPX rcaron oslash -18 KPX rcaron otilde -18 KPX rcaron p -10 KPX rcaron period -100 KPX rcaron q -18 KPX rcaron v -10 KPX rcommaaccent c -18 KPX rcommaaccent cacute -18 KPX rcommaaccent ccaron -18 KPX rcommaaccent ccedilla -18 KPX rcommaaccent comma -92 KPX rcommaaccent e -18 KPX rcommaaccent eacute -18 KPX rcommaaccent ecaron -18 KPX rcommaaccent ecircumflex -18 KPX rcommaaccent edieresis -18 KPX rcommaaccent edotaccent -18 KPX rcommaaccent egrave -18 KPX rcommaaccent emacron -18 KPX rcommaaccent eogonek -18 KPX rcommaaccent g -10 KPX rcommaaccent gbreve -10 KPX rcommaaccent gcommaaccent -10 KPX rcommaaccent hyphen -37 KPX rcommaaccent n -15 KPX rcommaaccent nacute -15 KPX rcommaaccent ncaron -15 KPX rcommaaccent ncommaaccent -15 KPX rcommaaccent ntilde -15 KPX rcommaaccent o -18 KPX rcommaaccent oacute -18 KPX rcommaaccent ocircumflex -18 KPX rcommaaccent odieresis -18 KPX rcommaaccent ograve -18 KPX rcommaaccent ohungarumlaut -18 KPX rcommaaccent omacron -18 KPX rcommaaccent oslash -18 KPX rcommaaccent otilde -18 KPX rcommaaccent p -10 KPX rcommaaccent period -100 KPX rcommaaccent q -18 KPX rcommaaccent v -10 KPX space A -55 KPX space Aacute -55 KPX space Abreve -55 KPX space Acircumflex -55 KPX space Adieresis -55 KPX space Agrave -55 KPX space Amacron -55 KPX space Aogonek -55 KPX space Aring -55 KPX space Atilde -55 KPX space T -30 KPX space Tcaron -30 KPX space Tcommaaccent -30 KPX space V -45 KPX space W -30 KPX space Y -55 KPX space Yacute -55 KPX space Ydieresis -55 KPX v a -10 KPX v aacute -10 KPX v abreve -10 KPX v acircumflex -10 KPX v adieresis -10 KPX v agrave -10 KPX v amacron -10 KPX v aogonek -10 KPX v aring -10 KPX v atilde -10 KPX v comma -55 KPX v e -10 KPX v eacute -10 KPX v ecaron -10 KPX v ecircumflex -10 KPX v edieresis -10 KPX v edotaccent -10 KPX v egrave -10 KPX v emacron -10 KPX v eogonek -10 KPX v o -10 KPX v oacute -10 KPX v ocircumflex -10 KPX v odieresis -10 KPX v ograve -10 KPX v ohungarumlaut -10 KPX v omacron -10 KPX v oslash -10 KPX v otilde -10 KPX v period -70 KPX w comma -55 KPX w o -10 KPX w oacute -10 KPX w ocircumflex -10 KPX w odieresis -10 KPX w ograve -10 KPX w ohungarumlaut -10 KPX w omacron -10 KPX w oslash -10 KPX w otilde -10 KPX w period -70 KPX y comma -55 KPX y e -10 KPX y eacute -10 KPX y ecaron -10 KPX y ecircumflex -10 KPX y edieresis -10 KPX y edotaccent -10 KPX y egrave -10 KPX y emacron -10 KPX y eogonek -10 KPX y o -25 KPX y oacute -25 KPX y ocircumflex -25 KPX y odieresis -25 KPX y ograve -25 KPX y ohungarumlaut -25 KPX y omacron -25 KPX y oslash -25 KPX y otilde -25 KPX y period -70 KPX yacute comma -55 KPX yacute e -10 KPX yacute eacute -10 KPX yacute ecaron -10 KPX yacute ecircumflex -10 KPX yacute edieresis -10 KPX yacute edotaccent -10 KPX yacute egrave -10 KPX yacute emacron -10 KPX yacute eogonek -10 KPX yacute o -25 KPX yacute oacute -25 KPX yacute ocircumflex -25 KPX yacute odieresis -25 KPX yacute ograve -25 KPX yacute ohungarumlaut -25 KPX yacute omacron -25 KPX yacute oslash -25 KPX yacute otilde -25 KPX yacute period -70 KPX ydieresis comma -55 KPX ydieresis e -10 KPX ydieresis eacute -10 KPX ydieresis ecaron -10 KPX ydieresis ecircumflex -10 KPX ydieresis edieresis -10 KPX ydieresis edotaccent -10 KPX ydieresis egrave -10 KPX ydieresis emacron -10 KPX ydieresis eogonek -10 KPX ydieresis o -25 KPX ydieresis oacute -25 KPX ydieresis ocircumflex -25 KPX ydieresis odieresis -25 KPX ydieresis ograve -25 KPX ydieresis ohungarumlaut -25 KPX ydieresis omacron -25 KPX ydieresis oslash -25 KPX ydieresis otilde -25 KPX ydieresis period -70 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Times-BoldItalic.afm0000644000076500000240000017111212037547555020617 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 13:04:06 1997 Comment UniqueID 43066 Comment VMusage 45874 56899 FontName Times-BoldItalic FullName Times Bold Italic FamilyName Times Weight Bold ItalicAngle -15 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -200 -218 996 921 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 669 XHeight 462 Ascender 683 Descender -217 StdHW 42 StdVW 121 StartCharMetrics 315 C 32 ; WX 250 ; N space ; B 0 0 0 0 ; C 33 ; WX 389 ; N exclam ; B 67 -13 370 684 ; C 34 ; WX 555 ; N quotedbl ; B 136 398 536 685 ; C 35 ; WX 500 ; N numbersign ; B -33 0 533 700 ; C 36 ; WX 500 ; N dollar ; B -20 -100 497 733 ; C 37 ; WX 833 ; N percent ; B 39 -10 793 692 ; C 38 ; WX 778 ; N ampersand ; B 5 -19 699 682 ; C 39 ; WX 333 ; N quoteright ; B 98 369 302 685 ; C 40 ; WX 333 ; N parenleft ; B 28 -179 344 685 ; C 41 ; WX 333 ; N parenright ; B -44 -179 271 685 ; C 42 ; WX 500 ; N asterisk ; B 65 249 456 685 ; C 43 ; WX 570 ; N plus ; B 33 0 537 506 ; C 44 ; WX 250 ; N comma ; B -60 -182 144 134 ; C 45 ; WX 333 ; N hyphen ; B 2 166 271 282 ; C 46 ; WX 250 ; N period ; B -9 -13 139 135 ; C 47 ; WX 278 ; N slash ; B -64 -18 342 685 ; C 48 ; WX 500 ; N zero ; B 17 -14 477 683 ; C 49 ; WX 500 ; N one ; B 5 0 419 683 ; C 50 ; WX 500 ; N two ; B -27 0 446 683 ; C 51 ; WX 500 ; N three ; B -15 -13 450 683 ; C 52 ; WX 500 ; N four ; B -15 0 503 683 ; C 53 ; WX 500 ; N five ; B -11 -13 487 669 ; C 54 ; WX 500 ; N six ; B 23 -15 509 679 ; C 55 ; WX 500 ; N seven ; B 52 0 525 669 ; C 56 ; WX 500 ; N eight ; B 3 -13 476 683 ; C 57 ; WX 500 ; N nine ; B -12 -10 475 683 ; C 58 ; WX 333 ; N colon ; B 23 -13 264 459 ; C 59 ; WX 333 ; N semicolon ; B -25 -183 264 459 ; C 60 ; WX 570 ; N less ; B 31 -8 539 514 ; C 61 ; WX 570 ; N equal ; B 33 107 537 399 ; C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ; C 63 ; WX 500 ; N question ; B 79 -13 470 684 ; C 64 ; WX 832 ; N at ; B 63 -18 770 685 ; C 65 ; WX 667 ; N A ; B -67 0 593 683 ; C 66 ; WX 667 ; N B ; B -24 0 624 669 ; C 67 ; WX 667 ; N C ; B 32 -18 677 685 ; C 68 ; WX 722 ; N D ; B -46 0 685 669 ; C 69 ; WX 667 ; N E ; B -27 0 653 669 ; C 70 ; WX 667 ; N F ; B -13 0 660 669 ; C 71 ; WX 722 ; N G ; B 21 -18 706 685 ; C 72 ; WX 778 ; N H ; B -24 0 799 669 ; C 73 ; WX 389 ; N I ; B -32 0 406 669 ; C 74 ; WX 500 ; N J ; B -46 -99 524 669 ; C 75 ; WX 667 ; N K ; B -21 0 702 669 ; C 76 ; WX 611 ; N L ; B -22 0 590 669 ; C 77 ; WX 889 ; N M ; B -29 -12 917 669 ; C 78 ; WX 722 ; N N ; B -27 -15 748 669 ; C 79 ; WX 722 ; N O ; B 27 -18 691 685 ; C 80 ; WX 611 ; N P ; B -27 0 613 669 ; C 81 ; WX 722 ; N Q ; B 27 -208 691 685 ; C 82 ; WX 667 ; N R ; B -29 0 623 669 ; C 83 ; WX 556 ; N S ; B 2 -18 526 685 ; C 84 ; WX 611 ; N T ; B 50 0 650 669 ; C 85 ; WX 722 ; N U ; B 67 -18 744 669 ; C 86 ; WX 667 ; N V ; B 65 -18 715 669 ; C 87 ; WX 889 ; N W ; B 65 -18 940 669 ; C 88 ; WX 667 ; N X ; B -24 0 694 669 ; C 89 ; WX 611 ; N Y ; B 73 0 659 669 ; C 90 ; WX 611 ; N Z ; B -11 0 590 669 ; C 91 ; WX 333 ; N bracketleft ; B -37 -159 362 674 ; C 92 ; WX 278 ; N backslash ; B -1 -18 279 685 ; C 93 ; WX 333 ; N bracketright ; B -56 -157 343 674 ; C 94 ; WX 570 ; N asciicircum ; B 67 304 503 669 ; C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; C 96 ; WX 333 ; N quoteleft ; B 128 369 332 685 ; C 97 ; WX 500 ; N a ; B -21 -14 455 462 ; C 98 ; WX 500 ; N b ; B -14 -13 444 699 ; C 99 ; WX 444 ; N c ; B -5 -13 392 462 ; C 100 ; WX 500 ; N d ; B -21 -13 517 699 ; C 101 ; WX 444 ; N e ; B 5 -13 398 462 ; C 102 ; WX 333 ; N f ; B -169 -205 446 698 ; L i fi ; L l fl ; C 103 ; WX 500 ; N g ; B -52 -203 478 462 ; C 104 ; WX 556 ; N h ; B -13 -9 498 699 ; C 105 ; WX 278 ; N i ; B 2 -9 263 684 ; C 106 ; WX 278 ; N j ; B -189 -207 279 684 ; C 107 ; WX 500 ; N k ; B -23 -8 483 699 ; C 108 ; WX 278 ; N l ; B 2 -9 290 699 ; C 109 ; WX 778 ; N m ; B -14 -9 722 462 ; C 110 ; WX 556 ; N n ; B -6 -9 493 462 ; C 111 ; WX 500 ; N o ; B -3 -13 441 462 ; C 112 ; WX 500 ; N p ; B -120 -205 446 462 ; C 113 ; WX 500 ; N q ; B 1 -205 471 462 ; C 114 ; WX 389 ; N r ; B -21 0 389 462 ; C 115 ; WX 389 ; N s ; B -19 -13 333 462 ; C 116 ; WX 278 ; N t ; B -11 -9 281 594 ; C 117 ; WX 556 ; N u ; B 15 -9 492 462 ; C 118 ; WX 444 ; N v ; B 16 -13 401 462 ; C 119 ; WX 667 ; N w ; B 16 -13 614 462 ; C 120 ; WX 500 ; N x ; B -46 -13 469 462 ; C 121 ; WX 444 ; N y ; B -94 -205 392 462 ; C 122 ; WX 389 ; N z ; B -43 -78 368 449 ; C 123 ; WX 348 ; N braceleft ; B 5 -187 436 686 ; C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ; C 125 ; WX 348 ; N braceright ; B -129 -187 302 686 ; C 126 ; WX 570 ; N asciitilde ; B 54 173 516 333 ; C 161 ; WX 389 ; N exclamdown ; B 19 -205 322 492 ; C 162 ; WX 500 ; N cent ; B 42 -143 439 576 ; C 163 ; WX 500 ; N sterling ; B -32 -12 510 683 ; C 164 ; WX 167 ; N fraction ; B -169 -14 324 683 ; C 165 ; WX 500 ; N yen ; B 33 0 628 669 ; C 166 ; WX 500 ; N florin ; B -87 -156 537 707 ; C 167 ; WX 500 ; N section ; B 36 -143 459 685 ; C 168 ; WX 500 ; N currency ; B -26 34 526 586 ; C 169 ; WX 278 ; N quotesingle ; B 128 398 268 685 ; C 170 ; WX 500 ; N quotedblleft ; B 53 369 513 685 ; C 171 ; WX 500 ; N guillemotleft ; B 12 32 468 415 ; C 172 ; WX 333 ; N guilsinglleft ; B 32 32 303 415 ; C 173 ; WX 333 ; N guilsinglright ; B 10 32 281 415 ; C 174 ; WX 556 ; N fi ; B -188 -205 514 703 ; C 175 ; WX 556 ; N fl ; B -186 -205 553 704 ; C 177 ; WX 500 ; N endash ; B -40 178 477 269 ; C 178 ; WX 500 ; N dagger ; B 91 -145 494 685 ; C 179 ; WX 500 ; N daggerdbl ; B 10 -139 493 685 ; C 180 ; WX 250 ; N periodcentered ; B 51 257 199 405 ; C 182 ; WX 500 ; N paragraph ; B -57 -193 562 669 ; C 183 ; WX 350 ; N bullet ; B 0 175 350 525 ; C 184 ; WX 333 ; N quotesinglbase ; B -5 -182 199 134 ; C 185 ; WX 500 ; N quotedblbase ; B -57 -182 403 134 ; C 186 ; WX 500 ; N quotedblright ; B 53 369 513 685 ; C 187 ; WX 500 ; N guillemotright ; B 12 32 468 415 ; C 188 ; WX 1000 ; N ellipsis ; B 40 -13 852 135 ; C 189 ; WX 1000 ; N perthousand ; B 7 -29 996 706 ; C 191 ; WX 500 ; N questiondown ; B 30 -205 421 492 ; C 193 ; WX 333 ; N grave ; B 85 516 297 697 ; C 194 ; WX 333 ; N acute ; B 139 516 379 697 ; C 195 ; WX 333 ; N circumflex ; B 40 516 367 690 ; C 196 ; WX 333 ; N tilde ; B 48 536 407 655 ; C 197 ; WX 333 ; N macron ; B 51 553 393 623 ; C 198 ; WX 333 ; N breve ; B 71 516 387 678 ; C 199 ; WX 333 ; N dotaccent ; B 163 550 298 684 ; C 200 ; WX 333 ; N dieresis ; B 55 550 402 684 ; C 202 ; WX 333 ; N ring ; B 127 516 340 729 ; C 203 ; WX 333 ; N cedilla ; B -80 -218 156 5 ; C 205 ; WX 333 ; N hungarumlaut ; B 69 516 498 697 ; C 206 ; WX 333 ; N ogonek ; B 15 -183 244 34 ; C 207 ; WX 333 ; N caron ; B 79 516 411 690 ; C 208 ; WX 1000 ; N emdash ; B -40 178 977 269 ; C 225 ; WX 944 ; N AE ; B -64 0 918 669 ; C 227 ; WX 266 ; N ordfeminine ; B 16 399 330 685 ; C 232 ; WX 611 ; N Lslash ; B -22 0 590 669 ; C 233 ; WX 722 ; N Oslash ; B 27 -125 691 764 ; C 234 ; WX 944 ; N OE ; B 23 -8 946 677 ; C 235 ; WX 300 ; N ordmasculine ; B 56 400 347 685 ; C 241 ; WX 722 ; N ae ; B -5 -13 673 462 ; C 245 ; WX 278 ; N dotlessi ; B 2 -9 238 462 ; C 248 ; WX 278 ; N lslash ; B -7 -9 307 699 ; C 249 ; WX 500 ; N oslash ; B -3 -119 441 560 ; C 250 ; WX 722 ; N oe ; B 6 -13 674 462 ; C 251 ; WX 500 ; N germandbls ; B -200 -200 473 705 ; C -1 ; WX 389 ; N Idieresis ; B -32 0 450 862 ; C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ; C -1 ; WX 500 ; N abreve ; B -21 -14 471 678 ; C -1 ; WX 556 ; N uhungarumlaut ; B 15 -9 610 697 ; C -1 ; WX 444 ; N ecaron ; B 5 -13 467 690 ; C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ; C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ; C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ; C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ; C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ; C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ; C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ; C -1 ; WX 389 ; N scommaaccent ; B -19 -218 333 462 ; C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ; C -1 ; WX 722 ; N Uring ; B 67 -18 744 921 ; C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ; C -1 ; WX 500 ; N aogonek ; B -21 -183 455 462 ; C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ; C -1 ; WX 556 ; N uogonek ; B 15 -183 492 462 ; C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ; C -1 ; WX 722 ; N Dcroat ; B -31 0 700 669 ; C -1 ; WX 250 ; N commaaccent ; B -36 -218 131 -50 ; C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ; C -1 ; WX 667 ; N Emacron ; B -27 0 653 830 ; C -1 ; WX 444 ; N ccaron ; B -5 -13 467 690 ; C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ; C -1 ; WX 722 ; N Ncommaaccent ; B -27 -218 748 669 ; C -1 ; WX 278 ; N lacute ; B 2 -9 392 904 ; C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ; C -1 ; WX 611 ; N Tcommaaccent ; B 50 -218 650 669 ; C -1 ; WX 667 ; N Cacute ; B 32 -18 677 904 ; C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ; C -1 ; WX 667 ; N Edotaccent ; B -27 0 653 862 ; C -1 ; WX 389 ; N scaron ; B -19 -13 424 690 ; C -1 ; WX 389 ; N scedilla ; B -19 -218 333 462 ; C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ; C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ; C -1 ; WX 667 ; N Rcaron ; B -29 0 623 897 ; C -1 ; WX 722 ; N Gcommaaccent ; B 21 -218 706 685 ; C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ; C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ; C -1 ; WX 667 ; N Amacron ; B -67 0 593 830 ; C -1 ; WX 389 ; N rcaron ; B -21 0 424 690 ; C -1 ; WX 444 ; N ccedilla ; B -5 -218 392 462 ; C -1 ; WX 611 ; N Zdotaccent ; B -11 0 590 862 ; C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ; C -1 ; WX 722 ; N Omacron ; B 27 -18 691 830 ; C -1 ; WX 667 ; N Racute ; B -29 0 623 904 ; C -1 ; WX 556 ; N Sacute ; B 2 -18 531 904 ; C -1 ; WX 608 ; N dcaron ; B -21 -13 675 708 ; C -1 ; WX 722 ; N Umacron ; B 67 -18 744 830 ; C -1 ; WX 556 ; N uring ; B 15 -9 492 729 ; C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ; C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ; C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ; C -1 ; WX 667 ; N Abreve ; B -67 0 593 885 ; C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ; C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ; C -1 ; WX 611 ; N Tcaron ; B 50 0 650 897 ; C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ; C -1 ; WX 444 ; N ydieresis ; B -94 -205 443 655 ; C -1 ; WX 722 ; N Nacute ; B -27 -15 748 904 ; C -1 ; WX 278 ; N icircumflex ; B -3 -9 324 690 ; C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ; C -1 ; WX 500 ; N adieresis ; B -21 -14 476 655 ; C -1 ; WX 444 ; N edieresis ; B 5 -13 448 655 ; C -1 ; WX 444 ; N cacute ; B -5 -13 435 697 ; C -1 ; WX 556 ; N nacute ; B -6 -9 493 697 ; C -1 ; WX 556 ; N umacron ; B 15 -9 492 623 ; C -1 ; WX 722 ; N Ncaron ; B -27 -15 748 897 ; C -1 ; WX 389 ; N Iacute ; B -32 0 432 904 ; C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ; C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ; C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ; C -1 ; WX 722 ; N Gbreve ; B 21 -18 706 885 ; C -1 ; WX 389 ; N Idotaccent ; B -32 0 406 862 ; C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ; C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ; C -1 ; WX 389 ; N racute ; B -21 0 407 697 ; C -1 ; WX 500 ; N omacron ; B -3 -13 462 623 ; C -1 ; WX 611 ; N Zacute ; B -11 0 590 904 ; C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ; C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ; C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ; C -1 ; WX 278 ; N lcommaaccent ; B -42 -218 290 699 ; C -1 ; WX 366 ; N tcaron ; B -11 -9 434 754 ; C -1 ; WX 444 ; N eogonek ; B 5 -183 398 462 ; C -1 ; WX 722 ; N Uogonek ; B 67 -183 744 669 ; C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ; C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ; C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ; C -1 ; WX 389 ; N zacute ; B -43 -78 407 697 ; C -1 ; WX 278 ; N iogonek ; B -20 -183 263 684 ; C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ; C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ; C -1 ; WX 500 ; N amacron ; B -21 -14 467 623 ; C -1 ; WX 389 ; N sacute ; B -19 -13 407 697 ; C -1 ; WX 278 ; N idieresis ; B 2 -9 364 655 ; C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ; C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ; C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ; C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ; C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ; C -1 ; WX 278 ; N igrave ; B 2 -9 259 697 ; C -1 ; WX 500 ; N ohungarumlaut ; B -3 -13 582 697 ; C -1 ; WX 667 ; N Eogonek ; B -27 -183 653 669 ; C -1 ; WX 500 ; N dcroat ; B -21 -13 552 699 ; C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ; C -1 ; WX 556 ; N Scedilla ; B 2 -218 526 685 ; C -1 ; WX 382 ; N lcaron ; B 2 -9 448 708 ; C -1 ; WX 667 ; N Kcommaaccent ; B -21 -218 702 669 ; C -1 ; WX 611 ; N Lacute ; B -22 0 590 904 ; C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ; C -1 ; WX 444 ; N edotaccent ; B 5 -13 398 655 ; C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ; C -1 ; WX 389 ; N Imacron ; B -32 0 461 830 ; C -1 ; WX 611 ; N Lcaron ; B -22 0 671 718 ; C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ; C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ; C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ; C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 67 -18 744 904 ; C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ; C -1 ; WX 444 ; N emacron ; B 5 -13 439 623 ; C -1 ; WX 500 ; N gbreve ; B -52 -203 478 678 ; C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ; C -1 ; WX 556 ; N Scaron ; B 2 -18 553 897 ; C -1 ; WX 556 ; N Scommaaccent ; B 2 -218 526 685 ; C -1 ; WX 722 ; N Ohungarumlaut ; B 27 -18 723 904 ; C -1 ; WX 400 ; N degree ; B 83 397 369 683 ; C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ; C -1 ; WX 667 ; N Ccaron ; B 32 -18 677 897 ; C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ; C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ; C -1 ; WX 722 ; N Dcaron ; B -46 0 685 897 ; C -1 ; WX 389 ; N rcommaaccent ; B -67 -218 389 462 ; C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ; C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ; C -1 ; WX 667 ; N Rcommaaccent ; B -29 -218 623 669 ; C -1 ; WX 611 ; N Lcommaaccent ; B -22 -218 590 669 ; C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ; C -1 ; WX 667 ; N Aogonek ; B -67 -183 604 683 ; C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ; C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ; C -1 ; WX 389 ; N zdotaccent ; B -43 -78 368 655 ; C -1 ; WX 667 ; N Ecaron ; B -27 0 653 897 ; C -1 ; WX 389 ; N Iogonek ; B -32 -183 406 669 ; C -1 ; WX 500 ; N kcommaaccent ; B -23 -218 483 699 ; C -1 ; WX 606 ; N minus ; B 51 209 555 297 ; C -1 ; WX 389 ; N Icircumflex ; B -32 0 450 897 ; C -1 ; WX 556 ; N ncaron ; B -6 -9 523 690 ; C -1 ; WX 278 ; N tcommaaccent ; B -62 -218 281 594 ; C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ; C -1 ; WX 500 ; N odieresis ; B -3 -13 471 655 ; C -1 ; WX 556 ; N udieresis ; B 15 -9 499 655 ; C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ; C -1 ; WX 500 ; N gcommaaccent ; B -52 -203 478 767 ; C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ; C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ; C -1 ; WX 556 ; N ncommaaccent ; B -6 -218 493 462 ; C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ; C -1 ; WX 278 ; N imacron ; B 2 -9 294 623 ; C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2038 KPX A C -65 KPX A Cacute -65 KPX A Ccaron -65 KPX A Ccedilla -65 KPX A G -60 KPX A Gbreve -60 KPX A Gcommaaccent -60 KPX A O -50 KPX A Oacute -50 KPX A Ocircumflex -50 KPX A Odieresis -50 KPX A Ograve -50 KPX A Ohungarumlaut -50 KPX A Omacron -50 KPX A Oslash -50 KPX A Otilde -50 KPX A Q -55 KPX A T -55 KPX A Tcaron -55 KPX A Tcommaaccent -55 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -95 KPX A W -100 KPX A Y -70 KPX A Yacute -70 KPX A Ydieresis -70 KPX A quoteright -74 KPX A u -30 KPX A uacute -30 KPX A ucircumflex -30 KPX A udieresis -30 KPX A ugrave -30 KPX A uhungarumlaut -30 KPX A umacron -30 KPX A uogonek -30 KPX A uring -30 KPX A v -74 KPX A w -74 KPX A y -74 KPX A yacute -74 KPX A ydieresis -74 KPX Aacute C -65 KPX Aacute Cacute -65 KPX Aacute Ccaron -65 KPX Aacute Ccedilla -65 KPX Aacute G -60 KPX Aacute Gbreve -60 KPX Aacute Gcommaaccent -60 KPX Aacute O -50 KPX Aacute Oacute -50 KPX Aacute Ocircumflex -50 KPX Aacute Odieresis -50 KPX Aacute Ograve -50 KPX Aacute Ohungarumlaut -50 KPX Aacute Omacron -50 KPX Aacute Oslash -50 KPX Aacute Otilde -50 KPX Aacute Q -55 KPX Aacute T -55 KPX Aacute Tcaron -55 KPX Aacute Tcommaaccent -55 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -95 KPX Aacute W -100 KPX Aacute Y -70 KPX Aacute Yacute -70 KPX Aacute Ydieresis -70 KPX Aacute quoteright -74 KPX Aacute u -30 KPX Aacute uacute -30 KPX Aacute ucircumflex -30 KPX Aacute udieresis -30 KPX Aacute ugrave -30 KPX Aacute uhungarumlaut -30 KPX Aacute umacron -30 KPX Aacute uogonek -30 KPX Aacute uring -30 KPX Aacute v -74 KPX Aacute w -74 KPX Aacute y -74 KPX Aacute yacute -74 KPX Aacute ydieresis -74 KPX Abreve C -65 KPX Abreve Cacute -65 KPX Abreve Ccaron -65 KPX Abreve Ccedilla -65 KPX Abreve G -60 KPX Abreve Gbreve -60 KPX Abreve Gcommaaccent -60 KPX Abreve O -50 KPX Abreve Oacute -50 KPX Abreve Ocircumflex -50 KPX Abreve Odieresis -50 KPX Abreve Ograve -50 KPX Abreve Ohungarumlaut -50 KPX Abreve Omacron -50 KPX Abreve Oslash -50 KPX Abreve Otilde -50 KPX Abreve Q -55 KPX Abreve T -55 KPX Abreve Tcaron -55 KPX Abreve Tcommaaccent -55 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -95 KPX Abreve W -100 KPX Abreve Y -70 KPX Abreve Yacute -70 KPX Abreve Ydieresis -70 KPX Abreve quoteright -74 KPX Abreve u -30 KPX Abreve uacute -30 KPX Abreve ucircumflex -30 KPX Abreve udieresis -30 KPX Abreve ugrave -30 KPX Abreve uhungarumlaut -30 KPX Abreve umacron -30 KPX Abreve uogonek -30 KPX Abreve uring -30 KPX Abreve v -74 KPX Abreve w -74 KPX Abreve y -74 KPX Abreve yacute -74 KPX Abreve ydieresis -74 KPX Acircumflex C -65 KPX Acircumflex Cacute -65 KPX Acircumflex Ccaron -65 KPX Acircumflex Ccedilla -65 KPX Acircumflex G -60 KPX Acircumflex Gbreve -60 KPX Acircumflex Gcommaaccent -60 KPX Acircumflex O -50 KPX Acircumflex Oacute -50 KPX Acircumflex Ocircumflex -50 KPX Acircumflex Odieresis -50 KPX Acircumflex Ograve -50 KPX Acircumflex Ohungarumlaut -50 KPX Acircumflex Omacron -50 KPX Acircumflex Oslash -50 KPX Acircumflex Otilde -50 KPX Acircumflex Q -55 KPX Acircumflex T -55 KPX Acircumflex Tcaron -55 KPX Acircumflex Tcommaaccent -55 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -95 KPX Acircumflex W -100 KPX Acircumflex Y -70 KPX Acircumflex Yacute -70 KPX Acircumflex Ydieresis -70 KPX Acircumflex quoteright -74 KPX Acircumflex u -30 KPX Acircumflex uacute -30 KPX Acircumflex ucircumflex -30 KPX Acircumflex udieresis -30 KPX Acircumflex ugrave -30 KPX Acircumflex uhungarumlaut -30 KPX Acircumflex umacron -30 KPX Acircumflex uogonek -30 KPX Acircumflex uring -30 KPX Acircumflex v -74 KPX Acircumflex w -74 KPX Acircumflex y -74 KPX Acircumflex yacute -74 KPX Acircumflex ydieresis -74 KPX Adieresis C -65 KPX Adieresis Cacute -65 KPX Adieresis Ccaron -65 KPX Adieresis Ccedilla -65 KPX Adieresis G -60 KPX Adieresis Gbreve -60 KPX Adieresis Gcommaaccent -60 KPX Adieresis O -50 KPX Adieresis Oacute -50 KPX Adieresis Ocircumflex -50 KPX Adieresis Odieresis -50 KPX Adieresis Ograve -50 KPX Adieresis Ohungarumlaut -50 KPX Adieresis Omacron -50 KPX Adieresis Oslash -50 KPX Adieresis Otilde -50 KPX Adieresis Q -55 KPX Adieresis T -55 KPX Adieresis Tcaron -55 KPX Adieresis Tcommaaccent -55 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -95 KPX Adieresis W -100 KPX Adieresis Y -70 KPX Adieresis Yacute -70 KPX Adieresis Ydieresis -70 KPX Adieresis quoteright -74 KPX Adieresis u -30 KPX Adieresis uacute -30 KPX Adieresis ucircumflex -30 KPX Adieresis udieresis -30 KPX Adieresis ugrave -30 KPX Adieresis uhungarumlaut -30 KPX Adieresis umacron -30 KPX Adieresis uogonek -30 KPX Adieresis uring -30 KPX Adieresis v -74 KPX Adieresis w -74 KPX Adieresis y -74 KPX Adieresis yacute -74 KPX Adieresis ydieresis -74 KPX Agrave C -65 KPX Agrave Cacute -65 KPX Agrave Ccaron -65 KPX Agrave Ccedilla -65 KPX Agrave G -60 KPX Agrave Gbreve -60 KPX Agrave Gcommaaccent -60 KPX Agrave O -50 KPX Agrave Oacute -50 KPX Agrave Ocircumflex -50 KPX Agrave Odieresis -50 KPX Agrave Ograve -50 KPX Agrave Ohungarumlaut -50 KPX Agrave Omacron -50 KPX Agrave Oslash -50 KPX Agrave Otilde -50 KPX Agrave Q -55 KPX Agrave T -55 KPX Agrave Tcaron -55 KPX Agrave Tcommaaccent -55 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -95 KPX Agrave W -100 KPX Agrave Y -70 KPX Agrave Yacute -70 KPX Agrave Ydieresis -70 KPX Agrave quoteright -74 KPX Agrave u -30 KPX Agrave uacute -30 KPX Agrave ucircumflex -30 KPX Agrave udieresis -30 KPX Agrave ugrave -30 KPX Agrave uhungarumlaut -30 KPX Agrave umacron -30 KPX Agrave uogonek -30 KPX Agrave uring -30 KPX Agrave v -74 KPX Agrave w -74 KPX Agrave y -74 KPX Agrave yacute -74 KPX Agrave ydieresis -74 KPX Amacron C -65 KPX Amacron Cacute -65 KPX Amacron Ccaron -65 KPX Amacron Ccedilla -65 KPX Amacron G -60 KPX Amacron Gbreve -60 KPX Amacron Gcommaaccent -60 KPX Amacron O -50 KPX Amacron Oacute -50 KPX Amacron Ocircumflex -50 KPX Amacron Odieresis -50 KPX Amacron Ograve -50 KPX Amacron Ohungarumlaut -50 KPX Amacron Omacron -50 KPX Amacron Oslash -50 KPX Amacron Otilde -50 KPX Amacron Q -55 KPX Amacron T -55 KPX Amacron Tcaron -55 KPX Amacron Tcommaaccent -55 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -95 KPX Amacron W -100 KPX Amacron Y -70 KPX Amacron Yacute -70 KPX Amacron Ydieresis -70 KPX Amacron quoteright -74 KPX Amacron u -30 KPX Amacron uacute -30 KPX Amacron ucircumflex -30 KPX Amacron udieresis -30 KPX Amacron ugrave -30 KPX Amacron uhungarumlaut -30 KPX Amacron umacron -30 KPX Amacron uogonek -30 KPX Amacron uring -30 KPX Amacron v -74 KPX Amacron w -74 KPX Amacron y -74 KPX Amacron yacute -74 KPX Amacron ydieresis -74 KPX Aogonek C -65 KPX Aogonek Cacute -65 KPX Aogonek Ccaron -65 KPX Aogonek Ccedilla -65 KPX Aogonek G -60 KPX Aogonek Gbreve -60 KPX Aogonek Gcommaaccent -60 KPX Aogonek O -50 KPX Aogonek Oacute -50 KPX Aogonek Ocircumflex -50 KPX Aogonek Odieresis -50 KPX Aogonek Ograve -50 KPX Aogonek Ohungarumlaut -50 KPX Aogonek Omacron -50 KPX Aogonek Oslash -50 KPX Aogonek Otilde -50 KPX Aogonek Q -55 KPX Aogonek T -55 KPX Aogonek Tcaron -55 KPX Aogonek Tcommaaccent -55 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -95 KPX Aogonek W -100 KPX Aogonek Y -70 KPX Aogonek Yacute -70 KPX Aogonek Ydieresis -70 KPX Aogonek quoteright -74 KPX Aogonek u -30 KPX Aogonek uacute -30 KPX Aogonek ucircumflex -30 KPX Aogonek udieresis -30 KPX Aogonek ugrave -30 KPX Aogonek uhungarumlaut -30 KPX Aogonek umacron -30 KPX Aogonek uogonek -30 KPX Aogonek uring -30 KPX Aogonek v -74 KPX Aogonek w -74 KPX Aogonek y -34 KPX Aogonek yacute -34 KPX Aogonek ydieresis -34 KPX Aring C -65 KPX Aring Cacute -65 KPX Aring Ccaron -65 KPX Aring Ccedilla -65 KPX Aring G -60 KPX Aring Gbreve -60 KPX Aring Gcommaaccent -60 KPX Aring O -50 KPX Aring Oacute -50 KPX Aring Ocircumflex -50 KPX Aring Odieresis -50 KPX Aring Ograve -50 KPX Aring Ohungarumlaut -50 KPX Aring Omacron -50 KPX Aring Oslash -50 KPX Aring Otilde -50 KPX Aring Q -55 KPX Aring T -55 KPX Aring Tcaron -55 KPX Aring Tcommaaccent -55 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -95 KPX Aring W -100 KPX Aring Y -70 KPX Aring Yacute -70 KPX Aring Ydieresis -70 KPX Aring quoteright -74 KPX Aring u -30 KPX Aring uacute -30 KPX Aring ucircumflex -30 KPX Aring udieresis -30 KPX Aring ugrave -30 KPX Aring uhungarumlaut -30 KPX Aring umacron -30 KPX Aring uogonek -30 KPX Aring uring -30 KPX Aring v -74 KPX Aring w -74 KPX Aring y -74 KPX Aring yacute -74 KPX Aring ydieresis -74 KPX Atilde C -65 KPX Atilde Cacute -65 KPX Atilde Ccaron -65 KPX Atilde Ccedilla -65 KPX Atilde G -60 KPX Atilde Gbreve -60 KPX Atilde Gcommaaccent -60 KPX Atilde O -50 KPX Atilde Oacute -50 KPX Atilde Ocircumflex -50 KPX Atilde Odieresis -50 KPX Atilde Ograve -50 KPX Atilde Ohungarumlaut -50 KPX Atilde Omacron -50 KPX Atilde Oslash -50 KPX Atilde Otilde -50 KPX Atilde Q -55 KPX Atilde T -55 KPX Atilde Tcaron -55 KPX Atilde Tcommaaccent -55 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -95 KPX Atilde W -100 KPX Atilde Y -70 KPX Atilde Yacute -70 KPX Atilde Ydieresis -70 KPX Atilde quoteright -74 KPX Atilde u -30 KPX Atilde uacute -30 KPX Atilde ucircumflex -30 KPX Atilde udieresis -30 KPX Atilde ugrave -30 KPX Atilde uhungarumlaut -30 KPX Atilde umacron -30 KPX Atilde uogonek -30 KPX Atilde uring -30 KPX Atilde v -74 KPX Atilde w -74 KPX Atilde y -74 KPX Atilde yacute -74 KPX Atilde ydieresis -74 KPX B A -25 KPX B Aacute -25 KPX B Abreve -25 KPX B Acircumflex -25 KPX B Adieresis -25 KPX B Agrave -25 KPX B Amacron -25 KPX B Aogonek -25 KPX B Aring -25 KPX B Atilde -25 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -25 KPX D Aacute -25 KPX D Abreve -25 KPX D Acircumflex -25 KPX D Adieresis -25 KPX D Agrave -25 KPX D Amacron -25 KPX D Aogonek -25 KPX D Aring -25 KPX D Atilde -25 KPX D V -50 KPX D W -40 KPX D Y -50 KPX D Yacute -50 KPX D Ydieresis -50 KPX Dcaron A -25 KPX Dcaron Aacute -25 KPX Dcaron Abreve -25 KPX Dcaron Acircumflex -25 KPX Dcaron Adieresis -25 KPX Dcaron Agrave -25 KPX Dcaron Amacron -25 KPX Dcaron Aogonek -25 KPX Dcaron Aring -25 KPX Dcaron Atilde -25 KPX Dcaron V -50 KPX Dcaron W -40 KPX Dcaron Y -50 KPX Dcaron Yacute -50 KPX Dcaron Ydieresis -50 KPX Dcroat A -25 KPX Dcroat Aacute -25 KPX Dcroat Abreve -25 KPX Dcroat Acircumflex -25 KPX Dcroat Adieresis -25 KPX Dcroat Agrave -25 KPX Dcroat Amacron -25 KPX Dcroat Aogonek -25 KPX Dcroat Aring -25 KPX Dcroat Atilde -25 KPX Dcroat V -50 KPX Dcroat W -40 KPX Dcroat Y -50 KPX Dcroat Yacute -50 KPX Dcroat Ydieresis -50 KPX F A -100 KPX F Aacute -100 KPX F Abreve -100 KPX F Acircumflex -100 KPX F Adieresis -100 KPX F Agrave -100 KPX F Amacron -100 KPX F Aogonek -100 KPX F Aring -100 KPX F Atilde -100 KPX F a -95 KPX F aacute -95 KPX F abreve -95 KPX F acircumflex -95 KPX F adieresis -95 KPX F agrave -95 KPX F amacron -95 KPX F aogonek -95 KPX F aring -95 KPX F atilde -95 KPX F comma -129 KPX F e -100 KPX F eacute -100 KPX F ecaron -100 KPX F ecircumflex -100 KPX F edieresis -100 KPX F edotaccent -100 KPX F egrave -100 KPX F emacron -100 KPX F eogonek -100 KPX F i -40 KPX F iacute -40 KPX F icircumflex -40 KPX F idieresis -40 KPX F igrave -40 KPX F imacron -40 KPX F iogonek -40 KPX F o -70 KPX F oacute -70 KPX F ocircumflex -70 KPX F odieresis -70 KPX F ograve -70 KPX F ohungarumlaut -70 KPX F omacron -70 KPX F oslash -70 KPX F otilde -70 KPX F period -129 KPX F r -50 KPX F racute -50 KPX F rcaron -50 KPX F rcommaaccent -50 KPX J A -25 KPX J Aacute -25 KPX J Abreve -25 KPX J Acircumflex -25 KPX J Adieresis -25 KPX J Agrave -25 KPX J Amacron -25 KPX J Aogonek -25 KPX J Aring -25 KPX J Atilde -25 KPX J a -40 KPX J aacute -40 KPX J abreve -40 KPX J acircumflex -40 KPX J adieresis -40 KPX J agrave -40 KPX J amacron -40 KPX J aogonek -40 KPX J aring -40 KPX J atilde -40 KPX J comma -10 KPX J e -40 KPX J eacute -40 KPX J ecaron -40 KPX J ecircumflex -40 KPX J edieresis -40 KPX J edotaccent -40 KPX J egrave -40 KPX J emacron -40 KPX J eogonek -40 KPX J o -40 KPX J oacute -40 KPX J ocircumflex -40 KPX J odieresis -40 KPX J ograve -40 KPX J ohungarumlaut -40 KPX J omacron -40 KPX J oslash -40 KPX J otilde -40 KPX J period -10 KPX J u -40 KPX J uacute -40 KPX J ucircumflex -40 KPX J udieresis -40 KPX J ugrave -40 KPX J uhungarumlaut -40 KPX J umacron -40 KPX J uogonek -40 KPX J uring -40 KPX K O -30 KPX K Oacute -30 KPX K Ocircumflex -30 KPX K Odieresis -30 KPX K Ograve -30 KPX K Ohungarumlaut -30 KPX K Omacron -30 KPX K Oslash -30 KPX K Otilde -30 KPX K e -25 KPX K eacute -25 KPX K ecaron -25 KPX K ecircumflex -25 KPX K edieresis -25 KPX K edotaccent -25 KPX K egrave -25 KPX K emacron -25 KPX K eogonek -25 KPX K o -25 KPX K oacute -25 KPX K ocircumflex -25 KPX K odieresis -25 KPX K ograve -25 KPX K ohungarumlaut -25 KPX K omacron -25 KPX K oslash -25 KPX K otilde -25 KPX K u -20 KPX K uacute -20 KPX K ucircumflex -20 KPX K udieresis -20 KPX K ugrave -20 KPX K uhungarumlaut -20 KPX K umacron -20 KPX K uogonek -20 KPX K uring -20 KPX K y -20 KPX K yacute -20 KPX K ydieresis -20 KPX Kcommaaccent O -30 KPX Kcommaaccent Oacute -30 KPX Kcommaaccent Ocircumflex -30 KPX Kcommaaccent Odieresis -30 KPX Kcommaaccent Ograve -30 KPX Kcommaaccent Ohungarumlaut -30 KPX Kcommaaccent Omacron -30 KPX Kcommaaccent Oslash -30 KPX Kcommaaccent Otilde -30 KPX Kcommaaccent e -25 KPX Kcommaaccent eacute -25 KPX Kcommaaccent ecaron -25 KPX Kcommaaccent ecircumflex -25 KPX Kcommaaccent edieresis -25 KPX Kcommaaccent edotaccent -25 KPX Kcommaaccent egrave -25 KPX Kcommaaccent emacron -25 KPX Kcommaaccent eogonek -25 KPX Kcommaaccent o -25 KPX Kcommaaccent oacute -25 KPX Kcommaaccent ocircumflex -25 KPX Kcommaaccent odieresis -25 KPX Kcommaaccent ograve -25 KPX Kcommaaccent ohungarumlaut -25 KPX Kcommaaccent omacron -25 KPX Kcommaaccent oslash -25 KPX Kcommaaccent otilde -25 KPX Kcommaaccent u -20 KPX Kcommaaccent uacute -20 KPX Kcommaaccent ucircumflex -20 KPX Kcommaaccent udieresis -20 KPX Kcommaaccent ugrave -20 KPX Kcommaaccent uhungarumlaut -20 KPX Kcommaaccent umacron -20 KPX Kcommaaccent uogonek -20 KPX Kcommaaccent uring -20 KPX Kcommaaccent y -20 KPX Kcommaaccent yacute -20 KPX Kcommaaccent ydieresis -20 KPX L T -18 KPX L Tcaron -18 KPX L Tcommaaccent -18 KPX L V -37 KPX L W -37 KPX L Y -37 KPX L Yacute -37 KPX L Ydieresis -37 KPX L quoteright -55 KPX L y -37 KPX L yacute -37 KPX L ydieresis -37 KPX Lacute T -18 KPX Lacute Tcaron -18 KPX Lacute Tcommaaccent -18 KPX Lacute V -37 KPX Lacute W -37 KPX Lacute Y -37 KPX Lacute Yacute -37 KPX Lacute Ydieresis -37 KPX Lacute quoteright -55 KPX Lacute y -37 KPX Lacute yacute -37 KPX Lacute ydieresis -37 KPX Lcommaaccent T -18 KPX Lcommaaccent Tcaron -18 KPX Lcommaaccent Tcommaaccent -18 KPX Lcommaaccent V -37 KPX Lcommaaccent W -37 KPX Lcommaaccent Y -37 KPX Lcommaaccent Yacute -37 KPX Lcommaaccent Ydieresis -37 KPX Lcommaaccent quoteright -55 KPX Lcommaaccent y -37 KPX Lcommaaccent yacute -37 KPX Lcommaaccent ydieresis -37 KPX Lslash T -18 KPX Lslash Tcaron -18 KPX Lslash Tcommaaccent -18 KPX Lslash V -37 KPX Lslash W -37 KPX Lslash Y -37 KPX Lslash Yacute -37 KPX Lslash Ydieresis -37 KPX Lslash quoteright -55 KPX Lslash y -37 KPX Lslash yacute -37 KPX Lslash ydieresis -37 KPX N A -30 KPX N Aacute -30 KPX N Abreve -30 KPX N Acircumflex -30 KPX N Adieresis -30 KPX N Agrave -30 KPX N Amacron -30 KPX N Aogonek -30 KPX N Aring -30 KPX N Atilde -30 KPX Nacute A -30 KPX Nacute Aacute -30 KPX Nacute Abreve -30 KPX Nacute Acircumflex -30 KPX Nacute Adieresis -30 KPX Nacute Agrave -30 KPX Nacute Amacron -30 KPX Nacute Aogonek -30 KPX Nacute Aring -30 KPX Nacute Atilde -30 KPX Ncaron A -30 KPX Ncaron Aacute -30 KPX Ncaron Abreve -30 KPX Ncaron Acircumflex -30 KPX Ncaron Adieresis -30 KPX Ncaron Agrave -30 KPX Ncaron Amacron -30 KPX Ncaron Aogonek -30 KPX Ncaron Aring -30 KPX Ncaron Atilde -30 KPX Ncommaaccent A -30 KPX Ncommaaccent Aacute -30 KPX Ncommaaccent Abreve -30 KPX Ncommaaccent Acircumflex -30 KPX Ncommaaccent Adieresis -30 KPX Ncommaaccent Agrave -30 KPX Ncommaaccent Amacron -30 KPX Ncommaaccent Aogonek -30 KPX Ncommaaccent Aring -30 KPX Ncommaaccent Atilde -30 KPX Ntilde A -30 KPX Ntilde Aacute -30 KPX Ntilde Abreve -30 KPX Ntilde Acircumflex -30 KPX Ntilde Adieresis -30 KPX Ntilde Agrave -30 KPX Ntilde Amacron -30 KPX Ntilde Aogonek -30 KPX Ntilde Aring -30 KPX Ntilde Atilde -30 KPX O A -40 KPX O Aacute -40 KPX O Abreve -40 KPX O Acircumflex -40 KPX O Adieresis -40 KPX O Agrave -40 KPX O Amacron -40 KPX O Aogonek -40 KPX O Aring -40 KPX O Atilde -40 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -50 KPX O X -40 KPX O Y -50 KPX O Yacute -50 KPX O Ydieresis -50 KPX Oacute A -40 KPX Oacute Aacute -40 KPX Oacute Abreve -40 KPX Oacute Acircumflex -40 KPX Oacute Adieresis -40 KPX Oacute Agrave -40 KPX Oacute Amacron -40 KPX Oacute Aogonek -40 KPX Oacute Aring -40 KPX Oacute Atilde -40 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -50 KPX Oacute X -40 KPX Oacute Y -50 KPX Oacute Yacute -50 KPX Oacute Ydieresis -50 KPX Ocircumflex A -40 KPX Ocircumflex Aacute -40 KPX Ocircumflex Abreve -40 KPX Ocircumflex Acircumflex -40 KPX Ocircumflex Adieresis -40 KPX Ocircumflex Agrave -40 KPX Ocircumflex Amacron -40 KPX Ocircumflex Aogonek -40 KPX Ocircumflex Aring -40 KPX Ocircumflex Atilde -40 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -50 KPX Ocircumflex X -40 KPX Ocircumflex Y -50 KPX Ocircumflex Yacute -50 KPX Ocircumflex Ydieresis -50 KPX Odieresis A -40 KPX Odieresis Aacute -40 KPX Odieresis Abreve -40 KPX Odieresis Acircumflex -40 KPX Odieresis Adieresis -40 KPX Odieresis Agrave -40 KPX Odieresis Amacron -40 KPX Odieresis Aogonek -40 KPX Odieresis Aring -40 KPX Odieresis Atilde -40 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -50 KPX Odieresis X -40 KPX Odieresis Y -50 KPX Odieresis Yacute -50 KPX Odieresis Ydieresis -50 KPX Ograve A -40 KPX Ograve Aacute -40 KPX Ograve Abreve -40 KPX Ograve Acircumflex -40 KPX Ograve Adieresis -40 KPX Ograve Agrave -40 KPX Ograve Amacron -40 KPX Ograve Aogonek -40 KPX Ograve Aring -40 KPX Ograve Atilde -40 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -50 KPX Ograve X -40 KPX Ograve Y -50 KPX Ograve Yacute -50 KPX Ograve Ydieresis -50 KPX Ohungarumlaut A -40 KPX Ohungarumlaut Aacute -40 KPX Ohungarumlaut Abreve -40 KPX Ohungarumlaut Acircumflex -40 KPX Ohungarumlaut Adieresis -40 KPX Ohungarumlaut Agrave -40 KPX Ohungarumlaut Amacron -40 KPX Ohungarumlaut Aogonek -40 KPX Ohungarumlaut Aring -40 KPX Ohungarumlaut Atilde -40 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -50 KPX Ohungarumlaut X -40 KPX Ohungarumlaut Y -50 KPX Ohungarumlaut Yacute -50 KPX Ohungarumlaut Ydieresis -50 KPX Omacron A -40 KPX Omacron Aacute -40 KPX Omacron Abreve -40 KPX Omacron Acircumflex -40 KPX Omacron Adieresis -40 KPX Omacron Agrave -40 KPX Omacron Amacron -40 KPX Omacron Aogonek -40 KPX Omacron Aring -40 KPX Omacron Atilde -40 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -50 KPX Omacron X -40 KPX Omacron Y -50 KPX Omacron Yacute -50 KPX Omacron Ydieresis -50 KPX Oslash A -40 KPX Oslash Aacute -40 KPX Oslash Abreve -40 KPX Oslash Acircumflex -40 KPX Oslash Adieresis -40 KPX Oslash Agrave -40 KPX Oslash Amacron -40 KPX Oslash Aogonek -40 KPX Oslash Aring -40 KPX Oslash Atilde -40 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -50 KPX Oslash X -40 KPX Oslash Y -50 KPX Oslash Yacute -50 KPX Oslash Ydieresis -50 KPX Otilde A -40 KPX Otilde Aacute -40 KPX Otilde Abreve -40 KPX Otilde Acircumflex -40 KPX Otilde Adieresis -40 KPX Otilde Agrave -40 KPX Otilde Amacron -40 KPX Otilde Aogonek -40 KPX Otilde Aring -40 KPX Otilde Atilde -40 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -50 KPX Otilde X -40 KPX Otilde Y -50 KPX Otilde Yacute -50 KPX Otilde Ydieresis -50 KPX P A -85 KPX P Aacute -85 KPX P Abreve -85 KPX P Acircumflex -85 KPX P Adieresis -85 KPX P Agrave -85 KPX P Amacron -85 KPX P Aogonek -85 KPX P Aring -85 KPX P Atilde -85 KPX P a -40 KPX P aacute -40 KPX P abreve -40 KPX P acircumflex -40 KPX P adieresis -40 KPX P agrave -40 KPX P amacron -40 KPX P aogonek -40 KPX P aring -40 KPX P atilde -40 KPX P comma -129 KPX P e -50 KPX P eacute -50 KPX P ecaron -50 KPX P ecircumflex -50 KPX P edieresis -50 KPX P edotaccent -50 KPX P egrave -50 KPX P emacron -50 KPX P eogonek -50 KPX P o -55 KPX P oacute -55 KPX P ocircumflex -55 KPX P odieresis -55 KPX P ograve -55 KPX P ohungarumlaut -55 KPX P omacron -55 KPX P oslash -55 KPX P otilde -55 KPX P period -129 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX R O -40 KPX R Oacute -40 KPX R Ocircumflex -40 KPX R Odieresis -40 KPX R Ograve -40 KPX R Ohungarumlaut -40 KPX R Omacron -40 KPX R Oslash -40 KPX R Otilde -40 KPX R T -30 KPX R Tcaron -30 KPX R Tcommaaccent -30 KPX R U -40 KPX R Uacute -40 KPX R Ucircumflex -40 KPX R Udieresis -40 KPX R Ugrave -40 KPX R Uhungarumlaut -40 KPX R Umacron -40 KPX R Uogonek -40 KPX R Uring -40 KPX R V -18 KPX R W -18 KPX R Y -18 KPX R Yacute -18 KPX R Ydieresis -18 KPX Racute O -40 KPX Racute Oacute -40 KPX Racute Ocircumflex -40 KPX Racute Odieresis -40 KPX Racute Ograve -40 KPX Racute Ohungarumlaut -40 KPX Racute Omacron -40 KPX Racute Oslash -40 KPX Racute Otilde -40 KPX Racute T -30 KPX Racute Tcaron -30 KPX Racute Tcommaaccent -30 KPX Racute U -40 KPX Racute Uacute -40 KPX Racute Ucircumflex -40 KPX Racute Udieresis -40 KPX Racute Ugrave -40 KPX Racute Uhungarumlaut -40 KPX Racute Umacron -40 KPX Racute Uogonek -40 KPX Racute Uring -40 KPX Racute V -18 KPX Racute W -18 KPX Racute Y -18 KPX Racute Yacute -18 KPX Racute Ydieresis -18 KPX Rcaron O -40 KPX Rcaron Oacute -40 KPX Rcaron Ocircumflex -40 KPX Rcaron Odieresis -40 KPX Rcaron Ograve -40 KPX Rcaron Ohungarumlaut -40 KPX Rcaron Omacron -40 KPX Rcaron Oslash -40 KPX Rcaron Otilde -40 KPX Rcaron T -30 KPX Rcaron Tcaron -30 KPX Rcaron Tcommaaccent -30 KPX Rcaron U -40 KPX Rcaron Uacute -40 KPX Rcaron Ucircumflex -40 KPX Rcaron Udieresis -40 KPX Rcaron Ugrave -40 KPX Rcaron Uhungarumlaut -40 KPX Rcaron Umacron -40 KPX Rcaron Uogonek -40 KPX Rcaron Uring -40 KPX Rcaron V -18 KPX Rcaron W -18 KPX Rcaron Y -18 KPX Rcaron Yacute -18 KPX Rcaron Ydieresis -18 KPX Rcommaaccent O -40 KPX Rcommaaccent Oacute -40 KPX Rcommaaccent Ocircumflex -40 KPX Rcommaaccent Odieresis -40 KPX Rcommaaccent Ograve -40 KPX Rcommaaccent Ohungarumlaut -40 KPX Rcommaaccent Omacron -40 KPX Rcommaaccent Oslash -40 KPX Rcommaaccent Otilde -40 KPX Rcommaaccent T -30 KPX Rcommaaccent Tcaron -30 KPX Rcommaaccent Tcommaaccent -30 KPX Rcommaaccent U -40 KPX Rcommaaccent Uacute -40 KPX Rcommaaccent Ucircumflex -40 KPX Rcommaaccent Udieresis -40 KPX Rcommaaccent Ugrave -40 KPX Rcommaaccent Uhungarumlaut -40 KPX Rcommaaccent Umacron -40 KPX Rcommaaccent Uogonek -40 KPX Rcommaaccent Uring -40 KPX Rcommaaccent V -18 KPX Rcommaaccent W -18 KPX Rcommaaccent Y -18 KPX Rcommaaccent Yacute -18 KPX Rcommaaccent Ydieresis -18 KPX T A -55 KPX T Aacute -55 KPX T Abreve -55 KPX T Acircumflex -55 KPX T Adieresis -55 KPX T Agrave -55 KPX T Amacron -55 KPX T Aogonek -55 KPX T Aring -55 KPX T Atilde -55 KPX T O -18 KPX T Oacute -18 KPX T Ocircumflex -18 KPX T Odieresis -18 KPX T Ograve -18 KPX T Ohungarumlaut -18 KPX T Omacron -18 KPX T Oslash -18 KPX T Otilde -18 KPX T a -92 KPX T aacute -92 KPX T abreve -92 KPX T acircumflex -92 KPX T adieresis -92 KPX T agrave -92 KPX T amacron -92 KPX T aogonek -92 KPX T aring -92 KPX T atilde -92 KPX T colon -74 KPX T comma -92 KPX T e -92 KPX T eacute -92 KPX T ecaron -92 KPX T ecircumflex -92 KPX T edieresis -52 KPX T edotaccent -92 KPX T egrave -52 KPX T emacron -52 KPX T eogonek -92 KPX T hyphen -92 KPX T i -37 KPX T iacute -37 KPX T iogonek -37 KPX T o -95 KPX T oacute -95 KPX T ocircumflex -95 KPX T odieresis -95 KPX T ograve -95 KPX T ohungarumlaut -95 KPX T omacron -95 KPX T oslash -95 KPX T otilde -95 KPX T period -92 KPX T r -37 KPX T racute -37 KPX T rcaron -37 KPX T rcommaaccent -37 KPX T semicolon -74 KPX T u -37 KPX T uacute -37 KPX T ucircumflex -37 KPX T udieresis -37 KPX T ugrave -37 KPX T uhungarumlaut -37 KPX T umacron -37 KPX T uogonek -37 KPX T uring -37 KPX T w -37 KPX T y -37 KPX T yacute -37 KPX T ydieresis -37 KPX Tcaron A -55 KPX Tcaron Aacute -55 KPX Tcaron Abreve -55 KPX Tcaron Acircumflex -55 KPX Tcaron Adieresis -55 KPX Tcaron Agrave -55 KPX Tcaron Amacron -55 KPX Tcaron Aogonek -55 KPX Tcaron Aring -55 KPX Tcaron Atilde -55 KPX Tcaron O -18 KPX Tcaron Oacute -18 KPX Tcaron Ocircumflex -18 KPX Tcaron Odieresis -18 KPX Tcaron Ograve -18 KPX Tcaron Ohungarumlaut -18 KPX Tcaron Omacron -18 KPX Tcaron Oslash -18 KPX Tcaron Otilde -18 KPX Tcaron a -92 KPX Tcaron aacute -92 KPX Tcaron abreve -92 KPX Tcaron acircumflex -92 KPX Tcaron adieresis -92 KPX Tcaron agrave -92 KPX Tcaron amacron -92 KPX Tcaron aogonek -92 KPX Tcaron aring -92 KPX Tcaron atilde -92 KPX Tcaron colon -74 KPX Tcaron comma -92 KPX Tcaron e -92 KPX Tcaron eacute -92 KPX Tcaron ecaron -92 KPX Tcaron ecircumflex -92 KPX Tcaron edieresis -52 KPX Tcaron edotaccent -92 KPX Tcaron egrave -52 KPX Tcaron emacron -52 KPX Tcaron eogonek -92 KPX Tcaron hyphen -92 KPX Tcaron i -37 KPX Tcaron iacute -37 KPX Tcaron iogonek -37 KPX Tcaron o -95 KPX Tcaron oacute -95 KPX Tcaron ocircumflex -95 KPX Tcaron odieresis -95 KPX Tcaron ograve -95 KPX Tcaron ohungarumlaut -95 KPX Tcaron omacron -95 KPX Tcaron oslash -95 KPX Tcaron otilde -95 KPX Tcaron period -92 KPX Tcaron r -37 KPX Tcaron racute -37 KPX Tcaron rcaron -37 KPX Tcaron rcommaaccent -37 KPX Tcaron semicolon -74 KPX Tcaron u -37 KPX Tcaron uacute -37 KPX Tcaron ucircumflex -37 KPX Tcaron udieresis -37 KPX Tcaron ugrave -37 KPX Tcaron uhungarumlaut -37 KPX Tcaron umacron -37 KPX Tcaron uogonek -37 KPX Tcaron uring -37 KPX Tcaron w -37 KPX Tcaron y -37 KPX Tcaron yacute -37 KPX Tcaron ydieresis -37 KPX Tcommaaccent A -55 KPX Tcommaaccent Aacute -55 KPX Tcommaaccent Abreve -55 KPX Tcommaaccent Acircumflex -55 KPX Tcommaaccent Adieresis -55 KPX Tcommaaccent Agrave -55 KPX Tcommaaccent Amacron -55 KPX Tcommaaccent Aogonek -55 KPX Tcommaaccent Aring -55 KPX Tcommaaccent Atilde -55 KPX Tcommaaccent O -18 KPX Tcommaaccent Oacute -18 KPX Tcommaaccent Ocircumflex -18 KPX Tcommaaccent Odieresis -18 KPX Tcommaaccent Ograve -18 KPX Tcommaaccent Ohungarumlaut -18 KPX Tcommaaccent Omacron -18 KPX Tcommaaccent Oslash -18 KPX Tcommaaccent Otilde -18 KPX Tcommaaccent a -92 KPX Tcommaaccent aacute -92 KPX Tcommaaccent abreve -92 KPX Tcommaaccent acircumflex -92 KPX Tcommaaccent adieresis -92 KPX Tcommaaccent agrave -92 KPX Tcommaaccent amacron -92 KPX Tcommaaccent aogonek -92 KPX Tcommaaccent aring -92 KPX Tcommaaccent atilde -92 KPX Tcommaaccent colon -74 KPX Tcommaaccent comma -92 KPX Tcommaaccent e -92 KPX Tcommaaccent eacute -92 KPX Tcommaaccent ecaron -92 KPX Tcommaaccent ecircumflex -92 KPX Tcommaaccent edieresis -52 KPX Tcommaaccent edotaccent -92 KPX Tcommaaccent egrave -52 KPX Tcommaaccent emacron -52 KPX Tcommaaccent eogonek -92 KPX Tcommaaccent hyphen -92 KPX Tcommaaccent i -37 KPX Tcommaaccent iacute -37 KPX Tcommaaccent iogonek -37 KPX Tcommaaccent o -95 KPX Tcommaaccent oacute -95 KPX Tcommaaccent ocircumflex -95 KPX Tcommaaccent odieresis -95 KPX Tcommaaccent ograve -95 KPX Tcommaaccent ohungarumlaut -95 KPX Tcommaaccent omacron -95 KPX Tcommaaccent oslash -95 KPX Tcommaaccent otilde -95 KPX Tcommaaccent period -92 KPX Tcommaaccent r -37 KPX Tcommaaccent racute -37 KPX Tcommaaccent rcaron -37 KPX Tcommaaccent rcommaaccent -37 KPX Tcommaaccent semicolon -74 KPX Tcommaaccent u -37 KPX Tcommaaccent uacute -37 KPX Tcommaaccent ucircumflex -37 KPX Tcommaaccent udieresis -37 KPX Tcommaaccent ugrave -37 KPX Tcommaaccent uhungarumlaut -37 KPX Tcommaaccent umacron -37 KPX Tcommaaccent uogonek -37 KPX Tcommaaccent uring -37 KPX Tcommaaccent w -37 KPX Tcommaaccent y -37 KPX Tcommaaccent yacute -37 KPX Tcommaaccent ydieresis -37 KPX U A -45 KPX U Aacute -45 KPX U Abreve -45 KPX U Acircumflex -45 KPX U Adieresis -45 KPX U Agrave -45 KPX U Amacron -45 KPX U Aogonek -45 KPX U Aring -45 KPX U Atilde -45 KPX Uacute A -45 KPX Uacute Aacute -45 KPX Uacute Abreve -45 KPX Uacute Acircumflex -45 KPX Uacute Adieresis -45 KPX Uacute Agrave -45 KPX Uacute Amacron -45 KPX Uacute Aogonek -45 KPX Uacute Aring -45 KPX Uacute Atilde -45 KPX Ucircumflex A -45 KPX Ucircumflex Aacute -45 KPX Ucircumflex Abreve -45 KPX Ucircumflex Acircumflex -45 KPX Ucircumflex Adieresis -45 KPX Ucircumflex Agrave -45 KPX Ucircumflex Amacron -45 KPX Ucircumflex Aogonek -45 KPX Ucircumflex Aring -45 KPX Ucircumflex Atilde -45 KPX Udieresis A -45 KPX Udieresis Aacute -45 KPX Udieresis Abreve -45 KPX Udieresis Acircumflex -45 KPX Udieresis Adieresis -45 KPX Udieresis Agrave -45 KPX Udieresis Amacron -45 KPX Udieresis Aogonek -45 KPX Udieresis Aring -45 KPX Udieresis Atilde -45 KPX Ugrave A -45 KPX Ugrave Aacute -45 KPX Ugrave Abreve -45 KPX Ugrave Acircumflex -45 KPX Ugrave Adieresis -45 KPX Ugrave Agrave -45 KPX Ugrave Amacron -45 KPX Ugrave Aogonek -45 KPX Ugrave Aring -45 KPX Ugrave Atilde -45 KPX Uhungarumlaut A -45 KPX Uhungarumlaut Aacute -45 KPX Uhungarumlaut Abreve -45 KPX Uhungarumlaut Acircumflex -45 KPX Uhungarumlaut Adieresis -45 KPX Uhungarumlaut Agrave -45 KPX Uhungarumlaut Amacron -45 KPX Uhungarumlaut Aogonek -45 KPX Uhungarumlaut Aring -45 KPX Uhungarumlaut Atilde -45 KPX Umacron A -45 KPX Umacron Aacute -45 KPX Umacron Abreve -45 KPX Umacron Acircumflex -45 KPX Umacron Adieresis -45 KPX Umacron Agrave -45 KPX Umacron Amacron -45 KPX Umacron Aogonek -45 KPX Umacron Aring -45 KPX Umacron Atilde -45 KPX Uogonek A -45 KPX Uogonek Aacute -45 KPX Uogonek Abreve -45 KPX Uogonek Acircumflex -45 KPX Uogonek Adieresis -45 KPX Uogonek Agrave -45 KPX Uogonek Amacron -45 KPX Uogonek Aogonek -45 KPX Uogonek Aring -45 KPX Uogonek Atilde -45 KPX Uring A -45 KPX Uring Aacute -45 KPX Uring Abreve -45 KPX Uring Acircumflex -45 KPX Uring Adieresis -45 KPX Uring Agrave -45 KPX Uring Amacron -45 KPX Uring Aogonek -45 KPX Uring Aring -45 KPX Uring Atilde -45 KPX V A -85 KPX V Aacute -85 KPX V Abreve -85 KPX V Acircumflex -85 KPX V Adieresis -85 KPX V Agrave -85 KPX V Amacron -85 KPX V Aogonek -85 KPX V Aring -85 KPX V Atilde -85 KPX V G -10 KPX V Gbreve -10 KPX V Gcommaaccent -10 KPX V O -30 KPX V Oacute -30 KPX V Ocircumflex -30 KPX V Odieresis -30 KPX V Ograve -30 KPX V Ohungarumlaut -30 KPX V Omacron -30 KPX V Oslash -30 KPX V Otilde -30 KPX V a -111 KPX V aacute -111 KPX V abreve -111 KPX V acircumflex -111 KPX V adieresis -111 KPX V agrave -111 KPX V amacron -111 KPX V aogonek -111 KPX V aring -111 KPX V atilde -111 KPX V colon -74 KPX V comma -129 KPX V e -111 KPX V eacute -111 KPX V ecaron -111 KPX V ecircumflex -111 KPX V edieresis -71 KPX V edotaccent -111 KPX V egrave -71 KPX V emacron -71 KPX V eogonek -111 KPX V hyphen -70 KPX V i -55 KPX V iacute -55 KPX V iogonek -55 KPX V o -111 KPX V oacute -111 KPX V ocircumflex -111 KPX V odieresis -111 KPX V ograve -111 KPX V ohungarumlaut -111 KPX V omacron -111 KPX V oslash -111 KPX V otilde -111 KPX V period -129 KPX V semicolon -74 KPX V u -55 KPX V uacute -55 KPX V ucircumflex -55 KPX V udieresis -55 KPX V ugrave -55 KPX V uhungarumlaut -55 KPX V umacron -55 KPX V uogonek -55 KPX V uring -55 KPX W A -74 KPX W Aacute -74 KPX W Abreve -74 KPX W Acircumflex -74 KPX W Adieresis -74 KPX W Agrave -74 KPX W Amacron -74 KPX W Aogonek -74 KPX W Aring -74 KPX W Atilde -74 KPX W O -15 KPX W Oacute -15 KPX W Ocircumflex -15 KPX W Odieresis -15 KPX W Ograve -15 KPX W Ohungarumlaut -15 KPX W Omacron -15 KPX W Oslash -15 KPX W Otilde -15 KPX W a -85 KPX W aacute -85 KPX W abreve -85 KPX W acircumflex -85 KPX W adieresis -85 KPX W agrave -85 KPX W amacron -85 KPX W aogonek -85 KPX W aring -85 KPX W atilde -85 KPX W colon -55 KPX W comma -74 KPX W e -90 KPX W eacute -90 KPX W ecaron -90 KPX W ecircumflex -90 KPX W edieresis -50 KPX W edotaccent -90 KPX W egrave -50 KPX W emacron -50 KPX W eogonek -90 KPX W hyphen -50 KPX W i -37 KPX W iacute -37 KPX W iogonek -37 KPX W o -80 KPX W oacute -80 KPX W ocircumflex -80 KPX W odieresis -80 KPX W ograve -80 KPX W ohungarumlaut -80 KPX W omacron -80 KPX W oslash -80 KPX W otilde -80 KPX W period -74 KPX W semicolon -55 KPX W u -55 KPX W uacute -55 KPX W ucircumflex -55 KPX W udieresis -55 KPX W ugrave -55 KPX W uhungarumlaut -55 KPX W umacron -55 KPX W uogonek -55 KPX W uring -55 KPX W y -55 KPX W yacute -55 KPX W ydieresis -55 KPX Y A -74 KPX Y Aacute -74 KPX Y Abreve -74 KPX Y Acircumflex -74 KPX Y Adieresis -74 KPX Y Agrave -74 KPX Y Amacron -74 KPX Y Aogonek -74 KPX Y Aring -74 KPX Y Atilde -74 KPX Y O -25 KPX Y Oacute -25 KPX Y Ocircumflex -25 KPX Y Odieresis -25 KPX Y Ograve -25 KPX Y Ohungarumlaut -25 KPX Y Omacron -25 KPX Y Oslash -25 KPX Y Otilde -25 KPX Y a -92 KPX Y aacute -92 KPX Y abreve -92 KPX Y acircumflex -92 KPX Y adieresis -92 KPX Y agrave -92 KPX Y amacron -92 KPX Y aogonek -92 KPX Y aring -92 KPX Y atilde -92 KPX Y colon -92 KPX Y comma -92 KPX Y e -111 KPX Y eacute -111 KPX Y ecaron -111 KPX Y ecircumflex -71 KPX Y edieresis -71 KPX Y edotaccent -111 KPX Y egrave -71 KPX Y emacron -71 KPX Y eogonek -111 KPX Y hyphen -92 KPX Y i -55 KPX Y iacute -55 KPX Y iogonek -55 KPX Y o -111 KPX Y oacute -111 KPX Y ocircumflex -111 KPX Y odieresis -111 KPX Y ograve -111 KPX Y ohungarumlaut -111 KPX Y omacron -111 KPX Y oslash -111 KPX Y otilde -111 KPX Y period -74 KPX Y semicolon -92 KPX Y u -92 KPX Y uacute -92 KPX Y ucircumflex -92 KPX Y udieresis -92 KPX Y ugrave -92 KPX Y uhungarumlaut -92 KPX Y umacron -92 KPX Y uogonek -92 KPX Y uring -92 KPX Yacute A -74 KPX Yacute Aacute -74 KPX Yacute Abreve -74 KPX Yacute Acircumflex -74 KPX Yacute Adieresis -74 KPX Yacute Agrave -74 KPX Yacute Amacron -74 KPX Yacute Aogonek -74 KPX Yacute Aring -74 KPX Yacute Atilde -74 KPX Yacute O -25 KPX Yacute Oacute -25 KPX Yacute Ocircumflex -25 KPX Yacute Odieresis -25 KPX Yacute Ograve -25 KPX Yacute Ohungarumlaut -25 KPX Yacute Omacron -25 KPX Yacute Oslash -25 KPX Yacute Otilde -25 KPX Yacute a -92 KPX Yacute aacute -92 KPX Yacute abreve -92 KPX Yacute acircumflex -92 KPX Yacute adieresis -92 KPX Yacute agrave -92 KPX Yacute amacron -92 KPX Yacute aogonek -92 KPX Yacute aring -92 KPX Yacute atilde -92 KPX Yacute colon -92 KPX Yacute comma -92 KPX Yacute e -111 KPX Yacute eacute -111 KPX Yacute ecaron -111 KPX Yacute ecircumflex -71 KPX Yacute edieresis -71 KPX Yacute edotaccent -111 KPX Yacute egrave -71 KPX Yacute emacron -71 KPX Yacute eogonek -111 KPX Yacute hyphen -92 KPX Yacute i -55 KPX Yacute iacute -55 KPX Yacute iogonek -55 KPX Yacute o -111 KPX Yacute oacute -111 KPX Yacute ocircumflex -111 KPX Yacute odieresis -111 KPX Yacute ograve -111 KPX Yacute ohungarumlaut -111 KPX Yacute omacron -111 KPX Yacute oslash -111 KPX Yacute otilde -111 KPX Yacute period -74 KPX Yacute semicolon -92 KPX Yacute u -92 KPX Yacute uacute -92 KPX Yacute ucircumflex -92 KPX Yacute udieresis -92 KPX Yacute ugrave -92 KPX Yacute uhungarumlaut -92 KPX Yacute umacron -92 KPX Yacute uogonek -92 KPX Yacute uring -92 KPX Ydieresis A -74 KPX Ydieresis Aacute -74 KPX Ydieresis Abreve -74 KPX Ydieresis Acircumflex -74 KPX Ydieresis Adieresis -74 KPX Ydieresis Agrave -74 KPX Ydieresis Amacron -74 KPX Ydieresis Aogonek -74 KPX Ydieresis Aring -74 KPX Ydieresis Atilde -74 KPX Ydieresis O -25 KPX Ydieresis Oacute -25 KPX Ydieresis Ocircumflex -25 KPX Ydieresis Odieresis -25 KPX Ydieresis Ograve -25 KPX Ydieresis Ohungarumlaut -25 KPX Ydieresis Omacron -25 KPX Ydieresis Oslash -25 KPX Ydieresis Otilde -25 KPX Ydieresis a -92 KPX Ydieresis aacute -92 KPX Ydieresis abreve -92 KPX Ydieresis acircumflex -92 KPX Ydieresis adieresis -92 KPX Ydieresis agrave -92 KPX Ydieresis amacron -92 KPX Ydieresis aogonek -92 KPX Ydieresis aring -92 KPX Ydieresis atilde -92 KPX Ydieresis colon -92 KPX Ydieresis comma -92 KPX Ydieresis e -111 KPX Ydieresis eacute -111 KPX Ydieresis ecaron -111 KPX Ydieresis ecircumflex -71 KPX Ydieresis edieresis -71 KPX Ydieresis edotaccent -111 KPX Ydieresis egrave -71 KPX Ydieresis emacron -71 KPX Ydieresis eogonek -111 KPX Ydieresis hyphen -92 KPX Ydieresis i -55 KPX Ydieresis iacute -55 KPX Ydieresis iogonek -55 KPX Ydieresis o -111 KPX Ydieresis oacute -111 KPX Ydieresis ocircumflex -111 KPX Ydieresis odieresis -111 KPX Ydieresis ograve -111 KPX Ydieresis ohungarumlaut -111 KPX Ydieresis omacron -111 KPX Ydieresis oslash -111 KPX Ydieresis otilde -111 KPX Ydieresis period -74 KPX Ydieresis semicolon -92 KPX Ydieresis u -92 KPX Ydieresis uacute -92 KPX Ydieresis ucircumflex -92 KPX Ydieresis udieresis -92 KPX Ydieresis ugrave -92 KPX Ydieresis uhungarumlaut -92 KPX Ydieresis umacron -92 KPX Ydieresis uogonek -92 KPX Ydieresis uring -92 KPX b b -10 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX c h -10 KPX c k -10 KPX c kcommaaccent -10 KPX cacute h -10 KPX cacute k -10 KPX cacute kcommaaccent -10 KPX ccaron h -10 KPX ccaron k -10 KPX ccaron kcommaaccent -10 KPX ccedilla h -10 KPX ccedilla k -10 KPX ccedilla kcommaaccent -10 KPX comma quotedblright -95 KPX comma quoteright -95 KPX e b -10 KPX eacute b -10 KPX ecaron b -10 KPX ecircumflex b -10 KPX edieresis b -10 KPX edotaccent b -10 KPX egrave b -10 KPX emacron b -10 KPX eogonek b -10 KPX f comma -10 KPX f dotlessi -30 KPX f e -10 KPX f eacute -10 KPX f edotaccent -10 KPX f eogonek -10 KPX f f -18 KPX f o -10 KPX f oacute -10 KPX f ocircumflex -10 KPX f ograve -10 KPX f ohungarumlaut -10 KPX f oslash -10 KPX f otilde -10 KPX f period -10 KPX f quoteright 55 KPX k e -30 KPX k eacute -30 KPX k ecaron -30 KPX k ecircumflex -30 KPX k edieresis -30 KPX k edotaccent -30 KPX k egrave -30 KPX k emacron -30 KPX k eogonek -30 KPX k o -10 KPX k oacute -10 KPX k ocircumflex -10 KPX k odieresis -10 KPX k ograve -10 KPX k ohungarumlaut -10 KPX k omacron -10 KPX k oslash -10 KPX k otilde -10 KPX kcommaaccent e -30 KPX kcommaaccent eacute -30 KPX kcommaaccent ecaron -30 KPX kcommaaccent ecircumflex -30 KPX kcommaaccent edieresis -30 KPX kcommaaccent edotaccent -30 KPX kcommaaccent egrave -30 KPX kcommaaccent emacron -30 KPX kcommaaccent eogonek -30 KPX kcommaaccent o -10 KPX kcommaaccent oacute -10 KPX kcommaaccent ocircumflex -10 KPX kcommaaccent odieresis -10 KPX kcommaaccent ograve -10 KPX kcommaaccent ohungarumlaut -10 KPX kcommaaccent omacron -10 KPX kcommaaccent oslash -10 KPX kcommaaccent otilde -10 KPX n v -40 KPX nacute v -40 KPX ncaron v -40 KPX ncommaaccent v -40 KPX ntilde v -40 KPX o v -15 KPX o w -25 KPX o x -10 KPX o y -10 KPX o yacute -10 KPX o ydieresis -10 KPX oacute v -15 KPX oacute w -25 KPX oacute x -10 KPX oacute y -10 KPX oacute yacute -10 KPX oacute ydieresis -10 KPX ocircumflex v -15 KPX ocircumflex w -25 KPX ocircumflex x -10 KPX ocircumflex y -10 KPX ocircumflex yacute -10 KPX ocircumflex ydieresis -10 KPX odieresis v -15 KPX odieresis w -25 KPX odieresis x -10 KPX odieresis y -10 KPX odieresis yacute -10 KPX odieresis ydieresis -10 KPX ograve v -15 KPX ograve w -25 KPX ograve x -10 KPX ograve y -10 KPX ograve yacute -10 KPX ograve ydieresis -10 KPX ohungarumlaut v -15 KPX ohungarumlaut w -25 KPX ohungarumlaut x -10 KPX ohungarumlaut y -10 KPX ohungarumlaut yacute -10 KPX ohungarumlaut ydieresis -10 KPX omacron v -15 KPX omacron w -25 KPX omacron x -10 KPX omacron y -10 KPX omacron yacute -10 KPX omacron ydieresis -10 KPX oslash v -15 KPX oslash w -25 KPX oslash x -10 KPX oslash y -10 KPX oslash yacute -10 KPX oslash ydieresis -10 KPX otilde v -15 KPX otilde w -25 KPX otilde x -10 KPX otilde y -10 KPX otilde yacute -10 KPX otilde ydieresis -10 KPX period quotedblright -95 KPX period quoteright -95 KPX quoteleft quoteleft -74 KPX quoteright d -15 KPX quoteright dcroat -15 KPX quoteright quoteright -74 KPX quoteright r -15 KPX quoteright racute -15 KPX quoteright rcaron -15 KPX quoteright rcommaaccent -15 KPX quoteright s -74 KPX quoteright sacute -74 KPX quoteright scaron -74 KPX quoteright scedilla -74 KPX quoteright scommaaccent -74 KPX quoteright space -74 KPX quoteright t -37 KPX quoteright tcommaaccent -37 KPX quoteright v -15 KPX r comma -65 KPX r period -65 KPX racute comma -65 KPX racute period -65 KPX rcaron comma -65 KPX rcaron period -65 KPX rcommaaccent comma -65 KPX rcommaaccent period -65 KPX space A -37 KPX space Aacute -37 KPX space Abreve -37 KPX space Acircumflex -37 KPX space Adieresis -37 KPX space Agrave -37 KPX space Amacron -37 KPX space Aogonek -37 KPX space Aring -37 KPX space Atilde -37 KPX space V -70 KPX space W -70 KPX space Y -70 KPX space Yacute -70 KPX space Ydieresis -70 KPX v comma -37 KPX v e -15 KPX v eacute -15 KPX v ecaron -15 KPX v ecircumflex -15 KPX v edieresis -15 KPX v edotaccent -15 KPX v egrave -15 KPX v emacron -15 KPX v eogonek -15 KPX v o -15 KPX v oacute -15 KPX v ocircumflex -15 KPX v odieresis -15 KPX v ograve -15 KPX v ohungarumlaut -15 KPX v omacron -15 KPX v oslash -15 KPX v otilde -15 KPX v period -37 KPX w a -10 KPX w aacute -10 KPX w abreve -10 KPX w acircumflex -10 KPX w adieresis -10 KPX w agrave -10 KPX w amacron -10 KPX w aogonek -10 KPX w aring -10 KPX w atilde -10 KPX w comma -37 KPX w e -10 KPX w eacute -10 KPX w ecaron -10 KPX w ecircumflex -10 KPX w edieresis -10 KPX w edotaccent -10 KPX w egrave -10 KPX w emacron -10 KPX w eogonek -10 KPX w o -15 KPX w oacute -15 KPX w ocircumflex -15 KPX w odieresis -15 KPX w ograve -15 KPX w ohungarumlaut -15 KPX w omacron -15 KPX w oslash -15 KPX w otilde -15 KPX w period -37 KPX x e -10 KPX x eacute -10 KPX x ecaron -10 KPX x ecircumflex -10 KPX x edieresis -10 KPX x edotaccent -10 KPX x egrave -10 KPX x emacron -10 KPX x eogonek -10 KPX y comma -37 KPX y period -37 KPX yacute comma -37 KPX yacute period -37 KPX ydieresis comma -37 KPX ydieresis period -37 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Times-Italic.afm0000644000076500000240000020660312037547555020022 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:56:55 1997 Comment UniqueID 43067 Comment VMusage 47727 58752 FontName Times-Italic FullName Times Italic FamilyName Times Weight Medium ItalicAngle -15.5 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -169 -217 1010 883 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 653 XHeight 441 Ascender 683 Descender -217 StdHW 32 StdVW 76 StartCharMetrics 315 C 32 ; WX 250 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 39 -11 302 667 ; C 34 ; WX 420 ; N quotedbl ; B 144 421 432 666 ; C 35 ; WX 500 ; N numbersign ; B 2 0 540 676 ; C 36 ; WX 500 ; N dollar ; B 31 -89 497 731 ; C 37 ; WX 833 ; N percent ; B 79 -13 790 676 ; C 38 ; WX 778 ; N ampersand ; B 76 -18 723 666 ; C 39 ; WX 333 ; N quoteright ; B 151 436 290 666 ; C 40 ; WX 333 ; N parenleft ; B 42 -181 315 669 ; C 41 ; WX 333 ; N parenright ; B 16 -180 289 669 ; C 42 ; WX 500 ; N asterisk ; B 128 255 492 666 ; C 43 ; WX 675 ; N plus ; B 86 0 590 506 ; C 44 ; WX 250 ; N comma ; B -4 -129 135 101 ; C 45 ; WX 333 ; N hyphen ; B 49 192 282 255 ; C 46 ; WX 250 ; N period ; B 27 -11 138 100 ; C 47 ; WX 278 ; N slash ; B -65 -18 386 666 ; C 48 ; WX 500 ; N zero ; B 32 -7 497 676 ; C 49 ; WX 500 ; N one ; B 49 0 409 676 ; C 50 ; WX 500 ; N two ; B 12 0 452 676 ; C 51 ; WX 500 ; N three ; B 15 -7 465 676 ; C 52 ; WX 500 ; N four ; B 1 0 479 676 ; C 53 ; WX 500 ; N five ; B 15 -7 491 666 ; C 54 ; WX 500 ; N six ; B 30 -7 521 686 ; C 55 ; WX 500 ; N seven ; B 75 -8 537 666 ; C 56 ; WX 500 ; N eight ; B 30 -7 493 676 ; C 57 ; WX 500 ; N nine ; B 23 -17 492 676 ; C 58 ; WX 333 ; N colon ; B 50 -11 261 441 ; C 59 ; WX 333 ; N semicolon ; B 27 -129 261 441 ; C 60 ; WX 675 ; N less ; B 84 -8 592 514 ; C 61 ; WX 675 ; N equal ; B 86 120 590 386 ; C 62 ; WX 675 ; N greater ; B 84 -8 592 514 ; C 63 ; WX 500 ; N question ; B 132 -12 472 664 ; C 64 ; WX 920 ; N at ; B 118 -18 806 666 ; C 65 ; WX 611 ; N A ; B -51 0 564 668 ; C 66 ; WX 611 ; N B ; B -8 0 588 653 ; C 67 ; WX 667 ; N C ; B 66 -18 689 666 ; C 68 ; WX 722 ; N D ; B -8 0 700 653 ; C 69 ; WX 611 ; N E ; B -1 0 634 653 ; C 70 ; WX 611 ; N F ; B 8 0 645 653 ; C 71 ; WX 722 ; N G ; B 52 -18 722 666 ; C 72 ; WX 722 ; N H ; B -8 0 767 653 ; C 73 ; WX 333 ; N I ; B -8 0 384 653 ; C 74 ; WX 444 ; N J ; B -6 -18 491 653 ; C 75 ; WX 667 ; N K ; B 7 0 722 653 ; C 76 ; WX 556 ; N L ; B -8 0 559 653 ; C 77 ; WX 833 ; N M ; B -18 0 873 653 ; C 78 ; WX 667 ; N N ; B -20 -15 727 653 ; C 79 ; WX 722 ; N O ; B 60 -18 699 666 ; C 80 ; WX 611 ; N P ; B 0 0 605 653 ; C 81 ; WX 722 ; N Q ; B 59 -182 699 666 ; C 82 ; WX 611 ; N R ; B -13 0 588 653 ; C 83 ; WX 500 ; N S ; B 17 -18 508 667 ; C 84 ; WX 556 ; N T ; B 59 0 633 653 ; C 85 ; WX 722 ; N U ; B 102 -18 765 653 ; C 86 ; WX 611 ; N V ; B 76 -18 688 653 ; C 87 ; WX 833 ; N W ; B 71 -18 906 653 ; C 88 ; WX 611 ; N X ; B -29 0 655 653 ; C 89 ; WX 556 ; N Y ; B 78 0 633 653 ; C 90 ; WX 556 ; N Z ; B -6 0 606 653 ; C 91 ; WX 389 ; N bracketleft ; B 21 -153 391 663 ; C 92 ; WX 278 ; N backslash ; B -41 -18 319 666 ; C 93 ; WX 389 ; N bracketright ; B 12 -153 382 663 ; C 94 ; WX 422 ; N asciicircum ; B 0 301 422 666 ; C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; C 96 ; WX 333 ; N quoteleft ; B 171 436 310 666 ; C 97 ; WX 500 ; N a ; B 17 -11 476 441 ; C 98 ; WX 500 ; N b ; B 23 -11 473 683 ; C 99 ; WX 444 ; N c ; B 30 -11 425 441 ; C 100 ; WX 500 ; N d ; B 15 -13 527 683 ; C 101 ; WX 444 ; N e ; B 31 -11 412 441 ; C 102 ; WX 278 ; N f ; B -147 -207 424 678 ; L i fi ; L l fl ; C 103 ; WX 500 ; N g ; B 8 -206 472 441 ; C 104 ; WX 500 ; N h ; B 19 -9 478 683 ; C 105 ; WX 278 ; N i ; B 49 -11 264 654 ; C 106 ; WX 278 ; N j ; B -124 -207 276 654 ; C 107 ; WX 444 ; N k ; B 14 -11 461 683 ; C 108 ; WX 278 ; N l ; B 41 -11 279 683 ; C 109 ; WX 722 ; N m ; B 12 -9 704 441 ; C 110 ; WX 500 ; N n ; B 14 -9 474 441 ; C 111 ; WX 500 ; N o ; B 27 -11 468 441 ; C 112 ; WX 500 ; N p ; B -75 -205 469 441 ; C 113 ; WX 500 ; N q ; B 25 -209 483 441 ; C 114 ; WX 389 ; N r ; B 45 0 412 441 ; C 115 ; WX 389 ; N s ; B 16 -13 366 442 ; C 116 ; WX 278 ; N t ; B 37 -11 296 546 ; C 117 ; WX 500 ; N u ; B 42 -11 475 441 ; C 118 ; WX 444 ; N v ; B 21 -18 426 441 ; C 119 ; WX 667 ; N w ; B 16 -18 648 441 ; C 120 ; WX 444 ; N x ; B -27 -11 447 441 ; C 121 ; WX 444 ; N y ; B -24 -206 426 441 ; C 122 ; WX 389 ; N z ; B -2 -81 380 428 ; C 123 ; WX 400 ; N braceleft ; B 51 -177 407 687 ; C 124 ; WX 275 ; N bar ; B 105 -217 171 783 ; C 125 ; WX 400 ; N braceright ; B -7 -177 349 687 ; C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ; C 161 ; WX 389 ; N exclamdown ; B 59 -205 322 473 ; C 162 ; WX 500 ; N cent ; B 77 -143 472 560 ; C 163 ; WX 500 ; N sterling ; B 10 -6 517 670 ; C 164 ; WX 167 ; N fraction ; B -169 -10 337 676 ; C 165 ; WX 500 ; N yen ; B 27 0 603 653 ; C 166 ; WX 500 ; N florin ; B 25 -182 507 682 ; C 167 ; WX 500 ; N section ; B 53 -162 461 666 ; C 168 ; WX 500 ; N currency ; B -22 53 522 597 ; C 169 ; WX 214 ; N quotesingle ; B 132 421 241 666 ; C 170 ; WX 556 ; N quotedblleft ; B 166 436 514 666 ; C 171 ; WX 500 ; N guillemotleft ; B 53 37 445 403 ; C 172 ; WX 333 ; N guilsinglleft ; B 51 37 281 403 ; C 173 ; WX 333 ; N guilsinglright ; B 52 37 282 403 ; C 174 ; WX 500 ; N fi ; B -141 -207 481 681 ; C 175 ; WX 500 ; N fl ; B -141 -204 518 682 ; C 177 ; WX 500 ; N endash ; B -6 197 505 243 ; C 178 ; WX 500 ; N dagger ; B 101 -159 488 666 ; C 179 ; WX 500 ; N daggerdbl ; B 22 -143 491 666 ; C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ; C 182 ; WX 523 ; N paragraph ; B 55 -123 616 653 ; C 183 ; WX 350 ; N bullet ; B 40 191 310 461 ; C 184 ; WX 333 ; N quotesinglbase ; B 44 -129 183 101 ; C 185 ; WX 556 ; N quotedblbase ; B 57 -129 405 101 ; C 186 ; WX 556 ; N quotedblright ; B 151 436 499 666 ; C 187 ; WX 500 ; N guillemotright ; B 55 37 447 403 ; C 188 ; WX 889 ; N ellipsis ; B 57 -11 762 100 ; C 189 ; WX 1000 ; N perthousand ; B 25 -19 1010 706 ; C 191 ; WX 500 ; N questiondown ; B 28 -205 368 471 ; C 193 ; WX 333 ; N grave ; B 121 492 311 664 ; C 194 ; WX 333 ; N acute ; B 180 494 403 664 ; C 195 ; WX 333 ; N circumflex ; B 91 492 385 661 ; C 196 ; WX 333 ; N tilde ; B 100 517 427 624 ; C 197 ; WX 333 ; N macron ; B 99 532 411 583 ; C 198 ; WX 333 ; N breve ; B 117 492 418 650 ; C 199 ; WX 333 ; N dotaccent ; B 207 548 305 646 ; C 200 ; WX 333 ; N dieresis ; B 107 548 405 646 ; C 202 ; WX 333 ; N ring ; B 155 492 355 691 ; C 203 ; WX 333 ; N cedilla ; B -30 -217 182 0 ; C 205 ; WX 333 ; N hungarumlaut ; B 93 494 486 664 ; C 206 ; WX 333 ; N ogonek ; B 20 -169 203 40 ; C 207 ; WX 333 ; N caron ; B 121 492 426 661 ; C 208 ; WX 889 ; N emdash ; B -6 197 894 243 ; C 225 ; WX 889 ; N AE ; B -27 0 911 653 ; C 227 ; WX 276 ; N ordfeminine ; B 42 406 352 676 ; C 232 ; WX 556 ; N Lslash ; B -8 0 559 653 ; C 233 ; WX 722 ; N Oslash ; B 60 -105 699 722 ; C 234 ; WX 944 ; N OE ; B 49 -8 964 666 ; C 235 ; WX 310 ; N ordmasculine ; B 67 406 362 676 ; C 241 ; WX 667 ; N ae ; B 23 -11 640 441 ; C 245 ; WX 278 ; N dotlessi ; B 49 -11 235 441 ; C 248 ; WX 278 ; N lslash ; B 41 -11 312 683 ; C 249 ; WX 500 ; N oslash ; B 28 -135 469 554 ; C 250 ; WX 667 ; N oe ; B 20 -12 646 441 ; C 251 ; WX 500 ; N germandbls ; B -168 -207 493 679 ; C -1 ; WX 333 ; N Idieresis ; B -8 0 435 818 ; C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ; C -1 ; WX 500 ; N abreve ; B 17 -11 502 650 ; C -1 ; WX 500 ; N uhungarumlaut ; B 42 -11 580 664 ; C -1 ; WX 444 ; N ecaron ; B 31 -11 482 661 ; C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ; C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ; C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ; C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ; C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ; C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ; C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ; C -1 ; WX 389 ; N scommaaccent ; B 16 -217 366 442 ; C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ; C -1 ; WX 722 ; N Uring ; B 102 -18 765 883 ; C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ; C -1 ; WX 500 ; N aogonek ; B 17 -169 476 441 ; C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ; C -1 ; WX 500 ; N uogonek ; B 42 -169 477 441 ; C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ; C -1 ; WX 722 ; N Dcroat ; B -8 0 700 653 ; C -1 ; WX 250 ; N commaaccent ; B 8 -217 133 -50 ; C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ; C -1 ; WX 611 ; N Emacron ; B -1 0 634 795 ; C -1 ; WX 444 ; N ccaron ; B 30 -11 482 661 ; C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ; C -1 ; WX 667 ; N Ncommaaccent ; B -20 -187 727 653 ; C -1 ; WX 278 ; N lacute ; B 41 -11 395 876 ; C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ; C -1 ; WX 556 ; N Tcommaaccent ; B 59 -217 633 653 ; C -1 ; WX 667 ; N Cacute ; B 66 -18 690 876 ; C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ; C -1 ; WX 611 ; N Edotaccent ; B -1 0 634 818 ; C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ; C -1 ; WX 389 ; N scedilla ; B 16 -217 366 442 ; C -1 ; WX 278 ; N iacute ; B 49 -11 355 664 ; C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ; C -1 ; WX 611 ; N Rcaron ; B -13 0 588 873 ; C -1 ; WX 722 ; N Gcommaaccent ; B 52 -217 722 666 ; C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ; C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ; C -1 ; WX 611 ; N Amacron ; B -51 0 564 795 ; C -1 ; WX 389 ; N rcaron ; B 45 0 434 661 ; C -1 ; WX 444 ; N ccedilla ; B 30 -217 425 441 ; C -1 ; WX 556 ; N Zdotaccent ; B -6 0 606 818 ; C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ; C -1 ; WX 722 ; N Omacron ; B 60 -18 699 795 ; C -1 ; WX 611 ; N Racute ; B -13 0 588 876 ; C -1 ; WX 500 ; N Sacute ; B 17 -18 508 876 ; C -1 ; WX 544 ; N dcaron ; B 15 -13 658 683 ; C -1 ; WX 722 ; N Umacron ; B 102 -18 765 795 ; C -1 ; WX 500 ; N uring ; B 42 -11 475 691 ; C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ; C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ; C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ; C -1 ; WX 611 ; N Abreve ; B -51 0 564 862 ; C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ; C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ; C -1 ; WX 556 ; N Tcaron ; B 59 0 633 873 ; C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ; C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ; C -1 ; WX 667 ; N Nacute ; B -20 -15 727 876 ; C -1 ; WX 278 ; N icircumflex ; B 33 -11 327 661 ; C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ; C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ; C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ; C -1 ; WX 444 ; N cacute ; B 30 -11 459 664 ; C -1 ; WX 500 ; N nacute ; B 14 -9 477 664 ; C -1 ; WX 500 ; N umacron ; B 42 -11 485 583 ; C -1 ; WX 667 ; N Ncaron ; B -20 -15 727 873 ; C -1 ; WX 333 ; N Iacute ; B -8 0 433 876 ; C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ; C -1 ; WX 275 ; N brokenbar ; B 105 -142 171 708 ; C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ; C -1 ; WX 722 ; N Gbreve ; B 52 -18 722 862 ; C -1 ; WX 333 ; N Idotaccent ; B -8 0 384 818 ; C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ; C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ; C -1 ; WX 389 ; N racute ; B 45 0 431 664 ; C -1 ; WX 500 ; N omacron ; B 27 -11 495 583 ; C -1 ; WX 556 ; N Zacute ; B -6 0 606 876 ; C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 658 ; C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ; C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ; C -1 ; WX 278 ; N lcommaaccent ; B 22 -217 279 683 ; C -1 ; WX 300 ; N tcaron ; B 37 -11 407 681 ; C -1 ; WX 444 ; N eogonek ; B 31 -169 412 441 ; C -1 ; WX 722 ; N Uogonek ; B 102 -184 765 653 ; C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ; C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ; C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ; C -1 ; WX 389 ; N zacute ; B -2 -81 431 664 ; C -1 ; WX 278 ; N iogonek ; B 49 -169 264 654 ; C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ; C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ; C -1 ; WX 500 ; N amacron ; B 17 -11 495 583 ; C -1 ; WX 389 ; N sacute ; B 16 -13 431 664 ; C -1 ; WX 278 ; N idieresis ; B 49 -11 352 606 ; C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ; C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ; C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ; C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ; C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ; C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ; C -1 ; WX 500 ; N ohungarumlaut ; B 27 -11 590 664 ; C -1 ; WX 611 ; N Eogonek ; B -1 -169 634 653 ; C -1 ; WX 500 ; N dcroat ; B 15 -13 572 683 ; C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ; C -1 ; WX 500 ; N Scedilla ; B 17 -217 508 667 ; C -1 ; WX 300 ; N lcaron ; B 41 -11 407 683 ; C -1 ; WX 667 ; N Kcommaaccent ; B 7 -217 722 653 ; C -1 ; WX 556 ; N Lacute ; B -8 0 559 876 ; C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ; C -1 ; WX 444 ; N edotaccent ; B 31 -11 412 606 ; C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ; C -1 ; WX 333 ; N Imacron ; B -8 0 441 795 ; C -1 ; WX 611 ; N Lcaron ; B -8 0 586 653 ; C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ; C -1 ; WX 549 ; N lessequal ; B 26 0 523 658 ; C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ; C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 102 -18 765 876 ; C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ; C -1 ; WX 444 ; N emacron ; B 31 -11 457 583 ; C -1 ; WX 500 ; N gbreve ; B 8 -206 487 650 ; C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ; C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ; C -1 ; WX 500 ; N Scommaaccent ; B 17 -217 508 667 ; C -1 ; WX 722 ; N Ohungarumlaut ; B 60 -18 699 876 ; C -1 ; WX 400 ; N degree ; B 101 390 387 676 ; C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ; C -1 ; WX 667 ; N Ccaron ; B 66 -18 689 873 ; C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ; C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ; C -1 ; WX 722 ; N Dcaron ; B -8 0 700 873 ; C -1 ; WX 389 ; N rcommaaccent ; B -3 -217 412 441 ; C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ; C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ; C -1 ; WX 611 ; N Rcommaaccent ; B -13 -187 588 653 ; C -1 ; WX 556 ; N Lcommaaccent ; B -8 -217 559 653 ; C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ; C -1 ; WX 611 ; N Aogonek ; B -51 -169 566 668 ; C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ; C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ; C -1 ; WX 389 ; N zdotaccent ; B -2 -81 380 606 ; C -1 ; WX 611 ; N Ecaron ; B -1 0 634 873 ; C -1 ; WX 333 ; N Iogonek ; B -8 -169 384 653 ; C -1 ; WX 444 ; N kcommaaccent ; B 14 -187 461 683 ; C -1 ; WX 675 ; N minus ; B 86 220 590 286 ; C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ; C -1 ; WX 500 ; N ncaron ; B 14 -9 510 661 ; C -1 ; WX 278 ; N tcommaaccent ; B 2 -217 296 546 ; C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ; C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ; C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ; C -1 ; WX 549 ; N notequal ; B 12 -29 537 541 ; C -1 ; WX 500 ; N gcommaaccent ; B 8 -206 472 706 ; C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ; C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ; C -1 ; WX 500 ; N ncommaaccent ; B 14 -187 474 441 ; C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ; C -1 ; WX 278 ; N imacron ; B 46 -11 311 583 ; C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2321 KPX A C -30 KPX A Cacute -30 KPX A Ccaron -30 KPX A Ccedilla -30 KPX A G -35 KPX A Gbreve -35 KPX A Gcommaaccent -35 KPX A O -40 KPX A Oacute -40 KPX A Ocircumflex -40 KPX A Odieresis -40 KPX A Ograve -40 KPX A Ohungarumlaut -40 KPX A Omacron -40 KPX A Oslash -40 KPX A Otilde -40 KPX A Q -40 KPX A T -37 KPX A Tcaron -37 KPX A Tcommaaccent -37 KPX A U -50 KPX A Uacute -50 KPX A Ucircumflex -50 KPX A Udieresis -50 KPX A Ugrave -50 KPX A Uhungarumlaut -50 KPX A Umacron -50 KPX A Uogonek -50 KPX A Uring -50 KPX A V -105 KPX A W -95 KPX A Y -55 KPX A Yacute -55 KPX A Ydieresis -55 KPX A quoteright -37 KPX A u -20 KPX A uacute -20 KPX A ucircumflex -20 KPX A udieresis -20 KPX A ugrave -20 KPX A uhungarumlaut -20 KPX A umacron -20 KPX A uogonek -20 KPX A uring -20 KPX A v -55 KPX A w -55 KPX A y -55 KPX A yacute -55 KPX A ydieresis -55 KPX Aacute C -30 KPX Aacute Cacute -30 KPX Aacute Ccaron -30 KPX Aacute Ccedilla -30 KPX Aacute G -35 KPX Aacute Gbreve -35 KPX Aacute Gcommaaccent -35 KPX Aacute O -40 KPX Aacute Oacute -40 KPX Aacute Ocircumflex -40 KPX Aacute Odieresis -40 KPX Aacute Ograve -40 KPX Aacute Ohungarumlaut -40 KPX Aacute Omacron -40 KPX Aacute Oslash -40 KPX Aacute Otilde -40 KPX Aacute Q -40 KPX Aacute T -37 KPX Aacute Tcaron -37 KPX Aacute Tcommaaccent -37 KPX Aacute U -50 KPX Aacute Uacute -50 KPX Aacute Ucircumflex -50 KPX Aacute Udieresis -50 KPX Aacute Ugrave -50 KPX Aacute Uhungarumlaut -50 KPX Aacute Umacron -50 KPX Aacute Uogonek -50 KPX Aacute Uring -50 KPX Aacute V -105 KPX Aacute W -95 KPX Aacute Y -55 KPX Aacute Yacute -55 KPX Aacute Ydieresis -55 KPX Aacute quoteright -37 KPX Aacute u -20 KPX Aacute uacute -20 KPX Aacute ucircumflex -20 KPX Aacute udieresis -20 KPX Aacute ugrave -20 KPX Aacute uhungarumlaut -20 KPX Aacute umacron -20 KPX Aacute uogonek -20 KPX Aacute uring -20 KPX Aacute v -55 KPX Aacute w -55 KPX Aacute y -55 KPX Aacute yacute -55 KPX Aacute ydieresis -55 KPX Abreve C -30 KPX Abreve Cacute -30 KPX Abreve Ccaron -30 KPX Abreve Ccedilla -30 KPX Abreve G -35 KPX Abreve Gbreve -35 KPX Abreve Gcommaaccent -35 KPX Abreve O -40 KPX Abreve Oacute -40 KPX Abreve Ocircumflex -40 KPX Abreve Odieresis -40 KPX Abreve Ograve -40 KPX Abreve Ohungarumlaut -40 KPX Abreve Omacron -40 KPX Abreve Oslash -40 KPX Abreve Otilde -40 KPX Abreve Q -40 KPX Abreve T -37 KPX Abreve Tcaron -37 KPX Abreve Tcommaaccent -37 KPX Abreve U -50 KPX Abreve Uacute -50 KPX Abreve Ucircumflex -50 KPX Abreve Udieresis -50 KPX Abreve Ugrave -50 KPX Abreve Uhungarumlaut -50 KPX Abreve Umacron -50 KPX Abreve Uogonek -50 KPX Abreve Uring -50 KPX Abreve V -105 KPX Abreve W -95 KPX Abreve Y -55 KPX Abreve Yacute -55 KPX Abreve Ydieresis -55 KPX Abreve quoteright -37 KPX Abreve u -20 KPX Abreve uacute -20 KPX Abreve ucircumflex -20 KPX Abreve udieresis -20 KPX Abreve ugrave -20 KPX Abreve uhungarumlaut -20 KPX Abreve umacron -20 KPX Abreve uogonek -20 KPX Abreve uring -20 KPX Abreve v -55 KPX Abreve w -55 KPX Abreve y -55 KPX Abreve yacute -55 KPX Abreve ydieresis -55 KPX Acircumflex C -30 KPX Acircumflex Cacute -30 KPX Acircumflex Ccaron -30 KPX Acircumflex Ccedilla -30 KPX Acircumflex G -35 KPX Acircumflex Gbreve -35 KPX Acircumflex Gcommaaccent -35 KPX Acircumflex O -40 KPX Acircumflex Oacute -40 KPX Acircumflex Ocircumflex -40 KPX Acircumflex Odieresis -40 KPX Acircumflex Ograve -40 KPX Acircumflex Ohungarumlaut -40 KPX Acircumflex Omacron -40 KPX Acircumflex Oslash -40 KPX Acircumflex Otilde -40 KPX Acircumflex Q -40 KPX Acircumflex T -37 KPX Acircumflex Tcaron -37 KPX Acircumflex Tcommaaccent -37 KPX Acircumflex U -50 KPX Acircumflex Uacute -50 KPX Acircumflex Ucircumflex -50 KPX Acircumflex Udieresis -50 KPX Acircumflex Ugrave -50 KPX Acircumflex Uhungarumlaut -50 KPX Acircumflex Umacron -50 KPX Acircumflex Uogonek -50 KPX Acircumflex Uring -50 KPX Acircumflex V -105 KPX Acircumflex W -95 KPX Acircumflex Y -55 KPX Acircumflex Yacute -55 KPX Acircumflex Ydieresis -55 KPX Acircumflex quoteright -37 KPX Acircumflex u -20 KPX Acircumflex uacute -20 KPX Acircumflex ucircumflex -20 KPX Acircumflex udieresis -20 KPX Acircumflex ugrave -20 KPX Acircumflex uhungarumlaut -20 KPX Acircumflex umacron -20 KPX Acircumflex uogonek -20 KPX Acircumflex uring -20 KPX Acircumflex v -55 KPX Acircumflex w -55 KPX Acircumflex y -55 KPX Acircumflex yacute -55 KPX Acircumflex ydieresis -55 KPX Adieresis C -30 KPX Adieresis Cacute -30 KPX Adieresis Ccaron -30 KPX Adieresis Ccedilla -30 KPX Adieresis G -35 KPX Adieresis Gbreve -35 KPX Adieresis Gcommaaccent -35 KPX Adieresis O -40 KPX Adieresis Oacute -40 KPX Adieresis Ocircumflex -40 KPX Adieresis Odieresis -40 KPX Adieresis Ograve -40 KPX Adieresis Ohungarumlaut -40 KPX Adieresis Omacron -40 KPX Adieresis Oslash -40 KPX Adieresis Otilde -40 KPX Adieresis Q -40 KPX Adieresis T -37 KPX Adieresis Tcaron -37 KPX Adieresis Tcommaaccent -37 KPX Adieresis U -50 KPX Adieresis Uacute -50 KPX Adieresis Ucircumflex -50 KPX Adieresis Udieresis -50 KPX Adieresis Ugrave -50 KPX Adieresis Uhungarumlaut -50 KPX Adieresis Umacron -50 KPX Adieresis Uogonek -50 KPX Adieresis Uring -50 KPX Adieresis V -105 KPX Adieresis W -95 KPX Adieresis Y -55 KPX Adieresis Yacute -55 KPX Adieresis Ydieresis -55 KPX Adieresis quoteright -37 KPX Adieresis u -20 KPX Adieresis uacute -20 KPX Adieresis ucircumflex -20 KPX Adieresis udieresis -20 KPX Adieresis ugrave -20 KPX Adieresis uhungarumlaut -20 KPX Adieresis umacron -20 KPX Adieresis uogonek -20 KPX Adieresis uring -20 KPX Adieresis v -55 KPX Adieresis w -55 KPX Adieresis y -55 KPX Adieresis yacute -55 KPX Adieresis ydieresis -55 KPX Agrave C -30 KPX Agrave Cacute -30 KPX Agrave Ccaron -30 KPX Agrave Ccedilla -30 KPX Agrave G -35 KPX Agrave Gbreve -35 KPX Agrave Gcommaaccent -35 KPX Agrave O -40 KPX Agrave Oacute -40 KPX Agrave Ocircumflex -40 KPX Agrave Odieresis -40 KPX Agrave Ograve -40 KPX Agrave Ohungarumlaut -40 KPX Agrave Omacron -40 KPX Agrave Oslash -40 KPX Agrave Otilde -40 KPX Agrave Q -40 KPX Agrave T -37 KPX Agrave Tcaron -37 KPX Agrave Tcommaaccent -37 KPX Agrave U -50 KPX Agrave Uacute -50 KPX Agrave Ucircumflex -50 KPX Agrave Udieresis -50 KPX Agrave Ugrave -50 KPX Agrave Uhungarumlaut -50 KPX Agrave Umacron -50 KPX Agrave Uogonek -50 KPX Agrave Uring -50 KPX Agrave V -105 KPX Agrave W -95 KPX Agrave Y -55 KPX Agrave Yacute -55 KPX Agrave Ydieresis -55 KPX Agrave quoteright -37 KPX Agrave u -20 KPX Agrave uacute -20 KPX Agrave ucircumflex -20 KPX Agrave udieresis -20 KPX Agrave ugrave -20 KPX Agrave uhungarumlaut -20 KPX Agrave umacron -20 KPX Agrave uogonek -20 KPX Agrave uring -20 KPX Agrave v -55 KPX Agrave w -55 KPX Agrave y -55 KPX Agrave yacute -55 KPX Agrave ydieresis -55 KPX Amacron C -30 KPX Amacron Cacute -30 KPX Amacron Ccaron -30 KPX Amacron Ccedilla -30 KPX Amacron G -35 KPX Amacron Gbreve -35 KPX Amacron Gcommaaccent -35 KPX Amacron O -40 KPX Amacron Oacute -40 KPX Amacron Ocircumflex -40 KPX Amacron Odieresis -40 KPX Amacron Ograve -40 KPX Amacron Ohungarumlaut -40 KPX Amacron Omacron -40 KPX Amacron Oslash -40 KPX Amacron Otilde -40 KPX Amacron Q -40 KPX Amacron T -37 KPX Amacron Tcaron -37 KPX Amacron Tcommaaccent -37 KPX Amacron U -50 KPX Amacron Uacute -50 KPX Amacron Ucircumflex -50 KPX Amacron Udieresis -50 KPX Amacron Ugrave -50 KPX Amacron Uhungarumlaut -50 KPX Amacron Umacron -50 KPX Amacron Uogonek -50 KPX Amacron Uring -50 KPX Amacron V -105 KPX Amacron W -95 KPX Amacron Y -55 KPX Amacron Yacute -55 KPX Amacron Ydieresis -55 KPX Amacron quoteright -37 KPX Amacron u -20 KPX Amacron uacute -20 KPX Amacron ucircumflex -20 KPX Amacron udieresis -20 KPX Amacron ugrave -20 KPX Amacron uhungarumlaut -20 KPX Amacron umacron -20 KPX Amacron uogonek -20 KPX Amacron uring -20 KPX Amacron v -55 KPX Amacron w -55 KPX Amacron y -55 KPX Amacron yacute -55 KPX Amacron ydieresis -55 KPX Aogonek C -30 KPX Aogonek Cacute -30 KPX Aogonek Ccaron -30 KPX Aogonek Ccedilla -30 KPX Aogonek G -35 KPX Aogonek Gbreve -35 KPX Aogonek Gcommaaccent -35 KPX Aogonek O -40 KPX Aogonek Oacute -40 KPX Aogonek Ocircumflex -40 KPX Aogonek Odieresis -40 KPX Aogonek Ograve -40 KPX Aogonek Ohungarumlaut -40 KPX Aogonek Omacron -40 KPX Aogonek Oslash -40 KPX Aogonek Otilde -40 KPX Aogonek Q -40 KPX Aogonek T -37 KPX Aogonek Tcaron -37 KPX Aogonek Tcommaaccent -37 KPX Aogonek U -50 KPX Aogonek Uacute -50 KPX Aogonek Ucircumflex -50 KPX Aogonek Udieresis -50 KPX Aogonek Ugrave -50 KPX Aogonek Uhungarumlaut -50 KPX Aogonek Umacron -50 KPX Aogonek Uogonek -50 KPX Aogonek Uring -50 KPX Aogonek V -105 KPX Aogonek W -95 KPX Aogonek Y -55 KPX Aogonek Yacute -55 KPX Aogonek Ydieresis -55 KPX Aogonek quoteright -37 KPX Aogonek u -20 KPX Aogonek uacute -20 KPX Aogonek ucircumflex -20 KPX Aogonek udieresis -20 KPX Aogonek ugrave -20 KPX Aogonek uhungarumlaut -20 KPX Aogonek umacron -20 KPX Aogonek uogonek -20 KPX Aogonek uring -20 KPX Aogonek v -55 KPX Aogonek w -55 KPX Aogonek y -55 KPX Aogonek yacute -55 KPX Aogonek ydieresis -55 KPX Aring C -30 KPX Aring Cacute -30 KPX Aring Ccaron -30 KPX Aring Ccedilla -30 KPX Aring G -35 KPX Aring Gbreve -35 KPX Aring Gcommaaccent -35 KPX Aring O -40 KPX Aring Oacute -40 KPX Aring Ocircumflex -40 KPX Aring Odieresis -40 KPX Aring Ograve -40 KPX Aring Ohungarumlaut -40 KPX Aring Omacron -40 KPX Aring Oslash -40 KPX Aring Otilde -40 KPX Aring Q -40 KPX Aring T -37 KPX Aring Tcaron -37 KPX Aring Tcommaaccent -37 KPX Aring U -50 KPX Aring Uacute -50 KPX Aring Ucircumflex -50 KPX Aring Udieresis -50 KPX Aring Ugrave -50 KPX Aring Uhungarumlaut -50 KPX Aring Umacron -50 KPX Aring Uogonek -50 KPX Aring Uring -50 KPX Aring V -105 KPX Aring W -95 KPX Aring Y -55 KPX Aring Yacute -55 KPX Aring Ydieresis -55 KPX Aring quoteright -37 KPX Aring u -20 KPX Aring uacute -20 KPX Aring ucircumflex -20 KPX Aring udieresis -20 KPX Aring ugrave -20 KPX Aring uhungarumlaut -20 KPX Aring umacron -20 KPX Aring uogonek -20 KPX Aring uring -20 KPX Aring v -55 KPX Aring w -55 KPX Aring y -55 KPX Aring yacute -55 KPX Aring ydieresis -55 KPX Atilde C -30 KPX Atilde Cacute -30 KPX Atilde Ccaron -30 KPX Atilde Ccedilla -30 KPX Atilde G -35 KPX Atilde Gbreve -35 KPX Atilde Gcommaaccent -35 KPX Atilde O -40 KPX Atilde Oacute -40 KPX Atilde Ocircumflex -40 KPX Atilde Odieresis -40 KPX Atilde Ograve -40 KPX Atilde Ohungarumlaut -40 KPX Atilde Omacron -40 KPX Atilde Oslash -40 KPX Atilde Otilde -40 KPX Atilde Q -40 KPX Atilde T -37 KPX Atilde Tcaron -37 KPX Atilde Tcommaaccent -37 KPX Atilde U -50 KPX Atilde Uacute -50 KPX Atilde Ucircumflex -50 KPX Atilde Udieresis -50 KPX Atilde Ugrave -50 KPX Atilde Uhungarumlaut -50 KPX Atilde Umacron -50 KPX Atilde Uogonek -50 KPX Atilde Uring -50 KPX Atilde V -105 KPX Atilde W -95 KPX Atilde Y -55 KPX Atilde Yacute -55 KPX Atilde Ydieresis -55 KPX Atilde quoteright -37 KPX Atilde u -20 KPX Atilde uacute -20 KPX Atilde ucircumflex -20 KPX Atilde udieresis -20 KPX Atilde ugrave -20 KPX Atilde uhungarumlaut -20 KPX Atilde umacron -20 KPX Atilde uogonek -20 KPX Atilde uring -20 KPX Atilde v -55 KPX Atilde w -55 KPX Atilde y -55 KPX Atilde yacute -55 KPX Atilde ydieresis -55 KPX B A -25 KPX B Aacute -25 KPX B Abreve -25 KPX B Acircumflex -25 KPX B Adieresis -25 KPX B Agrave -25 KPX B Amacron -25 KPX B Aogonek -25 KPX B Aring -25 KPX B Atilde -25 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -35 KPX D Aacute -35 KPX D Abreve -35 KPX D Acircumflex -35 KPX D Adieresis -35 KPX D Agrave -35 KPX D Amacron -35 KPX D Aogonek -35 KPX D Aring -35 KPX D Atilde -35 KPX D V -40 KPX D W -40 KPX D Y -40 KPX D Yacute -40 KPX D Ydieresis -40 KPX Dcaron A -35 KPX Dcaron Aacute -35 KPX Dcaron Abreve -35 KPX Dcaron Acircumflex -35 KPX Dcaron Adieresis -35 KPX Dcaron Agrave -35 KPX Dcaron Amacron -35 KPX Dcaron Aogonek -35 KPX Dcaron Aring -35 KPX Dcaron Atilde -35 KPX Dcaron V -40 KPX Dcaron W -40 KPX Dcaron Y -40 KPX Dcaron Yacute -40 KPX Dcaron Ydieresis -40 KPX Dcroat A -35 KPX Dcroat Aacute -35 KPX Dcroat Abreve -35 KPX Dcroat Acircumflex -35 KPX Dcroat Adieresis -35 KPX Dcroat Agrave -35 KPX Dcroat Amacron -35 KPX Dcroat Aogonek -35 KPX Dcroat Aring -35 KPX Dcroat Atilde -35 KPX Dcroat V -40 KPX Dcroat W -40 KPX Dcroat Y -40 KPX Dcroat Yacute -40 KPX Dcroat Ydieresis -40 KPX F A -115 KPX F Aacute -115 KPX F Abreve -115 KPX F Acircumflex -115 KPX F Adieresis -115 KPX F Agrave -115 KPX F Amacron -115 KPX F Aogonek -115 KPX F Aring -115 KPX F Atilde -115 KPX F a -75 KPX F aacute -75 KPX F abreve -75 KPX F acircumflex -75 KPX F adieresis -75 KPX F agrave -75 KPX F amacron -75 KPX F aogonek -75 KPX F aring -75 KPX F atilde -75 KPX F comma -135 KPX F e -75 KPX F eacute -75 KPX F ecaron -75 KPX F ecircumflex -75 KPX F edieresis -75 KPX F edotaccent -75 KPX F egrave -75 KPX F emacron -75 KPX F eogonek -75 KPX F i -45 KPX F iacute -45 KPX F icircumflex -45 KPX F idieresis -45 KPX F igrave -45 KPX F imacron -45 KPX F iogonek -45 KPX F o -105 KPX F oacute -105 KPX F ocircumflex -105 KPX F odieresis -105 KPX F ograve -105 KPX F ohungarumlaut -105 KPX F omacron -105 KPX F oslash -105 KPX F otilde -105 KPX F period -135 KPX F r -55 KPX F racute -55 KPX F rcaron -55 KPX F rcommaaccent -55 KPX J A -40 KPX J Aacute -40 KPX J Abreve -40 KPX J Acircumflex -40 KPX J Adieresis -40 KPX J Agrave -40 KPX J Amacron -40 KPX J Aogonek -40 KPX J Aring -40 KPX J Atilde -40 KPX J a -35 KPX J aacute -35 KPX J abreve -35 KPX J acircumflex -35 KPX J adieresis -35 KPX J agrave -35 KPX J amacron -35 KPX J aogonek -35 KPX J aring -35 KPX J atilde -35 KPX J comma -25 KPX J e -25 KPX J eacute -25 KPX J ecaron -25 KPX J ecircumflex -25 KPX J edieresis -25 KPX J edotaccent -25 KPX J egrave -25 KPX J emacron -25 KPX J eogonek -25 KPX J o -25 KPX J oacute -25 KPX J ocircumflex -25 KPX J odieresis -25 KPX J ograve -25 KPX J ohungarumlaut -25 KPX J omacron -25 KPX J oslash -25 KPX J otilde -25 KPX J period -25 KPX J u -35 KPX J uacute -35 KPX J ucircumflex -35 KPX J udieresis -35 KPX J ugrave -35 KPX J uhungarumlaut -35 KPX J umacron -35 KPX J uogonek -35 KPX J uring -35 KPX K O -50 KPX K Oacute -50 KPX K Ocircumflex -50 KPX K Odieresis -50 KPX K Ograve -50 KPX K Ohungarumlaut -50 KPX K Omacron -50 KPX K Oslash -50 KPX K Otilde -50 KPX K e -35 KPX K eacute -35 KPX K ecaron -35 KPX K ecircumflex -35 KPX K edieresis -35 KPX K edotaccent -35 KPX K egrave -35 KPX K emacron -35 KPX K eogonek -35 KPX K o -40 KPX K oacute -40 KPX K ocircumflex -40 KPX K odieresis -40 KPX K ograve -40 KPX K ohungarumlaut -40 KPX K omacron -40 KPX K oslash -40 KPX K otilde -40 KPX K u -40 KPX K uacute -40 KPX K ucircumflex -40 KPX K udieresis -40 KPX K ugrave -40 KPX K uhungarumlaut -40 KPX K umacron -40 KPX K uogonek -40 KPX K uring -40 KPX K y -40 KPX K yacute -40 KPX K ydieresis -40 KPX Kcommaaccent O -50 KPX Kcommaaccent Oacute -50 KPX Kcommaaccent Ocircumflex -50 KPX Kcommaaccent Odieresis -50 KPX Kcommaaccent Ograve -50 KPX Kcommaaccent Ohungarumlaut -50 KPX Kcommaaccent Omacron -50 KPX Kcommaaccent Oslash -50 KPX Kcommaaccent Otilde -50 KPX Kcommaaccent e -35 KPX Kcommaaccent eacute -35 KPX Kcommaaccent ecaron -35 KPX Kcommaaccent ecircumflex -35 KPX Kcommaaccent edieresis -35 KPX Kcommaaccent edotaccent -35 KPX Kcommaaccent egrave -35 KPX Kcommaaccent emacron -35 KPX Kcommaaccent eogonek -35 KPX Kcommaaccent o -40 KPX Kcommaaccent oacute -40 KPX Kcommaaccent ocircumflex -40 KPX Kcommaaccent odieresis -40 KPX Kcommaaccent ograve -40 KPX Kcommaaccent ohungarumlaut -40 KPX Kcommaaccent omacron -40 KPX Kcommaaccent oslash -40 KPX Kcommaaccent otilde -40 KPX Kcommaaccent u -40 KPX Kcommaaccent uacute -40 KPX Kcommaaccent ucircumflex -40 KPX Kcommaaccent udieresis -40 KPX Kcommaaccent ugrave -40 KPX Kcommaaccent uhungarumlaut -40 KPX Kcommaaccent umacron -40 KPX Kcommaaccent uogonek -40 KPX Kcommaaccent uring -40 KPX Kcommaaccent y -40 KPX Kcommaaccent yacute -40 KPX Kcommaaccent ydieresis -40 KPX L T -20 KPX L Tcaron -20 KPX L Tcommaaccent -20 KPX L V -55 KPX L W -55 KPX L Y -20 KPX L Yacute -20 KPX L Ydieresis -20 KPX L quoteright -37 KPX L y -30 KPX L yacute -30 KPX L ydieresis -30 KPX Lacute T -20 KPX Lacute Tcaron -20 KPX Lacute Tcommaaccent -20 KPX Lacute V -55 KPX Lacute W -55 KPX Lacute Y -20 KPX Lacute Yacute -20 KPX Lacute Ydieresis -20 KPX Lacute quoteright -37 KPX Lacute y -30 KPX Lacute yacute -30 KPX Lacute ydieresis -30 KPX Lcommaaccent T -20 KPX Lcommaaccent Tcaron -20 KPX Lcommaaccent Tcommaaccent -20 KPX Lcommaaccent V -55 KPX Lcommaaccent W -55 KPX Lcommaaccent Y -20 KPX Lcommaaccent Yacute -20 KPX Lcommaaccent Ydieresis -20 KPX Lcommaaccent quoteright -37 KPX Lcommaaccent y -30 KPX Lcommaaccent yacute -30 KPX Lcommaaccent ydieresis -30 KPX Lslash T -20 KPX Lslash Tcaron -20 KPX Lslash Tcommaaccent -20 KPX Lslash V -55 KPX Lslash W -55 KPX Lslash Y -20 KPX Lslash Yacute -20 KPX Lslash Ydieresis -20 KPX Lslash quoteright -37 KPX Lslash y -30 KPX Lslash yacute -30 KPX Lslash ydieresis -30 KPX N A -27 KPX N Aacute -27 KPX N Abreve -27 KPX N Acircumflex -27 KPX N Adieresis -27 KPX N Agrave -27 KPX N Amacron -27 KPX N Aogonek -27 KPX N Aring -27 KPX N Atilde -27 KPX Nacute A -27 KPX Nacute Aacute -27 KPX Nacute Abreve -27 KPX Nacute Acircumflex -27 KPX Nacute Adieresis -27 KPX Nacute Agrave -27 KPX Nacute Amacron -27 KPX Nacute Aogonek -27 KPX Nacute Aring -27 KPX Nacute Atilde -27 KPX Ncaron A -27 KPX Ncaron Aacute -27 KPX Ncaron Abreve -27 KPX Ncaron Acircumflex -27 KPX Ncaron Adieresis -27 KPX Ncaron Agrave -27 KPX Ncaron Amacron -27 KPX Ncaron Aogonek -27 KPX Ncaron Aring -27 KPX Ncaron Atilde -27 KPX Ncommaaccent A -27 KPX Ncommaaccent Aacute -27 KPX Ncommaaccent Abreve -27 KPX Ncommaaccent Acircumflex -27 KPX Ncommaaccent Adieresis -27 KPX Ncommaaccent Agrave -27 KPX Ncommaaccent Amacron -27 KPX Ncommaaccent Aogonek -27 KPX Ncommaaccent Aring -27 KPX Ncommaaccent Atilde -27 KPX Ntilde A -27 KPX Ntilde Aacute -27 KPX Ntilde Abreve -27 KPX Ntilde Acircumflex -27 KPX Ntilde Adieresis -27 KPX Ntilde Agrave -27 KPX Ntilde Amacron -27 KPX Ntilde Aogonek -27 KPX Ntilde Aring -27 KPX Ntilde Atilde -27 KPX O A -55 KPX O Aacute -55 KPX O Abreve -55 KPX O Acircumflex -55 KPX O Adieresis -55 KPX O Agrave -55 KPX O Amacron -55 KPX O Aogonek -55 KPX O Aring -55 KPX O Atilde -55 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -50 KPX O X -40 KPX O Y -50 KPX O Yacute -50 KPX O Ydieresis -50 KPX Oacute A -55 KPX Oacute Aacute -55 KPX Oacute Abreve -55 KPX Oacute Acircumflex -55 KPX Oacute Adieresis -55 KPX Oacute Agrave -55 KPX Oacute Amacron -55 KPX Oacute Aogonek -55 KPX Oacute Aring -55 KPX Oacute Atilde -55 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -50 KPX Oacute X -40 KPX Oacute Y -50 KPX Oacute Yacute -50 KPX Oacute Ydieresis -50 KPX Ocircumflex A -55 KPX Ocircumflex Aacute -55 KPX Ocircumflex Abreve -55 KPX Ocircumflex Acircumflex -55 KPX Ocircumflex Adieresis -55 KPX Ocircumflex Agrave -55 KPX Ocircumflex Amacron -55 KPX Ocircumflex Aogonek -55 KPX Ocircumflex Aring -55 KPX Ocircumflex Atilde -55 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -50 KPX Ocircumflex X -40 KPX Ocircumflex Y -50 KPX Ocircumflex Yacute -50 KPX Ocircumflex Ydieresis -50 KPX Odieresis A -55 KPX Odieresis Aacute -55 KPX Odieresis Abreve -55 KPX Odieresis Acircumflex -55 KPX Odieresis Adieresis -55 KPX Odieresis Agrave -55 KPX Odieresis Amacron -55 KPX Odieresis Aogonek -55 KPX Odieresis Aring -55 KPX Odieresis Atilde -55 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -50 KPX Odieresis X -40 KPX Odieresis Y -50 KPX Odieresis Yacute -50 KPX Odieresis Ydieresis -50 KPX Ograve A -55 KPX Ograve Aacute -55 KPX Ograve Abreve -55 KPX Ograve Acircumflex -55 KPX Ograve Adieresis -55 KPX Ograve Agrave -55 KPX Ograve Amacron -55 KPX Ograve Aogonek -55 KPX Ograve Aring -55 KPX Ograve Atilde -55 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -50 KPX Ograve X -40 KPX Ograve Y -50 KPX Ograve Yacute -50 KPX Ograve Ydieresis -50 KPX Ohungarumlaut A -55 KPX Ohungarumlaut Aacute -55 KPX Ohungarumlaut Abreve -55 KPX Ohungarumlaut Acircumflex -55 KPX Ohungarumlaut Adieresis -55 KPX Ohungarumlaut Agrave -55 KPX Ohungarumlaut Amacron -55 KPX Ohungarumlaut Aogonek -55 KPX Ohungarumlaut Aring -55 KPX Ohungarumlaut Atilde -55 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -50 KPX Ohungarumlaut X -40 KPX Ohungarumlaut Y -50 KPX Ohungarumlaut Yacute -50 KPX Ohungarumlaut Ydieresis -50 KPX Omacron A -55 KPX Omacron Aacute -55 KPX Omacron Abreve -55 KPX Omacron Acircumflex -55 KPX Omacron Adieresis -55 KPX Omacron Agrave -55 KPX Omacron Amacron -55 KPX Omacron Aogonek -55 KPX Omacron Aring -55 KPX Omacron Atilde -55 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -50 KPX Omacron X -40 KPX Omacron Y -50 KPX Omacron Yacute -50 KPX Omacron Ydieresis -50 KPX Oslash A -55 KPX Oslash Aacute -55 KPX Oslash Abreve -55 KPX Oslash Acircumflex -55 KPX Oslash Adieresis -55 KPX Oslash Agrave -55 KPX Oslash Amacron -55 KPX Oslash Aogonek -55 KPX Oslash Aring -55 KPX Oslash Atilde -55 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -50 KPX Oslash X -40 KPX Oslash Y -50 KPX Oslash Yacute -50 KPX Oslash Ydieresis -50 KPX Otilde A -55 KPX Otilde Aacute -55 KPX Otilde Abreve -55 KPX Otilde Acircumflex -55 KPX Otilde Adieresis -55 KPX Otilde Agrave -55 KPX Otilde Amacron -55 KPX Otilde Aogonek -55 KPX Otilde Aring -55 KPX Otilde Atilde -55 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -50 KPX Otilde X -40 KPX Otilde Y -50 KPX Otilde Yacute -50 KPX Otilde Ydieresis -50 KPX P A -90 KPX P Aacute -90 KPX P Abreve -90 KPX P Acircumflex -90 KPX P Adieresis -90 KPX P Agrave -90 KPX P Amacron -90 KPX P Aogonek -90 KPX P Aring -90 KPX P Atilde -90 KPX P a -80 KPX P aacute -80 KPX P abreve -80 KPX P acircumflex -80 KPX P adieresis -80 KPX P agrave -80 KPX P amacron -80 KPX P aogonek -80 KPX P aring -80 KPX P atilde -80 KPX P comma -135 KPX P e -80 KPX P eacute -80 KPX P ecaron -80 KPX P ecircumflex -80 KPX P edieresis -80 KPX P edotaccent -80 KPX P egrave -80 KPX P emacron -80 KPX P eogonek -80 KPX P o -80 KPX P oacute -80 KPX P ocircumflex -80 KPX P odieresis -80 KPX P ograve -80 KPX P ohungarumlaut -80 KPX P omacron -80 KPX P oslash -80 KPX P otilde -80 KPX P period -135 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX R O -40 KPX R Oacute -40 KPX R Ocircumflex -40 KPX R Odieresis -40 KPX R Ograve -40 KPX R Ohungarumlaut -40 KPX R Omacron -40 KPX R Oslash -40 KPX R Otilde -40 KPX R U -40 KPX R Uacute -40 KPX R Ucircumflex -40 KPX R Udieresis -40 KPX R Ugrave -40 KPX R Uhungarumlaut -40 KPX R Umacron -40 KPX R Uogonek -40 KPX R Uring -40 KPX R V -18 KPX R W -18 KPX R Y -18 KPX R Yacute -18 KPX R Ydieresis -18 KPX Racute O -40 KPX Racute Oacute -40 KPX Racute Ocircumflex -40 KPX Racute Odieresis -40 KPX Racute Ograve -40 KPX Racute Ohungarumlaut -40 KPX Racute Omacron -40 KPX Racute Oslash -40 KPX Racute Otilde -40 KPX Racute U -40 KPX Racute Uacute -40 KPX Racute Ucircumflex -40 KPX Racute Udieresis -40 KPX Racute Ugrave -40 KPX Racute Uhungarumlaut -40 KPX Racute Umacron -40 KPX Racute Uogonek -40 KPX Racute Uring -40 KPX Racute V -18 KPX Racute W -18 KPX Racute Y -18 KPX Racute Yacute -18 KPX Racute Ydieresis -18 KPX Rcaron O -40 KPX Rcaron Oacute -40 KPX Rcaron Ocircumflex -40 KPX Rcaron Odieresis -40 KPX Rcaron Ograve -40 KPX Rcaron Ohungarumlaut -40 KPX Rcaron Omacron -40 KPX Rcaron Oslash -40 KPX Rcaron Otilde -40 KPX Rcaron U -40 KPX Rcaron Uacute -40 KPX Rcaron Ucircumflex -40 KPX Rcaron Udieresis -40 KPX Rcaron Ugrave -40 KPX Rcaron Uhungarumlaut -40 KPX Rcaron Umacron -40 KPX Rcaron Uogonek -40 KPX Rcaron Uring -40 KPX Rcaron V -18 KPX Rcaron W -18 KPX Rcaron Y -18 KPX Rcaron Yacute -18 KPX Rcaron Ydieresis -18 KPX Rcommaaccent O -40 KPX Rcommaaccent Oacute -40 KPX Rcommaaccent Ocircumflex -40 KPX Rcommaaccent Odieresis -40 KPX Rcommaaccent Ograve -40 KPX Rcommaaccent Ohungarumlaut -40 KPX Rcommaaccent Omacron -40 KPX Rcommaaccent Oslash -40 KPX Rcommaaccent Otilde -40 KPX Rcommaaccent U -40 KPX Rcommaaccent Uacute -40 KPX Rcommaaccent Ucircumflex -40 KPX Rcommaaccent Udieresis -40 KPX Rcommaaccent Ugrave -40 KPX Rcommaaccent Uhungarumlaut -40 KPX Rcommaaccent Umacron -40 KPX Rcommaaccent Uogonek -40 KPX Rcommaaccent Uring -40 KPX Rcommaaccent V -18 KPX Rcommaaccent W -18 KPX Rcommaaccent Y -18 KPX Rcommaaccent Yacute -18 KPX Rcommaaccent Ydieresis -18 KPX T A -50 KPX T Aacute -50 KPX T Abreve -50 KPX T Acircumflex -50 KPX T Adieresis -50 KPX T Agrave -50 KPX T Amacron -50 KPX T Aogonek -50 KPX T Aring -50 KPX T Atilde -50 KPX T O -18 KPX T Oacute -18 KPX T Ocircumflex -18 KPX T Odieresis -18 KPX T Ograve -18 KPX T Ohungarumlaut -18 KPX T Omacron -18 KPX T Oslash -18 KPX T Otilde -18 KPX T a -92 KPX T aacute -92 KPX T abreve -92 KPX T acircumflex -92 KPX T adieresis -92 KPX T agrave -92 KPX T amacron -92 KPX T aogonek -92 KPX T aring -92 KPX T atilde -92 KPX T colon -55 KPX T comma -74 KPX T e -92 KPX T eacute -92 KPX T ecaron -92 KPX T ecircumflex -52 KPX T edieresis -52 KPX T edotaccent -92 KPX T egrave -52 KPX T emacron -52 KPX T eogonek -92 KPX T hyphen -74 KPX T i -55 KPX T iacute -55 KPX T iogonek -55 KPX T o -92 KPX T oacute -92 KPX T ocircumflex -92 KPX T odieresis -92 KPX T ograve -92 KPX T ohungarumlaut -92 KPX T omacron -92 KPX T oslash -92 KPX T otilde -92 KPX T period -74 KPX T r -55 KPX T racute -55 KPX T rcaron -55 KPX T rcommaaccent -55 KPX T semicolon -65 KPX T u -55 KPX T uacute -55 KPX T ucircumflex -55 KPX T udieresis -55 KPX T ugrave -55 KPX T uhungarumlaut -55 KPX T umacron -55 KPX T uogonek -55 KPX T uring -55 KPX T w -74 KPX T y -74 KPX T yacute -74 KPX T ydieresis -34 KPX Tcaron A -50 KPX Tcaron Aacute -50 KPX Tcaron Abreve -50 KPX Tcaron Acircumflex -50 KPX Tcaron Adieresis -50 KPX Tcaron Agrave -50 KPX Tcaron Amacron -50 KPX Tcaron Aogonek -50 KPX Tcaron Aring -50 KPX Tcaron Atilde -50 KPX Tcaron O -18 KPX Tcaron Oacute -18 KPX Tcaron Ocircumflex -18 KPX Tcaron Odieresis -18 KPX Tcaron Ograve -18 KPX Tcaron Ohungarumlaut -18 KPX Tcaron Omacron -18 KPX Tcaron Oslash -18 KPX Tcaron Otilde -18 KPX Tcaron a -92 KPX Tcaron aacute -92 KPX Tcaron abreve -92 KPX Tcaron acircumflex -92 KPX Tcaron adieresis -92 KPX Tcaron agrave -92 KPX Tcaron amacron -92 KPX Tcaron aogonek -92 KPX Tcaron aring -92 KPX Tcaron atilde -92 KPX Tcaron colon -55 KPX Tcaron comma -74 KPX Tcaron e -92 KPX Tcaron eacute -92 KPX Tcaron ecaron -92 KPX Tcaron ecircumflex -52 KPX Tcaron edieresis -52 KPX Tcaron edotaccent -92 KPX Tcaron egrave -52 KPX Tcaron emacron -52 KPX Tcaron eogonek -92 KPX Tcaron hyphen -74 KPX Tcaron i -55 KPX Tcaron iacute -55 KPX Tcaron iogonek -55 KPX Tcaron o -92 KPX Tcaron oacute -92 KPX Tcaron ocircumflex -92 KPX Tcaron odieresis -92 KPX Tcaron ograve -92 KPX Tcaron ohungarumlaut -92 KPX Tcaron omacron -92 KPX Tcaron oslash -92 KPX Tcaron otilde -92 KPX Tcaron period -74 KPX Tcaron r -55 KPX Tcaron racute -55 KPX Tcaron rcaron -55 KPX Tcaron rcommaaccent -55 KPX Tcaron semicolon -65 KPX Tcaron u -55 KPX Tcaron uacute -55 KPX Tcaron ucircumflex -55 KPX Tcaron udieresis -55 KPX Tcaron ugrave -55 KPX Tcaron uhungarumlaut -55 KPX Tcaron umacron -55 KPX Tcaron uogonek -55 KPX Tcaron uring -55 KPX Tcaron w -74 KPX Tcaron y -74 KPX Tcaron yacute -74 KPX Tcaron ydieresis -34 KPX Tcommaaccent A -50 KPX Tcommaaccent Aacute -50 KPX Tcommaaccent Abreve -50 KPX Tcommaaccent Acircumflex -50 KPX Tcommaaccent Adieresis -50 KPX Tcommaaccent Agrave -50 KPX Tcommaaccent Amacron -50 KPX Tcommaaccent Aogonek -50 KPX Tcommaaccent Aring -50 KPX Tcommaaccent Atilde -50 KPX Tcommaaccent O -18 KPX Tcommaaccent Oacute -18 KPX Tcommaaccent Ocircumflex -18 KPX Tcommaaccent Odieresis -18 KPX Tcommaaccent Ograve -18 KPX Tcommaaccent Ohungarumlaut -18 KPX Tcommaaccent Omacron -18 KPX Tcommaaccent Oslash -18 KPX Tcommaaccent Otilde -18 KPX Tcommaaccent a -92 KPX Tcommaaccent aacute -92 KPX Tcommaaccent abreve -92 KPX Tcommaaccent acircumflex -92 KPX Tcommaaccent adieresis -92 KPX Tcommaaccent agrave -92 KPX Tcommaaccent amacron -92 KPX Tcommaaccent aogonek -92 KPX Tcommaaccent aring -92 KPX Tcommaaccent atilde -92 KPX Tcommaaccent colon -55 KPX Tcommaaccent comma -74 KPX Tcommaaccent e -92 KPX Tcommaaccent eacute -92 KPX Tcommaaccent ecaron -92 KPX Tcommaaccent ecircumflex -52 KPX Tcommaaccent edieresis -52 KPX Tcommaaccent edotaccent -92 KPX Tcommaaccent egrave -52 KPX Tcommaaccent emacron -52 KPX Tcommaaccent eogonek -92 KPX Tcommaaccent hyphen -74 KPX Tcommaaccent i -55 KPX Tcommaaccent iacute -55 KPX Tcommaaccent iogonek -55 KPX Tcommaaccent o -92 KPX Tcommaaccent oacute -92 KPX Tcommaaccent ocircumflex -92 KPX Tcommaaccent odieresis -92 KPX Tcommaaccent ograve -92 KPX Tcommaaccent ohungarumlaut -92 KPX Tcommaaccent omacron -92 KPX Tcommaaccent oslash -92 KPX Tcommaaccent otilde -92 KPX Tcommaaccent period -74 KPX Tcommaaccent r -55 KPX Tcommaaccent racute -55 KPX Tcommaaccent rcaron -55 KPX Tcommaaccent rcommaaccent -55 KPX Tcommaaccent semicolon -65 KPX Tcommaaccent u -55 KPX Tcommaaccent uacute -55 KPX Tcommaaccent ucircumflex -55 KPX Tcommaaccent udieresis -55 KPX Tcommaaccent ugrave -55 KPX Tcommaaccent uhungarumlaut -55 KPX Tcommaaccent umacron -55 KPX Tcommaaccent uogonek -55 KPX Tcommaaccent uring -55 KPX Tcommaaccent w -74 KPX Tcommaaccent y -74 KPX Tcommaaccent yacute -74 KPX Tcommaaccent ydieresis -34 KPX U A -40 KPX U Aacute -40 KPX U Abreve -40 KPX U Acircumflex -40 KPX U Adieresis -40 KPX U Agrave -40 KPX U Amacron -40 KPX U Aogonek -40 KPX U Aring -40 KPX U Atilde -40 KPX U comma -25 KPX U period -25 KPX Uacute A -40 KPX Uacute Aacute -40 KPX Uacute Abreve -40 KPX Uacute Acircumflex -40 KPX Uacute Adieresis -40 KPX Uacute Agrave -40 KPX Uacute Amacron -40 KPX Uacute Aogonek -40 KPX Uacute Aring -40 KPX Uacute Atilde -40 KPX Uacute comma -25 KPX Uacute period -25 KPX Ucircumflex A -40 KPX Ucircumflex Aacute -40 KPX Ucircumflex Abreve -40 KPX Ucircumflex Acircumflex -40 KPX Ucircumflex Adieresis -40 KPX Ucircumflex Agrave -40 KPX Ucircumflex Amacron -40 KPX Ucircumflex Aogonek -40 KPX Ucircumflex Aring -40 KPX Ucircumflex Atilde -40 KPX Ucircumflex comma -25 KPX Ucircumflex period -25 KPX Udieresis A -40 KPX Udieresis Aacute -40 KPX Udieresis Abreve -40 KPX Udieresis Acircumflex -40 KPX Udieresis Adieresis -40 KPX Udieresis Agrave -40 KPX Udieresis Amacron -40 KPX Udieresis Aogonek -40 KPX Udieresis Aring -40 KPX Udieresis Atilde -40 KPX Udieresis comma -25 KPX Udieresis period -25 KPX Ugrave A -40 KPX Ugrave Aacute -40 KPX Ugrave Abreve -40 KPX Ugrave Acircumflex -40 KPX Ugrave Adieresis -40 KPX Ugrave Agrave -40 KPX Ugrave Amacron -40 KPX Ugrave Aogonek -40 KPX Ugrave Aring -40 KPX Ugrave Atilde -40 KPX Ugrave comma -25 KPX Ugrave period -25 KPX Uhungarumlaut A -40 KPX Uhungarumlaut Aacute -40 KPX Uhungarumlaut Abreve -40 KPX Uhungarumlaut Acircumflex -40 KPX Uhungarumlaut Adieresis -40 KPX Uhungarumlaut Agrave -40 KPX Uhungarumlaut Amacron -40 KPX Uhungarumlaut Aogonek -40 KPX Uhungarumlaut Aring -40 KPX Uhungarumlaut Atilde -40 KPX Uhungarumlaut comma -25 KPX Uhungarumlaut period -25 KPX Umacron A -40 KPX Umacron Aacute -40 KPX Umacron Abreve -40 KPX Umacron Acircumflex -40 KPX Umacron Adieresis -40 KPX Umacron Agrave -40 KPX Umacron Amacron -40 KPX Umacron Aogonek -40 KPX Umacron Aring -40 KPX Umacron Atilde -40 KPX Umacron comma -25 KPX Umacron period -25 KPX Uogonek A -40 KPX Uogonek Aacute -40 KPX Uogonek Abreve -40 KPX Uogonek Acircumflex -40 KPX Uogonek Adieresis -40 KPX Uogonek Agrave -40 KPX Uogonek Amacron -40 KPX Uogonek Aogonek -40 KPX Uogonek Aring -40 KPX Uogonek Atilde -40 KPX Uogonek comma -25 KPX Uogonek period -25 KPX Uring A -40 KPX Uring Aacute -40 KPX Uring Abreve -40 KPX Uring Acircumflex -40 KPX Uring Adieresis -40 KPX Uring Agrave -40 KPX Uring Amacron -40 KPX Uring Aogonek -40 KPX Uring Aring -40 KPX Uring Atilde -40 KPX Uring comma -25 KPX Uring period -25 KPX V A -60 KPX V Aacute -60 KPX V Abreve -60 KPX V Acircumflex -60 KPX V Adieresis -60 KPX V Agrave -60 KPX V Amacron -60 KPX V Aogonek -60 KPX V Aring -60 KPX V Atilde -60 KPX V O -30 KPX V Oacute -30 KPX V Ocircumflex -30 KPX V Odieresis -30 KPX V Ograve -30 KPX V Ohungarumlaut -30 KPX V Omacron -30 KPX V Oslash -30 KPX V Otilde -30 KPX V a -111 KPX V aacute -111 KPX V abreve -111 KPX V acircumflex -111 KPX V adieresis -111 KPX V agrave -111 KPX V amacron -111 KPX V aogonek -111 KPX V aring -111 KPX V atilde -111 KPX V colon -65 KPX V comma -129 KPX V e -111 KPX V eacute -111 KPX V ecaron -111 KPX V ecircumflex -111 KPX V edieresis -71 KPX V edotaccent -111 KPX V egrave -71 KPX V emacron -71 KPX V eogonek -111 KPX V hyphen -55 KPX V i -74 KPX V iacute -74 KPX V icircumflex -34 KPX V idieresis -34 KPX V igrave -34 KPX V imacron -34 KPX V iogonek -74 KPX V o -111 KPX V oacute -111 KPX V ocircumflex -111 KPX V odieresis -111 KPX V ograve -111 KPX V ohungarumlaut -111 KPX V omacron -111 KPX V oslash -111 KPX V otilde -111 KPX V period -129 KPX V semicolon -74 KPX V u -74 KPX V uacute -74 KPX V ucircumflex -74 KPX V udieresis -74 KPX V ugrave -74 KPX V uhungarumlaut -74 KPX V umacron -74 KPX V uogonek -74 KPX V uring -74 KPX W A -60 KPX W Aacute -60 KPX W Abreve -60 KPX W Acircumflex -60 KPX W Adieresis -60 KPX W Agrave -60 KPX W Amacron -60 KPX W Aogonek -60 KPX W Aring -60 KPX W Atilde -60 KPX W O -25 KPX W Oacute -25 KPX W Ocircumflex -25 KPX W Odieresis -25 KPX W Ograve -25 KPX W Ohungarumlaut -25 KPX W Omacron -25 KPX W Oslash -25 KPX W Otilde -25 KPX W a -92 KPX W aacute -92 KPX W abreve -92 KPX W acircumflex -92 KPX W adieresis -92 KPX W agrave -92 KPX W amacron -92 KPX W aogonek -92 KPX W aring -92 KPX W atilde -92 KPX W colon -65 KPX W comma -92 KPX W e -92 KPX W eacute -92 KPX W ecaron -92 KPX W ecircumflex -92 KPX W edieresis -52 KPX W edotaccent -92 KPX W egrave -52 KPX W emacron -52 KPX W eogonek -92 KPX W hyphen -37 KPX W i -55 KPX W iacute -55 KPX W iogonek -55 KPX W o -92 KPX W oacute -92 KPX W ocircumflex -92 KPX W odieresis -92 KPX W ograve -92 KPX W ohungarumlaut -92 KPX W omacron -92 KPX W oslash -92 KPX W otilde -92 KPX W period -92 KPX W semicolon -65 KPX W u -55 KPX W uacute -55 KPX W ucircumflex -55 KPX W udieresis -55 KPX W ugrave -55 KPX W uhungarumlaut -55 KPX W umacron -55 KPX W uogonek -55 KPX W uring -55 KPX W y -70 KPX W yacute -70 KPX W ydieresis -70 KPX Y A -50 KPX Y Aacute -50 KPX Y Abreve -50 KPX Y Acircumflex -50 KPX Y Adieresis -50 KPX Y Agrave -50 KPX Y Amacron -50 KPX Y Aogonek -50 KPX Y Aring -50 KPX Y Atilde -50 KPX Y O -15 KPX Y Oacute -15 KPX Y Ocircumflex -15 KPX Y Odieresis -15 KPX Y Ograve -15 KPX Y Ohungarumlaut -15 KPX Y Omacron -15 KPX Y Oslash -15 KPX Y Otilde -15 KPX Y a -92 KPX Y aacute -92 KPX Y abreve -92 KPX Y acircumflex -92 KPX Y adieresis -92 KPX Y agrave -92 KPX Y amacron -92 KPX Y aogonek -92 KPX Y aring -92 KPX Y atilde -92 KPX Y colon -65 KPX Y comma -92 KPX Y e -92 KPX Y eacute -92 KPX Y ecaron -92 KPX Y ecircumflex -92 KPX Y edieresis -52 KPX Y edotaccent -92 KPX Y egrave -52 KPX Y emacron -52 KPX Y eogonek -92 KPX Y hyphen -74 KPX Y i -74 KPX Y iacute -74 KPX Y icircumflex -34 KPX Y idieresis -34 KPX Y igrave -34 KPX Y imacron -34 KPX Y iogonek -74 KPX Y o -92 KPX Y oacute -92 KPX Y ocircumflex -92 KPX Y odieresis -92 KPX Y ograve -92 KPX Y ohungarumlaut -92 KPX Y omacron -92 KPX Y oslash -92 KPX Y otilde -92 KPX Y period -92 KPX Y semicolon -65 KPX Y u -92 KPX Y uacute -92 KPX Y ucircumflex -92 KPX Y udieresis -92 KPX Y ugrave -92 KPX Y uhungarumlaut -92 KPX Y umacron -92 KPX Y uogonek -92 KPX Y uring -92 KPX Yacute A -50 KPX Yacute Aacute -50 KPX Yacute Abreve -50 KPX Yacute Acircumflex -50 KPX Yacute Adieresis -50 KPX Yacute Agrave -50 KPX Yacute Amacron -50 KPX Yacute Aogonek -50 KPX Yacute Aring -50 KPX Yacute Atilde -50 KPX Yacute O -15 KPX Yacute Oacute -15 KPX Yacute Ocircumflex -15 KPX Yacute Odieresis -15 KPX Yacute Ograve -15 KPX Yacute Ohungarumlaut -15 KPX Yacute Omacron -15 KPX Yacute Oslash -15 KPX Yacute Otilde -15 KPX Yacute a -92 KPX Yacute aacute -92 KPX Yacute abreve -92 KPX Yacute acircumflex -92 KPX Yacute adieresis -92 KPX Yacute agrave -92 KPX Yacute amacron -92 KPX Yacute aogonek -92 KPX Yacute aring -92 KPX Yacute atilde -92 KPX Yacute colon -65 KPX Yacute comma -92 KPX Yacute e -92 KPX Yacute eacute -92 KPX Yacute ecaron -92 KPX Yacute ecircumflex -92 KPX Yacute edieresis -52 KPX Yacute edotaccent -92 KPX Yacute egrave -52 KPX Yacute emacron -52 KPX Yacute eogonek -92 KPX Yacute hyphen -74 KPX Yacute i -74 KPX Yacute iacute -74 KPX Yacute icircumflex -34 KPX Yacute idieresis -34 KPX Yacute igrave -34 KPX Yacute imacron -34 KPX Yacute iogonek -74 KPX Yacute o -92 KPX Yacute oacute -92 KPX Yacute ocircumflex -92 KPX Yacute odieresis -92 KPX Yacute ograve -92 KPX Yacute ohungarumlaut -92 KPX Yacute omacron -92 KPX Yacute oslash -92 KPX Yacute otilde -92 KPX Yacute period -92 KPX Yacute semicolon -65 KPX Yacute u -92 KPX Yacute uacute -92 KPX Yacute ucircumflex -92 KPX Yacute udieresis -92 KPX Yacute ugrave -92 KPX Yacute uhungarumlaut -92 KPX Yacute umacron -92 KPX Yacute uogonek -92 KPX Yacute uring -92 KPX Ydieresis A -50 KPX Ydieresis Aacute -50 KPX Ydieresis Abreve -50 KPX Ydieresis Acircumflex -50 KPX Ydieresis Adieresis -50 KPX Ydieresis Agrave -50 KPX Ydieresis Amacron -50 KPX Ydieresis Aogonek -50 KPX Ydieresis Aring -50 KPX Ydieresis Atilde -50 KPX Ydieresis O -15 KPX Ydieresis Oacute -15 KPX Ydieresis Ocircumflex -15 KPX Ydieresis Odieresis -15 KPX Ydieresis Ograve -15 KPX Ydieresis Ohungarumlaut -15 KPX Ydieresis Omacron -15 KPX Ydieresis Oslash -15 KPX Ydieresis Otilde -15 KPX Ydieresis a -92 KPX Ydieresis aacute -92 KPX Ydieresis abreve -92 KPX Ydieresis acircumflex -92 KPX Ydieresis adieresis -92 KPX Ydieresis agrave -92 KPX Ydieresis amacron -92 KPX Ydieresis aogonek -92 KPX Ydieresis aring -92 KPX Ydieresis atilde -92 KPX Ydieresis colon -65 KPX Ydieresis comma -92 KPX Ydieresis e -92 KPX Ydieresis eacute -92 KPX Ydieresis ecaron -92 KPX Ydieresis ecircumflex -92 KPX Ydieresis edieresis -52 KPX Ydieresis edotaccent -92 KPX Ydieresis egrave -52 KPX Ydieresis emacron -52 KPX Ydieresis eogonek -92 KPX Ydieresis hyphen -74 KPX Ydieresis i -74 KPX Ydieresis iacute -74 KPX Ydieresis icircumflex -34 KPX Ydieresis idieresis -34 KPX Ydieresis igrave -34 KPX Ydieresis imacron -34 KPX Ydieresis iogonek -74 KPX Ydieresis o -92 KPX Ydieresis oacute -92 KPX Ydieresis ocircumflex -92 KPX Ydieresis odieresis -92 KPX Ydieresis ograve -92 KPX Ydieresis ohungarumlaut -92 KPX Ydieresis omacron -92 KPX Ydieresis oslash -92 KPX Ydieresis otilde -92 KPX Ydieresis period -92 KPX Ydieresis semicolon -65 KPX Ydieresis u -92 KPX Ydieresis uacute -92 KPX Ydieresis ucircumflex -92 KPX Ydieresis udieresis -92 KPX Ydieresis ugrave -92 KPX Ydieresis uhungarumlaut -92 KPX Ydieresis umacron -92 KPX Ydieresis uogonek -92 KPX Ydieresis uring -92 KPX a g -10 KPX a gbreve -10 KPX a gcommaaccent -10 KPX aacute g -10 KPX aacute gbreve -10 KPX aacute gcommaaccent -10 KPX abreve g -10 KPX abreve gbreve -10 KPX abreve gcommaaccent -10 KPX acircumflex g -10 KPX acircumflex gbreve -10 KPX acircumflex gcommaaccent -10 KPX adieresis g -10 KPX adieresis gbreve -10 KPX adieresis gcommaaccent -10 KPX agrave g -10 KPX agrave gbreve -10 KPX agrave gcommaaccent -10 KPX amacron g -10 KPX amacron gbreve -10 KPX amacron gcommaaccent -10 KPX aogonek g -10 KPX aogonek gbreve -10 KPX aogonek gcommaaccent -10 KPX aring g -10 KPX aring gbreve -10 KPX aring gcommaaccent -10 KPX atilde g -10 KPX atilde gbreve -10 KPX atilde gcommaaccent -10 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX c h -15 KPX c k -20 KPX c kcommaaccent -20 KPX cacute h -15 KPX cacute k -20 KPX cacute kcommaaccent -20 KPX ccaron h -15 KPX ccaron k -20 KPX ccaron kcommaaccent -20 KPX ccedilla h -15 KPX ccedilla k -20 KPX ccedilla kcommaaccent -20 KPX comma quotedblright -140 KPX comma quoteright -140 KPX e comma -10 KPX e g -40 KPX e gbreve -40 KPX e gcommaaccent -40 KPX e period -15 KPX e v -15 KPX e w -15 KPX e x -20 KPX e y -30 KPX e yacute -30 KPX e ydieresis -30 KPX eacute comma -10 KPX eacute g -40 KPX eacute gbreve -40 KPX eacute gcommaaccent -40 KPX eacute period -15 KPX eacute v -15 KPX eacute w -15 KPX eacute x -20 KPX eacute y -30 KPX eacute yacute -30 KPX eacute ydieresis -30 KPX ecaron comma -10 KPX ecaron g -40 KPX ecaron gbreve -40 KPX ecaron gcommaaccent -40 KPX ecaron period -15 KPX ecaron v -15 KPX ecaron w -15 KPX ecaron x -20 KPX ecaron y -30 KPX ecaron yacute -30 KPX ecaron ydieresis -30 KPX ecircumflex comma -10 KPX ecircumflex g -40 KPX ecircumflex gbreve -40 KPX ecircumflex gcommaaccent -40 KPX ecircumflex period -15 KPX ecircumflex v -15 KPX ecircumflex w -15 KPX ecircumflex x -20 KPX ecircumflex y -30 KPX ecircumflex yacute -30 KPX ecircumflex ydieresis -30 KPX edieresis comma -10 KPX edieresis g -40 KPX edieresis gbreve -40 KPX edieresis gcommaaccent -40 KPX edieresis period -15 KPX edieresis v -15 KPX edieresis w -15 KPX edieresis x -20 KPX edieresis y -30 KPX edieresis yacute -30 KPX edieresis ydieresis -30 KPX edotaccent comma -10 KPX edotaccent g -40 KPX edotaccent gbreve -40 KPX edotaccent gcommaaccent -40 KPX edotaccent period -15 KPX edotaccent v -15 KPX edotaccent w -15 KPX edotaccent x -20 KPX edotaccent y -30 KPX edotaccent yacute -30 KPX edotaccent ydieresis -30 KPX egrave comma -10 KPX egrave g -40 KPX egrave gbreve -40 KPX egrave gcommaaccent -40 KPX egrave period -15 KPX egrave v -15 KPX egrave w -15 KPX egrave x -20 KPX egrave y -30 KPX egrave yacute -30 KPX egrave ydieresis -30 KPX emacron comma -10 KPX emacron g -40 KPX emacron gbreve -40 KPX emacron gcommaaccent -40 KPX emacron period -15 KPX emacron v -15 KPX emacron w -15 KPX emacron x -20 KPX emacron y -30 KPX emacron yacute -30 KPX emacron ydieresis -30 KPX eogonek comma -10 KPX eogonek g -40 KPX eogonek gbreve -40 KPX eogonek gcommaaccent -40 KPX eogonek period -15 KPX eogonek v -15 KPX eogonek w -15 KPX eogonek x -20 KPX eogonek y -30 KPX eogonek yacute -30 KPX eogonek ydieresis -30 KPX f comma -10 KPX f dotlessi -60 KPX f f -18 KPX f i -20 KPX f iogonek -20 KPX f period -15 KPX f quoteright 92 KPX g comma -10 KPX g e -10 KPX g eacute -10 KPX g ecaron -10 KPX g ecircumflex -10 KPX g edieresis -10 KPX g edotaccent -10 KPX g egrave -10 KPX g emacron -10 KPX g eogonek -10 KPX g g -10 KPX g gbreve -10 KPX g gcommaaccent -10 KPX g period -15 KPX gbreve comma -10 KPX gbreve e -10 KPX gbreve eacute -10 KPX gbreve ecaron -10 KPX gbreve ecircumflex -10 KPX gbreve edieresis -10 KPX gbreve edotaccent -10 KPX gbreve egrave -10 KPX gbreve emacron -10 KPX gbreve eogonek -10 KPX gbreve g -10 KPX gbreve gbreve -10 KPX gbreve gcommaaccent -10 KPX gbreve period -15 KPX gcommaaccent comma -10 KPX gcommaaccent e -10 KPX gcommaaccent eacute -10 KPX gcommaaccent ecaron -10 KPX gcommaaccent ecircumflex -10 KPX gcommaaccent edieresis -10 KPX gcommaaccent edotaccent -10 KPX gcommaaccent egrave -10 KPX gcommaaccent emacron -10 KPX gcommaaccent eogonek -10 KPX gcommaaccent g -10 KPX gcommaaccent gbreve -10 KPX gcommaaccent gcommaaccent -10 KPX gcommaaccent period -15 KPX k e -10 KPX k eacute -10 KPX k ecaron -10 KPX k ecircumflex -10 KPX k edieresis -10 KPX k edotaccent -10 KPX k egrave -10 KPX k emacron -10 KPX k eogonek -10 KPX k o -10 KPX k oacute -10 KPX k ocircumflex -10 KPX k odieresis -10 KPX k ograve -10 KPX k ohungarumlaut -10 KPX k omacron -10 KPX k oslash -10 KPX k otilde -10 KPX k y -10 KPX k yacute -10 KPX k ydieresis -10 KPX kcommaaccent e -10 KPX kcommaaccent eacute -10 KPX kcommaaccent ecaron -10 KPX kcommaaccent ecircumflex -10 KPX kcommaaccent edieresis -10 KPX kcommaaccent edotaccent -10 KPX kcommaaccent egrave -10 KPX kcommaaccent emacron -10 KPX kcommaaccent eogonek -10 KPX kcommaaccent o -10 KPX kcommaaccent oacute -10 KPX kcommaaccent ocircumflex -10 KPX kcommaaccent odieresis -10 KPX kcommaaccent ograve -10 KPX kcommaaccent ohungarumlaut -10 KPX kcommaaccent omacron -10 KPX kcommaaccent oslash -10 KPX kcommaaccent otilde -10 KPX kcommaaccent y -10 KPX kcommaaccent yacute -10 KPX kcommaaccent ydieresis -10 KPX n v -40 KPX nacute v -40 KPX ncaron v -40 KPX ncommaaccent v -40 KPX ntilde v -40 KPX o g -10 KPX o gbreve -10 KPX o gcommaaccent -10 KPX o v -10 KPX oacute g -10 KPX oacute gbreve -10 KPX oacute gcommaaccent -10 KPX oacute v -10 KPX ocircumflex g -10 KPX ocircumflex gbreve -10 KPX ocircumflex gcommaaccent -10 KPX ocircumflex v -10 KPX odieresis g -10 KPX odieresis gbreve -10 KPX odieresis gcommaaccent -10 KPX odieresis v -10 KPX ograve g -10 KPX ograve gbreve -10 KPX ograve gcommaaccent -10 KPX ograve v -10 KPX ohungarumlaut g -10 KPX ohungarumlaut gbreve -10 KPX ohungarumlaut gcommaaccent -10 KPX ohungarumlaut v -10 KPX omacron g -10 KPX omacron gbreve -10 KPX omacron gcommaaccent -10 KPX omacron v -10 KPX oslash g -10 KPX oslash gbreve -10 KPX oslash gcommaaccent -10 KPX oslash v -10 KPX otilde g -10 KPX otilde gbreve -10 KPX otilde gcommaaccent -10 KPX otilde v -10 KPX period quotedblright -140 KPX period quoteright -140 KPX quoteleft quoteleft -111 KPX quoteright d -25 KPX quoteright dcroat -25 KPX quoteright quoteright -111 KPX quoteright r -25 KPX quoteright racute -25 KPX quoteright rcaron -25 KPX quoteright rcommaaccent -25 KPX quoteright s -40 KPX quoteright sacute -40 KPX quoteright scaron -40 KPX quoteright scedilla -40 KPX quoteright scommaaccent -40 KPX quoteright space -111 KPX quoteright t -30 KPX quoteright tcommaaccent -30 KPX quoteright v -10 KPX r a -15 KPX r aacute -15 KPX r abreve -15 KPX r acircumflex -15 KPX r adieresis -15 KPX r agrave -15 KPX r amacron -15 KPX r aogonek -15 KPX r aring -15 KPX r atilde -15 KPX r c -37 KPX r cacute -37 KPX r ccaron -37 KPX r ccedilla -37 KPX r comma -111 KPX r d -37 KPX r dcroat -37 KPX r e -37 KPX r eacute -37 KPX r ecaron -37 KPX r ecircumflex -37 KPX r edieresis -37 KPX r edotaccent -37 KPX r egrave -37 KPX r emacron -37 KPX r eogonek -37 KPX r g -37 KPX r gbreve -37 KPX r gcommaaccent -37 KPX r hyphen -20 KPX r o -45 KPX r oacute -45 KPX r ocircumflex -45 KPX r odieresis -45 KPX r ograve -45 KPX r ohungarumlaut -45 KPX r omacron -45 KPX r oslash -45 KPX r otilde -45 KPX r period -111 KPX r q -37 KPX r s -10 KPX r sacute -10 KPX r scaron -10 KPX r scedilla -10 KPX r scommaaccent -10 KPX racute a -15 KPX racute aacute -15 KPX racute abreve -15 KPX racute acircumflex -15 KPX racute adieresis -15 KPX racute agrave -15 KPX racute amacron -15 KPX racute aogonek -15 KPX racute aring -15 KPX racute atilde -15 KPX racute c -37 KPX racute cacute -37 KPX racute ccaron -37 KPX racute ccedilla -37 KPX racute comma -111 KPX racute d -37 KPX racute dcroat -37 KPX racute e -37 KPX racute eacute -37 KPX racute ecaron -37 KPX racute ecircumflex -37 KPX racute edieresis -37 KPX racute edotaccent -37 KPX racute egrave -37 KPX racute emacron -37 KPX racute eogonek -37 KPX racute g -37 KPX racute gbreve -37 KPX racute gcommaaccent -37 KPX racute hyphen -20 KPX racute o -45 KPX racute oacute -45 KPX racute ocircumflex -45 KPX racute odieresis -45 KPX racute ograve -45 KPX racute ohungarumlaut -45 KPX racute omacron -45 KPX racute oslash -45 KPX racute otilde -45 KPX racute period -111 KPX racute q -37 KPX racute s -10 KPX racute sacute -10 KPX racute scaron -10 KPX racute scedilla -10 KPX racute scommaaccent -10 KPX rcaron a -15 KPX rcaron aacute -15 KPX rcaron abreve -15 KPX rcaron acircumflex -15 KPX rcaron adieresis -15 KPX rcaron agrave -15 KPX rcaron amacron -15 KPX rcaron aogonek -15 KPX rcaron aring -15 KPX rcaron atilde -15 KPX rcaron c -37 KPX rcaron cacute -37 KPX rcaron ccaron -37 KPX rcaron ccedilla -37 KPX rcaron comma -111 KPX rcaron d -37 KPX rcaron dcroat -37 KPX rcaron e -37 KPX rcaron eacute -37 KPX rcaron ecaron -37 KPX rcaron ecircumflex -37 KPX rcaron edieresis -37 KPX rcaron edotaccent -37 KPX rcaron egrave -37 KPX rcaron emacron -37 KPX rcaron eogonek -37 KPX rcaron g -37 KPX rcaron gbreve -37 KPX rcaron gcommaaccent -37 KPX rcaron hyphen -20 KPX rcaron o -45 KPX rcaron oacute -45 KPX rcaron ocircumflex -45 KPX rcaron odieresis -45 KPX rcaron ograve -45 KPX rcaron ohungarumlaut -45 KPX rcaron omacron -45 KPX rcaron oslash -45 KPX rcaron otilde -45 KPX rcaron period -111 KPX rcaron q -37 KPX rcaron s -10 KPX rcaron sacute -10 KPX rcaron scaron -10 KPX rcaron scedilla -10 KPX rcaron scommaaccent -10 KPX rcommaaccent a -15 KPX rcommaaccent aacute -15 KPX rcommaaccent abreve -15 KPX rcommaaccent acircumflex -15 KPX rcommaaccent adieresis -15 KPX rcommaaccent agrave -15 KPX rcommaaccent amacron -15 KPX rcommaaccent aogonek -15 KPX rcommaaccent aring -15 KPX rcommaaccent atilde -15 KPX rcommaaccent c -37 KPX rcommaaccent cacute -37 KPX rcommaaccent ccaron -37 KPX rcommaaccent ccedilla -37 KPX rcommaaccent comma -111 KPX rcommaaccent d -37 KPX rcommaaccent dcroat -37 KPX rcommaaccent e -37 KPX rcommaaccent eacute -37 KPX rcommaaccent ecaron -37 KPX rcommaaccent ecircumflex -37 KPX rcommaaccent edieresis -37 KPX rcommaaccent edotaccent -37 KPX rcommaaccent egrave -37 KPX rcommaaccent emacron -37 KPX rcommaaccent eogonek -37 KPX rcommaaccent g -37 KPX rcommaaccent gbreve -37 KPX rcommaaccent gcommaaccent -37 KPX rcommaaccent hyphen -20 KPX rcommaaccent o -45 KPX rcommaaccent oacute -45 KPX rcommaaccent ocircumflex -45 KPX rcommaaccent odieresis -45 KPX rcommaaccent ograve -45 KPX rcommaaccent ohungarumlaut -45 KPX rcommaaccent omacron -45 KPX rcommaaccent oslash -45 KPX rcommaaccent otilde -45 KPX rcommaaccent period -111 KPX rcommaaccent q -37 KPX rcommaaccent s -10 KPX rcommaaccent sacute -10 KPX rcommaaccent scaron -10 KPX rcommaaccent scedilla -10 KPX rcommaaccent scommaaccent -10 KPX space A -18 KPX space Aacute -18 KPX space Abreve -18 KPX space Acircumflex -18 KPX space Adieresis -18 KPX space Agrave -18 KPX space Amacron -18 KPX space Aogonek -18 KPX space Aring -18 KPX space Atilde -18 KPX space T -18 KPX space Tcaron -18 KPX space Tcommaaccent -18 KPX space V -35 KPX space W -40 KPX space Y -75 KPX space Yacute -75 KPX space Ydieresis -75 KPX v comma -74 KPX v period -74 KPX w comma -74 KPX w period -74 KPX y comma -55 KPX y period -55 KPX yacute comma -55 KPX yacute period -55 KPX ydieresis comma -55 KPX ydieresis period -55 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/Times-Roman.afm0000644000076500000240000017263712037547555017702 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 12:49:17 1997 Comment UniqueID 43068 Comment VMusage 43909 54934 FontName Times-Roman FullName Times Roman FamilyName Times Weight Roman ItalicAngle 0 IsFixedPitch false CharacterSet ExtendedRoman FontBBox -168 -218 1000 898 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries. EncodingScheme AdobeStandardEncoding CapHeight 662 XHeight 450 Ascender 683 Descender -217 StdHW 28 StdVW 84 StartCharMetrics 315 C 32 ; WX 250 ; N space ; B 0 0 0 0 ; C 33 ; WX 333 ; N exclam ; B 130 -9 238 676 ; C 34 ; WX 408 ; N quotedbl ; B 77 431 331 676 ; C 35 ; WX 500 ; N numbersign ; B 5 0 496 662 ; C 36 ; WX 500 ; N dollar ; B 44 -87 457 727 ; C 37 ; WX 833 ; N percent ; B 61 -13 772 676 ; C 38 ; WX 778 ; N ampersand ; B 42 -13 750 676 ; C 39 ; WX 333 ; N quoteright ; B 79 433 218 676 ; C 40 ; WX 333 ; N parenleft ; B 48 -177 304 676 ; C 41 ; WX 333 ; N parenright ; B 29 -177 285 676 ; C 42 ; WX 500 ; N asterisk ; B 69 265 432 676 ; C 43 ; WX 564 ; N plus ; B 30 0 534 506 ; C 44 ; WX 250 ; N comma ; B 56 -141 195 102 ; C 45 ; WX 333 ; N hyphen ; B 39 194 285 257 ; C 46 ; WX 250 ; N period ; B 70 -11 181 100 ; C 47 ; WX 278 ; N slash ; B -9 -14 287 676 ; C 48 ; WX 500 ; N zero ; B 24 -14 476 676 ; C 49 ; WX 500 ; N one ; B 111 0 394 676 ; C 50 ; WX 500 ; N two ; B 30 0 475 676 ; C 51 ; WX 500 ; N three ; B 43 -14 431 676 ; C 52 ; WX 500 ; N four ; B 12 0 472 676 ; C 53 ; WX 500 ; N five ; B 32 -14 438 688 ; C 54 ; WX 500 ; N six ; B 34 -14 468 684 ; C 55 ; WX 500 ; N seven ; B 20 -8 449 662 ; C 56 ; WX 500 ; N eight ; B 56 -14 445 676 ; C 57 ; WX 500 ; N nine ; B 30 -22 459 676 ; C 58 ; WX 278 ; N colon ; B 81 -11 192 459 ; C 59 ; WX 278 ; N semicolon ; B 80 -141 219 459 ; C 60 ; WX 564 ; N less ; B 28 -8 536 514 ; C 61 ; WX 564 ; N equal ; B 30 120 534 386 ; C 62 ; WX 564 ; N greater ; B 28 -8 536 514 ; C 63 ; WX 444 ; N question ; B 68 -8 414 676 ; C 64 ; WX 921 ; N at ; B 116 -14 809 676 ; C 65 ; WX 722 ; N A ; B 15 0 706 674 ; C 66 ; WX 667 ; N B ; B 17 0 593 662 ; C 67 ; WX 667 ; N C ; B 28 -14 633 676 ; C 68 ; WX 722 ; N D ; B 16 0 685 662 ; C 69 ; WX 611 ; N E ; B 12 0 597 662 ; C 70 ; WX 556 ; N F ; B 12 0 546 662 ; C 71 ; WX 722 ; N G ; B 32 -14 709 676 ; C 72 ; WX 722 ; N H ; B 19 0 702 662 ; C 73 ; WX 333 ; N I ; B 18 0 315 662 ; C 74 ; WX 389 ; N J ; B 10 -14 370 662 ; C 75 ; WX 722 ; N K ; B 34 0 723 662 ; C 76 ; WX 611 ; N L ; B 12 0 598 662 ; C 77 ; WX 889 ; N M ; B 12 0 863 662 ; C 78 ; WX 722 ; N N ; B 12 -11 707 662 ; C 79 ; WX 722 ; N O ; B 34 -14 688 676 ; C 80 ; WX 556 ; N P ; B 16 0 542 662 ; C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ; C 82 ; WX 667 ; N R ; B 17 0 659 662 ; C 83 ; WX 556 ; N S ; B 42 -14 491 676 ; C 84 ; WX 611 ; N T ; B 17 0 593 662 ; C 85 ; WX 722 ; N U ; B 14 -14 705 662 ; C 86 ; WX 722 ; N V ; B 16 -11 697 662 ; C 87 ; WX 944 ; N W ; B 5 -11 932 662 ; C 88 ; WX 722 ; N X ; B 10 0 704 662 ; C 89 ; WX 722 ; N Y ; B 22 0 703 662 ; C 90 ; WX 611 ; N Z ; B 9 0 597 662 ; C 91 ; WX 333 ; N bracketleft ; B 88 -156 299 662 ; C 92 ; WX 278 ; N backslash ; B -9 -14 287 676 ; C 93 ; WX 333 ; N bracketright ; B 34 -156 245 662 ; C 94 ; WX 469 ; N asciicircum ; B 24 297 446 662 ; C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ; C 96 ; WX 333 ; N quoteleft ; B 115 433 254 676 ; C 97 ; WX 444 ; N a ; B 37 -10 442 460 ; C 98 ; WX 500 ; N b ; B 3 -10 468 683 ; C 99 ; WX 444 ; N c ; B 25 -10 412 460 ; C 100 ; WX 500 ; N d ; B 27 -10 491 683 ; C 101 ; WX 444 ; N e ; B 25 -10 424 460 ; C 102 ; WX 333 ; N f ; B 20 0 383 683 ; L i fi ; L l fl ; C 103 ; WX 500 ; N g ; B 28 -218 470 460 ; C 104 ; WX 500 ; N h ; B 9 0 487 683 ; C 105 ; WX 278 ; N i ; B 16 0 253 683 ; C 106 ; WX 278 ; N j ; B -70 -218 194 683 ; C 107 ; WX 500 ; N k ; B 7 0 505 683 ; C 108 ; WX 278 ; N l ; B 19 0 257 683 ; C 109 ; WX 778 ; N m ; B 16 0 775 460 ; C 110 ; WX 500 ; N n ; B 16 0 485 460 ; C 111 ; WX 500 ; N o ; B 29 -10 470 460 ; C 112 ; WX 500 ; N p ; B 5 -217 470 460 ; C 113 ; WX 500 ; N q ; B 24 -217 488 460 ; C 114 ; WX 333 ; N r ; B 5 0 335 460 ; C 115 ; WX 389 ; N s ; B 51 -10 348 460 ; C 116 ; WX 278 ; N t ; B 13 -10 279 579 ; C 117 ; WX 500 ; N u ; B 9 -10 479 450 ; C 118 ; WX 500 ; N v ; B 19 -14 477 450 ; C 119 ; WX 722 ; N w ; B 21 -14 694 450 ; C 120 ; WX 500 ; N x ; B 17 0 479 450 ; C 121 ; WX 500 ; N y ; B 14 -218 475 450 ; C 122 ; WX 444 ; N z ; B 27 0 418 450 ; C 123 ; WX 480 ; N braceleft ; B 100 -181 350 680 ; C 124 ; WX 200 ; N bar ; B 67 -218 133 782 ; C 125 ; WX 480 ; N braceright ; B 130 -181 380 680 ; C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ; C 161 ; WX 333 ; N exclamdown ; B 97 -218 205 467 ; C 162 ; WX 500 ; N cent ; B 53 -138 448 579 ; C 163 ; WX 500 ; N sterling ; B 12 -8 490 676 ; C 164 ; WX 167 ; N fraction ; B -168 -14 331 676 ; C 165 ; WX 500 ; N yen ; B -53 0 512 662 ; C 166 ; WX 500 ; N florin ; B 7 -189 490 676 ; C 167 ; WX 500 ; N section ; B 70 -148 426 676 ; C 168 ; WX 500 ; N currency ; B -22 58 522 602 ; C 169 ; WX 180 ; N quotesingle ; B 48 431 133 676 ; C 170 ; WX 444 ; N quotedblleft ; B 43 433 414 676 ; C 171 ; WX 500 ; N guillemotleft ; B 42 33 456 416 ; C 172 ; WX 333 ; N guilsinglleft ; B 63 33 285 416 ; C 173 ; WX 333 ; N guilsinglright ; B 48 33 270 416 ; C 174 ; WX 556 ; N fi ; B 31 0 521 683 ; C 175 ; WX 556 ; N fl ; B 32 0 521 683 ; C 177 ; WX 500 ; N endash ; B 0 201 500 250 ; C 178 ; WX 500 ; N dagger ; B 59 -149 442 676 ; C 179 ; WX 500 ; N daggerdbl ; B 58 -153 442 676 ; C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ; C 182 ; WX 453 ; N paragraph ; B -22 -154 450 662 ; C 183 ; WX 350 ; N bullet ; B 40 196 310 466 ; C 184 ; WX 333 ; N quotesinglbase ; B 79 -141 218 102 ; C 185 ; WX 444 ; N quotedblbase ; B 45 -141 416 102 ; C 186 ; WX 444 ; N quotedblright ; B 30 433 401 676 ; C 187 ; WX 500 ; N guillemotright ; B 44 33 458 416 ; C 188 ; WX 1000 ; N ellipsis ; B 111 -11 888 100 ; C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 706 ; C 191 ; WX 444 ; N questiondown ; B 30 -218 376 466 ; C 193 ; WX 333 ; N grave ; B 19 507 242 678 ; C 194 ; WX 333 ; N acute ; B 93 507 317 678 ; C 195 ; WX 333 ; N circumflex ; B 11 507 322 674 ; C 196 ; WX 333 ; N tilde ; B 1 532 331 638 ; C 197 ; WX 333 ; N macron ; B 11 547 322 601 ; C 198 ; WX 333 ; N breve ; B 26 507 307 664 ; C 199 ; WX 333 ; N dotaccent ; B 118 581 216 681 ; C 200 ; WX 333 ; N dieresis ; B 18 581 315 681 ; C 202 ; WX 333 ; N ring ; B 67 512 266 711 ; C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ; C 205 ; WX 333 ; N hungarumlaut ; B -3 507 377 678 ; C 206 ; WX 333 ; N ogonek ; B 62 -165 243 0 ; C 207 ; WX 333 ; N caron ; B 11 507 322 674 ; C 208 ; WX 1000 ; N emdash ; B 0 201 1000 250 ; C 225 ; WX 889 ; N AE ; B 0 0 863 662 ; C 227 ; WX 276 ; N ordfeminine ; B 4 394 270 676 ; C 232 ; WX 611 ; N Lslash ; B 12 0 598 662 ; C 233 ; WX 722 ; N Oslash ; B 34 -80 688 734 ; C 234 ; WX 889 ; N OE ; B 30 -6 885 668 ; C 235 ; WX 310 ; N ordmasculine ; B 6 394 304 676 ; C 241 ; WX 667 ; N ae ; B 38 -10 632 460 ; C 245 ; WX 278 ; N dotlessi ; B 16 0 253 460 ; C 248 ; WX 278 ; N lslash ; B 19 0 259 683 ; C 249 ; WX 500 ; N oslash ; B 29 -112 470 551 ; C 250 ; WX 722 ; N oe ; B 30 -10 690 460 ; C 251 ; WX 500 ; N germandbls ; B 12 -9 468 683 ; C -1 ; WX 333 ; N Idieresis ; B 18 0 315 835 ; C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ; C -1 ; WX 444 ; N abreve ; B 37 -10 442 664 ; C -1 ; WX 500 ; N uhungarumlaut ; B 9 -10 501 678 ; C -1 ; WX 444 ; N ecaron ; B 25 -10 424 674 ; C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ; C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ; C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ; C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ; C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ; C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ; C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ; C -1 ; WX 389 ; N scommaaccent ; B 51 -218 348 460 ; C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ; C -1 ; WX 722 ; N Uring ; B 14 -14 705 898 ; C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ; C -1 ; WX 444 ; N aogonek ; B 37 -165 469 460 ; C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ; C -1 ; WX 500 ; N uogonek ; B 9 -155 487 450 ; C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ; C -1 ; WX 722 ; N Dcroat ; B 16 0 685 662 ; C -1 ; WX 250 ; N commaaccent ; B 59 -218 184 -50 ; C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ; C -1 ; WX 611 ; N Emacron ; B 12 0 597 813 ; C -1 ; WX 444 ; N ccaron ; B 25 -10 412 674 ; C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ; C -1 ; WX 722 ; N Ncommaaccent ; B 12 -198 707 662 ; C -1 ; WX 278 ; N lacute ; B 19 0 290 890 ; C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ; C -1 ; WX 611 ; N Tcommaaccent ; B 17 -218 593 662 ; C -1 ; WX 667 ; N Cacute ; B 28 -14 633 890 ; C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ; C -1 ; WX 611 ; N Edotaccent ; B 12 0 597 835 ; C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ; C -1 ; WX 389 ; N scedilla ; B 51 -215 348 460 ; C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ; C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ; C -1 ; WX 667 ; N Rcaron ; B 17 0 659 886 ; C -1 ; WX 722 ; N Gcommaaccent ; B 32 -218 709 676 ; C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ; C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ; C -1 ; WX 722 ; N Amacron ; B 15 0 706 813 ; C -1 ; WX 333 ; N rcaron ; B 5 0 335 674 ; C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ; C -1 ; WX 611 ; N Zdotaccent ; B 9 0 597 835 ; C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ; C -1 ; WX 722 ; N Omacron ; B 34 -14 688 813 ; C -1 ; WX 667 ; N Racute ; B 17 0 659 890 ; C -1 ; WX 556 ; N Sacute ; B 42 -14 491 890 ; C -1 ; WX 588 ; N dcaron ; B 27 -10 589 695 ; C -1 ; WX 722 ; N Umacron ; B 14 -14 705 813 ; C -1 ; WX 500 ; N uring ; B 9 -10 479 711 ; C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ; C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ; C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ; C -1 ; WX 722 ; N Abreve ; B 15 0 706 876 ; C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ; C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ; C -1 ; WX 611 ; N Tcaron ; B 17 0 593 886 ; C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ; C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ; C -1 ; WX 722 ; N Nacute ; B 12 -11 707 890 ; C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ; C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ; C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ; C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ; C -1 ; WX 444 ; N cacute ; B 25 -10 413 678 ; C -1 ; WX 500 ; N nacute ; B 16 0 485 678 ; C -1 ; WX 500 ; N umacron ; B 9 -10 479 601 ; C -1 ; WX 722 ; N Ncaron ; B 12 -11 707 886 ; C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ; C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ; C -1 ; WX 200 ; N brokenbar ; B 67 -143 133 707 ; C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ; C -1 ; WX 722 ; N Gbreve ; B 32 -14 709 876 ; C -1 ; WX 333 ; N Idotaccent ; B 18 0 315 835 ; C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ; C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ; C -1 ; WX 333 ; N racute ; B 5 0 335 678 ; C -1 ; WX 500 ; N omacron ; B 29 -10 470 601 ; C -1 ; WX 611 ; N Zacute ; B 9 0 597 890 ; C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ; C -1 ; WX 549 ; N greaterequal ; B 26 0 523 666 ; C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ; C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ; C -1 ; WX 278 ; N lcommaaccent ; B 19 -218 257 683 ; C -1 ; WX 326 ; N tcaron ; B 13 -10 318 722 ; C -1 ; WX 444 ; N eogonek ; B 25 -165 424 460 ; C -1 ; WX 722 ; N Uogonek ; B 14 -165 705 662 ; C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ; C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ; C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ; C -1 ; WX 444 ; N zacute ; B 27 0 418 678 ; C -1 ; WX 278 ; N iogonek ; B 16 -165 265 683 ; C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ; C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ; C -1 ; WX 444 ; N amacron ; B 37 -10 442 601 ; C -1 ; WX 389 ; N sacute ; B 51 -10 348 678 ; C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ; C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ; C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ; C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ; C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ; C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ; C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ; C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ; C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ; C -1 ; WX 500 ; N ohungarumlaut ; B 29 -10 491 678 ; C -1 ; WX 611 ; N Eogonek ; B 12 -165 597 662 ; C -1 ; WX 500 ; N dcroat ; B 27 -10 500 683 ; C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ; C -1 ; WX 556 ; N Scedilla ; B 42 -215 491 676 ; C -1 ; WX 344 ; N lcaron ; B 19 0 347 695 ; C -1 ; WX 722 ; N Kcommaaccent ; B 34 -198 723 662 ; C -1 ; WX 611 ; N Lacute ; B 12 0 598 890 ; C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ; C -1 ; WX 444 ; N edotaccent ; B 25 -10 424 623 ; C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ; C -1 ; WX 333 ; N Imacron ; B 11 0 322 813 ; C -1 ; WX 611 ; N Lcaron ; B 12 0 598 676 ; C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ; C -1 ; WX 549 ; N lessequal ; B 26 0 523 666 ; C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ; C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ; C -1 ; WX 722 ; N Uhungarumlaut ; B 14 -14 705 890 ; C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ; C -1 ; WX 444 ; N emacron ; B 25 -10 424 601 ; C -1 ; WX 500 ; N gbreve ; B 28 -218 470 664 ; C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ; C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ; C -1 ; WX 556 ; N Scommaaccent ; B 42 -218 491 676 ; C -1 ; WX 722 ; N Ohungarumlaut ; B 34 -14 688 890 ; C -1 ; WX 400 ; N degree ; B 57 390 343 676 ; C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ; C -1 ; WX 667 ; N Ccaron ; B 28 -14 633 886 ; C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ; C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ; C -1 ; WX 722 ; N Dcaron ; B 16 0 685 886 ; C -1 ; WX 333 ; N rcommaaccent ; B 5 -218 335 460 ; C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ; C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ; C -1 ; WX 667 ; N Rcommaaccent ; B 17 -198 659 662 ; C -1 ; WX 611 ; N Lcommaaccent ; B 12 -218 598 662 ; C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ; C -1 ; WX 722 ; N Aogonek ; B 15 -165 738 674 ; C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ; C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ; C -1 ; WX 444 ; N zdotaccent ; B 27 0 418 623 ; C -1 ; WX 611 ; N Ecaron ; B 12 0 597 886 ; C -1 ; WX 333 ; N Iogonek ; B 18 -165 315 662 ; C -1 ; WX 500 ; N kcommaaccent ; B 7 -218 505 683 ; C -1 ; WX 564 ; N minus ; B 30 220 534 286 ; C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ; C -1 ; WX 500 ; N ncaron ; B 16 0 485 674 ; C -1 ; WX 278 ; N tcommaaccent ; B 13 -218 279 579 ; C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ; C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ; C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ; C -1 ; WX 549 ; N notequal ; B 12 -31 537 547 ; C -1 ; WX 500 ; N gcommaaccent ; B 28 -218 470 749 ; C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ; C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ; C -1 ; WX 500 ; N ncommaaccent ; B 16 -218 485 460 ; C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ; C -1 ; WX 278 ; N imacron ; B 6 0 271 601 ; C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ; EndCharMetrics StartKernData StartKernPairs 2073 KPX A C -40 KPX A Cacute -40 KPX A Ccaron -40 KPX A Ccedilla -40 KPX A G -40 KPX A Gbreve -40 KPX A Gcommaaccent -40 KPX A O -55 KPX A Oacute -55 KPX A Ocircumflex -55 KPX A Odieresis -55 KPX A Ograve -55 KPX A Ohungarumlaut -55 KPX A Omacron -55 KPX A Oslash -55 KPX A Otilde -55 KPX A Q -55 KPX A T -111 KPX A Tcaron -111 KPX A Tcommaaccent -111 KPX A U -55 KPX A Uacute -55 KPX A Ucircumflex -55 KPX A Udieresis -55 KPX A Ugrave -55 KPX A Uhungarumlaut -55 KPX A Umacron -55 KPX A Uogonek -55 KPX A Uring -55 KPX A V -135 KPX A W -90 KPX A Y -105 KPX A Yacute -105 KPX A Ydieresis -105 KPX A quoteright -111 KPX A v -74 KPX A w -92 KPX A y -92 KPX A yacute -92 KPX A ydieresis -92 KPX Aacute C -40 KPX Aacute Cacute -40 KPX Aacute Ccaron -40 KPX Aacute Ccedilla -40 KPX Aacute G -40 KPX Aacute Gbreve -40 KPX Aacute Gcommaaccent -40 KPX Aacute O -55 KPX Aacute Oacute -55 KPX Aacute Ocircumflex -55 KPX Aacute Odieresis -55 KPX Aacute Ograve -55 KPX Aacute Ohungarumlaut -55 KPX Aacute Omacron -55 KPX Aacute Oslash -55 KPX Aacute Otilde -55 KPX Aacute Q -55 KPX Aacute T -111 KPX Aacute Tcaron -111 KPX Aacute Tcommaaccent -111 KPX Aacute U -55 KPX Aacute Uacute -55 KPX Aacute Ucircumflex -55 KPX Aacute Udieresis -55 KPX Aacute Ugrave -55 KPX Aacute Uhungarumlaut -55 KPX Aacute Umacron -55 KPX Aacute Uogonek -55 KPX Aacute Uring -55 KPX Aacute V -135 KPX Aacute W -90 KPX Aacute Y -105 KPX Aacute Yacute -105 KPX Aacute Ydieresis -105 KPX Aacute quoteright -111 KPX Aacute v -74 KPX Aacute w -92 KPX Aacute y -92 KPX Aacute yacute -92 KPX Aacute ydieresis -92 KPX Abreve C -40 KPX Abreve Cacute -40 KPX Abreve Ccaron -40 KPX Abreve Ccedilla -40 KPX Abreve G -40 KPX Abreve Gbreve -40 KPX Abreve Gcommaaccent -40 KPX Abreve O -55 KPX Abreve Oacute -55 KPX Abreve Ocircumflex -55 KPX Abreve Odieresis -55 KPX Abreve Ograve -55 KPX Abreve Ohungarumlaut -55 KPX Abreve Omacron -55 KPX Abreve Oslash -55 KPX Abreve Otilde -55 KPX Abreve Q -55 KPX Abreve T -111 KPX Abreve Tcaron -111 KPX Abreve Tcommaaccent -111 KPX Abreve U -55 KPX Abreve Uacute -55 KPX Abreve Ucircumflex -55 KPX Abreve Udieresis -55 KPX Abreve Ugrave -55 KPX Abreve Uhungarumlaut -55 KPX Abreve Umacron -55 KPX Abreve Uogonek -55 KPX Abreve Uring -55 KPX Abreve V -135 KPX Abreve W -90 KPX Abreve Y -105 KPX Abreve Yacute -105 KPX Abreve Ydieresis -105 KPX Abreve quoteright -111 KPX Abreve v -74 KPX Abreve w -92 KPX Abreve y -92 KPX Abreve yacute -92 KPX Abreve ydieresis -92 KPX Acircumflex C -40 KPX Acircumflex Cacute -40 KPX Acircumflex Ccaron -40 KPX Acircumflex Ccedilla -40 KPX Acircumflex G -40 KPX Acircumflex Gbreve -40 KPX Acircumflex Gcommaaccent -40 KPX Acircumflex O -55 KPX Acircumflex Oacute -55 KPX Acircumflex Ocircumflex -55 KPX Acircumflex Odieresis -55 KPX Acircumflex Ograve -55 KPX Acircumflex Ohungarumlaut -55 KPX Acircumflex Omacron -55 KPX Acircumflex Oslash -55 KPX Acircumflex Otilde -55 KPX Acircumflex Q -55 KPX Acircumflex T -111 KPX Acircumflex Tcaron -111 KPX Acircumflex Tcommaaccent -111 KPX Acircumflex U -55 KPX Acircumflex Uacute -55 KPX Acircumflex Ucircumflex -55 KPX Acircumflex Udieresis -55 KPX Acircumflex Ugrave -55 KPX Acircumflex Uhungarumlaut -55 KPX Acircumflex Umacron -55 KPX Acircumflex Uogonek -55 KPX Acircumflex Uring -55 KPX Acircumflex V -135 KPX Acircumflex W -90 KPX Acircumflex Y -105 KPX Acircumflex Yacute -105 KPX Acircumflex Ydieresis -105 KPX Acircumflex quoteright -111 KPX Acircumflex v -74 KPX Acircumflex w -92 KPX Acircumflex y -92 KPX Acircumflex yacute -92 KPX Acircumflex ydieresis -92 KPX Adieresis C -40 KPX Adieresis Cacute -40 KPX Adieresis Ccaron -40 KPX Adieresis Ccedilla -40 KPX Adieresis G -40 KPX Adieresis Gbreve -40 KPX Adieresis Gcommaaccent -40 KPX Adieresis O -55 KPX Adieresis Oacute -55 KPX Adieresis Ocircumflex -55 KPX Adieresis Odieresis -55 KPX Adieresis Ograve -55 KPX Adieresis Ohungarumlaut -55 KPX Adieresis Omacron -55 KPX Adieresis Oslash -55 KPX Adieresis Otilde -55 KPX Adieresis Q -55 KPX Adieresis T -111 KPX Adieresis Tcaron -111 KPX Adieresis Tcommaaccent -111 KPX Adieresis U -55 KPX Adieresis Uacute -55 KPX Adieresis Ucircumflex -55 KPX Adieresis Udieresis -55 KPX Adieresis Ugrave -55 KPX Adieresis Uhungarumlaut -55 KPX Adieresis Umacron -55 KPX Adieresis Uogonek -55 KPX Adieresis Uring -55 KPX Adieresis V -135 KPX Adieresis W -90 KPX Adieresis Y -105 KPX Adieresis Yacute -105 KPX Adieresis Ydieresis -105 KPX Adieresis quoteright -111 KPX Adieresis v -74 KPX Adieresis w -92 KPX Adieresis y -92 KPX Adieresis yacute -92 KPX Adieresis ydieresis -92 KPX Agrave C -40 KPX Agrave Cacute -40 KPX Agrave Ccaron -40 KPX Agrave Ccedilla -40 KPX Agrave G -40 KPX Agrave Gbreve -40 KPX Agrave Gcommaaccent -40 KPX Agrave O -55 KPX Agrave Oacute -55 KPX Agrave Ocircumflex -55 KPX Agrave Odieresis -55 KPX Agrave Ograve -55 KPX Agrave Ohungarumlaut -55 KPX Agrave Omacron -55 KPX Agrave Oslash -55 KPX Agrave Otilde -55 KPX Agrave Q -55 KPX Agrave T -111 KPX Agrave Tcaron -111 KPX Agrave Tcommaaccent -111 KPX Agrave U -55 KPX Agrave Uacute -55 KPX Agrave Ucircumflex -55 KPX Agrave Udieresis -55 KPX Agrave Ugrave -55 KPX Agrave Uhungarumlaut -55 KPX Agrave Umacron -55 KPX Agrave Uogonek -55 KPX Agrave Uring -55 KPX Agrave V -135 KPX Agrave W -90 KPX Agrave Y -105 KPX Agrave Yacute -105 KPX Agrave Ydieresis -105 KPX Agrave quoteright -111 KPX Agrave v -74 KPX Agrave w -92 KPX Agrave y -92 KPX Agrave yacute -92 KPX Agrave ydieresis -92 KPX Amacron C -40 KPX Amacron Cacute -40 KPX Amacron Ccaron -40 KPX Amacron Ccedilla -40 KPX Amacron G -40 KPX Amacron Gbreve -40 KPX Amacron Gcommaaccent -40 KPX Amacron O -55 KPX Amacron Oacute -55 KPX Amacron Ocircumflex -55 KPX Amacron Odieresis -55 KPX Amacron Ograve -55 KPX Amacron Ohungarumlaut -55 KPX Amacron Omacron -55 KPX Amacron Oslash -55 KPX Amacron Otilde -55 KPX Amacron Q -55 KPX Amacron T -111 KPX Amacron Tcaron -111 KPX Amacron Tcommaaccent -111 KPX Amacron U -55 KPX Amacron Uacute -55 KPX Amacron Ucircumflex -55 KPX Amacron Udieresis -55 KPX Amacron Ugrave -55 KPX Amacron Uhungarumlaut -55 KPX Amacron Umacron -55 KPX Amacron Uogonek -55 KPX Amacron Uring -55 KPX Amacron V -135 KPX Amacron W -90 KPX Amacron Y -105 KPX Amacron Yacute -105 KPX Amacron Ydieresis -105 KPX Amacron quoteright -111 KPX Amacron v -74 KPX Amacron w -92 KPX Amacron y -92 KPX Amacron yacute -92 KPX Amacron ydieresis -92 KPX Aogonek C -40 KPX Aogonek Cacute -40 KPX Aogonek Ccaron -40 KPX Aogonek Ccedilla -40 KPX Aogonek G -40 KPX Aogonek Gbreve -40 KPX Aogonek Gcommaaccent -40 KPX Aogonek O -55 KPX Aogonek Oacute -55 KPX Aogonek Ocircumflex -55 KPX Aogonek Odieresis -55 KPX Aogonek Ograve -55 KPX Aogonek Ohungarumlaut -55 KPX Aogonek Omacron -55 KPX Aogonek Oslash -55 KPX Aogonek Otilde -55 KPX Aogonek Q -55 KPX Aogonek T -111 KPX Aogonek Tcaron -111 KPX Aogonek Tcommaaccent -111 KPX Aogonek U -55 KPX Aogonek Uacute -55 KPX Aogonek Ucircumflex -55 KPX Aogonek Udieresis -55 KPX Aogonek Ugrave -55 KPX Aogonek Uhungarumlaut -55 KPX Aogonek Umacron -55 KPX Aogonek Uogonek -55 KPX Aogonek Uring -55 KPX Aogonek V -135 KPX Aogonek W -90 KPX Aogonek Y -105 KPX Aogonek Yacute -105 KPX Aogonek Ydieresis -105 KPX Aogonek quoteright -111 KPX Aogonek v -74 KPX Aogonek w -52 KPX Aogonek y -52 KPX Aogonek yacute -52 KPX Aogonek ydieresis -52 KPX Aring C -40 KPX Aring Cacute -40 KPX Aring Ccaron -40 KPX Aring Ccedilla -40 KPX Aring G -40 KPX Aring Gbreve -40 KPX Aring Gcommaaccent -40 KPX Aring O -55 KPX Aring Oacute -55 KPX Aring Ocircumflex -55 KPX Aring Odieresis -55 KPX Aring Ograve -55 KPX Aring Ohungarumlaut -55 KPX Aring Omacron -55 KPX Aring Oslash -55 KPX Aring Otilde -55 KPX Aring Q -55 KPX Aring T -111 KPX Aring Tcaron -111 KPX Aring Tcommaaccent -111 KPX Aring U -55 KPX Aring Uacute -55 KPX Aring Ucircumflex -55 KPX Aring Udieresis -55 KPX Aring Ugrave -55 KPX Aring Uhungarumlaut -55 KPX Aring Umacron -55 KPX Aring Uogonek -55 KPX Aring Uring -55 KPX Aring V -135 KPX Aring W -90 KPX Aring Y -105 KPX Aring Yacute -105 KPX Aring Ydieresis -105 KPX Aring quoteright -111 KPX Aring v -74 KPX Aring w -92 KPX Aring y -92 KPX Aring yacute -92 KPX Aring ydieresis -92 KPX Atilde C -40 KPX Atilde Cacute -40 KPX Atilde Ccaron -40 KPX Atilde Ccedilla -40 KPX Atilde G -40 KPX Atilde Gbreve -40 KPX Atilde Gcommaaccent -40 KPX Atilde O -55 KPX Atilde Oacute -55 KPX Atilde Ocircumflex -55 KPX Atilde Odieresis -55 KPX Atilde Ograve -55 KPX Atilde Ohungarumlaut -55 KPX Atilde Omacron -55 KPX Atilde Oslash -55 KPX Atilde Otilde -55 KPX Atilde Q -55 KPX Atilde T -111 KPX Atilde Tcaron -111 KPX Atilde Tcommaaccent -111 KPX Atilde U -55 KPX Atilde Uacute -55 KPX Atilde Ucircumflex -55 KPX Atilde Udieresis -55 KPX Atilde Ugrave -55 KPX Atilde Uhungarumlaut -55 KPX Atilde Umacron -55 KPX Atilde Uogonek -55 KPX Atilde Uring -55 KPX Atilde V -135 KPX Atilde W -90 KPX Atilde Y -105 KPX Atilde Yacute -105 KPX Atilde Ydieresis -105 KPX Atilde quoteright -111 KPX Atilde v -74 KPX Atilde w -92 KPX Atilde y -92 KPX Atilde yacute -92 KPX Atilde ydieresis -92 KPX B A -35 KPX B Aacute -35 KPX B Abreve -35 KPX B Acircumflex -35 KPX B Adieresis -35 KPX B Agrave -35 KPX B Amacron -35 KPX B Aogonek -35 KPX B Aring -35 KPX B Atilde -35 KPX B U -10 KPX B Uacute -10 KPX B Ucircumflex -10 KPX B Udieresis -10 KPX B Ugrave -10 KPX B Uhungarumlaut -10 KPX B Umacron -10 KPX B Uogonek -10 KPX B Uring -10 KPX D A -40 KPX D Aacute -40 KPX D Abreve -40 KPX D Acircumflex -40 KPX D Adieresis -40 KPX D Agrave -40 KPX D Amacron -40 KPX D Aogonek -40 KPX D Aring -40 KPX D Atilde -40 KPX D V -40 KPX D W -30 KPX D Y -55 KPX D Yacute -55 KPX D Ydieresis -55 KPX Dcaron A -40 KPX Dcaron Aacute -40 KPX Dcaron Abreve -40 KPX Dcaron Acircumflex -40 KPX Dcaron Adieresis -40 KPX Dcaron Agrave -40 KPX Dcaron Amacron -40 KPX Dcaron Aogonek -40 KPX Dcaron Aring -40 KPX Dcaron Atilde -40 KPX Dcaron V -40 KPX Dcaron W -30 KPX Dcaron Y -55 KPX Dcaron Yacute -55 KPX Dcaron Ydieresis -55 KPX Dcroat A -40 KPX Dcroat Aacute -40 KPX Dcroat Abreve -40 KPX Dcroat Acircumflex -40 KPX Dcroat Adieresis -40 KPX Dcroat Agrave -40 KPX Dcroat Amacron -40 KPX Dcroat Aogonek -40 KPX Dcroat Aring -40 KPX Dcroat Atilde -40 KPX Dcroat V -40 KPX Dcroat W -30 KPX Dcroat Y -55 KPX Dcroat Yacute -55 KPX Dcroat Ydieresis -55 KPX F A -74 KPX F Aacute -74 KPX F Abreve -74 KPX F Acircumflex -74 KPX F Adieresis -74 KPX F Agrave -74 KPX F Amacron -74 KPX F Aogonek -74 KPX F Aring -74 KPX F Atilde -74 KPX F a -15 KPX F aacute -15 KPX F abreve -15 KPX F acircumflex -15 KPX F adieresis -15 KPX F agrave -15 KPX F amacron -15 KPX F aogonek -15 KPX F aring -15 KPX F atilde -15 KPX F comma -80 KPX F o -15 KPX F oacute -15 KPX F ocircumflex -15 KPX F odieresis -15 KPX F ograve -15 KPX F ohungarumlaut -15 KPX F omacron -15 KPX F oslash -15 KPX F otilde -15 KPX F period -80 KPX J A -60 KPX J Aacute -60 KPX J Abreve -60 KPX J Acircumflex -60 KPX J Adieresis -60 KPX J Agrave -60 KPX J Amacron -60 KPX J Aogonek -60 KPX J Aring -60 KPX J Atilde -60 KPX K O -30 KPX K Oacute -30 KPX K Ocircumflex -30 KPX K Odieresis -30 KPX K Ograve -30 KPX K Ohungarumlaut -30 KPX K Omacron -30 KPX K Oslash -30 KPX K Otilde -30 KPX K e -25 KPX K eacute -25 KPX K ecaron -25 KPX K ecircumflex -25 KPX K edieresis -25 KPX K edotaccent -25 KPX K egrave -25 KPX K emacron -25 KPX K eogonek -25 KPX K o -35 KPX K oacute -35 KPX K ocircumflex -35 KPX K odieresis -35 KPX K ograve -35 KPX K ohungarumlaut -35 KPX K omacron -35 KPX K oslash -35 KPX K otilde -35 KPX K u -15 KPX K uacute -15 KPX K ucircumflex -15 KPX K udieresis -15 KPX K ugrave -15 KPX K uhungarumlaut -15 KPX K umacron -15 KPX K uogonek -15 KPX K uring -15 KPX K y -25 KPX K yacute -25 KPX K ydieresis -25 KPX Kcommaaccent O -30 KPX Kcommaaccent Oacute -30 KPX Kcommaaccent Ocircumflex -30 KPX Kcommaaccent Odieresis -30 KPX Kcommaaccent Ograve -30 KPX Kcommaaccent Ohungarumlaut -30 KPX Kcommaaccent Omacron -30 KPX Kcommaaccent Oslash -30 KPX Kcommaaccent Otilde -30 KPX Kcommaaccent e -25 KPX Kcommaaccent eacute -25 KPX Kcommaaccent ecaron -25 KPX Kcommaaccent ecircumflex -25 KPX Kcommaaccent edieresis -25 KPX Kcommaaccent edotaccent -25 KPX Kcommaaccent egrave -25 KPX Kcommaaccent emacron -25 KPX Kcommaaccent eogonek -25 KPX Kcommaaccent o -35 KPX Kcommaaccent oacute -35 KPX Kcommaaccent ocircumflex -35 KPX Kcommaaccent odieresis -35 KPX Kcommaaccent ograve -35 KPX Kcommaaccent ohungarumlaut -35 KPX Kcommaaccent omacron -35 KPX Kcommaaccent oslash -35 KPX Kcommaaccent otilde -35 KPX Kcommaaccent u -15 KPX Kcommaaccent uacute -15 KPX Kcommaaccent ucircumflex -15 KPX Kcommaaccent udieresis -15 KPX Kcommaaccent ugrave -15 KPX Kcommaaccent uhungarumlaut -15 KPX Kcommaaccent umacron -15 KPX Kcommaaccent uogonek -15 KPX Kcommaaccent uring -15 KPX Kcommaaccent y -25 KPX Kcommaaccent yacute -25 KPX Kcommaaccent ydieresis -25 KPX L T -92 KPX L Tcaron -92 KPX L Tcommaaccent -92 KPX L V -100 KPX L W -74 KPX L Y -100 KPX L Yacute -100 KPX L Ydieresis -100 KPX L quoteright -92 KPX L y -55 KPX L yacute -55 KPX L ydieresis -55 KPX Lacute T -92 KPX Lacute Tcaron -92 KPX Lacute Tcommaaccent -92 KPX Lacute V -100 KPX Lacute W -74 KPX Lacute Y -100 KPX Lacute Yacute -100 KPX Lacute Ydieresis -100 KPX Lacute quoteright -92 KPX Lacute y -55 KPX Lacute yacute -55 KPX Lacute ydieresis -55 KPX Lcaron quoteright -92 KPX Lcaron y -55 KPX Lcaron yacute -55 KPX Lcaron ydieresis -55 KPX Lcommaaccent T -92 KPX Lcommaaccent Tcaron -92 KPX Lcommaaccent Tcommaaccent -92 KPX Lcommaaccent V -100 KPX Lcommaaccent W -74 KPX Lcommaaccent Y -100 KPX Lcommaaccent Yacute -100 KPX Lcommaaccent Ydieresis -100 KPX Lcommaaccent quoteright -92 KPX Lcommaaccent y -55 KPX Lcommaaccent yacute -55 KPX Lcommaaccent ydieresis -55 KPX Lslash T -92 KPX Lslash Tcaron -92 KPX Lslash Tcommaaccent -92 KPX Lslash V -100 KPX Lslash W -74 KPX Lslash Y -100 KPX Lslash Yacute -100 KPX Lslash Ydieresis -100 KPX Lslash quoteright -92 KPX Lslash y -55 KPX Lslash yacute -55 KPX Lslash ydieresis -55 KPX N A -35 KPX N Aacute -35 KPX N Abreve -35 KPX N Acircumflex -35 KPX N Adieresis -35 KPX N Agrave -35 KPX N Amacron -35 KPX N Aogonek -35 KPX N Aring -35 KPX N Atilde -35 KPX Nacute A -35 KPX Nacute Aacute -35 KPX Nacute Abreve -35 KPX Nacute Acircumflex -35 KPX Nacute Adieresis -35 KPX Nacute Agrave -35 KPX Nacute Amacron -35 KPX Nacute Aogonek -35 KPX Nacute Aring -35 KPX Nacute Atilde -35 KPX Ncaron A -35 KPX Ncaron Aacute -35 KPX Ncaron Abreve -35 KPX Ncaron Acircumflex -35 KPX Ncaron Adieresis -35 KPX Ncaron Agrave -35 KPX Ncaron Amacron -35 KPX Ncaron Aogonek -35 KPX Ncaron Aring -35 KPX Ncaron Atilde -35 KPX Ncommaaccent A -35 KPX Ncommaaccent Aacute -35 KPX Ncommaaccent Abreve -35 KPX Ncommaaccent Acircumflex -35 KPX Ncommaaccent Adieresis -35 KPX Ncommaaccent Agrave -35 KPX Ncommaaccent Amacron -35 KPX Ncommaaccent Aogonek -35 KPX Ncommaaccent Aring -35 KPX Ncommaaccent Atilde -35 KPX Ntilde A -35 KPX Ntilde Aacute -35 KPX Ntilde Abreve -35 KPX Ntilde Acircumflex -35 KPX Ntilde Adieresis -35 KPX Ntilde Agrave -35 KPX Ntilde Amacron -35 KPX Ntilde Aogonek -35 KPX Ntilde Aring -35 KPX Ntilde Atilde -35 KPX O A -35 KPX O Aacute -35 KPX O Abreve -35 KPX O Acircumflex -35 KPX O Adieresis -35 KPX O Agrave -35 KPX O Amacron -35 KPX O Aogonek -35 KPX O Aring -35 KPX O Atilde -35 KPX O T -40 KPX O Tcaron -40 KPX O Tcommaaccent -40 KPX O V -50 KPX O W -35 KPX O X -40 KPX O Y -50 KPX O Yacute -50 KPX O Ydieresis -50 KPX Oacute A -35 KPX Oacute Aacute -35 KPX Oacute Abreve -35 KPX Oacute Acircumflex -35 KPX Oacute Adieresis -35 KPX Oacute Agrave -35 KPX Oacute Amacron -35 KPX Oacute Aogonek -35 KPX Oacute Aring -35 KPX Oacute Atilde -35 KPX Oacute T -40 KPX Oacute Tcaron -40 KPX Oacute Tcommaaccent -40 KPX Oacute V -50 KPX Oacute W -35 KPX Oacute X -40 KPX Oacute Y -50 KPX Oacute Yacute -50 KPX Oacute Ydieresis -50 KPX Ocircumflex A -35 KPX Ocircumflex Aacute -35 KPX Ocircumflex Abreve -35 KPX Ocircumflex Acircumflex -35 KPX Ocircumflex Adieresis -35 KPX Ocircumflex Agrave -35 KPX Ocircumflex Amacron -35 KPX Ocircumflex Aogonek -35 KPX Ocircumflex Aring -35 KPX Ocircumflex Atilde -35 KPX Ocircumflex T -40 KPX Ocircumflex Tcaron -40 KPX Ocircumflex Tcommaaccent -40 KPX Ocircumflex V -50 KPX Ocircumflex W -35 KPX Ocircumflex X -40 KPX Ocircumflex Y -50 KPX Ocircumflex Yacute -50 KPX Ocircumflex Ydieresis -50 KPX Odieresis A -35 KPX Odieresis Aacute -35 KPX Odieresis Abreve -35 KPX Odieresis Acircumflex -35 KPX Odieresis Adieresis -35 KPX Odieresis Agrave -35 KPX Odieresis Amacron -35 KPX Odieresis Aogonek -35 KPX Odieresis Aring -35 KPX Odieresis Atilde -35 KPX Odieresis T -40 KPX Odieresis Tcaron -40 KPX Odieresis Tcommaaccent -40 KPX Odieresis V -50 KPX Odieresis W -35 KPX Odieresis X -40 KPX Odieresis Y -50 KPX Odieresis Yacute -50 KPX Odieresis Ydieresis -50 KPX Ograve A -35 KPX Ograve Aacute -35 KPX Ograve Abreve -35 KPX Ograve Acircumflex -35 KPX Ograve Adieresis -35 KPX Ograve Agrave -35 KPX Ograve Amacron -35 KPX Ograve Aogonek -35 KPX Ograve Aring -35 KPX Ograve Atilde -35 KPX Ograve T -40 KPX Ograve Tcaron -40 KPX Ograve Tcommaaccent -40 KPX Ograve V -50 KPX Ograve W -35 KPX Ograve X -40 KPX Ograve Y -50 KPX Ograve Yacute -50 KPX Ograve Ydieresis -50 KPX Ohungarumlaut A -35 KPX Ohungarumlaut Aacute -35 KPX Ohungarumlaut Abreve -35 KPX Ohungarumlaut Acircumflex -35 KPX Ohungarumlaut Adieresis -35 KPX Ohungarumlaut Agrave -35 KPX Ohungarumlaut Amacron -35 KPX Ohungarumlaut Aogonek -35 KPX Ohungarumlaut Aring -35 KPX Ohungarumlaut Atilde -35 KPX Ohungarumlaut T -40 KPX Ohungarumlaut Tcaron -40 KPX Ohungarumlaut Tcommaaccent -40 KPX Ohungarumlaut V -50 KPX Ohungarumlaut W -35 KPX Ohungarumlaut X -40 KPX Ohungarumlaut Y -50 KPX Ohungarumlaut Yacute -50 KPX Ohungarumlaut Ydieresis -50 KPX Omacron A -35 KPX Omacron Aacute -35 KPX Omacron Abreve -35 KPX Omacron Acircumflex -35 KPX Omacron Adieresis -35 KPX Omacron Agrave -35 KPX Omacron Amacron -35 KPX Omacron Aogonek -35 KPX Omacron Aring -35 KPX Omacron Atilde -35 KPX Omacron T -40 KPX Omacron Tcaron -40 KPX Omacron Tcommaaccent -40 KPX Omacron V -50 KPX Omacron W -35 KPX Omacron X -40 KPX Omacron Y -50 KPX Omacron Yacute -50 KPX Omacron Ydieresis -50 KPX Oslash A -35 KPX Oslash Aacute -35 KPX Oslash Abreve -35 KPX Oslash Acircumflex -35 KPX Oslash Adieresis -35 KPX Oslash Agrave -35 KPX Oslash Amacron -35 KPX Oslash Aogonek -35 KPX Oslash Aring -35 KPX Oslash Atilde -35 KPX Oslash T -40 KPX Oslash Tcaron -40 KPX Oslash Tcommaaccent -40 KPX Oslash V -50 KPX Oslash W -35 KPX Oslash X -40 KPX Oslash Y -50 KPX Oslash Yacute -50 KPX Oslash Ydieresis -50 KPX Otilde A -35 KPX Otilde Aacute -35 KPX Otilde Abreve -35 KPX Otilde Acircumflex -35 KPX Otilde Adieresis -35 KPX Otilde Agrave -35 KPX Otilde Amacron -35 KPX Otilde Aogonek -35 KPX Otilde Aring -35 KPX Otilde Atilde -35 KPX Otilde T -40 KPX Otilde Tcaron -40 KPX Otilde Tcommaaccent -40 KPX Otilde V -50 KPX Otilde W -35 KPX Otilde X -40 KPX Otilde Y -50 KPX Otilde Yacute -50 KPX Otilde Ydieresis -50 KPX P A -92 KPX P Aacute -92 KPX P Abreve -92 KPX P Acircumflex -92 KPX P Adieresis -92 KPX P Agrave -92 KPX P Amacron -92 KPX P Aogonek -92 KPX P Aring -92 KPX P Atilde -92 KPX P a -15 KPX P aacute -15 KPX P abreve -15 KPX P acircumflex -15 KPX P adieresis -15 KPX P agrave -15 KPX P amacron -15 KPX P aogonek -15 KPX P aring -15 KPX P atilde -15 KPX P comma -111 KPX P period -111 KPX Q U -10 KPX Q Uacute -10 KPX Q Ucircumflex -10 KPX Q Udieresis -10 KPX Q Ugrave -10 KPX Q Uhungarumlaut -10 KPX Q Umacron -10 KPX Q Uogonek -10 KPX Q Uring -10 KPX R O -40 KPX R Oacute -40 KPX R Ocircumflex -40 KPX R Odieresis -40 KPX R Ograve -40 KPX R Ohungarumlaut -40 KPX R Omacron -40 KPX R Oslash -40 KPX R Otilde -40 KPX R T -60 KPX R Tcaron -60 KPX R Tcommaaccent -60 KPX R U -40 KPX R Uacute -40 KPX R Ucircumflex -40 KPX R Udieresis -40 KPX R Ugrave -40 KPX R Uhungarumlaut -40 KPX R Umacron -40 KPX R Uogonek -40 KPX R Uring -40 KPX R V -80 KPX R W -55 KPX R Y -65 KPX R Yacute -65 KPX R Ydieresis -65 KPX Racute O -40 KPX Racute Oacute -40 KPX Racute Ocircumflex -40 KPX Racute Odieresis -40 KPX Racute Ograve -40 KPX Racute Ohungarumlaut -40 KPX Racute Omacron -40 KPX Racute Oslash -40 KPX Racute Otilde -40 KPX Racute T -60 KPX Racute Tcaron -60 KPX Racute Tcommaaccent -60 KPX Racute U -40 KPX Racute Uacute -40 KPX Racute Ucircumflex -40 KPX Racute Udieresis -40 KPX Racute Ugrave -40 KPX Racute Uhungarumlaut -40 KPX Racute Umacron -40 KPX Racute Uogonek -40 KPX Racute Uring -40 KPX Racute V -80 KPX Racute W -55 KPX Racute Y -65 KPX Racute Yacute -65 KPX Racute Ydieresis -65 KPX Rcaron O -40 KPX Rcaron Oacute -40 KPX Rcaron Ocircumflex -40 KPX Rcaron Odieresis -40 KPX Rcaron Ograve -40 KPX Rcaron Ohungarumlaut -40 KPX Rcaron Omacron -40 KPX Rcaron Oslash -40 KPX Rcaron Otilde -40 KPX Rcaron T -60 KPX Rcaron Tcaron -60 KPX Rcaron Tcommaaccent -60 KPX Rcaron U -40 KPX Rcaron Uacute -40 KPX Rcaron Ucircumflex -40 KPX Rcaron Udieresis -40 KPX Rcaron Ugrave -40 KPX Rcaron Uhungarumlaut -40 KPX Rcaron Umacron -40 KPX Rcaron Uogonek -40 KPX Rcaron Uring -40 KPX Rcaron V -80 KPX Rcaron W -55 KPX Rcaron Y -65 KPX Rcaron Yacute -65 KPX Rcaron Ydieresis -65 KPX Rcommaaccent O -40 KPX Rcommaaccent Oacute -40 KPX Rcommaaccent Ocircumflex -40 KPX Rcommaaccent Odieresis -40 KPX Rcommaaccent Ograve -40 KPX Rcommaaccent Ohungarumlaut -40 KPX Rcommaaccent Omacron -40 KPX Rcommaaccent Oslash -40 KPX Rcommaaccent Otilde -40 KPX Rcommaaccent T -60 KPX Rcommaaccent Tcaron -60 KPX Rcommaaccent Tcommaaccent -60 KPX Rcommaaccent U -40 KPX Rcommaaccent Uacute -40 KPX Rcommaaccent Ucircumflex -40 KPX Rcommaaccent Udieresis -40 KPX Rcommaaccent Ugrave -40 KPX Rcommaaccent Uhungarumlaut -40 KPX Rcommaaccent Umacron -40 KPX Rcommaaccent Uogonek -40 KPX Rcommaaccent Uring -40 KPX Rcommaaccent V -80 KPX Rcommaaccent W -55 KPX Rcommaaccent Y -65 KPX Rcommaaccent Yacute -65 KPX Rcommaaccent Ydieresis -65 KPX T A -93 KPX T Aacute -93 KPX T Abreve -93 KPX T Acircumflex -93 KPX T Adieresis -93 KPX T Agrave -93 KPX T Amacron -93 KPX T Aogonek -93 KPX T Aring -93 KPX T Atilde -93 KPX T O -18 KPX T Oacute -18 KPX T Ocircumflex -18 KPX T Odieresis -18 KPX T Ograve -18 KPX T Ohungarumlaut -18 KPX T Omacron -18 KPX T Oslash -18 KPX T Otilde -18 KPX T a -80 KPX T aacute -80 KPX T abreve -80 KPX T acircumflex -80 KPX T adieresis -40 KPX T agrave -40 KPX T amacron -40 KPX T aogonek -80 KPX T aring -80 KPX T atilde -40 KPX T colon -50 KPX T comma -74 KPX T e -70 KPX T eacute -70 KPX T ecaron -70 KPX T ecircumflex -70 KPX T edieresis -30 KPX T edotaccent -70 KPX T egrave -70 KPX T emacron -30 KPX T eogonek -70 KPX T hyphen -92 KPX T i -35 KPX T iacute -35 KPX T iogonek -35 KPX T o -80 KPX T oacute -80 KPX T ocircumflex -80 KPX T odieresis -80 KPX T ograve -80 KPX T ohungarumlaut -80 KPX T omacron -80 KPX T oslash -80 KPX T otilde -80 KPX T period -74 KPX T r -35 KPX T racute -35 KPX T rcaron -35 KPX T rcommaaccent -35 KPX T semicolon -55 KPX T u -45 KPX T uacute -45 KPX T ucircumflex -45 KPX T udieresis -45 KPX T ugrave -45 KPX T uhungarumlaut -45 KPX T umacron -45 KPX T uogonek -45 KPX T uring -45 KPX T w -80 KPX T y -80 KPX T yacute -80 KPX T ydieresis -80 KPX Tcaron A -93 KPX Tcaron Aacute -93 KPX Tcaron Abreve -93 KPX Tcaron Acircumflex -93 KPX Tcaron Adieresis -93 KPX Tcaron Agrave -93 KPX Tcaron Amacron -93 KPX Tcaron Aogonek -93 KPX Tcaron Aring -93 KPX Tcaron Atilde -93 KPX Tcaron O -18 KPX Tcaron Oacute -18 KPX Tcaron Ocircumflex -18 KPX Tcaron Odieresis -18 KPX Tcaron Ograve -18 KPX Tcaron Ohungarumlaut -18 KPX Tcaron Omacron -18 KPX Tcaron Oslash -18 KPX Tcaron Otilde -18 KPX Tcaron a -80 KPX Tcaron aacute -80 KPX Tcaron abreve -80 KPX Tcaron acircumflex -80 KPX Tcaron adieresis -40 KPX Tcaron agrave -40 KPX Tcaron amacron -40 KPX Tcaron aogonek -80 KPX Tcaron aring -80 KPX Tcaron atilde -40 KPX Tcaron colon -50 KPX Tcaron comma -74 KPX Tcaron e -70 KPX Tcaron eacute -70 KPX Tcaron ecaron -70 KPX Tcaron ecircumflex -30 KPX Tcaron edieresis -30 KPX Tcaron edotaccent -70 KPX Tcaron egrave -70 KPX Tcaron emacron -30 KPX Tcaron eogonek -70 KPX Tcaron hyphen -92 KPX Tcaron i -35 KPX Tcaron iacute -35 KPX Tcaron iogonek -35 KPX Tcaron o -80 KPX Tcaron oacute -80 KPX Tcaron ocircumflex -80 KPX Tcaron odieresis -80 KPX Tcaron ograve -80 KPX Tcaron ohungarumlaut -80 KPX Tcaron omacron -80 KPX Tcaron oslash -80 KPX Tcaron otilde -80 KPX Tcaron period -74 KPX Tcaron r -35 KPX Tcaron racute -35 KPX Tcaron rcaron -35 KPX Tcaron rcommaaccent -35 KPX Tcaron semicolon -55 KPX Tcaron u -45 KPX Tcaron uacute -45 KPX Tcaron ucircumflex -45 KPX Tcaron udieresis -45 KPX Tcaron ugrave -45 KPX Tcaron uhungarumlaut -45 KPX Tcaron umacron -45 KPX Tcaron uogonek -45 KPX Tcaron uring -45 KPX Tcaron w -80 KPX Tcaron y -80 KPX Tcaron yacute -80 KPX Tcaron ydieresis -80 KPX Tcommaaccent A -93 KPX Tcommaaccent Aacute -93 KPX Tcommaaccent Abreve -93 KPX Tcommaaccent Acircumflex -93 KPX Tcommaaccent Adieresis -93 KPX Tcommaaccent Agrave -93 KPX Tcommaaccent Amacron -93 KPX Tcommaaccent Aogonek -93 KPX Tcommaaccent Aring -93 KPX Tcommaaccent Atilde -93 KPX Tcommaaccent O -18 KPX Tcommaaccent Oacute -18 KPX Tcommaaccent Ocircumflex -18 KPX Tcommaaccent Odieresis -18 KPX Tcommaaccent Ograve -18 KPX Tcommaaccent Ohungarumlaut -18 KPX Tcommaaccent Omacron -18 KPX Tcommaaccent Oslash -18 KPX Tcommaaccent Otilde -18 KPX Tcommaaccent a -80 KPX Tcommaaccent aacute -80 KPX Tcommaaccent abreve -80 KPX Tcommaaccent acircumflex -80 KPX Tcommaaccent adieresis -40 KPX Tcommaaccent agrave -40 KPX Tcommaaccent amacron -40 KPX Tcommaaccent aogonek -80 KPX Tcommaaccent aring -80 KPX Tcommaaccent atilde -40 KPX Tcommaaccent colon -50 KPX Tcommaaccent comma -74 KPX Tcommaaccent e -70 KPX Tcommaaccent eacute -70 KPX Tcommaaccent ecaron -70 KPX Tcommaaccent ecircumflex -30 KPX Tcommaaccent edieresis -30 KPX Tcommaaccent edotaccent -70 KPX Tcommaaccent egrave -30 KPX Tcommaaccent emacron -70 KPX Tcommaaccent eogonek -70 KPX Tcommaaccent hyphen -92 KPX Tcommaaccent i -35 KPX Tcommaaccent iacute -35 KPX Tcommaaccent iogonek -35 KPX Tcommaaccent o -80 KPX Tcommaaccent oacute -80 KPX Tcommaaccent ocircumflex -80 KPX Tcommaaccent odieresis -80 KPX Tcommaaccent ograve -80 KPX Tcommaaccent ohungarumlaut -80 KPX Tcommaaccent omacron -80 KPX Tcommaaccent oslash -80 KPX Tcommaaccent otilde -80 KPX Tcommaaccent period -74 KPX Tcommaaccent r -35 KPX Tcommaaccent racute -35 KPX Tcommaaccent rcaron -35 KPX Tcommaaccent rcommaaccent -35 KPX Tcommaaccent semicolon -55 KPX Tcommaaccent u -45 KPX Tcommaaccent uacute -45 KPX Tcommaaccent ucircumflex -45 KPX Tcommaaccent udieresis -45 KPX Tcommaaccent ugrave -45 KPX Tcommaaccent uhungarumlaut -45 KPX Tcommaaccent umacron -45 KPX Tcommaaccent uogonek -45 KPX Tcommaaccent uring -45 KPX Tcommaaccent w -80 KPX Tcommaaccent y -80 KPX Tcommaaccent yacute -80 KPX Tcommaaccent ydieresis -80 KPX U A -40 KPX U Aacute -40 KPX U Abreve -40 KPX U Acircumflex -40 KPX U Adieresis -40 KPX U Agrave -40 KPX U Amacron -40 KPX U Aogonek -40 KPX U Aring -40 KPX U Atilde -40 KPX Uacute A -40 KPX Uacute Aacute -40 KPX Uacute Abreve -40 KPX Uacute Acircumflex -40 KPX Uacute Adieresis -40 KPX Uacute Agrave -40 KPX Uacute Amacron -40 KPX Uacute Aogonek -40 KPX Uacute Aring -40 KPX Uacute Atilde -40 KPX Ucircumflex A -40 KPX Ucircumflex Aacute -40 KPX Ucircumflex Abreve -40 KPX Ucircumflex Acircumflex -40 KPX Ucircumflex Adieresis -40 KPX Ucircumflex Agrave -40 KPX Ucircumflex Amacron -40 KPX Ucircumflex Aogonek -40 KPX Ucircumflex Aring -40 KPX Ucircumflex Atilde -40 KPX Udieresis A -40 KPX Udieresis Aacute -40 KPX Udieresis Abreve -40 KPX Udieresis Acircumflex -40 KPX Udieresis Adieresis -40 KPX Udieresis Agrave -40 KPX Udieresis Amacron -40 KPX Udieresis Aogonek -40 KPX Udieresis Aring -40 KPX Udieresis Atilde -40 KPX Ugrave A -40 KPX Ugrave Aacute -40 KPX Ugrave Abreve -40 KPX Ugrave Acircumflex -40 KPX Ugrave Adieresis -40 KPX Ugrave Agrave -40 KPX Ugrave Amacron -40 KPX Ugrave Aogonek -40 KPX Ugrave Aring -40 KPX Ugrave Atilde -40 KPX Uhungarumlaut A -40 KPX Uhungarumlaut Aacute -40 KPX Uhungarumlaut Abreve -40 KPX Uhungarumlaut Acircumflex -40 KPX Uhungarumlaut Adieresis -40 KPX Uhungarumlaut Agrave -40 KPX Uhungarumlaut Amacron -40 KPX Uhungarumlaut Aogonek -40 KPX Uhungarumlaut Aring -40 KPX Uhungarumlaut Atilde -40 KPX Umacron A -40 KPX Umacron Aacute -40 KPX Umacron Abreve -40 KPX Umacron Acircumflex -40 KPX Umacron Adieresis -40 KPX Umacron Agrave -40 KPX Umacron Amacron -40 KPX Umacron Aogonek -40 KPX Umacron Aring -40 KPX Umacron Atilde -40 KPX Uogonek A -40 KPX Uogonek Aacute -40 KPX Uogonek Abreve -40 KPX Uogonek Acircumflex -40 KPX Uogonek Adieresis -40 KPX Uogonek Agrave -40 KPX Uogonek Amacron -40 KPX Uogonek Aogonek -40 KPX Uogonek Aring -40 KPX Uogonek Atilde -40 KPX Uring A -40 KPX Uring Aacute -40 KPX Uring Abreve -40 KPX Uring Acircumflex -40 KPX Uring Adieresis -40 KPX Uring Agrave -40 KPX Uring Amacron -40 KPX Uring Aogonek -40 KPX Uring Aring -40 KPX Uring Atilde -40 KPX V A -135 KPX V Aacute -135 KPX V Abreve -135 KPX V Acircumflex -135 KPX V Adieresis -135 KPX V Agrave -135 KPX V Amacron -135 KPX V Aogonek -135 KPX V Aring -135 KPX V Atilde -135 KPX V G -15 KPX V Gbreve -15 KPX V Gcommaaccent -15 KPX V O -40 KPX V Oacute -40 KPX V Ocircumflex -40 KPX V Odieresis -40 KPX V Ograve -40 KPX V Ohungarumlaut -40 KPX V Omacron -40 KPX V Oslash -40 KPX V Otilde -40 KPX V a -111 KPX V aacute -111 KPX V abreve -111 KPX V acircumflex -71 KPX V adieresis -71 KPX V agrave -71 KPX V amacron -71 KPX V aogonek -111 KPX V aring -111 KPX V atilde -71 KPX V colon -74 KPX V comma -129 KPX V e -111 KPX V eacute -111 KPX V ecaron -71 KPX V ecircumflex -71 KPX V edieresis -71 KPX V edotaccent -111 KPX V egrave -71 KPX V emacron -71 KPX V eogonek -111 KPX V hyphen -100 KPX V i -60 KPX V iacute -60 KPX V icircumflex -20 KPX V idieresis -20 KPX V igrave -20 KPX V imacron -20 KPX V iogonek -60 KPX V o -129 KPX V oacute -129 KPX V ocircumflex -129 KPX V odieresis -89 KPX V ograve -89 KPX V ohungarumlaut -129 KPX V omacron -89 KPX V oslash -129 KPX V otilde -89 KPX V period -129 KPX V semicolon -74 KPX V u -75 KPX V uacute -75 KPX V ucircumflex -75 KPX V udieresis -75 KPX V ugrave -75 KPX V uhungarumlaut -75 KPX V umacron -75 KPX V uogonek -75 KPX V uring -75 KPX W A -120 KPX W Aacute -120 KPX W Abreve -120 KPX W Acircumflex -120 KPX W Adieresis -120 KPX W Agrave -120 KPX W Amacron -120 KPX W Aogonek -120 KPX W Aring -120 KPX W Atilde -120 KPX W O -10 KPX W Oacute -10 KPX W Ocircumflex -10 KPX W Odieresis -10 KPX W Ograve -10 KPX W Ohungarumlaut -10 KPX W Omacron -10 KPX W Oslash -10 KPX W Otilde -10 KPX W a -80 KPX W aacute -80 KPX W abreve -80 KPX W acircumflex -80 KPX W adieresis -80 KPX W agrave -80 KPX W amacron -80 KPX W aogonek -80 KPX W aring -80 KPX W atilde -80 KPX W colon -37 KPX W comma -92 KPX W e -80 KPX W eacute -80 KPX W ecaron -80 KPX W ecircumflex -80 KPX W edieresis -40 KPX W edotaccent -80 KPX W egrave -40 KPX W emacron -40 KPX W eogonek -80 KPX W hyphen -65 KPX W i -40 KPX W iacute -40 KPX W iogonek -40 KPX W o -80 KPX W oacute -80 KPX W ocircumflex -80 KPX W odieresis -80 KPX W ograve -80 KPX W ohungarumlaut -80 KPX W omacron -80 KPX W oslash -80 KPX W otilde -80 KPX W period -92 KPX W semicolon -37 KPX W u -50 KPX W uacute -50 KPX W ucircumflex -50 KPX W udieresis -50 KPX W ugrave -50 KPX W uhungarumlaut -50 KPX W umacron -50 KPX W uogonek -50 KPX W uring -50 KPX W y -73 KPX W yacute -73 KPX W ydieresis -73 KPX Y A -120 KPX Y Aacute -120 KPX Y Abreve -120 KPX Y Acircumflex -120 KPX Y Adieresis -120 KPX Y Agrave -120 KPX Y Amacron -120 KPX Y Aogonek -120 KPX Y Aring -120 KPX Y Atilde -120 KPX Y O -30 KPX Y Oacute -30 KPX Y Ocircumflex -30 KPX Y Odieresis -30 KPX Y Ograve -30 KPX Y Ohungarumlaut -30 KPX Y Omacron -30 KPX Y Oslash -30 KPX Y Otilde -30 KPX Y a -100 KPX Y aacute -100 KPX Y abreve -100 KPX Y acircumflex -100 KPX Y adieresis -60 KPX Y agrave -60 KPX Y amacron -60 KPX Y aogonek -100 KPX Y aring -100 KPX Y atilde -60 KPX Y colon -92 KPX Y comma -129 KPX Y e -100 KPX Y eacute -100 KPX Y ecaron -100 KPX Y ecircumflex -100 KPX Y edieresis -60 KPX Y edotaccent -100 KPX Y egrave -60 KPX Y emacron -60 KPX Y eogonek -100 KPX Y hyphen -111 KPX Y i -55 KPX Y iacute -55 KPX Y iogonek -55 KPX Y o -110 KPX Y oacute -110 KPX Y ocircumflex -110 KPX Y odieresis -70 KPX Y ograve -70 KPX Y ohungarumlaut -110 KPX Y omacron -70 KPX Y oslash -110 KPX Y otilde -70 KPX Y period -129 KPX Y semicolon -92 KPX Y u -111 KPX Y uacute -111 KPX Y ucircumflex -111 KPX Y udieresis -71 KPX Y ugrave -71 KPX Y uhungarumlaut -111 KPX Y umacron -71 KPX Y uogonek -111 KPX Y uring -111 KPX Yacute A -120 KPX Yacute Aacute -120 KPX Yacute Abreve -120 KPX Yacute Acircumflex -120 KPX Yacute Adieresis -120 KPX Yacute Agrave -120 KPX Yacute Amacron -120 KPX Yacute Aogonek -120 KPX Yacute Aring -120 KPX Yacute Atilde -120 KPX Yacute O -30 KPX Yacute Oacute -30 KPX Yacute Ocircumflex -30 KPX Yacute Odieresis -30 KPX Yacute Ograve -30 KPX Yacute Ohungarumlaut -30 KPX Yacute Omacron -30 KPX Yacute Oslash -30 KPX Yacute Otilde -30 KPX Yacute a -100 KPX Yacute aacute -100 KPX Yacute abreve -100 KPX Yacute acircumflex -100 KPX Yacute adieresis -60 KPX Yacute agrave -60 KPX Yacute amacron -60 KPX Yacute aogonek -100 KPX Yacute aring -100 KPX Yacute atilde -60 KPX Yacute colon -92 KPX Yacute comma -129 KPX Yacute e -100 KPX Yacute eacute -100 KPX Yacute ecaron -100 KPX Yacute ecircumflex -100 KPX Yacute edieresis -60 KPX Yacute edotaccent -100 KPX Yacute egrave -60 KPX Yacute emacron -60 KPX Yacute eogonek -100 KPX Yacute hyphen -111 KPX Yacute i -55 KPX Yacute iacute -55 KPX Yacute iogonek -55 KPX Yacute o -110 KPX Yacute oacute -110 KPX Yacute ocircumflex -110 KPX Yacute odieresis -70 KPX Yacute ograve -70 KPX Yacute ohungarumlaut -110 KPX Yacute omacron -70 KPX Yacute oslash -110 KPX Yacute otilde -70 KPX Yacute period -129 KPX Yacute semicolon -92 KPX Yacute u -111 KPX Yacute uacute -111 KPX Yacute ucircumflex -111 KPX Yacute udieresis -71 KPX Yacute ugrave -71 KPX Yacute uhungarumlaut -111 KPX Yacute umacron -71 KPX Yacute uogonek -111 KPX Yacute uring -111 KPX Ydieresis A -120 KPX Ydieresis Aacute -120 KPX Ydieresis Abreve -120 KPX Ydieresis Acircumflex -120 KPX Ydieresis Adieresis -120 KPX Ydieresis Agrave -120 KPX Ydieresis Amacron -120 KPX Ydieresis Aogonek -120 KPX Ydieresis Aring -120 KPX Ydieresis Atilde -120 KPX Ydieresis O -30 KPX Ydieresis Oacute -30 KPX Ydieresis Ocircumflex -30 KPX Ydieresis Odieresis -30 KPX Ydieresis Ograve -30 KPX Ydieresis Ohungarumlaut -30 KPX Ydieresis Omacron -30 KPX Ydieresis Oslash -30 KPX Ydieresis Otilde -30 KPX Ydieresis a -100 KPX Ydieresis aacute -100 KPX Ydieresis abreve -100 KPX Ydieresis acircumflex -100 KPX Ydieresis adieresis -60 KPX Ydieresis agrave -60 KPX Ydieresis amacron -60 KPX Ydieresis aogonek -100 KPX Ydieresis aring -100 KPX Ydieresis atilde -100 KPX Ydieresis colon -92 KPX Ydieresis comma -129 KPX Ydieresis e -100 KPX Ydieresis eacute -100 KPX Ydieresis ecaron -100 KPX Ydieresis ecircumflex -100 KPX Ydieresis edieresis -60 KPX Ydieresis edotaccent -100 KPX Ydieresis egrave -60 KPX Ydieresis emacron -60 KPX Ydieresis eogonek -100 KPX Ydieresis hyphen -111 KPX Ydieresis i -55 KPX Ydieresis iacute -55 KPX Ydieresis iogonek -55 KPX Ydieresis o -110 KPX Ydieresis oacute -110 KPX Ydieresis ocircumflex -110 KPX Ydieresis odieresis -70 KPX Ydieresis ograve -70 KPX Ydieresis ohungarumlaut -110 KPX Ydieresis omacron -70 KPX Ydieresis oslash -110 KPX Ydieresis otilde -70 KPX Ydieresis period -129 KPX Ydieresis semicolon -92 KPX Ydieresis u -111 KPX Ydieresis uacute -111 KPX Ydieresis ucircumflex -111 KPX Ydieresis udieresis -71 KPX Ydieresis ugrave -71 KPX Ydieresis uhungarumlaut -111 KPX Ydieresis umacron -71 KPX Ydieresis uogonek -111 KPX Ydieresis uring -111 KPX a v -20 KPX a w -15 KPX aacute v -20 KPX aacute w -15 KPX abreve v -20 KPX abreve w -15 KPX acircumflex v -20 KPX acircumflex w -15 KPX adieresis v -20 KPX adieresis w -15 KPX agrave v -20 KPX agrave w -15 KPX amacron v -20 KPX amacron w -15 KPX aogonek v -20 KPX aogonek w -15 KPX aring v -20 KPX aring w -15 KPX atilde v -20 KPX atilde w -15 KPX b period -40 KPX b u -20 KPX b uacute -20 KPX b ucircumflex -20 KPX b udieresis -20 KPX b ugrave -20 KPX b uhungarumlaut -20 KPX b umacron -20 KPX b uogonek -20 KPX b uring -20 KPX b v -15 KPX c y -15 KPX c yacute -15 KPX c ydieresis -15 KPX cacute y -15 KPX cacute yacute -15 KPX cacute ydieresis -15 KPX ccaron y -15 KPX ccaron yacute -15 KPX ccaron ydieresis -15 KPX ccedilla y -15 KPX ccedilla yacute -15 KPX ccedilla ydieresis -15 KPX comma quotedblright -70 KPX comma quoteright -70 KPX e g -15 KPX e gbreve -15 KPX e gcommaaccent -15 KPX e v -25 KPX e w -25 KPX e x -15 KPX e y -15 KPX e yacute -15 KPX e ydieresis -15 KPX eacute g -15 KPX eacute gbreve -15 KPX eacute gcommaaccent -15 KPX eacute v -25 KPX eacute w -25 KPX eacute x -15 KPX eacute y -15 KPX eacute yacute -15 KPX eacute ydieresis -15 KPX ecaron g -15 KPX ecaron gbreve -15 KPX ecaron gcommaaccent -15 KPX ecaron v -25 KPX ecaron w -25 KPX ecaron x -15 KPX ecaron y -15 KPX ecaron yacute -15 KPX ecaron ydieresis -15 KPX ecircumflex g -15 KPX ecircumflex gbreve -15 KPX ecircumflex gcommaaccent -15 KPX ecircumflex v -25 KPX ecircumflex w -25 KPX ecircumflex x -15 KPX ecircumflex y -15 KPX ecircumflex yacute -15 KPX ecircumflex ydieresis -15 KPX edieresis g -15 KPX edieresis gbreve -15 KPX edieresis gcommaaccent -15 KPX edieresis v -25 KPX edieresis w -25 KPX edieresis x -15 KPX edieresis y -15 KPX edieresis yacute -15 KPX edieresis ydieresis -15 KPX edotaccent g -15 KPX edotaccent gbreve -15 KPX edotaccent gcommaaccent -15 KPX edotaccent v -25 KPX edotaccent w -25 KPX edotaccent x -15 KPX edotaccent y -15 KPX edotaccent yacute -15 KPX edotaccent ydieresis -15 KPX egrave g -15 KPX egrave gbreve -15 KPX egrave gcommaaccent -15 KPX egrave v -25 KPX egrave w -25 KPX egrave x -15 KPX egrave y -15 KPX egrave yacute -15 KPX egrave ydieresis -15 KPX emacron g -15 KPX emacron gbreve -15 KPX emacron gcommaaccent -15 KPX emacron v -25 KPX emacron w -25 KPX emacron x -15 KPX emacron y -15 KPX emacron yacute -15 KPX emacron ydieresis -15 KPX eogonek g -15 KPX eogonek gbreve -15 KPX eogonek gcommaaccent -15 KPX eogonek v -25 KPX eogonek w -25 KPX eogonek x -15 KPX eogonek y -15 KPX eogonek yacute -15 KPX eogonek ydieresis -15 KPX f a -10 KPX f aacute -10 KPX f abreve -10 KPX f acircumflex -10 KPX f adieresis -10 KPX f agrave -10 KPX f amacron -10 KPX f aogonek -10 KPX f aring -10 KPX f atilde -10 KPX f dotlessi -50 KPX f f -25 KPX f i -20 KPX f iacute -20 KPX f quoteright 55 KPX g a -5 KPX g aacute -5 KPX g abreve -5 KPX g acircumflex -5 KPX g adieresis -5 KPX g agrave -5 KPX g amacron -5 KPX g aogonek -5 KPX g aring -5 KPX g atilde -5 KPX gbreve a -5 KPX gbreve aacute -5 KPX gbreve abreve -5 KPX gbreve acircumflex -5 KPX gbreve adieresis -5 KPX gbreve agrave -5 KPX gbreve amacron -5 KPX gbreve aogonek -5 KPX gbreve aring -5 KPX gbreve atilde -5 KPX gcommaaccent a -5 KPX gcommaaccent aacute -5 KPX gcommaaccent abreve -5 KPX gcommaaccent acircumflex -5 KPX gcommaaccent adieresis -5 KPX gcommaaccent agrave -5 KPX gcommaaccent amacron -5 KPX gcommaaccent aogonek -5 KPX gcommaaccent aring -5 KPX gcommaaccent atilde -5 KPX h y -5 KPX h yacute -5 KPX h ydieresis -5 KPX i v -25 KPX iacute v -25 KPX icircumflex v -25 KPX idieresis v -25 KPX igrave v -25 KPX imacron v -25 KPX iogonek v -25 KPX k e -10 KPX k eacute -10 KPX k ecaron -10 KPX k ecircumflex -10 KPX k edieresis -10 KPX k edotaccent -10 KPX k egrave -10 KPX k emacron -10 KPX k eogonek -10 KPX k o -10 KPX k oacute -10 KPX k ocircumflex -10 KPX k odieresis -10 KPX k ograve -10 KPX k ohungarumlaut -10 KPX k omacron -10 KPX k oslash -10 KPX k otilde -10 KPX k y -15 KPX k yacute -15 KPX k ydieresis -15 KPX kcommaaccent e -10 KPX kcommaaccent eacute -10 KPX kcommaaccent ecaron -10 KPX kcommaaccent ecircumflex -10 KPX kcommaaccent edieresis -10 KPX kcommaaccent edotaccent -10 KPX kcommaaccent egrave -10 KPX kcommaaccent emacron -10 KPX kcommaaccent eogonek -10 KPX kcommaaccent o -10 KPX kcommaaccent oacute -10 KPX kcommaaccent ocircumflex -10 KPX kcommaaccent odieresis -10 KPX kcommaaccent ograve -10 KPX kcommaaccent ohungarumlaut -10 KPX kcommaaccent omacron -10 KPX kcommaaccent oslash -10 KPX kcommaaccent otilde -10 KPX kcommaaccent y -15 KPX kcommaaccent yacute -15 KPX kcommaaccent ydieresis -15 KPX l w -10 KPX lacute w -10 KPX lcommaaccent w -10 KPX lslash w -10 KPX n v -40 KPX n y -15 KPX n yacute -15 KPX n ydieresis -15 KPX nacute v -40 KPX nacute y -15 KPX nacute yacute -15 KPX nacute ydieresis -15 KPX ncaron v -40 KPX ncaron y -15 KPX ncaron yacute -15 KPX ncaron ydieresis -15 KPX ncommaaccent v -40 KPX ncommaaccent y -15 KPX ncommaaccent yacute -15 KPX ncommaaccent ydieresis -15 KPX ntilde v -40 KPX ntilde y -15 KPX ntilde yacute -15 KPX ntilde ydieresis -15 KPX o v -15 KPX o w -25 KPX o y -10 KPX o yacute -10 KPX o ydieresis -10 KPX oacute v -15 KPX oacute w -25 KPX oacute y -10 KPX oacute yacute -10 KPX oacute ydieresis -10 KPX ocircumflex v -15 KPX ocircumflex w -25 KPX ocircumflex y -10 KPX ocircumflex yacute -10 KPX ocircumflex ydieresis -10 KPX odieresis v -15 KPX odieresis w -25 KPX odieresis y -10 KPX odieresis yacute -10 KPX odieresis ydieresis -10 KPX ograve v -15 KPX ograve w -25 KPX ograve y -10 KPX ograve yacute -10 KPX ograve ydieresis -10 KPX ohungarumlaut v -15 KPX ohungarumlaut w -25 KPX ohungarumlaut y -10 KPX ohungarumlaut yacute -10 KPX ohungarumlaut ydieresis -10 KPX omacron v -15 KPX omacron w -25 KPX omacron y -10 KPX omacron yacute -10 KPX omacron ydieresis -10 KPX oslash v -15 KPX oslash w -25 KPX oslash y -10 KPX oslash yacute -10 KPX oslash ydieresis -10 KPX otilde v -15 KPX otilde w -25 KPX otilde y -10 KPX otilde yacute -10 KPX otilde ydieresis -10 KPX p y -10 KPX p yacute -10 KPX p ydieresis -10 KPX period quotedblright -70 KPX period quoteright -70 KPX quotedblleft A -80 KPX quotedblleft Aacute -80 KPX quotedblleft Abreve -80 KPX quotedblleft Acircumflex -80 KPX quotedblleft Adieresis -80 KPX quotedblleft Agrave -80 KPX quotedblleft Amacron -80 KPX quotedblleft Aogonek -80 KPX quotedblleft Aring -80 KPX quotedblleft Atilde -80 KPX quoteleft A -80 KPX quoteleft Aacute -80 KPX quoteleft Abreve -80 KPX quoteleft Acircumflex -80 KPX quoteleft Adieresis -80 KPX quoteleft Agrave -80 KPX quoteleft Amacron -80 KPX quoteleft Aogonek -80 KPX quoteleft Aring -80 KPX quoteleft Atilde -80 KPX quoteleft quoteleft -74 KPX quoteright d -50 KPX quoteright dcroat -50 KPX quoteright l -10 KPX quoteright lacute -10 KPX quoteright lcommaaccent -10 KPX quoteright lslash -10 KPX quoteright quoteright -74 KPX quoteright r -50 KPX quoteright racute -50 KPX quoteright rcaron -50 KPX quoteright rcommaaccent -50 KPX quoteright s -55 KPX quoteright sacute -55 KPX quoteright scaron -55 KPX quoteright scedilla -55 KPX quoteright scommaaccent -55 KPX quoteright space -74 KPX quoteright t -18 KPX quoteright tcommaaccent -18 KPX quoteright v -50 KPX r comma -40 KPX r g -18 KPX r gbreve -18 KPX r gcommaaccent -18 KPX r hyphen -20 KPX r period -55 KPX racute comma -40 KPX racute g -18 KPX racute gbreve -18 KPX racute gcommaaccent -18 KPX racute hyphen -20 KPX racute period -55 KPX rcaron comma -40 KPX rcaron g -18 KPX rcaron gbreve -18 KPX rcaron gcommaaccent -18 KPX rcaron hyphen -20 KPX rcaron period -55 KPX rcommaaccent comma -40 KPX rcommaaccent g -18 KPX rcommaaccent gbreve -18 KPX rcommaaccent gcommaaccent -18 KPX rcommaaccent hyphen -20 KPX rcommaaccent period -55 KPX space A -55 KPX space Aacute -55 KPX space Abreve -55 KPX space Acircumflex -55 KPX space Adieresis -55 KPX space Agrave -55 KPX space Amacron -55 KPX space Aogonek -55 KPX space Aring -55 KPX space Atilde -55 KPX space T -18 KPX space Tcaron -18 KPX space Tcommaaccent -18 KPX space V -50 KPX space W -30 KPX space Y -90 KPX space Yacute -90 KPX space Ydieresis -90 KPX v a -25 KPX v aacute -25 KPX v abreve -25 KPX v acircumflex -25 KPX v adieresis -25 KPX v agrave -25 KPX v amacron -25 KPX v aogonek -25 KPX v aring -25 KPX v atilde -25 KPX v comma -65 KPX v e -15 KPX v eacute -15 KPX v ecaron -15 KPX v ecircumflex -15 KPX v edieresis -15 KPX v edotaccent -15 KPX v egrave -15 KPX v emacron -15 KPX v eogonek -15 KPX v o -20 KPX v oacute -20 KPX v ocircumflex -20 KPX v odieresis -20 KPX v ograve -20 KPX v ohungarumlaut -20 KPX v omacron -20 KPX v oslash -20 KPX v otilde -20 KPX v period -65 KPX w a -10 KPX w aacute -10 KPX w abreve -10 KPX w acircumflex -10 KPX w adieresis -10 KPX w agrave -10 KPX w amacron -10 KPX w aogonek -10 KPX w aring -10 KPX w atilde -10 KPX w comma -65 KPX w o -10 KPX w oacute -10 KPX w ocircumflex -10 KPX w odieresis -10 KPX w ograve -10 KPX w ohungarumlaut -10 KPX w omacron -10 KPX w oslash -10 KPX w otilde -10 KPX w period -65 KPX x e -15 KPX x eacute -15 KPX x ecaron -15 KPX x ecircumflex -15 KPX x edieresis -15 KPX x edotaccent -15 KPX x egrave -15 KPX x emacron -15 KPX x eogonek -15 KPX y comma -65 KPX y period -65 KPX yacute comma -65 KPX yacute period -65 KPX ydieresis comma -65 KPX ydieresis period -65 EndKernPairs EndKernData EndFontMetrics PyX-0.14.1/pyx/data/afm/ZapfDingbats.afm0000644000076500000240000002303012037547555020101 0ustar andrestaff00000000000000StartFontMetrics 4.1 Comment Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved. Comment Creation Date: Thu May 1 15:14:13 1997 Comment UniqueID 43082 Comment VMusage 45775 55535 FontName ZapfDingbats FullName ITC Zapf Dingbats FamilyName ZapfDingbats Weight Medium ItalicAngle 0 IsFixedPitch false CharacterSet Special FontBBox -1 -143 981 820 UnderlinePosition -100 UnderlineThickness 50 Version 002.000 Notice Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation. EncodingScheme FontSpecific StdHW 28 StdVW 90 StartCharMetrics 202 C 32 ; WX 278 ; N space ; B 0 0 0 0 ; C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ; C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ; C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ; C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ; C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ; C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ; C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ; C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ; C 41 ; WX 690 ; N a117 ; B 34 138 655 553 ; C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ; C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ; C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ; C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ; C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ; C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ; C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ; C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ; C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ; C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ; C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ; C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ; C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ; C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ; C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ; C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ; C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ; C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ; C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ; C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ; C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ; C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ; C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ; C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ; C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ; C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ; C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ; C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ; C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ; C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ; C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ; C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ; C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ; C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ; C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ; C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ; C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ; C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ; C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ; C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ; C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ; C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ; C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ; C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ; C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ; C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ; C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ; C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ; C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ; C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ; C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ; C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ; C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ; C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ; C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ; C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ; C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ; C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ; C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ; C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ; C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ; C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ; C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ; C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ; C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ; C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ; C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ; C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ; C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ; C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ; C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ; C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ; C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ; C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ; C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ; C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ; C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ; C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ; C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ; C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ; C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ; C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ; C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ; C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ; C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ; C 128 ; WX 390 ; N a89 ; B 35 -14 356 705 ; C 129 ; WX 390 ; N a90 ; B 35 -14 355 705 ; C 130 ; WX 317 ; N a93 ; B 35 0 283 692 ; C 131 ; WX 317 ; N a94 ; B 35 0 283 692 ; C 132 ; WX 276 ; N a91 ; B 35 0 242 692 ; C 133 ; WX 276 ; N a92 ; B 35 0 242 692 ; C 134 ; WX 509 ; N a205 ; B 35 0 475 692 ; C 135 ; WX 509 ; N a85 ; B 35 0 475 692 ; C 136 ; WX 410 ; N a206 ; B 35 0 375 692 ; C 137 ; WX 410 ; N a86 ; B 35 0 375 692 ; C 138 ; WX 234 ; N a87 ; B 35 -14 199 705 ; C 139 ; WX 234 ; N a88 ; B 35 -14 199 705 ; C 140 ; WX 334 ; N a95 ; B 35 0 299 692 ; C 141 ; WX 334 ; N a96 ; B 35 0 299 692 ; C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ; C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ; C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ; C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ; C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ; C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ; C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ; C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ; C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ; C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ; C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ; C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ; C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ; C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ; C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ; C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ; C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ; C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ; C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ; C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ; C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ; C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ; C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ; C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ; C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ; C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ; C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ; C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ; C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ; C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ; C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ; C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ; C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ; C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ; C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ; C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ; C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ; C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ; C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ; C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ; C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ; C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ; C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ; C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ; C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ; C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ; C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ; C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ; C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ; C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ; C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ; C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ; C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ; C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ; C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ; C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ; C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ; C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ; C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ; C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ; C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ; C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ; C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ; C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ; C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ; C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ; C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ; C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ; C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ; C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ; C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ; C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ; C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ; C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ; C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ; C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ; C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ; C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ; C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ; C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ; C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ; C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ; C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ; C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ; C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ; C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ; C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ; C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ; C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ; C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ; C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ; C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ; C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ; EndCharMetrics EndFontMetrics PyX-0.14.1/pyx/data/def/0000755000076500000240000000000012615763300015023 5ustar andrestaff00000000000000PyX-0.14.1/pyx/data/def/pyx.def0000644000076500000240000001350512037547555016341 0ustar andrestaff00000000000000%% %% This is file 'pyx.def', %% %% Copyright (C) 2003,2006 Michael Schindler %% %% this file is based on `dvips.def' from the Standard LaTeX `Graphics Bundle', %% available via ftp from CTAN %% %% `pyx.def' may be distributed under the terms of the LaTeX Project Public %% License, as described in lppl.txt in the base LaTeX distribution. %% Either version 1.0 or, at your option, any later version. %% %% % TODO: - documentation % \ProvidesFile{pyx.def} [2006/05/17 driver-dependant file] % %%%%%% auxiliary macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % used in DEF file only: % check if #1 is in [0,1] % \def\c@lor@arg#1{% \dimen@#1\p@ \ifdim\dimen@<\z@\dimen@\maxdimen\fi \ifdim\dimen@>\p@ \PackageError{color}{Argument `#1' not in range [0,1]}\@ehd \fi} % % >>> % %%%%%% (1a) gray, cmyk, rgb and RGB colors %%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % used in color.sty: \color@gray, cmyk, rgb, RGB, hsb % these commands are created with \csname as a % combination of 'color@' and 'gray'/'cmyk'/'rgb'/'RGB'/'hsb' % in color.sty by \@undeclaredcolor % gray, cmyk, rgb, hsb all take numbers in [0,1] as first argument(s) % RGB takes numbers in [0,255] as first arguments % \def\color@gray#1#2{% \c@lor@arg{#2}% % check the argument \edef#1{gray #2}% % prepare for command } % \def\color@cmyk#1#2{\c@lor@@cmyk#2\@@#1} % \@@ is only a separator for the arguments! \def\c@lor@@cmyk#1,#2,#3,#4\@@#5{% \c@lor@arg{#4}% \c@lor@arg{#1}% \c@lor@arg{#2}% \c@lor@arg{#3}% \edef#5{cmyk #1 #2 #3 #4}% #5 is always \current@color (only once a \tempa) } % \def\color@rgb#1#2{\c@lor@@rgb#2\@@#1} \def\c@lor@@rgb#1,#2,#3\@@#4{% \c@lor@arg{#1}% \c@lor@arg{#2}% \c@lor@arg{#3}% \edef#4{rgb #1 #2 #3}% } % \def\color@RGB#1#2{\c@lor@@RGB#2\@@#1} \def\c@lor@@RGB#1,#2,#3\@@#4{% \c@lor@RGB@rgb{#1}\@tempa % renormalise \c@lor@RGB@rgb{#2}\@tempb \c@lor@RGB@rgb{#3}\@tempc \c@lor@@rgb\@tempa,\@tempb,\@tempc\@@#4% % call with normalised values } \def\c@lor@RGB@rgb#1#2{% \dimen@#1\p@ \divide\dimen@\@cclv % divide by 255 \edef#2{\strip@pt\dimen@}} % strip the number % \def\color@hsb#1#2{\c@lor@@hsb#2\@@#1} \def\c@lor@@hsb#1,#2,#3\@@#4{% \c@lor@arg{#1}% \c@lor@arg{#2}% \c@lor@arg{#3}% \edef#4{hsb #1 #2 #3}% this is the string defining the color in the special. % % it is stored in the variable \current@color } %% >>> % %%%%%% (1b) "texnamed" colors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % used in color.sty: \color@named \col@... % like above with the use of \csname % \def\color@named#1#2{\c@lor@@named#2,,\@@#1} \def\c@lor@@named#1,#2,#3\@@#4{% \@ifundefined{col@#1}% {\PackageError{color}{Undefined color `#1'}\@ehd}% {\edef#4{texnamed #1}}% % arguments 2,3 are thrown away? Maybe an error detection mechanism } % \col@#1 is defined by \define@color@named \def\current@color{texnamed Black} \def\define@color@named#1#2{% for \DefineNamedColor only \expandafter\let\csname col@#1\endcsname\@nnil} % >>> % %%%%%% (1c) "pyxcolor" colors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % % use with \textcolor[pyxcolor]{Name} % where Name has to be defined in PyX as 'color.cmyk.Name', 'color.rgb.red', ... % Attention! PyX has to do the error detection if the color is not defined! % \def\color@pyx#1#2{\c@olor@@pyx#2\@@#1} \def\c@olor@@pyx#1\@@#2{% \edef#2{pyxcolor #1}} % >>> % %%%%%% (1) colors general %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % % \set@color is called by \@(un)declaredcolor in color.sty % This is the starting string of the special % \def\set@color{% \special{PyX:color_begin \current@color }\aftergroup\reset@color} % the 'group' is the one in \@textcolor: arguments 1 and 3 \def\reset@color{\special{PyX:color_end}} % % BACKGROUND COLOR is disabled \def\set@page@color{\PackageError{color}{Please adjust the pagecolor in PyX, not in LaTeX!}} % >>> % %%%%%% (2) eps-file inclusion %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % \def\Ginclude@eps#1{% \message{<#1>}% \bgroup \def\@tempa{!}% \dimen@=0.996264009963\Gin@req@width \@tempdima=0.996264009963\Gin@req@height \special{PyX:epsinclude\space file=\Gin@base\Gin@ext\space llx=\Gin@llx\space lly=\Gin@lly\space urx=\Gin@urx\space ury=\Gin@ury\space \ifx\Gin@scalex\@tempa\else width=\strip@pt\dimen@\space\fi \ifx\Gin@scaley\@tempa\else height=\strip@pt\@tempdima\space\fi \ifGin@clip clip=1\fi}% \egroup} % % bmp, oztex, pntg, pict file inclusions: % not available anymore % \Ginclude@bmp eventually used in graphics(x).sty % \Ginclude@pntg eventually used in graphics(x).sty % \Ginclude@pict eventually used in graphics(x).sty % \def\Ginclude@bmp#1{% \PackageError{color}{bmp file inclusion is not supported in PyX. Please use eps files.}} \def\Ginclude@pntg#1{ \PackageError{color}{pntg file inclusion is not supported in PyX. Please use eps files.}} \def\Ginclude@pict#1{ \PackageError{color}{pict file inclusion is not supported in PyX. Please use eps files.}} % % general stuff % %\def\Gin@PS@raw#1{\special{ps: #1}} %\def\Gin@PS@restored#1{\special{" #1}} %\def\Gin@PS@literal@header#1{\AtBeginDvi{\special{! #1}}} %\def\Gin@PS@file@header#1{\AtBeginDvi{\special{header=#1}}} % \def\Gin@extensions{.eps,.ps} \@namedef{Gin@rule@.ps}#1{{eps}{.ps}{#1}} \@namedef{Gin@rule@.eps}#1{{eps}{.eps}{#1}} \@namedef{Gin@rule@*}#1{{eps}{\Gin@ext}{#1}} % % >>> % %%%%%% (3) rotations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< \def\Grot@start{\special{PyX:rotate_begin \Grot@angle}} \def\Grot@end{\special{PyX:rotate_end}} % >>> % %%%%%% (4) scalings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<< % \def\Gscale@start{\special{PyX:scale_begin \Gscale@x\space \Gscale@y}} \def\Gscale@end{\special{PyX:scale_end}} % >>> \endinput % vim:foldmethod=marker:foldmarker=<<<,>>> % vim:syntax=tex %% End of file `pyx.def'. PyX-0.14.1/pyx/data/lfs/0000755000076500000240000000000012615763300015051 5ustar andrestaff00000000000000PyX-0.14.1/pyx/data/lfs/10pt.lfs0000644000076500000240000001477112037547555016367 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="10pt" % \latexclassname="article" % \latexclassopt="10pt" % \latexinit="" \def\tiny{\font\pyxfont=cmr5\pyxfont\font\pyxfonttfa=cmr5\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi5\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy5\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr7\pyxfont\font\pyxfonttfa=cmr7\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr9\pyxfont\font\pyxfonttfa=cmr9\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi9\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy9\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/10ptex.lfs0000644000076500000240000001514712037547555016722 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="10ptex" % \latexclassname="article" % \latexclassopt="10pt" % \latexinit="\usepackage{exscale}" \def\tiny{\font\pyxfont=cmr5\pyxfont\font\pyxfonttfa=cmr5\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi5\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy5\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr7\pyxfont\font\pyxfonttfa=cmr7\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex8\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr9\pyxfont\font\pyxfonttfa=cmr9\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi9\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy9\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex9\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 12.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex8\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 14.4pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 17.28pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 12.0pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 14.4pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 12.0pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 17.28pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/11pt.lfs0000644000076500000240000001505112037547555016360 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="11pt" % \latexclassname="article" % \latexclassopt="11pt" % \latexinit="" \def\tiny{\font\pyxfont=cmr6\pyxfont\font\pyxfonttfa=cmr6\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi6\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy6\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr9\pyxfont\font\pyxfonttfa=cmr9\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi9\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy9\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr10 at 10.95pt\pyxfont\font\pyxfonttfa=cmr10 at 10.95pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 10.95pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 10.95pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/11ptex.lfs0000644000076500000240000001524312037547555016720 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="11ptex" % \latexclassname="article" % \latexclassopt="11pt" % \latexinit="\usepackage{exscale}" \def\tiny{\font\pyxfont=cmr6\pyxfont\font\pyxfonttfa=cmr6\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi6\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy6\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex8\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr9\pyxfont\font\pyxfonttfa=cmr9\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi9\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy9\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex9\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr10 at 10.95pt\pyxfont\font\pyxfonttfa=cmr10 at 10.95pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 10.95pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 10.95pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 10.95pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex8\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 12.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex8\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 14.4pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 17.28pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 12.0pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 14.4pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 12.0pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 17.28pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/12pt.lfs0000644000076500000240000001522612037547555016365 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="12pt" % \latexclassname="article" % \latexclassopt="12pt" % \latexinit="" \def\tiny{\font\pyxfont=cmr6\pyxfont\font\pyxfonttfa=cmr6\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi6\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy6\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr10 at 10.95pt\pyxfont\font\pyxfonttfa=cmr10 at 10.95pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 10.95pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 10.95pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/12ptex.lfs0000644000076500000240000001546412037547555016726 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="12ptex" % \latexclassname="article" % \latexclassopt="12pt" % \latexinit="\usepackage{exscale}" \def\tiny{\font\pyxfont=cmr6\pyxfont\font\pyxfonttfa=cmr6\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr5\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi6\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi5\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy6\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy5\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmr8\pyxfont\font\pyxfonttfa=cmr8\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr6\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi8\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi6\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy8\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy6\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex8\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmr10\pyxfont\font\pyxfonttfa=cmr10\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr5\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi5\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy5\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmr10 at 10.95pt\pyxfont\font\pyxfonttfa=cmr10 at 10.95pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 10.95pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 10.95pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 10.95pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex8\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmr12\pyxfont\font\pyxfonttfa=cmr12\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr8\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr6\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi8\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi6\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 12.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy8\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy6\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 12.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex8\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmr12 at 14.4pt\pyxfont\font\pyxfonttfa=cmr12 at 14.4pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 14.4pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 14.4pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 14.4pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmr17\pyxfont\font\pyxfonttfa=cmr17\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 17.28pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 17.28pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 12.0pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 17.28pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 12.0pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmr17 at 20.74pt\pyxfont\font\pyxfonttfa=cmr17 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr12 at 14.4pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr12\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 14.4pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 14.4pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 12.0pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 14.4pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 12.0pt\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 17.28pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmr17 at 24.88pt\pyxfont\font\pyxfonttfa=cmr17 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr17 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr17\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi12 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi12 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi12 at 17.28pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 17.28pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 17.28pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/createlfs.py0000755000076500000240000000301312177540653017402 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002 Jörg Lehmann # Copyright (C) 2002 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import os styles = (("10pt", "article", "10pt", "" , ), ("11pt", "article", "11pt", "" , ), ("12pt", "article", "12pt", "" , ), ("10ptex", "article", "10pt", "\\usepackage{exscale}" , ), ("11ptex", "article", "11pt", "\\usepackage{exscale}" , ), ("12ptex", "article", "12pt", "\\usepackage{exscale}" , ), ("foils17pt", "foils", "17pt", "" , ), ("foils20pt", "foils", "20pt", "" , ), ("foils25pt", "foils", "25pt", "" , ), ("foils30pt", "foils", "30pt", "" , ), ) for style in styles: os.system("echo \'%s\n%s\n%s\n%s\'|latex createlfs.tex" % style) PyX-0.14.1/pyx/data/lfs/createlfs.tex0000644000076500000240000000727712171007751017556 0ustar andrestaff00000000000000% Copyright (C) 2002 Jörg Lehmann % Copyright (C) 2002 André Wobst % % This file is part of PyX (http://pyx.sourceforge.net/). % % PyX is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % PyX is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with PyX; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \endlinechar=-1 % don't add tailing space while \read \message{latex style name (e.g. 12ptex)? } \read-1 to\latexstylename \message{latex class name (e.g. article)? } \read-1 to\latexclassname \message{latex class options (e.g. 12pt)? } \read-1 to\latexclassopt \message{initial commands (e.g. \string\usepackage\string{exscale\string})? } \read-1 to\latexinit \endlinechar=13 \newwrite\myfile \newbox\mybox \documentclass[\latexclassopt]{\latexclassname} \latexinit \newcommand{\writefontsize}[1]{ \setbox\mybox=\hbox{#1 a $a$ \immediate\write\myfile{% \string\def\string#1{% \string\font\string\pyxfont=\fontname\font \string\pyxfont \string\font\string\pyxfonttfa=\fontname\textfont0 \string\textfont0=\string\pyxfonttfa \string\font\string\pyxfontsfa=\fontname\scriptfont0 \string\scriptfont0=\string\pyxfontsfa \string\font\string\pyxfontssfa=\fontname\scriptscriptfont0 \string\scriptscriptfont0=\string\pyxfontssfa \string\font\string\pyxfonttfb=\fontname\textfont1 \string\textfont1=\string\pyxfonttfb \string\font\string\pyxfontsfb=\fontname\scriptfont1 \string\scriptfont1=\string\pyxfontsfb \string\font\string\pyxfontssfb=\fontname\scriptscriptfont1 \string\scriptscriptfont1=\string\pyxfontssfb \string\font\string\pyxfonttfc=\fontname\textfont2 \string\textfont2=\string\pyxfonttfc \string\font\string\pyxfontsfc=\fontname\scriptfont2 \string\scriptfont2=\string\pyxfontsfc \string\font\string\pyxfontssfc=\fontname\scriptscriptfont2 \string\scriptscriptfont2=\string\pyxfontssfc \string\font\string\pyxfonttfd=\fontname\textfont3 \string\textfont3=\string\pyxfonttfd \string\font\string\pyxfontsfd=\fontname\scriptfont3 \string\scriptfont3=\string\pyxfontsfd \string\font\string\pyxfontssfd=\fontname\scriptscriptfont3 \string\scriptscriptfont3=\string\pyxfontssfd }% } } } \begin{document} \immediate\openout\myfile=\latexstylename.lfs {\catcode`\%=12\immediate\write\myfile{% This automatically generated file is part of PyX (http://pyx.sourceforge.net/).}} {\catcode`\%=12\immediate\write\myfile{% \string\latexstylename="\expandafter\string\latexstylename"}} {\catcode`\%=12\immediate\write\myfile{% \string\latexclassname="\expandafter\string\latexclassname"}} {\catcode`\%=12\immediate\write\myfile{% \string\latexclassopt="\expandafter\string\latexclassopt"}} {\catcode`\%=12\immediate\write\myfile{% \string\latexinit="\expandafter\string\latexinit"}} \writefontsize{\tiny} \writefontsize{\scriptsize} \writefontsize{\footnotesize} \writefontsize{\small} \writefontsize{\normalsize} \writefontsize{\large} \writefontsize{\Large} \writefontsize{\LARGE} \writefontsize{\huge} \writefontsize{\Huge} \immediate\closeout\myfile \end{document} PyX-0.14.1/pyx/data/lfs/foils17pt.lfs0000644000076500000240000001705512037547555017431 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="foils17pt" % \latexclassname="foils" % \latexclassopt="17pt" % \latexinit="" \def\tiny{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmss10 at 14.4pt\pyxfont\font\pyxfonttfa=cmr7 at 14.5pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 14.5pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 14.5pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 14.5pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmss10 at 17.28pt\pyxfont\font\pyxfonttfa=cmr7 at 17.38pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 17.38pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 17.38pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 17.38pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmss10 at 20.74pt\pyxfont\font\pyxfonttfa=cmr10 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 14.5pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 14.5pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 14.5pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 14.5pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmss10 at 24.88pt\pyxfont\font\pyxfonttfa=cmr10 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 17.38pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 14.5pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 17.38pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 14.5pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 17.38pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 14.5pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 17.38pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 14.5pt\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmss10 at 29.86pt\pyxfont\font\pyxfonttfa=cmr10 at 29.86pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 17.38pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 29.86pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 17.38pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 29.86pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 17.38pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 29.86pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 17.38pt\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmss10 at 35.83pt\pyxfont\font\pyxfonttfa=cmr10 at 35.83pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 24.88pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 20.74pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 35.83pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 24.88pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 20.74pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 35.83pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 24.88pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 20.74pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 35.83pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 24.88pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 20.74pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmss10 at 43.0pt\pyxfont\font\pyxfonttfa=cmr10 at 43.0pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 29.86pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 24.88pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 43.0pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 29.86pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 24.88pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 43.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 29.86pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 24.88pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 43.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 29.86pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 24.88pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/foils20pt.lfs0000644000076500000240000001710112037547555017413 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="foils20pt" % \latexclassname="foils" % \latexclassopt="20pt" % \latexinit="" \def\tiny{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmss10 at 14.4pt\pyxfont\font\pyxfonttfa=cmr7 at 14.5pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 14.5pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 14.5pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 14.5pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmss10 at 17.28pt\pyxfont\font\pyxfonttfa=cmr7 at 17.38pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 17.38pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 17.38pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 17.38pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmss10 at 20.74pt\pyxfont\font\pyxfonttfa=cmr10 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 14.5pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 14.5pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 14.5pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 14.5pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmss10 at 24.88pt\pyxfont\font\pyxfonttfa=cmr10 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 17.38pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 14.5pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 17.38pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 14.5pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 17.38pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 14.5pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 17.38pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 14.5pt\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmss10 at 29.86pt\pyxfont\font\pyxfonttfa=cmr10 at 29.86pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 17.38pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 29.86pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 17.38pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 29.86pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 17.38pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 29.86pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 17.38pt\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmss10 at 35.83pt\pyxfont\font\pyxfonttfa=cmr10 at 35.83pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 24.88pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 20.74pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 35.83pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 24.88pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 20.74pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 35.83pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 24.88pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 20.74pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 35.83pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 24.88pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 20.74pt\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmss10 at 43.0pt\pyxfont\font\pyxfonttfa=cmr10 at 43.0pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 29.86pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 24.88pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 43.0pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 29.86pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 24.88pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 43.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 29.86pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 24.88pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 43.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 29.86pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 24.88pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/foils25pt.lfs0000644000076500000240000001712512037547555017426 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="foils25pt" % \latexclassname="foils" % \latexclassopt="25pt" % \latexinit="" \def\tiny{\font\pyxfont=cmss10 at 12.0pt\pyxfont\font\pyxfonttfa=cmr7 at 12.1pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 12.1pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 12.1pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 12.1pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmss10 at 14.4pt\pyxfont\font\pyxfonttfa=cmr7 at 14.5pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 14.5pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 14.5pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 14.5pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmss10 at 17.28pt\pyxfont\font\pyxfonttfa=cmr7 at 17.38pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 17.38pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 17.38pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 17.38pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmss10 at 20.74pt\pyxfont\font\pyxfonttfa=cmr10 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 14.5pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 14.5pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 14.5pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 14.5pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmss10 at 24.88pt\pyxfont\font\pyxfonttfa=cmr10 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 17.38pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 14.5pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 17.38pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 14.5pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 17.38pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 14.5pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 17.38pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 14.5pt\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmss10 at 29.86pt\pyxfont\font\pyxfonttfa=cmr10 at 29.86pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 17.38pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 29.86pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 17.38pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 29.86pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 17.38pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 29.86pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 17.38pt\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmss10 at 35.83pt\pyxfont\font\pyxfonttfa=cmr10 at 35.83pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 24.88pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 20.74pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 35.83pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 24.88pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 20.74pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 35.83pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 24.88pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 20.74pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 35.83pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 24.88pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 20.74pt\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmss10 at 43.0pt\pyxfont\font\pyxfonttfa=cmr10 at 43.0pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 29.86pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 24.88pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 43.0pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 29.86pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 24.88pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 43.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 29.86pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 24.88pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 43.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 29.86pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 24.88pt\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/lfs/foils30pt.lfs0000644000076500000240000001715112037547555017421 0ustar andrestaff00000000000000% This automatically generated file is part of PyX (http://pyx.sourceforge.net/). % \latexstylename="foils30pt" % \latexclassname="foils" % \latexclassopt="30pt" % \latexinit="" \def\tiny{\font\pyxfont=cmss10 at 14.4pt\pyxfont\font\pyxfonttfa=cmr7 at 14.5pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 14.5pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 14.5pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 14.5pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\scriptsize{\font\pyxfont=cmss10 at 17.28pt\pyxfont\font\pyxfonttfa=cmr7 at 17.38pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 12.1pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi7 at 17.38pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 12.1pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy7 at 17.38pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 12.1pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex7 at 17.38pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 12.1pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\footnotesize{\font\pyxfont=cmss10 at 20.74pt\pyxfont\font\pyxfonttfa=cmr10 at 20.74pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 14.5pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 12.1pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 20.74pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 14.5pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 12.1pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 20.74pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 14.5pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 12.1pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 20.74pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 14.5pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 12.1pt\scriptscriptfont3=\pyxfontssfd} \def\small{\font\pyxfont=cmss10 at 24.88pt\pyxfont\font\pyxfonttfa=cmr10 at 24.88pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr7 at 17.38pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 14.5pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 24.88pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi7 at 17.38pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 14.5pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 24.88pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy7 at 17.38pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 14.5pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 24.88pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex7 at 17.38pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 14.5pt\scriptscriptfont3=\pyxfontssfd} \def\normalsize{\font\pyxfont=cmss10 at 29.86pt\pyxfont\font\pyxfonttfa=cmr10 at 29.86pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 20.74pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr7 at 17.38pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 29.86pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 20.74pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi7 at 17.38pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 29.86pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 20.74pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy7 at 17.38pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 29.86pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 20.74pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex7 at 17.38pt\scriptscriptfont3=\pyxfontssfd} \def\large{\font\pyxfont=cmss10 at 35.83pt\pyxfont\font\pyxfonttfa=cmr10 at 35.83pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 24.88pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 20.74pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 35.83pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 24.88pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 20.74pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 35.83pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 24.88pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 20.74pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 35.83pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 24.88pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 20.74pt\scriptscriptfont3=\pyxfontssfd} \def\Large{\font\pyxfont=cmss10 at 43.0pt\pyxfont\font\pyxfonttfa=cmr10 at 43.0pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 29.86pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 24.88pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 43.0pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 29.86pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 24.88pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 43.0pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 29.86pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 24.88pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 43.0pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 29.86pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 24.88pt\scriptscriptfont3=\pyxfontssfd} \def\LARGE{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} \def\huge{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} \def\Huge{\font\pyxfont=cmss10 at 51.6pt\pyxfont\font\pyxfonttfa=cmr10 at 51.6pt\textfont0=\pyxfonttfa\font\pyxfontsfa=cmr10 at 35.83pt\scriptfont0=\pyxfontsfa\font\pyxfontssfa=cmr10 at 29.86pt\scriptscriptfont0=\pyxfontssfa\font\pyxfonttfb=cmmi10 at 51.6pt\textfont1=\pyxfonttfb\font\pyxfontsfb=cmmi10 at 35.83pt\scriptfont1=\pyxfontsfb\font\pyxfontssfb=cmmi10 at 29.86pt\scriptscriptfont1=\pyxfontssfb\font\pyxfonttfc=cmsy10 at 51.6pt\textfont2=\pyxfonttfc\font\pyxfontsfc=cmsy10 at 35.83pt\scriptfont2=\pyxfontsfc\font\pyxfontssfc=cmsy10 at 29.86pt\scriptscriptfont2=\pyxfontssfc\font\pyxfonttfd=cmex10 at 51.6pt\textfont3=\pyxfonttfd\font\pyxfontsfd=cmex10 at 35.83pt\scriptfont3=\pyxfontsfd\font\pyxfontssfd=cmex10 at 29.86pt\scriptscriptfont3=\pyxfontssfd} PyX-0.14.1/pyx/data/pyxrc0000644000076500000240000000661412254600623015361 0ustar andrestaff00000000000000# This file is an example containing the runtime configuration options # of PyX and its default values. You may copy it to ~/.pyxrc for personal # configuration. [general] # general options # Some options can contain several values and the space character is # used by default to separate several values. In case the space # character is needed itself as part of the values, you can set an # unused replacement string to encode the space character being # part of the value. By default 'SPACE' is this magic string: space = SPACE [text] # runtime configuration of the text module # 'tex' specifies the TeX executable and defaults to 'tex'. tex = tex # 'latex' specifies the LaTeX executable and defaults to 'latex'. latex = latex # 'psfontmaps' is a whitespace separated list of options listing font # mapping files. Those files contain information about the available # type1 fonts. Depending on your TeX-installation you may need to add # further font mapping files like psfonts.cmz (if your TeX installation # is not configured to use type1 fonts by default). For further # information browse the FAQ for the term 'font mapping file'. psfontmaps = psfonts.map # 'pdffontmaps' is similar to psfontmaps, but used when pdf output # is generated. (Note that pdf has a different set of builtin fonts.) pdffontmaps = pdftex.map # 'wait' is an positive integer. It is the number of seconds # to be waited for an appropriate response from TeX/LaTeX. wait = 60 # 'showwait' is an non-negative integer. It is the number of # seconds to be waited until (and between) emitting messages # indicating the waiting for an appropriate response from TeX/LaTeX. # This feature can be turned off by setting showwaitfortex to 0. showwait = 5 # 'texipc' is a boolean controlling the usage of the --ipc option of # TeX/LaTeX. You should turn on this option when the ipc-extension is # available in your TeX installation (check the output of tex --help). # You will gain immediate access to the dvi-output of TeX by that, # which will substantially improve the performance of certain # operations (e.g. the usage of PyX markers). texipc = 0 [filelocator] # runtime configuration of file search mechanism # 'methods' defines a list of methods to be tried one after each other # to find files like, e.g., fonts and corresponding metrics information. # # Available methods are: # - 'local': locates files in the current directory. # - 'internal': locates files within the PyX data tree (works inside # of zipped Python eggs too) # - 'recursivedir': locates files by searching recursively in a # space-separated list of directories, which can # be specified by the option 'recursivedir'. # - 'ls-R': locates files by searching a list of ls-R files, # which can be specified by the option 'ls-R'. # - 'pykpathsea': locate files using the pykpathsea extension if available. # Building of this module can be enabled in the setup.cfg # file distributed with PyX. # - 'kpsewhich': locate files using the kpsewhich executable if available. # The name of the executable can be set by the 'kpsewhich' # option and defaults to 'kpsewhich'. # - 'locate': locate files using a locate executable if available. # The name of the executable can be set by the 'locate' # option and defaults to 'locate'. methods = local internal pykpathsea kpsewhich PyX-0.14.1/pyx/deco.py0000644000076500000240000015027612576615541014664 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2003-2011 Michael Schindler # Copyright (C) 2002-2013 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # TODO: # - should we improve on the arc length -> arg parametrization routine or # should we at least factor it out? import sys, math from . import attr, baseclasses, canvas, color, path, normpath, style, trafo, unit, deformer _marker = object() # # Decorated path # class decoratedpath(baseclasses.canvasitem): """Decorated path The main purpose of this class is during the drawing (stroking/filling) of a path. It collects attributes for the stroke and/or fill operations. """ def __init__(self, path, strokepath=None, fillpath=None, styles=None, strokestyles=None, fillstyles=None, ornaments=None): self.path = path # global style for stroking and filling and subdps self.styles = styles # styles which apply only for stroking and filling self.strokestyles = strokestyles self.fillstyles = fillstyles # the decoratedpath can contain additional elements of the # path (ornaments), e.g., arrowheads. if ornaments is None: self.ornaments = canvas.canvas() else: self.ornaments = ornaments self.nostrokeranges = None def ensurenormpath(self): """convert self.path into a normpath""" assert self.nostrokeranges is None or isinstance(self.path, path.normpath), "you don't understand what you are doing" self.path = self.path.normpath() def excluderange(self, begin, end): assert isinstance(self.path, path.normpath), "you don't understand what this is about" if self.nostrokeranges is None: self.nostrokeranges = [(begin, end)] else: ibegin = 0 while ibegin < len(self.nostrokeranges) and self.nostrokeranges[ibegin][1] < begin: ibegin += 1 if ibegin == len(self.nostrokeranges): self.nostrokeranges.append((begin, end)) return iend = len(self.nostrokeranges) - 1 while 0 <= iend and end < self.nostrokeranges[iend][0]: iend -= 1 if iend == -1: self.nostrokeranges.insert(0, (begin, end)) return if self.nostrokeranges[ibegin][0] < begin: begin = self.nostrokeranges[ibegin][0] if end < self.nostrokeranges[iend][1]: end = self.nostrokeranges[iend][1] self.nostrokeranges[ibegin:iend+1] = [(begin, end)] def bbox(self): pathbbox = self.path.bbox() ornamentsbbox = self.ornaments.bbox() if ornamentsbbox is not None: return ornamentsbbox + pathbbox else: return pathbbox def strokepath(self): if self.nostrokeranges: splitlist = [] for begin, end in self.nostrokeranges: splitlist.append(begin) splitlist.append(end) split = self.path.split(splitlist) # XXX properly handle closed paths? result = split[0] for i in range(2, len(split), 2): result += split[i] return result else: return self.path def processPS(self, file, writer, context, registry, bbox): # draw (stroke and/or fill) the decoratedpath on the canvas # while trying to produce an efficient output, e.g., by # not writing one path two times # small helper def _writestyles(styles, context, registry): for style in styles: style.processPS(file, writer, context, registry) strokepath = self.strokepath() fillpath = self.path # apply global styles if self.styles: file.write("gsave\n") context = context() _writestyles(self.styles, context, registry) if self.fillstyles is not None: file.write("newpath\n") fillpath.outputPS(file, writer) if self.strokestyles is not None and strokepath is fillpath: # do efficient stroking + filling if respective paths are identical file.write("gsave\n") if self.fillstyles: _writestyles(self.fillstyles, context(), registry) if context.fillrule: file.write("eofill\n") else: file.write("fill\n") file.write("grestore\n") acontext = context() if self.strokestyles: file.write("gsave\n") _writestyles(self.strokestyles, acontext, registry) file.write("stroke\n") # take linewidth into account for bbox when stroking a path bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("grestore\n") else: # only fill fillpath - for the moment if self.fillstyles: file.write("gsave\n") _writestyles(self.fillstyles, context(), registry) if context.fillrule: file.write("eofill\n") else: file.write("fill\n") bbox += fillpath.bbox() if self.fillstyles: file.write("grestore\n") if self.strokestyles is not None and (strokepath is not fillpath or self.fillstyles is None): # this is the only relevant case still left # Note that a possible filling has already been done. acontext = context() if self.strokestyles: file.write("gsave\n") _writestyles(self.strokestyles, acontext, registry) file.write("newpath\n") strokepath.outputPS(file, writer) file.write("stroke\n") # take linewidth into account for bbox when stroking a path bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("grestore\n") # now, draw additional elements of decoratedpath self.ornaments.processPS(file, writer, context, registry, bbox) # restore global styles if self.styles: file.write("grestore\n") def processPDF(self, file, writer, context, registry, bbox): # draw (stroke and/or fill) the decoratedpath on the canvas def _writestyles(styles, context, registry): for style in styles: style.processPDF(file, writer, context, registry) def _writestrokestyles(strokestyles, context, registry): context.fillattr = 0 for style in strokestyles: style.processPDF(file, writer, context, registry) context.fillattr = 1 def _writefillstyles(fillstyles, context, registry): context.strokeattr = 0 for style in fillstyles: style.processPDF(file, writer, context, registry) context.strokeattr = 1 strokepath = self.strokepath() fillpath = self.path # apply global styles if self.styles: file.write("q\n") # gsave context = context() _writestyles(self.styles, context, registry) if self.fillstyles is not None: fillpath.outputPDF(file, writer) if self.strokestyles is not None and strokepath is fillpath: # do efficient stroking + filling file.write("q\n") # gsave acontext = context() if self.fillstyles: _writefillstyles(self.fillstyles, acontext, registry) if self.strokestyles: _writestrokestyles(self.strokestyles, acontext, registry) if context.fillrule: file.write("B*\n") else: file.write("B\n") # both stroke and fill # take linewidth into account for bbox when stroking a path bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) file.write("Q\n") # grestore else: # only fill fillpath - for the moment if self.fillstyles: file.write("q\n") # gsave _writefillstyles(self.fillstyles, context(), registry) if context.fillrule: file.write("f*\n") else: file.write("f\n") # fill bbox += fillpath.bbox() if self.fillstyles: file.write("Q\n") # grestore if self.strokestyles is not None and (strokepath is not fillpath or self.fillstyles is None): # this is the only relevant case still left # Note that a possible stroking has already been done. acontext = context() if self.strokestyles: file.write("q\n") # gsave _writestrokestyles(self.strokestyles, acontext, registry) strokepath.outputPDF(file, writer) file.write("S\n") # stroke # take linewidth into account for bbox when stroking a path bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("Q\n") # grestore # now, draw additional elements of decoratedpath self.ornaments.processPDF(file, writer, context, registry, bbox) # restore global styles if self.styles: file.write("Q\n") # grestore def processSVG(self, xml, writer, context, registry, bbox): def _writestyles(attrs, context): for style in self.styles or []: style.processSVGattrs(attrs, writer, context, registry) def _writestrokestyles(attrs, context): context.fillattr = False for style in self.strokestyles or []: style.processSVGattrs(attrs, writer, context, registry) context.fillattr = True def _writefillstyles(attrs, context): context.strokeattr = False for style in self.fillstyles or []: style.processSVGattrs(attrs, writer, context, registry) context.strokeattr = True strokepath = self.strokepath() fillpath = self.path if self.styles: acontext = context() attrs = {} _writestyles(attrs, acontext) xml.startSVGElement("g", attrs) else: acontext = context if strokepath is not fillpath: if self.strokestyles is not None: attrs = {"d": strokepath.returnSVGdata()} _writestrokestyles(attrs, acontext) attrs["stroke"] = acontext.strokecolor if acontext.strokeopacity != 1: attrs["opacity"] = "%f" % acontext.strokeopacity xml.startSVGElement("path", attrs) xml.endSVGElement("path") bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.fillstyles is not None: attrs = {"d": fillpath.returnSVGdata()} _writefillstyles(attrs, acontext) attrs["fill"] = acontext.fillcolor if acontext.fillopacity != 1: attrs["opacity"] = "%f" % acontext.fillopacity xml.startSVGElement("path", attrs) xml.endSVGElement("path") bbox += fillpath.bbox() else: attrs = {"d": fillpath.returnSVGdata()} _writestrokestyles(attrs, acontext) _writefillstyles(attrs, acontext) if self.strokestyles is not None: attrs["stroke"] = acontext.strokecolor if self.fillstyles is not None: attrs["fill"] = acontext.fillcolor if acontext.strokeopacity != acontext.fillopacity and self.strokestyles is not None and self.fillstyles is not None: if acontext.strokeopacity != 1: attrs["opacity"] = "%f" % acontext.strokeopacity attrs["stroke"] = acontext.strokecolor attrs["fill"] = "none" xml.startSVGElement("path", attrs) xml.endSVGElement("path") if acontext.fillopacity != 1: attrs["opacity"] = "%f" % acontext.fillopacity attrs["stroke"] = "none" attrs["fill"] = acontext.fillcolor xml.startSVGElement("path", attrs) xml.endSVGElement("path") else: if acontext.strokeopacity != 1 and self.strokestyles is not None: attrs["opacity"] = "%f" % acontext.strokeopacity if acontext.fillopacity != 1 and self.fillstyles is not None: attrs["opacity"] = "%f" % acontext.fillopacity xml.startSVGElement("path", attrs) xml.endSVGElement("path") if self.strokestyles is not None: bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) else: bbox += strokepath.bbox() self.ornaments.processSVG(xml, writer, acontext, registry, bbox) if self.styles: xml.endSVGElement("g") # # Path decorators # class deco: """decorators In contrast to path styles, path decorators depend on the concrete path to which they are applied. In particular, they don't make sense without any path and can thus not be used in canvas.set! """ def decorate(self, dp, texrunner): """apply a style to a given decoratedpath object dp decorate accepts a decoratedpath object dp, applies PathStyle by modifying dp in place. """ pass # # stroked and filled: basic decos which stroked and fill, # respectively the path # class _stroked(deco, attr.exclusiveattr): """stroked is a decorator, which draws the outline of the path""" def __init__(self, styles=[]): attr.exclusiveattr.__init__(self, _stroked) self.styles = attr.mergeattrs(styles) attr.checkattrs(self.styles, [style.strokestyle]) def __call__(self, styles=[]): # XXX or should we also merge self.styles return _stroked(styles) def decorate(self, dp, texrunner): if dp.strokestyles is not None: raise RuntimeError("Cannot stroke an already stroked path") dp.strokestyles = self.styles stroked = _stroked() stroked.clear = attr.clearclass(_stroked) class _filled(deco, attr.exclusiveattr): """filled is a decorator, which fills the interior of the path""" def __init__(self, styles=[]): attr.exclusiveattr.__init__(self, _filled) self.styles = attr.mergeattrs(styles) attr.checkattrs(self.styles, [style.fillstyle]) def __call__(self, styles=[]): # XXX or should we also merge self.styles return _filled(styles) def decorate(self, dp, texrunner): if dp.fillstyles is not None: raise RuntimeError("Cannot fill an already filled path") dp.fillstyles = self.styles filled = _filled() filled.clear = attr.clearclass(_filled) # # Arrows # # helper function which constructs the arrowhead def _arrowhead(anormpath, arclenfrombegin, direction, size, angle, constriction, constrictionlen): """helper routine, which returns an arrowhead from a given anormpath - arclenfrombegin: position of arrow in arc length from the start of the path - direction: +1 for an arrow pointing along the direction of anormpath or -1 for an arrow pointing opposite to the direction of normpath - size: size of the arrow as arc length - angle. opening angle - constriction: boolean to indicate whether the constriction point is to be taken into account or not - constrictionlen: arc length of constriction. (not used when constriction is false) """ # arc length and coordinates of tip tx, ty = anormpath.at(arclenfrombegin) # construct the template for the arrow by cutting the path at the # corresponding length arrowtemplate = anormpath.split([arclenfrombegin, arclenfrombegin - direction * size])[1] # from this template, we construct the two outer curves of the arrow arrowl = arrowtemplate.transformed(trafo.rotate(-angle/2.0, tx, ty)) arrowr = arrowtemplate.transformed(trafo.rotate( angle/2.0, tx, ty)) # now come the joining backward parts if constriction: # constriction point (cx, cy) lies on path cx, cy = anormpath.at(arclenfrombegin - direction * constrictionlen) arrowcr= path.line(*(arrowr.atend() + (cx,cy))) arrow = arrowl.reversed() << arrowr << arrowcr else: arrow = arrowl.reversed() << arrowr arrow[-1].close() return arrow _base = 6 * unit.v_pt class arrow(deco, attr.attr): """arrow is a decorator which adds an arrow to either side of the path""" def __init__(self, attrs=[], pos=1, reversed=0, size=_base, angle=45, constriction=0.8): self.attrs = attr.mergeattrs([style.linestyle.solid, filled] + attrs) attr.checkattrs(self.attrs, [deco, style.fillstyle, style.strokestyle]) self.pos = pos self.reversed = reversed self.size = size self.angle = angle self.constriction = constriction # calculate absolute arc length of constricition # Note that we have to correct this length because the arrowtemplates are rotated # by self.angle/2 to the left and right. Hence, if we want no constriction, i.e., for # self.constriction = 1, we actually have a length which is approximately shorter # by the given geometrical factor. if self.constriction is not None: self.constrictionlen = self.size * self.constriction * math.cos(math.radians(self.angle/2.0)) else: # if we do not want a constriction, i.e. constriction is None, we still # need constrictionlen for cutting the path self.constrictionlen = self.size * 1 * math.cos(math.radians(self.angle/2.0)) def __call__(self, attrs=None, pos=None, reversed=None, size=None, angle=None, constriction=_marker): if attrs is None: attrs = self.attrs if pos is None: pos = self.pos if reversed is None: reversed = self.reversed if size is None: size = self.size if angle is None: angle = self.angle if constriction is _marker: constriction = self.constriction return arrow(attrs=attrs, pos=pos, reversed=reversed, size=size, angle=angle, constriction=constriction) def decorate(self, dp, texrunner): dp.ensurenormpath() anormpath = dp.path arclenfrombegin = (1-self.reversed)*self.constrictionlen + self.pos * (anormpath.arclen() - self.constrictionlen) direction = self.reversed and -1 or 1 arrowhead = _arrowhead(anormpath, arclenfrombegin, direction, self.size, self.angle, self.constriction is not None, self.constrictionlen) # add arrowhead to decoratedpath dp.ornaments.draw(arrowhead, self.attrs) # exlude part of the path from stroking when the arrow is strictly at the begin or the end if self.pos == 0 and self.reversed: dp.excluderange(0, min(self.size, self.constrictionlen)) elif self.pos == 1 and not self.reversed: dp.excluderange(anormpath.end() - min(self.size, self.constrictionlen), anormpath.end()) arrow.clear = attr.clearclass(arrow) # arrows at begin of path barrow = arrow(pos=0, reversed=1) barrow.SMALL = barrow(size=_base/math.sqrt(64)) barrow.SMALl = barrow(size=_base/math.sqrt(32)) barrow.SMAll = barrow(size=_base/math.sqrt(16)) barrow.SMall = barrow(size=_base/math.sqrt(8)) barrow.Small = barrow(size=_base/math.sqrt(4)) barrow.small = barrow(size=_base/math.sqrt(2)) barrow.normal = barrow(size=_base) barrow.large = barrow(size=_base*math.sqrt(2)) barrow.Large = barrow(size=_base*math.sqrt(4)) barrow.LArge = barrow(size=_base*math.sqrt(8)) barrow.LARge = barrow(size=_base*math.sqrt(16)) barrow.LARGe = barrow(size=_base*math.sqrt(32)) barrow.LARGE = barrow(size=_base*math.sqrt(64)) # arrows at end of path earrow = arrow() earrow.SMALL = earrow(size=_base/math.sqrt(64)) earrow.SMALl = earrow(size=_base/math.sqrt(32)) earrow.SMAll = earrow(size=_base/math.sqrt(16)) earrow.SMall = earrow(size=_base/math.sqrt(8)) earrow.Small = earrow(size=_base/math.sqrt(4)) earrow.small = earrow(size=_base/math.sqrt(2)) earrow.normal = earrow(size=_base) earrow.large = earrow(size=_base*math.sqrt(2)) earrow.Large = earrow(size=_base*math.sqrt(4)) earrow.LArge = earrow(size=_base*math.sqrt(8)) earrow.LARge = earrow(size=_base*math.sqrt(16)) earrow.LARGe = earrow(size=_base*math.sqrt(32)) earrow.LARGE = earrow(size=_base*math.sqrt(64)) class text(deco, attr.attr): """a simple text decorator""" def __init__(self, text, textattrs=[], angle=0, relangle=None, textdist=0.2, relarclenpos=0.5, arclenfrombegin=None, arclenfromend=None, texrunner=None): if arclenfrombegin is not None and arclenfromend is not None: raise ValueError("either set arclenfrombegin or arclenfromend") self.text = text self.textattrs = textattrs self.angle = angle self.relangle = relangle self.textdist = textdist self.relarclenpos = relarclenpos self.arclenfrombegin = arclenfrombegin self.arclenfromend = arclenfromend self.texrunner = texrunner def decorate(self, dp, texrunner): if self.texrunner: texrunner = self.texrunner from . import text as textmodule textattrs = attr.mergeattrs([textmodule.halign.center, textmodule.vshift.mathaxis] + self.textattrs) dp.ensurenormpath() if self.arclenfrombegin is not None: param = dp.path.begin() + self.arclenfrombegin elif self.arclenfromend is not None: param = dp.path.end() - self.arclenfromend else: # relarcpos is used, when neither arcfrombegin nor arcfromend is given param = self.relarclenpos * dp.path.arclen() x, y = dp.path.at(param) if self.relangle is not None: a = dp.path.trafo(param).apply_pt(math.cos(self.relangle*math.pi/180), math.sin(self.relangle*math.pi/180)) b = dp.path.trafo(param).apply_pt(0, 0) angle = math.atan2(a[1] - b[1], a[0] - b[0]) else: angle = self.angle*math.pi/180 t = texrunner.text(x, y, self.text, textattrs) t.linealign(self.textdist, math.cos(angle), math.sin(angle)) dp.ornaments.insert(t) class curvedtext(deco, attr.attr): """a text decorator for curved text - text: is typeset along the path to which this decorator is applied - relarclenpos: position for the base point of the text (default: 0) - arlenfrombegin, arclenfromend: alternative ways of specifying the position of the base point; use of relarclenpos, arclenfrombegin and arclenfromend is mutually exclusive - textattrs, texrunner: standard text arguments (defaults: [] resp None) """ # defaulttextattrs = [textmodule.halign.center] # TODO: not possible due to cyclic import issue def __init__(self, text, textattrs=[], relarclenpos=0.5, arclenfrombegin=None, arclenfromend=None, texrunner=None, exclude=None): if arclenfrombegin is not None and arclenfromend is not None: raise ValueError("either set arclenfrombegin or arclenfromend") self.text = text self.textattrs = textattrs self.relarclenpos = relarclenpos self.arclenfrombegin = arclenfrombegin self.arclenfromend = arclenfromend self.texrunner = texrunner self.exclude = exclude def decorate(self, dp, texrunner): if self.texrunner: texrunner = self.texrunner from . import text as textmodule self.defaulttextattrs = [textmodule.halign.center] dp.ensurenormpath() if self.arclenfrombegin is not None: textpos = dp.path.begin() + self.arclenfrombegin elif self.arclenfromend is not None: textpos = dp.path.end() - self.arclenfromend else: # relarcpos is used if neither arcfrombegin nor arcfromend is given textpos = self.relarclenpos * dp.path.arclen() textattrs = self.defaulttextattrs + self.textattrs t = texrunner.text(0, 0, self.text, textattrs, singlecharmode=1) t.do_finish() # we copy the style from the original textbox and modify the position for each dvicanvas item c = canvas.canvas(t.dvicanvas.styles) for item in t.dvicanvas.items: bbox = item.bbox() bbox = bbox.transformed(t.texttrafo) x = bbox.center()[0] atrafo = dp.path.trafo(textpos+x) c.insert(item, [t.texttrafo] + [trafo.translate(-x, 0)] + [atrafo]) if self.exclude is not None: dp.excluderange(textpos+bbox.left()-self.exclude, textpos+bbox.right()+self.exclude) dp.ornaments.insert(c) class shownormpath(deco, attr.attr): default_normline_attrs = [color.rgb.blue] default_normcurve_attrs = [color.rgb.green] default_endpoint_attrs = [] default_controlline_attrs = [color.rgb.red, style.linestyle.dashed] default_controlpoint_attrs = [color.rgb.red] def __init__(self, normline_attrs=[], normcurve_attrs=[], endpoint_size=0.05*unit.v_cm, endpoint_attrs=[], controlline_attrs=[], controlpoint_size=0.05*unit.v_cm, controlpoint_attrs=[]): self.normline_attrs = attr.refineattrs(normline_attrs, self.default_normline_attrs, [style.strokestyle]) self.normcurve_attrs = attr.refineattrs(normcurve_attrs, self.default_normcurve_attrs, [style.strokestyle]) self.endpoint_size_pt = unit.topt(endpoint_size) self.endpoint_attrs = attr.refineattrs(endpoint_attrs, self.default_endpoint_attrs, [style.fillstyle]) self.controlline_attrs = attr.refineattrs(controlline_attrs, self.default_controlline_attrs, [style.strokestyle]) self.controlpoint_size_pt = unit.topt(controlpoint_size) self.controlpoint_attrs = attr.refineattrs(controlpoint_attrs, self.default_controlpoint_attrs, [style.fillstyle]) def decorate(self, dp, texrunner): dp.ensurenormpath() for normsubpath in dp.path.normsubpaths: for i, normsubpathitem in enumerate(normsubpath.normsubpathitems): p = path.path(path.moveto_pt(*normsubpathitem.atbegin_pt()), normsubpathitem.pathitem()) if isinstance(normsubpathitem, normpath.normcurve_pt): if self.normcurve_attrs is not None: dp.ornaments.stroke(p, self.normcurve_attrs) else: if self.normline_attrs is not None: dp.ornaments.stroke(p, self.normline_attrs) for normsubpath in dp.path.normsubpaths: for i, normsubpathitem in enumerate(normsubpath.normsubpathitems): if isinstance(normsubpathitem, normpath.normcurve_pt): if self.controlline_attrs is not None: dp.ornaments.stroke(path.line_pt(normsubpathitem.x0_pt, normsubpathitem.y0_pt, normsubpathitem.x1_pt, normsubpathitem.y1_pt), self.controlline_attrs) dp.ornaments.stroke(path.line_pt(normsubpathitem.x2_pt, normsubpathitem.y2_pt, normsubpathitem.x3_pt, normsubpathitem.y3_pt), self.controlline_attrs) if self.controlpoint_attrs is not None: dp.ornaments.fill(path.circle_pt(normsubpathitem.x1_pt, normsubpathitem.y1_pt, self.controlpoint_size_pt), self.controlpoint_attrs) dp.ornaments.fill(path.circle_pt(normsubpathitem.x2_pt, normsubpathitem.y2_pt, self.controlpoint_size_pt), self.controlpoint_attrs) if self.endpoint_attrs is not None: for normsubpath in dp.path.normsubpaths: for i, normsubpathitem in enumerate(normsubpath.normsubpathitems): if not i: x_pt, y_pt = normsubpathitem.atbegin_pt() dp.ornaments.fill(path.circle_pt(x_pt, y_pt, self.endpoint_size_pt), self.endpoint_attrs) x_pt, y_pt = normsubpathitem.atend_pt() dp.ornaments.fill(path.circle_pt(x_pt, y_pt, self.endpoint_size_pt), self.endpoint_attrs) class linehatched(deco, attr.exclusiveattr, attr.clearclass): """draws a pattern with explicit lines This class acts as a drop-in replacement for postscript patterns from the pattern module which are not understood by some printers""" def __init__(self, dist, angle, strokestyles=[], cross=0): attr.clearclass.__init__(self, _filled) attr.exclusiveattr.__init__(self, linehatched) self.dist = dist self.angle = angle self.strokestyles = attr.mergeattrs([style.linewidth.THIN] + strokestyles) attr.checkattrs(self.strokestyles, [style.strokestyle]) self.cross = cross def __call__(self, dist=None, angle=None, strokestyles=None, cross=None): if dist is None: dist = self.dist if angle is None: angle = self.angle if strokestyles is None: strokestyles = self.strokestyles if cross is None: cross = self.cross return linehatched(dist, angle, strokestyles, cross) def _decocanvas(self, angle, dp, texrunner): dp.ensurenormpath() dist_pt = unit.topt(self.dist) c = canvas.canvas([canvas.clip(dp.path)]) llx_pt, lly_pt, urx_pt, ury_pt = dp.path.bbox().highrestuple_pt() center_pt = 0.5*(llx_pt+urx_pt), 0.5*(lly_pt+ury_pt) radius_pt = 0.5*math.hypot(urx_pt-llx_pt, ury_pt-lly_pt) + dist_pt n = int(2*radius_pt / dist_pt) + 1 for i in range(n): x_pt = center_pt[0] - radius_pt + i*dist_pt c.stroke(path.line_pt(x_pt, center_pt[1]-radius_pt, x_pt, center_pt[1]+radius_pt), [trafo.rotate_pt(angle, center_pt[0], center_pt[1])] + self.strokestyles) return c def decorate(self, dp, texrunner): dp.ornaments.insert(self._decocanvas(self.angle, dp, texrunner)) if self.cross: dp.ornaments.insert(self._decocanvas(self.angle+90, dp, texrunner)) def merge(self, attrs): # act as attr.clearclass and as attr.exclusiveattr at the same time newattrs = attr.exclusiveattr.merge(self, attrs) return attr.clearclass.merge(self, newattrs) linehatched.clear = attr.clearclass(linehatched) _hatch_base = 0.1 * unit.v_cm linehatched0 = linehatched(_hatch_base, 0) linehatched0.SMALL = linehatched0(_hatch_base/math.sqrt(64)) linehatched0.SMALL = linehatched0(_hatch_base/math.sqrt(64)) linehatched0.SMALl = linehatched0(_hatch_base/math.sqrt(32)) linehatched0.SMAll = linehatched0(_hatch_base/math.sqrt(16)) linehatched0.SMall = linehatched0(_hatch_base/math.sqrt(8)) linehatched0.Small = linehatched0(_hatch_base/math.sqrt(4)) linehatched0.small = linehatched0(_hatch_base/math.sqrt(2)) linehatched0.normal = linehatched0(_hatch_base) linehatched0.large = linehatched0(_hatch_base*math.sqrt(2)) linehatched0.Large = linehatched0(_hatch_base*math.sqrt(4)) linehatched0.LArge = linehatched0(_hatch_base*math.sqrt(8)) linehatched0.LARge = linehatched0(_hatch_base*math.sqrt(16)) linehatched0.LARGe = linehatched0(_hatch_base*math.sqrt(32)) linehatched0.LARGE = linehatched0(_hatch_base*math.sqrt(64)) linehatched45 = linehatched(_hatch_base, 45) linehatched45.SMALL = linehatched45(_hatch_base/math.sqrt(64)) linehatched45.SMALl = linehatched45(_hatch_base/math.sqrt(32)) linehatched45.SMAll = linehatched45(_hatch_base/math.sqrt(16)) linehatched45.SMall = linehatched45(_hatch_base/math.sqrt(8)) linehatched45.Small = linehatched45(_hatch_base/math.sqrt(4)) linehatched45.small = linehatched45(_hatch_base/math.sqrt(2)) linehatched45.normal = linehatched45(_hatch_base) linehatched45.large = linehatched45(_hatch_base*math.sqrt(2)) linehatched45.Large = linehatched45(_hatch_base*math.sqrt(4)) linehatched45.LArge = linehatched45(_hatch_base*math.sqrt(8)) linehatched45.LARge = linehatched45(_hatch_base*math.sqrt(16)) linehatched45.LARGe = linehatched45(_hatch_base*math.sqrt(32)) linehatched45.LARGE = linehatched45(_hatch_base*math.sqrt(64)) linehatched90 = linehatched(_hatch_base, 90) linehatched90.SMALL = linehatched90(_hatch_base/math.sqrt(64)) linehatched90.SMALl = linehatched90(_hatch_base/math.sqrt(32)) linehatched90.SMAll = linehatched90(_hatch_base/math.sqrt(16)) linehatched90.SMall = linehatched90(_hatch_base/math.sqrt(8)) linehatched90.Small = linehatched90(_hatch_base/math.sqrt(4)) linehatched90.small = linehatched90(_hatch_base/math.sqrt(2)) linehatched90.normal = linehatched90(_hatch_base) linehatched90.large = linehatched90(_hatch_base*math.sqrt(2)) linehatched90.Large = linehatched90(_hatch_base*math.sqrt(4)) linehatched90.LArge = linehatched90(_hatch_base*math.sqrt(8)) linehatched90.LARge = linehatched90(_hatch_base*math.sqrt(16)) linehatched90.LARGe = linehatched90(_hatch_base*math.sqrt(32)) linehatched90.LARGE = linehatched90(_hatch_base*math.sqrt(64)) linehatched135 = linehatched(_hatch_base, 135) linehatched135.SMALL = linehatched135(_hatch_base/math.sqrt(64)) linehatched135.SMALl = linehatched135(_hatch_base/math.sqrt(32)) linehatched135.SMAll = linehatched135(_hatch_base/math.sqrt(16)) linehatched135.SMall = linehatched135(_hatch_base/math.sqrt(8)) linehatched135.Small = linehatched135(_hatch_base/math.sqrt(4)) linehatched135.small = linehatched135(_hatch_base/math.sqrt(2)) linehatched135.normal = linehatched135(_hatch_base) linehatched135.large = linehatched135(_hatch_base*math.sqrt(2)) linehatched135.Large = linehatched135(_hatch_base*math.sqrt(4)) linehatched135.LArge = linehatched135(_hatch_base*math.sqrt(8)) linehatched135.LARge = linehatched135(_hatch_base*math.sqrt(16)) linehatched135.LARGe = linehatched135(_hatch_base*math.sqrt(32)) linehatched135.LARGE = linehatched135(_hatch_base*math.sqrt(64)) crosslinehatched0 = linehatched(_hatch_base, 0, cross=1) crosslinehatched0.SMALL = crosslinehatched0(_hatch_base/math.sqrt(64)) crosslinehatched0.SMALl = crosslinehatched0(_hatch_base/math.sqrt(32)) crosslinehatched0.SMAll = crosslinehatched0(_hatch_base/math.sqrt(16)) crosslinehatched0.SMall = crosslinehatched0(_hatch_base/math.sqrt(8)) crosslinehatched0.Small = crosslinehatched0(_hatch_base/math.sqrt(4)) crosslinehatched0.small = crosslinehatched0(_hatch_base/math.sqrt(2)) crosslinehatched0.normal = crosslinehatched0 crosslinehatched0.large = crosslinehatched0(_hatch_base*math.sqrt(2)) crosslinehatched0.Large = crosslinehatched0(_hatch_base*math.sqrt(4)) crosslinehatched0.LArge = crosslinehatched0(_hatch_base*math.sqrt(8)) crosslinehatched0.LARge = crosslinehatched0(_hatch_base*math.sqrt(16)) crosslinehatched0.LARGe = crosslinehatched0(_hatch_base*math.sqrt(32)) crosslinehatched0.LARGE = crosslinehatched0(_hatch_base*math.sqrt(64)) crosslinehatched45 = linehatched(_hatch_base, 45, cross=1) crosslinehatched45.SMALL = crosslinehatched45(_hatch_base/math.sqrt(64)) crosslinehatched45.SMALl = crosslinehatched45(_hatch_base/math.sqrt(32)) crosslinehatched45.SMAll = crosslinehatched45(_hatch_base/math.sqrt(16)) crosslinehatched45.SMall = crosslinehatched45(_hatch_base/math.sqrt(8)) crosslinehatched45.Small = crosslinehatched45(_hatch_base/math.sqrt(4)) crosslinehatched45.small = crosslinehatched45(_hatch_base/math.sqrt(2)) crosslinehatched45.normal = crosslinehatched45 crosslinehatched45.large = crosslinehatched45(_hatch_base*math.sqrt(2)) crosslinehatched45.Large = crosslinehatched45(_hatch_base*math.sqrt(4)) crosslinehatched45.LArge = crosslinehatched45(_hatch_base*math.sqrt(8)) crosslinehatched45.LARge = crosslinehatched45(_hatch_base*math.sqrt(16)) crosslinehatched45.LARGe = crosslinehatched45(_hatch_base*math.sqrt(32)) crosslinehatched45.LARGE = crosslinehatched45(_hatch_base*math.sqrt(64)) class colorgradient(deco, attr.attr): """inserts pieces of the path in different colors""" def __init__(self, grad, attrs=[], steps=20): self.attrs = attrs self.grad = grad self.steps = steps def decorate(self, dp, texrunner): dp.ensurenormpath() l = dp.path.arclen() colors = [self.grad.select(n, self.steps) for n in range(self.steps)] colors.reverse() params = dp.path.arclentoparam([l*i/float(self.steps) for i in range(self.steps)]) params.reverse() c = canvas.canvas() # treat the end pieces separately c.stroke(dp.path.split(params[1])[1], attr.mergeattrs([colors[0]] + self.attrs)) for n in range(1,self.steps-1): c.stroke(dp.path.split([params[n-1],params[n+1]])[1], attr.mergeattrs([colors[n]] + self.attrs)) c.stroke(dp.path.split(params[-2])[0], attr.mergeattrs([colors[-1]] + self.attrs)) dp.ornaments.insert(c) class brace(deco, attr.attr): r"""draws a nicely curled brace In most cases, the original line is not wanted use canvas.canvas.draw(..) for it Geometrical parameters: inner /\ strokes ____________/ \__________ / bar bar \ outer / \ strokes totalheight distance from the jaws to the middle cap barthickness thickness of the main bars innerstrokesthickness thickness of the two ending strokes outerstrokesthickness thickness of the inner strokes at the middle cap innerstrokesrelheight height of the inner/outer strokes, relative to the total height outerstrokesrelheight this determines the angle of the main bars! should be around 0.5 Note: if innerstrokesrelheight + outerstrokesrelheight == 1 then the main bars will be aligned parallel to the connecting line between the endpoints outerstrokesangle angle of the two ending strokes innerstrokesangle angle between the inner strokes at the middle cap slantstrokesangle extra slanting of the inner/outer strokes innerstrokessmoothness smoothing parameter for the inner + outer strokes outerstrokessmoothness should be around 1 (allowed: [0,infty)) middlerelpos position of the middle cap (0 == left, 1 == right) """ # This code is experimental because it is unclear # how the brace fits into the concepts of PyX # # Some thoughts: # - a brace needs to be decoratable with text # it needs stroking and filling attributes # - the brace is not really a box: # it has two "anchor" points that are important for aligning it to other things # and one "anchor" point (plus direction) for aligning other things # - a brace is not a deformer: # it does not look at anything else than begin/endpoint of a path # - a brace might be a connector (which is to be dissolved into the box concept later?) def __init__(self, reverse=1, stretch=None, dist=None, fillattrs=[], totalheight=12*unit.x_pt, barthickness=0.5*unit.x_pt, innerstrokesthickness=0.25*unit.x_pt, outerstrokesthickness=0.25*unit.x_pt, innerstrokesrelheight=0.6, outerstrokesrelheight=0.7, innerstrokesangle=30, outerstrokesangle=25, slantstrokesangle=5, innerstrokessmoothness=2.0, outerstrokessmoothness=2.5, middlerelpos=0.5): self.fillattrs = fillattrs self.reverse = reverse self.stretch = stretch self.dist = dist self.totalheight = totalheight self.barthickness = barthickness self.innerstrokesthickness = innerstrokesthickness self.outerstrokesthickness = outerstrokesthickness self.innerstrokesrelheight = innerstrokesrelheight self.outerstrokesrelheight = outerstrokesrelheight self.innerstrokesangle = innerstrokesangle self.outerstrokesangle = outerstrokesangle self.slantstrokesangle = slantstrokesangle self.innerstrokessmoothness = innerstrokessmoothness self.outerstrokessmoothness = outerstrokessmoothness self.middlerelpos = middlerelpos def __call__(self, **kwargs): for name in ["reverse", "stretch", "dist", "fillattrs", "totalheight", "barthickness", "innerstrokesthickness", "outerstrokesthickness", "innerstrokesrelheight", "outerstrokesrelheight", "innerstrokesangle", "outerstrokesangle", "slantstrokesangle", "innerstrokessmoothness", "outerstrokessmoothness", "middlerelpos"]: if name not in kwargs: kwargs[name] = self.__dict__[name] return brace(**kwargs) def _halfbracepath_pt(self, length_pt, height_pt, ilength_pt, olength_pt, # <<< ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle): ismooth = self.innerstrokessmoothness osmooth = self.outerstrokessmoothness # these two parameters are not important enough to be seen outside inner_cap_param = 1.5 outer_cap_param = 2.5 outerextracurved = 0.6 # in (0, 1] # 1.0 will lead to F=G, the outer strokes will not be curved at their ends. # The smaller, the more curvature # build an orientation path (three straight lines) # # \q1 # / \ # / \ # _/ \______________________________________q5 # q2 q3 q4 \ # \ # \ # \q6 # # get the points for that: q1 = (0, height_pt - inner_cap_param * ithick_pt + 0.5*ithick_pt/sin_iangle) q2 = (q1[0] + ilength_pt * sin_iangle, q1[1] - ilength_pt * cos_iangle) q6 = (length_pt, 0) q5 = (q6[0] - olength_pt * sin_oangle, q6[1] + olength_pt * cos_oangle) bardir = (q5[0] - q2[0], q5[1] - q2[1]) bardirnorm = math.hypot(*bardir) bardir = (bardir[0]/bardirnorm, bardir[1]/bardirnorm) ismoothlength_pt = ilength_pt * ismooth osmoothlength_pt = olength_pt * osmooth if bardirnorm < ismoothlength_pt + osmoothlength_pt: ismoothlength_pt = bardirnorm * ismoothlength_pt / (ismoothlength_pt + osmoothlength_pt) osmoothlength_pt = bardirnorm * osmoothlength_pt / (ismoothlength_pt + osmoothlength_pt) q3 = (q2[0] + ismoothlength_pt * bardir[0], q2[1] + ismoothlength_pt * bardir[1]) q4 = (q5[0] - osmoothlength_pt * bardir[0], q5[1] - osmoothlength_pt * bardir[1]) # # P _O # / | \A2 # / A1\ \ # / \ B2C2________D2___________E2_______F2___G2 # \______________________________________ \ # B1,C1 D1 E1 F1 G1 \ # \ \ # \ \H2 # H1\_/I2 # I1 # # the halfbraces meet in P and A1: P = (0, height_pt) A1 = (0, height_pt - inner_cap_param * ithick_pt) # A2 is A1, shifted by the inner thickness A2 = (A1[0] + ithick_pt * cos_iangle, A1[1] + ithick_pt * sin_iangle) s, t = deformer.intersection(P, A2, (cos_slangle, sin_slangle), (sin_iangle, -cos_iangle)) O = (P[0] + s * cos_slangle, P[1] + s * sin_slangle) # from D1 to E1 is the straight part of the brace # also back from E2 to D1 D1 = (q3[0] + bthick_pt * bardir[1], q3[1] - bthick_pt * bardir[0]) D2 = (q3[0] - bthick_pt * bardir[1], q3[1] + bthick_pt * bardir[0]) E1 = (q4[0] + bthick_pt * bardir[1], q4[1] - bthick_pt * bardir[0]) E2 = (q4[0] - bthick_pt * bardir[1], q4[1] + bthick_pt * bardir[0]) # I1, I2 are the control points at the outer stroke I1 = (q6[0] - 0.5 * othick_pt * cos_oangle, q6[1] - 0.5 * othick_pt * sin_oangle) I2 = (q6[0] + 0.5 * othick_pt * cos_oangle, q6[1] + 0.5 * othick_pt * sin_oangle) # get the control points for the curved parts of the brace s, t = deformer.intersection(A1, D1, (sin_iangle, -cos_iangle), bardir) B1 = (D1[0] + t * bardir[0], D1[1] + t * bardir[1]) s, t = deformer.intersection(A2, D2, (sin_iangle, -cos_iangle), bardir) B2 = (D2[0] + t * bardir[0], D2[1] + t * bardir[1]) s, t = deformer.intersection(E1, I1, bardir, (-sin_oangle, cos_oangle)) G1 = (E1[0] + s * bardir[0], E1[1] + s * bardir[1]) s, t = deformer.intersection(E2, I2, bardir, (-sin_oangle, cos_oangle)) G2 = (E2[0] + s * bardir[0], E2[1] + s * bardir[1]) # at the inner strokes: use curvature zero at both ends C1 = B1 C2 = B2 # at the outer strokes: use curvature zero only at the connection to # the straight part F1 = (outerextracurved * G1[0] + (1 - outerextracurved) * E1[0], outerextracurved * G1[1] + (1 - outerextracurved) * E1[1]) F2 = (outerextracurved * G2[0] + (1 - outerextracurved) * E2[0], outerextracurved * G2[1] + (1 - outerextracurved) * E2[1]) # the tip of the outer stroke, endpoints of the bezier curve H1 = (I1[0] - outer_cap_param * othick_pt * sin_oangle, I1[1] + outer_cap_param * othick_pt * cos_oangle) H2 = (I2[0] - outer_cap_param * othick_pt * sin_oangle, I2[1] + outer_cap_param * othick_pt * cos_oangle) #for qq in [A1,B1,C1,D1,E1,F1,G1,H1,I1, # A2,B2,C2,D2,E2,F2,G2,H2,I2, # O,P # ]: # cc.fill(path.circle(qq[0], qq[1], 0.5), [color.rgb.green]) # now build the right halfbrace bracepath = path.path(path.moveto_pt(*A1)) bracepath.append(path.curveto_pt(B1[0], B1[1], C1[0], C1[1], D1[0], D1[1])) bracepath.append(path.lineto_pt(E1[0], E1[1])) bracepath.append(path.curveto_pt(F1[0], F1[1], G1[0], G1[1], H1[0], H1[1])) # the tip of the right halfbrace bracepath.append(path.curveto_pt(I1[0], I1[1], I2[0], I2[1], H2[0], H2[1])) # the rest of the right halfbrace bracepath.append(path.curveto_pt(G2[0], G2[1], F2[0], F2[1], E2[0], E2[1])) bracepath.append(path.lineto_pt(D2[0], D2[1])) bracepath.append(path.curveto_pt(C2[0], C2[1], B2[0], B2[1], A2[0], A2[1])) # the tip in the middle of the brace bracepath.append(path.curveto_pt(O[0], O[1], O[0], O[1], P[0], P[1])) return bracepath # >>> def _bracepath(self, x0_pt, y0_pt, x1_pt, y1_pt): # <<< height_pt = unit.topt(self.totalheight) totallength_pt = math.hypot(x1_pt - x0_pt, y1_pt - y0_pt) leftlength_pt = self.middlerelpos * totallength_pt rightlength_pt = totallength_pt - leftlength_pt ithick_pt = unit.topt(self.innerstrokesthickness) othick_pt = unit.topt(self.outerstrokesthickness) bthick_pt = unit.topt(self.barthickness) # create the left halfbrace with positive slanting # because we will mirror this part cos_iangle = math.cos(math.radians(0.5*self.innerstrokesangle - self.slantstrokesangle)) sin_iangle = math.sin(math.radians(0.5*self.innerstrokesangle - self.slantstrokesangle)) cos_oangle = math.cos(math.radians(self.outerstrokesangle - self.slantstrokesangle)) sin_oangle = math.sin(math.radians(self.outerstrokesangle - self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = self._halfbracepath_pt(leftlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle).reversed().transformed(trafo.mirror(90)) # create the right halfbrace with negative slanting cos_iangle = math.cos(math.radians(0.5*self.innerstrokesangle + self.slantstrokesangle)) sin_iangle = math.sin(math.radians(0.5*self.innerstrokesangle + self.slantstrokesangle)) cos_oangle = math.cos(math.radians(self.outerstrokesangle + self.slantstrokesangle)) sin_oangle = math.sin(math.radians(self.outerstrokesangle + self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = bracepath << self._halfbracepath_pt(rightlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle) return bracepath.transformed( # two trafos for matching the given endpoints trafo.translate_pt(x0_pt, y0_pt) * trafo.rotate_pt(math.degrees(math.atan2(y1_pt-y0_pt, x1_pt-x0_pt))) * # one trafo to move the brace's left outer stroke to zero trafo.translate_pt(leftlength_pt, 0)) # >>> def decorate(self, dp, texrunner): dp.ensurenormpath() x0_pt, y0_pt = dp.path.atbegin_pt() x1_pt, y1_pt = dp.path.atend_pt() if self.reverse: x0_pt, y0_pt, x1_pt, y1_pt = x1_pt, y1_pt, x0_pt, y0_pt if self.stretch is not None: xm, ym = 0.5*(x0_pt+x1_pt), 0.5*(y0_pt+y1_pt) x0_pt, y0_pt = xm + self.stretch*(x0_pt-xm), ym + self.stretch*(y0_pt-ym) x1_pt, y1_pt = xm + self.stretch*(x1_pt-xm), ym + self.stretch*(y1_pt-ym) if self.dist is not None: d = unit.topt(self.dist) dx, dy = dp.path.rotation_pt(dp.path.begin()).apply_pt(0, 1) x0_pt += d*dx; y0_pt += d*dy dx, dy = dp.path.rotation_pt(dp.path.end()).apply_pt(0, 1) x1_pt += d*dx; y1_pt += d*dy dp.ornaments.fill(self._bracepath(x0_pt, y0_pt, x1_pt, y1_pt), self.fillattrs) brace.clear = attr.clearclass(brace) leftbrace = brace(reverse=0, middlerelpos=0.55, innerstrokesrelheight=0.6, outerstrokesrelheight=0.7, slantstrokesangle=-10) rightbrace = brace(reverse=1, middlerelpos=0.45, innerstrokesrelheight=0.6, outerstrokesrelheight=0.7, slantstrokesangle=10) belowbrace = brace(reverse=1, middlerelpos=0.55, innerstrokesrelheight=0.7, outerstrokesrelheight=0.9, slantstrokesangle=-10) abovebrace = brace(reverse=0, middlerelpos=0.45, innerstrokesrelheight=0.7, outerstrokesrelheight=0.9, slantstrokesangle=-10) straightbrace = brace(innerstrokesrelheight=0.5, outerstrokesrelheight=0.5, innerstrokesangle=30, outerstrokesangle=30, slantstrokesangle=0, innerstrokessmoothness=1.0, outerstrokessmoothness=1.0) PyX-0.14.1/pyx/deformer.py0000644000076500000240000024266412254662347015557 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2003-2013 Michael Schindler # Copyright (C) 2003-2005 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import functools, logging, math from . import attr, baseclasses, mathutils, path, normpath, unit, color normpath.invalid = 175e175 # Just a very crude workaround to get the code running again. normpath.invalid does not exist anymore. logger = logging.getLogger("pyx") # specific exception for an invalid parameterization point # used in parallel class InvalidParamException(Exception): def __init__(self, param): self.normsubpathitemparam = param # error raised in parallel if we are trying to get badly defined intersections class IntersectionError(Exception): pass # None has a meaning in linesmoothed class _marker: pass class inf_curvature: pass def curvescontrols_from_endlines_pt(B, tangent1, tangent2, r1, r2, softness): # <<< # calculates the parameters for two bezier curves connecting two lines (curvature=0) # starting at B - r1*tangent1 # ending at B + r2*tangent2 # # Takes the corner B # and two tangent vectors heading to and from B # and two radii r1 and r2: # All arguments must be in Points # Returns the seven control points of the two bezier curves: # - start d1 # - control points g1 and f1 # - midpoint e # - control points f2 and g2 # - endpoint d2 # make direction vectors d1: from B to A # d2: from B to C d1 = -tangent1[0] / math.hypot(*tangent1), -tangent1[1] / math.hypot(*tangent1) d2 = tangent2[0] / math.hypot(*tangent2), tangent2[1] / math.hypot(*tangent2) # 0.3192 has turned out to be the maximum softness available # for straight lines ;-) f = 0.3192 * softness g = (15.0 * f + math.sqrt(-15.0*f*f + 24.0*f))/12.0 # make the control points of the two bezier curves f1 = B[0] + f * r1 * d1[0], B[1] + f * r1 * d1[1] f2 = B[0] + f * r2 * d2[0], B[1] + f * r2 * d2[1] g1 = B[0] + g * r1 * d1[0], B[1] + g * r1 * d1[1] g2 = B[0] + g * r2 * d2[0], B[1] + g * r2 * d2[1] d1 = B[0] + r1 * d1[0], B[1] + r1 * d1[1] d2 = B[0] + r2 * d2[0], B[1] + r2 * d2[1] e = 0.5 * (f1[0] + f2[0]), 0.5 * (f1[1] + f2[1]) return (d1, g1, f1, e, f2, g2, d2) # >>> def controldists_from_endgeometry_pt(A, B, tangA, tangB, curvA, curvB, allownegative=False, curv_epsilon=1.0e-8): # <<< """For a curve with given tangents and curvatures at the endpoints this gives the distances between the controlpoints This helper routine returns a list of two distances between the endpoints and the corresponding control points of a (cubic) bezier curve that has prescribed tangents tangentA, tangentB and curvatures curvA, curvB at the end points. Note: The returned distances are not always positive. But only positive values are geometrically correct, so please check! The outcome is sorted so that the first entry is expected to be the most reasonable one """ debug = 0 def test_divisions(T, D, E, AB, curvA, curvB, debug):# <<< small = AB * 1.0e-4 # at infinite curvature, avoid setting control points exactly on the startpoint # TODO: is this consistent with the avoiding of curv=inf in normpath? arbitrary = AB * 0.33 # at zero curvature, we know nothing about a or b def is_zero(x): return abs(x) < curv_epsilon # the following gave different results for forward/reverse paths # in test/functional/test_deformer parallel G #try: # 1.0 / x #except ZeroDivisionError: # return True #return False if is_zero(T): if curvA is inf_curvature: a = small if curvB is inf_curvature: b = small elif is_zero(curvB): assert abs(E) < 1.0e-10 b = arbitrary else: b = math.sqrt(abs(E / (1.5 * curvB))) * mathutils.sign(E*curvB) elif is_zero(curvA): assert abs(D) < 1.0e-10 a = arbitrary if curvB is inf_curvature: b = small elif is_zero(curvB): assert abs(E) < 1.0e-10 b = arbitrary else: b = math.sqrt(abs(E / (1.5 * curvB))) * mathutils.sign(E*curvB) else: a = math.sqrt(abs(D / (1.5 * curvA))) * mathutils.sign(D*curvA) if curvB is inf_curvature: b = small elif is_zero(curvB): assert abs(E) < 1.0e-10 b = arbitrary else: b = math.sqrt(abs(E / (1.5 * curvB))) * mathutils.sign(E*curvB) else: if curvA is inf_curvature: a = small if curvB is inf_curvature: b = small elif is_zero(curvB): b = arbitrary else: b1 = math.sqrt(abs(E / (1.5 * curvB))) * mathutils.sign(E*curvB) b2 = D / T if abs(b1) < abs(b2): b = b1 else: b = b2 elif curvB is inf_curvature: b = small if is_zero(curvA): a = arbitrary else: a1 = math.sqrt(abs(D / (1.5 * curvA))) * mathutils.sign(D*curvA) a2 = E / T if abs(a1) < abs(a2): a = a1 else: a = a2 elif is_zero(curvA): b = D / T a = (E - 1.5*curvB*b*abs(b)) / T elif is_zero(curvB): a = E / T b = (D - 1.5*curvA*a*abs(a)) / T else: return [] if debug: print("fallback with exact zero value") return [(a, b)] # >>> def fallback_smallT(T, D, E, AB, curvA, curvB, threshold, debug):# <<< a = math.sqrt(abs(D / (1.5 * curvA))) * mathutils.sign(D*curvA) b = math.sqrt(abs(E / (1.5 * curvB))) * mathutils.sign(E*curvB) q1 = min(abs(1.5*a*a*curvA), abs(D)) q2 = min(abs(1.5*b*b*curvB), abs(E)) if (a >= 0 and b >= 0 and abs(b*T) < threshold * q1 and abs(1.5*a*abs(a)*curvA - D) < threshold * q1 and abs(a*T) < threshold * q2 and abs(1.5*b*abs(b)*curvB - E) < threshold * q2): if debug: print("fallback with T approx 0") return [(a, b)] return [] # >>> def fallback_smallcurv(T, D, E, AB, curvA, curvB, threshold, debug):# <<< result = [] # is curvB approx zero? a = E / T b = (D - 1.5*curvA*a*abs(a)) / T if (a >= 0 and b >= 0 and abs(1.5*b*b*curvB) < threshold * min(abs(a*T), abs(E)) and abs(a*T - E) < threshold * min(abs(a*T), abs(E))): if debug: print("fallback with curvB approx 0") result.append((a, b)) # is curvA approx zero? b = D / T a = (E - 1.5*curvB*b*abs(b)) / T if (a >= 0 and b >= 0 and abs(1.5*a*a*curvA) < threshold * min(abs(b*T), abs(D)) and abs(b*T - D) < threshold * min(abs(b*T), abs(D))): if debug: print("fallback with curvA approx 0") result.append((a, b)) return result # >>> def findnearest(x, ys): # <<< I = 0 Y = ys[I] mindist = abs(x - Y) # find the value in ys which is nearest to x for i, y in enumerate(ys[1:]): dist = abs(x - y) if dist < mindist: I, Y, mindist = i, y, dist return I, Y # >>> # some shortcuts T = tangA[0] * tangB[1] - tangA[1] * tangB[0] D = tangA[0] * (B[1]-A[1]) - tangA[1] * (B[0]-A[0]) E = tangB[0] * (A[1]-B[1]) - tangB[1] * (A[0]-B[0]) AB = math.hypot(A[0] - B[0], A[1] - B[1]) # try if one of the prefactors is exactly zero testsols = test_divisions(T, D, E, AB, curvA, curvB, debug) if testsols: return testsols # The general case: # we try to find all the zeros of the decoupled 4th order problem # for the combined problem: # The control points of a cubic Bezier curve are given by a, b: # A, A + a*tangA, B - b*tangB, B # for the derivation see /design/beziers.tex # 0 = 1.5 a |a| curvA + b * T - D # 0 = 1.5 b |b| curvB + a * T - E # because of the absolute values we get several possibilities for the signs # in the equation. We test all signs, also the invalid ones! if allownegative: signs = [(+1, +1), (-1, +1), (+1, -1), (-1, -1)] else: signs = [(+1, +1)] candidates_a = [] candidates_b = [] for sign_a, sign_b in signs: coeffs_a = (sign_b*3.375*curvA*curvA*curvB, 0.0, -sign_b*sign_a*4.5*curvA*curvB*D, T**3, sign_b*1.5*curvB*D*D - T*T*E) coeffs_b = (sign_a*3.375*curvA*curvB*curvB, 0.0, -sign_a*sign_b*4.5*curvA*curvB*E, T**3, sign_a*1.5*curvA*E*E - T*T*D) candidates_a += [root for root in mathutils.realpolyroots(*coeffs_a) if sign_a*root >= 0] candidates_b += [root for root in mathutils.realpolyroots(*coeffs_b) if sign_b*root >= 0] solutions = [] if candidates_a and candidates_b: for a in candidates_a: i, b = findnearest((D - 1.5*curvA*a*abs(a))/T, candidates_b) solutions.append((a, b)) # try if there is an approximate solution for thr in [1.0e-2, 1.0e-1]: if not solutions: solutions = fallback_smallT(T, D, E, AB, curvA, curvB, thr, debug) if not solutions: solutions = fallback_smallcurv(T, D, E, AB, curvA, curvB, thr, debug) # sort the solutions: the more reasonable values at the beginning def mycmp(x,y): # <<< # first the pairs that are purely positive, then all the pairs with some negative signs # inside the two sets: sort by magnitude sx = (x[0] > 0 and x[1] > 0) sy = (y[0] > 0 and y[1] > 0) # experimental stuff: # what criterion should be used for sorting ? # #errx = abs(1.5*curvA*x[0]*abs(x[0]) + x[1]*T - D) + abs(1.5*curvB*x[1]*abs(x[1]) + x[0]*T - E) #erry = abs(1.5*curvA*y[0]*abs(y[0]) + y[1]*T - D) + abs(1.5*curvB*y[1]*abs(y[1]) + y[0]*T - E) # # For each equation, a value like # # abs(1.5*curvA*y[0]*abs(y[0]) + y[1]*T - D) / abs(curvA*(D - y[1]*T)) # # indicates how good the solution is. In order to avoid the division, # # we here multiply with all four denominators: # errx = max(abs( (1.5*curvA*y[0]*abs(y[0]) + y[1]*T - D) * (curvB*(E - y[0]*T))*(curvA*(D - x[1]*T))*(curvB*(E - x[0]*T)) ), # abs( (1.5*curvB*y[1]*abs(y[1]) + y[0]*T - E) * (curvA*(D - y[1]*T))*(curvA*(D - x[1]*T))*(curvB*(E - x[0]*T)) )) # errx = max(abs( (1.5*curvA*x[0]*abs(x[0]) + x[1]*T - D) * (curvA*(D - y[1]*T))*(curvB*(E - y[0]*T))*(curvB*(E - x[0]*T)) ), # abs( (1.5*curvB*x[1]*abs(x[1]) + x[0]*T - E) * (curvA*(D - y[1]*T))*(curvB*(E - y[0]*T))*(curvA*(D - x[1]*T)) )) #errx = (abs(curvA*x[0]) - 1.0)**2 + (abs(curvB*x[1]) - 1.0)**2 #erry = (abs(curvA*y[0]) - 1.0)**2 + (abs(curvB*y[1]) - 1.0)**2 errx = x[0]**2 + x[1]**2 erry = y[0]**2 + y[1]**2 if sx == 1 and sy == 1: # try to use longer solutions if there are any crossings in the control-arms # the following combination yielded fewest sorting errors in test_bezier.py t, s = intersection(A, B, tangA, tangB) t, s = abs(t), abs(s) if (t > 0 and t < x[0] and s > 0 and s < x[1]): if (t > 0 and t < y[0] and s > 0 and s < y[1]): # use the shorter one return (errx > erry) - (errx < erry) else: # use the longer one return -1 else: if (t > 0 and t < y[0] and s > 0 and s < y[1]): # use the longer one return 1 else: # use the shorter one return (errx > erry) - (errx < erry) #return cmp(x[0]**2 + x[1]**2, y[0]**2 + y[1]**2) else: return (sy > sx) - (sy < sx) # >>> solutions.sort(key=functools.cmp_to_key(mycmp)) return solutions # >>> def normcurve_from_endgeometry_pt(A, B, tangA, tangB, curvA, curvB): # <<< a, b = controldists_from_endgeometry_pt(A, B, tangA, tangB, curvA, curvB)[0] return normpath.normcurve_pt(A[0], A[1], A[0] + a * tangA[0], A[1] + a * tangA[1], B[0] - b * tangB[0], B[1] - b * tangB[1], B[0], B[1]) # >>> def intersection(A, D, tangA, tangD): # <<< """returns the intersection parameters of two evens they are defined by: x(t) = A + t * tangA x(s) = D + s * tangD """ det = -tangA[0] * tangD[1] + tangA[1] * tangD[0] try: 1.0 / det except ArithmeticError: return None, None DA = D[0] - A[0], D[1] - A[1] t = (-tangD[1]*DA[0] + tangD[0]*DA[1]) / det s = (-tangA[1]*DA[0] + tangA[0]*DA[1]) / det return t, s # >>> class cycloid(baseclasses.deformer): # <<< """Wraps a cycloid around a path. The outcome looks like a spring with the originalpath as the axis. radius: radius of the cycloid halfloops: number of halfloops skipfirst/skiplast: undeformed end lines of the original path curvesperhloop: sign: start left (1) or right (-1) with the first halfloop turnangle: angle of perspective on a (3D) spring turnangle=0 will produce a sinus-like cycloid, turnangle=90 will procude a row of connected circles """ def __init__(self, radius=0.5*unit.t_cm, halfloops=10, skipfirst=1*unit.t_cm, skiplast=1*unit.t_cm, curvesperhloop=3, sign=1, turnangle=45): self.skipfirst = skipfirst self.skiplast = skiplast self.radius = radius self.halfloops = halfloops self.curvesperhloop = curvesperhloop self.sign = sign self.turnangle = turnangle def __call__(self, radius=None, halfloops=None, skipfirst=None, skiplast=None, curvesperhloop=None, sign=None, turnangle=None): if radius is None: radius = self.radius if halfloops is None: halfloops = self.halfloops if skipfirst is None: skipfirst = self.skipfirst if skiplast is None: skiplast = self.skiplast if curvesperhloop is None: curvesperhloop = self.curvesperhloop if sign is None: sign = self.sign if turnangle is None: turnangle = self.turnangle return cycloid(radius=radius, halfloops=halfloops, skipfirst=skipfirst, skiplast=skiplast, curvesperhloop=curvesperhloop, sign=sign, turnangle=turnangle) def deform(self, basepath): resultnormsubpaths = [self.deformsubpath(nsp) for nsp in basepath.normpath().normsubpaths] return normpath.normpath(resultnormsubpaths) def deformsubpath(self, normsubpath): skipfirst = abs(unit.topt(self.skipfirst)) skiplast = abs(unit.topt(self.skiplast)) radius = abs(unit.topt(self.radius)) turnangle = math.radians(self.turnangle) sign = mathutils.sign(self.sign) cosTurn = math.cos(turnangle) sinTurn = math.sin(turnangle) # make list of the lengths and parameters at points on normsubpath # where we will add cycloid-points totlength = normsubpath.arclen_pt() if totlength <= skipfirst + skiplast + 2*radius*sinTurn: logger.warning("normsubpath is too short for deformation with cycloid -- skipping...") return normsubpath # parameterization is in rotation-angle around the basepath # differences in length, angle ... between two basepoints # and between basepoints and controlpoints Dphi = math.pi / self.curvesperhloop phis = [i * Dphi for i in range(self.halfloops * self.curvesperhloop + 1)] DzDphi = (totlength - skipfirst - skiplast - 2*radius*sinTurn) * 1.0 / (self.halfloops * math.pi * cosTurn) # Dz = (totlength - skipfirst - skiplast - 2*radius*sinTurn) * 1.0 / (self.halfloops * self.curvesperhloop * cosTurn) # zs = [i * Dz for i in range(self.halfloops * self.curvesperhloop + 1)] # from path._arctobcurve: # optimal relative distance along tangent for second and third control point L = 4 * radius * (1 - math.cos(Dphi/2)) / (3 * math.sin(Dphi/2)) # Now the transformation of z into the turned coordinate system Zs = [ skipfirst + radius*sinTurn # here the coordinate z starts - sinTurn*radius*math.cos(phi) + cosTurn*DzDphi*phi # the transformed z-coordinate for phi in phis] params = normsubpath._arclentoparam_pt(Zs)[0] # get the positions of the splitpoints in the cycloid points = [] for phi, param in zip(phis, params): # the cycloid is a circle that is stretched along the normsubpath # here are the points of that circle basetrafo = normsubpath.trafo([param])[0] # The point on the cycloid, in the basepath's local coordinate system baseZ, baseY = 0, radius*math.sin(phi) # The tangent there, also in local coords tangentX = -cosTurn*radius*math.sin(phi) + sinTurn*DzDphi tangentY = radius*math.cos(phi) tangentZ = sinTurn*radius*math.sin(phi) + DzDphi*cosTurn norm = math.sqrt(tangentX*tangentX + tangentY*tangentY + tangentZ*tangentZ) tangentY, tangentZ = tangentY/norm, tangentZ/norm # Respect the curvature of the basepath for the cycloid's curvature # XXX this is only a heuristic, not a "true" expression for # the curvature in curved coordinate systems try: pathradius = 1/normsubpath.curvature_pt([param])[0] except ArithmeticError: factor = 1 else: factor = (pathradius - baseY) / pathradius factor = abs(factor) l = L * factor # The control points prior and after the point on the cycloid preeZ, preeY = baseZ - l * tangentZ, baseY - l * tangentY postZ, postY = baseZ + l * tangentZ, baseY + l * tangentY # Now put everything at the proper place points.append(basetrafo.apply_pt(preeZ, sign * preeY) + basetrafo.apply_pt(baseZ, sign * baseY) + basetrafo.apply_pt(postZ, sign * postY)) if len(points) <= 1: logger.warning("normsubpath is too short for deformation with cycloid -- skipping...") return normsubpath # Build the path from the pointlist # containing (control x 2, base x 2, control x 2) if skipfirst > normsubpath.epsilon: normsubpathitems = normsubpath.segments([0, params[0]])[0] normsubpathitems.append(normpath.normcurve_pt(*(points[0][2:6] + points[1][0:4]))) else: normsubpathitems = [normpath.normcurve_pt(*(points[0][2:6] + points[1][0:4]))] for i in range(1, len(points)-1): normsubpathitems.append(normpath.normcurve_pt(*(points[i][2:6] + points[i+1][0:4]))) if skiplast > normsubpath.epsilon: for nsp in normsubpath.segments([params[-1], len(normsubpath)]): normsubpathitems.extend(nsp.normsubpathitems) # That's it return normpath.normsubpath(normsubpathitems, epsilon=normsubpath.epsilon) # >>> cycloid.clear = attr.clearclass(cycloid) class cornersmoothed(baseclasses.deformer): # <<< """Bends corners in a normpath. This decorator replaces corners in a normpath with bezier curves. There are two cases: - If the corner lies between two lines, _two_ bezier curves will be used that are highly optimized to look good (their curvature is to be zero at the ends and has to have zero derivative in the middle). Additionally, it can controlled by the softness-parameter. - If the corner lies between curves then _one_ bezier is used that is (except in some special cases) uniquely determined by the tangents and curvatures at its end-points. In some cases it is necessary to use only the absolute value of the curvature to avoid a cusp-shaped connection of the new bezier to the old path. In this case the use of "obeycurv=0" allows the sign of the curvature to switch. - The radius argument gives the arclength-distance of the corner to the points where the old path is cut and the beziers are inserted. - Path elements that are too short (shorter than the radius) are skipped """ def __init__(self, radius, softness=1, obeycurv=0, relskipthres=0.01): self.radius = radius self.softness = softness self.obeycurv = obeycurv self.relskipthres = relskipthres def __call__(self, radius=None, softness=None, obeycurv=None, relskipthres=None): if radius is None: radius = self.radius if softness is None: softness = self.softness if obeycurv is None: obeycurv = self.obeycurv if relskipthres is None: relskipthres = self.relskipthres return cornersmoothed(radius=radius, softness=softness, obeycurv=obeycurv, relskipthres=relskipthres) def deform(self, basepath): return normpath.normpath([self.deformsubpath(normsubpath) for normsubpath in basepath.normpath().normsubpaths]) def deformsubpath(self, normsubpath): radius_pt = unit.topt(self.radius) epsilon = normsubpath.epsilon # remove too short normsubpath items (shorter than self.relskipthres*radius_pt or epsilon) pertinentepsilon = max(epsilon, self.relskipthres*radius_pt) pertinentnormsubpath = normpath.normsubpath(normsubpath.normsubpathitems, epsilon=pertinentepsilon) pertinentnormsubpath.flushskippedline() pertinentnormsubpathitems = pertinentnormsubpath.normsubpathitems # calculate the splitting parameters for the pertinentnormsubpathitems arclens_pt = [] params = [] for pertinentnormsubpathitem in pertinentnormsubpathitems: arclen_pt = pertinentnormsubpathitem.arclen_pt(epsilon) arclens_pt.append(arclen_pt) l1_pt = min(radius_pt, 0.5*arclen_pt) l2_pt = max(0.5*arclen_pt, arclen_pt - radius_pt) params.append(pertinentnormsubpathitem.arclentoparam_pt([l1_pt, l2_pt], epsilon)) # handle the first and last pertinentnormsubpathitems for a non-closed normsubpath if not normsubpath.closed: l1_pt = 0 l2_pt = max(0, arclens_pt[0] - radius_pt) params[0] = pertinentnormsubpathitems[0].arclentoparam_pt([l1_pt, l2_pt], epsilon) l1_pt = min(radius_pt, arclens_pt[-1]) l2_pt = arclens_pt[-1] params[-1] = pertinentnormsubpathitems[-1].arclentoparam_pt([l1_pt, l2_pt], epsilon) newnormsubpath = normpath.normsubpath(epsilon=normsubpath.epsilon) for i in range(len(pertinentnormsubpathitems)): this = i next = (i+1) % len(pertinentnormsubpathitems) thisparams = params[this] nextparams = params[next] thisnormsubpathitem = pertinentnormsubpathitems[this] nextnormsubpathitem = pertinentnormsubpathitems[next] thisarclen_pt = arclens_pt[this] nextarclen_pt = arclens_pt[next] # insert the middle segment newnormsubpath.append(thisnormsubpathitem.segments(thisparams)[0]) # insert replacement curves for the corners if next or normsubpath.closed: t1 = thisnormsubpathitem.rotation([thisparams[1]])[0].apply_pt(1, 0) t2 = nextnormsubpathitem.rotation([nextparams[0]])[0].apply_pt(1, 0) # TODO: normpath.invalid if (isinstance(thisnormsubpathitem, normpath.normline_pt) and isinstance(nextnormsubpathitem, normpath.normline_pt)): # case of two lines -> replace by two curves d1, g1, f1, e, f2, g2, d2 = curvescontrols_from_endlines_pt( thisnormsubpathitem.atend_pt(), t1, t2, thisarclen_pt*(1-thisparams[1]), nextarclen_pt*(nextparams[0]), softness=self.softness) p1 = thisnormsubpathitem.at_pt([thisparams[1]])[0] p2 = nextnormsubpathitem.at_pt([nextparams[0]])[0] newnormsubpath.append(normpath.normcurve_pt(*(d1 + g1 + f1 + e))) newnormsubpath.append(normpath.normcurve_pt(*(e + f2 + g2 + d2))) else: # generic case -> replace by a single curve with prescribed tangents and curvatures p1 = thisnormsubpathitem.at_pt([thisparams[1]])[0] p2 = nextnormsubpathitem.at_pt([nextparams[0]])[0] c1 = thisnormsubpathitem.curvature_pt([thisparams[1]])[0] c2 = nextnormsubpathitem.curvature_pt([nextparams[0]])[0] # TODO: normpath.invalid # TODO: more intelligent fallbacks: # circle -> line # circle -> circle if not self.obeycurv: # do not obey the sign of the curvature but # make the sign such that the curve smoothly passes to the next point # this results in a discontinuous curvature # (but the absolute value is still continuous) s1 = +mathutils.sign(t1[0] * (p2[1]-p1[1]) - t1[1] * (p2[0]-p1[0])) s2 = -mathutils.sign(t2[0] * (p2[1]-p1[1]) - t2[1] * (p2[0]-p1[0])) c1 = s1 * abs(c1) c2 = s2 * abs(c2) # get the length of the control "arms" controldists = controldists_from_endgeometry_pt(p1, p2, t1, t2, c1, c2) if controldists and (controldists[0][0] >= 0 and controldists[0][1] >= 0): # use the first entry in the controldists # this should be the "smallest" pair a, d = controldists[0] # avoid curves with invalid parameterization a = max(a, epsilon) d = max(d, epsilon) # avoid overshooting at the corners: # this changes not only the sign of the curvature # but also the magnitude if not self.obeycurv: t, s = intersection(p1, p2, t1, t2) if (t is not None and s is not None and t > 0 and s < 0): a = min(a, abs(t)) d = min(d, abs(s)) else: # use a fallback t, s = intersection(p1, p2, t1, t2) if t is not None and s is not None: a = 0.65 * abs(t) d = 0.65 * abs(s) else: # if there is no useful result: # take an arbitrary smoothing curve that does not obey # the curvature constraints dist = math.hypot(p1[0] - p2[0], p1[1] - p2[1]) a = dist / (3.0 * math.hypot(*t1)) d = dist / (3.0 * math.hypot(*t2)) # calculate the two missing control points q1 = p1[0] + a * t1[0], p1[1] + a * t1[1] q2 = p2[0] - d * t2[0], p2[1] - d * t2[1] newnormsubpath.append(normpath.normcurve_pt(*(p1 + q1 + q2 + p2))) if normsubpath.closed: newnormsubpath.close() return newnormsubpath # >>> cornersmoothed.clear = attr.clearclass(cornersmoothed) smoothed = cornersmoothed smoothed.clear = attr.clearclass(smoothed) class mynormpathparam(normpath.normpathparam): # <<< """In the parallel deformer we use properties such as the curvature, which are not continuous on a path (at points between normsubpathitems). We therefore require a better parameter class which really resolves the nsp-item """ # TODO: find reasonable values for these eps: rounding_eps = 1.0e-8 def __init__(self, np, normsubpathindex, normsubpathitemindex, normsubpathitemparam): normpath.normpathparam.__init__(self, np, normsubpathindex, normsubpathitemindex + normsubpathitemparam) self.normsubpathitemindex = normsubpathitemindex self.normsubpathitemparam = normsubpathitemparam self.beg_nspitem_known = False self.end_nspitem_known = False # guarantee that normpath.normpathparam always gets the correct item: if int(self.normsubpathparam) != self.normsubpathitemindex: if int(self.normsubpathparam) == self.normsubpathitemindex - 1: self.normsubpathparam = self.normsubpathitemindex + self.rounding_eps self.beg_nspitem_known = True elif int(self.normsubpathparam) == self.normsubpathitemindex + 1: self.normsubpathparam = (self.normsubpathitemindex + 1) - self.rounding_eps self.end_nspitem_known = True else: assert False assert int(self.normsubpathparam) == self.normsubpathitemindex #assert 0 <= self.normsubpathparam - self.normsubpathitemindex #assert 1 >= self.normsubpathparam - self.normsubpathitemindex def __str__(self): return "npp(%d, %d, %.3f)" % (self.normsubpathindex, self.normsubpathitemindex, self.normsubpathitemparam) def __eq__(self, other): if isinstance(other, mynormpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return (self.normsubpathindex, self.normsubpathitemindex, self.normsubpathitemparam) == (other.normsubpathindex, other.normsubpathitemindex, other.normsubpathitemparam) else: normpath.normpathparam.__eq__(self, other) def __lt__(self, other): if isinstance(other, mynormpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return (self.normsubpathindex, self.normsubpathitemindex, self.normsubpathitemparam) < (other.normsubpathindex, other.normsubpathitemindex, other.normsubpathitemparam) else: normpath.normpathparam.__eq__(self, other) def __hash__(self): return id(self) def smaller_equiv(self, epsilon=None): """Returns smaller equivalent parameter, if self is between two nsp-items""" if not self.is_beg_of_nspitem(epsilon): return self nsp = self.normpath[self.normsubpathindex] nspi_index = self.normsubpathitemindex - 1 nspi_param = 1 if nsp.closed: nspi_index = nspi_index % len(nsp) elif nspi_index < 0: nspi_index = 0 nspi_param = 0 other = mynormpathparam(self.normpath, self.normsubpathindex, nspi_index, nspi_param) if self.is_equiv(other, epsilon): return other return self def larger_equiv(self, epsilon=None): """Returns smaller equivalent parameter, if self is between two nsp-items""" if not self.is_end_of_nspitem(epsilon): return self nsp = self.normpath[self.normsubpathindex] nspi_index = self.normsubpathitemindex + 1 nspi_param = 0 if nsp.closed: nspi_index = nspi_index % len(nsp) elif nspi_index >= len(nsp): nspi_index = len(nsp) - 1 nspi_param = 1 other = mynormpathparam(self.normpath, self.normsubpathindex, nspi_index, nspi_param) if self.is_equiv(other, epsilon): return other return self def is_equiv(self, other, epsilon=None): """Test whether the two params yield essentially the same point""" assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" if self.normsubpathindex != other.normsubpathindex: return False nsp = self.normpath[self.normsubpathindex] if epsilon is None: epsilon = nsp.epsilon A, B = self.normpath.at_pt([self, other]) return math.hypot(A[0]-B[0], A[1]-B[1]) < epsilon def is_beg_of_nspitem(self, epsilon=None): if self.beg_nspitem_known: return True return self.is_equiv(mynormpathparam(self.normpath, self.normsubpathindex, self.normsubpathitemindex, 0), epsilon) def is_end_of_nspitem(self, epsilon=None): if self.end_nspitem_known: return True return self.is_equiv(mynormpathparam(self.normpath, self.normsubpathindex, self.normsubpathitemindex, 1), epsilon) def is_beg_of_nsp(self, epsilon=None): if self.normsubpathitemindex > 0: return False return self.is_equiv(mynormpathparam(self.normpath, self.normsubpathindex, 0, 0), epsilon) def is_end_of_nsp(self, epsilon=None): n = len(self.normpath[self.normsubpathindex]) - 1 if self.normsubpathitemindex < n: return False return self.is_equiv(mynormpathparam(self.normpath, self.normsubpathindex, n, 1), epsilon) # >>> def _length_pt(path, param1, param2): # <<< point1, point2 = path.at_pt([param1, param2]) return math.hypot(point1[0] - point2[0], point1[1] - point2[1]) # >>> class parallel(baseclasses.deformer): # <<< """creates a parallel normpath with constant distance to the original normpath A positive 'distance' results in a curve left of the original one -- and a negative 'distance' in a curve at the right. Left/right are understood in terms of the parameterization of the original curve. The construction of the paralel path is done in two steps: First, an "extended" parallel path is built. For each path element a parallel curve/line is constructed, which can be too long or too short, depending on the presence of corners. At corners, either a circular arc is drawn around the corner, or, if possible, the parallel curve is cut in order to also exhibit a corner. In a second step all self-intersection points are determined and unnecessary parts of the path are cut away. distance: the distance of the parallel normpath relerr: distance*relerr is the maximal allowed error in the parallel distance sharpoutercorners: make the outer corners not round but sharp. The inner corners (corners after inflection points) will stay round dointersection: boolean for doing the intersection step (default: 1). Set this value to 0 if you want the whole parallel path checkdistanceparams: a list of parameter values in the interval (0,1) where the parallel distance is checked on each normpathitem lookforcurvatures: number of points per normpathitem where is looked for a critical value of the curvature """ # TODO: # * DECIDE MEANING of arcs around corners (see case L in test/functional/test_deformer.py) # * eliminate double, triple, ... pairs # * implement self-intersection of normcurve_pt # * implement _between_paths also for normcurve_pt def __init__(self, distance, relerr=0.05, sharpoutercorners=False, dointersection=True, checkdistanceparams=[0.5], lookforcurvatures=11, searchstep=0.01, debug=None): self.distance = distance self.relerr = relerr self.sharpoutercorners = sharpoutercorners self.checkdistanceparams = checkdistanceparams self.lookforcurvatures = lookforcurvatures self.dointersection = dointersection self.searchstep = searchstep self.debug = debug def __call__(self, distance=None, relerr=None, sharpoutercorners=None, dointersection=None, checkdistanceparams=None, lookforcurvatures=None, searchstep=None, debug=None): # returns a copy of the deformer with different parameters if distance is None: distance = self.distance if relerr is None: relerr = self.relerr if sharpoutercorners is None: sharpoutercorners = self.sharpoutercorners if dointersection is None: dointersection = self.dointersection if checkdistanceparams is None: checkdistanceparams = self.checkdistanceparams if lookforcurvatures is None: lookforcurvatures = self.lookforcurvatures if searchstep is None: searchstep = self.searchstep if debug is None: debug = self.debug return parallel(distance=distance, relerr=relerr, sharpoutercorners=sharpoutercorners, dointersection=dointersection, checkdistanceparams=checkdistanceparams, lookforcurvatures=lookforcurvatures, searchstep=searchstep, debug=debug) def deform(self, basepath): basepath = basepath.normpath() self.dist_pt = unit.topt(self.distance) resultnormsubpaths = [] par_to_orig = {} for nsp in basepath.normsubpaths: parallel_normpath, tmp1, tmp2, par2orig = self.deformsubpath(nsp) resultnormsubpaths += parallel_normpath.normsubpaths for key in par2orig: par_to_orig[key] = par2orig[key] result = normpath.normpath(resultnormsubpaths) if self.dointersection: result = self.rebuild_intersected_normpath(result, basepath, par_to_orig) return result def deformsubpath(self, orig_nsp): # <<< """Performs the first step of the deformation: Returns a list of normsubpaths building the parallel to the given normsubpath. Then calls the intersection routine to do the second step.""" # the default case is not to join the result. dist = self.dist_pt epsilon = orig_nsp.epsilon assert len(orig_nsp.normsubpathitems) != 0 # avoid too small dists: we would run into instabilities if abs(dist) < abs(epsilon): assert orig_nsp.normsubpathitems par_to_orig = {} for nspitem in orig_nsp: par_to_orig[nspitem] = nspitem return normpath.normpath([orig_nsp]), None, None, par_to_orig result = None par_to_orig = None join_begin = None prev_joinend = None # iterate over the normsubpath in the following way: # * for each item first append the additional arc # and then add the next parallel piece # * for the first item only add the parallel piece # (because this is done for curr_orig_nspitem, we need to start with i=0) for i in range(len(orig_nsp.normsubpathitems)): prev_orig_nspitem = orig_nsp.normsubpathitems[i-1] curr_orig_nspitem = orig_nsp.normsubpathitems[i] # get the next parallel piece for the normpath next_parallel_normpath, joinbeg, joinend, par2orig = self.deformsubpathitem(curr_orig_nspitem, epsilon) if result is None: if join_begin is None: join_begin = joinbeg else: join_begin = (join_begin and joinbeg) if not (next_parallel_normpath.normsubpaths and next_parallel_normpath[0].normsubpathitems): if prev_joinend is None: prev_joinend = joinend else: prev_joinend = (prev_joinend and joinend) continue # this starts the whole normpath if result is None: result = next_parallel_normpath par_to_orig = {} for key in par2orig: par_to_orig[key] = par2orig[key] prev_joinend = joinend continue # there is nothing to join prev_tangent, next_tangent, is_straight, is_concave = self._get_angles(prev_orig_nspitem, curr_orig_nspitem, epsilon) if not (joinbeg and prev_joinend): # split due to loo large curvature result += next_parallel_normpath elif is_straight: # The path is quite straight between prev and next item: # normpath.normpath.join adds a straight line if necessary result.join(next_parallel_normpath) else: # The parallel path can be extended continuously. # We must add a corner or an arc around the corner: cornerpath = self._path_around_corner(curr_orig_nspitem.atbegin_pt(), result.atend_pt(), next_parallel_normpath.atbegin_pt(), prev_tangent, next_tangent, is_concave, epsilon) result.join(cornerpath) assert len(cornerpath) == 1 corner = curr_orig_nspitem.atbegin_pt() for cp_nspitem in cornerpath[0]: par_to_orig[cp_nspitem] = corner # append the next parallel piece to the path result.join(next_parallel_normpath) for key in par2orig: par_to_orig[key] = par2orig[key] prev_joinend = joinend # end here if nothing has been found so far if result is None: return normpath.normpath(), False, False, {} # the curve around the closing corner may still be missing if orig_nsp.closed: prev_tangent, next_tangent, is_straight, is_concave = self._get_angles(orig_nsp.normsubpathitems[-1], orig_nsp.normsubpathitems[0], epsilon) if not (joinend and join_begin): # do not close because of infinite curvature do_close = False elif is_straight: # The path is quite straight at end and beginning do_close = True else: # The parallel path can be extended continuously. do_close = True # We must add a corner or an arc around the corner: cornerpath = self._path_around_corner(orig_nsp.atend_pt(), result.atend_pt(), result.atbegin_pt(), prev_tangent, next_tangent, is_concave, epsilon) result.join(cornerpath) corner = orig_nsp.atend_pt() assert len(cornerpath) == 1 for cp_nspitem in cornerpath[0]: par_to_orig[cp_nspitem] = corner if do_close: if len(result) == 1: result[0].close() else: # if the parallel normpath is split into several subpaths anyway, # then use the natural beginning and ending # closing is not possible anymore for nspitem in result[0]: result[-1].append(nspitem) result.normsubpaths = result.normsubpaths[1:] join_begin, joinend = False, False return result, join_begin, joinend, par_to_orig # >>> def deformsubpathitem(self, nspitem, epsilon): # <<< """Returns a parallel normpath for a single normsubpathitem Analyzes the curvature of a normsubpathitem and returns a normpath with the appropriate number of normsubpaths. This must be a normpath because a normcurve can be strongly curved, such that the parallel path must contain a hole""" # the default case is to join the result. Only if there was an infinite # curvature at beginning/end, we return info not to join it. dist = self.dist_pt # for a simple line we return immediately if isinstance(nspitem, normpath.normline_pt): normal = nspitem.rotation([0])[0].apply_pt(0, 1) start = nspitem.atbegin_pt() end = nspitem.atend_pt() result = path.line_pt(start[0] + dist * normal[0], start[1] + dist * normal[1], end[0] + dist * normal[0], end[1] + dist * normal[1]).normpath(epsilon=epsilon) assert len(result) == 1 and len(result[0]) == 1 return result, True, True, {result[0][0]:nspitem} # for a curve we have to check if the curvatures # cross the singular value 1/dist crossings = list(self._distcrossingparameters(nspitem, epsilon)) crossings.sort() # depending on the number of crossings we must consider # three different cases: if crossings: # The curvature crosses the borderline 1/dist # the parallel curve contains points with infinite curvature! parallcurvs = [inf_curvature]*len(crossings) result = normpath.normpath() join_begin, join_end = False, False par_to_orig = {} # we need the endpoints of the nspitem if _length_pt(nspitem, crossings[0], 0) > epsilon: crossings.insert(0, 0) parallcurvs.insert(0, None) if _length_pt(nspitem, crossings[-1], 1) > epsilon: crossings.append(1) parallcurvs.append(None) for i in range(len(crossings) - 1): middleparam = 0.5*(crossings[i] + crossings[i+1]) middlecurv = nspitem.curvature_pt([middleparam])[0] # the radius is good if # - middlecurv and dist have opposite signs : distance vector points "out" of the original curve # - middlecurv is "smaller" than 1/dist : original curve is less curved than +-1/dist if dist*middlecurv < 0 or abs(dist*middlecurv) < 1: if i == 0: join_begin = True elif i == len(crossings) - 2: join_end = True parallel_nsp, par2orig = self.deformnicecurve(nspitem.segments(crossings[i:i+2])[0], epsilon, curvA=parallcurvs[i], curvD=parallcurvs[i+1]) # never append empty normsubpaths if parallel_nsp.normsubpathitems: # infinite curvatures interrupt the path and start a new nsp result.append(parallel_nsp) for key in par2orig: par_to_orig[key] = par2orig[key] if not (result.normsubpaths and result[0].normsubpathitems): return normpath.normpath(), True, True, {} return result, join_begin, join_end, par_to_orig # the curvature is either bigger or smaller than 1/dist middlecurv = nspitem.curvature_pt([0.5])[0] if dist*middlecurv < 0 or abs(dist*middlecurv) < 1: # The curve is everywhere less curved than 1/dist # We can proceed finding the parallel curve for the whole piece parallel_nsp, par2orig = self.deformnicecurve(nspitem, epsilon) # never append empty normsubpaths if parallel_nsp.normsubpathitems: par_to_orig = {} for key in par2orig: par_to_orig[key] = par2orig[key] return normpath.normpath([parallel_nsp]), True, True, par_to_orig # the curve is everywhere stronger curved than 1/dist # There is nothing to be returned. return normpath.normpath(), False, False, {} # >>> def deformnicecurve(self, normcurve, epsilon, startparam=0.0, endparam=1.0, curvA=None, curvD=None): # <<< """Returns a parallel normsubpath for the normcurve. This routine assumes that the normcurve is everywhere 'less' curved than 1/dist. Only at the ends, the curvature can be exactly +-1/dist, which is marked by curvA and/or curvD. """ dist = self.dist_pt # normalized tangent directions tangA, tangD = normcurve.rotation([startparam, endparam]) tangA = tangA.apply_pt(1, 0) tangD = tangD.apply_pt(1, 0) # the new starting points orig_A, orig_D = normcurve.at_pt([startparam, endparam]) A = orig_A[0] - dist * tangA[1], orig_A[1] + dist * tangA[0] D = orig_D[0] - dist * tangD[1], orig_D[1] + dist * tangD[0] # we need to end this _before_ we will run into epsilon-problems # when creating curves we do not want to calculate the length of # or even split it for recursive calls if (math.hypot(A[0] - D[0], A[1] - D[1]) < epsilon and abs(dist)*(tangA[0]*tangD[1] - tangA[1]*tangD[0]) < epsilon): nl = normpath.normline_pt(A[0], A[1], D[0], D[1]) return normpath.normsubpath([nl]), {nl:normcurve} result = normpath.normsubpath(epsilon=epsilon) # is there enough space on the normals before they intersect? a, d = intersection(orig_A, orig_D, (-tangA[1], tangA[0]), (-tangD[1], tangD[0])) # a,d are the lengths to the intersection points: # for a (and equally for b) we can proceed in one of the following cases: # a is None (means parallel normals) # a and dist have opposite signs (and the same for b) # a has the same sign but is bigger if ( (a is None or a*dist < 0 or abs(a) > abs(dist) + epsilon) or (d is None or d*dist < 0 or abs(d) > abs(dist) + epsilon) ): # the original path is long enough to draw a parallel piece # this is the generic case. Get the parallel curves orig_curvA, orig_curvD = normcurve.curvature_pt([startparam, endparam]) if curvA is None: curvA = orig_curvA / (1.0 - dist*orig_curvA) if curvD is None: curvD = orig_curvD / (1.0 - dist*orig_curvD) # first try to approximate the normcurve with a single item controldistpairs = controldists_from_endgeometry_pt(A, D, tangA, tangD, curvA, curvD) if controldistpairs: # TODO: is it good enough to get the first entry here? # from testing: this fails if there are loops in the original curve a, d = controldistpairs[0] if a >= 0 and d >= 0: # we avoid to create curves with invalid parameterization if a < epsilon and d < epsilon: result = normpath.normsubpath([normpath.normline_pt(A[0], A[1], D[0], D[1])], epsilon=epsilon) else: a = max(a, epsilon) d = max(d, epsilon) result = normpath.normsubpath([normpath.normcurve_pt( A[0], A[1], A[0] + a * tangA[0], A[1] + a * tangA[1], D[0] - d * tangD[0], D[1] - d * tangD[1], D[0], D[1])], epsilon=epsilon) # then try with two items, recursive call if ((not result.normsubpathitems) or (self.checkdistanceparams and result.normsubpathitems and not self._distchecked(normcurve, result, epsilon, startparam, endparam))): # TODO: does this ever converge? # TODO: what if this hits epsilon? middleparam = 0.5*(startparam + endparam) firstnsp, first_par2orig = self.deformnicecurve(normcurve, epsilon, startparam, middleparam, curvA, None) secondnsp, second_par2orig = self.deformnicecurve(normcurve, epsilon, middleparam, endparam, None, curvD) if not (firstnsp.normsubpathitems and secondnsp.normsubpathitems): result = normpath.normsubpath( [normpath.normline_pt(A[0], A[1], D[0], D[1])], epsilon=epsilon) else: result = firstnsp.joined(secondnsp) par_to_orig = {} for key in result: par_to_orig[key] = normcurve return result, par_to_orig # >>> def _path_around_corner(self, corner_pt, beg_pt, end_pt, beg_tangent, end_tangent, is_concave, epsilon): # <<< """Helper routine for parallel.deformsubpath: Draws an arc around a convex corner""" if self.sharpoutercorners and not is_concave: # straight lines: t1, t2 = intersection(beg_pt, end_pt, beg_tangent, end_tangent) B = beg_pt[0] + t1 * beg_tangent[0], beg_pt[1] + t1 * beg_tangent[1] return normpath.normpath([normpath.normsubpath([ normpath.normline_pt(beg_pt[0], beg_pt[1], B[0], B[1]), normpath.normline_pt(B[0], B[1], end_pt[0], end_pt[1]) ])]) # We append an arc around the corner # these asserts fail in test case "E" #assert abs(math.hypot(beg_pt[1] - corner_pt[1], beg_pt[0] - corner_pt[0]) - abs(self.dist_pt)) < epsilon #assert abs(math.hypot(end_pt[1] - corner_pt[1], end_pt[0] - corner_pt[0]) - abs(self.dist_pt)) < epsilon angle1 = math.atan2(beg_pt[1] - corner_pt[1], beg_pt[0] - corner_pt[0]) angle2 = math.atan2(end_pt[1] - corner_pt[1], end_pt[0] - corner_pt[0]) # depending on the direction we have to use arc or arcn sinangle = beg_tangent[0]*end_tangent[1] - beg_tangent[1]*end_tangent[0] # >0 for left-turning, <0 for right-turning if self.dist_pt > 0: arcclass = path.arcn_pt else: arcclass = path.arc_pt return path.path(arcclass( corner_pt[0], corner_pt[1], abs(self.dist_pt), math.degrees(angle1), math.degrees(angle2))).normpath(epsilon=epsilon) # >>> def _distchecked(self, orig_normcurve, parallel_normsubpath, epsilon, tstart, tend): # <<< """Helper routine for parallel.deformnicecurve: Checks the distances between orig_normcurve and parallel_normsubpath. The checking is done at parameters self.checkdistanceparams of orig_normcurve.""" dist = self.dist_pt # do not look closer than epsilon: dist_err = mathutils.sign(dist) * max(abs(self.relerr*dist), epsilon) checkdistanceparams = [tstart + (tend-tstart)*t for t in self.checkdistanceparams] for param, P, rotation in zip(checkdistanceparams, orig_normcurve.at_pt(checkdistanceparams), orig_normcurve.rotation(checkdistanceparams)): normal = rotation.apply_pt(0, 1) # create a short cutline for intersection only: cutline = normpath.normsubpath([normpath.normline_pt( P[0] + (dist - 2*dist_err) * normal[0], P[1] + (dist - 2*dist_err) * normal[1], P[0] + (dist + 2*dist_err) * normal[0], P[1] + (dist + 2*dist_err) * normal[1])], epsilon=epsilon) cutparams = parallel_normsubpath.intersect(cutline) distances = [math.hypot(P[0] - cutpoint[0], P[1] - cutpoint[1]) for cutpoint in cutline.at_pt(cutparams[1])] if (not distances) or (abs(min(distances) - abs(dist)) > abs(dist_err)): return False return True # >>> def _distcrossingparameters(self, normcurve, epsilon, tstart=0, tend=1): # <<< """Helper routine for parallel.deformsubpathitem: Returns a list of parameters where the curvature of normcurve is 1/distance""" assert tstart < tend dist = self.dist_pt # we _need_ to do this with the curvature, not with the radius # because the curvature is continuous at the straight line and the radius is not: # when passing from one slightly curved curve to the other with opposite curvature sign, # via the straight line, then the curvature changes its sign at curv=0, while the # radius changes its sign at +/-infinity # this causes instabilities for nearly straight curves # include tstart and tend params = [tstart + i * (tend - tstart) / (self.lookforcurvatures - 1.0) for i in range(self.lookforcurvatures)] curvs = normcurve.curvature_pt(params) parampairs = list(zip(params[:-1], params[1:])) curvpairs = list(zip(curvs[:-1], curvs[1:])) crossingparams = set() for parampair, curvpair in zip(parampairs, curvpairs): begparam, endparam = parampair begcurv, endcurv = curvpair begchange = begcurv*dist - 1 endchange = endcurv*dist - 1 if begchange*endchange < 0: # the curvature crosses the value 1/dist # get the parmeter value by linear interpolation: middleparam = ( (begparam * abs(begchange) + endparam * abs(endchange)) / (abs(begchange) + abs(endchange))) try: middleradius = 1/normcurve.curvature_pt([middleparam])[0] except ArithmeticError: raise InvalidParamException(middleparam) if abs(middleradius - dist) < epsilon or endparam-begparam < 1.0e-14: # get the parmeter value by linear interpolation: crossingparams.add(middleparam) else: # call recursively: for x in self._distcrossingparameters(normcurve, epsilon, tstart=begparam, tend=endparam): crossingparams.add(x) else: if begchange == 0: crossingparams.add(begparam) if endchange == 0: crossingparams.add(endparam) return crossingparams # >>> def _get_angles(self, prev_nspitem, next_nspitem, epsilon): # <<< prev_rotation = prev_nspitem.rotation([1])[0] next_rotation = next_nspitem.rotation([0])[0] prev_tangent = prev_rotation.apply_pt(1, 0) prev_orthogo = prev_rotation.apply_pt(0, self.dist_pt) # points towards parallel path (prev_nspitem is on original path) next_tangent = next_rotation.apply_pt(1, 0) #sinangle = prev_tangent[0]*next_tangent[1] - prev_tangent[1]*next_tangent[0] # >0 for left-turning, <0 for right-turning cosangle = prev_tangent[0]*next_tangent[0] + prev_tangent[1]*next_tangent[1] proj = prev_orthogo[0]*next_tangent[0] + prev_orthogo[1]*next_tangent[1] is_straight = (cosangle > 0 and abs(proj) < epsilon) is_concave = (proj > 0) return prev_tangent, next_tangent, is_straight, is_concave # >>> def rebuild_intersected_normpath(self, par_np, orig_np, par2orig, epsilon=None): # <<< dist = self.dist_pt if epsilon is None: epsilon = orig_np.normsubpaths[0].epsilon eps_comparepairs = 10*epsilon # calculate the self-intersections of the par_np forwardpairs, backwardpairs = self.normpath_selfintersections(par_np, epsilon, eps_comparepairs) # calculate the intersections of the par_np with the original path origintparams, orig_origintparams = self.normpath_origintersections(orig_np, par_np, epsilon) if not forwardpairs: if origintparams: return normpath.normpath() else: return par_np # parameters at begin and end of subnormpaths: # omit those which start/end on the original path beginparams = [] endparams = [] testparams = origintparams + list(forwardpairs.keys()) + list(forwardpairs.values()) for i, nsp in enumerate(par_np): beginparam = mynormpathparam(par_np, i, 0, 0) is_new = True for param in testparams: if beginparam.is_equiv(param): is_new = False break if is_new: beginparams.append(beginparam) endparam = mynormpathparam(par_np, i, len(nsp)-1, 1) is_new = True for param in testparams: if endparam.is_equiv(param): is_new = False break if is_new: endparams.append(endparam) beginparams.sort() endparams.sort() # we need a way to get the "next" param on the normpath # XXX why + beginparams + endparams ? allparams = list(forwardpairs.keys()) + list(backwardpairs.keys()) + origintparams + beginparams + endparams allparams.sort() done = {} for param in allparams: done[param] = False nextp = {} for i, param in enumerate(allparams[:-1]): nextp[param] = allparams[i+1] for endparam in endparams: if par_np[endparam.normsubpathindex].closed: begparam = [p for p in allparams if p.normsubpathindex == endparam.normsubpathindex][0] assert begparam.normsubpathitemindex == 0 assert begparam.normsubpathitemparam == 0 nextp[endparam] = begparam else: nextp[endparam] = None # exclude all intersections that are between the original and the parallel path: # See for example test/functional/test_deformer (parallel Z): There can # remain a little piece of the path (triangle) that lies between a lot # of intersection points. Simple intersection rules such as thoe in # trial_parampairs cannot exclude this piece. for param in forwardpairs: if done[param] or done[forwardpairs[param]]: done[param] = done[forwardpairs[param]] = True elif self._between_paths(par_np.at_pt(param), par2orig, 4*epsilon): done[param] = done[forwardpairs[param]] = True for param in beginparams + endparams: if self._between_paths(par_np.at_pt(param), par2orig, 4*epsilon): done[param] = True # visualize the intersection points: # <<< if self.debug is not None: for param1, param2 in forwardpairs.items(): point1, point2 = par_np.at([param1, param2]) if not done[param1]: self.debug.fill(path.circle(point1[0], point1[1], 0.05), [color.rgb.red]) if not done[param2]: self.debug.fill(path.circle(point2[0], point2[1], 0.03), [color.rgb.black]) for param in origintparams: #assert done[param] point = par_np.at([param])[0] self.debug.fill(path.circle(point[0], point[1], 0.05), [color.rgb.green]) for i, nsp in enumerate(par_np): for j, nspi in enumerate(nsp): x, y = nspi.at_pt([0.5])[0] self.debug.text_pt(x, y, "{}/{}".format(i,j))#, [text.halign.center, text.vshift.mathaxis]) print("aborted path intersection due to debug") return par_np # >>> def ptype(param): # <<< if param in forwardpairs : return "fw with partner %s" % (forwardpairs[param]) if param in backwardpairs : return "bw with partner %s" % (backwardpairs[param]) if param in origintparams: return "orig" if param in beginparams: return "begin" if param in endparams: return "end" # >>> def trial_parampairs(startp): # <<< """Starting at startp, try to find a valid series of intersection parameters""" tried = {} # a local copy of done for param in allparams: tried[param] = done[param] previousp = startp currentp = nextp[previousp] result = [] while True: # successful and unsuccessful termination conditions: if tried[currentp]: # we reached a branch that has already been treated # ==> this is not a valid parallel path return [] if currentp in origintparams: # we cross the original path # ==> this is not a valid parallel path return [] if currentp in backwardpairs: # we reached a branch that should be followed from another part # ==> this is not a valid parallel path return [] if currentp is startp: # we have reached again the starting point on a closed subpath. assert startp in beginparams assert previousp in endparams return result if currentp in forwardpairs: result.append((previousp, currentp)) if forwardpairs[currentp] is startp: # we have found the same point as the startp (its pair partner) return result previousp = forwardpairs[currentp] if currentp in endparams: result.append((previousp, currentp)) if nextp[currentp] is None: # open subpath # we have found the end of a non-closed subpath return result previousp = currentp # closed subpath # follow the crossings on valid startpairs tried[currentp] = True tried[previousp] = True currentp = nextp[previousp] assert False # never reach this point # >>> # first the paths that start at the beginning of a subnormpath: result = normpath.normpath() # paths can start on subnormpaths or crossings where we can "get away": bwkeys = list(backwardpairs.keys()) bwkeys.sort() for startp in beginparams + bwkeys: if done[startp]: continue # try to find a valid series of intersection points: parampairs = trial_parampairs(startp) if not parampairs: continue # collect all the pieces between parampairs: add_nsp = normpath.normsubpath(epsilon=epsilon) for begin, end in parampairs: # check that trial_parampairs works correctly assert begin is not end for item in par_np[begin.normsubpathindex].segments( [begin.normsubpathparam, end.normsubpathparam])[0].normsubpathitems: # TODO: this should be obsolete with an improved intersection algorithm # guaranteeing epsilon if add_nsp.normsubpathitems: item = item.modifiedbegin_pt(*(add_nsp.atend_pt())) add_nsp.append(item) done[begin] = True done[end] = True # close the path if necessary if add_nsp: if ((parampairs[-1][-1] in forwardpairs and forwardpairs[parampairs[-1][-1]] is parampairs[0][0]) or (parampairs[-1][-1] in endparams and parampairs[0][0] in beginparams and parampairs[0][0] is nextp[parampairs[-1][-1]])): add_nsp.normsubpathitems[-1] = add_nsp.normsubpathitems[-1].modifiedend_pt(*add_nsp.atbegin_pt()) add_nsp.close() result.extend([add_nsp]) return result # >>> def normpath_selfintersections(self, np, epsilon, eps_comparepairs): # <<< """Returns all self-intersection points of normpath np. This does not include the intersections of a single normcurve with itself, but all intersections of one normpathitem with a different one in the path. The intersection pairs are such that the parallel path can be continued from the first to the second parameter, but not vice-versa.""" dist = self.dist_pt n = len(np) forwardpairs = {} for nsp_i in range(n): for nsp_j in range(nsp_i, n): for nspitem_i in range(len(np[nsp_i])): if nsp_j == nsp_i: nspitem_j_range = list(range(nspitem_i+1, len(np[nsp_j]))) else: nspitem_j_range = list(range(len(np[nsp_j]))) for nspitem_j in nspitem_j_range: intsparams = np[nsp_i][nspitem_i].intersect(np[nsp_j][nspitem_j], epsilon) if intsparams: for intsparam_i, intsparam_j in intsparams: npp_i = mynormpathparam(np, nsp_i, nspitem_i, intsparam_i) npp_j = mynormpathparam(np, nsp_j, nspitem_j, intsparam_j) # skip successive nsp-items if nsp_i == nsp_j: if nspitem_j == nspitem_i+1 and (npp_i.is_end_of_nspitem(epsilon) or npp_j.is_beg_of_nspitem(epsilon)): continue if np[nsp_i].closed and ((npp_i.is_beg_of_nsp(epsilon) and npp_j.is_end_of_nsp(epsilon)) or (npp_j.is_beg_of_nsp(epsilon) and npp_i.is_end_of_nsp(epsilon))): continue # correct the order of the pair, such that we can use it to continue on the path if not self._can_continue(npp_i, npp_j, epsilon): assert self._can_continue(npp_j, npp_i, epsilon) npp_i, npp_j = npp_j, npp_i # if the intersection is between two nsp-items, take the smallest -> largest npp_i = npp_i.smaller_equiv(5*epsilon) npp_j = npp_j.larger_equiv(5*epsilon) # because of the above change of npp_ij, and because there may be intersections between nsp-items, # it may happen that we try to insert two times the same pair if self._skip_intersection_doublet(npp_i, npp_j, forwardpairs, eps_comparepairs): continue forwardpairs[npp_i] = npp_j # this is partially done in _skip_intersection_doublet #forwardpairs = self._elim_intersection_doublets(forwardpairs, eps_comparepairs) # create the reverse mapping backwardpairs = {} for p, q in forwardpairs.items(): backwardpairs[q] = p return forwardpairs, backwardpairs # >>> def normpath_origintersections(self, orig_np, par_np, epsilon): # <<< """return all intersection points of the original path and the parallel path""" # this code became necessary with introduction of mynormpathparam params = [] oparams = [] for nsp_i in range(len(orig_np)): for nsp_j in range(len(par_np)): for nspitem_i in range(len(orig_np[nsp_i])): for nspitem_j in range(len(par_np[nsp_j])): intsparams = orig_np[nsp_i][nspitem_i].intersect(par_np[nsp_j][nspitem_j], epsilon) if intsparams: for intsparam_i, intsparam_j in intsparams: npp_i = mynormpathparam(orig_np, nsp_i, nspitem_i, intsparam_i) npp_j = mynormpathparam(par_np, nsp_j, nspitem_j, intsparam_j) oparams.append(npp_i) params.append(npp_j) return params, oparams # >>> def _can_continue(self, param1, param2, epsilon=None): # <<< """Test whether the parallel path can be continued at the param-pair (param1, param2)""" par_np = param1.normpath if epsilon is None: epsilon = par_np[0].epsilon rot1, rot2 = par_np.rotation([param1, param2]) orth1 = rot1.apply_pt(0, self.dist_pt) # directs away from original path (as seen from parallel path) tang2 = rot2.apply_pt(1, 0) # the self-intersection is valid if the tangents # point into the correct direction or, for parallel tangents, # if the curvature is such that the on-going path does not # enter the region defined by dist proj = orth1[0]*tang2[0] + orth1[1]*tang2[1] if abs(proj) > epsilon: # the curves are not parallel # tang2 must go away from the original path return (proj > 0) # tang1 and tang2 are parallel. curv1, curv2 = par_np.curvature_pt([param1, param2]) # We need to treat also cases where the params are nspitem-endpoints. # There, we know that the tangents are continuous, but the curvature is # not necessarily continuous. We have to test whether the curve *after* # param2 has curvature such that it enters the forbidden side of the # curve after param1 if param1.is_end_of_nspitem(epsilon): curv1 = par_np.curvature_pt([param1.larger_equiv(epsilon)])[0] if param2.is_end_of_nspitem(epsilon): curv2 = par_np.curvature_pt([param2.larger_equiv(epsilon)])[0] tang1 = rot1.apply_pt(1, 0) running_back = (tang1[0]*tang2[0] + tang1[1]*tang2[1] < 0) if running_back: # the second curve is running "back" -- the curvature sign appears to be switched curv2 = -curv2 # endpoints of normsubpaths must be treated differently: if (not running_back) and param1.is_end_of_nsp(epsilon): return True if curv1 == curv2: raise IntersectionError("Cannot determine whether curves intersect (parallel and equally curved)") if self.dist_pt > 0: return (curv2 > curv1) else: return (curv2 < curv1) # >>> def _skip_intersection_doublet(self, npp_i, npp_j, parampairs, epsilon): # <<< # An intersection point that lies exactly between two nsp-items can occur twice or more # times if we calculate all mutual intersections. We should take only # one such parameter pair, namely the one with smallest first and # largest last param. result = False delete_keys = [] delete_values = [] # TODO: improve complexity? for pi, pj in parampairs.items(): if npp_i.is_equiv(pi, epsilon) and npp_j.is_equiv(pj, epsilon): #print("double pair: ", npp_i, npp_j, pi, pj) #print("... replacing ", pi, parampairs[pi], "by", min(npp_i, pi), max(npp_j, pj)) delete_keys.append(pi) delete_values.append(pj) result = True # we have already added this one newkey = min([npp_i] + delete_keys) newval = max([npp_j] + delete_values) for pi in delete_keys: del parampairs[pi] parampairs[newkey] = newval return result # >>> def _elim_intersection_doublets(self, parampairs, epsilon): # <<< # It may always happen that three intersections coincide. (It will # occur often with degenerate distances for technical designs such as # those used in microfluidics). We then have two equivalent pairs in our # forward list, and we must throw away one of them. # One of them is indeed forbidden by the _can_continue of the other. # TODO implement this keys = list(parampairs.keys()) n = len(keys) for i in range(n): start = "equivalent pairs\n" for j in range(i+1, n): key1, key2 = keys[i], keys[j] npp1 = parampairs[key1] npp2 = parampairs[key2] #assert key1.is_equiv(npp1, epsilon) #if not key2.is_equiv(npp2, epsilon): # np = key2.normpath # print(np.at_pt(key2), np.at_pt(npp2), _length_pt(np, key2, npp2)/epsilon) #assert key2.is_equiv(npp2, epsilon) if ((key1.is_equiv(key2, epsilon) and npp1.is_equiv(npp2, epsilon)) or (key1.is_equiv(npp2, epsilon) and npp1.is_equiv(key2, epsilon))): print(start,"pair: ", key1, npp1, " and ", key2, npp2) start = "" if not start: print() return parampairs # >>> def _between_paths(self, pos, par2orig, epsilon): # <<< """Tests whether the given point (pos) is found in the forbidden zone between an original and a parallel nsp-item (these are in par2orig) The test uses epsilon close to the original/parallel path, and sharp comparison at their ends.""" dist = self.dist_pt for par_nspitem in par2orig: origobj = par2orig[par_nspitem] if isinstance(origobj, normpath.normline_pt): rot = origobj.rotation([0])[0] t, s = intersection(pos, origobj.atbegin_pt(), rot.apply_pt(0, mathutils.sign(dist)), rot.apply_pt(origobj.arclen_pt(epsilon), 0)) if 0 <= s <= 1 and -abs(dist)+epsilon < t < -epsilon: return True elif isinstance(origobj, normpath.normcurve_pt): # TODO: implement this # TODO: pre-sort par2orig as a list to fasten up this code pass else: cx, cy = origobj if math.hypot(pos[0]-cx, pos[1]-cy) < abs(dist) - epsilon: if self.dist_pt > 0: # running around (cx,cy) in the negative sense (see _path_around_corner) x0, y0 = par_nspitem.atend_pt() x1, y1 = par_nspitem.atbegin_pt() else: # running around (cx,cy) in the positive sense x0, y0 = par_nspitem.atbegin_pt() x1, y1 = par_nspitem.atend_pt() t0, s0 = intersection(pos, (cx, cy), (-y0+cy, x0-cx), (x0-cx, y0-cy)) t1, s1 = intersection(pos, (cx, cy), ( y1-cy,-x1+cx), (x1-cx, y1-cy)) if t0 <= 0 and s0 >= 0 and t1 <= 0 and s1 >= 0: return True return False # >>> # >>> parallel.clear = attr.clearclass(parallel) class linesmoothed(baseclasses.deformer): # <<< def __init__(self, tension=1, atleast=False, lcurl=1, rcurl=1): """Tension and atleast control the tension of the replacement curves. l/rcurl control the curlynesses at (possible) endpoints. If a curl is set to None, the angle is taken from the original path.""" if atleast: self.tension = -abs(tension) else: self.tension = abs(tension) self.lcurl = lcurl self.rcurl = rcurl def __call__(self, tension=_marker, atleast=_marker, lcurl=_marker, rcurl=_marker): if tension is _marker: tension = self.tension if atleast is _marker: atleast = (self.tension < 0) if lcurl is _marker: lcurl = self.lcurl if rcurl is _marker: rcurl = self.rcurl return linesmoothed(tension, atleast, lcurl, rcurl) def deform(self, basepath): newnp = normpath.normpath() for nsp in basepath.normpath().normsubpaths: newnp += self.deformsubpath(nsp) return newnp def deformsubpath(self, nsp): from .metapost import path as mppath """Returns a path/normpath from the points in the given normsubpath""" # TODO: epsilon ? knots = [] # first point x_pt, y_pt = nsp.atbegin_pt() if nsp.closed: knots.append(mppath.smoothknot_pt(x_pt, y_pt)) elif self.lcurl is None: rot = nsp.rotation([0])[0] dx, dy = rot.apply_pt(1, 0) angle = math.atan2(dy, dx) knots.append(mppath.beginknot_pt(x_pt, y_pt, angle=angle)) else: knots.append(mppath.beginknot_pt(x_pt, y_pt, curl=self.lcurl)) # intermediate points: for npelem in nsp[:-1]: knots.append(mppath.tensioncurve(self.tension)) knots.append(mppath.smoothknot_pt(*npelem.atend_pt())) # last point knots.append(mppath.tensioncurve(self.tension)) x_pt, y_pt = nsp.atend_pt() if nsp.closed: pass elif self.rcurl is None: rot = nsp.rotation([len(nsp)])[0] dx, dy = rot.apply_pt(1, 0) angle = math.atan2(dy, dx) knots.append(mppath.endknot_pt(x_pt, y_pt, angle=angle)) else: knots.append(mppath.endknot_pt(x_pt, y_pt, curl=self.rcurl)) return mppath.path(knots) # >>> linesmoothed.clear = attr.clearclass(linesmoothed) # vim:foldmethod=marker:foldmarker=<<<,>>> PyX-0.14.1/pyx/document.py0000644000076500000240000002014712520247332015545 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 Jörg Lehmann # Copyright (C) 2005-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import logging, sys from . import bbox, pswriter, pdfwriter, svgwriter, trafo, style, unit logger = logging.getLogger("pyx") class paperformat: def __init__(self, width, height, name=None): self.width = width self.height = height self.name = name paperformat.A5 = paperformat(148.5 * unit.t_mm, 210 * unit.t_mm, "A5") paperformat.A4 = paperformat(210 * unit.t_mm, 297 * unit.t_mm, "A4") paperformat.A3 = paperformat(297 * unit.t_mm, 420 * unit.t_mm, "A3") paperformat.A2 = paperformat(420 * unit.t_mm, 594 * unit.t_mm, "A2") paperformat.A1 = paperformat(594 * unit.t_mm, 840 * unit.t_mm, "A1") paperformat.A0 = paperformat(840 * unit.t_mm, 1188 * unit.t_mm, "A0") paperformat.A0b = paperformat(910 * unit.t_mm, 1370 * unit.t_mm, None) # dedicated to our friends in Augsburg paperformat.Letter = paperformat(8.5 * unit.t_inch, 11 * unit.t_inch, "Letter") paperformat.Legal = paperformat(8.5 * unit.t_inch, 14 * unit.t_inch, "Legal") def _paperformatfromstring(name): return getattr(paperformat, name.capitalize()) class page: def __init__(self, canvas, pagename=None, paperformat=None, rotated=0, centered=1, fittosize=0, margin=1*unit.t_cm, bboxenlarge=1*unit.t_pt, bbox=None): self.canvas = canvas self.pagename = pagename # support for deprecated string specification of paper formats try: paperformat + "" except: self.paperformat = paperformat else: self.paperformat = _paperformatfromstring(paperformat) logger.warning("specification of paperformat by string is deprecated, use document.paperformat.%s instead" % paperformat.capitalize()) self.rotated = rotated self.centered = centered self.fittosize = fittosize self.margin = margin self.bboxenlarge = bboxenlarge self.pagebbox = bbox def _process(self, processMethod, contentfile, writer, context, registry, bbox): # usually, it is the bbox of the canvas enlarged by self.bboxenlarge, but # it might be a different bbox as specified in the page constructor assert not bbox if self.pagebbox: bbox.set(self.pagebbox) else: bbox.set(self.canvas.bbox()) # this bbox is not accurate bbox.enlarge(self.bboxenlarge) # check whether we expect a page trafo and use a temporary canvas to insert the # page canvas if self.paperformat and (self.rotated or self.centered or self.fittosize) and bbox: # calculate the pagetrafo paperwidth, paperheight = self.paperformat.width, self.paperformat.height # center (optionally rotated) output on page if self.rotated: pagetrafo = trafo.rotate(90).translated(paperwidth, 0) if self.centered or self.fittosize: if not self.fittosize and (bbox.height() > paperwidth or bbox.width() > paperheight): logger.warning("content exceeds the papersize") pagetrafo = pagetrafo.translated(-0.5*(paperwidth - bbox.height()) + bbox.bottom(), 0.5*(paperheight - bbox.width()) - bbox.left()) else: if not self.fittosize and (bbox.width() > paperwidth or bbox.height() > paperheight): logger.warning("content exceeds the papersize") pagetrafo = trafo.translate(0.5*(paperwidth - bbox.width()) - bbox.left(), 0.5*(paperheight - bbox.height()) - bbox.bottom()) if self.fittosize: if 2*self.margin > paperwidth or 2*self.margin > paperheight: raise ValueError("Margins too broad for selected paperformat. Aborting.") paperwidth -= 2 * self.margin paperheight -= 2 * self.margin # scale output to pagesize - margins if self.rotated: sfactor = min(unit.topt(paperheight)/bbox.width_pt(), unit.topt(paperwidth)/bbox.height_pt()) else: sfactor = min(unit.topt(paperwidth)/bbox.width_pt(), unit.topt(paperheight)/bbox.height_pt()) pagetrafo = pagetrafo.scaled(sfactor, sfactor, self.margin + 0.5*paperwidth, self.margin + 0.5*paperheight) bbox.transform(pagetrafo) from . import canvas as canvasmodule cc = canvasmodule.canvas() cc.insert(self.canvas, [pagetrafo]) else: cc = self.canvas if processMethod != "processSVG": # for SVG we write the pyx defaults as part of the svg node attributes in the writer getattr(style.linewidth.normal, processMethod)(contentfile, writer, context, registry) if self.pagebbox: bbox = bbox.copy() # don't alter the bbox provided to the constructor -> use a copy getattr(cc, processMethod)(contentfile, writer, context, registry, bbox) def processPS(self, *args): self._process("processPS", *args) def processPDF(self, *args): self._process("processPDF", *args) def processSVG(self, *args): self._process("processSVG", *args) class _noclose: def __init__(self, f): self.f = f def __enter__(self): return self.f def __exit__(self, type, value, tb): pass def _outputstream(file, suffix): if file is None: if not sys.argv[0].endswith(".py"): raise RuntimeError("could not auto-guess filename") return open("%s.%s" % (sys.argv[0][:-3], suffix), "wb") if file == "-": return _noclose(sys.stdout.buffer) try: file.write(b"") except: if not file.endswith(".%s" % suffix): return open("%s.%s" % (file, suffix), "wb") return open(file, "wb") else: return _noclose(file) class document: """holds a collection of page instances which are output as pages of a document""" def __init__(self, pages=None): if pages is None: self.pages = [] else: self.pages = pages def append(self, page): self.pages.append(page) def writeEPSfile(self, file=None, **kwargs): with _outputstream(file, "eps") as f: pswriter.EPSwriter(self, f, **kwargs) def writePSfile(self, file=None, **kwargs): with _outputstream(file, "ps") as f: pswriter.PSwriter(self, f, **kwargs) def writePDFfile(self, file=None, **kwargs): with _outputstream(file, "pdf") as f: pdfwriter.PDFwriter(self, f, **kwargs) def writeSVGfile(self, file=None, **kwargs): with _outputstream(file, "svg") as f: svgwriter.SVGwriter(self, f, **kwargs) def writetofile(self, filename, **kwargs): for suffix, method in [("eps", pswriter.EPSwriter), ("ps", pswriter.PSwriter), ("pdf", pdfwriter.PDFwriter), ("svg", svgwriter.SVGwriter)]: if filename.endswith(".{}".format(suffix)): with open(filename, "wb") as f: method(self, f, **kwargs) return raise ValueError("unknown file extension") PyX-0.14.1/pyx/dvi/0000755000076500000240000000000012615763300014136 5ustar andrestaff00000000000000PyX-0.14.1/pyx/dvi/__init__.py0000644000076500000240000000000112177540643016244 0ustar andrestaff00000000000000 PyX-0.14.1/pyx/dvi/dvifile.py0000644000076500000240000006733312225227547016153 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2003-2004,2006,2007 Michael Schindler # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, logging, math, re, string, struct, sys from pyx import bbox, canvas, color, epsfile, config, path, reader, trafo, unit from . import texfont, tfmfile logger = logging.getLogger("pyx") _DVI_CHARMIN = 0 # typeset a character and move right (range min) _DVI_CHARMAX = 127 # typeset a character and move right (range max) _DVI_SET1234 = 128 # typeset a character and move right _DVI_SETRULE = 132 # typeset a rule and move right _DVI_PUT1234 = 133 # typeset a character _DVI_PUTRULE = 137 # typeset a rule _DVI_NOP = 138 # no operation _DVI_BOP = 139 # beginning of page _DVI_EOP = 140 # ending of page _DVI_PUSH = 141 # save the current positions (h, v, w, x, y, z) _DVI_POP = 142 # restore positions (h, v, w, x, y, z) _DVI_RIGHT1234 = 143 # move right _DVI_W0 = 147 # move right by w _DVI_W1234 = 148 # move right and set w _DVI_X0 = 152 # move right by x _DVI_X1234 = 153 # move right and set x _DVI_DOWN1234 = 157 # move down _DVI_Y0 = 161 # move down by y _DVI_Y1234 = 162 # move down and set y _DVI_Z0 = 166 # move down by z _DVI_Z1234 = 167 # move down and set z _DVI_FNTNUMMIN = 171 # set current font (range min) _DVI_FNTNUMMAX = 234 # set current font (range max) _DVI_FNT1234 = 235 # set current font _DVI_SPECIAL1234 = 239 # special (dvi extention) _DVI_FNTDEF1234 = 243 # define the meaning of a font number _DVI_PRE = 247 # preamble _DVI_POST = 248 # postamble beginning _DVI_POSTPOST = 249 # postamble ending _DVI_VERSION = 2 # dvi version # position variable indices _POS_H = 0 _POS_V = 1 _POS_W = 2 _POS_X = 3 _POS_Y = 4 _POS_Z = 5 # reader states _READ_PRE = 1 _READ_NOPAGE = 2 _READ_PAGE = 3 _READ_POST = 4 # XXX not used _READ_POSTPOST = 5 # XXX not used _READ_DONE = 6 class DVIError(Exception): pass class DVIfile: def __init__(self, filename, debug=0, debugfile=sys.stdout): """ opens the dvi file and reads the preamble """ self.filename = filename self.debug = debug self.debugfile = debugfile self.debugstack = [] self.fonts = {} self.activefont = None # stack of fonts and fontscale currently used (used for VFs) self.fontstack = [] self.stack = [] # pointer to currently active page self.actpage = None # stack for self.file, self.fonts and self.stack, needed for VF inclusion self.statestack = [] self.file = reader.reader(self.filename) # currently read byte in file (for debugging output) self.filepos = None self._read_pre() # helper routines def beginsubpage(self, attrs): c = canvas.canvas(attrs) c.parent = self.actpage c.markers = {} self.actpage.insert(c) self.actpage = c def endsubpage(self): for key, value in list(self.actpage.markers.items()): self.actpage.parent.markers[key] = self.actpage.trafo.apply(*value) self.actpage = self.actpage.parent def flushtext(self, fontmap): """ finish currently active text object """ if self.activetext: x, y, charcodes = self.activetext x_pt, y_pt = x * self.pyxconv, -y*self.pyxconv self.actpage.insert(self.activefont.text_pt(x_pt, y_pt, charcodes, fontmap=fontmap)) if self.debug: self.debugfile.write("[%s]\n" % "".join([chr(char) for char in self.activetext[2]])) self.activetext = None def putrule(self, height, width, advancepos, fontmap): self.flushtext(fontmap) x1 = self.pos[_POS_H] * self.pyxconv y1 = -self.pos[_POS_V] * self.pyxconv w = width * self.pyxconv h = height * self.pyxconv if height > 0 and width > 0: if self.debug: self.debugfile.write("%d: %srule height %d, width %d (???x??? pixels)\n" % (self.filepos, advancepos and "set" or "put", height, width)) self.actpage.fill(path.rect_pt(x1, y1, w, h)) else: if self.debug: self.debugfile.write("%d: %srule height %d, width %d (invisible)\n" % (self.filepos, advancepos and "set" or "put", height, width)) if advancepos: if self.debug: self.debugfile.write(" h:=%d+%d=%d, hh:=???\n" % (self.pos[_POS_H], width, self.pos[_POS_H]+width)) self.pos[_POS_H] += width * self.scale def putchar(self, char, advancepos, id1234, fontmap): dx = advancepos and self.activefont.getwidth_dvi(char) or 0 if self.debug: self.debugfile.write("%d: %s%s%d h:=%d+%d=%d, hh:=???\n" % (self.filepos, advancepos and "set" or "put", id1234 and "%i " % id1234 or "char", char, self.pos[_POS_H], dx, self.pos[_POS_H]+dx)) if isinstance(self.activefont, texfont.virtualfont): # virtual font handling afterpos = list(self.pos) afterpos[_POS_H] += dx self._push_dvistring(self.activefont.getchar(char), self.activefont.getfonts(), afterpos, self.activefont.getsize_pt(), fontmap) else: if self.activetext is None: self.activetext = (self.pos[_POS_H], self.pos[_POS_V], []) self.activetext[2].append(char) self.pos[_POS_H] += dx if (not advancepos) or self.singlecharmode: self.flushtext(fontmap) def usefont(self, fontnum, id1234, fontmap): self.flushtext(fontmap) self.activefont = self.fonts[fontnum] if self.debug: self.debugfile.write("%d: fnt%s%i current font is %s\n" % (self.filepos, id1234 and "%i " % id1234 or "num", fontnum, self.fonts[fontnum].name)) def definefont(self, cmdnr, num, c, q, d, fontname): # cmdnr: type of fontdef command (only used for debugging output) # c: checksum # q: scaling factor (fix_word) # Note that q is actually s in large parts of the documentation. # d: design size (fix_word) # check whether it's a virtual font by trying to open it. if this fails, it is an ordinary TeX font try: with config.open(fontname, [config.format.vf]) as fontfile: afont = texfont.virtualfont(fontname, fontfile, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug>1) except EnvironmentError: afont = texfont.TeXfont(fontname, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug>1) self.fonts[num] = afont if self.debug: self.debugfile.write("%d: fntdef%d %i: %s\n" % (self.filepos, cmdnr, num, fontname)) # scale = round((1000.0*self.conv*q)/(self.trueconv*d)) # m = 1.0*q/d # scalestring = scale!=1000 and " scaled %d" % scale or "" # print ("Font %i: %s%s---loaded at size %d DVI units" % # (num, fontname, scalestring, q)) # if scale!=1000: # print " (this font is magnified %d%%)" % round(scale/10) def special(self, s, fontmap): x = self.pos[_POS_H] * self.pyxconv y = -self.pos[_POS_V] * self.pyxconv if self.debug: self.debugfile.write("%d: xxx '%s'\n" % (self.filepos, s)) if not s.startswith("PyX:"): logger.warning("ignoring special '%s'" % s) return # it is in general not safe to continue using the currently active font because # the specials may involve some gsave/grestore operations self.flushtext(fontmap) command, args = s[4:].split()[0], s[4:].split()[1:] if command == "color_begin": if args[0] == "cmyk": c = color.cmyk(float(args[1]), float(args[2]), float(args[3]), float(args[4])) elif args[0] == "gray": c = color.gray(float(args[1])) elif args[0] == "hsb": c = color.hsb(float(args[1]), float(args[2]), float(args[3])) elif args[0] == "rgb": c = color.rgb(float(args[1]), float(args[2]), float(args[3])) elif args[0] == "RGB": c = color.rgb(int(args[1])/255.0, int(args[2])/255.0, int(args[3])/255.0) elif args[0] == "texnamed": try: c = getattr(color.cmyk, args[1]) except AttributeError: raise RuntimeError("unknown TeX color '%s', aborting" % args[1]) elif args[0] == "pyxcolor": # pyx.color.cmyk.PineGreen or # pyx.color.cmyk(0,0,0,0.0) pat = re.compile(r"(pyx\.)?(color\.)?(?P(cmyk)|(rgb)|(grey)|(gray)|(hsb))[\.]?(?P.*)") sd = pat.match(" ".join(args[1:])) if sd: sd = sd.groupdict() if sd["arg"][0] == "(": numpat = re.compile(r"[+-]?((\d+\.\d*)|(\d*\.\d+)|(\d+))([eE][+-]\d+)?") arg = tuple([float(x[0]) for x in numpat.findall(sd["arg"])]) try: c = getattr(color, sd["model"])(*arg) except TypeError or AttributeError: raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:])) else: try: c = getattr(getattr(color, sd["model"]), sd["arg"]) except AttributeError: raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:])) else: raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:])) else: raise RuntimeError("color model '%s' cannot be handled by PyX, aborting" % args[0]) self.beginsubpage([c]) elif command == "color_end": self.endsubpage() elif command == "rotate_begin": self.beginsubpage([trafo.rotate_pt(float(args[0]), x, y)]) elif command == "rotate_end": self.endsubpage() elif command == "scale_begin": self.beginsubpage([trafo.scale_pt(float(args[0]), float(args[1]), x, y)]) elif command == "scale_end": self.endsubpage() elif command == "epsinclude": # parse arguments argdict = {} for arg in args: name, value = arg.split("=") argdict[name] = value # construct kwargs for epsfile constructor epskwargs = {} epskwargs["filename"] = argdict["file"] epskwargs["bbox"] = bbox.bbox_pt(float(argdict["llx"]), float(argdict["lly"]), float(argdict["urx"]), float(argdict["ury"])) if "width" in argdict: epskwargs["width"] = float(argdict["width"]) * unit.t_pt if "height" in argdict: epskwargs["height"] = float(argdict["height"]) * unit.t_pt if "clip" in argdict: epskwargs["clip"] = int(argdict["clip"]) self.actpage.insert(epsfile.epsfile(x * unit.t_pt, y * unit.t_pt, **epskwargs)) elif command == "marker": if len(args) != 1: raise RuntimeError("marker contains spaces") for c in args[0]: if c not in string.ascii_letters + string.digits + "@": raise RuntimeError("marker contains invalid characters") if args[0] in self.actpage.markers: raise RuntimeError("marker name occurred several times") self.actpage.markers[args[0]] = x * unit.t_pt, y * unit.t_pt else: raise RuntimeError("unknown PyX special '%s', aborting" % command) # routines for pushing and popping different dvi chunks on the reader def _push_dvistring(self, dvi, fonts, afterpos, fontsize, fontmap): """ push dvi string with defined fonts on top of reader stack. Every positions gets scaled relatively by the factor scale. After interpretating the dvi chunk, continue with self.pos=afterpos. The designsize of the virtual font is passed as a fix_word """ #if self.debug: # self.debugfile.write("executing new dvi chunk\n") self.debugstack.append(self.debug) self.debug = 0 self.statestack.append((self.file, self.fonts, self.activefont, afterpos, self.stack, self.scale)) # units in vf files are relative to the size of the font and given as fix_words # which can be converted to floats by diving by 2**20. # This yields the following scale factor for the height and width of rects: self.scale = fontsize/2**20/self.pyxconv self.file = reader.bytesreader(dvi) self.fonts = fonts self.stack = [] self.filepos = 0 self.usefont(0, 0, fontmap) def _pop_dvistring(self, fontmap): self.flushtext(fontmap) #if self.debug: # self.debugfile.write("finished executing dvi chunk\n") self.debug = self.debugstack.pop() self.file.close() self.file, self.fonts, self.activefont, self.pos, self.stack, self.scale = self.statestack.pop() # routines corresponding to the different reader states of the dvi maschine def _read_pre(self): afile = self.file while True: self.filepos = afile.tell() cmd = afile.readuchar() if cmd == _DVI_NOP: pass elif cmd == _DVI_PRE: if afile.readuchar() != _DVI_VERSION: raise DVIError num = afile.readuint32() den = afile.readuint32() self.mag = afile.readuint32() # For the interpretation of the lengths in dvi and tfm files, # three conversion factors are relevant: # - self.tfmconv: tfm units -> dvi units # - self.pyxconv: dvi units -> (PostScript) points # - self.conv: dvi units -> pixels self.tfmconv = (25400000.0/num)*(den/473628672.0)/16.0 # calculate conv as described in the DVIType docu using # a given resolution in dpi self.resolution = 300.0 self.conv = (num/254000.0)*(self.resolution/den) # self.pyxconv is the conversion factor from the dvi units # to (PostScript) points. It consists of # - self.mag/1000.0: magstep scaling # - self.conv: conversion from dvi units to pixels # - 1/self.resolution: conversion from pixels to inch # - 72 : conversion from inch to points self.pyxconv = self.mag/1000.0*self.conv/self.resolution*72 # scaling used for rules when VF chunks are interpreted self.scale = 1 comment = afile.read(afile.readuchar()) return else: raise DVIError def readpage(self, pageid=None, fontmap=None, singlecharmode=False, attrs=[]): """ reads a page from the dvi file This routine reads a page from the dvi file which is returned as a canvas. When there is no page left in the dvifile, None is returned and the file is closed properly.""" self.singlecharmode = singlecharmode while True: self.filepos = self.file.tell() cmd = self.file.readuchar() if cmd == _DVI_NOP: pass elif cmd == _DVI_BOP: ispageid = [self.file.readuint32() for i in range(10)] if pageid is not None and ispageid != pageid: raise DVIError("invalid pageid") if self.debug: self.debugfile.write("%d: beginning of page %i\n" % (self.filepos, ispageid[0])) self.file.readuint32() break elif cmd == _DVI_POST: self.file.close() return None # nothing left else: raise DVIError self.actpage = canvas.canvas(attrs) self.actpage.markers = {} self.pos = [0, 0, 0, 0, 0, 0] # tuple (hpos, vpos, codepoints) to be output, or None if no output is pending self.activetext = None while True: afile = self.file self.filepos = afile.tell() try: cmd = afile.readuchar() except struct.error: # we most probably (if the dvi file is not corrupt) hit the end of a dvi chunk, # so we have to continue with the rest of the dvi file self._pop_dvistring(fontmap) continue if cmd == _DVI_NOP: pass if cmd >= _DVI_CHARMIN and cmd <= _DVI_CHARMAX: self.putchar(cmd, True, 0, fontmap) elif cmd >= _DVI_SET1234 and cmd < _DVI_SET1234 + 4: self.putchar(afile.readint(cmd - _DVI_SET1234 + 1), True, cmd-_DVI_SET1234+1, fontmap) elif cmd == _DVI_SETRULE: self.putrule(afile.readint32()*self.scale, afile.readint32()*self.scale, True, fontmap) elif cmd >= _DVI_PUT1234 and cmd < _DVI_PUT1234 + 4: self.putchar(afile.readint(cmd - _DVI_PUT1234 + 1), False, cmd-_DVI_SET1234+1, fontmap) elif cmd == _DVI_PUTRULE: self.putrule(afile.readint32()*self.scale, afile.readint32()*self.scale, False, fontmap) elif cmd == _DVI_EOP: self.flushtext(fontmap) if self.debug: self.debugfile.write("%d: eop\n \n" % self.filepos) return self.actpage elif cmd == _DVI_PUSH: self.stack.append(list(self.pos)) if self.debug: self.debugfile.write("%s: push\n" "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" % ((self.filepos, len(self.stack)-1) + tuple(self.pos))) elif cmd == _DVI_POP: self.flushtext(fontmap) self.pos = self.stack.pop() if self.debug: self.debugfile.write("%s: pop\n" "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" % ((self.filepos, len(self.stack)) + tuple(self.pos))) elif cmd >= _DVI_RIGHT1234 and cmd < _DVI_RIGHT1234 + 4: self.flushtext(fontmap) dh = afile.readint(cmd - _DVI_RIGHT1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: right%d %d h:=%d%+d=%d, hh:=???\n" % (self.filepos, cmd - _DVI_RIGHT1234 + 1, dh, self.pos[_POS_H], dh, self.pos[_POS_H]+dh)) self.pos[_POS_H] += dh elif cmd == _DVI_W0: self.flushtext(fontmap) if self.debug: self.debugfile.write("%d: w0 %d h:=%d%+d=%d, hh:=???\n" % (self.filepos, self.pos[_POS_W], self.pos[_POS_H], self.pos[_POS_W], self.pos[_POS_H]+self.pos[_POS_W])) self.pos[_POS_H] += self.pos[_POS_W] elif cmd >= _DVI_W1234 and cmd < _DVI_W1234 + 4: self.flushtext(fontmap) self.pos[_POS_W] = afile.readint(cmd - _DVI_W1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: w%d %d h:=%d%+d=%d, hh:=???\n" % (self.filepos, cmd - _DVI_W1234 + 1, self.pos[_POS_W], self.pos[_POS_H], self.pos[_POS_W], self.pos[_POS_H]+self.pos[_POS_W])) self.pos[_POS_H] += self.pos[_POS_W] elif cmd == _DVI_X0: self.flushtext(fontmap) if self.debug: self.debugfile.write("%d: x0 %d h:=%d%+d=%d, hh:=???\n" % (self.filepos, self.pos[_POS_X], self.pos[_POS_H], self.pos[_POS_X], self.pos[_POS_H]+self.pos[_POS_X])) self.pos[_POS_H] += self.pos[_POS_X] elif cmd >= _DVI_X1234 and cmd < _DVI_X1234 + 4: self.flushtext(fontmap) self.pos[_POS_X] = afile.readint(cmd - _DVI_X1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: x%d %d h:=%d%+d=%d, hh:=???\n" % (self.filepos, cmd - _DVI_X1234 + 1, self.pos[_POS_X], self.pos[_POS_H], self.pos[_POS_X], self.pos[_POS_H]+self.pos[_POS_X])) self.pos[_POS_H] += self.pos[_POS_X] elif cmd >= _DVI_DOWN1234 and cmd < _DVI_DOWN1234 + 4: self.flushtext(fontmap) dv = afile.readint(cmd - _DVI_DOWN1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: down%d %d v:=%d%+d=%d, vv:=???\n" % (self.filepos, cmd - _DVI_DOWN1234 + 1, dv, self.pos[_POS_V], dv, self.pos[_POS_V]+dv)) self.pos[_POS_V] += dv elif cmd == _DVI_Y0: self.flushtext(fontmap) if self.debug: self.debugfile.write("%d: y0 %d v:=%d%+d=%d, vv:=???\n" % (self.filepos, self.pos[_POS_Y], self.pos[_POS_V], self.pos[_POS_Y], self.pos[_POS_V]+self.pos[_POS_Y])) self.pos[_POS_V] += self.pos[_POS_Y] elif cmd >= _DVI_Y1234 and cmd < _DVI_Y1234 + 4: self.flushtext(fontmap) self.pos[_POS_Y] = afile.readint(cmd - _DVI_Y1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: y%d %d v:=%d%+d=%d, vv:=???\n" % (self.filepos, cmd - _DVI_Y1234 + 1, self.pos[_POS_Y], self.pos[_POS_V], self.pos[_POS_Y], self.pos[_POS_V]+self.pos[_POS_Y])) self.pos[_POS_V] += self.pos[_POS_Y] elif cmd == _DVI_Z0: self.flushtext(fontmap) if self.debug: self.debugfile.write("%d: z0 %d v:=%d%+d=%d, vv:=???\n" % (self.filepos, self.pos[_POS_Z], self.pos[_POS_V], self.pos[_POS_Z], self.pos[_POS_V]+self.pos[_POS_Z])) self.pos[_POS_V] += self.pos[_POS_Z] elif cmd >= _DVI_Z1234 and cmd < _DVI_Z1234 + 4: self.flushtext(fontmap) self.pos[_POS_Z] = afile.readint(cmd - _DVI_Z1234 + 1, 1) * self.scale if self.debug: self.debugfile.write("%d: z%d %d v:=%d%+d=%d, vv:=???\n" % (self.filepos, cmd - _DVI_Z1234 + 1, self.pos[_POS_Z], self.pos[_POS_V], self.pos[_POS_Z], self.pos[_POS_V]+self.pos[_POS_Z])) self.pos[_POS_V] += self.pos[_POS_Z] elif cmd >= _DVI_FNTNUMMIN and cmd <= _DVI_FNTNUMMAX: self.usefont(cmd - _DVI_FNTNUMMIN, 0, fontmap) elif cmd >= _DVI_FNT1234 and cmd < _DVI_FNT1234 + 4: # note that according to the DVI docs, for four byte font numbers, # the font number is signed. Don't ask why! fntnum = afile.readint(cmd - _DVI_FNT1234 + 1, cmd == _DVI_FNT1234 + 3) self.usefont(fntnum, cmd-_DVI_FNT1234+1, fontmap) elif cmd >= _DVI_SPECIAL1234 and cmd < _DVI_SPECIAL1234 + 4: self.special(afile.read(afile.readint(cmd - _DVI_SPECIAL1234 + 1)).decode("ascii"), fontmap) elif cmd >= _DVI_FNTDEF1234 and cmd < _DVI_FNTDEF1234 + 4: if cmd == _DVI_FNTDEF1234: num = afile.readuchar() elif cmd == _DVI_FNTDEF1234+1: num = afile.readuint16() elif cmd == _DVI_FNTDEF1234+2: num = afile.readuint24() elif cmd == _DVI_FNTDEF1234+3: # Cool, here we have according to docu a signed int. Why? num = afile.readint32() self.definefont(cmd-_DVI_FNTDEF1234+1, num, afile.readint32(), afile.readint32(), afile.readint32(), afile.read(afile.readuchar()+afile.readuchar()).decode("ascii")) else: raise DVIError PyX-0.14.1/pyx/dvi/encfile.py0000644000076500000240000000365412177540643016133 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import reader class ENFfileError(Exception): pass class ENCfile: def __init__(self, bytes): c = reader.PStokenizer(bytes, "") # name of encoding self.name = c.gettoken() token = c.gettoken() if token != "[": raise ENCfileError("cannot parse encoding file '%s', expecting '[' got '%s'" % (filename, token)) self.vector = [] for i in range(256): token = c.gettoken() if token == "]": raise ENCfileError("not enough charcodes in encoding file '%s'" % filename) if not token[0] == "/": raise ENCfileError("token does not start with / in encoding file '%s'" % filename) self.vector.append(token[1:]) if c.gettoken() != "]": raise ENCfileError("too many charcodes in encoding file '%s'" % filename) token = c.gettoken() if token != "def": raise ENCfileError("cannot parse encoding file '%s', expecting 'def' got '%s'" % (filename, token)) PyX-0.14.1/pyx/dvi/mapfile.py0000644000076500000240000001700112177540643016132 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, logging, os.path, re from pyx import font, config from pyx.font import t1file, afmfile, pfmfile from pyx.dvi import encfile logger = logging.getLogger("pyx") class UnsupportedFontFormat(Exception): pass class UnsupportedPSFragment(Exception): pass class ParseError(Exception): pass _marker = object() class MAPline: tokenpattern = re.compile(r'"(.*?)("\s+|"$|$)|(.*?)(\s+|$)') def __init__(self, s): """ construct font mapping from line s of font mapping file """ self.texname = self.basepsname = self.fontfilename = None # standard encoding self.encodingfilename = None # supported postscript fragments occuring in psfonts.map # XXX extendfont not yet implemented self.reencodefont = self.extendfont = self.slant = None # cache for openend font and encoding self._font = None self._encoding = _marker tokens = [] while len(s): match = self.tokenpattern.match(s) if match: if match.groups()[0] is not None: tokens.append('"%s"' % match.groups()[0]) else: tokens.append(match.groups()[2]) s = s[match.end():] else: raise ParseError("Cannot tokenize string '%s'" % s) next_token_is_encfile = False for token in tokens: if next_token_is_encfile: self.encodingfilename = token next_token_is_encfile = False elif token.startswith("<"): if token == "<": next_token_is_encfile = True elif token.startswith("<<"): # XXX: support non-partial download here self.fontfilename = token[2:] elif token.startswith("<["): self.encodingfilename = token[2:] elif token.endswith(".pfa") or token.endswith(".pfb"): self.fontfilename = token[1:] elif token.endswith(".enc"): self.encodingfilename = token[1:] elif token.endswith(".ttf"): raise UnsupportedFontFormat("TrueType font") elif token.endswith(".t42"): raise UnsupportedFontFormat("Type 42 font") else: raise ParseError("Unknown token '%s'" % token) elif token.startswith('"'): pscode = token[1:-1].split() # parse standard postscript code fragments while pscode: try: arg, cmd = pscode[:2] except: raise UnsupportedPSFragment("Unsupported Postscript fragment '%s'" % pscode) pscode = pscode[2:] if cmd == "ReEncodeFont": self.reencodefont = arg elif cmd == "ExtendFont": self.extendfont = arg elif cmd == "SlantFont": self.slant = float(arg) else: raise UnsupportedPSFragment("Unsupported Postscript fragment '%s %s'" % (arg, cmd)) else: if self.texname is None: self.texname = token else: self.basepsname = token if self.basepsname is None: self.basepsname = self.texname def getfontname(self): return self.basepsname def getfont(self): if self._font is None: if self.fontfilename is not None: with config.open(self.fontfilename, [config.format.type1]) as fontfile: t1font = t1file.from_PF_bytes(fontfile.read()) assert self.basepsname == t1font.name, "corrupt MAP file" try: with config.open(os.path.splitext(self.fontfilename)[0], [config.format.afm], ascii=True) as metricfile: self._font = font.T1font(t1font, afmfile.AFMfile(metricfile)) except EnvironmentError: try: # fallback by using the pfm instead of the afm font metric # (in all major TeX distributions there is no pfm file format defined by kpsewhich, but # we can use the type1 format and search for the file including the expected suffix) with config.open("%s.pfm" % os.path.splitext(self.fontfilename)[0], [config.format.type1]) as metricfile: self._font = font.T1font(t1font, pfmfile.PFMfile(metricfile, t1font)) except EnvironmentError: # we need to continue without any metric file self._font = font.T1font(t1font) else: # builtin font with config.open(self.basepsname, [config.format.afm], ascii=True) as metricfile: self._font = font.T1builtinfont(self.basepsname, afmfile.AFMfile(metricfile)) return self._font def getencoding(self): if self._encoding is _marker: if self.encodingfilename is not None: with config.open(self.encodingfilename, [config.format.tex_ps_header]) as encodingfile: ef = encfile.ENCfile(encodingfile.read().decode("ascii", errors="surrogateescape")) assert ef.name == "/%s" % self.reencodefont self._encoding = ef.vector else: self._encoding = None return self._encoding def __str__(self): return ("'%s' is '%s' read from '%s' encoded as '%s'" % (self.texname, self.basepsname, self.fontfile, repr(self.encodingfile))) # generate fontmap def readfontmap(filenames): """ read font map from filename (without path) """ fontmap = {} for filename in filenames: with config.open(filename, [config.format.fontmap, config.format.dvips_config], ascii=True) as mapfile: lineno = 0 for line in mapfile.readlines(): lineno += 1 line = line.rstrip() if not (line=="" or line[0] in (" ", "%", "*", ";" , "#")): try: fm = MAPline(line) except (ParseError, UnsupportedPSFragment) as e: logger.warning("Ignoring line %i in mapping file '%s': %s" % (lineno, filename, e)) except UnsupportedFontFormat as e: pass else: fontmap[fm.texname] = fm return fontmap PyX-0.14.1/pyx/dvi/texfont.py0000644000076500000240000002070512511231033016167 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import bbox, font, config from . import tfmfile, vffile class TeXFontError(Exception): pass class TeXfont: def __init__(self, name, c, q, d, tfmconv, pyxconv, debug=0): self.name = name self.q = q # desired size of font (fix_word) in TeX points self.d = d # design size of font (fix_word) in TeX points self.tfmconv = tfmconv # conversion factor from tfm units to dvi units self.pyxconv = pyxconv # conversion factor from dvi units to PostScript points with config.open(self.name, [config.format.tfm]) as file: self.TFMfile = tfmfile.TFMfile(file, debug) # We only check for equality of font checksums if none of them # is zero. The case c == 0 happend in some VF files and # according to the VFtoVP documentation, paragraph 40, a check # is only performed if TFMfile.checksum > 0. Anyhow, being # more generous here seems to be reasonable if self.TFMfile.checksum != c and self.TFMfile.checksum > 0 and c > 0: raise TeXFontError("check sums do not agree: %d vs. %d" % (self.TFMfile.checksum, c)) # Check whether the given design size matches the one defined in the tfm file if abs(self.TFMfile.designsize - d) > 4: # XXX: why the deviation? raise TeXFontError("design sizes do not agree: %d vs. %d" % (self.TFMfile.designsize, d)) #if q < 0 or q > 134217728: # raise TeXFontError("font '%s' not loaded: bad scale" % self.name) if d < 0 or d > 134217728: raise TeXFontError("font '%s' not loaded: bad design size" % self.name) def __str__(self): return "font %s designed at %g TeX pts used at %g TeX pts" % (self.name, 16.0*self.d/16777216, 16.0*self.q/16777216) def getsize_pt(self): """ return size of font in (PS) points """ # The factor 16L/16777216L=2**(-20) converts a fix_word (here self.q) # to the corresponding float. Furthermore, we have to convert from TeX # points to points, hence the factor 72/72.27. return 72/72.27 * 16*self.q/16777216 def _convert_tfm_to_dvi(self, length): # doing the integer math with long integers will lead to different roundings # return 16*length*int(round(self.q*self.tfmconv))/16777216 # Knuth instead suggests the following algorithm based on 4 byte integer logic only # z = int(round(self.q*self.tfmconv)) # b0, b1, b2, b3 = [ord(c) for c in struct.pack(">L", length)] # assert b0 == 0 or b0 == 255 # shift = 4 # while z >= 8388608: # z >>= 1 # shift -= 1 # assert shift >= 0 # result = ( ( ( ( ( b3 * z ) >> 8 ) + ( b2 * z ) ) >> 8 ) + ( b1 * z ) ) >> shift # if b0 == 255: # result = result - (z << (8-shift)) # however, we can simplify this using a single long integer multiplication, # but take into account the transformation of z z = int(round(self.q*self.tfmconv)) assert -16777216 <= length < 16777216 # -(1 << 24) <= length < (1 << 24) assert z < 134217728 # 1 << 27 shift = 20 # 1 << 20 while z >= 8388608: # 1 << 23 z >>= 1 shift -= 1 # length*z is a long integer, but the result will be a regular integer return int(length*int(z) >> shift) def _convert_tfm_to_pt(self, length): return (16*int(round(length*float(self.q)*self.tfmconv))/16777216) * self.pyxconv # routines returning lengths as integers in dvi units def getwidth_dvi(self, charcode): return self._convert_tfm_to_dvi(self.TFMfile.width[self.TFMfile.char_info[charcode].width_index]) def getheight_dvi(self, charcode): return self._convert_tfm_to_dvi(self.TFMfile.height[self.TFMfile.char_info[charcode].height_index]) def getdepth_dvi(self, charcode): return self._convert_tfm_to_dvi(self.TFMfile.depth[self.TFMfile.char_info[charcode].depth_index]) def getitalic_dvi(self, charcode): return self._convert_tfm_to_dvi(self.TFMfile.italic[self.TFMfile.char_info[charcode].italic_index]) # routines returning lengths as floats in PostScript points def getwidth_pt(self, charcode): return self._convert_tfm_to_pt(self.TFMfile.width[self.TFMfile.char_info[charcode].width_index]) def getheight_pt(self, charcode): return self._convert_tfm_to_pt(self.TFMfile.height[self.TFMfile.char_info[charcode].height_index]) def getdepth_pt(self, charcode): return self._convert_tfm_to_pt(self.TFMfile.depth[self.TFMfile.char_info[charcode].depth_index]) def getitalic_pt(self, charcode): return self._convert_tfm_to_pt(self.TFMfile.italic[self.TFMfile.char_info[charcode].italic_index]) def text_pt(self, x_pt, y_pt, charcodes, fontmap=None): return TeXtext_pt(self, x_pt, y_pt, charcodes, self.getsize_pt(), fontmap=fontmap) def getMAPline(self, fontmap): if self.name not in fontmap: raise RuntimeError("missing font information for '%s'; check fontmapping file(s)" % self.name) return fontmap[self.name] class virtualfont(TeXfont): def __init__(self, name, file, c, q, d, tfmconv, pyxconv, debug=0): TeXfont.__init__(self, name, c, q, d, tfmconv, pyxconv, debug) self.vffile = vffile.vffile(file, 1.0*q/d, tfmconv, pyxconv, debug > 1) def getfonts(self): """ return fonts used in virtual font itself """ return self.vffile.getfonts() def getchar(self, cc): """ return dvi chunk corresponding to char code cc """ return self.vffile.getchar(cc) def text_pt(self, *args, **kwargs): raise RuntimeError("you don't know what you're doing") class TeXtext_pt(font.text_pt): def __init__(self, font, x_pt, y_pt, charcodes, size_pt, fontmap=None): self.font = font self.x_pt = x_pt self.y_pt = y_pt self.charcodes = charcodes self.size_pt = size_pt self.fontmap = fontmap self.width_pt = sum([self.font.getwidth_pt(charcode) for charcode in charcodes]) self.height_pt = max([self.font.getheight_pt(charcode) for charcode in charcodes]) self.depth_pt = max([self.font.getdepth_pt(charcode) for charcode in charcodes]) self._bbox = bbox.bbox_pt(self.x_pt, self.y_pt-self.depth_pt, self.x_pt+self.width_pt, self.y_pt+self.height_pt) def bbox(self): return self._bbox def _text(self, writer): if self.fontmap is not None: mapline = self.font.getMAPline(self.fontmap) else: mapline = self.font.getMAPline(writer.getfontmap()) font = mapline.getfont() return font.text_pt(self.x_pt, self.y_pt, self.charcodes, self.size_pt, decoding=mapline.getencoding(), slant=mapline.slant, ignorebbox=True) def textpath(self): from pyx import pswriter return self._text(pswriter._PSwriter()).textpath() def processPS(self, file, writer, context, registry, bbox): bbox += self.bbox() self._text(writer).processPS(file, writer, context, registry, bbox) def processPDF(self, file, writer, context, registry, bbox): bbox += self.bbox() self._text(writer).processPDF(file, writer, context, registry, bbox) def processSVG(self, xml, writer, context, registry, bbox): bbox += self.bbox() self._text(writer).processSVG(xml, writer, context, registry, bbox) PyX-0.14.1/pyx/dvi/tfmfile.py0000644000076500000240000001552612177540643016155 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import reader class char_info_word: def __init__(self, word): self.width_index = int((word & 0xFF000000) >> 24) #make sign-safe self.height_index = (word & 0x00F00000) >> 20 self.depth_index = (word & 0x000F0000) >> 16 self.italic_index = (word & 0x0000FC00) >> 10 self.tag = (word & 0x00000300) >> 8 self.remainder = (word & 0x000000FF) class TFMfile: def __init__(self, file, debug=0): with reader.bytesreader(file.read()) as file: # # read pre header # self.lf = file.readint16() self.lh = file.readint16() self.bc = file.readint16() self.ec = file.readint16() self.nw = file.readint16() self.nh = file.readint16() self.nd = file.readint16() self.ni = file.readint16() self.nl = file.readint16() self.nk = file.readint16() self.ne = file.readint16() self.np = file.readint16() if not (self.bc-1 <= self.ec <= 255 and self.ne <= 256 and self.lf == 6+self.lh+(self.ec-self.bc+1)+self.nw+self.nh+self.nd +self.ni+self.nl+self.nk+self.ne+self.np): raise RuntimeError("error in TFM pre-header") if debug: print("lh=%d" % self.lh) # # read header # self.checksum = file.readint32() self.designsize = file.readint32() assert self.designsize > 0, "invald design size" if self.lh > 2: assert self.lh > 11, "inconsistency in TFM file: incomplete field" self.charcoding = file.readstring(40) else: self.charcoding = None if self.lh > 12: assert self.lh > 16, "inconsistency in TFM file: incomplete field" self.fontfamily = file.readstring(20) else: self.fontfamily = None if debug: print("(FAMILY %s)" % self.fontfamily) print("(CODINGSCHEME %s)" % self.charcoding) print("(DESINGSIZE R %f)" % (16.0*self.designsize/16777216)) if self.lh > 17: self.sevenbitsave = file.readuchar() # ignore the following two bytes file.readint16() facechar = file.readuchar() # decode ugly face specification into the Knuth suggested string if facechar < 18: if facechar >= 12: self.face = "E" facechar -= 12 elif facechar >= 6: self.face = "C" facechar -= 6 else: self.face = "R" if facechar >= 4: self.face = "L" + self.face facechar -= 4 elif facechar >= 2: self.face = "B" + self.face facechar -= 2 else: self.face = "M" + self.face if facechar == 1: self.face = self.face[0] + "I" + self.face[1] else: self.face = self.face[0] + "R" + self.face[1] else: self.face = None else: self.sevenbitsave = self.face = None if self.lh > 18: # just ignore the rest print(file.read((self.lh-18)*4)) # # read char_info # self.char_info = [None]*(self.ec+1) for charcode in range(self.bc, self.ec+1): self.char_info[charcode] = char_info_word(file.readint32()) if self.char_info[charcode].width_index == 0: # disable character if width_index is zero self.char_info[charcode] = None # # read widths # self.width = [None for width_index in range(self.nw)] for width_index in range(self.nw): self.width[width_index] = file.readint32() # # read heights # self.height = [None for height_index in range(self.nh)] for height_index in range(self.nh): self.height[height_index] = file.readint32() # # read depths # self.depth = [None for depth_index in range(self.nd)] for depth_index in range(self.nd): self.depth[depth_index] = file.readint32() # # read italic # self.italic = [None for italic_index in range(self.ni)] for italic_index in range(self.ni): self.italic[italic_index] = file.readint32() # # read lig_kern # # XXX decode to lig_kern_command self.lig_kern = [None for lig_kern_index in range(self.nl)] for lig_kern_index in range(self.nl): self.lig_kern[lig_kern_index] = file.readint32() # # read kern # self.kern = [None for kern_index in range(self.nk)] for kern_index in range(self.nk): self.kern[kern_index] = file.readint32() # # read exten # # XXX decode to extensible_recipe self.exten = [None for exten_index in range(self.ne)] for exten_index in range(self.ne): self.exten[exten_index] = file.readint32() # # read param # # XXX decode self.param = [None for param_index in range(self.np)] for param_index in range(self.np): self.param[param_index] = file.readint32() PyX-0.14.1/pyx/dvi/vffile.py0000644000076500000240000001047312177540643015776 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2007 Jörg Lehmann # Copyright (C) 2002-2007 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import reader _VF_LONG_CHAR = 242 # character packet (long version) _VF_FNTDEF1234 = 243 # font definition _VF_PRE = 247 # preamble _VF_POST = 248 # postamble _VF_ID = 202 # VF id byte class VFError(Exception): pass class vffile: def __init__(self, file, scale, tfmconv, pyxconv, debug=0): self.scale = scale self.tfmconv = tfmconv self.pyxconv = pyxconv self.debug = debug self.fonts = {} # used fonts self.widths = {} # widths of defined chars self.chardefs = {} # dvi chunks for defined chars afile = reader.bytesreader(file.read()) cmd = afile.readuchar() if cmd == _VF_PRE: if afile.readuchar() != _VF_ID: raise VFError comment = afile.read(afile.readuchar()) self.cs = afile.readuint32() self.ds = afile.readuint32() else: raise VFError while True: cmd = afile.readuchar() if cmd >= _VF_FNTDEF1234 and cmd < _VF_FNTDEF1234 + 4: # font definition if cmd == _VF_FNTDEF1234: num = afile.readuchar() elif cmd == _VF_FNTDEF1234+1: num = afile.readuint16() elif cmd == _VF_FNTDEF1234+2: num = afile.readuint24() elif cmd == _VF_FNTDEF1234+3: num = afile.readint32() c = afile.readint32() s = afile.readint32() # relative scaling used for font (fix_word) d = afile.readint32() # design size of font fontname = afile.read(afile.readuchar() + afile.readuchar()).decode("ascii") # rescaled size of font: s is relative to the scaling # of the virtual font itself. Note that realscale has # to be a fix_word (like s) # XXX: check rounding reals = int(round(self.scale * (16*self.ds/16777216) * s)) # print ("defining font %s -- VF scale: %g, VF design size: %d, relative font size: %d => real size: %d" % # (fontname, self.scale, self.ds, s, reals) # ) # XXX allow for virtual fonts here too from . import texfont self.fonts[num] = texfont.TeXfont(fontname, c, reals, d, self.tfmconv, self.pyxconv, self.debug > 1) elif cmd == _VF_LONG_CHAR: # character packet (long form) pl = afile.readuint32() # packet length cc = afile.readuint32() # char code (assumed unsigned, but anyhow only 0 <= cc < 255 is actually used) tfm = afile.readuint24() # character width dvi = afile.read(pl) # dvi code of character self.widths[cc] = tfm self.chardefs[cc] = dvi elif cmd < _VF_LONG_CHAR: # character packet (short form) cc = afile.readuchar() # char code tfm = afile.readuint24() # character width dvi = afile.read(cmd) self.widths[cc] = tfm self.chardefs[cc] = dvi elif cmd == _VF_POST: break else: raise VFError def getfonts(self): return self.fonts def getchar(self, cc): return self.chardefs[cc] PyX-0.14.1/pyx/epsfile.py0000644000076500000240000003223112401142317015346 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import logging, os, string, tempfile from . import baseclasses, bbox, config, unit, trafo, pswriter logger = logging.getLogger("pyx") # PostScript-procedure definitions (cf. 5002.EPSF_Spec_v3.0.pdf) # with important correction in EndEPSF: # end operator is missing in the spec! _BeginEPSF = pswriter.PSdefinition("BeginEPSF", b"""{ /b4_Inc_state save def /dict_count countdictstack def /op_count count 1 sub def userdict begin /showpage { } def 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit [ ] 0 setdash newpath /languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint } if } if } bind""") _EndEPSF = pswriter.PSdefinition("EndEPSF", b"""{ end count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_Inc_state restore } bind""") class linefilereader: """a line by line file reader This line by line file reader allows for '\n', '\r' and '\r\n' as line separation characters. Line separation characters are not modified (binary mode). It implements a readline, a read and a close method similar to a regular file object.""" # note: '\n\r' is not considered to be a linebreak as its documented # in the DSC spec #5001, while '\n\r' *is* a *single* linebreak # according to the EPSF spec #5002 def __init__(self, file, typicallinelen=257): """Opens the file filename for reading. typicallinelen defines the default buffer increase to find the next linebreak.""" # note: The maximal line size in an EPS is 255 plus the # linebreak characters. However, we also handle # lines longer than that. self.file = file self.buffer = b"" self.typicallinelen = typicallinelen def read(self, count=None, EOFmsg="unexpected end of file"): """read bytes from the file count is the number of bytes to be read when set. Then count is unset, the rest of the file is returned. EOFmsg is used to raise a IOError, when the end of the file is reached while reading count bytes or when the rest of the file is empty when count is unset. When EOFmsg is set to None, less than the requested number of bytes might be returned.""" if count is not None: if count > len(self.buffer): self.buffer += self.file.read(count - len(self.buffer)) if EOFmsg is not None and len(self.buffer) < count: raise IOError(EOFmsg) result = self.buffer[:count] self.buffer = self.buffer[count:] return result else: self.buffer += self.file.read() if EOFmsg is not None and not len(self.buffer): raise IOError(EOFmsg) result = self.buffer self.buffer = "" return result def readline(self, EOFmsg="unexpected end of file"): """reads a line from the file Lines are separated by '\n', '\r' or '\r\n'. The line separation strings are included in the return value. The last line might not end with an line separation string. Reading beyond the file generates an IOError with the EOFmsg message. When EOFmsg is None, an empty string is returned when reading beyond the end of the file.""" EOF = 0 while True: crpos = self.buffer.find(b"\r") nlpos = self.buffer.find(b"\n") if nlpos == -1 and (crpos == -1 or crpos == len(self.buffer) - 1) and not EOF: newbuffer = self.file.read(self.typicallinelen) if not len(newbuffer): EOF = 1 self.buffer += newbuffer else: eol = len(self.buffer) if not eol and EOFmsg is not None: raise IOError(EOFmsg) if nlpos != -1: eol = nlpos + 1 if crpos != -1 and (nlpos == -1 or crpos < nlpos - 1): eol = crpos + 1 result = self.buffer[:eol] self.buffer = self.buffer[eol:] return result def _readbbox(file): """returns bounding box of EPS file filename""" file = linefilereader(file) # check the %! header comment if not file.readline().startswith(b"%!"): raise IOError("file doesn't start with a '%!' header comment") bboxatend = 0 # parse the header (use the first BoundingBox) while True: line = file.readline() if not line: break if line.startswith(b"%%BoundingBox:") and not bboxatend: values = line.split(b":", 1)[1].split() if values == ["(atend)"]: bboxatend = 1 else: if len(values) != 4: raise IOError("invalid number of bounding box values") return bbox.bbox_pt(*list(map(int, values))) elif (line.rstrip() == b"%%EndComments" or (len(line) >= 2 and chr(line[0]) != "%" and chr(line[1]) not in string.whitespace)): # implicit end of comments section break if not bboxatend: raise IOError("no bounding box information found") # parse the body nesting = 0 # allow for nested documents while True: line = file.readline() if line.startswith(b"%%BeginData:"): values = line.split(":", 1)[1].split() if len(values) > 3: raise IOError("invalid number of arguments") if len(values) == 3: if values[2] == b"Lines": for i in range(int(values[0])): file.readline() elif values[2] != b"Bytes": raise IOError("invalid bytesorlines-value") else: file.read(int(values[0])) else: file.read(int(values[0])) line = file.readline() # ignore tailing whitespace/newline for binary data if (len(values) < 3 or values[2] != "Lines") and not len(line.strip()): line = file.readline() if line.rstrip() != b"%%EndData": raise IOError("missing EndData") elif line.startswith(b"%%BeginBinary:"): file.read(int(line.split(":", 1)[1])) line = file.readline() # ignore tailing whitespace/newline if not len(line.strip()): line = file.readline() if line.rstrip() != b"%%EndBinary": raise IOError("missing EndBinary") elif line.startswith(b"%%BeginDocument:"): nesting += 1 elif line.rstrip() == b"%%EndDocument": if nesting < 1: raise IOError("unmatched EndDocument") nesting -= 1 elif not nesting and line.rstrip() == b"%%Trailer": break usebbox = None # parse the trailer (use the last BoundingBox) line = True while line: line = file.readline(EOFmsg=None) if line.startswith("%%BoundingBox:"): values = line.split(b":", 1)[1].split() if len(values) != 4: raise IOError("invalid number of bounding box values") usebbox = bbox.bbox_pt(*list(map(int, values))) if not usebbox: raise IOError("missing bounding box information in document trailer") return usebbox class epsfile(baseclasses.canvasitem): """class for epsfiles""" def __init__(self, x, y, filename, width=None, height=None, scale=None, align="bl", clip=1, translatebbox=1, bbox=None, kpsearch=0): """inserts epsfile Object for an EPS file named filename at position (x,y). Width, height, scale and aligment can be adjusted by the corresponding parameters. If clip is set, the result gets clipped to the bbox of the EPS file. If translatebbox is not set, the EPS graphics is not translated to the corresponding origin. If bbox is not None, it overrides the bounding box in the epsfile itself. If kpsearch is set then filename is searched using the kpathsea library. """ self.x_pt = unit.topt(x) self.y_pt = unit.topt(y) self.filename = filename self.kpsearch = kpsearch if bbox: self.mybbox = bbox else: with self.open() as epsfile: self.mybbox = _readbbox(epsfile) # determine scaling in x and y direction self.scalex = self.scaley = scale if width is not None or height is not None: if scale is not None: raise ValueError("cannot set both width and/or height and scale simultaneously") if height is not None: self.scaley = unit.topt(height)/(self.mybbox.ury_pt-self.mybbox.lly_pt) if width is not None: self.scalex = unit.topt(width)/(self.mybbox.urx_pt-self.mybbox.llx_pt) if self.scalex is None: self.scalex = self.scaley if self.scaley is None: self.scaley = self.scalex # set the actual width and height of the eps file (after a # possible scaling) self.width_pt = self.mybbox.urx_pt-self.mybbox.llx_pt if self.scalex: self.width_pt *= self.scalex self.height_pt = self.mybbox.ury_pt-self.mybbox.lly_pt if self.scaley: self.height_pt *= self.scaley # take alignment into account self.align = align if self.align[0]=="b": pass elif self.align[0]=="c": self.y_pt -= self.height_pt/2.0 elif self.align[0]=="t": self.y_pt -= self.height_pt else: raise ValueError("vertical alignment can only be b (bottom), c (center), or t (top)") if self.align[1]=="l": pass elif self.align[1]=="c": self.x_pt -= self.width_pt/2.0 elif self.align[1]=="r": self.x_pt -= self.width_pt else: raise ValueError("horizontal alignment can only be l (left), c (center), or r (right)") self.clip = clip self.translatebbox = translatebbox self.trafo = trafo.translate_pt(self.x_pt, self.y_pt) if self.scalex is not None: self.trafo = self.trafo * trafo.scale_pt(self.scalex, self.scaley) if translatebbox: self.trafo = self.trafo * trafo.translate_pt(-self.mybbox.llx_pt, -self.mybbox.lly_pt) def open(self): if self.kpsearch: return config.open(self.filename, [config.format.pict]) else: return open(self.filename, "rb") def bbox(self): return self.mybbox.transformed(self.trafo) def processPS(self, file, writer, context, registry, bbox): registry.add(_BeginEPSF) registry.add(_EndEPSF) bbox += self.bbox() file.write("BeginEPSF\n") if self.clip: llx_pt, lly_pt, urx_pt, ury_pt = self.mybbox.transformed(self.trafo).highrestuple_pt() file.write("%g %g %g %g rectclip\n" % (llx_pt, lly_pt, urx_pt-llx_pt, ury_pt-lly_pt)) self.trafo.processPS(file, writer, context, registry) file.write("%%%%BeginDocument: %s\n" % self.filename) with self.open() as epsfile: file.write_bytes(epsfile.read()) file.write("%%EndDocument\n") file.write("EndEPSF\n") def processPDF(self, file, writer, context, registry, bbox): logger.warning("EPS file is included as a bitmap created using pipeGS") from pyx import bitmap, canvas from PIL import Image c = canvas.canvas() c.insert(self) i = Image.open(c.pipeGS(device="pngalpha", resolution=600)) i.load() b = bitmap.bitmap_pt(self.bbox().llx_pt, self.bbox().lly_pt, i) # we slightly shift the bitmap to re-center it, as the bitmap might contain some additional border # unfortunately we need to construct another bitmap instance for that ... b = bitmap.bitmap_pt(self.bbox().llx_pt + 0.5*(self.bbox().width_pt()-b.bbox().width_pt()), self.bbox().lly_pt + 0.5*(self.bbox().height_pt()-b.bbox().height_pt()), i) b.processPDF(file, writer, context, registry, bbox) PyX-0.14.1/pyx/font/0000755000076500000240000000000012615763300014322 5ustar andrestaff00000000000000PyX-0.14.1/pyx/font/__init__.py0000644000076500000240000000212212177540643016436 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2011 Jörg Lehmann # Copyright (C) 2005-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from . import font __allfont__ = ["T1font", "T1builtinfont", "text_pt", "font"] for importfromfont in __allfont__: locals()[importfromfont] = getattr(font, importfromfont) __all__ = __allfont__ PyX-0.14.1/pyx/font/_t1code.c0000644000076500000240000000606312171330401015776 0ustar andrestaff00000000000000/* t1code.c: Copyright 2005 Jörg Lehmann * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #define C1 52845 #define C2 22719 /* def decoder(code, r, n): c1 = 52845 c2 = 22719 data = array.array("B") for x in array.array("B", code): data.append(x ^ (r >> 8)) r = ((x + r) * c1 + c2) & 0xffff return data.tobytes()[n:] */ static PyObject *py_decoder(PyObject *self, PyObject *args) { unsigned char *code; int lcode, pr, n; if (PyArg_ParseTuple(args, "y#ii", (char **) &code, &lcode, &pr, &n)) { unsigned char *data; int i; unsigned char x; uint16_t r=pr; PyObject *result; if (! (data = (unsigned char *) malloc(lcode)) ) return NULL; for (i=0; i> 8); r = (x + r) * C1 + C2; } /* convert result to string stripping first n chars */ result = PyBytes_FromStringAndSize((const char *)data + n, lcode - n); free(data); return result; } else return NULL; } /* def encoder(data, r, random): c1 = 52845 c2 = 22719 code = array.array("B") for x in array.array("B", random+data): code.append(x ^ (r >> 8)) r = ((code[-1] + r) * c1 + c2) & 0xffff; return code.tobytes() */ static PyObject *py_encoder(PyObject *self, PyObject *args) { unsigned char *data; unsigned char *random; int ldata, pr, lrandom; if (PyArg_ParseTuple(args, "y#iy#", (char **) &data, &ldata, &pr, (char **) &random, &lrandom)) { unsigned char *code; int i; uint16_t r=pr; PyObject *result; if (! (code = (unsigned char *) malloc(ldata + lrandom)) ) return NULL; for (i=0; i> 8); r = (code[i] + r) * C1 + C2; } for (i=0; i> 8); r = (code[i+lrandom] + r) * C1 + C2; } result = PyBytes_FromStringAndSize((const char *)code, ldata + lrandom); free(code); return result; } else return NULL; } /* exported methods */ static PyMethodDef t1code_methods[] = { {"decoder", py_decoder, METH_VARARGS, NULL}, {"encoder", py_encoder, METH_VARARGS, NULL}, {NULL, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_t1code", NULL, -1, t1code_methods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit__t1code(void) { PyObject *module = PyModule_Create(&moduledef); return module; } PyX-0.14.1/pyx/font/afmfile.py0000644000076500000240000015671312516236473016322 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2006-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import string from . import metric unicodestring = {" ": "space", "!": "exclam", "\"": "quotedbl", "#": "numbersign", "$": "dollar", "%": "percent", "&": "ampersand", "'": "quotesingle", "(": "parenleft", ")": "parenright", "*": "asterisk", "+": "plus", ",": "comma", "-": "hyphen", ".": "period", "/": "slash", "0": "zero", "1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six", "7": "seven", "8": "eight", "9": "nine", ":": "colon", ";": "semicolon", "<": "less", "=": "equal", ">": "greater", "?": "question", "@": "at", "A": "A", "B": "B", "C": "C", "D": "D", "E": "E", "F": "F", "G": "G", "H": "H", "I": "I", "J": "J", "K": "K", "L": "L", "M": "M", "N": "N", "O": "O", "P": "P", "Q": "Q", "R": "R", "S": "S", "T": "T", "U": "U", "V": "V", "W": "W", "X": "X", "Y": "Y", "Z": "Z", "[": "bracketleft", "\\": "backslash", "]": "bracketright", "^": "asciicircum", "_": "underscore", "`": "grave", "a": "a", "b": "b", "c": "c", "d": "d", "e": "e", "f": "f", "g": "g", "h": "h", "i": "i", "j": "j", "k": "k", "l": "l", "m": "m", "n": "n", "o": "o", "p": "p", "q": "q", "r": "r", "s": "s", "t": "t", "u": "u", "v": "v", "w": "w", "x": "x", "y": "y", "z": "z", "{": "braceleft", "|": "bar", "}": "braceright", "~": "asciitilde", "\xa0": "space", "\xa1": "exclamdown", "\xa2": "cent", "\xa3": "sterling", "\xa4": "currency", "\xa5": "yen", "\xa6": "brokenbar", "\xa7": "section", "\xa8": "dieresis", "\xa9": "copyright", "\xaa": "ordfeminine", "\xab": "guillemotleft", "\xac": "logicalnot", "\xad": "hyphen", "\xae": "registered", "\xaf": "macron", "\xb0": "degree", "\xb1": "plusminus", "\xb4": "acute", "\xb6": "paragraph", "\xb7": "periodcentered", "\xb8": "cedilla", "\xba": "ordmasculine", "\xbb": "guillemotright", "\xbc": "onequarter", "\xbd": "onehalf", "\xbe": "threequarters", "\xbf": "questiondown", "\xc0": "Agrave", "\xc1": "Aacute", "\xc2": "Acircumflex", "\xc3": "Atilde", "\xc4": "Adieresis", "\xc5": "Aring", "\xc6": "AE", "\xc7": "Ccedilla", "\xc8": "Egrave", "\xc9": "Eacute", "\xca": "Ecircumflex", "\xcb": "Edieresis", "\xcc": "Igrave", "\xcd": "Iacute", "\xce": "Icircumflex", "\xcf": "Idieresis", "\xd0": "Eth", "\xd1": "Ntilde", "\xd2": "Ograve", "\xd3": "Oacute", "\xd4": "Ocircumflex", "\xd5": "Otilde", "\xd6": "Odieresis", "\xd7": "multiply", "\xd8": "Oslash", "\xd9": "Ugrave", "\xda": "Uacute", "\xdb": "Ucircumflex", "\xdc": "Udieresis", "\xdd": "Yacute", "\xde": "Thorn", "\xdf": "germandbls", "\xe0": "agrave", "\xe1": "aacute", "\xe2": "acircumflex", "\xe3": "atilde", "\xe4": "adieresis", "\xe5": "aring", "\xe6": "ae", "\xe7": "ccedilla", "\xe8": "egrave", "\xe9": "eacute", "\xea": "ecircumflex", "\xeb": "edieresis", "\xec": "igrave", "\xed": "iacute", "\xee": "icircumflex", "\xef": "idieresis", "\xf0": "eth", "\xf1": "ntilde", "\xf2": "ograve", "\xf3": "oacute", "\xf4": "ocircumflex", "\xf5": "otilde", "\xf6": "odieresis", "\xf7": "divide", "\xf8": "oslash", "\xf9": "ugrave", "\xfa": "uacute", "\xfb": "ucircumflex", "\xfc": "udieresis", "\xfd": "yacute", "\xfe": "thorn", "\xff": "ydieresis", "\u0100": "Amacron", "\u0101": "amacron", "\u0102": "Abreve", "\u0103": "abreve", "\u0104": "Aogonek", "\u0105": "aogonek", "\u0106": "Cacute", "\u0107": "cacute", "\u0108": "Ccircumflex", "\u0109": "ccircumflex", "\u010a": "Cdotaccent", "\u010b": "cdotaccent", "\u010c": "Ccaron", "\u010d": "ccaron", "\u010e": "Dcaron", "\u010f": "dcaron", "\u0110": "Dcroat", "\u0111": "dcroat", "\u0112": "Emacron", "\u0113": "emacron", "\u0114": "Ebreve", "\u0115": "ebreve", "\u0116": "Edotaccent", "\u0117": "edotaccent", "\u0118": "Eogonek", "\u0119": "eogonek", "\u011a": "Ecaron", "\u011b": "ecaron", "\u011c": "Gcircumflex", "\u011d": "gcircumflex", "\u011e": "Gbreve", "\u011f": "gbreve", "\u0120": "Gdotaccent", "\u0121": "gdotaccent", "\u0122": "Gcommaaccent", "\u0123": "gcommaaccent", "\u0124": "Hcircumflex", "\u0125": "hcircumflex", "\u0126": "Hbar", "\u0127": "hbar", "\u0128": "Itilde", "\u0129": "itilde", "\u012a": "Imacron", "\u012b": "imacron", "\u012c": "Ibreve", "\u012d": "ibreve", "\u012e": "Iogonek", "\u012f": "iogonek", "\u0130": "Idotaccent", "\u0131": "dotlessi", "\u0132": "IJ", "\u0133": "ij", "\u0134": "Jcircumflex", "\u0135": "jcircumflex", "\u0136": "Kcommaaccent", "\u0137": "kcommaaccent", "\u0138": "kgreenlandic", "\u0139": "Lacute", "\u013a": "lacute", "\u013b": "Lcommaaccent", "\u013c": "lcommaaccent", "\u013d": "Lcaron", "\u013e": "lcaron", "\u013f": "Ldot", "\u0140": "ldot", "\u0141": "Lslash", "\u0142": "lslash", "\u0143": "Nacute", "\u0144": "nacute", "\u0145": "Ncommaaccent", "\u0146": "ncommaaccent", "\u0147": "Ncaron", "\u0148": "ncaron", "\u0149": "napostrophe", "\u014a": "Eng", "\u014b": "eng", "\u014c": "Omacron", "\u014d": "omacron", "\u014e": "Obreve", "\u014f": "obreve", "\u0150": "Ohungarumlaut", "\u0151": "ohungarumlaut", "\u0152": "OE", "\u0153": "oe", "\u0154": "Racute", "\u0155": "racute", "\u0156": "Rcommaaccent", "\u0157": "rcommaaccent", "\u0158": "Rcaron", "\u0159": "rcaron", "\u015a": "Sacute", "\u015b": "sacute", "\u015c": "Scircumflex", "\u015d": "scircumflex", "\u015e": "Scedilla", "\u015f": "scedilla", "\u0160": "Scaron", "\u0161": "scaron", "\u0162": "Tcommaaccent", "\u0163": "tcommaaccent", "\u0164": "Tcaron", "\u0165": "tcaron", "\u0166": "Tbar", "\u0167": "tbar", "\u0168": "Utilde", "\u0169": "utilde", "\u016a": "Umacron", "\u016b": "umacron", "\u016c": "Ubreve", "\u016d": "ubreve", "\u016e": "Uring", "\u016f": "uring", "\u0170": "Uhungarumlaut", "\u0171": "uhungarumlaut", "\u0172": "Uogonek", "\u0173": "uogonek", "\u0174": "Wcircumflex", "\u0175": "wcircumflex", "\u0176": "Ycircumflex", "\u0177": "ycircumflex", "\u0178": "Ydieresis", "\u0179": "Zacute", "\u017a": "zacute", "\u017b": "Zdotaccent", "\u017c": "zdotaccent", "\u017d": "Zcaron", "\u017e": "zcaron", "\u017f": "longs", "\u0192": "florin", "\u01a0": "Ohorn", "\u01a1": "ohorn", "\u01af": "Uhorn", "\u01b0": "uhorn", "\u01e6": "Gcaron", "\u01e7": "gcaron", "\u01fa": "Aringacute", "\u01fb": "aringacute", "\u01fc": "AEacute", "\u01fd": "aeacute", "\u01fe": "Oslashacute", "\u01ff": "oslashacute", "\u0218": "Scommaaccent", "\u0219": "scommaaccent", "\u02bc": "afii57929", "\u02bd": "afii64937", "\u02c6": "circumflex", "\u02c7": "caron", "\u02c9": "macron", "\u02d8": "breve", "\u02d9": "dotaccent", "\u02da": "ring", "\u02db": "ogonek", "\u02dc": "tilde", "\u02dd": "hungarumlaut", "\u0300": "gravecomb", "\u0301": "acutecomb", "\u0303": "tildecomb", "\u0309": "hookabovecomb", "\u0323": "dotbelowcomb", "\u0384": "tonos", "\u0385": "dieresistonos", "\u0386": "Alphatonos", "\u0387": "anoteleia", "\u0388": "Epsilontonos", "\u0389": "Etatonos", "\u038a": "Iotatonos", "\u038c": "Omicrontonos", "\u038e": "Upsilontonos", "\u038f": "Omegatonos", "\u0390": "iotadieresistonos", "\u0391": "Alpha", "\u0392": "Beta", "\u0393": "Gamma", "\u0394": "Delta", "\u0395": "Epsilon", "\u0396": "Zeta", "\u0397": "Eta", "\u0398": "Theta", "\u0399": "Iota", "\u039a": "Kappa", "\u039b": "Lambda", "\u039c": "Mu", "\u039d": "Nu", "\u039e": "Xi", "\u039f": "Omicron", "\u03a0": "Pi", "\u03a1": "Rho", "\u03a3": "Sigma", "\u03a4": "Tau", "\u03a5": "Upsilon", "\u03a6": "Phi", "\u03a7": "Chi", "\u03a8": "Psi", "\u03a9": "Omega", "\u03aa": "Iotadieresis", "\u03ab": "Upsilondieresis", "\u03ac": "alphatonos", "\u03ad": "epsilontonos", "\u03ae": "etatonos", "\u03af": "iotatonos", "\u03b0": "upsilondieresistonos", "\u03b1": "alpha", "\u03b2": "beta", "\u03b3": "gamma", "\u03b4": "delta", "\u03b5": "epsilon", "\u03b6": "zeta", "\u03b7": "eta", "\u03b8": "theta", "\u03b9": "iota", "\u03ba": "kappa", "\u03bb": "lambda", "\u03bc": "mu", "\u03bd": "nu", "\u03be": "xi", "\u03bf": "omicron", "\u03c0": "pi", "\u03c1": "rho", "\u03c2": "sigma1", "\u03c3": "sigma", "\u03c4": "tau", "\u03c5": "upsilon", "\u03c6": "phi", "\u03c7": "chi", "\u03c8": "psi", "\u03c9": "omega", "\u03ca": "iotadieresis", "\u03cb": "upsilondieresis", "\u03cc": "omicrontonos", "\u03cd": "upsilontonos", "\u03ce": "omegatonos", "\u03d1": "theta1", "\u03d2": "Upsilon1", "\u03d5": "phi1", "\u03d6": "omega1", "\u0401": "afii10023", "\u0402": "afii10051", "\u0403": "afii10052", "\u0404": "afii10053", "\u0405": "afii10054", "\u0406": "afii10055", "\u0407": "afii10056", "\u0408": "afii10057", "\u0409": "afii10058", "\u040a": "afii10059", "\u040b": "afii10060", "\u040c": "afii10061", "\u040e": "afii10062", "\u040f": "afii10145", "\u0410": "afii10017", "\u0411": "afii10018", "\u0412": "afii10019", "\u0413": "afii10020", "\u0414": "afii10021", "\u0415": "afii10022", "\u0416": "afii10024", "\u0417": "afii10025", "\u0418": "afii10026", "\u0419": "afii10027", "\u041a": "afii10028", "\u041b": "afii10029", "\u041c": "afii10030", "\u041d": "afii10031", "\u041e": "afii10032", "\u041f": "afii10033", "\u0420": "afii10034", "\u0421": "afii10035", "\u0422": "afii10036", "\u0423": "afii10037", "\u0424": "afii10038", "\u0425": "afii10039", "\u0426": "afii10040", "\u0427": "afii10041", "\u0428": "afii10042", "\u0429": "afii10043", "\u042a": "afii10044", "\u042b": "afii10045", "\u042c": "afii10046", "\u042d": "afii10047", "\u042e": "afii10048", "\u042f": "afii10049", "\u0430": "afii10065", "\u0431": "afii10066", "\u0432": "afii10067", "\u0433": "afii10068", "\u0434": "afii10069", "\u0435": "afii10070", "\u0436": "afii10072", "\u0437": "afii10073", "\u0438": "afii10074", "\u0439": "afii10075", "\u043a": "afii10076", "\u043b": "afii10077", "\u043c": "afii10078", "\u043d": "afii10079", "\u043e": "afii10080", "\u043f": "afii10081", "\u0440": "afii10082", "\u0441": "afii10083", "\u0442": "afii10084", "\u0443": "afii10085", "\u0444": "afii10086", "\u0445": "afii10087", "\u0446": "afii10088", "\u0447": "afii10089", "\u0448": "afii10090", "\u0449": "afii10091", "\u044a": "afii10092", "\u044b": "afii10093", "\u044c": "afii10094", "\u044d": "afii10095", "\u044e": "afii10096", "\u044f": "afii10097", "\u0451": "afii10071", "\u0452": "afii10099", "\u0453": "afii10100", "\u0454": "afii10101", "\u0455": "afii10102", "\u0456": "afii10103", "\u0457": "afii10104", "\u0458": "afii10105", "\u0459": "afii10106", "\u045a": "afii10107", "\u045b": "afii10108", "\u045c": "afii10109", "\u045e": "afii10110", "\u045f": "afii10193", "\u0462": "afii10146", "\u0463": "afii10194", "\u0472": "afii10147", "\u0473": "afii10195", "\u0474": "afii10148", "\u0475": "afii10196", "\u0490": "afii10050", "\u0491": "afii10098", "\u04d9": "afii10846", "\u05b0": "afii57799", "\u05b1": "afii57801", "\u05b2": "afii57800", "\u05b3": "afii57802", "\u05b4": "afii57793", "\u05b5": "afii57794", "\u05b6": "afii57795", "\u05b7": "afii57798", "\u05b8": "afii57797", "\u05b9": "afii57806", "\u05bb": "afii57796", "\u05bc": "afii57807", "\u05bd": "afii57839", "\u05be": "afii57645", "\u05bf": "afii57841", "\u05c0": "afii57842", "\u05c1": "afii57804", "\u05c2": "afii57803", "\u05c3": "afii57658", "\u05d0": "afii57664", "\u05d1": "afii57665", "\u05d2": "afii57666", "\u05d3": "afii57667", "\u05d4": "afii57668", "\u05d5": "afii57669", "\u05d6": "afii57670", "\u05d7": "afii57671", "\u05d8": "afii57672", "\u05d9": "afii57673", "\u05da": "afii57674", "\u05db": "afii57675", "\u05dc": "afii57676", "\u05dd": "afii57677", "\u05de": "afii57678", "\u05df": "afii57679", "\u05e0": "afii57680", "\u05e1": "afii57681", "\u05e2": "afii57682", "\u05e3": "afii57683", "\u05e4": "afii57684", "\u05e5": "afii57685", "\u05e6": "afii57686", "\u05e7": "afii57687", "\u05e8": "afii57688", "\u05e9": "afii57689", "\u05ea": "afii57690", "\u05f0": "afii57716", "\u05f1": "afii57717", "\u05f2": "afii57718", "\u060c": "afii57388", "\u061b": "afii57403", "\u061f": "afii57407", "\u0621": "afii57409", "\u0622": "afii57410", "\u0623": "afii57411", "\u0624": "afii57412", "\u0625": "afii57413", "\u0626": "afii57414", "\u0627": "afii57415", "\u0628": "afii57416", "\u0629": "afii57417", "\u062a": "afii57418", "\u062b": "afii57419", "\u062c": "afii57420", "\u062d": "afii57421", "\u062e": "afii57422", "\u062f": "afii57423", "\u0630": "afii57424", "\u0631": "afii57425", "\u0632": "afii57426", "\u0633": "afii57427", "\u0634": "afii57428", "\u0635": "afii57429", "\u0636": "afii57430", "\u0637": "afii57431", "\u0638": "afii57432", "\u0639": "afii57433", "\u063a": "afii57434", "\u0640": "afii57440", "\u0641": "afii57441", "\u0642": "afii57442", "\u0643": "afii57443", "\u0644": "afii57444", "\u0645": "afii57445", "\u0646": "afii57446", "\u0647": "afii57470", "\u0648": "afii57448", "\u0649": "afii57449", "\u064a": "afii57450", "\u064b": "afii57451", "\u064c": "afii57452", "\u064d": "afii57453", "\u064e": "afii57454", "\u064f": "afii57455", "\u0650": "afii57456", "\u0651": "afii57457", "\u0652": "afii57458", "\u0660": "afii57392", "\u0661": "afii57393", "\u0662": "afii57394", "\u0663": "afii57395", "\u0664": "afii57396", "\u0665": "afii57397", "\u0666": "afii57398", "\u0667": "afii57399", "\u0668": "afii57400", "\u0669": "afii57401", "\u066a": "afii57381", "\u066d": "afii63167", "\u0679": "afii57511", "\u067e": "afii57506", "\u0686": "afii57507", "\u0688": "afii57512", "\u0691": "afii57513", "\u0698": "afii57508", "\u06a4": "afii57505", "\u06af": "afii57509", "\u06ba": "afii57514", "\u06d2": "afii57519", "\u06d5": "afii57534", "\u1e80": "Wgrave", "\u1e81": "wgrave", "\u1e82": "Wacute", "\u1e83": "wacute", "\u1e84": "Wdieresis", "\u1e85": "wdieresis", "\u1ef2": "Ygrave", "\u1ef3": "ygrave", "\u200c": "afii61664", "\u200d": "afii301", "\u200e": "afii299", "\u200f": "afii300", "\u2012": "figuredash", "\u2013": "endash", "\u2014": "emdash", "\u2015": "afii00208", "\u2017": "underscoredbl", "\u2018": "quoteleft", "\u2019": "quoteright", "\u201a": "quotesinglbase", "\u201b": "quotereversed", "\u201c": "quotedblleft", "\u201d": "quotedblright", "\u201e": "quotedblbase", "\u2020": "dagger", "\u2021": "daggerdbl", "\u2022": "bullet", "\u2024": "onedotenleader", "\u2025": "twodotenleader", "\u2026": "ellipsis", "\u202c": "afii61573", "\u202d": "afii61574", "\u202e": "afii61575", "\u2030": "perthousand", "\u2032": "minute", "\u2033": "second", "\u2039": "guilsinglleft", "\u203a": "guilsinglright", "\u203c": "exclamdbl", "\u2044": "fraction", "\u20a1": "colonmonetary", "\u20a3": "franc", "\u20a4": "lira", "\u20a7": "peseta", "\u20aa": "afii57636", "\u20ab": "dong", "\u20ac": "Euro", "\u2105": "afii61248", "\u2111": "Ifraktur", "\u2113": "afii61289", "\u2116": "afii61352", "\u2118": "weierstrass", "\u211c": "Rfraktur", "\u211e": "prescription", "\u2122": "trademark", "\u212e": "estimated", "\u2135": "aleph", "\u2153": "onethird", "\u2154": "twothirds", "\u215b": "oneeighth", "\u215c": "threeeighths", "\u215d": "fiveeighths", "\u215e": "seveneighths", "\u2190": "arrowleft", "\u2191": "arrowup", "\u2192": "arrowright", "\u2193": "arrowdown", "\u2194": "arrowboth", "\u2195": "arrowupdn", "\u21a8": "arrowupdnbse", "\u21b5": "carriagereturn", "\u21d0": "arrowdblleft", "\u21d1": "arrowdblup", "\u21d2": "arrowdblright", "\u21d3": "arrowdbldown", "\u21d4": "arrowdblboth", "\u2200": "universal", "\u2202": "partialdiff", "\u2203": "existential", "\u2205": "emptyset", "\u2207": "gradient", "\u2208": "element", "\u2209": "notelement", "\u220b": "suchthat", "\u220f": "product", "\u2211": "summation", "\u2212": "minus", "\u2215": "fraction", "\u2217": "asteriskmath", "\u2219": "periodcentered", "\u221a": "radical", "\u221d": "proportional", "\u221e": "infinity", "\u221f": "orthogonal", "\u2220": "angle", "\u2227": "logicaland", "\u2228": "logicalor", "\u2229": "intersection", "\u222a": "union", "\u222b": "integral", "\u2234": "therefore", "\u223c": "similar", "\u2245": "congruent", "\u2248": "approxequal", "\u2260": "notequal", "\u2261": "equivalence", "\u2264": "lessequal", "\u2265": "greaterequal", "\u2282": "propersubset", "\u2283": "propersuperset", "\u2284": "notsubset", "\u2286": "reflexsubset", "\u2287": "reflexsuperset", "\u2295": "circleplus", "\u2297": "circlemultiply", "\u22a5": "perpendicular", "\u22c5": "dotmath", "\u2302": "house", "\u2310": "revlogicalnot", "\u2320": "integraltp", "\u2321": "integralbt", "\u2329": "angleleft", "\u232a": "angleright", "\u2500": "SF100000", "\u2502": "SF110000", "\u250c": "SF010000", "\u2510": "SF030000", "\u2514": "SF020000", "\u2518": "SF040000", "\u251c": "SF080000", "\u2524": "SF090000", "\u252c": "SF060000", "\u2534": "SF070000", "\u253c": "SF050000", "\u2550": "SF430000", "\u2551": "SF240000", "\u2552": "SF510000", "\u2553": "SF520000", "\u2554": "SF390000", "\u2555": "SF220000", "\u2556": "SF210000", "\u2557": "SF250000", "\u2558": "SF500000", "\u2559": "SF490000", "\u255a": "SF380000", "\u255b": "SF280000", "\u255c": "SF270000", "\u255d": "SF260000", "\u255e": "SF360000", "\u255f": "SF370000", "\u2560": "SF420000", "\u2561": "SF190000", "\u2562": "SF200000", "\u2563": "SF230000", "\u2564": "SF470000", "\u2565": "SF480000", "\u2566": "SF410000", "\u2567": "SF450000", "\u2568": "SF460000", "\u2569": "SF400000", "\u256a": "SF540000", "\u256b": "SF530000", "\u256c": "SF440000", "\u2580": "upblock", "\u2584": "dnblock", "\u2588": "block", "\u258c": "lfblock", "\u2590": "rtblock", "\u2591": "ltshade", "\u2592": "shade", "\u2593": "dkshade", "\u25a0": "filledbox", "\u25a1": "H22073", "\u25aa": "H18543", "\u25ab": "H18551", "\u25ac": "filledrect", "\u25b2": "triagup", "\u25ba": "triagrt", "\u25bc": "triagdn", "\u25c4": "triaglf", "\u25ca": "lozenge", "\u25cb": "circle", "\u25cf": "H18533", "\u25d8": "invbullet", "\u25d9": "invcircle", "\u25e6": "openbullet", "\u263a": "smileface", "\u263b": "invsmileface", "\u263c": "sun", "\u2640": "female", "\u2642": "male", "\u2660": "spade", "\u2663": "club", "\u2665": "heart", "\u2666": "diamond", "\u266a": "musicalnote", "\u266b": "musicalnotedbl", "\ufb01": "fi", "\ufb02": "fl"} class AFMError(Exception): pass # reader states _READ_START = 0 _READ_MAIN = 1 _READ_DIRECTION = 2 _READ_CHARMETRICS = 3 _READ_KERNDATA = 4 _READ_TRACKKERN = 5 _READ_KERNPAIRS = 6 _READ_COMPOSITES = 7 _READ_END = 8 # various parsing functions def _parseint(s): try: return int(s) except: raise AFMError("Expecting int, got '%s'" % s) def _parsehex(s): try: if s[0] != "<" or s[-1] != ">": raise AFMError() return int(s[1:-1], 16) except: raise AFMError("Expecting hexadecimal int, got '%s'" % s) def _parsefloat(s): try: return float(s) except: raise AFMError("Expecting float, got '%s'" % s) def _parsefloats(s, nos): try: numbers = s.split() result = list(map(float, numbers)) if len(result) != nos: raise AFMError() except: raise AFMError("Expecting list of %d numbers, got '%s'" % (s, nos)) return result def _parsestr(s): # XXX: check for invalid characters in s return s def _parsebool(s): s = s.rstrip() if s == "true": return True elif s == "false": return False else: raise AFMError("Expecting boolean, got '%s'" % s) class AFMcharmetrics: def __init__(self, code, widths=None, vvector=None, name=None, bbox=None, ligatures=None): self.code = code if widths is None: self.widths = [None] * 2 else: self.widths = widths self.vvector = vvector self.name = name self.bbox = bbox if ligatures is None: self.ligatures = [] else: self.ligatures = ligatures class AFMtrackkern: def __init__(self, degree, min_ptsize, min_kern, max_ptsize, max_kern): self.degree = degree self.min_ptsize = min_ptsize self.min_kern = min_kern self.max_ptsize = max_ptsize self.max_kern = max_kern class AFMkernpair: def __init__(self, name1, name2, x, y): self.name1 = name1 self.name2 = name2 self.x = x self.y = y class AFMcomposite: def __init__(self, name, parts): self.name = name self.parts = parts class AFMfile(metric.metric): def __init__(self, file): self.afmversion = None # version, required self.metricssets = 0 # int, optional self.fontname = None # str, required self.fullname = None # str, optional self.familyname = None # str, optional self.weight = None # str, optional self.fontbbox = None # 4 floats, required self.version = None # str, optional self.notice = None # str, optional self.encodingscheme = None # str, optional self.mappingscheme = None # int, optional (not present in base font programs) self.escchar = None # int, required if mappingscheme == 3 self.characterset = None # str, optional self.characters = None # int, optional self.isbasefont = True # bool, optional self.vvector = None # 2 floats, required if metricssets == 2 self.isfixedv = None # bool, default: true if vvector present, false otherwise self.capheight = None # float, optional self.xheight = None # float, optional self.ascender = None # float, optional self.descender = None # float, optional self.stdhw = None # float, optional self.stdvw = None # float, optional self.underlinepositions = [None] * 2 # int, optional (for each direction) self.underlinethicknesses = [None] * 2 # float, optional (for each direction) self.italicangles = [None] * 2 # float, optional (for each direction) self.charwidths = [None] * 2 # 2 floats, optional (for each direction) self.isfixedpitchs = [None] * 2 # bool, optional (for each direction) self.expected_entries = None # if set, internal variable to verify number of expected entries in a section self.charmetrics = None # list of character metrics information, optional self.charmetricsdict = {} # helper dictionary mapping glyph names to character metrics information self.trackkerns = None # list of track kernings, optional self.kernpairs = [None] * 2 # list of list of kerning pairs (for each direction), optional self.kernpairsdict = {} # helper dictionary mapping glyph names to kerning pairs, first direction self.kernpairsdict1 = {} # helper dictionary mapping glyph names to kerning pairs, second direction self.composites = None # list of composite character data sets, optional self.parse(file) if self.isfixedv is None: self.isfixedv = self.vvector is not None # XXX we should check the constraints on some parameters # the following methods process a line when the reader is in the corresponding # state and return the new state def _processline_start(self, line): key, args = line.split(None, 1) if key != "StartFontMetrics": raise AFMError("Expecting StartFontMetrics, no found") self.afmversion = tuple(map(int, args.split("."))) return _READ_MAIN, None def _processline_main(self, line): try: key, args = line.split(None, 1) except ValueError: key = line args = None if key == "Comment": return _READ_MAIN, None elif key == "MetricsSets": self.metricssets = _parseint(args) if direction is not None: raise AFMError("MetricsSets not allowed after first (implicit) StartDirection") elif key == "FontName": self.fontname = _parsestr(args) elif key == "FullName": self.fullname = _parsestr(args) elif key == "FamilyName": self.familyname = _parsestr(args) elif key == "Weight": self.weight = _parsestr(args) elif key == "FontBBox": self.fontbbox = _parsefloats(args, 4) elif key == "Version": if args is not None: self.version = _parsestr(args) elif key == "Notice": self.notice = _parsestr(args) elif key == "EncodingScheme": self.encodingscheme = _parsestr(args) elif key == "MappingScheme": self.mappingscheme = _parseint(args) elif key == "EscChar": self.escchar = _parseint(args) elif key == "CharacterSet": self.characterset = _parsestr(args) elif key == "Characters": self.characters = _parseint(args) elif key == "IsBaseFont": self.isbasefont = _parsebool(args) elif key == "VVector": self.vvector = _parsefloats(args, 2) elif key == "IsFixedV": self.isfixedv = _parsebool(args) elif key == "CapHeight": self.capheight = _parsefloat(args) elif key == "XHeight": self.xheight = _parsefloat(args) elif key == "Ascender": self.ascender = _parsefloat(args) elif key == "Descender": self.descender = _parsefloat(args) elif key == "StdHW": self.stdhw = _parsefloat(args) elif key == "StdVW": self.stdvw = _parsefloat(args) elif key == "StartDirection": direction = _parseint(args) if 0 <= direction <= 2: return _READ_DIRECTION, direction else: raise AFMError("Wrong direction number %d" % direction) elif (key == "UnderlinePosition" or key == "UnderlineThickness" or key == "ItalicAngle" or key == "Charwidth" or key == "IsFixedPitch"): # we implicitly entered a direction section, so we should process the line again return self._processline_direction(line, 0) elif key == "StartCharMetrics": if self.charmetrics is not None: raise AFMError("Multiple character metrics sections") if self.afmversion >= (2, 0): self.expected_entries = _parseint(args) else: self.expected_entries = None self.charmetrics = [] return _READ_CHARMETRICS, 0 elif key == "StartKernData": return _READ_KERNDATA, None elif key == "StartComposites": if self.composites is not None: raise AFMError("Multiple composite character data sections") if args is not None: self.expected_entries = _parseint(args) else: self.expected_entries = None self.composites = [] return _READ_COMPOSITES, 0 elif key == "EndFontMetrics": return _READ_END, None elif key[0] in string.ascii_lowercase: # ignoring private commands pass else: # and according to the AFM specs also all other unknown keys pass return _READ_MAIN, None def _processline_direction(self, line, direction): try: key, args = line.split(None, 1) except ValueError: key = line.strip() if key == "UnderlinePosition": self.underlinepositions[direction] = _parsefloat(args) elif key == "UnderlineThickness": self.underlinethicknesses[direction] = _parsefloat(args) elif key == "ItalicAngle": self.italicangles[direction] = _parsefloat(args) elif key == "Charwidth": self.charwidths[direction] = _parsefloats(args, 2) elif key == "IsFixedPitch": self.isfixedpitchs[direction] = _parsebool(args) elif key == "EndDirection": return _READ_MAIN, None else: # we assume that we are implicitly leaving the direction section again, # so try to reprocess the line in the header reader state return self._processline_main(line) return _READ_DIRECTION, direction def _processline_charmetrics(self, line, charno): if line.rstrip() == "EndCharMetrics": if self.expected_entries is not None and charno != self.expected_entries: # This seems to be a rather common error in AFM files, so we do not raise # an exception here, but just graticiously accept the file pass # raise AFMError("Fewer character metrics than expected") return _READ_MAIN, None has_name = False char = None for s in line.split(";"): s = s.strip() if not s: continue key, args = s.split(None, 1) if key == "C": if char is not None: raise AFMError("Cannot define char code twice") char = AFMcharmetrics(_parseint(args)) elif key == "CH": if char is not None: raise AFMError("Cannot define char code twice") char = AFMcharmetrics(_parsehex(args)) elif key == "WX" or key == "W0X": char.widths[0] = _parsefloat(args), 0 elif key == "W1X": char.widths[1] = _parsefloat(args), 0 elif key == "WY" or key == "W0Y": char.widths[0] = 0, _parsefloat(args) elif key == "W1Y": char.widths[1] = 0, _parsefloat(args) elif key == "W" or key == "W0": char.widths[0] = _parsefloats(args, 2) elif key == "W1": char.widths[1] = _parsefloats(args, 2) elif key == "VV": char.vvector = _parsefloats(args, 2) elif key == "N": # XXX: we should check that name is valid (no whitespace, etc.) has_name = True char.name = _parsestr(args) elif key == "B": char.bbox = _parsefloats(args, 4) elif key == "L": successor, ligature = args.split(None, 1) char.ligatures.append((_parsestr(successor), ligature)) else: raise AFMError("Undefined command in character widths specification: '%s'", s) if char is None: raise AFMError("Character metrics not defined") self.charmetrics.append(char) if has_name: self.charmetricsdict[char.name] = char return _READ_CHARMETRICS, charno+1 def _processline_kerndata(self, line): try: key, args = line.split(None, 1) except ValueError: key = line args = None if key == "Comment": return _READ_KERNDATA, None if key == "StartTrackKern": if self.trackkerns is not None: raise AFMError("Multiple track kernings data sections") self.trackkerns = [None] * _parseint(args) return _READ_TRACKKERN, 0 elif key == "StartKernPairs" or key == "StartKernPairs0": if self.kernpairs[0] is not None: raise AFMError("Multiple kerning pairs data sections for direction 0") if args is not None: self.expected_entries = _parseint(args) else: self.expected_entries = None self.kernpairs[0] = [] return _READ_KERNPAIRS, (0, 0) elif key == "StartKernPairs1": if self.kernpairs[1] is not None: raise AFMError("Multiple kerning pairs data sections for direction 1") self.expected_entries = _parseint(args) self.kernpairs[1] = [] return _READ_KERNPAIRS, (1, 0) elif key == "EndKernData": return _READ_MAIN, None else: raise AFMError("Unsupported key %s in kerning data section" % key) def _processline_trackkern(self, line, i): try: key, args = line.split(None, 1) except ValueError: key = line if key == "Comment": return _READ_TRACKKERN, i elif key == "TrackKern": if i >= len(self.trackkerns): raise AFMError("More track kerning data sets than expected") degrees, args = args.split(None, 1) self.trackkerns[i] = AFMtrackkern(int(degrees), *_parsefloats(args, 4)) return _READ_TRACKKERN, i+1 elif key == "EndTrackKern": if i < len(self.trackkerns): raise AFMError("Fewer track kerning data sets than expected") return _READ_KERNDATA, None else: raise AFMError("Unsupported key %s in kerning data section" % key) def _processline_kernpairs(self, line, xxx_todo_changeme): (direction, i) = xxx_todo_changeme try: key, args = line.split(None, 1) except ValueError: key = line if key == "Comment": return _READ_KERNPAIRS, (direction, i) elif key == "EndKernPairs": if i != self.expected_entries: # This seems to be a rather common error in AFM files, so we do not raise # an exception here, but just graticiously accept the file pass # raise AFMError("Fewer kerning pairs than expected") return _READ_KERNDATA, None else: if key == "KP": try: name1, name2, x, y = args.split() except: raise AFMError("Expecting name1, name2, x, y, got '%s'" % args) x = _parsefloat(x) y = _parsefloat(y) elif key == "KPH": try: hex1, hex2, x, y = args.split() except: raise AFMError("Expecting , , x, y, got '%s'" % args) name1 = _parsehex(hex1) name2 = _parsehex(hex2) x = _parsefloat(x) y = _parsefloat(y) elif key == "KPX": try: name1, name2, x = args.split() except: raise AFMError("Expecting name1, name2, x, got '%s'" % args) x = _parsefloat(x) y = 0 elif key == "KPY": try: name1, name2, y = args.split() except: raise AFMError("Expecting name1, name2, y, got '%s'" % args) x = 0 y = _parsefloat(y) else: raise AFMError("Unknown key '%s' in kern pair section" % key) kernpair = AFMkernpair(name1, name2, x, y) self.kernpairs[direction].append(kernpair) if direction: self.kernpairsdict1[name1, name2] = kernpair else: self.kernpairsdict[name1, name2] = kernpair return _READ_KERNPAIRS, (direction, i+1) def _processline_composites(self, line, i): if line == "EndComposites": if self.expected_entries is not None and i != self.expected_entries: raise AFMError("Fewer composites than expected") return _READ_MAIN, None name = None no = None parts = [] for s in line.split(";"): s = s.strip() if not s: continue key, args = s.split(None, 1) if key == "CC": try: name, no = args.split() except: raise AFMError("Expecting name number, got '%s'" % args) no = _parseint(no) elif key == "PCC": try: name1, x, y = args.split() except: raise AFMError("Expecting name x y, got '%s'" % args) parts.append((name1, _parsefloat(x), _parsefloat(y))) else: raise AFMError("Unknown key '%s' in composite character data section" % key) if len(parts) != no: raise AFMError("Wrong number of composite characters") return _READ_COMPOSITES, i+1 def parse(self, f): # state of the reader, consisting of # - the main state, i.e. the type of the section # - a parameter sstate state = _READ_START, None # Note that we do a line by line processing here, since one # of the states (_READ_DIRECTION) can be entered implicitly, i.e. # without a corresponding StartDirection section and we thus # may need to reprocess a line in the context of the new state for line in f: line = line[:-1].strip() mstate, sstate = state if mstate == _READ_START: state = self._processline_start(line) else: # except for the first line, any empty will be ignored if not line: continue if mstate == _READ_MAIN: state = self._processline_main(line) elif mstate == _READ_DIRECTION: state = self._processline_direction(line, sstate) elif mstate == _READ_CHARMETRICS: state = self._processline_charmetrics(line, sstate) elif mstate == _READ_KERNDATA: state = self._processline_kerndata(line) elif mstate == _READ_TRACKKERN: state = self._processline_trackkern(line, sstate) elif mstate == _READ_KERNPAIRS: state = self._processline_kernpairs(line, sstate) elif mstate == _READ_COMPOSITES: state = self._processline_composites(line, sstate) else: raise AFMError("Undefined state in AFM reader") def width_ds(self, glyphname): return self.charmetricsdict[glyphname].widths[0][0] def width_pt(self, glyphnames, size_pt): return sum([self.charmetricsdict[glyphname].widths[0][0] for glyphname in glyphnames])*size_pt/1000.0 def height_pt(self, glyphnames, size_pt): return max([self.charmetricsdict[glyphname].bbox[3] for glyphname in glyphnames])*size_pt/1000.0 def depth_pt(self, glyphnames, size_pt): return min([self.charmetricsdict[glyphname].bbox[1] for glyphname in glyphnames])*size_pt/1000.0 def resolveligatures(self, glyphnames): i = 1 while i < len(glyphnames): for glyphname, replacement in self.charmetricsdict[glyphnames[i-1]].ligatures: if glyphname == glyphnames[i]: glyphnames[i-1] = replacement del glyphnames[i] break else: i += 1 return glyphnames def resolvekernings(self, glyphnames, size_pt=None): result = [None]*(2*len(glyphnames)-1) for i, glyphname in enumerate(glyphnames): result[2*i] = glyphname if i: kernpair = self.kernpairsdict.get((glyphnames[i-1], glyphname)) if kernpair: if size_pt is not None: result[2*i-1] = kernpair.x*size_pt/1000.0 else: result[2*i-1] = kernpair.x return result def writePDFfontinfo(self, file, seriffont=False, symbolfont=True): flags = 0 if self.isfixedpitchs[0]: flags += 1<<0 if seriffont: flags += 1<<1 if symbolfont: flags += 1<<2 else: flags += 1<<5 if self.italicangles[0]: flags += 1<<6 file.write("/Flags %d\n" % flags) if self.italicangles[0] is not None: file.write("/ItalicAngles %d\n" % self.italicangles[0]) if self.ascender is not None: ascent = self.ascender elif self.fontbbox is not None: ascent = self.fontbbox[3] else: ascent = 1000 # guessed default file.write("/Ascent %d\n" % ascent) if self.descender is not None: descent = self.descender elif self.fontbbox is not None: descent = self.fontbbox[3] else: descent = -200 # guessed default file.write("/Descent %d\n" % descent) if self.fontbbox is not None: file.write("/FontBBox [%d %d %d %d]\n" % tuple(self.fontbbox)) else: # the fontbbox is required, so we have to have to provide some default file.write("/FontBBox [0 %d 1000 %d]\n" % (descent, ascent)) if self.capheight is not None: file.write("/CapHeight %d\n" % self.capheight) else: # the CapHeight is required, so we have to have to provide some default file.write("/CapHeight %d\n" % ascent) if self.stdvw is not None: stemv = self.stdvw elif self.weight is not None and ("bold" in self.weight.lower() or "black" in self.weight.lower()): stemv = 120 # guessed default else: stemv = 70 # guessed default file.write("/StemV %d\n" % stemv) PyX-0.14.1/pyx/font/font.py0000644000076500000240000007361412520243764015657 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 Jörg Lehmann # Copyright (C) 2006-2011 Michael Schindler # Copyright (C) 2005-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import logging from pyx import bbox, baseclasses, deco, path, pswriter, pdfwriter, svgwriter, trafo, unit from . import t1file, afmfile logger = logging.getLogger("pyx") ############################################################################## # PS resources ############################################################################## class PST1file(pswriter.PSresource): """ PostScript font definition included in the prolog """ def __init__(self, t1file, glyphnames, charcodes): """ include type 1 font t1file stripped to the given glyphnames""" self.type = "t1file" self.t1file = t1file self.id = t1file.name self.glyphnames = set(glyphnames) self.charcodes = set(charcodes) def merge(self, other): self.glyphnames.update(other.glyphnames) self.charcodes.update(other.charcodes) def output(self, file, writer, registry): file.write("%%%%BeginFont: %s\n" % self.t1file.name) if writer.strip_fonts: if self.glyphnames: file.write("%%Included glyphs: %s\n" % " ".join(self.glyphnames)) if self.charcodes: file.write("%%Included charcodes: %s\n" % " ".join([str(charcode) for charcode in self.charcodes])) self.t1file.getstrippedfont(self.glyphnames, self.charcodes).outputPS(file, writer) else: self.t1file.outputPS(file, writer) file.write("\n%%EndFont\n") _ReEncodeFont = pswriter.PSdefinition("ReEncodeFont", b"""{ 5 dict begin /newencoding exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfontdict basefontdict maxlength dict def basefontdict { exch dup dup /FID ne exch /Encoding ne and { exch newfontdict 3 1 roll put } { pop pop } ifelse } forall newfontdict /FontName newfontname put newfontdict /Encoding newencoding put newfontname newfontdict definefont pop end }""") class PSreencodefont(pswriter.PSresource): """ reencoded PostScript font""" def __init__(self, basefontname, newfontname, encoding): """ reencode the font """ self.type = "reencodefont" self.basefontname = basefontname self.id = self.newfontname = newfontname self.encoding = encoding def output(self, file, writer, registry): file.write("%%%%BeginResource: %s\n" % self.newfontname) file.write("/%s /%s\n[" % (self.basefontname, self.newfontname)) vector = [None] * len(self.encoding) for glyphname, charcode in list(self.encoding.items()): vector[charcode] = glyphname for i, glyphname in enumerate(vector): if i: if not (i % 8): file.write("\n") else: file.write(" ") file.write("/%s" % glyphname) file.write("]\n") file.write("ReEncodeFont\n") file.write("%%EndResource\n") _ChangeFontMatrix = pswriter.PSdefinition("ChangeFontMatrix", b"""{ 5 dict begin /newfontmatrix exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfontdict basefontdict maxlength dict def basefontdict { exch dup dup /FID ne exch /FontMatrix ne and { exch newfontdict 3 1 roll put } { pop pop } ifelse } forall newfontdict /FontName newfontname put newfontdict /FontMatrix newfontmatrix readonly put newfontname newfontdict definefont pop end }""") class PSchangefontmatrix(pswriter.PSresource): """ change font matrix of a PostScript font""" def __init__(self, basefontname, newfontname, newfontmatrix): """ change the font matrix """ self.type = "changefontmatrix" self.basefontname = basefontname self.id = self.newfontname = newfontname self.newfontmatrix = newfontmatrix def output(self, file, writer, registry): file.write("%%%%BeginResource: %s\n" % self.newfontname) file.write("/%s /%s\n" % (self.basefontname, self.newfontname)) file.write(str(self.newfontmatrix)) file.write("\nChangeFontMatrix\n") file.write("%%EndResource\n") ############################################################################## # PDF resources ############################################################################## class PDFfont(pdfwriter.PDFobject): def __init__(self, fontname, basefontname, charcodes, fontdescriptor, encoding, metric): pdfwriter.PDFobject.__init__(self, "font", fontname) self.fontname = fontname self.basefontname = basefontname self.charcodes = set(charcodes) self.fontdescriptor = fontdescriptor self.encoding = encoding self.metric = metric def merge(self, other): self.charcodes.update(other.charcodes) def write(self, file, writer, registry): file.write("<<\n" "/Type /Font\n" "/Subtype /Type1\n") file.write("/Name /%s\n" % self.fontname) file.write("/BaseFont /%s\n" % self.basefontname) firstchar = min(self.charcodes) lastchar = max(self.charcodes) file.write("/FirstChar %d\n" % firstchar) file.write("/LastChar %d\n" % lastchar) file.write("/Widths\n" "[") if self.encoding: encoding = self.encoding.getvector() else: if self.fontdescriptor.fontfile.t1file.encoding is None: self.fontdescriptor.fontfile.t1file._encoding() encoding = self.fontdescriptor.fontfile.t1file.encoding for i in range(firstchar, lastchar+1): if i: if not (i % 8): file.write("\n") else: file.write(" ") if i in self.charcodes: if self.metric is not None: file.write("%i" % self.metric.width_ds(encoding[i])) else: file.write("%i" % self.fontdescriptor.fontfile.t1file.getglyphinfo(encoding[i])[0]) else: file.write("0") file.write(" ]\n") file.write("/FontDescriptor %d 0 R\n" % registry.getrefno(self.fontdescriptor)) if self.encoding: file.write("/Encoding %d 0 R\n" % registry.getrefno(self.encoding)) file.write(">>\n") class PDFstdfont(pdfwriter.PDFobject): def __init__(self, basename): pdfwriter.PDFobject.__init__(self, "font", "stdfont-%s" % basename) self.name = basename # name is ignored by acroread self.basename = basename def write(self, file, writer, registry): file.write("<>\n") # the 14 standard fonts that are always available in PDF PDFTimesRoman = PDFstdfont("Times-Roman") PDFTimesBold = PDFstdfont("Times-Bold") PDFTimesItalic = PDFstdfont("Times-Italic") PDFTimesBoldItalic = PDFstdfont("Times-BoldItalic") PDFHelvetica = PDFstdfont("Helvetica") PDFHelveticaBold = PDFstdfont("Helvetica-Bold") PDFHelveticaOblique = PDFstdfont("Helvetica-Oblique") PDFHelveticaBoldOblique = PDFstdfont("Helvetica-BoldOblique") PDFCourier = PDFstdfont("Courier") PDFCourierBold = PDFstdfont("Courier-Bold") PDFCourierOblique = PDFstdfont("Courier-Oblique") PDFCourierBoldOblique = PDFstdfont("Courier-BoldOblique") PDFSymbol = PDFstdfont("Symbol") PDFZapfDingbats = PDFstdfont("ZapfDingbats") class PDFfontdescriptor(pdfwriter.PDFobject): def __init__(self, fontname, fontfile, metric): pdfwriter.PDFobject.__init__(self, "fontdescriptor", fontname) self.fontname = fontname self.fontfile = fontfile self.metric = metric def write(self, file, writer, registry): file.write("<<\n" "/Type /FontDescriptor\n" "/FontName /%s\n" % self.fontname) if self.metric is not None: self.metric.writePDFfontinfo(file) else: self.fontfile.t1file.writePDFfontinfo(file) if self.fontfile is not None: file.write("/FontFile %d 0 R\n" % registry.getrefno(self.fontfile)) file.write(">>\n") class PDFfontfile(pdfwriter.PDFobject): def __init__(self, t1file, glyphnames, charcodes): pdfwriter.PDFobject.__init__(self, "fontfile", t1file.name) self.t1file = t1file self.glyphnames = set(glyphnames) self.charcodes = set(charcodes) def merge(self, other): self.glyphnames.update(other.glyphnames) self.charcodes.update(other.charcodes) def write(self, file, writer, registry): if writer.strip_fonts: self.t1file.getstrippedfont(self.glyphnames, self.charcodes).outputPDF(file, writer) else: self.t1file.outputPDF(file, writer) class PDFencoding(pdfwriter.PDFobject): def __init__(self, encoding, name): pdfwriter.PDFobject.__init__(self, "encoding", name) self.encoding = encoding def getvector(self): # As self.encoding might be appended after the constructur has set it, # we need to defer the calculation until the whole content was constructed. vector = [None] * len(self.encoding) for glyphname, charcode in list(self.encoding.items()): vector[charcode] = glyphname return vector def write(self, file, writer, registry): file.write("<<\n" "/Type /Encoding\n" "/Differences\n" "[0") for i, glyphname in enumerate(self.getvector()): if i: if not (i % 8): file.write("\n") else: file.write(" ") file.write("/%s" % glyphname) file.write("]\n" ">>\n") ############################################################################## # SVG resources ############################################################################## _glyphnames = {glyphname: str for str, glyphname in afmfile.unicodestring.items()} _charcodes = {i: chr(i) for i in range(32, 127)} # 0x20 (space) to 0x7e (tilde) class SVGT1mapping: def __init__(self, glyphnames, charcodes): # glyphnames and charcodes are not stored as sets, but are dicts # mapping the values to unicode characters. If the glyphnames and # charcodes are contained in _glyphnames and _charcodes, use those # values, otherwise use the private use areas A and B. self.private_glyphname = 0xf0000 self.private_charcode = 0x100000 self.glyphnames = {} self.charcodes = {} self.merge_glyphnames(glyphnames) self.merge_charcodes(charcodes) def merge_glyphnames(self, glyphnames): for glyphname in glyphnames: if glyphname not in self.glyphnames: if glyphname in _glyphnames: self.glyphnames[glyphname] = _glyphnames[glyphname] else: self.glyphnames[glyphname] = chr(self.private_glyphname) self.private_glyphname += 1 def merge_charcodes(self, charcodes): for charcode in charcodes: if charcode not in self.charcodes: if charcode in _charcodes: self.charcodes[charcode] = _charcodes[charcode] else: self.charcodes[charcode] = chr(self.private_charcode) self.private_charcode += 1 class SVGT1file(svgwriter.SVGresource, SVGT1mapping): """ PostScript font definition included in the prolog """ def __init__(self, t1file, glyphnames, charcodes): """ include type 1 font t1file stripped to the given glyphnames""" self.t1file = t1file svgwriter.SVGresource.__init__(self, "t1file", t1file.name) SVGT1mapping.__init__(self, glyphnames, charcodes) def merge(self, other): # Note that merging the glyphnames and charcodes does not alter # any existing mapping to the private use areas for self (but for # other). If you merge before use, the mapping by self.glyphnames # and self.charcodes is already updated and also copied to "other". self.merge_glyphnames(other.glyphnames.keys()) self.merge_charcodes(other.charcodes.keys()) other.glyphnames = self.glyphnames other.charcodes = self.charcodes def output(self, xml, writer, registry): xml.startSVGElement("font", {}) xml.startSVGElement("font-face", {"font-family": self.t1file.name}) xml.endSVGElement("font-face") for glyphname in self.glyphnames: glyphpath = self.t1file.getglyphpath_pt(0, 0, glyphname, 1000, convertcharcode=False) attrs = {"unicode": self.glyphnames[glyphname], "horiz-adv-x": "%f" % glyphpath.wx_pt, "d": glyphpath.path.returnSVGdata(inverse_y=False)} xml.startSVGElement("glyph", attrs) xml.endSVGElement("glyph") for charcode in self.charcodes: glyphpath = self.t1file.getglyphpath_pt(0, 0, charcode, 1000, convertcharcode=True) attrs = {"unicode": self.charcodes[charcode], "horiz-adv-x": "%f" % glyphpath.wx_pt, "d": glyphpath.path.returnSVGdata(inverse_y=False)} xml.startSVGElement("glyph", attrs) xml.endSVGElement("glyph") xml.endSVGElement("font") ############################################################################## # basic PyX text output ############################################################################## class font: def text(self, x, y, charcodes, size_pt, **kwargs): return self.text_pt(unit.topt(x), unit.topt(y), charcodes, size_pt, **kwargs) class T1font(font): def __init__(self, t1file, metric=None): self.t1file = t1file self.name = t1file.name self.metric = metric def text_pt(self, x, y, charcodes, size_pt, **kwargs): return T1text_pt(self, x, y, charcodes, size_pt, **kwargs) class T1builtinfont(T1font): def __init__(self, name, metric): self.name = name self.t1file = None self.metric = metric class selectedfont: def __init__(self, name, size_pt): self.name = name self.size_pt = size_pt def __ne__(self, other): return self.name != other.name or self.size_pt != other.size_pt def outputPS(self, file, writer): file.write("/%s %f selectfont\n" % (self.name, self.size_pt)) def outputPDF(self, file, writer): file.write("/%s %f Tf\n" % (self.name, self.size_pt)) class text_pt(baseclasses.canvasitem): def requiretextregion(self): return True class T1text_pt(text_pt): def __init__(self, font, x_pt, y_pt, charcodes, size_pt, decoding=afmfile.unicodestring, slant=None, ignorebbox=False, kerning=False, ligatures=False, spaced_pt=0): if decoding is not None: self.glyphnames = [decoding[character] for character in charcodes] self.decode = True else: self.charcodes = charcodes self.decode = False self.font = font self.x_pt = x_pt self.y_pt = y_pt self.size_pt = size_pt self.slant = slant self.ignorebbox = ignorebbox self.kerning = kerning self.ligatures = ligatures self.spaced_pt = spaced_pt self._textpath = None if self.kerning and not self.decode: raise ValueError("decoding required for font metric access (kerning)") if self.ligatures and not self.decode: raise ValueError("decoding required for font metric access (ligatures)") if self.ligatures: self.glyphnames = self.font.metric.resolveligatures(self.glyphnames) def bbox(self): if self.font.metric is None: logger.warning("We are about to extract the bounding box from the path of the text. This is slow and differs from the font metric information. You should provide an afm file whenever possible.") return self.textpath().bbox() if not self.decode: raise ValueError("decoding required for font metric access (bbox)") if self.kerning: kerning_correction = sum(value or 0 for i, value in enumerate(self.font.metric.resolvekernings(self.glyphnames, self.size_pt)) if i%2) else: kerning_correction = 0 return bbox.bbox_pt(self.x_pt, self.y_pt+self.font.metric.depth_pt(self.glyphnames, self.size_pt), self.x_pt+self.font.metric.width_pt(self.glyphnames, self.size_pt) + (len(self.glyphnames)-1)*self.spaced_pt + kerning_correction, self.y_pt+self.font.metric.height_pt(self.glyphnames, self.size_pt)) def getencodingname(self, encodings): """returns the name of the encoding (in encodings) mapping self.glyphnames to codepoints If no such encoding can be found or extended, a new encoding is added to encodings """ glyphnames = set(self.glyphnames) if len(glyphnames) > 256: raise ValueError("glyphs do not fit into one single encoding") for encodingname, encoding in list(encodings.items()): glyphsmissing = [] for glyphname in glyphnames: if glyphname not in list(encoding.keys()): glyphsmissing.append(glyphname) if len(glyphsmissing) + len(encoding) < 256: # new glyphs fit in existing encoding which will thus be extended for glyphname in glyphsmissing: encoding[glyphname] = len(encoding) return encodingname # create a new encoding for the glyphnames encodingname = "encoding%d" % len(encodings) encodings[encodingname] = dict([(glyphname, i) for i, glyphname in enumerate(glyphnames)]) return encodingname def textpath(self): if self._textpath is None: if self.decode: if self.kerning: data = self.font.metric.resolvekernings(self.glyphnames, self.size_pt) else: data = self.glyphnames else: data = self.charcodes self._textpath = path.path() x_pt = self.x_pt y_pt = self.y_pt for i, value in enumerate(data): if self.kerning and i % 2: if value is not None: x_pt += value else: if i: x_pt += self.spaced_pt glyphpath = self.font.t1file.getglyphpath_pt(x_pt, y_pt, value, self.size_pt, convertcharcode=not self.decode) self._textpath += glyphpath.path x_pt += glyphpath.wx_pt y_pt += glyphpath.wy_pt return self._textpath def processPS(self, file, writer, context, registry, bbox): if not self.ignorebbox: bbox += self.bbox() if writer.text_as_path and not self.font.t1file: logger.warning("Cannot output text as path when font not given by a font file (like for builtin fonts).") if writer.text_as_path and self.font.t1file: deco.decoratedpath(self.textpath(), fillstyles=[]).processPS(file, writer, context, registry, bbox) else: # register resources if self.font.t1file is not None: if self.decode: registry.add(PST1file(self.font.t1file, self.glyphnames, [])) else: registry.add(PST1file(self.font.t1file, [], self.charcodes)) fontname = self.font.name if self.decode: encodingname = self.getencodingname(writer.encodings.setdefault(self.font.name, {})) encoding = writer.encodings[self.font.name][encodingname] newfontname = "%s-%s" % (fontname, encodingname) registry.add(_ReEncodeFont) registry.add(PSreencodefont(fontname, newfontname, encoding)) fontname = newfontname if self.slant: newfontmatrix = trafo.trafo_pt(matrix=((1, self.slant), (0, 1))) if self.font.t1file is not None: newfontmatrix = newfontmatrix * self.font.t1file.fontmatrix newfontname = "%s-slant%f" % (fontname, self.slant) registry.add(_ChangeFontMatrix) registry.add(PSchangefontmatrix(fontname, newfontname, newfontmatrix)) fontname = newfontname # select font if necessary sf = selectedfont(fontname, self.size_pt) if context.selectedfont is None or sf != context.selectedfont: context.selectedfont = sf sf.outputPS(file, writer) file.write("%f %f moveto (" % (self.x_pt, self.y_pt)) if self.decode: if self.kerning: data = self.font.metric.resolvekernings(self.glyphnames, self.size_pt) else: data = self.glyphnames else: data = self.charcodes for i, value in enumerate(data): if self.kerning and i % 2: if value is not None: file.write(") show\n%f 0 rmoveto (" % (value+self.spaced_pt)) elif self.spaced_pt: file.write(") show\n%f 0 rmoveto (" % self.spaced_pt) else: if i and not self.kerning and self.spaced_pt: file.write(") show\n%f 0 rmoveto (" % self.spaced_pt) if self.decode: value = encoding[value] if 32 < value < 127 and chr(value) not in "()[]<>\\": file.write("%s" % chr(value)) else: file.write("\\%03o" % value) file.write(") show\n") def processPDF(self, file, writer, context, registry, bbox): if not self.ignorebbox: bbox += self.bbox() if writer.text_as_path and not self.font.t1file: logger.warning("Cannot output text as path when font not given by a font file (like for builtin fonts).") if writer.text_as_path and self.font.t1file: deco.decoratedpath(self.textpath(), fillstyles=[]).processPDF(file, writer, context, registry, bbox) else: if self.decode: encodingname = self.getencodingname(writer.encodings.setdefault(self.font.name, {})) encoding = writer.encodings[self.font.name][encodingname] charcodes = [encoding[glyphname] for glyphname in self.glyphnames] else: charcodes = self.charcodes # create resources fontname = self.font.name if self.decode: newfontname = "%s-%s" % (fontname, encodingname) _encoding = PDFencoding(encoding, newfontname) fontname = newfontname else: _encoding = None if self.font.t1file is not None: if self.decode: fontfile = PDFfontfile(self.font.t1file, self.glyphnames, []) else: fontfile = PDFfontfile(self.font.t1file, [], self.charcodes) else: fontfile = None fontdescriptor = PDFfontdescriptor(self.font.name, fontfile, self.font.metric) font = PDFfont(fontname, self.font.name, charcodes, fontdescriptor, _encoding, self.font.metric) # register resources if fontfile is not None: registry.add(fontfile) registry.add(fontdescriptor) if _encoding is not None: registry.add(_encoding) registry.add(font) registry.addresource("Font", fontname, font, procset="Text") if self.slant is None: slantvalue = 0 else: slantvalue = self.slant # select font if necessary sf = selectedfont(fontname, self.size_pt) if context.selectedfont is None or sf != context.selectedfont: context.selectedfont = sf sf.outputPDF(file, writer) # convert inter-character spacing to font units spaced = self.spaced_pt*1000/self.size_pt if self.kerning or spaced: file.write("1 0 %f 1 %f %f Tm [(" % (slantvalue, self.x_pt, self.y_pt)) else: file.write("1 0 %f 1 %f %f Tm (" % (slantvalue, self.x_pt, self.y_pt)) if self.decode: if self.kerning: data = self.font.metric.resolvekernings(self.glyphnames) else: data = self.glyphnames else: data = self.charcodes for i, value in enumerate(data): if self.kerning and i % 2: if value is not None: file.write(")%f(" % (-value-spaced)) elif spaced: file.write(")%f(" % (-spaced)) else: if i and not self.kerning and spaced: file.write(")%f(" % (-spaced)) if self.decode: value = encoding[value] if 32 <= value <= 127 and chr(value) not in "()[]<>\\": file.write("%s" % chr(value)) else: file.write("\\%03o" % value) if self.kerning or spaced: file.write(")] TJ\n") else: file.write(") Tj\n") def processSVG(self, xml, writer, context, registry, bbox): if not self.ignorebbox: bbox += self.bbox() # this is too common to be warned about as text_as_path is the # default for svg due to the missing font support by current browsers # # if writer.text_as_path and not self.font.t1file: # logger.warning("Cannot output text as path when font not given by a font file (like for builtin fonts).") if writer.text_as_path and self.font.t1file: deco.decoratedpath(self.textpath(), fillstyles=[]).processSVG(xml, writer, context, registry, bbox) else: if self.font.t1file is not None: if self.decode: t1mapping = SVGT1file(self.font.t1file, self.glyphnames, []) else: t1mapping = SVGT1file(self.font.t1file, [], self.charcodes) registry.add(t1mapping) else: if self.decode: t1mapping = SVGT1mapping(self.glyphnames, []) else: t1mapping = SVGT1mapping([], self.charcodes) fontname = self.font.name if self.decode: if self.kerning: data = self.font.metric.resolvekernings(self.glyphnames, self.size_pt) else: data = self.glyphnames else: data = self.charcodes attrs = {"x": "%f" % self.x_pt, "y": "%f" % -self.y_pt, "font-size": "%f" % self.size_pt, "font-family": fontname, "fill": context.fillcolor} if context.fillopacity: attrs["opacity"] = "%f" % context.fillopacity if self.slant: trafo.trafo_pt(matrix=((1, self.slant), (0, 1))).outputSVGattrs(attrs, writer, context, registry) xml.startSVGElement("text", attrs) tspan = False for i, value in enumerate(data): if self.kerning and i % 2: if value is not None: if tspan: xml.endSVGElement("tspan") xml.startSVGElement("tspan", {"dx": "%f" % (value + self.spaced_pt)}) tspan = True elif self.spaced_pt: if tspan: xml.endSVGElement("tspan") xml.startSVGElement("tspan", {"dx": "%f" % (self.spaced_pt)}) tspan = True else: if i and not self.kerning and self.spaced_pt: if tspan: xml.endSVGElement("tspan") xml.startSVGElement("tspan", {"dx": "%f" % (self.spaced_pt)}) tspan = True if self.decode: xml.characters(t1mapping.glyphnames[value]) else: xml.characters(t1mapping.charcodes[value]) if tspan: xml.endSVGElement("tspan") xml.endSVGElement("text") PyX-0.14.1/pyx/font/metric.py0000644000076500000240000000277212177540643016175 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA class metric: def width_ds(self, glyphname): raise NotImplementedError() def width_pt(self, glyphnames, size_pt): raise NotImplementedError() def height_pt(self, glyphnames, size_pt): raise NotImplementedError() def depth_pt(self, glyphnames, size_pt): raise NotImplementedError() def resolveligatures(self, glyphnames): return glyphnames def resolvekernings(self, glyphnames, size_pt=None): result = [None]*(2*len(glyphnames)-1) for i, glyphname in enumerate(glyphnames): result[2*i] = glyphname return result PyX-0.14.1/pyx/font/pfmfile.py0000644000076500000240000003370712177540643016336 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import struct, re from . import metric ansiglyphs = {"space": 32, "exclam": 33, "quotedbl": 34, "numbersign": 35, "dollar": 36, "percent": 37, "ampersand": 38, "quotesingle": 39, "parenleft": 40, "parenright": 41, "asterisk": 42, "plus": 43, "comma": 44, "hyphen": 45, "period": 46, "slash": 47, "zero": 48, "one": 49, "two": 50, "three": 51, "four": 52, "five": 53, "six": 54, "seven": 55, "eight": 56, "nine": 57, "colon": 58, "semicolon": 59, "less": 60, "equal": 61, "greater": 62, "question": 63, "at": 64, "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74, "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84, "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "bracketleft": 91, "backslash": 92, "bracketright": 93, "asciicircum": 94, "underscore": 95, "grave": 96, "a": 97, "b": 98, "c": 99, "d": 100, "e":101, "f":102, "g":103, "h":104, "i":105, "j":106, "k":107, "l":108, "m":109, "n":110, "o":111, "p":112, "q":113, "r":114, "s":115, "t":116, "u":117, "v":118, "w":119, "x":120, "y":121, "z":122, "braceleft":123, "bar":124, "braceright":125, "asciitilde":126, "bullet":127, "Euro":128, "bullet":129, "quotesinglbase":130, "florin":131, "quotedblbase":132, "ellipsis":133, "dagger":134, "daggerdbl":135, "circumflex":136, "perthousand":137, "Scaron":138, "guilsinglleft":139, "OE":140, "bullet":141, "Zcaron":142, "bullet":143, "bullet":144, "quoteleft":145, "quoteright":146, "quotedblleft":147, "quotedblright":148, "bullet":149, "endash":150, "emdash":151, "tilde":152, "trademark":153, "scaron":154, "guilsinglright":155, "oe":156, "bullet":157, "zcaron":158, "Ydieresis":159, "space":160, "exclamdown":161, "cent":162, "sterling":163, "currency":164, "yen":165, "brokenbar":166, "section":167, "dieresis":168, "copyright":169, "ordfeminine":170, "guillemotleft":171, "logicalnot":172, "hyphen":173, "registered":174, "macron":175, "degree":176, "plusminus":177, "twosuperior":178, "threesuperior":179, "acute":180, "mu":181, "paragraph":182, "periodcentered":183, "cedilla":184, "onesuperior":185, "ordmasculine":186, "guillemotright":187, "onequarter":188, "onehalf":189, "threequarters":190, "questiondown":191, "Agrave":192, "Aacute":193, "Acircumflex":194, "Atilde":195, "Adieresis":196, "Aring":197, "AE":198, "Ccedilla":199, "Egrave":200, "Eacute":201, "Ecircumflex":202, "Edieresis":203, "Igrave":204, "Iacute":205, "Icircumflex":206, "Idieresis":207, "Eth":208, "Ntilde":209, "Ograve":210, "Oacute":211, "Ocircumflex":212, "Otilde":213, "Odieresis":214, "multiply":215, "Oslash":216, "Ugrave":217, "Uacute":218, "Ucircumflex":219, "Udieresis":220, "Yacute":221, "Thorn":222, "germandbls":223, "agrave":224, "aacute":225, "acircumflex":226, "atilde":227, "adieresis":228, "aring":229, "ae":230, "ccedilla":231, "egrave":232, "eacute":233, "ecircumflex":234, "edieresis":235, "igrave":236, "iacute":237, "icircumflex":238, "idieresis":239, "eth":240, "ntilde":241, "ograve":242, "oacute":243, "ocircumflex":244, "otilde":245, "odieresis":246, "divide":247, "oslash":248, "ugrave":249, "uacute":250, "ucircumflex":251, "udieresis":252, "yacute":253, "thorn":254, "ydieresis":255} fontbboxpattern = re.compile("/FontBBox\s*\{\s*(?P(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+))\s*\}\s*(readonly\s+)?def") def _readNullString(file): s = [] c = file.read(1) while c and c != "\0": s.append(c) c = file.read(1) return "".join(s) class PFMfile(metric.metric): def __init__(self, file, t1file): # pfm is rather incomplete, the t1file instance can be used to fill the gap (self.dfVersion, self.dfSize, self.dfCopyright, self.dfType, self.dfPoint, self.dfVertRes, self.dfHorizRes, self.dfAscent, self.dfInternalLeading, self.dfExternalLeading, self.dfItalic, self.dfUnderline, self.dfStrikeOut, self.dfWeight, self.dfCharSet, self.dfPixWidth, self.dfPixHeight, self.dfPitchAndFamily, self.dfAvgWidth, self.dfMaxWidth, self.dfFirstChar, self.dfLastChar, self.dfDefaultChar, self.dfBreakChar, self.dfWidthBytes, self.dfDevice, self.dfFace, self.dfBitsPointer, self.dfBitsOffset) = struct.unpack("= 600: stemv = 120 else: stemv = 70 file.write("/StemV %d\n" % stemv) PyX-0.14.1/pyx/font/t1code.py0000644000076500000240000000310112177540643016054 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import array c1 = 52845 c1_16, c1_8 = divmod(c1, 0x100) # to avoid overflow (or conversion to the slow long integers) c2 = 22719 def decoder(code, r, n): plain = array.array("B") for x in array.array("B", code): plain.append(x ^ (r >> 8)) # r = ((x + r) * c1 + c2) & 0xffff # this might overflow r = ((((x + r) * c1_16) & 0xff) * 0x100 + (x + r) * c1_8 + c2) & 0xffff return plain.tobytes()[n:] def encoder(data, r, random): code = array.array("B") for x in array.array("B", random+data): code.append(x ^ (r>>8)) # r = ((code[-1] + r) * c1 + c2) & 0xffff # this might overflow r = ((((code[-1] + r) * c1_16) & 0xff) * 0x100 + (code[-1] + r) * c1_8 + c2) & 0xffff return code.tobytes() PyX-0.14.1/pyx/font/t1file.py0000644000076500000240000012432612534341145016067 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 André Wobst # Copyright (C) 2006-2011 Jörg Lehmann # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import array, binascii, io, logging, math, re try: import zlib haszlib = True except ImportError: haszlib = False logger = logging.getLogger("pyx") from pyx import trafo, reader, writer from pyx.path import path, moveto_pt, lineto_pt, curveto_pt, closepath try: from ._t1code import * except: from .t1code import * adobestandardencoding = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", None, "endash", "dagger", "daggerdbl", "periodcentered", None, "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", None, "questiondown", None, "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", None, "ring", "cedilla", None, "hungarumlaut", "ogonek", "caron", "emdash", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "AE", None, "ordfeminine", None, None, None, None, "Lslash", "Oslash", "OE", "ordmasculine", None, None, None, None, None, "ae", None, None, None, "dotlessi", None, None, "lslash", "oslash", "oe", "germandbls", None, None, None, None] class T1context: def __init__(self, t1font, flex=True): """context for T1cmd evaluation""" self.t1font = t1font # state description self.x = None self.y = None self.wx = None self.wy = None self.t1stack = [] self.psstack = [] self.flex = flex ###################################################################### # T1 commands # Note, that the T1 commands are variable-free except for plain number, # which are stored as integers. All other T1 commands exist as a single # instance only T1cmds = {} T1subcmds = {} class T1cmd: def __init__(self, code, subcmd=0): self.code = code self.subcmd = subcmd if subcmd: T1subcmds[code] = self else: T1cmds[code] = self def __str__(self): """returns a string representation of the T1 command""" raise NotImplementedError def updatepath(self, path, trafo, context): """update path instance applying trafo to the points""" raise NotImplementedError def gathercalls(self, seacglyphs, subrs, context): """gather dependancy information subrs is the "called-subrs" dictionary. gathercalls will insert the subr number as key having the value 1, i.e. subrs will become the numbers of used subrs. Similar seacglyphs will contain all glyphs in composite characters (subrs for those glyphs will also already be included). This method might will not properly update all information in the context (especially consuming values from the stack) and will also skip various tests for performance reasons. For most T1 commands it just doesn't need to do anything. """ pass # commands for starting and finishing class _T1endchar(T1cmd): def __init__(self): T1cmd.__init__(self, 14) def __str__(self): return "endchar" def updatepath(self, path, trafo, context): pass T1endchar = _T1endchar() class _T1hsbw(T1cmd): def __init__(self): T1cmd.__init__(self, 13) def __str__(self): return "hsbw" def updatepath(self, path, trafo, context): sbx = context.t1stack.pop(0) wx = context.t1stack.pop(0) path.append(moveto_pt(*trafo.apply_pt(sbx, 0))) context.x = sbx context.y = 0 context.wx = wx context.wy = 0 T1hsbw = _T1hsbw() class _T1seac(T1cmd): def __init__(self): T1cmd.__init__(self, 6, subcmd=1) def __str__(self): return "seac" def updatepath(self, path, atrafo, context): sab = context.t1stack.pop(0) adx = context.t1stack.pop(0) ady = context.t1stack.pop(0) bchar = context.t1stack.pop(0) achar = context.t1stack.pop(0) aglyph = adobestandardencoding[achar] bglyph = adobestandardencoding[bchar] context.t1font.updateglyphpath(bglyph, path, atrafo, context) atrafo = atrafo * trafo.translate_pt(adx-sab, ady) context.t1font.updateglyphpath(aglyph, path, atrafo, context) def gathercalls(self, seacglyphs, subrs, context): achar = context.t1stack.pop() bchar = context.t1stack.pop() aglyph = adobestandardencoding[achar] bglyph = adobestandardencoding[bchar] seacglyphs.add(aglyph) seacglyphs.add(bglyph) context.t1font.gatherglyphcalls(bglyph, seacglyphs, subrs, context) context.t1font.gatherglyphcalls(aglyph, seacglyphs, subrs, context) T1seac = _T1seac() class _T1sbw(T1cmd): def __init__(self): T1cmd.__init__(self, 7, subcmd=1) def __str__(self): return "sbw" def updatepath(self, path, trafo, context): sbx = context.t1stack.pop(0) sby = context.t1stack.pop(0) wx = context.t1stack.pop(0) wy = context.t1stack.pop(0) path.append(moveto_pt(*trafo.apply_pt(sbx, sby))) context.x = sbx context.y = sby context.wx = wx context.wy = wy T1sbw = _T1sbw() # path construction commands class _T1closepath(T1cmd): def __init__(self): T1cmd.__init__(self, 9) def __str__(self): return "closepath" def updatepath(self, path, trafo, context): path.append(closepath()) # The closepath in T1 is different from PostScripts in that it does # *not* modify the current position; hence we need to add an additional # moveto here ... path.append(moveto_pt(*trafo.apply_pt(context.x, context.y))) T1closepath = _T1closepath() class _T1hlineto(T1cmd): def __init__(self): T1cmd.__init__(self, 6) def __str__(self): return "hlineto" def updatepath(self, path, trafo, context): dx = context.t1stack.pop(0) path.append(lineto_pt(*trafo.apply_pt(context.x + dx, context.y))) context.x += dx T1hlineto = _T1hlineto() class _T1hmoveto(T1cmd): def __init__(self): T1cmd.__init__(self, 22) def __str__(self): return "hmoveto" def updatepath(self, path, trafo, context): dx = context.t1stack.pop(0) path.append(moveto_pt(*trafo.apply_pt(context.x + dx, context.y))) context.x += dx T1hmoveto = _T1hmoveto() class _T1hvcurveto(T1cmd): def __init__(self): T1cmd.__init__(self, 31) def __str__(self): return "hvcurveto" def updatepath(self, path, trafo, context): dx1 = context.t1stack.pop(0) dx2 = context.t1stack.pop(0) dy2 = context.t1stack.pop(0) dy3 = context.t1stack.pop(0) path.append(curveto_pt(*(trafo.apply_pt(context.x + dx1, context.y) + trafo.apply_pt(context.x + dx1 + dx2, context.y + dy2) + trafo.apply_pt(context.x + dx1 + dx2, context.y + dy2 + dy3)))) context.x += dx1+dx2 context.y += dy2+dy3 T1hvcurveto = _T1hvcurveto() class _T1rlineto(T1cmd): def __init__(self): T1cmd.__init__(self, 5) def __str__(self): return "rlineto" def updatepath(self, path, trafo, context): dx = context.t1stack.pop(0) dy = context.t1stack.pop(0) path.append(lineto_pt(*trafo.apply_pt(context.x + dx, context.y + dy))) context.x += dx context.y += dy T1rlineto = _T1rlineto() class _T1rmoveto(T1cmd): def __init__(self): T1cmd.__init__(self, 21) def __str__(self): return "rmoveto" def updatepath(self, path, trafo, context): dx = context.t1stack.pop(0) dy = context.t1stack.pop(0) path.append(moveto_pt(*trafo.apply_pt(context.x + dx, context.y + dy))) context.x += dx context.y += dy T1rmoveto = _T1rmoveto() class _T1rrcurveto(T1cmd): def __init__(self): T1cmd.__init__(self, 8) def __str__(self): return "rrcurveto" def updatepath(self, path, trafo, context): dx1 = context.t1stack.pop(0) dy1 = context.t1stack.pop(0) dx2 = context.t1stack.pop(0) dy2 = context.t1stack.pop(0) dx3 = context.t1stack.pop(0) dy3 = context.t1stack.pop(0) path.append(curveto_pt(*(trafo.apply_pt(context.x + dx1, context.y + dy1) + trafo.apply_pt(context.x + dx1 + dx2, context.y + dy1 + dy2) + trafo.apply_pt(context.x + dx1 + dx2 + dx3, context.y + dy1 + dy2 + dy3)))) context.x += dx1+dx2+dx3 context.y += dy1+dy2+dy3 T1rrcurveto = _T1rrcurveto() class _T1vlineto(T1cmd): def __init__(self): T1cmd.__init__(self, 7) def __str__(self): return "vlineto" def updatepath(self, path, trafo, context): dy = context.t1stack.pop(0) path.append(lineto_pt(*trafo.apply_pt(context.x, context.y + dy))) context.y += dy T1vlineto = _T1vlineto() class _T1vmoveto(T1cmd): def __init__(self): T1cmd.__init__(self, 4) def __str__(self): return "vmoveto" def updatepath(self, path, trafo, context): dy = context.t1stack.pop(0) path.append(moveto_pt(*trafo.apply_pt(context.x, context.y + dy))) context.y += dy T1vmoveto = _T1vmoveto() class _T1vhcurveto(T1cmd): def __init__(self): T1cmd.__init__(self, 30) def __str__(self): return "vhcurveto" def updatepath(self, path, trafo, context): dy1 = context.t1stack.pop(0) dx2 = context.t1stack.pop(0) dy2 = context.t1stack.pop(0) dx3 = context.t1stack.pop(0) path.append(curveto_pt(*(trafo.apply_pt(context.x, context.y + dy1) + trafo.apply_pt(context.x + dx2, context.y + dy1 + dy2) + trafo.apply_pt(context.x + dx2 + dx3, context.y + dy1 + dy2)))) context.x += dx2+dx3 context.y += dy1+dy2 T1vhcurveto = _T1vhcurveto() # hint commands class _T1dotsection(T1cmd): def __init__(self): T1cmd.__init__(self, 0, subcmd=1) def __str__(self): return "dotsection" def updatepath(self, path, trafo, context): pass T1dotsection = _T1dotsection() class _T1hstem(T1cmd): def __init__(self): T1cmd.__init__(self, 1) def __str__(self): return "hstem" def updatepath(self, path, trafo, context): y = context.t1stack.pop(0) dy = context.t1stack.pop(0) T1hstem = _T1hstem() class _T1hstem3(T1cmd): def __init__(self): T1cmd.__init__(self, 2, subcmd=1) def __str__(self): return "hstem3" def updatepath(self, path, trafo, context): y0 = context.t1stack.pop(0) dy0 = context.t1stack.pop(0) y1 = context.t1stack.pop(0) dy1 = context.t1stack.pop(0) y2 = context.t1stack.pop(0) dy2 = context.t1stack.pop(0) T1hstem3 = _T1hstem3() class _T1vstem(T1cmd): def __init__(self): T1cmd.__init__(self, 3) def __str__(self): return "vstem" def updatepath(self, path, trafo, context): x = context.t1stack.pop(0) dx = context.t1stack.pop(0) T1vstem = _T1vstem() class _T1vstem3(T1cmd): def __init__(self): T1cmd.__init__(self, 1, subcmd=1) def __str__(self): return "vstem3" def updatepath(self, path, trafo, context): self.x0 = context.t1stack.pop(0) self.dx0 = context.t1stack.pop(0) self.x1 = context.t1stack.pop(0) self.dx1 = context.t1stack.pop(0) self.x2 = context.t1stack.pop(0) self.dx2 = context.t1stack.pop(0) T1vstem3 = _T1vstem3() # arithmetic command class _T1div(T1cmd): def __init__(self): T1cmd.__init__(self, 12, subcmd=1) def __str__(self): return "div" def updatepath(self, path, trafo, context): num2 = context.t1stack.pop() num1 = context.t1stack.pop() context.t1stack.append(divmod(num1, num2)[0]) def gathercalls(self, seacglyphs, subrs, context): num2 = context.t1stack.pop() num1 = context.t1stack.pop() context.t1stack.append(divmod(num1, num2)[0]) T1div = _T1div() # subroutine commands class _T1callothersubr(T1cmd): def __init__(self): T1cmd.__init__(self, 16, subcmd=1) def __str__(self): return "callothersubr" def updatepath(self, path, trafo, context): othersubrnumber = context.t1stack.pop() n = context.t1stack.pop() for i in range(n): context.psstack.append(context.t1stack.pop(0)) if othersubrnumber == 0: flex_size, x, y = context.psstack[-3:] if context.flex: x1, y1, x2, y2, x3, y3 = context.psstack[2:8] x1, y1 = trafo.apply_pt(x1, y1) x2, y2 = trafo.apply_pt(x2, y2) x3, y3 = trafo.apply_pt(x3, y3) path.append(curveto_pt(x1, y1, x2, y2, x3, y3)) x1, y1, x2, y2, x3, y3 = context.psstack[8:14] x1, y1 = trafo.apply_pt(x1, y1) x2, y2 = trafo.apply_pt(x2, y2) x3, y3 = trafo.apply_pt(x3, y3) path.append(curveto_pt(x1, y1, x2, y2, x3, y3)) else: path.append(lineto_pt(*trafo.apply_pt(x, y))) context.psstack = [y, x] elif othersubrnumber == 1: pass elif othersubrnumber == 2: path.pathitems.pop() context.psstack.append(context.x) context.psstack.append(context.y) def gathercalls(self, seacglyphs, subrs, context): othersubrnumber = context.t1stack.pop() n = context.t1stack.pop() context.psstack.extend([context.t1stack.pop() for i in range(n)][::-1]) T1callothersubr = _T1callothersubr() class _T1callsubr(T1cmd): def __init__(self): T1cmd.__init__(self, 10) def __str__(self): return "callsubr" def updatepath(self, path, trafo, context): subr = context.t1stack.pop() context.t1font.updatesubrpath(subr, path, trafo, context) def gathercalls(self, seacglyphs, subrs, context): subr = context.t1stack.pop() subrs.add(subr) context.t1font.gathersubrcalls(subr, seacglyphs, subrs, context) T1callsubr = _T1callsubr() class _T1pop(T1cmd): def __init__(self): T1cmd.__init__(self, 17, subcmd=1) def __str__(self): return "pop" def updatepath(self, path, trafo, context): context.t1stack.append(context.psstack.pop()) def gathercalls(self, seacglyphs, subrs, context): context.t1stack.append(context.psstack.pop()) T1pop = _T1pop() class _T1return(T1cmd): def __init__(self): T1cmd.__init__(self, 11) def __str__(self): return "return" def updatepath(self, path, trafo, context): pass T1return = _T1return() class _T1setcurrentpoint(T1cmd): def __init__(self): T1cmd.__init__(self, 33, subcmd=1) def __str__(self): return "setcurrentpoint" def updatepath(self, path, trafo, context): context.x = context.t1stack.pop(0) context.y = context.t1stack.pop(0) T1setcurrentpoint = _T1setcurrentpoint() ###################################################################### class T1file: eexecr = 55665 charstringr = 4330 fontnamepattern = re.compile("/FontName\s+/(.*?)\s+def\s+") fontmatrixpattern = re.compile("/FontMatrix\s*\[\s*(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+)\s+(-?[0-9.]+)\s*\]\s*(readonly\s+)?def") def __init__(self, data1, data2eexec, data3): """initializes a t1font instance data1 and data3 are the two clear text data parts and data2 is the binary data part""" self.data1 = data1 self._data2eexec = data2eexec self.data3 = data3 # marker and value for decoded data self._data2 = None # note that data2eexec is set to none by setsubrcmds and setglyphcmds # this *also* denotes, that data2 is out-of-date; hence they are both # marked by an _ and getdata2 and getdata2eexec will properly resolve # the current state of decoding ... # marker and value for standard encoding check self.encoding = None self.name, = self.fontnamepattern.search(self.data1).groups() m11, m12, m21, m22, v1, v2 = list(map(float, self.fontmatrixpattern.search(self.data1).groups()[:6])) self.fontmatrix = trafo.trafo_pt(matrix=((m11, m12), (m21, m22)), vector=(v1, v2)) def _eexecdecode(self, code): """eexec decoding of code""" return decoder(code, self.eexecr, 4) def _charstringdecode(self, code): """charstring decoding of code""" return decoder(code, self.charstringr, self.lenIV) def _eexecencode(self, data): """eexec encoding of data""" return encoder(data, self.eexecr, b"PyX!") def _charstringencode(self, data): """eexec encoding of data""" return encoder(data, self.charstringr, b"PyX!"[:self.lenIV]) def _encoding(self): """helper method to lookup the encoding in the font""" c = reader.PStokenizer(self.data1, "/Encoding") token1 = c.gettoken() token2 = c.gettoken() if token1 == "StandardEncoding" and token2 == "def": self.encoding = adobestandardencoding else: self.encoding = [None]*256 while True: self.encodingstart = c.pos if c.gettoken() == "dup": break while True: i = c.getint() glyph = c.gettoken() if 0 <= i < 256: self.encoding[i] = glyph[1:] token = c.gettoken(); assert token == "put" self.encodingend = c.pos token = c.gettoken() if token == "readonly" or token == "def": break assert token == "dup" lenIVpattern = re.compile(b"/lenIV\s+(\d+)\s+def\s+") flexhintsubrs = [[3, 0, T1callothersubr, T1pop, T1pop, T1setcurrentpoint, T1return], [0, 1, T1callothersubr, T1return], [0, 2, T1callothersubr, T1return], [T1return]] def _data2decode(self): """decodes data2eexec to the data2 string and the subr and glyphs dictionary It doesn't make sense to call this method twice -- check the content of data2 before calling. The method also keeps the subrs and charstrings start and end positions for later use.""" self._data2 = self._eexecdecode(self._data2eexec) m = self.lenIVpattern.search(self._data2) if m: self.lenIV = int(m.group(1)) else: self.lenIV = 4 self.emptysubr = self._charstringencode(b"\x0b") # 11, i.e. return # extract Subrs c = reader.PSbytes_tokenizer(self._data2, b"/Subrs") self.subrsstart = c.pos arraycount = c.getint() token = c.gettoken(); assert token == b"array" self.subrs = [] for i in range(arraycount): token = c.gettoken(); assert token == b"dup" token = c.getint(); assert token == i size = c.getint() if not i: self.subrrdtoken = c.gettoken() else: token = c.gettoken(); assert token == self.subrrdtoken self.subrs.append(c.getbytes(size)) token = c.gettoken() if token == b"noaccess": token = token + b" " + c.gettoken() if not i: self.subrnptoken = token else: assert token == self.subrnptoken self.subrsend = c.pos # hasflexhintsubrs is a boolean indicating that the font uses flex or # hint replacement subrs as specified by Adobe (tm). When it does, the # first 4 subrs should all be copied except when none of them are used # in the stripped version of the font since we then get a font not # using flex or hint replacement subrs at all. self.hasflexhintsubrs = (arraycount >= len(self.flexhintsubrs) and [self.getsubrcmds(i) for i in range(len(self.flexhintsubrs))] == self.flexhintsubrs) # extract glyphs self.glyphs = {} self.glyphlist = [] # we want to keep the order of the glyph names c = reader.PSbytes_tokenizer(self._data2, b"/CharStrings") self.charstringsstart = c.pos c.getint() token = c.gettoken(); assert token == b"dict" token = c.gettoken(); assert token == b"dup" token = c.gettoken(); assert token == b"begin" first = True while True: chartoken = c.gettoken().decode("ascii") if chartoken == "end": break assert chartoken[0] == "/" size = c.getint() if first: self.glyphrdtoken = c.gettoken() else: token = c.gettoken(); assert token == self.glyphrdtoken self.glyphlist.append(chartoken[1:]) self.glyphs[chartoken[1:]] = c.getbytes(size) if first: self.glyphndtoken = c.gettoken() else: token = c.gettoken(); assert token == self.glyphndtoken first = False self.charstringsend = c.pos assert not self.subrs or self.subrrdtoken == self.glyphrdtoken def _cmds(self, code): """return a list of T1cmd's for encoded charstring data in code""" code = array.array("B", self._charstringdecode(code)) cmds = [] while code: x = code.pop(0) if x == 12: # this starts an escaped cmd cmds.append(T1subcmds[code.pop(0)]) elif 0 <= x < 32: # those are cmd's cmds.append(T1cmds[x]) elif 32 <= x <= 246: # short ints cmds.append(x-139) elif 247 <= x <= 250: # mid size ints cmds.append(((x - 247)*256) + code.pop(0) + 108) elif 251 <= x <= 254: # mid size ints cmds.append(-((x - 251)*256) - code.pop(0) - 108) else: # x = 255, i.e. full size ints y = ((code.pop(0)*256+code.pop(0))*256+code.pop(0))*256+code.pop(0) if y > (1 << 31): cmds.append(y - (1 << 32)) else: cmds.append(y) return cmds def _code(self, cmds): """return an encoded charstring data for list of T1cmd's in cmds""" code = array.array("B") for cmd in cmds: try: if cmd.subcmd: code.append(12) code.append(cmd.code) except AttributeError: if -107 <= cmd <= 107: code.append(cmd+139) elif 108 <= cmd <= 1131: a, b = divmod(cmd-108, 256) code.append(a+247) code.append(b) elif -1131 <= cmd <= -108: a, b = divmod(-cmd-108, 256) code.append(a+251) code.append(b) else: if cmd < 0: cmd += 1 << 32 cmd, x4 = divmod(cmd, 256) cmd, x3 = divmod(cmd, 256) x1, x2 = divmod(cmd, 256) code.append(255) code.append(x1) code.append(x2) code.append(x3) code.append(x4) return self._charstringencode(code.tobytes()) def getsubrcmds(self, subr): """return a list of T1cmd's for subr subr""" if not self._data2: self._data2decode() return self._cmds(self.subrs[subr]) def getglyphcmds(self, glyph): """return a list of T1cmd's for glyph glyph""" if not self._data2: self._data2decode() return self._cmds(self.glyphs[glyph]) def setsubrcmds(self, subr, cmds): """replaces the T1cmd's by the list cmds for subr subr""" if not self._data2: self._data2decode() self._data2eexec = None self.subrs[subr] = self._code(cmds) def setglyphcmds(self, glyph, cmds): """replaces the T1cmd's by the list cmds for glyph glyph""" if not self._data2: self._data2decode() self._data2eexec = None self.glyphs[glyph] = self._code(cmds) def updatepath(self, cmds, path, trafo, context): for cmd in cmds: if isinstance(cmd, T1cmd): cmd.updatepath(path, trafo, context) else: context.t1stack.append(cmd) def updatesubrpath(self, subr, path, trafo, context): self.updatepath(self.getsubrcmds(subr), path, trafo, context) def updateglyphpath(self, glyph, path, trafo, context): self.updatepath(self.getglyphcmds(glyph), path, trafo, context) def gathercalls(self, cmds, seacglyphs, subrs, context): for cmd in cmds: if isinstance(cmd, T1cmd): cmd.gathercalls(seacglyphs, subrs, context) else: context.t1stack.append(cmd) def gathersubrcalls(self, subr, seacglyphs, subrs, context): self.gathercalls(self.getsubrcmds(subr), seacglyphs, subrs, context) def gatherglyphcalls(self, glyph, seacglyphs, subrs, context): self.gathercalls(self.getglyphcmds(glyph), seacglyphs, subrs, context) def getglyphpath_pt(self, x_pt, y_pt, glyph, size_pt, convertcharcode=False, flex=True): """return an object containing the PyX path, wx_pt and wy_pt for glyph named glyph""" if convertcharcode: if not self.encoding: self._encoding() glyph = self.encoding[glyph] t = self.fontmatrix.scaled(size_pt) tpath = t.translated_pt(x_pt, y_pt) context = T1context(self, flex=flex) p = path() self.updateglyphpath(glyph, p, tpath, context) class glyphpath: def __init__(self, p, wx_pt, wy_pt): self.path = p self.wx_pt = wx_pt self.wy_pt = wy_pt return glyphpath(p, *t.apply_pt(context.wx, context.wy)) def getdata2(self, subrs=None, glyphs=None): """makes a data2 string subrs is a dict containing those subrs numbers as keys, which are to be contained in the subrsstring to be created. If subrs is None, all subrs in self.subrs will be used. The subrs dict might be modified *in place*. glyphs is a dict containing those glyph names as keys, which are to be contained in the charstringsstring to be created. If glyphs is None, all glyphs in self.glyphs will be used.""" w = writer.writer(io.BytesIO()) def addsubrs(subrs): if subrs is not None: # some adjustments to the subrs dict if subrs: subrsmin = min(subrs) subrsmax = max(subrs) if self.hasflexhintsubrs and subrsmin < len(self.flexhintsubrs): # According to the spec we need to keep all the flex and hint subrs # as long as any of it is used. for subr in range(len(self.flexhintsubrs)): subrs.add(subr) subrsmax = max(subrs) else: subrsmax = -1 else: # build a new subrs dict containing all subrs subrs = dict([(subr, 1) for subr in range(len(self.subrs))]) subrsmax = len(self.subrs) - 1 # build the string from all selected subrs w.write("%d array\n" % (subrsmax + 1)) for subr in range(subrsmax+1): if subr in subrs: code = self.subrs[subr] else: code = self.emptysubr w.write("dup %d %d " % (subr, len(code))) w.write_bytes(self.subrrdtoken) w.write_bytes(b" ") w.write_bytes(code) w.write_bytes(b" ") w.write_bytes(self.subrnptoken) w.write_bytes(b"\n") def addcharstrings(glyphs): w.write("%d dict dup begin\n" % (glyphs is None and len(self.glyphlist) or len(glyphs))) for glyph in self.glyphlist: if glyphs is None or glyph in glyphs: w.write("/%s %d " % (glyph, len(self.glyphs[glyph]))) w.write_bytes(self.glyphrdtoken) w.write_bytes(b" ") w.write_bytes(self.glyphs[glyph]) w.write_bytes(b" ") w.write_bytes(self.glyphndtoken) w.write_bytes(b"\n") w.write("end\n") if self.subrsstart < self.charstringsstart: w.write_bytes(self._data2[:self.subrsstart]) addsubrs(subrs) w.write_bytes(self._data2[self.subrsend:self.charstringsstart]) addcharstrings(glyphs) w.write_bytes(self._data2[self.charstringsend:]) else: w.write_bytes(self._data2[:self.charstringsstart]) addcharstrings(glyphs) w.write_bytes(self._data2[self.charstringsend:self.subrsstart]) addsubrs(subrs) w.write_bytes(self._data2[self.subrsend:]) return w.file.getvalue() def getdata2eexec(self): if self._data2eexec: return self._data2eexec # note that self._data2 is out-of-date here too, hence we need to call getdata2 return self._eexecencode(self.getdata2()) newlinepattern = re.compile("\s*[\r\n]\s*") uniqueidstrpattern = re.compile("%?/UniqueID\s+\d+\s+def\s+") uniqueidbytespattern = re.compile(b"%?/UniqueID\s+\d+\s+def\s+") # when UniqueID is commented out (as in modern latin), prepare to remove the comment character as well def getstrippedfont(self, glyphs, charcodes): """create a T1file instance containing only certain glyphs glyphs is a set of the glyph names. It might be modified *in place*! """ if not self.encoding: self._encoding() for charcode in charcodes: glyphs.add(self.encoding[charcode]) # collect information about used glyphs and subrs seacglyphs = set() subrs = set() for glyph in glyphs: self.gatherglyphcalls(glyph, seacglyphs, subrs, T1context(self)) # while we have gathered all subrs for the seacglyphs alreadys, we # might have missed the glyphs themself (when they are not used stand-alone) glyphs.update(seacglyphs) glyphs.add(".notdef") # strip data1 if self.encoding is adobestandardencoding: data1 = self.data1 else: encodingstrings = [] for char, glyph in enumerate(self.encoding): if glyph in glyphs: encodingstrings.append("dup %i /%s put\n" % (char, glyph)) data1 = self.data1[:self.encodingstart] + "\n" + "".join(encodingstrings) + self.data1[self.encodingend:] data1 = self.newlinepattern.subn("\n", data1)[0] data1 = self.uniqueidstrpattern.subn("", data1)[0] # strip data2 data2 = self.uniqueidbytespattern.subn(b"", self.getdata2(subrs, glyphs))[0] # strip data3 data3 = self.newlinepattern.subn("\n", self.data3)[0] # create and return the new font instance return T1file(data1.rstrip() + "\n", self._eexecencode(data2), data3.rstrip() + "\n") # The following two methods, writePDFfontinfo and getglyphinfo, # extract informtion which should better be taken from the afm file. def writePDFfontinfo(self, file): try: glyphinfo_y = self.getglyphinfo("y") glyphinfo_W = self.getglyphinfo("W") glyphinfo_H = self.getglyphinfo("H") glyphinfo_h = self.getglyphinfo("h") glyphinfo_period = self.getglyphinfo("period") glyphinfo_colon = self.getglyphinfo("colon") except: logger.warning("Auto-guessing of font information for font '%s' failed. We're writing stub data instead." % self.name) file.write("/Flags 4\n") file.write("/FontBBox [0 -100 1000 1000]\n") file.write("/ItalicAngle 0\n") file.write("/Ascent 1000\n") file.write("/Descent -100\n") file.write("/CapHeight 700\n") file.write("/StemV 100\n") else: if not self.encoding: self._encoding() # As a simple heuristics we assume non-symbolic fonts if and only # if the Adobe standard encoding is used. All other font flags are # not specified here. if self.encoding is adobestandardencoding: file.write("/Flags 32\n") else: file.write("/Flags 4\n") file.write("/FontBBox [0 %f %f %f]\n" % (glyphinfo_y[3], glyphinfo_W[0], glyphinfo_H[5])) file.write("/ItalicAngle %f\n" % math.degrees(math.atan2(glyphinfo_period[4]-glyphinfo_colon[4], glyphinfo_colon[5]-glyphinfo_period[5]))) file.write("/Ascent %f\n" % glyphinfo_H[5]) file.write("/Descent %f\n" % glyphinfo_y[3]) file.write("/CapHeight %f\n" % glyphinfo_h[5]) file.write("/StemV %f\n" % (glyphinfo_period[4]-glyphinfo_period[2])) def getglyphinfo(self, glyph, flex=True): logger.warning("We are about to extract font information for the Type 1 font '%s' from its pfb file. This is bad practice (and it's slow). You should use an afm file instead." % self.name) context = T1context(self, flex=flex) p = path() self.updateglyphpath(glyph, p, trafo.trafo(), context) bbox = p.bbox() return context.wx, context.wy, bbox.llx_pt, bbox.lly_pt, bbox.urx_pt, bbox.ury_pt def outputPFA(self, file, remove_UniqueID_lookup=False): """output the T1file in PFA format""" data1 = self.data1 data3 = self.data3 if remove_UniqueID_lookup: m1 = re.search("""FontDirectory\s*/%(name)s\s+known{/%(name)s\s+findfont\s+dup\s*/UniqueID\s+known\s*{\s*dup\s* /UniqueID\s+get\s+\d+\s+eq\s+exch\s*/FontType\s+get\s+1\s+eq\s+and\s*}\s*{\s*pop\s+false\s*}\s*ifelse\s* {save\s+true\s*}\s*{\s*false\s*}\s*ifelse\s*}\s*{\s*false\s*}\s*ifelse""" % {"name": self.name}, data1, re.VERBOSE) m3 = re.search("\s*{restore}\s*if", data3) if m1 and m3: data1 = data1[:m1.start()] + data1[m1.end():] data3 = data3[:m3.start()] + data3[m3.end():] file.write(data1) data2eexechex = binascii.b2a_hex(self.getdata2eexec()) linelength = 64 for i in range((len(data2eexechex)-1)//linelength + 1): file.write_bytes(data2eexechex[i*linelength: i*linelength+linelength]) file.write("\n") file.write(data3) def outputPFB(self, file): """output the T1file in PFB format""" data2eexec = self.getdata2eexec() def pfblength(data): l = len(data) l, x1 = divmod(l, 256) l, x2 = divmod(l, 256) x4, x3 = divmod(l, 256) return chr(x1) + chr(x2) + chr(x3) + chr(x4) file.write("\200\1") file.write(pfblength(self.data1)) file.write(self.data1) file.write("\200\2") file.write(pfblength(data2eexec)) file.write(data2eexec) file.write("\200\1") file.write(pfblength(self.data3)) file.write(self.data3) file.write("\200\3") def outputPS(self, file, writer): """output the PostScript code for the T1file to the file file""" self.outputPFA(file, remove_UniqueID_lookup=True) def outputPDF(self, file, writer): data2eexec = self.getdata2eexec() data3 = self.data3 # we might be allowed to skip the third part ... if (data3.replace("\n", "") .replace("\r", "") .replace("\t", "") .replace(" ", "")) == "0"*512 + "cleartomark": data3 = "" data = self.data1.encode("ascii", errors="surrogateescape") + data2eexec + data3.encode("ascii", errors="surrogateescape") if writer.compress and haszlib: data = zlib.compress(data) file.write("<<\n" "/Length %d\n" "/Length1 %d\n" "/Length2 %d\n" "/Length3 %d\n" % (len(data), len(self.data1), len(data2eexec), len(data3))) if writer.compress and haszlib: file.write("/Filter /FlateDecode\n") file.write(">>\n" "stream\n") file.write_bytes(data) file.write("\n" "endstream\n") # factory functions class FontFormatError(Exception): pass def from_PFA_bytes(bytes): """create a T1file instance from a string of bytes corresponding to a PFA file""" try: m1 = bytes.index("eexec") + 6 m2 = bytes.index("0"*40) except ValueError: raise FontFormatError data1 = bytes[:m1].decode("ascii", errors="surrogateescape") data2eexec = binascii.a2b_hex(bytes[m1: m2].replace(" ", "").replace("\r", "").replace("\n", "")) data3 = bytes[m2:].decode("ascii", errors="surrogateescape") return T1file(data1, data2eexec, data3) def from_PFA_filename(filename): """create a T1file instance from PFA font file of given name""" with open(filename, "rb") as file: t1file = from_PFA_bytes(file.read()) return t1file def from_PFB_bytes(bytes): """create a T1file instance from a string of bytes corresponding to a PFB file""" def pfblength(s): if len(s) != 4: raise ValueError("invalid string length") return (s[0] + s[1]*256 + s[2]*256*256 + s[3]*256*256*256) class consumer: def __init__(self, bytes): self.bytes = bytes self.pos = 0 def __call__(self, n): result = self.bytes[self.pos:self.pos+n] self.pos += n return result consume = consumer(bytes) mark = consume(2) if mark != b"\200\1": raise FontFormatError data1 = consume(pfblength(consume(4))).decode("ascii", errors="surrogateescape") mark = consume(2) if mark != b"\200\2": raise FontFormatError data2eexec = b"" while mark == b"\200\2": data2eexec = data2eexec + consume(pfblength(consume(4))) mark = consume(2) if mark != b"\200\1": raise FontFormatError data3 = consume(pfblength(consume(4))).decode("ascii", errors="surrogateescape") mark = consume(2) if mark != b"\200\3": raise FontFormatError if consume(1): raise FontFormatError return T1file(data1, data2eexec, data3) def from_PFB_filename(filename): """create a T1file instance from PFB font file of given name""" with open(filename, "rb") as file: t1file = from_PFB_bytes(file.read()) return t1file def from_PF_bytes(bytes): #try: return from_PFB_bytes(bytes) #except FontFormatError: # return from_PFA_bytes(bytes) def from_PF_filename(filename): """create a T1file instance from PFA or PFB font file of given name""" with open(filename, "rb") as file: t1file = from_PF_bytes(file.read()) return t1file PyX-0.14.1/pyx/graph/0000755000076500000240000000000012615763300014455 5ustar andrestaff00000000000000PyX-0.14.1/pyx/graph/__init__.py0000644000076500000240000000227612177540643016603 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2004-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import importlib __allmodules__ = ["data", "key", "style", "axis"] for module in __allmodules__: importlib.import_module('.' + module, package='pyx.graph') from . import graph __allgraph__ = ["graphx", "graphxy", "graphxyz"] for importfromgraph in __allgraph__: locals()[importfromgraph] = getattr(graph, importfromgraph) __all__ = __allmodules__ + __allgraph__ PyX-0.14.1/pyx/graph/axis/0000755000076500000240000000000012615763300015421 5ustar andrestaff00000000000000PyX-0.14.1/pyx/graph/axis/__init__.py0000644000076500000240000000264612177540653017551 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2004-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA __allmodules__ = ["painter", "parter", "rater", "texter", "tick"] import importlib for module in __allmodules__: importlib.import_module('.' + module, package='pyx.graph.axis') from . import axis __allaxis__ = ["linear", "lin", "logarithmic", "log", "bar", "nestedbar", "split", "sizedlinear", "sizedlin", "autosizedlinear", "autosizedlin", "anchoredaxis", "linkedaxis", "anchoredpathaxis", "pathaxis"] for importfromaxis in __allaxis__: locals()[importfromaxis] = getattr(axis, importfromaxis) __all__ = __allmodules__ + __allaxis__ PyX-0.14.1/pyx/graph/axis/axis.py0000644000076500000240000005716512177540653016764 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2003-2011 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import functools, logging, math from pyx import attr, unit, text from pyx.graph.axis import painter, parter, positioner, rater, texter, tick logger = logging.getLogger("pyx") class _marker: pass class axisdata: """axis data storage class Instances of this class are used to store axis data local to the graph. It will always contain an axispos instance provided by the graph during initialization.""" def __init__(self, **kwargs): for key, value in list(kwargs.items()): setattr(self, key, value) class _axis: """axis""" def createlinked(self, data, positioner, graphtexrunner, errorname, linkpainter): canvas = painter.axiscanvas(self.painter, graphtexrunner) if linkpainter is not None: linkpainter.paint(canvas, data, self, positioner) return canvas class NoValidPartitionError(RuntimeError): pass class _regularaxis(_axis): """base implementation a regular axis Regular axis have a continuous variable like linear axes, logarithmic axes, time axes etc.""" def __init__(self, min=None, max=None, reverse=0, divisor=None, title=None, painter=painter.regular(), texter=texter.mixed(), linkpainter=painter.linked(), density=1, maxworse=2, manualticks=[], fallbackrange=None): if min is not None and max is not None and min > max: min, max, reverse = max, min, not reverse self.min = min self.max = max self.reverse = reverse self.divisor = divisor self.title = title self.painter = painter self.texter = texter self.linkpainter = linkpainter self.density = density self.maxworse = maxworse self.manualticks = self.checkfraclist(manualticks) self.fallbackrange = fallbackrange def createdata(self, errorname): return axisdata(min=self.min, max=self.max) zero = 0.0 def adjustaxis(self, data, columndata, graphtexrunner, errorname): if self.min is None or self.max is None: for value in columndata: try: value = value + self.zero except: pass else: if self.min is None and (data.min is None or value < data.min): data.min = value if self.max is None and (data.max is None or value > data.max): data.max = value def checkfraclist(self, fracs): "orders a list of fracs, equal entries are not allowed" if not len(fracs): return [] sorted = list(fracs) sorted.sort() last = sorted[0] for item in sorted[1:]: if last == item: raise ValueError("duplicate entry found") last = item return sorted def _create(self, data, positioner, graphtexrunner, parter, rater, errorname): errorname = " for axis %s" % errorname if data.min is None or data.max is None: raise RuntimeError("incomplete axis range%s" % errorname) if data.max == data.min: if self.fallbackrange is not None: try: data.min, data.max = data.min - 0.5*self.fallbackrange, data.min + 0.5*self.fallbackrange except TypeError: data.min, data.max = self.fallbackrange[0], self.fallbackrange[1] else: raise RuntimeError("zero axis range%s" % errorname) if self.divisor is not None: rational_divisor = tick.rational(self.divisor) convert_tick = lambda x: float(x)*self.divisor else: convert_tick = lambda x: x def layout(data): if data.ticks: self.adjustaxis(data, [convert_tick(data.ticks[0]), convert_tick(data.ticks[-1])], graphtexrunner, errorname) self.texter.labels(data.ticks) if self.divisor: for t in data.ticks: t *= rational_divisor canvas = painter.axiscanvas(self.painter, graphtexrunner) if self.painter is not None: self.painter.paint(canvas, data, self, positioner) return canvas if parter is None: data.ticks = self.manualticks return layout(data) # a variant is a data copy with local modifications to test several partitions @functools.total_ordering class variant: def __init__(self, data, **kwargs): self.data = data for key, value in list(kwargs.items()): setattr(self, key, value) def __getattr__(self, key): return getattr(data, key) def __lt__(self, other): # we can also sort variants by their rate return self.rate < other.rate def __eq__(self, other): # we can also sort variants by their rate return self.rate == other.rate # build a list of variants bestrate = None if self.divisor is not None: if data.min is not None: data_min_divided = data.min/self.divisor else: data_min_divided = None if data.max is not None: data_max_divided = data.max/self.divisor else: data_max_divided = None partfunctions = parter.partfunctions(data_min_divided, data_max_divided, self.min is None, self.max is None) else: partfunctions = parter.partfunctions(data.min, data.max, self.min is None, self.max is None) variants = [] for partfunction in partfunctions: worse = 0 while worse < self.maxworse: worse += 1 ticks = partfunction() if ticks is None: break ticks = tick.mergeticklists(self.manualticks, ticks, mergeequal=0) if ticks: rate = rater.rateticks(self, ticks, self.density) if rate is not None: if self.reverse: rate += rater.raterange(self.convert(data, convert_tick(ticks[0])) - self.convert(data, convert_tick(ticks[-1])), 1) else: rate += rater.raterange(self.convert(data, convert_tick(ticks[-1])) - self.convert(data, convert_tick(ticks[0])), 1) if bestrate is None or rate < bestrate: bestrate = rate worse = 0 variants.append(variant(data, rate=rate, ticks=ticks)) if not variants: raise RuntimeError("no axis partitioning found%s" % errorname) if len(variants) == 1 or self.painter is None: # When the painter is None, we could sort the variants here by their rating. # However, we didn't did this so far and there is no real reason to change that. data.ticks = variants[0].ticks return layout(data) # build the layout for best variants for variant in variants: variant.storedcanvas = None variants.sort() while not variants[0].storedcanvas: variants[0].storedcanvas = layout(variants[0]) ratelayout = rater.ratelayout(variants[0].storedcanvas, self.density) if ratelayout is None: del variants[0] if not variants: raise NoValidPartitionError("no valid axis partitioning found%s" % errorname) else: variants[0].rate += ratelayout variants.sort() self.adjustaxis(data, variants[0].ticks, graphtexrunner, errorname) data.ticks = variants[0].ticks return variants[0].storedcanvas class linear(_regularaxis): """linear axis""" def __init__(self, parter=parter.autolinear(), rater=rater.linear(), **args): _regularaxis.__init__(self, **args) self.parter = parter self.rater = rater def convert(self, data, value): """axis coordinates -> graph coordinates""" if self.reverse: return (data.max - float(value)) / (data.max - data.min) else: return (float(value) - data.min) / (data.max - data.min) def create(self, data, positioner, graphtexrunner, errorname): return _regularaxis._create(self, data, positioner, graphtexrunner, self.parter, self.rater, errorname) lin = linear class logarithmic(_regularaxis): """logarithmic axis""" def __init__(self, parter=parter.autologarithmic(), rater=rater.logarithmic(), linearparter=parter.autolinear(extendtick=None), **args): _regularaxis.__init__(self, **args) self.parter = parter self.rater = rater self.linearparter = linearparter def convert(self, data, value): """axis coordinates -> graph coordinates""" # TODO: store log(data.min) and log(data.max) if self.reverse: return (math.log(data.max) - math.log(float(value))) / (math.log(data.max) - math.log(data.min)) else: return (math.log(float(value)) - math.log(data.min)) / (math.log(data.max) - math.log(data.min)) def create(self, data, positioner, graphtexrunner, errorname): try: return _regularaxis._create(self, data, positioner, graphtexrunner, self.parter, self.rater, errorname) except NoValidPartitionError: if self.linearparter: logger.warning("no valid logarithmic partitioning found for axis %s, switch to linear partitioning" % errorname) return _regularaxis._create(self, data, positioner, graphtexrunner, self.linearparter, self.rater, errorname) raise log = logarithmic class subaxispositioner(positioner._positioner): """a subaxis positioner""" def __init__(self, basepositioner, subaxis): self.basepositioner = basepositioner self.vmin = subaxis.vmin self.vmax = subaxis.vmax self.vminover = subaxis.vminover self.vmaxover = subaxis.vmaxover def vbasepath(self, v1=None, v2=None): if v1 is not None: v1 = self.vmin+v1*(self.vmax-self.vmin) else: v1 = self.vminover if v2 is not None: v2 = self.vmin+v2*(self.vmax-self.vmin) else: v2 = self.vmaxover return self.basepositioner.vbasepath(v1, v2) def vgridpath(self, v): return self.basepositioner.vgridpath(self.vmin+v*(self.vmax-self.vmin)) def vtickpoint_pt(self, v, axis=None): return self.basepositioner.vtickpoint_pt(self.vmin+v*(self.vmax-self.vmin)) def vtickdirection(self, v, axis=None): return self.basepositioner.vtickdirection(self.vmin+v*(self.vmax-self.vmin)) class bar(_axis): def __init__(self, subaxes=None, defaultsubaxis=linear(painter=None, linkpainter=None, parter=None), dist=0.5, firstdist=None, lastdist=None, title=None, reverse=0, painter=painter.bar(), linkpainter=painter.linkedbar()): self.subaxes = subaxes self.defaultsubaxis = defaultsubaxis self.dist = dist if firstdist is not None: self.firstdist = firstdist else: self.firstdist = 0.5 * dist if lastdist is not None: self.lastdist = lastdist else: self.lastdist = 0.5 * dist self.title = title self.reverse = reverse self.painter = painter self.linkpainter = linkpainter def createdata(self, errorname): data = axisdata(size=self.firstdist+self.lastdist-self.dist, subaxes={}, names=[]) return data def addsubaxis(self, data, name, subaxis, graphtexrunner, errorname): subaxis = anchoredaxis(subaxis, graphtexrunner, "%s, subaxis %s" % (errorname, name)) subaxis.setcreatecall(lambda: None) subaxis.sized = hasattr(subaxis.data, "size") if subaxis.sized: data.size += subaxis.data.size else: data.size += 1 data.size += self.dist data.subaxes[name] = subaxis if self.reverse: data.names.insert(0, name) else: data.names.append(name) def adjustaxis(self, data, columndata, graphtexrunner, errorname): for value in columndata: # some checks and error messages try: len(value) except: raise ValueError("tuple expected by bar axis '%s'" % errorname) try: value + "" except: pass else: raise ValueError("tuple expected by bar axis '%s'" % errorname) assert len(value) == 2, "tuple of size two expected by bar axis '%s'" % errorname name = value[0] if name is not None and name not in data.names: if self.subaxes: if self.subaxes[name] is not None: self.addsubaxis(data, name, self.subaxes[name], graphtexrunner, errorname) else: self.addsubaxis(data, name, self.defaultsubaxis, graphtexrunner, errorname) for name in data.names: subaxis = data.subaxes[name] if subaxis.sized: data.size -= subaxis.data.size subaxis.axis.adjustaxis(subaxis.data, [value[1] for value in columndata if value[0] == name], graphtexrunner, "%s, subaxis %s" % (errorname, name)) if subaxis.sized: data.size += subaxis.data.size def convert(self, data, value): if value[0] is None: raise ValueError axis = data.subaxes[value[0]] vmin = axis.vmin vmax = axis.vmax return axis.vmin + axis.convert(value[1]) * (axis.vmax - axis.vmin) def create(self, data, positioner, graphtexrunner, errorname): canvas = painter.axiscanvas(self.painter, graphtexrunner) v = 0 position = self.firstdist for name in data.names: subaxis = data.subaxes[name] subaxis.vmin = position / float(data.size) if subaxis.sized: position += subaxis.data.size else: position += 1 subaxis.vmax = position / float(data.size) position += 0.5*self.dist subaxis.vminover = v if name == data.names[-1]: subaxis.vmaxover = 1 else: subaxis.vmaxover = position / float(data.size) subaxis.setpositioner(subaxispositioner(positioner, subaxis)) subaxis.create() for layer, subcanvas in list(subaxis.canvas.layers.items()): canvas.layer(layer).insert(subcanvas) assert len(subaxis.canvas.layers) == len(subaxis.canvas.items) if canvas.extent_pt < subaxis.canvas.extent_pt: canvas.extent_pt = subaxis.canvas.extent_pt position += 0.5*self.dist v = subaxis.vmaxover if self.painter is not None: self.painter.paint(canvas, data, self, positioner) return canvas def createlinked(self, data, positioner, graphtexrunner, errorname, linkpainter): canvas = painter.axiscanvas(self.painter, graphtexrunner) for name in data.names: subaxis = data.subaxes[name] subaxis = linkedaxis(subaxis, name) subaxis.setpositioner(subaxispositioner(positioner, data.subaxes[name])) subaxis.create() for layer, subcanvas in list(subaxis.canvas.layers.items()): canvas.layer(layer).insert(subcanvas) assert len(subaxis.canvas.layers) == len(subaxis.canvas.items) if canvas.extent_pt < subaxis.canvas.extent_pt: canvas.extent_pt = subaxis.canvas.extent_pt if linkpainter is not None: linkpainter.paint(canvas, data, self, positioner) return canvas class nestedbar(bar): def __init__(self, defaultsubaxis=bar(dist=0, painter=None, linkpainter=None), **kwargs): bar.__init__(self, defaultsubaxis=defaultsubaxis, **kwargs) class split(bar): def __init__(self, defaultsubaxis=linear(), firstdist=0, lastdist=0, painter=painter.split(), linkpainter=painter.linkedsplit(), **kwargs): bar.__init__(self, defaultsubaxis=defaultsubaxis, firstdist=firstdist, lastdist=lastdist, painter=painter, linkpainter=linkpainter, **kwargs) class sizedlinear(linear): def __init__(self, size=1, **kwargs): linear.__init__(self, **kwargs) self.size = size def createdata(self, errorname): data = linear.createdata(self, errorname) data.size = self.size return data sizedlin = sizedlinear class autosizedlinear(linear): def __init__(self, parter=parter.autolinear(extendtick=None), **kwargs): linear.__init__(self, parter=parter, **kwargs) def createdata(self, errorname): data = linear.createdata(self, errorname) try: data.size = data.max - data.min except: data.size = 0 return data def adjustaxis(self, data, columndata, graphtexrunner, errorname): linear.adjustaxis(self, data, columndata, graphtexrunner, errorname) try: data.size = data.max - data.min except: data.size = 0 def create(self, data, positioner, graphtexrunner, errorname): min = data.min max = data.max canvas = linear.create(self, data, positioner, graphtexrunner, errorname) if min != data.min or max != data.max: raise RuntimeError("range change during axis creation of autosized linear axis") return canvas autosizedlin = autosizedlinear class anchoredaxis: def __init__(self, axis, graphtexrunner, errorname): assert not isinstance(axis, anchoredaxis), errorname self.axis = axis self.errorname = errorname self.graphtexrunner = graphtexrunner self.data = axis.createdata(self.errorname) self.canvas = None self.positioner = None def setcreatecall(self, function, *args, **kwargs): self._createfunction = function self._createargs = args self._createkwargs = kwargs def docreate(self): if not self.canvas: self._createfunction(*self._createargs, **self._createkwargs) def setpositioner(self, positioner): assert positioner is not None, self.errorname assert self.positioner is None, self.errorname self.positioner = positioner def convert(self, x): self.docreate() return self.axis.convert(self.data, x) def adjustaxis(self, columndata): if self.canvas is None: self.axis.adjustaxis(self.data, columndata, self.graphtexrunner, self.errorname) else: logger.warning("ignore axis range adjustment of already created axis '%s'" % self.errorname) def vbasepath(self, v1=None, v2=None): return self.positioner.vbasepath(v1=v1, v2=v2) def basepath(self, x1=None, x2=None): self.docreate() if x1 is None: if x2 is None: return self.positioner.vbasepath() else: return self.positioner.vbasepath(v2=self.axis.convert(self.data, x2)) else: if x2 is None: return self.positioner.vbasepath(v1=self.axis.convert(self.data, x1)) else: return self.positioner.vbasepath(v1=self.axis.convert(self.data, x1), v2=self.axis.convert(self.data, x2)) def vgridpath(self, v): return self.positioner.vgridpath(v) def gridpath(self, x): self.docreate() return self.positioner.vgridpath(self.axis.convert(self.data, x)) def vtickpoint_pt(self, v): return self.positioner.vtickpoint_pt(v) def vtickpoint(self, v): return self.positioner.vtickpoint_pt(v) * unit.t_pt def tickpoint_pt(self, x): self.docreate() return self.positioner.vtickpoint_pt(self.axis.convert(self.data, x)) def tickpoint(self, x): self.docreate() x_pt, y_pt = self.positioner.vtickpoint_pt(self.axis.convert(self.data, x)) return x_pt * unit.t_pt, y_pt * unit.t_pt def vtickdirection(self, v): return self.positioner.vtickdirection(v) def tickdirection(self, x): self.docreate() return self.positioner.vtickdirection(self.axis.convert(self.data, x)) def create(self): if self.canvas is None: assert self.positioner is not None, self.errorname self.canvas = self.axis.create(self.data, self.positioner, self.graphtexrunner, self.errorname) return self.canvas class linkedaxis(anchoredaxis): def __init__(self, linkedaxis=None, errorname="manual-linked", painter=_marker): self.painter = painter self.linkedto = None self.errorname = errorname self.canvas = None self.positioner = None if linkedaxis: self.setlinkedaxis(linkedaxis) def setlinkedaxis(self, linkedaxis): assert isinstance(linkedaxis, anchoredaxis), self.errorname self.linkedto = linkedaxis self.axis = linkedaxis.axis self.graphtexrunner = self.linkedto.graphtexrunner self.errorname = "%s (linked to %s)" % (self.errorname, linkedaxis.errorname) self.data = linkedaxis.data if self.painter is _marker: self.painter = linkedaxis.axis.linkpainter def create(self): assert self.linkedto is not None, self.errorname assert self.positioner is not None, self.errorname if self.canvas is None: self.linkedto.docreate() self.canvas = self.axis.createlinked(self.data, self.positioner, self.graphtexrunner, self.errorname, self.painter) return self.canvas class anchoredpathaxis(anchoredaxis): """an anchored axis along a path""" def __init__(self, path, axis, **kwargs): anchoredaxis.__init__(self, axis, text.defaulttexrunner, "pathaxis") self.setpositioner(positioner.pathpositioner(path, **kwargs)) self.create() def pathaxis(*args, **kwargs): """creates an axiscanvas for an axis along a path""" return anchoredpathaxis(*args, **kwargs).canvas PyX-0.14.1/pyx/graph/axis/painter.py0000644000076500000240000004535212177540653017455 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from pyx import canvas, color, attr, text, style, unit, box, path from pyx import trafo as trafomodule from pyx.graph.axis import tick goldenmean = 0.5 * (math.sqrt(5) + 1) class axiscanvas(canvas.canvas): """axis canvas""" def __init__(self, painter, graphtexrunner): """initializes the instance - sets extent to zero - sets labels to an empty list""" canvas.canvas.__init__(self) self.extent_pt = 0 self.labels = [] if isinstance(painter, _text) and painter.texrunner: self.settexrunner(painter.texrunner) else: self.settexrunner(graphtexrunner) class rotatetext: """create rotations accordingly to tick directions""" def __init__(self, direction, epsilon=1e-10): self.direction = direction self.epsilon = epsilon def trafo(self, dx, dy): direction = self.direction + math.atan2(dy, dx) * 180 / math.pi while (direction > 180 + self.epsilon): direction -= 360 while (direction < -180 - self.epsilon): direction += 360 while (direction > 90 + self.epsilon): direction -= 180 while (direction < -90 - self.epsilon): direction += 180 return trafomodule.rotate(direction) rotatetext.parallel = rotatetext(90) rotatetext.orthogonal = rotatetext(180) class _text: """a painter with a texrunner""" def __init__(self, texrunner=None): self.texrunner = texrunner class _title(_text): """class for painting an axis title""" defaulttitleattrs = [text.halign.center, text.vshift.mathaxis] def __init__(self, titledist=0.3*unit.v_cm, titleattrs=[], titledirection=rotatetext.parallel, titlepos=0.5, **kwargs): self.titledist = titledist self.titleattrs = titleattrs self.titledirection = titledirection self.titlepos = titlepos _text.__init__(self, **kwargs) def paint(self, canvas, data, axis, axispos): if axis.title is not None and self.titleattrs is not None: x, y = axispos.vtickpoint_pt(self.titlepos) dx, dy = axispos.vtickdirection(self.titlepos) titleattrs = self.defaulttitleattrs + self.titleattrs if self.titledirection is not None: x2, y2 = axispos.vtickpoint_pt(self.titlepos+0.001) # XXX: axisdirection needed dx2, dy2 = x2-x, y2-y if dx*dy2-dy*dx2 < 0: dy2 *= -1 dx2 *= -1 titleattrs.append(self.titledirection.trafo(dy2, -dx2)) title = canvas.layer("title").text_pt(x, y, axis.title, titleattrs) canvas.extent_pt += unit.topt(self.titledist) title.linealign_pt(canvas.extent_pt, -dx, -dy) canvas.extent_pt += title.extent_pt(dx, dy) class geometricseries(attr.changeattr): def __init__(self, initial, factor): self.initial = initial self.factor = factor def select(self, index, total): return self.initial * (self.factor ** index) class ticklength(geometricseries): pass _base = 0.12 * unit.v_cm ticklength.SHORT = ticklength(_base/math.sqrt(64), 1/goldenmean) ticklength.SHORt = ticklength(_base/math.sqrt(32), 1/goldenmean) ticklength.SHOrt = ticklength(_base/math.sqrt(16), 1/goldenmean) ticklength.SHort = ticklength(_base/math.sqrt(8), 1/goldenmean) ticklength.Short = ticklength(_base/math.sqrt(4), 1/goldenmean) ticklength.short = ticklength(_base/math.sqrt(2), 1/goldenmean) ticklength.normal = ticklength(_base, 1/goldenmean) ticklength.long = ticklength(_base*math.sqrt(2), 1/goldenmean) ticklength.Long = ticklength(_base*math.sqrt(4), 1/goldenmean) ticklength.LOng = ticklength(_base*math.sqrt(8), 1/goldenmean) ticklength.LONg = ticklength(_base*math.sqrt(16), 1/goldenmean) ticklength.LONG = ticklength(_base*math.sqrt(32), 1/goldenmean) class regular(_title): """class for painting the ticks and labels of an axis""" defaulttickattrs = [] defaultgridattrs = [] defaultbasepathattrs = [style.linecap.square] defaultlabelattrs = [text.halign.center, text.vshift.mathaxis] def __init__(self, innerticklength=ticklength.normal, outerticklength=None, tickattrs=[], gridattrs=None, basepathattrs=[], labeldist=0.3*unit.v_cm, labelattrs=[], labeldirection=None, labelhequalize=0, labelvequalize=1, **kwargs): self.innerticklength = innerticklength self.outerticklength = outerticklength self.tickattrs = tickattrs self.gridattrs = gridattrs self.basepathattrs = basepathattrs self.labeldist = labeldist self.labelattrs = labelattrs self.labeldirection = labeldirection self.labelhequalize = labelhequalize self.labelvequalize = labelvequalize _title.__init__(self, **kwargs) def paint(self, canvas, data, axis, axispos): for t in data.ticks: t.temp_v = axis.convert(data, t) t.temp_x_pt, t.temp_y_pt = axispos.vtickpoint_pt(t.temp_v) t.temp_dx, t.temp_dy = axispos.vtickdirection(t.temp_v) maxticklevel, maxlabellevel = tick.maxlevels(data.ticks) labeldist_pt = unit.topt(self.labeldist) # create & align t.temp_labelbox for t in data.ticks: if t.labellevel is not None: labelattrs = attr.selectattrs(self.labelattrs, t.labellevel, maxlabellevel) if labelattrs is not None: labelattrs = self.defaultlabelattrs + labelattrs if self.labeldirection is not None: labelattrs.append(self.labeldirection.trafo(t.temp_dx, t.temp_dy)) if t.labelattrs is not None: labelattrs.extend(t.labelattrs) t.temp_labelbox = canvas.texrunner.text_pt(t.temp_x_pt, t.temp_y_pt, t.label, labelattrs) if len(data.ticks) > 1: equaldirection = 1 for t in data.ticks[1:]: if t.temp_dx != data.ticks[0].temp_dx or t.temp_dy != data.ticks[0].temp_dy: equaldirection = 0 else: equaldirection = 0 if equaldirection and ((not data.ticks[0].temp_dx and self.labelvequalize) or (not data.ticks[0].temp_dy and self.labelhequalize)): if self.labelattrs is not None: box.linealignequal_pt([t.temp_labelbox for t in data.ticks if t.labellevel is not None], labeldist_pt, -data.ticks[0].temp_dx, -data.ticks[0].temp_dy) else: for t in data.ticks: if t.labellevel is not None and self.labelattrs is not None: t.temp_labelbox.linealign_pt(labeldist_pt, -t.temp_dx, -t.temp_dy) for t in data.ticks: if t.ticklevel is not None and self.tickattrs is not None: tickattrs = attr.selectattrs(self.defaulttickattrs + self.tickattrs, t.ticklevel, maxticklevel) if tickattrs is not None: innerticklength = attr.selectattr(self.innerticklength, t.ticklevel, maxticklevel) outerticklength = attr.selectattr(self.outerticklength, t.ticklevel, maxticklevel) if innerticklength is not None or outerticklength is not None: if innerticklength is None: innerticklength = 0 if outerticklength is None: outerticklength = 0 innerticklength_pt = unit.topt(innerticklength) outerticklength_pt = unit.topt(outerticklength) x1 = t.temp_x_pt + t.temp_dx * innerticklength_pt y1 = t.temp_y_pt + t.temp_dy * innerticklength_pt x2 = t.temp_x_pt - t.temp_dx * outerticklength_pt y2 = t.temp_y_pt - t.temp_dy * outerticklength_pt canvas.layer("ticks").stroke(path.line_pt(x1, y1, x2, y2), tickattrs) if outerticklength_pt > canvas.extent_pt: canvas.extent_pt = outerticklength_pt if -innerticklength_pt > canvas.extent_pt: canvas.extent_pt = -innerticklength_pt if self.gridattrs is not None: gridattrs = attr.selectattrs(self.defaultgridattrs + self.gridattrs, t.ticklevel, maxticklevel) if gridattrs is not None: canvas.layer("grid").stroke(axispos.vgridpath(t.temp_v), gridattrs) if t.labellevel is not None and self.labelattrs is not None: canvas.layer("labels").insert(t.temp_labelbox) canvas.labels.append(t.temp_labelbox) extent_pt = t.temp_labelbox.extent_pt(t.temp_dx, t.temp_dy) + labeldist_pt if extent_pt > canvas.extent_pt: canvas.extent_pt = extent_pt if self.labelattrs is None: canvas.labels = None if self.basepathattrs is not None: canvas.layer("baseline").stroke(axispos.vbasepath(), self.defaultbasepathattrs + self.basepathattrs) # for t in data.ticks: # del t.temp_v # we've inserted those temporary variables ... and do not care any longer about them # del t.temp_x_pt # del t.temp_y_pt # del t.temp_dx # del t.temp_dy # if t.labellevel is not None and self.labelattrs is not None: # del t.temp_labelbox _title.paint(self, canvas, data, axis, axispos) class linked(regular): """class for painting a linked axis""" def __init__(self, labelattrs=None, # turn off labels and title titleattrs=None, **kwargs): regular.__init__(self, labelattrs=labelattrs, titleattrs=titleattrs, **kwargs) class bar(_title): """class for painting a baraxis""" defaulttickattrs = [] defaultbasepathattrs = [style.linecap.square] defaultnameattrs = [text.halign.center, text.vshift.mathaxis] def __init__(self, innerticklength=None, outerticklength=None, tickattrs=[], basepathattrs=[], namedist=0.3*unit.v_cm, nameattrs=[], namedirection=None, namepos=0.5, namehequalize=0, namevequalize=1, **args): self.innerticklength = innerticklength self.outerticklength = outerticklength self.tickattrs = tickattrs self.basepathattrs = basepathattrs self.namedist = namedist self.nameattrs = nameattrs self.namedirection = namedirection self.namepos = namepos self.namehequalize = namehequalize self.namevequalize = namevequalize _title.__init__(self, **args) def paint(self, canvas, data, axis, positioner): namepos = [] for name in data.names: subaxis = data.subaxes[name] v = subaxis.vmin + self.namepos * (subaxis.vmax - subaxis.vmin) x, y = positioner.vtickpoint_pt(v) dx, dy = positioner.vtickdirection(v) namepos.append((v, x, y, dx, dy)) nameboxes = [] if self.nameattrs is not None: for (v, x, y, dx, dy), name in zip(namepos, data.names): nameattrs = self.defaultnameattrs + self.nameattrs if self.namedirection is not None: nameattrs.append(self.namedirection.trafo(dx, dy)) nameboxes.append(canvas.texrunner.text_pt(x, y, str(name), nameattrs)) labeldist_pt = canvas.extent_pt + unit.topt(self.namedist) if len(namepos) > 1: equaldirection = 1 for np in namepos[1:]: if np[3] != namepos[0][3] or np[4] != namepos[0][4]: equaldirection = 0 else: equaldirection = 0 if equaldirection and ((not namepos[0][3] and self.namevequalize) or (not namepos[0][4] and self.namehequalize)): box.linealignequal_pt(nameboxes, labeldist_pt, -namepos[0][3], -namepos[0][4]) else: for namebox, np in zip(nameboxes, namepos): namebox.linealign_pt(labeldist_pt, -np[3], -np[4]) if self.basepathattrs is not None: p = positioner.vbasepath() if p is not None: canvas.layer("baseline").stroke(p, self.defaultbasepathattrs + self.basepathattrs) if ( self.tickattrs is not None and (self.innerticklength is not None or self.outerticklength is not None) ): if self.innerticklength is not None: innerticklength_pt = unit.topt(self.innerticklength) if canvas.extent_pt < -innerticklength_pt: canvas.extent_pt = -innerticklength_pt elif self.outerticklength is not None: innerticklength_pt = 0 if self.outerticklength is not None: outerticklength_pt = unit.topt(self.outerticklength) if canvas.extent_pt < outerticklength_pt: canvas.extent_pt = outerticklength_pt elif innerticklength_pt is not None: outerticklength_pt = 0 for v in [data.subaxes[name].vminover for name in data.names] + [1]: x, y = positioner.vtickpoint_pt(v) dx, dy = positioner.vtickdirection(v) x1 = x + dx * innerticklength_pt y1 = y + dy * innerticklength_pt x2 = x - dx * outerticklength_pt y2 = y - dy * outerticklength_pt canvas.layer("ticks").stroke(path.line_pt(x1, y1, x2, y2), self.defaulttickattrs + self.tickattrs) for (v, x, y, dx, dy), namebox in zip(namepos, nameboxes): newextent_pt = namebox.extent_pt(dx, dy) + labeldist_pt if canvas.extent_pt < newextent_pt: canvas.extent_pt = newextent_pt for namebox in nameboxes: canvas.layer("labels").insert(namebox) _title.paint(self, canvas, data, axis, positioner) class linkedbar(bar): """class for painting a linked baraxis""" def __init__(self, nameattrs=None, titleattrs=None, **kwargs): bar.__init__(self, nameattrs=nameattrs, titleattrs=titleattrs, **kwargs) def getsubaxis(self, subaxis, name): from pyx.graph.axis import linkedaxis return linkedaxis(subaxis, name) class split(_title): """class for painting a splitaxis""" defaultbreaklinesattrs = [] def __init__(self, breaklinesdist=0.05*unit.v_cm, breaklineslength=0.5*unit.v_cm, breaklinesangle=-60, breaklinesattrs=[], **args): self.breaklinesdist = breaklinesdist self.breaklineslength = breaklineslength self.breaklinesangle = breaklinesangle self.breaklinesattrs = breaklinesattrs self.sin = math.sin(self.breaklinesangle*math.pi/180.0) self.cos = math.cos(self.breaklinesangle*math.pi/180.0) _title.__init__(self, **args) def paint(self, canvas, data, axis, axispos): if self.breaklinesattrs is not None: breaklinesdist_pt = unit.topt(self.breaklinesdist) breaklineslength_pt = unit.topt(self.breaklineslength) breaklinesextent_pt = (0.5*breaklinesdist_pt*math.fabs(self.cos) + 0.5*breaklineslength_pt*math.fabs(self.sin)) if canvas.extent_pt < breaklinesextent_pt: canvas.extent_pt = breaklinesextent_pt for v in [data.subaxes[name].vminover for name in data.names[1:]]: # use a tangent of the basepath (this is independent of the tickdirection) p = axispos.vbasepath(v, None).normpath() breakline = p.tangent(0, length=self.breaklineslength) widthline = p.tangent(0, length=self.breaklinesdist).transformed(trafomodule.rotate(self.breaklinesangle+90, *breakline.atbegin())) # XXX Uiiii tocenter = [0.5*(x[0]-x[1]) for x in zip(breakline.atbegin(), breakline.atend())] towidth = [0.5*(x[0]-x[1]) for x in zip(widthline.atbegin(), widthline.atend())] breakline = breakline.transformed(trafomodule.translate(*tocenter).rotated(self.breaklinesangle, *breakline.atbegin())) breakline1 = breakline.transformed(trafomodule.translate(*towidth)) breakline2 = breakline.transformed(trafomodule.translate(-towidth[0], -towidth[1])) canvas.layer("baseline").fill(path.path(path.moveto_pt(*breakline1.atbegin_pt()), path.lineto_pt(*breakline1.atend_pt()), path.lineto_pt(*breakline2.atend_pt()), path.lineto_pt(*breakline2.atbegin_pt()), path.closepath()), [color.gray.white]) canvas.layer("baseline").stroke(breakline1, self.defaultbreaklinesattrs + self.breaklinesattrs) canvas.layer("baseline").stroke(breakline2, self.defaultbreaklinesattrs + self.breaklinesattrs) _title.paint(self, canvas, data, axis, axispos) class linkedsplit(split): def __init__(self, titleattrs=None, **kwargs): split.__init__(self, titleattrs=titleattrs, **kwargs) PyX-0.14.1/pyx/graph/axis/parter.py0000644000076500000240000003220612177540653017302 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from pyx.graph.axis import tick # Note: A partition is a list of ticks. class _partdata: """state storage class for a partfunction partdata is used to keep local data and a current state to emulate generators. In the future we might use yield statements within a partfunction. Currently we add partdata by a lambda construct and do inplace modifications within partdata to keep track of the state. """ def __init__(self, **kwargs): for key, value in list(kwargs.items()): setattr(self, key, value) class _parter: """interface of a partitioner""" def partfunctions(self, min, max, extendmin, extendmax): """returns a list of partfunctions A partfunction can be called without further arguments and it will return a new partition each time, or None. Several partfunctions are used to walk in different "directions" (like more and less partitions). Note that we do not alternate walking in different directions (i.e. alternate the partfunction calls). Instead we first walk into one direction (which should give less and less ticks) until the rating becomes bad and when try more ticks. We want to keep the number of ticks small compared to a simple alternate search. """ # This is a (useless) empty partitioner. return [] class linear(_parter): """partitioner to create a single linear partition""" def __init__(self, tickdists=None, labeldists=None, extendtick=0, extendlabel=None, epsilon=1e-10): if tickdists is None and labeldists is not None: self.ticklist = [tick.rational(labeldists[0])] else: self.ticklist = list(map(tick.rational, tickdists)) if labeldists is None and tickdists is not None: self.labellist = [tick.rational(tickdists[0])] else: self.labellist = list(map(tick.rational, labeldists)) self.extendtick = extendtick self.extendlabel = extendlabel self.epsilon = epsilon def extendminmax(self, min, max, dist, extendmin, extendmax): """return new min, max tuple extending the range min, max - dist is the tick distance to be used - extendmin and extendmax are booleans to allow for the extension""" if extendmin: min = float(dist) * math.floor(min / float(dist) + self.epsilon) if extendmax: max = float(dist) * math.ceil(max / float(dist) - self.epsilon) return min, max def getticks(self, min, max, dist, ticklevel=None, labellevel=None): """return a list of equal spaced ticks - the tick distance is dist, the ticklevel is set to ticklevel and the labellevel is set to labellevel - min, max is the range where ticks should be placed""" imin = int(math.ceil(min/float(dist) - 0.5*self.epsilon)) imax = int(math.floor(max/float(dist) + 0.5*self.epsilon)) ticks = [] for i in range(imin, imax + 1): ticks.append(tick.tick((i*dist.num, dist.denom), ticklevel=ticklevel, labellevel=labellevel)) return ticks def partfunction(self, data): if data.first: data.first = 0 min = data.min max = data.max if self.extendtick is not None and len(self.ticklist) > self.extendtick: min, max = self.extendminmax(min, max, self.ticklist[self.extendtick], data.extendmin, data.extendmax) if self.extendlabel is not None and len(self.labellist) > self.extendlabel: min, max = self.extendminmax(min, max, self.labellist[self.extendlabel], data.extendmin, data.extendmax) ticks = [] for i in range(len(self.ticklist)): ticks = tick.mergeticklists(ticks, self.getticks(min, max, self.ticklist[i], ticklevel=i)) for i in range(len(self.labellist)): ticks = tick.mergeticklists(ticks, self.getticks(min, max, self.labellist[i], labellevel=i)) return ticks return None def partfunctions(self, min, max, extendmin, extendmax): return [lambda d=_partdata(first=1, min=min, max=max, extendmin=extendmin, extendmax=extendmax): self.partfunction(d)] lin = linear class autolinear(_parter): """partitioner to create an arbitrary number of linear partitions""" defaultvariants = [[tick.rational((1, 1)), tick.rational((1, 2))], [tick.rational((2, 1)), tick.rational((1, 1))], [tick.rational((5, 2)), tick.rational((5, 4))], [tick.rational((5, 1)), tick.rational((5, 2))]] def __init__(self, variants=defaultvariants, extendtick=0, epsilon=1e-10): self.variants = variants self.extendtick = extendtick self.epsilon = epsilon def partfunctions(self, min, max, extendmin, extendmax): try: logmm = math.log(max - min) / math.log(10) except ArithmeticError: raise RuntimeError("partitioning failed due to empty or invalid axis range") if logmm < 0: # correction for rounding towards zero of the int routine base = tick.rational((10, 1), power=int(logmm-1)) else: base = tick.rational((10, 1), power=int(logmm)) ticks = list(map(tick.rational, self.variants[0])) useticks = [t * base for t in ticks] return [lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=1, tickindex=-1, base=tick.rational(base)): self.partfunction(d), lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, sign=-1, tickindex=0, base=tick.rational(base)): self.partfunction(d)] def partfunction(self, data): if data.sign == 1: if data.tickindex < len(self.variants) - 1: data.tickindex += 1 else: data.tickindex = 0 data.base.num *= 10 else: if data.tickindex: data.tickindex -= 1 else: data.tickindex = len(self.variants) - 1 data.base.denom *= 10 tickdists = [tick.rational(t) * data.base for t in self.variants[data.tickindex]] linearparter = linear(tickdists=tickdists, extendtick=self.extendtick, epsilon=self.epsilon) return linearparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]() autolin = autolinear class preexp: """definition of a logarithmic partition exp is an integer, which defines multiplicator (usually 10). pres are a list of tick positions (rational numbers, e.g. instances of rational). possible positions are the tick positions and arbitrary divisions and multiplications of the tick positions by exp.""" def __init__(self, pres, exp): self.pres = pres self.exp = exp class logarithmic(linear): """partitioner to create a single logarithmic partition""" # define some useful constants pre1exp = preexp([tick.rational((1, 1))], 10) pre125exp = preexp([tick.rational((1, 1)), tick.rational((2, 1)), tick.rational((5, 1))], 10) pre1to9exp = preexp([tick.rational((x, 1)) for x in range(1, 10)], 10) # ^- we always include 1 in order to get extendto(tick|label)level to work as expected def __init__(self, tickpreexps=None, labelpreexps=None, extendtick=0, extendlabel=None, epsilon=1e-10): if tickpreexps is None and labelpreexps is not None: self.ticklist = [labelpreexps[0]] else: self.ticklist = tickpreexps if labelpreexps is None and tickpreexps is not None: self.labellist = [tickpreexps[0]] else: self.labellist = labelpreexps self.extendtick = extendtick self.extendlabel = extendlabel self.epsilon = epsilon def extendminmax(self, min, max, preexp, extendmin, extendmax): minpower = None maxpower = None for i in range(len(preexp.pres)): imin = int(math.floor(math.log(min / float(preexp.pres[i])) / math.log(preexp.exp) + self.epsilon)) + 1 imax = int(math.ceil(math.log(max / float(preexp.pres[i])) / math.log(preexp.exp) - self.epsilon)) - 1 if minpower is None or imin < minpower: minpower, minindex = imin, i if maxpower is None or imax >= maxpower: maxpower, maxindex = imax, i if minindex: minrational = preexp.pres[minindex - 1] else: minrational = preexp.pres[-1] minpower -= 1 if maxindex != len(preexp.pres) - 1: maxrational = preexp.pres[maxindex + 1] else: maxrational = preexp.pres[0] maxpower += 1 if extendmin: min = float(minrational) * float(preexp.exp) ** minpower if extendmax: max = float(maxrational) * float(preexp.exp) ** maxpower return min, max def getticks(self, min, max, preexp, ticklevel=None, labellevel=None): ticks = [] minimin = 0 maximax = 0 for f in preexp.pres: thisticks = [] imin = int(math.ceil(math.log(min / float(f)) / math.log(preexp.exp) - 0.5 * self.epsilon)) imax = int(math.floor(math.log(max / float(f)) / math.log(preexp.exp) + 0.5 * self.epsilon)) for i in range(imin, imax + 1): pos = f * tick.rational((preexp.exp, 1), power=i) thisticks.append(tick.tick((pos.num, pos.denom), ticklevel = ticklevel, labellevel = labellevel)) ticks = tick.mergeticklists(ticks, thisticks) return ticks log = logarithmic class autologarithmic(logarithmic): """partitioner to create several logarithmic partitions""" defaultvariants = [([logarithmic.pre1exp, # ticks logarithmic.pre1to9exp], # subticks [logarithmic.pre1exp, # labels logarithmic.pre125exp]), # sublevels ([logarithmic.pre1exp, # ticks logarithmic.pre1to9exp], # subticks None)] # labels like ticks def __init__(self, variants=defaultvariants, extendtick=0, extendlabel=None, autoexponent=10, epsilon=1e-10): self.variants = variants self.extendtick = extendtick self.extendlabel = extendlabel self.autoexponent = autoexponent self.epsilon = epsilon def partfunctions(self, min, max, extendmin, extendmax): return [lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, variantsindex=len(self.variants)): self.variantspartfunction(d), lambda d=_partdata(min=min, max=max, extendmin=extendmin, extendmax=extendmax, exponent=self.autoexponent): self.autopartfunction(d)] def variantspartfunction(self, data): data.variantsindex -= 1 if 0 <= data.variantsindex: logarithmicparter= logarithmic(tickpreexps=self.variants[data.variantsindex][0], labelpreexps=self.variants[data.variantsindex][1], extendtick=self.extendtick, extendlabel=self.extendlabel, epsilon=self.epsilon) return logarithmicparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]() return None def autopartfunction(self, data): data.exponent *= self.autoexponent logarithmicparter= logarithmic(tickpreexps=[preexp([tick.rational((1, 1))], data.exponent), logarithmic.pre1exp], extendtick=self.extendtick, extendlabel=self.extendlabel, epsilon=self.epsilon) return logarithmicparter.partfunctions(min=data.min, max=data.max, extendmin=data.extendmin, extendmax=data.extendmax)[0]() autolog = autologarithmic PyX-0.14.1/pyx/graph/axis/positioner.py0000644000076500000240000001046412177540653020202 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from pyx import path, unit class _positioner: """interface definition of axis tick position methods - these methods are used for the postitioning of the ticks when painting an axis""" # TODO: should we add a local transformation (for label text etc?) # (this might replace tickdirection (and even tickposition?)) def vbasepath(self, v1=None, v2=None): """return the basepath as a path - like basepath, but for graph coordinates""" def vgridpath(self, v): """return the gridpath as a path for a given position v in graph coordinates - might return None when no gridpath is available""" return None def vtickpoint_pt(self, v): """return tick position (x, y) in pts for a tick at position v in graph coordinates""" def vtickdirection(self, v): """return direction tuple (dx, dy) for a tick at position v in graph coordinates""" class pathpositioner(_positioner): """axis tick position methods along an arbitrary path""" def __init__(self, p, direction=1): self.path = p self.normpath = p.normpath() self.arclen_pt = self.normpath.arclen_pt() self.arclen = self.arclen_pt * unit.t_pt self.direction = direction def vbasepath(self, v1=None, v2=None): if v1 is None: if v2 is None: return self.path else: return self.normpath.split(self.normpath.arclentoparam(v2 * self.arclen))[0] else: if v2 is None: return self.normpath.split(self.normpath.arclentoparam(v1 * self.arclen))[1] else: return self.normpath.split(*self.normpath.arclentoparam([v1 * self.arclen, v2 * self.arclen]))[1] def vtickpoint_pt(self, v): return self.normpath.at_pt(self.normpath.arclentoparam(v * self.arclen)) def vtickdirection(self, v): return self.normpath.rotation(self.normpath.arclentoparam(v * self.arclen)).apply_pt(0, self.direction) class lineaxispos_pt: """an axispos linear along a line with a fix direction for the ticks""" def __init__(self, x1_pt, y1_pt, x2_pt, y2_pt, fixtickdirection, vgridpath): self.x1_pt = x1_pt self.y1_pt = y1_pt self.x2_pt = x2_pt self.y2_pt = y2_pt self.fixtickdirection = fixtickdirection self.vgridpath = vgridpath def vbasepath(self, v1=None, v2=None): if v1 is None: v1 = 0 if v2 is None: v2 = 1 return path.line_pt((1-v1)*self.x1_pt+v1*self.x2_pt, (1-v1)*self.y1_pt+v1*self.y2_pt, (1-v2)*self.x1_pt+v2*self.x2_pt, (1-v2)*self.y1_pt+v2*self.y2_pt) def vtickpoint_pt(self, v): return (1-v)*self.x1_pt+v*self.x2_pt, (1-v)*self.y1_pt+v*self.y2_pt def vtickdirection(self, v): return self.fixtickdirection class flexlineaxispos_pt(lineaxispos_pt): """an axispos linear along a line with flexible direction for the ticks""" def __init__(self, vtickpoint_pt, vtickdirection, vgridpath): self.vtickpoint_pt = vtickpoint_pt self.vtickdirection = vtickdirection self.vgridpath = vgridpath def vbasepath(self, v1=None, v2=None): if v1 is None: v1 = 0 if v2 is None: v2 = 1 x1_pt, y1_pt = self.vtickpoint_pt(v1) x2_pt, y2_pt = self.vtickpoint_pt(v2) return path.line_pt(x1_pt, y1_pt, x2_pt, y2_pt) PyX-0.14.1/pyx/graph/axis/rater.py0000644000076500000240000002461712177540653017131 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import unit, box from pyx.graph.axis import tick # rater # conseptional remarks: # - raters are used to calculate a rating for a realization of something # - a rating means a positive floating point value # - ratings are used to order those realizations by their suitability # (small ratings are better) # - a rating of None means not suitable at all (those realizations should be # thrown out) class cube: """a value rater - a cube rater has an optimal value, where the rate becomes zero - for a left (below the optimum) and a right value (above the optimum), the rating is value is set to 1 (modified by an overall weight factor for the rating) - the analytic form of the rating is cubic for both, the left and the right side of the rater, independently""" def __init__(self, opt, left=None, right=None, weight=1): """initializes the rater - by default, left is set to zero, right is set to 3*opt - left should be smaller than opt, right should be bigger than opt - weight should be positive and is a factor multiplicated to the rates""" if left is None: left = 0 if right is None: right = 3*opt self.opt = opt self.left = left self.right = right self.weight = weight def rate(self, value, density): """returns a rating for a value - the density lineary rescales the rater (the optimum etc.), e.g. a value bigger than one increases the optimum (when it is positive) and a value lower than one decreases the optimum (when it is positive); the density itself should be positive""" opt = self.opt * density if value < opt: other = self.left * density elif value > opt: other = self.right * density else: return 0 factor = (value - opt) / float(other - opt) return self.weight * (factor ** 3) class distance: # TODO: update docstring """a distance rater (rates a list of distances) - the distance rater rates a list of distances by rating each independently and returning the average rate - there is an optimal value, where the rate becomes zero - the analytic form is linary for values above the optimal value (twice the optimal value has the rating one, three times the optimal value has the rating two, etc.) - the analytic form is reciprocal subtracting one for values below the optimal value (halve the optimal value has the rating one, one third of the optimal value has the rating two, etc.)""" def __init__(self, opt, weight=0.1): """inititializes the rater - opt is the optimal length (a visual PyX length) - weight should be positive and is a factor multiplicated to the rates""" self.opt = opt self.weight = weight def rate(self, distances, density): """rate distances - the distances are a list of positive floats in PostScript points - the density lineary rescales the rater (the optimum etc.), e.g. a value bigger than one increases the optimum (when it is positive) and a value lower than one decreases the optimum (when it is positive); the density itself should be positive""" if len(distances): opt = unit.topt(self.opt) / density rate = 0 for distance in distances: if distance < opt: rate += self.weight * (opt / distance - 1) else: rate += self.weight * (distance / opt - 1) return rate / float(len(distances)) class rater: """a rater for ticks - the rating of axes is splited into two separate parts: - rating of the ticks in terms of the number of ticks, subticks, labels, etc. - rating of the label distances - in the end, a rate for ticks is the sum of these rates - it is useful to first just rate the number of ticks etc. and selecting those partitions, where this fits well -> as soon as an complete rate (the sum of both parts from the list above) of a first ticks is below a rate of just the number of ticks, subticks labels etc. of other ticks, those other ticks will never be better than the first one -> we gain speed by minimizing the number of ticks, where label distances have to be taken into account) - both parts of the rating are shifted into instances of raters defined above --- right now, there is not yet a strict interface for this delegation (should be done as soon as it is needed)""" def __init__(self, ticks, labels, range, distance): """initializes the axis rater - ticks and labels are lists of instances of a value rater - the first entry in ticks rate the number of ticks, the second the number of subticks, etc.; when there are no ticks of a level or there is not rater for a level, the level is just ignored - labels is analogous, but for labels - within the rating, all ticks with a higher level are considered as ticks for a given level - range is a value rater instance, which rates the covering of an axis range by the ticks (as a relative value of the tick range vs. the axis range), ticks might cover less or more than the axis range (for the standard automatic axis partition schemes an extention of the axis range is normal and should get some penalty) - distance is an distance rater instance""" self.ticks = ticks self.labels = labels self.range = range self.distance = distance def rateticks(self, axis, ticks, density): """rates ticks by the number of ticks, subticks, labels etc. - takes into account the number of ticks, subticks, labels etc. and the coverage of the axis range by the ticks - when there are no ticks of a level or there was not rater given in the constructor for a level, the level is just ignored - the method returns the sum of the rating results divided by the sum of the weights of the raters - within the rating, all ticks with a higher level are considered as ticks for a given level""" maxticklevel, maxlabellevel = tick.maxlevels(ticks) if not maxticklevel and not maxlabellevel: return None numticks = [0]*maxticklevel numlabels = [0]*maxlabellevel for t in ticks: if t.ticklevel is not None: for level in range(t.ticklevel, maxticklevel): numticks[level] += 1 if t.labellevel is not None: for level in range(t.labellevel, maxlabellevel): numlabels[level] += 1 rate = 0 weight = 0 for numtick, rater in zip(numticks, self.ticks): rate += rater.rate(numtick, density) weight += rater.weight for numlabel, rater in zip(numlabels, self.labels): rate += rater.rate(numlabel, density) weight += rater.weight return rate/weight def raterange(self, tickrange, datarange): """rate the range covered by the ticks compared to the range of the data - tickrange and datarange are the ranges covered by the ticks and the data in graph coordinates - usually, the datarange is 1 (ticks are calculated for a given datarange) - the ticks might cover less or more than the data range (for the standard automatic axis partition schemes an extention of the axis range is normal and should get some penalty)""" return self.range.rate(tickrange, datarange) def ratelayout(self, axiscanvas, density): """rate distances of the labels in an axis canvas - the distances should be collected as box distances of subsequent labels - the axiscanvas provides a labels attribute for easy access to the labels whose distances have to be taken into account - the density is used within the distancerate instance""" if axiscanvas.labels is None: # to disable any layout rating return 0 if len(axiscanvas.labels) > 1: try: distances = [axiscanvas.labels[i].boxdistance_pt(axiscanvas.labels[i+1]) for i in range(len(axiscanvas.labels) - 1)] except box.BoxCrossError: return None return self.distance.rate(distances, density) else: return None class linear(rater): """a rater with predefined constructor arguments suitable for a linear axis""" def __init__(self, ticks=[cube(4), cube(10, weight=0.5)], labels=[cube(4)], range=cube(1, weight=2), distance=distance(1*unit.v_cm)): rater.__init__(self, ticks, labels, range, distance) lin = linear class logarithmic(rater): """a rater with predefined constructor arguments suitable for a logarithmic axis""" def __init__(self, ticks=[cube(5, right=20), cube(20, right=100, weight=0.5)], labels=[cube(5, right=20), cube(5, right=20, weight=0.5)], range=cube(1, weight=2), distance=distance(1*unit.v_cm)): rater.__init__(self, ticks, labels, range, distance) log = logarithmic PyX-0.14.1/pyx/graph/axis/texter.py0000644000076500000240000005330712610011345017304 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import text from pyx.graph.axis import tick class _Itexter: def labels(self, ticks): """fill the label attribute of ticks - ticks is a list of instances of tick - for each element of ticks the value of the attribute label is set to a string appropriate to the attributes num and denom of that tick instance - label attributes of the tick instances are just kept, whenever they are not equal to None - the method might modify the labelattrs attribute of the ticks; be sure to not modify it in-place!""" class decimal: "a texter creating decimal labels (e.g. '1.234' or even '0.\overline{3}')" __implements__ = _Itexter def __init__(self, prefix="", infix="", suffix="", equalprecision=0, decimalsep=".", thousandsep="", thousandthpartsep="", plus="", minus="-", period=r"\overline{%s}", labelattrs=[text.mathmode]): r"""initializes the instance - prefix, infix, and suffix (strings) are added at the begin, immediately after the minus, and at the end of the label, respectively - decimalsep, thousandsep, and thousandthpartsep (strings) are used as separators - plus or minus (string) is inserted for non-negative or negative numbers - period (string) is taken as a format string generating a period; it has to contain exactly one string insert operators "%s" for the period; usually it should be r"\overline{%s}" - labelattrs is a list of attributes to be added to the label attributes given in the painter""" self.prefix = prefix self.infix = infix self.suffix = suffix self.equalprecision = equalprecision self.decimalsep = decimalsep self.thousandsep = thousandsep self.thousandthpartsep = thousandthpartsep self.plus = plus self.minus = minus self.period = period self.labelattrs = labelattrs def labels(self, ticks): labeledticks = [] maxdecprecision = 0 for tick in ticks: if tick.label is None and tick.labellevel is not None: labeledticks.append(tick) m, n = tick.num, tick.denom if m < 0: m = -m if n < 0: n = -n quotient, remainder = divmod(m, n) quotient = str(quotient) if len(self.thousandsep): l = len(quotient) tick.label = "" for i in range(l): tick.label += quotient[i] if not ((l-i-1) % 3) and l > i+1: tick.label += self.thousandsep else: tick.label = quotient if remainder: tick.label += self.decimalsep oldremainders = [] tick.temp_decprecision = 0 while (remainder): tick.temp_decprecision += 1 if remainder in oldremainders: tick.temp_decprecision = None periodstart = len(tick.label) - (len(oldremainders) - oldremainders.index(remainder)) tick.label = tick.label[:periodstart] + self.period % tick.label[periodstart:] break oldremainders += [remainder] remainder *= 10 quotient, remainder = divmod(remainder, n) if not ((tick.temp_decprecision - 1) % 3) and tick.temp_decprecision > 1: tick.label += self.thousandthpartsep tick.label += str(quotient) else: if maxdecprecision < tick.temp_decprecision: maxdecprecision = tick.temp_decprecision if self.equalprecision: for tick in labeledticks: if tick.temp_decprecision is not None: if tick.temp_decprecision == 0 and maxdecprecision > 0: tick.label += self.decimalsep for i in range(tick.temp_decprecision, maxdecprecision): if not ((i - 1) % 3) and i > 1: tick.label += self.thousandthpartsep tick.label += "0" for tick in labeledticks: if tick.num * tick.denom < 0: plusminus = self.minus else: plusminus = self.plus tick.label = "%s%s%s%s%s" % (self.prefix, plusminus, self.infix, tick.label, self.suffix) tick.labelattrs = tick.labelattrs + self.labelattrs # del tick.temp_decprecision # we've inserted this temporary variable ... and do not care any longer about it class exponential: "a texter creating labels with exponentials (e.g. '2\cdot10^5')" __implements__ = _Itexter def __init__(self, plus="", minus="-", mantissaexp=r"{{%s}\cdot10^{%s}}", skipexp0=r"{%s}", skipexp1=None, nomantissaexp=r"{10^{%s}}", minusnomantissaexp=r"{-10^{%s}}", mantissamin=tick.rational((1, 1)), mantissamax=tick.rational((10, 1)), skipmantissa1=0, skipallmantissa1=1, mantissatexter=decimal()): r"""initializes the instance - plus or minus (string) is inserted for non-negative or negative exponents - mantissaexp (string) is taken as a format string generating the exponent; it has to contain exactly two string insert operators "%s" -- the first for the mantissa and the second for the exponent; examples are r"{{%s}\cdot10^{%s}}" and r"{{%s}{\rm e}{%s}}" - skipexp0 (string) is taken as a format string used for exponent 0; exactly one string insert operators "%s" for the mantissa; None turns off the special handling of exponent 0; an example is r"{%s}" - skipexp1 (string) is taken as a format string used for exponent 1; exactly one string insert operators "%s" for the mantissa; None turns off the special handling of exponent 1; an example is r"{{%s}\cdot10}" - nomantissaexp (string) is taken as a format string generating the exponent when the mantissa is one and should be skipped; it has to contain exactly one string insert operators "%s" for the exponent; an examples is r"{10^{%s}}" - minusnomantissaexp (string) is taken as a format string generating the exponent when the mantissa is minus one and should be skipped; it has to contain exactly one string insert operators "%s" for the exponent; None turns off the special handling of mantissa -1; an examples is r"{-10^{%s}}" - mantissamin and mantissamax are the minimum and maximum of the mantissa; they are rational instances greater than zero and mantissamin < mantissamax; the sign of the tick is ignored here - skipmantissa1 (boolean) turns on skipping of any mantissa equals one (and minus when minusnomantissaexp is set) - skipallmantissa1 (boolean) as above, but all mantissas must be 1 (or -1) - mantissatexter is the texter for the mantissa - the skipping of a mantissa is stronger than the skipping of an exponent""" self.plus = plus self.minus = minus self.mantissaexp = mantissaexp self.skipexp0 = skipexp0 self.skipexp1 = skipexp1 self.nomantissaexp = nomantissaexp self.minusnomantissaexp = minusnomantissaexp self.mantissamin = mantissamin self.mantissamax = mantissamax self.mantissamindivmax = self.mantissamin / self.mantissamax self.mantissamaxdivmin = self.mantissamax / self.mantissamin self.skipmantissa1 = skipmantissa1 self.skipallmantissa1 = skipallmantissa1 self.mantissatexter = mantissatexter def labels(self, ticks): labeledticks = [] for tick in ticks: if tick.label is None and tick.labellevel is not None: tick.temp_orgnum, tick.temp_orgdenom = tick.num, tick.denom labeledticks.append(tick) tick.temp_exp = 0 if tick.num: while abs(tick) >= self.mantissamax: tick.temp_exp += 1 x = tick * self.mantissamindivmax tick.num, tick.denom = x.num, x.denom while abs(tick) < self.mantissamin: tick.temp_exp -= 1 x = tick * self.mantissamaxdivmin tick.num, tick.denom = x.num, x.denom if tick.temp_exp < 0: tick.temp_exp = "%s%i" % (self.minus, -tick.temp_exp) else: tick.temp_exp = "%s%i" % (self.plus, tick.temp_exp) self.mantissatexter.labels(labeledticks) if self.minusnomantissaexp is not None: allmantissa1 = len(labeledticks) == len([tick for tick in labeledticks if abs(tick.num) == abs(tick.denom)]) else: allmantissa1 = len(labeledticks) == len([tick for tick in labeledticks if tick.num == tick.denom]) for tick in labeledticks: if (self.skipallmantissa1 and allmantissa1 or (self.skipmantissa1 and (tick.num == tick.denom or (tick.num == -tick.denom and self.minusnomantissaexp is not None)))): if tick.num == tick.denom: tick.label = self.nomantissaexp % tick.temp_exp else: tick.label = self.minusnomantissaexp % tick.temp_exp else: if tick.temp_exp == "0" and self.skipexp0 is not None: tick.label = self.skipexp0 % tick.label elif tick.temp_exp == "1" and self.skipexp1 is not None: tick.label = self.skipexp1 % tick.label else: tick.label = self.mantissaexp % (tick.label, tick.temp_exp) tick.num, tick.denom = tick.temp_orgnum, tick.temp_orgdenom # del tick.temp_orgnum # we've inserted those temporary variables ... and do not care any longer about them # del tick.temp_orgdenom # del tick.temp_exp class mixed: "a texter creating decimal or exponential labels" __implements__ = _Itexter def __init__(self, smallestdecimal=tick.rational((1, 1000)), biggestdecimal=tick.rational((9999, 1)), equaldecision=1, decimal=decimal(), exponential=exponential()): """initializes the instance - smallestdecimal and biggestdecimal are the smallest and biggest decimal values, where the decimal texter should be used; they are rational instances; the sign of the tick is ignored here; a tick at zero is considered for the decimal texter as well - equaldecision (boolean) uses decimal texter or exponential texter globaly (set) or for each tick separately (unset) - decimal and exponential are texters to be used""" self.smallestdecimal = smallestdecimal self.biggestdecimal = biggestdecimal self.equaldecision = equaldecision self.decimal = decimal self.exponential = exponential def labels(self, ticks): decticks = [] expticks = [] for tick in ticks: if tick.label is None and tick.labellevel is not None: if not tick.num or (abs(tick) >= self.smallestdecimal and abs(tick) <= self.biggestdecimal): decticks.append(tick) else: expticks.append(tick) if self.equaldecision: if len(expticks): self.exponential.labels(ticks) else: self.decimal.labels(ticks) else: for tick in decticks: self.decimal.labels([tick]) for tick in expticks: self.exponential.labels([tick]) class rational: "a texter creating rational labels (e.g. 'a/b' or even 'a \over b')" # XXX: we use divmod here to be more expicit __implements__ = _Itexter def __init__(self, prefix="", infix="", suffix="", numprefix="", numinfix="", numsuffix="", denomprefix="", denominfix="", denomsuffix="", plus="", minus="-", minuspos=0, over=r"{{%s}\over{%s}}", equaldenom=0, skip1=1, skipnum0=1, skipnum1=1, skipdenom1=1, labelattrs=[text.mathmode]): r"""initializes the instance - prefix, infix, and suffix (strings) are added at the begin, immediately after the minus, and at the end of the label, respectively - prefixnum, infixnum, and suffixnum (strings) are added to the labels numerator correspondingly - prefixdenom, infixdenom, and suffixdenom (strings) are added to the labels denominator correspondingly - plus or minus (string) is inserted for non-negative or negative numbers - minuspos is an integer, which determines the position, where the plus or minus sign has to be placed; the following values are allowed: 1 - writes the plus or minus in front of the numerator 0 - writes the plus or minus in front of the hole fraction -1 - writes the plus or minus in front of the denominator - over (string) is taken as a format string generating the fraction bar; it has to contain exactly two string insert operators "%s" -- the first for the numerator and the second for the denominator; by far the most common examples are r"{{%s}\over{%s}}" and "{{%s}/{%s}}" - usually the numerator and denominator are canceled; however, when equaldenom is set, the least common multiple of all denominators is used - skip1 (boolean) just prints the prefix, the plus or minus, the infix and the suffix, when the value is plus or minus one and at least one of prefix, infix and the suffix is present - skipnum0 (boolean) just prints a zero instead of the hole fraction, when the numerator is zero; no prefixes, infixes, and suffixes are taken into account - skipnum1 (boolean) just prints the numprefix, the plus or minus, the numinfix and the numsuffix, when the num value is plus or minus one and at least one of numprefix, numinfix and the numsuffix is present - skipdenom1 (boolean) just prints the numerator instead of the hole fraction, when the denominator is one and none of the parameters denomprefix, denominfix and denomsuffix are set and minuspos is not -1 or the fraction is positive - labelattrs is a list of attributes for a texrunners text method; None is considered as an empty list; labelattrs might be changed in the painter as well""" self.prefix = prefix self.infix = infix self.suffix = suffix self.numprefix = numprefix self.numinfix = numinfix self.numsuffix = numsuffix self.denomprefix = denomprefix self.denominfix = denominfix self.denomsuffix = denomsuffix self.plus = plus self.minus = minus self.minuspos = minuspos self.over = over self.equaldenom = equaldenom self.skip1 = skip1 self.skipnum0 = skipnum0 self.skipnum1 = skipnum1 self.skipdenom1 = skipdenom1 self.labelattrs = labelattrs def gcd(self, *n): """returns the greates common divisor of all elements in n - the elements of n must be non-negative integers - return None if the number of elements is zero - the greates common divisor is not affected when some of the elements are zero, but it becomes zero when all elements are zero""" if len(n) == 2: i, j = n if i < j: i, j = j, i while j > 0: i, (dummy, j) = j, divmod(i, j) return i if len(n): res = n[0] for i in n[1:]: res = self.gcd(res, i) return res def lcm(self, *n): """returns the least common multiple of all elements in n - the elements of n must be non-negative integers - return None if the number of elements is zero - the least common multiple is zero when some of the elements are zero""" if len(n): res = n[0] for i in n[1:]: res = divmod(res * i, self.gcd(res, i))[0] return res def labels(self, ticks): labeledticks = [] for tick in ticks: if tick.label is None and tick.labellevel is not None: labeledticks.append(tick) tick.temp_rationalnum = tick.num tick.temp_rationaldenom = tick.denom tick.temp_rationalminus = 1 if tick.temp_rationalnum < 0: tick.temp_rationalminus = -tick.temp_rationalminus tick.temp_rationalnum = -tick.temp_rationalnum if tick.temp_rationaldenom < 0: tick.temp_rationalminus = -tick.temp_rationalminus tick.temp_rationaldenom = -tick.temp_rationaldenom gcd = self.gcd(tick.temp_rationalnum, tick.temp_rationaldenom) (tick.temp_rationalnum, dummy1), (tick.temp_rationaldenom, dummy2) = divmod(tick.temp_rationalnum, gcd), divmod(tick.temp_rationaldenom, gcd) if self.equaldenom: equaldenom = self.lcm(*[tick.temp_rationaldenom for tick in ticks if tick.label is None]) if equaldenom is not None: for tick in labeledticks: factor, dummy = divmod(equaldenom, tick.temp_rationaldenom) tick.temp_rationalnum, tick.temp_rationaldenom = factor * tick.temp_rationalnum, factor * tick.temp_rationaldenom for tick in labeledticks: rationalminus = rationalnumminus = rationaldenomminus = "" if tick.temp_rationalminus == -1: plusminus = self.minus else: plusminus = self.plus if self.minuspos == 0: rationalminus = plusminus elif self.minuspos == 1: rationalnumminus = plusminus elif self.minuspos == -1: rationaldenomminus = plusminus else: raise RuntimeError("invalid minuspos") if self.skipnum0 and tick.temp_rationalnum == 0: tick.label = "0" elif (self.skip1 and self.skipdenom1 and tick.temp_rationalnum == 1 and tick.temp_rationaldenom == 1 and (len(self.prefix) or len(self.infix) or len(self.suffix)) and not len(rationalnumminus) and not len(self.numprefix) and not len(self.numinfix) and not len(self.numsuffix) and not len(rationaldenomminus) and not len(self.denomprefix) and not len(self.denominfix) and not len(self.denomsuffix)): tick.label = "%s%s%s%s" % (self.prefix, rationalminus, self.infix, self.suffix) else: if self.skipnum1 and tick.temp_rationalnum == 1 and (len(self.numprefix) or len(self.numinfix) or len(self.numsuffix)): tick.temp_rationalnum = "%s%s%s%s" % (self.numprefix, rationalnumminus, self.numinfix, self.numsuffix) else: tick.temp_rationalnum = "%s%s%s%i%s" % (self.numprefix, rationalnumminus, self.numinfix, tick.temp_rationalnum, self.numsuffix) if self.skipdenom1 and tick.temp_rationaldenom == 1 and not len(rationaldenomminus) and not len(self.denomprefix) and not len(self.denominfix) and not len(self.denomsuffix): rational = tick.temp_rationalnum else: tick.temp_rationaldenom = "%s%s%s%i%s" % (self.denomprefix, rationaldenomminus, self.denominfix, tick.temp_rationaldenom, self.denomsuffix) rational = self.over % (tick.temp_rationalnum, tick.temp_rationaldenom) tick.label = "%s%s%s%s%s" % (self.prefix, rationalminus, self.infix, rational, self.suffix) tick.labelattrs = tick.labelattrs + self.labelattrs # del tick.temp_rationalnum # we've inserted those temporary variables ... and do not care any longer about them # del tick.temp_rationaldenom # del tick.temp_rationalminus PyX-0.14.1/pyx/graph/axis/tick.py0000644000076500000240000002333512177540653016742 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2005 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import sys, functools # test automatic long conversion try: sys.maxsize+1 autolong = 1 except OverflowError: autolong = 0 @functools.total_ordering class rational: """rational class performing some basic rational arithmetics the axis partitioning uses rational arithmetics (with infinite accuracy) basically it contains self.num and self.denom""" def initfromstring(self, s): "converts a string 0.123 into a rational" expparts = s.strip().replace("E", "e").split("e") if len(expparts) > 2: raise ValueError("multiple 'e' found in '%s'" % s) commaparts = expparts[0].split(".") if len(commaparts) > 2: raise ValueError("multiple '.' found in '%s'" % expparts[0]) if len(commaparts) == 1: commaparts = [commaparts[0], ""] self.num = 1 if autolong: self.denom = 10 ** len(commaparts[1]) else: self.denom = 10 ** len(commaparts[1]) neg = len(commaparts[0]) and commaparts[0][0] == "-" if neg: commaparts[0] = commaparts[0][1:] elif len(commaparts[0]) and commaparts[0][0] == "+": commaparts[0] = commaparts[0][1:] if len(commaparts[0]): if not commaparts[0].isdigit(): raise ValueError("unrecognized characters in '%s'" % s) try: x = int(commaparts[0]) except: x = int(commaparts[0]) else: x = 0 if len(commaparts[1]): if not commaparts[1].isdigit(): raise ValueError("unrecognized characters in '%s'" % s) try: y = int(commaparts[1]) except: y = int(commaparts[1]) else: y = 0 self.num = x*self.denom + y if neg: self.num = -self.num if len(expparts) == 2: neg = expparts[1][0] == "-" if neg: expparts[1] = expparts[1][1:] elif expparts[1][0] == "+": expparts[1] = expparts[1][1:] if not expparts[1].isdigit(): raise ValueError("unrecognized characters in '%s'" % s) if neg: if autolong: self.denom *= 10 ** int(expparts[1]) else: self.denom *= 10 ** int(expparts[1]) else: if autolong: self.num *= 10 ** int(expparts[1]) else: self.num *= 10 ** int(expparts[1]) def initfromfloat(self, x, floatprecision): "converts a float into a rational with finite resolution" if floatprecision < 0: raise RuntimeError("float resolution must be non-negative") self.initfromstring(("%%.%ig" % floatprecision) % x) def __init__(self, x, power=1, floatprecision=10): """initializes a rational - rational=(num/denom)**power - x must be one of: - a string (like "1.2", "1.2e3", "1.2/3.4", etc.) - a float (converted using floatprecision) - a sequence of two integers - a rational instance""" if power == 0: self.num = 1 self.denom = 1 return try: # does x behave like a number x + 0 except: try: # does x behave like a string x + "" except: try: # x might be a tuple self.num, self.denom = x except: # otherwise it should have a num and denom self.num, self.denom = x.num, x.denom else: # x is a string fraction = x.split("/") if len(fraction) > 2: raise ValueError("multiple '/' found in '%s'" % x) self.initfromstring(fraction[0]) if len(fraction) == 2: self /= rational(fraction[1]) else: # x is a number self.initfromfloat(x, floatprecision) if not self.denom: raise ZeroDivisionError("zero denominator") if power == -1: self.num, self.denom = self.denom, self.num elif power < -1: if autolong: self.num, self.denom = self.denom ** (-power), self.num ** (-power) else: self.num, self.denom = int(self.denom) ** (-power), int(self.num) ** (-power) elif power > 1: if autolong: self.num = self.num ** power self.denom = self.denom ** power else: self.num = int(self.num) ** power self.denom = int(self.denom) ** power def __lt__(self, other): try: return self.num * other.denom < other.num * self.denom except: return float(self) < other def __eq__(self, other): try: return self.num * other.denom == other.num * self.denom except: return float(self) == other def __abs__(self): return rational((abs(self.num), abs(self.denom))) def __add__(self, other): assert abs(other) < 1e-10 return float(self) def __mul__(self, other): return rational((self.num * other.num, self.denom * other.denom)) def __imul__(self, other): self.num *= other.num self.denom *= other.denom return self def __div__(self, other): return rational((self.num * other.denom, self.denom * other.num)) __truediv__ = __div__ def __idiv__(self, other): self.num *= other.denom self.denom *= other.num return self __itruediv__ = __idiv__ def __float__(self): "caution: avoid final precision of floats" return float(self.num) / self.denom def __str__(self): return "%i/%i" % (self.num, self.denom) class tick(rational): """tick class a tick is a rational enhanced by - self.ticklevel (0 = tick, 1 = subtick, etc.) - self.labellevel (0 = label, 1 = sublabel, etc.) - self.label (a string) and self.labelattrs (a list, defaults to []) When ticklevel or labellevel is None, no tick or label is present at that value. When label is None, it should be automatically created (and stored), once the an axis painter needs it. Classes, which implement _Itexter do precisely that.""" def __init__(self, x, ticklevel=0, labellevel=0, label=None, labelattrs=[], **kwargs): """initializes the instance - see class description for the parameter description - **kwargs are passed to the rational constructor""" rational.__init__(self, x, **kwargs) self.ticklevel = ticklevel self.labellevel = labellevel self.label = label self.labelattrs = labelattrs def merge(self, other): """merges two ticks together: - the lower ticklevel/labellevel wins - the ticks should be at the same position (otherwise it doesn't make sense) -> this is NOT checked""" if self.ticklevel is None or (other.ticklevel is not None and other.ticklevel < self.ticklevel): self.ticklevel = other.ticklevel if self.labellevel is None or (other.labellevel is not None and other.labellevel < self.labellevel): self.labellevel = other.labellevel if self.label is None: self.label = other.label def mergeticklists(list1, list2, mergeequal=1): """helper function to merge tick lists - return a merged list of ticks out of list1 and list2 - CAUTION: original lists have to be ordered (the returned list is also ordered)""" # TODO: improve along the lines of http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305269 # do not destroy original lists list1 = list1[:] i = 0 j = 0 try: while True: # we keep on going until we reach an index error while list2[j] < list1[i]: # insert tick list1.insert(i, list2[j]) i += 1 j += 1 if list2[j] == list1[i]: # merge tick if mergeequal: list1[i].merge(list2[j]) j += 1 i += 1 except IndexError: if j < len(list2): list1 += list2[j:] return list1 def maxlevels(ticks): "returns a tuple maxticklevel, maxlabellevel from a list of tick instances" maxticklevel = maxlabellevel = 0 for tick in ticks: if tick.ticklevel is not None and tick.ticklevel >= maxticklevel: maxticklevel = tick.ticklevel + 1 if tick.labellevel is not None and tick.labellevel >= maxlabellevel: maxlabellevel = tick.labellevel + 1 return maxticklevel, maxlabellevel PyX-0.14.1/pyx/graph/axis/timeaxis.py0000644000076500000240000000617612177540653017637 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2004-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import datetime from pyx.graph import style from pyx.graph.axis import axis, rater """some experimental code for creating a time axis - it needs python 2.3 to be used (it is based on the new datetime data type) - a timeaxis is always based on the datetime data type (there is no distinction between times and dates) """ class timeaxis(axis.linear): "time axis mapping based " # TODO: how to deal with reversed timeaxis? def __init__(self, parter=None, rater=rater.linear(), **args): super().__init__(self, divisor=None, **args) self.parter = parter self.rater = rater def convert(self, data, x): # XXX float division of timedelta instances def mstimedelta(td): "return the timedelta in microseconds" return td.microseconds + 1000000*(td.seconds + 3600*24*td.days) return mstimedelta(x - data.min) / float(mstimedelta(data.max - data.min)) # we could store float(mstimedelta(self.dx)) instead of self.dx, but # I prefer a different solution (not based on huge integers) for the # future zero = datetime.timedelta(0) class timetick(datetime.datetime): # TODO: http://stackoverflow.com/questions/399022/why-cant-i-subclass-datetime-date # possible fix: make the datetime an attribute of the tick def __new__(cls, year, month, day, ticklevel=0, labellevel=0, label=None, labelattrs=[], **kwargs): return datetime.datetime.__new__(cls, year, month, day, **kwargs) def __init__(self, year, month, day, ticklevel=0, labellevel=0, label=None, labelattrs=[], **kwargs): self.ticklevel = ticklevel self.labellevel = labellevel self.label = label self.labelattrs = labelattrs[:] def merge(self, other): if self.ticklevel is None or (other.ticklevel is not None and other.ticklevel < self.ticklevel): self.ticklevel = other.ticklevel if self.labellevel is None or (other.labellevel is not None and other.labellevel < self.labellevel): self.labellevel = other.labellevel class timetexter: def __init__(self, format="%c"): self.format = format def labels(self, ticks): for tick in ticks: if tick.labellevel is not None and tick.label is None: tick.label = tick.strftime(self.format) PyX-0.14.1/pyx/graph/data.py0000644000076500000240000006265512177540643015764 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math, re, configparser, struct from pyx import text from . import style builtinlist = list def splitatvalue(value, *splitpoints): section = 0 while section < len(splitpoints) and splitpoints[section] < value: section += 1 if len(splitpoints) > 1: if section % 2: section = None else: section >>= 1 return (section, value) _mathglobals = {"neg": lambda x: -x, "abs": lambda x: x < 0 and -x or x, "sgn": lambda x: x < 0 and -1 or 1, "sqrt": math.sqrt, "exp": math.exp, "log": math.log, "sin": math.sin, "cos": math.cos, "tan": math.tan, "asin": math.asin, "acos": math.acos, "atan": math.atan, "sind": lambda x: math.sin(math.pi/180*x), "cosd": lambda x: math.cos(math.pi/180*x), "tand": lambda x: math.tan(math.pi/180*x), "asind": lambda x: 180/math.pi*math.asin(x), "acosd": lambda x: 180/math.pi*math.acos(x), "atand": lambda x: 180/math.pi*math.atan(x), "norm": lambda x, y: math.hypot(x, y), "splitatvalue": splitatvalue, "pi": math.pi, "e": math.e} class _data: """graph data interface Graph data consists of columns, where each column might be identified by a string or an integer. Each row in the resulting table refers to a data point. All methods except for the constructor should consider self and its attributes to be readonly, since the data instance might be shared between several graphs simultaneously. The instance variable columns is a dictionary mapping column names to the data of the column (i.e. to a list). Only static columns (known at construction time) are contained in that dictionary. For data with numbered columns the column data is also available via the list columndata. Otherwise the columndata list should be missing and an access to a column number will fail. The names of all columns (static and dynamic) must be fixed at the constructor and stated in the columnnames dictionary. The instance variable title and defaultstyles contain the data title and the default styles (a list of styles), respectively. If defaultstyles is None, the data cannot be plotted without user provided styles. """ def dynamiccolumns(self, graph, axisnames): """create and return dynamic columns data Returns dynamic data matching the given axes (the axes range and other data might be used). The return value is a dictionary similar to the columns instance variable. However, the static and dynamic data does not need to be correlated in any way, i.e. the number of data points in self.columns might differ from the number of data points represented by the return value of the dynamiccolumns method. """ return {} defaultsymbols = [style.symbol()] defaultlines = [style.line()] class values(_data): defaultstyles = defaultsymbols def __init__(self, title="user provided values", **columns): for i, values in enumerate(list(columns.values())): if i and len(values) != l: raise ValueError("different number of values") else: l = len(values) self.columns = columns self.columnnames = list(columns.keys()) self.title = title class points(_data): "Graph data from a list of points" defaultstyles = defaultsymbols def __init__(self, points, title="user provided points", addlinenumbers=1, **columns): if len(points): l = len(points[0]) self.columndata = [[x] for x in points[0]] for point in points[1:]: if l != len(point): raise ValueError("different number of columns per point") for i, x in enumerate(point): self.columndata[i].append(x) for v in list(columns.values()): if abs(v) > l or (not addlinenumbers and abs(v) == l): raise ValueError("column number bigger than number of columns") if addlinenumbers: self.columndata = [list(range(1, len(points) + 1))] + self.columndata self.columns = dict([(key, self.columndata[i]) for key, i in list(columns.items())]) else: self.columns = dict([(key, []) for key, i in list(columns.items())]) self.columnnames = list(self.columns.keys()) self.title = title class _notitle: pass _columnintref = re.compile(r"\$(-?\d+)", re.IGNORECASE) class data(_data): "creates a new data set out of an existing data set" def __init__(self, data, title=_notitle, context={}, copy=1, replacedollar=1, columncallback="__column__", **columns): # build a nice title if title is _notitle: items = list(columns.items()) items.sort() # we want sorted items (otherwise they would be unpredictable scrambled) self.title = "%s: %s" % (text.escapestring(data.title or "unkown source"), ", ".join(["%s=%s" % (text.escapestring(key), text.escapestring(str(value))) for key, value in items])) else: self.title = title self.orgdata = data self.defaultstyles = self.orgdata.defaultstyles # analyse the **columns argument self.columns = {} for columnname, value in list(columns.items()): # search in the columns dictionary try: self.columns[columnname] = self.orgdata.columns[value] except KeyError: # search in the columndata list try: self.columns[columnname] = self.orgdata.columndata[value] except (AttributeError, TypeError): # value was not an valid column identifier # i.e. take it as a mathematical expression if replacedollar: m = _columnintref.search(value) while m: value = "%s%s(%s)%s" % (value[:m.start()], columncallback, m.groups()[0], value[m.end():]) m = _columnintref.search(value) value = value.replace("$", columncallback) expression = compile(value.strip(), __file__, "eval") context = context.copy() context[columncallback] = self.columncallback if self.orgdata.columns: key, columndata = list(self.orgdata.columns.items())[0] count = len(columndata) elif self.orgdata.columndata: count = len(self.orgdata.columndata[0]) else: count = 0 newdata = [] for i in range(count): self.columncallbackcount = i for key, values in list(self.orgdata.columns.items()): context[key] = values[i] try: newdata.append(eval(expression, _mathglobals, context)) except (ArithmeticError, ValueError): newdata.append(None) self.columns[columnname] = newdata if copy: # copy other, non-conflicting column names for columnname, columndata in list(self.orgdata.columns.items()): if columnname not in self.columns: self.columns[columnname] = columndata self.columnnames = list(self.columns.keys()) def columncallback(self, value): try: return self.orgdata.columndata[value][self.columncallbackcount] except: return self.orgdata.columns[value][self.columncallbackcount] filecache = {} class file(data): defaultcommentpattern = re.compile(r"(#+|!+|%+)\s*") defaultstringpattern = re.compile(r"\"(.*?)\"(\s+|$)") defaultcolumnpattern = re.compile(r"(.*?)(\s+|$)") def splitline(self, line, stringpattern, columnpattern, tofloat=1): """returns a tuple created out of the string line - matches stringpattern and columnpattern, adds the first group of that match to the result and and removes those matches until the line is empty - when stringpattern matched, the result is always kept as a string - when columnpattern matched and tofloat is true, a conversion to a float is tried; when this conversion fails, the string is kept""" result = [] # try to gain speed by skip matching regular expressions if line.find('"')!=-1 or \ stringpattern is not self.defaultstringpattern or \ columnpattern is not self.defaultcolumnpattern: while len(line): match = stringpattern.match(line) if match: result.append(match.groups()[0]) line = line[match.end():] else: match = columnpattern.match(line) if tofloat: try: result.append(float(match.groups()[0])) except (TypeError, ValueError): result.append(match.groups()[0]) else: result.append(match.groups()[0]) line = line[match.end():] else: if tofloat: try: return list(map(float, line.split())) except (TypeError, ValueError): result = [] for r in line.split(): try: result.append(float(r)) except (TypeError, ValueError): result.append(r) else: return line.split() return result def getcachekey(self, *args): return ":".join([str(x) for x in args]) def __init__(self, filename, commentpattern=defaultcommentpattern, stringpattern=defaultstringpattern, columnpattern=defaultcolumnpattern, skiphead=0, skiptail=0, every=1, **kwargs): def readfile(file, title, self=self, commentpattern=commentpattern, stringpattern=stringpattern, columnpattern=columnpattern, skiphead=skiphead, skiptail=skiptail, every=every): columns = [] columndata = [] linenumber = 0 maxcolumns = 0 for line in file.readlines(): line = line.strip() match = commentpattern.match(line) if match: if not len(columndata): columns = self.splitline(line[match.end():], stringpattern, columnpattern, tofloat=0) else: linedata = [] for value in self.splitline(line, stringpattern, columnpattern, tofloat=1): linedata.append(value) if len(linedata): if linenumber >= skiphead and not ((linenumber - skiphead) % every): linedata = [linenumber + 1] + linedata if len(linedata) > maxcolumns: maxcolumns = len(linedata) columndata.append(linedata) linenumber += 1 if skiptail >= every: skip, x = divmod(skiptail, every) del columndata[-skip:] for i in range(len(columndata)): if len(columndata[i]) != maxcolumns: columndata[i].extend([None]*(maxcolumns-len(columndata[i]))) return points(columndata, title=title, addlinenumbers=0, **dict([(column, i+1) for i, column in enumerate(columns[:maxcolumns-1])])) try: filename.readlines except: # not a file-like object -> open it cachekey = self.getcachekey(filename, commentpattern, stringpattern, columnpattern, skiphead, skiptail, every) if cachekey not in filecache: with open(filename) as f: filecache[cachekey] = readfile(f, filename) data.__init__(self, filecache[cachekey], **kwargs) else: data.__init__(self, readfile(filename, "user provided file-like object"), **kwargs) conffilecache = {} class conffile(data): def __init__(self, filename, **kwargs): """read data from a config-like file - filename is a string - each row is defined by a section in the config-like file (see config module description) - the columns for each row are defined by lines in the section file; the option entries identify and name the columns - further keyword arguments are passed to the constructor of data, keyword arguments data and titles excluded""" def readfile(file, title): config = configparser.ConfigParser(strict=False) config.optionxform = str config.read_file(file) sections = config.sections() sections.sort() columndata = [None]*len(sections) maxcolumns = 1 columns = {} for i in range(len(sections)): point = [sections[i]] + [None]*(maxcolumns-1) for option in config.options(sections[i]): value = config.get(sections[i], option) try: value = float(value) except: pass try: index = columns[option] except KeyError: columns[option] = maxcolumns point.append(value) maxcolumns += 1 else: point[index] = value columndata[i] = point # wrap result into a data instance to remove column numbers result = data(points(columndata, addlinenumbers=0, **columns), title=title) # ... but reinsert sections as linenumbers result.columndata = [[x[0] for x in columndata]] return result try: filename.readlines except: # not a file-like object -> open it if filename not in filecache: filecache[filename] = readfile(open(filename), filename) data.__init__(self, filecache[filename], **kwargs) else: data.__init__(self, readfile(filename, "user provided file-like object"), **kwargs) cbdfilecache = {} class cbdfile(data): defaultstyles = defaultlines def getcachekey(self, *args): return ":".join([str(x) for x in args]) def __init__(self, filename, minrank=None, maxrank=None, **kwargs): class cbdhead: def __init__(self, file): (self.magic, self.dictaddr, self.segcount, self.segsize, self.segmax, self.fill) = struct.unpack("<5i20s", file.read(40)) if self.magic != 0x20770002: raise ValueError("bad magic number") class segdict: def __init__(self, file, i): self.index = i (self.segid, self.maxlat, self.minlat, self.maxlong, self.minlong, self.absaddr, self.nbytes, self.rank) = struct.unpack("<6i2h", file.read(28)) class segment: def __init__(self, file, sd): file.seek(sd.absaddr) (self.orgx, self.orgy, self.id, self.nstrokes, self.dummy) = struct.unpack("<3i2h", file.read(16)) oln, olt = self.orgx, self.orgy self.points = [(olt, oln)] for i in range(self.nstrokes): c1, c2 = struct.unpack("2c", file.read(2)) if ord(c2) & 0x40: if c1 > "\177": dy = ord(c1) - 256 else: dy = ord(c1) if c2 > "\177": dx = ord(c2) - 256 else: dx = ord(c2) - 64 else: c3, c4, c5, c6, c7, c8 = struct.unpack("6c", file.read(6)) if c2 > "\177": c2 = chr(ord(c2) | 0x40) dx, dy = struct.unpack("<2i", c3+c4+c1+c2+c7+c8+c5+c6) oln += dx olt += dy self.points.append((olt, oln)) sd.nstrokes = self.nstrokes def readfile(file, title): h = cbdhead(file) file.seek(h.dictaddr) sds = [segdict(file, i+1) for i in range(h.segcount)] sbs = [segment(file, sd) for sd in sds] # remove jumps at long +/- 180 for sd, sb in zip(sds, sbs): if sd.minlong < -150*3600 and sd.maxlong > 150*3600: for i, (lat, int) in enumerate(sb.points): if int < 0: sb.points[i] = lat, int + 360*3600 columndata = [] for sd, sb in zip(sds, sbs): if ((minrank is None or sd.rank >= minrank) and (maxrank is None or sd.rank <= maxrank)): if columndata: columndata.append((None, None)) columndata.extend([(int/3600.0, lat/3600.0) for lat, int in sb.points]) result = points(columndata, title=title) result.defaultstyles = self.defaultstyles return result try: filename.readlines except: # not a file-like object -> open it cachekey = self.getcachekey(filename, minrank, maxrank) if cachekey not in cbdfilecache: cbdfilecache[cachekey] = readfile(open(filename, "rb"), filename) data.__init__(self, cbdfilecache[cachekey], **kwargs) else: data.__init__(self, readfile(filename, "user provided file-like object"), **kwargs) class function(_data): defaultstyles = defaultlines assignmentpattern = re.compile(r"\s*([a-z_][a-z0-9_]*)\s*\(\s*([a-z_][a-z0-9_]*)\s*\)\s*=", re.IGNORECASE) def __init__(self, expression, title=_notitle, min=None, max=None, points=100, context={}): if title is _notitle: self.title = expression else: self.title = title self.min = min self.max = max self.numberofpoints = points self.context = context.copy() # be safe on late evaluations m = self.assignmentpattern.match(expression) if m: self.yname, self.xname = m.groups() expression = expression[m.end():] else: raise ValueError("y(x)=... or similar expected") if self.xname in context: raise ValueError("xname in context") self.expression = compile(expression.strip(), __file__, "eval") self.columns = {} self.columnnames = [self.xname, self.yname] def dynamiccolumns(self, graph, axisnames): dynamiccolumns = {self.xname: [], self.yname: []} xaxis = graph.axes[axisnames.get(self.xname, self.xname)] from pyx.graph.axis import logarithmic logaxis = isinstance(xaxis.axis, logarithmic) if self.min is not None: min = self.min else: min = xaxis.data.min if self.max is not None: max = self.max else: max = xaxis.data.max if logaxis: min = math.log(min) max = math.log(max) for i in range(self.numberofpoints): x = min + (max-min)*i / (self.numberofpoints-1.0) if logaxis: x = math.exp(x) dynamiccolumns[self.xname].append(x) self.context[self.xname] = x try: y = eval(self.expression, _mathglobals, self.context) except (ArithmeticError, ValueError): y = None dynamiccolumns[self.yname].append(y) return dynamiccolumns class functionxy(function): def __init__(self, f, min=None, max=None, **kwargs): function.__init__(self, "y(x)=f(x)", context={"f": f}, min=min, max=max, **kwargs) class paramfunction(_data): defaultstyles = defaultlines def __init__(self, varname, min, max, expression, title=_notitle, points=100, context={}): if varname in context: raise ValueError("varname in context") if title is _notitle: self.title = expression else: self.title = title varlist, expression = expression.split("=") expression = compile(expression.strip(), __file__, "eval") keys = [key.strip() for key in varlist.split(",")] self.columns = dict([(key, []) for key in keys]) context = context.copy() for i in range(points): param = min + (max-min)*i / (points-1.0) context[varname] = param values = eval(expression, _mathglobals, context) for key, value in zip(keys, values): self.columns[key].append(value) if len(keys) != len(values): raise ValueError("unpack tuple of wrong size") self.columnnames = list(self.columns.keys()) class paramfunctionxy(paramfunction): def __init__(self, f, min, max, **kwargs): paramfunction.__init__(self, "t", min, max, "x, y = f(t)", context={"f": f}, **kwargs) class _nodefaultstyles: pass class join(_data): "creates a new data set by joining from a list of data, it does however *not* combine points, but fills data with None if necessary" def merge_lists(self, lists): "merges list items w/o duplications, resulting order is arbitraty" result = set() for l in lists: result.update(set(l)) return builtinlist(result) def merge_dicts(self, dicts): """merge dicts containing lists as values (with equal number of items per list in each dict), missing data is padded by None""" keys = self.merge_lists([list(d.keys()) for d in dicts]) empties = [] for d in dicts: if len(list(d.keys())) == len(keys): empties.append(None) # won't be needed later on else: values = list(d.values()) if len(values): empties.append([None]*len(values[0])) else: # has no data at all -> do not add anything empties.append([]) result = {} for key in keys: result[key] = [] for d, e in zip(dicts, empties): result[key].extend(d.get(key, e)) return result def __init__(self, data, title=_notitle, defaultstyles=_nodefaultstyles): """takes a list of data, a title (if it should not be autoconstructed) and a defaultstyles list if there is no common defaultstyles setting for in the provided data""" assert len(data) self.data = data self.columnnames = self.merge_lists([d.columnnames for d in data]) self.columns = self.merge_dicts([d.columns for d in data]) if title is _notitle: self.title = " + ".join([d.title for d in data]) else: self.title = title if defaultstyles is _nodefaultstyles: self.defaultstyles = data[0].defaultstyles for d in data[1:]: if d.defaultstyles is not self.defaultstyles: self.defaultstyles = None break else: self.defaultstyles = defaultstyles def dynamiccolumns(self, graph, axisnames): return self.merge_dicts([d.dynamiccolumns(graph, axisnames) for d in self.data]) PyX-0.14.1/pyx/graph/graph.py0000644000076500000240000014360612465146623016150 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import logging, math, re, string from pyx import canvas, path, trafo, unit from pyx.graph.axis import axis, positioner logger = logging.getLogger("pyx") goldenmean = 0.5 * (math.sqrt(5) + 1) # The following two methods are used to register and get a default provider # for keys. A key is a variable name in sharedata. A provider is a style # which creates variables in sharedata. _defaultprovider = {} def registerdefaultprovider(style, keys): """sets a style as a default creator for sharedata variables 'keys'""" for key in keys: assert key in style.providesdata, "key not provided by style" # we might allow for overwriting the defaults, i.e. the following is not checked: # assert key in _defaultprovider.keys(), "default provider already registered for key" _defaultprovider[key] = style def getdefaultprovider(key): """returns a style, which acts as a default creator for the sharedata variable 'key'""" return _defaultprovider[key] class styledata: """style data storage class Instances of this class are used to store data from the styles and to pass point data to the styles by instances named privatedata and sharedata. sharedata is shared between all the style(s) in use by a data instance, while privatedata is private to each style and used as a storage place instead of self to prevent side effects when using a style several times.""" pass class plotitem: def __init__(self, graph, data, styles): self.data = data self.title = data.title addstyles = [None] while addstyles: # add styles to ensure all needs of the given styles provided = [] # already provided sharedata variables addstyles = [] # a list of style instances to be added in front for s in styles: for n in s.needsdata: if n not in provided: defaultprovider = getdefaultprovider(n) addstyles.append(defaultprovider) provided.extend(defaultprovider.providesdata) provided.extend(s.providesdata) styles = addstyles + styles self.styles = styles self.sharedata = styledata() self.dataaxisnames = {} self.privatedatalist = [styledata() for s in self.styles] # perform setcolumns to all styles self.usedcolumnnames = set() for privatedata, s in zip(self.privatedatalist, self.styles): self.usedcolumnnames.update(set(s.columnnames(privatedata, self.sharedata, graph, self.data.columnnames, self.dataaxisnames))) def selectstyles(self, graph, selectindex, selecttotal): for privatedata, style in zip(self.privatedatalist, self.styles): style.selectstyle(privatedata, self.sharedata, graph, selectindex, selecttotal) def adjustaxesstatic(self, graph): for columnname, data in list(self.data.columns.items()): for privatedata, style in zip(self.privatedatalist, self.styles): style.adjustaxis(privatedata, self.sharedata, graph, self, columnname, data) def makedynamicdata(self, graph): self.dynamiccolumns = self.data.dynamiccolumns(graph, self.dataaxisnames) def adjustaxesdynamic(self, graph): for columnname, data in list(self.dynamiccolumns.items()): for privatedata, style in zip(self.privatedatalist, self.styles): style.adjustaxis(privatedata, self.sharedata, graph, self, columnname, data) def draw(self, graph): for privatedata, style in zip(self.privatedatalist, self.styles): style.initdrawpoints(privatedata, self.sharedata, graph) point = dict([(columnname, None) for columnname in self.usedcolumnnames]) # fill point with (static) column data first columns = list(self.data.columns.keys()) for values in zip(*list(self.data.columns.values())): for column, value in zip(columns, values): point[column] = value for privatedata, style in zip(self.privatedatalist, self.styles): style.drawpoint(privatedata, self.sharedata, graph, point) point = dict([(columnname, None) for columnname in self.usedcolumnnames]) # insert an empty point if self.data.columns and self.dynamiccolumns: for privatedata, style in zip(self.privatedatalist, self.styles): style.drawpoint(privatedata, self.sharedata, graph, point) # fill point with dynamic column data columns = list(self.dynamiccolumns.keys()) for values in zip(*list(self.dynamiccolumns.values())): for key, value in zip(columns, values): point[key] = value for privatedata, style in zip(self.privatedatalist, self.styles): style.drawpoint(privatedata, self.sharedata, graph, point) for privatedata, style in zip(self.privatedatalist, self.styles): style.donedrawpoints(privatedata, self.sharedata, graph) def key_pt(self, graph, x_pt, y_pt, width_pt, height_pt): for privatedata, style in zip(self.privatedatalist, self.styles): style.key_pt(privatedata, self.sharedata, graph, x_pt, y_pt, width_pt, height_pt) def __getattr__(self, attr): # read only access to the styles privatedata # this is just a convenience method # use case: access the path of a the line style stylesdata = [getattr(styledata, attr) for styledata in self.privatedatalist if hasattr(styledata, attr)] if len(stylesdata) > 1: return stylesdata elif len(stylesdata) == 1: return stylesdata[0] raise AttributeError("access to styledata attribute '%s' failed" % attr) class graph(canvas.canvas): def __init__(self): canvas.canvas.__init__(self) for name in ["background", "filldata", "axes.grid", "axes.baseline", "axes.ticks", "axes.labels", "axes.title", "data", "key"]: self.layer(name) self.axes = {} self.plotitems = [] self.keyitems = [] self._calls = {} self.didranges = 0 self.didstyles = 0 def did(self, method, *args, **kwargs): if method not in self._calls: self._calls[method] = [] for callargs in self._calls[method]: if callargs == (args, kwargs): return 1 self._calls[method].append((args, kwargs)) return 0 def bbox(self): self.finish() return canvas.canvas.bbox(self) def processPS(self, file, writer, context, registry, bbox): self.finish() canvas.canvas.processPS(self, file, writer, context, registry, bbox) def processPDF(self, file, writer, context, registry, bbox): self.finish() canvas.canvas.processPDF(self, file, writer, context, registry, bbox) def plot(self, data, styles=None, rangewarning=1): if self.didranges and rangewarning: logger.warning("axes ranges have already been analysed; no further adjustments will be performed") if self.didstyles: raise RuntimeError("can't plot further data after dostyles() has been executed") singledata = 0 try: for d in data: pass except: usedata = [data] singledata = 1 else: usedata = data if styles is None: for d in usedata: if styles is None: styles = d.defaultstyles elif styles != d.defaultstyles: raise RuntimeError("defaultstyles differ") plotitems = [] for d in usedata: plotitems.append(plotitem(self, d, styles)) self.plotitems.extend(plotitems) if self.didranges: for aplotitem in plotitems: aplotitem.makedynamicdata(self) if singledata: return plotitems[0] else: return plotitems def doranges(self): if self.did(self.doranges): return for plotitem in self.plotitems: plotitem.adjustaxesstatic(self) for plotitem in self.plotitems: plotitem.makedynamicdata(self) for plotitem in self.plotitems: plotitem.adjustaxesdynamic(self) self.didranges = 1 def doaxiscreate(self, axisname): if self.did(self.doaxiscreate, axisname): return self.doaxispositioner(axisname) self.axes[axisname].create() def dolayout(self): raise NotImplementedError def dobackground(self): pass def doaxes(self): raise NotImplementedError def dostyles(self): if self.did(self.dostyles): return self.dolayout() self.dobackground() # count the usage of styles and perform selects styletotal = {} def stylesid(styles): return ":".join([str(id(style)) for style in styles]) for plotitem in self.plotitems: try: styletotal[stylesid(plotitem.styles)] += 1 except: styletotal[stylesid(plotitem.styles)] = 1 styleindex = {} for plotitem in self.plotitems: try: styleindex[stylesid(plotitem.styles)] += 1 except: styleindex[stylesid(plotitem.styles)] = 0 plotitem.selectstyles(self, styleindex[stylesid(plotitem.styles)], styletotal[stylesid(plotitem.styles)]) self.didstyles = 1 def doplotitem(self, plotitem): if self.did(self.doplotitem, plotitem): return self.dostyles() plotitem.draw(self) def doplot(self): for plotitem in self.plotitems: self.doplotitem(plotitem) def dodata(self): logger.warning("dodata() has been deprecated. Use doplot() instead.") self.doplot() def dokeyitem(self, plotitem): if self.did(self.dokeyitem, plotitem): return self.dostyles() if plotitem.title is not None: self.keyitems.append(plotitem) def dokey(self): raise NotImplementedError def finish(self): self.dobackground() self.doaxes() self.doplot() self.dokey() class graphxy(graph): def __init__(self, xpos=0, ypos=0, width=None, height=None, ratio=goldenmean, key=None, backgroundattrs=None, axesdist=0.8*unit.v_cm, flipped=False, xaxisat=None, yaxisat=None, **axes): graph.__init__(self) self.xpos = xpos self.ypos = ypos self.xpos_pt = unit.topt(self.xpos) self.ypos_pt = unit.topt(self.ypos) self.xaxisat = xaxisat self.yaxisat = yaxisat self.key = key self.backgroundattrs = backgroundattrs self.axesdist_pt = unit.topt(axesdist) self.flipped = flipped self.width = width self.height = height if width is None: if height is None: raise ValueError("specify width and/or height") else: self.width = ratio * self.height elif height is None: self.height = (1.0/ratio) * self.width self.width_pt = unit.topt(self.width) self.height_pt = unit.topt(self.height) for axisname, aaxis in list(axes.items()): if aaxis is not None: if not isinstance(aaxis, axis.linkedaxis): self.axes[axisname] = axis.anchoredaxis(aaxis, self.texrunner, axisname) else: self.axes[axisname] = aaxis for axisname, axisat in [("x", xaxisat), ("y", yaxisat)]: okey = axisname + "2" if axisname not in axes: if okey not in axes or axes[okey] is None: self.axes[axisname] = axis.anchoredaxis(axis.linear(), self.texrunner, axisname) if okey not in axes: self.axes[okey] = axis.linkedaxis(self.axes[axisname], okey) else: self.axes[axisname] = axis.linkedaxis(self.axes[okey], axisname) elif okey not in axes and axisat is None: self.axes[okey] = axis.linkedaxis(self.axes[axisname], okey) if "x" in self.axes: self.xbasepath = self.axes["x"].basepath self.xvbasepath = self.axes["x"].vbasepath self.xgridpath = self.axes["x"].gridpath self.xtickpoint_pt = self.axes["x"].tickpoint_pt self.xtickpoint = self.axes["x"].tickpoint self.xvtickpoint_pt = self.axes["x"].vtickpoint_pt self.xvtickpoint = self.axes["x"].tickpoint self.xtickdirection = self.axes["x"].tickdirection self.xvtickdirection = self.axes["x"].vtickdirection if "y" in self.axes: self.ybasepath = self.axes["y"].basepath self.yvbasepath = self.axes["y"].vbasepath self.ygridpath = self.axes["y"].gridpath self.ytickpoint_pt = self.axes["y"].tickpoint_pt self.ytickpoint = self.axes["y"].tickpoint self.yvtickpoint_pt = self.axes["y"].vtickpoint_pt self.yvtickpoint = self.axes["y"].vtickpoint self.ytickdirection = self.axes["y"].tickdirection self.yvtickdirection = self.axes["y"].vtickdirection self.axesnames = ([], []) for axisname, aaxis in list(self.axes.items()): if axisname[0] not in "xy" or (len(axisname) != 1 and (not axisname[1:].isdigit() or axisname[1:] == "1")): raise ValueError("invalid axis name") if axisname[0] == "x": self.axesnames[0].append(axisname) else: self.axesnames[1].append(axisname) aaxis.setcreatecall(self.doaxiscreate, axisname) self.axespositioners = dict(x=positioner.lineaxispos_pt(self.xpos_pt, self.ypos_pt, self.xpos_pt + self.width_pt, self.ypos_pt, (0, 1), self.xvgridpath), x2=positioner.lineaxispos_pt(self.xpos_pt, self.ypos_pt + self.height_pt, self.xpos_pt + self.width_pt, self.ypos_pt + self.height_pt, (0, -1), self.xvgridpath), y=positioner.lineaxispos_pt(self.xpos_pt, self.ypos_pt, self.xpos_pt, self.ypos_pt + self.height_pt, (1, 0), self.yvgridpath), y2=positioner.lineaxispos_pt(self.xpos_pt + self.width_pt, self.ypos_pt, self.xpos_pt + self.width_pt, self.ypos_pt + self.height_pt, (-1, 0), self.yvgridpath)) if self.flipped: self.axespositioners = dict(x=self.axespositioners["y2"], y2=self.axespositioners["x2"], y=self.axespositioners["x"], x2=self.axespositioners["y"]) def pos_pt(self, x, y, xaxis=None, yaxis=None): if xaxis is None: xaxis = self.axes["x"] if yaxis is None: yaxis = self.axes["y"] vx = xaxis.convert(x) vy = yaxis.convert(y) if self.flipped: vx, vy = vy, vx return (self.xpos_pt + vx*self.width_pt, self.ypos_pt + vy*self.height_pt) def pos(self, x, y, xaxis=None, yaxis=None): if xaxis is None: xaxis = self.axes["x"] if yaxis is None: yaxis = self.axes["y"] vx = xaxis.convert(x) vy = yaxis.convert(y) if self.flipped: vx, vy = vy, vx return (self.xpos + vx*self.width, self.ypos + vy*self.height) def vpos_pt(self, vx, vy): if self.flipped: vx, vy = vy, vx return (self.xpos_pt + vx*self.width_pt, self.ypos_pt + vy*self.height_pt) def vpos(self, vx, vy): if self.flipped: vx, vy = vy, vx return (self.xpos + vx*self.width, self.ypos + vy*self.height) def vzindex(self, vx, vy): return 0 def vangle(self, vx1, vy1, vx2, vy2, vx3, vy3): return 1 def vgeodesic(self, vx1, vy1, vx2, vy2): """returns a geodesic path between two points in graph coordinates""" if self.flipped: vx1, vy1 = vy1, vx1 vx2, vy2 = vy2, vx2 return path.line_pt(self.xpos_pt + vx1*self.width_pt, self.ypos_pt + vy1*self.height_pt, self.xpos_pt + vx2*self.width_pt, self.ypos_pt + vy2*self.height_pt) def vgeodesic_el(self, vx1, vy1, vx2, vy2): """returns a geodesic path element between two points in graph coordinates""" if self.flipped: vx1, vy1 = vy1, vx1 vx2, vy2 = vy2, vx2 return path.lineto_pt(self.xpos_pt + vx2*self.width_pt, self.ypos_pt + vy2*self.height_pt) def vcap_pt(self, coordinate, length_pt, vx, vy): """returns an error cap path for a given coordinate, lengths and point in graph coordinates""" if self.flipped: coordinate = 1-coordinate vx, vy = vy, vx if coordinate == 0: return path.line_pt(self.xpos_pt + vx*self.width_pt - 0.5*length_pt, self.ypos_pt + vy*self.height_pt, self.xpos_pt + vx*self.width_pt + 0.5*length_pt, self.ypos_pt + vy*self.height_pt) elif coordinate == 1: return path.line_pt(self.xpos_pt + vx*self.width_pt, self.ypos_pt + vy*self.height_pt - 0.5*length_pt, self.xpos_pt + vx*self.width_pt, self.ypos_pt + vy*self.height_pt + 0.5*length_pt) else: raise ValueError("direction invalid") def xvgridpath(self, vx): return path.line_pt(self.xpos_pt + vx*self.width_pt, self.ypos_pt, self.xpos_pt + vx*self.width_pt, self.ypos_pt + self.height_pt) def yvgridpath(self, vy): return path.line_pt(self.xpos_pt, self.ypos_pt + vy*self.height_pt, self.xpos_pt + self.width_pt, self.ypos_pt + vy*self.height_pt) def autokeygraphattrs(self): return dict(direction="vertical", length=self.height) def autokeygraphtrafo(self, keygraph): dependsonaxisnumber = None if self.flipped: dependsonaxisname = "x" else: dependsonaxisname = "y" for axisname in self.axes: if axisname[0] == dependsonaxisname: if len(axisname) == 1: axisname += "1" axisnumber = int(axisname[1:]) if not (axisnumber % 2) and not self.flipped or (axisnumber % 2) and self.flipped: if dependsonaxisnumber is None or dependsonaxisnumber < axisnumber: dependsonaxisnumber = axisnumber if dependsonaxisnumber is None: x_pt = self.xpos_pt + self.width_pt else: if dependsonaxisnumber > 1: dependsonaxisname += str(dependsonaxisnumber) self.doaxiscreate(dependsonaxisname) x_pt = self.axes[dependsonaxisname].positioner.x1_pt + self.axes[dependsonaxisname].canvas.extent_pt x_pt += self.axesdist_pt return trafo.translate_pt(x_pt, self.ypos_pt) def axisatv(self, axis, v): if axis.positioner.fixtickdirection[0]: # it is a y-axis t = trafo.translate_pt(self.xpos_pt + v*self.width_pt - axis.positioner.x1_pt, 0) else: # it is an x-axis t = trafo.translate_pt(0, self.ypos_pt + v*self.height_pt - axis.positioner.y1_pt) c = canvas.canvas() for layer, subcanvas in list(axis.canvas.layers.items()): c.layer(layer).insert(subcanvas, [t]) assert len(axis.canvas.layers) == len(axis.canvas.items), str(axis.canvas.items) axis.canvas = c def doaxispositioner(self, axisname): if self.did(self.doaxispositioner, axisname): return self.doranges() if axisname in ["x", "x2", "y", "y2"]: self.axes[axisname].setpositioner(self.axespositioners[axisname]) else: if axisname[1:] == "3": dependsonaxisname = axisname[0] else: dependsonaxisname = "%s%d" % (axisname[0], int(axisname[1:]) - 2) self.doaxiscreate(dependsonaxisname) sign = 2*(int(axisname[1:]) % 2) - 1 if axisname[0] == "x" and self.flipped: sign = -sign if axisname[0] == "x" and not self.flipped or axisname[0] == "y" and self.flipped: y_pt = self.axes[dependsonaxisname].positioner.y1_pt - sign * (self.axes[dependsonaxisname].canvas.extent_pt + self.axesdist_pt) self.axes[axisname].setpositioner(positioner.lineaxispos_pt(self.xpos_pt, y_pt, self.xpos_pt + self.width_pt, y_pt, (0, sign), self.xvgridpath)) else: x_pt = self.axes[dependsonaxisname].positioner.x1_pt - sign * (self.axes[dependsonaxisname].canvas.extent_pt + self.axesdist_pt) self.axes[axisname].setpositioner(positioner.lineaxispos_pt(x_pt, self.ypos_pt, x_pt, self.ypos_pt + self.height_pt, (sign, 0), self.yvgridpath)) def dolayout(self): if self.did(self.dolayout): return for axisname in list(self.axes.keys()): self.doaxiscreate(axisname) if self.xaxisat is not None: self.axisatv(self.axes["x"], self.axes["y"].convert(self.xaxisat)) if self.yaxisat is not None: self.axisatv(self.axes["y"], self.axes["x"].convert(self.yaxisat)) def dobackground(self): if self.did(self.dobackground): return if self.backgroundattrs is not None: self.layer("background").draw(path.rect_pt(self.xpos_pt, self.ypos_pt, self.width_pt, self.height_pt), self.backgroundattrs) def doaxes(self): if self.did(self.doaxes): return self.dolayout() self.dobackground() for axis in list(self.axes.values()): for layer, canvas in list(axis.canvas.layers.items()): self.layer("axes.%s" % layer).insert(canvas) assert len(axis.canvas.layers) == len(axis.canvas.items), str(axis.canvas.items) def dokey(self): if self.did(self.dokey): return self.dobackground() for plotitem in self.plotitems: self.dokeyitem(plotitem) if self.key is not None: c = self.key.paint(self.keyitems) bbox = c.bbox() def parentchildalign(pmin, pmax, cmin, cmax, pos, dist, inside): ppos = pmin+0.5*(cmax-cmin)+dist+pos*(pmax-pmin-cmax+cmin-2*dist) cpos = 0.5*(cmin+cmax)+(1-inside)*(1-2*pos)*(cmax-cmin+2*dist) return ppos-cpos if bbox: x = parentchildalign(self.xpos_pt, self.xpos_pt+self.width_pt, bbox.llx_pt, bbox.urx_pt, self.key.hpos, unit.topt(self.key.hdist), self.key.hinside) y = parentchildalign(self.ypos_pt, self.ypos_pt+self.height_pt, bbox.lly_pt, bbox.ury_pt, self.key.vpos, unit.topt(self.key.vdist), self.key.vinside) self.layer("key").insert(c, [trafo.translate_pt(x, y)]) class graphx(graphxy): def __init__(self, xpos=0, ypos=0, length=None, size=0.5*unit.v_cm, direction="vertical", key=None, backgroundattrs=None, axesdist=0.8*unit.v_cm, **axes): for name in axes: if not name.startswith("x"): raise ValueError("Only x axes are allowed") self.direction = direction if self.direction == "vertical": kwargsxy = dict(width=size, height=length, flipped=True) elif self.direction == "horizontal": kwargsxy = dict(width=length, height=size) else: raise ValueError("vertical or horizontal direction required") kwargsxy.update(**axes) graphxy.__init__(self, xpos=xpos, ypos=ypos, ratio=None, key=key, y=axis.lin(min=0, max=1, parter=None), backgroundattrs=backgroundattrs, axesdist=axesdist, **kwargsxy) def pos_pt(self, x, xaxis=None): return graphxy.pos_pt(self, x, 0.5, xaxis) def pos(self, x, xaxis=None): return graphxy.pos(self, x, 0.5, xaxis) def vpos_pt(self, vx): return graphxy.vpos_pt(self, vx, 0.5) def vpos(self, vx): return graphxy.vpos(self, vx, 0.5) def vgeodesic(self, vx1, vx2): return graphxy.vgeodesic(self, vx1, 0.5, vx2, 0.5) def vgeodesic_el(self, vx1, vy1, vx2, vy2): return graphxy.vgeodesic_el(self, vx1, 0.5, vx2, 0.5) def vcap_pt(self, coordinate, length_pt, vx): if coordinate == 0: return graphxy.vcap_pt(self, coordinate, length_pt, vx, 0.5) else: raise ValueError("direction invalid") def xvgridpath(self, vx): return graphxy.xvgridpath(self, vx) def yvgridpath(self, vy): raise Exception("This method does not exist on a one dimensional graph.") def axisatv(self, axis, v): raise Exception("This method does not exist on a one dimensional graph.") class graphxyz(graph): class central: def __init__(self, distance, phi, theta, anglefactor=math.pi/180): phi *= anglefactor theta *= anglefactor self.distance = distance self.a = (-math.sin(phi), math.cos(phi), 0) self.b = (-math.cos(phi)*math.sin(theta), -math.sin(phi)*math.sin(theta), math.cos(theta)) self.eye = (distance*math.cos(phi)*math.cos(theta), distance*math.sin(phi)*math.cos(theta), distance*math.sin(theta)) def point(self, x, y, z): d0 = (self.a[0]*self.b[1]*(z-self.eye[2]) + self.a[2]*self.b[0]*(y-self.eye[1]) + self.a[1]*self.b[2]*(x-self.eye[0]) - self.a[2]*self.b[1]*(x-self.eye[0]) - self.a[0]*self.b[2]*(y-self.eye[1]) - self.a[1]*self.b[0]*(z-self.eye[2])) da = (self.eye[0]*self.b[1]*(z-self.eye[2]) + self.eye[2]*self.b[0]*(y-self.eye[1]) + self.eye[1]*self.b[2]*(x-self.eye[0]) - self.eye[2]*self.b[1]*(x-self.eye[0]) - self.eye[0]*self.b[2]*(y-self.eye[1]) - self.eye[1]*self.b[0]*(z-self.eye[2])) db = (self.a[0]*self.eye[1]*(z-self.eye[2]) + self.a[2]*self.eye[0]*(y-self.eye[1]) + self.a[1]*self.eye[2]*(x-self.eye[0]) - self.a[2]*self.eye[1]*(x-self.eye[0]) - self.a[0]*self.eye[2]*(y-self.eye[1]) - self.a[1]*self.eye[0]*(z-self.eye[2])) return da/d0, db/d0 def zindex(self, x, y, z): return math.sqrt((x-self.eye[0])*(x-self.eye[0])+(y-self.eye[1])*(y-self.eye[1])+(z-self.eye[2])*(z-self.eye[2]))-self.distance def angle(self, x1, y1, z1, x2, y2, z2, x3, y3, z3): sx = (x1-self.eye[0]) sy = (y1-self.eye[1]) sz = (z1-self.eye[2]) nx = (y2-y1)*(z3-z1)-(z2-z1)*(y3-y1) ny = (z2-z1)*(x3-x1)-(x2-x1)*(z3-z1) nz = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1) return (sx*nx+sy*ny+sz*nz)/math.sqrt(nx*nx+ny*ny+nz*nz)/math.sqrt(sx*sx+sy*sy+sz*sz) class parallel: def __init__(self, phi, theta, anglefactor=math.pi/180): phi *= anglefactor theta *= anglefactor self.a = (-math.sin(phi), math.cos(phi), 0) self.b = (-math.cos(phi)*math.sin(theta), -math.sin(phi)*math.sin(theta), math.cos(theta)) self.c = (-math.cos(phi)*math.cos(theta), -math.sin(phi)*math.cos(theta), -math.sin(theta)) def point(self, x, y, z): return self.a[0]*x+self.a[1]*y+self.a[2]*z, self.b[0]*x+self.b[1]*y+self.b[2]*z def zindex(self, x, y, z): return self.c[0]*x+self.c[1]*y+self.c[2]*z def angle(self, x1, y1, z1, x2, y2, z2, x3, y3, z3): nx = (y2-y1)*(z3-z1)-(z2-z1)*(y3-y1) ny = (z2-z1)*(x3-x1)-(x2-x1)*(z3-z1) nz = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1) return (self.c[0]*nx+self.c[1]*ny+self.c[2]*nz)/math.sqrt(nx*nx+ny*ny+nz*nz) def __init__(self, xpos=0, ypos=0, size=None, xscale=1, yscale=1, zscale=1/goldenmean, xy12axesat=None, xy12axesatname="z", projector=central(10, -30, 30), axesdist=0.8*unit.v_cm, key=None, **axes): graph.__init__(self) for name in ["hiddenaxes.grid", "hiddenaxes.baseline", "hiddenaxes.ticks", "hiddenaxes.labels", "hiddenaxes.title"]: self.layer(name) self.layer("hiddenaxes", below="filldata") self.xpos = xpos self.ypos = ypos self.size = size self.xpos_pt = unit.topt(xpos) self.ypos_pt = unit.topt(ypos) self.size_pt = unit.topt(size) self.xscale = xscale self.yscale = yscale self.zscale = zscale self.xy12axesat = xy12axesat self.xy12axesatname = xy12axesatname self.projector = projector self.axesdist_pt = unit.topt(axesdist) self.key = key self.xorder = projector.zindex(0, -1, 0) > projector.zindex(0, 1, 0) and 1 or 0 self.yorder = projector.zindex(-1, 0, 0) > projector.zindex(1, 0, 0) and 1 or 0 self.zindexscale = math.sqrt(xscale*xscale+yscale*yscale+zscale*zscale) # the pXYshow attributes are booleans stating whether plane perpendicular to axis X # at the virtual graph coordinate Y will be hidden by data or not. An axis is considered # to be visible if one of the two planes it is part of is visible. Other axes are drawn # in the hiddenaxes layer (i.e. layer group). # TODO: Tick and grid visibility is treated like the axis visibility at the moment. self.pz0show = self.vangle(0, 0, 0, 1, 0, 0, 1, 1, 0) > 0 self.pz1show = self.vangle(0, 0, 1, 0, 1, 1, 1, 1, 1) > 0 self.py0show = self.vangle(0, 0, 0, 0, 0, 1, 1, 0, 1) > 0 self.py1show = self.vangle(0, 1, 0, 1, 1, 0, 1, 1, 1) > 0 self.px0show = self.vangle(0, 0, 0, 0, 1, 0, 0, 1, 1) > 0 self.px1show = self.vangle(1, 0, 0, 1, 0, 1, 1, 1, 1) > 0 for axisname, aaxis in list(axes.items()): if aaxis is not None: if not isinstance(aaxis, axis.linkedaxis): self.axes[axisname] = axis.anchoredaxis(aaxis, self.texrunner, axisname) else: self.axes[axisname] = aaxis for axisname in ["x", "y"]: okey = axisname + "2" if axisname not in axes: if okey not in axes or axes[okey] is None: self.axes[axisname] = axis.anchoredaxis(axis.linear(), self.texrunner, axisname) if okey not in axes: self.axes[okey] = axis.linkedaxis(self.axes[axisname], okey) else: self.axes[axisname] = axis.linkedaxis(self.axes[okey], axisname) elif okey not in axes: self.axes[okey] = axis.linkedaxis(self.axes[axisname], okey) if "z" not in axes: self.axes["z"] = axis.anchoredaxis(axis.linear(), self.texrunner, "z") if "x" in self.axes: self.xbasepath = self.axes["x"].basepath self.xvbasepath = self.axes["x"].vbasepath self.xgridpath = self.axes["x"].gridpath self.xtickpoint_pt = self.axes["x"].tickpoint_pt self.xtickpoint = self.axes["x"].tickpoint self.xvtickpoint_pt = self.axes["x"].vtickpoint_pt self.xvtickpoint = self.axes["x"].tickpoint self.xtickdirection = self.axes["x"].tickdirection self.xvtickdirection = self.axes["x"].vtickdirection if "y" in self.axes: self.ybasepath = self.axes["y"].basepath self.yvbasepath = self.axes["y"].vbasepath self.ygridpath = self.axes["y"].gridpath self.ytickpoint_pt = self.axes["y"].tickpoint_pt self.ytickpoint = self.axes["y"].tickpoint self.yvtickpoint_pt = self.axes["y"].vtickpoint_pt self.yvtickpoint = self.axes["y"].vtickpoint self.ytickdirection = self.axes["y"].tickdirection self.yvtickdirection = self.axes["y"].vtickdirection if "z" in self.axes: self.zbasepath = self.axes["z"].basepath self.zvbasepath = self.axes["z"].vbasepath self.zgridpath = self.axes["z"].gridpath self.ztickpoint_pt = self.axes["z"].tickpoint_pt self.ztickpoint = self.axes["z"].tickpoint self.zvtickpoint_pt = self.axes["z"].vtickpoint self.zvtickpoint = self.axes["z"].vtickpoint self.ztickdirection = self.axes["z"].tickdirection self.zvtickdirection = self.axes["z"].vtickdirection self.axesnames = ([], [], []) for axisname, aaxis in list(self.axes.items()): if axisname[0] not in "xyz" or (len(axisname) != 1 and (not axisname[1:].isdigit() or axisname[1:] == "1")): raise ValueError("invalid axis name") if axisname[0] == "x": self.axesnames[0].append(axisname) elif axisname[0] == "y": self.axesnames[1].append(axisname) else: self.axesnames[2].append(axisname) aaxis.setcreatecall(self.doaxiscreate, axisname) def pos_pt(self, x, y, z, xaxis=None, yaxis=None, zaxis=None): if xaxis is None: xaxis = self.axes["x"] if yaxis is None: yaxis = self.axes["y"] if zaxis is None: zaxis = self.axes["z"] return self.vpos_pt(xaxis.convert(x), yaxis.convert(y), zaxis.convert(z)) def pos(self, x, y, z, xaxis=None, yaxis=None, zaxis=None): if xaxis is None: xaxis = self.axes["x"] if yaxis is None: yaxis = self.axes["y"] if zaxis is None: zaxis = self.axes["z"] return self.vpos(xaxis.convert(x), yaxis.convert(y), zaxis.convert(z)) def vpos_pt(self, vx, vy, vz): x, y = self.projector.point(2*self.xscale*(vx - 0.5), 2*self.yscale*(vy - 0.5), 2*self.zscale*(vz - 0.5)) return self.xpos_pt+x*self.size_pt, self.ypos_pt+y*self.size_pt def vpos(self, vx, vy, vz): x, y = self.projector.point(2*self.xscale*(vx - 0.5), 2*self.yscale*(vy - 0.5), 2*self.zscale*(vz - 0.5)) return self.xpos+x*self.size, self.ypos+y*self.size def vzindex(self, vx, vy, vz): return self.projector.zindex(2*self.xscale*(vx - 0.5), 2*self.yscale*(vy - 0.5), 2*self.zscale*(vz - 0.5))/self.zindexscale def vangle(self, vx1, vy1, vz1, vx2, vy2, vz2, vx3, vy3, vz3): return self.projector.angle(2*self.xscale*(vx1 - 0.5), 2*self.yscale*(vy1 - 0.5), 2*self.zscale*(vz1 - 0.5), 2*self.xscale*(vx2 - 0.5), 2*self.yscale*(vy2 - 0.5), 2*self.zscale*(vz2 - 0.5), 2*self.xscale*(vx3 - 0.5), 2*self.yscale*(vy3 - 0.5), 2*self.zscale*(vz3 - 0.5)) def vgeodesic(self, vx1, vy1, vz1, vx2, vy2, vz2): """returns a geodesic path between two points in graph coordinates""" return path.line_pt(*(self.vpos_pt(vx1, vy1, vz1) + self.vpos_pt(vx2, vy2, vz2))) def vgeodesic_el(self, vx1, vy1, vz1, vx2, vy2, vz2): """returns a geodesic path element between two points in graph coordinates""" return path.lineto_pt(*self.vpos_pt(vx2, vy2, vz2)) def vcap_pt(self, coordinate, length_pt, vx, vy, vz): """returns an error cap path for a given coordinate, lengths and point in graph coordinates""" if coordinate == 0: return self.vgeodesic(vx-0.5*length_pt/self.size_pt, vy, vz, vx+0.5*length_pt/self.size_pt, vy, vz) elif coordinate == 1: return self.vgeodesic(vx, vy-0.5*length_pt/self.size_pt, vz, vx, vy+0.5*length_pt/self.size_pt, vz) elif coordinate == 2: return self.vgeodesic(vx, vy, vz-0.5*length_pt/self.size_pt, vx, vy, vz+0.5*length_pt/self.size_pt) else: raise ValueError("direction invalid") def xvtickdirection(self, vx): if self.xorder: x1_pt, y1_pt = self.vpos_pt(vx, 1, 0) x2_pt, y2_pt = self.vpos_pt(vx, 0, 0) else: x1_pt, y1_pt = self.vpos_pt(vx, 0, 0) x2_pt, y2_pt = self.vpos_pt(vx, 1, 0) dx_pt = x2_pt - x1_pt dy_pt = y2_pt - y1_pt norm = math.hypot(dx_pt, dy_pt) return dx_pt/norm, dy_pt/norm def yvtickdirection(self, vy): if self.yorder: x1_pt, y1_pt = self.vpos_pt(1, vy, 0) x2_pt, y2_pt = self.vpos_pt(0, vy, 0) else: x1_pt, y1_pt = self.vpos_pt(0, vy, 0) x2_pt, y2_pt = self.vpos_pt(1, vy, 0) dx_pt = x2_pt - x1_pt dy_pt = y2_pt - y1_pt norm = math.hypot(dx_pt, dy_pt) return dx_pt/norm, dy_pt/norm def vtickdirection(self, vx1, vy1, vz1, vx2, vy2, vz2): x1_pt, y1_pt = self.vpos_pt(vx1, vy1, vz1) x2_pt, y2_pt = self.vpos_pt(vx2, vy2, vz2) dx_pt = x2_pt - x1_pt dy_pt = y2_pt - y1_pt norm = math.hypot(dx_pt, dy_pt) return dx_pt/norm, dy_pt/norm def xvgridpath(self, vx): return path.path(path.moveto_pt(*self.vpos_pt(vx, 0, 0)), path.lineto_pt(*self.vpos_pt(vx, 1, 0)), path.lineto_pt(*self.vpos_pt(vx, 1, 1)), path.lineto_pt(*self.vpos_pt(vx, 0, 1)), path.closepath()) def yvgridpath(self, vy): return path.path(path.moveto_pt(*self.vpos_pt(0, vy, 0)), path.lineto_pt(*self.vpos_pt(1, vy, 0)), path.lineto_pt(*self.vpos_pt(1, vy, 1)), path.lineto_pt(*self.vpos_pt(0, vy, 1)), path.closepath()) def zvgridpath(self, vz): return path.path(path.moveto_pt(*self.vpos_pt(0, 0, vz)), path.lineto_pt(*self.vpos_pt(1, 0, vz)), path.lineto_pt(*self.vpos_pt(1, 1, vz)), path.lineto_pt(*self.vpos_pt(0, 1, vz)), path.closepath()) def autokeygraphattrs(self): return dict(direction="vertical", length=self.size) def autokeygraphtrafo(self, keygraph): self.doaxes() x_pt = self.layer("axes").bbox().right_pt() + self.axesdist_pt y_pt = 0.5*(self.layer("axes").bbox().top_pt() + self.layer("axes").bbox().bottom_pt() - self.size_pt) return trafo.translate_pt(x_pt, y_pt) def doaxispositioner(self, axisname): if self.did(self.doaxispositioner, axisname): return self.doranges() if self.xy12axesat is not None: self.doaxiscreate(self.xy12axesatname) self.doaxispositioner(self.xy12axesatname) xy12axesatv = self.axes[self.xy12axesatname].convert(self.xy12axesat) else: xy12axesatv = 0 if axisname == "x": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vx: self.vpos_pt(vx, self.xorder, xy12axesatv), lambda vx: self.vtickdirection(vx, self.xorder, 0, vx, 1-self.xorder, xy12axesatv), self.xvgridpath)) if self.xorder: self.axes[axisname].hidden = not self.py1show and not self.pz0show else: self.axes[axisname].hidden = not self.py0show and not self.pz0show elif axisname == "x2": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vx: self.vpos_pt(vx, 1-self.xorder, xy12axesatv), lambda vx: self.vtickdirection(vx, 1-self.xorder, 0, vx, self.xorder, xy12axesatv), self.xvgridpath)) if self.xorder: self.axes[axisname].hidden = not self.py0show and not self.pz0show else: self.axes[axisname].hidden = not self.py1show and not self.pz0show elif axisname == "x3": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vx: self.vpos_pt(vx, self.xorder, 1), lambda vx: self.vtickdirection(vx, self.xorder, 1, vx, 1-self.xorder, 1), self.xvgridpath)) if self.xorder: self.axes[axisname].hidden = not self.py1show and not self.pz1show else: self.axes[axisname].hidden = not self.py0show and not self.pz1show elif axisname == "x4": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vx: self.vpos_pt(vx, 1-self.xorder, 1), lambda vx: self.vtickdirection(vx, 1-self.xorder, 1, vx, self.xorder, 1), self.xvgridpath)) if self.xorder: self.axes[axisname].hidden = not self.py0show and not self.pz1show else: self.axes[axisname].hidden = not self.py1show and not self.pz1show elif axisname == "y": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vy: self.vpos_pt(self.yorder, vy, xy12axesatv), lambda vy: self.vtickdirection(self.yorder, vy, 0, 1-self.yorder, vy, xy12axesatv), self.yvgridpath)) if self.yorder: self.axes[axisname].hidden = not self.px1show and not self.pz0show else: self.axes[axisname].hidden = not self.px0show and not self.pz0show elif axisname == "y2": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vy: self.vpos_pt(1-self.yorder, vy, xy12axesatv), lambda vy: self.vtickdirection(1-self.yorder, vy, 0, self.yorder, vy, xy12axesatv), self.yvgridpath)) if self.yorder: self.axes[axisname].hidden = not self.px0show and not self.pz0show else: self.axes[axisname].hidden = not self.px1show and not self.pz0show elif axisname == "y3": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vy: self.vpos_pt(self.yorder, vy, 1), lambda vy: self.vtickdirection(self.yorder, vy, 1, 1-self.yorder, vy, 1), self.yvgridpath)) if self.yorder: self.axes[axisname].hidden = not self.px1show and not self.pz1show else: self.axes[axisname].hidden = not self.px0show and not self.pz1show elif axisname == "y4": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vy: self.vpos_pt(1-self.yorder, vy, 1), lambda vy: self.vtickdirection(1-self.yorder, vy, 1, self.yorder, vy, 1), self.yvgridpath)) if self.yorder: self.axes[axisname].hidden = not self.px0show and not self.pz1show else: self.axes[axisname].hidden = not self.px1show and not self.pz1show elif axisname == "z": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vz: self.vpos_pt(0, 0, vz), lambda vz: self.vtickdirection(0, 0, vz, 1, 1, vz), self.zvgridpath)) self.axes[axisname].hidden = not self.px0show and not self.py0show elif axisname == "z2": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vz: self.vpos_pt(1, 0, vz), lambda vz: self.vtickdirection(1, 0, vz, 0, 1, vz), self.zvgridpath)) self.axes[axisname].hidden = not self.px1show and not self.py0show elif axisname == "z3": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vz: self.vpos_pt(0, 1, vz), lambda vz: self.vtickdirection(0, 1, vz, 1, 0, vz), self.zvgridpath)) self.axes[axisname].hidden = not self.px0show and not self.py1show elif axisname == "z4": self.axes[axisname].setpositioner(positioner.flexlineaxispos_pt(lambda vz: self.vpos_pt(1, 1, vz), lambda vz: self.vtickdirection(1, 1, vz, 0, 0, vz), self.zvgridpath)) self.axes[axisname].hidden = not self.px1show and not self.py1show else: raise NotImplementedError("4 axis per dimension supported only") def dolayout(self): if self.did(self.dolayout): return for axisname in list(self.axes.keys()): self.doaxiscreate(axisname) def dobackground(self): if self.did(self.dobackground): return def doaxes(self): if self.did(self.doaxes): return self.dolayout() self.dobackground() for axis in list(self.axes.values()): if axis.hidden: self.layer("hiddenaxes").insert(axis.canvas) else: self.layer("axes").insert(axis.canvas) def dokey(self): if self.did(self.dokey): return self.dobackground() for plotitem in self.plotitems: self.dokeyitem(plotitem) if self.key is not None: c = self.key.paint(self.keyitems) bbox = c.bbox() def parentchildalign(pmin, pmax, cmin, cmax, pos, dist, inside): ppos = pmin+0.5*(cmax-cmin)+dist+pos*(pmax-pmin-cmax+cmin-2*dist) cpos = 0.5*(cmin+cmax)+(1-inside)*(1-2*pos)*(cmax-cmin+2*dist) return ppos-cpos if bbox: x = parentchildalign(self.xpos_pt, self.xpos_pt+self.size_pt, bbox.llx_pt, bbox.urx_pt, self.key.hpos, unit.topt(self.key.hdist), self.key.hinside) y = parentchildalign(self.ypos_pt, self.ypos_pt+self.size_pt, bbox.lly_pt, bbox.ury_pt, self.key.vpos, unit.topt(self.key.vdist), self.key.vinside) self.insert(c, [trafo.translate_pt(x, y)]) PyX-0.14.1/pyx/graph/key.py0000644000076500000240000001143412177540643015630 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from pyx import box, canvas, text, trafo, unit class key: defaulttextattrs = [text.vshift.mathaxis] def __init__(self, dist=0.2*unit.v_cm, pos="tr", hpos=None, vpos=None, hinside=1, vinside=1, hdist=0.6*unit.v_cm, vdist=0.4*unit.v_cm, symbolwidth=0.5*unit.v_cm, symbolheight=0.25*unit.v_cm, symbolspace=0.2*unit.v_cm, textattrs=[], columns=1, columndist=0.5*unit.v_cm, border=0.3*unit.v_cm, keyattrs=None): self.dist = dist self.hinside = hinside self.vinside = vinside self.hdist = hdist self.vdist = vdist self.symbolwidth = symbolwidth self.symbolheight = symbolheight self.symbolspace = symbolspace self.textattrs = textattrs self.columns = columns self.columndist = columndist self.border = border self.keyattrs = keyattrs if pos is not None: if vpos is not None or hpos is not None: raise ValueError("either specify pos or a combination of hpos, vpos") for poslist, hpos, vpos in [(["tr", "rt"], 1, 1), (["tc", "ct"], 0.5, 1), (["tl", "lt"], 0, 1), (["mr", "rm"], 1, 0.5), (["mc", "cm"], 0.5, 0.5), (["ml", "lm"], 0, 0.5), (["br", "rb"], 1, 0), (["bc", "cb"], 0.5, 0), (["bl", "lb"], 0, 0)]: if pos in poslist: self.hpos = hpos self.vpos = vpos break else: raise ValueError("invalid pos") else: if vpos is None or hpos is None: raise ValueError("either specify pos or a combination of hpos, vpos") self.hpos = hpos self.vpos = vpos def paintcolumn(self, plotitems): "creates the layout of a key column" c = canvas.canvas() self.dist_pt = unit.topt(self.dist) self.hdist_pt = unit.topt(self.hdist) self.vdist_pt = unit.topt(self.vdist) self.symbolwidth_pt = unit.topt(self.symbolwidth) self.symbolheight_pt = unit.topt(self.symbolheight) self.symbolspace_pt = unit.topt(self.symbolspace) titleboxes = [] for plotitem in plotitems: titlebox = c.texrunner.text_pt(0, 0, plotitem.title, self.defaulttextattrs + self.textattrs) titlebox.plotitem = plotitem titleboxes.append(titlebox) dy_pt = box.tile_pt(titleboxes, self.dist_pt, 0, -1) box.linealignequal_pt(titleboxes, self.symbolwidth_pt + self.symbolspace_pt, 1, 0) y_pt = -0.5 * self.symbolheight_pt + titleboxes[0].center[1] for titlebox in titleboxes: titlebox.plotitem.key_pt(c, 0, y_pt, self.symbolwidth_pt, self.symbolheight_pt) y_pt -= dy_pt for titlebox in titleboxes: c.insert(titlebox) return c def paint(self, plotitems): "creates the layout of the key" columndist_pt = unit.topt(self.columndist) c = canvas.canvas() itemspercolumn = (len(plotitems) + self.columns - 1) // self.columns x_pt = 0 while plotitems: subc = self.paintcolumn(plotitems[:itemspercolumn]) c.insert(subc, [trafo.translate_pt(x_pt, 0)]) x_pt += unit.topt(subc.bbox().width()) + columndist_pt del plotitems[:itemspercolumn] if self.keyattrs is not None: newc = canvas.canvas() newc.draw(c.bbox().enlarged(self.border).path(), self.keyattrs) newc.insert(c) c = newc return c PyX-0.14.1/pyx/graph/style.py0000644000076500000240000031540312254655336016205 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, logging, math from pyx import attr, deco, bitmap, style, color, unit, canvas, path, mesh, trafo from pyx import text as textmodule from .graph import registerdefaultprovider, graphx from . import axis builtinrange = range logger = logging.getLogger("pyx") class _style: """Interface class for graph styles Each graph style must support the methods described in this class. However, since a graph style might not need to perform actions on all the various events, it does not need to overwrite all methods of this base class (e.g. this class is not an abstract class in any respect). A style should never store private data by instance variables (i.e. accessing self), but it should use the sharedata and privatedata instances instead. A style instance can be used multiple times with different sharedata and privatedata instances at the very same time. The sharedata and privatedata instances act as data containers and sharedata allows for sharing information across several styles. Every style contains two class variables, which are not to be modified: - providesdata is a list of variable names a style offers via the sharedata instance. This list is used to determine whether all needs of subsequent styles are fulfilled. Otherwise getdefaultprovider should return a proper style to be used. - needsdata is a list of variable names the style needs to access in the sharedata instance. """ providesdata = [] # by default, we provide nothing needsdata = [] # and do not depend on anything def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): """Set column information This method is used setup the column name information to be accessible to the style later on. The style should analyse the list of column names. The method should return a list of column names which the style will make use of. If a style uses some column data to feed into an axis with a different name, it should add an entry into the dataaxisnames dictionary with key begin the column name and the value being the axis name.""" return [] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): """Adjust axis range This method is called in order to adjust the axis range to the provided data. columnname is the column name (each style is subsequently called for all column names).""" pass def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): """Select stroke/fill attributes This method is called to allow for the selection of changable attributes of a style.""" pass def initdrawpoints(self, privatedata, sharedata, graph): """Initialize drawing of data This method might be used to initialize the drawing of data.""" pass def drawpoint(self, privatedata, sharedata, graph, point): """Draw data This method is called for each data point. The data is available in the dictionary point. The dictionary keys are the column names.""" pass def donedrawpoints(self, privatedata, sharedata, graph): """Finalize drawing of data This method is called after the last data point was drawn using the drawpoint method above.""" pass def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): """Draw graph key""" pass class _marker: pass class _autokeygraph: pass class _keygraphstyle(_style): autographkey = _autokeygraph def __init__(self, colorname="color", gradient=color.gradient.Grey, coloraxis=None, keygraph=_autokeygraph): self.colorname = colorname self.gradient = gradient self.coloraxis = coloraxis self.keygraph = keygraph def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): return [self.colorname] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): if columnname == self.colorname: if self.keygraph is None: # we always need a keygraph, but we might not show it if self.coloraxis is None: coloraxis = axis.lin() else: coloraxis = self.coloraxis privatedata.keygraph = graphx(length=10, direction="vertical", x=coloraxis) elif self.keygraph is _autokeygraph: if self.coloraxis is None: coloraxis = axis.lin(title=plotitem.title) plotitem.title = None # Huui!? else: coloraxis = self.coloraxis privatedata.keygraph = graphx(x=coloraxis, **graph.autokeygraphattrs()) else: privatedata.keygraph = self.keygraph # TODO: we shouldn't have multiple plotitems from . import data as datamodule privatedata.keygraph.plot(datamodule.values(x=data), [gradient(gradient=self.gradient)]) def color(self, privatedata, c): vc = privatedata.keygraph.axes["x"].convert(c) if vc < 0: logger.warning("gradient color range is exceeded (lower bound)") vc = 0 if vc > 1: logger.warning("gradient color range is exceeded (upper bound)") vc = 1 return self.gradient.getcolor(vc) def donedrawpoints(self, privatedata, sharedata, graph): if self.keygraph is _autokeygraph: graph.layer("key").insert(privatedata.keygraph, [graph.autokeygraphtrafo(privatedata.keygraph)]) class pos(_style): providesdata = ["vpos", "vposmissing", "vposavailable", "vposvalid", "poscolumnnames"] def __init__(self, usenames={}, epsilon=1e-10): self.usenames = usenames self.epsilon = epsilon def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): privatedata.poscolumnnames = [] privatedata.vposmissing = [] privatedata.axisnames = {} for count, axisnames in enumerate(graph.axesnames): for axisname in axisnames: try: usename = self.usenames[axisname] except KeyError: usename = axisname for columnname in columnnames: if usename == columnname: privatedata.poscolumnnames.append(columnname) privatedata.axisnames[columnname] = axisname if len(privatedata.poscolumnnames) > count+1: raise ValueError("multiple axes per graph dimension") elif len(privatedata.poscolumnnames) < count+1: privatedata.vposmissing.append(count) privatedata.poscolumnnames.append(None) # Make poscolumnnames and vposmissing available to the outside, # but keep a private reference. A copy is not needed, because # the data is not altered in place, but might be exchanged my a # later, different pos style in the styles list (due to different # usenames). sharedata.poscolumnnames = privatedata.poscolumnnames sharedata.vposmissing = privatedata.vposmissing dataaxisnames.update(privatedata.axisnames) return [columnname for columnname in privatedata.poscolumnnames if columnname is not None] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): if columnname in privatedata.axisnames: graph.axes[privatedata.axisnames[columnname]].adjustaxis(data) def initdrawpoints(self, privatedata, sharedata, graph): sharedata.vpos = [None]*(len(graph.axesnames)) privatedata.pointpostmplist = [[columnname, index, graph.axes[privatedata.axisnames[columnname]]] # temporarily used by drawpoint only for index, columnname in enumerate([columnname for columnname in privatedata.poscolumnnames if columnname is not None])] for missing in privatedata.vposmissing: for pointpostmp in privatedata.pointpostmplist: if pointpostmp[1] >= missing: pointpostmp[1] += 1 def drawpoint(self, privatedata, sharedata, graph, point): sharedata.vposavailable = 1 # valid position (but might be outside of the graph) sharedata.vposvalid = 1 # valid position inside the graph for columnname, index, axis in privatedata.pointpostmplist: try: v = axis.convert(point[columnname]) except (ArithmeticError, ValueError, TypeError): sharedata.vposavailable = sharedata.vposvalid = 0 sharedata.vpos[index] = None else: if v < -self.epsilon or v > 1+self.epsilon: sharedata.vposvalid = 0 sharedata.vpos[index] = v registerdefaultprovider(pos(), pos.providesdata) class range(_style): providesdata = ["vrange", "vrangemissing", "vrangeminmissing", "vrangemaxmissing"] # internal bit masks mask_value = 1 mask_min = 2 mask_max = 4 mask_dmin = 8 mask_dmax = 16 mask_d = 32 def __init__(self, usenames={}, epsilon=1e-10): self.usenames = usenames self.epsilon = epsilon def _numberofbits(self, mask): if not mask: return 0 if mask & 1: return self._numberofbits(mask >> 1) + 1 else: return self._numberofbits(mask >> 1) def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): usecolumns = [] privatedata.rangeposcolumns = [] sharedata.vrangemissing = [] sharedata.vrangeminmissing = [] sharedata.vrangemaxmissing = [] privatedata.rangeposdeltacolumns = {} # temporarily used by adjustaxis only for count, axisnames in enumerate(graph.axesnames): for axisname in axisnames: try: usename = self.usenames[axisname] except KeyError: usename = axisname mask = 0 for columnname in columnnames: addusecolumns = 1 if usename == columnname: mask += self.mask_value elif usename + "min" == columnname: mask += self.mask_min elif usename + "max" == columnname: mask += self.mask_max elif "d" + usename + "min" == columnname: mask += self.mask_dmin elif "d" + usename + "max" == columnname: mask += self.mask_dmax elif "d" + usename == columnname: mask += self.mask_d else: addusecolumns = 0 if addusecolumns: usecolumns.append(columnname) dataaxisnames[columnname] = axisname if mask & (self.mask_min | self.mask_max | self.mask_dmin | self.mask_dmax | self.mask_d): if (self._numberofbits(mask & (self.mask_min | self.mask_dmin | self.mask_d)) > 1 or self._numberofbits(mask & (self.mask_max | self.mask_dmax | self.mask_d)) > 1): raise ValueError("multiple range definition") if mask & (self.mask_dmin | self.mask_dmax | self.mask_d): if not (mask & self.mask_value): raise ValueError("missing value for delta") privatedata.rangeposdeltacolumns[axisname] = {} privatedata.rangeposcolumns.append((axisname, usename, mask)) elif mask == self.mask_value: usecolumns = usecolumns[:-1] if len(privatedata.rangeposcolumns) + len(sharedata.vrangemissing) > count+1: raise ValueError("multiple axes per graph dimension") elif len(privatedata.rangeposcolumns) + len(sharedata.vrangemissing) < count+1: sharedata.vrangemissing.append(count) sharedata.vrangeminmissing.append(count) sharedata.vrangemaxmissing.append(count) else: if not (privatedata.rangeposcolumns[-1][2] & (self.mask_min | self.mask_dmin | self.mask_d)): sharedata.vrangeminmissing.append(count) if not (privatedata.rangeposcolumns[-1][2] & (self.mask_max | self.mask_dmax | self.mask_d)): sharedata.vrangemaxmissing.append(count) return usecolumns def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): for axisname, usename, mask in privatedata.rangeposcolumns: if columnname == usename + "min" and mask & self.mask_min: graph.axes[axisname].adjustaxis(data) if columnname == usename + "max" and mask & self.mask_max: graph.axes[axisname].adjustaxis(data) # delta handling: fill rangeposdeltacolumns for axisname, usename, mask in privatedata.rangeposcolumns: if columnname == usename and mask & (self.mask_dmin | self.mask_dmax | self.mask_d): privatedata.rangeposdeltacolumns[axisname][self.mask_value] = data if columnname == "d" + usename + "min" and mask & self.mask_dmin: privatedata.rangeposdeltacolumns[axisname][self.mask_dmin] = data if columnname == "d" + usename + "max" and mask & self.mask_dmax: privatedata.rangeposdeltacolumns[axisname][self.mask_dmax] = data if columnname == "d" + usename and mask & self.mask_d: privatedata.rangeposdeltacolumns[axisname][self.mask_d] = data # delta handling: process rangeposdeltacolumns for a, d in list(privatedata.rangeposdeltacolumns.items()): if self.mask_value in d: for k in list(d.keys()): if k != self.mask_value: if k & (self.mask_dmin | self.mask_d): mindata = [] for value, delta in zip(d[self.mask_value], d[k]): try: mindata.append(value-delta) except: pass graph.axes[a].adjustaxis(mindata) if k & (self.mask_dmax | self.mask_d): maxdata = [] for value, delta in zip(d[self.mask_value], d[k]): try: maxdata.append(value+delta) except: pass graph.axes[a].adjustaxis(maxdata) del d[k] def initdrawpoints(self, privatedata, sharedata, graph): sharedata.vrange = [[None for x in builtinrange(2)] for y in privatedata.rangeposcolumns + sharedata.vrangemissing] privatedata.rangepostmplist = [[usename, mask, index, graph.axes[axisname]] # temporarily used by drawpoint only for index, (axisname, usename, mask) in enumerate(privatedata.rangeposcolumns)] for missing in sharedata.vrangemissing: for rangepostmp in privatedata.rangepostmplist: if rangepostmp[2] >= missing: rangepostmp[2] += 1 def drawpoint(self, privatedata, sharedata, graph, point): for usename, mask, index, axis in privatedata.rangepostmplist: try: if mask & self.mask_min: sharedata.vrange[index][0] = axis.convert(point[usename + "min"]) if mask & self.mask_dmin: sharedata.vrange[index][0] = axis.convert(point[usename] - point["d" + usename + "min"]) if mask & self.mask_d: sharedata.vrange[index][0] = axis.convert(point[usename] - point["d" + usename]) except (ArithmeticError, ValueError, TypeError): sharedata.vrange[index][0] = None try: if mask & self.mask_max: sharedata.vrange[index][1] = axis.convert(point[usename + "max"]) if mask & self.mask_dmax: sharedata.vrange[index][1] = axis.convert(point[usename] + point["d" + usename + "max"]) if mask & self.mask_d: sharedata.vrange[index][1] = axis.convert(point[usename] + point["d" + usename]) except (ArithmeticError, ValueError, TypeError): sharedata.vrange[index][1] = None registerdefaultprovider(range(), range.providesdata) def _crosssymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.moveto_pt(x_pt-0.5*size_pt, y_pt-0.5*size_pt), path.lineto_pt(x_pt+0.5*size_pt, y_pt+0.5*size_pt), path.moveto_pt(x_pt-0.5*size_pt, y_pt+0.5*size_pt), path.lineto_pt(x_pt+0.5*size_pt, y_pt-0.5*size_pt)), attrs) def _plussymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.moveto_pt(x_pt-0.707106781*size_pt, y_pt), path.lineto_pt(x_pt+0.707106781*size_pt, y_pt), path.moveto_pt(x_pt, y_pt-0.707106781*size_pt), path.lineto_pt(x_pt, y_pt+0.707106781*size_pt)), attrs) def _squaresymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.moveto_pt(x_pt-0.5*size_pt, y_pt-0.5*size_pt), path.lineto_pt(x_pt+0.5*size_pt, y_pt-0.5*size_pt), path.lineto_pt(x_pt+0.5*size_pt, y_pt+0.5*size_pt), path.lineto_pt(x_pt-0.5*size_pt, y_pt+0.5*size_pt), path.closepath()), attrs) def _trianglesymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.moveto_pt(x_pt-0.759835685*size_pt, y_pt-0.438691337*size_pt), path.lineto_pt(x_pt+0.759835685*size_pt, y_pt-0.438691337*size_pt), path.lineto_pt(x_pt, y_pt+0.877382675*size_pt), path.closepath()), attrs) def _circlesymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.arc_pt(x_pt, y_pt, 0.564189583*size_pt, 0, 360), path.closepath()), attrs) def _diamondsymbol(c, x_pt, y_pt, size_pt, attrs): c.draw(path.path(path.moveto_pt(x_pt-0.537284965*size_pt, y_pt), path.lineto_pt(x_pt, y_pt-0.930604859*size_pt), path.lineto_pt(x_pt+0.537284965*size_pt, y_pt), path.lineto_pt(x_pt, y_pt+0.930604859*size_pt), path.closepath()), attrs) class _styleneedingpointpos(_style): needsdata = ["vposmissing"] def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if len(sharedata.vposmissing): raise ValueError("incomplete position information") return [] class symbol(_styleneedingpointpos): needsdata = ["vpos", "vposmissing", "vposvalid"] # "inject" the predefinied symbols into the class: # # Note, that statements like cross = _crosssymbol are # invalid, since the would lead to unbound methods, but # a single entry changeable list does the trick. # # Once we require Python 2.2+ we should use staticmethods # to implement the default symbols inplace. cross = attr.changelist([_crosssymbol]) plus = attr.changelist([_plussymbol]) square = attr.changelist([_squaresymbol]) triangle = attr.changelist([_trianglesymbol]) circle = attr.changelist([_circlesymbol]) diamond = attr.changelist([_diamondsymbol]) changecross = attr.changelist([_crosssymbol, _plussymbol, _squaresymbol, _trianglesymbol, _circlesymbol, _diamondsymbol]) changeplus = attr.changelist([_plussymbol, _squaresymbol, _trianglesymbol, _circlesymbol, _diamondsymbol, _crosssymbol]) changesquare = attr.changelist([_squaresymbol, _trianglesymbol, _circlesymbol, _diamondsymbol, _crosssymbol, _plussymbol]) changetriangle = attr.changelist([_trianglesymbol, _circlesymbol, _diamondsymbol, _crosssymbol, _plussymbol, _squaresymbol]) changecircle = attr.changelist([_circlesymbol, _diamondsymbol, _crosssymbol, _plussymbol, _squaresymbol, _trianglesymbol]) changediamond = attr.changelist([_diamondsymbol, _crosssymbol, _plussymbol, _squaresymbol, _trianglesymbol, _circlesymbol]) changesquaretwice = attr.changelist([_squaresymbol, _squaresymbol, _trianglesymbol, _trianglesymbol, _circlesymbol, _circlesymbol, _diamondsymbol, _diamondsymbol]) changetriangletwice = attr.changelist([_trianglesymbol, _trianglesymbol, _circlesymbol, _circlesymbol, _diamondsymbol, _diamondsymbol, _squaresymbol, _squaresymbol]) changecircletwice = attr.changelist([_circlesymbol, _circlesymbol, _diamondsymbol, _diamondsymbol, _squaresymbol, _squaresymbol, _trianglesymbol, _trianglesymbol]) changediamondtwice = attr.changelist([_diamondsymbol, _diamondsymbol, _squaresymbol, _squaresymbol, _trianglesymbol, _trianglesymbol, _circlesymbol, _circlesymbol]) changestrokedfilled = attr.changelist([deco.stroked, deco.filled]) changefilledstroked = attr.changelist([deco.filled, deco.stroked]) defaultsymbolattrs = [deco.stroked] def __init__(self, symbol=changecross, size=0.2*unit.v_cm, symbolattrs=[]): self.symbol = symbol self.size = size self.symbolattrs = symbolattrs def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.symbol = attr.selectattr(self.symbol, selectindex, selecttotal) privatedata.size_pt = unit.topt(attr.selectattr(self.size, selectindex, selecttotal)) if self.symbolattrs is not None: privatedata.symbolattrs = attr.selectattrs(self.defaultsymbolattrs + self.symbolattrs, selectindex, selecttotal) else: privatedata.symbolattrs = None def initdrawpoints(self, privatedata, sharedata, graph): privatedata.symbolcanvas = canvas.canvas() def drawpoint(self, privatedata, sharedata, graph, point): if sharedata.vposvalid and privatedata.symbolattrs is not None: x_pt, y_pt = graph.vpos_pt(*sharedata.vpos) privatedata.symbol(privatedata.symbolcanvas, x_pt, y_pt, privatedata.size_pt, privatedata.symbolattrs) def donedrawpoints(self, privatedata, sharedata, graph): graph.layer("data").insert(privatedata.symbolcanvas) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): if privatedata.symbolattrs is not None: privatedata.symbol(graph, x_pt+0.5*width_pt, y_pt+0.5*height_pt, privatedata.size_pt, privatedata.symbolattrs) class _line(_styleneedingpointpos): # this style is not a complete style, but it provides the basic functionality to # create a line, which is cut at the graph boundaries (or at otherwise invalid points) def __init__(self, epsilon=1e-10): self.epsilon = epsilon def initpointstopath(self, privatedata): privatedata.path = path.path() privatedata.linebasepoints = [] privatedata.lastvpos = None def addpointstopath(self, privatedata): # add baselinepoints to privatedata.path if len(privatedata.linebasepoints) > 1: privatedata.path.append(path.moveto_pt(*privatedata.linebasepoints[0])) if len(privatedata.linebasepoints) > 2: privatedata.path.append(path.multilineto_pt(privatedata.linebasepoints[1:])) else: privatedata.path.append(path.lineto_pt(*privatedata.linebasepoints[1])) privatedata.linebasepoints = [] def addpoint(self, privatedata, graphvpos_pt, vposavailable, vposvalid, vpos): # append linebasepoints if vposavailable: if len(privatedata.linebasepoints): # the last point was inside the graph if vposvalid: # shortcut for the common case privatedata.linebasepoints.append(graphvpos_pt(*vpos)) else: # cut end cut = 1 for vstart, vend in zip(privatedata.lastvpos, vpos): if abs(vend - vstart) > self.epsilon: newcut = None if vend > 1: # 1 = vstart + (vend - vstart) * cut newcut = (1 - vstart)/(vend - vstart) if vend < 0: # 0 = vstart + (vend - vstart) * cut newcut = - vstart/(vend - vstart) if newcut is not None and newcut < cut: cut = newcut cutvpos = [] for vstart, vend in zip(privatedata.lastvpos, vpos): cutvpos.append(vstart + (vend - vstart) * cut) privatedata.linebasepoints.append(graphvpos_pt(*cutvpos)) self.addpointstopath(privatedata) else: # the last point was outside the graph if privatedata.lastvpos is not None: if vposvalid: # cut beginning cut = 0 for vstart, vend in zip(privatedata.lastvpos, vpos): if abs(vend - vstart) > self.epsilon: newcut = None if vstart > 1: # 1 = vstart + (vend - vstart) * cut newcut = (1 - vstart)/(vend - vstart) if vstart < 0: # 0 = vstart + (vend - vstart) * cut newcut = - vstart/(vend - vstart) if newcut is not None and newcut > cut: cut = newcut cutvpos = [] for vstart, vend in zip(privatedata.lastvpos, vpos): cutvpos.append(vstart + (vend - vstart) * cut) privatedata.linebasepoints.append(graphvpos_pt(*cutvpos)) privatedata.linebasepoints.append(graphvpos_pt(*vpos)) else: # sometimes cut beginning and end cutfrom = 0 cutto = 1 for vstart, vend in zip(privatedata.lastvpos, vpos): if vstart > 1 and vend > 1: break if vstart < 0 and vend < 0: break if abs(vend - vstart) > self.epsilon: newcutfrom = None if vstart > 1: newcutfrom = (1 - vstart)/(vend - vstart) if vstart < 0: # 0 = vstart + (vend - vstart) * cutfrom newcutfrom = - vstart/(vend - vstart) if newcutfrom is not None and newcutfrom > cutfrom: cutfrom = newcutfrom newcutto = None if vend > 1: # 1 = vstart + (vend - vstart) * cutto newcutto = (1 - vstart)/(vend - vstart) if vend < 0: # 0 = vstart + (vend - vstart) * cutto newcutto = - vstart/(vend - vstart) if newcutto is not None and newcutto < cutto: cutto = newcutto else: if cutfrom < cutto: cutfromvpos = [] cuttovpos = [] for vstart, vend in zip(privatedata.lastvpos, vpos): cutfromvpos.append(vstart + (vend - vstart) * cutfrom) cuttovpos.append(vstart + (vend - vstart) * cutto) privatedata.linebasepoints.append(graphvpos_pt(*cutfromvpos)) privatedata.linebasepoints.append(graphvpos_pt(*cuttovpos)) self.addpointstopath(privatedata) privatedata.lastvpos = vpos[:] else: if len(privatedata.linebasepoints) > 1: self.addpointstopath(privatedata) privatedata.lastvpos = None def addinvalid(self, privatedata): if len(privatedata.linebasepoints) > 1: self.addpointstopath(privatedata) privatedata.lastvpos = None def donepointstopath(self, privatedata): if len(privatedata.linebasepoints) > 1: self.addpointstopath(privatedata) return privatedata.path class line(_line): needsdata = ["vpos", "vposmissing", "vposavailable", "vposvalid"] changelinestyle = attr.changelist([style.linestyle.solid, style.linestyle.dashed, style.linestyle.dotted, style.linestyle.dashdotted]) defaultlineattrs = [changelinestyle] def __init__(self, lineattrs=[], **kwargs): _line.__init__(self, **kwargs) self.lineattrs = lineattrs def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): if self.lineattrs is not None: privatedata.lineattrs = attr.selectattrs(self.defaultlineattrs + self.lineattrs, selectindex, selecttotal) else: privatedata.lineattrs = None def initdrawpoints(self, privatedata, sharedata, graph): self.initpointstopath(privatedata) def drawpoint(self, privatedata, sharedata, graph, point): self.addpoint(privatedata, graph.vpos_pt, sharedata.vposavailable, sharedata.vposvalid, sharedata.vpos) def donedrawpoints(self, privatedata, sharedata, graph): path = self.donepointstopath(privatedata) if privatedata.lineattrs is not None and len(path): graph.layer("data").stroke(path, privatedata.lineattrs) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): if privatedata.lineattrs is not None: graph.stroke(path.line_pt(x_pt, y_pt+0.5*height_pt, x_pt+width_pt, y_pt+0.5*height_pt), privatedata.lineattrs) class impulses(_styleneedingpointpos): needsdata = ["vpos", "vposmissing", "vposavailable", "vposvalid", "poscolumnnames"] defaultlineattrs = [line.changelinestyle] defaultfrompathattrs = [] def __init__(self, lineattrs=[], fromvalue=0, frompathattrs=[], valueaxisindex=1): self.lineattrs = lineattrs self.fromvalue = fromvalue self.frompathattrs = frompathattrs self.valueaxisindex = valueaxisindex def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.insertfrompath = selectindex == 0 if self.lineattrs is not None: privatedata.lineattrs = attr.selectattrs(self.defaultlineattrs + self.lineattrs, selectindex, selecttotal) else: privatedata.lineattrs = None def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): if self.fromvalue is not None: try: i = sharedata.poscolumnnames.index(columnname) except ValueError: pass else: if i == self.valueaxisindex: graph.axes[sharedata.poscolumnnames[i]].adjustaxis([self.fromvalue]) def initdrawpoints(self, privatedata, sharedata, graph): privatedata.impulsescanvas = canvas.canvas() if self.fromvalue is not None: valueaxisname = sharedata.poscolumnnames[self.valueaxisindex] privatedata.vfromvalue = graph.axes[valueaxisname].convert(self.fromvalue) privatedata.vfromvaluecut = 0 if privatedata.vfromvalue < 0: privatedata.vfromvalue = 0 if privatedata.vfromvalue > 1: privatedata.vfromvalue = 1 if self.frompathattrs is not None and privatedata.insertfrompath: graph.layer("data").stroke(graph.axes[valueaxisname].vgridpath(privatedata.vfromvalue), self.defaultfrompathattrs + self.frompathattrs) else: privatedata.vfromvalue = 0 def drawpoint(self, privatedata, sharedata, graph, point): if sharedata.vposvalid and privatedata.lineattrs is not None: vpos = sharedata.vpos[:] vpos[self.valueaxisindex] = privatedata.vfromvalue privatedata.impulsescanvas.stroke(graph.vgeodesic(*(vpos + sharedata.vpos)), privatedata.lineattrs) def donedrawpoints(self, privatedata, sharedata, graph): graph.layer("data").insert(privatedata.impulsescanvas) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): if privatedata.lineattrs is not None: graph.stroke(path.line_pt(x_pt, y_pt+0.5*height_pt, x_pt+width_pt, y_pt+0.5*height_pt), privatedata.lineattrs) class errorbar(_style): needsdata = ["vpos", "vposmissing", "vposavailable", "vposvalid", "vrange", "vrangeminmissing", "vrangemaxmissing"] defaulterrorbarattrs = [] def __init__(self, size=0.1*unit.v_cm, errorbarattrs=[], epsilon=1e-10): self.size = size self.errorbarattrs = errorbarattrs self.epsilon = epsilon def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): for i in sharedata.vposmissing: if i in sharedata.vrangeminmissing and i in sharedata.vrangemaxmissing: raise ValueError("position and range for a graph dimension missing") return [] def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.errorsize_pt = unit.topt(attr.selectattr(self.size, selectindex, selecttotal)) privatedata.errorbarattrs = attr.selectattrs(self.defaulterrorbarattrs + self.errorbarattrs, selectindex, selecttotal) def initdrawpoints(self, privatedata, sharedata, graph): if privatedata.errorbarattrs is not None: privatedata.errorbarcanvas = canvas.canvas(privatedata.errorbarattrs) privatedata.dimensionlist = list(builtinrange(len(sharedata.vpos))) def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.errorbarattrs is not None: for i in privatedata.dimensionlist: for j in privatedata.dimensionlist: if (i != j and (sharedata.vpos[j] is None or sharedata.vpos[j] < -self.epsilon or sharedata.vpos[j] > 1+self.epsilon)): break else: if ((sharedata.vrange[i][0] is None and sharedata.vpos[i] is None) or (sharedata.vrange[i][1] is None and sharedata.vpos[i] is None) or (sharedata.vrange[i][0] is None and sharedata.vrange[i][1] is None)): continue vminpos = sharedata.vpos[:] if sharedata.vrange[i][0] is not None: vminpos[i] = sharedata.vrange[i][0] mincap = 1 else: mincap = 0 if vminpos[i] > 1+self.epsilon: continue if vminpos[i] < -self.epsilon: vminpos[i] = 0 mincap = 0 vmaxpos = sharedata.vpos[:] if sharedata.vrange[i][1] is not None: vmaxpos[i] = sharedata.vrange[i][1] maxcap = 1 else: maxcap = 0 if vmaxpos[i] < -self.epsilon: continue if vmaxpos[i] > 1+self.epsilon: vmaxpos[i] = 1 maxcap = 0 privatedata.errorbarcanvas.stroke(graph.vgeodesic(*(vminpos + vmaxpos))) for j in privatedata.dimensionlist: if i != j: if mincap: privatedata.errorbarcanvas.stroke(graph.vcap_pt(j, privatedata.errorsize_pt, *vminpos)) if maxcap: privatedata.errorbarcanvas.stroke(graph.vcap_pt(j, privatedata.errorsize_pt, *vmaxpos)) def donedrawpoints(self, privatedata, sharedata, graph): if privatedata.errorbarattrs is not None: graph.layer("data").insert(privatedata.errorbarcanvas) class text(_styleneedingpointpos): needsdata = ["vpos", "vposmissing", "vposvalid"] defaulttextattrs = [textmodule.halign.center, textmodule.vshift.mathaxis] def __init__(self, textname="text", dxname=None, dyname=None, dxunit=0.3*unit.v_cm, dyunit=0.3*unit.v_cm, textdx=0*unit.v_cm, textdy=0.3*unit.v_cm, textattrs=[]): self.textname = textname self.dxname = dxname self.dyname = dyname self.dxunit = dxunit self.dyunit = dyunit self.textdx = textdx self.textdy = textdy self.textattrs = textattrs def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if self.textname not in columnnames: raise ValueError("column '%s' missing" % self.textname) names = [self.textname] if self.dxname is not None: if self.dxname not in columnnames: raise ValueError("column '%s' missing" % self.dxname) names.append(self.dxname) if self.dyname is not None: if self.dyname not in columnnames: raise ValueError("column '%s' missing" % self.dyname) names.append(self.dyname) return names + _styleneedingpointpos.columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames) def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): if self.textattrs is not None: privatedata.textattrs = attr.selectattrs(self.defaulttextattrs + self.textattrs, selectindex, selecttotal) else: privatedata.textattrs = None def initdrawpoints(self, privatedata, sharedata, grap): if self.dxname is None: privatedata.textdx_pt = unit.topt(self.textdx) else: privatedata.dxunit_pt = unit.topt(self.dxunit) if self.dyname is None: privatedata.textdy_pt = unit.topt(self.textdy) else: privatedata.dyunit_pt = unit.topt(self.dyunit) def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.textattrs is not None and sharedata.vposvalid: x_pt, y_pt = graph.vpos_pt(*sharedata.vpos) try: text = str(point[self.textname]) except: pass else: if self.dxname is None: dx_pt = privatedata.textdx_pt else: dx_pt = float(point[self.dxname]) * privatedata.dxunit_pt if self.dyname is None: dy_pt = privatedata.textdy_pt else: dy_pt = float(point[self.dyname]) * privatedata.dyunit_pt graph.layer("data").text_pt(x_pt + dx_pt, y_pt + dy_pt, text, privatedata.textattrs) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): raise RuntimeError("Style currently doesn't provide a graph key") class arrow(_styleneedingpointpos): needsdata = ["vpos", "vposmissing", "vposvalid"] defaultlineattrs = [] defaultarrowattrs = [] def __init__(self, linelength=0.25*unit.v_cm, arrowsize=0.15*unit.v_cm, lineattrs=[], arrowattrs=[], arrowpos=0.5, epsilon=1e-5, decorator=deco.earrow): self.linelength = linelength self.arrowsize = arrowsize self.lineattrs = lineattrs self.arrowattrs = arrowattrs self.arrowpos = arrowpos self.epsilon = epsilon self.decorator = decorator def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if len(graph.axesnames) != 2: raise ValueError("arrow style restricted on two-dimensional graphs") if "size" not in columnnames: raise ValueError("size missing") if "angle" not in columnnames: raise ValueError("angle missing") return ["size", "angle"] + _styleneedingpointpos.columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames) def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): if self.lineattrs is not None: privatedata.lineattrs = attr.selectattrs(self.defaultlineattrs + self.lineattrs, selectindex, selecttotal) else: privatedata.lineattrs = None if self.arrowattrs is not None: privatedata.arrowattrs = attr.selectattrs(self.defaultarrowattrs + self.arrowattrs, selectindex, selecttotal) else: privatedata.arrowattrs = None def initdrawpoints(self, privatedata, sharedata, graph): privatedata.arrowcanvas = canvas.canvas() def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.lineattrs is not None and privatedata.arrowattrs is not None and sharedata.vposvalid: linelength_pt = unit.topt(self.linelength) x_pt, y_pt = graph.vpos_pt(*sharedata.vpos) try: angle = point["angle"] + 0.0 size = point["size"] + 0.0 except: pass else: if point["size"] > self.epsilon: dx = math.cos(angle*math.pi/180) dy = math.sin(angle*math.pi/180) x1 = x_pt-self.arrowpos*dx*linelength_pt*size y1 = y_pt-self.arrowpos*dy*linelength_pt*size x2 = x_pt+(1-self.arrowpos)*dx*linelength_pt*size y2 = y_pt+(1-self.arrowpos)*dy*linelength_pt*size if self.decorator: privatedata.arrowcanvas.stroke(path.line_pt(x1, y1, x2, y2), privatedata.lineattrs+[self.decorator(privatedata.arrowattrs, size=self.arrowsize*size)]) else: privatedata.arrowcanvas.stroke(path.line_pt(x1, y1, x2, y2), privatedata.lineattrs) def donedrawpoints(self, privatedata, sharedata, graph): graph.layer("data").insert(privatedata.arrowcanvas) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): raise RuntimeError("Style currently doesn't provide a graph key") class rect(_keygraphstyle): needsdata = ["vrange", "vrangeminmissing", "vrangemaxmissing"] def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if len(graph.axesnames) != 2: raise TypeError("rect style restricted on two-dimensional graphs") if len(sharedata.vrangeminmissing) + len(sharedata.vrangemaxmissing): raise ValueError("incomplete range") return _keygraphstyle.columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames) def initdrawpoints(self, privatedata, sharedata, graph): privatedata.rectcanvas = graph.layer("filldata").insert(canvas.canvas()) def drawpoint(self, privatedata, sharedata, graph, point): xvmin = sharedata.vrange[0][0] xvmax = sharedata.vrange[0][1] yvmin = sharedata.vrange[1][0] yvmax = sharedata.vrange[1][1] if (xvmin is not None and xvmin < 1 and xvmax is not None and xvmax > 0 and yvmin is not None and yvmin < 1 and yvmax is not None and yvmax > 0): if xvmin < 0: xvmin = 0 elif xvmax > 1: xvmax = 1 if yvmin < 0: yvmin = 0 elif yvmax > 1: yvmax = 1 p = graph.vgeodesic(xvmin, yvmin, xvmax, yvmin) p.append(graph.vgeodesic_el(xvmax, yvmin, xvmax, yvmax)) p.append(graph.vgeodesic_el(xvmax, yvmax, xvmin, yvmax)) p.append(graph.vgeodesic_el(xvmin, yvmax, xvmin, yvmin)) p.append(path.closepath()) privatedata.rectcanvas.fill(p, [self.color(privatedata, point["color"])]) class histogram(_style): needsdata = ["vpos", "vposmissing", "vrange", "vrangeminmissing", "vrangemaxmissing"] defaultlineattrs = [deco.stroked] defaultfrompathattrs = [] def __init__(self, lineattrs=[], steps=0, fromvalue=0, frompathattrs=[], fillable=0, rectkey=0, autohistogramaxisindex=0, autohistogrampointpos=0.5, epsilon=1e-10): self.lineattrs = lineattrs self.steps = steps self.fromvalue = fromvalue self.frompathattrs = frompathattrs self.fillable = fillable # TODO: fillable paths might not properly be closed by straight lines on curved graph geometries self.rectkey = rectkey self.autohistogramaxisindex = autohistogramaxisindex self.autohistogrampointpos = autohistogrampointpos self.epsilon = epsilon def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if len(graph.axesnames) != 2: raise TypeError("histogram style restricted on two-dimensional graphs") privatedata.rangeaxisindex = None for i in builtinrange(len(graph.axesnames)): if i in sharedata.vrangeminmissing or i in sharedata.vrangemaxmissing: if i in sharedata.vposmissing: raise ValueError("pos and range missing") else: if privatedata.rangeaxisindex is not None: raise ValueError("multiple ranges") privatedata.rangeaxisindex = i if privatedata.rangeaxisindex is None: privatedata.rangeaxisindex = self.autohistogramaxisindex privatedata.autohistogram = 1 else: privatedata.autohistogram = 0 return [] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): if privatedata.autohistogram and columnname == sharedata.poscolumnnames[privatedata.rangeaxisindex]: if len(data) == 1: raise ValueError("several data points needed for automatic histogram width calculation") if len(data) > 1: delta = data[1] - data[0] min = data[0] - self.autohistogrampointpos * delta max = data[-1] + (1-self.autohistogrampointpos) * delta graph.axes[columnname].adjustaxis([min, max]) elif self.fromvalue is not None and columnname == sharedata.poscolumnnames[1-privatedata.rangeaxisindex]: graph.axes[columnname].adjustaxis([self.fromvalue]) def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.insertfrompath = selectindex == 0 if self.lineattrs is not None: privatedata.lineattrs = attr.selectattrs(self.defaultlineattrs + self.lineattrs, selectindex, selecttotal) else: privatedata.lineattrs = None def vmoveto(self, privatedata, sharedata, graph, vpos, vvalue): if -self.epsilon < vpos < 1+self.epsilon and -self.epsilon < vvalue < 1+self.epsilon: if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vvalue, vpos))) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vpos, vvalue))) def vposline(self, privatedata, sharedata, graph, vpos, vvalue1, vvalue2): if -self.epsilon < vpos < 1+self.epsilon: vvalue1cut = 0 if vvalue1 < 0: vvalue1 = 0 vvalue1cut = -1 elif vvalue1 > 1: vvalue1 = 1 vvalue1cut = 1 vvalue2cut = 0 if vvalue2 < 0: vvalue2 = 0 vvalue2cut = -1 elif vvalue2 > 1: vvalue2 = 1 vvalue2cut = 1 if abs(vvalue1cut + vvalue2cut) <= 1: if vvalue1cut and not self.fillable: if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vvalue1, vpos))) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vpos, vvalue1))) if privatedata.rangeaxisindex: privatedata.path.append(graph.vgeodesic_el(vvalue1, vpos, vvalue2, vpos)) else: privatedata.path.append(graph.vgeodesic_el(vpos, vvalue1, vpos, vvalue2)) def vvalueline(self, privatedata, sharedata, graph, vvalue, vpos1, vpos2): if self.fillable: if vvalue < -self.epsilon: vvalue = 0 logger.warning("cut at graph boundary adds artificial lines to fillable step histogram path") if vvalue > 1+self.epsilon: vvalue = 1 logger.warning("cut at graph boundary adds artificial lines to fillable step histogram path") if self.fillable or (-self.epsilon < vvalue < 1+self.epsilon): vpos1cut = 0 if vpos1 < 0: vpos1 = 0 vpos1cut = -1 elif vpos1 > 1: vpos1 = 1 vpos1cut = 1 vpos2cut = 0 if vpos2 < 0: vpos2 = 0 vpos2cut = -1 elif vpos2 > 1: vpos2 = 1 vpos2cut = 1 if abs(vpos1cut + vpos2cut) <= 1: if vpos1cut: if self.fillable: if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(privatedata.vfromvalue, vpos1))) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vpos1, vvalue, vpos1)) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vpos1, privatedata.vfromvalue))) privatedata.path.append(graph.vgeodesic_el(vpos1, privatedata.vfromvalue, vpos1, vvalue)) else: if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vvalue, vpos1))) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vpos1, vvalue))) if privatedata.rangeaxisindex: privatedata.path.append(graph.vgeodesic_el(vvalue, vpos1, vvalue, vpos2)) else: privatedata.path.append(graph.vgeodesic_el(vpos1, vvalue, vpos2, vvalue)) if self.fillable and vpos2cut: logger.warning("cut at graph boundary adds artificial lines to fillable step histogram path") if privatedata.rangeaxisindex: privatedata.path.append(graph.vgeodesic_el(vvalue, vpos2, privatedata.vfromvalue, vpos2)) else: privatedata.path.append(graph.vgeodesic_el(vpos2, vvalue, vpos2, privatedata.vfromvalue)) def drawvalue(self, privatedata, sharedata, graph, vmin, vmax, vvalue): currentvalid = vmin is not None and vmax is not None and vvalue is not None if self.fillable and not self.steps: if not currentvalid: return vmincut = 0 if vmin < -self.epsilon: vmin = 0 vmincut = -1 elif vmin > 1+self.epsilon: vmin = 1 vmincut = 1 vmaxcut = 0 if vmax < -self.epsilon: vmax = 0 vmaxcut = -1 if vmax > 1+self.epsilon: vmax = 1 vmaxcut = 1 vvaluecut = 0 if vvalue < -self.epsilon: vvalue = 0 vvaluecut = -1 if vvalue > 1+self.epsilon: vvalue = 1 vvaluecut = 1 done = 0 if abs(vmincut) + abs(vmaxcut) + abs(vvaluecut) + abs(privatedata.vfromvaluecut) > 1: if abs(vmincut + vmaxcut) > 1 or abs(vvaluecut+privatedata.vfromvaluecut) > 1: done = 1 else: logger.warning("multiple cuts at graph boundary add artificial lines to fillable rectangle histogram path") elif vmincut: done = 1 if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(privatedata.vfromvalue, vmin))) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmin, privatedata.vfromvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmax, vvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmax, vvalue, vmin)) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vmin, privatedata.vfromvalue))) privatedata.path.append(graph.vgeodesic_el(vmin, privatedata.vfromvalue, vmax, privatedata.vfromvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, privatedata.vfromvalue, vmax, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, vvalue, vmin, vvalue)) elif vmaxcut: done = 1 if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vvalue, vmax))) privatedata.path.append(graph.vgeodesic_el(vvalue, vmax, vvalue, vmin)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmin, privatedata.vfromvalue, vmin)) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmin, privatedata.vfromvalue, vmax)) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vmax, vvalue))) privatedata.path.append(graph.vgeodesic_el(vmax, vvalue, vmin, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmin, vvalue, vmin, privatedata.vfromvalue)) privatedata.path.append(graph.vgeodesic_el(vmin, privatedata.vfromvalue, vmax, privatedata.vfromvalue)) elif privatedata.vfromvaluecut: done = 1 if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(privatedata.vfromvalue, vmax))) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmax, vvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmax, vvalue, vmin)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmin, privatedata.vfromvalue, vmin)) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vmax, privatedata.vfromvalue))) privatedata.path.append(graph.vgeodesic_el(vmax, privatedata.vfromvalue, vmax, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, vvalue, vmin, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmin, vvalue, vmin, privatedata.vfromvalue)) elif vvaluecut: done = 1 if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vvalue, vmin))) privatedata.path.append(graph.vgeodesic_el(vvalue, vmin, privatedata.vfromvalue, vmin)) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmin, privatedata.vfromvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmax, vvalue, vmax)) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vmin, vvalue))) privatedata.path.append(graph.vgeodesic_el(vmin, vvalue, vmin, privatedata.vfromvalue)) privatedata.path.append(graph.vgeodesic_el(vmin, privatedata.vfromvalue, vmax, privatedata.vfromvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, privatedata.vfromvalue, vmax, vvalue)) if not done: if privatedata.rangeaxisindex: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(privatedata.vfromvalue, vmin))) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmin, privatedata.vfromvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(privatedata.vfromvalue, vmax, vvalue, vmax)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmax, vvalue, vmin)) privatedata.path.append(graph.vgeodesic_el(vvalue, vmin, privatedata.vfromvalue, vmin)) privatedata.path.append(path.closepath()) else: privatedata.path.append(path.moveto_pt(*graph.vpos_pt(vmin, privatedata.vfromvalue))) privatedata.path.append(graph.vgeodesic_el(vmin, privatedata.vfromvalue, vmax, privatedata.vfromvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, privatedata.vfromvalue, vmax, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmax, vvalue, vmin, vvalue)) privatedata.path.append(graph.vgeodesic_el(vmin, vvalue, vmin, privatedata.vfromvalue)) privatedata.path.append(path.closepath()) else: try: gap = abs(vmin - privatedata.lastvmax) > self.epsilon except (ArithmeticError, ValueError, TypeError): gap = 1 if (privatedata.lastvvalue is not None and currentvalid and not gap and (self.steps or (privatedata.lastvvalue-privatedata.vfromvalue)*(vvalue-privatedata.vfromvalue) < 0)): self.vposline(privatedata, sharedata, graph, vmin, privatedata.lastvvalue, vvalue) else: if privatedata.lastvvalue is not None and currentvalid: currentbigger = abs(privatedata.lastvvalue-privatedata.vfromvalue) < abs(vvalue-privatedata.vfromvalue) if privatedata.lastvvalue is not None and (not currentvalid or not currentbigger or gap): self.vposline(privatedata, sharedata, graph, privatedata.lastvmax, privatedata.lastvvalue, privatedata.vfromvalue) if currentvalid: self.vmoveto(privatedata, sharedata, graph, vmin, vvalue) if currentvalid and (privatedata.lastvvalue is None or currentbigger or gap): self.vmoveto(privatedata, sharedata, graph, vmin, privatedata.vfromvalue) self.vposline(privatedata, sharedata, graph, vmin, privatedata.vfromvalue, vvalue) if currentvalid: self.vvalueline(privatedata, sharedata, graph, vvalue, vmin, vmax) privatedata.lastvvalue = vvalue privatedata.lastvmax = vmax else: privatedata.lastvvalue = privatedata.lastvmax = None def initdrawpoints(self, privatedata, sharedata, graph): privatedata.path = path.path() privatedata.lastvvalue = privatedata.lastvmax = None privatedata.vcurrentpoint = None privatedata.count = 0 if self.fromvalue is not None: valueaxisname = sharedata.poscolumnnames[1-privatedata.rangeaxisindex] privatedata.vfromvalue = graph.axes[valueaxisname].convert(self.fromvalue) privatedata.vfromvaluecut = 0 if privatedata.vfromvalue < 0: privatedata.vfromvalue = 0 privatedata.vfromvaluecut = -1 if privatedata.vfromvalue > 1: privatedata.vfromvalue = 1 privatedata.vfromvaluecut = 1 if self.frompathattrs is not None and privatedata.insertfrompath: graph.layer("data").stroke(graph.axes[valueaxisname].vgridpath(privatedata.vfromvalue), self.defaultfrompathattrs + self.frompathattrs) else: privatedata.vfromvalue = 0 def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.autohistogram: # automatic range handling privatedata.count += 1 if privatedata.count == 2: if privatedata.rangeaxisindex: privatedata.vrange = sharedata.vpos[1] - privatedata.lastvpos[1] self.drawvalue(privatedata, sharedata, graph, privatedata.lastvpos[1] - self.autohistogrampointpos*privatedata.vrange, privatedata.lastvpos[1] + (1-self.autohistogrampointpos)*privatedata.vrange, privatedata.lastvpos[0]) else: privatedata.vrange = sharedata.vpos[0] - privatedata.lastvpos[0] self.drawvalue(privatedata, sharedata, graph, privatedata.lastvpos[0] - self.autohistogrampointpos*privatedata.vrange, privatedata.lastvpos[0] + (1-self.autohistogrampointpos)*privatedata.vrange, privatedata.lastvpos[1]) elif privatedata.count > 2: if privatedata.rangeaxisindex: vrange = sharedata.vpos[1] - privatedata.lastvpos[1] else: vrange = sharedata.vpos[0] - privatedata.lastvpos[0] if abs(privatedata.vrange - vrange) > self.epsilon: raise ValueError("equal steps (in graph coordinates) needed for automatic width calculation") if privatedata.count > 1: if privatedata.rangeaxisindex: self.drawvalue(privatedata, sharedata, graph, sharedata.vpos[1] - self.autohistogrampointpos*privatedata.vrange, sharedata.vpos[1] + (1-self.autohistogrampointpos)*privatedata.vrange, sharedata.vpos[0]) else: self.drawvalue(privatedata, sharedata, graph, sharedata.vpos[0] - self.autohistogrampointpos*privatedata.vrange, sharedata.vpos[0] + (1-self.autohistogrampointpos)*privatedata.vrange, sharedata.vpos[1]) privatedata.lastvpos = sharedata.vpos[:] else: if privatedata.rangeaxisindex: self.drawvalue(privatedata, sharedata, graph, sharedata.vrange[1][0], sharedata.vrange[1][1], sharedata.vpos[0]) else: self.drawvalue(privatedata, sharedata, graph, sharedata.vrange[0][0], sharedata.vrange[0][1], sharedata.vpos[1]) def donedrawpoints(self, privatedata, sharedata, graph): self.drawvalue(privatedata, sharedata, graph, None, None, None) if privatedata.lineattrs is not None and len(privatedata.path): graph.layer("data").draw(privatedata.path, privatedata.lineattrs) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): if privatedata.lineattrs is not None: if self.rectkey: p = path.rect_pt(x_pt, y_pt, width_pt, height_pt) else: p = path.line_pt(x_pt, y_pt+0.5*height_pt, x_pt+width_pt, y_pt+0.5*height_pt) graph.draw(p, privatedata.lineattrs) class barpos(_style): providesdata = ["vpos", "vposmissing", "vposavailable", "vposvalid", "vbarrange", "barposcolumnnames", "barvalueindex", "lastbarvalue", "stackedbar", "stackedbardraw"] defaultfrompathattrs = [] def __init__(self, fromvalue=None, frompathattrs=[], epsilon=1e-10): self.fromvalue = fromvalue self.frompathattrs = frompathattrs self.epsilon = epsilon def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): sharedata.barposcolumnnames = [] sharedata.barvalueindex = None for dimension, axisnames in enumerate(graph.axesnames): found = 0 for axisname in axisnames: if axisname in columnnames: if sharedata.barvalueindex is not None: raise ValueError("multiple values") sharedata.barvalueindex = dimension sharedata.barposcolumnnames.append(axisname) found += 1 if (axisname + "name") in columnnames: sharedata.barposcolumnnames.append(axisname + "name") found += 1 if found > 1: raise ValueError("multiple names and value") if not found: raise ValueError("value/name missing") if sharedata.barvalueindex is None: raise ValueError("missing value") sharedata.vposmissing = [] return sharedata.barposcolumnnames def addsubvalue(self, value, subvalue): try: value + "" except: try: return value[0], self.addsubvalue(value[1], subvalue) except: return value, subvalue else: return value, subvalue def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): try: i = sharedata.barposcolumnnames.index(columnname) except ValueError: pass else: if i == sharedata.barvalueindex: if self.fromvalue is not None: graph.axes[sharedata.barposcolumnnames[i]].adjustaxis([self.fromvalue]) graph.axes[sharedata.barposcolumnnames[i]].adjustaxis(data) else: graph.axes[sharedata.barposcolumnnames[i][:-4]].adjustaxis([self.addsubvalue(x, 0) for x in data]) graph.axes[sharedata.barposcolumnnames[i][:-4]].adjustaxis([self.addsubvalue(x, 1) for x in data]) def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.insertfrompath = selectindex == 0 def initdrawpoints(self, privatedata, sharedata, graph): sharedata.vpos = [None]*(len(sharedata.barposcolumnnames)) sharedata.vbarrange = [[None for i in builtinrange(2)] for x in sharedata.barposcolumnnames] sharedata.stackedbar = sharedata.stackedbardraw = 0 if self.fromvalue is not None: privatedata.vfromvalue = graph.axes[sharedata.barposcolumnnames[sharedata.barvalueindex]].convert(self.fromvalue) if privatedata.vfromvalue < 0: privatedata.vfromvalue = 0 if privatedata.vfromvalue > 1: privatedata.vfromvalue = 1 if self.frompathattrs is not None and privatedata.insertfrompath: graph.layer("data").stroke(graph.axes[sharedata.barposcolumnnames[sharedata.barvalueindex]].vgridpath(privatedata.vfromvalue), self.defaultfrompathattrs + self.frompathattrs) else: privatedata.vfromvalue = 0 def drawpoint(self, privatedata, sharedata, graph, point): sharedata.vposavailable = sharedata.vposvalid = 1 for i, barname in enumerate(sharedata.barposcolumnnames): if i == sharedata.barvalueindex: sharedata.vbarrange[i][0] = privatedata.vfromvalue sharedata.lastbarvalue = point[barname] try: sharedata.vpos[i] = sharedata.vbarrange[i][1] = graph.axes[barname].convert(sharedata.lastbarvalue) except (ArithmeticError, ValueError, TypeError): sharedata.vpos[i] = sharedata.vbarrange[i][1] = None else: for j in builtinrange(2): try: sharedata.vbarrange[i][j] = graph.axes[barname[:-4]].convert(self.addsubvalue(point[barname], j)) except (ArithmeticError, ValueError, TypeError): sharedata.vbarrange[i][j] = None try: sharedata.vpos[i] = 0.5*(sharedata.vbarrange[i][0]+sharedata.vbarrange[i][1]) except (ArithmeticError, ValueError, TypeError): sharedata.vpos[i] = None if sharedata.vpos[i] is None: sharedata.vposavailable = sharedata.vposvalid = 0 elif sharedata.vpos[i] < -self.epsilon or sharedata.vpos[i] > 1+self.epsilon: sharedata.vposvalid = 0 registerdefaultprovider(barpos(), ["vbarrange", "barposcolumnnames", "barvalueindex", "lastbarvalue", "stackedbar", "stackedbardraw"]) class stackedbarpos(_style): # provides no additional data, but needs some data (and modifies some of them) needsdata = ["vbarrange", "barposcolumnnames", "barvalueindex", "lastbarvalue", "stackedbar", "stackedbardraw"] def __init__(self, stackname, addontop=0, epsilon=1e-10): self.stackname = stackname self.epsilon = epsilon self.addontop = addontop def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): if self.stackname not in columnnames: raise ValueError("column '%s' missing" % self.stackname) return [self.stackname] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): if columnname == self.stackname: graph.axes[sharedata.barposcolumnnames[sharedata.barvalueindex]].adjustaxis(data) def initdrawpoints(self, privatedata, sharedata, graph): if sharedata.stackedbardraw: # do not count the start bar when not gets painted sharedata.stackedbar += 1 def drawpoint(self, privatedata, sharedata, graph, point): sharedata.vbarrange[sharedata.barvalueindex][0] = sharedata.vbarrange[sharedata.barvalueindex][1] if self.addontop: try: sharedata.lastbarvalue += point[self.stackname] except (ArithmeticError, ValueError, TypeError): sharedata.lastbarvalue = None else: sharedata.lastbarvalue = point[self.stackname] try: sharedata.vpos[sharedata.barvalueindex] = sharedata.vbarrange[sharedata.barvalueindex][1] = graph.axes[sharedata.barposcolumnnames[sharedata.barvalueindex]].convert(sharedata.lastbarvalue) except (ArithmeticError, ValueError, TypeError): sharedata.vpos[sharedata.barvalueindex] = sharedata.vbarrange[sharedata.barvalueindex][1] = None sharedata.vposavailable = sharedata.vposvalid = 0 else: if not sharedata.vposavailable or not sharedata.vposvalid: sharedata.vposavailable = sharedata.vposvalid = 1 for v in sharedata.vpos: if v is None: sharedata.vposavailable = sharedata.vposvalid = 0 break if v < -self.epsilon or v > 1+self.epsilon: sharedata.vposvalid = 0 class bar(_style): needsdata = ["vbarrange"] defaultbarattrs = [color.gradient.Rainbow, deco.stroked([color.grey.black])] def __init__(self, barattrs=[], epsilon=1e-10, gradient=color.gradient.RedBlack): self.barattrs = barattrs self.epsilon = epsilon self.gradient = gradient def lighting(self, angle, zindex): return self.gradient.getcolor(0.7-0.4*abs(angle)+0.1*zindex) def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): return [] def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): privatedata.barattrs = attr.selectattrs(self.defaultbarattrs + self.barattrs, selectindex, selecttotal) def initdrawpoints(self, privatedata, sharedata, graph): privatedata.barcanvas = graph.layer("filldata").insert(canvas.canvas()) sharedata.stackedbardraw = 1 privatedata.stackedbar = sharedata.stackedbar privatedata.todraw = [] def drawpointfill(self, privatedata, p): if p: privatedata.barcanvas.fill(p, privatedata.barattrs) def drawpoint(self, privatedata, sharedata, graph, point): vbarrange = [] for vmin, vmax in sharedata.vbarrange: if vmin is None or vmax is None: self.drawpointfill(privatedata, None) return if vmin > vmax: vmin, vmax = vmax, vmin if vmin > 1 or vmax < 0: self.drawpointfill(privatedata, None) return if vmin < 0: vmin = 0 if vmax > 1: vmax = 1 vbarrange.append((vmin, vmax)) if len(vbarrange) == 2: p = graph.vgeodesic(vbarrange[0][0], vbarrange[1][0], vbarrange[0][1], vbarrange[1][0]) p.append(graph.vgeodesic_el(vbarrange[0][1], vbarrange[1][0], vbarrange[0][1], vbarrange[1][1])) p.append(graph.vgeodesic_el(vbarrange[0][1], vbarrange[1][1], vbarrange[0][0], vbarrange[1][1])) p.append(graph.vgeodesic_el(vbarrange[0][0], vbarrange[1][1], vbarrange[0][0], vbarrange[1][0])) p.append(path.closepath()) self.drawpointfill(privatedata, p) elif len(vbarrange) == 3: planes = [] if abs(vbarrange[0][0] - vbarrange[0][1]) > self.epsilon and abs(vbarrange[1][0] - vbarrange[1][1]): planes.append((vbarrange[0][0], vbarrange[1][0], vbarrange[2][0], vbarrange[0][1], vbarrange[1][0], vbarrange[2][0], vbarrange[0][1], vbarrange[1][1], vbarrange[2][0], vbarrange[0][0], vbarrange[1][1], vbarrange[2][0])) planes.append((vbarrange[0][0], vbarrange[1][0], vbarrange[2][1], vbarrange[0][0], vbarrange[1][1], vbarrange[2][1], vbarrange[0][1], vbarrange[1][1], vbarrange[2][1], vbarrange[0][1], vbarrange[1][0], vbarrange[2][1])) if abs(vbarrange[0][0] - vbarrange[0][1]) > self.epsilon and abs(vbarrange[2][0] - vbarrange[2][1]): planes.append((vbarrange[0][0], vbarrange[1][0], vbarrange[2][0], vbarrange[0][0], vbarrange[1][0], vbarrange[2][1], vbarrange[0][1], vbarrange[1][0], vbarrange[2][1], vbarrange[0][1], vbarrange[1][0], vbarrange[2][0])) planes.append((vbarrange[0][0], vbarrange[1][1], vbarrange[2][0], vbarrange[0][1], vbarrange[1][1], vbarrange[2][0], vbarrange[0][1], vbarrange[1][1], vbarrange[2][1], vbarrange[0][0], vbarrange[1][1], vbarrange[2][1])) if abs(vbarrange[1][0] - vbarrange[1][1]) > self.epsilon and abs(vbarrange[2][0] - vbarrange[2][1]): planes.append((vbarrange[0][0], vbarrange[1][0], vbarrange[2][0], vbarrange[0][0], vbarrange[1][1], vbarrange[2][0], vbarrange[0][0], vbarrange[1][1], vbarrange[2][1], vbarrange[0][0], vbarrange[1][0], vbarrange[2][1])) planes.append((vbarrange[0][1], vbarrange[1][0], vbarrange[2][0], vbarrange[0][1], vbarrange[1][0], vbarrange[2][1], vbarrange[0][1], vbarrange[1][1], vbarrange[2][1], vbarrange[0][1], vbarrange[1][1], vbarrange[2][0])) v = [0.5 * (vbarrange[0][0] + vbarrange[0][1]), 0.5 * (vbarrange[1][0] + vbarrange[1][1]), 0.5 * (vbarrange[2][0] + vbarrange[2][1])] v[sharedata.barvalueindex] = 0.5 zindex = graph.vzindex(*v) for v11, v12, v13, v21, v22, v23, v31, v32, v33, v41, v42, v43 in planes: angle = graph.vangle(v11, v12, v13, v21, v22, v23, v41, v42, v43) if angle > 0: p = graph.vgeodesic(v11, v12, v13, v21, v22, v23) p.append(graph.vgeodesic_el(v21, v22, v23, v31, v32, v33)) p.append(graph.vgeodesic_el(v31, v32, v33, v41, v42, v43)) p.append(graph.vgeodesic_el(v41, v42, v43, v11, v12, v13)) p.append(path.closepath()) if self.gradient: privatedata.todraw.append((-zindex, p, privatedata.barattrs + [self.lighting(angle, zindex)])) else: privatedata.todraw.append((-zindex, p, privatedata.barattrs)) else: raise TypeError("bar style restricted to two- and three dimensional graphs") def donedrawpoints(self, privatedata, sharedata, graph): privatedata.todraw.sort(key=lambda x: x[0]) for vzindex, p, a in privatedata.todraw: privatedata.barcanvas.fill(p, a) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): selectindex = privatedata.stackedbar selecttotal = sharedata.stackedbar + 1 graph.fill(path.rect_pt(x_pt + width_pt*selectindex/float(selecttotal), y_pt, width_pt/float(selecttotal), height_pt), privatedata.barattrs) class changebar(bar): def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): if selecttotal != 1: raise RuntimeError("Changebar can't change its appearance. Thus you can't use it to plot several bars side by side on a subaxis.") def initdrawpoints(self, privatedata, sharedata, graph): if len(graph.axesnames) != 2: raise TypeError("changebar style restricted on two-dimensional graphs (at least for the moment)") bar.initdrawpoints(self, privatedata, sharedata, graph) privatedata.bars = [] def drawpointfill(self, privatedata, p): privatedata.bars.append(p) def donedrawpoints(self, privatedata, sharedata, graph): selecttotal = len(privatedata.bars) for selectindex, p in enumerate(privatedata.bars): if p: barattrs = attr.selectattrs(self.defaultbarattrs + self.barattrs, selectindex, selecttotal) privatedata.barcanvas.fill(p, barattrs) def key_pt(self, privatedata, sharedata, graph, x_pt, y_pt, width_pt, height_pt): raise RuntimeError("Style currently doesn't provide a graph key") class gridpos(_style): needsdata = ["vpos", "vposmissing", "vposavailable", "vposvalid"] providesdata = ["values1", "values2", "data12", "data21", "index1", "index2"] def __init__(self, index1=0, index2=1, epsilon=1e-10): self.index1 = index1 self.index2 = index2 self.epsilon = epsilon def initdrawpoints(self, privatedata, sharedata, graph): sharedata.index1 = self.index1 sharedata.index2 = self.index2 sharedata.values1 = {} sharedata.values2 = {} sharedata.data12 = {} sharedata.data21 = {} def drawpoint(self, privatedata, sharedata, graph, point): if sharedata.vposavailable: sharedata.value1 = sharedata.vpos[self.index1] sharedata.value2 = sharedata.vpos[self.index2] if sharedata.value1 not in sharedata.values1: for hasvalue in list(sharedata.values1.keys()): if hasvalue - self.epsilon <= sharedata.value1 <= hasvalue + self.epsilon: sharedata.value1 = hasvalue break else: sharedata.values1[sharedata.value1] = 1 if sharedata.value2 not in sharedata.values2: for hasvalue in list(sharedata.values2.keys()): if hasvalue - self.epsilon <= sharedata.value2 <= hasvalue + self.epsilon: sharedata.value2 = hasvalue break else: sharedata.values2[sharedata.value2] = 1 data = sharedata.vposavailable, sharedata.vposvalid, sharedata.vpos[:] sharedata.data12.setdefault(sharedata.value1, {})[sharedata.value2] = data sharedata.data21.setdefault(sharedata.value2, {})[sharedata.value1] = data registerdefaultprovider(gridpos(), gridpos.providesdata) class grid(_line): needsdata = ["values1", "values2", "data12", "data21"] defaultgridattrs = [line.changelinestyle] def __init__(self, gridlines1=1, gridlines2=1, gridattrs=[], **kwargs): _line.__init__(self, **kwargs) self.gridlines1 = gridlines1 self.gridlines2 = gridlines2 self.gridattrs = gridattrs def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): if self.gridattrs is not None: privatedata.gridattrs = attr.selectattrs(self.defaultgridattrs + self.gridattrs, selectindex, selecttotal) else: privatedata.gridattrs = None def donedrawpoints(self, privatedata, sharedata, graph): values1 = list(sharedata.values1.keys()) values1.sort() values2 = list(sharedata.values2.keys()) values2.sort() if self.gridlines1: for value2 in values2: data1 = sharedata.data21[value2] self.initpointstopath(privatedata) for value1 in values1: try: data = data1[value1] except KeyError: self.addinvalid(privatedata) else: self.addpoint(privatedata, graph.vpos_pt, *data) p = self.donepointstopath(privatedata) if len(p): graph.layer("data").stroke(p, privatedata.gridattrs) if self.gridlines2: for value1 in values1: data2 = sharedata.data12[value1] self.initpointstopath(privatedata) for value2 in values2: try: data = data2[value2] except KeyError: self.addinvalid(privatedata) else: self.addpoint(privatedata, graph.vpos_pt, *data) p = self.donepointstopath(privatedata) if len(p): graph.layer("data").stroke(p, privatedata.gridattrs) class surface(_keygraphstyle): needsdata = ["values1", "values2", "data12", "data21"] def __init__(self, gridlines1=0.05, gridlines2=0.05, gridcolor=None, backcolor=color.gray.black, **kwargs): _keygraphstyle.__init__(self, **kwargs) self.gridlines1 = gridlines1 self.gridlines2 = gridlines2 self.gridcolor = gridcolor self.backcolor = backcolor colorspacestring = self.gradient.getcolor(0).colorspacestring() if self.gridcolor is not None and self.gridcolor.colorspacestring() != colorspacestring: raise RuntimeError("colorspace mismatch (gradient/grid)") if self.backcolor is not None and self.backcolor.colorspacestring() != colorspacestring: raise RuntimeError("colorspace mismatch (gradient/back)") def midvalue(self, v1, v2, v3, v4): return [0.25*sum(values) for values in zip(v1, v2, v3, v4)] def midcolor(self, c1, c2, c3, c4): return 0.25*(c1+c2+c3+c4) def lighting(self, angle, zindex): if angle < 0 and self.backcolor is not None: return self.backcolor return self.gradient.getcolor(0.7-0.4*abs(angle)+0.1*zindex) def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): privatedata.colorize = self.colorname in columnnames if privatedata.colorize: return _keygraphstyle.columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames) return [] def initdrawpoints(self, privatedata, sharedata, graph): privatedata.colors = {} def drawpoint(self, privatedata, sharedata, graph, point): if privatedata.colorize: privatedata.colors.setdefault(sharedata.value1, {})[sharedata.value2] = point[self.colorname] def donedrawpoints(self, privatedata, sharedata, graph): v1 = [0]*len(graph.axesnames) v2 = [0]*len(graph.axesnames) v3 = [0]*len(graph.axesnames) v4 = [0]*len(graph.axesnames) v1[sharedata.index2] = 0.5 v2[sharedata.index1] = 0.5 v3[sharedata.index1] = 0.5 v3[sharedata.index2] = 1 v4[sharedata.index1] = 1 v4[sharedata.index2] = 0.5 sortElements = [-graph.vzindex(*v1), -graph.vzindex(*v2), -graph.vzindex(*v3), -graph.vzindex(*v4)] values1 = list(sharedata.values1.keys()) values1.sort() v1 = [0]*len(graph.axesnames) v2 = [0]*len(graph.axesnames) v1[sharedata.index1] = -1 v2[sharedata.index1] = 1 sign = 1 if graph.vzindex(*v1) < graph.vzindex(*v2): values1.reverse() sign *= -1 sortElements = [sortElements[3], sortElements[1], sortElements[2], sortElements[0]] values2 = list(sharedata.values2.keys()) values2.sort() v1 = [0]*len(graph.axesnames) v2 = [0]*len(graph.axesnames) v1[sharedata.index2] = -1 v2[sharedata.index2] = 1 if graph.vzindex(*v1) < graph.vzindex(*v2): values2.reverse() sign *= -1 sortElements = [sortElements[0], sortElements[2], sortElements[1], sortElements[3]] sortElements = [(zindex, i) for i, zindex in enumerate(sortElements)] sortElements.sort() nodes = [] elements = [] for value1a, value1b in zip(values1[:-1], values1[1:]): for value2a, value2b in zip(values2[:-1], values2[1:]): try: available1, valid1, v1 = sharedata.data12[value1a][value2a] available2, valid2, v2 = sharedata.data12[value1a][value2b] available3, valid3, v3 = sharedata.data12[value1b][value2a] available4, valid4, v4 = sharedata.data12[value1b][value2b] except KeyError: continue if not available1 or not available2 or not available3 or not available4: continue if not valid1 or not valid2 or not valid3 or not valid4: logger.warning("surface elements partially outside of the graph are (currently) skipped completely") continue def shrink(index, v1, v2, by): v1 = v1[:] v2 = v2[:] for i in builtinrange(3): if i != index: v1[i], v2[i] = v1[i] + by*(v2[i]-v1[i]), v2[i] + by*(v1[i]-v2[i]) return v1, v2 v1f, v2f, v3f, v4f = v1, v2, v3, v4 if self.gridcolor is not None and self.gridlines1: v1, v2 = shrink(sharedata.index1, v1, v2, self.gridlines1) v3, v4 = shrink(sharedata.index1, v3, v4, self.gridlines1) if self.gridcolor is not None and self.gridlines2: v1, v3 = shrink(sharedata.index2, v1, v3, self.gridlines2) v2, v4 = shrink(sharedata.index2, v2, v4, self.gridlines2) v5 = self.midvalue(v1, v2, v3, v4) x1_pt, y1_pt = graph.vpos_pt(*v1) x2_pt, y2_pt = graph.vpos_pt(*v2) x3_pt, y3_pt = graph.vpos_pt(*v3) x4_pt, y4_pt = graph.vpos_pt(*v4) x5_pt, y5_pt = graph.vpos_pt(*v5) if privatedata.colorize: c1 = privatedata.colors[value1a][value2a] c2 = privatedata.colors[value1a][value2b] c3 = privatedata.colors[value1b][value2a] c4 = privatedata.colors[value1b][value2b] c5 = self.midcolor(c1, c2, c3, c4) c1a = c1b = self.color(privatedata, c1) c2a = c2c = self.color(privatedata, c2) c3b = c3d = self.color(privatedata, c3) c4c = c4d = self.color(privatedata, c4) c5a = c5b = c5c = c5d = self.color(privatedata, c5) if self.backcolor is not None and sign*graph.vangle(*(v1+v2+v5)) < 0: c1a = c2a = c5a = self.backcolor if self.backcolor is not None and sign*graph.vangle(*(v3+v1+v5)) < 0: c3b = c1b = c5b = self.backcolor if self.backcolor is not None and sign*graph.vangle(*(v2+v4+v5)) < 0: c2c = c4c = c5c = self.backcolor if self.backcolor is not None and sign*graph.vangle(*(v4+v3+v5)) < 0: c4d = c3d = c5d = self.backcolor else: zindex = graph.vzindex(*v5) c1a = c2a = c5a = self.lighting(sign*graph.vangle(*(v1+v2+v5)), zindex) c3b = c1b = c5b = self.lighting(sign*graph.vangle(*(v3+v1+v5)), zindex) c2c = c4c = c5c = self.lighting(sign*graph.vangle(*(v2+v4+v5)), zindex) c4d = c3d = c5d = self.lighting(sign*graph.vangle(*(v4+v3+v5)), zindex) for zindex, i in sortElements: if i == 0: elements.append(mesh.element((mesh.node_pt((x1_pt, y1_pt), c1a), mesh.node_pt((x2_pt, y2_pt), c2a), mesh.node_pt((x5_pt, y5_pt), c5a)))) if self.gridcolor is not None and self.gridlines2: elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v1f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v2), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v1), self.gridcolor)))) elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v1f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v2), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v2f), self.gridcolor)))) elif i == 1: elements.append(mesh.element((mesh.node_pt((x3_pt, y3_pt), c3b), mesh.node_pt((x1_pt, y1_pt), c1b), mesh.node_pt((x5_pt, y5_pt), c5b)))) if self.gridcolor is not None and self.gridlines1: elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v1f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v3), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v1), self.gridcolor)))) elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v1f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v3), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v3f), self.gridcolor)))) elif i == 2: elements.append(mesh.element((mesh.node_pt((x2_pt, y2_pt), c2c), mesh.node_pt((x4_pt, y4_pt), c4c), mesh.node_pt((x5_pt, y5_pt), c5c)))) if self.gridcolor is not None and self.gridlines1: elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v2f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v2), self.gridcolor)))) elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v2f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4f), self.gridcolor)))) elif i == 3: elements.append(mesh.element((mesh.node_pt((x4_pt, y4_pt), c4d), mesh.node_pt((x3_pt, y3_pt), c3d), mesh.node_pt((x5_pt, y5_pt), c5d)))) if self.gridcolor is not None and self.gridlines2: elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v3f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v3), self.gridcolor)))) elements.append(mesh.element((mesh.node_pt(graph.vpos_pt(*v3f), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4), self.gridcolor), mesh.node_pt(graph.vpos_pt(*v4f), self.gridcolor)))) m = mesh.mesh(elements, check=0) graph.layer("filldata").insert(m) if privatedata.colorize: _keygraphstyle.donedrawpoints(self, privatedata, sharedata, graph) class density(_keygraphstyle): needsdata = ["values1", "values2", "data12", "data21"] def __init__(self, epsilon=1e-10, **kwargs): _keygraphstyle.__init__(self, **kwargs) self.epsilon = epsilon def initdrawpoints(self, privatedata, sharedata, graph): privatedata.colors = {} privatedata.vfixed = [None]*len(graph.axesnames) def drawpoint(self, privatedata, sharedata, graph, point): privatedata.colors.setdefault(sharedata.value1, {})[sharedata.value2] = point[self.colorname] if len(privatedata.vfixed) > 2 and sharedata.vposavailable: for i, (v1, v2) in enumerate(list(zip(privatedata.vfixed, sharedata.vpos))): if i != sharedata.index1 and i != sharedata.index2: if v1 is None: privatedata.vfixed[i] = v2 elif abs(v1-v2) > self.epsilon: raise ValueError("data must be in a plane for the density style") def donedrawpoints(self, privatedata, sharedata, graph): privatedata.keygraph.doaxes() values1 = sorted(list(sharedata.values1.keys())) values2 = sorted(list(sharedata.values2.keys())) def equidistant(values): l = len(values) - 1 if l < 1: raise ValueError("several data points required by the density style in each dimension") range = values[-1] - values[0] for i, value in enumerate(values): if abs(value - values[0] - i * range / l) > self.epsilon: raise ValueError("data must be equidistant for the density style") equidistant(values1) equidistant(values2) needalpha = False for value2 in values2: for value1 in values1: try: available, valid, v = sharedata.data12[value1][value2] except KeyError: needalpha = True break if not available: needalpha = True continue else: continue break mode = {"/DeviceGray": "L", "/DeviceRGB": "RGB", "/DeviceCMYK": "CMYK"}[self.gradient.getcolor(0).colorspacestring()] if needalpha: mode = "A" + mode empty = b"\0"*len(mode) data = io.BytesIO() for value2 in values2: for value1 in values1: try: available, valid, v = sharedata.data12[value1][value2] except KeyError: data.write(empty) continue if not available: data.write(empty) continue c = privatedata.colors[value1][value2] c = self.color(privatedata, c) if needalpha: data.write(bytes((255,))) data.write(c.to8bitbytes()) i = bitmap.image(len(values1), len(values2), mode, data.getvalue()) v1enlargement = (values1[-1]-values1[0])*0.5/(len(values1)-1) v2enlargement = (values2[-1]-values2[0])*0.5/(len(values2)-1) privatedata.vfixed[sharedata.index1] = values1[0]-v1enlargement privatedata.vfixed[sharedata.index2] = values2[-1]+v2enlargement x1_pt, y1_pt = graph.vpos_pt(*privatedata.vfixed) privatedata.vfixed[sharedata.index1] = values1[-1]+v1enlargement privatedata.vfixed[sharedata.index2] = values2[-1]+v2enlargement x2_pt, y2_pt = graph.vpos_pt(*privatedata.vfixed) privatedata.vfixed[sharedata.index1] = values1[0]-v1enlargement privatedata.vfixed[sharedata.index2] = values2[0]-v2enlargement x3_pt, y3_pt = graph.vpos_pt(*privatedata.vfixed) t = trafo.trafo_pt(((x2_pt-x1_pt, x3_pt-x1_pt), (y2_pt-y1_pt, y3_pt-y1_pt)), (x1_pt, y1_pt)) privatedata.vfixed[sharedata.index1] = values1[-1]+v1enlargement privatedata.vfixed[sharedata.index2] = values2[0]-v2enlargement vx4, vy4 = t.inverse().apply_pt(*graph.vpos_pt(*privatedata.vfixed)) if abs(vx4 - 1) > self.epsilon or abs(vy4 - 1) > self.epsilon: raise ValueError("invalid graph layout for density style (bitmap positioning by affine transformation failed)") p = path.path() privatedata.vfixed[sharedata.index1] = 0 privatedata.vfixed[sharedata.index2] = 0 p.append(path.moveto_pt(*graph.vpos_pt(*privatedata.vfixed))) vfixed2 = privatedata.vfixed + privatedata.vfixed vfixed2[sharedata.index1] = 0 vfixed2[sharedata.index2] = 0 vfixed2[sharedata.index1 + len(graph.axesnames)] = 1 vfixed2[sharedata.index2 + len(graph.axesnames)] = 0 p.append(graph.vgeodesic_el(*vfixed2)) vfixed2[sharedata.index1] = 1 vfixed2[sharedata.index2] = 0 vfixed2[sharedata.index1 + len(graph.axesnames)] = 1 vfixed2[sharedata.index2 + len(graph.axesnames)] = 1 p.append(graph.vgeodesic_el(*vfixed2)) vfixed2[sharedata.index1] = 1 vfixed2[sharedata.index2] = 1 vfixed2[sharedata.index1 + len(graph.axesnames)] = 0 vfixed2[sharedata.index2 + len(graph.axesnames)] = 1 p.append(graph.vgeodesic_el(*vfixed2)) vfixed2[sharedata.index1] = 0 vfixed2[sharedata.index2] = 1 vfixed2[sharedata.index1 + len(graph.axesnames)] = 0 vfixed2[sharedata.index2 + len(graph.axesnames)] = 0 p.append(graph.vgeodesic_el(*vfixed2)) p.append(path.closepath()) c = canvas.canvas([canvas.clip(p)]) b = bitmap.bitmap_trafo(t, i) c.insert(b) graph.layer("filldata").insert(c) _keygraphstyle.donedrawpoints(self, privatedata, sharedata, graph) class gradient(_style): defaultbarattrs = [color.gradient.Rainbow, deco.stroked([color.grey.black])] def __init__(self, gradient=color.gradient.Gray, resolution=100, columnname="x"): self.gradient = gradient self.resolution = resolution self.columnname = columnname def columnnames(self, privatedata, sharedata, graph, columnnames, dataaxisnames): return [self.columnname] def adjustaxis(self, privatedata, sharedata, graph, plotitem, columnname, data): graph.axes[self.columnname].adjustaxis(data) def selectstyle(self, privatedata, sharedata, graph, selectindex, selecttotal): pass def initdrawpoints(self, privatedata, sharedata, graph): pass def drawpoint(self, privatedata, sharedata, graph, point): pass def donedrawpoints(self, privatedata, sharedata, graph): mode = {"/DeviceGray": "L", "/DeviceRGB": "RGB", "/DeviceCMYK": "CMYK"}[self.gradient.getcolor(0).colorspacestring()] data = io.BytesIO() for i in builtinrange(self.resolution): c = self.gradient.getcolor(i*1.0/self.resolution) data.write(c.to8bitbytes()) i = bitmap.image(self.resolution, 1, mode, data.getvalue()) llx_pt, lly_pt = graph.vpos_pt(0) urx_pt, ury_pt = graph.vpos_pt(1) if graph.direction == "horizontal": lly_pt -= 0.5*graph.height_pt ury_pt += 0.5*graph.height_pt else: llx_pt -= 0.5*graph.width_pt urx_pt += 0.5*graph.width_pt c = canvas.canvas([canvas.clip(path.rect_pt(llx_pt, lly_pt, urx_pt-llx_pt, ury_pt-lly_pt))]) if graph.direction == "horizontal": add_pt = (urx_pt-llx_pt)*0.5/(self.resolution-1) llx_pt -= add_pt urx_pt += add_pt else: add_pt = (ury_pt-lly_pt)*0.5/(self.resolution-1) lly_pt -= add_pt ury_pt += add_pt if graph.direction == "horizontal": t = trafo.trafo_pt(((urx_pt-llx_pt,0 ), (0, ury_pt-lly_pt)), (llx_pt, lly_pt)) else: t = trafo.trafo_pt(((0, urx_pt-llx_pt), (ury_pt-lly_pt, 0)), (llx_pt, lly_pt)) b = bitmap.bitmap_trafo(t, i) c.insert(b) graph.layer("filldata").insert(c) PyX-0.14.1/pyx/mathutils.py0000644000076500000240000001233612230165054015740 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2006 Michael Schindler # Copyright (C) 2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math, types # try: # import Numeric, LinearAlgebra # _has_numeric = 1 # except: # _has_numeric = 0 def sign(x): """sign of x, i.e. +1 or -1; returns 1 for x == 0""" if x >= 0: return 1 return -1 def asinh(x): """Return the arc hyperbolic sine of x.""" return math.log(x+math.sqrt(x*x+1)) def acosh(x): """Return the arc hyperbolic cosine of x.""" return math.log(x+math.sqrt(x*x-1)) def _realroots_quadratic(a1, a0): """gives the real roots of x**2 + a1 * x + a0 = 0""" D = a1*a1 - 4*a0 if D < 0: return [] SD = math.sqrt(D) return [0.5 * (-a1 + SD), 0.5 * (-a1 - SD)] def _realroots_cubic(a2, a1, a0): """gives the real roots of x**3 + a2 * x**2 + a1 * x + a0 = 0""" # see http://mathworld.wolfram.com/CubicFormula.html for details Q = (3*a1 - a2*a2) / 9.0 R = (9*a2*a1 - 27*a0 - 2*a2*a2*a2) / 54.0 D = Q*Q*Q + R*R if D > 0: # one real and two complex roots SD = math.sqrt(D) if R + SD >= 0: S = (R + SD)**(1/3.0) else: S = -(-R - SD)**(1/3.0) if R - SD >= 0: T = (R - SD)**(1/3.0) else: T = -(SD - R)**(1/3.0) return [S + T - a2/3.0] elif D == 0: if Q == 0: # one real root (R==0) return [-a2/3.0] else: # two real roots (R>0, Q<0) S = -math.sqrt(-Q) return [2*S - a2/3.0, -S - a2/3.0] else: # three real roots (Q<0) SQ = math.sqrt(-Q) arg = R / (SQ**3) if arg >= 1: theta = 0 elif arg <= -1: theta = math.pi else: theta = math.acos(R/(SQ**3)) return [2 * SQ * math.cos((theta + 2*2*i*math.pi)/3.0) - a2/3.0 for i in range(3)] def _realroots_quartic(a3, a2, a1, a0): """gives the real roots of x**4 + a3 * x**3 + a2 * x**2 + a1 * x + a0 = 0""" # see http://mathworld.wolfram.com/QuarticEquation.html for details ys = _realroots_cubic(-a2, a1*a3 - 4*a0, 4*a0*a2 - a1*a1 - a0*a3*a3) ys = [y for y in ys if a3*a3-4*a2+4*y >= 0 and y*y-4*a0 >= 0] if not ys: return [] y1 = min(ys) if a3*y1-2*a1 < 0: return (_realroots_quadratic(0.5*(a3+math.sqrt(a3*a3-4*a2+4*y1)), 0.5*(y1-math.sqrt(y1*y1-4*a0))) + _realroots_quadratic(0.5*(a3-math.sqrt(a3*a3-4*a2+4*y1)), 0.5*(y1+math.sqrt(y1*y1-4*a0)))) else: return (_realroots_quadratic(0.5*(a3+math.sqrt(a3*a3-4*a2+4*y1)), 0.5*(y1+math.sqrt(y1*y1-4*a0))) + _realroots_quadratic(0.5*(a3-math.sqrt(a3*a3-4*a2+4*y1)), 0.5*(y1-math.sqrt(y1*y1-4*a0)))) def realpolyroots(*cs): """returns the roots of a polynom with given coefficients polynomial with coefficients given in cs: 0 = \sum_i cs[i] * x^(len(cs)-i-1) """ if not cs: return [0] try: f = 1.0/cs[0] cs = [f*c for c in cs[1:]] except ArithmeticError: return realpolyroots(*cs[1:]) else: n = len(cs) if n == 0: return [] elif n == 1: return [-cs[0]] elif n == 2: return _realroots_quadratic(*cs) elif n == 3: return _realroots_cubic(*cs) elif n == 4: return _realroots_quartic(*cs) else: raise RuntimeError("realpolyroots solver currently limited to polynoms up to the power of 4") # def realpolyroots_eigenvalue(*cs): # # as realpolyroots but using an equivalent eigenvalue problem # # (this code is currently used for functional tests only) # if not _has_numeric: # raise RuntimeError("realpolyroots_eigenvalue depends on Numeric") # if not cs: # return [0] # try: # f = 1.0/cs[0] # cs = [f*c for c in cs[1:]] # except ArithmeticError: # return realpolyroots_eigenvalue(*cs[1:]) # else: # if not cs: # return [] # n = len(cs) # a = Numeric.zeros((n, n), Numeric.Float) # for i in range(n-1): # a[i+1][i] = 1 # for i in range(n): # a[0][i] = -cs[i] # rs = [] # for r in LinearAlgebra.eigenvalues(a): # if type(r) == types.ComplexType: # if not r.imag: # rs.append(r.real) # else: # rs.append(r) # return rs # PyX-0.14.1/pyx/mesh.py0000644000076500000240000001760612517447320014676 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2006-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # Just a quick'n'dirty ascii art (I'll do a nice PyX plot later on): # # # node1 * # | \ # | \ neighbor2 # | \ # | \ # neighbor3 |element * node3 # | / # | / # | / neighbor1 # | / # node2 * import struct, binascii, zlib, os, tempfile from . import bbox, baseclasses, color, pdfwriter, unit class node_pt: def __init__(self, coords_pt, value): self.coords_pt = coords_pt self.value = value class node(node_pt): def __init__(self, coords, value): node_pt.__init__(self, [unit.topt(coord) for coord in coords], value) class element: def __init__(self, nodes, neighbors=None): self.nodes = nodes self.neighbors = neighbors def coords24bit_pt(coords_pt, min_pt, max_pt): return struct.pack(">I", int((coords_pt-min_pt)*16777215.0/(max_pt-min_pt)))[1:] class PDFGenericResource(pdfwriter.PDFobject): def __init__(self, type, name, content): pdfwriter.PDFobject.__init__(self, type, name) self.content = content def write(self, file, writer, registry): file.write_bytes(self.content) class mesh(baseclasses.canvasitem): def __init__(self, elements, check=1): self.elements = elements if check: colorspacestring = "" for element in elements: if len(element.nodes) != 3: raise ValueError("triangular mesh expected") try: for node in element.nodes: if not colorspacestring: colorspacestring = node.value.colorspacestring() elif node.value.colorspacestring() != colorspacestring: raise ValueError("color space mismatch") except AttributeError: raise ValueError("gray, rgb or cmyk color values expected") for node in element.nodes: if len(node.coords_pt) != 2: raise ValueError("two dimensional coordinates expected") def bbox(self): return bbox.bbox_pt(min([node.coords_pt[0] for element in self.elements for node in element.nodes]), min([node.coords_pt[1] for element in self.elements for node in element.nodes]), max([node.coords_pt[0] for element in self.elements for node in element.nodes]), max([node.coords_pt[1] for element in self.elements for node in element.nodes])) def data(self, bbox): return b"".join([b"\000" + coords24bit_pt(node.coords_pt[0], bbox.llx_pt, bbox.urx_pt) + coords24bit_pt(node.coords_pt[1], bbox.lly_pt, bbox.ury_pt) + node.value.to8bitbytes() for element in self.elements for node in element.nodes]) def processPS(self, file, writer, context, registry, bbox): if writer.mesh_as_bitmap: from pyx import bitmap, canvas from PIL import Image c = canvas.canvas() c.insert(self) i = Image.open(c.pipeGS("pngalpha", resolution=writer.mesh_as_bitmap_resolution)) i.load() b = bitmap.bitmap_pt(self.bbox().llx_pt, self.bbox().lly_pt, i) # we slightly shift the bitmap to re-center it, as the bitmap might contain some additional border # unfortunately we need to construct another bitmap instance for that ... b = bitmap.bitmap_pt(self.bbox().llx_pt + 0.5*(self.bbox().width_pt()-b.bbox().width_pt()), self.bbox().lly_pt + 0.5*(self.bbox().height_pt()-b.bbox().height_pt()), i) b.processPS(file, writer, context, registry, bbox) else: thisbbox = self.bbox() bbox += thisbbox file.write("""<< /ShadingType 4 /ColorSpace %s /BitsPerCoordinate 24 /BitsPerComponent 8 /BitsPerFlag 8 /Decode [%f %f %f %f %s] /DataSource currentfile /ASCIIHexDecode filter /FlateDecode filter >> shfill\n""" % (self.elements[0].nodes[0].value.colorspacestring(), thisbbox.llx_pt, thisbbox.urx_pt, thisbbox.lly_pt, thisbbox.ury_pt, " ".join(["0 1" for value in self.elements[0].nodes[0].value.to8bitbytes()]))) file.write_bytes(binascii.b2a_hex(zlib.compress(self.data(thisbbox)))) file.write(">\n") def processPDF(self, file, writer, context, registry, bbox): if writer.mesh_as_bitmap: from pyx import bitmap, canvas from PIL import Image c = canvas.canvas() c.insert(self) i = Image.open(c.pipeGS("pngalpha", resolution=writer.mesh_as_bitmap_resolution)) i.load() b = bitmap.bitmap_pt(self.bbox().llx_pt, self.bbox().lly_pt, i) # we slightly shift the bitmap to re-center it, as the bitmap might contain some additional border # unfortunately we need to construct another bitmap instance for that ... b = bitmap.bitmap_pt(self.bbox().llx_pt + 0.5*(self.bbox().width_pt()-b.bbox().width_pt()), self.bbox().lly_pt + 0.5*(self.bbox().height_pt()-b.bbox().height_pt()), i) b.processPDF(file, writer, context, registry, bbox) else: thisbbox = self.bbox() bbox += thisbbox d = self.data(thisbbox) if writer.compress: filter = "/Filter /FlateDecode\n" d = zlib.compress(d) else: filter = "" name = "shading-%s" % id(self) shading = PDFGenericResource("shading", name, ("""<< /ShadingType 4 /ColorSpace %s /BitsPerCoordinate 24 /BitsPerComponent 8 /BitsPerFlag 8 /Decode [%f %f %f %f %s] /Length %i %s>> stream """ % (self.elements[0].nodes[0].value.colorspacestring(), thisbbox.llx_pt, thisbbox.urx_pt, thisbbox.lly_pt, thisbbox.ury_pt, " ".join(["0 1" for value in self.elements[0].nodes[0].value.to8bitbytes()]), len(d), filter)).encode('ascii') + d + b"\nendstream\n") registry.add(shading) registry.addresource("Shading", name, shading) file.write("/%s sh\n" % name) def processSVG(self, xml, writer, context, registry, bbox): from pyx import bitmap, canvas from PIL import Image c = canvas.canvas() c.insert(self) i = Image.open(c.pipeGS("pngalpha", resolution=writer.mesh_as_bitmap_resolution)) i.load() b = bitmap.bitmap_pt(self.bbox().llx_pt, self.bbox().lly_pt, i) # we slightly shift the bitmap to re-center it, as the bitmap might contain some additional border # unfortunately we need to construct another bitmap instance for that ... b = bitmap.bitmap_pt(self.bbox().llx_pt + 0.5*(self.bbox().width_pt()-b.bbox().width_pt()), self.bbox().lly_pt + 0.5*(self.bbox().height_pt()-b.bbox().height_pt()), i) b.processSVG(xml, writer, context, registry, bbox) PyX-0.14.1/pyx/metapost/0000755000076500000240000000000012615763300015210 5ustar andrestaff00000000000000PyX-0.14.1/pyx/metapost/__init__.py0000644000076500000240000000155512177540643017335 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2011 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA __all__ = ["path", "mp_path"] PyX-0.14.1/pyx/metapost/mp_path.py0000644000076500000240000004324312177540643017226 0ustar andrestaff00000000000000# -*- coding: ISO-8859-1 -*- # # Copyright (C) 2011 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from math import atan2, sin, cos, sqrt, pi ################################################################################ # Internal functions of MetaPost # # This file re-implements some of the functionality of MetaPost # (http://tug.org/metapost). MetaPost was developed by John D. Hobby and # others. The code of Metapost is in the public domain, which we understand as # an implicit permission to reuse the code here (see the comment at # http://www.gnu.org/licenses/license-list.html) # # This file is based on the MetaPost version distributed by TeXLive: # svn://tug.org/texlive/trunk/Build/source/texk/web2c/mplibdir revision 22737 # # (2011-05-31) ################################################################################ # from mplib.h: mp_endpoint = 0 mp_explicit = 1 mp_given = 2 mp_curl = 3 mp_open = 4 mp_end_cycle = 5 # from mpmath.c: unity = 1.0 two = 2.0 fraction_half = 0.5 fraction_one = 1.0 fraction_three = 3.0 one_eighty_deg = pi three_sixty_deg = 2*pi def mp_make_choices(knots, epsilon): # <<< """Implements mp_make_choices from metapost (mp.c)""" # 334: If consecutive knots are equal, join them explicitly p = knots while True: q = p.next if p.rtype > mp_explicit and (p.x_pt-q.x_pt)**2 + (p.y_pt-q.y_pt)**2 < epsilon**2: p.rtype = mp_explicit if p.ltype == mp_open: p.ltype = mp_curl p.set_left_curl(unity) q.ltype = mp_explicit if q.rtype == mp_open: q.rtype = mp_curl q.set_right_curl(unity) p.rx_pt = p.x_pt q.lx_pt = p.x_pt p.ry_pt = p.y_pt q.ly_pt = p.y_pt p = q if p is knots: break # 335: # If there are no breakpoints, it is necessary to compute the direction angles around an entire cycle. # In this case the mp left type of the first node is temporarily changed to end cycle. # Find the first breakpoint, h, on the path # insert an artificial breakpoint if the path is an unbroken cycle h = knots while True: if h.ltype != mp_open or h.rtype != mp_open: break h = h.next if h is knots: h.ltype = mp_end_cycle break p = h while True: # 336: # Fill in the control points between p and the next breakpoint, then advance p to that breakpoint q = p.next if p.rtype >= mp_given: while q.ltype == mp_open and q.rtype == mp_open: q = q.next # the breakpoints are now p and q # 346: # Calculate the turning angles psi_k and the distances d(k, k+1) # set n to the length of the path k = 0 s = p n = knots.linked_len() delta_x, delta_y, delta, psi = [], [], [], [None] while True: t = s.next assert len(delta_x) == k delta_x.append(t.x_pt - s.x_pt) delta_y.append(t.y_pt - s.y_pt) delta.append(mp_pyth_add(delta_x[k], delta_y[k])) if k > 0: sine = mp_make_fraction(delta_y[k-1], delta[k-1]) cosine = mp_make_fraction(delta_x[k-1], delta[k-1]) psi.append(mp_n_arg( mp_take_fraction(delta_x[k], cosine) + mp_take_fraction(delta_y[k], sine), mp_take_fraction(delta_y[k], cosine) - mp_take_fraction(delta_x[k], sine))) k += 1 s = t if s == q: n = k if k >= n and s.ltype != mp_end_cycle: break if k == n: psi.append(0) else: # for closed paths: psi.append(psi[1]) # 347: Remove open types at the breakpoints if q.ltype == mp_open: delx_pt = q.rx_pt - q.x_pt dely_pt = q.ry_pt - q.y_pt if delx_pt**2 + dely_pt**2 < epsilon**2: # use curl if the controls are not usable for giving an angle q.ltype = mp_curl q.set_left_curl(unity) else: q.ltype = mp_given q.set_left_given(mp_n_arg(delx_pt, dely_pt)) if p.rtype == mp_open and p.ltype == mp_explicit: delx_pt = p.x_pt - p.lx_pt dely_pt = p.y_pt - p.ly_pt if delx_pt**2 + dely_pt**2 < epsilon**2: p.rtype = mp_curl p.set_right_curl(unity) else: p.rtype = mp_given p.set_right_given(mp_n_arg(delx_pt, dely_pt)) # call the internal solving routine mp_solve_choices(p, q, n, delta_x, delta_y, delta, psi) elif p.rtype == mp_endpoint: # 337: Give reasonable values for the unused control points between p and q p.rx_pt = p.x_pt p.ry_pt = p.y_pt q.lx_pt = q.x_pt q.ly_pt = q.y_pt p = q if p is h: break # >>> def mp_solve_choices(p, q, n, delta_x, delta_y, delta, psi): # <<< """Implements mp_solve_choices form metapost (mp.c)""" uu = [None]*(len(delta)+1) # relations between adjacent angles ("matrix" entries) ww = [None]*len(uu) # additional matrix entries for the cyclic case vv = [None]*len(uu) # angles ("rhs" entries) theta = [None]*len(uu) # solution of the linear system of equations # 348: # the "matrix" is in tridiagonal form, the solution is obtained by Gaussian elimination. # uu and ww are of type "fraction", vv and theta are of type "angle" # k is the current knot number # r, s, t registers for list traversal k = 0 s = p r = 0 while True: t = s.next if k == 0: # <<< # 354: # Get the linear equations started # or return with the control points in place, if linear equations needn't be solved if s.rtype == mp_given: # <<< if t.ltype == mp_given: # 372: Reduce to simple case of two givens and return aa = mp_n_arg(delta_x[0], delta_y[0]) ct, st = mp_n_sin_cos(p.right_given() - aa) cf, sf = mp_n_sin_cos(q.left_given() - aa) mp_set_controls(p, q, delta_x[0], delta_y[0], st, ct, -sf, cf) return else: # 362: vv[0] = s.right_given() - mp_n_arg(delta_x[0], delta_y[0]) vv[0] = reduce_angle(vv[0]) uu[0] = 0 ww[0] = 0 # >>> elif s.rtype == mp_curl: # <<< if t.ltype == mp_curl: # 373: (mp.pdf) Reduce to simple case of straight line and return p.rtype = mp_explicit q.ltype = mp_explicit lt = abs(q.left_tension()) rt = abs(p.right_tension()) ff = mp_make_fraction(unity, 3.0*rt) p.rx_pt = p.x_pt + mp_take_fraction(delta_x[0], ff) p.ry_pt = p.y_pt + mp_take_fraction(delta_y[0], ff) ff = mp_make_fraction(unity, 3.0*lt) q.lx_pt = q.x_pt - mp_take_fraction(delta_x[0], ff) q.ly_pt = q.y_pt - mp_take_fraction(delta_y[0], ff) return else: # t.ltype != mp_curl # 363: cc = s.right_curl() lt = abs(t.left_tension()) rt = abs(s.right_tension()) uu[0] = mp_curl_ratio(cc, rt, lt) vv[0] = -mp_take_fraction(psi[1], uu[0]) ww[0] = 0 # >>> elif s.rtype == mp_open: # <<< uu[0] = 0 vv[0] = 0 ww[0] = fraction_one # >>> # end of 354 >>> else: # k > 0 <<< if s.ltype == mp_end_cycle or s.ltype == mp_open: # <<< # 356: Set up equation to match mock curvatures at z_k; # then finish loop with theta_n adjusted to equal theta_0, if a # cycle has ended # 357: Calculate the values # aa = Ak/Bk, bb = Dk/Ck, dd = (3-alpha_{k-1})d(k,k+1), # ee = (3-beta_{k+1})d(k-1,k), cc=(Bk-uk-Ak)/Bk aa = mp_make_fraction(unity, 3.0*abs(r.right_tension()) - unity) dd = mp_take_fraction(delta[k], fraction_three - mp_make_fraction(unity, abs(r.right_tension()))) bb = mp_make_fraction(unity, 3*abs(t.left_tension()) - unity) ee = mp_take_fraction(delta[k-1], fraction_three - mp_make_fraction(unity, abs(t.left_tension()))) cc = fraction_one - mp_take_fraction(uu[k-1], aa) # 358: Calculate the ratio ff = Ck/(Ck + Bk - uk-1Ak) dd = mp_take_fraction(dd, cc) lt = abs(s.left_tension()) rt = abs(s.right_tension()) if lt < rt: dd *= (lt/rt)**2 elif lt > rt: ee *= (rt/lt)**2 ff = mp_make_fraction(ee, ee + dd) uu[k] = mp_take_fraction(ff, bb) # 359: Calculate the values of vk and wk acc = -mp_take_fraction(psi[k+1], uu[k]) if r.rtype == mp_curl: ww[k] = 0 vv[k] = acc - mp_take_fraction(psi[1], fraction_one - ff) else: ff = mp_make_fraction(fraction_one - ff, cc) acc = acc - mp_take_fraction(psi[k], ff) ff = mp_take_fraction(ff, aa) vv[k] = acc - mp_take_fraction(vv[k-1], ff) ww[k] = -mp_take_fraction(ww[k-1], ff) if s.ltype == mp_end_cycle: # 360: Adjust theta_n to equal theta_0 and finish loop aa = 0 bb = fraction_one while True: k -= 1 if k == 0: k = n aa = vv[k] - mp_take_fraction(aa, uu[k]) bb = ww[k] - mp_take_fraction(bb, uu[k]) if k == n: break aa = mp_make_fraction(aa, fraction_one - bb) theta[n] = aa vv[0] = aa for k in range(1, n): vv[k] = vv[k] + mp_take_fraction(aa, ww[k]) break # >>> elif s.ltype == mp_curl: # <<< # 364: cc = s.left_curl() lt = abs(s.left_tension()) rt = abs(r.right_tension()) ff = mp_curl_ratio(cc, lt, rt) theta[n] = -mp_make_fraction(mp_take_fraction(vv[n-1], ff), fraction_one - mp_take_fraction(ff, uu[n-1])) break # >>> elif s.ltype == mp_given: # <<< # 361: theta[n] = s.left_given() - mp_n_arg(delta_x[n-1], delta_y[n-1]) theta[n] = reduce_angle(theta[n]) break # >>> # end of k == 0, k != 0 >>> r = s s = t k += 1 # 367: # Finish choosing angles and assigning control points for k in range(n-1, -1, -1): theta[k] = vv[k] - mp_take_fraction(theta[k+1], uu[k]) s = p k = 0 while True: t = s.next ct, st = mp_n_sin_cos(theta[k]) cf, sf = mp_n_sin_cos(-psi[k+1]-theta[k+1]) mp_set_controls(s, t, delta_x[k], delta_y[k], st, ct, sf, cf) k += 1 s = t if k == n: break # >>> def mp_n_arg(x, y): # <<< return atan2(y, x) # >>> def mp_n_sin_cos(z): # <<< """Given an integer z that is 2**20 times an angle theta in degrees, the purpose of n sin cos(z) is to set x = r cos theta and y = r sin theta (approximately), for some rather large number r. The maximum of x and y will be between 2**28 and 2**30, so that there will be hardly any loss of accuracy. Then x and y are divided by r.""" # 67: mpmath.pdf return cos(z), sin(z) # >>> def mp_set_controls(p, q, delta_x, delta_y, st, ct, sf, cf): # <<< """The set controls routine actually puts the control points into a pair of consecutive nodes p and q. Global variables are used to record the values of sin(theta), cos(theta), sin(phi), and cos(phi) needed in this calculation. See mp.pdf, item 370""" lt = abs(q.left_tension()) rt = abs(p.right_tension()) rr = mp_velocity(st, ct, sf, cf, rt) ss = mp_velocity(sf, cf, st, ct, lt) if p.right_tension() < 0 or q.left_tension() < 0: # 371: Decrease the velocities, if necessary, to stay inside the bounding triangle # this is the only place where the sign of the tension counts if (st >= 0 and sf >= 0) or (st <= 0 and sf <= 0): sine = mp_take_fraction(abs(st), cf) + mp_take_fraction(abs(sf), ct) # sin(theta+phi) if sine > 0: #sine = mp_take_fraction(sine, fraction_one + unity) # safety factor sine *= 1.00024414062 # safety factor if p.right_tension() < 0: if mp_ab_vs_cd(abs(sf), fraction_one, rr, sine) < 0: rr = mp_make_fraction(abs(sf), sine) if q.left_tension() < 0: if mp_ab_vs_cd(abs(st), fraction_one, ss, sine) < 0: ss = mp_make_fraction(abs(st), sine) p.rx_pt = p.x_pt + mp_take_fraction(mp_take_fraction(delta_x, ct) - mp_take_fraction(delta_y, st), rr) p.ry_pt = p.y_pt + mp_take_fraction(mp_take_fraction(delta_y, ct) + mp_take_fraction(delta_x, st), rr) q.lx_pt = q.x_pt - mp_take_fraction(mp_take_fraction(delta_x, cf) + mp_take_fraction(delta_y, sf), ss) q.ly_pt = q.y_pt - mp_take_fraction(mp_take_fraction(delta_y, cf) - mp_take_fraction(delta_x, sf), ss) p.rtype = mp_explicit q.ltype = mp_explicit # >>> def mp_make_fraction(p, q): # <<< # 17: mpmath.pdf """The make fraction routine produces the fraction equivalent of p/q, given integers p and q; it computes the integer f = floor(2**28 p/q + 1/2), when p and q are positive. In machine language this would simply be (2**28*p)div q""" return p/q # >>> def mp_take_fraction(q, f): # <<< # 20: mpmath.pdf """The dual of make fraction is take fraction, which multiplies a given integer q by a fraction f. When the operands are positive, it computes p = floor(q*f/2**28 + 1/2), a symmetric function of q and f.""" return q*f # >>> def mp_pyth_add(a, b): # <<< # 44: mpmath.pdf """Pythagorean addition sqrt(a**2 + b**2) is implemented by an elegant iterative scheme due to Cleve Moler and Donald Morrison [IBM Journal of Research and Development 27 (1983), 577-581]. It modifies a and b in such a way that their Pythagorean sum remains invariant, while the smaller argument decreases.""" return sqrt(a*a + b*b) # >>> def mp_curl_ratio(gamma, a_tension, b_tension): # <<< """The curl ratio subroutine has three arguments, which our previous notation encourages us to call gamma, 1/alpha, and 1/beta. It is a somewhat tedious program to calculate [(3-alpha)alpha^2 gamma + beta^3] / [alpha^3 gamma + (3-beta)beta^2], with the result reduced to 4 if it exceeds 4. (This reduction of curl is necessary only if the curl and tension are both large.) The values of alpha and beta will be at most 4/3. See mp.pdf (items 365, 366).""" alpha = 1.0/a_tension beta = 1.0/b_tension return min(4.0, ((3.0-alpha)*alpha**2*gamma + beta**3) / (alpha**3*gamma + (3.0-beta)*beta**2)) # >>> def mp_ab_vs_cd(a, b, c, d): # <<< """Tests rigorously if ab is greater than, equal to, or less than cd, given integers (a, b, c, d). In most cases a quick decision is reached. The result is +1, 0, or -1 in the three respective cases. See mpmath.pdf (item 33).""" if a*b == c*d: return 0 if a*b > c*d: return 1 return -1 # >>> def mp_velocity(st, ct, sf, cf, t): # <<< """Metapost's standard velocity subroutine for cubic Bezier curves. See mpmath.pdf (item 30) and mp.pdf (item 339).""" return min(4.0, (2.0 + sqrt(2)*(st-sf/16.0)*(sf-st/16.0)*(ct-cf)) / (1.5*t*(2+(sqrt(5)-1)*ct + (3-sqrt(5))*cf))) # >>> def reduce_angle(A): # <<< """A macro in mp.c""" if abs(A) > one_eighty_deg: if A > 0: A -= three_sixty_deg else: A += three_sixty_deg return A # >>> # vim:foldmethod=marker:foldmarker=<<<,>>> PyX-0.14.1/pyx/metapost/path.py0000644000076500000240000003110512177540643016524 0ustar andrestaff00000000000000# -*- coding: ISO-8859-1 -*- # # Copyright (C) 2011 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from math import atan2, radians from pyx import unit, attr, normpath from pyx import path as pathmodule from .mp_path import mp_endpoint, mp_explicit, mp_given, mp_curl, mp_open, mp_end_cycle, mp_make_choices # global epsilon (default precision length of metapost, in pt) _epsilon = 1e-5 def set(epsilon=None): global _epsilon if epsilon is not None: _epsilon = epsilon ################################################################################ # Path knots ################################################################################ class _knot: """Internal knot as used in MetaPost (mp.c)""" def __init__(self, x_pt, y_pt, ltype, lx_pt, ly_pt, rtype, rx_pt, ry_pt): self.x_pt = x_pt self.y_pt = y_pt self.ltype = ltype self.lx_pt = lx_pt self.ly_pt = ly_pt self.rtype = rtype self.rx_pt = rx_pt self.ry_pt = ry_pt # this is a linked list: self.next = self def set_left_tension(self, tens): self.ly_pt = tens def set_right_tension(self, tens): self.ry_pt = tens def set_left_curl(self, curl): self.lx_pt = curl def set_right_curl(self, curl): self.rx_pt = curl set_left_given = set_left_curl set_right_given = set_right_curl def left_tension(self): return self.ly_pt def right_tension(self): return self.ry_pt def left_curl(self): return self.lx_pt def right_curl(self): return self.rx_pt left_given = left_curl right_given = right_curl def linked_len(self): """returns the length of a circularly linked list of knots""" n = 1 p = self.next while not p is self: n += 1 p = p.next return n def __repr__(self): result = "" # left if self.ltype == mp_endpoint: pass elif self.ltype == mp_explicit: result += "{explicit %s %s}" % (self.lx_pt, self.ly_pt) elif self.ltype == mp_given: result += "{given %g tens %g}" % (self.lx_pt, self.ly_pt) elif self.ltype == mp_curl: result += "{curl %g tens %g}" % (self.lx_pt, self.ly_pt) elif self.ltype == mp_open: result += "{open tens %g}" % (self.ly_pt) elif self.ltype == mp_end_cycle: result += "{cycle tens %g}" % (self.ly_pt) result += "(%g %g)" % (self.x_pt, self.y_pt) # right if self.rtype == mp_endpoint: pass elif self.rtype == mp_explicit: result += "{explicit %g %g}" % (self.rx_pt, self.ry_pt) elif self.rtype == mp_given: result += "{given %g tens %g}" % (self.rx_pt, self.ry_pt) elif self.rtype == mp_curl: result += "{curl %g tens %g}" % (self.rx_pt, self.ry_pt) elif self.rtype == mp_open: result += "{open tens %g}" % (self.ry_pt) elif self.rtype == mp_end_cycle: result += "{cycle tens %g}" % (self.ry_pt) return result class beginknot_pt(_knot): """A knot which interrupts a path, or which allows to continue it with a straight line""" def __init__(self, x_pt, y_pt, curl=1, angle=None): if angle is None: type, value = mp_curl, curl else: type, value = mp_given, angle # tensions are modified by the adjacent curve, but default is 1 _knot.__init__(self, x_pt, y_pt, mp_endpoint, None, None, type, value, 1) class beginknot(beginknot_pt): def __init__(self, x, y, curl=1, angle=None): if not (angle is None): angle = radians(angle) beginknot_pt.__init__(self, unit.topt(x), unit.topt(y), curl, angle) startknot = beginknot class endknot_pt(_knot): """A knot which interrupts a path, or which allows to continue it with a straight line""" def __init__(self, x_pt, y_pt, curl=1, angle=None): if angle is None: type, value = mp_curl, curl else: type, value = mp_given, angle # tensions are modified by the adjacent curve, but default is 1 _knot.__init__(self, x_pt, y_pt, type, value, 1, mp_endpoint, None, None) class endknot(endknot_pt): def __init__(self, x, y, curl=1, angle=None): if not (angle is None): angle = radians(angle) endknot_pt.__init__(self, unit.topt(x), unit.topt(y), curl, angle) class smoothknot_pt(_knot): """A knot with continous tangent and "mock" curvature.""" def __init__(self, x_pt, y_pt): # tensions are modified by the adjacent curve, but default is 1 _knot.__init__(self, x_pt, y_pt, mp_open, None, 1, mp_open, None, 1) class smoothknot(smoothknot_pt): def __init__(self, x, y): smoothknot_pt.__init__(self, unit.topt(x), unit.topt(y)) knot = smoothknot class roughknot_pt(_knot): """A knot with noncontinous tangent.""" def __init__(self, x_pt, y_pt, lcurl=1, rcurl=None, langle=None, rangle=None): """Specify either the relative curvatures, or tangent angles left (l) or right (r) of the point.""" if langle is None: ltype, lvalue = mp_curl, lcurl else: ltype, lvalue = mp_given, langle if rcurl is not None: rtype, rvalue = mp_curl, rcurl elif rangle is not None: rtype, rvalue = mp_given, rangle else: rtype, rvalue = ltype, lvalue # tensions are modified by the adjacent curve, but default is 1 _knot.__init__(self, x_pt, y_pt, ltype, lvalue, 1, rtype, rvalue, 1) class roughknot(roughknot_pt): def __init__(self, x, y, lcurl=1, rcurl=None, langle=None, rangle=None): if langle is not None: langle = radians(langle) if rangle is not None: rangle = radians(rangle) roughknot_pt.__init__(self, unit.topt(x), unit.topt(y), lcurl, rcurl, langle, rangle) ################################################################################ # Path links ################################################################################ class _link: def set_knots(self, left_knot, right_knot): """Sets the internal properties of the metapost knots""" pass class line(_link): """A straight line""" def __init__(self, keepangles=False): """The option keepangles will guarantee a continuous tangent. The curvature may become discontinuous, however""" self.keepangles = keepangles def set_knots(self, left_knot, right_knot): left_knot.rtype = mp_endpoint right_knot.ltype = mp_endpoint left_knot.rx_pt, left_knot.ry_pt = None, None right_knot.lx_pt, right_knot.ly_pt = None, None if self.keepangles: angle = atan2(right_knot.y_pt-left_knot.y_pt, right_knot.x_pt-left_knot.x_pt) left_knot.ltype = mp_given left_knot.set_left_given(angle) right_knot.rtype = mp_given right_knot.set_right_given(angle) class controlcurve_pt(_link): """A cubic Bezier curve which has its control points explicity set""" def __init__(self, lcontrol_pt, rcontrol_pt): """The control points at the beginning (l) and the end (r) must be coordinate pairs""" self.lcontrol_pt = lcontrol_pt self.rcontrol_pt = rcontrol_pt def set_knots(self, left_knot, right_knot): left_knot.rtype = mp_explicit right_knot.ltype = mp_explicit left_knot.rx_pt, left_knot.ry_pt = self.lcontrol_pt right_knot.lx_pt, right_knot.ly_pt = self.rcontrol_pt class controlcurve(controlcurve_pt): def __init__(self, lcontrol, rcontrol): controlcurve_pt.__init__(self, (unit.topt(lcontrol[0]), unit.topt(lcontrol[1])), (unit.topt(rcontrol[0]), unit.topt(rcontrol[1]))) class tensioncurve(_link): """A yet unspecified cubic Bezier curve""" def __init__(self, ltension=1, latleast=False, rtension=None, ratleast=None): """The tension parameters indicate the tensions at the beginning (l) and the end (r) of the curve. Set the parameters (l/r)atleast to True if you want to avoid inflection points.""" if rtension is None: rtension = ltension if ratleast is None: ratleast = latleast # make sure that tension >= 0.75 (p. 9 mpman.pdf) self.ltension = max(0.75, abs(ltension)) self.rtension = max(0.75, abs(rtension)) if latleast: self.ltension = -self.ltension if ratleast: self.rtension = -self.rtension def set_knots(self, left_knot, right_knot): if left_knot.rtype <= mp_explicit or right_knot.ltype <= mp_explicit: raise Exception("metapost curve with given tension cannot have explicit knots") left_knot.set_right_tension(self.ltension) right_knot.set_left_tension(self.rtension) curve = tensioncurve ################################################################################ # Path creation class ################################################################################ class path(pathmodule.path): """A MetaPost-like path, which finds an optimal way through given points. At points, you can either specify a given tangent direction (angle in degrees) or a certain "curlyness" (relative to the curvature at the other end of a curve), or nothing. In the latter case, both the tangent and the "mock" curvature (an approximation to the real curvature, introduced by J.D. Hobby in MetaPost) will be continuous. The shape of the cubic Bezier curves between two points is controlled by its "tension", unless you choose to set the control points manually.""" def __init__(self, elems, epsilon=None): """elems should contain metapost knots or links""" if epsilon is None: epsilon = _epsilon knots = [] is_closed = True for i, elem in enumerate(elems): if isinstance(elem, _link): elem.set_knots(elems[i-1], elems[(i+1)%len(elems)]) elif isinstance(elem, _knot): knots.append(elem) if elem.ltype == mp_endpoint or elem.rtype == mp_endpoint: is_closed = False # link the knots among each other for i in range(len(knots)): knots[i-1].next = knots[i] # determine the control points mp_make_choices(knots[0], epsilon) pathmodule.path.__init__(self) # build up the path do_moveto = True do_lineto = False do_curveto = False prev = None for i, elem in enumerate(elems): if isinstance(elem, _link): do_moveto = False if isinstance(elem, line): do_lineto, do_curveto = True, False else: do_lineto, do_curveto = False, True elif isinstance(elem, _knot): if do_moveto: self.append(pathmodule.moveto_pt(elem.x_pt, elem.y_pt)) if do_lineto: self.append(pathmodule.lineto_pt(elem.x_pt, elem.y_pt)) elif do_curveto: self.append(pathmodule.curveto_pt(prev.rx_pt, prev.ry_pt, elem.lx_pt, elem.ly_pt, elem.x_pt, elem.y_pt)) do_moveto = True do_lineto = False do_curveto = False prev = elem # close the path if necessary if knots[0].ltype == mp_explicit: elem = knots[0] if do_lineto and is_closed: self.append(pathmodule.closepath()) elif do_curveto: self.append(pathmodule.curveto_pt(prev.rx_pt, prev.ry_pt, elem.lx_pt, elem.ly_pt, elem.x_pt, elem.y_pt)) if is_closed: self.append(pathmodule.closepath()) PyX-0.14.1/pyx/normpath.py0000644000076500000240000025047612534660543015601 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2003-2013 Michael Schindler # Copyright (C) 2002-2013 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math, functools from . import mathutils, trafo, unit from . import bbox as bboxmodule class _marker: pass # specific exception for normpath-related problems class NormpathException(Exception): pass # global epsilon (default precision of normsubpaths) _epsilon = 1e-5 def set(epsilon=None): global _epsilon if epsilon is not None: _epsilon = epsilon ################################################################################ # normsubpathitems ################################################################################ class normsubpathitem: """element of a normalized sub path Various operations on normsubpathitems might be subject of approximitions. Those methods get the finite precision epsilon, which is the accuracy needed expressed as a length in pts. normsubpathitems should never be modified inplace, since references might be shared between several normsubpaths. """ def arclen_pt(self, epsilon, upper=False): """return arc length in pts When upper is set, the upper bound is calculated, otherwise the lower bound is returned.""" pass def _arclentoparam_pt(self, lengths_pt, epsilon): """return a tuple of params and the total length arc length in pts""" pass def arclentoparam_pt(self, lengths_pt, epsilon): """return a tuple of params""" pass def at_pt(self, params): """return coordinates at params in pts""" pass def atbegin_pt(self): """return coordinates of first point in pts""" pass def atend_pt(self): """return coordinates of last point in pts""" pass def bbox(self): """return bounding box of normsubpathitem""" pass def cbox(self): """return control box of normsubpathitem The control box also fully encloses the normsubpathitem but in the case of a Bezier curve it is not the minimal box doing so. On the other hand, it is much faster to calculate. """ pass def curvature_pt(self, params): """return the curvature at params in 1/pts""" pass def intersect(self, other, epsilon): """intersect self with other normsubpathitem""" pass def modifiedbegin_pt(self, x_pt, y_pt): """return a normsubpathitem with a modified beginning point""" pass def modifiedend_pt(self, x_pt, y_pt): """return a normsubpathitem with a modified end point""" pass def _paramtoarclen_pt(self, param, epsilon): """return a tuple of arc lengths and the total arc length in pts""" pass def pathitem(self): """return pathitem corresponding to normsubpathitem""" def reversed(self): """return reversed normsubpathitem""" pass def rotation(self, params): """return rotation trafos (i.e. trafos without translations) at params""" pass def segments(self, params): """return segments of the normsubpathitem The returned list of normsubpathitems for the segments between the params. params needs to contain at least two values. """ pass def trafo(self, params): """return transformations at params""" def transformed(self, trafo): """return transformed normsubpathitem according to trafo""" pass def outputPS(self, file, writer): """write PS code corresponding to normsubpathitem to file""" pass def outputPDF(self, file, writer): """write PDF code corresponding to normsubpathitem to file""" pass def returnSVGdata(self, inverse_y): """return SVG code corresponding to normsubpathitem""" pass class normline_pt(normsubpathitem): """Straight line from (x0_pt, y0_pt) to (x1_pt, y1_pt) (coordinates in pts)""" __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt" def __init__(self, x0_pt, y0_pt, x1_pt, y1_pt): self.x0_pt = x0_pt self.y0_pt = y0_pt self.x1_pt = x1_pt self.y1_pt = y1_pt def __str__(self): return "normline_pt(%g, %g, %g, %g)" % (self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt) def _arclentoparam_pt(self, lengths_pt, epsilon): # do self.arclen_pt inplace for performance reasons l_pt = math.hypot(self.x0_pt-self.x1_pt, self.y0_pt-self.y1_pt) return [length_pt/l_pt for length_pt in lengths_pt], l_pt def arclentoparam_pt(self, lengths_pt, epsilon): """return a tuple of params""" return self._arclentoparam_pt(lengths_pt, epsilon)[0] def arclen_pt(self, epsilon, upper=False): return math.hypot(self.x0_pt-self.x1_pt, self.y0_pt-self.y1_pt) def at_pt(self, params): return [(self.x0_pt+(self.x1_pt-self.x0_pt)*t, self.y0_pt+(self.y1_pt-self.y0_pt)*t) for t in params] def atbegin_pt(self): return self.x0_pt, self.y0_pt def atend_pt(self): return self.x1_pt, self.y1_pt def bbox(self): return bboxmodule.bbox_pt(min(self.x0_pt, self.x1_pt), min(self.y0_pt, self.y1_pt), max(self.x0_pt, self.x1_pt), max(self.y0_pt, self.y1_pt)) cbox = bbox def curvature_pt(self, params): return [0] * len(params) def intersect(self, other, epsilon): if isinstance(other, normline_pt): a_deltax_pt = self.x1_pt - self.x0_pt a_deltay_pt = self.y1_pt - self.y0_pt b_deltax_pt = other.x1_pt - other.x0_pt b_deltay_pt = other.y1_pt - other.y0_pt invdet = b_deltax_pt * a_deltay_pt - b_deltay_pt * a_deltax_pt if abs(invdet) < epsilon * epsilon: # As invdet measures the area spanned by the two lines, least # one of the lines is either very short or the lines are almost # parallel. In both cases, a proper colinear check is adequate, # already. Let's first check for short lines. short_self = math.hypot(self.x1_pt - self.x0_pt, self.y1_pt - self.y0_pt) < epsilon short_other = math.hypot(other.x1_pt - other.x0_pt, other.y1_pt - other.y0_pt) < epsilon # For short lines we will only take their middle point into # account. if short_self: sx_pt = 0.5*(self.x0_pt + self.x1_pt) sy_pt = 0.5*(self.y0_pt + self.x1_pt) if short_other: ox_pt = 0.5*(other.x0_pt + other.x1_pt) oy_pt = 0.5*(other.y0_pt + other.y1_pt) def closepoint(x_pt, y_pt, x0_pt, y0_pt, x1_pt, y1_pt): """Returns the line parameter p in range [0, 1] for which the point (x_pt, y_pt) is closest to the line defined by ((x0_pt, y0_pt), (x1_pt, y1_pt)). The distance of (x0_pt, y0_pt) and (x1_pt, y1_pt) must be larger than epsilon. If the point has a greater distance than epsilon, None is returned.""" p = (((x0_pt - x_pt)*(x0_pt - x1_pt) + (y0_pt - y_pt)*(y0_pt - y1_pt))/ ((x1_pt - x0_pt)**2 + (y1_pt - y0_pt)**2)) p = min(1, max(0, p)) xs_pt = x0_pt + p*(x1_pt - x0_pt) ys_pt = y0_pt + p*(y1_pt - y0_pt) if math.hypot(xs_pt - x_pt, ys_pt - y_pt) < epsilon: return p return None # just be explicit in returning None here if short_self and short_other: # If both lines are short, we just measure the distance of # the middle points. if math.hypot(ox_pt - sx_pt, oy_pt - sy_pt) < epsilon: return [(0.5, 0.5)] elif short_self: p = closepoint(sx_pt, sy_pt, other.x0_pt, other.y0_pt, other.x1_pt, other.y1_pt) if p is not None: return [(0.5, p)] elif short_other: p = closepoint(ox_pt, oy_pt, self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt) if p is not None: return [(p, 0.5)] else: # For two long colinear lines, we need to test the # beginning and end point of the two lines with respect to # the other line, in all combinations. We return just one # solution even when the lines intersect for a whole range. p = closepoint(self.x0_pt, self.y0_pt, other.x0_pt, other.y0_pt, other.x1_pt, other.y1_pt) if p is not None: return [(0, p)] p = closepoint(self.x1_pt, self.y1_pt, other.x0_pt, other.y0_pt, other.x1_pt, other.y1_pt) if p is not None: return [(1, p)] p = closepoint(other.x0_pt, other.y0_pt, self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt) if p is not None: return [(p, 0)] p = closepoint(other.x1_pt, other.y1_pt, self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt) if p is not None: return [(p, 1)] return [] det = 1.0 / invdet ba_deltax0_pt = other.x0_pt - self.x0_pt ba_deltay0_pt = other.y0_pt - self.y0_pt a_t = (b_deltax_pt * ba_deltay0_pt - b_deltay_pt * ba_deltax0_pt) * det b_t = (a_deltax_pt * ba_deltay0_pt - a_deltay_pt * ba_deltax0_pt) * det # check for intersections out of bound if not (0<=a_t<=1 and 0<=b_t<=1): # correct the parameters, if the deviation is smaller than epsilon a_t = min(1, max(0, a_t)) b_t = min(1, max(0, b_t)) a_x = self.x0_pt + a_deltax_pt*a_t a_y = self.y0_pt + a_deltay_pt*a_t b_x = other.x0_pt + b_deltax_pt*b_t b_y = other.y0_pt + b_deltay_pt*b_t if math.hypot(a_x - b_x, a_y - b_y) > epsilon: return [] # return parameters of intersection return [(a_t, b_t)] else: return [(s_t, o_t) for o_t, s_t in other.intersect(self, epsilon)] def modifiedbegin_pt(self, x_pt, y_pt): return normline_pt(x_pt, y_pt, self.x1_pt, self.y1_pt) def modifiedend_pt(self, x_pt, y_pt): return normline_pt(self.x0_pt, self.y0_pt, x_pt, y_pt) def _paramtoarclen_pt(self, params, epsilon): totalarclen_pt = self.arclen_pt(epsilon) arclens_pt = [totalarclen_pt * param for param in params + [1]] return arclens_pt[:-1], arclens_pt[-1] def pathitem(self): from . import path return path.lineto_pt(self.x1_pt, self.y1_pt) def reversed(self): return normline_pt(self.x1_pt, self.y1_pt, self.x0_pt, self.y0_pt) def rotation(self, params): return [trafo.rotate(math.degrees(math.atan2(self.y1_pt-self.y0_pt, self.x1_pt-self.x0_pt)))]*len(params) def segments(self, params): if len(params) < 2: raise ValueError("at least two parameters needed in segments") result = [] xl_pt = yl_pt = None for t in params: xr_pt = self.x0_pt + (self.x1_pt-self.x0_pt)*t yr_pt = self.y0_pt + (self.y1_pt-self.y0_pt)*t if xl_pt is not None: result.append(normline_pt(xl_pt, yl_pt, xr_pt, yr_pt)) xl_pt = xr_pt yl_pt = yr_pt return result def trafo(self, params): rotate = trafo.rotate(math.degrees(math.atan2(self.y1_pt-self.y0_pt, self.x1_pt-self.x0_pt))) return [trafo.translate_pt(*at_pt) * rotate for param, at_pt in zip(params, self.at_pt(params))] def transformed(self, trafo): return normline_pt(*(trafo.apply_pt(self.x0_pt, self.y0_pt) + trafo.apply_pt(self.x1_pt, self.y1_pt))) def outputPS(self, file, writer): file.write("%g %g lineto\n" % (self.x1_pt, self.y1_pt)) def outputPDF(self, file, writer): file.write("%f %f l\n" % (self.x1_pt, self.y1_pt)) def returnSVGdata(self, inverse_y): if inverse_y: return "L%g %g" % (self.x1_pt, -self.y1_pt) return "L%g %g" % (self.x1_pt, self.y1_pt) class normcurve_pt(normsubpathitem): """Bezier curve with control points x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt (coordinates in pts)""" __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt", "x2_pt", "y2_pt", "x3_pt", "y3_pt" def __init__(self, x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt): self.x0_pt = x0_pt self.y0_pt = y0_pt self.x1_pt = x1_pt self.y1_pt = y1_pt self.x2_pt = x2_pt self.y2_pt = y2_pt self.x3_pt = x3_pt self.y3_pt = y3_pt def __str__(self): return "normcurve_pt(%g, %g, %g, %g, %g, %g, %g, %g)" % (self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) def _split(self, t=0.5, epsilon=None, intersect=False): """Split curve into two parts The splitting point is defined by the parameter t (in range 0 to 1). When epsilon is None, the two resulting curves are returned. However, when epsilon is set to a (small) float, the method can be used recursively to reduce the complexity of a problem by turning a normcurve_pt into several normline_pt segments. The method returns normcurve_pt instances only, when they are not yet straight enough to be replaceable by normline_pt instances. The criteria for returning a line instead of a curve depends on the value of the boolean intersect. When not set, the abort cirteria is defined by the error of the arclen of the curve vs. the line not being larger than epsilon. When in intersect mode, all points of the curve must be closer to the line than epsilon. """ s = 1-t # first, we have to calculate the midpoints between adjacent # control points x01_pt = s*self.x0_pt + t*self.x1_pt y01_pt = s*self.y0_pt + t*self.y1_pt x12_pt = s*self.x1_pt + t*self.x2_pt y12_pt = s*self.y1_pt + t*self.y2_pt x23_pt = s*self.x2_pt + t*self.x3_pt y23_pt = s*self.y2_pt + t*self.y3_pt # In the next iterative step, we need the midpoints between 01 and 12 # and between 12 and 23 x01_12_pt = s*x01_pt + t*x12_pt y01_12_pt = s*y01_pt + t*y12_pt x12_23_pt = s*x12_pt + t*x23_pt y12_23_pt = s*y12_pt + t*y23_pt # Finally the midpoint is given by xmidpoint_pt = s*x01_12_pt + t*x12_23_pt ymidpoint_pt = s*y01_12_pt + t*y12_23_pt def subcurve(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt, newline, newcurve): if epsilon is None: return normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt) # Before returning the subcurve we check whether we can # replace it by a normline within an error of epsilon pts. l0_pt = math.hypot(x3_pt-x0_pt, y3_pt-y0_pt) l1_pt = math.hypot(x1_pt-x0_pt, y1_pt-y0_pt) l2_pt = math.hypot(x2_pt-x1_pt, y2_pt-y1_pt) l3_pt = math.hypot(x3_pt-x2_pt, y3_pt-y2_pt) # When arclen calculation is performed, the maximal error value is # given by the modulus of the difference between the length of the # control polygon (i.e. |P1-P0|+|P2-P1|+|P3-P2|), which consitutes # an upper bound for the length, and the length of the straight # line between start and end point of the normcurve (i.e. |P3-P1|), # which represents a lower bound. if not intersect and l1_pt+l2_pt+l3_pt-l0_pt < epsilon: # We can ignore the sign of l1_pt, l2_pt and l3_pt, as the sum # of the absolute values is close to l0_pt anyway. return newline(x0_pt, y0_pt, x3_pt, y3_pt, l1_pt, l2_pt, l3_pt) if intersect: # For intersections we calculate the distance of (x1_pt, y1_pt) # and (x2_pt, y2_pt) from the line defined by (x0_pt, y0_pt) # and (x3_pt, y3_pt). We skip the division by l0_pt in the # result and calculate d1_pt*l0_pt and d2_pt*l0_pt instead. d1_pt_times_l0_pt = (x3_pt-x0_pt)*(y0_pt-y1_pt) - (x0_pt-x1_pt)*(y3_pt-y0_pt) d2_pt_times_l0_pt = (x0_pt-x3_pt)*(y3_pt-y2_pt) - (x3_pt-x2_pt)*(y0_pt-y3_pt) if abs(d1_pt_times_l0_pt) < epsilon*l0_pt and abs(d2_pt_times_l0_pt) < epsilon*l0_pt: # We could return the line now, but for this to be correct, # we would need to take into account the signs of l1_pt, # l2_pt, and l3_pt. In addition, this could result in # multiple parameters matching a position on the line. s1 = (x1_pt-x0_pt)*(x3_pt-x0_pt)+(y1_pt-y0_pt)*(y3_pt-y0_pt) s2 = (x2_pt-x1_pt)*(x3_pt-x0_pt)+(y2_pt-y1_pt)*(y3_pt-y0_pt) s3 = (x2_pt-x3_pt)*(x0_pt-x3_pt)+(y2_pt-y3_pt)*(y0_pt-y3_pt) # If the signs are negative (i.e. we have backwards # directed segments in the control polygon), we can still # continue, if the corresponding segment is smaller than # epsilon. if ((s1 > 0 or l1_pt < epsilon) and (s2 > 0 or l2_pt < epsilon) and (s3 > 0 or l3_pt < epsilon)): # As the sign of the segments is either positive or the # segments are short, we can continue with the unsigned # values for the segment lengths, as for the arclen # calculation. return newline(x0_pt, y0_pt, x3_pt, y3_pt, l1_pt, l2_pt, l3_pt) return newcurve(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt) return (subcurve(self.x0_pt, self.y0_pt, x01_pt, y01_pt, x01_12_pt, y01_12_pt, xmidpoint_pt, ymidpoint_pt, _leftnormline_pt, _leftnormcurve_pt), subcurve(xmidpoint_pt, ymidpoint_pt, x12_23_pt, y12_23_pt, x23_pt, y23_pt, self.x3_pt, self.y3_pt, _rightnormline_pt, _rightnormcurve_pt)) def _arclentoparam_pt(self, lengths_pt, epsilon): a, b = self._split(epsilon=epsilon) params_a, arclen_a_pt = a._arclentoparam_pt(lengths_pt, 0.5*epsilon) params_b, arclen_b_pt = b._arclentoparam_pt([length_pt - arclen_a_pt for length_pt in lengths_pt], 0.5*epsilon) params = [] for param_a, param_b, length_pt in zip(params_a, params_b, lengths_pt): if length_pt > arclen_a_pt: params.append(b.subparamtoparam(param_b)) else: params.append(a.subparamtoparam(param_a)) return params, arclen_a_pt + arclen_b_pt def arclentoparam_pt(self, lengths_pt, epsilon): """return a tuple of params""" return self._arclentoparam_pt(lengths_pt, epsilon)[0] def arclen_pt(self, epsilon, upper=False): a, b = self._split(epsilon=epsilon) return a.arclen_pt(0.5*epsilon, upper=upper) + b.arclen_pt(0.5*epsilon, upper=upper) def at_pt(self, params): return [( (-self.x0_pt+3*self.x1_pt-3*self.x2_pt+self.x3_pt)*t*t*t + (3*self.x0_pt-6*self.x1_pt+3*self.x2_pt )*t*t + (-3*self.x0_pt+3*self.x1_pt )*t + self.x0_pt, (-self.y0_pt+3*self.y1_pt-3*self.y2_pt+self.y3_pt)*t*t*t + (3*self.y0_pt-6*self.y1_pt+3*self.y2_pt )*t*t + (-3*self.y0_pt+3*self.y1_pt )*t + self.y0_pt ) for t in params] def atbegin_pt(self): return self.x0_pt, self.y0_pt def atend_pt(self): return self.x3_pt, self.y3_pt def bbox(self): from . import path xmin_pt, xmax_pt = path._bezierpolyrange(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt) ymin_pt, ymax_pt = path._bezierpolyrange(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt) return bboxmodule.bbox_pt(xmin_pt, ymin_pt, xmax_pt, ymax_pt) def cbox(self): return bboxmodule.bbox_pt(min(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), min(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt), max(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), max(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt)) def curvature_pt(self, params): result = [] # see notes in rotation approxarclen = (math.hypot(self.x1_pt-self.x0_pt, self.y1_pt-self.y0_pt) + math.hypot(self.x2_pt-self.x1_pt, self.y2_pt-self.y1_pt) + math.hypot(self.x3_pt-self.x2_pt, self.y3_pt-self.y2_pt)) for param in params: xdot = ( 3 * (1-param)*(1-param) * (-self.x0_pt + self.x1_pt) + 6 * (1-param)*param * (-self.x1_pt + self.x2_pt) + 3 * param*param * (-self.x2_pt + self.x3_pt) ) ydot = ( 3 * (1-param)*(1-param) * (-self.y0_pt + self.y1_pt) + 6 * (1-param)*param * (-self.y1_pt + self.y2_pt) + 3 * param*param * (-self.y2_pt + self.y3_pt) ) xddot = ( 6 * (1-param) * (self.x0_pt - 2*self.x1_pt + self.x2_pt) + 6 * param * (self.x1_pt - 2*self.x2_pt + self.x3_pt) ) yddot = ( 6 * (1-param) * (self.y0_pt - 2*self.y1_pt + self.y2_pt) + 6 * param * (self.y1_pt - 2*self.y2_pt + self.y3_pt) ) hypot = math.hypot(xdot, ydot) result.append((xdot*yddot - ydot*xddot) / hypot**3) return result def intersect(self, other, epsilon): # There can be no intersection point if the control boxes do not # overlap. Note that we use the control box instead of the bounding # box here, because the former can be calculated more efficiently for # Bezier curves. if not self.cbox().enlarged_pt(epsilon).intersects(other.cbox()): return [] a, b = self._split(epsilon=epsilon, intersect=True) # To improve the performance in the general case we alternate the # splitting process between the two normsubpathitems return ( [(a.subparamtoparam(a_t), o_t) for o_t, a_t in other.intersect(a, epsilon)] + [(b.subparamtoparam(b_t), o_t) for o_t, b_t in other.intersect(b, epsilon)] ) def modifiedbegin_pt(self, x_pt, y_pt): return normcurve_pt(x_pt, y_pt, self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) def modifiedend_pt(self, x_pt, y_pt): return normcurve_pt(self.x0_pt, self.y0_pt, self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, x_pt, y_pt) def _paramtoarclen_pt(self, params, epsilon): arclens_pt = [segment.arclen_pt(epsilon) for segment in self.segments([0] + list(params) + [1])] for i in range(1, len(arclens_pt)): arclens_pt[i] += arclens_pt[i-1] return arclens_pt[:-1], arclens_pt[-1] def pathitem(self): from . import path return path.curveto_pt(self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) def reversed(self): return normcurve_pt(self.x3_pt, self.y3_pt, self.x2_pt, self.y2_pt, self.x1_pt, self.y1_pt, self.x0_pt, self.y0_pt) def rotation(self, params): result = [] for param in params: tdx_pt = (3*( -self.x0_pt+3*self.x1_pt-3*self.x2_pt+self.x3_pt)*param*param + 2*( 3*self.x0_pt-6*self.x1_pt+3*self.x2_pt )*param + (-3*self.x0_pt+3*self.x1_pt )) tdy_pt = (3*( -self.y0_pt+3*self.y1_pt-3*self.y2_pt+self.y3_pt)*param*param + 2*( 3*self.y0_pt-6*self.y1_pt+3*self.y2_pt )*param + (-3*self.y0_pt+3*self.y1_pt )) result.append(trafo.rotate(math.degrees(math.atan2(tdy_pt, tdx_pt)))) return result def segments(self, params): if len(params) < 2: raise ValueError("at least two parameters needed in segments") # first, we calculate the coefficients corresponding to our # original bezier curve. These represent a useful starting # point for the following change of the polynomial parameter a0x_pt = self.x0_pt a0y_pt = self.y0_pt a1x_pt = 3*(-self.x0_pt+self.x1_pt) a1y_pt = 3*(-self.y0_pt+self.y1_pt) a2x_pt = 3*(self.x0_pt-2*self.x1_pt+self.x2_pt) a2y_pt = 3*(self.y0_pt-2*self.y1_pt+self.y2_pt) a3x_pt = -self.x0_pt+3*(self.x1_pt-self.x2_pt)+self.x3_pt a3y_pt = -self.y0_pt+3*(self.y1_pt-self.y2_pt)+self.y3_pt result = [] for i in range(len(params)-1): t1 = params[i] dt = params[i+1]-t1 # [t1,t2] part # # the new coefficients of the [t1,t1+dt] part of the bezier curve # are then given by expanding # a0 + a1*(t1+dt*u) + a2*(t1+dt*u)**2 + # a3*(t1+dt*u)**3 in u, yielding # # a0 + a1*t1 + a2*t1**2 + a3*t1**3 + # ( a1 + 2*a2 + 3*a3*t1**2 )*dt * u + # ( a2 + 3*a3*t1 )*dt**2 * u**2 + # a3*dt**3 * u**3 # # from this values we obtain the new control points by inversion # # TODO: we could do this more efficiently by reusing for # (x0_pt, y0_pt) the control point (x3_pt, y3_pt) from the previous # Bezier curve x0_pt = a0x_pt + a1x_pt*t1 + a2x_pt*t1*t1 + a3x_pt*t1*t1*t1 y0_pt = a0y_pt + a1y_pt*t1 + a2y_pt*t1*t1 + a3y_pt*t1*t1*t1 x1_pt = (a1x_pt+2*a2x_pt*t1+3*a3x_pt*t1*t1)*dt/3.0 + x0_pt y1_pt = (a1y_pt+2*a2y_pt*t1+3*a3y_pt*t1*t1)*dt/3.0 + y0_pt x2_pt = (a2x_pt+3*a3x_pt*t1)*dt*dt/3.0 - x0_pt + 2*x1_pt y2_pt = (a2y_pt+3*a3y_pt*t1)*dt*dt/3.0 - y0_pt + 2*y1_pt x3_pt = a3x_pt*dt*dt*dt + x0_pt - 3*x1_pt + 3*x2_pt y3_pt = a3y_pt*dt*dt*dt + y0_pt - 3*y1_pt + 3*y2_pt result.append(normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt)) return result def trafo(self, params): result = [] for rotation, at_pt in zip(self.rotation(params), self.at_pt(params)): result.append(trafo.translate_pt(*at_pt) * rotation) return result def transformed(self, trafo): x0_pt, y0_pt = trafo.apply_pt(self.x0_pt, self.y0_pt) x1_pt, y1_pt = trafo.apply_pt(self.x1_pt, self.y1_pt) x2_pt, y2_pt = trafo.apply_pt(self.x2_pt, self.y2_pt) x3_pt, y3_pt = trafo.apply_pt(self.x3_pt, self.y3_pt) return normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt) def outputPS(self, file, writer): file.write("%g %g %g %g %g %g curveto\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) def outputPDF(self, file, writer): file.write("%f %f %f %f %f %f c\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) def returnSVGdata(self, inverse_y): if inverse_y: return "C%g %g %g %g %g %g" % (self.x1_pt, -self.y1_pt, self.x2_pt, -self.y2_pt, self.x3_pt, -self.y3_pt) return "C%g %g %g %g %g %g" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) def x_pt(self, t): return ((( self.x3_pt-3*self.x2_pt+3*self.x1_pt-self.x0_pt)*t + 3*self.x0_pt-6*self.x1_pt+3*self.x2_pt)*t + 3*self.x1_pt-3*self.x0_pt)*t + self.x0_pt def xdot_pt(self, t): return ((3*self.x3_pt-9*self.x2_pt+9*self.x1_pt-3*self.x0_pt)*t + 6*self.x0_pt-12*self.x1_pt+6*self.x2_pt)*t + 3*self.x1_pt - 3*self.x0_pt def xddot_pt(self, t): return (6*self.x3_pt-18*self.x2_pt+18*self.x1_pt-6*self.x0_pt)*t + 6*self.x0_pt - 12*self.x1_pt + 6*self.x2_pt def xdddot_pt(self, t): return 6*self.x3_pt-18*self.x2_pt+18*self.x1_pt-6*self.x0_pt def y_pt(self, t): return ((( self.y3_pt-3*self.y2_pt+3*self.y1_pt-self.y0_pt)*t + 3*self.y0_pt-6*self.y1_pt+3*self.y2_pt)*t + 3*self.y1_pt-3*self.y0_pt)*t + self.y0_pt def ydot_pt(self, t): return ((3*self.y3_pt-9*self.y2_pt+9*self.y1_pt-3*self.y0_pt)*t + 6*self.y0_pt-12*self.y1_pt+6*self.y2_pt)*t + 3*self.y1_pt - 3*self.y0_pt def yddot_pt(self, t): return (6*self.y3_pt-18*self.y2_pt+18*self.y1_pt-6*self.y0_pt)*t + 6*self.y0_pt - 12*self.y1_pt + 6*self.y2_pt def ydddot_pt(self, t): return 6*self.y3_pt-18*self.y2_pt+18*self.y1_pt-6*self.y0_pt # curve replacements used by midpointsplit: # The replacements are normline_pt and normcurve_pt instances with an # additional subparamtoparam function for proper conversion of the # parametrization. Note that we only one direction (when a parameter # gets calculated), since the other way around direction midpointsplit # is not needed at all class _leftnormline_pt(normline_pt): __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt", "l1_pt", "l2_pt", "l3_pt" def __init__(self, x0_pt, y0_pt, x1_pt, y1_pt, l1_pt, l2_pt, l3_pt): normline_pt.__init__(self, x0_pt, y0_pt, x1_pt, y1_pt) self.l1_pt = l1_pt self.l2_pt = l2_pt self.l3_pt = l3_pt def arclen_pt(self, epsilon, upper=False): if upper: return self.l1_pt + self.l2_pt + self.l3_pt else: return math.hypot(self.x0_pt-self.x1_pt, self.y0_pt-self.y1_pt) def subparamtoparam(self, param): if 0 <= param <= 1: params = mathutils.realpolyroots(self.l1_pt-2*self.l2_pt+self.l3_pt, -3*self.l1_pt+3*self.l2_pt, 3*self.l1_pt, -param*(self.l1_pt+self.l2_pt+self.l3_pt)) # we might get several solutions and choose the one closest to 0.5 # (we want the solution to be in the range 0 <= param <= 1; in case # we get several solutions in this range, they all will be close to # each other since l1_pt+l2_pt+l3_pt-l0_pt < epsilon) params.sort(key=lambda t: abs(t-0.5)) return 0.5*params[0] else: # when we are outside the proper parameter range, we skip the non-linear # transformation, since it becomes slow and it might even start to be # numerically instable return 0.5*param class _rightnormline_pt(_leftnormline_pt): __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt", "l1_pt", "l2_pt", "l3_pt" def subparamtoparam(self, param): return 0.5+_leftnormline_pt.subparamtoparam(self, param) class _leftnormcurve_pt(normcurve_pt): __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt", "x2_pt", "y2_pt", "x3_pt", "y3_pt" def subparamtoparam(self, param): return 0.5*param class _rightnormcurve_pt(normcurve_pt): __slots__ = "x0_pt", "y0_pt", "x1_pt", "y1_pt", "x2_pt", "y2_pt", "x3_pt", "y3_pt" def subparamtoparam(self, param): return 0.5+0.5*param ################################################################################ # normsubpath ################################################################################ class normsubpath: """sub path of a normalized path A subpath consists of a list of normsubpathitems, i.e., normlines_pt and normcurves_pt and can either be closed or not. Some invariants, which have to be obeyed: - All normsubpathitems have to be longer than epsilon pts. - At the end there may be a normline (stored in self.skippedline) whose length is shorter than epsilon -- it has to be taken into account when adding further normsubpathitems - The last point of a normsubpathitem and the first point of the next element have to be equal. - When the path is closed, the last point of last normsubpathitem has to be equal to the first point of the first normsubpathitem. - epsilon might be none, disallowing any numerics, but allowing for arbitrary short paths. This is used in pdf output, where all paths need to be transformed to normpaths. """ __slots__ = "normsubpathitems", "closed", "epsilon", "skippedline" def __init__(self, normsubpathitems=[], closed=0, epsilon=_marker): """construct a normsubpath""" if epsilon is _marker: epsilon = _epsilon self.epsilon = epsilon # If one or more items appended to the normsubpath have been # skipped (because their total length was shorter than epsilon), # we remember this fact by a line because we have to take it # properly into account when appending further normsubpathitems self.skippedline = None self.normsubpathitems = [] self.closed = 0 # a test (might be temporary) for anormsubpathitem in normsubpathitems: assert isinstance(anormsubpathitem, normsubpathitem), "only list of normsubpathitem instances allowed" self.extend(normsubpathitems) if closed: self.close() def __getitem__(self, i): """return normsubpathitem i""" return self.normsubpathitems[i] def __len__(self): """return number of normsubpathitems""" return len(self.normsubpathitems) def __str__(self): l = ", ".join(map(str, self.normsubpathitems)) if self.closed: return "normsubpath([%s], closed=1)" % l else: return "normsubpath([%s])" % l def _distributeparams(self, params): """return a dictionary mapping normsubpathitemindices to a tuple of a paramindices and normsubpathitemparams. normsubpathitemindex specifies a normsubpathitem containing one or several positions. paramindex specify the index of the param in the original list and normsubpathitemparam is the parameter value in the normsubpathitem. """ result = {} for i, param in enumerate(params): if param > 0: index = int(param) if index > len(self.normsubpathitems) - 1: index = len(self.normsubpathitems) - 1 else: index = 0 result.setdefault(index, ([], [])) result[index][0].append(i) result[index][1].append(param - index) return result def append(self, anormsubpathitem): """append normsubpathitem Fails on closed normsubpath. """ if self.epsilon is None: self.normsubpathitems.append(anormsubpathitem) else: # consitency tests (might be temporary) assert isinstance(anormsubpathitem, normsubpathitem), "only normsubpathitem instances allowed" if self.skippedline: assert math.hypot(*[x-y for x, y in zip(self.skippedline.atend_pt(), anormsubpathitem.atbegin_pt())]) < self.epsilon, "normsubpathitems do not match" elif self.normsubpathitems: assert math.hypot(*[x-y for x, y in zip(self.normsubpathitems[-1].atend_pt(), anormsubpathitem.atbegin_pt())]) < self.epsilon, "normsubpathitems do not match" if self.closed: raise NormpathException("Cannot append to closed normsubpath") if self.skippedline: anormsubpathitem = anormsubpathitem.modifiedbegin_pt(*self.skippedline.atbegin_pt()) self.skippedline = None if isinstance(anormsubpathitem, normline_pt): if math.hypot(anormsubpathitem.x1_pt-anormsubpathitem.x0_pt, anormsubpathitem.y1_pt-anormsubpathitem.y0_pt) >= self.epsilon: self.normsubpathitems.append(anormsubpathitem) else: self.skippedline = anormsubpathitem else: # it is a normcurve_pt x0_pt = anormsubpathitem.x0_pt y0_pt = anormsubpathitem.y0_pt x1_pt = anormsubpathitem.x1_pt y1_pt = anormsubpathitem.y1_pt x2_pt = anormsubpathitem.x2_pt y2_pt = anormsubpathitem.y2_pt x3_pt = anormsubpathitem.x3_pt y3_pt = anormsubpathitem.y3_pt l03_pt = math.hypot(x3_pt-x0_pt, y3_pt-y0_pt) l01_pt = math.hypot(x1_pt-x0_pt, y1_pt-y0_pt) l02_pt = math.hypot(x2_pt-x0_pt, y2_pt-y0_pt) l23_pt = math.hypot(x2_pt-x3_pt, y2_pt-y3_pt) l13_pt = math.hypot(x1_pt-x3_pt, y1_pt-y3_pt) if l03_pt >= self.epsilon or ( (l01_pt*3 >= self.epsilon or l02_pt*3 >= self.epsilon) and (l23_pt*3 >= self.epsilon or l13_pt*3 >= self.epsilon) ): # We first may shift (x1_pt, y1_pt) and (x2_pt, y2_pt) to # have minimal derivates at the beginning and end point. # keep a copy of (x1_pt, y1_pt) for shifting (x2_pt, y2_pt) x1o_pt = x1_pt y1o_pt = y1_pt # When repositioning the control points, use a factor 2.9 # instead of 3 to get a derivative above the threshold as # otherwise deep recursions can occur. if l01_pt*3 < self.epsilon: if l02_pt*3 >= self.epsilon: x1_pt = x0_pt + (x2_pt-x0_pt)*self.epsilon/l02_pt/2.9 y1_pt = y0_pt + (y2_pt-y0_pt)*self.epsilon/l02_pt/2.9 else: x1_pt = x0_pt + (x3_pt-x0_pt)*self.epsilon/l03_pt/2.9 y1_pt = y0_pt + (y3_pt-y0_pt)*self.epsilon/l03_pt/2.9 if l23_pt*3 < self.epsilon: if l13_pt*3 >= self.epsilon: x2_pt = x3_pt + (x1o_pt-x3_pt)*self.epsilon/l13_pt/2.9 y2_pt = y3_pt + (y1o_pt-y3_pt)*self.epsilon/l13_pt/2.9 else: x2_pt = x3_pt + (x0_pt-x3_pt)*self.epsilon/l03_pt/2.9 y2_pt = y3_pt + (y0_pt-y3_pt)*self.epsilon/l03_pt/2.9 newitems = [normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt)] # find extrema of the derivative ax = x3_pt - 3*x2_pt + 3*x1_pt - x0_pt bx = 2*x0_pt - 4*x1_pt + 2*x2_pt cx = x1_pt - x0_pt ay = y3_pt - 3*y2_pt + 3*y1_pt - y0_pt by = 2*y0_pt - 4*y1_pt + 2*y2_pt cy = y1_pt - y0_pt roots = mathutils.realpolyroots(4*ax*ax + 4*ay*ay, 6*ax*bx + 6*ay*by, 4*ax*cx + 4*ay*cy + 2*bx*bx + 2*by*by, 2*bx*cx + 2*by*cy) # split at points of too small derivative splitpoints = [t for t in roots if 0 < t < 1 and 9*((ax*t*t+bx*t+cx)**2+(ay*t*t+by*t+cy)**2) < self.epsilon*self.epsilon] if not splitpoints: self.normsubpathitems.extend(newitems) else: splitpoints.sort() for i, splitpoint in enumerate(splitpoints): if i: # take splitpoint relative to the subcurve splitpoint = (splitpoint-splitpoints[i-1])/(1-splitpoints[i-1]) newitems.extend(newitems.pop()._split(splitpoint)) # Replace short curves by lines. Otherwise skippedline # could shake up the short curve completely. for i in range(len(newitems)): l01_pt = math.hypot(newitems[i].x1_pt-newitems[i].x0_pt, newitems[i].y1_pt-newitems[i].y0_pt) l12_pt = math.hypot(newitems[i].x2_pt-newitems[i].x1_pt, newitems[i].y2_pt-newitems[i].y1_pt) l23_pt = math.hypot(newitems[i].x3_pt-newitems[i].x2_pt, newitems[i].y3_pt-newitems[i].y2_pt) if l01_pt+l12_pt+l23_pt < self.epsilon: newitems[i] = normline_pt(newitems[i].x0_pt, newitems[i].y0_pt, newitems[i].x3_pt, newitems[i].y3_pt) self.extend(newitems) else: self.skippedline = normline_pt(anormsubpathitem.x0_pt, anormsubpathitem.y0_pt, anormsubpathitem.x3_pt, anormsubpathitem.y3_pt) def arclen_pt(self, upper=False): """return arc length in pts When upper is set, the upper bound is calculated, otherwise the lower bound is returned.""" return sum([npitem.arclen_pt(self.epsilon, upper=upper) for npitem in self.normsubpathitems]) def _arclentoparam_pt(self, lengths_pt): """return a tuple of params and the total length arc length in pts""" # work on a copy which is counted down to negative values lengths_pt = lengths_pt[:] results = [None] * len(lengths_pt) totalarclen = 0 for normsubpathindex, normsubpathitem in enumerate(self.normsubpathitems): params, arclen = normsubpathitem._arclentoparam_pt(lengths_pt, self.epsilon) for i in range(len(results)): if results[i] is None: lengths_pt[i] -= arclen if lengths_pt[i] < 0 or normsubpathindex == len(self.normsubpathitems) - 1: # overwrite the results until the length has become negative results[i] = normsubpathindex + params[i] totalarclen += arclen return results, totalarclen def arclentoparam_pt(self, lengths_pt): """return a tuple of params""" return self._arclentoparam_pt(lengths_pt)[0] def at_pt(self, params): """return coordinates at params in pts""" if not self.normsubpathitems and self.skippedline: return [self.skippedline.atbegin_pt()]*len(params) result = [None] * len(params) for normsubpathitemindex, (indices, params) in list(self._distributeparams(params).items()): for index, point_pt in zip(indices, self.normsubpathitems[normsubpathitemindex].at_pt(params)): result[index] = point_pt return result def atbegin_pt(self): """return coordinates of first point in pts""" if not self.normsubpathitems and self.skippedline: return self.skippedline.atbegin_pt() return self.normsubpathitems[0].atbegin_pt() def atend_pt(self): """return coordinates of last point in pts""" if self.skippedline: return self.skippedline.atend_pt() return self.normsubpathitems[-1].atend_pt() def bbox(self): """return bounding box of normsubpath""" if self.normsubpathitems: abbox = self.normsubpathitems[0].bbox() for anormpathitem in self.normsubpathitems[1:]: abbox += anormpathitem.bbox() return abbox else: return bboxmodule.empty() def close(self): """close subnormpath Fails on closed normsubpath. """ if self.closed: raise NormpathException("Cannot close already closed normsubpath") if not self.normsubpathitems: if self.skippedline is None: raise NormpathException("Cannot close empty normsubpath") else: raise NormpathException("Normsubpath too short, cannot be closed") xs_pt, ys_pt = self.normsubpathitems[-1].atend_pt() xe_pt, ye_pt = self.normsubpathitems[0].atbegin_pt() self.append(normline_pt(xs_pt, ys_pt, xe_pt, ye_pt)) self.flushskippedline() self.closed = 1 def copy(self): """return copy of normsubpath""" # Since normsubpathitems are never modified inplace, we just # need to copy the normsubpathitems list. We do not pass the # normsubpathitems to the constructor to not repeat the checks # for minimal length of each normsubpathitem. result = normsubpath(epsilon=self.epsilon) result.normsubpathitems = self.normsubpathitems[:] result.closed = self.closed # We can share the reference to skippedline, since it is a # normsubpathitem as well and thus not modified in place either. result.skippedline = self.skippedline return result def curvature_pt(self, params): """return the curvature at params in 1/pts""" result = [None] * len(params) for normsubpathitemindex, (indices, params) in list(self._distributeparams(params).items()): for index, curvature_pt in zip(indices, self.normsubpathitems[normsubpathitemindex].curvature_pt(params)): result[index] = curvature_pt return result def extend(self, normsubpathitems): """extend path by normsubpathitems Fails on closed normsubpath. """ for normsubpathitem in normsubpathitems: self.append(normsubpathitem) def flushskippedline(self): """flush the skippedline, i.e. apply it to the normsubpath remove the skippedline by modifying the end point of the existing normsubpath """ while self.skippedline: try: lastnormsubpathitem = self.normsubpathitems.pop() except IndexError: raise ValueError("normsubpath too short to flush the skippedline") lastnormsubpathitem = lastnormsubpathitem.modifiedend_pt(*self.skippedline.atend_pt()) self.skippedline = None self.append(lastnormsubpathitem) def intersect(self, other): """intersect self with other normsubpath Returns a tuple of lists consisting of the parameter values of the intersection points of the corresponding normsubpath. """ intersections_a = [] intersections_b = [] epsilon = min(self.epsilon, other.epsilon) # Intersect all subpaths of self with the subpaths of other, possibly including # one intersection point several times for t_a, pitem_a in enumerate(self.normsubpathitems): for t_b, pitem_b in enumerate(other.normsubpathitems): for intersection_a, intersection_b in pitem_a.intersect(pitem_b, epsilon): intersections_a.append(intersection_a + t_a) intersections_b.append(intersection_b + t_b) # although intersectipns_a are sorted for the different normsubpathitems, # within a normsubpathitem, the ordering has to be ensured separately: intersections = list(zip(intersections_a, intersections_b)) intersections.sort() intersections_a = [a for a, b in intersections] intersections_b = [b for a, b in intersections] # for symmetry reasons we enumerate intersections_a as well, although # they are already sorted (note we do not need to sort intersections_a) intersections_a = list(zip(intersections_a, list(range(len(intersections_a))))) intersections_b = list(zip(intersections_b, list(range(len(intersections_b))))) intersections_b.sort() # now we search for intersections points which are closer together than epsilon # This task is handled by the following function def closepoints(normsubpath, intersections): split = normsubpath.segments([0] + [intersection for intersection, index in intersections] + [len(normsubpath)]) result = [] if normsubpath.closed: # note that the number of segments of a closed path is off by one # compared to an open path i = 0 while i < len(split): splitnormsubpath = split[i] j = i while not splitnormsubpath.normsubpathitems: # i.e. while "is short" ip1, ip2 = intersections[i-1][1], intersections[j][1] if ip1 0: index = int(param) if index > len(self.normsubpathitems) - 1: index = len(self.normsubpathitems) - 1 param -= index else: index = 0 if index != collectindex: if collectindex is not None: # append end point depening on the forthcoming index if index > collectindex: collectparams.append(1) else: collectparams.append(0) # get segments of the normsubpathitem and add them to the result segments = self.normsubpathitems[collectindex].segments(collectparams) result[-1].append(segments[0]) result.extend([normsubpath([segment], epsilon=self.epsilon) for segment in segments[1:]]) # add normsubpathitems and first segment parameter to close the # gap to the forthcoming index if index > collectindex: for i in range(collectindex+1, index): result[-1].append(self.normsubpathitems[i]) collectparams = [0] else: for i in range(collectindex-1, index, -1): result[-1].append(self.normsubpathitems[i].reversed()) collectparams = [1] collectindex = index collectparams.append(param) # add remaining collectparams to the result segments = self.normsubpathitems[collectindex].segments(collectparams) result[-1].append(segments[0]) result.extend([normsubpath([segment], epsilon=self.epsilon) for segment in segments[1:]]) if self.closed: # join last and first segment together if the normsubpath was # originally closed and first and the last parameters are the # beginning and end points of the normsubpath if ( ( params[0] == 0 and params[-1] == len(self.normsubpathitems) ) or ( params[-1] == 0 and params[0] == len(self.normsubpathitems) ) ): result[-1].normsubpathitems.extend(result[0].normsubpathitems) result = result[-1:] + result[1:-1] return result def trafo(self, params): """return transformations at params""" result = [None] * len(params) for normsubpathitemindex, (indices, params) in list(self._distributeparams(params).items()): for index, trafo in zip(indices, self.normsubpathitems[normsubpathitemindex].trafo(params)): result[index] = trafo return result def transformed(self, trafo): """return transformed path""" nnormsubpath = normsubpath(epsilon=self.epsilon) for pitem in self.normsubpathitems: nnormsubpath.append(pitem.transformed(trafo)) if self.closed: nnormsubpath.close() elif self.skippedline is not None: nnormsubpath.append(self.skippedline.transformed(trafo)) return nnormsubpath def outputPS(self, file, writer): # if the normsubpath is closed, we must not output a normline at # the end if not self.normsubpathitems: return if self.closed and isinstance(self.normsubpathitems[-1], normline_pt): assert len(self.normsubpathitems) > 1, "a closed normsubpath should contain more than a single normline_pt" normsubpathitems = self.normsubpathitems[:-1] else: normsubpathitems = self.normsubpathitems file.write("%g %g moveto\n" % self.atbegin_pt()) for anormsubpathitem in normsubpathitems: anormsubpathitem.outputPS(file, writer) if self.closed: file.write("closepath\n") def outputPDF(self, file, writer): # if the normsubpath is closed, we must not output a normline at # the end if not self.normsubpathitems: return if self.closed and isinstance(self.normsubpathitems[-1], normline_pt): assert len(self.normsubpathitems) > 1, "a closed normsubpath should contain more than a single normline_pt" normsubpathitems = self.normsubpathitems[:-1] else: normsubpathitems = self.normsubpathitems file.write("%f %f m\n" % self.atbegin_pt()) for anormsubpathitem in normsubpathitems: anormsubpathitem.outputPDF(file, writer) if self.closed: file.write("h\n") def returnSVGdata(self, inverse_y): # if the normsubpath is closed, we must not output a normline at # the end if not self.normsubpathitems: return "" if self.closed and isinstance(self.normsubpathitems[-1], normline_pt): assert len(self.normsubpathitems) > 1, "a closed normsubpath should contain more than a single normline_pt" normsubpathitems = self.normsubpathitems[:-1] else: normsubpathitems = self.normsubpathitems x_pt, y_pt = self.atbegin_pt() if inverse_y: y_pt = -y_pt data = ["M%g %g" % (x_pt, y_pt)] for anormsubpathitem in normsubpathitems: data.append(anormsubpathitem.returnSVGdata(inverse_y)) if self.closed: data.append("Z") return "".join(data) ################################################################################ # normpath ################################################################################ @functools.total_ordering class normpathparam: """parameter of a certain point along a normpath""" __slots__ = "normpath", "normsubpathindex", "normsubpathparam" def __init__(self, normpath, normsubpathindex, normsubpathparam): self.normpath = normpath self.normsubpathindex = normsubpathindex self.normsubpathparam = normsubpathparam def __str__(self): return "normpathparam(%s, %s, %s)" % (self.normpath, self.normsubpathindex, self.normsubpathparam) def __add__(self, other): if isinstance(other, normpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) + other.normpath.paramtoarclen_pt(other)) else: return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) + unit.topt(other)) __radd__ = __add__ def __sub__(self, other): if isinstance(other, normpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) - other.normpath.paramtoarclen_pt(other)) else: return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) - unit.topt(other)) def __rsub__(self, other): # other has to be a length in this case return self.normpath.arclentoparam_pt(-self.normpath.paramtoarclen_pt(self) + unit.topt(other)) def __mul__(self, factor): return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) * factor) __rmul__ = __mul__ def __div__(self, divisor): return self.normpath.arclentoparam_pt(self.normpath.paramtoarclen_pt(self) / divisor) def __neg__(self): return self.normpath.arclentoparam_pt(-self.normpath.paramtoarclen_pt(self)) def __eq__(self, other): if isinstance(other, normpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return (self.normsubpathindex, self.normsubpathparam) == (other.normsubpathindex, other.normsubpathparam) else: return self.normpath.paramtoarclen_pt(self) == unit.topt(other) def __lt__(self, other): if isinstance(other, normpathparam): assert self.normpath is other.normpath, "normpathparams have to belong to the same normpath" return (self.normsubpathindex, self.normsubpathparam) < (other.normsubpathindex, other.normsubpathparam) else: return self.normpath.paramtoarclen_pt(self) < unit.topt(other) def arclen_pt(self): """return arc length in pts corresponding to the normpathparam """ return self.normpath.paramtoarclen_pt(self) def arclen(self): """return arc length corresponding to the normpathparam """ return self.normpath.paramtoarclen(self) def _valueorlistmethod(method): """Creates a method which takes a single argument or a list and returns a single value or a list out of method, which always works on lists.""" @functools.wraps(method) def wrappedmethod(self, valueorlist, *args, **kwargs): try: for item in valueorlist: break except: return method(self, [valueorlist], *args, **kwargs)[0] return method(self, valueorlist, *args, **kwargs) return wrappedmethod class normpath: """normalized path A normalized path consists of a list of normsubpaths. """ def __init__(self, normsubpaths=None): """construct a normpath from a list of normsubpaths""" if normsubpaths is None: self.normsubpaths = [] # make a fresh list else: self.normsubpaths = normsubpaths for subpath in normsubpaths: assert isinstance(subpath, normsubpath), "only list of normsubpath instances allowed" def __add__(self, other): """create new normpath out of self and other""" result = self.copy() result += other return result def __iadd__(self, other): """add other inplace""" for normsubpath in other.normpath().normsubpaths: self.normsubpaths.append(normsubpath.copy()) return self def __getitem__(self, i): """return normsubpath i""" return self.normsubpaths[i] def __len__(self): """return the number of normsubpaths""" return len(self.normsubpaths) def __str__(self): return "normpath([%s])" % ", ".join(map(str, self.normsubpaths)) def _convertparams(self, params, convertmethod): """return params with all non-normpathparam arguments converted by convertmethod usecases: - self._convertparams(params, self.arclentoparam_pt) - self._convertparams(params, self.arclentoparam) """ converttoparams = [] convertparamindices = [] for i, param in enumerate(params): if not isinstance(param, normpathparam): converttoparams.append(param) convertparamindices.append(i) if converttoparams: params = params[:] for i, param in zip(convertparamindices, convertmethod(converttoparams)): params[i] = param return params def _distributeparams(self, params): """return a dictionary mapping subpathindices to a tuple of a paramindices and subpathparams subpathindex specifies a subpath containing one or several positions. paramindex specify the index of the normpathparam in the original list and subpathparam is the parameter value in the subpath. """ result = {} for i, param in enumerate(params): assert param.normpath is self, "normpathparam has to belong to this path" result.setdefault(param.normsubpathindex, ([], [])) result[param.normsubpathindex][0].append(i) result[param.normsubpathindex][1].append(param.normsubpathparam) return result def append(self, item): """append a normpath by a normsubpath or a pathitem""" from . import path if isinstance(item, normsubpath): # the normsubpaths list can be appended by a normsubpath only self.normsubpaths.append(item) elif isinstance(item, path.pathitem): # ... but we are kind and allow for regular path items as well # in order to make a normpath to behave more like a regular path if self.normsubpaths: context = path.context(*(self.normsubpaths[-1].atend_pt() + self.normsubpaths[-1].atbegin_pt())) item.updatenormpath(self, context) else: self.normsubpaths = item.createnormpath(self).normsubpaths def arclen_pt(self, upper=False): """return arc length in pts When upper is set, the upper bound is calculated, otherwise the lower bound is returned.""" return sum([normsubpath.arclen_pt(upper=upper) for normsubpath in self.normsubpaths]) def arclen(self, upper=False): """return arc length When upper is set, the upper bound is calculated, otherwise the lower bound is returned.""" return self.arclen_pt(upper=upper) * unit.t_pt def _arclentoparam_pt(self, lengths_pt): """return the params matching the given lengths_pt""" # work on a copy which is counted down to negative values lengths_pt = lengths_pt[:] results = [None] * len(lengths_pt) for normsubpathindex, normsubpath in enumerate(self.normsubpaths): params, arclen = normsubpath._arclentoparam_pt(lengths_pt) done = 1 for i, result in enumerate(results): if results[i] is None: lengths_pt[i] -= arclen if lengths_pt[i] < 0 or normsubpathindex == len(self.normsubpaths) - 1: # overwrite the results until the length has become negative results[i] = normpathparam(self, normsubpathindex, params[i]) done = 0 if done: break return results arclentoparam_pt = _valueorlistmethod(_arclentoparam_pt) @_valueorlistmethod def arclentoparam(self, lengths): """return the param(s) matching the given length(s)""" return self._arclentoparam_pt([unit.topt(l) for l in lengths]) def _at_pt(self, params): """return coordinates of normpath in pts at params""" result = [None] * len(params) for normsubpathindex, (indices, params) in list(self._distributeparams(params).items()): for index, point_pt in zip(indices, self.normsubpaths[normsubpathindex].at_pt(params)): result[index] = point_pt return result @_valueorlistmethod def at_pt(self, params): """return coordinates of normpath in pts at param(s) or lengths in pts""" return self._at_pt(self._convertparams(params, self.arclentoparam_pt)) @_valueorlistmethod def at(self, params): """return coordinates of normpath at param(s) or arc lengths""" return [(x_pt * unit.t_pt, y_pt * unit.t_pt) for x_pt, y_pt in self._at_pt(self._convertparams(params, self.arclentoparam))] def atbegin_pt(self): """return coordinates of the beginning of first subpath in normpath in pts""" if self.normsubpaths: return self.normsubpaths[0].atbegin_pt() else: raise NormpathException("cannot return first point of empty path") def atbegin(self): """return coordinates of the beginning of first subpath in normpath""" x, y = self.atbegin_pt() return x * unit.t_pt, y * unit.t_pt def atend_pt(self): """return coordinates of the end of last subpath in normpath in pts""" if self.normsubpaths: return self.normsubpaths[-1].atend_pt() else: raise NormpathException("cannot return last point of empty path") def atend(self): """return coordinates of the end of last subpath in normpath""" x, y = self.atend_pt() return x * unit.t_pt, y * unit.t_pt def bbox(self): """return bbox of normpath""" abbox = bboxmodule.empty() for normsubpath in self.normsubpaths: abbox += normsubpath.bbox() return abbox def begin(self): """return param corresponding of the beginning of the normpath""" if self.normsubpaths: return normpathparam(self, 0, 0) else: raise NormpathException("empty path") def copy(self): """return copy of normpath""" result = normpath() for normsubpath in self.normsubpaths: result.append(normsubpath.copy()) return result @_valueorlistmethod def curvature_pt(self, params): """return the curvature in 1/pt at params or arc length(s) in pts""" result = [None] * len(params) for normsubpathindex, (indices, params) in list(self._distributeparams(self._convertparams(params, self.arclentoparam_pt)).items()): for index, curvature_pt in zip(indices, self.normsubpaths[normsubpathindex].curvature_pt(params)): result[index] = curvature_pt return result def end(self): """return param corresponding of the end of the path""" if self.normsubpaths: return normpathparam(self, len(self)-1, len(self.normsubpaths[-1])) else: raise NormpathException("empty path") def extend(self, normsubpaths): """extend path by normsubpaths or pathitems""" for anormsubpath in normsubpaths: # use append to properly handle regular path items as well as normsubpaths self.append(anormsubpath) def intersect(self, other): """intersect self with other path Returns a tuple of lists consisting of the parameter values of the intersection points of the corresponding normpath. """ other = other.normpath() # here we build up the result intersections = ([], []) # Intersect all normsubpaths of self with the normsubpaths of # other. for ia, normsubpath_a in enumerate(self.normsubpaths): for ib, normsubpath_b in enumerate(other.normsubpaths): for intersection in zip(*normsubpath_a.intersect(normsubpath_b)): intersections[0].append(normpathparam(self, ia, intersection[0])) intersections[1].append(normpathparam(other, ib, intersection[1])) return intersections def join(self, other): """join other normsubpath inplace Both normpaths must contain at least one normsubpath. The last normsubpath of self will be joined to the first normsubpath of other. """ other = other.normpath() if not self.normsubpaths: raise NormpathException("cannot join to empty path") if not other.normsubpaths: raise NormpathException("cannot join empty path") self.normsubpaths[-1].join(other.normsubpaths[0]) self.normsubpaths.extend(other.normsubpaths[1:]) def joined(self, other): """return joined self and other Both normpaths must contain at least one normsubpath. The last normsubpath of self will be joined to the first normsubpath of other. """ result = self.copy() result.join(other.normpath()) return result # << operator also designates joining __lshift__ = joined def normpath(self): """return a normpath, i.e. self""" return self def _paramtoarclen_pt(self, params): """return arc lengths in pts matching the given params""" result = [None] * len(params) totalarclen_pt = 0 distributeparams = self._distributeparams(params) for normsubpathindex in range(max(distributeparams.keys()) + 1): if normsubpathindex in distributeparams: indices, params = distributeparams[normsubpathindex] arclens_pt, normsubpatharclen_pt = self.normsubpaths[normsubpathindex]._paramtoarclen_pt(params) for index, arclen_pt in zip(indices, arclens_pt): result[index] = totalarclen_pt + arclen_pt totalarclen_pt += normsubpatharclen_pt else: totalarclen_pt += self.normsubpaths[normsubpathindex].arclen_pt() return result paramtoarclen_pt = _valueorlistmethod(_paramtoarclen_pt) @_valueorlistmethod def paramtoarclen(self, params): """return arc length(s) matching the given param(s)""" return [arclen_pt * unit.t_pt for arclen_pt in self._paramtoarclen_pt(params)] def path(self): """return path corresponding to normpath""" from . import path pathitems = [] for normsubpath in self.normsubpaths: pathitems.extend(normsubpath.pathitems()) return path.path(*pathitems) def reversed(self): """return reversed path""" nnormpath = normpath() for i in range(len(self.normsubpaths)): nnormpath.normsubpaths.append(self.normsubpaths[-(i+1)].reversed()) return nnormpath def _rotation(self, params): """return rotation at params""" result = [None] * len(params) for normsubpathindex, (indices, params) in list(self._distributeparams(params).items()): for index, rotation in zip(indices, self.normsubpaths[normsubpathindex].rotation(params)): result[index] = rotation return result @_valueorlistmethod def rotation_pt(self, params): """return rotation at param(s) or arc length(s) in pts""" return self._rotation(self._convertparams(params, self.arclentoparam_pt)) @_valueorlistmethod def rotation(self, params): """return rotation at param(s) or arc length(s)""" return self._rotation(self._convertparams(params, self.arclentoparam)) def _split_pt(self, params): """split path at params and return list of normpaths""" if not params: return [self.copy()] # instead of distributing the parameters, we need to keep their # order and collect parameters for splitting of normsubpathitem # with index collectindex collectindex = None for param in params: if param.normsubpathindex != collectindex: if collectindex is not None: # append end point depening on the forthcoming index if param.normsubpathindex > collectindex: collectparams.append(len(self.normsubpaths[collectindex])) else: collectparams.append(0) # get segments of the normsubpath and add them to the result segments = self.normsubpaths[collectindex].segments(collectparams) result[-1].append(segments[0]) result.extend([normpath([segment]) for segment in segments[1:]]) # add normsubpathitems and first segment parameter to close the # gap to the forthcoming index if param.normsubpathindex > collectindex: for i in range(collectindex+1, param.normsubpathindex): result[-1].append(self.normsubpaths[i]) collectparams = [0] else: for i in range(collectindex-1, param.normsubpathindex, -1): result[-1].append(self.normsubpaths[i].reversed()) collectparams = [len(self.normsubpaths[param.normsubpathindex])] else: result = [normpath(self.normsubpaths[:param.normsubpathindex])] collectparams = [0] collectindex = param.normsubpathindex collectparams.append(param.normsubpathparam) # add remaining collectparams to the result collectparams.append(len(self.normsubpaths[collectindex])) segments = self.normsubpaths[collectindex].segments(collectparams) result[-1].append(segments[0]) result.extend([normpath([segment]) for segment in segments[1:]]) result[-1].extend(self.normsubpaths[collectindex+1:]) return result def split_pt(self, params): """split path at param(s) or arc length(s) in pts and return list of normpaths""" try: for param in params: break except: params = [params] return self._split_pt(self._convertparams(params, self.arclentoparam_pt)) def split(self, params): """split path at param(s) or arc length(s) and return list of normpaths""" try: for param in params: break except: params = [params] return self._split_pt(self._convertparams(params, self.arclentoparam)) def _tangent(self, params, length_pt): """return tangent vector of path at params If length_pt in pts is not None, the tangent vector will be scaled to the desired length. """ from . import path result = [None] * len(params) tangenttemplate = path.line_pt(0, 0, length_pt, 0).normpath() for normsubpathindex, (indices, params) in list(self._distributeparams(params).items()): for index, atrafo in zip(indices, self.normsubpaths[normsubpathindex].trafo(params)): result[index] = tangenttemplate.transformed(atrafo) return result @_valueorlistmethod def tangent_pt(self, params, length_pt): """return tangent vector of path at param(s) or arc length(s) in pts If length in pts is not None, the tangent vector will be scaled to the desired length. """ return self._tangent(self._convertparams(params, self.arclentoparam_pt), length_pt) @_valueorlistmethod def tangent(self, params, length=1): """return tangent vector of path at param(s) or arc length(s) If length is not None, the tangent vector will be scaled to the desired length. """ return self._tangent(self._convertparams(params, self.arclentoparam), unit.topt(length)) def _trafo(self, params): """return transformation at params""" result = [None] * len(params) for normsubpathindex, (indices, params) in list(self._distributeparams(params).items()): for index, trafo in zip(indices, self.normsubpaths[normsubpathindex].trafo(params)): result[index] = trafo return result @_valueorlistmethod def trafo_pt(self, params): """return transformation at param(s) or arc length(s) in pts""" return self._trafo(self._convertparams(params, self.arclentoparam_pt)) @_valueorlistmethod def trafo(self, params): """return transformation at param(s) or arc length(s)""" return self._trafo(self._convertparams(params, self.arclentoparam)) def transformed(self, trafo): """return transformed normpath""" return normpath([normsubpath.transformed(trafo) for normsubpath in self.normsubpaths]) def outputPS(self, file, writer): for normsubpath in self.normsubpaths: normsubpath.outputPS(file, writer) def outputPDF(self, file, writer): for normsubpath in self.normsubpaths: normsubpath.outputPDF(file, writer) def returnSVGdata(self, inverse_y=True): return "".join(normsubpath.returnSVGdata(inverse_y) for normsubpath in self.normsubpaths) PyX-0.14.1/pyx/path.py0000644000076500000240000014454012605473420014672 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2003-2005 Michael Schindler # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from math import cos, sin, tan, acos, pi, radians, degrees from . import trafo, unit from .normpath import NormpathException, normpath, normsubpath, normline_pt, normcurve_pt from . import bbox as bboxmodule # set is available as an external interface to the normpath.set method from .normpath import set class _marker: pass ################################################################################ # specific exception for path-related problems class PathException(Exception): pass ################################################################################ # Bezier helper functions ################################################################################ def _bezierpolyrange(x0, x1, x2, x3): tc = [0, 1] a = x3 - 3*x2 + 3*x1 - x0 b = 2*x0 - 4*x1 + 2*x2 c = x1 - x0 s = b*b - 4*a*c if s >= 0: if b >= 0: q = -0.5*(b+math.sqrt(s)) else: q = -0.5*(b-math.sqrt(s)) try: t = q*1.0/a except ZeroDivisionError: pass else: if 0 < t < 1: tc.append(t) try: t = c*1.0/q except ZeroDivisionError: pass else: if 0 < t < 1: tc.append(t) p = [(((a*t + 1.5*b)*t + 3*c)*t + x0) for t in tc] return min(*p), max(*p) def _arctobcurve(x_pt, y_pt, r_pt, phi1, phi2): """generate the best bezier curve corresponding to an arc segment""" dphi = phi2-phi1 if dphi==0: return None # the two endpoints should be clear x0_pt, y0_pt = x_pt+r_pt*cos(phi1), y_pt+r_pt*sin(phi1) x3_pt, y3_pt = x_pt+r_pt*cos(phi2), y_pt+r_pt*sin(phi2) # optimal relative distance along tangent for second and third # control point l = r_pt*4*(1-cos(dphi/2))/(3*sin(dphi/2)) x1_pt, y1_pt = x0_pt-l*sin(phi1), y0_pt+l*cos(phi1) x2_pt, y2_pt = x3_pt+l*sin(phi2), y3_pt-l*cos(phi2) return normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt) def _arctobezierpath(x_pt, y_pt, r_pt, phi1, phi2, dphimax=45): apath = [] phi1 = radians(phi1) phi2 = radians(phi2) dphimax = radians(dphimax) if phi2phi1 ... phi2 = phi2 + (math.floor((phi1-phi2)/(2*pi))+1)*2*pi elif phi2>phi1+2*pi: # ... or remove unnecessary multiples of 2*pi phi2 = phi2 - (math.floor((phi2-phi1)/(2*pi))-1)*2*pi if r_pt == 0 or phi1-phi2 == 0: return [] subdivisions = int((phi2-phi1)/dphimax)+1 dphi = (phi2-phi1)/subdivisions for i in range(subdivisions): apath.append(_arctobcurve(x_pt, y_pt, r_pt, phi1+i*dphi, phi1+(i+1)*dphi)) return apath def _arcpoint(x_pt, y_pt, r_pt, angle): """return starting point of arc segment""" return x_pt+r_pt*cos(radians(angle)), y_pt+r_pt*sin(radians(angle)) def _arcbboxdata(x_pt, y_pt, r_pt, angle1, angle2): phi1 = radians(angle1) phi2 = radians(angle2) # starting end end point of arc segment sarcx_pt, sarcy_pt = _arcpoint(x_pt, y_pt, r_pt, angle1) earcx_pt, earcy_pt = _arcpoint(x_pt, y_pt, r_pt, angle2) # Now, we have to determine the corners of the bbox for the # arc segment, i.e. global maxima/mimima of cos(phi) and sin(phi) # in the interval [phi1, phi2]. These can either be located # on the borders of this interval or in the interior. if phi2 < phi1: # guarantee that phi2>phi1 phi2 = phi2 + (math.floor((phi1-phi2)/(2*pi))+1)*2*pi # next minimum of cos(phi) looking from phi1 in counterclockwise # direction: 2*pi*floor((phi1-pi)/(2*pi)) + 3*pi if phi2 < (2*math.floor((phi1-pi)/(2*pi))+3)*pi: minarcx_pt = min(sarcx_pt, earcx_pt) else: minarcx_pt = x_pt-r_pt # next minimum of sin(phi) looking from phi1 in counterclockwise # direction: 2*pi*floor((phi1-3*pi/2)/(2*pi)) + 7/2*pi if phi2 < (2*math.floor((phi1-3.0*pi/2)/(2*pi))+7.0/2)*pi: minarcy_pt = min(sarcy_pt, earcy_pt) else: minarcy_pt = y_pt-r_pt # next maximum of cos(phi) looking from phi1 in counterclockwise # direction: 2*pi*floor((phi1)/(2*pi))+2*pi if phi2 < (2*math.floor((phi1)/(2*pi))+2)*pi: maxarcx_pt = max(sarcx_pt, earcx_pt) else: maxarcx_pt = x_pt+r_pt # next maximum of sin(phi) looking from phi1 in counterclockwise # direction: 2*pi*floor((phi1-pi/2)/(2*pi)) + 1/2*pi if phi2 < (2*math.floor((phi1-pi/2)/(2*pi))+5.0/2)*pi: maxarcy_pt = max(sarcy_pt, earcy_pt) else: maxarcy_pt = y_pt+r_pt return minarcx_pt, minarcy_pt, maxarcx_pt, maxarcy_pt ################################################################################ # path context and pathitem base class ################################################################################ class context: """context for pathitem""" def __init__(self, x_pt, y_pt, subfirstx_pt, subfirsty_pt): """initializes a context for path items x_pt, y_pt are the currentpoint. subfirstx_pt, subfirsty_pt are the starting point of the current subpath. There are no invalid contexts, i.e. all variables need to be set to integer or float numbers. """ self.x_pt = x_pt self.y_pt = y_pt self.subfirstx_pt = subfirstx_pt self.subfirsty_pt = subfirsty_pt class pathitem: """element of a PS style path""" def __str__(self): raise NotImplementedError() def createcontext(self): """creates a context from the current pathitem Returns a context instance. Is called, when no context has yet been defined, i.e. for the very first pathitem. Most of the pathitems do not provide this method. Note, that you should pass the context created by createcontext to updatebbox and updatenormpath of successive pathitems only; use the context-free createbbox and createnormpath for the first pathitem instead. """ raise PathException("path must start with moveto or the like (%r)" % self) def createbbox(self): """creates a bbox from the current pathitem Returns a bbox instance. Is called, when a bbox has to be created instead of updating it, i.e. for the very first pathitem. Most pathitems do not provide this method. updatebbox must not be called for the created instance and the same pathitem. """ raise PathException("path must start with moveto or the like (%r)" % self) def createnormpath(self, epsilon=_marker): """create a normpath from the current pathitem Return a normpath instance. Is called, when a normpath has to be created instead of updating it, i.e. for the very first pathitem. Most pathitems do not provide this method. updatenormpath must not be called for the created instance and the same pathitem. """ raise PathException("path must start with moveto or the like (%r)" % self) def updatebbox(self, bbox, context): """updates the bbox to contain the pathitem for the given context Is called for all subsequent pathitems in a path to complete the bbox information. Both, the bbox and context are updated inplace. Does not return anything. """ raise NotImplementedError(self) def updatenormpath(self, normpath, context): """update the normpath to contain the pathitem for the given context Is called for all subsequent pathitems in a path to complete the normpath. Both the normpath and the context are updated inplace. Most pathitem implementations will use normpath.normsubpath[-1].append to add normsubpathitem(s). Does not return anything. """ raise NotImplementedError(self) def outputPS(self, file, writer): """write PS representation of pathitem to file""" raise NotImplementedError(self) def returnSVGdata(self, inverse_y, first, context): """return SVG representation of pathitem :param bool inverse_y: reverts y coordinate as SVG uses a different y direction, but when creating font paths no y inversion is needed. :param bool first: :class:`arc` and :class:`arcn` need to know whether it is first in the path to prepend a line or a move. Note that it can't tell from the context as it is not stored in the context whether it is first. :param context: :class:`arct` need the currentpoint and closepath needs the startingpoint of the last subpath to update the currentpoint :type context: :class:`context` :rtype: string """ raise NotImplementedError(self) ################################################################################ # various pathitems ################################################################################ # Each one comes in two variants: # - one with suffix _pt. This one requires the coordinates # to be already in pts (mainly used for internal purposes) # - another which accepts arbitrary units class closepath(pathitem): """Connect subpath back to its starting point""" __slots__ = () def __str__(self): return "closepath()" def updatebbox(self, bbox, context): context.x_pt = context.subfirstx_pt context.y_pt = context.subfirsty_pt def updatenormpath(self, normpath, context): normpath.normsubpaths[-1].close() context.x_pt = context.subfirstx_pt context.y_pt = context.subfirsty_pt def outputPS(self, file, writer): file.write("closepath\n") def returnSVGdata(self, inverse_y, first, context): return "Z" class pdfmoveto_pt(normline_pt): def outputPDF(self, file, writer): pass class moveto_pt(pathitem): """Start a new subpath and set current point to (x_pt, y_pt) (coordinates in pts)""" __slots__ = "x_pt", "y_pt" def __init__(self, x_pt, y_pt): self.x_pt = x_pt self.y_pt = y_pt def __str__(self): return "moveto_pt(%g, %g)" % (self.x_pt, self.y_pt) def createcontext(self): return context(self.x_pt, self.y_pt, self.x_pt, self.y_pt) def createbbox(self): return bboxmodule.bbox_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt) def createnormpath(self, epsilon=_marker): if epsilon is _marker: return normpath([normsubpath([normline_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt)])]) elif epsilon is None: return normpath([normsubpath([pdfmoveto_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt)], epsilon=epsilon)]) else: return normpath([normsubpath([normline_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt)], epsilon=epsilon)]) def updatebbox(self, bbox, context): bbox.includepoint_pt(self.x_pt, self.y_pt) context.x_pt = context.subfirstx_pt = self.x_pt context.y_pt = context.subfirsty_pt = self.y_pt def updatenormpath(self, normpath, context): if normpath.normsubpaths[-1].epsilon is not None: normpath.append(normsubpath([normline_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt)], epsilon=normpath.normsubpaths[-1].epsilon)) else: normpath.append(normsubpath(epsilon=normpath.normsubpaths[-1].epsilon)) context.x_pt = context.subfirstx_pt = self.x_pt context.y_pt = context.subfirsty_pt = self.y_pt def outputPS(self, file, writer): file.write("%g %g moveto\n" % (self.x_pt, self.y_pt) ) def returnSVGdata(self, inverse_y, first, context): context.x_pt = context.subfirstx_pt = self.x_pt context.y_pt = context.subfirsty_pt = self.y_pt if inverse_y: return "M%g %g" % (self.x_pt, -self.y_pt) return "M%g %g" % (self.x_pt, self.y_pt) class lineto_pt(pathitem): """Append straight line to (x_pt, y_pt) (coordinates in pts)""" __slots__ = "x_pt", "y_pt" def __init__(self, x_pt, y_pt): self.x_pt = x_pt self.y_pt = y_pt def __str__(self): return "lineto_pt(%g, %g)" % (self.x_pt, self.y_pt) def updatebbox(self, bbox, context): bbox.includepoint_pt(self.x_pt, self.y_pt) context.x_pt = self.x_pt context.y_pt = self.y_pt def updatenormpath(self, normpath, context): normpath.normsubpaths[-1].append(normline_pt(context.x_pt, context.y_pt, self.x_pt, self.y_pt)) context.x_pt = self.x_pt context.y_pt = self.y_pt def outputPS(self, file, writer): file.write("%g %g lineto\n" % (self.x_pt, self.y_pt) ) def returnSVGdata(self, inverse_y, first, context): context.x_pt = self.x_pt context.y_pt = self.y_pt if inverse_y: return "L%g %g" % (self.x_pt, -self.y_pt) return "L%g %g" % (self.x_pt, self.y_pt) class curveto_pt(pathitem): """Append curveto (coordinates in pts)""" __slots__ = "x1_pt", "y1_pt", "x2_pt", "y2_pt", "x3_pt", "y3_pt" def __init__(self, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt): self.x1_pt = x1_pt self.y1_pt = y1_pt self.x2_pt = x2_pt self.y2_pt = y2_pt self.x3_pt = x3_pt self.y3_pt = y3_pt def __str__(self): return "curveto_pt(%g, %g, %g, %g, %g, %g)" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) def updatebbox(self, bbox, context): xmin_pt, xmax_pt = _bezierpolyrange(context.x_pt, self.x1_pt, self.x2_pt, self.x3_pt) ymin_pt, ymax_pt = _bezierpolyrange(context.y_pt, self.y1_pt, self.y2_pt, self.y3_pt) bbox.includepoint_pt(xmin_pt, ymin_pt) bbox.includepoint_pt(xmax_pt, ymax_pt) context.x_pt = self.x3_pt context.y_pt = self.y3_pt def updatenormpath(self, normpath, context): normpath.normsubpaths[-1].append(normcurve_pt(context.x_pt, context.y_pt, self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) context.x_pt = self.x3_pt context.y_pt = self.y3_pt def outputPS(self, file, writer): file.write("%g %g %g %g %g %g curveto\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) def returnSVGdata(self, inverse_y, first, context): context.x_pt = self.x3_pt context.y_pt = self.y3_pt if inverse_y: return "C%g %g %g %g %g %g" % (self.x1_pt, -self.y1_pt, self.x2_pt, -self.y2_pt, self.x3_pt, -self.y3_pt) return "C%g %g %g %g %g %g" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt) class rmoveto_pt(pathitem): """Perform relative moveto (coordinates in pts)""" __slots__ = "dx_pt", "dy_pt" def __init__(self, dx_pt, dy_pt): self.dx_pt = dx_pt self.dy_pt = dy_pt def __str__(self): return "rmoveto_pt(%g, %g)" % (self.dx_pt, self.dy_pt) def updatebbox(self, bbox, context): bbox.includepoint_pt(context.x_pt + self.dx_pt, context.y_pt + self.dy_pt) context.x_pt += self.dx_pt context.y_pt += self.dy_pt context.subfirstx_pt = context.x_pt context.subfirsty_pt = context.y_pt def updatenormpath(self, normpath, context): context.x_pt += self.dx_pt context.y_pt += self.dy_pt context.subfirstx_pt = context.x_pt context.subfirsty_pt = context.y_pt if normpath.normsubpaths[-1].epsilon is not None: normpath.append(normsubpath([normline_pt(context.x_pt, context.y_pt, context.x_pt, context.y_pt)], epsilon=normpath.normsubpaths[-1].epsilon)) else: normpath.append(normsubpath(epsilon=normpath.normsubpaths[-1].epsilon)) def outputPS(self, file, writer): file.write("%g %g rmoveto\n" % (self.dx_pt, self.dy_pt) ) def returnSVGdata(self, inverse_y, first, context): context.x_pt += self.dx_pt context.y_pt += self.dy_pt context.subfirstx_pt = context.x_pt context.subfirsty_pt = context.y_pt if inverse_y: return "m%g %g" % (self.dx_pt, -self.dy_pt) return "m%g %g" % (self.dx_pt, self.dy_pt) class rlineto_pt(pathitem): """Perform relative lineto (coordinates in pts)""" __slots__ = "dx_pt", "dy_pt" def __init__(self, dx_pt, dy_pt): self.dx_pt = dx_pt self.dy_pt = dy_pt def __str__(self): return "rlineto_pt(%g %g)" % (self.dx_pt, self.dy_pt) def updatebbox(self, bbox, context): bbox.includepoint_pt(context.x_pt + self.dx_pt, context.y_pt + self.dy_pt) context.x_pt += self.dx_pt context.y_pt += self.dy_pt def updatenormpath(self, normpath, context): normpath.normsubpaths[-1].append(normline_pt(context.x_pt, context.y_pt, context.x_pt + self.dx_pt, context.y_pt + self.dy_pt)) context.x_pt += self.dx_pt context.y_pt += self.dy_pt def outputPS(self, file, writer): file.write("%g %g rlineto\n" % (self.dx_pt, self.dy_pt) ) def returnSVGdata(self, inverse_y, first, context): context.x_pt += self.dx_pt context.y_pt += self.dy_pt if inverse_y: return "l%g %g" % (self.dx_pt, -self.dy_pt) return "l%g %g" % (self.dx_pt, self.dy_pt) class rcurveto_pt(pathitem): """Append rcurveto (coordinates in pts)""" __slots__ = "dx1_pt", "dy1_pt", "dx2_pt", "dy2_pt", "dx3_pt", "dy3_pt" def __init__(self, dx1_pt, dy1_pt, dx2_pt, dy2_pt, dx3_pt, dy3_pt): self.dx1_pt = dx1_pt self.dy1_pt = dy1_pt self.dx2_pt = dx2_pt self.dy2_pt = dy2_pt self.dx3_pt = dx3_pt self.dy3_pt = dy3_pt def __str__(self): return "rcurveto_pt(%g, %g, %g, %g, %g, %g)" % (self.dx1_pt, self.dy1_pt, self.dx2_pt, self.dy2_pt, self.dx3_pt, self.dy3_pt) def updatebbox(self, bbox, context): xmin_pt, xmax_pt = _bezierpolyrange(context.x_pt, context.x_pt+self.dx1_pt, context.x_pt+self.dx2_pt, context.x_pt+self.dx3_pt) ymin_pt, ymax_pt = _bezierpolyrange(context.y_pt, context.y_pt+self.dy1_pt, context.y_pt+self.dy2_pt, context.y_pt+self.dy3_pt) bbox.includepoint_pt(xmin_pt, ymin_pt) bbox.includepoint_pt(xmax_pt, ymax_pt) context.x_pt += self.dx3_pt context.y_pt += self.dy3_pt def updatenormpath(self, normpath, context): normpath.normsubpaths[-1].append(normcurve_pt(context.x_pt, context.y_pt, context.x_pt + self.dx1_pt, context.y_pt + self.dy1_pt, context.x_pt + self.dx2_pt, context.y_pt + self.dy2_pt, context.x_pt + self.dx3_pt, context.y_pt + self.dy3_pt)) context.x_pt += self.dx3_pt context.y_pt += self.dy3_pt def outputPS(self, file, writer): file.write("%g %g %g %g %g %g rcurveto\n" % (self.dx1_pt, self.dy1_pt, self.dx2_pt, self.dy2_pt, self.dx3_pt, self.dy3_pt)) def returnSVGdata(self, inverse_y, first, context): context.x_pt += self.dx3_pt context.y_pt += self.dy3_pt if inverse_y: return "c%g %g %g %g %g %g" % (self.dx1_pt, -self.dy1_pt, self.dx2_pt, -self.dy2_pt, self.dx3_pt, -self.dy3_pt) return "c%g %g %g %g %g %g" % (self.dx1_pt, self.dy1_pt, self.dx2_pt, self.dy2_pt, self.dx3_pt, self.dy3_pt) class arc_pt(pathitem): """Append counterclockwise arc (coordinates in pts)""" __slots__ = "x_pt", "y_pt", "r_pt", "angle1", "angle2" sweep = 0 def __init__(self, x_pt, y_pt, r_pt, angle1, angle2): self.x_pt = x_pt self.y_pt = y_pt self.r_pt = r_pt self.angle1 = angle1 self.angle2 = angle2 def __str__(self): return "arc_pt(%g, %g, %g, %g, %g)" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2) def createcontext(self): x1_pt, y1_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1) x2_pt, y2_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) return context(x2_pt, y2_pt, x1_pt, y1_pt) def createbbox(self): return bboxmodule.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2)) def createnormpath(self, epsilon=_marker): if epsilon is _marker: return normpath([normsubpath(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2))]) else: return normpath([normsubpath(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2), epsilon=epsilon)]) def updatebbox(self, bbox, context): minarcx_pt, minarcy_pt, maxarcx_pt, maxarcy_pt = _arcbboxdata(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2) bbox.includepoint_pt(minarcx_pt, minarcy_pt) bbox.includepoint_pt(maxarcx_pt, maxarcy_pt) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) def updatenormpath(self, normpath, context): if normpath.normsubpaths[-1].closed: normpath.append(normsubpath([normline_pt(context.x_pt, context.y_pt, *_arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1))], epsilon=normpath.normsubpaths[-1].epsilon)) else: normpath.normsubpaths[-1].append(normline_pt(context.x_pt, context.y_pt, *_arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1))) normpath.normsubpaths[-1].extend(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2)) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) def outputPS(self, file, writer): file.write("%g %g %g %g %g arc\n" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2)) def returnSVGdata(self, inverse_y, first, context): # move or line to the start point x_pt, y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1) if inverse_y: y_pt = -y_pt if first: data = ["M%g %g" % (x_pt, y_pt)] else: data = ["L%g %g" % (x_pt, y_pt)] angle1 = self.angle1 angle2 = self.angle2 # make 0 < angle2-angle1 < 2*360 if angle2 < angle1: angle2 += (math.floor((angle1-angle2)/360)+1)*360 elif angle2 > angle1 + 360: angle2 -= (math.floor((angle2-angle1)/360)-1)*360 # svg arcs become unstable when close to 360 degree and cannot # express more than 360 degree at all, so we might need to split. subdivisions = int((angle2-angle1)/350)+1 # we equal split by subdivisions large = "1" if (angle2-angle1)/subdivisions > 180 else "0" for i in range(subdivisions): x_pt, y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, angle1 + (i+1)*(angle2-angle1)/subdivisions) if inverse_y: y_pt = -y_pt data.append("A%g %g 0 %s 0 %g %g" % (self.r_pt, self.r_pt, large, x_pt, y_pt)) context.x_pt = x_pt context.y_pt = y_pt return "".join(data) class arcn_pt(pathitem): """Append clockwise arc (coordinates in pts)""" __slots__ = "x_pt", "y_pt", "r_pt", "angle1", "angle2" sweep = 1 def __init__(self, x_pt, y_pt, r_pt, angle1, angle2): self.x_pt = x_pt self.y_pt = y_pt self.r_pt = r_pt self.angle1 = angle1 self.angle2 = angle2 def __str__(self): return "arcn_pt(%g, %g, %g, %g, %g)" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2) def createcontext(self): x1_pt, y1_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1) x2_pt, y2_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) return context(x2_pt, y2_pt, x1_pt, y1_pt) def createbbox(self): return bboxmodule.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, self.angle2, self.angle1)) def createnormpath(self, epsilon=_marker): if epsilon is _marker: return normpath([normsubpath(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle2, self.angle1))]).reversed() else: return normpath([normsubpath(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle2, self.angle1), epsilon=epsilon)]).reversed() def updatebbox(self, bbox, context): minarcx_pt, minarcy_pt, maxarcx_pt, maxarcy_pt = _arcbboxdata(self.x_pt, self.y_pt, self.r_pt, self.angle2, self.angle1) bbox.includepoint_pt(minarcx_pt, minarcy_pt) bbox.includepoint_pt(maxarcx_pt, maxarcy_pt) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) def updatenormpath(self, normpath, context): if normpath.normsubpaths[-1].closed: normpath.append(normsubpath([normline_pt(context.x_pt, context.y_pt, *_arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1))], epsilon=normpath.normsubpaths[-1].epsilon)) else: normpath.normsubpaths[-1].append(normline_pt(context.x_pt, context.y_pt, *_arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1))) bpathitems = _arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle2, self.angle1) bpathitems.reverse() for bpathitem in bpathitems: normpath.normsubpaths[-1].append(bpathitem.reversed()) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) def outputPS(self, file, writer): file.write("%g %g %g %g %g arcn\n" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2)) def returnSVGdata(self, inverse_y, first, context): # move or line to the start point x_pt, y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle1) if inverse_y: y_pt = -y_pt if first: data = ["M%g %g" % (x_pt, y_pt)] else: data = ["L%g %g" % (x_pt, y_pt)] angle1 = self.angle1 angle2 = self.angle2 # make 0 < angle1-angle2 < 2*360 if angle1 < angle2: angle1 += (math.floor((angle2-angle1)/360)+1)*360 elif angle1 > angle2 + 360: angle1 -= (math.floor((angle1-angle2)/360)-1)*360 # svg arcs become unstable when close to 360 degree and cannot # express more than 360 degree at all, so we might need to split. subdivisions = int((angle1-angle2)/350)+1 # we equal split by subdivisions large = "1" if (angle1-angle2)/subdivisions > 180 else "0" for i in range(subdivisions): x_pt, y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, angle1 + (i+1)*(angle2-angle1)/subdivisions) if inverse_y: y_pt = -y_pt data.append("A%g %g 0 %s 1 %g %g" % (self.r_pt, self.r_pt, large, x_pt, y_pt)) context.x_pt = x_pt context.y_pt = y_pt return "".join(data) class arct_pt(pathitem): """Append tangent arc (coordinates in pts)""" __slots__ = "x1_pt", "y1_pt", "x2_pt", "y2_pt", "r_pt" def __init__(self, x1_pt, y1_pt, x2_pt, y2_pt, r_pt): self.x1_pt = x1_pt self.y1_pt = y1_pt self.x2_pt = x2_pt self.y2_pt = y2_pt self.r_pt = r_pt def __str__(self): return "arct_pt(%g, %g, %g, %g, %g)" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.r_pt) def _pathitems(self, x_pt, y_pt): """return pathitems corresponding to arct for given currentpoint x_pt, y_pt. The return is a list containing line_pt, arc_pt, a arcn_pt instances. This is a helper routine for updatebbox and updatenormpath, which will delegate the work to the constructed pathitem. """ # direction of tangent 1 dx1_pt, dy1_pt = self.x1_pt-x_pt, self.y1_pt-y_pt l1_pt = math.hypot(dx1_pt, dy1_pt) dx1, dy1 = dx1_pt/l1_pt, dy1_pt/l1_pt # direction of tangent 2 dx2_pt, dy2_pt = self.x2_pt-self.x1_pt, self.y2_pt-self.y1_pt l2_pt = math.hypot(dx2_pt, dy2_pt) dx2, dy2 = dx2_pt/l2_pt, dy2_pt/l2_pt # intersection angle between two tangents in the range (-pi, pi). # We take the orientation from the sign of the vector product. # Negative (positive) angles alpha corresponds to a turn to the right (left) # as seen from currentpoint. if dx1*dy2-dy1*dx2 > 0: alpha = acos(dx1*dx2+dy1*dy2) else: alpha = -acos(dx1*dx2+dy1*dy2) try: # two tangent points xt1_pt = self.x1_pt - dx1*self.r_pt*tan(abs(alpha)/2) yt1_pt = self.y1_pt - dy1*self.r_pt*tan(abs(alpha)/2) xt2_pt = self.x1_pt + dx2*self.r_pt*tan(abs(alpha)/2) yt2_pt = self.y1_pt + dy2*self.r_pt*tan(abs(alpha)/2) # direction point 1 -> center of arc dmx_pt = 0.5*(xt1_pt+xt2_pt) - self.x1_pt dmy_pt = 0.5*(yt1_pt+yt2_pt) - self.y1_pt lm_pt = math.hypot(dmx_pt, dmy_pt) dmx, dmy = dmx_pt/lm_pt, dmy_pt/lm_pt # center of arc mx_pt = self.x1_pt + dmx*self.r_pt/cos(alpha/2) my_pt = self.y1_pt + dmy*self.r_pt/cos(alpha/2) # angle around which arc is centered phi = degrees(math.atan2(-dmy, -dmx)) # half angular width of arc deltaphi = degrees(alpha)/2 line = lineto_pt(*_arcpoint(mx_pt, my_pt, self.r_pt, phi-deltaphi)) if alpha > 0: return [line, arc_pt(mx_pt, my_pt, self.r_pt, phi-deltaphi, phi+deltaphi)] else: return [line, arcn_pt(mx_pt, my_pt, self.r_pt, phi-deltaphi, phi+deltaphi)] except ZeroDivisionError: # in the degenerate case, we just return a line as specified by the PS # language reference return [lineto_pt(self.x1_pt, self.y1_pt)] def updatebbox(self, bbox, context): for pathitem in self._pathitems(context.x_pt, context.y_pt): pathitem.updatebbox(bbox, context) def updatenormpath(self, normpath, context): for pathitem in self._pathitems(context.x_pt, context.y_pt): pathitem.updatenormpath(normpath, context) def outputPS(self, file, writer): file.write("%g %g %g %g %g arct\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.r_pt)) def returnSVGdata(self, inverse_y, first, context): # first is always False as arct cannot be first, it has no createcontext method return "".join(pathitem.returnSVGdata(inverse_y, first, context) for pathitem in self._pathitems(context.x_pt, context.y_pt)) # # now the pathitems that convert from user coordinates to pts # class moveto(moveto_pt): """Set current point to (x, y)""" __slots__ = "x_pt", "y_pt" def __init__(self, x, y): moveto_pt.__init__(self, unit.topt(x), unit.topt(y)) class lineto(lineto_pt): """Append straight line to (x, y)""" __slots__ = "x_pt", "y_pt" def __init__(self, x, y): lineto_pt.__init__(self, unit.topt(x), unit.topt(y)) class curveto(curveto_pt): """Append curveto""" __slots__ = "x1_pt", "y1_pt", "x2_pt", "y2_pt", "x3_pt", "y3_pt" def __init__(self, x1, y1, x2, y2, x3, y3): curveto_pt.__init__(self, unit.topt(x1), unit.topt(y1), unit.topt(x2), unit.topt(y2), unit.topt(x3), unit.topt(y3)) class rmoveto(rmoveto_pt): """Perform relative moveto""" __slots__ = "dx_pt", "dy_pt" def __init__(self, dx, dy): rmoveto_pt.__init__(self, unit.topt(dx), unit.topt(dy)) class rlineto(rlineto_pt): """Perform relative lineto""" __slots__ = "dx_pt", "dy_pt" def __init__(self, dx, dy): rlineto_pt.__init__(self, unit.topt(dx), unit.topt(dy)) class rcurveto(rcurveto_pt): """Append rcurveto""" __slots__ = "dx1_pt", "dy1_pt", "dx2_pt", "dy2_pt", "dx3_pt", "dy3_pt" def __init__(self, dx1, dy1, dx2, dy2, dx3, dy3): rcurveto_pt.__init__(self, unit.topt(dx1), unit.topt(dy1), unit.topt(dx2), unit.topt(dy2), unit.topt(dx3), unit.topt(dy3)) class arcn(arcn_pt): """Append clockwise arc""" __slots__ = "x_pt", "y_pt", "r_pt", "angle1", "angle2" def __init__(self, x, y, r, angle1, angle2): arcn_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(r), angle1, angle2) class arc(arc_pt): """Append counterclockwise arc""" __slots__ = "x_pt", "y_pt", "r_pt", "angle1", "angle2" def __init__(self, x, y, r, angle1, angle2): arc_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(r), angle1, angle2) class arct(arct_pt): """Append tangent arc""" __slots__ = "x1_pt", "y1_pt", "x2_pt", "y2_pt", "r_pt" def __init__(self, x1, y1, x2, y2, r): arct_pt.__init__(self, unit.topt(x1), unit.topt(y1), unit.topt(x2), unit.topt(y2), unit.topt(r)) # # "combined" pathitems provided for performance reasons # class multilineto_pt(pathitem): """Perform multiple linetos (coordinates in pts)""" __slots__ = "points_pt" def __init__(self, points_pt): self.points_pt = points_pt def __str__(self): result = [] for point_pt in self.points_pt: result.append("(%g, %g)" % point_pt ) return "multilineto_pt([%s])" % (", ".join(result)) def updatebbox(self, bbox, context): for point_pt in self.points_pt: bbox.includepoint_pt(*point_pt) if self.points_pt: context.x_pt, context.y_pt = self.points_pt[-1] def updatenormpath(self, normpath, context): x0_pt, y0_pt = context.x_pt, context.y_pt for point_pt in self.points_pt: normpath.normsubpaths[-1].append(normline_pt(x0_pt, y0_pt, *point_pt)) x0_pt, y0_pt = point_pt context.x_pt, context.y_pt = x0_pt, y0_pt def outputPS(self, file, writer): for point_pt in self.points_pt: file.write("%g %g lineto\n" % point_pt ) def returnSVGdata(self, inverse_y, first, context): if self.points_pt: context.x_pt, context.y_pt = self.points_pt[-1] if inverse_y: return "".join("L%g %g" % (x_pt, -y_pt) for x_pt, y_pt in self.points_pt) return "".join("L%g %g" % point_pt for point_pt in self.points_pt) class multicurveto_pt(pathitem): """Perform multiple curvetos (coordinates in pts)""" __slots__ = "points_pt" def __init__(self, points_pt): self.points_pt = points_pt def __str__(self): result = [] for point_pt in self.points_pt: result.append("(%g, %g, %g, %g, %g, %g)" % point_pt ) return "multicurveto_pt([%s])" % (", ".join(result)) def updatebbox(self, bbox, context): for point_pt in self.points_pt: xmin_pt, xmax_pt = _bezierpolyrange(context.x_pt, point_pt[0], point_pt[2], point_pt[4]) ymin_pt, ymax_pt = _bezierpolyrange(context.y_pt, point_pt[1], point_pt[3], point_pt[5]) bbox.includepoint_pt(xmin_pt, ymin_pt) bbox.includepoint_pt(xmax_pt, ymax_pt) context.x_pt, context.y_pt = point_pt[4:] def updatenormpath(self, normpath, context): x0_pt, y0_pt = context.x_pt, context.y_pt for point_pt in self.points_pt: normpath.normsubpaths[-1].append(normcurve_pt(x0_pt, y0_pt, *point_pt)) x0_pt, y0_pt = point_pt[4:] context.x_pt, context.y_pt = x0_pt, y0_pt def outputPS(self, file, writer): for point_pt in self.points_pt: file.write("%g %g %g %g %g %g curveto\n" % point_pt) def returnSVGdata(self, inverse_y, first, context): if self.points_pt: context.x_pt, context.y_pt = self.points_pt[-1][4:] if inverse_y: return "".join("C%g %g %g %g %g %g" % (x1_pt, -y1_pt, x2_pt, -y2_pt, x3_pt, -y3_pt) for x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt in self.points_pt) return "".join("C%g %g %g %g %g %g" % point_pt for point_pt in self.points_pt) ################################################################################ # path: PS style path ################################################################################ class path: """PS style path""" __slots__ = "pathitems", "_normpath" def __init__(self, *pathitems): """construct a path from pathitems *args""" for apathitem in pathitems: assert isinstance(apathitem, pathitem), "only pathitem instances allowed" self.pathitems = list(pathitems) # normpath cache (when no epsilon is set) self._normpath = None def __add__(self, other): """create new path out of self and other""" return path(*(self.pathitems + other.path().pathitems)) def __iadd__(self, other): """add other inplace If other is a normpath instance, it is converted to a path before being added. """ self.pathitems += other.path().pathitems self._normpath = None return self def __getitem__(self, i): """return path item i""" return self.pathitems[i] def __len__(self): """return the number of path items""" return len(self.pathitems) def __str__(self): l = ", ".join(map(str, self.pathitems)) return "path(%s)" % l def append(self, apathitem): """append a path item""" assert isinstance(apathitem, pathitem), "only pathitem instance allowed" self.pathitems.append(apathitem) self._normpath = None def arclen_pt(self): """return arc length in pts""" return self.normpath().arclen_pt() def arclen(self): """return arc length""" return self.normpath().arclen() def arclentoparam_pt(self, lengths_pt): """return the param(s) matching the given length(s)_pt in pts""" return self.normpath().arclentoparam_pt(lengths_pt) def arclentoparam(self, lengths): """return the param(s) matching the given length(s)""" return self.normpath().arclentoparam(lengths) def at_pt(self, params): """return coordinates of path in pts at param(s) or arc length(s) in pts""" return self.normpath().at_pt(params) def at(self, params): """return coordinates of path at param(s) or arc length(s)""" return self.normpath().at(params) def atbegin_pt(self): """return coordinates of the beginning of first subpath in path in pts""" return self.normpath().atbegin_pt() def atbegin(self): """return coordinates of the beginning of first subpath in path""" return self.normpath().atbegin() def atend_pt(self): """return coordinates of the end of last subpath in path in pts""" return self.normpath().atend_pt() def atend(self): """return coordinates of the end of last subpath in path""" return self.normpath().atend() def bbox(self): """return bbox of path""" if self.pathitems: bbox = self.pathitems[0].createbbox() context = self.pathitems[0].createcontext() for pathitem in self.pathitems[1:]: pathitem.updatebbox(bbox, context) return bbox else: return bboxmodule.empty() def begin(self): """return param corresponding of the beginning of the path""" return self.normpath().begin() def curvature_pt(self, params): """return the curvature in 1/pts at param(s) or arc length(s) in pts""" return self.normpath().curvature_pt(params) def end(self): """return param corresponding of the end of the path""" return self.normpath().end() def extend(self, pathitems): """extend path by pathitems""" for apathitem in pathitems: assert isinstance(apathitem, pathitem), "only pathitem instance allowed" self.pathitems.extend(pathitems) self._normpath = None def intersect(self, other): """intersect self with other path Returns a tuple of lists consisting of the parameter values of the intersection points of the corresponding normpath. """ return self.normpath().intersect(other) def join(self, other): """join other path/normpath inplace If other is a normpath instance, it is converted to a path before being joined. """ self.pathitems = self.joined(other).path().pathitems self._normpath = None return self def joined(self, other): """return path consisting of self and other joined together""" return self.normpath().joined(other).path() # << operator also designates joining __lshift__ = joined def normpath(self, epsilon=_marker): """convert the path into a normpath""" # use cached value if existent and epsilon is _marker if self._normpath is not None and epsilon is _marker: return self._normpath if self.pathitems: if epsilon is _marker: np = self.pathitems[0].createnormpath() else: np = self.pathitems[0].createnormpath(epsilon) context = self.pathitems[0].createcontext() for pathitem in self.pathitems[1:]: pathitem.updatenormpath(np, context) else: np = normpath() if epsilon is _marker: self._normpath = np return np def paramtoarclen_pt(self, params): """return arc lenght(s) in pts matching the given param(s)""" return self.normpath().paramtoarclen_pt(params) def paramtoarclen(self, params): """return arc lenght(s) matching the given param(s)""" return self.normpath().paramtoarclen(params) def path(self): """return corresponding path, i.e., self""" return self def reversed(self): """return reversed normpath""" # TODO: couldn't we try to return a path instead of converting it # to a normpath (but this might not be worth the trouble) return self.normpath().reversed() def rotation_pt(self, params): """return rotation at param(s) or arc length(s) in pts""" return self.normpath().rotation(params) def rotation(self, params): """return rotation at param(s) or arc length(s)""" return self.normpath().rotation(params) def split_pt(self, params): """split normpath at param(s) or arc length(s) in pts and return list of normpaths""" return self.normpath().split_pt(params) def split(self, params): """split normpath at param(s) or arc length(s) and return list of normpaths""" return self.normpath().split(params) def tangent_pt(self, params, length): """return tangent vector of path at param(s) or arc length(s) in pts If length in pts is not None, the tangent vector will be scaled to the desired length. """ return self.normpath().tangent_pt(params, length) def tangent(self, params, length=1): """return tangent vector of path at param(s) or arc length(s) If length is not None, the tangent vector will be scaled to the desired length. """ return self.normpath().tangent(params, length) def trafo_pt(self, params): """return transformation at param(s) or arc length(s) in pts""" return self.normpath().trafo(params) def trafo(self, params): """return transformation at param(s) or arc length(s)""" return self.normpath().trafo(params) def transformed(self, trafo): """return transformed path""" return self.normpath().transformed(trafo) def outputPS(self, file, writer): """write PS code to file""" for pitem in self.pathitems: pitem.outputPS(file, writer) def outputPDF(self, file, writer): """write PDF code to file""" # PDF only supports normsubpathitems; we need to use a normpath # with epsilon equals None to prevent failure for paths shorter # than epsilon self.normpath(epsilon=None).outputPDF(file, writer) def returnSVGdata(self, inverse_y=True): """return SVG code""" if not self.pathitems: return "" context = self.pathitems[0].createcontext() return "".join(pitem.returnSVGdata(inverse_y, not i, context) for i, pitem in enumerate(self.pathitems)) # # some special kinds of path, again in two variants # class line_pt(path): """straight line from (x1_pt, y1_pt) to (x2_pt, y2_pt) in pts""" def __init__(self, x1_pt, y1_pt, x2_pt, y2_pt): path.__init__(self, moveto_pt(x1_pt, y1_pt), lineto_pt(x2_pt, y2_pt)) class curve_pt(path): """bezier curve with control points (x0_pt, y1_pt),..., (x3_pt, y3_pt) in pts""" def __init__(self, x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt): path.__init__(self, moveto_pt(x0_pt, y0_pt), curveto_pt(x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt)) class rect_pt(path): """rectangle at position (x_pt, y_pt) with width_pt and height_pt in pts""" def __init__(self, x_pt, y_pt, width_pt, height_pt): path.__init__(self, moveto_pt(x_pt, y_pt), lineto_pt(x_pt+width_pt, y_pt), lineto_pt(x_pt+width_pt, y_pt+height_pt), lineto_pt(x_pt, y_pt+height_pt), closepath()) class circle_pt(path): """circle with center (x_pt, y_pt) and radius_pt in pts""" def __init__(self, x_pt, y_pt, radius_pt, arcepsilon=0.1): path.__init__(self, moveto_pt(x_pt+radius_pt, y_pt), arc_pt(x_pt, y_pt, radius_pt, arcepsilon, 360-arcepsilon), closepath()) class ellipse_pt(path): """ellipse with center (x_pt, y_pt) in pts, the two axes (a_pt, b_pt) in pts, and the angle angle of the first axis""" def __init__(self, x_pt, y_pt, a_pt, b_pt, angle, **kwargs): t = trafo.scale(a_pt, b_pt).rotated(angle).translated_pt(x_pt, y_pt) p = circle_pt(0, 0, 1, **kwargs).normpath(epsilon=None).transformed(t).path() path.__init__(self, *p.pathitems) class line(line_pt): """straight line from (x1, y1) to (x2, y2)""" def __init__(self, x1, y1, x2, y2): line_pt.__init__(self, unit.topt(x1), unit.topt(y1), unit.topt(x2), unit.topt(y2)) class curve(curve_pt): """bezier curve with control points (x0, y1),..., (x3, y3)""" def __init__(self, x0, y0, x1, y1, x2, y2, x3, y3): curve_pt.__init__(self, unit.topt(x0), unit.topt(y0), unit.topt(x1), unit.topt(y1), unit.topt(x2), unit.topt(y2), unit.topt(x3), unit.topt(y3)) class rect(rect_pt): """rectangle at position (x,y) with width and height""" def __init__(self, x, y, width, height): rect_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(width), unit.topt(height)) class circle(circle_pt): """circle with center (x,y) and radius""" def __init__(self, x, y, radius, **kwargs): circle_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(radius), **kwargs) class ellipse(ellipse_pt): """ellipse with center (x, y), the two axes (a, b), and the angle angle of the first axis""" def __init__(self, x, y, a, b, angle, **kwargs): ellipse_pt.__init__(self, unit.topt(x), unit.topt(y), unit.topt(a), unit.topt(b), angle, **kwargs) PyX-0.14.1/pyx/pattern.py0000644000076500000240000003777612520000740015412 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, logging, math from . import attr, canvas, path, pdfwriter, pswriter, svgwriter, style, unit, trafo from . import writer as writermodule from . import bbox as bboxmodule logger = logging.getLogger("pyx") class _marker: pass # TODO: pattern should not derive from canvas but wrap a canvas class pattern(canvas.canvas, attr.exclusiveattr, style.fillstyle): def __init__(self, painttype=1, tilingtype=1, xstep=None, ystep=None, bbox=None, trafo=None, bboxenlarge=None, **kwargs): canvas.canvas.__init__(self, **kwargs) attr.exclusiveattr.__init__(self, pattern) self.id = "pattern%d" % id(self) self.patterntype = 1 if painttype not in (1, 2): raise ValueError("painttype must be 1 or 2") self.painttype = painttype if tilingtype not in (1, 2, 3): raise ValueError("tilingtype must be 1, 2, or 3") self.tilingtype = tilingtype self.xstep = xstep self.ystep = ystep self.patternbbox = bbox self.patterntrafo = trafo self.bboxenlarge = bboxenlarge def __call__(self, painttype=_marker, tilingtype=_marker, xstep=_marker, ystep=_marker, bbox=_marker, trafo=_marker, bboxenlarge=_marker): if painttype is not _marker: painttype = self.painttype if tilingtype is not _marker: tilingtype = self.tilingtype if xstep is not _marker: xstep = self.xstep if ystep is not _marker: ystep = self.ystep if bbox is not _marker: bbox = self.bbox if trafo is not _marker: trafo = self.trafo if bboxenlarge is not _marker: bboxenlarge = self.bboxenlarge return pattern(painttype, tilingtype, xstep, ystep, bbox, trafo, bboxenlarge) def processPS(self, file, writer, context, registry): # process pattern, letting it register its resources and calculate the bbox of the pattern patternfile = writermodule.writer(io.BytesIO()) realpatternbbox = bboxmodule.empty() canvas.canvas.processPS(self, patternfile, writer, pswriter.context(), registry, realpatternbbox) patternproc = patternfile.file.getvalue() if self.xstep is None: xstep = unit.topt(realpatternbbox.width()) else: xstep = unit.topt(self.xstep) if self.ystep is None: ystep = unit.topt(realpatternbbox.height()) else: ystep = unit.topt(self.ystep) if not xstep: raise ValueError("xstep in pattern cannot be zero") if not ystep: raise ValueError("ystep in pattern cannot be zero") if self.patternbbox: patternbbox = self.patternbbox else: patternbbox = realpatternbbox if self.bboxenlarge: patternbbox.enlarge(self.bboxenlarge) patternprefix = "\n".join(("<<", "/PatternType %d" % self.patterntype, "/PaintType %d" % self.painttype, "/TilingType %d" % self.tilingtype, "/BBox [%g %g %g %g]" % patternbbox.highrestuple_pt(), "/XStep %g" % xstep, "/YStep %g" % ystep, "/PaintProc {\nbegin\n")) patterntrafostring = self.patterntrafo is None and "matrix" or str(self.patterntrafo) patternsuffix = "end\n} bind\n>>\n%s\nmakepattern" % patterntrafostring registry.add(pswriter.PSdefinition(self.id, patternprefix.encode("ascii") + patternproc + patternsuffix.encode("ascii"))) # activate pattern file.write("%s setpattern\n" % self.id) def processPDF(self, file, writer, context, registry): # we need to keep track of the resources used by the pattern, hence # we create our own registry, which we merge immediately in the main registry patternregistry = pdfwriter.PDFregistry() patternfile = writermodule.writer(io.BytesIO()) realpatternbbox = bboxmodule.empty() canvas.canvas.processPDF(self, patternfile, writer, pdfwriter.context(), patternregistry, realpatternbbox) patternproc = patternfile.file.getvalue() registry.mergeregistry(patternregistry) if self.xstep is None: xstep = unit.topt(realpatternbbox.width()) else: xstep = unit.topt(self.xstep) if self.ystep is None: ystep = unit.topt(realpatternbbox.height()) else: ystep = unit.topt(self.ystep) if not xstep: raise ValueError("xstep in pattern cannot be zero") if not ystep: raise ValueError("ystep in pattern cannot be zero") if self.patternbbox: patternbbox = self.patternbbox else: patternbbox = realpatternbbox if self.bboxenlarge: patternbbox.enlarge(self.bboxenlarge) patterntrafo = self.patterntrafo or trafo.trafo() registry.add(PDFpattern(self.id, self.patterntype, self.painttype, self.tilingtype, patternbbox, xstep, ystep, patterntrafo, patternproc, writer, registry, patternregistry)) # activate pattern if context.colorspace != "Pattern": # we only set the fill color space (see next comment) file.write("/Pattern cs\n") context.colorspace = "Pattern" if context.strokeattr: # using patterns as stroke colors doesn't seem to work, so # we just don't do this... logger.warning("ignoring stroke color for patterns in PDF") if context.fillattr: file.write("/%s scn\n"% self.id) def processSVGattrs(self, attrs, writer, context, registry): assert self.patterntype == 1 if self.painttype != 1: raise ValueError("grayscale patterns not supported") # tilingtype is an implementation detail in PS and PDF and is ignored if self.xstep is not None or self.ystep is not None or self.bboxenlarge is not None: raise ValueError("step and bbox modifications not supported") svgpattern = SVGpattern(self) registry.add(svgpattern) if context.strokeattr: context.strokecolor = "url(#%s)" % svgpattern.svgid if context.fillattr: context.fillcolor = "url(#%s)" % svgpattern.svgid pattern.clear = attr.clearclass(pattern) _base = 0.1 * unit.v_cm class hatched(pattern): def __init__(self, dist, angle, strokestyles=[]): pattern.__init__(self, painttype=1, tilingtype=1, xstep=dist, ystep=100*unit.t_pt, bbox=None, trafo=trafo.rotate(angle)) self.strokestyles = attr.mergeattrs([style.linewidth.THIN] + strokestyles) attr.checkattrs(self.strokestyles, [style.strokestyle]) self.dist = dist self.angle = angle self.stroke(path.line_pt(0, -50, 0, 50), self.strokestyles) def __call__(self, dist=None, angle=None, strokestyles=None): if dist is None: dist = self.dist if angle is None: angle = self.angle if strokestyles is None: strokestyles = self.strokestyles return hatched(dist, angle, strokestyles) hatched0 = hatched(_base, 0) hatched0.SMALL = hatched0(_base/math.sqrt(64)) hatched0.SMALL = hatched0(_base/math.sqrt(64)) hatched0.SMALl = hatched0(_base/math.sqrt(32)) hatched0.SMAll = hatched0(_base/math.sqrt(16)) hatched0.SMall = hatched0(_base/math.sqrt(8)) hatched0.Small = hatched0(_base/math.sqrt(4)) hatched0.small = hatched0(_base/math.sqrt(2)) hatched0.normal = hatched0(_base) hatched0.large = hatched0(_base*math.sqrt(2)) hatched0.Large = hatched0(_base*math.sqrt(4)) hatched0.LArge = hatched0(_base*math.sqrt(8)) hatched0.LARge = hatched0(_base*math.sqrt(16)) hatched0.LARGe = hatched0(_base*math.sqrt(32)) hatched0.LARGE = hatched0(_base*math.sqrt(64)) hatched45 = hatched(_base, 45) hatched45.SMALL = hatched45(_base/math.sqrt(64)) hatched45.SMALl = hatched45(_base/math.sqrt(32)) hatched45.SMAll = hatched45(_base/math.sqrt(16)) hatched45.SMall = hatched45(_base/math.sqrt(8)) hatched45.Small = hatched45(_base/math.sqrt(4)) hatched45.small = hatched45(_base/math.sqrt(2)) hatched45.normal = hatched45(_base) hatched45.large = hatched45(_base*math.sqrt(2)) hatched45.Large = hatched45(_base*math.sqrt(4)) hatched45.LArge = hatched45(_base*math.sqrt(8)) hatched45.LARge = hatched45(_base*math.sqrt(16)) hatched45.LARGe = hatched45(_base*math.sqrt(32)) hatched45.LARGE = hatched45(_base*math.sqrt(64)) hatched90 = hatched(_base, 90) hatched90.SMALL = hatched90(_base/math.sqrt(64)) hatched90.SMALl = hatched90(_base/math.sqrt(32)) hatched90.SMAll = hatched90(_base/math.sqrt(16)) hatched90.SMall = hatched90(_base/math.sqrt(8)) hatched90.Small = hatched90(_base/math.sqrt(4)) hatched90.small = hatched90(_base/math.sqrt(2)) hatched90.normal = hatched90(_base) hatched90.large = hatched90(_base*math.sqrt(2)) hatched90.Large = hatched90(_base*math.sqrt(4)) hatched90.LArge = hatched90(_base*math.sqrt(8)) hatched90.LARge = hatched90(_base*math.sqrt(16)) hatched90.LARGe = hatched90(_base*math.sqrt(32)) hatched90.LARGE = hatched90(_base*math.sqrt(64)) hatched135 = hatched(_base, 135) hatched135.SMALL = hatched135(_base/math.sqrt(64)) hatched135.SMALl = hatched135(_base/math.sqrt(32)) hatched135.SMAll = hatched135(_base/math.sqrt(16)) hatched135.SMall = hatched135(_base/math.sqrt(8)) hatched135.Small = hatched135(_base/math.sqrt(4)) hatched135.small = hatched135(_base/math.sqrt(2)) hatched135.normal = hatched135(_base) hatched135.large = hatched135(_base*math.sqrt(2)) hatched135.Large = hatched135(_base*math.sqrt(4)) hatched135.LArge = hatched135(_base*math.sqrt(8)) hatched135.LARge = hatched135(_base*math.sqrt(16)) hatched135.LARGe = hatched135(_base*math.sqrt(32)) hatched135.LARGE = hatched135(_base*math.sqrt(64)) class crosshatched(pattern): def __init__(self, dist, angle, strokestyles=[]): pattern.__init__(self, painttype=1, tilingtype=1, xstep=dist, ystep=dist, bbox=None, trafo=trafo.rotate(angle)) self.strokestyles = attr.mergeattrs([style.linewidth.THIN] + strokestyles) attr.checkattrs(self.strokestyles, [style.strokestyle]) self.dist = dist self.angle = angle self.stroke(path.line_pt(0, 0, 0, unit.topt(dist)), self.strokestyles) self.stroke(path.line_pt(0, 0, unit.topt(dist), 0), self.strokestyles) def __call__(self, dist=None, angle=None, strokestyles=None): if dist is None: dist = self.dist if angle is None: angle = self.angle if strokestyles is None: strokestyles = self.strokestyles return crosshatched(dist, angle, strokestyles) crosshatched0 = crosshatched(_base, 0) crosshatched0.SMALL = crosshatched0(_base/math.sqrt(64)) crosshatched0.SMALl = crosshatched0(_base/math.sqrt(32)) crosshatched0.SMAll = crosshatched0(_base/math.sqrt(16)) crosshatched0.SMall = crosshatched0(_base/math.sqrt(8)) crosshatched0.Small = crosshatched0(_base/math.sqrt(4)) crosshatched0.small = crosshatched0(_base/math.sqrt(2)) crosshatched0.normal = crosshatched0 crosshatched0.large = crosshatched0(_base*math.sqrt(2)) crosshatched0.Large = crosshatched0(_base*math.sqrt(4)) crosshatched0.LArge = crosshatched0(_base*math.sqrt(8)) crosshatched0.LARge = crosshatched0(_base*math.sqrt(16)) crosshatched0.LARGe = crosshatched0(_base*math.sqrt(32)) crosshatched0.LARGE = crosshatched0(_base*math.sqrt(64)) crosshatched45 = crosshatched(_base, 45) crosshatched45.SMALL = crosshatched45(_base/math.sqrt(64)) crosshatched45.SMALl = crosshatched45(_base/math.sqrt(32)) crosshatched45.SMAll = crosshatched45(_base/math.sqrt(16)) crosshatched45.SMall = crosshatched45(_base/math.sqrt(8)) crosshatched45.Small = crosshatched45(_base/math.sqrt(4)) crosshatched45.small = crosshatched45(_base/math.sqrt(2)) crosshatched45.normal = crosshatched45 crosshatched45.large = crosshatched45(_base*math.sqrt(2)) crosshatched45.Large = crosshatched45(_base*math.sqrt(4)) crosshatched45.LArge = crosshatched45(_base*math.sqrt(8)) crosshatched45.LARge = crosshatched45(_base*math.sqrt(16)) crosshatched45.LARGe = crosshatched45(_base*math.sqrt(32)) crosshatched45.LARGE = crosshatched45(_base*math.sqrt(64)) class PDFpattern(pdfwriter.PDFobject): def __init__(self, name, patterntype, painttype, tilingtype, bbox, xstep, ystep, trafo, patternproc, writer, registry, patternregistry): self.patternregistry = patternregistry pdfwriter.PDFobject.__init__(self, "pattern", name) registry.addresource("Pattern", name, self) self.name = name self.patterntype = patterntype self.painttype = painttype self.tilingtype = tilingtype self.bbox = bbox self.xstep = xstep self.ystep = ystep self.trafo = trafo self.patternproc = patternproc def write(self, file, writer, registry): file.write("<<\n" "/Type /Pattern\n" "/PatternType %d\n" % self.patterntype) file.write("/PaintType %d\n" % self.painttype) file.write("/TilingType %d\n" % self.tilingtype) file.write("/BBox [%d %d %d %d]\n" % self.bbox.lowrestuple_pt()) file.write("/XStep %f\n" % self.xstep) file.write("/YStep %f\n" % self.ystep) file.write("/Matrix %s\n" % str(self.trafo)) file.write("/Resources ") self.patternregistry.writeresources(file) if writer.compress: import zlib content = zlib.compress(self.patternproc) else: content = self.patternproc file.write("/Length %i\n" % len(content)) if writer.compress: file.write("/Filter /FlateDecode\n") file.write(">>\n" "stream\n") file.write_bytes(content) file.write("endstream\n") class SVGpattern(svgwriter.SVGresource): def __init__(self, pattern): self.svgid = "pattern%d" % id(pattern) super().__init__("pattern", self.svgid) self.pattern = pattern def output(self, xml, writer, registry): if self.pattern.patternbbox: patternbbox = self.pattern.patternbbox else: patternfile = io.BytesIO() patternxml = svgwriter.SVGGenerator(patternfile) patternbbox = bboxmodule.empty() patternxml.startSVGDocument() self.pattern.processSVG(patternxml, writer, svgwriter.context(), svgwriter.SVGregistry(), patternbbox) attrs = {"id": self.svgid, "patternUnits": "userSpaceOnUse"} llx, lly, urx, ury = patternbbox.highrestuple_pt() attrs["viewBox"] = "%g %g %g %g" % (llx, -ury, urx-llx, ury-lly) attrs["width"] = "%g" % (urx-llx) attrs["height"] = "%g" % (ury-lly) if self.pattern.patterntrafo: self.pattern.patterntrafo.processSVGattrs(attrs, self, svgwriter.context(), registry) attrs["patternTransform"] = attrs["transform"] del attrs["transform"] xml.startSVGElement("pattern", attrs) self.pattern.processSVG(xml, writer, svgwriter.context(), registry, bboxmodule.empty()) xml.endSVGElement("pattern") PyX-0.14.1/pyx/pdfextra.py0000644000076500000240000007101412177540640015551 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2006 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, math from . import baseclasses, bbox, pdfwriter, color, unit from .font.font import PDFHelvetica, PDFZapfDingbats # TODO: # - discuss behaviour under transformations with André and Jörg # - what about fillstyles here? # - where should e.g. a font be added to the registry: # in processPDF or in __init__ of the PDF-item? # - test for double occurrance of field names: # this leads to wrong/no display # # TODO horizontal alignment in textfields # flags for annotations: PDFannotflags = [("invisible", 0), ("hidden", 1), ("printable", 2), ("nozoom", 3), ("norotate", 4), ("noview", 5), ("readonly", 6)] # flags for form fields PDFformflags = [("readonly", 0), ("required", 1), ("noexport", 2), # flags for the button field ("notoggletooff", 14), ("radio", 15), ("pushbutton", 16), # flags for the choice list field ("combo", 17), ("edit", 18), ("sort", 19), ("multiselect", 21), # flags for the text field ("multiline", 12), ("password", 13), ("fileselect", 20), ("donotspellcheck", 22), ("donotscroll", 23)] class flag: # <<< """A helper class for handling flags in pdf forms and annotations""" def __init__(self, value=None): self.value = value def is_set(self, bit): return self.value is not None and (self.value & 1<>> def _pdfflags(flags): # <<< """Splits flags into annotation/form part the flag for the annotation dictionary the flag for the form (field) dictionary All flags are handled equally here, independent of their use for the specific form field. """ # we initialize with 0 and set only those flags which are not 0 annotflag = flag(value=0) formflag = flag(value=0) for key, value in PDFannotflags: if key in flags and flags[key]: annotflag.set(value) for key, value in PDFformflags: if key in flags and flags[key]: formflag.set(value) return int(annotflag), int(formflag) # >>> def _pdfalignment(string): # <<< alignflag = 0 if string == "c": alignflag = 1 elif string == "r": alignflag = 2 return alignflag # >>> def _topt(value, type="u", un="cm"): # <<< if isinstance(value, unit.length): return unit.topt(value) else: return unit.topt(unit.length(value, type, un)) # >>> def _simplestring(text): # <<< result = "" for x in text: if x.isalnum(): result += x return result # >>> def _sizetrafo(s, tr): # <<< x1, y1 = tr.apply_pt(s, s) x0, y0 = tr.apply_pt(0, 0) return math.hypot(x1 - x0, y1 - y0) * math.sqrt(0.5) # >>> class formfield(baseclasses.canvasitem): # <<< """Base class for acroforms""" defaultflags = dict() def selectflags(self, flags): newflags = dict(**self.defaultflags) # overwrite the default flags with given values: for key, value in list(flags.items()): if key in newflags: newflags[key] = value else: raise RuntimeError("unknown argument \"%s\" to formfield" % key) return newflags def bbox(self): return bbox.bbox_pt(self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) def processPS(self, file, writer, context, registry, bbox): raise RuntimeError("postscript output of forms is not supported") # >>> class textfield(formfield): # <<< """An interactive pdf form field for text input. The "name" is used for the graphical user interface and for exporing the input data. Note that the behaviour under rotations is undefined.""" defaultflags = dict(invisible=0, hidden=0, printable=1, nozoom=0, norotate=0, noview=0, readonly=0, required=0, noexport=0, multiline=0, password=0, fileselect=0, donotspellcheck=1, donotscroll=0) def __init__(self, x, y, width, height, name, defaultvalue="", fontsize=10, font=PDFHelvetica, fontrelleading=1.16, borderwidth=0, align="l", **flags): self.llx_pt, self.lly_pt = _topt(x), _topt(y) self.urx_pt, self.ury_pt = _topt(x+width), _topt(y+height) self.name = name self.defaultvalue = defaultvalue self.fontsize_pt = _topt(fontsize, "x", "pt") self.font = font self.fontrelleading = fontrelleading self.borderwidth_pt = _topt(borderwidth, "x", "pt") self.align = align self.flags = self.selectflags(flags) def processPDF(self, file, writer, context, registry, bbox): # the bounding box is transformed by the canvas bbox += self.bbox() # the annotation rectangle must be transformed separately: llx_pt, lly_pt = context.trafo.apply_pt(self.llx_pt, self.lly_pt) urx_pt, ury_pt = context.trafo.apply_pt(self.urx_pt, self.ury_pt) fontsize_pt = _sizetrafo(self.fontsize_pt, context.trafo) borderwidth_pt = _sizetrafo(self.borderwidth_pt, context.trafo) # we create numbers from the flags given annotflag, formflag = _pdfflags(self.flags) alignflag = _pdfalignment(self.align) registry.add(PDFtextfield((llx_pt, lly_pt, urx_pt, ury_pt), self.name, self.defaultvalue, fontsize_pt, self.font, self.fontrelleading*fontsize_pt, borderwidth_pt, (not self.flags["multiline"]), alignflag, annotflag, formflag, context.fillstyles, writer, registry)) # >>> class PDFtextfield(pdfwriter.PDFobject): # <<< def __init__(self, bb_pt, name, defaultvalue, fontsize, font, fontleading, borderwidth, vcenter, alignflag, annotflag, formflag, fillstyles, writer, registry): pdfwriter.PDFobject.__init__(self, "formfield_text") # append this formfield to the global document form # and to the annotation list of the page: self.PDFform = None for object in registry.objects: if object.type == "form": object.append(self) self.PDFform = object elif object.type == "annotations": object.append(self) self.name = name self.bb_pt = bb_pt self.defaultvalue = defaultvalue self.fontsize = fontsize self.font = font if self.font is None: self.font = PDFHelvetica self.fontleading = fontleading self.borderwidth = borderwidth self.alignflag = alignflag self.formflag = formflag self.annotflag = annotflag self.registry = pdfwriter.PDFregistry() self.registry.addresource("Font", self.font.name, self.font, procset="Text") self.registry.add(self.font) if self.defaultvalue: text = self.defaultvalue.split("\n") self.defaulttext = PDFdefaulttext(writer, registry, self.fontsize, self.font, self.fontleading, text, self.bb_pt, self.borderwidth, vcenter) self.registry.add(self.defaulttext) else: self.defaulttext = None # process some fillstyles: fillstring = io.StringIO() for attr in fillstyles: if 1:#isinstance(attr, color.color): cont = pdfwriter.context() cont.fillattr = 1 cont.strokeattr = 0 attr.processPDF(fillstring, writer, cont, self.registry, bbox) self.fillstyles = fillstring.getvalue() fillstring.close() registry.mergeregistry(self.registry) def write(self, file, writer, registry): ### the dictionary entries for the annotation file.write("<>\n") # border style dictionary file.write("/Border [0 0 %f]\n" % self.borderwidth) # border style file.write("/F %d\n" % self.annotflag) ### the dictionary entries for the widget annotations file.write("/Subtype /Widget\n") file.write("/H /N\n") # highlight behaviour if self.defaulttext: file.write("/AP <>\n" % registry.getrefno(self.defaulttext)) # appearance dictionary ### the dictionary entries for the form field file.write("/FT /Tx\n") # type of the form field file.write("/T (%s)\n" % self.name) # partial field name file.write("/TU (%s)\n" % self.name) # field name for the user-interface file.write("/TM (%s)\n" % self.name) # field name for exporting the data file.write("/V (%s)\n" % self.defaultvalue) # starting value file.write("/DV (%s)\n" % self.defaultvalue) # reset value file.write("/Ff %d\n" % self.formflag) # flags for various purposes ### the dictionary entries for the text field file.write("/DR ") self.registry.writeresources(file) # default resources for appearance file.write("/DA (%s /%s %f Tf %f TL)\n" % (self.fillstyles, self.font.name, self.fontsize, self.fontleading)) # default appearance string file.write("/Q %d\n" % self.alignflag) file.write(">>\n") # >>> class PDFdefaulttext(pdfwriter.PDFobject): # <<< def __init__(self, writer, registry, fontsize, font, fontleading, texts, bb, borderwidth, vcenter): pdfwriter.PDFobject.__init__(self, "defaulttext") self.font = font self.fontsize = fontsize self.fontleading = fontleading self.registry = pdfwriter.PDFregistry() self.registry.addresource("Font", self.font.name, self.font, procset="Text") self.registry.add(self.font) self.bb = (0, 0, bb[2] - bb[0], bb[3] - bb[1]) self.texts = [t for t in texts if t] self.borderwidth = borderwidth # try to imitate the shifting of PDF: # the font orientation point is on the baseline of the text self.hshift = 2*self.borderwidth if vcenter: baselinevrel = 0.215 self.vshift = 0.5 * (bb[3] - bb[1]) + (len(self.texts) / 2.0 - 1)*self.fontleading + baselinevrel*self.fontsize elif (bb[3] - bb[1]) < self.fontleading + 4*self.borderwidth: baselinevrel = 0.215 self.vshift = 2*self.borderwidth + baselinevrel * self.fontsize #self.vshift = 0.5 * (bb[3] - bb[1]) - (0.5 - baselinevrel - 0.5*addrelshift)*self.fontsize else: baselinevrel = 0.215 addrelshift = 0.215 self.vshift = (bb[3] - bb[1]) - 2*self.borderwidth - self.fontleading + (baselinevrel - addrelshift)*self.fontsize registry.mergeregistry(self.registry) def write(self, file, writer, registry): content = "/Tx BMC q BT /%s %f Tf %f TL %f %f Td (%s) Tj" % (self.font.name, self.fontsize, self.fontleading, self.hshift, self.vshift, self.texts[0]) for text in self.texts[1:]: content += " (%s)'" % (text) content += " ET Q EMC\n" if writer.compress: import zlib content = zlib.compress(content) file.write("<<\n") file.write("/Type /XObject\n") file.write("/Subtype /Form\n") file.write("/BBox [%f %f %f %f]\n" % self.bb) #ile.write("/Matrix [0.98 0.17 -0.17 0.98 0 0]\n") file.write("/Resources ") self.registry.writeresources(file) # default resources for appearance file.write("/Length %i\n" % len(content)) if writer.compress: file.write("/Filter /FlateDecode\n") file.write(">>\n" "stream\n") file.write(content) file.write("endstream\n") # >>> class radiobuttons(formfield): # <<< """A set of related buttons that can each be on or off. Typically, at most one radio button in a set may be on at any given time, and selecting any one of the buttons automatically deselects all the others. Note that the behaviour under rotations is undefined.""" defaultflags = dict(invisible=0, hidden=0, printable=1, nozoom=0, norotate=0, noview=0, readonly=0, required=0, noexport=0, notoggletooff=0) def __init__(self, positions, name, values, defaultvalue=None, size=10, baselinerelpos=0.2, **flags): self.name = name self.size_pt = _topt(size, "x", "pt") self.positions_pt = [(_topt(x), _topt(y) - baselinerelpos*self.size_pt) for x, y in positions] self.flags = self.selectflags(flags) self.flags["radio"] = 1 self.values = values self.defaultvalue = defaultvalue def bbox(self): llx = min([x[0] for x in self.positions_pt]) lly = min([x[1] for x in self.positions_pt]) urx = max([x[0] for x in self.positions_pt]) + self.size_pt ury = max([x[1] for x in self.positions_pt]) + self.size_pt return bbox.bbox_pt(llx, lly, urx, ury) def processPDF(self, file, writer, context, registry, bbox): # the bbox is transformed by the canvas bbox += self.bbox() # the annotation rectangle must be transformed separately: positions_pt = [context.trafo.apply_pt(x, y) for x, y in self.positions_pt] size_pt = _sizetrafo(self.size_pt, context.trafo) # we create numbers from the flags given annotflag, formflag = _pdfflags(self.flags) onstate = PDFButtonState(writer, registry, 10, PDFZapfDingbats, bgchar="m", fgchar="8", bgscale=1.1, bgrelshift=(0, 0.18), fgrelshift=(0.12, 0.26)) offstate = PDFButtonState(writer, registry, 10, PDFZapfDingbats, bgchar="m", fgchar=None, bgscale=1.1, bgrelshift=(0, 0.18)) registry.add(onstate) registry.add(offstate) registry.add(PDFbuttonlist(positions_pt, self.name, size_pt, self.values, self.defaultvalue, annotflag, formflag, onstate, offstate, writer, registry)) # >>> class checkbox(formfield): # <<< """Toggles between two states, on and off Note that the behaviour under rotations is undefined.""" defaultflags = dict(invisible=0, hidden=0, printable=1, nozoom=0, norotate=0, noview=0, readonly=0, required=0, noexport=0) def __init__(self, x, y, name, defaulton=0, size=10, baselinerelpos=0.2, **flags): self.name = name self.size_pt = _topt(size, "x", "pt") self.llx_pt, self.lly_pt = _topt(x), _topt(y) - baselinerelpos*self.size_pt self.urx_pt, self.ury_pt = self.llx_pt + self.size_pt, self.lly_pt + self.size_pt self.flags = self.selectflags(flags) self.defaulton = defaulton def processPDF(self, file, writer, context, registry, bbox): # the bbox is transformed by the canvas bbox += self.bbox() # the annotation rectangle must be transformed separately: positions_pt = [context.trafo.apply_pt(self.llx_pt, self.lly_pt)] size_pt = _sizetrafo(self.size_pt, context.trafo) # we create numbers from the flags given annotflag, formflag = _pdfflags(self.flags) onstate = PDFButtonState(writer, registry, 10, PDFZapfDingbats, bgchar="o", fgchar="4", bgscale=1.2, bgrelshift=(0, 0.08), fgscale=0.9, fgrelshift=(0.15, 0.25)) offstate = PDFButtonState(writer, registry, 10, PDFZapfDingbats, bgchar="o", fgchar=None, bgscale=1.2, bgrelshift=(0, 0.08)) registry.add(onstate) registry.add(offstate) if self.defaulton: default = "Yes" else: default = "Off" registry.add(PDFbuttonlist(positions_pt, self.name, size_pt, ["Yes"], default, annotflag, formflag, onstate, offstate, writer, registry)) # >>> class PDFbuttonlist(pdfwriter.PDFobject): # <<< def __init__(self, positions_pt, name, size_pt, values, defaultvalue, annotflag, formflag, onstate, offstate, writer, registry): pdfwriter.PDFobject.__init__(self, "formfield_buttonlist") # append this formfield to the global document form # but we do not treat this as a fully valid annotation field for object in registry.objects: if object.type == "form": object.append(self) self.name = name self.formflag = formflag self.annotflag = annotflag self.size_pt = size_pt self.defaultvalue = defaultvalue self.onstate = onstate self.offstate = offstate self.checkboxes = [] for i, pos_pt, value in zip(list(range(len(values))), positions_pt, values): chbox = PDFcheckboxfield(pos_pt, value, size_pt, _simplestring(value), (value == defaultvalue), self, self.onstate, self.offstate, self.annotflag, self.formflag, writer, registry) self.checkboxes.append(chbox) registry.add(chbox) def write(self, file, writer, registry): ### implementation note: There are some (undocumented) PDF flaws which ### do not allow to inherit certain variables: ### * The parent button may not have /Ff (otherwise, notoggletooff fails) ### * The Kids of a radio button may not have a /T on their own (otherwise, they are not displayed) ### * The /BS and /Border do not draw anything. ### Nevertheless, the border width of /Border is used ### the dictionary entries for the annotation file.write("<<\n") ### the dictionary entries for the form field file.write("/FT /Btn\n") # type of the form field file.write("/Kids [%s]\n" % " ".join(["%d 0 R" % registry.getrefno(x) for x in self.checkboxes])) file.write("/T (%s)\n" % self.name) # partial field name file.write("/TU (%s)\n" % self.name) # field name for the user-interface file.write("/TM (%s)\n" % self.name) # field name for exporting the data ### the dictionary entries for the radiobuttons field file.write("/V /%s\n" % self.defaultvalue) file.write(">>\n") # >>> class PDFcheckboxfield(pdfwriter.PDFobject): # <<< def __init__(self, pos_pt, name, size_pt, valuename, defaulton, parent, onstate, offstate, annotflag, formflag, writer, registry): pdfwriter.PDFobject.__init__(self, "formfield_checkbox") # we treat this as an annotation only, since the parent is # already in the form field self.PDFform = None for object in registry.objects: if object.type == "form": assert self.PDFform is None self.PDFform = object if object.type == "annotations": object.append(self) self.bb_pt = (pos_pt[0], pos_pt[1], pos_pt[0] + size_pt, pos_pt[1] + size_pt) self.name = name self.size_pt = size_pt self.valuename = valuename if defaulton: self.defaultvalue = self.valuename else: self.defaultvalue = "Off" self.parent = parent self.onstate = onstate self.offstate = offstate self.annotflag = annotflag self.formflag = formflag def write(self, file, writer, registry): ### the dictionary entries for the annotation file.write("<<\n") file.write("/Type /Annot\n") file.write("/Subtype /Widget\n") file.write("/P %d 0 R\n" % registry.getrefno(self.PDFform)) # reference to the page objects file.write("/Rect [%f %f %f %f]\n" % self.bb_pt) # the annotation rectangle file.write("/F %d\n" % self.annotflag) # flags ### the dictionary entries for the widget annotations file.write("/H /N\n") # hightlight behaviour ### the dictionary entries for the form field file.write("/FT /Btn\n") # type of the form field file.write("/Parent %d 0 R\n" % registry.getrefno(self.parent)) # only for hierarchy file.write("/AP << /N << /%s %d 0 R /Off %d 0 R >> >>\n" % (self.valuename, registry.getrefno(self.onstate), registry.getrefno(self.offstate))) file.write("/AS /%s\n" % self.defaultvalue) file.write("/Ff %d\n" % self.formflag) # Ff may not come from parent! file.write(">>\n") # >>> class PDFButtonState(pdfwriter.PDFobject): # <<< def __init__(self, writer, registry, fontsize, font, bgchar, fgchar, bgscale=None, bgrelshift=None, fgscale=None, fgrelshift=None): pdfwriter.PDFobject.__init__(self, "buttonstate", "buttonstate" + "_".join(map(str, list(map(id, [fontsize, font, bgchar, fgchar, bgscale, bgrelshift, fgscale, fgrelshift]))))) self.font = font self.fontsize = fontsize registry.addresource("Font", self.font.name, self.font, procset="Text") registry.add(self.font) self.bb = 0, 0, fontsize, fontsize self.bgchar = bgchar self.fgchar = fgchar if bgscale is None and bgrelshift is not None: bgscale = 1 if bgscale is not None and bgrelshift is None: bgrelshift = 0, 0 if bgscale is not None: self.bgtrafo = "%f 0 0 %f %f %f Tm" % (bgscale, bgscale, bgrelshift[0]*self.fontsize, bgrelshift[1]*self.fontsize) else: self.bgtrafo = "" if fgscale is None and fgrelshift is not None: fgscale = 1 if fgscale is not None and fgrelshift is None: fgrelshift = 0, 0 if fgscale is not None: self.fgtrafo = "%f 0 0 %f %f %f Tm" % (fgscale, fgscale, fgrelshift[0]*self.fontsize, fgrelshift[1]*self.fontsize) else: self.fgtrafo = "" def write(self, file, writer, registry): content = "" if self.bgchar: content += "q BT /%s %f Tf %s (%s) Tj ET Q\n" % (self.font.name, self.fontsize, self.bgtrafo, self.bgchar) if self.fgchar: content += "q BT /%s %f Tf %s (%s) Tj ET Q\n" % (self.font.name, self.fontsize, self.fgtrafo, self.fgchar) if writer.compress: import zlib content = zlib.compress(content) file.write("<<\n") file.write("/Type /XObject\n") file.write("/Subtype /Form\n") file.write("/BBox [%f %f %f %f]\n" % self.bb) #ile.write("/Matrix [0.98 0.17 -0.17 0.98 0 0]\n") file.write("/Resources <> /ProcSet [/PDF /Text] >>\n" % (self.font.name, registry.getrefno(self.font))) file.write("/Length %i\n" % len(content)) if writer.compress: file.write("/Filter /FlateDecode\n") file.write(">>\n" "stream\n") file.write(content) file.write("endstream\n") ## Zapf Dingbats symbols for further buttonstates: # "3" = thin checkmark # "4" = thick checkmark # "5" = thin large cross # "6" = thick large cross # "7" = thin small cross # "8" = thick small cross # "l" = filled circle # "m" = empty circle # "n" = filled rectangle # "o" = empty rectangle (shadow bottom right) # "p" = empty rectangle (shadow top right) # "q" = empty box (to bottom right) # "r" = empty box (to top right) # >>> class choicefield(formfield): # <<< """An interactive pdf form field for text input. The name is used for the graphical user interface and for exporing the input data. Note that the behaviour under rotations is undefined.""" defaultflags = dict(invisible=0, hidden=0, printable=1, nozoom=0, norotate=0, noview=0, readonly=0, required=0, noexport=0, combo=1, edit=0, sort=0, multiselect=0, donotspellcheck=1) def __init__(self, x, y, width, height, name, values, defaultvalue=None, fontsize=10, font=None, borderwidth=0, align="l", **flags): self.llx_pt, self.lly_pt = _topt(x), _topt(y) self.urx_pt, self.ury_pt = _topt(x+width), _topt(y+height) self.name = name self.values = values self.defaultvalue = defaultvalue self.fontsize_pt = _topt(fontsize, "x", "pt") self.font = font # TODO: add the generic fonts self.borderwidth_pt = _topt(borderwidth, "x", "pt") self.flags = self.selectflags(flags) self.align = align def processPDF(self, file, writer, context, registry, bbox): # the bounding box is transformed by the canvas bbox += self.bbox() # the annotation rectangle must be transformed separately: llx_pt, lly_pt = context.trafo.apply_pt(self.llx_pt, self.lly_pt) urx_pt, ury_pt = context.trafo.apply_pt(self.urx_pt, self.ury_pt) fontsize_pt = _sizetrafo(self.fontsize_pt, context.trafo) borderwidth_pt = _sizetrafo(self.borderwidth_pt, context.trafo) # we create numbers from the flags given annotflag, formflag = _pdfflags(self.flags) alignflag = _pdfalignment(self.align) registry.add(PDFchoicefield((llx_pt, lly_pt, urx_pt, ury_pt), self.name, self.values, self.defaultvalue, fontsize_pt, self.font, borderwidth_pt, alignflag, annotflag, formflag, writer, registry)) # >>> class PDFchoicefield(pdfwriter.PDFobject): # <<< def __init__(self, bb_pt, name, values, defaultvalue, fontsize, font, borderwidth_pt, alignflag, annotflag, formflag, writer, registry): pdfwriter.PDFobject.__init__(self, "formfield_choice") # append this formfield to the global document form # and to the annotation list of the page: self.PDFform = None for object in registry.objects: if object.type == "form": object.append(self) self.PDFform = object elif object.type == "annotations": object.append(self) self.name = name self.bb_pt = bb_pt self.values = values self.defaultvalue = defaultvalue self.fontsize = fontsize self.font = font if self.font is None: self.font = PDFHelvetica registry.addresource("Font", self.font.name, self.font, procset="Text") registry.add(self.font) self.borderwidth_pt = borderwidth_pt self.alignflag = alignflag self.formflag = formflag self.annotflag = annotflag def write(self, file, writer, registry): ### the dictionary entries for the annotation file.write("<>\n" # border style dictionary file.write("/Border [0 0 %f]\n" % self.borderwidth_pt) # border style file.write("/F %d\n" % self.annotflag) ### the dictionary entries for the widget annotations file.write("/Subtype /Widget\n") file.write("/H /N\n") # highlight behaviour #ile.write("/AP <>\n") # appearance dictionary TODO ### the dictionary entries for the form field file.write("/FT /Ch\n") # type of the form field file.write("/T (%s)\n" % self.name) # partial field name file.write("/TU (%s)\n" % self.name) # field name for the user-interface file.write("/TM (%s)\n" % self.name) # field name for exporting the data if self.defaultvalue in self.values: file.write("/V (%s)\n" % self.defaultvalue) # starting value file.write("/Ff %d\n" % self.formflag) # flags for various purposes ### the dictionary entries for the text field file.write("/DR <> >>\n" % (self.font.name, registry.getrefno(self.font))) # default resources for appearance file.write("/DA (/%s %f Tf)\n" % (self.font.name, self.fontsize)) # default appearance string file.write("/Q %d\n" % self.alignflag) file.write("/Opt [") for value in self.values: file.write(" (%s)" % value) file.write(" ]\n") file.write(">>\n") # >>> # vim:foldmethod=marker:foldmarker=<<<,>>> PyX-0.14.1/pyx/pdfwriter.py0000644000076500000240000003276312177540640015752 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 Jörg Lehmann # Copyright (C) 2007 Michael Schindler # Copyright (C) 2005-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, copy, logging, time logger = logging.getLogger("pyx") try: import zlib haszlib = True except: haszlib = False from . import bbox, config, style, unit, version, trafo, writer class PDFregistry: def __init__(self): self.types = {} # we want to keep the order of the resources self.objects = [] self.resources = {} self.procsets = {"PDF": 1} self.merged = None def add(self, object): """ register object, merging it with an already registered object of the same type and id """ sameobjects = self.types.setdefault(object.type, {}) if object.id in sameobjects: sameobjects[object.id].merge(object) else: self.objects.append(object) sameobjects[object.id] = object def getrefno(self, object): if self.merged: return self.merged.getrefno(object) else: return self.types[object.type][object.id].refno def mergeregistry(self, registry): for object in registry.objects: self.add(object) registry.merged = self def write(self, file, writer, catalog): # first we set all refnos refno = 1 for object in self.objects: object.refno = refno refno += 1 # second, all objects are written, keeping the positions in the output file fileposes = [] for object in self.objects: fileposes.append(file.tell()) file.write("%i 0 obj\n" % object.refno) object.write(file, writer, self) file.write("endobj\n") # xref xrefpos = file.tell() file.write("xref\n" "0 %d\n" "0000000000 65535 f \n" % refno) for filepos in fileposes: file.write("%010i 00000 n \n" % filepos) # trailer file.write("trailer\n" "<<\n" "/Size %i\n" % refno) file.write("/Root %i 0 R\n" % self.getrefno(catalog)) file.write("/Info %i 0 R\n" % self.getrefno(catalog.PDFinfo)) file.write(">>\n" "startxref\n" "%i\n" % xrefpos) file.write("%%EOF\n") def addresource(self, resourcetype, resourcename, object, procset=None): self.resources.setdefault(resourcetype, {})[resourcename] = object if procset: self.procsets[procset] = 1 def writeresources(self, file): file.write("<<\n") file.write("/ProcSet [ %s ]\n" % " ".join(["/%s" % p for p in list(self.procsets.keys())])) if self.resources: for resourcetype, resources in list(self.resources.items()): file.write("/%s <<\n%s\n>>\n" % (resourcetype, "\n".join(["/%s %i 0 R" % (name, self.getrefno(object)) for name, object in list(resources.items())]))) file.write(">>\n") class PDFobject: def __init__(self, type, _id=None): """create a PDFobject - type has to be a string describing the type of the object - _id is a unique identification used for the object if it is not None. Otherwise id(self) is used """ self.type = type if _id is None: self.id = id(self) else: self.id = _id def merge(self, other): pass def write(self, file, writer, registry): raise NotImplementedError("write method has to be provided by PDFobject subclass") class PDFcatalog(PDFobject): def __init__(self, document, writer, registry): PDFobject.__init__(self, "catalog") self.PDFform = PDFform(writer, registry) registry.add(self.PDFform) self.PDFpages = PDFpages(document, writer, registry) registry.add(self.PDFpages) self.PDFinfo = PDFinfo() registry.add(self.PDFinfo) def write(self, file, writer, registry): file.write("<<\n" "/Type /Catalog\n" "/Pages %i 0 R\n" % registry.getrefno(self.PDFpages)) if not self.PDFform.empty(): file.write("/AcroForm %i 0 R\n" % registry.getrefno(self.PDFform)) if writer.fullscreen: file.write("/PageMode /FullScreen\n") file.write(">>\n") class PDFinfo(PDFobject): def __init__(self): PDFobject.__init__(self, "info") def write(self, file, writer, registry): if time.timezone < 0: # divmod on positive numbers, otherwise the minutes have a different sign from the hours timezone = "-%02i'%02i'" % divmod(-time.timezone/60, 60) elif time.timezone > 0: timezone = "+%02i'%02i'" % divmod(time.timezone/60, 60) else: timezone = "Z00'00'" def pdfstring(s): r = "" for c in s: if 32 <= ord(c) <= 127 and c not in "()[]<>\\": r += c else: r += "\\%03o" % ord(c) return r file.write("<<\n") if writer.title: file.write("/Title (%s)\n" % pdfstring(writer.title)) if writer.author: file.write("/Author (%s)\n" % pdfstring(writer.author)) if writer.subject: file.write("/Subject (%s)\n" % pdfstring(writer.subject)) if writer.keywords: file.write("/Keywords (%s)\n" % pdfstring(writer.keywords)) file.write("/Creator (PyX %s)\n" % version.version) file.write("/CreationDate (D:%s%s)\n" % (time.strftime("%Y%m%d%H%M"), timezone)) file.write(">>\n") class PDFpages(PDFobject): def __init__(self, document, writer, registry): PDFobject.__init__(self, "pages") self.PDFpagelist = [] for pageno, page in enumerate(document.pages): page = PDFpage(page, pageno, self, writer, registry) registry.add(page) self.PDFpagelist.append(page) def write(self, file, writer, registry): file.write("<<\n" "/Type /Pages\n" "/Kids [%s]\n" "/Count %i\n" ">>\n" % (" ".join(["%i 0 R" % registry.getrefno(page) for page in self.PDFpagelist]), len(self.PDFpagelist))) class PDFpage(PDFobject): def __init__(self, page, pageno, PDFpages, writer, registry): PDFobject.__init__(self, "page") self.PDFpages = PDFpages self.page = page # every page uses its own registry in order to find out which # resources are used within the page. However, the # pageregistry is also merged in the global registry self.pageregistry = PDFregistry() self.pageregistry.add(self) self.PDFannotations = PDFannotations() self.pageregistry.add(self.PDFannotations) # we eventually need the form dictionary to append formfields for object in registry.objects: if object.type == "form": self.pageregistry.add(object) self.PDFcontent = PDFcontent(page, writer, self.pageregistry) self.pageregistry.add(self.PDFcontent) registry.mergeregistry(self.pageregistry) def write(self, file, writer, registry): file.write("<<\n" "/Type /Page\n" "/Parent %i 0 R\n" % registry.getrefno(self.PDFpages)) paperformat = self.page.paperformat if paperformat: file.write("/MediaBox [0 0 %f %f]\n" % (unit.topt(paperformat.width), unit.topt(paperformat.height))) else: file.write("/MediaBox [%f %f %f %f]\n" % self.PDFcontent.bbox.highrestuple_pt()) if self.PDFcontent.bbox and writer.writebbox: file.write("/CropBox [%f %f %f %f]\n" % self.PDFcontent.bbox.highrestuple_pt()) if self.page.rotated: file.write("/Rotate 90\n") if not self.PDFannotations.empty(): file.write("/Annots %i 0 R\n" % registry.getrefno(self.PDFannotations)) file.write("/Contents %i 0 R\n" % registry.getrefno(self.PDFcontent)) file.write("/Resources ") self.pageregistry.writeresources(file) file.write(">>\n") class PDFcontent(PDFobject): def __init__(self, page, awriter, registry): PDFobject.__init__(self, registry, "content") contentfile = writer.writer(io.BytesIO()) self.bbox = bbox.empty() acontext = context() page.processPDF(contentfile, awriter, acontext, registry, self.bbox) self.content = contentfile.file.getvalue() def write(self, file, awriter, registry): if awriter.compress: content = zlib.compress(self.content) else: content = self.content file.write("<<\n" "/Length %i\n" % len(content)) if awriter.compress: file.write("/Filter /FlateDecode\n") file.write(">>\n" "stream\n") file.write_bytes(content) file.write("endstream\n") class PDFwriter: def __init__(self, document, file, title=None, author=None, subject=None, keywords=None, fullscreen=False, writebbox=False, compress=True, compresslevel=6, strip_fonts=True, text_as_path=False, mesh_as_bitmap=False, mesh_as_bitmap_resolution=300): self._fontmap = None self.title = title self.author = author self.subject = subject self.keywords = keywords self.fullscreen = fullscreen self.writebbox = writebbox if compress and not haszlib: compress = 0 logger.warning("PDFwriter: compression disabled due to missing zlib module") self.compress = compress self.compresslevel = compresslevel self.strip_fonts = strip_fonts self.text_as_path = text_as_path self.mesh_as_bitmap = mesh_as_bitmap self.mesh_as_bitmap_resolution = mesh_as_bitmap_resolution # dictionary mapping font names to dictionaries mapping encoding names to encodings # encodings themselves are mappings from glyphnames to codepoints self.encodings = {} # the PDFcatalog class automatically builds up the pdfobjects from a document registry = PDFregistry() catalog = PDFcatalog(document, self, registry) registry.add(catalog) file = writer.writer(file) file.write_bytes(b"%PDF-1.4\n%\xc3\xb6\xc3\xa9\n") registry.write(file, self, catalog) def getfontmap(self): if self._fontmap is None: # late import due to cyclic dependency from pyx.dvi import mapfile fontmapfiles = config.getlist("text", "pdffontmaps", ["pdftex.map"]) self._fontmap = mapfile.readfontmap(fontmapfiles) return self._fontmap class PDFannotations(PDFobject): def __init__(self): PDFobject.__init__(self, "annotations") self.annots = [] def append(self, item): if item not in self.annots: self.annots.append(item) def empty(self): return len(self.annots) == 0 def write(self, file, writer, registry): # XXX problem: This object will be written to the file even if it is useless (empty) file.write("[ %s ]\n" % " ".join(["%d 0 R" % registry.getrefno(annot) for annot in self.annots])) class PDFform(PDFobject): def __init__(self, writer, registry): PDFobject.__init__(self, "form") self.fields = [] def merge(self, other): for field in other.fields: self.append(field) def append(self, field): if field not in self.fields: self.fields.append(field) def empty(self): return len(self.fields) == 0 def write(self, file, writer, registry): # XXX problem: This object will be written to the file even if it is useless (empty) file.write("<<") file.write("/Fields [") for field in self.fields: file.write(" %d 0 R" % registry.getrefno(field)) file.write(" ]\n") file.write(">>\n") class context: def __init__(self): self.linewidth_pt = None # XXX there are both stroke and fill color spaces self.colorspace = None self.strokeattr = 1 self.fillattr = 1 self.selectedfont = None self.trafo = trafo.trafo() self.fillstyles = [] self.fillrule = 0 def __call__(self, **kwargs): newcontext = copy.copy(self) for key, value in list(kwargs.items()): setattr(newcontext, key, value) return newcontext PyX-0.14.1/pyx/pswriter.py0000644000076500000240000002166512177540640015622 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2005-2011 Jörg Lehmann # Copyright (C) 2005-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, copy, time, math from . import bbox, config, style, version, unit, trafo, writer class PSregistry: def __init__(self): # in order to keep a consistent order of the registered resources we # not only store them in a hash but also keep an ordered list (up to a # possible merging of resources, in which case the first instance is # kept) self.resourceshash = {} self.resourceslist = [] def add(self, resource): rkey = (resource.type, resource.id) if rkey in self.resourceshash: self.resourceshash[rkey].merge(resource) else: self.resourceshash[rkey] = resource self.resourceslist.append(resource) def mergeregistry(self, registry): for resource in registry.resources: self.add(resource) def output(self, file, writer): """ write all PostScript code of the prolog resources """ for resource in self.resourceslist: resource.output(file, writer, self) # # Abstract base class # class PSresource: """ a PostScript resource """ def __init__(self, type, id): # Every PSresource has to have a type and a unique id. # Resources with the same type and id will be merged # when they are registered in the PSregistry self.type = type self.id = id def merge(self, other): """ merge self with other, which has to be a resource of the same type and with the same id""" pass def output(self, file, writer, registry): raise NotImplementedError("output not implemented for %s" % repr(self)) class PSdefinition(PSresource): """ PostScript function definition included in the prolog """ def __init__(self, id, body): self.type = "definition" self.id = id self.body = body def output(self, file, writer, registry): file.write("%%%%BeginResource: %s\n" % self.id) file.write_bytes(self.body) file.write(" /%s exch def\n" % self.id) file.write("%%EndResource\n") # # Writers # class _PSwriter: def __init__(self, title=None, strip_fonts=True, text_as_path=False, mesh_as_bitmap=False, mesh_as_bitmap_resolution=300): self._fontmap = None self.title = title self.strip_fonts = strip_fonts self.text_as_path = text_as_path self.mesh_as_bitmap = mesh_as_bitmap self.mesh_as_bitmap_resolution = mesh_as_bitmap_resolution # dictionary mapping font names to dictionaries mapping encoding names to encodings # encodings themselves are mappings from glyphnames to codepoints self.encodings = {} def writeinfo(self, file): file.write("%%%%Creator: PyX %s\n" % version.version) if self.title is not None: file.write("%%%%Title: %s\n" % self.title) file.write("%%%%CreationDate: %s\n" % time.asctime(time.localtime(time.time()))) def getfontmap(self): if self._fontmap is None: # late import due to cyclic dependency from pyx.dvi import mapfile fontmapfiles = config.getlist("text", "psfontmaps", ["psfonts.map"]) self._fontmap = mapfile.readfontmap(fontmapfiles) return self._fontmap class EPSwriter(_PSwriter): def __init__(self, document, file, **kwargs): _PSwriter.__init__(self, **kwargs) file = writer.writer(file) if len(document.pages) != 1: raise ValueError("EPS file can be constructed out of a single page document only") page = document.pages[0] canvas = page.canvas pagefile = writer.writer(io.BytesIO()) registry = PSregistry() acontext = context() pagebbox = bbox.empty() page.processPS(pagefile, self, acontext, registry, pagebbox) file.write("%!PS-Adobe-3.0 EPSF-3.0\n") if pagebbox: file.write("%%%%BoundingBox: %d %d %d %d\n" % pagebbox.lowrestuple_pt()) file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % pagebbox.highrestuple_pt()) self.writeinfo(file) file.write("%%EndComments\n") file.write("%%BeginProlog\n") registry.output(file, self) file.write("%%EndProlog\n") file.write_bytes(pagefile.file.getvalue()) file.write("showpage\n") file.write("%%Trailer\n") file.write("%%EOF\n") class PSwriter(_PSwriter): def __init__(self, document, file, writebbox=False, **kwargs): _PSwriter.__init__(self, **kwargs) file = writer.writer(file) # We first have to process the content of the pages, writing them into the stream pagesfile # Doing so, we fill the registry and also calculate the page bounding boxes, which are # stored in page._bbox for every page pagesfile = writer.writer(io.BytesIO()) registry = PSregistry() # calculated bounding boxes of the whole document documentbbox = bbox.empty() for nr, page in enumerate(document.pages): # process contents of page pagefile = writer.writer(io.BytesIO()) acontext = context() pagebbox = bbox.empty() page.processPS(pagefile, self, acontext, registry, pagebbox) documentbbox += pagebbox pagesfile.write("%%%%Page: %s %d\n" % (page.pagename is None and str(nr+1) or page.pagename, nr+1)) if page.paperformat: pagesfile.write("%%%%PageMedia: %s\n" % page.paperformat.name) pagesfile.write("%%%%PageOrientation: %s\n" % (page.rotated and "Landscape" or "Portrait")) if pagebbox and writebbox: pagesfile.write("%%%%PageBoundingBox: %d %d %d %d\n" % pagebbox.lowrestuple_pt()) # page setup section pagesfile.write("%%BeginPageSetup\n") pagesfile.write("/pgsave save def\n") pagesfile.write("%%EndPageSetup\n") pagesfile.write_bytes(pagefile.file.getvalue()) pagesfile.write("pgsave restore\n") pagesfile.write("showpage\n") pagesfile.write("%%PageTrailer\n") file.write("%!PS-Adobe-3.0\n") if documentbbox and writebbox: file.write("%%%%BoundingBox: %d %d %d %d\n" % documentbbox.lowrestuple_pt()) file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % documentbbox.highrestuple_pt()) self.writeinfo(file) # required paper formats paperformats = {} for page in document.pages: if page.paperformat: paperformats[page.paperformat] = page.paperformat first = 1 for paperformat in list(paperformats.values()): if first: file.write("%%DocumentMedia: ") first = 0 else: file.write("%%+ ") file.write("%s %d %d 75 white ()\n" % (paperformat.name, unit.topt(paperformat.width), unit.topt(paperformat.height))) # file.write(%%DocumentNeededResources: ") # register not downloaded fonts here file.write("%%%%Pages: %d\n" % len(document.pages)) file.write("%%PageOrder: Ascend\n") file.write("%%EndComments\n") # document defaults section #file.write("%%BeginDefaults\n") #file.write("%%EndDefaults\n") # document prolog section file.write("%%BeginProlog\n") registry.output(file, self) file.write("%%EndProlog\n") # document setup section #file.write("%%BeginSetup\n") #file.write("%%EndSetup\n") file.write_bytes(pagesfile.file.getvalue()) file.write("%%Trailer\n") file.write("%%EOF\n") class context: def __init__(self): self.linewidth_pt = None self.colorspace = None self.selectedfont = None self.fillrule = 0 def __call__(self, **kwargs): newcontext = copy.copy(self) for key, value in list(kwargs.items()): setattr(newcontext, key, value) return newcontext PyX-0.14.1/pyx/pykpathsea.c0000644000076500000240000001256312171330402015666 0ustar andrestaff00000000000000/* pykpathsea.c: Copyright 2003-2011 Jörg Lehmann, André Wobst * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include static PyObject *py_kpse_find_file(PyObject *self, PyObject *args) { char *filename; char *format; char *completefilename; PyObject *returnvalue; kpse_file_format_type kpse_file_format; if (PyArg_ParseTuple(args, "ss", &filename, &format)) { /* if (!strcmp(format, "gf")) kpse_file_format = kpse_gf_format; else */ /* if (!strcmp(format, "pk")) kpse_file_format = kpse_pk_format; else */ /* if (!strcmp(format, "bitmap font")) kpse_file_format = kpse_any_glyph_format; else */ if (!strcmp(format, "tfm")) kpse_file_format = kpse_tfm_format; else if (!strcmp(format, "afm")) kpse_file_format = kpse_afm_format; else /* if (!strcmp(format, "base")) kpse_file_format = kpse_base_format; else */ /* if (!strcmp(format, "bib")) kpse_file_format = kpse_bib_format; else */ /* if (!strcmp(format, "bst")) kpse_file_format = kpse_bst_format; else */ /* if (!strcmp(format, "cnf")) kpse_file_format = kpse_cnf_format; else */ /* if (!strcmp(format, "ls-R")) kpse_file_format = kpse_db_format; else */ /* if (!strcmp(format, "fmt")) kpse_file_format = kpse_fmt_format; else */ if (!strcmp(format, "map")) kpse_file_format = kpse_fontmap_format; else /* if (!strcmp(format, "mem")) kpse_file_format = kpse_mem_format; else */ /* if (!strcmp(format, "mf")) kpse_file_format = kpse_mf_format; else */ /* if (!strcmp(format, "mfpool")) kpse_file_format = kpse_mfpool_format; else */ /* if (!strcmp(format, "mft")) kpse_file_format = kpse_mft_format; else */ /* if (!strcmp(format, "mp")) kpse_file_format = kpse_mp_format; else */ /* if (!strcmp(format, "mppool")) kpse_file_format = kpse_mppool_format; else */ /* if (!strcmp(format, "MetaPost support")) kpse_file_format = kpse_mpsupport_format; else */ /* if (!strcmp(format, "ocp")) kpse_file_format = kpse_ocp_format; else */ /* if (!strcmp(format, "ofm")) kpse_file_format = kpse_ofm_format; else */ /* if (!strcmp(format, "opl")) kpse_file_format = kpse_opl_format; else */ /* if (!strcmp(format, "otp")) kpse_file_format = kpse_otp_format; else */ /* if (!strcmp(format, "ovf")) kpse_file_format = kpse_ovf_format; else */ /* if (!strcmp(format, "ovp")) kpse_file_format = kpse_ovp_format; else */ if (!strcmp(format, "graphic/figure")) kpse_file_format = kpse_pict_format; else /* if (!strcmp(format, "tex")) kpse_file_format = kpse_tex_format; else */ /* if (!strcmp(format, "TeX system documentation")) kpse_file_format = kpse_texdoc_format; else */ /* if (!strcmp(format, "texpool")) kpse_file_format = kpse_texpool_format; else */ /* if (!strcmp(format, "TeX system sources")) kpse_file_format = kpse_texsource_format; else */ if (!strcmp(format, "PostScript header")) kpse_file_format = kpse_tex_ps_header_format; else /* if (!strcmp(format, "Troff fonts")) kpse_file_format = kpse_troff_font_format; else */ if (!strcmp(format, "type1 fonts")) kpse_file_format = kpse_type1_format; else if (!strcmp(format, "vf")) kpse_file_format = kpse_vf_format; else if (!strcmp(format, "dvips config")) kpse_file_format = kpse_dvips_config_format; else /* if (!strcmp(format, "ist")) kpse_file_format = kpse_ist_format; else */ /* if (!strcmp(format, "truetype fonts")) kpse_file_format = kpse_truetype_format; else */ /* if (!strcmp(format, "type42 fonts")) kpse_file_format = kpse_type42_format; else */ /* if (!strcmp(format, "web2c files")) kpse_file_format = kpse_web2c_format; else */ /* if (!strcmp(format, "other text files")) kpse_file_format = kpse_program_text_format; else */ /* if (!strcmp(format, "other binary files")) kpse_file_format = kpse_program_binary_format; else */ /* if (!strcmp(format, "misc fonts")) kpse_file_format = kpse_miscfonts_format; else */ return NULL; completefilename = kpse_find_file(filename, kpse_file_format, 1); returnvalue = Py_BuildValue("s", completefilename); /* XXX: free(completefilename); */ return returnvalue; } return NULL; } /* exported methods */ static PyMethodDef pykpathsea_methods[] = { {"find_file", (PyCFunction) py_kpse_find_file, METH_VARARGS, NULL}, {NULL, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "pykpathsea", NULL, -1, pykpathsea_methods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_pykpathsea(void) { PyObject *module = PyModule_Create(&moduledef); if (module == NULL) return NULL; kpse_set_program_name("dvips", "dvips"); return module; } PyX-0.14.1/pyx/reader.py0000644000076500000240000001353612177540640015203 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2007-2011 Jörg Lehmann # Copyright (C) 2007-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, struct class reader: def __init__(self, filename): self.file = open(filename, "rb") def tell(self): return self.file.tell() def eof(self): return self.file.eof() def read(self, bytes): return self.file.read(bytes) def readint(self, bytes=4, signed=0): first = 1 result = 0 while bytes: value = ord(self.file.read(1)) if first and signed and value > 127: value -= 256 first = 0 result = 256 * result + value bytes -= 1 return result def readint32(self): return struct.unpack(">l", self.file.read(4))[0] def readuint32(self): return struct.unpack(">L", self.file.read(4))[0] def readint24(self): return struct.unpack(">l", b"\0"+self.file.read(3))[0] def readuint24(self): return struct.unpack(">L", b"\0"+self.file.read(3))[0] def readint16(self): return struct.unpack(">h", self.file.read(2))[0] def readuint16(self): return struct.unpack(">H", self.file.read(2))[0] def readchar(self): return struct.unpack("b", self.file.read(1))[0] def readuchar(self): return struct.unpack("B", self.file.read(1))[0] def readstring(self, bytes): l = self.readuchar() assert l <= bytes-1, "inconsistency in file: string too long" return self.file.read(bytes-1)[:l] def close(self): self.file.close() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): return self.file.__exit__(exc_type, exc_value, traceback) class bytesreader(reader): def __init__(self, b): self.file = io.BytesIO(b) class PStokenizer: """cursor to read a string token by token""" def __init__(self, data, startstring=None, eattokensep=1, tokenseps=" \t\r\n", tokenstarts="()<>[]{}/%", commentchar="%", newlinechars="\r\n"): """creates a cursor for the string data startstring is a string at which the cursor should start at. The first ocurance of startstring is used. When startstring is not in data, an exception is raised, otherwise the cursor is set to the position right after the startstring. When eattokenseps is set, startstring must be followed by a tokensep and this first tokensep is also consumed. tokenseps is a string containing characters to be used as token separators. tokenstarts is a string containing characters which directly (even without intermediate token separator) start a new token. """ self.data = data if startstring is not None: self.pos = self.data.index(startstring) + len(startstring) else: self.pos = 0 self.tokenseps = tokenseps self.tokenstarts = tokenstarts self.commentchar = commentchar self.newlinechars = newlinechars if eattokensep: if self.data[self.pos] not in self.tokenstarts: if self.data[self.pos] not in self.tokenseps: raise ValueError("cursor initialization string is not followed by a token separator") self.pos += 1 def gettoken(self): """get the next token Leading token separators and comments are silently consumed. The first token separator after the token is also silently consumed.""" while self.data[self.pos] in self.tokenseps: self.pos += 1 # ignore comments including subsequent whitespace characters while self.data[self.pos] == self.commentchar: while self.data[self.pos] not in self.newlinechars: self.pos += 1 while self.data[self.pos] in self.tokenseps: self.pos += 1 startpos = self.pos while self.data[self.pos] not in self.tokenseps: # any character in self.tokenstarts ends the token if self.pos>startpos and self.data[self.pos] in self.tokenstarts: break self.pos += 1 result = self.data[startpos:self.pos] if self.data[self.pos] in self.tokenseps: self.pos += 1 # consume a single tokensep return result def getint(self): """get the next token as an integer""" return int(self.gettoken()) def getbytes(self, count): """get the next count bytes""" startpos = self.pos self.pos += count return self.data[startpos: self.pos] class PSbytes_tokenizer(PStokenizer): def __init__(self, data, startstring=None, eattokensep=1, tokenseps=b" \t\r\n", tokenstarts=b"()<>[]{}/%", commentchar=b"%", newlinechars=b"\r\n"): super().__init__(data, startstring=startstring, eattokensep=eattokensep, tokenseps=tokenseps, tokenstarts=tokenstarts, commentchar=commentchar, newlinechars=newlinechars) PyX-0.14.1/pyx/style.py0000644000076500000240000002104712517522665015102 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2003-2006 Michael Schindler # Copyright (C) 2002-2012 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from . import attr, unit # # base classes for stroke and fill styles # class style: pass class strokestyle(style): pass class fillstyle(style): pass # # common stroke styles # class linecap(attr.exclusiveattr, strokestyle): """linecap of paths""" def __init__(self, value=0): attr.exclusiveattr.__init__(self, linecap) self.value = value def processPS(self, file, writer, context, registry): file.write("%d setlinecap\n" % self.value) def processPDF(self, file, writer, context, registry): file.write("%d J\n" % self.value) def processSVGattrs(self, attrs, writer, context, registry): attrs["stroke-linecap"] = {0: "butt", 1: "round", 2: "square"}[self.value] linecap.butt = linecap(0) linecap.round = linecap(1) linecap.square = linecap(2) linecap.clear = attr.clearclass(linecap) class linejoin(attr.exclusiveattr, strokestyle): """linejoin of paths""" def __init__(self, value=0): attr.exclusiveattr.__init__(self, linejoin) self.value = value def processPS(self, file, writer, context, registry): file.write("%d setlinejoin\n" % self.value) def processPDF(self, file, writer, context, registry): file.write("%d j\n" % self.value) def processSVGattrs(self, attrs, writer, context, registry): attrs["stroke-linejoin"] = {0: "miter", 1: "round", 2: "bevel"}[self.value] linejoin.miter = linejoin(0) linejoin.round = linejoin(1) linejoin.bevel = linejoin(2) linejoin.clear = attr.clearclass(linejoin) class miterlimit(attr.exclusiveattr, strokestyle): """miterlimit of paths""" def __init__(self, value=10.0): attr.exclusiveattr.__init__(self, miterlimit) self.value = value def processPS(self, file, writer, context, registry): file.write("%f setmiterlimit\n" % self.value) def processPDF(self, file, writer, context, registry): file.write("%f M\n" % self.value) def processSVGattrs(self, attrs, writer, context, registry): attrs["stroke-miterlimit"] = "%f" % self.value miterlimit.lessthan180deg = miterlimit(1/math.sin(math.pi*180/360)) miterlimit.lessthan90deg = miterlimit(1/math.sin(math.pi*90/360)) miterlimit.lessthan60deg = miterlimit(1/math.sin(math.pi*60/360)) miterlimit.lessthan45deg = miterlimit(1/math.sin(math.pi*45/360)) miterlimit.lessthan11deg = miterlimit(10) # the default, approximately 11.4783 degress miterlimit.clear = attr.clearclass(miterlimit) _defaultlinewidth = 0.02 * unit.w_cm _defaultlinewidth_pt = unit.topt(_defaultlinewidth) class dash(attr.exclusiveattr, strokestyle): """dash of paths""" def __init__(self, pattern=[], offset=0, rellengths=1): """set pattern with offset. If rellengths is True, interpret all dash lengths relative to current linewidth. """ attr.exclusiveattr.__init__(self, dash) self.pattern = pattern self.offset = offset self.rellengths = rellengths def processPS(self, file, writer, context, registry): if self.rellengths: patternstring = " ".join(["%f" % (element * context.linewidth_pt/_defaultlinewidth_pt) for element in self.pattern]) else: patternstring = " ".join(["%f" % element for element in self.pattern]) file.write("[%s] %f setdash\n" % (patternstring, self.offset)) def processPDF(self, file, writer, context, registry): if self.rellengths: patternstring = " ".join(["%f" % (element * context.linewidth_pt/_defaultlinewidth_pt) for element in self.pattern]) else: patternstring = " ".join(["%f" % element for element in self.pattern]) file.write("[%s] %f d\n" % (patternstring, self.offset)) def processSVGattrs(self, attrs, writer, context, registry): if self.rellengths: patternstring = " ".join(["%f" % (element * context.linewidth_pt/_defaultlinewidth_pt) for element in self.pattern]) else: patternstring = " ".join(["%f" % element for element in self.pattern]) if patternstring: attrs["stroke-dasharray"] = patternstring attrs["stroke-dashoffset"] = "%f" % self.offset else: attrs["stroke-dasharray"] = "none" dash.clear = attr.clearclass(dash) class linestyle(attr.exclusiveattr, strokestyle): """linestyle (linecap together with dash) of paths""" def __init__(self, c=linecap.butt, d=dash([])): # XXX better, but at the moment not supported by attr.exlusiveattr would be: # XXX attr.exclusiveattr.__init__(self, [linestyle, linecap, dash]) attr.exclusiveattr.__init__(self, linestyle) self.c = c self.d = d def processPS(self, file, writer, context, registry): self.c.processPS(file, writer, context, registry) self.d.processPS(file, writer, context, registry) def processPDF(self, file, writer, context, registry): self.c.processPDF(file, writer, context, registry) self.d.processPDF(file, writer, context, registry) def processSVGattrs(self, attrs, writer, context, registry): self.c.processSVGattrs(attrs, writer, context, registry) self.d.processSVGattrs(attrs, writer, context, registry) linestyle.solid = linestyle(linecap.butt, dash([])) linestyle.dashed = linestyle(linecap.butt, dash([2])) linestyle.dotted = linestyle(linecap.round, dash([0, 2])) linestyle.dashdotted = linestyle(linecap.round, dash([0, 2, 2, 2])) linestyle.clear = attr.clearclass(linestyle) class linewidth(attr.sortbeforeexclusiveattr, strokestyle): """linewidth of paths""" def __init__(self, width): attr.sortbeforeexclusiveattr.__init__(self, linewidth, [dash, linestyle]) self.width = width def processPS(self, file, writer, context, registry): context.linewidth_pt = unit.topt(self.width) file.write("%f setlinewidth\n" % context.linewidth_pt) def processPDF(self, file, writer, context, registry): context.linewidth_pt = unit.topt(self.width) file.write("%f w\n" % context.linewidth_pt) def processSVGattrs(self, attrs, writer, context, registry): context.linewidth_pt = unit.topt(self.width) attrs["stroke-width"] = "%f" % context.linewidth_pt linewidth.THIN = linewidth(_defaultlinewidth/math.sqrt(32)) linewidth.THIn = linewidth(_defaultlinewidth/math.sqrt(16)) linewidth.THin = linewidth(_defaultlinewidth/math.sqrt(8)) linewidth.Thin = linewidth(_defaultlinewidth/math.sqrt(4)) linewidth.thin = linewidth(_defaultlinewidth/math.sqrt(2)) linewidth.normal = linewidth(_defaultlinewidth) linewidth.thick = linewidth(_defaultlinewidth*math.sqrt(2)) linewidth.Thick = linewidth(_defaultlinewidth*math.sqrt(4)) linewidth.THick = linewidth(_defaultlinewidth*math.sqrt(8)) linewidth.THIck = linewidth(_defaultlinewidth*math.sqrt(16)) linewidth.THICk = linewidth(_defaultlinewidth*math.sqrt(32)) linewidth.THICK = linewidth(_defaultlinewidth*math.sqrt(64)) linewidth.clear = attr.clearclass(linewidth) class fillrule(attr.exclusiveattr, fillstyle): """defines the fill rule to be used""" def __init__(self, even_odd): attr.exclusiveattr.__init__(self, fillrule) self.even_odd = even_odd def processPS(self, file, writer, context, registry): context.fillrule = self.even_odd def processPDF(self, file, writer, context, registry): context.fillrule = self.even_odd def processSVGattrs(self, attrs, writer, context, registry): attrs["fill-rule"] = {0: "nonzero", 1: "evenodd"}[self.even_odd] fillrule.nonzero_winding = fillrule(0) fillrule.even_odd = fillrule(1) fillrule.clear = attr.clearclass(fillrule) PyX-0.14.1/pyx/svgfile.py0000644000076500000240000007700612520441445015375 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2015 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import xml.sax, re, math, logging from . import baseclasses, bbox, canvas, path, trafo, deco, style, color, unit logger = logging.getLogger("pyx") def endpointarc(x1, y1, x2, y2, fA, fS, rx, ry, phi): # Note: all lengths are _pt, but has been skipped to prevent clumsy notation # See http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes # F.6.6 step 1 if rx == 0 or ry == 0: return path.line_pt(x1, y1, x2, y2) # F.6.6 step 2 if rx < 0: rx = -rx if ry < 0: ry = -ry # F.6.5 step 1 cos_phi = math.cos(math.radians(phi)) sin_phi = math.sin(math.radians(phi)) dx = (x1 - x2) / 2 dy = (y1 - y2) / 2 x1prim = cos_phi * dx + sin_phi * dy y1prim = -sin_phi * dx + cos_phi * dy # F.6.6 step 3 Lambda = (x1prim/rx)**2 + (y1prim/ry)**2 if Lambda > 1: Lambda_sqrt = math.sqrt(Lambda) rx *= Lambda_sqrt ry *= Lambda_sqrt # F.6.5 step 2 c_sq = ((rx*ry)**2 - (rx*y1prim)**2 - (ry*x1prim)**2) / ((rx*y1prim)**2 + (ry*x1prim)**2) c = math.sqrt(c_sq) if c_sq > 0 else 0 if fA == fS: c = -c cxprim = c * rx * y1prim / ry cyprim = -c * ry * x1prim / rx # F.6.5 step 3 cx = cos_phi * cxprim - sin_phi * cyprim + dx cy = sin_phi * cxprim + cos_phi * cyprim + dy # F.6.5 step 4 theta1 = math.atan2((y1prim - cyprim)/ry, (x1prim - cxprim)/rx) theta2 = math.atan2((-y1prim - cyprim)/ry, (-x1prim - cxprim)/rx) if fS: # clockwise and counterclockwise are exchanged due to negative y axis direction arc = path.path(path.arc_pt(0, 0, 1, theta1*180/math.pi, theta2*180/math.pi)) else: arc = path.path(path.arcn_pt(0, 0, 1, theta1*180/math.pi, theta2*180/math.pi)) arc = arc.transformed(trafo.scale(rx, ry).rotated(phi)) x1p, y1p = arc.atbegin_pt() return arc.transformed(trafo.translate_pt(x1-x1p, y1-y1p)) class svgValueError(ValueError): pass class _marker: pass _svgFloatPattern = re.compile("(?P[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)(?P(px|pt|pc|mm|cm|in|%)?)\s*,?\s*") _svgBoolPattern = re.compile("(?P[01])\s*,?\s*") _svgPathPattern = re.compile("(?P[mlhvcsqtaz])\s*(?P(([^mlhvcsqtaz]|pt|pc|mm|cm)*))", re.IGNORECASE) _svgColorAbsPattern = re.compile("rgb\(\s*(?P[0-9]+)\s*,\s*(?P[0-9]+)\s*,\s*(?P[0-9]+)\s*\)$", re.IGNORECASE) _svgColorRelPattern = re.compile("rgb\(\s*(?P[0-9]+)%\s*,\s*(?P[0-9]+)%\s*,\s*(?P[0-9]+)%\s*\)$", re.IGNORECASE) class svgBaseHandler(xml.sax.ContentHandler): def __init__(self, resolution): self.resolution = resolution self.units = {"": 72/self.resolution, "px": 72/self.resolution, "pt": 1, "pc": 12, "mm": 72/25.4, "cm": 72/2.54, "in": 72} def toFloat(self, arg, relative=None, single=False, units=True): match = _svgFloatPattern.match(arg) if not match: raise svgValueError("could not match float for '%s'" % arg) if match.group("unit") and not units: raise svgValueError("no units allowed for '%s'" % arg) value = float(match.group("value")) if match.group("unit") == "%": if relative is not None: value *= 0.01 * relative else: raise svgValueError("missing support for relative coordinates") elif units: value *= self.units[match.group("unit")] if single: if match.end() < len(arg): raise svgValueError("could not match single float for '%s'" % arg) return value return value, arg[match.end():] def toFloats(self, args, units=True): while args: float, args = self.toFloat(args, units=units) yield float class svgHandler(svgBaseHandler): def __init__(self, resolution): super().__init__(resolution) self.stack = [] self.stroke = None self.fill = color.grey.black def toBool(self, arg): match = _svgBoolPattern.match(arg) if not match: raise svgValueError("could not match boolean for '%s'" % arg) return match.group("bool") == "1", arg[match.end():] def toPath(self, svgPath): # Note: all lengths are _pt, but _pt has been skipped to prevent clumsy notation p = path.path() for match in _svgPathPattern.finditer(svgPath): cmd = match.group("cmd") args = match.group("args") try: if cmd not in "aA": args = self.toFloats(args) if cmd in "MmLl": first = True while args: x, y, *args = args if cmd in "Ll" or not first: p.append(path.lineto_pt(x, y) if cmd.isupper() else path.rlineto_pt(x, y)) else: p.append(path.moveto_pt(x, y) if cmd.isupper() or not p else path.rmoveto_pt(x, y)) first = False elif cmd in "HhVv": x, y = p.atend_pt() if cmd.isupper() else (0, 0) for arg in args: if cmd in "Hh": x = arg else: y = arg p.append(path.lineto_pt(x, y) if cmd.isupper() else path.rlineto_pt(x, y)) elif cmd in "CcSs": while args: if cmd in "Cc": x1, y1, x2, y2, x3, y3, *args = args else: x2, y2, x3, y3, *args = args if isinstance(p[-1], path.curveto_pt): x1 = p[-1].x3_pt - p[-1].x2_pt y1 = p[-1].y3_pt - p[-1].y2_pt elif isinstance(p[-1], path.rcurveto_pt): x1 = p[-1].dx3_pt - p[-1].dx2_pt y1 = p[-1].dy3_pt - p[-1].dy2_pt else: x1, y1 = 0, 0 if cmd == "S": x0, y0 = p.atend_pt() x1 += x0 y1 += y0 p.append(path.curveto_pt(x1, y1, x2, y2, x3, y3) if cmd.isupper() else path.rcurveto_pt(x1, y1, x2, y2, x3, y3)) elif cmd in "QqTt": while args: x0, y0 = p.atend_pt() if cmd in "Qq": xq, yq, x3, y3, *args = args if cmd == "q": xq += x0 yq += y0 x3 += x0 y3 += y0 else: x3, y3, *args = args if cmd == "t": x3 += x0 y3 += y0 if isinstance(p[-1], path.curveto_pt): xq = x0 + 3/2 * (p[-1].x3_pt - p[-1].x2_pt) yq = y0 + 3/2 * (p[-1].y3_pt - p[-1].y2_pt) elif isinstance(p[-1], path.rcurveto_pt): xq = x0 + 3/2 * (p[-1].dx3_pt - p[-1].dx2_pt) yq = y0 + 3/2 * (p[-1].dy3_pt - p[-1].dy2_pt) else: xq, yq = p.atend_pt() x1 = x0 + 2/3 * (xq - x0) y1 = y0 + 2/3 * (yq - y0) x2 = x3 + 2/3 * (xq - x3) y2 = y3 + 2/3 * (yq - y3) p.append(path.curveto_pt(x1, y1, x2, y2, x3, y3)) elif cmd in "aA": while args: rx, args = self.toFloat(args) ry, args = self.toFloat(args) phi, args = self.toFloat(args) fA, args = self.toBool(args) fS, args = self.toBool(args) x2, args = self.toFloat(args) y2, args = self.toFloat(args) x1, y1 = p.atend_pt() if cmd == "a": x2 += x1 y2 += y1 p.join(endpointarc(x1, y1, x2, y2, fA, fS, rx, ry, phi)) else: assert cmd in "zZ" p.append(path.closepath()) except svgValueError: pass return p def toTrafo(self, svgTrafo): t = trafo.identity for match in reversed(list(re.finditer("(?Pmatrix|translate|scale|rotate|skewX|skewY)\((?P[^)]*)\)", svgTrafo))): cmd = match.group("cmd") args = match.group("args") if cmd == "matrix": a, args = self.toFloat(args, units=False) b, args = self.toFloat(args, units=False) c, args = self.toFloat(args, units=False) d, args = self.toFloat(args, units=False) e, args = self.toFloat(args) f = self.toFloat(args, single=True) t = t * trafo.trafo_pt(((a, b), (c, d)), (e, f)) elif cmd == "translate": args = list(self.toFloats(args)) if len(args) == 1: args.append(0) assert len(args) == 2 t = t.translated_pt(args[0], args[1]) elif cmd == "scale": args = list(self.toFloats(args, units=False)) if len(args) == 1: args.append(args[0]) assert len(args) == 2 t = t.scaled(args[0], args[1]) elif cmd == "rotate": a, args = self.toFloat(args, units=False) if args: b, args = self.toFloat(args) c = self.toFloat(args, single=True) else: b, c = 0, 0 t = t.rotated_pt(a, b, c) elif cmd == "skewX": t = t * trafo.trafo_pt(((1, math.tan(self.toFloat(args, units=False, single=True)*math.pi/180)), (0, 1))) else: assert cmd == "skewY" t = t * trafo.trafo_pt(((1, 0), (math.tan(self.toFloat(args, units=False, single=True)*math.pi/180), 1))) return t def toColor(self, name, inherit): if name == "currentColor": return None # TODO if name == "inherit": return inherit if name == "none": return None names = {"aliceblue": "rgb(240, 248, 255)", "antiquewhite": "rgb(250, 235, 215)", "aqua": "rgb( 0, 255, 255)", "aquamarine": "rgb(127, 255, 212)", "azure": "rgb(240, 255, 255)", "beige": "rgb(245, 245, 220)", "bisque": "rgb(255, 228, 196)", "black": "rgb( 0, 0, 0)", "blanchedalmond": "rgb(255, 235, 205)", "blue": "rgb( 0, 0, 255)", "blueviolet": "rgb(138, 43, 226)", "brown": "rgb(165, 42, 42)", "burlywood": "rgb(222, 184, 135)", "cadetblue": "rgb( 95, 158, 160)", "chartreuse": "rgb(127, 255, 0)", "chocolate": "rgb(210, 105, 30)", "coral": "rgb(255, 127, 80)", "cornflowerblue": "rgb(100, 149, 237)", "cornsilk": "rgb(255, 248, 220)", "crimson": "rgb(220, 20, 60)", "cyan": "rgb( 0, 255, 255)", "darkblue": "rgb( 0, 0, 139)", "darkcyan": "rgb( 0, 139, 139)", "darkgoldenrod": "rgb(184, 134, 11)", "darkgray": "rgb(169, 169, 169)", "darkgreen": "rgb( 0, 100, 0)", "darkgrey": "rgb(169, 169, 169)", "darkkhaki": "rgb(189, 183, 107)", "darkmagenta": "rgb(139, 0, 139)", "darkolivegreen": "rgb( 85, 107, 47)", "darkorange": "rgb(255, 140, 0)", "darkorchid": "rgb(153, 50, 204)", "darkred": "rgb(139, 0, 0)", "darksalmon": "rgb(233, 150, 122)", "darkseagreen": "rgb(143, 188, 143)", "darkslateblue": "rgb( 72, 61, 139)", "darkslategray": "rgb( 47, 79, 79)", "darkslategrey": "rgb( 47, 79, 79)", "darkturquoise": "rgb( 0, 206, 209)", "darkviolet": "rgb(148, 0, 211)", "deeppink": "rgb(255, 20, 147)", "deepskyblue": "rgb( 0, 191, 255)", "dimgray": "rgb(105, 105, 105)", "dimgrey": "rgb(105, 105, 105)", "dodgerblue": "rgb( 30, 144, 255)", "firebrick": "rgb(178, 34, 34)", "floralwhite": "rgb(255, 250, 240)", "forestgreen": "rgb( 34, 139, 34)", "fuchsia": "rgb(255, 0, 255)", "gainsboro": "rgb(220, 220, 220)", "ghostwhite": "rgb(248, 248, 255)", "gold": "rgb(255, 215, 0)", "goldenrod": "rgb(218, 165, 32)", "gray": "rgb(128, 128, 128)", "grey": "rgb(128, 128, 128)", "green": "rgb( 0, 128, 0)", "greenyellow": "rgb(173, 255, 47)", "honeydew": "rgb(240, 255, 240)", "hotpink": "rgb(255, 105, 180)", "indianred": "rgb(205, 92, 92)", "indigo": "rgb( 75, 0, 130)", "ivory": "rgb(255, 255, 240)", "khaki": "rgb(240, 230, 140)", "lavender": "rgb(230, 230, 250)", "lavenderblush": "rgb(255, 240, 245)", "lawngreen": "rgb(124, 252, 0)", "lemonchiffon": "rgb(255, 250, 205)", "lightblue": "rgb(173, 216, 230)", "lightcoral": "rgb(240, 128, 128)", "lightcyan": "rgb(224, 255, 255)", "lightgoldenrodyellow": "rgb(250, 250, 210)", "lightgray": "rgb(211, 211, 211)", "lightgreen": "rgb(144, 238, 144)", "lightgrey": "rgb(211, 211, 211)", "lightpink": "rgb(255, 182, 193)", "lightsalmon": "rgb(255, 160, 122)", "lightseagreen": "rgb( 32, 178, 170)", "lightskyblue": "rgb(135, 206, 250)", "lightslategray": "rgb(119, 136, 153)", "lightslategrey": "rgb(119, 136, 153)", "lightsteelblue": "rgb(176, 196, 222)", "lightyellow": "rgb(255, 255, 224)", "lime": "rgb( 0, 255, 0)", "limegreen": "rgb( 50, 205, 50)", "linen": "rgb(250, 240, 230)", "magenta": "rgb(255, 0, 255)", "maroon": "rgb(128, 0, 0)", "mediumaquamarine": "rgb(102, 205, 170)", "mediumblue": "rgb( 0, 0, 205)", "mediumorchid": "rgb(186, 85, 211)", "mediumpurple": "rgb(147, 112, 219)", "mediumseagreen": "rgb( 60, 179, 113)", "mediumslateblue": "rgb(123, 104, 238)", "mediumspringgreen": "rgb( 0, 250, 154)", "mediumturquoise": "rgb( 72, 209, 204)", "mediumvioletred": "rgb(199, 21, 133)", "midnightblue": "rgb( 25, 25, 112)", "mintcream": "rgb(245, 255, 250)", "mistyrose": "rgb(255, 228, 225)", "moccasin": "rgb(255, 228, 181)", "navajowhite": "rgb(255, 222, 173)", "navy": "rgb( 0, 0, 128)", "oldlace": "rgb(253, 245, 230)", "olive": "rgb(128, 128, 0)", "olivedrab": "rgb(107, 142, 35)", "orange": "rgb(255, 165, 0)", "orangered": "rgb(255, 69, 0)", "orchid": "rgb(218, 112, 214)", "palegoldenrod": "rgb(238, 232, 170)", "palegreen": "rgb(152, 251, 152)", "paleturquoise": "rgb(175, 238, 238)", "palevioletred": "rgb(219, 112, 147)", "papayawhip": "rgb(255, 239, 213)", "peachpuff": "rgb(255, 218, 185)", "peru": "rgb(205, 133, 63)", "pink": "rgb(255, 192, 203)", "plum": "rgb(221, 160, 221)", "powderblue": "rgb(176, 224, 230)", "purple": "rgb(128, 0, 128)", "red": "rgb(255, 0, 0)", "rosybrown": "rgb(188, 143, 143)", "royalblue": "rgb( 65, 105, 225)", "saddlebrown": "rgb(139, 69, 19)", "salmon": "rgb(250, 128, 114)", "sandybrown": "rgb(244, 164, 96)", "seagreen": "rgb( 46, 139, 87)", "seashell": "rgb(255, 245, 238)", "sienna": "rgb(160, 82, 45)", "silver": "rgb(192, 192, 192)", "skyblue": "rgb(135, 206, 235)", "slateblue": "rgb(106, 90, 205)", "slategray": "rgb(112, 128, 144)", "slategrey": "rgb(112, 128, 144)", "snow": "rgb(255, 250, 250)", "springgreen": "rgb( 0, 255, 127)", "steelblue": "rgb( 70, 130, 180)", "tan": "rgb(210, 180, 140)", "teal": "rgb( 0, 128, 128)", "thistle": "rgb(216, 191, 216)", "tomato": "rgb(255, 99, 71)", "turquoise": "rgb( 64, 224, 208)", "violet": "rgb(238, 130, 238)", "wheat": "rgb(245, 222, 179)", "white": "rgb(255, 255, 255)", "whitesmoke": "rgb(245, 245, 245)", "yellow": "rgb(255, 255, 0)", "yellowgreen": "rgb(154, 205, 50)"} name = names.get(name, name) match = _svgColorAbsPattern.match(name.strip()) if match: return color.rgb(int(match.group("red"))/255, int(match.group("green"))/255, int(match.group("blue"))/255) match = _svgColorRelPattern.match(name.strip()) if match: return color.rgb(int(match.group("red"))/100, int(match.group("green"))/100, int(match.group("blue"))/100) return color.rgbfromhexstring(name) def startElementNS(self, name, qname, attributes): def floatAttr(localname, default=_marker): if default is _marker: return self.toFloat(attributes[None, localname])[0] else: try: return self.toFloat(attributes[None, localname])[0] except KeyError: return default def pathAttrs(default=_marker): if default is not _marker: attrs = default else: attrs = [] if (None, "transform") in attributes: attrs.append(self.toTrafo(attributes[None, "transform"])) if (None, "stroke-dasharray") in attributes: attrs.append(style.dash(self.toFloats(attributes[None, "stroke-dasharray"]), offset=floatAttr("stroke-dashoffset", 0), rellengths=False)) if (None, "stroke-linecap") in attributes: attrs.append({"butt": style.linecap.butt, "round": style.linecap.round, "square": style.linecap.square}[attributes[None, "stroke-linecap"]]) if (None, "stroke-linejoin") in attributes: attrs.append({"miter": style.linejoin.miter, "round": style.linejoin.round, "bevel": style.linejoin.bevel}[attributes[None, "stroke-linejoin"]]) if (None, "stroke-miterlimit") in attributes: attrs.append(style.miterlimit(floatAttr("stroke-miterlimit"))) if (None, "stroke-width") in attributes: attrs.append(style.linewidth(floatAttr("stroke-width")*unit.t_pt)) if (None, "fill-rule") in attributes: attrs.append({"nonzero": style.fillrule.nonzero_winding, "evenodd": style.fillrule.even_odd}[attributes[None, "fill-rule"]]) return attrs namespace, localname = name if namespace == "http://www.w3.org/2000/svg": if localname == "svg": attrs = pathAttrs([style.linewidth(1*unit.t_pt), style.miterlimit(4)]) outer_x = self.toFloat(attributes.get((None, "x"), "0"), single=True) outer_y = self.toFloat(attributes.get((None, "y"), "0"), single=True) if (None, "viewBox") in attributes: inner_x, inner_y, inner_width, inner_height = self.toFloats(attributes[None, "viewBox"]) if attributes.get((None, "clip"), "auto") == "auto": attrs.append(canvas.clip(path.rect(inner_x, inner_y, inner_width, inner_height))) outer_width = self.toFloat(attributes.get((None, "width"), "100%"), single=True, relative=inner_width) outer_height = self.toFloat(attributes.get((None, "height"), "100%"), single=True, relative=inner_height) self.bbox = bbox.bbox_pt(outer_x, -outer_y, outer_x+outer_width, -outer_y+outer_height) attrs.append(trafo.translate_pt(-inner_x, -inner_y)) attrs.append(trafo.scale(outer_width/inner_width, outer_height/inner_height)) attrs.append(trafo.translate_pt(outer_x, outer_y)) attrs.append(trafo.translate_pt(0, -outer_height)) elif (None, "width") in attributes and (None, "height") in attributes: outer_width = self.toFloat(attributes.get((None, "width"), "100%"), single=True) outer_height = self.toFloat(attributes.get((None, "height"), "100%"), single=True) self.bbox = bbox.bbox_pt(outer_x, -outer_y, outer_x+outer_width, -outer_y+outer_height) attrs.append(trafo.translate_pt(outer_x, outer_y)) attrs.append(trafo.translate_pt(0, -outer_height)) else: self.bbox = None raise ValueError("SVG viewbox or width and height missing, we continue by aligning by SVG coordinates (top-left) instead of PyX-like (bottom-left) and calculate the bbox from the SVG content") attrs.append(trafo.mirror(0)) self.canvas = canvas.canvas(attrs) elif localname == "g": self.stack.append((self.canvas, self.stroke, self.fill)) self.canvas = self.canvas.insert(canvas.canvas(pathAttrs())) self.fill = self.toColor(attributes.get((None, "fill"), "inherit"), self.fill) self.stroke = self.toColor(attributes.get((None, "stroke"), "inherit"), self.stroke) elif localname in ["rect", "circle", "ellipse", "line", "polyline", "polygon", "path"]: if localname == "line": p = path.line_pt(floatAttr("x1"), floatAttr("y1"), floatAttr("x2"), floatAttr("y2")) elif localname == "rect": x, y = floatAttr("x", 0), floatAttr("y", 0) width, height = floatAttr("width"), floatAttr("height") if width == 0 or height == 0: p = None else: rx, ry = floatAttr("rx", None), floatAttr("ry", None) if ((rx is None or rx < 1e-10) and (ry is None or ry < 1e-10)): p = path.rect_pt(x, y, width, height) else: if rx is None: rx = ry elif ry is None: ry = rx if 2*rx > width: rx = 0.5*width if 2*ry > height: ry = 0.5*height c = path.circle_pt(0, 0, 1).transformed(trafo.scale(rx, ry)) c1, c2, c3, c4 = c.split_pt([i*c.arclen_pt()/4 for i in range(4)]) p = c1.transformed(trafo.translate_pt(x+width-rx, y+ry)) p.join(c2.transformed(trafo.translate_pt(x+width-rx, y+height-ry))) p.join(c3.transformed(trafo.translate_pt(x+rx, y+height-ry))) p.join(c4.transformed(trafo.translate_pt(x+rx, y+ry))) p.append(path.closepath()) elif localname == "circle": if floatAttr("r") != 0: p = path.circle_pt(floatAttr("cx", 0), floatAttr("cy", 0), floatAttr("r")) else: p = None elif localname == "ellipse": if floatAttr("rx") != 0 and floatAttr("ry") != 0: p = path.ellipse_pt(floatAttr("cx", 0), floatAttr("cy", 0), floatAttr("rx"), floatAttr("ry"), angle=0) else: p = None elif localname == "polyline" or localname == "polygon": x, y, *args = self.toFloats(attributes[None, "points"]) p = path.path(path.moveto_pt(x, y)) while len(args) >= 2: x, y, *args = args p.append(path.lineto_pt(x, y)) if localname == "polygon": p.append(path.closepath()) else: assert localname == "path" p = self.toPath(attributes[None, "d"]) if p is not None: attrs = pathAttrs() fill = self.toColor(attributes.get((None, "fill"), "inherit"), self.fill) if fill: attrs.append(deco.filled([fill])) stroke = self.toColor(attributes.get((None, "stroke"), "inherit"), self.stroke) if stroke: attrs.append(deco.stroked([stroke])) if stroke or fill: self.canvas.draw(p, attrs) def endElementNS(self, name, qname): namespace, localname = name if namespace == "http://www.w3.org/2000/svg": if localname == "g": self.canvas, self.stroke, self.fill = self.stack.pop() class svgBboxDoneException(Exception): pass class svgBboxHandler(svgBaseHandler): def startElementNS(self, name, qname, attributes): if name != ("http://www.w3.org/2000/svg", "svg"): raise ValueError("not an SVG file") if (None, "width") not in attributes or (None, "height") not in attributes: raise ValueError("SVG width and height missing, which is required for unparsed SVG inclusion") outer_x = self.toFloat(attributes.get((None, "x"), "0"), single=True) outer_y = self.toFloat(attributes.get((None, "y"), "0"), single=True) try: outer_width = self.toFloat(attributes.get((None, "width")), single=True) outer_height = self.toFloat(attributes.get((None, "height")), single=True) self.trafo = trafo.translate_pt(0, outer_height) * trafo.scale(72/self.resolution) except svgValueError: inner_x, inner_y, inner_width, inner_height = self.toFloats(attributes[None, "viewBox"]) outer_width = self.toFloat(attributes.get((None, "width")), relative=inner_width, single=True) outer_height = self.toFloat(attributes.get((None, "height")), relative=inner_height, single=True) self.trafo = trafo.translate_pt(-0.5*outer_width, outer_height) self.bbox = bbox.bbox_pt(outer_x, -outer_y, outer_x+outer_width, -outer_y+outer_height) raise svgBboxDoneException() class svgfile_pt(baseclasses.canvasitem): def __init__(self, x_pt, y_pt, filename, width_pt=None, height_pt=None, ratio=None, parsed=False, resolution=96): self.filename = filename self.parsed = parsed self.resolution = resolution if parsed: self.svg = svgHandler(resolution) else: self.svg = svgBboxHandler(resolution) parser = xml.sax.make_parser() parser.setContentHandler(self.svg) parser.setFeature(xml.sax.handler.feature_namespaces, True) parser.setFeature(xml.sax.handler.feature_external_ges, False) parser.setFeature(xml.sax.handler.feature_external_pes, False) if parsed: with open(filename, "rb") as f: parser.parse(f) else: try: with open(filename, "rb") as f: parser.parse(f) except svgBboxDoneException: pass else: raise ValueError("no XML found") if not self.svg.bbox: # fallback for parsed svg without viewbox self.svg.bbox = self.svg.canvas.bbox() self.trafo = trafo.translate_pt(x_pt, y_pt) if width_pt is not None or height_pt is not None: svgwidth_pt = self.svg.bbox.width_pt() svgheight_pt = self.svg.bbox.height_pt() if width_pt is None: if ratio is None: width_pt = height_pt * svgwidth_pt / svgheight_pt else: width_pt = ratio * height_pt elif height_pt is None: if ratio is None: height_pt = width_pt * svgheight_pt / svgwidth_pt else: height_pt = (1.0/ratio) * width_pt elif ratio is not None: raise ValueError("can't specify a ratio when setting width_pt and height_pt") self.trafo *= trafo.scale_pt(width_pt/svgwidth_pt, height_pt/svgheight_pt) else: if ratio is not None: raise ValueError("must specify width_pt or height_pt to set a ratio") self.trafo *= trafo.translate_pt(-self.svg.bbox.llx_pt, -self.svg.bbox.lly_pt) self._bbox = self.svg.bbox.transformed(self.trafo) if self.parsed: self.canvas = canvas.canvas([self.trafo]) self.canvas.insert(self.svg.canvas) def bbox(self): return self._bbox def processPS(self, file, writer, context, registry, bbox): if not self.parsed: raise ValueError("cannot output unparsed SVG to PostScript") self.canvas.processPS(file, writer, context, registry, bbox) def processPDF(self, file, writer, context, registry, bbox): if not self.parsed: raise ValueError("cannot output unparsed SVG to PDF") self.canvas.processPDF(file, writer, context, registry, bbox) def processSVG(self, svg, writer, context, registry, bbox): if self.parsed: self.canvas.processSVG(svg, writer, context, registry, bbox) else: t = self.trafo * self.svg.trafo attrs = {"fill": "black"} t.processSVGattrs(attrs, writer, context, registry) svg.startSVGElement("g", attrs) parser = xml.sax.make_parser() parser.setContentHandler(svg) parser.setFeature(xml.sax.handler.feature_namespaces, True) parser.setFeature(xml.sax.handler.feature_external_ges, False) parser.setFeature(xml.sax.handler.feature_external_pes, False) svg.passthrough = True with open(self.filename, "rb") as f: parser.parse(f) svg.passthrough = False svg.endSVGElement("g") class svgfile(svgfile_pt): def __init__(self, x, y, filename, width=None, height=None, *args, **kwargs): x_pt = unit.topt(x) y_pt = unit.topt(y) if width is not None: width_pt = unit.topt(width) else: width_pt = None if height is not None: height_pt = unit.topt(height) else: height_pt = None super().__init__(x_pt, y_pt, filename, width_pt, height_pt, *args, **kwargs) PyX-0.14.1/pyx/svgwriter.py0000644000076500000240000002075712534566433016005 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2015 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import io, copy, time, xml.sax.saxutils from . import bbox, config, style, version, unit, trafo svg_uri = "http://www.w3.org/2000/svg" xlink_uri = "http://www.w3.org/1999/xlink" class SVGregistry: def __init__(self): # in order to keep a consistent order of the registered resources we # not only store them in a hash but also keep an ordered list (up to a # possible merging of resources, in which case the first instance is # kept) self.resourceshash = {} self.resourceslist = [] def add(self, resource): rkey = (resource.type, resource.id) if rkey in self.resourceshash: self.resourceshash[rkey].merge(resource) else: self.resourceshash[rkey] = resource self.resourceslist.append(resource) def mergeregistry(self, registry): for resource in registry.resources: self.add(resource) def output(self, xml, writer): if self.resourceslist: xml.startSVGElement("defs", {}) for resource in self.resourceslist: resource.output(xml, writer, self) xml.endSVGElement("defs") # # Abstract base class # class SVGresource: def __init__(self, type, id): # Every SVGresource has to have a type and a unique id. # Resources with the same type and id will be merged # when they are registered in the SVGregistry self.type = type self.id = id def merge(self, other): """ merge self with other, which has to be a resource of the same type and with the same id""" pass def output(self, xml, writer, registry): raise NotImplementedError("output not implemented for %s" % repr(self)) # # XML generator with shortcut namespace support # class SVGGenerator(xml.sax.saxutils.XMLGenerator): def __init__(self, svg, xlink=True): super().__init__(svg, "utf-8", short_empty_elements=True) self.svg = svg self.xlink_enabled = xlink self.passthrough = False def convertName(self, name): split = name.split(":") if len(split) == 1: uri = svg_uri name = split[0] else: short_uri, name = split assert short_uri == "xlink" if not self.xlink_enabled: raise ValueError("xlink namespace found but not enabled") self.xlink_used = True uri = xlink_uri return uri, name def convertAttrs(self, attrs): return {self.convertName(name): value for name, value in attrs.items()} def startDocument(self, *args, **kwargs): if not self.passthrough: raise NotImplemented("use startSVGDocument") def endDocument(self, *args, **kwargs): if not self.passthrough: raise NotImplemented("use endSVGDocument") def startElementNS(self, *args, **kwargs): if not self.passthrough: raise NotImplemented("use startSVGElement") super().startElementNS(*args, **kwargs) def endElementNS(self, *args, **kwargs): if not self.passthrough: raise NotImplemented("use endSVGElement") super().endElementNS(*args, **kwargs) def startSVGDocument(self): super().startDocument() super().startPrefixMapping(None, svg_uri) if self.xlink_enabled: super().startPrefixMapping("xlink", xlink_uri) self.indent = 0 self.newline = True self.xlink_used = False def startSVGElement(self, name, attrs): if name != "tspan": if not self.newline: self.characters("\n") self.characters(" "*self.indent) super().startElementNS(self.convertName(name), None, self.convertAttrs(attrs)) if name != "tspan": self.indent += 1 self.last_was_end = False self.newline = False def newline_and_tell(self): self.characters("\n") self.newline = True return self.svg.tell() def endSVGElement(self, name): if name != "tspan": self.indent -= 1 if self.last_was_end: if not self.newline: self.characters("\n") self.characters(" "*self.indent) super().endElementNS(self.convertName(name), None) if name != "tspan": self.last_was_end = True self.newline = False def endSVGDocument(self): assert not self.indent self.characters("\n") super().endPrefixMapping(None) if self.xlink_enabled: super().endPrefixMapping("xlink") super().endDocument() # # Writer # class SVGwriter: def __init__(self, document, file, text_as_path=True, mesh_as_bitmap_resolution=300): self._fontmap = None self.text_as_path = text_as_path self.mesh_as_bitmap_resolution = mesh_as_bitmap_resolution # dictionary mapping font names to dictionaries mapping encoding names to encodings # encodings themselves are mappings from glyphnames to codepoints self.encodings = {} if len(document.pages) != 1: raise ValueError("SVG file can be constructed out of a single page document only") page = document.pages[0] pagefile = io.BytesIO() pagesvg = SVGGenerator(pagefile) registry = SVGregistry() acontext = context() pagebbox = bbox.empty() pagesvg.startSVGDocument() pagesvg.startSVGElement("svg", {}) pagexml_start = pagesvg.newline_and_tell() page.processSVG(pagesvg, self, acontext, registry, pagebbox) pagexml_end = pagesvg.newline_and_tell() pagesvg.endSVGElement("svg") pagesvg.endSVGDocument() x = SVGGenerator(file, xlink=pagesvg.xlink_used) x.startSVGDocument() attrs = {"fill": "none", "version": "1.1"} if pagebbox: # note that svg uses an inverse y coordinate; to compansate this # PyX writes negative y coordinates and the viewbox needs to be # adjusted accordingly (by that instead of a transforamtion # a text remains upright). llx, lly, urx, ury = pagebbox.highrestuple_pt() attrs["viewBox"] = "%g %g %g %g" % (llx, -ury, urx-llx, ury-lly) attrs["x"] = "%gpt" % llx attrs["y"] = "%gpt" % -ury attrs["width"] = "%gpt" % (urx-llx) attrs["height"] = "%gpt" % (ury-lly) style.linewidth.normal.processSVGattrs(attrs, self, acontext, registry) style.miterlimit.lessthan11deg.processSVGattrs(attrs, self, acontext, registry) x.startSVGElement("svg", attrs) registry.output(x, self) pagedata = pagefile.getvalue() x.newline_and_tell() file.write(pagedata[pagexml_start:pagexml_end]) x.endSVGElement("svg") x.endSVGDocument() def getfontmap(self): if self._fontmap is None: # late import due to cyclic dependency from pyx.dvi import mapfile fontmapfiles = config.getlist("text", "psfontmaps", ["psfonts.map"]) self._fontmap = mapfile.readfontmap(fontmapfiles) return self._fontmap class context: def __init__(self): self.linewidth_pt = unit.topt(style.linewidth.normal.width) self.strokeattr = True self.fillattr = True self.fillcolor = "black" self.strokecolor = "black" self.fillopacity = 1 self.strokeopacity = 1 self.indent = 1 def __call__(self, **kwargs): newcontext = copy.copy(self) newcontext.indent += 1 for key, value in list(kwargs.items()): setattr(newcontext, key, value) return newcontext PyX-0.14.1/pyx/text.py0000644000076500000240000017420612615757465014743 0ustar andrestaff00000000000000# Copyright (C) 2002-2013 Jörg Lehmann # Copyright (C) 2003-2011 Michael Schindler # Copyright (C) 2002-2013 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import atexit, errno, functools, glob, inspect, io, itertools, logging, os import queue, re, shutil, sys, tempfile, textwrap, threading from pyx import config, unit, box, baseclasses, trafo, version, attr, style, path from pyx import bbox as bboxmodule from pyx.dvi import dvifile logger = logging.getLogger("pyx") def indent_text(text): "Prepends two spaces to each line in text." return "".join(" " + line for line in text.splitlines(True)) def remove_string(p, s): """Removes a string from a string. The function removes the first occurrence of a string in another string. :param str p: string to be removed :param str s: string to be searched :returns: tuple of the result string and a success boolean (``True`` when the string was removed) :rtype: tuple of str and bool Example: >>> remove_string("XXX", "abcXXXdefXXXghi") ('abcdefXXXghi', True) """ r = s.replace(p, '', 1) return r, r != s def remove_pattern(p, s, ignore_nl=True): r"""Removes a pattern from a string. The function removes the first occurence of the pattern from a string. It returns a tuple of the resulting string and the matching object (or ``None``, if the pattern did not match). :param re.regex p: pattern to be removed :param str s: string to be searched :param bool ignore_nl: When ``True``, newlines in the string are ignored during the pattern search. The returned string will still contain all newline characters outside of the matching part of the string, whereas the returned matching object will not contain the newline characters inside of the matching part of the string. :returns: the result string and the match object or ``None`` if search failed :rtype: tuple of str and (re.match or None) Example: >>> r, m = remove_pattern(re.compile("XXX"), 'ab\ncXX\nXdefXX\nX') >>> r 'ab\ncdefXX\nX' >>> m.string[m.start():m.end()] 'XXX' """ if ignore_nl: r = s.replace('\n', '') has_nl = r != s else: r = s has_nl = False m = p.search(r) if m: s_start = r_start = m.start() s_end = r_end = m.end() if has_nl: j = 0 for c in s: if c == '\n': if j < r_end: s_end += 1 if j <= r_start: s_start += 1 else: j += 1 return s[:s_start] + s[s_end:], m return s, None def index_all(c, s): """Return list of positions of a character in a string. Example: >>> index_all("X", "abXcdXef") [2, 5] """ assert len(c) == 1 return [i for i, x in enumerate(s) if x == c] def pairwise(i): """Returns iterator over pairs of data from an iterable. Example: >>> list(pairwise([1, 2, 3])) [(1, 2), (2, 3)] """ a, b = itertools.tee(i) next(b, None) return zip(a, b) def remove_nested_brackets(s, openbracket="(", closebracket=")", quote='"'): """Remove nested brackets Return a modified string with all nested brackets 1 removed, i.e. only keep the first bracket nesting level. In case an opening bracket is immediately followed by a quote, the quoted string is left untouched, even if it contains brackets. The use-case for that are files in the folder "Program Files (x86)". If the bracket nesting level is broken (unbalanced), the unmodified string is returned. Example: >>> remove_nested_brackets('aaa("bb()bb" cc(dd(ee))ff)ggg'*2) 'aaa("bb()bb" ccff)gggaaa("bb()bb" ccff)ggg' """ openpos = index_all(openbracket, s) closepos = index_all(closebracket, s) if quote is not None: quotepos = index_all(quote, s) for openquote, closequote in pairwise(quotepos): if openquote-1 in openpos: # ignore brackets in quoted string openpos = [pos for pos in openpos if not (openquote < pos < closequote)] closepos = [pos for pos in closepos if not (openquote < pos < closequote)] if len(openpos) != len(closepos): # unbalanced brackets return s # keep the original string in case we need to return due to broken nesting levels r = s level = 0 # Iterate over the bracket positions from the end. # We go reversely to be able to immediately remove nested bracket levels # without influencing bracket positions yet to come in the loop. for pos, leveldelta in sorted(itertools.chain(zip(openpos, itertools.repeat(-1)), zip(closepos, itertools.repeat(1))), reverse=True): # the current bracket nesting level level += leveldelta if level < 0: # unbalanced brackets return s if leveldelta == 1 and level == 2: # a closing bracket to cut after endpos = pos+1 if leveldelta == -1 and level == 1: # an opening bracket to cut at -> remove r = r[:pos] + r[endpos:] return r class TexResultError(ValueError): "Error raised by :class:`texmessage` parsers." pass class texmessage: """Collection of TeX output parsers. This class is not meant to be instanciated. Instead, it serves as a namespace for TeX output parsers, which are functions receiving a TeX output and returning parsed output. In addition, this class also contains some generator functions (namely :attr:`texmessage.no_file` and :attr:`texmessage.pattern`), which return a function according to the given parameters. They are used to generate some of the parsers in this class and can be used to create others as well. """ start_pattern = re.compile(r"This is [-0-9a-zA-Z\s_]*TeX") @staticmethod def start(msg): r"""Validate TeX/LaTeX startup message including scrollmode test. Example: >>> texmessage.start(r''' ... This is e-TeX (version) ... *! Undefined control sequence. ... <*> \raiseerror ... % ... ''') '' """ # check for "This is e-TeX" etc. if not texmessage.start_pattern.search(msg): raise TexResultError("TeX startup failed") # check for \raiseerror -- just to be sure that communication works new = msg.split("*! Undefined control sequence.\n<*> \\raiseerror\n %\n", 1)[-1] if msg == new: raise TexResultError("TeX scrollmode check failed") return new @staticmethod def no_file(fileending, qualname=None): "Generator function to ignore the missing file message for fileending." def check(msg): "Ignore the missing {} file message." return msg.replace("No file texput.%s." % fileending, "").replace("No file %s%stexput.%s." % (os.curdir, os.sep, fileending), "") check.__doc__ = check.__doc__.format(fileending) if qualname is not None: check.__qualname__ = qualname return check no_aux = staticmethod(no_file.__func__("aux", "texmessage.no_aux")) no_nav = staticmethod(no_file.__func__("nav", "texmessage.no_nav")) aux_pattern = re.compile(r'\(([^()]+\.aux|"[^"]+\.aux")\)') log_pattern = re.compile(r"Transcript written on .*texput\.log\.", re.DOTALL) @staticmethod def end(msg): "Validate TeX shutdown message." msg = re.sub(texmessage.aux_pattern, "", msg).replace("(see the transcript file for additional information)", "") # check for "Transcript written on ...log." msg, m = remove_pattern(texmessage.log_pattern, msg) if not m: raise TexResultError("TeX logfile message expected") return msg quoted_file_pattern = re.compile(r'\("(?P[^"]+)".*?\)') file_pattern = re.compile(r'\((?P[^"][^ )]*).*?\)', re.DOTALL) @staticmethod def load(msg): """Ignore file loading messages. Removes text starting with a round bracket followed by a filename ignoring all further text until the corresponding closing bracket. Quotes and/or line breaks in the filename are handled as needed for TeX output. Without quoting the filename, the necessary removal of line breaks is not well defined and the different possibilities are tested to check whether one solution is ok. The last of the examples below checks this behavior. Examples: >>> texmessage.load(r'''other (text.py) things''') 'other things' >>> texmessage.load(r'''other ("text.py") things''') 'other things' >>> texmessage.load(r'''other ("tex ... t.py" further (ignored) ... text) things''') 'other things' >>> texmessage.load(r'''other (t ... ext ... .py ... fur ... ther (ignored) text) things''') 'other things' """ r = remove_nested_brackets(msg) r, m = remove_pattern(texmessage.quoted_file_pattern, r) while m: if not os.path.isfile(config.get("text", "chroot", "") + m.group("filename")): return msg r, m = remove_pattern(texmessage.quoted_file_pattern, r) r, m = remove_pattern(texmessage.file_pattern, r, ignore_nl=False) while m: for filename in itertools.accumulate(m.group("filename").split("\n")): if os.path.isfile(config.get("text", "chroot", "") + filename): break else: return msg r, m = remove_pattern(texmessage.file_pattern, r, ignore_nl=False) return r quoted_def_pattern = re.compile(r'\("(?P[^"]+\.(fd|def))"\)') def_pattern = re.compile(r'\((?P[^"][^ )]*\.(fd|def))\)') @staticmethod def load_def(msg): "Ignore font definition (``*.fd`` and ``*.def``) loading messages." r = msg for p in [texmessage.quoted_def_pattern, texmessage.def_pattern]: r, m = remove_pattern(p, r) while m: if not os.path.isfile(config.get("text", "chroot", "") + m.group("filename")): return msg r, m = remove_pattern(p, r) return r quoted_graphics_pattern = re.compile(r'<"(?P[^"]+\.eps)">') graphics_pattern = re.compile(r'<(?P[^"][^>]*\.eps)>') @staticmethod def load_graphics(msg): "Ignore graphics file (``*.eps``) loading messages." r = msg for p in [texmessage.quoted_graphics_pattern, texmessage.graphics_pattern]: r, m = remove_pattern(p, r) while m: if not os.path.isfile(config.get("text", "chroot", "") + m.group("filename")): return msg r, m = remove_pattern(texmessage.quoted_file_pattern, r) return r @staticmethod def ignore(msg): """Ignore all messages. Should be used as a last resort only. You should write a proper TeX output parser function for the output you observe. """ return "" @staticmethod def warn(msg): """Warn about all messages. Similar to :attr:`ignore`, but writing a warning to the logger about the TeX output. This is considered to be better when you need to get it working quickly as you will still be prompted about the unresolved output, while the processing continues. """ if msg: logger.warning("ignoring TeX warnings:\n%s" % indent_text(msg.rstrip())) return "" @staticmethod def pattern(p, warning, qualname=None): "Warn by regular expression pattern matching." def check(msg): "Warn about {}." msg, m = remove_pattern(p, msg, ignore_nl=False) while m: logger.warning("ignoring %s:\n%s" % (warning, m.string[m.start(): m.end()].rstrip())) msg, m = remove_pattern(p, msg, ignore_nl=False) return msg check.__doc__ = check.__doc__.format(warning) if qualname is not None: check.__qualname__ = qualname return check box_warning = staticmethod(pattern.__func__(re.compile(r"^(Overfull|Underfull) \\[hv]box.*$(\n^..*$)*\n^$\n", re.MULTILINE), "overfull/underfull box", qualname="texmessage.box_warning")) font_warning = staticmethod(pattern.__func__(re.compile(r"^LaTeX Font Warning: .*$(\n^\(Font\).*$)*", re.MULTILINE), "font substitutions of NFSS", qualname="texmessage.font_warning")) package_warning = staticmethod(pattern.__func__(re.compile(r"^package\s+(?P\S+)\s+warning\s*:[^\n]+(?:\n\(?(?P=packagename)\)?[^\n]*)*", re.MULTILINE | re.IGNORECASE), "generic package messages", qualname="texmessage.package_warning")) rerun_warning = staticmethod(pattern.__func__(re.compile(r"^(LaTeX Warning: Label\(s\) may have changed\. Rerun to get cross-references right\s*\.)$", re.MULTILINE), "rerun required message", qualname="texmessage.rerun_warning")) nobbl_warning = staticmethod(pattern.__func__(re.compile(r"^[\s\*]*(No file .*\.bbl.)\s*", re.MULTILINE), "no-bbl message", qualname="texmessage.nobbl_warning")) ############################################################################### # textattrs ############################################################################### _textattrspreamble = "" class textattr: "a textattr defines a apply method, which modifies a (La)TeX expression" class _localattr: pass _textattrspreamble += r"""\gdef\PyXFlushHAlign{0}% \def\PyXragged{% \leftskip=0pt plus \PyXFlushHAlign fil% \rightskip=0pt plus 1fil% \advance\rightskip0pt plus -\PyXFlushHAlign fil% \parfillskip=0pt% \pretolerance=9999% \tolerance=9999% \parindent=0pt% \hyphenpenalty=9999% \exhyphenpenalty=9999}% """ class boxhalign(attr.exclusiveattr, textattr, _localattr): def __init__(self, aboxhalign): self.boxhalign = aboxhalign attr.exclusiveattr.__init__(self, boxhalign) def apply(self, expr): return r"\gdef\PyXBoxHAlign{%.5f}%s" % (self.boxhalign, expr) boxhalign.left = boxhalign(0) boxhalign.center = boxhalign(0.5) boxhalign.right = boxhalign(1) # boxhalign.clear = attr.clearclass(boxhalign) # we can't defined a clearclass for boxhalign since it can't clear a halign's boxhalign class flushhalign(attr.exclusiveattr, textattr, _localattr): def __init__(self, aflushhalign): self.flushhalign = aflushhalign attr.exclusiveattr.__init__(self, flushhalign) def apply(self, expr): return r"\gdef\PyXFlushHAlign{%.5f}\PyXragged{}%s" % (self.flushhalign, expr) flushhalign.left = flushhalign(0) flushhalign.center = flushhalign(0.5) flushhalign.right = flushhalign(1) # flushhalign.clear = attr.clearclass(flushhalign) # we can't defined a clearclass for flushhalign since it couldn't clear a halign's flushhalign class halign(boxhalign, flushhalign, _localattr): def __init__(self, aboxhalign, aflushhalign): self.boxhalign = aboxhalign self.flushhalign = aflushhalign attr.exclusiveattr.__init__(self, halign) def apply(self, expr): return r"\gdef\PyXBoxHAlign{%.5f}\gdef\PyXFlushHAlign{%.5f}\PyXragged{}%s" % (self.boxhalign, self.flushhalign, expr) halign.left = halign(0, 0) halign.center = halign(0.5, 0.5) halign.right = halign(1, 1) halign.clear = attr.clearclass(halign) halign.boxleft = boxhalign.left halign.boxcenter = boxhalign.center halign.boxright = boxhalign.right halign.flushleft = halign.raggedright = flushhalign.left halign.flushcenter = halign.raggedcenter = flushhalign.center halign.flushright = halign.raggedleft = flushhalign.right class _mathmode(attr.attr, textattr, _localattr): "math mode" def apply(self, expr): return r"$\displaystyle{%s}$" % expr mathmode = _mathmode() clearmathmode = attr.clearclass(_mathmode) class _phantom(attr.attr, textattr, _localattr): "phantom text" def apply(self, expr): return r"\phantom{%s}" % expr phantom = _phantom() clearphantom = attr.clearclass(_phantom) _textattrspreamble += "\\newbox\\PyXBoxVBox%\n\\newdimen\\PyXDimenVBox%\n" class parbox_pt(attr.sortbeforeexclusiveattr, textattr): top = 1 middle = 2 bottom = 3 def __init__(self, width, baseline=top): self.width = width * 72.27 / (unit.scale["x"] * 72) self.baseline = baseline attr.sortbeforeexclusiveattr.__init__(self, parbox_pt, [_localattr]) def apply(self, expr): if self.baseline == self.top: return r"\linewidth=%.5ftruept\vtop{\hsize=\linewidth\textwidth=\linewidth{}%s}" % (self.width, expr) elif self.baseline == self.middle: return r"\linewidth=%.5ftruept\setbox\PyXBoxVBox=\hbox{{\vtop{\hsize=\linewidth\textwidth=\linewidth{}%s}}}\PyXDimenVBox=0.5\dp\PyXBoxVBox\setbox\PyXBoxVBox=\hbox{{\vbox{\hsize=\linewidth\textwidth=\linewidth{}%s}}}\advance\PyXDimenVBox by -0.5\dp\PyXBoxVBox\lower\PyXDimenVBox\box\PyXBoxVBox" % (self.width, expr, expr) elif self.baseline == self.bottom: return r"\linewidth=%.5ftruept\vbox{\hsize=\linewidth\textwidth=\linewidth{}%s}" % (self.width, expr) else: ValueError("invalid baseline argument") parbox_pt.clear = attr.clearclass(parbox_pt) class parbox(parbox_pt): def __init__(self, width, **kwargs): parbox_pt.__init__(self, unit.topt(width), **kwargs) parbox.clear = parbox_pt.clear _textattrspreamble += "\\newbox\\PyXBoxVAlign%\n\\newdimen\\PyXDimenVAlign%\n" class valign(attr.sortbeforeexclusiveattr, textattr): def __init__(self, avalign): self.valign = avalign attr.sortbeforeexclusiveattr.__init__(self, valign, [parbox_pt, _localattr]) def apply(self, expr): return r"\setbox\PyXBoxVAlign=\hbox{{%s}}\PyXDimenVAlign=%.5f\ht\PyXBoxVAlign\advance\PyXDimenVAlign by -%.5f\dp\PyXBoxVAlign\lower\PyXDimenVAlign\box\PyXBoxVAlign" % (expr, 1-self.valign, self.valign) valign.top = valign(0) valign.middle = valign(0.5) valign.bottom = valign(1) valign.clear = valign.baseline = attr.clearclass(valign) _textattrspreamble += "\\newdimen\\PyXDimenVShift%\n" class _vshift(attr.sortbeforeattr, textattr): def __init__(self): attr.sortbeforeattr.__init__(self, [valign, parbox_pt, _localattr]) def apply(self, expr): return r"%s\setbox0\hbox{{%s}}\lower\PyXDimenVShift\box0" % (self.setheightexpr(), expr) class vshift(_vshift): "vertical down shift by a fraction of a character height" def __init__(self, lowerratio, heightstr="0"): _vshift.__init__(self) self.lowerratio = lowerratio self.heightstr = heightstr def setheightexpr(self): return r"\setbox0\hbox{{%s}}\PyXDimenVShift=%.5f\ht0" % (self.heightstr, self.lowerratio) class _vshiftmathaxis(_vshift): "vertical down shift by the height of the math axis" def setheightexpr(self): return r"\setbox0\hbox{$\vcenter{\vrule width0pt}$}\PyXDimenVShift=\ht0" vshift.bottomzero = vshift(0) vshift.middlezero = vshift(0.5) vshift.topzero = vshift(1) vshift.mathaxis = _vshiftmathaxis() vshift.clear = attr.clearclass(_vshift) defaultsizelist = ["normalsize", "large", "Large", "LARGE", "huge", "Huge", None, "tiny", "scriptsize", "footnotesize", "small"] class size(attr.sortbeforeattr, textattr): "font size" def __init__(self, sizeindex=None, sizename=None, sizelist=defaultsizelist): if (sizeindex is None and sizename is None) or (sizeindex is not None and sizename is not None): raise ValueError("either specify sizeindex or sizename") attr.sortbeforeattr.__init__(self, [_mathmode, _vshift]) if sizeindex is not None: if sizeindex >= 0 and sizeindex < sizelist.index(None): self.size = sizelist[sizeindex] elif sizeindex < 0 and sizeindex + len(sizelist) > sizelist.index(None): self.size = sizelist[sizeindex] else: raise IndexError("index out of sizelist range") else: self.size = sizename def apply(self, expr): return r"\%s{}%s" % (self.size, expr) size.tiny = size(-4) size.scriptsize = size.script = size(-3) size.footnotesize = size.footnote = size(-2) size.small = size(-1) size.normalsize = size.normal = size(0) size.large = size(1) size.Large = size(2) size.LARGE = size(3) size.huge = size(4) size.Huge = size(5) size.clear = attr.clearclass(size) ############################################################################### # texrunner ############################################################################### class MonitorOutput(threading.Thread): def __init__(self, name, output): """Deadlock-safe output stream reader and monitor. An instance of this class creates a thread to continously read lines from a stream. By that a deadlock due to a full pipe is prevented. In addition, the stream content can be monitored for containing a certain string (see :meth:`expect` and :meth:`wait`) and return all the collected output (see :meth:`read`). :param string name: name to be used while logging in :meth:`wait` and :meth:`done` :param file output: output stream """ self.output = output self._expect = queue.Queue(1) self._received = threading.Event() self._output = queue.Queue() threading.Thread.__init__(self, name=name) self.daemon = True self.start() def expect(self, s): """Expect a string on a **single** line in the output. This method must be called **before** the output occurs, i.e. before the input is written to the TeX/LaTeX process. :param s: expected string or ``None`` if output is expected to become empty :type s: str or None """ self._expect.put_nowait(s) def read(self): """Read all output collected since its previous call. The output reading should be synchronized by the :meth:`expect` and :meth:`wait` methods. :returns: collected output from the stream :rtype: str """ l = [] try: while True: l.append(self._output.get_nowait()) except queue.Empty: pass return "".join(l).replace("\r\n", "\n").replace("\r", "\n") def _wait(self, waiter, checker): """Helper method to implement :meth:`wait` and :meth:`done`. Waits for an event using the *waiter* and *checker* functions while providing user feedback to the ``pyx``-logger using the warning level according to the ``wait`` and ``showwait`` from the ``text`` section of the pyx :mod:`config`. :param function waiter: callback to wait for (the function gets called with a timeout parameter) :param function checker: callback returing ``True`` if waiting was successful :returns: ``True`` when wait was successful :rtype: bool """ wait = config.getint("text", "wait", 60) showwait = config.getint("text", "showwait", 5) if showwait: waited = 0 hasevent = False while waited < wait and not hasevent: if wait - waited > showwait: waiter(showwait) waited += showwait else: waiter(wait - waited) waited += wait - waited hasevent = checker() if not hasevent: if waited < wait: logger.warning("Still waiting for {} " "after {} (of {}) seconds..." .format(self.name, waited, wait)) else: logger.warning("The timeout of {} seconds expired " "and {} did not respond." .format(waited, self.name)) return hasevent else: waiter(wait) return checker() def wait(self): """Wait for the expected output to happen. Waits either until a line containing the string set by the previous :meth:`expect` call is found, or a timeout occurs. :returns: ``True`` when the expected string was found :rtype: bool """ r = self._wait(self._received.wait, self._received.isSet) if r: self._received.clear() return r def done(self): """Waits until the output becomes empty. Waits either until the output becomes empty, or a timeout occurs. The generated output can still be catched by :meth:`read` after :meth:`done` was successful. In the proper workflow :meth:`expect` should be called with ``None`` before the output completes, as otherwise a ``ValueError`` is raised in the :meth:`run`. :returns: ``True`` when the output has become empty :rtype: bool """ return self._wait(self.join, lambda self=self: not self.is_alive()) def _readline(self): """Read a line from the output. To be used **inside** the thread routine only. :returns: one line of the output as a string :rtype: str """ while True: try: return self.output.readline() except IOError as e: if e.errno != errno.EINTR: raise def run(self): """Thread routine. **Not** to be called from outside. :raises ValueError: output becomes empty while some string is expected """ expect = None while True: line = self._readline() if expect is None: try: expect = self._expect.get_nowait() except queue.Empty: pass if not line: break self._output.put(line) if expect is not None: found = line.find(expect) if found != -1: self._received.set() expect = None self.output.close() if expect is not None: raise ValueError("{} finished unexpectedly".format(self.name)) class textbox_pt(box.rect, baseclasses.canvasitem): def __init__(self, x_pt, y_pt, left_pt, right_pt, height_pt, depth_pt, do_finish, fontmap, singlecharmode, fillstyles): """Text output. An instance of this class contains the text output generated by PyX. It is a :class:`baseclasses.canvasitem` and thus can be inserted into a canvas. .. A text has a center (x_pt, y_pt) as well as extents in x-direction .. (left_pt and right_pt) and y-direction (hight_pt and depth_pt). The .. textbox positions the output accordingly and scales it by the .. x-scale from the :mod:`unit`. .. :param float x_pt: x coordinate of the center in pts .. :param float y_pt: y coordinate of the center in pts .. :param float left_pt: unscaled left extent in pts .. :param float right_pt: unscaled right extent in pts .. :param float height_pt: unscaled height in pts .. :param float depth_pt: unscaled depth in pts .. :param function do_finish: callable to execute :meth:`readdvipage` .. :param fontmap: force a fontmap to be used (instead of the default .. depending on the output format) .. :type fontmap: None or fontmap .. :param bool singlecharmode: position each character separately .. :param fillstyles: fill styles to be applied .. :type fillstyles: list of fillstyles """ self.left = left_pt*unit.x_pt #: left extent of the text (PyX length) self.right = right_pt*unit.x_pt #: right extent of the text (PyX length) self.width = self.left + self.right #: width of the text (PyX length) self.height = height_pt*unit.x_pt #: height of the text (PyX length) self.depth = depth_pt*unit.x_pt #: height of the text (PyX length) self.do_finish = do_finish self.fontmap = fontmap self.singlecharmode = singlecharmode self.fillstyles = fillstyles self.texttrafo = trafo.scale(unit.scale["x"]).translated_pt(x_pt, y_pt) box.rect_pt.__init__(self, x_pt - left_pt*unit.scale["x"], y_pt - depth_pt*unit.scale["x"], (left_pt + right_pt)*unit.scale["x"], (depth_pt + height_pt)*unit.scale["x"], abscenter_pt = (left_pt*unit.scale["x"], depth_pt*unit.scale["x"])) self._dvicanvas = None def transform(self, *trafos): box.rect.transform(self, *trafos) for trafo in trafos: self.texttrafo = trafo * self.texttrafo if self._dvicanvas is not None: for trafo in trafos: self._dvicanvas.trafo = trafo * self._dvicanvas.trafo def readdvipage(self, dvifile, page): self._dvicanvas = dvifile.readpage([ord("P"), ord("y"), ord("X"), page, 0, 0, 0, 0, 0, 0], fontmap=self.fontmap, singlecharmode=self.singlecharmode, attrs=[self.texttrafo] + self.fillstyles) @property def dvicanvas(self): if self._dvicanvas is None: self.do_finish() return self._dvicanvas def marker(self, name): """Return the position of a marker. :param str name: name of the marker :returns: position of the marker :rtype: tuple of two PyX lengths This method returns the position of the marker of the given name within, previously defined by the ``\\PyXMarker{name}`` macro in the typeset text. Please do not use the ``@`` character within your name to prevent name clashes with PyX internal uses (although we don’t the marker feature internally right now). Similar to generating actual output, the marker function accesses the DVI output, stopping. The :ref:`texipc` feature will allow for this access without stopping the TeX interpreter. """ return self.texttrafo.apply(*self.dvicanvas.markers[name]) def textpath(self): textpath = path.path() for item in self.dvicanvas.items: textpath += item.textpath() return textpath.transformed(self.texttrafo) def processPS(self, file, writer, context, registry, bbox): abbox = bboxmodule.empty() self.dvicanvas.processPS(file, writer, context, registry, abbox) bbox += box.rect.bbox(self) def processPDF(self, file, writer, context, registry, bbox): abbox = bboxmodule.empty() self.dvicanvas.processPDF(file, writer, context, registry, abbox) bbox += box.rect.bbox(self) def processSVG(self, xml, writer, context, registry, bbox): abbox = bboxmodule.empty() self.dvicanvas.processSVG(xml, writer, context, registry, abbox) bbox += box.rect.bbox(self) class _marker: pass class errordetail: "Constants defining the verbosity of the :exc:`TexResultError`." none = 0 #: Without any input and output. default = 1 #: Input and parsed output shortend to 5 lines. full = 2 #: Full input and unparsed as well as parsed output. class Tee(object): def __init__(self, *files): """Apply write, flush, and close to each of the given files.""" self.files = files def write(self, data): for file in self.files: file.write(data) def flush(self): for file in self.files: file.flush() def close(self): for file in self.files: file.close() # The texrunner state represents the next (or current) execute state. STATE_START, STATE_PREAMBLE, STATE_TYPESET, STATE_DONE = range(4) PyXBoxPattern = re.compile(r"PyXBox:page=(?P\d+),lt=(?P-?\d*((\d\.?)|(\.?\d))\d*)pt,rt=(?P-?\d*((\d\.?)|(\.?\d))\d*)pt,ht=(?P-?\d*((\d\.?)|(\.?\d))\d*)pt,dp=(?P-?\d*((\d\.?)|(\.?\d))\d*)pt:") dvi_pattern = re.compile(r"Output written on .*texput\.dvi \((?P\d+) pages?, \d+ bytes\)\.", re.DOTALL) class TexDoneError(Exception): pass class SingleRunner: #: default :class:`texmessage` parsers at interpreter startup texmessages_start_default = [texmessage.start] #: default :class:`texmessage` parsers at interpreter shutdown texmessages_end_default = [texmessage.end, texmessage.font_warning, texmessage.rerun_warning, texmessage.nobbl_warning] #: default :class:`texmessage` parsers for preamble output texmessages_preamble_default = [texmessage.load] #: default :class:`texmessage` parsers for typeset output texmessages_run_default = [texmessage.font_warning, texmessage.box_warning, texmessage.package_warning, texmessage.load_def, texmessage.load_graphics] def __init__(self, cmd, texenc="ascii", usefiles=[], texipc=config.getboolean("text", "texipc", 0), copyinput=None, dvitype=False, errordetail=errordetail.default, texmessages_start=[], texmessages_end=[], texmessages_preamble=[], texmessages_run=[]): """Base class for the TeX interface. .. note:: This class cannot be used directly. It is the base class for all texrunners and provides most of the implementation. Still, to the end user the parameters except for *cmd* are important, as they are preserved in derived classes usually. :param cmd: command and arguments to start the TeX interpreter :type cmd: list of str :param str texenc: encoding to use in the communication with the TeX interpreter :param usefiles: list of supplementary files to be copied to and from the temporary working directory (see :ref:`debug` for usage details) :type usefiles: list of str :param bool texipc: :ref:`texipc` flag. :param copyinput: filename or file to be used to store a copy of all the input passed to the TeX interpreter :type copyinput: None or str or file :param bool dvitype: flag to turn on dvitype-like output :param errordetail: verbosity of the :exc:`TexResultError` :type errordetail: :class:`errordetail` :param texmessages_start: additional message parsers at interpreter startup :type texmessages_start: list of :class:`texmessage` parsers :param texmessages_end: additional message parsers at interpreter shutdown :type texmessages_end: list of :class:`texmessage` parsers :param texmessages_preamble: additional message parsers for preamble output :type texmessages_preamble: list of :class:`texmessage` parsers :param texmessages_run: additional message parsers for typset output :type texmessages_run: list of :class:`texmessage` parsers """ self.cmd = cmd self.texenc = texenc self.usefiles = usefiles self.texipc = texipc self.copyinput = copyinput self.dvitype = dvitype self.errordetail = errordetail self.texmessages_start = texmessages_start self.texmessages_end = texmessages_end self.texmessages_preamble = texmessages_preamble self.texmessages_run = texmessages_run self.state = STATE_START self.executeid = 0 self.page = 0 self.needdvitextboxes = [] # when texipc-mode off self.dvifile = None def _cleanup(self): """Clean-up TeX interpreter and tmp directory. This funtion is hooked up in atexit to quit the TeX interpreter, to save the contents of usefiles, and to remove the temporary directory. """ try: if self.state > STATE_START: if self.state < STATE_DONE: self.do_finish() if self.state < STATE_DONE: # cleanup while TeX is still running? self.texoutput.expect(None) self.force_done() for f, msg in [(self.texinput.close, "We tried to communicate to %s to quit itself, but this seem to have failed. Trying by terminate signal now ...".format(self.name)), (self.popen.terminate, "Failed, too. Trying by kill signal now ..."), (self.popen.kill, "We tried very hard to get rid of the %s process, but we ultimately failed (as far as we can tell). Sorry.".format(self.name))]: f() if self.texoutput.done(): break logger.warning(msg) for usefile in self.usefiles: extpos = usefile.rfind(".") try: os.rename(os.path.join(self.tmpdir, "texput" + usefile[extpos:]), usefile) except EnvironmentError: logger.warning("Could not save '{}'.".format(usefile)) if os.path.isfile(usefile): try: os.unlink(usefile) except EnvironmentError: logger.warning("Failed to remove spurious file '{}'.".format(usefile)) finally: shutil.rmtree(self.tmpdir, ignore_errors=True) def _execute(self, expr, texmessages, oldstate, newstate): """Execute TeX expression. :param str expr: expression to be passed to TeX :param texmessages: message parsers to analyse the textual output of TeX :type texmessages: list of :class:`texmessage` parsers :param int oldstate: state of the TeX interpreter prior to the expression execution :param int newstate: state of the TeX interpreter after to the expression execution """ assert STATE_PREAMBLE <= oldstate <= STATE_TYPESET assert oldstate == self.state assert newstate >= oldstate if newstate == STATE_DONE: self.texoutput.expect(None) self.texinput.write(expr) else: if oldstate == newstate == STATE_TYPESET: self.page += 1 expr = "\\ProcessPyXBox{%s%%\n}{%i}" % (expr, self.page) self.executeid += 1 self.texoutput.expect("PyXInputMarker:executeid=%i:" % self.executeid) expr += "%%\n\\PyXInput{%i}%%\n" % self.executeid self.texinput.write(expr) self.texinput.flush() self.state = newstate if newstate == STATE_DONE: wait_ok = self.texoutput.done() else: wait_ok = self.texoutput.wait() try: parsed = unparsed = self.texoutput.read() if not wait_ok: raise TexResultError("TeX didn't respond as expected within the timeout period.") if newstate != STATE_DONE: parsed, m = remove_string("PyXInputMarker:executeid=%s:" % self.executeid, parsed) if not m: raise TexResultError("PyXInputMarker expected") if oldstate == newstate == STATE_TYPESET: parsed, m = remove_pattern(PyXBoxPattern, parsed, ignore_nl=False) if not m: raise TexResultError("PyXBox expected") if m.group("page") != str(self.page): raise TexResultError("Wrong page number in PyXBox") extent_pt = [float(x)*72/72.27 for x in m.group("lt", "rt", "ht", "dp")] parsed, m = remove_string("[80.121.88.%s]" % self.page, parsed) if not m: raise TexResultError("PyXPageOutMarker expected") else: # check for "Output written on ...dvi (1 page, 220 bytes)." if self.page: parsed, m = remove_pattern(dvi_pattern, parsed) if not m: raise TexResultError("TeX dvifile messages expected") if m.group("page") != str(self.page): raise TexResultError("wrong number of pages reported") else: parsed, m = remove_string("No pages of output.", parsed) if not m: raise TexResultError("no dvifile expected") for t in texmessages: parsed = t(parsed) if parsed.replace(r"(Please type a command or say `\end')", "").replace(" ", "").replace("*\n", "").replace("\n", ""): raise TexResultError("unhandled TeX response (might be an error)") except TexResultError as e: if self.errordetail > errordetail.none: def add(msg): e.args = (e.args[0] + msg,) add("\nThe expression passed to TeX was:\n{}".format(indent_text(expr.rstrip()))) if self.errordetail == errordetail.full: add("\nThe return message from TeX was:\n{}".format(indent_text(unparsed.rstrip()))) if self.errordetail == errordetail.default: if parsed.count('\n') > 6: parsed = "\n".join(parsed.split("\n")[:5] + ["(cut after 5 lines; use errordetail.full for all output)"]) add("\nAfter parsing the return message from TeX, the following was left:\n{}".format(indent_text(parsed.rstrip()))) raise e if oldstate == newstate == STATE_TYPESET: return extent_pt def do_start(self): """Setup environment and start TeX interpreter.""" assert self.state == STATE_START self.state = STATE_PREAMBLE chroot = config.get("text", "chroot", "") if chroot: chroot_tmpdir = config.get("text", "tmpdir", "/tmp") chroot_tmpdir_rel = os.path.relpath(chroot_tmpdir, os.sep) base_tmpdir = os.path.join(chroot, chroot_tmpdir_rel) else: base_tmpdir = config.get("text", "tmpdir", None) self.tmpdir = tempfile.mkdtemp(prefix="pyx", dir=base_tmpdir) atexit.register(self._cleanup) for usefile in self.usefiles: extpos = usefile.rfind(".") try: os.rename(usefile, os.path.join(self.tmpdir, "texput" + usefile[extpos:])) except OSError: pass if chroot: tex_tmpdir = os.sep + os.path.relpath(self.tmpdir, chroot) else: tex_tmpdir = self.tmpdir cmd = self.cmd + ['--output-directory', tex_tmpdir] if self.texipc: cmd.append("--ipc") self.popen = config.Popen(cmd, stdin=config.PIPE, stdout=config.PIPE, stderr=config.STDOUT, bufsize=0) self.texinput = io.TextIOWrapper(self.popen.stdin, encoding=self.texenc) if self.copyinput: try: self.copyinput.write except AttributeError: self.texinput = Tee(open(self.copyinput, "w", encoding=self.texenc), self.texinput) else: self.texinput = Tee(self.copyinput, self.texinput) self.texoutput = MonitorOutput(self.name, io.TextIOWrapper(self.popen.stdout, encoding=self.texenc)) self._execute("\\scrollmode\n\\raiseerror%\n" # switch to and check scrollmode "\\def\\PyX{P\\kern-.3em\\lower.5ex\hbox{Y}\kern-.18em X}%\n" # just the PyX Logo "\\gdef\\PyXBoxHAlign{0}%\n" # global PyXBoxHAlign (0.0-1.0) for the horizontal alignment, default to 0 "\\newbox\\PyXBox%\n" # PyXBox will contain the output "\\newbox\\PyXBoxHAligned%\n" # PyXBox will contain the horizontal aligned output "\\newdimen\\PyXDimenHAlignLT%\n" # PyXDimenHAlignLT/RT will contain the left/right extent "\\newdimen\\PyXDimenHAlignRT%\n" + _textattrspreamble + # insert preambles for textattrs macros "\\long\\def\\ProcessPyXBox#1#2{%\n" # the ProcessPyXBox definition (#1 is expr, #2 is page number) "\\setbox\\PyXBox=\\hbox{{#1}}%\n" # push expression into PyXBox "\\PyXDimenHAlignLT=\\PyXBoxHAlign\\wd\\PyXBox%\n" # calculate the left/right extent "\\PyXDimenHAlignRT=\\wd\\PyXBox%\n" "\\advance\\PyXDimenHAlignRT by -\\PyXDimenHAlignLT%\n" "\\gdef\\PyXBoxHAlign{0}%\n" # reset the PyXBoxHAlign to the default 0 "\\immediate\\write16{PyXBox:page=#2," # write page and extents of this box to stdout "lt=\\the\\PyXDimenHAlignLT," "rt=\\the\\PyXDimenHAlignRT," "ht=\\the\\ht\\PyXBox," "dp=\\the\\dp\\PyXBox:}%\n" "\\setbox\\PyXBoxHAligned=\\hbox{\\kern-\\PyXDimenHAlignLT\\box\\PyXBox}%\n" # align horizontally "\\ht\\PyXBoxHAligned0pt%\n" # baseline alignment (hight to zero) "{\\count0=80\\count1=121\\count2=88\\count3=#2\\shipout\\box\\PyXBoxHAligned}}%\n" # shipout PyXBox to Page 80.121.88. "\\def\\PyXInput#1{\\immediate\\write16{PyXInputMarker:executeid=#1:}}%\n" # write PyXInputMarker to stdout "\\def\\PyXMarker#1{\\hskip0pt\\special{PyX:marker #1}}%", # write PyXMarker special into the dvi-file self.texmessages_start_default + self.texmessages_start, STATE_PREAMBLE, STATE_PREAMBLE) def do_preamble(self, expr, texmessages): """Ensure preamble mode and execute expr.""" if self.state < STATE_PREAMBLE: self.do_start() self._execute(expr, texmessages, STATE_PREAMBLE, STATE_PREAMBLE) def do_typeset(self, expr, texmessages): """Ensure typeset mode and typeset expr.""" if self.state < STATE_PREAMBLE: self.do_start() if self.state < STATE_TYPESET: self.go_typeset() return self._execute(expr, texmessages, STATE_TYPESET, STATE_TYPESET) def do_finish(self): """Teardown TeX interpreter and cleanup environment.""" if self.state == STATE_DONE: return if self.state < STATE_TYPESET: self.go_typeset() self.go_finish() assert self.state == STATE_DONE self.texinput.close() # close the input queue and self.texoutput.done() # wait for finish of the output if self.needdvitextboxes: dvifilename = os.path.join(self.tmpdir, "texput.dvi") self.dvifile = dvifile.DVIfile(dvifilename, debug=self.dvitype) page = 1 for box in self.needdvitextboxes: box.readdvipage(self.dvifile, page) page += 1 if self.dvifile is not None and self.dvifile.readpage(None) is not None: raise ValueError("end of dvifile expected but further pages follow") atexit.unregister(self._cleanup) self._cleanup() def preamble(self, expr, texmessages=[]): """Execute a preamble. :param str expr: expression to be executed :param texmessages: additional message parsers :type texmessages: list of :class:`texmessage` parsers Preambles must not generate output, but are used to load files, perform settings, define macros, *etc*. In LaTeX mode, preambles are executed before ``\\begin{document}``. The method can be called multiple times, but only prior to :meth:`SingleRunner.text` and :meth:`SingleRunner.text_pt`. """ texmessages = self.texmessages_preamble_default + self.texmessages_preamble + texmessages self.do_preamble(expr, texmessages) def text_pt(self, x_pt, y_pt, expr, textattrs=[], texmessages=[], fontmap=None, singlecharmode=False): """Typeset text. :param float x_pt: x position in pts :param float y_pt: y position in pts :param str expr: text to be typeset :param textattrs: styles and attributes to be applied to the text :type textattrs: list of :class:`textattr, :class:`trafo.trafo_pt`, and :class:`style.fillstyle` :param texmessages: additional message parsers :type texmessages: list of :class:`texmessage` parsers :param fontmap: force a fontmap to be used (instead of the default depending on the output format) :type fontmap: None or fontmap :param bool singlecharmode: position each character separately :returns: text output insertable into a canvas. :rtype: :class:`textbox_pt` :raises: :exc:`TexDoneError`: when the TeX interpreter has been terminated already. """ if self.state == STATE_DONE: raise TexDoneError("typesetting process was terminated already") textattrs = attr.mergeattrs(textattrs) # perform cleans attr.checkattrs(textattrs, [textattr, trafo.trafo_pt, style.fillstyle]) trafos = attr.getattrs(textattrs, [trafo.trafo_pt]) fillstyles = attr.getattrs(textattrs, [style.fillstyle]) textattrs = attr.getattrs(textattrs, [textattr]) for ta in textattrs[::-1]: expr = ta.apply(expr) first = self.state < STATE_TYPESET left_pt, right_pt, height_pt, depth_pt = self.do_typeset(expr, self.texmessages_run_default + self.texmessages_run + texmessages) if self.texipc and first: self.dvifile = dvifile.DVIfile(os.path.join(self.tmpdir, "texput.dvi"), debug=self.dvitype) box = textbox_pt(x_pt, y_pt, left_pt, right_pt, height_pt, depth_pt, self.do_finish, fontmap, singlecharmode, fillstyles) for t in trafos: box.reltransform(t) # TODO: should trafos really use reltransform??? # this is quite different from what we do elsewhere!!! # see https://sourceforge.net/mailarchive/forum.php?thread_id=9137692&forum_id=23700 if self.texipc: box.readdvipage(self.dvifile, self.page) else: self.needdvitextboxes.append(box) return box def text(self, x, y, *args, **kwargs): """Typeset text. This method is identical to :meth:`text_pt` with the only difference of using PyX lengths to position the output. :param x: x position :type x: PyX length :param y: y position :type y: PyX length """ return self.text_pt(unit.topt(x), unit.topt(y), *args, **kwargs) class SingleTexRunner(SingleRunner): def __init__(self, cmd=config.getlist("text", "tex", ["tex"]), lfs="10pt", **kwargs): """Plain TeX interface. This class adjusts the :class:`SingleRunner` to use plain TeX. :param cmd: command and arguments to start the TeX interpreter :type cmd: list of str :param lfs: resemble LaTeX font settings within plain TeX by loading a lfs-file :type lfs: str or None :param kwargs: additional arguments passed to :class:`SingleRunner` An lfs-file is a file defining a set of font commands like ``\\normalsize`` by font selection commands in plain TeX. Several of those files resembling standard settings of LaTeX are distributed along with PyX in the ``pyx/data/lfs`` directory. This directory also contains a LaTeX file to create lfs files for different settings (LaTeX class, class options, and style files). """ super().__init__(cmd=cmd, **kwargs) self.lfs = lfs self.name = "TeX" def go_typeset(self): assert self.state == STATE_PREAMBLE self.state = STATE_TYPESET def go_finish(self): self._execute("\\end%\n", self.texmessages_end_default + self.texmessages_end, STATE_TYPESET, STATE_DONE) def force_done(self): self.texinput.write("\n\\end\n") def do_start(self): super().do_start() if self.lfs: if not self.lfs.endswith(".lfs"): self.lfs = "%s.lfs" % self.lfs with config.open(self.lfs, []) as lfsfile: lfsdef = lfsfile.read().decode("ascii") self._execute(lfsdef, [], STATE_PREAMBLE, STATE_PREAMBLE) self._execute("\\normalsize%\n", [], STATE_PREAMBLE, STATE_PREAMBLE) self._execute("\\newdimen\\linewidth\\newdimen\\textwidth%\n", [], STATE_PREAMBLE, STATE_PREAMBLE) class SingleLatexRunner(SingleRunner): #: default :class:`texmessage` parsers at LaTeX class loading texmessages_docclass_default = [texmessage.load] #: default :class:`texmessage` parsers at ``\begin{document}`` texmessages_begindoc_default = [texmessage.load, texmessage.no_aux] def __init__(self, cmd=config.getlist("text", "latex", ["latex"]), docclass="article", docopt=None, pyxgraphics=True, texmessages_docclass=[], texmessages_begindoc=[], **kwargs): """LaTeX interface. This class adjusts the :class:`SingleRunner` to use LaTeX. :param cmd: command and arguments to start the TeX interpreter in LaTeX mode :type cmd: list of str :param str docclass: document class :param docopt: document loading options :type docopt: str or None :param bool pyxgraphics: activate graphics bundle support, see :ref:`pyxgraphics` :param texmessages_docclass: additional message parsers at LaTeX class loading :type texmessages_docclass: list of :class:`texmessage` parsers :param texmessages_begindoc: additional message parsers at ``\\begin{document}`` :type texmessages_begindoc: list of :class:`texmessage` parsers :param kwargs: additional arguments passed to :class:`SingleRunner` """ super().__init__(cmd=cmd, **kwargs) self.docclass = docclass self.docopt = docopt self.pyxgraphics = pyxgraphics self.texmessages_docclass = texmessages_docclass self.texmessages_begindoc = texmessages_begindoc self.name = "LaTeX" def go_typeset(self): self._execute("\\begin{document}", self.texmessages_begindoc_default + self.texmessages_begindoc, STATE_PREAMBLE, STATE_TYPESET) def go_finish(self): self._execute("\\end{document}%\n", self.texmessages_end_default + self.texmessages_end, STATE_TYPESET, STATE_DONE) def force_done(self): self.texinput.write("\n\\catcode`\\@11\\relax\\@@end\n") def do_start(self): super().do_start() if self.pyxgraphics: with config.open("pyx.def", []) as source, open(os.path.join(self.tmpdir, "pyx.def"), "wb") as dest: dest.write(source.read()) self._execute("\\makeatletter%\n" "\\let\\saveProcessOptions=\\ProcessOptions%\n" "\\def\\ProcessOptions{%\n" "\\def\\Gin@driver{" + self.tmpdir.replace(os.sep, "/") + "/pyx.def}%\n" "\\def\\c@lor@namefile{dvipsnam.def}%\n" "\\saveProcessOptions}%\n" "\\makeatother", [], STATE_PREAMBLE, STATE_PREAMBLE) if self.docopt is not None: self._execute("\\documentclass[%s]{%s}" % (self.docopt, self.docclass), self.texmessages_docclass_default + self.texmessages_docclass, STATE_PREAMBLE, STATE_PREAMBLE) else: self._execute("\\documentclass{%s}" % self.docclass, self.texmessages_docclass_default + self.texmessages_docclass, STATE_PREAMBLE, STATE_PREAMBLE) def reset_for_tex_done(f): @functools.wraps(f) def wrapped(self, *args, **kwargs): try: return f(self, *args, **kwargs) except TexDoneError: self.reset(reinit=True) return f(self, *args, **kwargs) return wrapped class MultiRunner: def __init__(self, cls, *args, **kwargs): """A restartable :class:`SingleRunner` class :param cls: the class being wrapped :type cls: :class:`SingleRunner` class :param list args: args at class instantiation :param dict kwargs: keyword args at at class instantiation """ self.cls = cls self.args = args self.kwargs = kwargs self.reset() def preamble(self, expr, texmessages=[]): "resembles :meth:`SingleRunner.preamble`" self.preambles.append((expr, texmessages)) self.instance.preamble(expr, texmessages) @reset_for_tex_done def text_pt(self, *args, **kwargs): "resembles :meth:`SingleRunner.text_pt`" return self.instance.text_pt(*args, **kwargs) @reset_for_tex_done def text(self, *args, **kwargs): "resembles :meth:`SingleRunner.text`" return self.instance.text(*args, **kwargs) def reset(self, reinit=False): """Start a new :class:`SingleRunner` instance :param bool reinit: replay :meth:`preamble` calls on the new instance After executing this function further preamble calls are allowed, whereas once a text output has been created, :meth:`preamble` calls are forbidden. """ self.instance = self.cls(*self.args, **self.kwargs) if reinit: for expr, texmessages in self.preambles: self.instance.preamble(expr, texmessages) else: self.preambles = [] class TexRunner(MultiRunner): def __init__(self, *args, **kwargs): """A restartable :class:`SingleTexRunner` class :param list args: args at class instantiation :param dict kwargs: keyword args at at class instantiation """ super().__init__(SingleTexRunner, *args, **kwargs) class LatexRunner(MultiRunner): def __init__(self, *args, **kwargs): """A restartable :class:`SingleLatexRunner` class :param list args: args at class instantiation :param dict kwargs: keyword args at at class instantiation """ super().__init__(SingleLatexRunner, *args, **kwargs) # old, deprecated names: texrunner = TexRunner latexrunner = LatexRunner # module level interface documentation for autodoc # the actual values are setup by the set function #: the current :class:`MultiRunner` instance for the module level functions default_runner = None #: default_runner.preamble (bound method) preamble = None #: default_runner.text_pt (bound method) text_pt = None #: default_runner.text (bound method) text = None #: default_runner.reset (bound method) reset = None def set(cls=TexRunner, mode=None, *args, **kwargs): """Setup a new module level :class:`MultiRunner` :param cls: the module level :class:`MultiRunner` to be used, i.e. :class:`TexRunner` or :class:`LatexRunner` :type cls: :class:`MultiRunner` object, not instance :param mode: ``"tex"`` for :class:`TexRunner` or ``"latex"`` for :class:`LatexRunner` with arbitraty capitalization, overwriting the cls value :deprecated: use the cls argument instead :type mode: str or None :param list args: args at class instantiation :param dict kwargs: keyword args at at class instantiation """ # note: defaulttexrunner is deprecated global default_runner, defaulttexrunner, reset, preamble, text, text_pt if mode is not None: logger.warning("mode setting is deprecated, use the cls argument instead") cls = {"tex": TexRunner, "latex": LatexRunner}[mode.lower()] default_runner = defaulttexrunner = cls(*args, **kwargs) preamble = default_runner.preamble text_pt = default_runner.text_pt text = default_runner.text reset = default_runner.reset # initialize default_runner set() def escapestring(s, replace={" ": "~", "$": "\\$", "&": "\\&", "#": "\\#", "_": "\\_", "%": "\\%", "^": "\\string^", "~": "\\string~", "<": "{$<$}", ">": "{$>$}", "{": "{$\{$}", "}": "{$\}$}", "\\": "{$\setminus$}", "|": "{$\mid$}"}): "Escapes ASCII characters such that they can be typeset by TeX/LaTeX""" i = 0 while i < len(s): if not 32 <= ord(s[i]) < 127: raise ValueError("escapestring function handles ascii strings only") c = s[i] try: r = replace[c] except KeyError: i += 1 else: s = s[:i] + r + s[i+1:] i += len(r) return s PyX-0.14.1/pyx/trafo.py0000644000076500000240000002112112516264143015037 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2011 Jörg Lehmann # Copyright (C) 2002-2011 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import math from . import attr, baseclasses, unit # some helper routines def _rmatrix(angle): phi = math.pi*angle/180.0 return ((math.cos(phi), -math.sin(phi)), (math.sin(phi), math.cos(phi))) def _rvector(angle, x, y): phi = math.pi*angle/180.0 return ((1-math.cos(phi))*x + math.sin(phi) *y, -math.sin(phi) *x + (1-math.cos(phi))*y) def _mmatrix(angle): phi = math.pi*angle/180.0 return ( (math.cos(phi)*math.cos(phi)-math.sin(phi)*math.sin(phi), -2*math.sin(phi)*math.cos(phi) ), (-2*math.sin(phi)*math.cos(phi), math.sin(phi)*math.sin(phi)-math.cos(phi)*math.cos(phi) ) ) # trafo: affine transformations class trafo_pt(baseclasses.deformer): """affine transformation (coordinates in constructor in pts) Note that though the coordinates in the constructor are in pts (which is useful for internal purposes), all other methods only accept units in the standard user notation. """ def __init__(self, matrix=((1, 0), (0, 1)), vector=(0, 0)): """Return trafo with given transformation matrix and vector. """ self.matrix = matrix self.vector = vector def __mul__(self, other): if isinstance(other, trafo_pt): matrix = ( ( self.matrix[0][0]*other.matrix[0][0] + self.matrix[0][1]*other.matrix[1][0], self.matrix[0][0]*other.matrix[0][1] + self.matrix[0][1]*other.matrix[1][1] ), ( self.matrix[1][0]*other.matrix[0][0] + self.matrix[1][1]*other.matrix[1][0], self.matrix[1][0]*other.matrix[0][1] + self.matrix[1][1]*other.matrix[1][1] ) ) vector = ( self.matrix[0][0]*other.vector[0] + self.matrix[0][1]*other.vector[1] + self.vector[0], self.matrix[1][0]*other.vector[0] + self.matrix[1][1]*other.vector[1] + self.vector[1] ) return trafo_pt(matrix=matrix, vector=vector) else: raise NotImplementedError("can only multiply two transformations") def __str__(self): return "[%f %f %f %f %f %f]" % \ ( self.matrix[0][0], self.matrix[1][0], self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) def processPS(self, file, writer, context, registry): file.write("[%f %f %f %f %f %f] concat\n" % \ ( self.matrix[0][0], self.matrix[1][0], self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) ) def processPDF(self, file, writer, context, registry): file.write("%f %f %f %f %f %f cm\n" % \ ( self.matrix[0][0], self.matrix[1][0], self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) ) def processSVGattrs(self, attrs, writer, context, registry): assert "transform" not in attrs attrs["transform"] = "matrix(%f,%f,%f,%f,%f,%f)" % \ ( self.matrix[0][0], -self.matrix[1][0], -self.matrix[0][1], self.matrix[1][1], self.vector[0], -self.vector[1] ) def apply_pt(self, x_pt, y_pt): """apply transformation to point (x_pt, y_pt) in pts""" return ( self.matrix[0][0]*x_pt + self.matrix[0][1]*y_pt + self.vector[0], self.matrix[1][0]*x_pt + self.matrix[1][1]*y_pt + self.vector[1] ) def apply(self, x, y): # for the transformation we have to convert to points tx, ty = self.apply_pt(unit.topt(x), unit.topt(y)) return tx * unit.t_pt, ty * unit.t_pt def deform(self, path): return path.transformed(self) def inverse(self): det = 1.0*(self.matrix[0][0]*self.matrix[1][1] - self.matrix[0][1]*self.matrix[1][0]) matrix = ( ( self.matrix[1][1]/det, -self.matrix[0][1]/det), (-self.matrix[1][0]/det, self.matrix[0][0]/det) ) return ( trafo_pt(matrix=matrix) * trafo_pt(vector=(-self.vector[0], -self.vector[1])) ) def mirrored(self, angle): return mirror(angle) * self def rotated_pt(self, angle, x=None, y=None): return rotate_pt(angle, x, y) * self def rotated(self, angle, x=None, y=None): return rotate(angle, x, y) * self def scaled_pt(self, sx, sy=None, x=None, y=None): return scale_pt(sx, sy, x, y) * self def scaled(self, sx, sy=None, x=None, y=None): return scale(sx, sy, x, y) * self def slanted_pt(self, a, angle=0, x=None, y=None): return slant_pt(a, angle, x, y) * self def slanted(self, a, angle=0, x=None, y=None): return slant(a, angle, x, y) * self def translated_pt(self, x, y): return translate_pt(x, y) * self def translated(self, x, y): return translate(x, y) * self class trafo(trafo_pt): """affine transformation""" def __init__(self, matrix=((1,0), (0,1)), vector=(0, 0)): trafo_pt.__init__(self, matrix, (unit.topt(vector[0]), unit.topt(vector[1]))) # # some standard transformations # identity = trafo() class mirror(trafo): def __init__(self, angle=0): trafo.__init__(self, matrix=_mmatrix(angle)) class rotate_pt(trafo_pt): def __init__(self, angle, x=None, y=None): vector = 0, 0 if x is not None or y is not None: if x is None or y is None: raise TrafoException("either specify both x and y or none of them") vector=_rvector(angle, x, y) trafo_pt.__init__(self, matrix=_rmatrix(angle), vector=vector) class rotate(trafo_pt): def __init__(self, angle, x=None, y=None): vector = 0, 0 if x is not None or y is not None: if x is None or y is None: raise TrafoException("either specify both x and y or none of them") vector=_rvector(angle, unit.topt(x), unit.topt(y)) trafo_pt.__init__(self, matrix=_rmatrix(angle), vector=vector) class scale_pt(trafo_pt): def __init__(self, sx, sy=None, x=None, y=None): if sy is None: sy = sx vector = 0, 0 if x is not None or y is not None: if x is None or y is None: raise TrafoException("either specify both x and y or none of them") vector = (1-sx)*x, (1-sy)*y trafo_pt.__init__(self, matrix=((sx, 0), (0, sy)), vector=vector) class scale(trafo): def __init__(self, sx, sy=None, x=None, y=None): if sy is None: sy = sx vector = 0, 0 if x is not None or y is not None: if x is None or y is None: raise TrafoException("either specify both x and y or none of them") vector = (1-sx)*x, (1-sy)*y trafo.__init__(self, matrix=((sx, 0), (0, sy)), vector=vector) class slant_pt(trafo_pt): def __init__(self, a, angle=0, x=None, y=None): t = ( rotate_pt(-angle, x, y) * trafo(matrix=((1, a), (0, 1))) * rotate_pt(angle, x, y) ) trafo_pt.__init__(self, t.matrix, t.vector) class slant(trafo): def __init__(self, a, angle=0, x=None, y=None): t = ( rotate(-angle, x, y) * trafo(matrix=((1, a), (0, 1))) * rotate(angle, x, y) ) trafo.__init__(self, t.matrix, t.vector) class translate_pt(trafo_pt): def __init__(self, x, y): trafo_pt.__init__(self, vector=(x, y)) class translate(trafo): def __init__(self, x, y): trafo.__init__(self, vector=(x, y)) PyX-0.14.1/pyx/unit.py0000644000076500000240000001646712177540640014726 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2004 Jörg Lehmann # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import types, functools scale = dict(u=1, v=1, w=1, x=1) _default_unit = "cm" _m = { "m": 1, "cm": 0.01, "mm": 0.001, "inch": 0.01*2.54, "pt": 0.01*2.54/72, } def set(uscale=None, vscale=None, wscale=None, xscale=None, defaultunit=None): if uscale is not None: scale["u"] = uscale if vscale is not None: scale["v"] = vscale if wscale is not None: scale["w"] = wscale if xscale is not None: scale["x"] = xscale if defaultunit is not None: global _default_unit _default_unit = defaultunit def _convert_to(l, dest_unit="m"): if isinstance(l, length): return (l.t + l.u*scale["u"] + l.v*scale["v"] + l.w*scale["w"] + l.x*scale["x"]) / _m[dest_unit] else: return l * _m[_default_unit] * scale["u"] / _m[dest_unit] def tom(l): return _convert_to(l, "m") def tocm(l): return _convert_to(l, "cm") def tomm(l): return _convert_to(l, "mm") def toinch(l): return _convert_to(l, "inch") def topt(l): return _convert_to(l, "pt") ################################################################################ # class for generic length ################################################################################ @functools.total_ordering class length: """ PyX lengths PyX lengths are composed of five components (t=true, u=user, v=visual, w=width, and x=TeX) which can be scaled separately (except for the true component, which is always unscaled). Lengths can be constructed in units of "pt", "mm", "cm", "m" and "inch". When no unit is given, a module default is used, which can be changed with the help of the module level function set(). """ def __init__(self, f=0, type="u", unit=None): """ create a length instance of the given type with a length f in the given unit. If unit is not set, the currently set default unit is used. """ self.t = self.u = self.v = self.w = self.x = 0 l = float(f) * _m[unit or _default_unit] if type == "t": self.t = l elif type == "u": self.u = l elif type == "v": self.v = l elif type == "w": self.w = l elif type == "x": self.x = l def __eq__(self, other): try: return tom(self) == tom(other) except TypeError: return NotImplemented def __lt__(self, other): try: return tom(self) < tom(other) except TypeError: return NotImplemented def __mul__(self, factor): result = length() result.t = factor * self.t result.u = factor * self.u result.v = factor * self.v result.w = factor * self.w result.x = factor * self.x return result __rmul__=__mul__ def __div__(self, divisor): if isinstance(divisor, length): return tom(self) / tom(divisor) result = length() result.t = self.t / divisor result.u = self.u / divisor result.v = self.v / divisor result.w = self.w / divisor result.x = self.x / divisor return result __truediv__ = __div__ def __add__(self, other): # convert to length if necessary if not isinstance(other, length): # if other is not a length, we try to convert it into a length and # if this fails, we give other a chance to do the addition try: other = length(other) except: return other + self result = length() result.t = self.t + other.t result.u = self.u + other.u result.v = self.v + other.v result.w = self.w + other.w result.x = self.x + other.x return result __radd__ = __add__ def __sub__(self, other): # convert to length if necessary if not isinstance(other, length): # if other is not a length, we try to convert it into a length and # if this fails, we give other a chance to do the subtraction try: other = length(other) except: return -other + self result = length() result.t = self.t - other.t result.u = self.u - other.u result.v = self.v - other.v result.w = self.w - other.w result.x = self.x - other.x return result def __rsub__(self, other): # convert to length if necessary if not isinstance(other, length): other = length(other) result = length() result.t = other.t - self.t result.u = other.u - self.u result.v = other.v - self.v result.w = other.w - self.w result.x = other.x - self.x return result def __neg__(self): result = length() result.t = -self.t result.u = -self.u result.v = -self.v result.w = -self.w result.x = -self.x return result def __str__(self): return "(%(t)f t + %(u)f u + %(v)f v + %(w)f w + %(x)f x) m" % self.__dict__ ################################################################################ # predefined instances which can be used as length units ################################################################################ # user lengths and unqualified length which are also user length u_pt = pt = length(1, type="u", unit="pt") u_m = m = length(1, type="u", unit="m") u_mm = mm = length(1, type="u", unit="mm") u_cm = cm = length(1, type="u", unit="cm") u_inch = inch = length(1, type="u", unit="inch") # true lengths t_pt = length(1, type="t", unit="pt") t_m = length(1, type="t", unit="m") t_mm = length(1, type="t", unit="mm") t_cm = length(1, type="t", unit="cm") t_inch = length(1, type="t", unit="inch") # visual lengths v_pt = length(1, type="v", unit="pt") v_m = length(1, type="v", unit="m") v_mm = length(1, type="v", unit="mm") v_cm = length(1, type="v", unit="cm") v_inch = length(1, type="v", unit="inch") # width lengths w_pt = length(1, type="w", unit="pt") w_m = length(1, type="w", unit="m") w_mm = length(1, type="w", unit="mm") w_cm = length(1, type="w", unit="cm") w_inch = length(1, type="w", unit="inch") # TeX lengths x_pt = length(1, type="x", unit="pt") x_m = length(1, type="x", unit="m") x_mm = length(1, type="x", unit="mm") x_cm = length(1, type="x", unit="cm") x_inch = length(1, type="x", unit="inch") PyX-0.14.1/pyx/version.py0000644000076500000240000000200312615760677015424 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2002-2012 Jörg Lehmann # Copyright (C) 2002-2012 André Wobst # Copyright (C) 2011 Michael Schindler # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA version = "0.14.1" date = "2015/11/02" PyX-0.14.1/pyx/writer.py0000644000076500000240000000265412177540640015254 0ustar andrestaff00000000000000# -*- encoding: utf-8 -*- # # # Copyright (C) 2013 Jörg Lehmann # Copyright (C) 2013 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # # PyX is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PyX is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyX; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA class writer: def __init__(self, file, encoding="ascii", errors="surrogateescape"): self.file = file self.encoding = encoding self.errors = errors def write(self, s): self.file.write(s.encode(self.encoding, errors=self.errors)) def write_bytes(self, b): self.file.write(b) def tell(self): return self.file.tell() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): return self.file.__exit__(exc_type, exc_value, traceback) PyX-0.14.1/README0000644000076500000240000000265112037344757013431 0ustar andrestaff00000000000000 PyX - Python graphics package ============================= PyX is a Python package for the creation of PostScript and PDF files. It combines an abstraction of the PostScript drawing model with a TeX/LaTeX interface. Complex tasks like 2d and 3d plots in publication-ready quality are built out of these primitives. Installation ------------ The installation of PyX is described in the file INSTALL. Documentation ------------- A prebuilt version of the manual can be found on the PyX webpage under http://pyx.sourceforge.net/manual.pdf. For answers to frequently asked questions, we refer to pyx/pyxfaq.pdf. We also recommend taking a look on the nice examples for the use of PyX, which can be found in the examples directory. License ------- PyX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. PyX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with PyX; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA PyX-0.14.1/setup.cfg0000644000076500000240000000122612516237224014357 0ustar andrestaff00000000000000[PyX] # In this section you can specify which c extension modules should be built # C extension module for fast t1font decoding and encoding build_t1code=0 # Python bindings for the kpathsea library. You need the kpathsea header # and library and you may need to specify their location below. build_pykpathsea=0 # use setuptools instead of distutils use_setuptools=0 [build_ext] # additional include and library directories: # insert paths to the libkpathsea headers and library, when building # the pykpathsea extention module and libkpathsea is not installed in # the default search paths of your compiler and linker # include_dirs= # library_dirs= PyX-0.14.1/setup.py0000755000076500000240000000564712615753150014267 0ustar andrestaff00000000000000#!/usr/bin/env python3 # -*- encoding: utf-8 -*- """Python package for the generation of PostScript, PDF, and SVG files PyX is a Python package for the creation of PostScript, PDF, and SVG files. It combines an abstraction of the PostScript drawing model with a TeX/LaTeX interface. Complex tasks like 2d and 3d plots in publication-ready quality are built out of these primitives.""" import sys if sys.version_info[0] == 2: print("""*** Sorry, this version of PyX runs on Python 3 only. *** If you want to use PyX on Python 2, please use one of our old releases up to PyX 0.12.x, i.e. execute something like: pip install pyx==0.12.1 """) exit() import configparser import pyx.version cfg = configparser.ConfigParser() cfg.read("setup.cfg") # obtain information on which modules have to be built and whether to use setuptools # instead of distutils from setup.cfg file if cfg.has_section("PyX"): if cfg.has_option("PyX", "use_setuptools") and cfg.getboolean("PyX", "use_setuptools"): from setuptools import setup, Extension setuptools_args={"zip_safe": True} else: from distutils.core import setup, Extension setuptools_args={} # build list of extension modules ext_modules = [] pykpathsea_ext_module = Extension("pyx.pykpathsea", sources=["pyx/pykpathsea.c"], libraries=["kpathsea"]) t1code_ext_module = Extension("pyx.font._t1code", sources=["pyx/font/_t1code.c"]) if cfg.has_option("PyX", "build_pykpathsea") and cfg.getboolean("PyX", "build_pykpathsea"): ext_modules.append(pykpathsea_ext_module) if cfg.has_option("PyX", "build_t1code") and cfg.getboolean("PyX", "build_t1code"): ext_modules.append(t1code_ext_module) description, long_description = __doc__.split("\n\n", 1) setup(name="PyX", version=pyx.version.version, author="Jörg Lehmann, André Wobst", author_email="pyx-devel@lists.sourceforge.net", url="http://pyx.sourceforge.net/", description=description, long_description=long_description, license="GPL", packages=["pyx", "pyx/graph", "pyx/graph/axis", "pyx/font", "pyx/dvi", "pyx/metapost"], package_data={"pyx": ["data/afm/*", "data/lfs/*", "data/def/*", "data/pyxrc"]}, ext_modules=ext_modules, classifiers=["Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "License :: OSI Approved :: GNU General Public License (GPL)", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Multimedia :: Graphics", "Topic :: Scientific/Engineering :: Visualization", "Topic :: Software Development :: Libraries :: Python Modules"], platforms="OS independent", **setuptools_args)