Mercurial > hgrepos > Python2 > PyMuPDF
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. |
