diff --git a/LICENSE/LICENSE_AMSFONTS b/LICENSE/LICENSE_AMSFONTS new file mode 100644 index 000000000000..3627bb9bb617 --- /dev/null +++ b/LICENSE/LICENSE_AMSFONTS @@ -0,0 +1,240 @@ +The cmr10.pfb file is a Type-1 version of one of Knuth's Computer Modern fonts. +It is included here as test data only, but the following license applies. + +Copyright (c) 1997, 2009, American Mathematical Society (http://www.ams.org). +All Rights Reserved. + +"cmb10" is a Reserved Font Name for this Font Software. +"cmbsy10" is a Reserved Font Name for this Font Software. +"cmbsy5" is a Reserved Font Name for this Font Software. +"cmbsy6" is a Reserved Font Name for this Font Software. +"cmbsy7" is a Reserved Font Name for this Font Software. +"cmbsy8" is a Reserved Font Name for this Font Software. +"cmbsy9" is a Reserved Font Name for this Font Software. +"cmbx10" is a Reserved Font Name for this Font Software. +"cmbx12" is a Reserved Font Name for this Font Software. +"cmbx5" is a Reserved Font Name for this Font Software. +"cmbx6" is a Reserved Font Name for this Font Software. +"cmbx7" is a Reserved Font Name for this Font Software. +"cmbx8" is a Reserved Font Name for this Font Software. +"cmbx9" is a Reserved Font Name for this Font Software. +"cmbxsl10" is a Reserved Font Name for this Font Software. +"cmbxti10" is a Reserved Font Name for this Font Software. +"cmcsc10" is a Reserved Font Name for this Font Software. +"cmcsc8" is a Reserved Font Name for this Font Software. +"cmcsc9" is a Reserved Font Name for this Font Software. +"cmdunh10" is a Reserved Font Name for this Font Software. +"cmex10" is a Reserved Font Name for this Font Software. +"cmex7" is a Reserved Font Name for this Font Software. +"cmex8" is a Reserved Font Name for this Font Software. +"cmex9" is a Reserved Font Name for this Font Software. +"cmff10" is a Reserved Font Name for this Font Software. +"cmfi10" is a Reserved Font Name for this Font Software. +"cmfib8" is a Reserved Font Name for this Font Software. +"cminch" is a Reserved Font Name for this Font Software. +"cmitt10" is a Reserved Font Name for this Font Software. +"cmmi10" is a Reserved Font Name for this Font Software. +"cmmi12" is a Reserved Font Name for this Font Software. +"cmmi5" is a Reserved Font Name for this Font Software. +"cmmi6" is a Reserved Font Name for this Font Software. +"cmmi7" is a Reserved Font Name for this Font Software. +"cmmi8" is a Reserved Font Name for this Font Software. +"cmmi9" is a Reserved Font Name for this Font Software. +"cmmib10" is a Reserved Font Name for this Font Software. +"cmmib5" is a Reserved Font Name for this Font Software. +"cmmib6" is a Reserved Font Name for this Font Software. +"cmmib7" is a Reserved Font Name for this Font Software. +"cmmib8" is a Reserved Font Name for this Font Software. +"cmmib9" is a Reserved Font Name for this Font Software. +"cmr10" is a Reserved Font Name for this Font Software. +"cmr12" is a Reserved Font Name for this Font Software. +"cmr17" is a Reserved Font Name for this Font Software. +"cmr5" is a Reserved Font Name for this Font Software. +"cmr6" is a Reserved Font Name for this Font Software. +"cmr7" is a Reserved Font Name for this Font Software. +"cmr8" is a Reserved Font Name for this Font Software. +"cmr9" is a Reserved Font Name for this Font Software. +"cmsl10" is a Reserved Font Name for this Font Software. +"cmsl12" is a Reserved Font Name for this Font Software. +"cmsl8" is a Reserved Font Name for this Font Software. +"cmsl9" is a Reserved Font Name for this Font Software. +"cmsltt10" is a Reserved Font Name for this Font Software. +"cmss10" is a Reserved Font Name for this Font Software. +"cmss12" is a Reserved Font Name for this Font Software. +"cmss17" is a Reserved Font Name for this Font Software. +"cmss8" is a Reserved Font Name for this Font Software. +"cmss9" is a Reserved Font Name for this Font Software. +"cmssbx10" is a Reserved Font Name for this Font Software. +"cmssdc10" is a Reserved Font Name for this Font Software. +"cmssi10" is a Reserved Font Name for this Font Software. +"cmssi12" is a Reserved Font Name for this Font Software. +"cmssi17" is a Reserved Font Name for this Font Software. +"cmssi8" is a Reserved Font Name for this Font Software. +"cmssi9" is a Reserved Font Name for this Font Software. +"cmssq8" is a Reserved Font Name for this Font Software. +"cmssqi8" is a Reserved Font Name for this Font Software. +"cmsy10" is a Reserved Font Name for this Font Software. +"cmsy5" is a Reserved Font Name for this Font Software. +"cmsy6" is a Reserved Font Name for this Font Software. +"cmsy7" is a Reserved Font Name for this Font Software. +"cmsy8" is a Reserved Font Name for this Font Software. +"cmsy9" is a Reserved Font Name for this Font Software. +"cmtcsc10" is a Reserved Font Name for this Font Software. +"cmtex10" is a Reserved Font Name for this Font Software. +"cmtex8" is a Reserved Font Name for this Font Software. +"cmtex9" is a Reserved Font Name for this Font Software. +"cmti10" is a Reserved Font Name for this Font Software. +"cmti12" is a Reserved Font Name for this Font Software. +"cmti7" is a Reserved Font Name for this Font Software. +"cmti8" is a Reserved Font Name for this Font Software. +"cmti9" is a Reserved Font Name for this Font Software. +"cmtt10" is a Reserved Font Name for this Font Software. +"cmtt12" is a Reserved Font Name for this Font Software. +"cmtt8" is a Reserved Font Name for this Font Software. +"cmtt9" is a Reserved Font Name for this Font Software. +"cmu10" is a Reserved Font Name for this Font Software. +"cmvtt10" is a Reserved Font Name for this Font Software. +"euex10" is a Reserved Font Name for this Font Software. +"euex7" is a Reserved Font Name for this Font Software. +"euex8" is a Reserved Font Name for this Font Software. +"euex9" is a Reserved Font Name for this Font Software. +"eufb10" is a Reserved Font Name for this Font Software. +"eufb5" is a Reserved Font Name for this Font Software. +"eufb7" is a Reserved Font Name for this Font Software. +"eufm10" is a Reserved Font Name for this Font Software. +"eufm5" is a Reserved Font Name for this Font Software. +"eufm7" is a Reserved Font Name for this Font Software. +"eurb10" is a Reserved Font Name for this Font Software. +"eurb5" is a Reserved Font Name for this Font Software. +"eurb7" is a Reserved Font Name for this Font Software. +"eurm10" is a Reserved Font Name for this Font Software. +"eurm5" is a Reserved Font Name for this Font Software. +"eurm7" is a Reserved Font Name for this Font Software. +"eusb10" is a Reserved Font Name for this Font Software. +"eusb5" is a Reserved Font Name for this Font Software. +"eusb7" is a Reserved Font Name for this Font Software. +"eusm10" is a Reserved Font Name for this Font Software. +"eusm5" is a Reserved Font Name for this Font Software. +"eusm7" is a Reserved Font Name for this Font Software. +"lasy10" is a Reserved Font Name for this Font Software. +"lasy5" is a Reserved Font Name for this Font Software. +"lasy6" is a Reserved Font Name for this Font Software. +"lasy7" is a Reserved Font Name for this Font Software. +"lasy8" is a Reserved Font Name for this Font Software. +"lasy9" is a Reserved Font Name for this Font Software. +"lasyb10" is a Reserved Font Name for this Font Software. +"lcircle1" is a Reserved Font Name for this Font Software. +"lcirclew" is a Reserved Font Name for this Font Software. +"lcmss8" is a Reserved Font Name for this Font Software. +"lcmssb8" is a Reserved Font Name for this Font Software. +"lcmssi8" is a Reserved Font Name for this Font Software. +"line10" is a Reserved Font Name for this Font Software. +"linew10" is a Reserved Font Name for this Font Software. +"msam10" is a Reserved Font Name for this Font Software. +"msam5" is a Reserved Font Name for this Font Software. +"msam6" is a Reserved Font Name for this Font Software. +"msam7" is a Reserved Font Name for this Font Software. +"msam8" is a Reserved Font Name for this Font Software. +"msam9" is a Reserved Font Name for this Font Software. +"msbm10" is a Reserved Font Name for this Font Software. +"msbm5" is a Reserved Font Name for this Font Software. +"msbm6" is a Reserved Font Name for this Font Software. +"msbm7" is a Reserved Font Name for this Font Software. +"msbm8" is a Reserved Font Name for this Font Software. +"msbm9" is a Reserved Font Name for this Font Software. +"wncyb10" is a Reserved Font Name for this Font Software. +"wncyi10" is a Reserved Font Name for this Font Software. +"wncyr10" is a Reserved Font Name for this Font Software. +"wncysc10" is a Reserved Font Name for this Font Software. +"wncyss10" is a Reserved Font Name for this Font Software. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/lib/matplotlib/tests/cmr10.pfb b/lib/matplotlib/tests/cmr10.pfb new file mode 100644 index 000000000000..fa8c833d374e Binary files /dev/null and b/lib/matplotlib/tests/cmr10.pfb differ diff --git a/lib/matplotlib/tests/test_type1font.py b/lib/matplotlib/tests/test_type1font.py new file mode 100644 index 000000000000..751571f93a8e --- /dev/null +++ b/lib/matplotlib/tests/test_type1font.py @@ -0,0 +1,55 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from nose.tools import assert_equal, assert_in +import matplotlib.type1font as t1f +import os.path +import difflib + + +def test_Type1Font(): + filename = os.path.join(os.path.dirname(__file__), 'cmr10.pfb') + font = t1f.Type1Font(filename) + slanted = font.transform({'slant': 1}) + condensed = font.transform({'extend': 0.5}) + rawdata = open(filename, 'rb').read() + assert_equal(font.parts[0], rawdata[0x0006:0x10c5]) + assert_equal(font.parts[1], rawdata[0x10cb:0x897f]) + assert_equal(font.parts[2], rawdata[0x8985:0x8ba6]) + assert_equal(font.parts[1:], slanted.parts[1:]) + assert_equal(font.parts[1:], condensed.parts[1:]) + + differ = difflib.Differ() + diff = list(differ.compare( + font.parts[0].decode('latin-1').splitlines(), + slanted.parts[0].decode('latin-1').splitlines())) + for line in ( + # Removes UniqueID + '- FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup', + '+ FontDirectory/CMR10 known{/CMR10 findfont dup', + # Changes the font name + '- /FontName /CMR10 def', + '+ /FontName /CMR10_Slant_1000 def', + # Alters FontMatrix + '- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def', + '+ /FontMatrix [0.001 0.0 0.001 0.001 0.0 0.0]readonly def', + # Alters ItalicAngle + '- /ItalicAngle 0 def', + '+ /ItalicAngle -45.0 def'): + assert_in(line, diff, 'diff to slanted font must contain %s' % line) + + diff = list(differ.compare(font.parts[0].decode('latin-1').splitlines(), + condensed.parts[0].decode('latin-1').splitlines())) + for line in ( + # Removes UniqueID + '- FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup', + '+ FontDirectory/CMR10 known{/CMR10 findfont dup', + # Changes the font name + '- /FontName /CMR10 def', + '+ /FontName /CMR10_Extend_500 def', + # Alters FontMatrix + '- /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def', + '+ /FontMatrix [0.0005 0.0 0.0 0.001 0.0 0.0]readonly def'): + assert_in(line, diff, 'diff to condensed font must contain %s' % line) diff --git a/lib/matplotlib/type1font.py b/lib/matplotlib/type1font.py index ba457e840959..afd541a5fa2f 100644 --- a/lib/matplotlib/type1font.py +++ b/lib/matplotlib/type1font.py @@ -29,6 +29,7 @@ from six.moves import filter from six import unichr +import binascii import io import itertools import numpy as np @@ -92,8 +93,7 @@ def _read(self, file): if type == 1: # ASCII text: include verbatim data += segment elif type == 2: # binary data: encode in hexadecimal - data += b''.join([('%02x' % ord(char)).encode('ascii') - for char in segment]) + data += binascii.hexlify(segment) elif type == 3: # end of file break else: @@ -123,9 +123,8 @@ def _split(self, data): # zeros backward idx = data.rindex(b'cleartomark') - 1 zeros = 512 - while zeros and ord(data[idx]) in ( - ord(b'0'[0]), ord(b'\n'[0]), ord(b'\r'[0])): - if ord(data[idx]) == ord(b'0'[0]): + while zeros and data[idx] in b'0' or data[idx] in b'\r\n': + if data[idx] in b'0': zeros -= 1 idx -= 1 if zeros: @@ -136,17 +135,16 @@ def _split(self, data): # but if we read a pfa file, this part is already in hex, and # I am not quite sure if even the pfb format guarantees that # it will be in binary). - binary = b''.join([unichr(int(data[i:i + 2], 16)).encode('latin-1') - for i in range(len1, idx, 2)]) + binary = binascii.unhexlify(data[len1:idx+1]) - return data[:len1], binary, data[idx:] + return data[:len1], binary, data[idx+1:] _whitespace_re = re.compile(br'[\0\t\r\014\n ]+') _token_re = re.compile(br'/{0,2}[^]\0\t\r\v\n ()<>{}/%[]+') _comment_re = re.compile(br'%[^\r\n\v]*') _instring_re = re.compile(br'[()\\]') - # token types + # token types, compared via object identity (poor man's enum) _whitespace = object() _name = object() _string = object() @@ -166,7 +164,7 @@ def _tokens(cls, text): if match: yield (cls._whitespace, match.group()) pos += match.end() - elif text[pos] == '(': + elif text[pos] == b'(': start = pos pos += 1 depth = 1 @@ -175,19 +173,19 @@ def _tokens(cls, text): if match is None: return pos += match.end() - if match.group() == '(': + if match.group() == b'(': depth += 1 - elif match.group() == ')': + elif match.group() == b')': depth -= 1 else: # a backslash - skip the next character pos += 1 yield (cls._string, text[start:pos]) - elif text[pos:pos + 2] in ('<<', '>>'): + elif text[pos:pos + 2] in (b'<<', b'>>'): yield (cls._delimiter, text[pos:pos + 2]) pos += 2 - elif text[pos] == '<': + elif text[pos] == b'<': start = pos - pos += text[pos:].index('>') + pos += text[pos:].index(b'>') yield (cls._string, text[start:pos]) else: match = cls._token_re.match(text[pos:]) @@ -256,16 +254,16 @@ def _transformer(cls, tokens, slant, extend): def fontname(name): result = name if slant: - result += '_Slant_' + str(int(1000 * slant)) + result += b'_Slant_' + str(int(1000 * slant)).encode('latin-1') if extend != 1.0: - result += '_Extend_' + str(int(1000 * extend)) + result += b'_Extend_' + str(int(1000 * extend)).encode('latin-1') return result def italicangle(angle): - return str(float(angle) - np.arctan(slant) / np.pi * 180) + return str(float(angle) - np.arctan(slant) / np.pi * 180).encode('latin-1') def fontmatrix(array): - array = array.lstrip('[').rstrip(']').strip().split() + array = array.lstrip(b'[').rstrip(b']').strip().split() array = [float(x) for x in array] oldmatrix = np.eye(3, 3) oldmatrix[0:3, 0] = array[::2] @@ -276,40 +274,41 @@ def fontmatrix(array): newmatrix = np.dot(modifier, oldmatrix) array[::2] = newmatrix[0:3, 0] array[1::2] = newmatrix[0:3, 1] - return '[' + ' '.join(str(x) for x in array) + ']' + as_string = u'[' + u' '.join(str(x) for x in array) + u']' + return as_string.encode('latin-1') def replace(fun): def replacer(tokens): token, value = next(tokens) # name, e.g., /FontMatrix - yield value + yield bytes(value) token, value = next(tokens) # possible whitespace - while token == 'whitespace': - yield value + while token is cls._whitespace: + yield bytes(value) token, value = next(tokens) - if value != '[': # name/number/etc. - yield fun(value) - else: # array, e.g., [1 2 3] - array = [] - while value != ']': - array += value + if value != b'[': # name/number/etc. + yield bytes(fun(value)) + else: # array, e.g., [1 2 3] + result = b'' + while value != b']': + result += value token, value = next(tokens) - array += value - yield fun(''.join(array)) + result += value + yield fun(result) return replacer def suppress(tokens): - for x in itertools.takewhile(lambda x: x[1] != 'def', tokens): + for x in itertools.takewhile(lambda x: x[1] != b'def', tokens): pass - yield '' + yield b'' - table = {'/FontName': replace(fontname), - '/ItalicAngle': replace(italicangle), - '/FontMatrix': replace(fontmatrix), - '/UniqueID': suppress} + table = {b'/FontName': replace(fontname), + b'/ItalicAngle': replace(italicangle), + b'/FontMatrix': replace(fontmatrix), + b'/UniqueID': suppress} while True: token, value = next(tokens) - if token == 'name' and value in table: + if token is cls._name and value in table: for value in table[value](itertools.chain([(token, value)], tokens)): yield value @@ -325,18 +324,10 @@ def transform(self, effects): multiplier by which the font is to be extended (so values less than 1.0 condense). Returns a new :class:`Type1Font` object. """ - buffer = io.BytesIO() - try: + with io.BytesIO() as buffer: tokenizer = self._tokens(self.parts[0]) - for value in self._transformer(tokenizer, - slant=effects.get('slant', 0.0), - extend=effects.get('extend', 1.0)): - if six.PY3 and isinstance(value, int): - value = chr(value) - value = value.encode('latin-1') - buffer.write(value) - result = buffer.getvalue() - finally: - buffer.close() - - return Type1Font((result, self.parts[1], self.parts[2])) + transformed = self._transformer(tokenizer, + slant=effects.get('slant', 0.0), + extend=effects.get('extend', 1.0)) + list(map(buffer.write, transformed)) + return Type1Font((buffer.getvalue(), self.parts[1], self.parts[2]))