Split combo/listbox code out of CPDF_GenerateAP::GenerateFormAP()
Move code into GenerateComboBoxAP() and GenerateListBoxAP() helpers.
Change-Id: Ib716083cbb76ec445ef275574fbeaa2f29df95ee
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126651
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index 711ea5e..beb05f8 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -689,6 +689,159 @@
ap_dict->SetNewFor<CPDF_Reference>("N", doc, normal_stream->GetObjNum());
}
+ByteString GenerateComboBoxAP(const CPDF_Dictionary* annot_dict,
+ const CFX_FloatRect& body_rect,
+ const CFX_Color& text_color,
+ float font_size,
+ CPVT_VariableText::Provider& provider) {
+ fxcrt::ostringstream body_stream;
+
+ RetainPtr<const CPDF_Object> v_field =
+ CPDF_FormField::GetFieldAttrForDict(annot_dict, pdfium::form_fields::kV);
+ WideString value = v_field ? v_field->GetUnicodeText() : WideString();
+ CPVT_VariableText vt(&provider);
+ CFX_FloatRect button_rect = body_rect;
+ button_rect.left = button_rect.right - 13;
+ button_rect.Normalize();
+ CFX_FloatRect edit_rect = body_rect;
+ edit_rect.right = button_rect.left;
+ edit_rect.Normalize();
+ vt.SetPlateRect(edit_rect);
+ if (FXSYS_IsFloatZero(font_size)) {
+ vt.SetAutoFontSize(true);
+ } else {
+ vt.SetFontSize(font_size);
+ }
+
+ vt.Initialize();
+ vt.SetText(value);
+ vt.RearrangeAll();
+ CFX_FloatRect content_rect = vt.GetContentRect();
+ CFX_PointF offset =
+ CFX_PointF(0.0f, (content_rect.Height() - edit_rect.Height()) / 2.0f);
+ ByteString edit =
+ GenerateEditAP(provider.GetFontMap(), vt.GetIterator(), offset, true, 0);
+ if (edit.GetLength() > 0) {
+ body_stream << "/Tx BMC\nq\n";
+ WriteRect(body_stream, edit_rect) << " re\nW\nn\n";
+ body_stream << "BT\n"
+ << GenerateColorAP(text_color, PaintOperation::kFill) << edit
+ << "ET\n"
+ << "Q\nEMC\n";
+ }
+ ByteString button =
+ GenerateColorAP(CFX_Color(CFX_Color::Type::kRGB, 220.0f / 255.0f,
+ 220.0f / 255.0f, 220.0f / 255.0f),
+ PaintOperation::kFill);
+ if (button.GetLength() > 0 && !button_rect.IsEmpty()) {
+ body_stream << "q\n" << button;
+ WriteRect(body_stream, button_rect) << " re f\n";
+ body_stream << "Q\n";
+ static const BorderStyleInfo kButtonBorderStyleInfo{
+ .width = 2, .style = BorderStyle::kBeveled, .dash_pattern{3, 0, 0}};
+ ByteString button_border =
+ GenerateBorderAP(button_rect, kButtonBorderStyleInfo,
+ CFX_Color(CFX_Color::Type::kGray, 0));
+ if (button_border.GetLength() > 0) {
+ body_stream << "q\n" << button_border << "Q\n";
+ }
+
+ CFX_PointF center((button_rect.left + button_rect.right) / 2,
+ (button_rect.top + button_rect.bottom) / 2);
+ if (FXSYS_IsFloatBigger(button_rect.Width(), 6) &&
+ FXSYS_IsFloatBigger(button_rect.Height(), 6)) {
+ body_stream << "q\n0 g\n";
+ WritePoint(body_stream, {center.x - 3, center.y + 1.5f}) << " m\n";
+ WritePoint(body_stream, {center.x + 3, center.y + 1.5f}) << " l\n";
+ WritePoint(body_stream, {center.x, center.y - 1.5f}) << " l\n";
+ WritePoint(body_stream, {center.x - 3, center.y + 1.5f}) << " l f\n";
+ body_stream << button << "Q\n";
+ }
+ }
+ return ByteString(body_stream);
+}
+
+ByteString GenerateListBoxAP(const CPDF_Dictionary* annot_dict,
+ const CFX_FloatRect& body_rect,
+ const CFX_Color& text_color,
+ float font_size,
+ CPVT_VariableText::Provider& provider) {
+ RetainPtr<const CPDF_Array> opts =
+ ToArray(CPDF_FormField::GetFieldAttrForDict(annot_dict, "Opt"));
+ if (!opts) {
+ return ByteString();
+ }
+
+ RetainPtr<const CPDF_Array> selections =
+ ToArray(CPDF_FormField::GetFieldAttrForDict(annot_dict, "I"));
+ RetainPtr<const CPDF_Object> top_index =
+ CPDF_FormField::GetFieldAttrForDict(annot_dict, "TI");
+ const int32_t top = top_index ? top_index->GetInteger() : 0;
+ fxcrt::ostringstream body_stream;
+
+ float fy = body_rect.top;
+ for (size_t i = top, sz = opts->size(); i < sz; i++) {
+ if (FXSYS_IsFloatSmaller(fy, body_rect.bottom)) {
+ break;
+ }
+
+ if (RetainPtr<const CPDF_Object> opt = opts->GetDirectObjectAt(i)) {
+ WideString item;
+ if (opt->IsString()) {
+ item = opt->GetUnicodeText();
+ } else if (const CPDF_Array* opt_array = opt->AsArray()) {
+ RetainPtr<const CPDF_Object> opt_item = opt_array->GetDirectObjectAt(1);
+ if (opt_item) {
+ item = opt_item->GetUnicodeText();
+ }
+ }
+ bool is_selected = false;
+ if (selections) {
+ for (size_t s = 0, ssz = selections->size(); s < ssz; s++) {
+ int value = selections->GetIntegerAt(s);
+ if (value >= 0 && i == static_cast<size_t>(value)) {
+ is_selected = true;
+ break;
+ }
+ }
+ }
+ CPVT_VariableText vt(&provider);
+ vt.SetPlateRect(
+ CFX_FloatRect(body_rect.left, 0.0f, body_rect.right, 0.0f));
+ vt.SetFontSize(FXSYS_IsFloatZero(font_size) ? 12.0f : font_size);
+ vt.Initialize();
+ vt.SetText(item);
+ vt.RearrangeAll();
+
+ const float item_height = vt.GetContentRect().Height();
+ if (is_selected) {
+ CFX_FloatRect item_rect = CFX_FloatRect(
+ body_rect.left, fy - item_height, body_rect.right, fy);
+ body_stream << "q\n"
+ << GenerateColorAP(
+ CFX_Color(CFX_Color::Type::kRGB, 0, 51.0f / 255.0f,
+ 113.0f / 255.0f),
+ PaintOperation::kFill);
+ WriteRect(body_stream, item_rect) << " re f\nQ\n";
+ body_stream << "BT\n"
+ << GenerateColorAP(CFX_Color(CFX_Color::Type::kGray, 1),
+ PaintOperation::kFill)
+ << GenerateEditAP(provider.GetFontMap(), vt.GetIterator(),
+ CFX_PointF(0.0f, fy), true, 0)
+ << "ET\n";
+ } else {
+ body_stream << "BT\n"
+ << GenerateColorAP(text_color, PaintOperation::kFill)
+ << GenerateEditAP(provider.GetFontMap(), vt.GetIterator(),
+ CFX_PointF(0.0f, fy), true, 0)
+ << "ET\n";
+ }
+ fy -= item_height;
+ }
+ }
+ return ByteString(body_stream);
+}
+
bool GenerateCircleAP(CPDF_Document* doc, CPDF_Dictionary* annot_dict) {
fxcrt::ostringstream app_stream;
app_stream << "/" << kGSDictName << " gs ";
@@ -1164,7 +1317,7 @@
CPVT_FontMap map(doc, std::move(resources_dict), std::move(default_font),
font_name);
- CPVT_VariableText::Provider prd(&map);
+ CPVT_VariableText::Provider provider(&map);
switch (type) {
case CPDF_GenerateAP::kTextField: {
RetainPtr<const CPDF_Object> v_field =
@@ -1181,7 +1334,7 @@
RetainPtr<const CPDF_Object> max_len_field =
CPDF_FormField::GetFieldAttrForDict(annot_dict, "MaxLen");
const uint32_t max_len = max_len_field ? max_len_field->GetInteger() : 0;
- CPVT_VariableText vt(&prd);
+ CPVT_VariableText vt(&provider);
vt.SetPlateRect(body_rect);
vt.SetAlignment(align);
if (FXSYS_IsFloatZero(font_size)) {
@@ -1232,147 +1385,16 @@
break;
}
case CPDF_GenerateAP::kComboBox: {
- RetainPtr<const CPDF_Object> v_field =
- CPDF_FormField::GetFieldAttrForDict(annot_dict,
- pdfium::form_fields::kV);
- WideString value = v_field ? v_field->GetUnicodeText() : WideString();
- CPVT_VariableText vt(&prd);
- CFX_FloatRect button_rect = body_rect;
- button_rect.left = button_rect.right - 13;
- button_rect.Normalize();
- CFX_FloatRect edit_rect = body_rect;
- edit_rect.right = button_rect.left;
- edit_rect.Normalize();
- vt.SetPlateRect(edit_rect);
- if (FXSYS_IsFloatZero(font_size)) {
- vt.SetAutoFontSize(true);
- } else {
- vt.SetFontSize(font_size);
- }
-
- vt.Initialize();
- vt.SetText(value);
- vt.RearrangeAll();
- CFX_FloatRect content_rect = vt.GetContentRect();
- CFX_PointF offset =
- CFX_PointF(0.0f, (content_rect.Height() - edit_rect.Height()) / 2.0f);
- ByteString edit = GenerateEditAP(&map, vt.GetIterator(), offset, true, 0);
- if (edit.GetLength() > 0) {
- app_stream << "/Tx BMC\nq\n";
- WriteRect(app_stream, edit_rect) << " re\nW\nn\n";
- app_stream << "BT\n"
- << GenerateColorAP(text_color, PaintOperation::kFill) << edit
- << "ET\n"
- << "Q\nEMC\n";
- }
- ByteString button =
- GenerateColorAP(CFX_Color(CFX_Color::Type::kRGB, 220.0f / 255.0f,
- 220.0f / 255.0f, 220.0f / 255.0f),
- PaintOperation::kFill);
- if (button.GetLength() > 0 && !button_rect.IsEmpty()) {
- app_stream << "q\n" << button;
- WriteRect(app_stream, button_rect) << " re f\n";
- app_stream << "Q\n";
- static const BorderStyleInfo kButtonBorderStyleInfo{
- .width = 2, .style = BorderStyle::kBeveled, .dash_pattern{3, 0, 0}};
- ByteString button_border =
- GenerateBorderAP(button_rect, kButtonBorderStyleInfo,
- CFX_Color(CFX_Color::Type::kGray, 0));
- if (button_border.GetLength() > 0) {
- app_stream << "q\n" << button_border << "Q\n";
- }
-
- CFX_PointF center((button_rect.left + button_rect.right) / 2,
- (button_rect.top + button_rect.bottom) / 2);
- if (FXSYS_IsFloatBigger(button_rect.Width(), 6) &&
- FXSYS_IsFloatBigger(button_rect.Height(), 6)) {
- app_stream << "q\n0 g\n";
- WritePoint(app_stream, {center.x - 3, center.y + 1.5f}) << " m\n";
- WritePoint(app_stream, {center.x + 3, center.y + 1.5f}) << " l\n";
- WritePoint(app_stream, {center.x, center.y - 1.5f}) << " l\n";
- WritePoint(app_stream, {center.x - 3, center.y + 1.5f}) << " l f\n";
- app_stream << button << "Q\n";
- }
- }
+ app_stream << GenerateComboBoxAP(annot_dict, body_rect, text_color,
+ font_size, provider);
break;
}
case CPDF_GenerateAP::kListBox: {
- RetainPtr<const CPDF_Array> opts =
- ToArray(CPDF_FormField::GetFieldAttrForDict(annot_dict, "Opt"));
- RetainPtr<const CPDF_Array> selections =
- ToArray(CPDF_FormField::GetFieldAttrForDict(annot_dict, "I"));
- RetainPtr<const CPDF_Object> top_index =
- CPDF_FormField::GetFieldAttrForDict(annot_dict, "TI");
- const int32_t top = top_index ? top_index->GetInteger() : 0;
- fxcrt::ostringstream body_stream;
- if (opts) {
- float fy = body_rect.top;
- for (size_t i = top, sz = opts->size(); i < sz; i++) {
- if (FXSYS_IsFloatSmaller(fy, body_rect.bottom)) {
- break;
- }
-
- if (RetainPtr<const CPDF_Object> opt = opts->GetDirectObjectAt(i)) {
- WideString item;
- if (opt->IsString()) {
- item = opt->GetUnicodeText();
- } else if (const CPDF_Array* opt_array = opt->AsArray()) {
- RetainPtr<const CPDF_Object> opt_item =
- opt_array->GetDirectObjectAt(1);
- if (opt_item) {
- item = opt_item->GetUnicodeText();
- }
- }
- bool is_selected = false;
- if (selections) {
- for (size_t s = 0, ssz = selections->size(); s < ssz; s++) {
- int value = selections->GetIntegerAt(s);
- if (value >= 0 && i == static_cast<size_t>(value)) {
- is_selected = true;
- break;
- }
- }
- }
- CPVT_VariableText vt(&prd);
- vt.SetPlateRect(
- CFX_FloatRect(body_rect.left, 0.0f, body_rect.right, 0.0f));
- vt.SetFontSize(FXSYS_IsFloatZero(font_size) ? 12.0f : font_size);
- vt.Initialize();
- vt.SetText(item);
- vt.RearrangeAll();
-
- const float item_height = vt.GetContentRect().Height();
- if (is_selected) {
- CFX_FloatRect item_rect = CFX_FloatRect(
- body_rect.left, fy - item_height, body_rect.right, fy);
- body_stream << "q\n"
- << GenerateColorAP(
- CFX_Color(CFX_Color::Type::kRGB, 0,
- 51.0f / 255.0f, 113.0f / 255.0f),
- PaintOperation::kFill);
- WriteRect(body_stream, item_rect) << " re f\nQ\n";
- body_stream << "BT\n"
- << GenerateColorAP(
- CFX_Color(CFX_Color::Type::kGray, 1),
- PaintOperation::kFill)
- << GenerateEditAP(&map, vt.GetIterator(),
- CFX_PointF(0.0f, fy), true, 0)
- << "ET\n";
- } else {
- body_stream << "BT\n"
- << GenerateColorAP(text_color, PaintOperation::kFill)
- << GenerateEditAP(&map, vt.GetIterator(),
- CFX_PointF(0.0f, fy), true, 0)
- << "ET\n";
- }
- fy -= item_height;
- }
- }
- }
- if (body_stream.tellp() > 0) {
+ const ByteString body = GenerateListBoxAP(
+ annot_dict, body_rect, text_color, font_size, provider);
+ if (body.GetLength() > 0) {
app_stream << "/Tx BMC\nq\n";
- WriteRect(app_stream, body_rect) << " re\nW\nn\n"
- << body_stream.str() << "Q\nEMC\n";
+ WriteRect(app_stream, body_rect) << " re\nW\nn\n" << body << "Q\nEMC\n";
}
break;
}