Fixed low resolution for cached images.

Regenerate the image cache if a larger jpeg2000 image is requested.
It is the correction of the error that occurred in this
change - https://pdfium-review.googlesource.com/c/pdfium/+/99970

Bug: pdfium:1924,chromium:1408476

Change-Id: I9fd2769ea480c24fab99ee80244ea24764aa9ada
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/103150
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/BUILD.gn b/core/fpdfapi/page/BUILD.gn
index 79aeda5..51b4adf 100644
--- a/core/fpdfapi/page/BUILD.gn
+++ b/core/fpdfapi/page/BUILD.gn
@@ -141,6 +141,7 @@
     "cpdf_colorspace_unittest.cpp",
     "cpdf_devicecs_unittest.cpp",
     "cpdf_function_unittest.cpp",
+    "cpdf_pageimagecache_unittest.cpp",
     "cpdf_pageobjectholder_unittest.cpp",
     "cpdf_psengine_unittest.cpp",
     "cpdf_streamcontentparser_unittest.cpp",
@@ -149,6 +150,7 @@
   deps = [
     ":page",
     "../parser",
+    "../render",
   ]
   pdfium_root_dir = "../../../"
 }
diff --git a/core/fpdfapi/page/cpdf_pageimagecache.cpp b/core/fpdfapi/page/cpdf_pageimagecache.cpp
index 63a1ad6..ae8f72e 100644
--- a/core/fpdfapi/page/cpdf_pageimagecache.cpp
+++ b/core/fpdfapi/page/cpdf_pageimagecache.cpp
@@ -176,7 +176,7 @@
     CPDF_ColorSpace::Family eFamily,
     bool bLoadMask,
     const CFX_Size& max_size_required) {
-  if (m_pCachedBitmap) {
+  if (m_pCachedBitmap && IsCacheValid(max_size_required)) {
     m_pCurBitmap = m_pCachedBitmap;
     m_pCurMask = m_pCachedMask;
     return CPDF_DIB::LoadState::kSuccess;
@@ -186,6 +186,8 @@
   CPDF_DIB::LoadState ret = m_pCurBitmap.AsRaw<CPDF_DIB>()->StartLoadDIBBase(
       true, pFormResources, pPageResources, bStdCS, eFamily, bLoadMask,
       max_size_required);
+  m_bCachedSetMaxSizeRequired =
+      (max_size_required.width != 0 && max_size_required.height != 0);
   if (ret == CPDF_DIB::LoadState::kContinue)
     return CPDF_DIB::LoadState::kContinue;
 
@@ -238,3 +240,16 @@
   if (m_pCachedMask)
     m_dwCacheSize += m_pCachedMask->GetEstimatedImageMemoryBurden();
 }
+
+bool CPDF_PageImageCache::Entry::IsCacheValid(
+    const CFX_Size& max_size_required) const {
+  if (!m_bCachedSetMaxSizeRequired) {
+    return true;
+  }
+  if (max_size_required.width == 0 && max_size_required.height == 0) {
+    return false;
+  }
+
+  return (m_pCachedBitmap->GetWidth() >= max_size_required.width) &&
+         (m_pCachedBitmap->GetHeight() >= max_size_required.height);
+}
diff --git a/core/fpdfapi/page/cpdf_pageimagecache.h b/core/fpdfapi/page/cpdf_pageimagecache.h
index 82702c5..5184ff6 100644
--- a/core/fpdfapi/page/cpdf_pageimagecache.h
+++ b/core/fpdfapi/page/cpdf_pageimagecache.h
@@ -80,6 +80,7 @@
    private:
     void ContinueGetCachedBitmap(CPDF_PageImageCache* pPageImageCache);
     void CalcSize();
+    bool IsCacheValid(const CFX_Size& max_size_required) const;
 
     uint32_t m_dwTimeCount = 0;
     uint32_t m_MatteColor = 0;
@@ -89,6 +90,7 @@
     RetainPtr<CFX_DIBBase> m_pCurMask;
     RetainPtr<CFX_DIBBase> m_pCachedBitmap;
     RetainPtr<CFX_DIBBase> m_pCachedMask;
+    bool m_bCachedSetMaxSizeRequired = false;
   };
 
   void ClearImageCacheEntry(const CPDF_Stream* pStream);
diff --git a/core/fpdfapi/page/cpdf_pageimagecache_unittest.cpp b/core/fpdfapi/page/cpdf_pageimagecache_unittest.cpp
new file mode 100644
index 0000000..34e436f
--- /dev/null
+++ b/core/fpdfapi/page/cpdf_pageimagecache_unittest.cpp
@@ -0,0 +1,81 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fpdfapi/page/cpdf_pageimagecache.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "core/fpdfapi/page/cpdf_docpagedata.h"
+#include "core/fpdfapi/page/cpdf_image.h"
+#include "core/fpdfapi/page/cpdf_imageobject.h"
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/page/cpdf_pagemodule.h"
+#include "core/fpdfapi/parser/cpdf_parser.h"
+#include "core/fpdfapi/render/cpdf_docrenderdata.h"
+#include "core/fxcrt/fx_stream.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/utils/path_service.h"
+
+TEST(CPDFPageImageCache, RenderBug1924) {
+  // If you render a page with a JPEG2000 image as a thumbnail (small picture)
+  // first, the image that gets cached has a low resolution. If you afterwards
+  // render it full-size, you should get a larger image - the image cache will
+  // be regenerate.
+
+  CPDF_PageModule::Create();
+  {
+    std::string file_path;
+    ASSERT_TRUE(PathService::GetTestFilePath("jpx_lzw.pdf", &file_path));
+    auto document =
+        std::make_unique<CPDF_Document>(std::make_unique<CPDF_DocRenderData>(),
+                                        std::make_unique<CPDF_DocPageData>());
+    ASSERT_EQ(document->LoadDoc(
+                  IFX_SeekableReadStream::CreateFromFilename(file_path.c_str()),
+                  nullptr),
+              CPDF_Parser::SUCCESS);
+
+    RetainPtr<CPDF_Dictionary> page_dict =
+        document->GetMutablePageDictionary(0);
+    ASSERT_TRUE(page_dict);
+    auto page =
+        pdfium::MakeRetain<CPDF_Page>(document.get(), std::move(page_dict));
+    page->AddPageImageCache();
+    page->ParseContent();
+
+    CPDF_PageImageCache* page_image_cache = page->GetPageImageCache();
+    ASSERT_TRUE(page_image_cache);
+
+    CPDF_PageObject* page_obj = page->GetPageObjectByIndex(0);
+    ASSERT_TRUE(page_obj);
+    CPDF_ImageObject* image = page_obj->AsImage();
+    ASSERT_TRUE(image);
+
+    // Render with small scale.
+    bool should_continue = page_image_cache->StartGetCachedBitmap(
+        image->GetImage(), nullptr, page->GetMutablePageResources(), true,
+        CPDF_ColorSpace::Family::kICCBased, false, {50, 50});
+    while (should_continue)
+      should_continue = page_image_cache->Continue(nullptr);
+
+    RetainPtr<CFX_DIBBase> bitmap_small = page_image_cache->DetachCurBitmap();
+
+    // And render with large scale.
+    should_continue = page_image_cache->StartGetCachedBitmap(
+        image->GetImage(), nullptr, page->GetMutablePageResources(), true,
+        CPDF_ColorSpace::Family::kICCBased, false, {100, 100});
+    while (should_continue)
+      should_continue = page_image_cache->Continue(nullptr);
+
+    RetainPtr<CFX_DIBBase> bitmap_large = page_image_cache->DetachCurBitmap();
+
+    ASSERT_GT(bitmap_large->GetWidth(), bitmap_small->GetWidth());
+    ASSERT_GT(bitmap_large->GetHeight(), bitmap_small->GetHeight());
+
+    ASSERT_TRUE(page->AsPDFPage());
+    page->AsPDFPage()->ClearView();
+  }
+  CPDF_PageModule::Destroy();
+}