Files
go-fitz/fitz_nocgo.go
landaiqing 5ce88674da
Some checks failed
Test / test (1.22.x, macos-latest) (push) Has been cancelled
Test / test (1.22.x, ubuntu-latest) (push) Has been cancelled
init commit
2026-02-10 14:45:18 +08:00

1098 lines
28 KiB
Go

//go:build !cgo || nocgo
package fitz
import (
"image"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"unsafe"
"github.com/ebitengine/purego"
"github.com/jupiterrider/ffi"
)
// Document represents fitz document.
type Document struct {
ctx *fzContext
data []byte // binds data to the Document lifecycle avoiding premature GC
doc *fzDocument
mtx sync.Mutex
stream *fzStream
}
// New returns new fitz document.
func New(filename string) (f *Document, err error) {
f = &Document{}
filename, err = filepath.Abs(filename)
if err != nil {
return
}
if _, e := os.Stat(filename); e != nil {
err = ErrNoSuchFile
return
}
f.ctx = fzNewContextImp(nil, nil, uint64(MaxStore), FzVersion)
if f.ctx == nil {
err = ErrCreateContext
return
}
fzRegisterDocumentHandlers(f.ctx)
f.doc = fzOpenDocument(f.ctx, filename)
if f.doc == nil {
err = ErrOpenDocument
return
}
ret := fzNeedsPassword(f.ctx, f.doc)
v := int(ret) != 0
if v {
err = ErrNeedsPassword
}
return
}
// NewFromMemory returns new fitz document from byte slice.
func NewFromMemory(b []byte) (f *Document, err error) {
if len(b) == 0 {
return nil, ErrEmptyBytes
}
f = &Document{}
f.ctx = fzNewContextImp(nil, nil, uint64(MaxStore), FzVersion)
if f.ctx == nil {
err = ErrCreateContext
return
}
fzRegisterDocumentHandlers(f.ctx)
f.stream = fzOpenMemory(f.ctx, unsafe.SliceData(b), uint64(len(b)))
if f.stream == nil {
err = ErrOpenMemory
return
}
magic := contentType(b)
if magic == "" {
err = ErrOpenMemory
return
}
f.data = b
f.doc = fzOpenDocumentWithStream(f.ctx, magic, f.stream)
if f.doc == nil {
err = ErrOpenDocument
}
ret := fzNeedsPassword(f.ctx, f.doc)
v := int(ret) != 0
if v {
err = ErrNeedsPassword
}
return
}
// NewFromReader returns new fitz document from io.Reader.
func NewFromReader(r io.Reader) (f *Document, err error) {
b, e := io.ReadAll(r)
if e != nil {
err = e
return
}
f, err = NewFromMemory(b)
return
}
// NumPage returns total number of pages in document.
func (f *Document) NumPage() int {
return fzCountPages(f.ctx, f.doc)
}
// Image returns image for given page number.
func (f *Document) Image(pageNumber int) (*image.RGBA, error) {
return f.ImageDPI(pageNumber, 300.0)
}
// ImageDPI returns image for given page number and DPI.
func (f *Document) ImageDPI(pageNumber int, dpi float64) (*image.RGBA, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return nil, ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
var ctm fzMatrix
ctm = scale(float32(dpi/72), float32(dpi/72))
var bbox fzIRect
bounds = transformRect(bounds, ctm)
bbox = roundRect(bounds)
pixmap := fzNewPixmap(f.ctx, fzDeviceRgb(f.ctx), int(bbox.X1), int(bbox.Y1), nil, 1)
if pixmap == nil {
return nil, ErrCreatePixmap
}
fzClearPixmapWithValue(f.ctx, pixmap, 0xff)
defer fzDropPixmap(f.ctx, pixmap)
device := newDrawDevice(f.ctx, ctm, pixmap)
fzEnableDeviceHints(f.ctx, device, fzNoCache)
defer fzDropDevice(f.ctx, device)
runPageContents(f.ctx, page, device, fzIdentity)
fzCloseDevice(f.ctx, device)
pixels := fzPixmapSamples(f.ctx, pixmap)
if pixels == nil {
return nil, ErrPixmapSamples
}
img := image.NewRGBA(image.Rect(int(bbox.X0), int(bbox.Y0), int(bbox.X1), int(bbox.Y1)))
copy(img.Pix, unsafe.Slice(pixels, 4*bbox.X1*bbox.Y1))
return img, nil
}
// ImagePNG returns image for given page number as PNG bytes.
func (f *Document) ImagePNG(pageNumber int, dpi float64) ([]byte, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return nil, ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
var ctm fzMatrix
ctm = scale(float32(dpi/72), float32(dpi/72))
var bbox fzIRect
bounds = transformRect(bounds, ctm)
bbox = roundRect(bounds)
pixmap := fzNewPixmap(f.ctx, fzDeviceRgb(f.ctx), int(bbox.X1), int(bbox.Y1), nil, 1)
if pixmap == nil {
return nil, ErrCreatePixmap
}
fzClearPixmapWithValue(f.ctx, pixmap, 0xff)
defer fzDropPixmap(f.ctx, pixmap)
device := newDrawDevice(f.ctx, ctm, pixmap)
fzEnableDeviceHints(f.ctx, device, fzNoCache)
defer fzDropDevice(f.ctx, device)
runPageContents(f.ctx, page, device, fzIdentity)
fzCloseDevice(f.ctx, device)
params := fzColorParams{1, 1, 0, 0}
buf := newBufferFromPixmapAsPNG(f.ctx, pixmap, params)
defer fzDropBuffer(f.ctx, buf)
size := fzBufferStorage(f.ctx, buf, nil)
ret := make([]byte, size)
copy(ret, unsafe.Slice(fzStringFromBuffer(f.ctx, buf), size))
return ret, nil
}
// Links returns slice of links for given page number.
func (f *Document) Links(pageNumber int) ([]Link, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return nil, ErrLoadPage
}
defer fzDropPage(f.ctx, page)
links := fzLoadLinks(f.ctx, page)
defer fzDropLink(f.ctx, links)
linkCount := 0
for currLink := links; currLink != nil; currLink = currLink.Next {
linkCount++
}
if linkCount == 0 {
return nil, nil
}
gLinks := make([]Link, linkCount)
currLink := links
for i := 0; i < linkCount; i++ {
gLinks[i] = Link{
URI: bytePtrToString((*uint8)(unsafe.Pointer(currLink.Uri))),
}
currLink = currLink.Next
}
return gLinks, nil
}
// Text returns text for given page number.
func (f *Document) Text(pageNumber int) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return "", ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
var ctm fzMatrix
ctm = scale(float32(72.0/72), float32(72.0/72))
text := newStextPage(f.ctx, bounds)
defer fzDropStextPage(f.ctx, text)
var opts fzStextOptions
opts.Flags = 0
device := fzNewStextDevice(f.ctx, text, &opts)
fzEnableDeviceHints(f.ctx, device, fzNoCache)
defer fzDropDevice(f.ctx, device)
runPageContents(f.ctx, page, device, ctm)
fzCloseDevice(f.ctx, device)
buf := fzNewBufferFromStextPage(f.ctx, text)
defer fzDropBuffer(f.ctx, buf)
ret := fzStringFromBuffer(f.ctx, buf)
return bytePtrToString(ret), nil
}
// HTML returns html for given page number.
func (f *Document) HTML(pageNumber int, header bool) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return "", ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
var ctm fzMatrix
ctm = scale(float32(72.0/72), float32(72.0/72))
text := newStextPage(f.ctx, bounds)
defer fzDropStextPage(f.ctx, text)
var opts fzStextOptions
opts.Flags = fzStextPreserveImages
device := fzNewStextDevice(f.ctx, text, &opts)
fzEnableDeviceHints(f.ctx, device, fzNoCache)
defer fzDropDevice(f.ctx, device)
runPageContents(f.ctx, page, device, ctm)
fzCloseDevice(f.ctx, device)
buf := fzNewBuffer(f.ctx, 1024)
defer fzDropBuffer(f.ctx, buf)
out := fzNewOutputWithBuffer(f.ctx, buf)
defer fzDropOutput(f.ctx, out)
if header {
fzPrintStextHeaderAsHTML(f.ctx, out)
}
fzPrintStextPageAsHTML(f.ctx, out, text, pageNumber)
if header {
fzPrintStextTrailerAsHTML(f.ctx, out)
}
fzCloseOutput(f.ctx, out)
ret := fzStringFromBuffer(f.ctx, buf)
return bytePtrToString(ret), nil
}
// SVG returns svg document for given page number.
func (f *Document) SVG(pageNumber int) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return "", ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
var ctm fzMatrix
ctm = scale(float32(72.0/72), float32(72.0/72))
bounds = transformRect(bounds, ctm)
buf := fzNewBuffer(f.ctx, 1024)
defer fzDropBuffer(f.ctx, buf)
out := fzNewOutputWithBuffer(f.ctx, buf)
defer fzDropOutput(f.ctx, out)
device := newSvgDevice(f.ctx, out, bounds.X1-bounds.X0, bounds.Y1-bounds.Y0, fzSvgTextAsPath, 1)
fzEnableDeviceHints(f.ctx, device, fzNoCache)
defer fzDropDevice(f.ctx, device)
runPageContents(f.ctx, page, device, ctm)
fzCloseDevice(f.ctx, device)
fzCloseOutput(f.ctx, out)
ret := fzStringFromBuffer(f.ctx, buf)
return bytePtrToString(ret), nil
}
// ToC returns the table of contents (also known as outline).
func (f *Document) ToC() ([]Outline, error) {
data := make([]Outline, 0)
outline := fzLoadOutline(f.ctx, f.doc)
if outline == nil {
return nil, ErrLoadOutline
}
defer fzDropOutline(f.ctx, outline)
var walk func(outline *fzOutline, level int)
walk = func(outline *fzOutline, level int) {
for outline != nil {
res := Outline{}
res.Level = level
res.Title = bytePtrToString((*uint8)(unsafe.Pointer(outline.Title)))
res.URI = bytePtrToString((*uint8)(unsafe.Pointer(outline.Uri)))
res.Page = int(outline.Page.Page)
res.Top = float64(outline.Y)
data = append(data, res)
if outline.Down != nil {
walk(outline.Down, level+1)
}
outline = outline.Next
}
}
walk(outline, 1)
return data, nil
}
// Metadata returns the map with standard metadata.
func (f *Document) Metadata() map[string]string {
data := make(map[string]string)
lookup := func(key string) string {
buf := make([]byte, 256)
fzLookupMetadata(f.ctx, f.doc, key, unsafe.SliceData(buf), len(buf))
return string(buf)
}
data["format"] = lookup("format")
data["encryption"] = lookup("encryption")
data["title"] = lookup("info:Title")
data["author"] = lookup("info:Author")
data["subject"] = lookup("info:Subject")
data["keywords"] = lookup("info:Keywords")
data["creator"] = lookup("info:Creator")
data["producer"] = lookup("info:Producer")
data["creationDate"] = lookup("info:CreationDate")
data["modDate"] = lookup("info:modDate")
return data
}
// Bound gives the Bounds of a given Page in the document.
func (f *Document) Bound(pageNumber int) (image.Rectangle, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return image.Rectangle{}, ErrPageMissing
}
page := fzLoadPage(f.ctx, f.doc, pageNumber)
if page == nil {
return image.Rectangle{}, ErrLoadPage
}
defer fzDropPage(f.ctx, page)
var bounds fzRect
bounds = boundPage(f.ctx, page)
return image.Rect(int(bounds.X0), int(bounds.Y0), int(bounds.X1), int(bounds.Y1)), nil
}
// Close closes the underlying fitz document.
func (f *Document) Close() error {
if f.stream != nil {
fzDropStream(f.ctx, f.stream)
}
fzDropDocument(f.ctx, f.doc)
fzDropContext(f.ctx)
f.data = nil
return nil
}
var (
libmupdf uintptr
fzBoundPage *bundle
fzTransformRect *bundle
fzRoundRect *bundle
fzScale *bundle
fzNewDrawDevice *bundle
fzRunPageContents *bundle
fzNewBufferFromPixmapAsPNG *bundle
fzNewStextPage *bundle
fzNewSvgDevice *bundle
fzNewContextImp func(alloc *fzAllocContext, locks *fzLocksContext, maxStore uint64, version string) *fzContext
fzDropContext func(ctx *fzContext)
fzOpenDocument func(ctx *fzContext, filename string) *fzDocument
fzOpenDocumentWithStream func(ctx *fzContext, magic string, stream *fzStream) *fzDocument
fzOpenMemory func(ctx *fzContext, data *uint8, len uint64) *fzStream
fzDropStream func(ctx *fzContext, stm *fzStream)
fzRegisterDocumentHandlers func(ctx *fzContext)
fzNeedsPassword func(ctx *fzContext, doc *fzDocument) int
fzDropDocument func(ctx *fzContext, doc *fzDocument)
fzCountPages func(ctx *fzContext, doc *fzDocument) int
fzLoadPage func(ctx *fzContext, doc *fzDocument, number int) *fzPage
fzDropPage func(ctx *fzContext, page *fzPage)
fzNewPixmap func(ctx *fzContext, colorspace *fzColorspace, w, h int, seps *fzSeparations, alpha int) *fzPixmap
fzDropPixmap func(ctx *fzContext, pix *fzPixmap)
fzPixmapSamples func(ctx *fzContext, pix *fzPixmap) *uint8
fzClearPixmapWithValue func(ctx *fzContext, pix *fzPixmap, value int)
fzEnableDeviceHints func(ctx *fzContext, dev *fzDevice, hints int)
fzDropDevice func(ctx *fzContext, dev *fzDevice)
fzCloseDevice func(ctx *fzContext, dev *fzDevice)
fzDeviceRgb func(ctx *fzContext) *fzColorspace
fzNewBuffer func(ctx *fzContext, size uint64) *fzBuffer
fzDropBuffer func(ctx *fzContext, buf *fzBuffer)
fzBufferStorage func(ctx *fzContext, buf *fzBuffer, data **uint8) uint64
fzStringFromBuffer func(ctx *fzContext, buf *fzBuffer) *uint8
fzLoadLinks func(ctx *fzContext, page *fzPage) *fzLink
fzDropLink func(ctx *fzContext, link *fzLink)
fzDropStextPage func(ctx *fzContext, page *fzStextPage)
fzNewStextDevice func(ctx *fzContext, page *fzStextPage, options *fzStextOptions) *fzDevice
fzNewBufferFromStextPage func(ctx *fzContext, page *fzStextPage) *fzBuffer
fzLookupMetadata func(ctx *fzContext, doc *fzDocument, key string, buf *uint8, size int) int
fzLoadOutline func(ctx *fzContext, doc *fzDocument) *fzOutline
fzDropOutline func(ctx *fzContext, outline *fzOutline)
fzNewOutputWithBuffer func(ctx *fzContext, buf *fzBuffer) *fzOutput
fzDropOutput func(ctx *fzContext, out *fzOutput)
fzCloseOutput func(ctx *fzContext, out *fzOutput)
fzPrintStextPageAsHTML func(ctx *fzContext, out *fzOutput, page *fzStextPage, id int)
fzPrintStextHeaderAsHTML func(ctx *fzContext, out *fzOutput)
fzPrintStextTrailerAsHTML func(ctx *fzContext, out *fzOutput)
)
func init() {
libmupdf = loadLibrary()
if os.Getenv("FZ_VERSION") != "" {
FzVersion = os.Getenv("FZ_VERSION")
}
fzBoundPage = newBundle("fz_bound_page", &typeFzRect, &ffi.TypePointer, &ffi.TypePointer)
fzTransformRect = newBundle("fz_transform_rect", &typeFzRect, &typeFzRect, &typeFzMatrix)
fzRoundRect = newBundle("fz_round_rect", &typeFzIRect, &typeFzRect)
fzScale = newBundle("fz_scale", &typeFzMatrix, &ffi.TypeFloat, &ffi.TypeFloat)
fzNewDrawDevice = newBundle("fz_new_draw_device", &ffi.TypePointer, &ffi.TypePointer, &typeFzMatrix, &ffi.TypePointer)
fzRunPageContents = newBundle("fz_run_page_contents", &ffi.TypeVoid, &ffi.TypePointer, &ffi.TypePointer, &ffi.TypePointer, &typeFzMatrix, &ffi.TypePointer)
fzNewBufferFromPixmapAsPNG = newBundle("fz_new_buffer_from_pixmap_as_png", &ffi.TypePointer, &ffi.TypePointer, &ffi.TypePointer, &typeFzColorParams)
fzNewStextPage = newBundle("fz_new_stext_page", &ffi.TypePointer, &ffi.TypePointer, &typeFzRect)
fzNewSvgDevice = newBundle("fz_new_svg_device", &ffi.TypePointer, &ffi.TypePointer, &ffi.TypePointer, &ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeSint32, &ffi.TypeSint32)
purego.RegisterLibFunc(&fzNewContextImp, libmupdf, "fz_new_context_imp")
purego.RegisterLibFunc(&fzDropContext, libmupdf, "fz_drop_context")
purego.RegisterLibFunc(&fzOpenDocument, libmupdf, "fz_open_document")
purego.RegisterLibFunc(&fzOpenDocumentWithStream, libmupdf, "fz_open_document_with_stream")
purego.RegisterLibFunc(&fzOpenMemory, libmupdf, "fz_open_memory")
purego.RegisterLibFunc(&fzDropStream, libmupdf, "fz_drop_stream")
purego.RegisterLibFunc(&fzRegisterDocumentHandlers, libmupdf, "fz_register_document_handlers")
purego.RegisterLibFunc(&fzNeedsPassword, libmupdf, "fz_needs_password")
purego.RegisterLibFunc(&fzDropDocument, libmupdf, "fz_drop_document")
purego.RegisterLibFunc(&fzCountPages, libmupdf, "fz_count_pages")
purego.RegisterLibFunc(&fzLoadPage, libmupdf, "fz_load_page")
purego.RegisterLibFunc(&fzDropPage, libmupdf, "fz_drop_page")
purego.RegisterLibFunc(&fzNewPixmap, libmupdf, "fz_new_pixmap")
purego.RegisterLibFunc(&fzDropPixmap, libmupdf, "fz_drop_pixmap")
purego.RegisterLibFunc(&fzPixmapSamples, libmupdf, "fz_pixmap_samples")
purego.RegisterLibFunc(&fzClearPixmapWithValue, libmupdf, "fz_clear_pixmap_with_value")
purego.RegisterLibFunc(&fzEnableDeviceHints, libmupdf, "fz_enable_device_hints")
purego.RegisterLibFunc(&fzDropDevice, libmupdf, "fz_drop_device")
purego.RegisterLibFunc(&fzCloseDevice, libmupdf, "fz_close_device")
purego.RegisterLibFunc(&fzDeviceRgb, libmupdf, "fz_device_rgb")
purego.RegisterLibFunc(&fzNewBuffer, libmupdf, "fz_new_buffer")
purego.RegisterLibFunc(&fzDropBuffer, libmupdf, "fz_drop_buffer")
purego.RegisterLibFunc(&fzBufferStorage, libmupdf, "fz_buffer_storage")
purego.RegisterLibFunc(&fzStringFromBuffer, libmupdf, "fz_string_from_buffer")
purego.RegisterLibFunc(&fzLoadLinks, libmupdf, "fz_load_links")
purego.RegisterLibFunc(&fzDropLink, libmupdf, "fz_drop_link")
purego.RegisterLibFunc(&fzDropStextPage, libmupdf, "fz_drop_stext_page")
purego.RegisterLibFunc(&fzNewStextDevice, libmupdf, "fz_new_stext_device")
purego.RegisterLibFunc(&fzNewBufferFromStextPage, libmupdf, "fz_new_buffer_from_stext_page")
purego.RegisterLibFunc(&fzLookupMetadata, libmupdf, "fz_lookup_metadata")
purego.RegisterLibFunc(&fzLoadOutline, libmupdf, "fz_load_outline")
purego.RegisterLibFunc(&fzDropOutline, libmupdf, "fz_drop_outline")
purego.RegisterLibFunc(&fzNewOutputWithBuffer, libmupdf, "fz_new_output_with_buffer")
purego.RegisterLibFunc(&fzDropOutput, libmupdf, "fz_drop_output")
purego.RegisterLibFunc(&fzCloseOutput, libmupdf, "fz_close_output")
purego.RegisterLibFunc(&fzPrintStextPageAsHTML, libmupdf, "fz_print_stext_page_as_html")
purego.RegisterLibFunc(&fzPrintStextHeaderAsHTML, libmupdf, "fz_print_stext_header_as_html")
purego.RegisterLibFunc(&fzPrintStextTrailerAsHTML, libmupdf, "fz_print_stext_trailer_as_html")
ver := version()
if ver != "" {
FzVersion = ver
}
}
func version() string {
if fzNewContextImp(nil, nil, uint64(MaxStore), FzVersion) != nil {
return FzVersion
}
s := strings.Split(FzVersion, ".")
v := strings.Join(s[:len(s)-1], ".")
for x := 10; x >= 0; x-- {
ver := v + "." + strconv.Itoa(x)
if ver == FzVersion {
continue
}
if fzNewContextImp(nil, nil, uint64(MaxStore), ver) != nil {
return ver
}
}
return ""
}
type bundle struct {
sym uintptr
cif ffi.Cif
}
func (b *bundle) call(rValue unsafe.Pointer, aValues ...unsafe.Pointer) {
ffi.Call(&b.cif, b.sym, rValue, aValues...)
}
func newBundle(name string, rType *ffi.Type, aTypes ...*ffi.Type) *bundle {
b := new(bundle)
b.sym = procAddress(libmupdf, name)
nArgs := uint32(len(aTypes))
if status := ffi.PrepCif(&b.cif, ffi.DefaultAbi, nArgs, rType, aTypes...); status != ffi.OK {
panic(status)
}
return b
}
var typeFzRect = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, nil}[0]}
var typeFzIRect = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, nil}[0]}
var typeFzMatrix = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, &ffi.TypeFloat, nil}[0]}
var typeFzColorParams = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, nil}[0]}
func boundPage(ctx *fzContext, page *fzPage) fzRect {
var ret fzRect
fzBoundPage.call(unsafe.Pointer(&ret), unsafe.Pointer(&ctx), unsafe.Pointer(&page))
return ret
}
func transformRect(rect fzRect, m fzMatrix) fzRect {
var ret fzRect
fzTransformRect.call(unsafe.Pointer(&ret), unsafe.Pointer(&rect), unsafe.Pointer(&m))
return ret
}
func roundRect(rect fzRect) fzIRect {
var ret fzIRect
fzRoundRect.call(unsafe.Pointer(&ret), unsafe.Pointer(&rect))
return ret
}
func scale(sx, sy float32) fzMatrix {
var ret fzMatrix
fzScale.call(unsafe.Pointer(&ret), unsafe.Pointer(&sx), unsafe.Pointer(&sy))
return ret
}
func newDrawDevice(ctx *fzContext, transform fzMatrix, dest *fzPixmap) *fzDevice {
var ret *fzDevice
fzNewDrawDevice.call(unsafe.Pointer(&ret), unsafe.Pointer(&ctx), unsafe.Pointer(&transform), unsafe.Pointer(&dest))
return ret
}
func runPageContents(ctx *fzContext, page *fzPage, dev *fzDevice, transform fzMatrix) {
var cookie fzCookie
fzRunPageContents.call(nil, unsafe.Pointer(&ctx), unsafe.Pointer(&page), unsafe.Pointer(&dev), unsafe.Pointer(&transform), unsafe.Pointer(&cookie))
}
func newBufferFromPixmapAsPNG(ctx *fzContext, pix *fzPixmap, params fzColorParams) *fzBuffer {
var ret *fzBuffer
fzNewBufferFromPixmapAsPNG.call(unsafe.Pointer(&ret), unsafe.Pointer(&ctx), unsafe.Pointer(&pix), unsafe.Pointer(&params))
return ret
}
func newStextPage(ctx *fzContext, mediabox fzRect) *fzStextPage {
var ret *fzStextPage
fzNewStextPage.call(unsafe.Pointer(&ret), unsafe.Pointer(&ctx), unsafe.Pointer(&mediabox))
return ret
}
func newSvgDevice(ctx *fzContext, out *fzOutput, pageWidth, pageHeight float32, textFormat, reuseImages int) *fzDevice {
var ret *fzDevice
fzNewSvgDevice.call(unsafe.Pointer(&ret), unsafe.Pointer(&ctx), unsafe.Pointer(&out), unsafe.Pointer(&pageWidth), unsafe.Pointer(&pageHeight), unsafe.Pointer(&textFormat), unsafe.Pointer(&reuseImages))
return ret
}
const (
fzNoCache = 2
fzStextPreserveImages = 4
fzSvgTextAsPath = 0
)
var fzIdentity = fzMatrix{A: 1, B: 0, C: 0, D: 1, E: 0, F: 0}
type fzContext struct {
User *byte
Alloc fzAllocContext
Locks fzLocksContext
Error fzErrorContext
Warn fzWarnContext
Aa fzAaContext
Seed48 [7]uint16
IccEnabled int32
ThrowOnRepair int32
Handler *fzDocumentHandlerContext
Archive *fzArchiveHandlerContext
Style *fzStyleContext
Tuning *fzTuningContext
StdDbg *fzOutput
Font *fzFontContext
Colorspace *fzColorspaceContext
Store *fzStore
GlyphCache *fzGlyphCache
}
type fzDocument struct {
Refs int32
DropDocument *[0]byte
NeedsPassword *[0]byte
AuthenticatePassword *[0]byte
HasPermission *[0]byte
LoadOutline *[0]byte
OutlineIterator *[0]byte
Layout *[0]byte
MakeBookmark *[0]byte
LookupBookmark *[0]byte
ResolveLinkDest *[0]byte
FormatLinkUri *[0]byte
CountChapters *[0]byte
CountPages *[0]byte
LoadPage *[0]byte
PageLabel *[0]byte
LookupMetadata *[0]byte
SetMetadata *[0]byte
GetOutputIntent *[0]byte
OutputAccelerator *[0]byte
RunStructure *[0]byte
AsPdf *[0]byte
DidLayout int32
IsReflowable int32
Open *fzPage
}
type fzOutline struct {
Refs int32
Title *int8
Uri *int8
Page fzLocation
X float32
Y float32
Next *fzOutline
Down *fzOutline
Open int32
_ [4]byte
}
type fzPage struct {
Refs int32
Doc *fzDocument
Chapter int32
Number int32
Incomplete int32
DropPage *[0]byte
BoundPage *[0]byte
RunPageContents *[0]byte
RunPageAnnots *[0]byte
RunPageWidgets *[0]byte
LoadLinks *[0]byte
PagePresentation *[0]byte
ControlSeparation *[0]byte
SeparationDisabled *[0]byte
Separations *[0]byte
Overprint *[0]byte
CreateLink *[0]byte
DeleteLink *[0]byte
Prev **fzPage
Next *fzPage
}
type fzOutput struct {
State *byte
Write *[0]byte
Seek *[0]byte
Tell *[0]byte
Close *[0]byte
Drop *[0]byte
Reset *[0]byte
Stream *[0]byte
Truncate *[0]byte
Closed int32
Bp *int8
Wp *int8
Ep *int8
Buffered int32
Bits int32
}
type fzLocation struct {
Chapter int32
Page int32
}
type fzStream struct {
Refs int32
Error int32
Eof int32
Progressive int32
Pos int64
Avail int32
Bits int32
Rp *uint8
Wp *uint8
State *byte
Next *[0]byte
Drop *[0]byte
Seek *[0]byte
}
type fzRect struct {
X0 float32
Y0 float32
X1 float32
Y1 float32
}
type fzIRect struct {
X0 int32
Y0 int32
X1 int32
Y1 int32
}
type fzMatrix struct {
A float32
B float32
C float32
D float32
E float32
F float32
}
type fzCookie struct {
Abort int32
Progress int32
Max uint64
Errors int32
Incomplete int32
}
type fzDevice struct {
Refs int32
Hints int32
Flags int32
CloseDevice *[0]byte
DropDevice *[0]byte
FillPath *[0]byte
StrokePath *[0]byte
ClipPath *[0]byte
ClipStrokePath *[0]byte
FillText *[0]byte
StrokeText *[0]byte
ClipText *[0]byte
ClipStrokeText *[0]byte
IgnoreText *[0]byte
FillShade *[0]byte
FillImage *[0]byte
FillImageMask *[0]byte
ClipImageMask *[0]byte
PopClip *[0]byte
BeginMask *[0]byte
EndMask *[0]byte
BeginGroup *[0]byte
EndGroup *[0]byte
BeginTile *[0]byte
EndTile *[0]byte
RenderFlags *[0]byte
SetDefaultColorspaces *[0]byte
BeginLayer *[0]byte
EndLayer *[0]byte
BeginStructure *[0]byte
EndStructure *[0]byte
BeginMetatext *[0]byte
EndMetatext *[0]byte
D1Rect fzRect
ContainerLen int32
ContainerCap int32
Container *fzDeviceContainerStack
}
type fzColorspace struct {
Storable fzKeyStorable
Type uint32
Flags int32
N int32
Name *int8
U [288]byte
}
type fzStorable struct {
Refs int32
Drop *[0]byte
Droppable *[0]byte
}
type fzKeyStorable struct {
Storable fzStorable
KeyRefs int16
_ [6]byte
}
type fzPixmap struct {
Storable fzStorable
X int32
Y int32
W int32
H int32
N uint8
S uint8
Alpha uint8
Flags uint8
Stride int64
Seps *fzSeparations
Xres int32
Yres int32
Colorspace *fzColorspace
Samples *uint8
Underlying *fzPixmap
}
type fzColorParams struct {
Ri uint8
Bp uint8
Op uint8
Opm uint8
}
type fzBuffer struct {
Refs int32
Data *uint8
Cap uint64
Len uint64
Bits int32
Shared int32
}
type fzLink struct {
Refs int32
Next *fzLink
Rect fzRect
Uri *int8
RectFn *[0]byte
UriFn *[0]byte
Drop *[0]byte
}
type fzStextPage struct {
Pool *fzPool
Mediabox fzRect
FirstBlock *fzStextBlock
LastBlock *fzStextBlock
}
type fzStextOptions struct {
Flags int32
Scale float32
}
type fzStextBlock struct {
Type int32
Bbox fzRect
_ [4]byte
U [32]byte
Prev *fzStextBlock
Next *fzStextBlock
}
type fzDeviceContainerStack struct {
Scissor fzRect
Type int32
User int32
}
type fzAllocContext struct {
User *byte
Malloc *[0]byte
Realloc *[0]byte
Free *[0]byte
}
type fzLocksContext struct {
User *byte
Lock *[0]byte
Unlock *[0]byte
}
type fzErrorContext struct {
Top *fzErrorStackSlot
Stack [256]fzErrorStackSlot
Padding fzErrorStackSlot
StackBase *fzErrorStackSlot
ErrCode int32
ErrNum int32
PrintUser *byte
Print *[0]byte
Message [256]int8
}
type fzWarnContext struct {
User *byte
Print *[0]byte
Count int32
Message [256]int8
_ [4]byte
}
type fzAaContext struct {
Hscale int32
Vscale int32
Scale int32
Bits int32
TextBits int32
MinLineWidth float32
}
type fzErrorStackSlot struct {
Buffer [1]int32
State int32
Code int32
Padding [24]int8
}
type fzFontContext struct{}
type fzColorspaceContext struct{}
type fzTuningContext struct{}
type fzStyleContext struct{}
type fzDocumentHandlerContext struct{}
type fzArchiveHandlerContext struct{}
type fzStore struct{}
type fzGlyphCache struct{}
type fzSeparations struct{}
type fzPool struct{}