Clean up pdfium_test.cc

- Move several blocks out of RenderPdf().
- Add an anonymous namespace.
- Check fwrite() results.
- Fix nits.

Change-Id: Ief0ddd5e49455d68b92d40674294dc9134adf86c
Reviewed-on: https://pdfium-review.googlesource.com/8650
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Jane Liu <janeliulwq@google.com>
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 83f18ed..dab734e 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -78,6 +78,8 @@
 #endif
 };
 
+namespace {
+
 struct Options {
   Options()
       : show_config(false),
@@ -123,12 +125,12 @@
   FPDF_FORMHANDLE form_handle;
 };
 
-static FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo(
+FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo(
     FPDF_FORMFILLINFO* form_fill_info) {
   return static_cast<FPDF_FORMFILLINFO_PDFiumTest*>(form_fill_info);
 }
 
-static bool CheckDimensions(int stride, int width, int height) {
+bool CheckDimensions(int stride, int width, int height) {
   if (stride < 0 || width < 0 || height < 0)
     return false;
   if (height > 0 && width > INT_MAX / height)
@@ -136,19 +138,19 @@
   return true;
 }
 
-static void OutputMD5Hash(const char* file_name, const char* buffer, int len) {
+void OutputMD5Hash(const char* file_name, const char* buffer, int len) {
   // Get the MD5 hash and write it to stdout.
   std::string hash =
       GenerateMD5Base16(reinterpret_cast<const uint8_t*>(buffer), len);
   printf("MD5:%s:%s\n", file_name, hash.c_str());
 }
 
-static std::string WritePpm(const char* pdf_name,
-                            int num,
-                            const void* buffer_void,
-                            int stride,
-                            int width,
-                            int height) {
+std::string WritePpm(const char* pdf_name,
+                     int num,
+                     const void* buffer_void,
+                     int stride,
+                     int width,
+                     int height) {
   const char* buffer = reinterpret_cast<const char*>(buffer_void);
 
   if (!CheckDimensions(stride, width, height))
@@ -180,7 +182,8 @@
       dest_line[(w * 3) + 2] = src_line[w * 4];
     }
   }
-  fwrite(result.data(), out_len, 1, fp);
+  if (fwrite(result.data(), out_len, 1, fp) != 1)
+    fprintf(stderr, "Failed to write to %s\n", filename);
   fclose(fp);
   return std::string(filename);
 }
@@ -203,17 +206,24 @@
 
   // Output in UTF32-LE.
   uint32_t bom = 0x0000FEFF;
-  fwrite(&bom, sizeof(bom), 1, fp);
+  if (fwrite(&bom, sizeof(bom), 1, fp) != 1) {
+    fprintf(stderr, "Failed to write to %s\n", filename);
+    (void)fclose(fp);
+    return;
+  }
 
   std::unique_ptr<void, FPDFTextPageDeleter> textpage(FPDFText_LoadPage(page));
   for (int i = 0; i < FPDFText_CountChars(textpage.get()); i++) {
     uint32_t c = FPDFText_GetUnicode(textpage.get(), i);
-    fwrite(&c, sizeof(c), 1, fp);
+    if (fwrite(&c, sizeof(c), 1, fp) != 1) {
+      fprintf(stderr, "Failed to write to %s\n", filename);
+      break;
+    }
   }
   (void)fclose(fp);
 }
 
-std::string AnnotSubtypeToString(FPDF_ANNOTATION_SUBTYPE subtype) {
+const char* AnnotSubtypeToCString(FPDF_ANNOTATION_SUBTYPE subtype) {
   if (subtype == FPDF_ANNOT_TEXT)
     return "Text";
   if (subtype == FPDF_ANNOT_LINK)
@@ -272,30 +282,36 @@
   return "";
 }
 
+void AppendFlagString(const char* flag, std::string* output) {
+  if (!output->empty())
+    *output += ", ";
+  *output += flag;
+}
+
 std::string AnnotFlagsToString(int flags) {
-  std::string str = "";
+  std::string str;
   if (flags & FPDF_ANNOT_FLAG_INVISIBLE)
-    str += "Invisible";
+    AppendFlagString("Invisible", &str);
   if (flags & FPDF_ANNOT_FLAG_HIDDEN)
-    str += std::string(str.empty() ? "" : ", ") + "Hidden";
+    AppendFlagString("Hidden", &str);
   if (flags & FPDF_ANNOT_FLAG_PRINT)
-    str += std::string(str.empty() ? "" : ", ") + "Print";
+    AppendFlagString("Print", &str);
   if (flags & FPDF_ANNOT_FLAG_NOZOOM)
-    str += std::string(str.empty() ? "" : ", ") + "NoZoom";
+    AppendFlagString("NoZoom", &str);
   if (flags & FPDF_ANNOT_FLAG_NOROTATE)
-    str += std::string(str.empty() ? "" : ", ") + "NoRotate";
+    AppendFlagString("NoRotate", &str);
   if (flags & FPDF_ANNOT_FLAG_NOVIEW)
-    str += std::string(str.empty() ? "" : ", ") + "NoView";
+    AppendFlagString("NoView", &str);
   if (flags & FPDF_ANNOT_FLAG_READONLY)
-    str += std::string(str.empty() ? "" : ", ") + "ReadOnly";
+    AppendFlagString("ReadOnly", &str);
   if (flags & FPDF_ANNOT_FLAG_LOCKED)
-    str += std::string(str.empty() ? "" : ", ") + "Locked";
+    AppendFlagString("Locked", &str);
   if (flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW)
-    str += std::string(str.empty() ? "" : ", ") + "ToggleNoView";
+    AppendFlagString("ToggleNoView", &str);
   return str;
 }
 
-std::string PageObjectTypeToString(int type) {
+const char* PageObjectTypeToCString(int type) {
   if (type == FPDF_PAGEOBJ_TEXT)
     return "Text";
   if (type == FPDF_PAGEOBJ_PATH)
@@ -339,7 +355,7 @@
       continue;
     }
     FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
-    fprintf(fp, "Subtype: %s\n", AnnotSubtypeToString(subtype).c_str());
+    fprintf(fp, "Subtype: %s\n", AnnotSubtypeToCString(subtype));
 
     // Retrieve the annotation flags.
     fprintf(fp, "Flags set: %s\n",
@@ -351,10 +367,9 @@
     if (obj_count > 0) {
       fprintf(fp, "Object types: ");
       for (int j = 0; j < obj_count; ++j) {
-        fprintf(fp, "%s  ",
-                PageObjectTypeToString(
-                    FPDFPageObj_GetType(FPDFAnnot_GetObject(annot, j)))
-                    .c_str());
+        const char* type = PageObjectTypeToCString(
+            FPDFPageObj_GetType(FPDFAnnot_GetObject(annot, j)));
+        fprintf(fp, "%s  ", type);
       }
       fprintf(fp, "\n");
     }
@@ -417,12 +432,12 @@
   (void)fclose(fp);
 }
 
-static std::string WritePng(const char* pdf_name,
-                            int num,
-                            const void* buffer_void,
-                            int stride,
-                            int width,
-                            int height) {
+std::string WritePng(const char* pdf_name,
+                     int num,
+                     const void* buffer_void,
+                     int stride,
+                     int width,
+                     int height) {
   if (!CheckDimensions(stride, width, height))
     return "";
 
@@ -452,19 +467,19 @@
   size_t bytes_written = fwrite(
       &png_encoding.front(), 1, png_encoding.size(), fp);
   if (bytes_written != png_encoding.size())
-    fprintf(stderr, "Failed to write to  %s\n", filename);
+    fprintf(stderr, "Failed to write to %s\n", filename);
 
   (void)fclose(fp);
   return std::string(filename);
 }
 
 #ifdef _WIN32
-static std::string WriteBmp(const char* pdf_name,
-                            int num,
-                            const void* buffer,
-                            int stride,
-                            int width,
-                            int height) {
+std::string WriteBmp(const char* pdf_name,
+                     int num,
+                     const void* buffer,
+                     int stride,
+                     int width,
+                     int height) {
   if (!CheckDimensions(stride, width, height))
     return "";
 
@@ -492,9 +507,11 @@
   file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len;
   file_header.bfOffBits = file_header.bfSize - out_len;
 
-  fwrite(&file_header, sizeof(file_header), 1, fp);
-  fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp);
-  fwrite(buffer, out_len, 1, fp);
+  if (fwrite(&file_header, sizeof(file_header), 1, fp) != 1 ||
+      fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp) != 1 ||
+      fwrite(buffer, out_len, 1, fp) != 1) {
+    fprintf(stderr, "Failed to write to %s\n", filename);
+  }
   fclose(fp);
   return std::string(filename);
 }
@@ -557,7 +574,10 @@
     const auto* comment = reinterpret_cast<const EMRGDICOMMENT*>(record);
     const char* data = reinterpret_cast<const char*>(comment->Data);
     uint16_t size = *reinterpret_cast<const uint16_t*>(data);
-    fwrite(data + sizeof(uint16_t), size, 1, fp);
+    if (fwrite(data + sizeof(uint16_t), size, 1, fp) != 1) {
+      fprintf(stderr, "Failed to write to %s\n", filename);
+      break;
+    }
   }
   fclose(fp);
   DeleteEnhMetaFile(emf);
@@ -565,9 +585,9 @@
 #endif  // _WIN32
 
 #ifdef PDF_ENABLE_SKIA
-static std::string WriteSkp(const char* pdf_name,
-                            int num,
-                            SkPictureRecorder* recorder) {
+std::string WriteSkp(const char* pdf_name,
+                     int num,
+                     SkPictureRecorder* recorder) {
   char filename[256];
   int chars_formatted =
       snprintf(filename, sizeof(filename), "%s.%d.skp", pdf_name, num);
@@ -832,6 +852,38 @@
   return true;
 }
 
+void PrintLastError() {
+  unsigned long err = FPDF_GetLastError();
+  fprintf(stderr, "Load pdf docs unsuccessful: ");
+  switch (err) {
+    case FPDF_ERR_SUCCESS:
+      fprintf(stderr, "Success");
+      break;
+    case FPDF_ERR_UNKNOWN:
+      fprintf(stderr, "Unknown error");
+      break;
+    case FPDF_ERR_FILE:
+      fprintf(stderr, "File not found or could not be opened");
+      break;
+    case FPDF_ERR_FORMAT:
+      fprintf(stderr, "File not in PDF format or corrupted");
+      break;
+    case FPDF_ERR_PASSWORD:
+      fprintf(stderr, "Password required or incorrect password");
+      break;
+    case FPDF_ERR_SECURITY:
+      fprintf(stderr, "Unsupported security scheme");
+      break;
+    case FPDF_ERR_PAGE:
+      fprintf(stderr, "Page not found or content error");
+      break;
+    default:
+      fprintf(stderr, "Unknown error %ld", err);
+  }
+  fprintf(stderr, ".\n");
+  return;
+}
+
 FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* avail, size_t offset, size_t size) {
   return true;
 }
@@ -983,6 +1035,87 @@
   printf("\n\n");
 }
 
+void DumpMetaData(FPDF_DOCUMENT doc) {
+  constexpr const char* meta_tags[] = {"Title",        "Author",  "Subject",
+                                       "Keywords",     "Creator", "Producer",
+                                       "CreationDate", "ModDate"};
+  for (const char* meta_tag : meta_tags) {
+    char meta_buffer[4096];
+    unsigned long len =
+        FPDF_GetMetaText(doc, meta_tag, meta_buffer, sizeof(meta_buffer));
+    if (!len)
+      continue;
+
+    auto* meta_string = reinterpret_cast<unsigned short*>(meta_buffer);
+    printf("%-12s = %ls (%lu bytes)\n", meta_tag,
+           GetPlatformWString(meta_string).c_str(), len);
+  }
+}
+
+void SaveAttachments(FPDF_DOCUMENT doc, const std::string& name) {
+  for (int i = 0; i < FPDFDoc_GetAttachmentCount(doc); ++i) {
+    FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(doc, i);
+
+    // Retrieve the attachment file name.
+    std::string attachment_name;
+    unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
+    if (len) {
+      std::vector<char> buf(len);
+      unsigned long actual_len =
+          FPDFAttachment_GetName(attachment, buf.data(), len);
+      if (actual_len == len) {
+        attachment_name =
+            GetPlatformString(reinterpret_cast<unsigned short*>(buf.data()));
+      }
+    }
+    if (attachment_name.empty()) {
+      fprintf(stderr, "Attachment #%d has an empty file name.\n", i + 1);
+      continue;
+    }
+
+    // Calculate the full attachment file name.
+    char save_name[256];
+    int chars_formatted =
+        snprintf(save_name, sizeof(save_name), "%s.attachment.%s", name.c_str(),
+                 attachment_name.c_str());
+    if (chars_formatted < 0 ||
+        static_cast<size_t>(chars_formatted) >= sizeof(save_name)) {
+      fprintf(stderr, "Filename %s is too long\n", save_name);
+      continue;
+    }
+
+    // Retrieve the attachment.
+    len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+    std::vector<char> data_buf(len);
+    if (len) {
+      unsigned long actual_len =
+          FPDFAttachment_GetFile(attachment, data_buf.data(), len);
+      if (actual_len != len)
+        data_buf.clear();
+    }
+    if (data_buf.empty()) {
+      fprintf(stderr, "Attachment \"%s\" is empty.\n", attachment_name.c_str());
+      continue;
+    }
+
+    // Write the attachment file.
+    FILE* fp = fopen(save_name, "wb");
+    if (!fp) {
+      fprintf(stderr, "Failed to open %s for saving attachment.\n", save_name);
+      continue;
+    }
+
+    size_t written_len = fwrite(data_buf.data(), 1, len, fp);
+    if (written_len == len) {
+      fprintf(stderr, "Saved attachment \"%s\" as: %s.\n",
+              attachment_name.c_str(), save_name);
+    } else {
+      fprintf(stderr, "Failed to write to %s\n", save_name);
+    }
+    fclose(fp);
+  }
+}
+
 // Note, for a client using progressive rendering you'd want to determine if you
 // need the rendering to pause instead of always saying |true|. This is for
 // testing to force the renderer to break whenever possible.
@@ -993,12 +1126,12 @@
 bool RenderPage(const std::string& name,
                 FPDF_DOCUMENT doc,
                 FPDF_FORMHANDLE form,
-                FPDF_FORMFILLINFO_PDFiumTest& form_fill_info,
+                FPDF_FORMFILLINFO_PDFiumTest* form_fill_info,
                 const int page_index,
                 const Options& options,
                 const std::string& events) {
   std::unique_ptr<void, FPDFPageDeleter> page(
-      GetPageForIndex(&form_fill_info, doc, page_index));
+      GetPageForIndex(form_fill_info, doc, page_index));
   if (!page.get())
     return false;
   if (options.send_events)
@@ -1109,7 +1242,7 @@
     fprintf(stderr, "Page was too large to be rendered.\n");
   }
 
-  form_fill_info.loaded_pages.erase(page_index);
+  form_fill_info->loaded_pages.erase(page_index);
   FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE);
   FORM_OnBeforeClosePage(page.get(), form);
   return !!bitmap;
