type1.py :  » GUI » Sketch » skencil-0.6.17 » Sketch » Lib » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » Sketch 
Sketch » skencil 0.6.17 » Sketch » Lib » type1.py
# Sketch - A Python-based interactive drawing program
# Copyright (C) 1998, 1999, 2003 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#
#       Extract character outlines from Type1 font files...
#

import sys
from cStringIO import StringIO
from types import StringType

from string import atoi,split,find,strip

import streamfilter

from Sketch import Point
from Sketch._type1 import decode,hexdecode
from Sketch.pstokenize import PSTokenizer,OPERATOR,NAME,INT,END

def read_type1_file(filename):
    data = StringIO()
    file = open(filename, 'rb')
    head = file.read(6)
    if head[:2] == '%!':
        line = file.readline()
        while line:
            line = file.readline()
            pos = find(line, 'eexec')
            if pos >= 0:
                data.write(line[:pos + 5] + '\n')
                line = line[pos + 5:]
                break
            data.write(line)

        try:
            buf = line + file.read(200)
            buf, extra = hexdecode(buf)
            buf, r = decode(buf, 55665)
            data.write(buf[4:])
            buf = extra + file.read(200)
            while buf:
                buf, extra = hexdecode(buf)
                buf, r = decode(buf, r)
                data.write(buf)
                buf = extra + file.read(200)
        except:
            pass
    else:
        while 1:
            if ord(head[0]) != 128:
                raise TypeError, 'not a pfb file'
            data_type = ord(head[1])
            if data_type == 3:
                # EOF
                break

            data_length = ord(head[2]) + 256 * ord(head[3]) \
                          + 65536 * ord(head[4]) + 16777216 * ord(head[5])
            if data_type == 1: # ASCII
                data.write(file.read(data_length))
            elif data_type == 2: #Binary
                # decode and discard the first 4 bytes
                buf = file.read(4)
                if len(buf) < 4:
                    raise IOError, "insufficient data"
                buf, r = decode(buf, 55665)
                data_length = data_length - 4
                if data_length < 0:
                    raise IOError, "invalid data"
                while data_length:
                    buf = file.read(min(1000, data_length))
                    if not buf:
                        raise IOError, "insufficient data"
                    buf, r = decode(buf, r)
                    data.write(buf)
                    data_length = data_length - len(buf)
            else:
                raise RuntimeError, "Invalid data type"
            head = file.read(6)


    data = data.getvalue()
    return data

def parse_type1_file(data):
    subrs = char_strings = None
    tokenizer = PSTokenizer(data)
    next = tokenizer.next
    
    while 1:
        token, value = next()
        if token == NAME:
            if value == 'Subrs':
                token, value = next()
                if token == INT:
                    subrs = read_subrs(tokenizer, value)
            elif value == 'CharStrings':
                char_strings = read_char_strings(tokenizer)
                if subrs is not None:
                    break
        elif token == END:
            break

    return subrs, char_strings


def read_subrs(tokenizer, num):
    if not num:
        return []
    subrs = [''] * num
    next = tokenizer.next
    read = tokenizer.read

    while not subrs[-1]:
        token, value = next()
        if token == OPERATOR and value == 'dup':
            token, index = next()
            token, length = next()
            next() # discard RD operator
            read(1) # discard space character
            data = read(length)
            subrs[index] = decode(data)[0][4:]
        elif token == END:
            break
    return subrs


def read_char_strings(tokenizer):
    char_strings = {}
    next = tokenizer.next
    read = tokenizer.read

    while 1:
        token, value = next()
        if token == NAME:
            token, length = next()
            next() # discard RD operator
            read(1) # discard space character
            data = read(length)
            char_strings[value] = decode(data)[0][4:]
        elif token == END or (token == OPERATOR and value == 'end'):
            break

    return char_strings

class SubrReturn(Exception):
    pass


