M68: Better determine if ICC colorspaces can be used for blending.

Implement CPDF_ColorSpace::IsNormal() and check it when rendering. While
IsNormal() is trivial for most colorspaces, it needs to be implemented
separately for ICC colorspaces.

This fixes a rendering regression from commit 1c0de38c.

BUG=chromium:847346
TBR=hnakashima@chromium.org

Change-Id: Iaafed3f8ee40b26ac2cbfbdf2251407f7935311b
Reviewed-on: https://pdfium-review.googlesource.com/36571
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
(cherry picked from commit 2895880fa8354b273b4e2b72e61a5b78d1985fa8)
Reviewed-on: https://pdfium-review.googlesource.com/37013
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index 31c485f..fff7159 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -208,8 +208,7 @@
                           int image_width,
                           int image_height,
                           bool bTransMask) const override;
-
-  bool IsSRGB() const { return m_pProfile->IsSRGB(); }
+  bool IsNormal() const override;
 
  private:
   // If no valid ICC profile or using sRGB, try looking for an alternate.
@@ -597,6 +596,12 @@
     m_dwStdConversion--;
 }
 
+bool CPDF_ColorSpace::IsNormal() const {
+  return GetFamily() == PDFCS_DEVICEGRAY || GetFamily() == PDFCS_DEVICERGB ||
+         GetFamily() == PDFCS_DEVICECMYK || GetFamily() == PDFCS_CALGRAY ||
+         GetFamily() == PDFCS_CALRGB;
+}
+
 CPDF_PatternCS* CPDF_ColorSpace::AsPatternCS() {
   NOTREACHED();
   return nullptr;
@@ -911,7 +916,7 @@
                              float* G,
                              float* B) const {
   ASSERT(m_pProfile);
-  if (IsSRGB()) {
+  if (m_pProfile->IsSRGB()) {
     *R = pBuf[0];
     *G = pBuf[1];
     *B = pBuf[2];
@@ -949,7 +954,7 @@
                                          int image_width,
                                          int image_height,
                                          bool bTransMask) const {
-  if (IsSRGB()) {
+  if (m_pProfile->IsSRGB()) {
     ReverseRGB(pDestBuf, pSrcBuf, pixels);
     return;
   }
@@ -1012,6 +1017,16 @@
   }
 }
 
+bool CPDF_ICCBasedCS::IsNormal() const {
+  if (m_pProfile->IsSRGB())
+    return true;
+  if (m_pProfile->transform())
+    return m_pProfile->transform()->m_bNormal;
+  if (m_pAlterCS)
+    return m_pAlterCS->IsNormal();
+  return false;
+}
+
 bool CPDF_ICCBasedCS::FindAlternateProfile(
     CPDF_Document* pDoc,
     const CPDF_Dictionary* pDict,
diff --git a/core/fpdfapi/page/cpdf_colorspace.h b/core/fpdfapi/page/cpdf_colorspace.h
index fba6391..1789e21 100644
--- a/core/fpdfapi/page/cpdf_colorspace.h
+++ b/core/fpdfapi/page/cpdf_colorspace.h
@@ -85,6 +85,8 @@
                                   bool bTransMask) const;
   virtual void EnableStdConversion(bool bEnabled);
 
+  virtual bool IsNormal() const;
+
   // Only call these 3 methods below if GetFamily() returns |PDFCS_PATTERN|.
 
   // Returns |this| as a CPDF_PatternCS* if |this| is a pattern.
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index c446a5e..6f5e2e5 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -2654,8 +2654,10 @@
     return kDefaultColor;
 
   int family = pCS->GetFamily();
-  if (family == PDFCS_LAB || family == PDFCS_ICCBASED || pCS->IsSpecial())
+  if (family == PDFCS_LAB || pCS->IsSpecial() ||
+      (family == PDFCS_ICCBASED && !pCS->IsNormal())) {
     return kDefaultColor;
+  }
 
   // Store Color Space Family to use in CPDF_RenderStatus::Initialize().
   *pCSFamily = family;
diff --git a/core/fxcodec/codec/ccodec_iccmodule.h b/core/fxcodec/codec/ccodec_iccmodule.h
index c304b4b..0d60c3f 100644
--- a/core/fxcodec/codec/ccodec_iccmodule.h
+++ b/core/fxcodec/codec/ccodec_iccmodule.h
@@ -22,12 +22,16 @@
 
 class CLcmsCmm {
  public:
-  CLcmsCmm(int srcComponents, cmsHTRANSFORM transform, bool isLab);
+  CLcmsCmm(int srcComponents,
+           cmsHTRANSFORM transform,
+           bool isLab,
+           bool bNormal);
   ~CLcmsCmm();
 
   cmsHTRANSFORM m_hTransform;
   int m_nSrcComponents;
   bool m_bLab;
+  const bool m_bNormal;
 };
 
 class CCodec_IccModule {
diff --git a/core/fxcodec/codec/fx_codec_icc.cpp b/core/fxcodec/codec/fx_codec_icc.cpp
index 29b37d1..208257d 100644
--- a/core/fxcodec/codec/fx_codec_icc.cpp
+++ b/core/fxcodec/codec/fx_codec_icc.cpp
@@ -30,10 +30,14 @@
 
 }  // namespace
 
-CLcmsCmm::CLcmsCmm(int srcComponents, cmsHTRANSFORM hTransform, bool isLab)
+CLcmsCmm::CLcmsCmm(int srcComponents,
+                   cmsHTRANSFORM hTransform,
+                   bool isLab,
+                   bool bNormal)
     : m_hTransform(hTransform),
       m_nSrcComponents(srcComponents),
-      m_bLab(isLab) {}
+      m_bLab(isLab),
+      m_bNormal(bNormal) {}
 
 CLcmsCmm::~CLcmsCmm() {
   cmsDeleteTransform(m_hTransform);
@@ -59,8 +63,6 @@
     cmsCloseProfile(srcProfile);
     return nullptr;
   }
-  int srcFormat;
-  bool bLab = false;
   cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
 
   *nSrcComponents = cmsChannelsOf(srcCS);
@@ -71,6 +73,9 @@
     return nullptr;
   }
 
+  int srcFormat;
+  bool bLab = false;
+  bool bNormal = false;
   if (srcCS == cmsSigLabData) {
     srcFormat =
         COLORSPACE_SH(PT_Lab) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(0);
@@ -78,6 +83,10 @@
   } else {
     srcFormat =
         COLORSPACE_SH(PT_ANY) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(1);
+    // TODO(thestig): Check to see if lcms2 supports more colorspaces that can
+    // be considered normal.
+    bNormal = srcCS == cmsSigGrayData || srcCS == cmsSigRgbData ||
+              srcCS == cmsSigCmykData;
   }
   cmsColorSpaceSignature dstCS = cmsGetColorSpace(dstProfile);
   if (!Check3Components(dstCS, true)) {
@@ -109,7 +118,8 @@
     cmsCloseProfile(dstProfile);
     return nullptr;
   }
-  auto pCmm = pdfium::MakeUnique<CLcmsCmm>(*nSrcComponents, hTransform, bLab);
+  auto pCmm =
+      pdfium::MakeUnique<CLcmsCmm>(*nSrcComponents, hTransform, bLab, bNormal);
   cmsCloseProfile(srcProfile);
   cmsCloseProfile(dstProfile);
   return pCmm;