Example #1
0
// transforms the page tree from the file into an array of pages
func getPages(file *pdf.File, ref pdf.ObjectReference) []pdf.IndirectObject {
	pages := []pdf.IndirectObject{}
	page_node := file.Get(ref).(pdf.Dictionary)

	switch page_node["Type"] {
	case pdf.Name("Pages"):
		for _, kid_ref := range page_node["Kids"].(pdf.Array) {
			kid_pages := getPages(file, kid_ref.(pdf.ObjectReference))
			pages = append(pages, kid_pages...)
		}
	case pdf.Name("Page"):
		pages = append(pages, pdf.IndirectObject{
			ObjectReference: ref,
			Object:          page_node,
		})
	default:
		panic(string(page_node["Type"].(pdf.Name)))
	}

	return pages
}
Example #2
0
func mergePageTrees(file *pdf.File, catalogs []pdf.Dictionary) pdf.ObjectReference {
	// reserve a reference for the new page tree root
	// needed to set the parent for the old page tree roots
	pageTreeRef, err := file.Add(pdf.Null{})
	if err != nil {
		log.Fatalln(err)
	}

	// use the old page tree roots as our page tree kids
	kids := pdf.Array{}
	pageCount := pdf.Integer(0)
	for _, catalog := range catalogs {
		// add the old page tree root to our list of kids
		pagesRef := catalog["Pages"].(pdf.ObjectReference)
		kids = append(kids, pagesRef)

		// now that the old page tree root is a kid, it needs a parent
		pages := file.Get(pagesRef).(pdf.Dictionary)
		pages["Parent"] = pageTreeRef
		_, err = file.Add(pdf.IndirectObject{
			ObjectReference: pagesRef,
			Object:          pages,
		})
		if err != nil {
			log.Fatalln(err)
		}

		pageCount += pages["Count"].(pdf.Integer)
	}

	// create the merged page tree
	_, err = file.Add(pdf.IndirectObject{
		ObjectReference: pageTreeRef,
		Object: pdf.Dictionary{
			"Type":  pdf.Name("Pages"),
			"Kids":  kids,
			"Count": pageCount,
		},
	})
	if err != nil {
		log.Fatalln(err)
	}

	return pageTreeRef
}
Example #3
0
// transforms the page tree from the file into an array of pages
func getPages(file *pdf.File, ref pdf.ObjectReference) []pdf.Dictionary {
	pages := []pdf.Dictionary{}
	pageNode := file.Get(ref).(pdf.Dictionary)

	switch pageNode["Type"] {
	case pdf.Name("Pages"):
		for _, kidRef := range pageNode["Kids"].(pdf.Array) {
			kidPages := getPages(file, kidRef.(pdf.ObjectReference))
			pages = append(pages, kidPages...)
			file.Free(kidRef.(pdf.ObjectReference).ObjectNumber)
		}
	case pdf.Name("Page"):
		pages = append(pages, pageNode)
		file.Free(ref.ObjectNumber)
	default:
		panic(string(pageNode["Type"].(pdf.Name)))
	}

	return pages
}
Example #4
0
func copyReferencedObjects(refs map[pdf.ObjectReference]pdf.ObjectReference, dst, src *pdf.File, obj pdf.Object) (map[pdf.ObjectReference]pdf.ObjectReference, pdf.Object) {
	var merge = func(newRefs map[pdf.ObjectReference]pdf.ObjectReference) {
		for k, v := range newRefs {
			refs[k] = v
		}
	}

	switch t := obj.(type) {
	case pdf.ObjectReference:
		if _, ok := refs[t]; ok {
			obj = refs[t]
			break
		}

		// get an object reference for the copied obj
		// needed to break reference cycles
		ref, err := dst.Add(pdf.Null{})
		if err != nil {
			log.Fatalln(err)
		}
		refs[t] = ref

		newRefs, newObj := copyReferencedObjects(refs, dst, src, src.Get(t))
		merge(newRefs)

		// now actually add the object to dst
		refs[t], err = dst.Add(pdf.IndirectObject{
			ObjectReference: ref,
			Object:          newObj,
		})
		if err != nil {
			log.Fatalln(err)
		}

		obj = refs[t]
	case pdf.Dictionary:
		for k, v := range t {
			var newRefs map[pdf.ObjectReference]pdf.ObjectReference
			newRefs, t[k] = copyReferencedObjects(refs, dst, src, v)

			merge(newRefs)
		}
		obj = t
	case pdf.Array:
		for i, v := range t {
			var newRefs map[pdf.ObjectReference]pdf.ObjectReference
			newRefs, t[i] = copyReferencedObjects(refs, dst, src, v)
			merge(newRefs)
		}
		obj = t
	case pdf.Stream:
		for k, v := range t.Dictionary {
			var newRefs map[pdf.ObjectReference]pdf.ObjectReference
			newRefs, t.Dictionary[k] = copyReferencedObjects(refs, dst, src, v)
			merge(newRefs)
		}
		obj = t
	case pdf.Name, pdf.Integer, pdf.String, pdf.Real:
		// these types can't have references
	default:
		log.Fatalf("unhandled %T", obj)
	}

	return refs, obj
}