class CharStringInterpreter:

    commands = {}

    def __init__(self, subrs):
        self.subrs = subrs
        self.reset()

    def print_path(self):
        for closed, path in self.paths:
            if closed:
                print 'closed:'
            else:
                print 'open:'
            for part in path:
                print part

    def reset(self):
        self.stack = []
        self.ps_stack = []
        self.paths = ()
        self.path = []
        self.closed = 0
        self.in_flex = 0
        self.flex = []
        self.cur = Point(0, 0)

    def execute(self, cs):
        stack = self.stack
        cs = map(ord, cs)
        try:
            while cs:
                code = cs[0]; del cs[0]
                if code >= 32:
                    if code <= 246:
                        stack.append(code - 139)
                    elif code <= 250:
                        stack.append((code - 247) * 256 + cs[0] + 108)
                        del cs[0]
                    elif code <= 254:
                        stack.append(-(code - 251) * 256 - cs[0] - 108)
                        del cs[0]
                    else:
                        stack.append(cs[0] * 0x01000000 + cs[1] * 0x10000
                                     + cs[2] * 0x100 + cs[3])
                        del cs[:4]
                else:
                    if code == 12:
                        code = 32 + cs[0]
                        del cs[0]
                    cmd = self.commands[code]
                    if cmd:
                        cmd(self)
        except SubrReturn:
            return

    def new_path(self):
        if self.path:
            self.paths = self.paths + ((self.closed, self.path),)
            self.path = []
            self.closed = 0

    def flush_stack(self, *rest):
        del self.stack[:]

    commands[32 + 0] = flush_stack      # dotsection
    commands[1]      = flush_stack      # hstem
    commands[32 + 2] = flush_stack      # hstem3
    commands[3]      = flush_stack      # vstem
    commands[32 + 1] = flush_stack      # vstem3

    def pop(self, n):
        result = self.stack[-n:]
        del self.stack[-n:]
        if n == 1:
            return result[0]
        return result

    def pop_all(self):
        result = self.stack[:]
        del self.stack[:]
        if len(result) == 1:
            return result[0]
        return result

    def endchar(self):
        self.new_path()
        self.flush_stack()
    commands[14] = endchar

    def hsbw(self):
        # horizontal sidebearing and width
        sbx, wx = self.pop_all()
        self.cur = Point(sbx, 0)
    commands[13] = hsbw

    def seac(self):
        # standard encoding accented character
        asb, adx, ady, bchar, achar = self.pop_all()
    commands[32 + 6] = seac

    def sbw(self):
        # sidebearing and width
        sbx, sby, wx, wy = self.pop_all()
        self.cur = Point(sbx, sby)
    commands[32 + 7] = sbw

    def closepath(self):
        self.pop_all()
        self.closed = 1
    commands[9] = closepath

    def rlineto(self):
        dx, dy = self.pop_all()
        self.cur = self.cur + Point(dx, dy)
        self.path.append(tuple(self.cur))
    commands[5] = rlineto

    def hlineto(self):
        dx = self.pop_all()
        self.cur = self.cur + Point(dx, 0)
        self.path.append(tuple(self.cur))
    commands[6] = hlineto

    def vlineto(self):
        dy = self.pop_all()
        self.cur = self.cur + Point(0, dy)
        self.path.append(tuple(self.cur))
    commands[7] = vlineto

    def rmoveto(self):
        dx, dy = self.pop_all()
        self.cur = self.cur + Point(dx, dy)
        if self.in_flex:
            self.flex.append(self.cur)
        else:
            self.new_path()
            self.path.append(tuple(self.cur))
    commands[21] = rmoveto

    def hmoveto(self):
        dx = self.pop_all()
        self.cur = self.cur + Point(dx, 0)
        self.new_path()
        self.path.append(tuple(self.cur))
    commands[22] = hmoveto

    def vmoveto(self):
        dy = self.pop_all()
        self.cur = self.cur + Point(0, dy)
        self.new_path()
        self.path.append(tuple(self.cur))
    commands[4] = vmoveto

    def rrcurveto(self):
        dx1, dy1, dx2, dy2, dx3, dy3 = self.pop_all()
        d1 = self.cur + Point(dx1, dy1)
        d2 = d1 + Point(dx2, dy2)
        d3 = d2 + Point(dx3, dy3)
        self.cur = d3
        self.path.append(tuple(d1) +tuple(d2) + tuple(d3))
    commands[8] = rrcurveto

    def hvcurveto(self):
        dx1, dx2, dy2, dy3 = self.pop_all()
        d1 = self.cur + Point(dx1, 0)
        d2 = d1 + Point(dx2, dy2)
        d3 = d2 + Point(0, dy3)
        self.cur = d3
        self.path.append(tuple(d1) + tuple(d2) + tuple(d3))
    commands[31] = hvcurveto

    def vhcurveto(self):
        dy1, dx2, dy2, dx3 = self.pop_all()
        d1 = self.cur + Point(0, dy1)
        d2 = d1 + Point(dx2, dy2)
        d3 = d2 + Point(dx3, 0)
        self.cur = d3
        self.path.append(tuple(d1) + tuple(d2) + tuple(d3))
    commands[30] = vhcurveto

    def start_flex(self):
        self.in_flex = 1
        self.flex = []

    def end_flex(self):
        size, x, y = self.pop_all()
        d1, d2, d3 = self.flex[1:4]
        self.path.append(tuple(d1) + tuple(d2) + tuple(d3))
        d1, d2, d3 = self.flex[4:7]
        self.path.append(tuple(d1) + tuple(d2) + tuple(d3))

    def div(self):
        num1, num2 = self.pop(2)
        self.stack.append(float(num1) / num2)
    commands[32 + 12] = div

    def callothersubr(self):
        n, sn = self.pop(2)
        if n:
            self.ps_stack = self.pop(n)
        if sn == 3:
            self.ps_stack = [3]
    commands[32 + 16] = callothersubr

    def callsubr(self):
        num = self.pop(1)
        if num == 0:
            self.end_flex()
        elif num == 1:
            self.start_flex()
        elif 2 <= num <= 3:
            return
        else:
            self.execute(self.subrs[num])
    commands[10] = callsubr

    def pop_ps(self):
        value = self.ps_stack[-1]
        del self.ps_stack[-1]
        self.stack.append(value)
    commands[32 + 17] = pop_ps

    def subr_return(self):
        raise SubrReturn
    commands[11] = subr_return

    def setcurrentpoint(self):
        x, y = self.pop_all()
        self.cur = Point(x, y)
    commands[32 + 33] = setcurrentpoint



