Generate default AP stream for underline annotation.

This patch generates a default AP stream for underline annotation so that
underline annotations without AP stream can be displayed.

Also, roll DEPS for testing/corpus to cae29d1 to test underline annotations.

BUG=62625

Review-Url: https://codereview.chromium.org/2205543002
diff --git a/DEPS b/DEPS
index 1347039..ed89247 100644
--- a/DEPS
+++ b/DEPS
@@ -14,7 +14,7 @@
   'gmock_revision': '29763965ab52f24565299976b936d1265cb6a271',
   'gtest_revision': '8245545b6dc9c4703e6496d1efd19e975ad2b038',
   'icu_revision': 'a5f86adbb0a58d04c035a5d1228747b1823cd485',
-  'pdfium_tests_revision': 'b63db0698bd3cac932807eb552e565b89dd2df9d',
+  'pdfium_tests_revision': 'cae29d1e4ac7a9c32add1a6ac0d04d60298a278e',
   'skia_revision': '7d46f4af7dc759002537a172af121f2bfe200981',
   'tools_memory_revision': '427f10475e1a8d72424c29d00bf689122b738e5d',
   'trace_event_revision': '54b8455be9505c2cb0cf5c26bb86739c236471aa',
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index a8578fc..77c117d 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -22,6 +22,8 @@
       m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")) {
   if (m_sSubtype == "Highlight")
     CPVT_GenerateAP::GenerateHighlightAP(m_pDocument, m_pAnnotDict);
+  else if (m_sSubtype == "Underline")
+    CPVT_GenerateAP::GenerateUnderlineAP(m_pDocument, m_pAnnotDict);
 }
 
 CPDF_Annot::~CPDF_Annot() {
diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp
index aaf4b79..9bde7e6 100644
--- a/core/fpdfdoc/cpvt_generateap.cpp
+++ b/core/fpdfdoc/cpvt_generateap.cpp
@@ -452,6 +452,65 @@
   return true;
 }
 
+CFX_ByteString GetColorStringWithDefault(CPDF_Dictionary* pAnnotDict,
+                                         const CPVT_Color& crDefaultColor,
+                                         PaintOperation nOperation) {
+  if (CPDF_Array* pColor = pAnnotDict->GetArrayBy("C")) {
+    CPVT_Color color = CPVT_Color::ParseColor(*pColor);
+    return CPVT_GenerateAP::GenerateColorAP(color, nOperation);
+  }
+
+  return CPVT_GenerateAP::GenerateColorAP(crDefaultColor, nOperation);
+}
+
+CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict,
+                                       const CFX_ByteString& sExtGSDictName,
+                                       const CFX_ByteString& sBlendMode) {
+  CPDF_Dictionary* pGSDict = new CPDF_Dictionary;
+  pGSDict->SetAtString("Type", "ExtGState");
+
+  FX_FLOAT fOpacity =
+      pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberBy("CA") : 1;
+  pGSDict->SetAtNumber("CA", fOpacity);
+  pGSDict->SetAtNumber("ca", fOpacity);
+  pGSDict->SetAtBoolean("AIS", false);
+  pGSDict->SetAtString("BM", sBlendMode);
+
+  CPDF_Dictionary* pExtGStateDict = new CPDF_Dictionary;
+  pExtGStateDict->SetAt(sExtGSDictName, pGSDict);
+
+  return pExtGStateDict;
+}
+
+// Takes ownership of |pExtGStateDict|.
+void GenerateAndSetAPDict(CPDF_Document* pDoc,
+                          CPDF_Dictionary* pAnnotDict,
+                          const CFX_ByteTextBuf& sAppStream,
+                          CPDF_Dictionary* pExtGStateDict) {
+  CPDF_Dictionary* pAPDict = new CPDF_Dictionary;
+  pAnnotDict->SetAt("AP", pAPDict);
+
+  CPDF_Stream* pNormalStream = new CPDF_Stream(nullptr, 0, nullptr);
+  int32_t objnum = pDoc->AddIndirectObject(pNormalStream);
+  pAnnotDict->GetDictBy("AP")->SetAtReference("N", pDoc, objnum);
+
+  pNormalStream->SetData(reinterpret_cast<uint8_t*>(sAppStream.GetBuffer()),
+                         sAppStream.GetSize(), FALSE, FALSE);
+
+  CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
+  pStreamDict->SetAtInteger("FormType", 1);
+  pStreamDict->SetAtString("Subtype", "Form");
+  pStreamDict->SetAtMatrix("Matrix", CFX_Matrix());
+
+  CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect");
+  pStreamDict->SetAtRect("BBox", rect);
+
+  CPDF_Dictionary* pResourceDict = new CPDF_Dictionary;
+  pResourceDict->SetAt("ExtGState", pExtGStateDict);
+
+  pStreamDict->SetAt("Resources", pResourceDict);
+}
+
 }  // namespace
 
 bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
