From 54e965785b55af418a8cc348a3e8c072e3d8690b Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Sat, 27 Jun 2020 03:30:18 +0300 Subject: [PATCH] Add cached Stream method for CMap objects (#382) * Add cached Stream method for CMaps * Use CMap Stream method when creating font PDF dictionary objects --- internal/cmap/cmap.go | 42 ++++++++++++++++++++++++++++++++---------- model/font.go | 5 ++--- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/internal/cmap/cmap.go b/internal/cmap/cmap.go index 2729f934..6f78b4ef 100644 --- a/internal/cmap/cmap.go +++ b/internal/cmap/cmap.go @@ -112,11 +112,18 @@ type CMap struct { codeToUnicode map[CharCode]string // CID -> Unicode string unicodeToCode map[string]CharCode // Unicode rune -> CID - // cached contains the raw CMap data. It is used by the Bytes method in - // order to avoid generating the data for every call. - // NOTE: While it is not currently required, a cache invalidation mechanism - // might be needed in the future. - cached []byte + // cachedBytes contains the raw CMap data. It is used by the Bytes + // method in order to avoid generating the data for each call. + // NOTE: While it is not currently required, a cache invalidation + // mechanism might be needed in the future. + cachedBytes []byte + + // cachedStream is a Flate encoded stream containing the raw CMap data. + // It is used by the Stream method in order to avoid generating the + // stream for each call. + // NOTE: While it is not currently required, a cache invalidation + // mechanism might be needed in the future. + cachedStream *core.PdfObjectStream } // NewToUnicodeCMap returns an identity CMap with codeToUnicode matching the `codeToRune` arg. @@ -380,7 +387,7 @@ func (cmap *CMap) Type() int { return cmap.ctype } -// Nbits returns 8 bits for simple font CMaps and 16 bits for CID font CMaps. +// NBits returns 8 bits for simple font CMaps and 16 bits for CID font CMaps. func (cmap *CMap) NBits() int { return cmap.nbits } @@ -411,14 +418,29 @@ func (cmap *CMap) String() string { // Bytes returns the raw bytes of a PDF CMap corresponding to `cmap`. func (cmap *CMap) Bytes() []byte { common.Log.Trace("cmap.Bytes: cmap=%s", cmap.String()) - if len(cmap.cached) > 0 { - return cmap.cached + if len(cmap.cachedBytes) > 0 { + return cmap.cachedBytes } - cmap.cached = []byte(strings.Join([]string{ + cmap.cachedBytes = []byte(strings.Join([]string{ cmapHeader, cmap.toBfData(), cmapTrailer, }, "\n")) - return cmap.cached + return cmap.cachedBytes +} + +// Stream returns a Flate encoded stream containing the raw CMap data. +func (cmap *CMap) Stream() (*core.PdfObjectStream, error) { + if cmap.cachedStream != nil { + return cmap.cachedStream, nil + } + + stream, err := core.MakeStream(cmap.Bytes(), core.NewFlateEncoder()) + if err != nil { + return nil, err + } + + cmap.cachedStream = stream + return cmap.cachedStream, nil } // matchCode attempts to match the byte array `data` with a character code in `cmap`'s codespaces. diff --git a/model/font.go b/model/font.go index dcf2e44c..7860752a 100644 --- a/model/font.go +++ b/model/font.go @@ -707,10 +707,9 @@ func (base fontCommon) asPdfObjectDictionary(subtype string) *core.PdfObjectDict if base.toUnicode != nil { d.Set("ToUnicode", base.toUnicode) } else if base.toUnicodeCmap != nil { - data := base.toUnicodeCmap.Bytes() - o, err := core.MakeStream(data, core.NewFlateEncoder()) + o, err := base.toUnicodeCmap.Stream() if err != nil { - common.Log.Debug("MakeStream failed. err=%v", err) + common.Log.Debug("WARN: could not get CMap stream. err=%v", err) } else { d.Set("ToUnicode", o) }