File D119700-FF117.patch of Package firefox

diff -urN firefox-117.0.1-orig/image/decoders/nsJXLDecoder.cpp firefox-117.0.1/image/decoders/nsJXLDecoder.cpp
--- firefox-117.0.1-orig/image/decoders/nsJXLDecoder.cpp	2023-09-12 10:42:00.000000000 +0900
+++ firefox-117.0.1/image/decoders/nsJXLDecoder.cpp	2023-09-23 10:15:44.993482583 +0900
@@ -45,9 +45,16 @@
              Transition::TerminateSuccess()),
       mDecoder(JxlDecoderMake(nullptr)),
       mParallelRunner(
-          JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())) {
-  JxlDecoderSubscribeEvents(mDecoder.get(),
-                            JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
+          JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())),
+      mUsePipeTransform(true),
+      mCMSLine(nullptr) {
+  int events = JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE;
+
+  if (mCMSMode != CMSMode::Off) {
+    events |= JXL_DEC_COLOR_ENCODING;
+  }
+
+  JxlDecoderSubscribeEvents(mDecoder.get(), events);
   JxlDecoderSetParallelRunner(mDecoder.get(), JxlThreadParallelRunner,
                               mParallelRunner.get());
 
@@ -58,6 +65,10 @@
 nsJXLDecoder::~nsJXLDecoder() {
   MOZ_LOG(sJXLLog, LogLevel::Debug,
           ("[this=%p] nsJXLDecoder::~nsJXLDecoder", this));
+
+  if (mCMSLine) {
+    free(mCMSLine);
+  }
 }
 
 size_t nsJXLDecoder::PreferredThreadCount() {
@@ -112,35 +123,111 @@
       case JXL_DEC_BASIC_INFO: {
         JXL_TRY(JxlDecoderGetBasicInfo(mDecoder.get(), &mInfo));
         PostSize(mInfo.xsize, mInfo.ysize);
+
         if (mInfo.alpha_bits > 0) {
           PostHasTransparency();
         }
+
         if (IsMetadataDecode()) {
           return Transition::TerminateSuccess();
         }
+
+        // If CMS is off or the image is RGB, always output in RGBA.
+        // If the image is grayscale, then the pipe transform can't be used.
+        if (mCMSMode != CMSMode::Off) {
+          mChannels = mInfo.num_color_channels == 1
+                          ? 1 + (mInfo.alpha_bits > 0 ? 1 : 0)
+                          : 4;
+        } else {
+          mChannels = 4;
+        }
+
+        mFormat = {mChannels, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
+
         break;
       }
 
       case JXL_DEC_NEED_IMAGE_OUT_BUFFER: {
         size_t size = 0;
-        JxlPixelFormat format{4, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
-        JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &format, &size));
+        JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &mFormat, &size));
 
         mOutBuffer.clear();
         JXL_TRY_BOOL(mOutBuffer.growBy(size));
-        JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &format,
+        JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &mFormat,
                                             mOutBuffer.begin(), size));
         break;
       }
 
+      case JXL_DEC_COLOR_ENCODING: {
+        size_t size = 0;
+        JXL_TRY(JxlDecoderGetICCProfileSize(
+            mDecoder.get(), JXL_COLOR_PROFILE_TARGET_DATA, &size))
+        std::vector<uint8_t> icc_profile(size);
+        JXL_TRY(JxlDecoderGetColorAsICCProfile(mDecoder.get(),
+                                               JXL_COLOR_PROFILE_TARGET_DATA,
+                                               icc_profile.data(), size))
+
+        mInProfile = qcms_profile_from_memory((char*)icc_profile.data(), size);
+
+        uint32_t profileSpace = qcms_profile_get_color_space(mInProfile);
+
+        // Skip color management if color profile is not compatible with number
+        // of channels.
+        if (profileSpace != icSigRgbData &&
+            (mInfo.num_color_channels == 3 || profileSpace != icSigGrayData)) {
+          break;
+        }
+
+        mUsePipeTransform =
+            profileSpace == icSigRgbData && mInfo.num_color_channels == 3;
+
+        qcms_data_type inType;
+        if (mInfo.num_color_channels == 3) {
+          inType = QCMS_DATA_RGBA_8;
+        } else if (mInfo.alpha_bits > 0) {
+          inType = QCMS_DATA_GRAYA_8;
+        } else {
+          inType = QCMS_DATA_GRAY_8;
+        }
+
+        if (!mUsePipeTransform) {
+          mCMSLine =
+              static_cast<uint8_t*>(malloc(sizeof(uint32_t) * mInfo.xsize));
+        }
+
+        int intent = gfxPlatform::GetRenderingIntent();
+        if (intent == -1) {
+          intent = qcms_profile_get_rendering_intent(mInProfile);
+        }
+
+        mTransform =
+            qcms_transform_create(mInProfile, inType, GetCMSOutputProfile(),
+                                  QCMS_DATA_RGBA_8, (qcms_intent)intent);
+
+        break;
+      }
+
       case JXL_DEC_FULL_IMAGE: {
         OrientedIntSize size(mInfo.xsize, mInfo.ysize);
+
+        qcms_transform* pipeTransform =
+            mUsePipeTransform ? mTransform : nullptr;
+
         Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
             this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8,
-            SurfaceFormat::OS_RGBA, Nothing(), nullptr, SurfacePipeFlags());
+            SurfaceFormat::OS_RGBA, Nothing(), pipeTransform,
+            SurfacePipeFlags());
+
         for (uint8_t* rowPtr = mOutBuffer.begin(); rowPtr < mOutBuffer.end();
-             rowPtr += mInfo.xsize * 4) {
-          pipe->WriteBuffer(reinterpret_cast<uint32_t*>(rowPtr));
+             rowPtr += mInfo.xsize * mChannels) {
+          uint8_t* rowToWrite = rowPtr;
+
+          if (!mUsePipeTransform && mTransform) {
+            qcms_transform_data(mTransform, rowToWrite, mCMSLine, mInfo.xsize);
+            rowToWrite = mCMSLine;
+          }
+
+          pipe->WriteBuffer(reinterpret_cast<uint32_t*>(rowToWrite));
         }
 
         if (Maybe<SurfaceInvalidRect> invalidRect = pipe->TakeInvalidRect()) {
diff -urN firefox-117.0.1-orig/image/decoders/nsJXLDecoder.h firefox-117.0.1/image/decoders/nsJXLDecoder.h
--- firefox-117.0.1-orig/image/decoders/nsJXLDecoder.h	2023-09-12 10:42:00.000000000 +0900
+++ firefox-117.0.1/image/decoders/nsJXLDecoder.h	2023-09-23 10:10:32.163440585 +0900
@@ -47,7 +47,12 @@
   JxlThreadParallelRunnerPtr mParallelRunner;
   Vector<uint8_t> mBuffer;
   Vector<uint8_t> mOutBuffer;
-  JxlBasicInfo mInfo{};
+  JxlBasicInfo mInfo;
+  JxlPixelFormat mFormat;
+
+  bool mUsePipeTransform;
+  uint8_t mChannels;
+  uint8_t* mCMSLine;
 };
 
 }  // namespace mozilla::image
openSUSE Build Service is sponsored by