Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / lcms / src / cmsprecache.c
blob953c4b0da3bbd0a217f6e35bd6e78be28173ab56
1 // Little cms
2 // Copyright (C) 2008 Mozilla Foundation
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the Software
9 // is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
16 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #include "lcms.h"
26 * Helper Macro for allocating precache tables and freeing them
27 * appropriately. We need a macro here so we can select the appropriate member
28 * of the union.
30 #define cmsAllocPrecacheTables(aProf, cacheType, unionMemb, nTables, elemSize, nElems) \
32 unsigned i, j; \
33 for (i = 0; i < nTables; ++i) { \
34 aProf->Precache[cacheType]->Impl.unionMemb.Cache[i] = \
35 _cmsMalloc(elemSize * nElems); \
36 if (aProf->Precache[cacheType]->Impl.unionMemb.Cache[i] == NULL) { \
37 for (j = 0; j < i; ++j) \
38 _cmsFree(aProf->Precache[cacheType]->Impl.unionMemb.Cache[j]); \
39 _cmsFree(aProf->Precache[cacheType]); \
40 aProf->Precache[cacheType] = NULL; \
41 return FALSE; \
42 } \
43 } \
47 * Precaches the results specified in Type in a reference-counted table.
49 * Returns true if the precache succeeded (or if the information was already
50 * precached), false otherwise (including cases where the profile was not
51 * precacheable).
53 LCMSBOOL LCMSEXPORT cmsPrecacheProfile(cmsHPROFILE hProfile,
54 LCMSPRECACHETYPE Type) {
56 // Locals.
57 LPGAMMATABLE GTables[3];
58 LCMSBOOL hasGammaTables;
59 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
60 L16PARAMS p16;
61 unsigned i, j;
63 // Input Validation
64 CMSASSERT(Type < PRECACHE_TYPE_COUNT);
66 /* Do we already have what we need? */
67 if (Icc->Precache[Type] != NULL)
68 return TRUE;
70 /* Determine if we have gamma tables in the profile. */
71 hasGammaTables = cmsIsTag(hProfile, icSigRedTRCTag) &&
72 cmsIsTag(hProfile, icSigGreenTRCTag) &&
73 cmsIsTag(hProfile, icSigBlueTRCTag);
75 /* Zero Out the Gamma Table Pointers. */
76 ZeroMemory(GTables, sizeof(GTables));
78 // Create and zero a precache structure
79 Icc->Precache[Type] = _cmsMalloc(sizeof(LCMSPRECACHE));
80 if (Icc->Precache[Type] == NULL)
81 return FALSE;
82 ZeroMemory(Icc->Precache[Type], sizeof(LCMSPRECACHE));
84 // Grab a Reference to the precache
85 PRECACHE_ADDREF(Icc->Precache[Type]);
87 // Tag the precache with its type (necessary for freeing)
88 Icc->Precache[Type]->Type = Type;
90 // Read the Gamma Tables if we need then
91 if (IS_LI_REVERSE(Type)) {
93 // Read in the reversed Gamma curves
94 if (hasGammaTables) {
95 GTables[0] = cmsReadICCGammaReversed(hProfile, icSigRedTRCTag);
96 GTables[1] = cmsReadICCGammaReversed(hProfile, icSigGreenTRCTag);
97 GTables[2] = cmsReadICCGammaReversed(hProfile, icSigBlueTRCTag);
100 // Check tables
101 if (!GTables[0] || !GTables[1] || !GTables[2]) {
102 _cmsFree(Icc->Precache[Type]);
103 Icc->Precache[Type] = NULL;
104 return FALSE;
107 else if (IS_LI_FORWARD(Type)) {
109 // Read in the Gamma curves
110 if (hasGammaTables) {
111 GTables[0] = cmsReadICCGamma(hProfile, icSigRedTRCTag);
112 GTables[1] = cmsReadICCGamma(hProfile, icSigGreenTRCTag);
113 GTables[2] = cmsReadICCGamma(hProfile, icSigBlueTRCTag);
116 // Check tables
117 if (!GTables[0] || !GTables[1] || !GTables[2]) {
118 _cmsFree(Icc->Precache[Type]);
119 Icc->Precache[Type] = NULL;
120 return FALSE;
124 // Type-Specific Precache Operations
125 switch(Type) {
127 case CMS_PRECACHE_LI1616_REVERSE:
129 // Allocate the precache tables
130 cmsAllocPrecacheTables(Icc, Type, LI1616_REVERSE, 3, sizeof(WORD), (1 << 16));
132 // Calculate the interpolation parameters
133 cmsCalcL16Params(GTables[0]->nEntries, &p16);
135 // Compute the cache
136 for (i = 0; i < 3; ++i)
137 for (j = 0; j < (1 << 16); ++j)
138 Icc->Precache[Type]->Impl.LI1616_REVERSE.Cache[i][j] =
139 cmsLinearInterpLUT16((WORD)j, GTables[i]->GammaTable, &p16);
140 break;
142 case CMS_PRECACHE_LI168_REVERSE:
144 // Allocate the precache tables
145 cmsAllocPrecacheTables(Icc, Type, LI168_REVERSE, 3, sizeof(BYTE), (1 << 16));
147 // Calculate the interpolation parameters
148 cmsCalcL16Params(GTables[0]->nEntries, &p16);
150 // Compute the cache
151 for (i = 0; i < 3; ++i)
152 for (j = 0; j < (1 << 16); ++j)
153 Icc->Precache[Type]->Impl.LI168_REVERSE.Cache[i][j] =
154 RGB_16_TO_8(cmsLinearInterpLUT16((WORD)j, GTables[i]->GammaTable, &p16));
155 break;
157 case CMS_PRECACHE_LI16W_FORWARD:
159 // Allocate the precache tables
160 cmsAllocPrecacheTables(Icc, Type, LI16W_FORWARD, 3, sizeof(Fixed32), (1 << 16));
162 // Calculate the interpolation parameters
163 cmsCalcL16Params(GTables[0]->nEntries, &p16);
165 // Compute the cache
166 for (i = 0; i < 3; ++i)
167 for (j = 0; j < (1 << 16); ++j)
168 Icc->Precache[Type]->Impl.LI16W_FORWARD.Cache[i][j] =
169 cmsLinearInterpFixed((WORD)j, GTables[i]->GammaTable, &p16);
170 break;
172 case CMS_PRECACHE_LI8F_FORWARD:
174 // Allocate the precache tables
175 cmsAllocPrecacheTables(Icc, Type, LI8F_FORWARD, 3, sizeof(FLOAT), 256);
177 // Calculate the interpolation parameters
178 cmsCalcL16Params(GTables[0]->nEntries, &p16);
180 // Compute the cache
181 for (i = 0; i < 3; ++i)
182 for (j = 0; j < 256; ++j)
183 Icc->Precache[Type]->Impl.LI8F_FORWARD.Cache[i][j] =
184 ToFloatDomain(cmsLinearInterpLUT16(RGB_8_TO_16(((BYTE)j)), GTables[i]->GammaTable, &p16));
185 break;
187 default:
188 // TODO: change non-critical asserts to CMS warnings
189 CMSASSERT(0); // Not implemented
190 break;
193 // Free the gamma tables
194 if (hasGammaTables) {
195 CMSASSERT(GTables[0] != NULL);
196 cmsFreeGammaTriple(GTables);
199 // Success
200 return TRUE;
204 * Frees a Precache structure.
206 * This function is invoked by the refcounting mechanism when the refcount on
207 * the precache object drops to zero. If should never be invoked manually.
209 void cmsPrecacheFree(LPLCMSPRECACHE Cache) {
211 // Locals
212 unsigned i;
214 // Validate Input/State
215 CMSASSERT(Cache != NULL);
216 CMSASSERT(Cache->RefCount == 0);
218 // Type-Specific behavior
219 switch(Cache->Type) {
221 case CMS_PRECACHE_LI1616_REVERSE:
222 for (i = 0; i < 3; ++i)
223 _cmsFree(Cache->Impl.LI1616_REVERSE.Cache[i]);
224 break;
226 case CMS_PRECACHE_LI168_REVERSE:
227 for (i = 0; i < 3; ++i)
228 _cmsFree(Cache->Impl.LI168_REVERSE.Cache[i]);
229 break;
231 case CMS_PRECACHE_LI16W_FORWARD:
232 for (i = 0; i < 3; ++i)
233 _cmsFree(Cache->Impl.LI16W_FORWARD.Cache[i]);
234 break;
236 case CMS_PRECACHE_LI8F_FORWARD:
237 for (i = 0; i < 3; ++i)
238 _cmsFree(Cache->Impl.LI8F_FORWARD.Cache[i]);
239 break;
241 default:
242 // TODO: proper warning
243 CMSASSERT(0); // Bad Type
244 break;
247 // Free the structure itself
248 _cmsFree(Cache);