@@ -1120,8 +1253,7 @@
                size_t len,
                const Options& options,
                const std::string& events) {
-  IPDF_JSPLATFORM platform_callbacks;
-  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
+  IPDF_JSPLATFORM platform_callbacks = {};
   platform_callbacks.version = 3;
   platform_callbacks.app_alert = ExampleAppAlert;
   platform_callbacks.app_response = ExampleAppResponse;
@@ -1138,19 +1270,16 @@
   form_callbacks.m_pJsPlatform = &platform_callbacks;
 
   TestLoader loader(pBuf, len);
-  FPDF_FILEACCESS file_access;
-  memset(&file_access, '\0', sizeof(file_access));
+  FPDF_FILEACCESS file_access = {};
   file_access.m_FileLen = static_cast<unsigned long>(len);
   file_access.m_GetBlock = TestLoader::GetBlock;
   file_access.m_Param = &loader;
 
-  FX_FILEAVAIL file_avail;
-  memset(&file_avail, '\0', sizeof(file_avail));
+  FX_FILEAVAIL file_avail = {};
   file_avail.version = 1;
   file_avail.IsDataAvail = Is_Data_Avail;
 
-  FX_DOWNLOADHINTS hints;
-  memset(&hints, '\0', sizeof(hints));
+  FX_DOWNLOADHINTS hints = {};
   hints.version = 1;
   hints.AddSegment = Add_Segment;
 
@@ -1184,103 +1313,17 @@
   }
 
   if (!doc) {
-    unsigned long err = FPDF_GetLastError();
-    fprintf(stderr, "Load pdf docs unsuccessful: ");
-    switch (err) {
-      case FPDF_ERR_SUCCESS:
-        fprintf(stderr, "Success");
-        break;
-      case FPDF_ERR_UNKNOWN:
-        fprintf(stderr, "Unknown error");
-        break;
-      case FPDF_ERR_FILE:
-        fprintf(stderr, "File not found or could not be opened");
-        break;
-      case FPDF_ERR_FORMAT:
-        fprintf(stderr, "File not in PDF format or corrupted");
-        break;
-      case FPDF_ERR_PASSWORD:
-        fprintf(stderr, "Password required or incorrect password");
-        break;
-      case FPDF_ERR_SECURITY:
-        fprintf(stderr, "Unsupported security scheme");
-        break;
-      case FPDF_ERR_PAGE:
-        fprintf(stderr, "Page not found or content error");
-        break;
-      default:
-        fprintf(stderr, "Unknown error %ld", err);
-    }
-    fprintf(stderr, ".\n");
+    PrintLastError();
     return;
   }
 
   (void)FPDF_GetDocPermissions(doc.get());
 
