├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CSS.py ├── Configuration.py ├── ConfigurationDialogue.qml ├── ExtrudeCommand.py ├── LICENSE.md ├── Parser.py ├── README.md ├── SVGToolpathReader.py ├── TravelCommand.py ├── WriteGCode.py ├── __init__.py ├── cmake ├── [Content_Types].xml ├── _rels │ ├── .rels │ └── package.json.rels └── package.json.in ├── freetype ├── __init__.py ├── ft_enums │ ├── __init__.py │ ├── ft_curve_tags.py │ ├── ft_encodings.py │ ├── ft_face_flags.py │ ├── ft_fstypes.py │ ├── ft_glyph_bbox_modes.py │ ├── ft_glyph_formats.py │ ├── ft_kerning_modes.py │ ├── ft_lcd_filters.py │ ├── ft_load_flags.py │ ├── ft_load_targets.py │ ├── ft_open_modes.py │ ├── ft_outline_flags.py │ ├── ft_pixel_modes.py │ ├── ft_render_modes.py │ ├── ft_stroker_borders.py │ ├── ft_stroker_linecaps.py │ ├── ft_stroker_linejoins.py │ ├── ft_style_flags.py │ ├── tt_adobe_ids.py │ ├── tt_apple_ids.py │ ├── tt_mac_ids.py │ ├── tt_mac_langids.py │ ├── tt_ms_ids.py │ ├── tt_ms_langids.py │ ├── tt_name_ids.py │ └── tt_platforms.py ├── ft_errors.py ├── ft_structs.py ├── ft_types.py ├── libfreetype.dll ├── libfreetype.dylib └── raw.py ├── icon.svg ├── plugin.json.in └── test ├── circle.svg ├── ellipse.svg ├── line.svg ├── path.svg ├── polygon.svg ├── polyline.svg ├── rect.svg ├── stroke-dasharray.svg ├── text.svg ├── transform.svg └── use.svg /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 1.2.2 - Bug Fixes 2 | ==== 3 | * The plug-in now loads properly in Cura 5.0 and 5.1. 4 | * Fixed crash when loading an SVG with a text element that doesn't have text. 5 | * Fixed font-weight with text values, like 'normal' and 'bold'. 6 | * Fixed dash-array having value 'none'. 7 | * If loading an SVG file via the command line before a printer is added, an error is shown to the user now. 8 | 9 | 1.2.1 - Bug Fixes 10 | ==== 11 | * Fixed sometimes not skipping retractions for 0-length travels due to rounding errors. 12 | * Fixed crash if the user clicks the buttons of the dialog multiple times in quick succession. 13 | * Fixed parsing of paths with scientific notation in the parameters. 14 | 15 | 1.2.0 - Getting Taller 16 | ==== 17 | This update adds support for multi-layer prints. 18 | 19 | New Features 20 | ---- 21 | * Support for repeating the print across multiple layers. 22 | * When loading an SVG file you now get a dialogue asking you how high the print should be. 23 | * Optimise the order of extruded paths to reduce travel distance. Contributed by Jorisa. 24 | * Limit precision to nanometres, to reduce g-code size. 25 | 26 | Bug Fixes 27 | ---- 28 | * Tiny movements will no longer trigger scientific-notation numbers causing retractions with the E parameter. 29 | * Skip 0-length moves. 30 | * Fix getting font families on some Linux installations. 31 | * Fix inheritance of font-family CSS property. 32 | * Fix the viewport offset if it doesn't start on 0,0. 33 | 34 | 1.1.3 - Bug Fixes 35 | ==== 36 | * Add support for Cura 4.4 using SDK version 7.0.0. 37 | 38 | 1.1.2 - Bug Fixes 39 | ==== 40 | * Use the correct unretraction speed. 41 | * Fix the fan speed when retractions are enabled. 42 | 43 | 1.1.1 - Bug Fixes 44 | ==== 45 | * Fix loading the FreeType binary on MacOS. 46 | * Fix detecting features with the `requiredFeatures` attribute. 47 | * Package FreeType with the CuraPackage files. 48 | 49 | 1.1.0 - Literacy Update 50 | ==== 51 | This update adds support for text, among a few other things. 52 | 53 | New Features 54 | ---- 55 | * Support for `defs` and `use` SVG elements. 56 | * Support for `text` SVG elements. 57 | * Support for `font-size` attribute. 58 | * Support for `font-family` attribute. 59 | * Support for `text-transform` attribute. 60 | * Support for `stroke-dasharray` attribute. 61 | * Support for `stroke-dashoffset` attribute. 62 | * Support for `text-decoration-line` attribute. 63 | * Support for `text-decoration-style` attribute. 64 | * Support for `text-decoration` attribute. 65 | * Support for actual lengths in `%`, `mm`, `pt`, etc. No font-size related lengths (like `em`) though. 66 | * Support for the viewport of the SVG file. 67 | * Generate CuraPackage files automatically with CMake. 68 | * Installation to the latest Cura installation with CMake. 69 | 70 | Bug Fixes 71 | ---- 72 | * Order of transformations if more than one transformation is applied to the same element. 73 | * Sizes being relative to the viewport instead of in pure `mm`. 74 | * Rotating around different coordinates than 0,0 was not applied correctly. 75 | * Use the initial layer flow setting rather than normal flow. 76 | 77 | 1.0.0 - Initial Release 78 | ==== 79 | This is the initial release of SVGToolpathReader. It was designed as a way to perform accurate single-line-single-layer tests easily. 80 | 81 | Features 82 | ---- 83 | * Reading SVG files into Cura. 84 | * Reading SVG elements `svg`, `rect`, `circle`, `g`, `ellipse`, `polygon`, `polyline`, `line`, `path`, `style` and `switch`. 85 | * Reading SVG attributes `stroke-width` and `transform`. 86 | * Output the paths as g-code. 87 | * Generate basic g-code with proper g-code headers. -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Cura plug-in to read SVG files as toolpaths. 2 | #Copyright (C) 2019 Ghostkeeper 3 | #This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | #This plug-in 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 Affero General Public License for details. 5 | #You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | project(SVGToolpathReader) 8 | cmake_minimum_required(VERSION 3.10.2) #Oldest version it's been tested with. 9 | 10 | #Project metadata. 11 | set(SVGTOOLPATHREADER_PLUGIN_NAME "SVG Toolpath Reader" CACHE STRING "The name of the plug-in in distribution.") 12 | set(SVGTOOLPATHREADER_VERSION_MAJOR 1 CACHE STRING "The major version number, indicating a backward compatibility break.") 13 | set(SVGTOOLPATHREADER_VERSION_MINOR 2 CACHE STRING "The minor version number, indicating a forward compatibility break.") 14 | set(SVGTOOLPATHREADER_VERSION_PATCH 2 CACHE STRING "The patch version number, indicating an incremental improvement without compatibility break.") 15 | set(SVGTOOLPATHREADER_SUPPORTED_SDKS "5.0.0;6.0.0;7.0.0;8.0.0" CACHE STRING "List of supported Cura SDK versions.") 16 | 17 | #Installation. 18 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/plugin.json.in" plugin.json) 19 | set(installed_files 20 | __init__.py 21 | Configuration.py 22 | ConfigurationDialogue.qml 23 | ExtrudeCommand.py 24 | icon.svg 25 | LICENSE.md 26 | Parser.py 27 | README.md 28 | SVGToolpathReader.py 29 | TravelCommand.py 30 | WriteGCode.py 31 | ) 32 | set(installed_files_freetype 33 | __init__.py 34 | ft_errors.py 35 | ft_structs.py 36 | ft_types.py 37 | libfreetype.dll 38 | libfreetype.dylib 39 | raw.py 40 | ) 41 | set(installed_files_freetype_ft_enums 42 | __init__.py 43 | ft_curve_tags.py 44 | ft_encodings.py 45 | ft_face_flags.py 46 | ft_fstypes.py 47 | ft_glyph_bbox_modes.py 48 | ft_glyph_formats.py 49 | ft_kerning_modes.py 50 | ft_lcd_filters.py 51 | ft_load_flags.py 52 | ft_load_targets.py 53 | ft_open_modes.py 54 | ft_outline_flags.py 55 | ft_pixel_modes.py 56 | ft_render_modes.py 57 | ft_stroker_borders.py 58 | ft_stroker_linecaps.py 59 | ft_stroker_linejoins.py 60 | ft_style_flags.py 61 | tt_adobe_ids.py 62 | tt_apple_ids.py 63 | tt_mac_ids.py 64 | tt_mac_langids.py 65 | tt_ms_ids.py 66 | tt_ms_langids.py 67 | tt_name_ids.py 68 | tt_platforms.py 69 | ) 70 | set(installed_paths "") 71 | foreach(f IN LISTS installed_files) 72 | list(APPEND installed_paths ${CMAKE_CURRENT_SOURCE_DIR}/${f}) 73 | endforeach() 74 | list(APPEND installed_paths ${CMAKE_CURRENT_BINARY_DIR}/plugin.json) 75 | set(installed_paths_freetype "") 76 | foreach(f IN LISTS installed_files_freetype) 77 | list(APPEND installed_paths_freetype ${CMAKE_CURRENT_SOURCE_DIR}/freetype/${f}) 78 | endforeach() 79 | set(installed_paths_freetype_ft_enums "") 80 | foreach(f IN LISTS installed_files_freetype_ft_enums) 81 | list(APPEND installed_paths_freetype_ft_enums ${CMAKE_CURRENT_SOURCE_DIR}/freetype/ft_enums/${f}) 82 | endforeach() 83 | 84 | #Find out where to install this thing. 85 | if(WIN32) 86 | set(cura_directory "$ENV{APPDATA}\\cura") 87 | elseif(APPLE) 88 | set(cura_directory "$ENV{HOME}/Library/Application Support/cura") 89 | else() 90 | set(cura_directory "$ENV{HOME}/.local/share/cura") 91 | endif() 92 | #Figure out the latest Cura release that's installed. 93 | file(GLOB versions RELATIVE "${cura_directory}" "${cura_directory}/*") 94 | set(latest_version 2.0) 95 | foreach(version ${versions}) 96 | if(IS_DIRECTORY "${cura_directory}/${version}") 97 | if(${version} VERSION_GREATER ${latest_version}) 98 | set(latest_version ${version}) 99 | endif() 100 | endif() 101 | endforeach() 102 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 103 | set(CMAKE_INSTALL_PREFIX "${cura_directory}/${latest_version}/plugins" CACHE PATH "Location of the Cura plug-ins folder to install this plug-in to." FORCE) 104 | endif() 105 | install(FILES ${installed_paths} DESTINATION SVGToolpathReader) 106 | install(FILES ${installed_paths_freetype} DESTINATION SVGToolpathReader/freetype) 107 | install(FILES ${installed_paths_freetype_ft_enums} DESTINATION SVGToolpathReader/freetype/ft_enums) 108 | 109 | #Packing this into a .curapackage file. 110 | add_custom_target(pack COMMAND "") #Packs for all supported SDK versions. 111 | foreach(sdk_version ${SVGTOOLPATHREADER_SUPPORTED_SDKS}) 112 | file(COPY ${installed_paths} DESTINATION pack${sdk_version}/files/plugins/SVGToolpathReader) 113 | file(COPY ${installed_paths_freetype} DESTINATION pack${sdk_version}/files/plugins/SVGToolpathReader/freetype) 114 | file(COPY ${installed_paths_freetype_ft_enums} DESTINATION pack${sdk_version}/files/plugins/SVGToolpathReader/freetype/ft_enums) 115 | file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/[Content_Types].xml" DESTINATION pack${sdk_version}) 116 | file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/_rels" DESTINATION pack${sdk_version}) 117 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/package.json.in" pack${sdk_version}/package.json) 118 | set(packaged_files 119 | package.json 120 | [Content_Types].xml 121 | _rels 122 | files 123 | ) 124 | add_custom_target(pack${sdk_version} 125 | COMMAND "${CMAKE_COMMAND}" -E tar cfv ../SVGToolpathReader${SVGTOOLPATHREADER_VERSION_MAJOR}.${SVGTOOLPATHREADER_VERSION_MINOR}.${SVGTOOLPATHREADER_VERSION_PATCH}-sdk${sdk_version}.curapackage --format=zip ${packaged_files} 126 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pack${sdk_version} 127 | ) 128 | add_dependencies(pack pack${sdk_version}) 129 | endforeach() 130 | 131 | #Let CPack find it. 132 | include(InstallRequiredSystemLibraries) 133 | set(CPACK_PACKAGE_VERSION_MAJOR ${SVGTOOLPATHREADER_VERSION_MAJOR}) 134 | set(CPACK_PACKAGE_VERSION_MINOR ${SVGTOOLPATHREADER_VERSION_MINOR}) 135 | set(CPACK_PACKAGE_VERSION_PATCH ${SVGTOOLPATHREADER_VERSION_PATCH}) 136 | set(CPACK_PACKAGE_NAME ${SVGTOOLPATHREADER_PLUGIN_NAME}) 137 | set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md) 138 | set(CPACK_GENERATOR ZIP) 139 | include(CPack) 140 | -------------------------------------------------------------------------------- /CSS.py: -------------------------------------------------------------------------------- 1 | #Cura plug-in to read SVG files as toolpaths. 2 | #Copyright (C) 2019 Ghostkeeper 3 | #This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | #This plug-in 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 Affero General Public License for details. 5 | #You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | import collections # For the named tuple. 8 | import math # For computing transformation matrices from Euclidean angles. 9 | import numpy # For computing transformation matrices. 10 | import re # For parsing the CSS source. 11 | import typing 12 | import UM.Logger # Reporting parsing failures. 13 | 14 | CSSAttribute = collections.namedtuple("CSSAttribute", [ 15 | "name", # The name of the attribute. 16 | "value", # The current value of the attribute. 17 | "validate", # A validation predicate for the attribute. 18 | ]) 19 | 20 | class CSS: 21 | """ 22 | Tracks and parses CSS attributes for an element. 23 | 24 | The main function of this class is to group together all CSS properties for 25 | an element. In order to construct it easily, it will also do the work of 26 | parsing the (supported) CSS attributes. 27 | """ 28 | 29 | def __init__(self, parser) -> None: 30 | """ 31 | Creates a new set of CSS attributes. 32 | 33 | The attributes are initialised to their defaults. 34 | :param parser: The parser that is currently parsing a document. 35 | """ 36 | self.parser = parser 37 | 38 | # Some re-usable validation functions 39 | is_float = lambda s: re.fullmatch(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", s) is not None 40 | tautology = lambda s: True 41 | is_list_of_lengths = lambda s: re.fullmatch(r"([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?(cap|ch|em|ex|ic|lh|rem|rlh|vh|vw|vi|vb|vmin|vmax|px|cm|mm|Q|in|pc|pt|%)?[,\s])*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)?(cap|ch|em|ex|ic|lh|rem|rlh|vh|vw|vi|vb|vmin|vmax|px|cm|mm|Q|in|pc|pt|%)?", s) is not None 42 | is_length = lambda s: re.fullmatch(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?(cap|ch|em|ex|ic|lh|rem|rlh|vh|vw|vi|vb|vmin|vmax|px|cm|mm|Q|in|pc|pt|%)?", s) 43 | 44 | self.attributes = { 45 | # Name Name again Default Validation function 46 | "font-family": CSSAttribute("font-family", "serif", tautology), 47 | "font-size": CSSAttribute("font-size", "12pt", is_length), 48 | "font-style": CSSAttribute("font-style", "normal", lambda s: s in {"normal", "italic", "oblique", "initial"}), # Don't include "inherit" since we want it to inherit then as if not set. 49 | "font-weight": CSSAttribute("font-weight", "400", is_float), 50 | "stroke-dasharray": CSSAttribute("stroke-dasharray", "", is_list_of_lengths), 51 | "stroke-dashoffset": CSSAttribute("stroke-dashoffset", "0", is_length), 52 | "stroke-width": CSSAttribute("stroke-width", "0", is_length), 53 | "text-decoration": CSSAttribute("text-decoration", "", tautology), # Not going to do any sort of validation on this one since it has all the colours and that's just way too complex. 54 | "text-decoration-line": CSSAttribute("text-decoration-line", "", lambda s: all([part in {"none", "overline", "underline", "line-through", "initial"} for part in s.split()])), 55 | "text-decoration-style": CSSAttribute("text-decoration-style", "solid", lambda s: s in {"solid", "double", "dotted", "dashed", "wavy", "initial"}), 56 | "text-transform": CSSAttribute("text-transform", "none", lambda s: s in {"none", "capitalize", "uppercase", "lowercase", "initial"}), # Don't include "inherit" again. 57 | "transform": CSSAttribute("transform", "", tautology) # Not going to do any sort of validation on this one because all the transformation functions make it very complex. 58 | } 59 | self.dasharray = [] 60 | self.dasharray_length = 0 61 | 62 | def parse(self, css) -> None: 63 | """ 64 | Parse the supported CSS properties from a string of serialised CSS. 65 | 66 | The results are stored in this CSS instance. 67 | :param css: The piece of CSS to parse. 68 | """ 69 | pieces = css.split(";") 70 | for piece in pieces: 71 | piece = piece.strip() 72 | if ":" not in piece: # Only parse well-formed CSS rules, which are key-value pairs separated by a colon. 73 | UM.Logger.Logger.log("w", "Ill-formed CSS rule: {piece}".format(piece=piece)) 74 | continue 75 | attribute = piece[:piece.index(":")] 76 | value = piece[piece.index(":") + 1] 77 | if attribute not in self.attributes: 78 | UM.Logger.Logger.log("w", "Unknown CSS attribute {attribute}".format(attribute=attribute)) 79 | continue 80 | if not self.attributes[attribute].validate(value): 81 | UM.Logger.Logger.log("w", "Invalid value for CSS attribute {attribute}: {value}".format(attribute=attribute, value=value)) 82 | continue 83 | self.attributes[attribute].value = value 84 | 85 | def convert_dasharray(self, dasharray) -> None: 86 | """ 87 | Parses a stroke-dasharray property out of CSS. 88 | 89 | The length elements are converted into millimetres for extrusion. 90 | 91 | The result is stored in self.dasharray, to be used with the next drawn 92 | lines. Also, the total length is computed and stored in 93 | self.dasharray_length for re-use. 94 | :param dasharray: A stroke-dasharray property value. 95 | """ 96 | dasharray = dasharray.replace(",", " ") 97 | length_list = dasharray.split() 98 | self.dasharray = [] 99 | self.dasharray_length = 0 100 | for length in length_list: 101 | length_mm = self.convert_length(length) 102 | if length_mm < 0: 103 | continue # Invalid. Ignore this one. 104 | self.dasharray.append(length_mm) 105 | self.dasharray_length += length_mm 106 | if len(self.dasharray) % 2 == 1: # Double the sequence so that every segment is the same w.r.t. which is extruded and which is travelled. 107 | self.dasharray *= 2 108 | self.dasharray_length *= 2 109 | 110 | def convert_length(self, dimension, vertical=False, parent_size=None) -> float: 111 | """ 112 | Converts a CSS dimension to millimetres. 113 | 114 | For pixels, this assumes a resolution of 96 dots per inch. 115 | :param dimension: A CSS dimension. 116 | :param vertical: The dimension is a vertical one, so it should be taken 117 | relative to other vertical dimensions for some units, such as the 118 | vertical size of the parent if using percentages. 119 | :param parent_size: The size in millimetres of the element that contains 120 | the element that we're getting the dimension for. If ``None``, this will 121 | be set to the printer's width. 122 | :return: How many millimetres long that dimension is. 123 | """ 124 | number = re.match(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", dimension) 125 | if not number: 126 | return 0 127 | number = number.group(0) 128 | unit = dimension[len(number):].strip().lower() 129 | number = float(number) 130 | 131 | if unit == "mm": 132 | return number 133 | elif unit == "px": 134 | return number / 96 * 25.4 135 | elif unit == "cm": 136 | return number * 10 137 | elif unit == "q": 138 | return number / 4 139 | elif unit == "in": 140 | return number * 25.4 141 | elif unit == "pc": 142 | return number * 12 / 72 * 25.4 143 | elif unit == "pt": 144 | return number / 72 * 25.4 145 | 146 | elif unit == "%": 147 | if parent_size is None: 148 | if vertical: 149 | parent_size = self.parser.image_h 150 | else: 151 | parent_size = self.parser.image_w 152 | return number / 100 * parent_size 153 | elif unit == "vh" or unit == "vb": 154 | return number / 100 * self.parser.image_w 155 | elif unit == "vw" or unit == "vi": 156 | return number / 100 * self.parser.image_h 157 | elif unit == "vmin": 158 | return number / 100 * min(self.parser.image_w, self.parser.image_h) 159 | elif unit == "vmax": 160 | return number / 100 * max(self.parser.image_w, self.parser.image_h) 161 | 162 | else: # Assume viewport-units. 163 | if vertical: 164 | return number * self.parser.unit_h 165 | else: 166 | return number * self.parser.unit_w 167 | #TODO: Implement font-relative sizes. 168 | 169 | def convert_float(self, dictionary, attribute, default: float) -> float: 170 | """ 171 | Parses an attribute as float, if possible. 172 | 173 | If impossible or missing, this returns the default. 174 | :param dictionary: The attributes dictionary to get the attribute from. 175 | :param attribute: The attribute to get from the dictionary. 176 | :param default: The default value for this attribute, in case the 177 | value is missing or invalid. 178 | :return: A floating point number that was in the attribute, or the default. 179 | """ 180 | try: 181 | return float(dictionary.get(attribute, default)) 182 | except ValueError: # Not parsable as float. 183 | return default 184 | 185 | def convert_font_family(self, font_family) -> str: 186 | """ 187 | Parses a font-family, converting it to the file name of a single font 188 | that is installed on the system. 189 | :param font_family: The font-family property from CSS. 190 | :return: The file name of a font that is installed on the system that 191 | most closely approximates the desired font family. 192 | """ 193 | fonts = font_family.split(",") 194 | fonts = [font.strip() for font in fonts] 195 | 196 | self.parser.detect_fonts_thread.join() # All fonts need to be in at this point. 197 | 198 | for font in fonts: 199 | if font in self.parser.safe_fonts: 200 | font = self.parser.safe_fonts[font] 201 | for candidate in self.parser.system_fonts: 202 | if font.lower() == candidate.lower(): # Case-insensitive matching. 203 | return candidate 204 | UM.Logger.Logger.log("w", "Desired fonts not available on the system: {family}".format(family=font_family)) 205 | if self.parser.safe_fonts["serif"] in self.parser.system_fonts: 206 | return self.parser.safe_fonts["serif"] 207 | if self.parser.system_fonts: 208 | return next(iter(self.parser.system_fonts)) # Take an arbitrary font that is available. Running out of options, here! 209 | return "Noto Sans" # Default font of Cura. Hopefully that gets installed somewhere. 210 | 211 | def convert_points(self, points) -> typing.Generator[typing.Tuple[float, float], None, None]: 212 | """ 213 | Parses a points attribute, turning it into a list of coordinate pairs. 214 | 215 | If there is a syntax error, that part of the points will get ignored. 216 | Other parts might still be included. 217 | :param points: A series of points. 218 | :return: A list of x,y pairs. 219 | """ 220 | points = points.replace(",", " ") 221 | while " " in points: 222 | points = points.replace(" ", " ") 223 | points = points.strip() 224 | points = points.split() 225 | if len(points) % 2 != 0: # If we have an odd number of points, leave out the last. 226 | points = points[:-1] 227 | 228 | for x, y in (points[i:i + 2] for i in range(0, len(points), 2)): 229 | try: 230 | yield float(x), float(y) 231 | except ValueError: # Not properly formatted floats. 232 | continue 233 | 234 | def convert_transform(self, transform) -> numpy.ndarray: 235 | """ 236 | Parses a transformation attribute, turning it into a transformation 237 | matrix. 238 | 239 | If there is a syntax error somewhere in the transformation, that part of 240 | the transformation gets ignored. Other parts might still be applied. 241 | 242 | 3D transformations are not supported. 243 | :param transform: A series of transformation commands. 244 | :return: A Numpy array that would apply the transformations indicated 245 | by the commands. The array is a 2D affine transformation (3x3). 246 | """ 247 | transformation = numpy.identity(3) 248 | 249 | transform = transform.replace(")", ") ") #Ensure that every command is separated by spaces, even though func(0.5)fanc(2) is allowed. 250 | while " " in transform: 251 | transform = transform.replace(" ", " ") 252 | transform = transform.replace(", ", ",") #Don't split on commas. 253 | transform = transform.replace(" ,", ",") 254 | commands = transform.split() 255 | for command in commands: 256 | command = command.strip() 257 | if command == "none": 258 | continue #Ignore. 259 | if command == "initial": 260 | transformation = numpy.identity(3) 261 | continue 262 | 263 | if "(" not in command: 264 | continue #Invalid: Not a function. 265 | name_and_value = command.split("(") 266 | if len(name_and_value) != 2: 267 | continue #Invalid: More than one opening bracket. 268 | name, value = name_and_value 269 | name = name.strip().lower() 270 | if ")" not in value: 271 | continue #Invalid: Bracket not closed. 272 | value = value[:value.find(")")] #Ignore everything after closing bracket. Should be nothing due to splitting on spaces higher. 273 | values = [float(val) for val in value.replace(",", " ").split() if val] 274 | 275 | if name == "matrix": 276 | if len(values) != 6: 277 | continue #Invalid: Needs 6 arguments. 278 | transformation = numpy.matmul(transformation, numpy.array(((values[0], values[1], values[2]), (values[3], values[4], values[5]), (0, 0, 1)))) 279 | elif name == "translate": 280 | if len(values) == 1: 281 | values.append(0) 282 | if len(values) != 2: 283 | continue #Invalid: Translate needs at least 1 and at most 2 arguments. 284 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, values[0]), (0, 1, values[1]), (0, 0, 1)))) 285 | elif name == "translatex": 286 | if len(values) != 1: 287 | continue #Invalid: Needs 1 argument. 288 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, values[0]), (0, 1, 0), (0, 0, 1)))) 289 | elif name == "translatey": 290 | if len(values) != 1: 291 | continue #Invalid: Needs 1 argument. 292 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, 0), (0, 1, values[0]), (0, 0, 1)))) 293 | elif name == "scale": 294 | if len(values) == 1: 295 | values.append(values[0]) #Y scale needs to be the same as X scale then. 296 | if len(values) != 2: 297 | continue #Invalid: Scale needs at least 1 and at most 2 arguments. 298 | transformation = numpy.matmul(transformation, numpy.array(((values[0], 0, 0), (0, values[1], 0), (0, 0, 1)))) 299 | elif name == "scalex": 300 | if len(values) != 1: 301 | continue #Invalid: Needs 1 argument. 302 | transformation = numpy.matmul(transformation, numpy.array(((values[0], 0, 0), (0, 1, 0), (0, 0, 1)))) 303 | elif name == "scaley": 304 | if len(values) != 1: 305 | continue #Invalid: Needs 1 argument. 306 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, 0), (0, values[0], 0), (0, 0, 1)))) 307 | elif name == "rotate" or name == "rotatez": #Allow the 3D operation rotateZ as it simply rotates the 2D image in the same way. 308 | if len(values) == 1: 309 | values.append(0) 310 | values.append(0) 311 | if len(values) != 3: 312 | continue #Invalid: Rotate needs 1 or 3 arguments. 313 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, values[1]), (0, 1, values[2]), (0, 0, 1)))) 314 | transformation = numpy.matmul(transformation, numpy.array(((math.cos(values[0] / 180 * math.pi), -math.sin(values[0] / 180 * math.pi), 0), (math.sin(values[0] / 180 * math.pi), math.cos(values[0] / 180 * math.pi), 0), (0, 0, 1)))) 315 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, -values[1]), (0, 1, -values[2]), (0, 0, 1)))) 316 | elif name == "skew": 317 | if len(values) != 2: 318 | continue #Invalid: Needs 2 arguments. 319 | transformation = numpy.matmul(transformation, numpy.array(((1, math.tan(values[0] / 180 * math.pi), 0), (math.tan(values[1] / 180 * math.pi), 1, 0), (0, 0, 1)))) 320 | elif name == "skewx": 321 | if len(values) != 1: 322 | continue #Invalid: Needs 1 argument. 323 | transformation = numpy.matmul(transformation, numpy.array(((1, math.tan(values[0] / 180 * math.pi), 0), (0, 1, 0), (0, 0, 1)))) 324 | elif name == "skewy": 325 | if len(values) != 1: 326 | continue #Invalid: Needs 1 argument. 327 | transformation = numpy.matmul(transformation, numpy.array(((1, 0, 0), (math.tan(values[0] / 180 * math.pi), 1, 0), (0, 0, 1)))) 328 | else: 329 | continue #Invalid: Unrecognised transformation operation (or 3D). 330 | 331 | return transformation -------------------------------------------------------------------------------- /Configuration.py: -------------------------------------------------------------------------------- 1 | # Cura plug-in to read SVG files as toolpaths. 2 | # Copyright (C) 2022 Ghostkeeper 3 | # This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | # This plug-in 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 Affero General Public License for details. 5 | # You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | import os.path # To find the QML file to display. 8 | try: 9 | from PyQt6.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot, Qt # To display an interface to the user. 10 | qt_version = 6 11 | except ImportError: 12 | from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot, Qt 13 | qt_version = 5 14 | import threading # To wait for the user to close the UI. 15 | import UM.Application 16 | import UM.Mesh.MeshReader # To return the correct prompt response for the preread. 17 | import UM.Message # To show errors. 18 | 19 | class Configuration(QObject): 20 | """ 21 | This class shows a dialogue that asks the user how he'd like to load the 22 | file. 23 | 24 | You can show the dialogue with the ``prompt`` function. 25 | """ 26 | 27 | _show_ui_trigger = pyqtSignal() 28 | """ 29 | Signal to show the UI. 30 | 31 | This is necessary because the UI can only be created on the QML Engine 32 | thread. Creating it from the emittance of this trigger moves the creation 33 | to that thread. 34 | """ 35 | 36 | def __init__(self) -> None: 37 | """ 38 | Creates the configuration object. 39 | 40 | This doesn't create the actual UI yet. That will be created lazily by 41 | the ``prompt`` function. 42 | """ 43 | super().__init__(parent=UM.Application.Application.getInstance().getMainWindow()) 44 | self.ui_element = None 45 | self._file_name = None 46 | self._ui_lock = threading.Lock() 47 | self._status = UM.Mesh.MeshReader.MeshReader.PreReadResult.failed 48 | self._show_ui_trigger.connect(self._prompt) 49 | self._height = 0.1 50 | 51 | def prompt(self, file_name) -> UM.Mesh.MeshReader.MeshReader.PreReadResult: 52 | """ 53 | Asks the user how he'd like to read the file. 54 | 55 | This will show a dialogue to the user with some options. The thread 56 | will be blocked until the dialogue is closed. 57 | :param file_name: The path to the file that is to be read. 58 | :return: The result of the dialogue, whether it is accepted, declined 59 | or there was an error. 60 | """ 61 | self._file_name = file_name 62 | self._ui_lock.acquire() 63 | self._show_ui_trigger.emit() 64 | self._wait_for_ui() 65 | return self._status 66 | 67 | def create_ui(self): 68 | """ 69 | Loads the dialogue element from the QML file. 70 | """ 71 | application = UM.Application.Application.getInstance() 72 | 73 | if application.getGlobalContainerStack() is None: 74 | message = UM.Message.Message("Unable to load in SVG files before adding a printer. Please add a printer first") 75 | message.show() 76 | return 77 | self._height = application.getGlobalContainerStack().getProperty("layer_height_0", "value") # First time showing this dialogue, use one layer as height. 78 | qml_path = os.path.join(application.getPluginRegistry().getPluginPath("SVGToolpathReader"), "ConfigurationDialogue.qml") 79 | self.ui_element = application.createQmlComponent(qml_path, {"manager": self}) 80 | if qt_version >= 6: 81 | self.ui_element.setFlags(self.ui_element.flags() & Qt.WindowType.WindowCloseButtonHint & Qt.WindowType.WindowMinimizeButtonHint & Qt.WindowType.WindowMaximizeButtonHint) 82 | else: 83 | self.ui_element.setFlags(self.ui_element.flags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowMinimizeButtonHint & ~Qt.WindowMaximizeButtonHint) 84 | 85 | @pyqtSlot() 86 | def confirm(self): 87 | """ 88 | Triggered when the user clicks the OK button in the interface. 89 | 90 | This allows the SVG file to be read with the settings written in that 91 | interface. 92 | """ 93 | self._status = UM.Mesh.MeshReader.MeshReader.PreReadResult.accepted 94 | self.ui_element.close() 95 | self._ui_lock.acquire(blocking=False) 96 | self._ui_lock.release() 97 | 98 | @pyqtSlot() 99 | def cancel(self): 100 | """ 101 | Triggered when the user closes the dialogue rather than clicking OK. 102 | """ 103 | self._status = UM.Mesh.MeshReader.MeshReader.PreReadResult.cancelled 104 | self.ui_element.close() 105 | self._ui_lock.acquire(blocking=False) 106 | self._ui_lock.release() 107 | 108 | heightChanged = pyqtSignal() 109 | 110 | @pyqtSlot(int) 111 | def setHeight(self, height): 112 | if height != self._height: 113 | self._height = height 114 | self.heightChanged.emit() 115 | 116 | @pyqtProperty(float, notify=heightChanged, fset=setHeight) 117 | def height(self): 118 | return self._height 119 | 120 | def _prompt(self) -> UM.Mesh.MeshReader.MeshReader.PreReadResult: 121 | """ 122 | Actually asks the user how he'd like to read the file. 123 | 124 | This time it will be executed in the QML engine thread so that new 125 | elements can be created if necessary. 126 | :param file_name: The path to the file that is to be read. 127 | :return: The result of the dialogue, whether it is accepted, declined 128 | or there was an error. 129 | """ 130 | if self.ui_element is None: 131 | self.create_ui() 132 | self.ui_element.show() 133 | return UM.Mesh.MeshReader.MeshReader.PreReadResult.accepted 134 | 135 | def _wait_for_ui(self): 136 | self._ui_lock.acquire() 137 | self._ui_lock.release() -------------------------------------------------------------------------------- /ConfigurationDialogue.qml: -------------------------------------------------------------------------------- 1 | //Cura plug-in to read SVG files as toolpaths. 2 | //Copyright (C) 2020 Ghostkeeper 3 | //This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | //This plug-in 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 Affero General Public License for details. 5 | //You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | import QtQuick 2.1 8 | import QtQuick.Controls 2.1 9 | 10 | import UM 1.1 as UM 11 | 12 | UM.Dialog { 13 | id: svg_reader_config_dialogue 14 | minimumWidth: 350 * screenScaleFactor 15 | minimumHeight: 100 * screenScaleFactor 16 | 17 | title: "Load SVG image as toolpath" 18 | 19 | onRejected: manager.cancel() 20 | onAccepted: manager.confirm() 21 | 22 | Item { //Row for height (mm). 23 | anchors { 24 | left: parent.left 25 | right: parent.right 26 | } 27 | height: childrenRect.height 28 | 29 | Label { 30 | text: "Height (mm)" 31 | anchors.verticalCenter: heightField.verticalCenter 32 | } 33 | TextField { 34 | id: heightField 35 | selectByMouse: true 36 | anchors.right: parent.right 37 | validator: DoubleValidator { 38 | bottom: 0 39 | } 40 | text: manager.height 41 | onEditingFinished: manager.height = text 42 | } 43 | } 44 | 45 | Item { //Row for buttons. 46 | anchors { 47 | left: parent.left 48 | right: parent.right 49 | bottom: parent.bottom 50 | } 51 | height: childrenRect.height 52 | 53 | Button { 54 | anchors.left: parent.left 55 | text: "Cancel" 56 | onClicked: svg_reader_config_dialogue.rejected() 57 | } 58 | 59 | Button { 60 | anchors.right: parent.right 61 | text: "OK" 62 | onClicked: svg_reader_config_dialogue.accept() 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /ExtrudeCommand.py: -------------------------------------------------------------------------------- 1 | #Cura plug-in to read SVG files as toolpaths. 2 | #Copyright (C) 2019 Ghostkeeper 3 | #This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | #This plug-in 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 Affero General Public License for details. 5 | #You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | class ExtrudeCommand: 8 | """ 9 | Data structure that represents a command to extrude while moving to a 10 | certain spot. 11 | 12 | Such intermediary data structures are necessary in order to perform the 13 | transformations on SVG elements correctly. 14 | """ 15 | 16 | def __init__(self, x=0, y=0, line_width=0.35): 17 | """ 18 | Initialises defaults for all fields. 19 | :param x: The X position to extrude towards. 20 | :param y: The Y position to extrude towards. 21 | """ 22 | self.x = x 23 | self.y = y 24 | self.line_width = line_width -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SVG Toolpath Reader 2 | ----------------- 3 | This is a plug-in for Cura that allows you to read an SVG file directly as g-code. The outlines of the shapes in your SVG image will get printed as outer walls. 4 | 5 | Installation 6 | ------------ 7 | You can install this plug-in in one of four ways. 8 | 1. **Marketplace:** In Cura, go to the Marketplace and find SVG Toolpath Reader in the list. Click it, then click on "install" and restart Cura. 9 | 2. **From package:** Go to the [releases](https://github.com/Ghostkeeper/SVGToolpathReader/releases) page to download the latest release. Select the SDK version that fits your version of Cura: 10 | 11 | | Cura version | SDK | 12 | |--------------|-----| 13 | | 3.5 - 3.6 | 5.0 | 14 | | 4.0 - 4.3 | 6.0 | 15 | | 4.4 - 4.13 | 7.0 | 16 | | 5.0 - 5.1 | 8.0 | 17 | 18 | Drag that package file onto the Cura window, then restart Cura. 19 | 3. **Building packages:** Download the latest source code [from Github](https://github.com/Ghostkeeper/SVGToolpathReader/archive/master.zip), then in a terminal run `cmake . && make pack` to create a .curapackage file for each supported SDK version. Similar to the previous option, select the SDK version that fits your version of Cura and drag it onto the Cura window, then restart Cura. 20 | 4. **From source:** Download the latest source code [from Github](https://github.com/Ghostkeeper/SVGToolpathReader/archive/master.zip). In Cura, click on "Help", "Show configuration folder". Navigate to the "plugins" subfolder and unpack the .zip file from Github there. Rename the folder to "SVGToolpathReader" (removing any suffix that Github added such as "-master"). Rename the `plugin.json.in` file to simply `plugin.json` and fill in the CMake variables inside. Restart Cura. 21 | 22 | Usage 23 | ----- 24 | To use this plug-in, simply load an SVG file. There are a couple of things you might want to watch out for though. 25 | * This plug-in reads your file in as if it's a g-code file. It doesn't load a model and lets Cura slice that model, but produces g-code directly. This means that it doesn't suffer from the same issues as Cura's slicing does. This was originally why this plug-in was developed, as a way to find out whether a print problem was caused by CuraEngine or by the printer hardware. 26 | * Not all elements are supported. See the SVG Support header below for a list of what is supported. 27 | * Curves will get sampled in segments of the Maximum Resolution. That may be too high of a sample rate for your printer to cope with. 28 | * Unless your printer has the origin in the centre, the coordinate origin is in the back left corner of the printer. It is not the front left corner, like with g-code. This makes the image render in proper orientation. Coordinates are in millimetres. 29 | * If you see nothing in the layer view, your image coordinates may be out of whack, causing the lines to be positioned out of view. 30 | * There is no check for whether your print stays within the build volume. This might generate g-code that instructs the printer to go out of its build volume. 31 | * The actual stroke width of the shape is used as the line width to print with. Common stroke widths in SVG are often too wide to print. 32 | 33 | Settings 34 | -------- 35 | This plug-in will use the current settings in your currently activated extruder as the settings to print with. The following settings will influence your print: 36 | 37 | | Setting | Effect | 38 | |---------------------------------------|----------------------------------------------------------------------------| 39 | | Initial Layer Height | This will be used as the height of your first layer. | 40 | | Layer Height | This will be used as the height of the rest of the layers. | 41 | | Initial Layer Flow | Adjusts the amount of material extruded linearly during the first layer. | 42 | | Flow | Adjusts the amount of material extruded linearly. | 43 | | Diameter | Compute the correct length of filament to extrude. | 44 | | Initial Layer Travel Speed | The speed at which travel moves are made during the first layer. | 45 | | Travel Speed | The speed at which travel moves are made. | 46 | | Initial Layer Print Speed | The speed at which lines are printed during the first layer. | 47 | | Print Speed | The speed at which lines are printed. | 48 | | Enable Retraction | Whether all travel moves should be made with filament retracted. | 49 | | Retraction Distance | How far to retract. | 50 | | Retraction Retract Speed | The speed at which to retract the filament. | 51 | | Retraction Prime Speed | The speed at which to unretract the filament. | 52 | | Outer Wall Line Width | The line width used for shapes that don't specify a line width themselves. | 53 | | Outer Wall Acceleration | The acceleration to use throughout the print (also for travel moves). | 54 | | Outer Wall Jerk | The jerk to use throughout the print (also for travel moves). | 55 | | Maximum Resolution | Length of segments in all curves. | 56 | | Printing Temperature Initial Layer | The temperature at which to print during the first layer. | 57 | | Printing Temperature | The temperature at which to print. | 58 | | Build Plate Temperature Initial Layer | The build plate temperature during the first layer of the print. | 59 | | Build Plate Temperature | The build plate temperature during the rest of the print. | 60 | | Enable Prime Blob | Whether or not to prime before the print. | 61 | | Extruder Prime X Position | The X coordinate of where to prime. | 62 | | Extruder Prime Y Position | The Y coordinate of where to prime. | 63 | 64 | SVG Support 65 | ----------- 66 | Not all elements of the SVG specification will be printed. For some things, this is intended. For instance, all fills, gradients, glow effects, etc. should not be printed. For other things they may just not be supported yet. The following elements are currently supported: 67 | * SVG (viewBox, width, height) 68 | * rect (x, y, width, height, rx, ry) 69 | * circle (cx, cy, r) 70 | * g 71 | * ellipse (cx, cy, rx, ry) 72 | * polygon (points) 73 | * polyline (points) 74 | * line (x1, y1, x2, y2) 75 | * path (d) 76 | * style 77 | * switch (requiredFeatures) 78 | * defs 79 | * use (x, y) 80 | * text (x, y, dx, dy, rotate) 81 | 82 | The following attributes are supported for each of these: 83 | * stroke-width 84 | * transform 85 | * style 86 | 87 | The following CSS properties are supported: 88 | * font-family 89 | * font-size 90 | * font-weight 91 | * font-style 92 | * stroke-dasharray 93 | * stroke-dashoffset 94 | * text-decoration 95 | * text-decoration-line 96 | * text-decoration-style 97 | * text-transform 98 | 99 | Line Widths 100 | ----------- 101 | To draw the lines, the stroke width of the actual element in SVG is used. If this line width is 0, the outer wall line width will be used. The stroke of a line width can be specified using the `stroke-width` attribute in most elements, or using the `style` attribute or `style` element. However support for CSS is very limited. Classes are not supported and may even get interpreted wrongly. -------------------------------------------------------------------------------- /SVGToolpathReader.py: -------------------------------------------------------------------------------- 1 | # Cura plug-in to read SVG files as toolpaths. 2 | # Copyright (C) 2020 Ghostkeeper 3 | # This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | # This plug-in 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 Affero General Public License for details. 5 | # You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | import cura.Scene.CuraSceneNode #To create a mesh node in the scene as result of our read. 8 | import cura.Scene.GCodeListDecorator #To store g-code in the mesh so that you could print it. 9 | import cura.CuraApplication #To get the active build plate. 10 | import cura.LayerDataDecorator #To store layer data in the mesh so that you can visualise it in layer view. 11 | import numpy #For the material colour mapping. 12 | import UM.Mesh.MeshReader #The class we're extending. 13 | import UM.MimeTypeDatabase #Register the SVG MIME type. 14 | import xml.etree.ElementTree #To read SVG files. 15 | 16 | from . import Configuration 17 | from . import Parser #To parse the SVG. 18 | from . import WriteGCode #To serialise the commands as g-code. 19 | 20 | class SVGToolpathReader(UM.Mesh.MeshReader.MeshReader): 21 | """ 22 | Interface class between Cura and the logic to read SVG files as toolpath. 23 | """ 24 | 25 | def __init__(self): 26 | """ 27 | Register the SVG extension upon start-up. 28 | """ 29 | super().__init__() 30 | self._supported_extensions = ["svg"] 31 | UM.MimeTypeDatabase.MimeTypeDatabase.addMimeType(UM.MimeTypeDatabase.MimeType(name="image/svg+xml", comment="Scalable Vector Graphics", suffixes=self._supported_extensions)) 32 | self.config_dialogue = Configuration.Configuration() 33 | 34 | def preRead(self, file_name, *args, **kwargs) -> UM.Mesh.MeshReader.MeshReader.PreReadResult: 35 | """ 36 | Handles the configuration before we start reading the SVG file. 37 | 38 | This will display a dialogue to a user and wait for the user to 39 | respond. 40 | :param file_name: The path to the file to read. 41 | """ 42 | return self.config_dialogue.prompt(file_name) 43 | 44 | def _read(self, file_name) -> cura.Scene.CuraSceneNode.CuraSceneNode: 45 | """ 46 | Read the specified SVG file. 47 | 48 | The toolpath represented by the file gets put in the current scene as 49 | g-code. 50 | :param file_name: The name of the file to read. 51 | :return: A scene node that contains the print to execute. 52 | """ 53 | #Parse the document and generate its g-code. 54 | document = xml.etree.ElementTree.parse(file_name) 55 | parser = Parser.Parser() 56 | definitions = parser.find_definitions(document.getroot()) 57 | parser.dereference_uses(document.getroot(), definitions) 58 | parser.defaults(document.getroot()) 59 | parser.inheritance(document.getroot()) 60 | commands = parser.parse(document.getroot()) 61 | gcode, layer_data_builder = WriteGCode.write_gcode(self.config_dialogue, commands) 62 | 63 | scene_node = cura.Scene.CuraSceneNode.CuraSceneNode() 64 | 65 | #Build the layer data decorator. 66 | material_colour_map = numpy.zeros((8, 4), dtype=numpy.float32) 67 | material_colour_map[0, :] = [0.0, 0.7, 0.9, 1.0] 68 | material_colour_map[1, :] = [0.7, 0.9, 0.0, 1.0] 69 | material_colour_map[2, :] = [0.9, 0.0, 0.7, 1.0] 70 | material_colour_map[3, :] = [0.7, 0.0, 0.0, 1.0] 71 | material_colour_map[4, :] = [0.0, 0.7, 0.0, 1.0] 72 | material_colour_map[5, :] = [0.0, 0.0, 0.7, 1.0] 73 | material_colour_map[6, :] = [0.3, 0.3, 0.3, 1.0] 74 | material_colour_map[7, :] = [0.7, 0.7, 0.7, 1.0] 75 | layer_data = layer_data_builder.build(material_colour_map) 76 | layer_data_decorator = cura.LayerDataDecorator.LayerDataDecorator() 77 | layer_data_decorator.setLayerData(layer_data) 78 | scene_node.addDecorator(layer_data_decorator) 79 | 80 | #Store the g-code. 81 | gcode_list_decorator = cura.Scene.GCodeListDecorator.GCodeListDecorator() 82 | gcode_list = [gcode] 83 | gcode_list_decorator.setGCodeList(gcode_list) 84 | scene_node.addDecorator(gcode_list_decorator) 85 | active_build_plate_id = cura.CuraApplication.CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate 86 | gcode_dict = {active_build_plate_id: gcode_list} 87 | cura.CuraApplication.CuraApplication.getInstance().getController().getScene().gcode_dict = gcode_dict 88 | 89 | cura.CuraApplication.CuraApplication.getInstance().getBackend().backendStateChange.emit(UM.Backend.Backend.BackendState.Disabled) #Don't try slicing this node. 90 | 91 | return scene_node -------------------------------------------------------------------------------- /TravelCommand.py: -------------------------------------------------------------------------------- 1 | #Cura plug-in to read SVG files as toolpaths. 2 | #Copyright (C) 2019 Ghostkeeper 3 | #This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | #This plug-in 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 Affero General Public License for details. 5 | #You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | class TravelCommand: 8 | """ 9 | Data structure that represents a movement to a certain spot without 10 | extruding. 11 | 12 | Such intermediary data structures are necessary in order to perform the 13 | transformations on SVG elements correctly. 14 | """ 15 | 16 | def __init__(self, x=0, y=0): 17 | """ 18 | Initialises defaults for all fields. 19 | :param x: The X position to travel to. 20 | :param y: The Y position to travel to. 21 | """ 22 | self.x = x 23 | self.y = y -------------------------------------------------------------------------------- /WriteGCode.py: -------------------------------------------------------------------------------- 1 | # Cura plug-in to read SVG files as toolpaths. 2 | # Copyright (C) 2019 Ghostkeeper 3 | # This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | # This plug-in 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 Affero General Public License for details. 5 | # You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | import cura.Settings.ExtruderManager # To get settings from the active extruder. 8 | import cura.LayerDataBuilder # One of the results of the function. 9 | import cura.LayerPolygon # Filling layer data. 10 | import itertools # To use the same commands for every layer. 11 | import json # To read this plugin's version for the g-code headers. 12 | import math 13 | import numpy # To create the Polygon data. 14 | import os.path # To read this plugin's version for the g-code headers. 15 | import UM.PluginRegistry # To read this plugin's version for the g-code headers. 16 | import time # To get today's date for the g-code headers. 17 | import typing 18 | 19 | from . import ExtrudeCommand # To differentiate between the command types. 20 | from . import TravelCommand # To differentiate between the command types. 21 | 22 | def get_distance(point1, point2): 23 | return math.sqrt((point2.x - point1.x)**2 + (point2.y - point1.y)**2) 24 | 25 | def sort_commands(commands): 26 | # Split commands into extrude segments (split by TravelCommand) 27 | segments = [] 28 | for command in commands: 29 | if isinstance(command, TravelCommand.TravelCommand): 30 | segments.append([]) 31 | segments[-1].append(command) 32 | 33 | # Sort segments by minimum travel distance (to both start + end of next segment) 34 | segments_sorted = [segments.pop(0)] 35 | while(segments): 36 | last_command = segments_sorted[-1][-1] 37 | distances = [min(get_distance(last_command, segment[0]), get_distance(last_command, segment[-1])) for segment in segments] 38 | index = distances.index(min(distances)) 39 | segment = segments.pop(index) 40 | if(get_distance(last_command, segment[0]) > get_distance(last_command, segment[-1])): 41 | # Dirty way to reverse the segment 42 | segment = list(reversed(segment)) 43 | segment[-1] = ExtrudeCommand.ExtrudeCommand(segment[-1].x, segment[-1].y, segment[0].line_width) 44 | segment[0] = TravelCommand.TravelCommand(segment[0].x, segment[0].y) 45 | segments_sorted.append(segment) 46 | 47 | return sum(segments_sorted, []) 48 | 49 | def write_gcode(config, commands) -> typing.Tuple[str, cura.LayerDataBuilder.LayerDataBuilder]: 50 | """ 51 | Converts a list of commands into g-code. 52 | :param config: The SVG configuration to print for. 53 | :param commands: The list of extrude and travel commands to write. 54 | :return: A g-code string that would print the commands, as well as a layer 55 | data builder that represents the same file for layer view. 56 | """ 57 | # Cache some settings we'll use often. 58 | extruder_number = cura.Settings.ExtruderManager.ExtruderManager.getInstance().activeExtruderIndex 59 | extruder_stack = cura.Settings.ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack() 60 | layer_height = extruder_stack.getProperty("layer_height", "value") 61 | layer_height_0 = extruder_stack.getProperty("layer_height_0", "value") 62 | material_flow = extruder_stack.getProperty("material_flow", "value") / 100 63 | material_flow_layer_0 = extruder_stack.getProperty("material_flow_layer_0", "value") / 100 64 | material_diameter = extruder_stack.getProperty("material_diameter", "value") 65 | machine_center_is_zero = extruder_stack.getProperty("machine_center_is_zero", "value") # Necessary to know if we need to offset the coordinates for layer view. 66 | machine_gcode_flavor = extruder_stack.getProperty("machine_gcode_flavor", "value") # Necessary to track if we need to extrude volumetric or lengthwise. 67 | machine_end_gcode = extruder_stack.getProperty("machine_end_gcode", "value") 68 | machine_width = extruder_stack.getProperty("machine_width", "value") 69 | machine_depth = extruder_stack.getProperty("machine_depth", "value") 70 | is_volumetric = machine_gcode_flavor in {"UltiGCode", "RepRap (Volumetric)"} 71 | speed_travel = extruder_stack.getProperty("speed_travel", "value") 72 | speed_travel_layer_0 = extruder_stack.getProperty("speed_travel_layer_0", "value") 73 | speed_wall_0 = extruder_stack.getProperty("speed_wall_0", "value") 74 | speed_print_layer_0 = extruder_stack.getProperty("speed_print_layer_0", "value") 75 | retraction_enable = extruder_stack.getProperty("retraction_enable", "value") 76 | retraction_speed = extruder_stack.getProperty("retraction_retract_speed", "value") 77 | unretraction_speed = extruder_stack.getProperty("retraction_prime_speed", "value") 78 | retraction_distance = extruder_stack.getProperty("retraction_amount", "value") 79 | material_bed_temperature = extruder_stack.getProperty("material_bed_temperature", "value") 80 | material_print_temperature = extruder_stack.getProperty("material_print_temperature", "value") 81 | magic_spiralize = extruder_stack.getProperty("magic_spiralize", "value") and extruder_stack.getProperty("smooth_spiralized_contours", "value") 82 | 83 | gcodes = [] 84 | commands = sort_commands(commands) 85 | 86 | x = 0 87 | y = 0 88 | e = 0 89 | f = 0 90 | min_x = machine_width 91 | min_y = machine_depth 92 | max_x = -machine_width 93 | max_y = -machine_depth 94 | is_retracted = retraction_enable # If retracting, we start off retracted as per the start g-code. 95 | 96 | # Get all of the layer heights. 97 | total_height = config.height 98 | total_height -= layer_height_0 # Always use at least 1 layer, even if the user entered 0mm. Assume that this was a user error. 99 | layer_heights = [layer_height_0] 100 | layer_thicknesses = [layer_height_0] 101 | num_layers = int(total_height / layer_height) 102 | for i in range(num_layers): 103 | layer_heights.append(layer_height_0 + (i + 1) * layer_height) 104 | layer_thicknesses.append(layer_height) 105 | num_layers += 1 106 | 107 | total_layer_length = 0 108 | if magic_spiralize: # Only calculate the total length if we need to use it for spiralise. 109 | spiralize_x = 0 # Track our position. 110 | spiralize_y = 0 111 | for command in commands: 112 | if isinstance(command, TravelCommand.TravelCommand): 113 | spiralize_x = command.x 114 | spiralize_y = command.y 115 | if isinstance(command, ExtrudeCommand.ExtrudeCommand): 116 | total_layer_length += math.sqrt((spiralize_x - command.x) * (spiralize_x - command.x) + (spiralize_y - command.y) * (spiralize_y - command.y)) # Pythagoras. 117 | spiralize_x = command.x 118 | spiralize_y = command.y 119 | 120 | builder = cura.LayerDataBuilder.LayerDataBuilder() 121 | 122 | for layer_nr in range(num_layers): 123 | if not magic_spiralize: 124 | gcodes.append("G0 Z{z:.6f}".format(z=layer_heights[layer_nr])) 125 | if layer_nr == 1: 126 | gcodes.append("M104 S{temperature}".format(temperature=material_print_temperature)) 127 | gcodes.append("M140 S{temperature}".format(temperature=material_bed_temperature)) 128 | builder.addLayer(layer_nr) 129 | layer = builder.getLayer(layer_nr) 130 | builder.setLayerHeight(layer_nr, layer_heights[layer_nr]) 131 | builder.setLayerThickness(layer_nr, layer_thicknesses[layer_nr]) 132 | path = [] 133 | if not machine_center_is_zero: 134 | path.append([x - machine_width / 2, -y + machine_depth / 2, 0]) 135 | else: 136 | path.append([x, -y, 0]) 137 | 138 | current_layer_length = 0 # How much we've extruded this layer (tracked for spiralise). 139 | for command in commands: 140 | gcode = ";Unknown command of type {typename}!".format(typename=command.__class__.__name__) 141 | if isinstance(command, TravelCommand.TravelCommand): 142 | # Since SVG has positive Y going down but g-code has positive Y going up, we need to invert the Y axis. 143 | if not machine_center_is_zero: 144 | command_y = machine_depth - command.y 145 | else: 146 | command_y = -command.y 147 | if abs(command.x - x) < 0.001 and abs(command_y - y) < 0.001: 148 | continue # Travel move wouldn't have any effect. 149 | 150 | gcode = "" 151 | if not is_retracted and retraction_enable: 152 | gcode += "G0 F{speed} E{e:.6f}\n".format(speed=retraction_speed * 60, e=e - retraction_distance) 153 | is_retracted = True 154 | gcode += "G0" 155 | if command.x != x: 156 | x = command.x 157 | min_x = min(min_x, x) 158 | max_x = max(max_x, x) 159 | gcode += " X{x:.6f}".format(x=x) 160 | if command_y != y: 161 | y = command_y 162 | min_y = min(min_y, y) 163 | max_y = max(max_y, y) 164 | gcode += " Y{y:.6f}".format(y=y) 165 | if layer_nr == 0: 166 | if speed_travel_layer_0 * 60 != f: 167 | f = speed_travel_layer_0 * 60 168 | gcode += " F{f:.6f}".format(f=f) 169 | else: 170 | if speed_travel * 60 != f: 171 | f = speed_travel * 60 172 | gcode += " F{f:.6f}".format(f=f) 173 | if not machine_center_is_zero: 174 | path.append([x - machine_width / 2, -y + machine_depth / 2, 0]) 175 | else: 176 | path.append([x, -y, 0]) 177 | elif isinstance(command, ExtrudeCommand.ExtrudeCommand): 178 | # Since SVG has positive Y going down but g-code has positive Y going up, we need to invert the Y axis. 179 | if not machine_center_is_zero: 180 | command_y = machine_depth - command.y 181 | else: 182 | command_y = -command.y 183 | 184 | distance = math.sqrt((command.x - x) * (command.x - x) + (command_y - y) * (command_y - y)) 185 | if magic_spiralize: 186 | current_layer_length += distance 187 | if layer_nr == 0: 188 | mm3 = distance * layer_thicknesses[layer_nr] * command.line_width * material_flow_layer_0 189 | else: 190 | mm3 = distance * layer_thicknesses[layer_nr] * command.line_width * material_flow 191 | delta_e = mm3 if is_volumetric else (mm3 / (math.pi * material_diameter * material_diameter / 4)) 192 | 193 | gcode = "" 194 | if is_retracted: 195 | gcode += "G0 F{speed} E{e:.6f}\n".format(speed=unretraction_speed * 60, e=e) 196 | is_retracted = False 197 | gcode += "G1" 198 | if command.x != x: 199 | x = command.x 200 | min_x = min(min_x, x) 201 | max_x = max(max_x, x) 202 | gcode += " X{x:.6f}".format(x=x) 203 | if command_y != y: 204 | y = command_y 205 | min_y = min(min_y, y) 206 | max_y = max(max_y, y) 207 | gcode += " Y{y:.6f}".format(y=y) 208 | if magic_spiralize: 209 | gcode += " Z{z:.6f}".format(z=current_layer_length / total_layer_length * layer_height - layer_height + layer_heights[layer_nr]) 210 | if layer_nr == 0: 211 | if speed_print_layer_0 * 60 != f: 212 | f = speed_print_layer_0 * 60 213 | gcode += " F{f:.6f}".format(f=f) 214 | else: 215 | if speed_wall_0 * 60 != f: 216 | f = speed_wall_0 * 60 217 | gcode += " F{f:.6f}".format(f=f) 218 | if delta_e != 0: 219 | if magic_spiralize and layer_nr == 0: 220 | e += delta_e * current_layer_length / total_layer_length 221 | else: 222 | e += delta_e 223 | gcode += " E{e:.6f}".format(e=e) 224 | if not machine_center_is_zero: 225 | path.append([x - machine_width / 2, -y + machine_depth / 2, command.line_width]) 226 | else: 227 | path.append([x, -y, command.line_width]) 228 | gcodes.append(gcode) 229 | 230 | if path: 231 | coordinates = numpy.empty((len(path), 3), numpy.float32) 232 | types = numpy.empty((len(path) - 1, 1), numpy.int32) 233 | widths = numpy.empty((len(path) - 1, 1), numpy.float32) 234 | thicknesses = numpy.empty((len(path) - 1, 1), numpy.float32) 235 | feedrates = numpy.empty((len(path) - 1, 1), numpy.float32) 236 | for i, point in enumerate(path): 237 | coordinates[i, :] = [point[0], layer_heights[layer_nr], point[1]] 238 | if i > 0: 239 | if point[2] == 0: 240 | if layer_nr == 0: 241 | feedrates[i - 1] = speed_travel_layer_0 242 | else: 243 | feedrates[i - 1] = speed_travel 244 | if retraction_enable: 245 | types[i - 1] = cura.LayerPolygon.LayerPolygon.MoveRetractionType 246 | else: 247 | types[i - 1] = cura.LayerPolygon.LayerPolygon.MoveCombingType 248 | widths[i - 1] = 0.1 249 | thicknesses[i - 1] = 0.0 250 | else: 251 | if layer_nr == 0: 252 | feedrates[i - 1] = speed_print_layer_0 253 | else: 254 | feedrates[i - 1] = speed_wall_0 255 | types[i - 1] = cura.LayerPolygon.LayerPolygon.Inset0Type 256 | widths[i - 1] = point[2] 257 | thicknesses[i - 1] = layer_height_0 258 | 259 | polygon = cura.LayerPolygon.LayerPolygon(extruder_number, types, coordinates, widths, thicknesses, feedrates) 260 | polygon.buildCache() 261 | layer.polygons.append(polygon) 262 | 263 | layer_nr += 1 264 | 265 | machine_start_gcode = get_start_gcode(min_x, min_y, max_x, max_y) 266 | gcodes = [machine_start_gcode] + gcodes 267 | 268 | gcodes.append("M140 S0") #Cool everything down. 269 | gcodes.append("M104 S0") 270 | gcodes.append("M107") #Fans off. 271 | gcodes.append(machine_end_gcode) 272 | 273 | return "\n".join(gcodes), builder 274 | 275 | def get_start_gcode(min_x, min_y, max_x, max_y) -> str: 276 | """ 277 | Returns the proper starting g-code for the current printer. 278 | 279 | This doesn't just include the ordinary start g-code setting, but also any 280 | headers specified by the g-code flavour, heating commands, priming maybe, 281 | just anything that is required to get the printer going. 282 | :param min_x: The minimum X coordinate that we're moving to. 283 | :param min_y: The minimum Y coordinate that we're moving to. 284 | :param max_x: The maximum X coordinate that we're moving to. 285 | :param max_y: The maximum Y coordinate that we're moving to. 286 | :return: The proper starting g-code for the current printer. 287 | """ 288 | extruder_number = cura.Settings.ExtruderManager.ExtruderManager.getInstance().activeExtruderIndex 289 | extruder_stack = cura.Settings.ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack() 290 | machine_gcode_flavor = extruder_stack.getProperty("machine_gcode_flavor", "value") 291 | machine_name = extruder_stack.getProperty("machine_name", "value") 292 | material_print_temperature_layer_0 = extruder_stack.getProperty("material_print_temperature_layer_0", "value") 293 | material_guid = extruder_stack.getProperty("material_guid", "value") 294 | machine_nozzle_size = extruder_stack.getProperty("machine_nozzle_size", "value") 295 | machine_nozzle_id = extruder_stack.getProperty("machine_nozzle_id", "value") 296 | machine_buildplate_type = extruder_stack.getProperty("machine_buildplate_type", "value") 297 | material_bed_temperature_layer_0 = extruder_stack.getProperty("material_bed_temperature_layer_0", "value") 298 | machine_width = extruder_stack.getProperty("machine_width", "value") 299 | machine_depth = extruder_stack.getProperty("machine_depth", "value") 300 | machine_height = extruder_stack.getProperty("machine_height", "value") 301 | prime_blob_enable = extruder_stack.getProperty("prime_blob_enable", "value") 302 | extruder_prime_pos_x = extruder_stack.getProperty("extruder_prime_pos_x", "value") 303 | extruder_prime_pos_y = extruder_stack.getProperty("extruder_prime_pos_y", "value") 304 | acceleration_wall_0 = extruder_stack.getProperty("acceleration_wall_0", "value") 305 | jerk_wall_0 = extruder_stack.getProperty("jerk_wall_0", "value") 306 | layer_height_0 = extruder_stack.getProperty("layer_height_0", "value") 307 | retraction_enable = extruder_stack.getProperty("retraction_enable", "value") 308 | retraction_speed = extruder_stack.getProperty("retraction_speed", "value") 309 | retraction_distance = extruder_stack.getProperty("retraction_amount", "value") 310 | 311 | result = "" 312 | 313 | if machine_gcode_flavor == "Griffin": 314 | plugin_path = UM.PluginRegistry.PluginRegistry.getInstance().getPluginPath("SVGToolpathReader") 315 | with open(os.path.join(plugin_path, "plugin.json")) as f: 316 | plugin_json = json.load(f) 317 | svgtoolpathreader_version = plugin_json["version"] 318 | result += """;START_OF_HEADER 319 | ;HEADER_VERSION:0.1 320 | ;FLAVOR:Griffin 321 | ;GENERATOR.NAME:SVGToolpathReader 322 | ;GENERATOR.VERSION:{svgtoolpathreader_version} 323 | ;GENERATOR.BUILD_DATE:{today} 324 | ;TARGET_MACHINE.NAME:{printer_name} 325 | ;EXTRUDER_TRAIN.{extruder_number}.INITIAL_TEMPERATURE:{print_temperature} 326 | ;EXTRUDER_TRAIN.{extruder_number}.MATERIAL.VOLUME_USED:6666 327 | ;EXTRUDER_TRAIN.{extruder_number}.MATERIAL.GUID:{guid} 328 | ;EXTRUDER_TRAIN.{extruder_number}.NOZZLE.DIAMETER:{nozzle_diameter} 329 | ;EXTRUDER_TRAIN.{extruder_number}.NOZZLE.NAME:{nozzle_name} 330 | ;BUILD_PLATE.TYPE:{buildplate_type} 331 | ;BUILD_PLATE.INITIAL_TEMPERATURE:{buildplate_temperature} 332 | ;PRINT.TIME:666 333 | ;PRINT.SIZE.MIN.X:{min_x} 334 | ;PRINT.SIZE.MIN.Y:{min_y} 335 | ;PRINT.SIZE.MIN.Z:{layer_height} 336 | ;PRINT.SIZE.MAX.X:{max_x} 337 | ;PRINT.SIZE.MAX.Y:{max_y} 338 | ;PRINT.SIZE.MAX.Z:{layer_height} 339 | ;END_OF_HEADER 340 | """.format(svgtoolpathreader_version=svgtoolpathreader_version, 341 | today=time.strftime("%Y-%m-%d"), 342 | printer_name=machine_name, 343 | extruder_number=extruder_number, 344 | print_temperature=material_print_temperature_layer_0, 345 | guid=material_guid, 346 | nozzle_diameter=machine_nozzle_size, 347 | nozzle_name=machine_nozzle_id, 348 | buildplate_type=machine_buildplate_type, 349 | buildplate_temperature=material_bed_temperature_layer_0, 350 | printer_width=machine_width, 351 | printer_depth=machine_depth, 352 | printer_height=machine_height, 353 | min_x=min_x, 354 | min_y=min_y, 355 | max_x=max_x, 356 | max_y=max_y, 357 | layer_height=layer_height_0) 358 | 359 | result += "T" + str(extruder_number) + "\n" #Correct extruder. 360 | result += "M82\n" #Absolute extrusion mode only. 361 | result += "G92 E0\n" #Reset E, wherever it ended up in the previous print is now 0. 362 | result += "M109 S{print_temperature}\n".format(print_temperature=material_print_temperature_layer_0) #Heat extruder. 363 | result += "M190 S{bed_temperature}\n".format(bed_temperature=material_bed_temperature_layer_0) #Heat build plate. 364 | if prime_blob_enable: #Prime, if necessary. 365 | result += "G0 F15000 X{prime_x} Y{prime_y} Z2\n".format(prime_x=extruder_prime_pos_x, prime_y=extruder_prime_pos_y) 366 | result += "G280\n" 367 | if retraction_enable: 368 | result += "G0 F{speed} E-{distance}\n".format(speed=retraction_speed * 60, distance=retraction_distance) 369 | result += "M107\n" #Fans on. 370 | result += "M204 S{acceleration}\n".format(acceleration=acceleration_wall_0) 371 | result += "M205 X{jerk} Y{jerk}\n".format(jerk=jerk_wall_0) 372 | result += ";LAYER:0\n" 373 | result += "G0 F15000 Z{layer_height}".format(layer_height=layer_height_0) 374 | 375 | return result -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | #Cura plug-in to read SVG files as toolpaths. 2 | #Copyright (C) 2019 Ghostkeeper 3 | #This plug-in is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 4 | #This plug-in 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 Affero General Public License for details. 5 | #You should have received a copy of the GNU Affero General Public License along with this plug-in. If not, see . 6 | 7 | from . import SVGToolpathReader 8 | 9 | def getMetaData(): 10 | return { 11 | "mesh_reader": [ 12 | { 13 | "extension": "svg", 14 | "description": "SVG file as toolpath" 15 | } 16 | ] 17 | } 18 | 19 | def register(application): 20 | application.addNonSliceableExtension(".svg") 21 | return {"mesh_reader": SVGToolpathReader.SVGToolpathReader()} -------------------------------------------------------------------------------- /cmake/[Content_Types].xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /cmake/_rels/.rels: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /cmake/_rels/package.json.rels: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /cmake/package.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "author_id": "Ghostkeeper", 4 | "display_name": "Ghostkeeper", 5 | "email": "rubend@tutanota.com", 6 | "website": "https://github.com/Ghostkeeper" 7 | }, 8 | "description": "Allows reading SVG image files and lets the printer draw the outlines directly.", 9 | "display_name": "SVG Toolpath Reader", 10 | "package_id": "SVGToolpathReader", 11 | "package_type": "plugin", 12 | "package_version": "${SVGTOOLPATHREADER_VERSION_MAJOR}.${SVGTOOLPATHREADER_VERSION_MINOR}.${SVGTOOLPATHREADER_VERSION_PATCH}", 13 | "sdk_version": 5, 14 | "sdk_version_semver": "${sdk_version}", 15 | "website": "https://github.com/Ghostkeeper/SVGToolpathReader" 16 | } -------------------------------------------------------------------------------- /freetype/ft_enums/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | ''' 9 | Freetype enum types 10 | ------------------- 11 | 12 | FT_CURVE_TAGS: An enumeration type for each point on an outline to indicate 13 | whether it describes a point used to control a line segment 14 | or an arc. 15 | 16 | FT_PIXEL_MODES: An enumeration type used to describe the format of pixels in a 17 | given bitmap. Note that additional formats may be added in the 18 | future. 19 | 20 | FT_GLYPH_BBOX_MODES: The mode how the values of FT_Glyph_Get_CBox are returned. 21 | 22 | FT_GLYPH_FORMATS: An enumeration type used to describe the format of a given 23 | glyph image. Note that this version of FreeType only supports 24 | two image formats, even though future font drivers will be 25 | able to register their own format. 26 | 27 | FT_ENCODINGS: An enumeration used to specify character sets supported by 28 | charmaps. Used in the FT_Select_Charmap API function. 29 | 30 | FT_RENDER_MODES: An enumeration type that lists the render modes supported by 31 | FreeType 2. Each mode corresponds to a specific type of 32 | scanline conversion performed on the outline. 33 | 34 | FT_LOAD_TARGETS: A list of values that are used to select a specific hinting 35 | algorithm to use by the hinter. You should OR one of these 36 | values to your 'load_flags' when calling FT_Load_Glyph. 37 | 38 | FT_LOAD_FLAGS: A list of bit-field constants used with FT_Load_Glyph to 39 | indicate what kind of operations to perform during glyph 40 | loading. 41 | 42 | FT_STYLE_FLAGS: A list of bit-flags used to indicate the style of a given 43 | face. These are used in the 'style_flags' field of FT_FaceRec. 44 | 45 | FT_FSTYPES: A list of bit flags that inform client applications of embedding 46 | and subsetting restrictions associated with a font. 47 | 48 | FT_FACE_FLAGS: A list of bit flags used in the 'face_flags' field of the 49 | FT_FaceRec structure. They inform client applications of 50 | properties of the corresponding face. 51 | 52 | FT_OUTLINE_FLAGS: A list of bit-field constants use for the flags in an 53 | outline's 'flags' field. 54 | 55 | FT_OPEN_MODES: A list of bit-field constants used within the 'flags' field of 56 | the FT_Open_Args structure. 57 | 58 | FT_KERNING_MODES: An enumeration used to specify which kerning values to return 59 | in FT_Get_Kerning. 60 | 61 | FT_STROKER_LINEJOINS: These values determine how two joining lines are rendered 62 | in a stroker. 63 | 64 | FT_STROKER_LINECAPS: These values determine how the end of opened sub-paths are 65 | rendered in a stroke. 66 | 67 | FT_STROKER_BORDERS: These values are used to select a given stroke border in 68 | FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder. 69 | 70 | FT_LCD_FILTERS: A list of values to identify various types of LCD filters. 71 | 72 | TT_PLATFORMS: A list of valid values for the 'platform_id' identifier code in 73 | FT_CharMapRec and FT_SfntName structures. 74 | 75 | TT_APPLE_IDS: A list of valid values for the 'encoding_id' for 76 | TT_PLATFORM_APPLE_UNICODE charmaps and name entries. 77 | 78 | TT_MAC_IDS: A list of valid values for the 'encoding_id' for 79 | TT_PLATFORM_MACINTOSH charmaps and name entries. 80 | 81 | TT_MS_IDS: A list of valid values for the 'encoding_id' for 82 | TT_PLATFORM_MICROSOFT charmaps and name entries. 83 | 84 | TT_ADOBE_IDS: A list of valid values for the 'encoding_id' for 85 | TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific 86 | extension! 87 | 88 | TT_MAC_LANGIDS: Possible values of the language identifier field in the name 89 | records of the TTF `name' table if the `platform' identifier 90 | code is TT_PLATFORM_MACINTOSH. 91 | 92 | TT_MS_LANGIDS: Possible values of the language identifier field in the name 93 | records of the TTF `name' table if the `platform' identifier 94 | code is TT_PLATFORM_MICROSOFT. 95 | 96 | TT_NAME_IDS: Possible values of the `name' identifier field in the name 97 | records of the TTF `name' table. These values are platform 98 | independent. 99 | ''' 100 | from freetype.ft_enums.ft_curve_tags import * 101 | from freetype.ft_enums.ft_fstypes import * 102 | from freetype.ft_enums.ft_face_flags import * 103 | from freetype.ft_enums.ft_encodings import * 104 | from freetype.ft_enums.ft_glyph_bbox_modes import * 105 | from freetype.ft_enums.ft_glyph_formats import * 106 | from freetype.ft_enums.ft_kerning_modes import * 107 | from freetype.ft_enums.ft_lcd_filters import * 108 | from freetype.ft_enums.ft_load_flags import * 109 | from freetype.ft_enums.ft_load_targets import * 110 | from freetype.ft_enums.ft_open_modes import * 111 | from freetype.ft_enums.ft_outline_flags import * 112 | from freetype.ft_enums.ft_pixel_modes import * 113 | from freetype.ft_enums.ft_render_modes import * 114 | from freetype.ft_enums.ft_stroker_borders import * 115 | from freetype.ft_enums.ft_stroker_linecaps import * 116 | from freetype.ft_enums.ft_stroker_linejoins import * 117 | from freetype.ft_enums.ft_style_flags import * 118 | from freetype.ft_enums.tt_adobe_ids import * 119 | from freetype.ft_enums.tt_apple_ids import * 120 | from freetype.ft_enums.tt_mac_ids import * 121 | from freetype.ft_enums.tt_ms_ids import * 122 | from freetype.ft_enums.tt_ms_langids import * 123 | from freetype.ft_enums.tt_mac_langids import * 124 | from freetype.ft_enums.tt_name_ids import * 125 | from freetype.ft_enums.tt_platforms import * 126 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_curve_tags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2017 Hin-Tak Leung 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration type that lists the curve tags supported by FreeType 2. 10 | 11 | Each point of an outline has a specific tag which indicates whether it 12 | describes a point used to control a line segment or an arc. The tags can take 13 | the following values: 14 | 15 | FT_CURVE_TAG_ON 16 | 17 | Used when the point is ‘on’ the curve. This corresponds to start and end 18 | points of segments and arcs. The other tags specify what is called an ‘off’ 19 | point, i.e., a point which isn't located on the contour itself, but serves 20 | as a control point for a Bézier arc. 21 | 22 | FT_CURVE_TAG_CONIC 23 | 24 | Used for an ‘off’ point used to control a conic Bézier arc. 25 | 26 | FT_CURVE_TAG_CUBIC 27 | 28 | Used for an ‘off’ point used to control a cubic Bézier arc. 29 | 30 | 31 | FT_Curve_Tag_On, FT_Curve_Tag_Conic, FT_Curve_Tag_Cubic are their 32 | correspondning mixed-case aliases. 33 | 34 | Use the FT_CURVE_TAG(tag) macro to filter out other, internally used flags. 35 | 36 | """ 37 | 38 | FT_CURVE_TAGS = { 39 | 'FT_CURVE_TAG_ON' : 1, 40 | 'FT_CURVE_TAG_CONIC' : 0, 41 | 'FT_CURVE_TAG_CUBIC' : 2} 42 | globals().update(FT_CURVE_TAGS) 43 | 44 | FT_Curve_Tag_On = FT_CURVE_TAG_ON 45 | FT_Curve_Tag_Conic = FT_CURVE_TAG_CONIC 46 | FT_Curve_Tag_Cubic = FT_CURVE_TAG_CUBIC 47 | 48 | def FT_CURVE_TAG( flag ): 49 | return ( flag & 3 ) 50 | 51 | # FreeType itself does not have mixed-case macros 52 | FT_Curve_Tag = FT_CURVE_TAG 53 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_encodings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration used to specify character sets supported by charmaps. Used in 10 | the FT_Select_Charmap API function. 11 | 12 | FT_ENCODING_NONE 13 | 14 | The encoding value 0 is reserved. 15 | 16 | FT_ENCODING_UNICODE 17 | 18 | Corresponds to the Unicode character set. This value covers all versions of 19 | the Unicode repertoire, including ASCII and Latin-1. Most fonts include a 20 | Unicode charmap, but not all of them. 21 | 22 | For example, if you want to access Unicode value U+1F028 (and the font 23 | contains it), use value 0x1F028 as the input value for FT_Get_Char_Index. 24 | 25 | FT_ENCODING_MS_SYMBOL 26 | 27 | Corresponds to the Microsoft Symbol encoding, used to encode mathematical 28 | symbols in the 32..255 character code range. For more information, see 29 | 'http://www.ceviz.net/symbol.htm'. 30 | 31 | FT_ENCODING_SJIS 32 | 33 | Corresponds to Japanese SJIS encoding. More info at at 34 | 'http://langsupport.japanreference.com/encoding.shtml'. See note on 35 | multi-byte encodings below. 36 | 37 | FT_ENCODING_GB2312 38 | 39 | Corresponds to an encoding system for Simplified Chinese as used used in 40 | mainland China. 41 | 42 | FT_ENCODING_BIG5 43 | 44 | Corresponds to an encoding system for Traditional Chinese as used in Taiwan 45 | and Hong Kong. 46 | 47 | FT_ENCODING_WANSUNG 48 | 49 | Corresponds to the Korean encoding system known as Wansung. For more 50 | information see 'http://www.microsoft.com/typography/unicode/949.txt'. 51 | 52 | FT_ENCODING_JOHAB 53 | 54 | The Korean standard character set (KS C 5601-1992), which corresponds to MS 55 | Windows code page 1361. This character set includes all possible Hangeul 56 | character combinations. 57 | 58 | FT_ENCODING_ADOBE_LATIN_1 59 | 60 | Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript font. It 61 | is limited to 256 character codes. 62 | 63 | FT_ENCODING_ADOBE_STANDARD 64 | 65 | Corresponds to the Adobe Standard encoding, as found in Type 1, CFF, and 66 | OpenType/CFF fonts. It is limited to 256 character codes. 67 | 68 | FT_ENCODING_ADOBE_EXPERT 69 | 70 | Corresponds to the Adobe Expert encoding, as found in Type 1, CFF, and 71 | OpenType/CFF fonts. It is limited to 256 character codes. 72 | 73 | FT_ENCODING_ADOBE_CUSTOM 74 | 75 | Corresponds to a custom encoding, as found in Type 1, CFF, and OpenType/CFF 76 | fonts. It is limited to 256 character codes. 77 | 78 | FT_ENCODING_APPLE_ROMAN 79 | 80 | Corresponds to the 8-bit Apple roman encoding. Many TrueType and OpenType 81 | fonts contain a charmap for this encoding, since older versions of Mac OS are 82 | able to use it. 83 | 84 | FT_ENCODING_OLD_LATIN_2 85 | 86 | This value is deprecated and was never used nor reported by FreeType. Don't 87 | use or test for it. 88 | """ 89 | 90 | def _FT_ENC_TAG(a,b,c,d): 91 | return ( ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d) ) 92 | 93 | FT_ENCODINGS = {'FT_ENCODING_NONE' : _FT_ENC_TAG('\0','\0','\0','\0'), 94 | 'FT_ENCODING_MS_SYMBOL' : _FT_ENC_TAG( 's','y','m','b' ), 95 | 'FT_ENCODING_UNICODE' : _FT_ENC_TAG( 'u','n','i','c' ), 96 | 'FT_ENCODING_SJIS' : _FT_ENC_TAG( 's','j','i','s' ), 97 | 'FT_ENCODING_GB2312' : _FT_ENC_TAG( 'g','b',' ',' ' ), 98 | 'FT_ENCODING_BIG5' : _FT_ENC_TAG( 'b','i','g','5' ), 99 | 'FT_ENCODING_WANSUNG' : _FT_ENC_TAG( 'w','a','n','s' ), 100 | 'FT_ENCODING_JOHAB' : _FT_ENC_TAG( 'j','o','h','a' ), 101 | 'FT_ENCODING_ADOBE_STANDARD' : _FT_ENC_TAG( 'A','D','O','B' ), 102 | 'FT_ENCODING_ADOBE_EXPERT' : _FT_ENC_TAG( 'A','D','B','E' ), 103 | 'FT_ENCODING_ADOBE_CUSTOM' : _FT_ENC_TAG( 'A','D','B','C' ), 104 | 'FT_ENCODING_ADOBE_LATIN1' : _FT_ENC_TAG( 'l','a','t','1' ), 105 | 'FT_ENCODING_OLD_LATIN2' : _FT_ENC_TAG( 'l','a','t','2' ), 106 | 'FT_ENCODING_APPLE_ROMAN' : _FT_ENC_TAG( 'a','r','m','n' ) } 107 | globals().update(FT_ENCODINGS) 108 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_face_flags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit flags used in the 'face_flags' field of the FT_FaceRec 10 | structure. They inform client applications of properties of the corresponding 11 | face. 12 | 13 | 14 | FT_FACE_FLAG_SCALABLE 15 | 16 | Indicates that the face contains outline glyphs. This doesn't prevent bitmap 17 | strikes, i.e., a face can have both this and and FT_FACE_FLAG_FIXED_SIZES 18 | set. 19 | 20 | 21 | FT_FACE_FLAG_FIXED_SIZES 22 | 23 | Indicates that the face contains bitmap strikes. See also the 24 | 'num_fixed_sizes' and 'available_sizes' fields of FT_FaceRec. 25 | 26 | 27 | FT_FACE_FLAG_FIXED_WIDTH 28 | 29 | Indicates that the face contains fixed-width characters (like Courier, 30 | Lucido, MonoType, etc.). 31 | 32 | 33 | FT_FACE_FLAG_SFNT 34 | 35 | Indicates that the face uses the 'sfnt' storage scheme. For now, this means 36 | TrueType and OpenType. 37 | 38 | 39 | FT_FACE_FLAG_HORIZONTAL 40 | 41 | Indicates that the face contains horizontal glyph metrics. This should be set 42 | for all common formats. 43 | 44 | 45 | FT_FACE_FLAG_VERTICAL 46 | 47 | Indicates that the face contains vertical glyph metrics. This is only 48 | available in some formats, not all of them. 49 | 50 | 51 | FT_FACE_FLAG_KERNING 52 | 53 | Indicates that the face contains kerning information. If set, the kerning 54 | distance can be retrieved through the function FT_Get_Kerning. Otherwise the 55 | function always return the vector (0,0). Note that FreeType doesn't handle 56 | kerning data from the 'GPOS' table (as present in some OpenType fonts). 57 | 58 | 59 | FT_FACE_FLAG_MULTIPLE_MASTERS 60 | 61 | Indicates that the font contains multiple masters and is capable of 62 | interpolating between them. See the multiple-masters specific API for 63 | details. 64 | 65 | 66 | FT_FACE_FLAG_GLYPH_NAMES 67 | 68 | Indicates that the font contains glyph names that can be retrieved through 69 | FT_Get_Glyph_Name. Note that some TrueType fonts contain broken glyph name 70 | tables. Use the function FT_Has_PS_Glyph_Names when needed. 71 | 72 | 73 | FT_FACE_FLAG_EXTERNAL_STREAM 74 | 75 | Used internally by FreeType to indicate that a face's stream was provided by 76 | the client application and should not be destroyed when FT_Done_Face is 77 | called. Don't read or test this flag. 78 | 79 | 80 | FT_FACE_FLAG_HINTER 81 | 82 | Set if the font driver has a hinting machine of its own. For example, with 83 | TrueType fonts, it makes sense to use data from the SFNT 'gasp' table only if 84 | the native TrueType hinting engine (with the bytecode interpreter) is 85 | available and active. 86 | 87 | 88 | FT_FACE_FLAG_CID_KEYED 89 | 90 | Set if the font is CID-keyed. In that case, the font is not accessed by glyph 91 | indices but by CID values. For subsetted CID-keyed fonts this has the 92 | consequence that not all index values are a valid argument to 93 | FT_Load_Glyph. Only the CID values for which corresponding glyphs in the 94 | subsetted font exist make FT_Load_Glyph return successfully; in all other 95 | cases you get an 'FT_Err_Invalid_Argument' error. 96 | 97 | Note that CID-keyed fonts which are in an SFNT wrapper don't have this flag 98 | set since the glyphs are accessed in the normal way (using contiguous 99 | indices); the 'CID-ness' isn't visible to the application. 100 | 101 | 102 | FT_FACE_FLAG_TRICKY 103 | 104 | Set if the font is 'tricky', this is, it always needs the font format's 105 | native hinting engine to get a reasonable result. A typical example is the 106 | Chinese font 'mingli.ttf' which uses TrueType bytecode instructions to move 107 | and scale all of its subglyphs. 108 | 109 | It is not possible to autohint such fonts using FT_LOAD_FORCE_AUTOHINT; it 110 | will also ignore FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING 111 | and FT_LOAD_NO_AUTOHINT to really disable hinting; however, you probably 112 | never want this except for demonstration purposes. 113 | 114 | Currently, there are six TrueType fonts in the list of tricky fonts; they are 115 | hard-coded in file 'ttobjs.c'. 116 | """ 117 | FT_FACE_FLAGS = { 'FT_FACE_FLAG_SCALABLE' : 1 << 0, 118 | 'FT_FACE_FLAG_FIXED_SIZES' : 1 << 1, 119 | 'FT_FACE_FLAG_FIXED_WIDTH' : 1 << 2, 120 | 'FT_FACE_FLAG_SFNT' : 1 << 3, 121 | 'FT_FACE_FLAG_HORIZONTAL' : 1 << 4, 122 | 'FT_FACE_FLAG_VERTICAL' : 1 << 5, 123 | 'FT_FACE_FLAG_KERNING' : 1 << 6, 124 | 'FT_FACE_FLAG_FAST_GLYPHS' : 1 << 7, 125 | 'FT_FACE_FLAG_MULTIPLE_MASTERS' : 1 << 8, 126 | 'FT_FACE_FLAG_GLYPH_NAMES' : 1 << 9, 127 | 'FT_FACE_FLAG_EXTERNAL_STREAM' : 1 << 10, 128 | 'FT_FACE_FLAG_HINTER' : 1 << 11, 129 | 'FT_FACE_FLAG_CID_KEYED' : 1 << 12, 130 | 'FT_FACE_FLAG_TRICKY' : 1 << 13 131 | } 132 | globals().update(FT_FACE_FLAGS) 133 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_fstypes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit flags that inform client applications of embedding and 10 | subsetting restrictions associated with a font. 11 | 12 | FT_FSTYPE_INSTALLABLE_EMBEDDING 13 | 14 | Fonts with no fsType bit set may be embedded and permanently installed on 15 | the remote system by an application. 16 | 17 | 18 | FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 19 | 20 | Fonts that have only this bit set must not be modified, embedded or exchanged 21 | in any manner without first obtaining permission of the font software 22 | copyright owner. 23 | 24 | 25 | FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 26 | 27 | If this bit is set, the font may be embedded and temporarily loaded on the 28 | remote system. Documents containing Preview & Print fonts must be opened 29 | 'read-only'; no edits can be applied to the document. 30 | 31 | 32 | FT_FSTYPE_EDITABLE_EMBEDDING 33 | 34 | If this bit is set, the font may be embedded but must only be installed 35 | temporarily on other systems. In contrast to Preview & Print fonts, 36 | documents containing editable fonts may be opened for reading, editing is 37 | permitted, and changes may be saved. 38 | 39 | 40 | FT_FSTYPE_NO_SUBSETTING 41 | 42 | If this bit is set, the font may not be subsetted prior to embedding. 43 | 44 | 45 | FT_FSTYPE_BITMAP_EMBEDDING_ONLY 46 | 47 | If this bit is set, only bitmaps contained in the font may be embedded; no 48 | outline data may be embedded. If there are no bitmaps available in the font, 49 | then the font is unembeddable. 50 | """ 51 | 52 | FT_FSTYPES = {'FT_FSTYPE_INSTALLABLE_EMBEDDING' : 0x0000, 53 | 'FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING' : 0x0002, 54 | 'FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING' : 0x0004, 55 | 'FT_FSTYPE_EDITABLE_EMBEDDING' : 0x0008, 56 | 'FT_FSTYPE_NO_SUBSETTING' : 0x0100, 57 | 'FT_FSTYPE_BITMAP_EMBEDDING_ONLY' : 0x0200,} 58 | globals().update(FT_FSTYPES) 59 | ft_fstype_installable_embedding = FT_FSTYPE_INSTALLABLE_EMBEDDING 60 | ft_fstype_restricted_license_embedding = FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 61 | ft_fstype_preview_and_print_embedding = FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 62 | ft_fstype_editable_embedding = FT_FSTYPE_EDITABLE_EMBEDDING 63 | ft_fstype_no_subsetting = FT_FSTYPE_NO_SUBSETTING 64 | ft_fstype_bitmap_embedding_only = FT_FSTYPE_BITMAP_EMBEDDING_ONLY 65 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_glyph_bbox_modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | The mode how the values of FT_Glyph_Get_CBox are returned. 10 | 11 | FT_GLYPH_BBOX_UNSCALED 12 | 13 | Return unscaled font units. 14 | 15 | FT_GLYPH_BBOX_SUBPIXELS 16 | 17 | Return unfitted 26.6 coordinates. 18 | 19 | FT_GLYPH_BBOX_GRIDFIT 20 | 21 | Return grid-fitted 26.6 coordinates. 22 | 23 | FT_GLYPH_BBOX_TRUNCATE 24 | 25 | Return coordinates in integer pixels. 26 | 27 | FT_GLYPH_BBOX_PIXELS 28 | 29 | Return grid-fitted pixel coordinates. 30 | """ 31 | FT_GLYPH_BBOX_MODES = {'FT_GLYPH_BBOX_UNSCALED' : 0, 32 | 'FT_GLYPH_BBOX_SUBPIXELS' : 0, 33 | 'FT_GLYPH_BBOX_GRIDFIT' : 1, 34 | 'FT_GLYPH_BBOX_TRUNCATE' : 2, 35 | 'FT_GLYPH_BBOX_PIXELS' : 3} 36 | globals().update(FT_GLYPH_BBOX_MODES) 37 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_glyph_formats.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration type used to describe the format of a given glyph image. Note 10 | that this version of FreeType only supports two image formats, even though 11 | future font drivers will be able to register their own format. 12 | 13 | FT_GLYPH_FORMAT_NONE 14 | 15 | The value 0 is reserved. 16 | 17 | FT_GLYPH_FORMAT_COMPOSITE 18 | 19 | The glyph image is a composite of several other images. This format is only 20 | used with FT_LOAD_NO_RECURSE, and is used to report compound glyphs (like 21 | accented characters). 22 | 23 | FT_GLYPH_FORMAT_BITMAP 24 | 25 | The glyph image is a bitmap, and can be described as an FT_Bitmap. You 26 | generally need to access the 'bitmap' field of the FT_GlyphSlotRec structure 27 | to read it. 28 | 29 | FT_GLYPH_FORMAT_OUTLINE 30 | 31 | The glyph image is a vectorial outline made of line segments and Bezier arcs; 32 | it can be described as an FT_Outline; you generally want to access the 33 | 'outline' field of the FT_GlyphSlotRec structure to read it. 34 | 35 | FT_GLYPH_FORMAT_PLOTTER 36 | 37 | The glyph image is a vectorial path with no inside and outside contours. Some 38 | Type 1 fonts, like those in the Hershey family, contain glyphs in this 39 | format. These are described as FT_Outline, but FreeType isn't currently 40 | capable of rendering them correctly. 41 | """ 42 | 43 | def _FT_IMAGE_TAG(a,b,c,d): 44 | return ( ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d) ) 45 | 46 | FT_GLYPH_FORMATS = { 47 | 'FT_GLYPH_FORMAT_NONE' : _FT_IMAGE_TAG( '\0','\0','\0','\0' ), 48 | 'FT_GLYPH_FORMAT_COMPOSITE' : _FT_IMAGE_TAG( 'c','o','m','p' ), 49 | 'FT_GLYPH_FORMAT_BITMAP' : _FT_IMAGE_TAG( 'b','i','t','s' ), 50 | 'FT_GLYPH_FORMAT_OUTLINE' : _FT_IMAGE_TAG( 'o','u','t','l' ), 51 | 'FT_GLYPH_FORMAT_PLOTTER' : _FT_IMAGE_TAG( 'p','l','o','t' )} 52 | globals().update(FT_GLYPH_FORMATS) 53 | ft_glyph_format_none = FT_GLYPH_FORMAT_NONE 54 | ft_glyph_format_composite = FT_GLYPH_FORMAT_COMPOSITE 55 | ft_glyph_format_bitmap = FT_GLYPH_FORMAT_BITMAP 56 | ft_glyph_format_outline = FT_GLYPH_FORMAT_OUTLINE 57 | ft_glyph_format_plotter = FT_GLYPH_FORMAT_PLOTTER 58 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_kerning_modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration used to specify which kerning values to return in 10 | FT_Get_Kerning. 11 | 12 | 13 | FT_KERNING_DEFAULT 14 | 15 | Return scaled and grid-fitted kerning distances (value is 0). 16 | 17 | 18 | FT_KERNING_UNFITTED 19 | 20 | Return scaled but un-grid-fitted kerning distances. 21 | 22 | 23 | FT_KERNING_UNSCALED 24 | 25 | Return the kerning vector in original font units. 26 | """ 27 | FT_KERNING_MODES = { 'FT_KERNING_DEFAULT' : 0, 28 | 'FT_KERNING_UNFITTED' : 1, 29 | 'FT_KERNING_UNSCALED' : 2 } 30 | globals().update(FT_KERNING_MODES) 31 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_lcd_filters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | 9 | """ 10 | A list of values to identify various types of LCD filters. 11 | 12 | 13 | FT_LCD_FILTER_NONE 14 | 15 | Do not perform filtering. When used with subpixel rendering, this results in 16 | sometimes severe color fringes. 17 | 18 | 19 | FT_LCD_FILTER_DEFAULT 20 | 21 | The default filter reduces color fringes considerably, at the cost of a 22 | slight blurriness in the output. 23 | 24 | 25 | FT_LCD_FILTER_LIGHT 26 | 27 | The light filter is a variant that produces less blurriness at the cost of 28 | slightly more color fringes than the default one. It might be better, 29 | depending on taste, your monitor, or your personal vision. 30 | 31 | 32 | FT_LCD_FILTER_LEGACY 33 | 34 | This filter corresponds to the original libXft color filter. It provides high 35 | contrast output but can exhibit really bad color fringes if glyphs are not 36 | extremely well hinted to the pixel grid. In other words, it only works well 37 | if the TrueType bytecode interpreter is enabled and high-quality hinted fonts 38 | are used. 39 | 40 | This filter is only provided for comparison purposes, and might be disabled 41 | or stay unsupported in the future. 42 | """ 43 | 44 | FT_LCD_FILTERS = {'FT_LCD_FILTER_NONE' : 0, 45 | 'FT_LCD_FILTER_DEFAULT' : 1, 46 | 'FT_LCD_FILTER_LIGHT' : 2, 47 | 'FT_LCD_FILTER_LEGACY' : 16} 48 | globals().update(FT_LCD_FILTERS) 49 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_load_flags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit-field constants used with FT_Load_Glyph to indicate what kind 10 | of operations to perform during glyph loading. 11 | 12 | 13 | FT_LOAD_DEFAULT 14 | 15 | Corresponding to 0, this value is used as the default glyph load 16 | operation. In this case, the following happens: 17 | 18 | 1. FreeType looks for a bitmap for the glyph corresponding to the face's 19 | current size. If one is found, the function returns. The bitmap data can 20 | be accessed from the glyph slot (see note below). 21 | 22 | 2. If no embedded bitmap is searched or found, FreeType looks for a scalable 23 | outline. If one is found, it is loaded from the font file, scaled to 24 | device pixels, then 'hinted' to the pixel grid in order to optimize 25 | it. The outline data can be accessed from the glyph slot (see note below). 26 | 27 | Note that by default, the glyph loader doesn't render outlines into 28 | bitmaps. The following flags are used to modify this default behaviour to 29 | more specific and useful cases. 30 | 31 | 32 | FT_LOAD_NO_SCALE 33 | 34 | Don't scale the outline glyph loaded, but keep it in font units. 35 | 36 | This flag implies FT_LOAD_NO_HINTING and FT_LOAD_NO_BITMAP, and unsets 37 | FT_LOAD_RENDER. 38 | 39 | 40 | FT_LOAD_NO_HINTING 41 | 42 | Disable hinting. This generally generates 'blurrier' bitmap glyph when the 43 | glyph is rendered in any of the anti-aliased modes. See also the note below. 44 | 45 | This flag is implied by FT_LOAD_NO_SCALE. 46 | 47 | 48 | FT_LOAD_RENDER 49 | 50 | Call FT_Render_Glyph after the glyph is loaded. By default, the glyph is 51 | rendered in FT_RENDER_MODE_NORMAL mode. This can be overridden by 52 | FT_LOAD_TARGET_XXX or FT_LOAD_MONOCHROME. 53 | 54 | This flag is unset by FT_LOAD_NO_SCALE. 55 | 56 | 57 | FT_LOAD_NO_BITMAP 58 | 59 | Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag. 60 | 61 | FT_LOAD_NO_SCALE always sets this flag. 62 | 63 | 64 | FT_LOAD_VERTICAL_LAYOUT 65 | 66 | Load the glyph for vertical text layout. Don't use it as it is problematic 67 | currently. 68 | 69 | 70 | FT_LOAD_FORCE_AUTOHINT 71 | 72 | Indicates that the auto-hinter is preferred over the font's native 73 | hinter. See also the note below. 74 | 75 | 76 | FT_LOAD_CROP_BITMAP 77 | 78 | Indicates that the font driver should crop the loaded bitmap glyph (i.e., 79 | remove all space around its black bits). Not all drivers implement this. 80 | 81 | 82 | FT_LOAD_PEDANTIC 83 | 84 | Indicates that the font driver should perform pedantic verifications during 85 | glyph loading. This is mostly used to detect broken glyphs in fonts. By 86 | default, FreeType tries to handle broken fonts also. 87 | 88 | 89 | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 90 | 91 | Indicates that the font driver should ignore the global advance width defined 92 | in the font. By default, that value is used as the advance width for all 93 | glyphs when the face has FT_FACE_FLAG_FIXED_WIDTH set. 94 | 95 | This flag exists for historical reasons (to support buggy CJK fonts). 96 | 97 | 98 | FT_LOAD_NO_RECURSE 99 | 100 | This flag is only used internally. It merely indicates that the font driver 101 | should not load composite glyphs recursively. Instead, it should set the 102 | 'num_subglyph' and 'subglyphs' values of the glyph slot accordingly, and set 103 | 'glyph->format' to FT_GLYPH_FORMAT_COMPOSITE. 104 | 105 | The description of sub-glyphs is not available to client applications for now. 106 | 107 | This flag implies FT_LOAD_NO_SCALE and FT_LOAD_IGNORE_TRANSFORM. 108 | 109 | 110 | FT_LOAD_IGNORE_TRANSFORM 111 | 112 | Indicates that the transform matrix set by FT_Set_Transform should be ignored. 113 | 114 | 115 | FT_LOAD_MONOCHROME 116 | 117 | This flag is used with FT_LOAD_RENDER to indicate that you want to render an 118 | outline glyph to a 1-bit monochrome bitmap glyph, with 8 pixels packed into 119 | each byte of the bitmap data. 120 | 121 | Note that this has no effect on the hinting algorithm used. You should rather 122 | use FT_LOAD_TARGET_MONO so that the monochrome-optimized hinting algorithm is 123 | used. 124 | 125 | 126 | FT_LOAD_LINEAR_DESIGN 127 | 128 | Indicates that the 'linearHoriAdvance' and 'linearVertAdvance' fields of 129 | FT_GlyphSlotRec should be kept in font units. See FT_GlyphSlotRec for 130 | details. 131 | 132 | 133 | FT_LOAD_NO_AUTOHINT 134 | 135 | Disable auto-hinter. See also the note below. 136 | 137 | 138 | FT_LOAD_COLOR 139 | 140 | This flag is used to request loading of color embedded-bitmap images. The 141 | resulting color bitmaps, if available, will have the FT_PIXEL_MODE_BGRA 142 | format. When the flag is not used and color bitmaps are found, they will be 143 | converted to 256-level gray bitmaps transparently. Those bitmaps will be in 144 | the FT_PIXEL_MODE_GRAY format. 145 | 146 | 147 | FT_LOAD_COMPUTE_METRICS 148 | Compute glyph metrics from the glyph data, without the use of bundled metrics 149 | tables (for example, the `hdmx' table in TrueType fonts). This flag is 150 | mainly used by font validating or font editing applications, which need to 151 | ignore, verify, or edit those tables. 152 | 153 | Currently, this flag is only implemented for TrueType fonts. 154 | 155 | 156 | FT_LOAD_BITMAP_METRICS_ONLY 157 | Request loading of the metrics and bitmap image information of a (possibly 158 | embedded) bitmap glyph without allocating or copying the bitmap image data 159 | itself. No effect if the target glyph is not a bitmap image. 160 | 161 | This flag unsets FT_LOAD_RENDER. 162 | """ 163 | 164 | FT_LOAD_FLAGS = { 'FT_LOAD_DEFAULT' : 0x0, 165 | 'FT_LOAD_NO_SCALE' : 0x1, 166 | 'FT_LOAD_NO_HINTING' : 0x2, 167 | 'FT_LOAD_RENDER' : 0x4, 168 | 'FT_LOAD_NO_BITMAP' : 0x8, 169 | 'FT_LOAD_VERTICAL_LAYOUT' : 0x10, 170 | 'FT_LOAD_FORCE_AUTOHINT' : 0x20, 171 | 'FT_LOAD_CROP_BITMAP' : 0x40, 172 | 'FT_LOAD_PEDANTIC' : 0x80, 173 | 'FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH' : 0x200, 174 | 'FT_LOAD_NO_RECURSE' : 0x400, 175 | 'FT_LOAD_IGNORE_TRANSFORM' : 0x800, 176 | 'FT_LOAD_MONOCHROME' : 0x1000, 177 | 'FT_LOAD_LINEAR_DESIGN' : 0x2000, 178 | 'FT_LOAD_NO_AUTOHINT' : 0x8000, 179 | 'FT_LOAD_COLOR' : 0x100000, 180 | 'FT_LOAD_COMPUTE_METRICS' : 0x200000, 181 | 'FT_LOAD_BITMAP_METRICS_ONLY' : 0x400000 } 182 | globals().update(FT_LOAD_FLAGS) 183 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_load_targets.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of values that are used to select a specific hinting algorithm to use 10 | by the hinter. You should OR one of these values to your 'load_flags' when 11 | calling FT_Load_Glyph. 12 | 13 | Note that font's native hinters may ignore the hinting algorithm you have 14 | specified (e.g., the TrueType bytecode interpreter). You can set 15 | FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. 16 | 17 | Also note that FT_LOAD_TARGET_LIGHT is an exception, in that it always 18 | implies FT_LOAD_FORCE_AUTOHINT. 19 | 20 | 21 | FT_LOAD_TARGET_NORMAL 22 | 23 | This corresponds to the default hinting algorithm, optimized for standard 24 | gray-level rendering. For monochrome output, use FT_LOAD_TARGET_MONO instead. 25 | 26 | 27 | FT_LOAD_TARGET_LIGHT 28 | 29 | A lighter hinting algorithm for non-monochrome modes. Many generated glyphs 30 | are more fuzzy but better resemble its original shape. A bit like rendering 31 | on Mac OS X. 32 | 33 | As a special exception, this target implies FT_LOAD_FORCE_AUTOHINT. 34 | 35 | 36 | FT_LOAD_TARGET_MONO 37 | 38 | Strong hinting algorithm that should only be used for monochrome output. The 39 | result is probably unpleasant if the glyph is rendered in non-monochrome 40 | modes. 41 | 42 | 43 | FT_LOAD_TARGET_LCD 44 | 45 | A variant of FT_LOAD_TARGET_NORMAL optimized for horizontally decimated LCD 46 | displays. 47 | 48 | 49 | FT_LOAD_TARGET_LCD_V 50 | 51 | A variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD 52 | displays. 53 | """ 54 | 55 | from freetype.ft_enums.ft_render_modes import * 56 | 57 | 58 | def _FT_LOAD_TARGET_(x): 59 | return (x & 15) << 16 60 | FT_LOAD_TARGETS = { 61 | 'FT_LOAD_TARGET_NORMAL' : _FT_LOAD_TARGET_(FT_RENDER_MODE_NORMAL), 62 | 'FT_LOAD_TARGET_LIGHT' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LIGHT), 63 | 'FT_LOAD_TARGET_MONO' : _FT_LOAD_TARGET_(FT_RENDER_MODE_MONO), 64 | 'FT_LOAD_TARGET_LCD' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LCD), 65 | 'FT_LOAD_TARGET_LCD_V' : _FT_LOAD_TARGET_(FT_RENDER_MODE_LCD_V) } 66 | globals().update(FT_LOAD_TARGETS) 67 | #def FT_LOAD_TARGET_MODE(x): 68 | # return (x >> 16) & 15 69 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_open_modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit-field constants used within the 'flags' field of the 10 | FT_Open_Args structure. 11 | 12 | 13 | FT_OPEN_MEMORY 14 | 15 | This is a memory-based stream. 16 | 17 | 18 | FT_OPEN_STREAM 19 | 20 | Copy the stream from the 'stream' field. 21 | 22 | 23 | FT_OPEN_PATHNAME 24 | 25 | Create a new input stream from a C path name. 26 | 27 | 28 | FT_OPEN_DRIVER 29 | 30 | Use the 'driver' field. 31 | 32 | 33 | FT_OPEN_PARAMS 34 | 35 | Use the 'num_params' and 'params' fields. 36 | """ 37 | FT_OPEN_MODES = {'FT_OPEN_MEMORY': 0x1, 38 | 'FT_OPEN_STREAM': 0x2, 39 | 'FT_OPEN_PATHNAME': 0x4, 40 | 'FT_OPEN_DRIVER': 0x8, 41 | 'FT_OPEN_PARAMS': 0x10 } 42 | globals().update(FT_OPEN_MODES) 43 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_outline_flags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit-field constants use for the flags in an outline's 'flags' 10 | field. 11 | 12 | 13 | FT_OUTLINE_NONE 14 | 15 | Value 0 is reserved. 16 | 17 | 18 | FT_OUTLINE_OWNER 19 | 20 | If set, this flag indicates that the outline's field arrays (i.e., 'points', 21 | 'flags', and 'contours') are 'owned' by the outline object, and should thus 22 | be freed when it is destroyed. 23 | 24 | 25 | FT_OUTLINE_EVEN_ODD_FILL 26 | 27 | By default, outlines are filled using the non-zero winding rule. If set to 1, 28 | the outline will be filled using the even-odd fill rule (only works with the 29 | smooth rasterizer). 30 | 31 | 32 | FT_OUTLINE_REVERSE_FILL 33 | 34 | By default, outside contours of an outline are oriented in clock-wise 35 | direction, as defined in the TrueType specification. This flag is set if the 36 | outline uses the opposite direction (typically for Type 1 fonts). This flag 37 | is ignored by the scan converter. 38 | 39 | 40 | FT_OUTLINE_IGNORE_DROPOUTS 41 | 42 | By default, the scan converter will try to detect drop-outs in an outline and 43 | correct the glyph bitmap to ensure consistent shape continuity. If set, this 44 | flag hints the scan-line converter to ignore such cases. See below for more 45 | information. 46 | 47 | 48 | FT_OUTLINE_SMART_DROPOUTS 49 | 50 | Select smart dropout control. If unset, use simple dropout control. Ignored 51 | if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. 52 | 53 | 54 | FT_OUTLINE_INCLUDE_STUBS 55 | 56 | If set, turn pixels on for 'stubs', otherwise exclude them. Ignored if 57 | FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. 58 | 59 | 60 | FT_OUTLINE_HIGH_PRECISION 61 | 62 | This flag indicates that the scan-line converter should try to convert this 63 | outline to bitmaps with the highest possible quality. It is typically set for 64 | small character sizes. Note that this is only a hint that might be completely 65 | ignored by a given scan-converter. 66 | 67 | 68 | FT_OUTLINE_SINGLE_PASS 69 | 70 | This flag is set to force a given scan-converter to only use a single pass 71 | over the outline to render a bitmap glyph image. Normally, it is set for very 72 | large character sizes. It is only a hint that might be completely ignored by 73 | a given scan-converter. 74 | """ 75 | FT_OUTLINE_FLAGS = { 'FT_OUTLINE_NONE' : 0x0, 76 | 'FT_OUTLINE_OWNER' : 0x1, 77 | 'FT_OUTLINE_EVEN_ODD_FILL' : 0x2, 78 | 'FT_OUTLINE_REVERSE_FILL' : 0x4, 79 | 'FT_OUTLINE_IGNORE_DROPOUTS' : 0x8, 80 | 'FT_OUTLINE_SMART_DROPOUTS' : 0x10, 81 | 'FT_OUTLINE_INCLUDE_STUBS' : 0x20, 82 | 'FT_OUTLINE_HIGH_PRECISION' : 0x100, 83 | 'FT_OUTLINE_SINGLE_PASS' : 0x200 } 84 | globals().update(FT_OUTLINE_FLAGS) 85 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_pixel_modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration type that lists the render modes supported by FreeType 2. Each 10 | mode corresponds to a specific type of scanline conversion performed on the 11 | outline. 12 | 13 | 14 | FT_PIXEL_MODE_NONE 15 | 16 | Value 0 is reserved. 17 | 18 | 19 | FT_PIXEL_MODE_MONO 20 | 21 | A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in 22 | most-significant order (MSB), which means that the left-most pixel in a byte 23 | has value 128. 24 | 25 | 26 | FT_PIXEL_MODE_GRAY 27 | 28 | An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each 29 | pixel is stored in one byte. Note that the number of 'gray' levels is stored 30 | in the 'num_grays' field of the FT_Bitmap structure (it generally is 256). 31 | 32 | 33 | FT_PIXEL_MODE_GRAY2 34 | 35 | A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in 36 | font files according to the OpenType specification. We haven't found a single 37 | font using this format, however. 38 | 39 | 40 | FT_PIXEL_MODE_GRAY4 41 | 42 | A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font 43 | files according to the OpenType specification. We haven't found a single font 44 | using this format, however. 45 | 46 | 47 | FT_PIXEL_MODE_LCD 48 | 49 | An 8-bit bitmap, representing RGB or BGR decimated glyph images used for 50 | display on LCD displays; the bitmap is three times wider than the original 51 | glyph image. See also FT_RENDER_MODE_LCD. 52 | 53 | 54 | FT_PIXEL_MODE_LCD_V 55 | 56 | An 8-bit bitmap, representing RGB or BGR decimated glyph images used for 57 | display on rotated LCD displays; the bitmap is three times taller than the 58 | original glyph image. See also FT_RENDER_MODE_LCD_V. 59 | 60 | """ 61 | 62 | FT_PIXEL_MODES = {'FT_PIXEL_MODE_NONE' : 0, 63 | 'FT_PIXEL_MODE_MONO' : 1, 64 | 'FT_PIXEL_MODE_GRAY' : 2, 65 | 'FT_PIXEL_MODE_GRAY2': 3, 66 | 'FT_PIXEL_MODE_GRAY4': 4, 67 | 'FT_PIXEL_MODE_LCD' : 5, 68 | 'FT_PIXEL_MODE_LCD_V': 6, 69 | 'FT_PIXEL_MODE_MAX' : 7} 70 | globals().update(FT_PIXEL_MODES) 71 | ft_pixel_mode_none = FT_PIXEL_MODE_NONE 72 | ft_pixel_mode_mono = FT_PIXEL_MODE_MONO 73 | ft_pixel_mode_grays = FT_PIXEL_MODE_GRAY 74 | ft_pixel_mode_pal2 = FT_PIXEL_MODE_GRAY2 75 | ft_pixel_mode_pal4 = FT_PIXEL_MODE_GRAY4 76 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_render_modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | An enumeration type that lists the render modes supported by FreeType 2. Each 10 | mode corresponds to a specific type of scanline conversion performed on the 11 | outline. 12 | 13 | For bitmap fonts and embedded bitmaps the 'bitmap->pixel_mode' field in the 14 | FT_GlyphSlotRec structure gives the format of the returned bitmap. 15 | 16 | All modes except FT_RENDER_MODE_MONO use 256 levels of opacity. 17 | 18 | 19 | FT_RENDER_MODE_NORMAL 20 | 21 | This is the default render mode; it corresponds to 8-bit anti-aliased 22 | bitmaps. 23 | 24 | 25 | FT_RENDER_MODE_LIGHT 26 | 27 | This is equivalent to FT_RENDER_MODE_NORMAL. It is only defined as a separate 28 | value because render modes are also used indirectly to define hinting 29 | algorithm selectors. See FT_LOAD_TARGET_XXX for details. 30 | 31 | 32 | FT_RENDER_MODE_MONO 33 | 34 | This mode corresponds to 1-bit bitmaps (with 2 levels of opacity). 35 | 36 | 37 | FT_RENDER_MODE_LCD 38 | 39 | This mode corresponds to horizontal RGB and BGR sub-pixel displays like LCD 40 | screens. It produces 8-bit bitmaps that are 3 times the width of the original 41 | glyph outline in pixels, and which use the FT_PIXEL_MODE_LCD mode. 42 | 43 | 44 | FT_RENDER_MODE_LCD_V 45 | 46 | This mode corresponds to vertical RGB and BGR sub-pixel displays (like PDA 47 | screens, rotated LCD displays, etc.). It produces 8-bit bitmaps that are 3 48 | times the height of the original glyph outline in pixels and use the 49 | FT_PIXEL_MODE_LCD_V mode. 50 | """ 51 | FT_RENDER_MODES = { 'FT_RENDER_MODE_NORMAL' : 0, 52 | 'FT_RENDER_MODE_LIGHT' : 1, 53 | 'FT_RENDER_MODE_MONO' : 2, 54 | 'FT_RENDER_MODE_LCD' : 3, 55 | 'FT_RENDER_MODE_LCD_V' : 4 } 56 | globals().update(FT_RENDER_MODES) 57 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_stroker_borders.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | These values are used to select a given stroke border in 10 | FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder. 11 | 12 | 13 | FT_STROKER_BORDER_LEFT 14 | 15 | Select the left border, relative to the drawing direction. 16 | 17 | 18 | FT_STROKER_BORDER_RIGHT 19 | 20 | Select the right border, relative to the drawing direction. 21 | 22 | 23 | Note 24 | 25 | Applications are generally interested in the 'inside' and 'outside' 26 | borders. However, there is no direct mapping between these and the 'left' and 27 | 'right' ones, since this really depends on the glyph's drawing orientation, 28 | which varies between font formats. 29 | 30 | You can however use FT_Outline_GetInsideBorder and 31 | FT_Outline_GetOutsideBorder to get these. 32 | """ 33 | FT_STROKER_BORDERS = { 'FT_STROKER_BORDER_LEFT' : 0, 34 | 'FT_STROKER_BORDER_RIGHT' : 1} 35 | globals().update(FT_STROKER_BORDERS) 36 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_stroker_linecaps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | These values determine how the end of opened sub-paths are rendered in a 10 | stroke. 11 | 12 | 13 | FT_STROKER_LINECAP_BUTT 14 | 15 | The end of lines is rendered as a full stop on the last point itself. 16 | 17 | 18 | FT_STROKER_LINECAP_ROUND 19 | 20 | The end of lines is rendered as a half-circle around the last point. 21 | 22 | 23 | FT_STROKER_LINECAP_SQUARE 24 | 25 | The end of lines is rendered as a square around the last point. 26 | """ 27 | 28 | FT_STROKER_LINECAPS = { 'FT_STROKER_LINECAP_BUTT' : 0, 29 | 'FT_STROKER_LINECAP_ROUND' : 1, 30 | 'FT_STROKER_LINECAP_SQUARE' : 2} 31 | globals().update(FT_STROKER_LINECAPS) 32 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_stroker_linejoins.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | These values determine how two joining lines are rendered in a stroker. 10 | 11 | 12 | FT_STROKER_LINEJOIN_ROUND 13 | 14 | Used to render rounded line joins. Circular arcs are used to join two lines 15 | smoothly. 16 | 17 | 18 | FT_STROKER_LINEJOIN_BEVEL 19 | 20 | Used to render beveled line joins; i.e., the two joining lines are extended 21 | until they intersect. 22 | 23 | 24 | FT_STROKER_LINEJOIN_MITER 25 | 26 | Same as beveled rendering, except that an additional line break is added if 27 | the angle between the two joining lines is too closed (this is useful to 28 | avoid unpleasant spikes in beveled rendering). 29 | """ 30 | FT_STROKER_LINEJOINS = { 'FT_STROKER_LINEJOIN_ROUND' : 0, 31 | 'FT_STROKER_LINEJOIN_BEVEL' : 1, 32 | 'FT_STROKER_LINEJOIN_MITER' : 2} 33 | globals().update(FT_STROKER_LINEJOINS) 34 | -------------------------------------------------------------------------------- /freetype/ft_enums/ft_style_flags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of bit-flags used to indicate the style of a given face. These are 10 | used in the 'style_flags' field of FT_FaceRec. 11 | 12 | 13 | FT_STYLE_FLAG_ITALIC 14 | 15 | Indicates that a given face style is italic or oblique. 16 | 17 | 18 | FT_STYLE_FLAG_BOLD 19 | 20 | Indicates that a given face is bold. 21 | """ 22 | FT_STYLE_FLAGS = {'FT_STYLE_FLAG_ITALIC' : 1, 23 | 'FT_STYLE_FLAG_BOLD' : 2 } 24 | globals().update(FT_STYLE_FLAGS) 25 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_adobe_ids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of valid values for the 'encoding_id' for TT_PLATFORM_ADOBE 10 | charmaps. This is a FreeType-specific extension! 11 | 12 | TT_ADOBE_ID_STANDARD 13 | 14 | Adobe standard encoding. 15 | 16 | 17 | TT_ADOBE_ID_EXPERT 18 | 19 | Adobe expert encoding. 20 | 21 | 22 | TT_ADOBE_ID_CUSTOM 23 | 24 | Adobe custom encoding. 25 | 26 | 27 | TT_ADOBE_ID_LATIN_1 28 | 29 | Adobe Latin 1 encoding. 30 | """ 31 | 32 | TT_ADOBE_IDS = { 33 | 'TT_ADOBE_ID_STANDARD' : 0, 34 | 'TT_ADOBE_ID_EXPERT' : 1, 35 | 'TT_ADOBE_ID_CUSTOM' : 2, 36 | 'TT_ADOBE_ID_LATIN_1' : 3 } 37 | globals().update(TT_ADOBE_IDS) 38 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_apple_ids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of valid values for the 'encoding_id' for TT_PLATFORM_APPLE_UNICODE 10 | charmaps and name entries. 11 | 12 | 13 | TT_APPLE_ID_DEFAULT 14 | 15 | Unicode version 1.0. 16 | 17 | 18 | TT_APPLE_ID_UNICODE_1_1 19 | 20 | Unicode 1.1; specifies Hangul characters starting at U+34xx. 21 | 22 | 23 | TT_APPLE_ID_ISO_10646 24 | 25 | Deprecated (identical to preceding). 26 | 27 | 28 | TT_APPLE_ID_UNICODE_2_0 29 | 30 | Unicode 2.0 and beyond (UTF-16 BMP only). 31 | 32 | 33 | TT_APPLE_ID_UNICODE_32 34 | 35 | Unicode 3.1 and beyond, using UTF-32. 36 | 37 | 38 | TT_APPLE_ID_VARIANT_SELECTOR 39 | 40 | From Adobe, not Apple. Not a normal cmap. Specifies variations on a real 41 | cmap. 42 | """ 43 | TT_APPLE_IDS = { 44 | 'TT_APPLE_ID_DEFAULT' : 0, 45 | 'TT_APPLE_ID_UNICODE_1_1' : 1, 46 | 'TT_APPLE_ID_ISO_10646' : 2, 47 | 'TT_APPLE_ID_UNICODE_2_0' : 3, 48 | 'TT_APPLE_ID_UNICODE_32' : 4, 49 | 'TT_APPLE_ID_VARIANT_SELECTOR' : 5 } 50 | globals().update(TT_APPLE_IDS) 51 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_mac_ids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of valid values for the 'encoding_id' for TT_PLATFORM_MACINTOSH 10 | charmaps and name entries. 11 | 12 | TT_MAC_ID_ROMAN 13 | 14 | TT_MAC_ID_TELUGU 15 | 16 | TT_MAC_ID_GURMUKHI 17 | 18 | TT_MAC_ID_TIBETAN 19 | 20 | TT_MAC_ID_SIMPLIFIED_CHINESE 21 | 22 | TT_MAC_ID_SINDHI 23 | 24 | TT_MAC_ID_SINHALESE 25 | 26 | TT_MAC_ID_RUSSIAN 27 | 28 | TT_MAC_ID_KANNADA 29 | 30 | TT_MAC_ID_VIETNAMESE 31 | 32 | TT_MAC_ID_MONGOLIAN 33 | 34 | TT_MAC_ID_DEVANAGARI 35 | 36 | TT_MAC_ID_HEBREW 37 | 38 | TT_MAC_ID_TAMIL 39 | 40 | TT_MAC_ID_THAI 41 | 42 | TT_MAC_ID_BURMESE 43 | 44 | TT_MAC_ID_MALDIVIAN 45 | 46 | TT_MAC_ID_TRADITIONAL_CHINESE 47 | 48 | TT_MAC_ID_JAPANESE 49 | 50 | TT_MAC_ID_GREEK 51 | 52 | TT_MAC_ID_LAOTIAN 53 | 54 | TT_MAC_ID_KHMER 55 | 56 | TT_MAC_ID_UNINTERP 57 | 58 | TT_MAC_ID_ORIYA 59 | 60 | TT_MAC_ID_RSYMBOL 61 | 62 | TT_MAC_ID_MALAYALAM 63 | 64 | TT_MAC_ID_GEEZ 65 | 66 | TT_MAC_ID_KOREAN 67 | 68 | TT_MAC_ID_GUJARATI 69 | 70 | TT_MAC_ID_BENGALI 71 | 72 | TT_MAC_ID_ARABIC 73 | 74 | TT_MAC_ID_GEORGIAN 75 | 76 | TT_MAC_ID_ARMENIAN 77 | 78 | TT_MAC_ID_SLAVIC 79 | """ 80 | 81 | TT_MAC_IDS = { 82 | 'TT_MAC_ID_ROMAN' : 0, 83 | 'TT_MAC_ID_JAPANESE' : 1, 84 | 'TT_MAC_ID_TRADITIONAL_CHINESE' : 2, 85 | 'TT_MAC_ID_KOREAN' : 3, 86 | 'TT_MAC_ID_ARABIC' : 4, 87 | 'TT_MAC_ID_HEBREW' : 5, 88 | 'TT_MAC_ID_GREEK' : 6, 89 | 'TT_MAC_ID_RUSSIAN' : 7, 90 | 'TT_MAC_ID_RSYMBOL' : 8, 91 | 'TT_MAC_ID_DEVANAGARI' : 9, 92 | 'TT_MAC_ID_GURMUKHI' : 10, 93 | 'TT_MAC_ID_GUJARATI' : 11, 94 | 'TT_MAC_ID_ORIYA' : 12, 95 | 'TT_MAC_ID_BENGALI' : 13, 96 | 'TT_MAC_ID_TAMIL' : 14, 97 | 'TT_MAC_ID_TELUGU' : 15, 98 | 'TT_MAC_ID_KANNADA' : 16, 99 | 'TT_MAC_ID_MALAYALAM' : 17, 100 | 'TT_MAC_ID_SINHALESE' : 18, 101 | 'TT_MAC_ID_BURMESE' : 19, 102 | 'TT_MAC_ID_KHMER' : 20, 103 | 'TT_MAC_ID_THAI' : 21, 104 | 'TT_MAC_ID_LAOTIAN' : 22, 105 | 'TT_MAC_ID_GEORGIAN' : 23, 106 | 'TT_MAC_ID_ARMENIAN' : 24, 107 | 'TT_MAC_ID_MALDIVIAN' : 25, 108 | 'TT_MAC_ID_SIMPLIFIED_CHINESE' : 25, 109 | 'TT_MAC_ID_TIBETAN' : 26, 110 | 'TT_MAC_ID_MONGOLIAN' : 27, 111 | 'TT_MAC_ID_GEEZ' : 28, 112 | 'TT_MAC_ID_SLAVIC' : 29, 113 | 'TT_MAC_ID_VIETNAMESE' : 30, 114 | 'TT_MAC_ID_SINDHI' : 31, 115 | 'TT_MAC_ID_UNINTERP' : 32} 116 | globals().update(TT_MAC_IDS) 117 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_mac_langids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | Possible values of the language identifier field in the name records of the 10 | TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MACINTOSH. 11 | 12 | TT_MAC_LANGID_LATIN 13 | 14 | TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 15 | 16 | TT_MAC_LANGID_HINDI 17 | 18 | TT_MAC_LANGID_CATALAN 19 | 20 | TT_MAC_LANGID_MARATHI 21 | 22 | TT_MAC_LANGID_ICELANDIC 23 | 24 | TT_MAC_LANGID_ARABIC 25 | 26 | TT_MAC_LANGID_SWAHILI 27 | 28 | TT_MAC_LANGID_KHMER 29 | 30 | TT_MAC_LANGID_UKRAINIAN 31 | 32 | TT_MAC_LANGID_FINNISH 33 | 34 | TT_MAC_LANGID_POLISH 35 | 36 | TT_MAC_LANGID_NEPALI 37 | 38 | TT_MAC_LANGID_UZBEK 39 | 40 | TT_MAC_LANGID_TELUGU 41 | 42 | TT_MAC_LANGID_MALTESE 43 | 44 | TT_MAC_LANGID_AFRIKAANS 45 | 46 | TT_MAC_LANGID_CHEWA 47 | 48 | TT_MAC_LANGID_BASQUE 49 | 50 | TT_MAC_LANGID_CZECH 51 | 52 | TT_MAC_LANGID_ROMANIAN 53 | 54 | TT_MAC_LANGID_QUECHUA 55 | 56 | TT_MAC_LANGID_TAGALOG 57 | 58 | TT_MAC_LANGID_HUNGARIAN 59 | 60 | TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 61 | 62 | TT_MAC_LANGID_TONGAN 63 | 64 | TT_MAC_LANGID_SUNDANESE 65 | 66 | TT_MAC_LANGID_JAPANESE 67 | 68 | TT_MAC_LANGID_MONGOLIAN 69 | 70 | TT_MAC_LANGID_ALBANIAN 71 | 72 | TT_MAC_LANGID_NORWEGIAN 73 | 74 | TT_MAC_LANGID_SLOVAK 75 | 76 | TT_MAC_LANGID_MALAGASY 77 | 78 | TT_MAC_LANGID_DZONGKHA 79 | 80 | TT_MAC_LANGID_DUTCH 81 | 82 | TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 | 84 | TT_MAC_LANGID_SERBIAN 85 | 86 | TT_MAC_LANGID_GERMAN 87 | 88 | TT_MAC_LANGID_SOMALI 89 | 90 | TT_MAC_LANGID_KOREAN 91 | 92 | TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 93 | 94 | TT_MAC_LANGID_CROATIAN 95 | 96 | TT_MAC_LANGID_TURKISH 97 | 98 | TT_MAC_LANGID_MOLDAVIAN 99 | 100 | TT_MAC_LANGID_LAO 101 | 102 | TT_MAC_LANGID_ORIYA 103 | 104 | TT_MAC_LANGID_BRETON 105 | 106 | TT_MAC_LANGID_PASHTO 107 | 108 | TT_MAC_LANGID_GUARANI 109 | 110 | TT_MAC_LANGID_HEBREW 111 | 112 | TT_MAC_LANGID_SLOVENIAN 113 | 114 | TT_MAC_LANGID_ESTONIAN 115 | 116 | TT_MAC_LANGID_RUNDI 117 | 118 | TT_MAC_LANGID_URDU 119 | 120 | TT_MAC_LANGID_CHINESE_TRADITIONAL 121 | 122 | TT_MAC_LANGID_TATAR 123 | 124 | TT_MAC_LANGID_CHINESE_SIMPLIFIED 125 | 126 | TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 127 | 128 | TT_MAC_LANGID_SANSKRIT 129 | 130 | TT_MAC_LANGID_KURDISH 131 | 132 | TT_MAC_LANGID_FAEROESE 133 | 134 | TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 135 | 136 | TT_MAC_LANGID_TIGRINYA 137 | 138 | TT_MAC_LANGID_THAI 139 | 140 | TT_MAC_LANGID_DANISH 141 | 142 | TT_MAC_LANGID_KAZAKH 143 | 144 | TT_MAC_LANGID_YIDDISH 145 | 146 | TT_MAC_LANGID_ESPERANTO 147 | 148 | TT_MAC_LANGID_LITHUANIAN 149 | 150 | TT_MAC_LANGID_FARSI 151 | 152 | TT_MAC_LANGID_LETTISH 153 | 154 | TT_MAC_LANGID_VIETNAMESE 155 | 156 | TT_MAC_LANGID_PORTUGUESE 157 | 158 | TT_MAC_LANGID_IRISH 159 | 160 | TT_MAC_LANGID_WELSH 161 | 162 | TT_MAC_LANGID_PUNJABI 163 | 164 | TT_MAC_LANGID_GREEK 165 | 166 | TT_MAC_LANGID_INUKTITUT 167 | 168 | TT_MAC_LANGID_FRENCH 169 | 170 | TT_MAC_LANGID_GREEK_POLYTONIC 171 | 172 | TT_MAC_LANGID_AZERBAIJANI 173 | 174 | TT_MAC_LANGID_JAVANESE 175 | 176 | TT_MAC_LANGID_SWEDISH 177 | 178 | TT_MAC_LANGID_UIGHUR 179 | 180 | TT_MAC_LANGID_BENGALI 181 | 182 | TT_MAC_LANGID_RUANDA 183 | 184 | TT_MAC_LANGID_SINDHI 185 | 186 | TT_MAC_LANGID_TIBETAN 187 | 188 | TT_MAC_LANGID_ENGLISH 189 | 190 | TT_MAC_LANGID_SAAMISK 191 | 192 | TT_MAC_LANGID_INDONESIAN 193 | 194 | TT_MAC_LANGID_MANX_GAELIC 195 | 196 | TT_MAC_LANGID_BYELORUSSIAN 197 | 198 | TT_MAC_LANGID_BULGARIAN 199 | 200 | TT_MAC_LANGID_GEORGIAN 201 | 202 | TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 203 | 204 | TT_MAC_LANGID_ITALIAN 205 | 206 | TT_MAC_LANGID_SCOTTISH_GAELIC 207 | 208 | TT_MAC_LANGID_ARMENIAN 209 | 210 | TT_MAC_LANGID_GALLA 211 | 212 | TT_MAC_LANGID_MACEDONIAN 213 | 214 | TT_MAC_LANGID_IRISH_GAELIC 215 | 216 | TT_MAC_LANGID_KIRGHIZ 217 | 218 | TT_MAC_LANGID_TAMIL 219 | 220 | TT_MAC_LANGID_SPANISH 221 | 222 | TT_MAC_LANGID_BURMESE 223 | 224 | TT_MAC_LANGID_KANNADA 225 | 226 | TT_MAC_LANGID_GALICIAN 227 | 228 | TT_MAC_LANGID_FLEMISH 229 | 230 | TT_MAC_LANGID_TAJIKI 231 | 232 | TT_MAC_LANGID_ASSAMESE 233 | 234 | TT_MAC_LANGID_SINHALESE 235 | 236 | TT_MAC_LANGID_GREELANDIC 237 | 238 | TT_MAC_LANGID_AMHARIC 239 | 240 | TT_MAC_LANGID_KASHMIRI 241 | 242 | TT_MAC_LANGID_AYMARA 243 | 244 | TT_MAC_LANGID_GUJARATI 245 | 246 | TT_MAC_LANGID_RUSSIAN 247 | 248 | TT_MAC_LANGID_TURKMEN 249 | 250 | TT_MAC_LANGID_MALAYALAM 251 | """ 252 | TT_MAC_LANGIDS = { 253 | 'TT_MAC_LANGID_ENGLISH' : 0, 254 | 'TT_MAC_LANGID_FRENCH' : 1, 255 | 'TT_MAC_LANGID_GERMAN' : 2, 256 | 'TT_MAC_LANGID_ITALIAN' : 3, 257 | 'TT_MAC_LANGID_DUTCH' : 4, 258 | 'TT_MAC_LANGID_SWEDISH' : 5, 259 | 'TT_MAC_LANGID_SPANISH' : 6, 260 | 'TT_MAC_LANGID_DANISH' : 7, 261 | 'TT_MAC_LANGID_PORTUGUESE' : 8, 262 | 'TT_MAC_LANGID_NORWEGIAN' : 9, 263 | 'TT_MAC_LANGID_HEBREW' : 10, 264 | 'TT_MAC_LANGID_JAPANESE' : 11, 265 | 'TT_MAC_LANGID_ARABIC' : 12, 266 | 'TT_MAC_LANGID_FINNISH' : 13, 267 | 'TT_MAC_LANGID_GREEK' : 14, 268 | 'TT_MAC_LANGID_ICELANDIC' : 15, 269 | 'TT_MAC_LANGID_MALTESE' : 16, 270 | 'TT_MAC_LANGID_TURKISH' : 17, 271 | 'TT_MAC_LANGID_CROATIAN' : 18, 272 | 'TT_MAC_LANGID_CHINESE_TRADITIONAL' : 19, 273 | 'TT_MAC_LANGID_URDU' : 20, 274 | 'TT_MAC_LANGID_HINDI' : 21, 275 | 'TT_MAC_LANGID_THAI' : 22, 276 | 'TT_MAC_LANGID_KOREAN' : 23, 277 | 'TT_MAC_LANGID_LITHUANIAN' : 24, 278 | 'TT_MAC_LANGID_POLISH' : 25, 279 | 'TT_MAC_LANGID_HUNGARIAN' : 26, 280 | 'TT_MAC_LANGID_ESTONIAN' : 27, 281 | 'TT_MAC_LANGID_LETTISH' : 28, 282 | 'TT_MAC_LANGID_SAAMISK' : 29, 283 | 'TT_MAC_LANGID_FAEROESE' : 30, 284 | 'TT_MAC_LANGID_FARSI' : 31, 285 | 'TT_MAC_LANGID_RUSSIAN' : 32, 286 | 'TT_MAC_LANGID_CHINESE_SIMPLIFIED' : 33, 287 | 'TT_MAC_LANGID_FLEMISH' : 34, 288 | 'TT_MAC_LANGID_IRISH' : 35, 289 | 'TT_MAC_LANGID_ALBANIAN' : 36, 290 | 'TT_MAC_LANGID_ROMANIAN' : 37, 291 | 'TT_MAC_LANGID_CZECH' : 38, 292 | 'TT_MAC_LANGID_SLOVAK' : 39, 293 | 'TT_MAC_LANGID_SLOVENIAN' : 40, 294 | 'TT_MAC_LANGID_YIDDISH' : 41, 295 | 'TT_MAC_LANGID_SERBIAN' : 42, 296 | 'TT_MAC_LANGID_MACEDONIAN' : 43, 297 | 'TT_MAC_LANGID_BULGARIAN' : 44, 298 | 'TT_MAC_LANGID_UKRAINIAN' : 45, 299 | 'TT_MAC_LANGID_BYELORUSSIAN' : 46, 300 | 'TT_MAC_LANGID_UZBEK' : 47, 301 | 'TT_MAC_LANGID_KAZAKH' : 48, 302 | 'TT_MAC_LANGID_AZERBAIJANI' : 49, 303 | 'TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT': 49, 304 | 'TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT' : 50, 305 | 'TT_MAC_LANGID_ARMENIAN' : 51, 306 | 'TT_MAC_LANGID_GEORGIAN' : 52, 307 | 'TT_MAC_LANGID_MOLDAVIAN' : 53, 308 | 'TT_MAC_LANGID_KIRGHIZ' : 54, 309 | 'TT_MAC_LANGID_TAJIKI' : 55, 310 | 'TT_MAC_LANGID_TURKMEN' : 56, 311 | 'TT_MAC_LANGID_MONGOLIAN' : 57, 312 | 'TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT' : 57, 313 | 'TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT' : 58, 314 | 'TT_MAC_LANGID_PASHTO' : 59, 315 | 'TT_MAC_LANGID_KURDISH' : 60, 316 | 'TT_MAC_LANGID_KASHMIRI' : 61, 317 | 'TT_MAC_LANGID_SINDHI' : 62, 318 | 'TT_MAC_LANGID_TIBETAN' : 63, 319 | 'TT_MAC_LANGID_NEPALI' : 64, 320 | 'TT_MAC_LANGID_SANSKRIT' : 65, 321 | 'TT_MAC_LANGID_MARATHI' : 66, 322 | 'TT_MAC_LANGID_BENGALI' : 67, 323 | 'TT_MAC_LANGID_ASSAMESE' : 68, 324 | 'TT_MAC_LANGID_GUJARATI' : 69, 325 | 'TT_MAC_LANGID_PUNJABI' : 70, 326 | 'TT_MAC_LANGID_ORIYA' : 71, 327 | 'TT_MAC_LANGID_MALAYALAM' : 72, 328 | 'TT_MAC_LANGID_KANNADA' : 73, 329 | 'TT_MAC_LANGID_TAMIL' : 74, 330 | 'TT_MAC_LANGID_TELUGU' : 75, 331 | 'TT_MAC_LANGID_SINHALESE' : 76, 332 | 'TT_MAC_LANGID_BURMESE' : 77, 333 | 'TT_MAC_LANGID_KHMER' : 78, 334 | 'TT_MAC_LANGID_LAO' : 79, 335 | 'TT_MAC_LANGID_VIETNAMESE' : 80, 336 | 'TT_MAC_LANGID_INDONESIAN' : 81, 337 | 'TT_MAC_LANGID_TAGALOG' : 82, 338 | 'TT_MAC_LANGID_MALAY_ROMAN_SCRIPT' : 83, 339 | 'TT_MAC_LANGID_MALAY_ARABIC_SCRIPT' : 84, 340 | 'TT_MAC_LANGID_AMHARIC' : 85, 341 | 'TT_MAC_LANGID_TIGRINYA' : 86, 342 | 'TT_MAC_LANGID_GALLA' : 87, 343 | 'TT_MAC_LANGID_SOMALI' : 88, 344 | 'TT_MAC_LANGID_SWAHILI' : 89, 345 | 'TT_MAC_LANGID_RUANDA' : 90, 346 | 'TT_MAC_LANGID_RUNDI' : 91, 347 | 'TT_MAC_LANGID_CHEWA' : 92, 348 | 'TT_MAC_LANGID_MALAGASY' : 93, 349 | 'TT_MAC_LANGID_ESPERANTO' : 94, 350 | 'TT_MAC_LANGID_WELSH' : 128, 351 | 'TT_MAC_LANGID_BASQUE' : 129, 352 | 'TT_MAC_LANGID_CATALAN' : 130, 353 | 'TT_MAC_LANGID_LATIN' : 131, 354 | 'TT_MAC_LANGID_QUECHUA' : 132, 355 | 'TT_MAC_LANGID_GUARANI' : 133, 356 | 'TT_MAC_LANGID_AYMARA' : 134, 357 | 'TT_MAC_LANGID_TATAR' : 135, 358 | 'TT_MAC_LANGID_UIGHUR' : 136, 359 | 'TT_MAC_LANGID_DZONGKHA' : 137, 360 | 'TT_MAC_LANGID_JAVANESE' : 138, 361 | 'TT_MAC_LANGID_SUNDANESE' : 139, 362 | 'TT_MAC_LANGID_GALICIAN' : 140, 363 | 'TT_MAC_LANGID_AFRIKAANS' : 141, 364 | 'TT_MAC_LANGID_BRETON' : 142, 365 | 'TT_MAC_LANGID_INUKTITUT' : 143, 366 | 'TT_MAC_LANGID_SCOTTISH_GAELIC' : 144, 367 | 'TT_MAC_LANGID_MANX_GAELIC' : 145, 368 | 'TT_MAC_LANGID_IRISH_GAELIC' : 146, 369 | 'TT_MAC_LANGID_TONGAN' : 147, 370 | 'TT_MAC_LANGID_GREEK_POLYTONIC' : 148, 371 | 'TT_MAC_LANGID_GREELANDIC' : 149, 372 | 'TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT' : 150 } 373 | globals().update(TT_MAC_LANGIDS) 374 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_ms_ids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of valid values for the 'encoding_id' for TT_PLATFORM_MICROSOFT 10 | charmaps and name entries. 11 | 12 | 13 | TT_MS_ID_SYMBOL_CS 14 | 15 | Corresponds to Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL. 16 | 17 | 18 | TT_MS_ID_UNICODE_CS 19 | 20 | Corresponds to a Microsoft WGL4 charmap, matching Unicode. See 21 | FT_ENCODING_UNICODE. 22 | 23 | 24 | TT_MS_ID_SJIS 25 | 26 | Corresponds to SJIS Japanese encoding. See FT_ENCODING_SJIS. 27 | 28 | 29 | TT_MS_ID_GB2312 30 | 31 | Corresponds to Simplified Chinese as used in Mainland China. See 32 | FT_ENCODING_GB2312. 33 | 34 | 35 | TT_MS_ID_BIG_5 36 | 37 | Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. See 38 | FT_ENCODING_BIG5. 39 | 40 | 41 | TT_MS_ID_WANSUNG 42 | 43 | Corresponds to Korean Wansung encoding. See FT_ENCODING_WANSUNG. 44 | 45 | TT_MS_ID_JOHAB 46 | 47 | Corresponds to Johab encoding. See FT_ENCODING_JOHAB. 48 | 49 | 50 | TT_MS_ID_UCS_4 51 | 52 | Corresponds to UCS-4 or UTF-32 charmaps. This has been added to the OpenType 53 | specification version 1.4 (mid-2001.) 54 | """ 55 | 56 | TT_MS_IDS = { 57 | 'TT_MS_ID_SYMBOL_CS' : 0, 58 | 'TT_MS_ID_UNICODE_CS' : 1, 59 | 'TT_MS_ID_SJIS' : 2, 60 | 'TT_MS_ID_GB2312' : 3, 61 | 'TT_MS_ID_BIG_5' : 4, 62 | 'TT_MS_ID_WANSUNG' : 5, 63 | 'TT_MS_ID_JOHAB' : 6, 64 | 'TT_MS_ID_UCS_4' : 10 } 65 | globals().update(TT_MS_IDS) 66 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_ms_langids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | Possible values of the language identifier field in the name records of the 10 | TTF 'name' table if the 'platform' identifier code is TT_PLATFORM_MICROSOFT. 11 | 12 | TT_MS_LANGID_SANSKRIT_INDIA 13 | 14 | TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 15 | 16 | TT_MS_LANGID_ENGLISH_BELIZE 17 | 18 | TT_MS_LANGID_ARABIC_LEBANON 19 | 20 | TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 21 | 22 | TT_MS_LANGID_TURKISH_TURKEY 23 | 24 | TT_MS_LANGID_WELSH_WALES 25 | 26 | TT_MS_LANGID_GERMAN_AUSTRIA 27 | 28 | TT_MS_LANGID_DUTCH_BELGIUM 29 | 30 | TT_MS_LANGID_YI_CHINA 31 | 32 | TT_MS_LANGID_QUECHUA_ECUADOR 33 | 34 | TT_MS_LANGID_SPANISH_EL_SALVADOR 35 | 36 | TT_MS_LANGID_SWAHILI_KENYA 37 | 38 | TT_MS_LANGID_QUECHUA_BOLIVIA 39 | 40 | TT_MS_LANGID_SLOVENE_SLOVENIA 41 | 42 | TT_MS_LANGID_ORIYA_INDIA 43 | 44 | TT_MS_LANGID_FARSI_IRAN 45 | 46 | TT_MS_LANGID_ENGLISH_CANADA 47 | 48 | TT_MS_LANGID_NEPALI_NEPAL 49 | 50 | TT_MS_LANGID_DHIVEHI_MALDIVES 51 | 52 | TT_MS_LANGID_GERMAN_LIECHTENSTEI 53 | 54 | TT_MS_LANGID_TAMIL_INDIA 55 | 56 | TT_MS_LANGID_ARABIC_UAE 57 | 58 | TT_MS_LANGID_JAPANESE_JAPAN 59 | 60 | TT_MS_LANGID_TAMAZIGHT_MOROCCO 61 | 62 | TT_MS_LANGID_FRENCH_FRANCE 63 | 64 | TT_MS_LANGID_CHINESE_MACAU 65 | 66 | TT_MS_LANGID_VIETNAMESE_VIET_NAM 67 | 68 | TT_MS_LANGID_HEBREW_ISRAEL 69 | 70 | TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 71 | 72 | TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 73 | 74 | TT_MS_LANGID_SWEDISH_SWEDEN 75 | 76 | TT_MS_LANGID_FRENCH_REUNION 77 | 78 | TT_MS_LANGID_ARABIC_BAHRAIN 79 | 80 | TT_MS_LANGID_ENGLISH_INDIA 81 | 82 | TT_MS_LANGID_NEPALI_INDIA 83 | 84 | TT_MS_LANGID_THAI_THAILAND 85 | 86 | TT_MS_LANGID_ENGLISH_GENERAL 87 | 88 | TT_MS_LANGID_SAMI_LULE_NORWAY 89 | 90 | TT_MS_LANGID_ARABIC_OMAN 91 | 92 | TT_MS_LANGID_SPANISH_HONDURAS 93 | 94 | TT_MS_LANGID_ENGLISH_JAMAICA 95 | 96 | TT_MS_LANGID_ESTONIAN_ESTONIA 97 | 98 | TT_MS_LANGID_FRISIAN_NETHERLANDS 99 | 100 | TT_MS_LANGID_LATIN 101 | 102 | TT_MS_LANGID_ENGLISH_INDONESIA 103 | 104 | TT_MS_LANGID_ENGLISH_IRELAND 105 | 106 | TT_MS_LANGID_TIBETAN_CHINA 107 | 108 | TT_MS_LANGID_PUNJABI_INDIA 109 | 110 | TT_MS_LANGID_FRENCH_MALI 111 | 112 | TT_MS_LANGID_GERMAN_LUXEMBOURG 113 | 114 | TT_MS_LANGID_SUTU_SOUTH_AFRICA 115 | 116 | TT_MS_LANGID_FRENCH_CAMEROON 117 | 118 | TT_MS_LANGID_FRENCH_CONGO 119 | 120 | TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 121 | 122 | TT_MS_LANGID_MALAYALAM_INDIA 123 | 124 | TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 125 | 126 | TT_MS_LANGID_CHEROKEE_UNITED_STATES 127 | 128 | TT_MS_LANGID_SPANISH_GUATEMALA 129 | 130 | TT_MS_LANGID_CZECH_CZECH_REPUBLIC 131 | 132 | TT_MS_LANGID_MANIPURI_INDIA 133 | 134 | TT_MS_LANGID_ENGLISH_AUSTRALIA 135 | 136 | TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 137 | 138 | TT_MS_LANGID_ARABIC_LIBYA 139 | 140 | TT_MS_LANGID_FRENCH_WEST_INDIES 141 | 142 | TT_MS_LANGID_ENGLISH_TRINIDAD 143 | 144 | TT_MS_LANGID_ARABIC_QATAR 145 | 146 | TT_MS_LANGID_SPANISH_COLOMBIA 147 | 148 | TT_MS_LANGID_GUARANI_PARAGUAY 149 | 150 | TT_MS_LANGID_EDO_NIGERIA 151 | 152 | TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 153 | 154 | TT_MS_LANGID_ENGLISH_HONG_KONG 155 | 156 | TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 157 | 158 | TT_MS_LANGID_TATAR_TATARSTAN 159 | 160 | TT_MS_LANGID_PASHTO_AFGHANISTAN 161 | 162 | TT_MS_LANGID_KASHMIRI_PAKISTAN 163 | 164 | TT_MS_LANGID_GALICIAN_SPAIN 165 | 166 | TT_MS_LANGID_TAJIK_TAJIKISTAN 167 | 168 | TT_MS_LANGID_SAMI_INARI_FINLAND 169 | 170 | TT_MS_LANGID_KASHMIRI_SASIA 171 | 172 | TT_MS_LANGID_SPANISH_ARGENTINA 173 | 174 | TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 175 | 176 | TT_MS_LANGID_CROATIAN_CROATIA 177 | 178 | TT_MS_LANGID_GUJARATI_INDIA 179 | 180 | TT_MS_LANGID_TIBETAN_BHUTAN 181 | 182 | TT_MS_LANGID_TIGRIGNA_ETHIOPIA 183 | 184 | TT_MS_LANGID_FINNISH_FINLAND 185 | 186 | TT_MS_LANGID_ENGLISH_UNITED_STATES 187 | 188 | TT_MS_LANGID_ITALIAN_SWITZERLAND 189 | 190 | TT_MS_LANGID_ARABIC_EGYPT 191 | 192 | TT_MS_LANGID_SPANISH_LATIN_AMERICA 193 | 194 | TT_MS_LANGID_LITHUANIAN_LITHUANIA 195 | 196 | TT_MS_LANGID_ARABIC_ALGERIA 197 | 198 | TT_MS_LANGID_MALAY_MALAYSIA 199 | 200 | TT_MS_LANGID_ARABIC_GENERAL 201 | 202 | TT_MS_LANGID_CHINESE_PRC 203 | 204 | TT_MS_LANGID_BENGALI_BANGLADESH 205 | 206 | TT_MS_LANGID_SPANISH_PERU 207 | 208 | TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 209 | 210 | TT_MS_LANGID_DIVEHI_MALDIVES 211 | 212 | TT_MS_LANGID_LATVIAN_LATVIA 213 | 214 | TT_MS_LANGID_TURKMEN_TURKMENISTAN 215 | 216 | TT_MS_LANGID_XHOSA_SOUTH_AFRICA 217 | 218 | TT_MS_LANGID_KHMER_CAMBODIA 219 | 220 | TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 221 | 222 | TT_MS_LANGID_ARABIC_MOROCCO 223 | 224 | TT_MS_LANGID_FRENCH_SENEGAL 225 | 226 | TT_MS_LANGID_YORUBA_NIGERIA 227 | 228 | TT_MS_LANGID_CATALAN_SPAIN 229 | 230 | TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 231 | 232 | TT_MS_LANGID_ZULU_SOUTH_AFRICA 233 | 234 | TT_MS_LANGID_SPANISH_URUGUAY 235 | 236 | TT_MS_LANGID_SPANISH_ECUADOR 237 | 238 | TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 239 | 240 | TT_MS_LANGID_CHINESE_GENERAL 241 | 242 | TT_MS_LANGID_SPANISH_PARAGUAY 243 | 244 | TT_MS_LANGID_HINDI_INDIA 245 | 246 | TT_MS_LANGID_FRENCH_LUXEMBOURG 247 | 248 | TT_MS_LANGID_TSWANA_SOUTH_AFRICA 249 | 250 | TT_MS_LANGID_HUNGARIAN_HUNGARY 251 | 252 | TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 253 | 254 | TT_MS_LANGID_ENGLISH_SINGAPORE 255 | 256 | TT_MS_LANGID_MALTESE_MALTA 257 | 258 | TT_MS_LANGID_SAMI_NORTHERN_FINLAND 259 | 260 | TT_MS_LANGID_FRENCH_CANADA 261 | 262 | TT_MS_LANGID_SAMI_LULE_SWEDEN 263 | 264 | TT_MS_LANGID_KANURI_NIGERIA 265 | 266 | TT_MS_LANGID_IRISH_GAELIC_IRELAND 267 | 268 | TT_MS_LANGID_ARABIC_SAUDI_ARABIA 269 | 270 | TT_MS_LANGID_FRENCH_HAITI 271 | 272 | TT_MS_LANGID_SPANISH_PUERTO_RICO 273 | 274 | TT_MS_LANGID_BURMESE_MYANMAR 275 | 276 | TT_MS_LANGID_POLISH_POLAND 277 | 278 | TT_MS_LANGID_PORTUGUESE_PORTUGAL 279 | 280 | TT_MS_LANGID_ENGLISH_CARIBBEAN 281 | 282 | TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC 283 | 284 | TT_MS_LANGID_ICELANDIC_ICELAND 285 | 286 | TT_MS_LANGID_BENGALI_INDIA 287 | 288 | TT_MS_LANGID_HAUSA_NIGERIA 289 | 290 | TT_MS_LANGID_BASQUE_SPAIN 291 | 292 | TT_MS_LANGID_UIGHUR_CHINA 293 | 294 | TT_MS_LANGID_ENGLISH_MALAYSIA 295 | 296 | TT_MS_LANGID_FRENCH_MONACO 297 | 298 | TT_MS_LANGID_SPANISH_BOLIVIA 299 | 300 | TT_MS_LANGID_SORBIAN_GERMANY 301 | 302 | TT_MS_LANGID_SINDHI_INDIA 303 | 304 | TT_MS_LANGID_CHINESE_SINGAPORE 305 | 306 | TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 307 | 308 | TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 309 | 310 | TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 311 | 312 | TT_MS_LANGID_SAMI_SKOLT_FINLAND 313 | 314 | TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 315 | 316 | TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 317 | 318 | TT_MS_LANGID_ARABIC_JORDAN 319 | 320 | TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 321 | 322 | TT_MS_LANGID_SERBIAN_SERBIA_LATIN 323 | 324 | TT_MS_LANGID_RUSSIAN_RUSSIA 325 | 326 | TT_MS_LANGID_ROMANIAN_ROMANIA 327 | 328 | TT_MS_LANGID_FRENCH_NORTH_AFRICA 329 | 330 | TT_MS_LANGID_MONGOLIAN_MONGOLIA 331 | 332 | TT_MS_LANGID_TSONGA_SOUTH_AFRICA 333 | 334 | TT_MS_LANGID_SOMALI_SOMALIA 335 | 336 | TT_MS_LANGID_SAAMI_LAPONIA 337 | 338 | TT_MS_LANGID_SPANISH_COSTA_RICA 339 | 340 | TT_MS_LANGID_ARABIC_SYRIA 341 | 342 | TT_MS_LANGID_SPANISH_PANAMA 343 | 344 | TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 345 | 346 | TT_MS_LANGID_ASSAMESE_INDIA 347 | 348 | TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 349 | 350 | TT_MS_LANGID_DUTCH_NETHERLANDS 351 | 352 | TT_MS_LANGID_SINDHI_PAKISTAN 353 | 354 | TT_MS_LANGID_MACEDONIAN_MACEDONIA 355 | 356 | TT_MS_LANGID_KAZAK_KAZAKSTAN 357 | 358 | TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 359 | 360 | TT_MS_LANGID_BELARUSIAN_BELARUS 361 | 362 | TT_MS_LANGID_FRENCH_MOROCCO 363 | 364 | TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 365 | 366 | TT_MS_LANGID_ALBANIAN_ALBANIA 367 | 368 | TT_MS_LANGID_SINHALESE_SRI_LANKA 369 | 370 | TT_MS_LANGID_SPANISH_MEXICO 371 | 372 | TT_MS_LANGID_ENGLISH_ZIMBABWE 373 | 374 | TT_MS_LANGID_OROMO_ETHIOPIA 375 | 376 | TT_MS_LANGID_INDONESIAN_INDONESIA 377 | 378 | TT_MS_LANGID_SAMI_NORTHERN_NORWAY 379 | 380 | TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 381 | 382 | TT_MS_LANGID_SLOVAK_SLOVAKIA 383 | 384 | TT_MS_LANGID_KASHMIRI_INDIA 385 | 386 | TT_MS_LANGID_GERMAN_SWITZERLAND 387 | 388 | TT_MS_LANGID_URDU_INDIA 389 | 390 | TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 391 | 392 | TT_MS_LANGID_SYRIAC_SYRIA 393 | 394 | TT_MS_LANGID_SPANISH_CHILE 395 | 396 | TT_MS_LANGID_FILIPINO_PHILIPPINES 397 | 398 | TT_MS_LANGID_ARABIC_YEMEN 399 | 400 | TT_MS_LANGID_KONKANI_INDIA 401 | 402 | TT_MS_LANGID_AMHARIC_ETHIOPIA 403 | 404 | TT_MS_LANGID_ENGLISH_NEW_ZEALAND 405 | 406 | TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 407 | 408 | TT_MS_LANGID_ARABIC_TUNISIA 409 | 410 | TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA 411 | 412 | TT_MS_LANGID_QUECHUA_PERU 413 | 414 | TT_MS_LANGID_DANISH_DENMARK 415 | 416 | TT_MS_LANGID_ENGLISH_PHILIPPINES 417 | 418 | TT_MS_LANGID_SPANISH_NICARAGUA 419 | 420 | TT_MS_LANGID_INUKTITUT_CANADA 421 | 422 | TT_MS_LANGID_UKRAINIAN_UKRAINE 423 | 424 | TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 425 | 426 | TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 427 | 428 | TT_MS_LANGID_FRENCH_BELGIUM 429 | 430 | TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 431 | 432 | TT_MS_LANGID_HAWAIIAN_UNITED_STATES 433 | 434 | TT_MS_LANGID_ARABIC_IRAQ 435 | 436 | TT_MS_LANGID_KANNADA_INDIA 437 | 438 | TT_MS_LANGID_DZONGHKA_BHUTAN 439 | 440 | TT_MS_LANGID_CHINESE_TAIWAN 441 | 442 | TT_MS_LANGID_SPANISH_UNITED_STATES 443 | 444 | TT_MS_LANGID_ARMENIAN_ARMENIA 445 | 446 | TT_MS_LANGID_LAO_LAOS 447 | 448 | TT_MS_LANGID_TIGRIGNA_ERYTREA 449 | 450 | TT_MS_LANGID_MARATHI_INDIA 451 | 452 | TT_MS_LANGID_ARABIC_KUWAIT 453 | 454 | TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 455 | 456 | TT_MS_LANGID_PORTUGUESE_BRAZIL 457 | 458 | TT_MS_LANGID_TIGRIGNA_ERYTHREA 459 | 460 | TT_MS_LANGID_GREEK_GREECE 461 | 462 | TT_MS_LANGID_URDU_PAKISTAN 463 | 464 | TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN 465 | 466 | TT_MS_LANGID_YIDDISH_GERMANY 467 | 468 | TT_MS_LANGID_GERMAN_GERMANY 469 | 470 | TT_MS_LANGID_TELUGU_INDIA 471 | 472 | TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 473 | 474 | TT_MS_LANGID_KOREAN_JOHAB_KOREA 475 | 476 | TT_MS_LANGID_ITALIAN_ITALY 477 | 478 | TT_MS_LANGID_MAORI_NEW_ZEALAND 479 | 480 | TT_MS_LANGID_SPANISH_VENEZUELA 481 | 482 | TT_MS_LANGID_IGBO_NIGERIA 483 | 484 | TT_MS_LANGID_IBIBIO_NIGERIA 485 | 486 | TT_MS_LANGID_CHINESE_HONG_KONG 487 | 488 | TT_MS_LANGID_FRENCH_SWITZERLAND 489 | 490 | TT_MS_LANGID_BULGARIAN_BULGARIA 491 | 492 | TT_MS_LANGID_FULFULDE_NIGERIA 493 | 494 | TT_MS_LANGID_RUSSIAN_MOLDAVIA 495 | 496 | TT_MS_LANGID_VENDA_SOUTH_AFRICA 497 | 498 | TT_MS_LANGID_GEORGIAN_GEORGIA 499 | 500 | TT_MS_LANGID_SWEDISH_FINLAND 501 | """ 502 | 503 | TT_MS_LANGIDS = { 504 | 'TT_MS_LANGID_ARABIC_GENERAL' : 0x0001, 505 | 'TT_MS_LANGID_ARABIC_SAUDI_ARABIA' : 0x0401, 506 | 'TT_MS_LANGID_ARABIC_IRAQ' : 0x0801, 507 | 'TT_MS_LANGID_ARABIC_EGYPT' : 0x0c01, 508 | 'TT_MS_LANGID_ARABIC_LIBYA' : 0x1001, 509 | 'TT_MS_LANGID_ARABIC_ALGERIA' : 0x1401, 510 | 'TT_MS_LANGID_ARABIC_MOROCCO' : 0x1801, 511 | 'TT_MS_LANGID_ARABIC_TUNISIA' : 0x1c01, 512 | 'TT_MS_LANGID_ARABIC_OMAN' : 0x2001, 513 | 'TT_MS_LANGID_ARABIC_YEMEN' : 0x2401, 514 | 'TT_MS_LANGID_ARABIC_SYRIA' : 0x2801, 515 | 'TT_MS_LANGID_ARABIC_JORDAN' : 0x2c01, 516 | 'TT_MS_LANGID_ARABIC_LEBANON' : 0x3001, 517 | 'TT_MS_LANGID_ARABIC_KUWAIT' : 0x3401, 518 | 'TT_MS_LANGID_ARABIC_UAE' : 0x3801, 519 | 'TT_MS_LANGID_ARABIC_BAHRAIN' : 0x3c01, 520 | 'TT_MS_LANGID_ARABIC_QATAR' : 0x4001, 521 | 'TT_MS_LANGID_BULGARIAN_BULGARIA' : 0x0402, 522 | 'TT_MS_LANGID_CATALAN_SPAIN' : 0x0403, 523 | 'TT_MS_LANGID_CHINESE_GENERAL' : 0x0004, 524 | 'TT_MS_LANGID_CHINESE_TAIWAN' : 0x0404, 525 | 'TT_MS_LANGID_CHINESE_PRC' : 0x0804, 526 | 'TT_MS_LANGID_CHINESE_HONG_KONG' : 0x0c04, 527 | 'TT_MS_LANGID_CHINESE_SINGAPORE' : 0x1004, 528 | 'TT_MS_LANGID_CHINESE_MACAU' : 0x1404, 529 | 'TT_MS_LANGID_CZECH_CZECH_REPUBLIC' : 0x0405, 530 | 'TT_MS_LANGID_DANISH_DENMARK' : 0x0406, 531 | 'TT_MS_LANGID_GERMAN_GERMANY' : 0x0407, 532 | 'TT_MS_LANGID_GERMAN_SWITZERLAND' : 0x0807, 533 | 'TT_MS_LANGID_GERMAN_AUSTRIA' : 0x0c07, 534 | 'TT_MS_LANGID_GERMAN_LUXEMBOURG' : 0x1007, 535 | 'TT_MS_LANGID_GERMAN_LIECHTENSTEI' : 0x1407, 536 | 'TT_MS_LANGID_GREEK_GREECE' : 0x0408, 537 | 'TT_MS_LANGID_ENGLISH_GENERAL' : 0x0009, 538 | 'TT_MS_LANGID_ENGLISH_UNITED_STATES' : 0x0409, 539 | 'TT_MS_LANGID_ENGLISH_UNITED_KINGDOM' : 0x0809, 540 | 'TT_MS_LANGID_ENGLISH_AUSTRALIA' : 0x0c09, 541 | 'TT_MS_LANGID_ENGLISH_CANADA' : 0x1009, 542 | 'TT_MS_LANGID_ENGLISH_NEW_ZEALAND' : 0x1409, 543 | 'TT_MS_LANGID_ENGLISH_IRELAND' : 0x1809, 544 | 'TT_MS_LANGID_ENGLISH_SOUTH_AFRICA' : 0x1c09, 545 | 'TT_MS_LANGID_ENGLISH_JAMAICA' : 0x2009, 546 | 'TT_MS_LANGID_ENGLISH_CARIBBEAN' : 0x2409, 547 | 'TT_MS_LANGID_ENGLISH_BELIZE' : 0x2809, 548 | 'TT_MS_LANGID_ENGLISH_TRINIDAD' : 0x2c09, 549 | 'TT_MS_LANGID_ENGLISH_ZIMBABWE' : 0x3009, 550 | 'TT_MS_LANGID_ENGLISH_PHILIPPINES' : 0x3409, 551 | 'TT_MS_LANGID_ENGLISH_INDONESIA' : 0x3809, 552 | 'TT_MS_LANGID_ENGLISH_HONG_KONG' : 0x3c09, 553 | 'TT_MS_LANGID_ENGLISH_INDIA' : 0x4009, 554 | 'TT_MS_LANGID_ENGLISH_MALAYSIA' : 0x4409, 555 | 'TT_MS_LANGID_ENGLISH_SINGAPORE' : 0x4809, 556 | 'TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT' : 0x040a, 557 | 'TT_MS_LANGID_SPANISH_MEXICO' : 0x080a, 558 | 'TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT' : 0x0c0a, 559 | 'TT_MS_LANGID_SPANISH_GUATEMALA' : 0x100a, 560 | 'TT_MS_LANGID_SPANISH_COSTA_RICA' : 0x140a, 561 | 'TT_MS_LANGID_SPANISH_PANAMA' : 0x180a, 562 | 'TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC' : 0x1c0a, 563 | 'TT_MS_LANGID_SPANISH_VENEZUELA' : 0x200a, 564 | 'TT_MS_LANGID_SPANISH_COLOMBIA' : 0x240a, 565 | 'TT_MS_LANGID_SPANISH_PERU' : 0x280a, 566 | 'TT_MS_LANGID_SPANISH_ARGENTINA' : 0x2c0a, 567 | 'TT_MS_LANGID_SPANISH_ECUADOR' : 0x300a, 568 | 'TT_MS_LANGID_SPANISH_CHILE' : 0x340a, 569 | 'TT_MS_LANGID_SPANISH_URUGUAY' : 0x380a, 570 | 'TT_MS_LANGID_SPANISH_PARAGUAY' : 0x3c0a, 571 | 'TT_MS_LANGID_SPANISH_BOLIVIA' : 0x400a, 572 | 'TT_MS_LANGID_SPANISH_EL_SALVADOR' : 0x440a, 573 | 'TT_MS_LANGID_SPANISH_HONDURAS' : 0x480a, 574 | 'TT_MS_LANGID_SPANISH_NICARAGUA' : 0x4c0a, 575 | 'TT_MS_LANGID_SPANISH_PUERTO_RICO' : 0x500a, 576 | 'TT_MS_LANGID_SPANISH_UNITED_STATES' : 0x540a, 577 | 'TT_MS_LANGID_SPANISH_LATIN_AMERICA' : 0xE40a, 578 | 'TT_MS_LANGID_FINNISH_FINLAND' : 0x040b, 579 | 'TT_MS_LANGID_FRENCH_FRANCE' : 0x040c, 580 | 'TT_MS_LANGID_FRENCH_BELGIUM' : 0x080c, 581 | 'TT_MS_LANGID_FRENCH_CANADA' : 0x0c0c, 582 | 'TT_MS_LANGID_FRENCH_SWITZERLAND' : 0x100c, 583 | 'TT_MS_LANGID_FRENCH_LUXEMBOURG' : 0x140c, 584 | 'TT_MS_LANGID_FRENCH_MONACO' : 0x180c, 585 | 'TT_MS_LANGID_FRENCH_WEST_INDIES' : 0x1c0c, 586 | 'TT_MS_LANGID_FRENCH_REUNION' : 0x200c, 587 | 'TT_MS_LANGID_FRENCH_CONGO' : 0x240c, 588 | 'TT_MS_LANGID_FRENCH_SENEGAL' : 0x280c, 589 | 'TT_MS_LANGID_FRENCH_CAMEROON' : 0x2c0c, 590 | 'TT_MS_LANGID_FRENCH_COTE_D_IVOIRE' : 0x300c, 591 | 'TT_MS_LANGID_FRENCH_MALI' : 0x340c, 592 | 'TT_MS_LANGID_FRENCH_MOROCCO' : 0x380c, 593 | 'TT_MS_LANGID_FRENCH_HAITI' : 0x3c0c, 594 | 'TT_MS_LANGID_FRENCH_NORTH_AFRICA' : 0xE40c, 595 | 'TT_MS_LANGID_HEBREW_ISRAEL' : 0x040d, 596 | 'TT_MS_LANGID_HUNGARIAN_HUNGARY' : 0x040e, 597 | 'TT_MS_LANGID_ICELANDIC_ICELAND' : 0x040f, 598 | 'TT_MS_LANGID_ITALIAN_ITALY' : 0x0410, 599 | 'TT_MS_LANGID_ITALIAN_SWITZERLAND' : 0x0810, 600 | 'TT_MS_LANGID_JAPANESE_JAPAN' : 0x0411, 601 | 'TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA' : 0x0412, 602 | 'TT_MS_LANGID_KOREAN_JOHAB_KOREA' : 0x0812, 603 | 'TT_MS_LANGID_DUTCH_NETHERLANDS' : 0x0413, 604 | 'TT_MS_LANGID_DUTCH_BELGIUM' : 0x0813, 605 | 'TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL' : 0x0414, 606 | 'TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK' : 0x0814, 607 | 'TT_MS_LANGID_POLISH_POLAND' : 0x0415, 608 | 'TT_MS_LANGID_PORTUGUESE_BRAZIL' : 0x0416, 609 | 'TT_MS_LANGID_PORTUGUESE_PORTUGAL' : 0x0816, 610 | 'TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND' : 0x0417, 611 | 'TT_MS_LANGID_ROMANIAN_ROMANIA' : 0x0418, 612 | 'TT_MS_LANGID_MOLDAVIAN_MOLDAVIA' : 0x0818, 613 | 'TT_MS_LANGID_RUSSIAN_RUSSIA' : 0x0419, 614 | 'TT_MS_LANGID_RUSSIAN_MOLDAVIA' : 0x0819, 615 | 'TT_MS_LANGID_CROATIAN_CROATIA' : 0x041a, 616 | 'TT_MS_LANGID_SERBIAN_SERBIA_LATIN' : 0x081a, 617 | 'TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC' : 0x0c1a, 618 | 'TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA' : 0x101a, 619 | 'TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA' : 0x141a, 620 | 'TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN' : 0x181a, 621 | 'TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC' : 0x181a, 622 | 'TT_MS_LANGID_SLOVAK_SLOVAKIA' : 0x041b, 623 | 'TT_MS_LANGID_ALBANIAN_ALBANIA' : 0x041c, 624 | 'TT_MS_LANGID_SWEDISH_SWEDEN' : 0x041d, 625 | 'TT_MS_LANGID_SWEDISH_FINLAND' : 0x081d, 626 | 'TT_MS_LANGID_THAI_THAILAND' : 0x041e, 627 | 'TT_MS_LANGID_TURKISH_TURKEY' : 0x041f, 628 | 'TT_MS_LANGID_URDU_PAKISTAN' : 0x0420, 629 | 'TT_MS_LANGID_URDU_INDIA' : 0x0820, 630 | 'TT_MS_LANGID_INDONESIAN_INDONESIA' : 0x0421, 631 | 'TT_MS_LANGID_UKRAINIAN_UKRAINE' : 0x0422, 632 | 'TT_MS_LANGID_BELARUSIAN_BELARUS' : 0x0423, 633 | 'TT_MS_LANGID_SLOVENE_SLOVENIA' : 0x0424, 634 | 'TT_MS_LANGID_ESTONIAN_ESTONIA' : 0x0425, 635 | 'TT_MS_LANGID_LATVIAN_LATVIA' : 0x0426, 636 | 'TT_MS_LANGID_LITHUANIAN_LITHUANIA' : 0x0427, 637 | 'TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA' : 0x0827, 638 | 'TT_MS_LANGID_TAJIK_TAJIKISTAN' : 0x0428, 639 | 'TT_MS_LANGID_FARSI_IRAN' : 0x0429, 640 | 'TT_MS_LANGID_VIETNAMESE_VIET_NAM' : 0x042a, 641 | 'TT_MS_LANGID_ARMENIAN_ARMENIA' : 0x042b, 642 | 'TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN' : 0x042c, 643 | 'TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC' : 0x082c, 644 | 'TT_MS_LANGID_BASQUE_SPAIN' : 0x042d, 645 | 'TT_MS_LANGID_SORBIAN_GERMANY' : 0x042e, 646 | 'TT_MS_LANGID_MACEDONIAN_MACEDONIA' : 0x042f, 647 | 'TT_MS_LANGID_SUTU_SOUTH_AFRICA' : 0x0430, 648 | 'TT_MS_LANGID_TSONGA_SOUTH_AFRICA' : 0x0431, 649 | 'TT_MS_LANGID_TSWANA_SOUTH_AFRICA' : 0x0432, 650 | 'TT_MS_LANGID_VENDA_SOUTH_AFRICA' : 0x0433, 651 | 'TT_MS_LANGID_XHOSA_SOUTH_AFRICA' : 0x0434, 652 | 'TT_MS_LANGID_ZULU_SOUTH_AFRICA' : 0x0435, 653 | 'TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA' : 0x0436, 654 | 'TT_MS_LANGID_GEORGIAN_GEORGIA' : 0x0437, 655 | 'TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS' : 0x0438, 656 | 'TT_MS_LANGID_HINDI_INDIA' : 0x0439, 657 | 'TT_MS_LANGID_MALTESE_MALTA' : 0x043a, 658 | 'TT_MS_LANGID_SAMI_NORTHERN_NORWAY' : 0x043b, 659 | 'TT_MS_LANGID_SAMI_NORTHERN_SWEDEN' : 0x083b, 660 | 'TT_MS_LANGID_SAMI_NORTHERN_FINLAND' : 0x0C3b, 661 | 'TT_MS_LANGID_SAMI_LULE_NORWAY' : 0x103b, 662 | 'TT_MS_LANGID_SAMI_LULE_SWEDEN' : 0x143b, 663 | 'TT_MS_LANGID_SAMI_SOUTHERN_NORWAY' : 0x183b, 664 | 'TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN' : 0x1C3b, 665 | 'TT_MS_LANGID_SAMI_SKOLT_FINLAND' : 0x203b, 666 | 'TT_MS_LANGID_SAMI_INARI_FINLAND' : 0x243b, 667 | 'TT_MS_LANGID_SAAMI_LAPONIA' : 0x043b, 668 | 'TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM' : 0x083c, 669 | 'TT_MS_LANGID_IRISH_GAELIC_IRELAND' : 0x043c, 670 | 'TT_MS_LANGID_YIDDISH_GERMANY' : 0x043d, 671 | 'TT_MS_LANGID_MALAY_MALAYSIA' : 0x043e, 672 | 'TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM' : 0x083e, 673 | 'TT_MS_LANGID_KAZAK_KAZAKSTAN' : 0x043f, 674 | 'TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN' : 0x0440, 675 | 'TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC' : 0x0440, 676 | 'TT_MS_LANGID_SWAHILI_KENYA' : 0x0441, 677 | 'TT_MS_LANGID_TURKMEN_TURKMENISTAN' : 0x0442, 678 | 'TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN' : 0x0443, 679 | 'TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC' : 0x0843, 680 | 'TT_MS_LANGID_TATAR_TATARSTAN' : 0x0444, 681 | 'TT_MS_LANGID_BENGALI_INDIA' : 0x0445, 682 | 'TT_MS_LANGID_BENGALI_BANGLADESH' : 0x0845, 683 | 'TT_MS_LANGID_PUNJABI_INDIA' : 0x0446, 684 | 'TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN' : 0x0846, 685 | 'TT_MS_LANGID_GUJARATI_INDIA' : 0x0447, 686 | 'TT_MS_LANGID_ORIYA_INDIA' : 0x0448, 687 | 'TT_MS_LANGID_TAMIL_INDIA' : 0x0449, 688 | 'TT_MS_LANGID_TELUGU_INDIA' : 0x044a, 689 | 'TT_MS_LANGID_KANNADA_INDIA' : 0x044b, 690 | 'TT_MS_LANGID_MALAYALAM_INDIA' : 0x044c, 691 | 'TT_MS_LANGID_ASSAMESE_INDIA' : 0x044d, 692 | 'TT_MS_LANGID_MARATHI_INDIA' : 0x044e, 693 | 'TT_MS_LANGID_SANSKRIT_INDIA' : 0x044f, 694 | 'TT_MS_LANGID_MONGOLIAN_MONGOLIA' : 0x0450, 695 | 'TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN' : 0x0850, 696 | 'TT_MS_LANGID_TIBETAN_CHINA' : 0x0451, 697 | 'TT_MS_LANGID_DZONGHKA_BHUTAN' : 0x0851, 698 | 'TT_MS_LANGID_TIBETAN_BHUTAN' : 0x0851, 699 | 'TT_MS_LANGID_WELSH_WALES' : 0x0452, 700 | 'TT_MS_LANGID_KHMER_CAMBODIA' : 0x0453, 701 | 'TT_MS_LANGID_LAO_LAOS' : 0x0454, 702 | 'TT_MS_LANGID_BURMESE_MYANMAR' : 0x0455, 703 | 'TT_MS_LANGID_GALICIAN_SPAIN' : 0x0456, 704 | 'TT_MS_LANGID_KONKANI_INDIA' : 0x0457, 705 | 'TT_MS_LANGID_MANIPURI_INDIA' : 0x0458, 706 | 'TT_MS_LANGID_SINDHI_INDIA' : 0x0459, 707 | 'TT_MS_LANGID_SINDHI_PAKISTAN' : 0x0859, 708 | 'TT_MS_LANGID_SYRIAC_SYRIA' : 0x045a, 709 | 'TT_MS_LANGID_SINHALESE_SRI_LANKA' : 0x045b, 710 | 'TT_MS_LANGID_CHEROKEE_UNITED_STATES' : 0x045c, 711 | 'TT_MS_LANGID_INUKTITUT_CANADA' : 0x045d, 712 | 'TT_MS_LANGID_AMHARIC_ETHIOPIA' : 0x045e, 713 | 'TT_MS_LANGID_TAMAZIGHT_MOROCCO' : 0x045f, 714 | 'TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN' : 0x085f, 715 | 'TT_MS_LANGID_KASHMIRI_PAKISTAN' : 0x0460, 716 | 'TT_MS_LANGID_KASHMIRI_SASIA' : 0x0860, 717 | 'TT_MS_LANGID_KASHMIRI_INDIA' : 0x0860, 718 | 'TT_MS_LANGID_NEPALI_NEPAL' : 0x0461, 719 | 'TT_MS_LANGID_NEPALI_INDIA' : 0x0861, 720 | 'TT_MS_LANGID_FRISIAN_NETHERLANDS' : 0x0462, 721 | 'TT_MS_LANGID_PASHTO_AFGHANISTAN' : 0x0463, 722 | 'TT_MS_LANGID_FILIPINO_PHILIPPINES' : 0x0464, 723 | 'TT_MS_LANGID_DHIVEHI_MALDIVES' : 0x0465, 724 | 'TT_MS_LANGID_DIVEHI_MALDIVES' : 0x0465, 725 | 'TT_MS_LANGID_EDO_NIGERIA' : 0x0466, 726 | 'TT_MS_LANGID_FULFULDE_NIGERIA' : 0x0467, 727 | 'TT_MS_LANGID_HAUSA_NIGERIA' : 0x0468, 728 | 'TT_MS_LANGID_IBIBIO_NIGERIA' : 0x0469, 729 | 'TT_MS_LANGID_YORUBA_NIGERIA' : 0x046a, 730 | 'TT_MS_LANGID_QUECHUA_BOLIVIA' : 0x046b, 731 | 'TT_MS_LANGID_QUECHUA_ECUADOR' : 0x086b, 732 | 'TT_MS_LANGID_QUECHUA_PERU' : 0x0c6b, 733 | 'TT_MS_LANGID_SEPEDI_SOUTH_AFRICA' : 0x046c, 734 | 'TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA' : 0x046c, 735 | 'TT_MS_LANGID_IGBO_NIGERIA' : 0x0470, 736 | 'TT_MS_LANGID_KANURI_NIGERIA' : 0x0471, 737 | 'TT_MS_LANGID_OROMO_ETHIOPIA' : 0x0472, 738 | 'TT_MS_LANGID_TIGRIGNA_ETHIOPIA' : 0x0473, 739 | 'TT_MS_LANGID_TIGRIGNA_ERYTHREA' : 0x0873, 740 | 'TT_MS_LANGID_TIGRIGNA_ERYTREA' : 0x0873, 741 | 'TT_MS_LANGID_GUARANI_PARAGUAY' : 0x0474, 742 | 'TT_MS_LANGID_HAWAIIAN_UNITED_STATES' : 0x0475, 743 | 'TT_MS_LANGID_LATIN' : 0x0476, 744 | 'TT_MS_LANGID_SOMALI_SOMALIA' : 0x0477, 745 | 'TT_MS_LANGID_YI_CHINA' : 0x0478, 746 | 'TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES' : 0x0479, 747 | 'TT_MS_LANGID_UIGHUR_CHINA' : 0x0480, 748 | 'TT_MS_LANGID_MAORI_NEW_ZEALAND' : 0x0481 } 749 | globals().update(TT_MS_LANGIDS) 750 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_name_ids.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | 9 | """ 10 | Possible values of the 'name' identifier field in the name records of the TTF 11 | 'name' table. These values are platform independent. 12 | 13 | TT_NAME_ID_COPYRIGHT 14 | 15 | TT_NAME_ID_FONT_FAMILY 16 | 17 | TT_NAME_ID_FONT_SUBFAMILY 18 | 19 | TT_NAME_ID_UNIQUE_ID 20 | 21 | TT_NAME_ID_FULL_NAME 22 | 23 | TT_NAME_ID_VERSION_STRING 24 | 25 | TT_NAME_ID_PS_NAME 26 | 27 | TT_NAME_ID_TRADEMARK 28 | 29 | TT_NAME_ID_MANUFACTURER 30 | 31 | TT_NAME_ID_DESIGNER 32 | 33 | TT_NAME_ID_DESCRIPTION 34 | 35 | TT_NAME_ID_VENDOR_URL 36 | 37 | TT_NAME_ID_DESIGNER_URL 38 | 39 | TT_NAME_ID_LICENSE 40 | 41 | TT_NAME_ID_LICENSE_URL 42 | 43 | TT_NAME_ID_PREFERRED_FAMILY 44 | 45 | TT_NAME_ID_PREFERRED_SUBFAMILY 46 | 47 | TT_NAME_ID_MAC_FULL_NAME 48 | 49 | TT_NAME_ID_SAMPLE_TEXT 50 | 51 | TT_NAME_ID_CID_FINDFONT_NAME 52 | 53 | TT_NAME_ID_WWS_FAMILY 54 | 55 | TT_NAME_ID_WWS_SUBFAMILY 56 | """ 57 | 58 | 59 | TT_NAME_IDS = { 60 | 'TT_NAME_ID_COPYRIGHT' : 0, 61 | 'TT_NAME_ID_FONT_FAMILY' : 1, 62 | 'TT_NAME_ID_FONT_SUBFAMILY' : 2, 63 | 'TT_NAME_ID_UNIQUE_ID' : 3, 64 | 'TT_NAME_ID_FULL_NAME' : 4, 65 | 'TT_NAME_ID_VERSION_STRING' : 5, 66 | 'TT_NAME_ID_PS_NAME' : 6, 67 | 'TT_NAME_ID_TRADEMARK' : 7, 68 | 69 | # the following values are from the OpenType spec 70 | 'TT_NAME_ID_MANUFACTURER' : 8, 71 | 'TT_NAME_ID_DESIGNER' : 9, 72 | 'TT_NAME_ID_DESCRIPTION' : 10, 73 | 'TT_NAME_ID_VENDOR_URL' : 11, 74 | 'TT_NAME_ID_DESIGNER_URL' : 12, 75 | 'TT_NAME_ID_LICENSE' : 13, 76 | 'TT_NAME_ID_LICENSE_URL' : 14, 77 | # number 15 is reserved 78 | 'TT_NAME_ID_PREFERRED_FAMILY' : 16, 79 | 'TT_NAME_ID_PREFERRED_SUBFAMILY' : 17, 80 | 'TT_NAME_ID_MAC_FULL_NAME' : 18, 81 | 82 | # The following code is new as of 2000-01-21 83 | 'TT_NAME_ID_SAMPLE_TEXT' : 19, 84 | 85 | # This is new in OpenType 1.3 86 | 'TT_NAME_ID_CID_FINDFONT_NAME' : 20, 87 | 88 | # This is new in OpenType 1.5 89 | 'TT_NAME_ID_WWS_FAMILY' : 21, 90 | 'TT_NAME_ID_WWS_SUBFAMILY' : 22 } 91 | globals().update(TT_NAME_IDS) 92 | -------------------------------------------------------------------------------- /freetype/ft_enums/tt_platforms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | """ 9 | A list of valid values for the 'platform_id' identifier code in FT_CharMapRec 10 | and FT_SfntName structures. 11 | 12 | 13 | TT_PLATFORM_APPLE_UNICODE 14 | 15 | Used by Apple to indicate a Unicode character map and/or name entry. See 16 | TT_APPLE_ID_XXX for corresponding 'encoding_id' values. Note that name 17 | entries in this format are coded as big-endian UCS-2 character codes only. 18 | 19 | 20 | TT_PLATFORM_MACINTOSH 21 | 22 | Used by Apple to indicate a MacOS-specific charmap and/or name entry. See 23 | TT_MAC_ID_XXX for corresponding 'encoding_id' values. Note that most TrueType 24 | fonts contain an Apple roman charmap to be usable on MacOS systems (even if 25 | they contain a Microsoft charmap as well). 26 | 27 | 28 | TT_PLATFORM_ISO 29 | 30 | This value was used to specify ISO/IEC 10646 charmaps. It is however now 31 | deprecated. See TT_ISO_ID_XXX for a list of corresponding 'encoding_id' 32 | values. 33 | 34 | 35 | TT_PLATFORM_MICROSOFT 36 | 37 | Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for 38 | a list of corresponding 'encoding_id' values. Note that most fonts contain a 39 | Unicode charmap using (TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS). 40 | 41 | 42 | TT_PLATFORM_CUSTOM 43 | 44 | Used to indicate application-specific charmaps. 45 | 46 | 47 | TT_PLATFORM_ADOBE 48 | 49 | This value isn't part of any font format specification, but is used by 50 | FreeType to report Adobe-specific charmaps in an FT_CharMapRec structure. See 51 | TT_ADOBE_ID_XXX. 52 | """ 53 | 54 | TT_PLATFORMS = { 55 | 'TT_PLATFORM_APPLE_UNICODE' : 0, 56 | 'TT_PLATFORM_MACINTOSH' : 1, 57 | 'TT_PLATFORM_ISO' : 2, # deprecated 58 | 'TT_PLATFORM_MICROSOFT' : 3, 59 | 'TT_PLATFORM_CUSTOM' : 4, 60 | 'TT_PLATFORM_ADOBE' : 7} # artificial 61 | globals().update(TT_PLATFORMS) 62 | -------------------------------------------------------------------------------- /freetype/ft_errors.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # 4 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 5 | # Distributed under the terms of the new BSD license. 6 | # 7 | # ----------------------------------------------------------------------------- 8 | ''' 9 | Internal exception with freetype error message 10 | ''' 11 | class FT_Exception(Exception): 12 | def __init__(self, errcode, message=''): 13 | self.message = message 14 | self.errcode = errcode 15 | 16 | def __str__(self): 17 | return '%s: %s (%s)'%(self.__class__.__name__, self.message, 18 | self._errors.get(self.errcode, 'unknown error')) 19 | 20 | _errors = { 21 | 0x00: "no error" , 22 | 0x01: "cannot open resource" , 23 | 0x02: "unknown file format" , 24 | 0x03: "broken file" , 25 | 0x04: "invalid FreeType version" , 26 | 0x05: "module version is too low" , 27 | 0x06: "invalid argument" , 28 | 0x07: "unimplemented feature" , 29 | 0x08: "broken table" , 30 | 0x09: "broken offset within table" , 31 | 0x0A: "array allocation size too large" , 32 | 0x0B: "missing module" , 33 | 0x0C: "missing property" , 34 | 0x10: "invalid glyph index" , 35 | 0x11: "invalid character code" , 36 | 0x12: "unsupported glyph image format" , 37 | 0x13: "cannot render this glyph format" , 38 | 0x14: "invalid outline" , 39 | 0x15: "invalid composite glyph" , 40 | 0x16: "too many hints" , 41 | 0x17: "invalid pixel size" , 42 | 0x20: "invalid object handle" , 43 | 0x21: "invalid library handle" , 44 | 0x22: "invalid module handle" , 45 | 0x23: "invalid face handle" , 46 | 0x24: "invalid size handle" , 47 | 0x25: "invalid glyph slot handle" , 48 | 0x26: "invalid charmap handle" , 49 | 0x27: "invalid cache manager handle" , 50 | 0x28: "invalid stream handle" , 51 | 0x30: "too many modules" , 52 | 0x31: "too many extensions" , 53 | 0x40: "out of memory" , 54 | 0x41: "unlisted object" , 55 | 0x51: "cannot open stream" , 56 | 0x52: "invalid stream seek" , 57 | 0x53: "invalid stream skip" , 58 | 0x54: "invalid stream read" , 59 | 0x55: "invalid stream operation" , 60 | 0x56: "invalid frame operation" , 61 | 0x57: "nested frame access" , 62 | 0x58: "invalid frame read" , 63 | 0x60: "raster uninitialized" , 64 | 0x61: "raster corrupted" , 65 | 0x62: "raster overflow" , 66 | 0x63: "negative height while rastering" , 67 | 0x70: "too many registered caches" , 68 | 0x80: "invalid opcode" , 69 | 0x81: "too few arguments" , 70 | 0x82: "stack overflow" , 71 | 0x83: "code overflow" , 72 | 0x84: "bad argument" , 73 | 0x85: "division by zero" , 74 | 0x86: "invalid reference" , 75 | 0x87: "found debug opcode" , 76 | 0x88: "found ENDF opcode in execution stream" , 77 | 0x89: "nested DEFS" , 78 | 0x8A: "invalid code range" , 79 | 0x8B: "execution context too long" , 80 | 0x8C: "too many function definitions" , 81 | 0x8D: "too many instruction definitions" , 82 | 0x8E: "SFNT font table missing" , 83 | 0x8F: "horizontal header (hhea, table missing" , 84 | 0x90: "locations (loca, table missing" , 85 | 0x91: "name table missing" , 86 | 0x92: "character map (cmap, table missing" , 87 | 0x93: "horizontal metrics (hmtx, table missing" , 88 | 0x94: "PostScript (post, table missing" , 89 | 0x95: "invalid horizontal metrics" , 90 | 0x96: "invalid character map (cmap, format" , 91 | 0x97: "invalid ppem value" , 92 | 0x98: "invalid vertical metrics" , 93 | 0x99: "could not find context" , 94 | 0x9A: "invalid PostScript (post, table format" , 95 | 0x9B: "invalid PostScript (post, table" , 96 | 0x9C: "found FDEF or IDEF opcode in glyf bytecode" , 97 | 0x9D: "missing bitmap in strike" , 98 | 0xA0: "opcode syntax error" , 99 | 0xA1: "argument stack underflow" , 100 | 0xA2: "ignore" , 101 | 0xA3: "no Unicode glyph name found" , 102 | 0xA4: "glyph too big for hinting" , 103 | 0xB0: "`STARTFONT' field missing" , 104 | 0xB1: "`FONT' field missing" , 105 | 0xB2: "`SIZE' field missing" , 106 | 0xB3: "`FONTBOUNDINGBOX' field missing" , 107 | 0xB4: "`CHARS' field missing" , 108 | 0xB5: "`STARTCHAR' field missing" , 109 | 0xB6: "`ENCODING' field missing" , 110 | 0xB7: "`BBX' field missing" , 111 | 0xB8: "`BBX' too big" , 112 | 0xB9: "Font header corrupted or missing fields" , 113 | 0xBA: "Font glyphs corrupted or missing fields" , 114 | } 115 | -------------------------------------------------------------------------------- /freetype/ft_types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # ----------------------------------------------------------------------------- 4 | # 5 | # FreeType high-level python API - Copyright 2011 Nicolas P. Rougier 6 | # Distributed under the terms of the new BSD license. 7 | # 8 | # ----------------------------------------------------------------------------- 9 | ''' 10 | Freetype basic data types 11 | ------------------------- 12 | 13 | FT_Byte : A simple typedef for the unsigned char type. 14 | 15 | FT_Bytes : A typedef for constant memory areas. 16 | 17 | FT_Char : A simple typedef for the signed char type. 18 | 19 | FT_Int : A typedef for the int type. 20 | 21 | FT_UInt : A typedef for the unsigned int type. 22 | 23 | FT_Int16 : A typedef for a 16bit signed integer type. 24 | 25 | FT_UInt16 : A typedef for a 16bit unsigned integer type. 26 | 27 | FT_Int32 : A typedef for a 32bit signed integer type. 28 | 29 | FT_UInt32 : A typedef for a 32bit unsigned integer type. 30 | 31 | FT_Short : A typedef for signed short. 32 | 33 | FT_UShort : A typedef for unsigned short. 34 | 35 | FT_Long : A typedef for signed long. 36 | 37 | FT_ULong : A typedef for unsigned long. 38 | 39 | FT_Bool : A typedef of unsigned char, used for simple booleans. As usual, 40 | values 1 and 0 represent true and false, respectively. 41 | 42 | FT_Offset : This is equivalent to the ANSI C 'size_t' type, i.e., the largest 43 | unsigned integer type used to express a file size or position, or 44 | a memory block size. 45 | 46 | FT_PtrDist : This is equivalent to the ANSI C 'ptrdiff_t' type, i.e., the 47 | largest signed integer type used to express the distance between 48 | two pointers. 49 | 50 | FT_String : A simple typedef for the char type, usually used for strings. 51 | 52 | FT_Tag : A typedef for 32-bit tags (as used in the SFNT format). 53 | 54 | FT_Error : The FreeType error code type. A value of 0 is always interpreted as 55 | a successful operation. 56 | 57 | FT_Fixed : This type is used to store 16.16 fixed float values, like scaling 58 | values or matrix coefficients. 59 | 60 | FT_Pointer : A simple typedef for a typeless pointer. 61 | 62 | FT_Pos : The type FT_Pos is used to store vectorial coordinates. Depending on 63 | the context, these can represent distances in integer font units, or 64 | 16.16, or 26.6 fixed float pixel coordinates. 65 | 66 | FT_FWord : A signed 16-bit integer used to store a distance in original font 67 | units. 68 | 69 | FT_UFWord : An unsigned 16-bit integer used to store a distance in original 70 | font units. 71 | 72 | FT_F2Dot14 : A signed 2.14 fixed float type used for unit vectors. 73 | 74 | FT_F26Dot6 : A signed 26.6 fixed float type used for vectorial pixel 75 | coordinates. 76 | ''' 77 | from ctypes import * 78 | 79 | 80 | FT_Byte = c_ubyte # A simple typedef for the unsigned char type. 81 | 82 | FT_Bytes = c_char_p # A typedef for constant memory areas. 83 | 84 | FT_Char = c_char # A simple typedef for the signed char type. 85 | 86 | FT_Int = c_int # A typedef for the int type. 87 | 88 | FT_UInt = c_uint # A typedef for the unsigned int type. 89 | 90 | FT_Int16 = c_short # A typedef for a 16bit signed integer type. 91 | 92 | FT_UInt16 = c_ushort # A typedef for a 16bit unsigned integer type. 93 | 94 | FT_Int32 = c_int32 # A typedef for a 32bit signed integer type. 95 | 96 | FT_UInt32 = c_uint32 # A typedef for a 32bit unsigned integer type. 97 | 98 | FT_Short = c_short # A typedef for signed short. 99 | 100 | FT_UShort = c_ushort # A typedef for unsigned short. 101 | 102 | FT_Long = c_long # A typedef for signed long. 103 | 104 | FT_ULong = c_ulong # A typedef for unsigned long. 105 | 106 | FT_Bool = c_char # A typedef of unsigned char, used for simple booleans. As 107 | # usual, values 1 and 0 represent true and false, 108 | # respectively. 109 | 110 | FT_Offset = c_size_t # This is equivalent to the ANSI C 'size_t' type, i.e., 111 | # the largest unsigned integer type used to express a file 112 | # size or position, or a memory block size. 113 | 114 | FT_PtrDist = c_longlong # This is equivalent to the ANSI C 'ptrdiff_t' type, 115 | # i.e., the largest signed integer type used to express 116 | # the distance between two pointers. 117 | 118 | FT_String = c_char # A simple typedef for the char type, usually used for strings. 119 | 120 | FT_String_p= c_char_p 121 | 122 | FT_Tag = FT_UInt32 # A typedef for 32-bit tags (as used in the SFNT format). 123 | 124 | FT_Error = c_int # The FreeType error code type. A value of 0 is always 125 | # interpreted as a successful operation. 126 | 127 | FT_Fixed = c_long # This type is used to store 16.16 fixed float values, 128 | # like scaling values or matrix coefficients. 129 | 130 | FT_Angle = FT_Fixed # This type is used to model angle values in FreeType. Note that the 131 | # angle is a 16.16 fixed-point value expressed in degrees. 132 | 133 | FT_Pointer = c_void_p # A simple typedef for a typeless pointer. 134 | 135 | FT_Pos = c_long # The type FT_Pos is used to store vectorial 136 | # coordinates. Depending on the context, these can 137 | # represent distances in integer font units, or 16.16, or 138 | # 26.6 fixed float pixel coordinates. 139 | 140 | FT_FWord = c_short # A signed 16-bit integer used to store a distance in 141 | # original font units. 142 | 143 | FT_UFWord = c_ushort # An unsigned 16-bit integer used to store a distance in 144 | # original font units. 145 | 146 | FT_F2Dot14 = c_short # A signed 2.14 fixed float type used for unit vectors. 147 | 148 | FT_F26Dot6 = c_long # A signed 26.6 fixed float type used for vectorial pixel 149 | # coordinates. 150 | 151 | FT_Glyph_Format = c_int 152 | 153 | FT_Encoding = c_int 154 | 155 | 156 | # Describe a function used to destroy the 'client' data of any FreeType 157 | # object. See the description of the FT_Generic type for details of usage. 158 | FT_Generic_Finalizer = CFUNCTYPE(None, c_void_p) 159 | -------------------------------------------------------------------------------- /freetype/libfreetype.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostkeeper/SVGToolpathReader/deb2442b53be52d90f7cdf8bd7ffbeec1e187d0a/freetype/libfreetype.dll -------------------------------------------------------------------------------- /freetype/libfreetype.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ghostkeeper/SVGToolpathReader/deb2442b53be52d90f7cdf8bd7ffbeec1e187d0a/freetype/libfreetype.dylib -------------------------------------------------------------------------------- /freetype/raw.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ----------------------------------------------------------------------------- 3 | # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier 4 | # Distributed under the terms of the new BSD license. 5 | # ----------------------------------------------------------------------------- 6 | ''' 7 | Freetype raw API 8 | 9 | This is the raw ctypes freetype binding. 10 | ''' 11 | import os 12 | import platform 13 | from ctypes import * 14 | import ctypes.util 15 | 16 | import freetype 17 | from freetype.ft_types import * 18 | from freetype.ft_enums import * 19 | from freetype.ft_errors import * 20 | from freetype.ft_structs import * 21 | 22 | # First, look for a bundled FreeType shared object on the top-level of the 23 | # installed freetype-py module. 24 | system = platform.system() 25 | if system == 'Windows': 26 | library_name = 'libfreetype.dll' 27 | elif system == 'Darwin': 28 | library_name = 'libfreetype.dylib' 29 | else: 30 | library_name = 'libfreetype.so' 31 | 32 | filename = os.path.join(os.path.dirname(freetype.__file__), library_name) 33 | 34 | # If no bundled shared object is found, look for a system-wide installed one. 35 | if not os.path.exists(filename): 36 | # on windows all ctypes does when checking for the library 37 | # is to append .dll to the end and look for an exact match 38 | # within any entry in PATH. 39 | filename = ctypes.util.find_library('freetype') 40 | 41 | if filename is None: 42 | if platform.system() == 'Windows': 43 | # Check current working directory for dll as ctypes fails to do so 44 | filename = os.path.join(os.path.realpath('.'), "freetype.dll") 45 | else: 46 | filename = library_name 47 | 48 | try: 49 | _lib = ctypes.CDLL(filename) 50 | except (OSError, TypeError): 51 | _lib = None 52 | raise RuntimeError('Freetype library not found') 53 | 54 | FT_Init_FreeType = _lib.FT_Init_FreeType 55 | FT_Done_FreeType = _lib.FT_Done_FreeType 56 | FT_Library_Version = _lib.FT_Library_Version 57 | 58 | try: 59 | FT_Library_SetLcdFilter= _lib.FT_Library_SetLcdFilter 60 | except AttributeError: 61 | def FT_Library_SetLcdFilter (*args, **kwargs): 62 | return 0 63 | try: 64 | FT_Library_SetLcdFilterWeights = _lib.FT_Library_SetLcdFilterWeights 65 | except AttributeError: 66 | pass 67 | 68 | FT_New_Face = _lib.FT_New_Face 69 | FT_New_Memory_Face = _lib.FT_New_Memory_Face 70 | FT_Open_Face = _lib.FT_Open_Face 71 | FT_Attach_File = _lib.FT_Attach_File 72 | FT_Attach_Stream = _lib.FT_Attach_Stream 73 | 74 | try: 75 | FT_Reference_Face = _lib.FT_Reference_Face 76 | except AttributeError: 77 | pass 78 | 79 | FT_Done_Face = _lib.FT_Done_Face 80 | FT_Done_Glyph = _lib.FT_Done_Glyph 81 | FT_Select_Size = _lib.FT_Select_Size 82 | FT_Request_Size = _lib.FT_Request_Size 83 | FT_Set_Char_Size = _lib.FT_Set_Char_Size 84 | FT_Set_Pixel_Sizes = _lib.FT_Set_Pixel_Sizes 85 | FT_Load_Glyph = _lib.FT_Load_Glyph 86 | FT_Load_Char = _lib.FT_Load_Char 87 | FT_Set_Transform = _lib.FT_Set_Transform 88 | FT_Render_Glyph = _lib.FT_Render_Glyph 89 | FT_Get_Kerning = _lib.FT_Get_Kerning 90 | FT_Get_Track_Kerning = _lib.FT_Get_Track_Kerning 91 | FT_Get_Glyph_Name = _lib.FT_Get_Glyph_Name 92 | FT_Get_Glyph = _lib.FT_Get_Glyph 93 | 94 | FT_Glyph_Get_CBox = _lib.FT_Glyph_Get_CBox 95 | 96 | FT_Get_Postscript_Name = _lib.FT_Get_Postscript_Name 97 | FT_Get_Postscript_Name.restype = c_char_p 98 | FT_Select_Charmap = _lib.FT_Select_Charmap 99 | FT_Set_Charmap = _lib.FT_Set_Charmap 100 | FT_Get_Charmap_Index = _lib.FT_Get_Charmap_Index 101 | FT_Get_CMap_Language_ID= _lib.FT_Get_CMap_Language_ID 102 | try: 103 | #introduced between 2.2.x and 2.3.x 104 | FT_Get_CMap_Format = _lib.FT_Get_CMap_Format 105 | except AttributeError: 106 | pass 107 | FT_Get_Char_Index = _lib.FT_Get_Char_Index 108 | FT_Get_First_Char = _lib.FT_Get_First_Char 109 | FT_Get_Next_Char = _lib.FT_Get_Next_Char 110 | FT_Get_Name_Index = _lib.FT_Get_Name_Index 111 | FT_Get_SubGlyph_Info = _lib.FT_Get_SubGlyph_Info 112 | 113 | try: 114 | FT_Get_FSType_Flags = _lib.FT_Get_FSType_Flags 115 | FT_Get_FSType_Flags.restype = c_ushort 116 | except AttributeError: 117 | pass 118 | 119 | FT_Get_X11_Font_Format = _lib.FT_Get_X11_Font_Format 120 | FT_Get_X11_Font_Format.restype = c_char_p 121 | 122 | FT_Get_Sfnt_Name_Count = _lib.FT_Get_Sfnt_Name_Count 123 | FT_Get_Sfnt_Name = _lib.FT_Get_Sfnt_Name 124 | try: 125 | # introduced between 2.2.x and 2.3.x 126 | FT_Get_Advance = _lib.FT_Get_Advance 127 | except AttributeError: 128 | pass 129 | 130 | 131 | FT_Outline_GetInsideBorder = _lib.FT_Outline_GetInsideBorder 132 | FT_Outline_GetOutsideBorder = _lib.FT_Outline_GetOutsideBorder 133 | FT_Outline_Get_BBox = _lib.FT_Outline_Get_BBox 134 | FT_Outline_Get_CBox = _lib.FT_Outline_Get_CBox 135 | FT_Stroker_New = _lib.FT_Stroker_New 136 | FT_Stroker_Set = _lib.FT_Stroker_Set 137 | FT_Stroker_Rewind = _lib.FT_Stroker_Rewind 138 | FT_Stroker_ParseOutline = _lib.FT_Stroker_ParseOutline 139 | FT_Stroker_BeginSubPath = _lib.FT_Stroker_BeginSubPath 140 | FT_Stroker_EndSubPath = _lib.FT_Stroker_EndSubPath 141 | FT_Stroker_LineTo = _lib.FT_Stroker_LineTo 142 | FT_Stroker_ConicTo = _lib.FT_Stroker_ConicTo 143 | FT_Stroker_CubicTo = _lib.FT_Stroker_CubicTo 144 | FT_Stroker_GetBorderCounts = _lib.FT_Stroker_GetBorderCounts 145 | FT_Stroker_ExportBorder = _lib.FT_Stroker_ExportBorder 146 | FT_Stroker_GetCounts = _lib.FT_Stroker_GetCounts 147 | FT_Stroker_Export = _lib.FT_Stroker_Export 148 | FT_Stroker_Done = _lib.FT_Stroker_Done 149 | FT_Glyph_Stroke = _lib.FT_Glyph_Stroke 150 | FT_Glyph_StrokeBorder = _lib.FT_Glyph_StrokeBorder 151 | FT_Glyph_To_Bitmap = _lib.FT_Glyph_To_Bitmap 152 | 153 | 154 | # FT_Property_Get/FT_Property_Set requires FreeType 2.7.x+ 155 | try: 156 | FT_Property_Get = _lib.FT_Property_Get 157 | FT_Property_Set = _lib.FT_Property_Set 158 | except AttributeError: 159 | pass 160 | 161 | # These two are only found when TT debugger is enabled 162 | try: 163 | TT_New_Context = _lib.TT_New_Context 164 | TT_RunIns = _lib.TT_RunIns 165 | except AttributeError: 166 | pass 167 | 168 | 169 | # Wholesale import of 102 routines which can be reasonably expected 170 | # to be found in freetype 2.2.x onwards. Some of these might need 171 | # to be protected with try:/except AttributeError: in some freetype builds. 172 | 173 | FTC_CMapCache_Lookup = _lib.FTC_CMapCache_Lookup 174 | FTC_CMapCache_New = _lib.FTC_CMapCache_New 175 | FTC_ImageCache_Lookup = _lib.FTC_ImageCache_Lookup 176 | FTC_ImageCache_New = _lib.FTC_ImageCache_New 177 | FTC_Manager_Done = _lib.FTC_Manager_Done 178 | FTC_Manager_LookupFace = _lib.FTC_Manager_LookupFace 179 | FTC_Manager_LookupSize = _lib.FTC_Manager_LookupSize 180 | FTC_Manager_New = _lib.FTC_Manager_New 181 | FTC_Manager_RemoveFaceID = _lib.FTC_Manager_RemoveFaceID 182 | FTC_Manager_Reset = _lib.FTC_Manager_Reset 183 | FTC_Node_Unref = _lib.FTC_Node_Unref 184 | FTC_SBitCache_Lookup = _lib.FTC_SBitCache_Lookup 185 | FTC_SBitCache_New = _lib.FTC_SBitCache_New 186 | 187 | FT_Activate_Size = _lib.FT_Activate_Size 188 | FT_Add_Default_Modules = _lib.FT_Add_Default_Modules 189 | FT_Add_Module = _lib.FT_Add_Module 190 | FT_Angle_Diff = _lib.FT_Angle_Diff 191 | FT_Atan2 = _lib.FT_Atan2 192 | FT_Bitmap_Convert = _lib.FT_Bitmap_Convert 193 | FT_Bitmap_Copy = _lib.FT_Bitmap_Copy 194 | FT_Bitmap_Done = _lib.FT_Bitmap_Done 195 | FT_Bitmap_Embolden = _lib.FT_Bitmap_Embolden 196 | FT_Bitmap_New = _lib.FT_Bitmap_New 197 | FT_CeilFix = _lib.FT_CeilFix 198 | FT_ClassicKern_Free = _lib.FT_ClassicKern_Free 199 | FT_ClassicKern_Validate = _lib.FT_ClassicKern_Validate 200 | FT_Cos = _lib.FT_Cos 201 | FT_DivFix = _lib.FT_DivFix 202 | FT_Done_Library = _lib.FT_Done_Library 203 | FT_Done_Size = _lib.FT_Done_Size 204 | FT_FloorFix = _lib.FT_FloorFix 205 | try: 206 | # Not in default windows build of 2.8.x 207 | FT_Get_BDF_Charset_ID = _lib.FT_Get_BDF_Charset_ID 208 | FT_Get_BDF_Property = _lib.FT_Get_BDF_Property 209 | except AttributeError: 210 | pass 211 | FT_Get_MM_Var = _lib.FT_Get_MM_Var 212 | FT_Get_Module = _lib.FT_Get_Module 213 | FT_Get_Multi_Master = _lib.FT_Get_Multi_Master 214 | FT_Get_PFR_Advance = _lib.FT_Get_PFR_Advance 215 | FT_Get_PFR_Kerning = _lib.FT_Get_PFR_Kerning 216 | FT_Get_PFR_Metrics = _lib.FT_Get_PFR_Metrics 217 | FT_Get_PS_Font_Info = _lib.FT_Get_PS_Font_Info 218 | FT_Get_PS_Font_Private = _lib.FT_Get_PS_Font_Private 219 | FT_Get_Renderer = _lib.FT_Get_Renderer 220 | FT_Get_Sfnt_Table = _lib.FT_Get_Sfnt_Table 221 | FT_Get_TrueType_Engine_Type = _lib.FT_Get_TrueType_Engine_Type 222 | FT_Get_WinFNT_Header = _lib.FT_Get_WinFNT_Header 223 | FT_Glyph_Copy = _lib.FT_Glyph_Copy 224 | FT_GlyphSlot_Embolden = _lib.FT_GlyphSlot_Embolden 225 | FT_GlyphSlot_Oblique = _lib.FT_GlyphSlot_Oblique 226 | FT_GlyphSlot_Own_Bitmap = _lib.FT_GlyphSlot_Own_Bitmap 227 | FT_Glyph_Transform = _lib.FT_Glyph_Transform 228 | FT_Has_PS_Glyph_Names = _lib.FT_Has_PS_Glyph_Names 229 | FT_List_Add = _lib.FT_List_Add 230 | FT_List_Finalize = _lib.FT_List_Finalize 231 | FT_List_Find = _lib.FT_List_Find 232 | FT_List_Insert = _lib.FT_List_Insert 233 | FT_List_Iterate = _lib.FT_List_Iterate 234 | FT_List_Remove = _lib.FT_List_Remove 235 | FT_List_Up = _lib.FT_List_Up 236 | FT_Load_Sfnt_Table = _lib.FT_Load_Sfnt_Table 237 | FT_Matrix_Invert = _lib.FT_Matrix_Invert 238 | FT_Matrix_Multiply = _lib.FT_Matrix_Multiply 239 | FT_MulDiv = _lib.FT_MulDiv 240 | FT_MulFix = _lib.FT_MulFix 241 | FT_New_Library = _lib.FT_New_Library 242 | FT_New_Size = _lib.FT_New_Size 243 | FT_OpenType_Free = _lib.FT_OpenType_Free 244 | FT_OpenType_Validate = _lib.FT_OpenType_Validate 245 | FT_Outline_Check = _lib.FT_Outline_Check 246 | FT_Outline_Copy = _lib.FT_Outline_Copy 247 | FT_Outline_Decompose = _lib.FT_Outline_Decompose 248 | FT_Outline_Done = _lib.FT_Outline_Done 249 | FT_Outline_Embolden = _lib.FT_Outline_Embolden 250 | FT_Outline_Get_Bitmap = _lib.FT_Outline_Get_Bitmap 251 | FT_Outline_Get_Orientation = _lib.FT_Outline_Get_Orientation 252 | FT_Outline_New = _lib.FT_Outline_New 253 | FT_Outline_Render = _lib.FT_Outline_Render 254 | FT_Outline_Reverse = _lib.FT_Outline_Reverse 255 | FT_Outline_Transform = _lib.FT_Outline_Transform 256 | FT_Outline_Translate = _lib.FT_Outline_Translate 257 | FT_Remove_Module = _lib.FT_Remove_Module 258 | FT_RoundFix = _lib.FT_RoundFix 259 | FT_Set_Debug_Hook = _lib.FT_Set_Debug_Hook 260 | FT_Set_MM_Blend_Coordinates = _lib.FT_Set_MM_Blend_Coordinates 261 | FT_Set_MM_Design_Coordinates = _lib.FT_Set_MM_Design_Coordinates 262 | FT_Set_Renderer = _lib.FT_Set_Renderer 263 | FT_Set_Var_Blend_Coordinates = _lib.FT_Set_Var_Blend_Coordinates 264 | FT_Set_Var_Design_Coordinates = _lib.FT_Set_Var_Design_Coordinates 265 | FT_Sfnt_Table_Info = _lib.FT_Sfnt_Table_Info 266 | FT_Sin = _lib.FT_Sin 267 | FT_Stream_OpenGzip = _lib.FT_Stream_OpenGzip 268 | FT_Stream_OpenLZW = _lib.FT_Stream_OpenLZW 269 | FT_Tan = _lib.FT_Tan 270 | FT_TrueTypeGX_Free = _lib.FT_TrueTypeGX_Free 271 | FT_TrueTypeGX_Validate = _lib.FT_TrueTypeGX_Validate 272 | FT_Vector_From_Polar = _lib.FT_Vector_From_Polar 273 | FT_Vector_Length = _lib.FT_Vector_Length 274 | FT_Vector_Polarize = _lib.FT_Vector_Polarize 275 | FT_Vector_Rotate = _lib.FT_Vector_Rotate 276 | FT_Vector_Transform = _lib.FT_Vector_Transform 277 | FT_Vector_Unit = _lib.FT_Vector_Unit 278 | 279 | # Wholesale import ends 280 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /plugin.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "name": "${SVGTOOLPATHREADER_PLUGIN_NAME}", 3 | "author": "Ghostkeeper", 4 | "version": "${SVGTOOLPATHREADER_VERSION_MAJOR}.${SVGTOOLPATHREADER_VERSION_MINOR}.${SVGTOOLPATHREADER_VERSION_PATCH}", 5 | "description": "Reads SVG files as toolpaths, for debugging printer movements.", 6 | "api": 5, 7 | "supported_sdk_versions": ["5.0.0", "6.0.0", "7.0.0", "8.0.0"] 8 | } 9 | -------------------------------------------------------------------------------- /test/circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/ellipse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/path.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /test/polygon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/polyline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/rect.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/stroke-dasharray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ghostkeeper 5 | -------------------------------------------------------------------------------- /test/transform.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/use.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | --------------------------------------------------------------------------------