comparison mupdf-source/thirdparty/lcms2/doc/WhyThisFork.txt @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 LCMS 2.10.MT
2 ============
3
4 Why does this fork exist?
5 ~~~~~~~~~~~~~~~~~~~~~~~~~
6
7 We, Artifex Software, use LCMS 2 in both our Ghostscript and MuPDF
8 projects. It's a great library that performs well, and does almost
9 exactly what we want.
10
11 Almost.
12
13 In the course of pulling LCMS 2 into MuPDF, we hit some problems
14 with the library (described in more detail below). We've changed
15 the code to fix these problems, and therefore released this
16 version of the library.
17
18
19 Why don't you just pass the changes back to mainline LCMS?
20 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 Sadly, the changes we've made require changes to some of the API
23 to LCMS. We consider these changes to be pretty minor, and to
24 improve the overall API, but they are unavoidable.
25
26 You can't just drop this version of the library into an existing
27 project that uses vanilla LCMS and expect it to work. You will
28 need to make some changes in your code. Small ones, but changes
29 nonetheless.
30
31 We have offered these changes upstream, with a view to getting
32 them adopted into mainstream LCMS - perhaps as LCMS 3. Marti
33 Maria, the original author of LCMS is considering them at the
34 moment, but no decision has been made.
35
36 Marti has plans of his own for LCMS, so until such time as we
37 figure out a mutually satisfactory way of working, we're doing
38 this separate release.
39
40
41 So what problem was this intended to solve?
42 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43
44 Put simply, we ran into problems with using LCMS in a multi-threaded
45 environment.
46
47 A few years ago, Marti kindly made some changes within LittleCMS
48 to enable us to safely use LCMS with Ghostscript when run with
49 multiple threads.
50
51 Specifically, Ghostscript needed to use different allocators from
52 each thread. In order to account for this, Marti added the idea
53 of the 'cmsContext'. These would carry a 'void *UserData' value
54 that could be retrieved in the allocators. By using a different
55 cmsContext in each thread, we could therefore pass thread specific
56 information through LCMS and safely have it reach the allocators.
57
58 In order to make this change without breaking the existing API
59 Marti added new functions, suffixed with THR, that took these
60 cmsContext's.
61
62 So where in old lcms we had:
63
64 CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
65
66 we now also had:
67
68 CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
69
70 Internally within LCMS, the cmsContext values were often stored
71 within things like profiles and links. For Ghostscript this was
72 absolutely fine, because we didn't share profiles or links between
73 different threads.
74
75 For MuPDF, however, this was a significant restriction. MuPDF is
76 designed as a C level library from which people can build applications.
77 Data objects are reference counted, and are designed to be able to
78 be passed around the system as required. It would be almost impossible
79 to enforce the idea that profiles and links can only be used within
80 the original thread (cmsContext) within which they were created.
81 Also new versions of Ghostscript will also share profiles and links
82 among threads to enhance performance with multi-threaded rendering.
83
84 Lastly, Ghostscript made use of cmsChangeBuffersFormat to switch the
85 input or output data format (planar, bytes per component, etc.) to
86 allow a link profile to be re-used without the computation needed to
87 create a new link profile. Since the input and output format are
88 stored within the link profile, one thread changing the format while
89 another thread was using it for color transform would cause problems.
90
91 So what changes have been made?
92 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93
94 The changes are very simple and systematic.
95
96 1) Every API function (or at least those that might allocate) now takes
97 a cmsContext pointer.
98
99 2) cmsContexts are now passed explicitly throughout the system. They
100 are never stored in any structures.
101
102 3) Accordingly, we have removed the 'THR' API functions (as they no
103 longer serve any purpose).
104
105 4) We have removed the cmsChangeBuffersFormat function (use of which
106 could lead to a link profile being changed by one thread while it
107 was in use by another) and replaced it with a thread safe alternative,
108 cmsCloneTransformChangingFormats. This creates a new transform that
109 shares the underlying tables of the original transform, but with
110 new buffer format handlers. Since the underlying tables for the link
111 are shared, the cost of cloning the profile is very low.
112
113 In addition, we've made 1 other change that breaks the ABI, but not
114 the API:
115
116 5) The organisation of the flags word used to describe the format of
117 input/output pixels has been altered to accommodate more 'extra'
118 channels (now a maximum of 63 rather than 7).
119
120 Finally:
121
122 6) We have renamed lcms2.h to be lcms2mt.h.
123
124 7) We have tweaked the LCMS_VERSION value (and some of the code
125 that reads it), to ensure that people don't link binary plugins
126 expecting other versions against us without an error being given.
127
128
129 So what's the plan from here?
130 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132 Well, at the very least we hope to keep pulling fixes from mainline
133 LCMS into this version. We (Artifex Software) need to keep it up to
134 date and secure for our use of the library.
135
136 In the fullness of time we'd love to see these fixes folded back
137 into a new LCMS release, but this will have to wait for this to be
138 a convenient time for Marti.
139
140
141 So where should we report bugs?
142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143
144 Report bugs to us, by all means, but please also report them to Marti.
145 He's likely to be in a far better position to evaluate potential
146 problems and fixes than we are - this is his library after all.
147 Ideally every problem that gets fixed in mainline LCMS should get
148 pulled into our version.
149
150 Indeed, to keep this simple, we don't really want to diverge our
151 version from mainline more than we have to.