diff --git a/ps.go b/ps.go index 90c551e..438a327 100644 --- a/ps.go +++ b/ps.go @@ -49,77 +49,93 @@ func newDict() Value { // in PDF files, such as cmap files that describe the mapping from font code // points to Unicode code points. // -// There is no support for executable blocks, among other limitations. +// A stream can also be represented by an array of streams that has to be handled as a single stream +// In the case of a simple stream read only once, otherwise get the length of the stream to handle it properly // +// There is no support for executable blocks, among other limitations. func Interpret(strm Value, do func(stk *Stack, op string)) { - rd := strm.Reader() - b := newBuffer(rd, 0) - b.allowEOF = true - b.allowObjptr = false - b.allowStream = false var stk Stack var dicts []dict -Reading: - for { - tok := b.readToken() - if tok == io.EOF { - break + s := strm + strmlen := 1 + if strm.Kind() == Array { + strmlen = strm.Len() + } + + for i := 0; i < strmlen; i++ { + if strm.Kind() == Array { + s = strm.Index(i) } - if kw, ok := tok.(keyword); ok { - switch kw { - case "null", "[", "]", "<<", ">>": + + rd := s.Reader() + + b := newBuffer(rd, 0) + b.allowEOF = true + b.allowObjptr = false + b.allowStream = false + + Reading: + for { + tok := b.readToken() + if tok == io.EOF { break - default: - for i := len(dicts) - 1; i >= 0; i-- { - if v, ok := dicts[i][name(kw)]; ok { - stk.Push(Value{nil, objptr{}, v}) - continue Reading + } + if kw, ok := tok.(keyword); ok { + switch kw { + case "null", "[", "]", "<<", ">>": + break + default: + for i := len(dicts) - 1; i >= 0; i-- { + if v, ok := dicts[i][name(kw)]; ok { + stk.Push(Value{nil, objptr{}, v}) + continue Reading + } } + do(&stk, string(kw)) + continue + case "dict": + stk.Pop() + stk.Push(Value{nil, objptr{}, make(dict)}) + continue + case "currentdict": + if len(dicts) == 0 { + panic("no current dictionary") + } + stk.Push(Value{nil, objptr{}, dicts[len(dicts)-1]}) + continue + case "begin": + d := stk.Pop() + if d.Kind() != Dict { + panic("cannot begin non-dict") + } + dicts = append(dicts, d.data.(dict)) + continue + case "end": + if len(dicts) <= 0 { + panic("mismatched begin/end") + } + dicts = dicts[:len(dicts)-1] + continue + case "def": + if len(dicts) <= 0 { + panic("def without open dict") + } + val := stk.Pop() + key, ok := stk.Pop().data.(name) + if !ok { + panic("def of non-name") + } + dicts[len(dicts)-1][key] = val.data + continue + case "pop": + stk.Pop() + continue } - do(&stk, string(kw)) - continue - case "dict": - stk.Pop() - stk.Push(Value{nil, objptr{}, make(dict)}) - continue - case "currentdict": - if len(dicts) == 0 { - panic("no current dictionary") - } - stk.Push(Value{nil, objptr{}, dicts[len(dicts)-1]}) - continue - case "begin": - d := stk.Pop() - if d.Kind() != Dict { - panic("cannot begin non-dict") - } - dicts = append(dicts, d.data.(dict)) - continue - case "end": - if len(dicts) <= 0 { - panic("mismatched begin/end") - } - dicts = dicts[:len(dicts)-1] - continue - case "def": - if len(dicts) <= 0 { - panic("def without open dict") - } - val := stk.Pop() - key, ok := stk.Pop().data.(name) - if !ok { - panic("def of non-name") - } - dicts[len(dicts)-1][key] = val.data - continue - case "pop": - stk.Pop() - continue } + b.unreadToken(tok) + obj := b.readObject() + stk.Push(Value{nil, objptr{}, obj}) } - b.unreadToken(tok) - obj := b.readObject() - stk.Push(Value{nil, objptr{}, obj}) } }