1diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c 2index 5ea1b4c85..8a1171820 100644 3--- a/third_party/lcms/src/cmsopt.c 4+++ b/third_party/lcms/src/cmsopt.c 5@@ -104,6 +104,39 @@ typedef struct { 6 // Simple optimizations ---------------------------------------------------------------------------------------------------------- 7 8 9+// Clamp a fixed point integer to signed 28 bits to avoid overflow in 10+// calculations. Clamp is intended for use with colorants, requiring one bit 11+// for a colorant and another two bits to avoid overflow when combining the 12+// colors. 13+cmsINLINE cmsS1Fixed14Number _FixedClamp(cmsS1Fixed14Number n) { 14+ const cmsS1Fixed14Number max_positive = 268435455; // 0x0FFFFFFF; 15+ const cmsS1Fixed14Number max_negative = -268435456; // 0xF0000000; 16+ // Normally expect the provided number to be in the range [0..1] (but in 17+ // fixed 1.14 format), so can perform a quick check for this typical case 18+ // to reduce number of compares. 19+ const cmsS1Fixed14Number typical_range_mask = 0xFFFF8000; 20+ 21+ if (!(n & typical_range_mask)) 22+ return n; 23+ if (n < max_negative) 24+ return max_negative; 25+ if (n > max_positive) 26+ return max_positive; 27+ return n; 28+} 29+ 30+// Perform one row of matrix multiply with translation for MatShaperEval16(). 31+cmsINLINE cmsInt64Number _MatShaperEvaluateRow(cmsS1Fixed14Number* mat, 32+ cmsS1Fixed14Number off, 33+ cmsS1Fixed14Number r, 34+ cmsS1Fixed14Number g, 35+ cmsS1Fixed14Number b) { 36+ return ((cmsInt64Number)mat[0] * r + 37+ (cmsInt64Number)mat[1] * g + 38+ (cmsInt64Number)mat[2] * b + 39+ off + 0x2000) >> 14; 40+} 41+ 42 // Remove an element in linked chain 43 static 44 void _RemoveElement(cmsStage** head) 45@@ -1527,7 +1560,8 @@ void MatShaperEval16(register const cmsUInt16Number In[], 46 register const void* D) 47 { 48 MatShaper8Data* p = (MatShaper8Data*) D; 49- cmsS1Fixed14Number l1, l2, l3, r, g, b; 50+ cmsS1Fixed14Number r, g, b; 51+ cmsInt64Number l1, l2, l3; 52 cmsUInt32Number ri, gi, bi; 53 54 // In this case (and only in this case!) we can use this simplification since 55@@ -1537,14 +1571,14 @@ void MatShaperEval16(register const cmsUInt16Number In[], 56 bi = In[2] & 0xFFU; 57 58 // Across first shaper, which also converts to 1.14 fixed point 59- r = p->Shaper1R[ri]; 60- g = p->Shaper1G[gi]; 61- b = p->Shaper1B[bi]; 62+ r = _FixedClamp(p->Shaper1R[ri]); 63+ g = _FixedClamp(p->Shaper1G[gi]); 64+ b = _FixedClamp(p->Shaper1B[bi]); 65 66 // Evaluate the matrix in 1.14 fixed point 67- l1 = (p->Mat[0][0] * r + p->Mat[0][1] * g + p->Mat[0][2] * b + p->Off[0] + 0x2000) >> 14; 68- l2 = (p->Mat[1][0] * r + p->Mat[1][1] * g + p->Mat[1][2] * b + p->Off[1] + 0x2000) >> 14; 69- l3 = (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14; 70+ l1 = _MatShaperEvaluateRow(p->Mat[0], p->Off[0], r, g, b); 71+ l2 = _MatShaperEvaluateRow(p->Mat[1], p->Off[1], r, g, b); 72+ l3 = _MatShaperEvaluateRow(p->Mat[2], p->Off[2], r, g, b); 73 74 // Now we have to clip to 0..1.0 range 75 ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384U : (cmsUInt32Number) l1); 76