-  if (options.show_metadata) {
-    const char* metaTags[] = {"Title",   "Author",   "Subject",      "Keywords",
-                              "Creator", "Producer", "CreationDate", "ModDate"};
-    for (const char* metaTag : metaTags) {
-      char metaBuffer[4096];
-      int len = FPDF_GetMetaText(doc.get(), metaTag, metaBuffer, 4096);
-      printf("%-12s = %ls (%d bytes)\n", metaTag,
-             GetPlatformWString(reinterpret_cast<unsigned short*>(metaBuffer))
-                 .c_str(),
-             len);
-    }
-  }
+  if (options.show_metadata)
+    DumpMetaData(doc.get());
 
-  if (options.save_attachments) {
-    for (int i = 0; i < FPDFDoc_GetAttachmentCount(doc.get()); ++i) {
-      FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(doc.get(), i);
-
-      // Retrieve the attachment file name.
-      unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
-      if (!len) {
-        fprintf(stderr, "Warning: Attachment #%d has an empty file name.\n",
-                i + 1);
-      }
-      std::vector<char> buf(len);
-      FPDFAttachment_GetName(attachment, buf.data(), len);
-      std::string attachment_name =
-          GetPlatformString(reinterpret_cast<unsigned short*>(buf.data()));
-
-      // Open the attachment file for writing.
-      char save_name[256];
-      int chars_formatted =
-          snprintf(save_name, sizeof(save_name), "%s.attachment.%s",
-                   name.c_str(), attachment_name.c_str());
-      if (chars_formatted < 0 ||
-          static_cast<size_t>(chars_formatted) >= sizeof(save_name)) {
-        fprintf(stderr, "Filename %s is too long\n", save_name);
-        continue;
-      }
-      FILE* fp = fopen(save_name, "wb");
-      if (!fp) {
-        fprintf(stderr, "Failed to open %s for saving attachment.\n",
-                save_name);
-        continue;
-      }
-
-      // Write the attachment file.
-      len = FPDFAttachment_GetFile(attachment, nullptr, 0);
-      if (!len) {
-        fprintf(stderr, "Warning: Attachment \"%s\" is empty.\n",
-                attachment_name.c_str());
-      }
-      buf.clear();
-      buf.resize(len);
-      FPDFAttachment_GetFile(attachment, buf.data(), len);
-      size_t written_len = fwrite(buf.data(), sizeof(char), len, fp);
-      if (written_len != len) {
-        fprintf(stderr, "Warning: Unsuccessful write to file \"%s\".\n",
-                save_name);
-      }
-      fclose(fp);
-
-      fprintf(stderr, "Saved attachment \"%s\".\n", attachment_name.c_str());
-    }
-  }
+  if (options.save_attachments)
+    SaveAttachments(doc.get(), name);
 
   std::unique_ptr<void, FPDFFormHandleDeleter> form(
       FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks));