@@ -510,16 +569,11 @@
     return false;
 
   CFX_ByteTextBuf sAppStream;
-  sAppStream << "/GS gs ";
+  CFX_ByteString sExtGSDictName = "GS";
+  sAppStream << "/" << sExtGSDictName << " gs ";
 
-  if (pAnnotDict->KeyExist("C")) {
-    CPDF_Array* pColor = pAnnotDict->GetArrayBy("C");
-    CPVT_Color color = CPVT_Color::ParseColor(*pColor);
-    sAppStream << CPVT_GenerateAP::GenerateColorAP(color, PaintOperation::FILL);
-  } else {
-    // Defaults to 0xFFFF00 color for highlight.
-    sAppStream << "1 1 0 rg \n";
-  }
+  sAppStream << GetColorStringWithDefault(
+      pAnnotDict, CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), PaintOperation::FILL);
 
   CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect");
   rect.Normalize();
@@ -529,39 +583,39 @@
              << rect.left << " " << rect.bottom << " l "
              << "h f\n";
 
-  CPDF_Dictionary* pAPDict = new CPDF_Dictionary;
-  pAnnotDict->SetAt("AP", pAPDict);
+  CPDF_Dictionary* pExtGStateDict =
+      GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply");
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
 
-  CPDF_Stream* pNormalStream = new CPDF_Stream(nullptr, 0, nullptr);
-  int32_t objnum = pDoc->AddIndirectObject(pNormalStream);
-  pAnnotDict->GetDictBy("AP")->SetAtReference("N", pDoc, objnum);
+  return true;
+}
 
-  pNormalStream->SetData(reinterpret_cast<uint8_t*>(sAppStream.GetBuffer()),
-                         sAppStream.GetSize(), FALSE, FALSE);
+bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc,
+                                          CPDF_Dictionary* pAnnotDict) {
+  // If AP dictionary exists, we use the appearance defined in the
+  // existing AP dictionary.
+  if (pAnnotDict->KeyExist("AP"))
+    return false;
 
-  CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
-  pStreamDict->SetAtInteger("FormType", 1);
-  pStreamDict->SetAtString("Subtype", "Form");
-  pStreamDict->SetAtMatrix("Matrix", CFX_Matrix());
-  pStreamDict->SetAtRect("BBox", rect);
+  CFX_ByteTextBuf sAppStream;
+  CFX_ByteString sExtGSDictName = "GS";
+  sAppStream << "/" << sExtGSDictName << " gs ";
 
-  CPDF_Dictionary* pGSDict = new CPDF_Dictionary;
-  pGSDict->SetAtString("Type", "ExtGState");
+  sAppStream << GetColorStringWithDefault(pAnnotDict,
+                                          CPVT_Color(CPVT_Color::kRGB, 0, 0, 0),
+                                          PaintOperation::STROKE);
 
-  FX_FLOAT fOpacity =
-      pAnnotDict->KeyExist("CA") ? pAnnotDict->GetNumberBy("CA") : 1;
-  pGSDict->SetAtNumber("ca", fOpacity);
-  pGSDict->SetAtNumber("CA", fOpacity);
-  pGSDict->SetAtBoolean("AIS", false);
-  pGSDict->SetAtString("BM", "Multiply");
+  CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect");
+  rect.Normalize();
 
-  CPDF_Dictionary* pExtGStateDict = new CPDF_Dictionary;
-  pExtGStateDict->SetAt("GS", pGSDict);
+  FX_FLOAT fLineWidth = 1.0;
+  sAppStream << fLineWidth << " w " << rect.left << " "
+             << rect.bottom + fLineWidth << " m " << rect.right << " "
+             << rect.bottom + fLineWidth << " l S\n";
 
-  CPDF_Dictionary* pResourceDict = new CPDF_Dictionary;
-  pResourceDict->SetAt("ExtGState", pExtGStateDict);
-
-  pStreamDict->SetAt("Resources", pResourceDict);
+  CPDF_Dictionary* pExtGStateDict =
+      GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal");
+  GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict);
   return true;
 }
 
diff --git a/core/fpdfdoc/cpvt_generateap.h b/core/fpdfdoc/cpvt_generateap.h
index 6cd9dce..233a6f3 100644
--- a/core/fpdfdoc/cpvt_generateap.h
+++ b/core/fpdfdoc/cpvt_generateap.h
@@ -33,6 +33,8 @@
                                 CPDF_Dictionary* pAnnotDict);
   static bool GenerateTextFieldAP(CPDF_Document* pDoc,
                                   CPDF_Dictionary* pAnnotDict);
+  static bool GenerateUnderlineAP(CPDF_Document* pDoc,
+                                  CPDF_Dictionary* pAnnotDict);
   static CFX_ByteString GenerateEditAP(IPVT_FontMap* pFontMap,
                                        CPDF_VariableText::Iterator* pIterator,
                                        const CFX_FloatPoint& ptOffset,