Age | Commit message (Collapse) | Author |
|
This means that repeated scaling of the same pixmap (or scales of
'stacked' pixmaps) will do less needless recalculation.
|
|
By manually inserting a literal pool, we can avoid the need to
split draw_simple_scale.c out.
|
|
Move the assembly macros into fitz-internal.h.
|
|
|
|
This avoids a stall, and saves time on repeated loops.
|
|
Requires android-ndk-profiler to be copied into android and android/jni.
Also requires r8c of the NDK.
|
|
When shutting down a draw device, we were not freeing pixmaps all
the way down the stack. Tweaked code to hopefully be clearer
when I come back to read it again.
Thanks to zeniko for pointing this out.
|
|
Previously these were only used for shadings in test builds.
By the same argument that they are applied for shadings, it
can be argued that they ought to be applied everywhere trig
functions are used.
|
|
|
|
Currently, the mupdf code loads shadings at parse time, and
instantly decomposes them into a mesh of triangles. This mesh
of triangles is the transformed and rendered as required.
Unfortunately the storage space for the mesh is typically much
greater than the original representation.
In this commit, we move the shading stream parsing/decomposition
code into a general 'fz_process_mesh' function within res_shade.
We then grab a copy of the buffer at load time, and 'process'
(decompose/paint) at render time.
For the test file on the bug, memory falls from the reported 660Mb
to 30Mb. For another test file (txt9780547775815_ingested.pdf
page 271) it reduces memory use from 750Meg to 33Meg. These figures
could be further reduced by storing the compressed streams from the
pdf file rather than the uncompressed ones.
Incorporating typo fix and unused function removal from Sebras. Thanks.
Remove unused function in shading code
|
|
We'd never got around to implementing text clipping with oversized
glyphs before, at least partly due to a lack of files showing the
problem. Now, thanks to a file from Paul Hudson, we have an
example and hence a fix.
|
|
Variable i can never be zero at this point. The desired point of testing
against i was to ensure that the test did not evaluate true at the
first run, and the other parts of the condition are sufficent to
ensure this, so just remove the test on i.
|
|
Since the commit to replace abs/min/max/clamp with inline versions,
"1522 - diagramm missing above 88 pc zoom.pdf" has been missing a
diagram. This is because the diagram contains sections like:
-2147483648 -2147483648 m
-2147483648 2147483647 l
2147483647 2147483647 l
2147483647 -2147483648 l
These extreme values, when transformed would give floating point values
that when naively cast down to int, flip sign (e.g. extreme positive
when cast to int becomes extreme negative).
I had been relying on the cast down giving sane results to enable me to
use fz_clampi. Revert to using fz_clamp and all is fine.
|
|
The FT_Stroker doesn't support dash patterns. Fall back to the normal
path rendering, same as with glyphs that are too big to fit the cache.
|
|
|
|
Instead of using macros for min/max/abs/clamp, we move to using
inline functions. These are more typesafe, and should produce
equivalent code on compilers that support inline (i.e. pretty much
everything we care about these days).
People can always do their own macro versions if they prefer.
|
|
When we allocate a pixmap > 2G, but < 4G, the index into that
pixmap, when calculated as an int can be negative. Fix this with
various casts to unsigned int.
If we ever move to support >4G images we'll need to rejig the
casting to cast each part of the element to ptrdiff_t first.
|
|
Keep texture position calculations in floats as long as possible, as
prematurely dropping back to ints can cause overflows in the
intermediate stages that don't nicely cancel out.
The fix for this makes 2000 or so bitmap differences, most trivial, but
with some progressions.
|
|
The scale_row_from_temp code was broken. Firstly the rounding was wrong
in the 'bulk' case (not a big deal), but more importantly on
configurations where unaligned loads were not allowed (such as the nook),
we could still crash due to an incorrect test to avoid that code.
Thanks to Kammerer for the report, and testing of fixed version.
|
|
|
|
Once the shape was combined with the image in the file in question
the width/height drop to be below zero. Detect this case and bale.
File rendering looks fine.
|
|
See Bug 688655 for analysis of what we SHOULD be doing. The code changes
to do this are actually quite small.
Essentially, when we join we only draw the 'top' (or 'outer') join in a
join dependent way. The 'under' join was always joined as a bevel before
as this was easy. This produces bad effects when the lines have a
significant angle between them and a large linewidth.
The correct (i.e. matching Acrobat and others) way to work is to
join the bottom of the line via the centre point. The sole exception
to this is when drawing under beziers, as we don't want to make our
approximation-by-lines obvious.
All fixed in this patch.
|
|
If this is defined during building, we use our own sinf/cosf/atan2f
functions during shading. This is set automatically if CLUSTER is defined
too, so this should remove the cross-platform differences seen during
cluster rendering.
|
|
Restricts rendering to a sub rectangle of the supplied bbox.
|
|
Don't reset the size of arrays until we have successfully resized them.
|
|
Currently all conversions from rect to bbox are done using a single
function, fz_round_rect. This causes problems, as sometimes we want
'round, allowing for slight calculation errors' and sometimes we
want 'round slavishly to ensure we have a bbox that covers the rect'.
We therefore split these 2 cases into 2 separate functions;
fz_round_rect is kept, meaning "round outwards allowing for slight
errors", and fz_bbox_covering_rect is added to mean "give us the
smallest bbox that is guaranteed to cover rect".
No regressions seen.
|
|
Taken from Sumatra.patch - Many thanks.
|
|
|
|
Debug printing functions: debug -> print.
Accessors: get noun attribute -> noun attribute.
Find -> lookup when the returned value is not reference counted.
pixmap_with_rect -> pixmap_with_bbox.
We are reserving the word "find" to mean lookups that give ownership
of objects to the caller. Lookup is used in other places where the
ownership is not transferred, or simple values are returned.
The rename is done by the sed script in scripts/rename3.sed
|
|
Code was copying the wrong structure. Thanks to Pedro Rivera
for pointing this out.
|
|
|
|
In the existing code, glyphs are stored/retrieved from the glyphcache
with no reference to the antialias level used to create them. This
means that if we are using different aa levels in different threads,
we can retrieve 'non-matching' glyphs and hence get rendering
indeterminisms.
Fixed simply here by storing the aa level in the glyphcache too.
|
|
C's standard is copy(dst, src), so we move to adopt that here.
Hopefully no one is calling this routine other than us - if they are,
then I apologise! Better to aim for consistency before we freeze
the API at v1.0 than to carry an inconsistent API around ever after.
|
|
C's standard is copy(dst, src), so we move to adopt that here.
Hopefully no one is calling this routine other than us - if they are,
then I apologise! Better to aim for consistency before we freeze
the API at v1.0 than to carry an inconsistent API around ever after.
|
|
|
|
|
|
Make fz_clone_context copy existing AA settings.
Add accessor function for fz_bitmap.
Add more documentation for various functions/types.
|
|
In the cancel or error case, we cleanup pixmaps left on the
draw devices stack. We were cleaning up one layer more in
the error code than in normal code, leading to a double free.
|
|
Attempt to separate public API from internal functions.
|
|
Introduce a new 'fz_image' type; this type contains rudimentary
information about images (such as native, size, colorspace etc)
and a function to call to get a pixmap of that image (with a
size hint).
Instead of passing pixmaps through the device interface (and
holding pixmaps in the display list) we now pass images instead.
The rendering routines therefore call fz_image_to_pixmap to get
pixmaps to render, and fz_pixmap_drop those afterwards.
The file format handling routines therefore need to produce
images rather than pixmaps; xps and cbz currently just wrap
pixmaps as images. PDF is more involved.
The stream handling routines in PDF have been altered so that
they can recognise when the last stream entry in a filter
dictionary is an image decoding filter. Rather than applying
this filter, they read and store the parameters into a
pdf_image_params structure, and stop decoding at that point.
This allows us to read the compressed data for an image into
memory as a block. We can then restart the image decode process
later.
pdf_images therefore consist of the compressed image data for
images. When a pixmap is requested for such an image, the code
checks to see if we have one (of an appropriate size), and if
not, decodes it.
The size hint is used to determine whether it is possible to
subsample the image; currently this is only supported for
JPEGs, but we could add generic subsampling code later.
In order to handle caching the produced images, various changes
have been made to the store and the underlying hash table.
Previously the store was indexed purely by fz_obj keys; we don't
have an fz_obj key any more, so have extended the store by adding
a concept of a key 'type'. A key type is a pointer to a set of
functions that keep/drop/compare and make a hashable key from
a key pointer.
We make a pdf_store.c file that contains functions to offer the
existing fz_obj based functions, and add a new 'type' for keys
(based on the fz_image handle, and the subsample factor) in the
pdf_image.c file.
While working on this, a problem became apparent in the existing
store codel; fz_obj objects had no protection on their reference
counts, hence an interpreter thread could try to alter a ref count
at the same time as a malloc caused an eviction from the store.
This has been solved by using the alloc lock as protection. This in
turn requires some tweaks to the code to make sure we don't try
and keep/drop fz_obj's from the store code while the alloc lock is
held.
A side effect of this work is that when a hash table is created, we
inform it what lock should be used to protect its innards (if any).
If the alloc lock is used, the insert method knows to drop/retake it
to allow it to safely expand the hash table. Callers to the hash
functions have the responsibility of taking/dropping the appropriate
lock, and ensuring that they cope with the possibility that insert
might drop the alloc lock, causing race conditions.
|
|
We only open one instance of freetype per document. We therefore
have to ensure that only 1 call to it takes place at a time. We
introduce a lock for this purpose (FZ_LOCK_FREETYPE), and arrange
to take/release it as required.
We also update the font context so it is properly shared.
|
|
|
|
This is a significant change to the use of locks in MuPDF.
Previously, the user had the option of passing us lock/unlock
functions for a single mutex as part of the allocation struct.
Now we remove these entries from the allocation struct, and
make a separate 'locks' struct. This enables people to use
fz_alloc_default with locking.
If multithreaded operation is required, then the user is
required to create FZ_LOCK_MAX mutexes, which will be locked
or unlocked by MuPDF calling the lock/unlock functions within
the new fz_locks_context structure passed in at context creation.
These mutexes are not required to be recursive (they may be, but
MuPDF should never call them in this way). MuPDF avoids deadlocks
by imposing a locking ordering on itself; a thread will never take
lock n, if it already holds any lock i for which 0 <= i <= n.
Currently, there are 4 locks used within MuPDF.
Lock 0: The alloc lock; taken around all calls to user supplied
(or default) allocation functions. Also taken around all accesses
to the refs field of storable items.
Lock 1: The store lock; taken whenever the store data structures
(specifically the linked list pointers) are accessed.
Lock 2: The file lock; taken whenever a thread is accessing the raw
file. We use the debugging macros to insist that this is held
whenever we do a file based seek or read. We also insist that this
is never held when we resolve an indirect reference, as this can
have the effect of moving the file pointer.
Lock 3: The glyphcache lock; taken whenever a thread calls freetype,
or accesses the glyphcache data structures. This introduces some
complexities w.r.t type3 fonts.
Locking can be hugely problematic, so to ease our minds as to
the correctness of this code, we introduce some debugging macros.
These compile away to nothing unless FITZ_DEBUG_LOCKING is defined.
fz_assert_lock_held(ctx, lock) checks that we hold lock.
fz_assert_lock_not_held(ctx, lock) checks that we do not hold lock.
In addition fz_lock_debug_lock and fz_lock_debug_unlock are used
on every fz_lock/fz_unlock to check the validity of the operation
we are performing - in particular it checks that we do/do not already
hold the lock we are trying to take/drop, and that by taking this
lock we are not violating our defined locking order.
The RESOLVE macro (used throughout the code to check whether we need
to resolve an indirect reference) calls fz_assert_lock_not_held to
ensure that we aren't about to resolve an indirect reference (and
hence move the stream pointer) when the file is locked.
In order to implement the file locking properly, pdf_open_stream
(and friends) now lock the file as a side effect (because they
fz_seek to the start of the stream). The lock is automatically
dropped on an fz_close of such streams.
Previously, the glyph cache was created in a context when it was first
required; this presents problems as it can be shared between several
contexts or not, depending on whether it is created before the
contexts are cloned. We now always create it at startup, so it is
always shared.
This means that we need reference counting for the glyph caches.
Added here.
In fz_render_glyph, we take the glyph cache lock, and check to see
whether the glyph is in the cache. If it is, we bump the refcount,
drop the lock and returned the cached character. If it is not, we
need to render the character.
For freetype based fonts we keep the lock throughout the rendering
process, thus ensuring that freetype is only called in a single
threaded manner.
For type3 fonts, however, we need to invoke the interpreter again
to render the glyph streams. This can require reentrance to this
routine. We therefore drop the glyph cache lock, call the
interpreter to render us our pixmap, and take the lock again.
This dropping and retaking of the lock introduces a possible race
condition; 2 threads may try to render the same character at the
same time. We therefore modify our hash table insert routines to
behave differently if it comes to insert an entry only to find
that an entry with the same key is already there.
We spot this case; if we have just rendered a type3 glyph and when
we try to insert it into the cache discover that someone has beaten
us to it, we just discard our entry and use the cached one.
Hopefully this will seldom be a problem in practise; to solve it
properly would require greater complexity (probably involving
spotting that another thread is already working on the desired
rendering, and sleeping on a semaphore until it completes).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
On extreme downscales, the weights for each pixel can all round to
zero; this results in no weights being stored at all, and causes
either an exception or a SEGV. The simple fix is to ensure that the
first pixel that's actually in range (and there will always be one)
always has a weight of at least 1.
Thanks to malc for finding the test cases that lead to this bugfix.
|