@@ -1301,9 +1344,9 @@
 
 #if _WIN32
   if (options.output_format == OUTPUT_PS2)
-    FPDF_SetPrintMode(2);
+    FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT2);
   else if (options.output_format == OUTPUT_PS3)
-    FPDF_SetPrintMode(3);
+    FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3);
 #endif
 
   int page_count = FPDF_GetPageCount(doc.get());
@@ -1323,11 +1366,12 @@
         return;
       }
     }
-    if (RenderPage(name, doc.get(), form.get(), form_callbacks, i, options,
-                   events))
+    if (RenderPage(name, doc.get(), form.get(), &form_callbacks, i, options,
+                   events)) {
       ++rendered_pages;
-    else
+    } else {
       ++bad_pages;
+    }
   }
 
   FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
@@ -1336,7 +1380,7 @@
     fprintf(stderr, "Skipped %d bad pages.\n", bad_pages);
 }
 
-static void ShowConfig() {
+void ShowConfig() {
   std::string config;
   std::string maybe_comma;
 #if PDF_ENABLE_V8
@@ -1362,7 +1406,7 @@
   printf("%s\n", config.c_str());
 }
 
-static const char kUsageString[] =
+constexpr char kUsageString[] =
     "Usage: pdfium_test [OPTION] [FILE]...\n"
     "  --show-config       - print build options and exit\n"
     "  --show-metadata     - print the file metadata\n"
@@ -1396,6 +1440,8 @@
     "  --md5   - write output image paths and their md5 hashes to stdout.\n"
     "";
 
+}  // namespace
+
 int main(int argc, const char* argv[]) {
   std::vector<std::string> args(argv, argv + argc);
   Options options;
@@ -1441,8 +1487,7 @@
   }
   FPDF_InitLibraryWithConfig(&config);
 
-  UNSUPPORT_INFO unsupported_info;
-  memset(&unsupported_info, '\0', sizeof(unsupported_info));
+  UNSUPPORT_INFO unsupported_info = {};
   unsupported_info.version = 1;
   unsupported_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler;
 
diff --git a/testing/test_support.cpp b/testing/test_support.cpp
index e5c3ab4..0ebb747 100644
--- a/testing/test_support.cpp
+++ b/testing/test_support.cpp
@@ -105,10 +105,9 @@
 }
 
 std::string GetPlatformString(FPDF_WIDESTRING wstr) {
-  return std::string(
-      CFX_WideString::FromUTF16LE(wstr, CFX_WideString::WStringLength(wstr))
-          .UTF8Encode()
-          .c_str());
+  CFX_WideString wide_string =
+      CFX_WideString::FromUTF16LE(wstr, CFX_WideString::WStringLength(wstr));
+  return std::string(wide_string.UTF8Encode().c_str());
 }
 
 std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) {