9.3 Cookie

The cookie is a lightweight mechanism for controlling and detecting the behaviour of a given interpretation call (i.e. fz_run_page, fz_run_page_contents, fz_run_annot, fz_run_display_list etc).

To use the cookie, a caller should simply define:

fz_cookie *cookie = { 0 };

set any required fields, for example:

cookie.incomplete_ok = 1;

and then pass &cookie as the last parameter to the interpretation call, for example:

fz_run_page(ctx, page, dev, transform, &cookie);

The contents and definition of fz_cookie are even more subject to change than other structures, so it is important to always initialise all the subfields to zero. The safest way to do this is as given above. If new fields are added to the structure, callers code should not need to change, and the default behaviour of zero-valued new fields will always remain the same.

9.3.1 Detecting errors

When displaying a page, if we hit an error, what should we do?

We could choose to stop interpretation entirely, but that would mean that a relatively unimportant error (such as a missing or broken font) would prevent us getting anything useful out of a page.

We could choose to ignore the errors and continue, but that would be a problem for (say) a print run, where it would undesirable for us to print 1000 copies of a document only to discover that it’s missing an image.

The strategy taken by MuPDF is to swallow errors during interpretation, but keep a count of them in the errors field within the cookie. That way callers can check that cookie.errors == 0 at the end to know whether a run completed without incident.

9.3.2 Using the cookie with threads

Content interpretations can take a (relatively) long time. Once one has been started, it can be useful a) to know how far through processing we are, and b) to be able to abort processing should the results of a run no longer be required.

As a run progresses, 2 fields in the cookie are updated. Firstly, progress will be set to a number that increases as progress is made. Think of this informally as being the number of objects that have been processed so far. In some cases (notably when processing a display list) we can know an upper bound for this value, and this value will be given as progress_max. In cases where no upper bound is known, progress_max will be set to -1. It is possible that the upper bound may start as -1, and then change to a known value later.

These values are intended to enable user feedback to be given, and should not be taken as guarantees of performance.

While running content, the interpreter periodically checks the abort field of the cookie. If it is discovered to be non zero, the rest of the content is ignored.

If the caller decides that it does not need the results of a run once it has been started (perhaps the user changes the page, or closes the file), then it should therefore set the abort field of the cookie to 1.

No guarantees are made about how often the cookie is checked, nor about how fast an interpreter will respond to the abort field once it is set. Setting the abort flag will never hurt, and will frequently help, however. Once the flag has been set to 1, it should never be reset to 0, as the results will be unpredictable.

Resources used by a run cannot be released until the end of a run, regardless of the setting of abort. Callers still need to wait for the fz_run_page (or other) call to complete before the page etc can be safely dropped.

9.3.3 Using the cookie to control partial rendering

The cookie also has a role to play when working in Progressive Mode. The incomplete_ok and incomplete fields are used for this. See chapter 16 Progressive Mode for more details.