func refToken(f fancy.Reader) ([]byte, int64) { tok, p := ps.Token(f) if len(tok) > 0 && tok[0] >= '0' && tok[0] <= '9' { ps.Token(f) r, q := ps.Token(f) if string(r) == "R" { f.Seek(p, 0) tok = f.Slice(int(1 + q - p)) } else { f.Seek(p+int64(len(tok)), 0) } } return tok, p }
// xrefReadTable() reads the xref table(s) of a PDF file. This is not recursive // in favour of not to have to keep track of already used starting points // for xrefs. func xrefReadTable(f fancy.Reader, p int) (map[int]int, DictionaryT) { var trailer DictionaryT var back [MAX_PDF_UPDATES]int b := 0 s := _Bytes for ok := true; ok; { back[b] = p b++ p = xrefSkip(f, p) f.Seek(int64(p), 0) s, _ = ps.Token(f) if string(s) != "trailer" { util.Log("no trailer / xref table") return nil, nil } s, _ = ps.Token(f) if trailer == nil { trailer = Dictionary(s) } s, ok = Dictionary(s)["/Prev"] p = num(s) } r := make(map[int]int) for b != 0 { b-- f.Seek(int64(back[b]), 0) ps.Token(f) // skip "xref" for { m := tuple(f, 2) if string(m[0]) == "trailer" { break } ps.SkipLE(f) o := num(m[0]) dat := f.Slice(num(m[1]) * 20) for i := 0; i < len(dat); i += 20 { if dat[i+17] != 'n' { delete(r, o) } else { r[o] = num(dat[i : i+10]) } o++ } } } return r, trailer }
func Token(f fancy.Reader) ([]byte, int64) { again: c := skipSpaces(f) if c == 0 { return []byte{}, -1 } p := fpos(f) - 1 switch c { case '%': skipComment(f) goto again case '<', '[', '{': skipComposite(f) case '(': skipString(f) default: if skipToDelim(f) != 255 { f.UnreadByte() } } n := int(fpos(f) - p) f.Seek(p, 0) return f.Slice(n), p }
// xrefReadStream() reads the xref stream(s) of a PDF file. This is not recursive // in favour of not to have to keep track of already used starting points // for xrefs. func xrefReadStream(f fancy.Reader, p int) (xr map[int]int, r [][2]int, trailer DictionaryT) { s := _Bytes xr = map[int]int{} r = [][2]int{} for ok := true; ok; { f.Seek(int64(p), 0) ps.Token(f) // skip "xref" //for { m := tuple(f, 2) if string(m[1]) != "obj" { util.Logf("unexpected %q\n", m) return nil, nil, nil } s, _ = ps.Token(f) dic := Dictionary(s) if trailer == nil { trailer = dic } s, ok = dic["/Prev"] p = num(s) s, _ = ps.Token(f) if string(s) != "stream" { util.Log("not a stream", s) return nil, nil, nil } ps.SkipLE(f) for k, v := range dic { util.Logf("%s %s", k, v) } size := num(dic["/Size"]) index := []int{0, size} if _, ok := dic["/Index"]; ok { a := Array(dic["/Index"]) index[0] = num(a[0]) index[1] = num(a[1]) // can len(index) be != 2 ? } l := num(dic["/Length"]) xref := f.Slice(l) w := Array(dic["/W"]) if len(w) != 3 { util.Log("unexpected /W", w) } fl1 := num(w[0]) fl2 := num(w[1]) fl3 := num(w[2]) width := fl1 + fl2 + fl3 xref = decodeStream(dic, xref) s, _ = ps.Token(f) // endstream s, _ = ps.Token(f) // endobj pos := index[0] for i := 0; i < len(xref); i += width { ent := xref[i : i+width] f1 := bnum(ent[0:fl1]) f2 := bnum(ent[fl1 : fl1+fl2]) f3 := bnum(ent[fl1+fl2:]) switch f1 { case 0: // free object util.Log("free", f2, f3) // delete(r, f2) case 1: // regular object util.Log("ref", pos, f3, f2) xr[pos] = f2 case 2: // compressed object util.Log("cref", pos, f2, f3) r = append(r, [2]int{f2, f3}) } pos += 1 } //} } return xr, r, trailer }