Add cached Stream method for CMap objects (#382)

* Add cached Stream method for CMaps

* Use CMap Stream method when creating font PDF dictionary objects
This commit is contained in:
Adrian-George Bostan 2020-06-27 03:30:18 +03:00 committed by GitHub
parent 4f96762674
commit 54e965785b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 13 deletions

View File

@ -112,11 +112,18 @@ type CMap struct {
codeToUnicode map[CharCode]string // CID -> Unicode string codeToUnicode map[CharCode]string // CID -> Unicode string
unicodeToCode map[string]CharCode // Unicode rune -> CID unicodeToCode map[string]CharCode // Unicode rune -> CID
// cached contains the raw CMap data. It is used by the Bytes method in // cachedBytes contains the raw CMap data. It is used by the Bytes
// order to avoid generating the data for every call. // method in order to avoid generating the data for each call.
// NOTE: While it is not currently required, a cache invalidation mechanism // NOTE: While it is not currently required, a cache invalidation
// might be needed in the future. // mechanism might be needed in the future.
cached []byte 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. // NewToUnicodeCMap returns an identity CMap with codeToUnicode matching the `codeToRune` arg.
@ -380,7 +387,7 @@ func (cmap *CMap) Type() int {
return cmap.ctype 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 { func (cmap *CMap) NBits() int {
return cmap.nbits return cmap.nbits
} }
@ -411,14 +418,29 @@ func (cmap *CMap) String() string {
// Bytes returns the raw bytes of a PDF CMap corresponding to `cmap`. // Bytes returns the raw bytes of a PDF CMap corresponding to `cmap`.
func (cmap *CMap) Bytes() []byte { func (cmap *CMap) Bytes() []byte {
common.Log.Trace("cmap.Bytes: cmap=%s", cmap.String()) common.Log.Trace("cmap.Bytes: cmap=%s", cmap.String())
if len(cmap.cached) > 0 { if len(cmap.cachedBytes) > 0 {
return cmap.cached return cmap.cachedBytes
} }
cmap.cached = []byte(strings.Join([]string{ cmap.cachedBytes = []byte(strings.Join([]string{
cmapHeader, cmap.toBfData(), cmapTrailer, cmapHeader, cmap.toBfData(), cmapTrailer,
}, "\n")) }, "\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. // matchCode attempts to match the byte array `data` with a character code in `cmap`'s codespaces.

View File

@ -707,10 +707,9 @@ func (base fontCommon) asPdfObjectDictionary(subtype string) *core.PdfObjectDict
if base.toUnicode != nil { if base.toUnicode != nil {
d.Set("ToUnicode", base.toUnicode) d.Set("ToUnicode", base.toUnicode)
} else if base.toUnicodeCmap != nil { } else if base.toUnicodeCmap != nil {
data := base.toUnicodeCmap.Bytes() o, err := base.toUnicodeCmap.Stream()
o, err := core.MakeStream(data, core.NewFlateEncoder())
if err != nil { if err != nil {
common.Log.Debug("MakeStream failed. err=%v", err) common.Log.Debug("WARN: could not get CMap stream. err=%v", err)
} else { } else {
d.Set("ToUnicode", o) d.Set("ToUnicode", o)
} }