WhyThisFork.txt 5.7 KB

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