context.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. #ifndef MUPDF_FITZ_CONTEXT_H
  2. #define MUPDF_FITZ_CONTEXT_H
  3. #include "mupdf/fitz/version.h"
  4. #include "mupdf/fitz/system.h"
  5. #include "mupdf/fitz/geometry.h"
  6. /*
  7. Contexts
  8. */
  9. typedef struct fz_alloc_context_s fz_alloc_context;
  10. typedef struct fz_error_context_s fz_error_context;
  11. typedef struct fz_error_stack_slot_s fz_error_stack_slot;
  12. typedef struct fz_id_context_s fz_id_context;
  13. typedef struct fz_warn_context_s fz_warn_context;
  14. typedef struct fz_font_context_s fz_font_context;
  15. typedef struct fz_colorspace_context_s fz_colorspace_context;
  16. typedef struct fz_aa_context_s fz_aa_context;
  17. typedef struct fz_style_context_s fz_style_context;
  18. typedef struct fz_locks_context_s fz_locks_context;
  19. typedef struct fz_tuning_context_s fz_tuning_context;
  20. typedef struct fz_store_s fz_store;
  21. typedef struct fz_glyph_cache_s fz_glyph_cache;
  22. typedef struct fz_document_handler_context_s fz_document_handler_context;
  23. typedef struct fz_output_context_s fz_output_context;
  24. typedef struct fz_context_s fz_context;
  25. struct fz_alloc_context_s
  26. {
  27. void *user;
  28. void *(*malloc)(void *, size_t);
  29. void *(*realloc)(void *, void *, size_t);
  30. void (*free)(void *, void *);
  31. };
  32. struct fz_error_stack_slot_s
  33. {
  34. int code;
  35. fz_jmp_buf buffer;
  36. };
  37. struct fz_error_context_s
  38. {
  39. fz_error_stack_slot *top;
  40. fz_error_stack_slot stack[256];
  41. int errcode;
  42. char message[256];
  43. };
  44. void fz_var_imp(void *);
  45. #define fz_var(var) fz_var_imp((void *)&(var))
  46. /*
  47. Exception macro definitions. Just treat these as a black box - pay no
  48. attention to the man behind the curtain.
  49. */
  50. #define fz_try(ctx) \
  51. { \
  52. if (fz_push_try(ctx)) { \
  53. if (fz_setjmp((ctx)->error->top->buffer) == 0) do \
  54. #define fz_always(ctx) \
  55. while (0); \
  56. } \
  57. if (ctx->error->top->code < 3) { \
  58. ctx->error->top->code++; \
  59. do \
  60. #define fz_catch(ctx) \
  61. while (0); \
  62. } \
  63. } \
  64. if ((ctx->error->top--)->code > 1)
  65. int fz_push_try(fz_context *ctx);
  66. FZ_NORETURN void fz_vthrow(fz_context *ctx, int errcode, const char *, va_list ap);
  67. FZ_NORETURN void fz_throw(fz_context *ctx, int errcode, const char *, ...) __printflike(3, 4);
  68. FZ_NORETURN void fz_rethrow(fz_context *ctx);
  69. void fz_vwarn(fz_context *ctx, const char *fmt, va_list ap);
  70. void fz_warn(fz_context *ctx, const char *fmt, ...) __printflike(2, 3);
  71. const char *fz_caught_message(fz_context *ctx);
  72. int fz_caught(fz_context *ctx);
  73. void fz_rethrow_if(fz_context *ctx, int errcode);
  74. enum
  75. {
  76. FZ_ERROR_NONE = 0,
  77. FZ_ERROR_MEMORY = 1,
  78. FZ_ERROR_GENERIC = 2,
  79. FZ_ERROR_SYNTAX = 3,
  80. FZ_ERROR_TRYLATER = 4,
  81. FZ_ERROR_ABORT = 5,
  82. FZ_ERROR_COUNT
  83. };
  84. /*
  85. fz_flush_warnings: Flush any repeated warnings.
  86. Repeated warnings are buffered, counted and eventually printed
  87. along with the number of repetitions. Call fz_flush_warnings
  88. to force printing of the latest buffered warning and the
  89. number of repetitions, for example to make sure that all
  90. warnings are printed before exiting an application.
  91. Does not throw exceptions.
  92. */
  93. void fz_flush_warnings(fz_context *ctx);
  94. struct fz_context_s
  95. {
  96. void *user;
  97. const fz_alloc_context *alloc;
  98. const fz_locks_context *locks;
  99. fz_id_context *id;
  100. fz_error_context *error;
  101. fz_warn_context *warn;
  102. fz_font_context *font;
  103. fz_colorspace_context *colorspace;
  104. fz_aa_context *aa;
  105. fz_style_context *style;
  106. fz_store *store;
  107. fz_glyph_cache *glyph_cache;
  108. fz_tuning_context *tuning;
  109. fz_document_handler_context *handler;
  110. fz_output_context *output;
  111. };
  112. /*
  113. Specifies the maximum size in bytes of the resource store in
  114. fz_context. Given as argument to fz_new_context.
  115. FZ_STORE_UNLIMITED: Let resource store grow unbounded.
  116. FZ_STORE_DEFAULT: A reasonable upper bound on the size, for
  117. devices that are not memory constrained.
  118. */
  119. enum {
  120. FZ_STORE_UNLIMITED = 0,
  121. FZ_STORE_DEFAULT = 256 << 20,
  122. };
  123. /*
  124. fz_new_context: Allocate context containing global state.
  125. The global state contains an exception stack, resource store,
  126. etc. Most functions in MuPDF take a context argument to be
  127. able to reference the global state. See fz_drop_context for
  128. freeing an allocated context.
  129. alloc: Supply a custom memory allocator through a set of
  130. function pointers. Set to NULL for the standard library
  131. allocator. The context will keep the allocator pointer, so the
  132. data it points to must not be modified or freed during the
  133. lifetime of the context.
  134. locks: Supply a set of locks and functions to lock/unlock
  135. them, intended for multi-threaded applications. Set to NULL
  136. when using MuPDF in a single-threaded applications. The
  137. context will keep the locks pointer, so the data it points to
  138. must not be modified or freed during the lifetime of the
  139. context.
  140. max_store: Maximum size in bytes of the resource store, before
  141. it will start evicting cached resources such as fonts and
  142. images. FZ_STORE_UNLIMITED can be used if a hard limit is not
  143. desired. Use FZ_STORE_DEFAULT to get a reasonable size.
  144. Does not throw exceptions, but may return NULL.
  145. */
  146. fz_context *fz_new_context_imp(const fz_alloc_context *alloc, const fz_locks_context *locks, size_t max_store, const char *version);
  147. #define fz_new_context(alloc, locks, max_store) fz_new_context_imp(alloc, locks, max_store, FZ_VERSION)
  148. /*
  149. fz_clone_context: Make a clone of an existing context.
  150. This function is meant to be used in multi-threaded
  151. applications where each thread requires its own context, yet
  152. parts of the global state, for example caching, is shared.
  153. ctx: Context obtained from fz_new_context to make a copy of.
  154. ctx must have had locks and lock/functions setup when created.
  155. The two contexts will share the memory allocator, resource
  156. store, locks and lock/unlock functions. They will each have
  157. their own exception stacks though.
  158. Does not throw exception, but may return NULL.
  159. */
  160. fz_context *fz_clone_context(fz_context *ctx);
  161. /*
  162. fz_drop_context: Free a context and its global state.
  163. The context and all of its global state is freed, and any
  164. buffered warnings are flushed (see fz_flush_warnings). If NULL
  165. is passed in nothing will happen.
  166. Does not throw exceptions.
  167. */
  168. void fz_drop_context(fz_context *ctx);
  169. /*
  170. fz_set_user_context: Set the user field in the context.
  171. NULL initially, this field can be set to any opaque value
  172. required by the user. It is copied on clones.
  173. Does not throw exceptions.
  174. */
  175. void fz_set_user_context(fz_context *ctx, void *user);
  176. /*
  177. fz_user_context: Read the user field from the context.
  178. Does not throw exceptions.
  179. */
  180. void *fz_user_context(fz_context *ctx);
  181. /*
  182. In order to tune MuPDF's behaviour, certain functions can
  183. (optionally) be provided by callers.
  184. */
  185. /*
  186. fz_tune_image_decode_fn: Given the width and height of an image,
  187. the subsample factor, and the subarea of the image actually
  188. required, the caller can decide whether to decode the whole image
  189. or just a subarea.
  190. arg: The caller supplied opaque argument.
  191. w, h: The width/height of the complete image.
  192. l2factor: The log2 factor for subsampling (i.e. image will be
  193. decoded to (w>>l2factor, h>>l2factor)).
  194. subarea: The actual subarea required for the current operation.
  195. The tuning function is allowed to increase this in size if required.
  196. */
  197. typedef void (fz_tune_image_decode_fn)(void *arg, int w, int h, int l2factor, fz_irect *subarea);
  198. /*
  199. fz_tune_image_scale_fn: Given the source width and height of
  200. image, together with the actual required width and height,
  201. decide whether we should use mitchell scaling.
  202. arg: The caller supplied opaque argument.
  203. dst_w, dst_h: The actual width/height required on the target device.
  204. src_w, src_h: The source width/height of the image.
  205. Return 0 not to use the Mitchell scaler, 1 to use the Mitchell scaler. All
  206. other values reserved.
  207. */
  208. typedef int (fz_tune_image_scale_fn)(void *arg, int dst_w, int dst_h, int src_w, int src_h);
  209. /*
  210. fz_tune_image_decode: Set the tuning function to use for
  211. image decode.
  212. image_decode: Function to use.
  213. arg: Opaque argument to be passed to tuning function.
  214. */
  215. void fz_tune_image_decode(fz_context *ctx, fz_tune_image_decode_fn *image_decode, void *arg);
  216. /*
  217. fz_tune_image_scale: Set the tuning function to use for
  218. image scaling.
  219. image_scale: Function to use.
  220. arg: Opaque argument to be passed to tuning function.
  221. */
  222. void fz_tune_image_scale(fz_context *ctx, fz_tune_image_scale_fn *image_scale, void *arg);
  223. /*
  224. fz_aa_level: Get the number of bits of antialiasing we are
  225. using (for graphics). Between 0 and 8.
  226. */
  227. int fz_aa_level(fz_context *ctx);
  228. /*
  229. fz_set_aa_level: Set the number of bits of antialiasing we should
  230. use (for both text and graphics).
  231. bits: The number of bits of antialiasing to use (values are clamped
  232. to within the 0 to 8 range).
  233. */
  234. void fz_set_aa_level(fz_context *ctx, int bits);
  235. /*
  236. fz_text_aa_level: Get the number of bits of antialiasing we are
  237. using for text. Between 0 and 8.
  238. */
  239. int fz_text_aa_level(fz_context *ctx);
  240. /*
  241. fz_set_text_aa_level: Set the number of bits of antialiasing we
  242. should use for text.
  243. bits: The number of bits of antialiasing to use (values are clamped
  244. to within the 0 to 8 range).
  245. */
  246. void fz_set_text_aa_level(fz_context *ctx, int bits);
  247. /*
  248. fz_graphics_aa_level: Get the number of bits of antialiasing we are
  249. using for graphics. Between 0 and 8.
  250. */
  251. int fz_graphics_aa_level(fz_context *ctx);
  252. /*
  253. fz_set_graphics_aa_level: Set the number of bits of antialiasing we
  254. should use for graphics.
  255. bits: The number of bits of antialiasing to use (values are clamped
  256. to within the 0 to 8 range).
  257. */
  258. void fz_set_graphics_aa_level(fz_context *ctx, int bits);
  259. /*
  260. fz_graphics_min_line_width: Get the minimum line width to be
  261. used for stroked lines.
  262. min_line_width: The minimum line width to use (in pixels).
  263. */
  264. float fz_graphics_min_line_width(fz_context *ctx);
  265. /*
  266. fz_set_graphics_min_line_width: Set the minimum line width to be
  267. used for stroked lines.
  268. min_line_width: The minimum line width to use (in pixels).
  269. */
  270. void fz_set_graphics_min_line_width(fz_context *ctx, float min_line_width);
  271. /*
  272. fz_user_css: Get the user stylesheet source text.
  273. */
  274. const char *fz_user_css(fz_context *ctx);
  275. /*
  276. fz_set_user_css: Set the user stylesheet source text for use with HTML and EPUB.
  277. */
  278. void fz_set_user_css(fz_context *ctx, const char *text);
  279. /*
  280. fz_use_document_css: Return whether to respect document styles in HTML and EPUB.
  281. */
  282. int fz_use_document_css(fz_context *ctx);
  283. /*
  284. fz_set_use_document_css: Toggle whether to respect document styles in HTML and EPUB.
  285. */
  286. void fz_set_use_document_css(fz_context *ctx, int use);
  287. /*
  288. Locking functions
  289. MuPDF is kept deliberately free of any knowledge of particular
  290. threading systems. As such, in order for safe multi-threaded
  291. operation, we rely on callbacks to client provided functions.
  292. A client is expected to provide FZ_LOCK_MAX number of mutexes,
  293. and a function to lock/unlock each of them. These may be
  294. recursive mutexes, but do not have to be.
  295. If a client does not intend to use multiple threads, then it
  296. may pass NULL instead of a lock structure.
  297. In order to avoid deadlocks, we have one simple rule
  298. internally as to how we use locks: We can never take lock n
  299. when we already hold any lock i, where 0 <= i <= n. In order
  300. to verify this, we have some debugging code, that can be
  301. enabled by defining FITZ_DEBUG_LOCKING.
  302. */
  303. struct fz_locks_context_s
  304. {
  305. void *user;
  306. void (*lock)(void *user, int lock);
  307. void (*unlock)(void *user, int lock);
  308. };
  309. enum {
  310. FZ_LOCK_ALLOC = 0,
  311. FZ_LOCK_FREETYPE,
  312. FZ_LOCK_GLYPHCACHE,
  313. FZ_LOCK_MAX
  314. };
  315. /*
  316. Memory Allocation and Scavenging:
  317. All calls to MuPDF's allocator functions pass through to the
  318. underlying allocators passed in when the initial context is
  319. created, after locks are taken (using the supplied locking function)
  320. to ensure that only one thread at a time calls through.
  321. If the underlying allocator fails, MuPDF attempts to make room for
  322. the allocation by evicting elements from the store, then retrying.
  323. Any call to allocate may then result in several calls to the underlying
  324. allocator, and result in elements that are only referred to by the
  325. store being freed.
  326. */
  327. /*
  328. fz_malloc: Allocate a block of memory (with scavenging)
  329. size: The number of bytes to allocate.
  330. Returns a pointer to the allocated block. May return NULL if size is
  331. 0. Throws exception on failure to allocate.
  332. */
  333. void *fz_malloc(fz_context *ctx, size_t size);
  334. /*
  335. fz_calloc: Allocate a zeroed block of memory (with scavenging)
  336. count: The number of objects to allocate space for.
  337. size: The size (in bytes) of each object.
  338. Returns a pointer to the allocated block. May return NULL if size
  339. and/or count are 0. Throws exception on failure to allocate.
  340. */
  341. void *fz_calloc(fz_context *ctx, size_t count, size_t size);
  342. /*
  343. fz_malloc_struct: Allocate storage for a structure (with scavenging),
  344. clear it, and (in Memento builds) tag the pointer as belonging to a
  345. struct of this type.
  346. CTX: The context.
  347. STRUCT: The structure type.
  348. Returns a pointer to allocated (and cleared) structure. Throws
  349. exception on failure to allocate.
  350. */
  351. #define fz_malloc_struct(CTX, STRUCT) \
  352. ((STRUCT *)Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT))
  353. /*
  354. fz_malloc_array: Allocate a block of (non zeroed) memory (with
  355. scavenging). Equivalent to fz_calloc without the memory clearing.
  356. count: The number of objects to allocate space for.
  357. size: The size (in bytes) of each object.
  358. Returns a pointer to the allocated block. May return NULL if size
  359. and/or count are 0. Throws exception on failure to allocate.
  360. */
  361. void *fz_malloc_array(fz_context *ctx, size_t count, size_t size);
  362. /*
  363. fz_resize_array: Resize a block of memory (with scavenging).
  364. p: The existing block to resize
  365. count: The number of objects to resize to.
  366. size: The size (in bytes) of each object.
  367. Returns a pointer to the resized block. May return NULL if size
  368. and/or count are 0. Throws exception on failure to resize (original
  369. block is left unchanged).
  370. */
  371. void *fz_resize_array(fz_context *ctx, void *p, size_t count, size_t size);
  372. /*
  373. fz_strdup: Duplicate a C string (with scavenging)
  374. s: The string to duplicate.
  375. Returns a pointer to a duplicated string. Throws exception on failure
  376. to allocate.
  377. */
  378. char *fz_strdup(fz_context *ctx, const char *s);
  379. /*
  380. fz_free: Frees an allocation.
  381. Does not throw exceptions.
  382. */
  383. void fz_free(fz_context *ctx, void *p);
  384. /*
  385. fz_malloc_no_throw: Allocate a block of memory (with scavenging)
  386. size: The number of bytes to allocate.
  387. Returns a pointer to the allocated block. May return NULL if size is
  388. 0. Returns NULL on failure to allocate.
  389. */
  390. void *fz_malloc_no_throw(fz_context *ctx, size_t size);
  391. /*
  392. fz_calloc_no_throw: Allocate a zeroed block of memory (with scavenging)
  393. count: The number of objects to allocate space for.
  394. size: The size (in bytes) of each object.
  395. Returns a pointer to the allocated block. May return NULL if size
  396. and/or count are 0. Returns NULL on failure to allocate.
  397. */
  398. void *fz_calloc_no_throw(fz_context *ctx, size_t count, size_t size);
  399. /*
  400. fz_malloc_array_no_throw: Allocate a block of (non zeroed) memory
  401. (with scavenging). Equivalent to fz_calloc_no_throw without the
  402. memory clearing.
  403. count: The number of objects to allocate space for.
  404. size: The size (in bytes) of each object.
  405. Returns a pointer to the allocated block. May return NULL if size
  406. and/or count are 0. Returns NULL on failure to allocate.
  407. */
  408. void *fz_malloc_array_no_throw(fz_context *ctx, size_t count, size_t size);
  409. /*
  410. fz_resize_array_no_throw: Resize a block of memory (with scavenging).
  411. p: The existing block to resize
  412. count: The number of objects to resize to.
  413. size: The size (in bytes) of each object.
  414. Returns a pointer to the resized block. May return NULL if size
  415. and/or count are 0. Returns NULL on failure to resize (original
  416. block is left unchanged).
  417. */
  418. void *fz_resize_array_no_throw(fz_context *ctx, void *p, size_t count, size_t size);
  419. /*
  420. fz_strdup_no_throw: Duplicate a C string (with scavenging)
  421. s: The string to duplicate.
  422. Returns a pointer to a duplicated string. Returns NULL on failure
  423. to allocate.
  424. */
  425. char *fz_strdup_no_throw(fz_context *ctx, const char *s);
  426. /*
  427. fz_gen_id: Generate an id (guaranteed unique within this family of
  428. contexts).
  429. */
  430. int fz_gen_id(fz_context *ctx);
  431. struct fz_warn_context_s
  432. {
  433. char message[256];
  434. int count;
  435. };
  436. /* Default allocator */
  437. extern fz_alloc_context fz_alloc_default;
  438. /* Default locks */
  439. extern fz_locks_context fz_locks_default;
  440. #if defined(MEMENTO) || !defined(NDEBUG)
  441. #define FITZ_DEBUG_LOCKING
  442. #endif
  443. #ifdef FITZ_DEBUG_LOCKING
  444. void fz_assert_lock_held(fz_context *ctx, int lock);
  445. void fz_assert_lock_not_held(fz_context *ctx, int lock);
  446. void fz_lock_debug_lock(fz_context *ctx, int lock);
  447. void fz_lock_debug_unlock(fz_context *ctx, int lock);
  448. #else
  449. #define fz_assert_lock_held(A,B) do { } while (0)
  450. #define fz_assert_lock_not_held(A,B) do { } while (0)
  451. #define fz_lock_debug_lock(A,B) do { } while (0)
  452. #define fz_lock_debug_unlock(A,B) do { } while (0)
  453. #endif /* !FITZ_DEBUG_LOCKING */
  454. static inline void
  455. fz_lock(fz_context *ctx, int lock)
  456. {
  457. fz_lock_debug_lock(ctx, lock);
  458. ctx->locks->lock(ctx->locks->user, lock);
  459. }
  460. static inline void
  461. fz_unlock(fz_context *ctx, int lock)
  462. {
  463. fz_lock_debug_unlock(ctx, lock);
  464. ctx->locks->unlock(ctx->locks->user, lock);
  465. }
  466. static inline void *
  467. fz_keep_imp(fz_context *ctx, void *p, int *refs)
  468. {
  469. if (p)
  470. {
  471. if (*refs > 0)
  472. (void)Memento_takeRef(p);
  473. fz_lock(ctx, FZ_LOCK_ALLOC);
  474. if (*refs > 0)
  475. ++*refs;
  476. fz_unlock(ctx, FZ_LOCK_ALLOC);
  477. }
  478. return p;
  479. }
  480. static inline void *
  481. fz_keep_imp8(fz_context *ctx, void *p, int8_t *refs)
  482. {
  483. if (p)
  484. {
  485. if (*refs > 0)
  486. (void)Memento_takeRef(p);
  487. fz_lock(ctx, FZ_LOCK_ALLOC);
  488. if (*refs > 0)
  489. ++*refs;
  490. fz_unlock(ctx, FZ_LOCK_ALLOC);
  491. }
  492. return p;
  493. }
  494. static inline void *
  495. fz_keep_imp16(fz_context *ctx, void *p, int16_t *refs)
  496. {
  497. if (p)
  498. {
  499. if (*refs > 0)
  500. (void)Memento_takeRef(p);
  501. fz_lock(ctx, FZ_LOCK_ALLOC);
  502. if (*refs > 0)
  503. ++*refs;
  504. fz_unlock(ctx, FZ_LOCK_ALLOC);
  505. }
  506. return p;
  507. }
  508. static inline int
  509. fz_drop_imp(fz_context *ctx, void *p, int *refs)
  510. {
  511. if (p)
  512. {
  513. int drop;
  514. if (*refs > 0)
  515. (void)Memento_dropRef(p);
  516. fz_lock(ctx, FZ_LOCK_ALLOC);
  517. if (*refs > 0)
  518. drop = --*refs == 0;
  519. else
  520. drop = 0;
  521. fz_unlock(ctx, FZ_LOCK_ALLOC);
  522. return drop;
  523. }
  524. return 0;
  525. }
  526. static inline int
  527. fz_drop_imp8(fz_context *ctx, void *p, int8_t *refs)
  528. {
  529. if (p)
  530. {
  531. int drop;
  532. if (*refs > 0)
  533. (void)Memento_dropRef(p);
  534. fz_lock(ctx, FZ_LOCK_ALLOC);
  535. if (*refs > 0)
  536. drop = --*refs == 0;
  537. else
  538. drop = 0;
  539. fz_unlock(ctx, FZ_LOCK_ALLOC);
  540. return drop;
  541. }
  542. return 0;
  543. }
  544. static inline int
  545. fz_drop_imp16(fz_context *ctx, void *p, int16_t *refs)
  546. {
  547. if (p)
  548. {
  549. int drop;
  550. if (*refs > 0)
  551. (void)Memento_dropRef(p);
  552. fz_lock(ctx, FZ_LOCK_ALLOC);
  553. if (*refs > 0)
  554. drop = --*refs == 0;
  555. else
  556. drop = 0;
  557. fz_unlock(ctx, FZ_LOCK_ALLOC);
  558. return drop;
  559. }
  560. return 0;
  561. }
  562. #endif