Add public API for setting the blend mode on a page object.

BUG=pdfium:720
R=npm@chromium.org

Change-Id: I2a43b34da6946265ca06502b9ff19ad352fd18cb
Reviewed-on: https://pdfium-review.googlesource.com/5953
Commit-Queue: Nicolás Peña <npm@chromium.org>
Reviewed-by: Nicolás Peña <npm@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index e9ea064..2cf10bd 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -225,8 +225,12 @@
   GraphicsData graphD;
   graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha();
   graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha();
-  if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f)
+  int blend_type = pPageObj->m_GeneralState.GetBlendType();
+  if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f &&
+      (blend_type == FXDIB_BLEND_UNSUPPORTED ||
+       blend_type == FXDIB_BLEND_NORMAL)) {
     return;
+  }
 
   CFX_ByteString name;
   auto it = m_pPage->m_GraphicsMap.find(graphD);
@@ -234,8 +238,17 @@
     name = it->second;
   } else {
     auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
-    gsDict->SetNewFor<CPDF_Number>("ca", graphD.fillAlpha);
-    gsDict->SetNewFor<CPDF_Number>("CA", graphD.strokeAlpha);
+    if (graphD.fillAlpha != 1.0f)
+      gsDict->SetNewFor<CPDF_Number>("ca", graphD.fillAlpha);
+
+    if (graphD.strokeAlpha != 1.0f)
+      gsDict->SetNewFor<CPDF_Number>("CA", graphD.strokeAlpha);
+
+    if (blend_type != FXDIB_BLEND_UNSUPPORTED &&
+        blend_type != FXDIB_BLEND_NORMAL) {
+      gsDict->SetNewFor<CPDF_Name>("BM",
+                                   pPageObj->m_GeneralState.GetBlendMode());
+    }
     CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
     uint32_t dwObjNum = pDict->GetObjNum();
     name = RealizeResource(dwObjNum, "ExtGState");
diff --git a/core/fpdfapi/page/cpdf_generalstate.cpp b/core/fpdfapi/page/cpdf_generalstate.cpp
index e07a3ca..5407074 100644
--- a/core/fpdfapi/page/cpdf_generalstate.cpp
+++ b/core/fpdfapi/page/cpdf_generalstate.cpp
@@ -78,6 +78,43 @@
 void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri) {
   m_Ref.GetPrivateCopy()->m_RenderIntent = RI_StringToId(ri);
 }
+CFX_ByteString CPDF_GeneralState::GetBlendMode() const {
+  switch (GetBlendType()) {
+    case FXDIB_BLEND_NORMAL:
+      return CFX_ByteString("Normal");
+    case FXDIB_BLEND_MULTIPLY:
+      return CFX_ByteString("Multiply");
+    case FXDIB_BLEND_SCREEN:
+      return CFX_ByteString("Screen");
+    case FXDIB_BLEND_OVERLAY:
+      return CFX_ByteString("Overlay");
+    case FXDIB_BLEND_DARKEN:
+      return CFX_ByteString("Darken");
+    case FXDIB_BLEND_LIGHTEN:
+      return CFX_ByteString("Lighten");
+    case FXDIB_BLEND_COLORDODGE:
+      return CFX_ByteString("ColorDodge");
+    case FXDIB_BLEND_COLORBURN:
+      return CFX_ByteString("ColorBurn");
+    case FXDIB_BLEND_HARDLIGHT:
+      return CFX_ByteString("HardLight");
+    case FXDIB_BLEND_SOFTLIGHT:
+      return CFX_ByteString("SoftLight");
+    case FXDIB_BLEND_DIFFERENCE:
+      return CFX_ByteString("Difference");
+    case FXDIB_BLEND_EXCLUSION:
+      return CFX_ByteString("Exclusion");
+    case FXDIB_BLEND_HUE:
+      return CFX_ByteString("Hue");
+    case FXDIB_BLEND_SATURATION:
+      return CFX_ByteString("Saturation");
+    case FXDIB_BLEND_COLOR:
+      return CFX_ByteString("Color");
+    case FXDIB_BLEND_LUMINOSITY:
+      return CFX_ByteString("Luminosity");
+  }
+  return CFX_ByteString("Normal");
+}
 
 int CPDF_GeneralState::GetBlendType() const {
   const StateData* pData = m_Ref.GetObject();
diff --git a/core/fpdfapi/page/cpdf_generalstate.h b/core/fpdfapi/page/cpdf_generalstate.h
index 4ec08ca..3568416 100644
--- a/core/fpdfapi/page/cpdf_generalstate.h
+++ b/core/fpdfapi/page/cpdf_generalstate.h
@@ -27,6 +27,7 @@
 
   void SetRenderIntent(const CFX_ByteString& ri);
 
+  CFX_ByteString GetBlendMode() const;
   int GetBlendType() const;
   void SetBlendType(int type);
 
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index 37469ed..a474414 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -264,6 +264,15 @@
   pPageObj->Transform(matrix);
 }
 
+DLLEXPORT void STDCALL FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object,
+                                                FPDF_BYTESTRING blend_mode) {
+  CPDF_PageObject* pPageObj = static_cast<CPDF_PageObject*>(page_object);
+  if (!pPageObj)
+    return;
+
+  pPageObj->m_GeneralState.SetBlendMode(blend_mode);
+}
+
 DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page,
                                                 double a,
                                                 double b,
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 677bdb2..2014e6f 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -311,6 +311,17 @@
                                                   float* right,
                                                   float* top);
 
+// Set the blend mode of |pageObject|.
+//
+// pageObject - handle to a page object.
+// blend_mode - string containing the blend mode.
+//
+// Blend mode can be one of following: Color, ColorBurn, ColorDodge, Darken,
+// Difference, Exclusion, HardLight, Hue, Lighten, Luminosity, Multiply, Normal,
+// Overlay, Saturation, Screen, SoftLight
+DLLEXPORT void STDCALL FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page,
+                                                FPDF_BYTESTRING blend_mode);
+
 // Set the stroke RGBA of a path. Range of values: 0 - 255.
 //
 // path   - the handle to the path object.