#
# read_outlines(FILENAME)
#
# Return the outlines of the glyphs in the Type1 font stored in the file
# FILENAME as a tuple (CHAR_STRINGS, INTERPRETER). CHAR_STRINGS is a
# dictionary mapping glyph names to strings containing the outline
# description, INTERPRETER is an instance of CharStringInterpreter
# initialized with the appropriate Subrs.
def read_outlines(filename):
    data = read_type1_file(filename)
    data = streamfilter.StringDecode(data, None)
    subrs, char_strings = parse_type1_file(data)
    interpreter = CharStringInterpreter(subrs)
    return char_strings, interpreter






def embed_type1_file(fontfile, outfile):
    if type(fontfile) == StringType:
        file = open(filename, 'rb')
    else:
        file = fontfile
    head = file.read(6)
    if head[:2] == '%!':
        # PFA
        outfile.write(head)
        data = file.read(4000)
        while data:
            outfile.write(data)
            data = file.read(4000)
    else:
        # Probably PFB
        while 1: # loop over all chunks
            if ord(head[0]) != 128:
                raise TypeError, 'not a pfb file'
            data_type = ord(head[1])
            if data_type == 3:
                # EOF
                break

            data_length = ord(head[2]) + 256 * ord(head[3]) \
                          + 65536 * ord(head[4]) + 16777216 * ord(head[5])
            if data_type == 1: # ASCII
                outfile.write(file.read(data_length))
            elif data_type == 2: #Binary
                # Hex encode data
                encoder = streamfilter.HexEncode(outfile)
                while data_length:
                    if data_length > 4000:
                        length = 4000
                    else:
                        length = data_length
                    data = file.read(length)
                    encoder.write(data)
                    data_length = data_length - length
                encoder.close()
            head = file.read(6)


#
#       some test functions...
#

def test():
    filename = sys.argv[1]
    data = read_type1_file(filename)
    data = streamfilter.StringDecode(data, None)
    subrs, char_strings = parse_type1_file(data)
    items = char_strings.items()
    items.sort()
    interpreter = CharStringInterpreter(subrs)
    for name, code in items:
        print name, `code`
        interpreter.execute(code)
        interpreter.print_path()
        interpreter.reset()

if __name__ == '__main__':
    test()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.