xref: /aosp_15_r20/external/pdfium/fpdfsdk/cpdfsdk_appstream.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_appstream.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <math.h>
10*3ac0a46fSAndroid Build Coastguard Worker 
11*3ac0a46fSAndroid Build Coastguard Worker #include <iterator>
12*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
13*3ac0a46fSAndroid Build Coastguard Worker #include <sstream>
14*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
15*3ac0a46fSAndroid Build Coastguard Worker 
16*3ac0a46fSAndroid Build Coastguard Worker #include "constants/appearance.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "constants/form_flags.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/edit/cpdf_contentstream_write_utils.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/font/cpdf_font.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_dictionary.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_document.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_name.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_number.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_reference.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_stream.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_string.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/fpdf_parser_decode.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/fpdf_parser_utility.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_bafontmap.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_formcontrol.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_icon.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpvt_word.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_string_wrappers.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_interactiveform.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_pageview.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_widget.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/pwl/cpwl_edit.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/pwl/cpwl_edit_impl.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/pwl/cpwl_wnd.h"
41*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/span.h"
42*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/numerics/safe_conversions.h"
43*3ac0a46fSAndroid Build Coastguard Worker 
44*3ac0a46fSAndroid Build Coastguard Worker namespace {
45*3ac0a46fSAndroid Build Coastguard Worker 
46*3ac0a46fSAndroid Build Coastguard Worker // Checkbox & radiobutton styles.
47*3ac0a46fSAndroid Build Coastguard Worker enum class CheckStyle { kCheck = 0, kCircle, kCross, kDiamond, kSquare, kStar };
48*3ac0a46fSAndroid Build Coastguard Worker 
49*3ac0a46fSAndroid Build Coastguard Worker // Pushbutton layout styles.
50*3ac0a46fSAndroid Build Coastguard Worker enum class ButtonStyle {
51*3ac0a46fSAndroid Build Coastguard Worker   kLabel = 0,
52*3ac0a46fSAndroid Build Coastguard Worker   kIcon,
53*3ac0a46fSAndroid Build Coastguard Worker   kIconTopLabelBottom,
54*3ac0a46fSAndroid Build Coastguard Worker   kIconBottomLabelTop,
55*3ac0a46fSAndroid Build Coastguard Worker   kIconLeftLabelRight,
56*3ac0a46fSAndroid Build Coastguard Worker   kIconRightLabelLeft,
57*3ac0a46fSAndroid Build Coastguard Worker   kLabelOverIcon
58*3ac0a46fSAndroid Build Coastguard Worker };
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker const char kAppendRectOperator[] = "re";
61*3ac0a46fSAndroid Build Coastguard Worker const char kConcatMatrixOperator[] = "cm";
62*3ac0a46fSAndroid Build Coastguard Worker const char kCurveToOperator[] = "c";
63*3ac0a46fSAndroid Build Coastguard Worker const char kEndPathNoFillOrStrokeOperator[] = "n";
64*3ac0a46fSAndroid Build Coastguard Worker const char kFillOperator[] = "f";
65*3ac0a46fSAndroid Build Coastguard Worker const char kFillEvenOddOperator[] = "f*";
66*3ac0a46fSAndroid Build Coastguard Worker const char kInvokeNamedXObjectOperator[] = "Do";
67*3ac0a46fSAndroid Build Coastguard Worker const char kLineToOperator[] = "l";
68*3ac0a46fSAndroid Build Coastguard Worker const char kMarkedSequenceBeginOperator[] = "BMC";
69*3ac0a46fSAndroid Build Coastguard Worker const char kMarkedSequenceEndOperator[] = "EMC";
70*3ac0a46fSAndroid Build Coastguard Worker const char kMoveTextPositionOperator[] = "Td";
71*3ac0a46fSAndroid Build Coastguard Worker const char kMoveToOperator[] = "m";
72*3ac0a46fSAndroid Build Coastguard Worker const char kSetCMYKOperator[] = "k";
73*3ac0a46fSAndroid Build Coastguard Worker const char kSetCMKYStrokedOperator[] = "K";
74*3ac0a46fSAndroid Build Coastguard Worker const char kSetDashOperator[] = "d";
75*3ac0a46fSAndroid Build Coastguard Worker const char kSetGrayOperator[] = "g";
76*3ac0a46fSAndroid Build Coastguard Worker const char kSetGrayStrokedOperator[] = "G";
77*3ac0a46fSAndroid Build Coastguard Worker const char kSetLineCapStyleOperator[] = "J";
78*3ac0a46fSAndroid Build Coastguard Worker const char kSetLineJoinStyleOperator[] = "j";
79*3ac0a46fSAndroid Build Coastguard Worker const char kSetLineWidthOperator[] = "w";
80*3ac0a46fSAndroid Build Coastguard Worker const char kSetNonZeroWindingClipOperator[] = "W";
81*3ac0a46fSAndroid Build Coastguard Worker const char kSetRGBOperator[] = "rg";
82*3ac0a46fSAndroid Build Coastguard Worker const char kSetRGBStrokedOperator[] = "RG";
83*3ac0a46fSAndroid Build Coastguard Worker const char kSetTextFontAndSizeOperator[] = "Tf";
84*3ac0a46fSAndroid Build Coastguard Worker const char kShowTextOperator[] = "Tj";
85*3ac0a46fSAndroid Build Coastguard Worker const char kStateRestoreOperator[] = "Q";
86*3ac0a46fSAndroid Build Coastguard Worker const char kStateSaveOperator[] = "q";
87*3ac0a46fSAndroid Build Coastguard Worker const char kStrokeOperator[] = "S";
88*3ac0a46fSAndroid Build Coastguard Worker const char kTextBeginOperator[] = "BT";
89*3ac0a46fSAndroid Build Coastguard Worker const char kTextEndOperator[] = "ET";
90*3ac0a46fSAndroid Build Coastguard Worker 
91*3ac0a46fSAndroid Build Coastguard Worker class AutoClosedCommand {
92*3ac0a46fSAndroid Build Coastguard Worker  public:
AutoClosedCommand(fxcrt::ostringstream * stream,ByteString open,ByteString close)93*3ac0a46fSAndroid Build Coastguard Worker   AutoClosedCommand(fxcrt::ostringstream* stream,
94*3ac0a46fSAndroid Build Coastguard Worker                     ByteString open,
95*3ac0a46fSAndroid Build Coastguard Worker                     ByteString close)
96*3ac0a46fSAndroid Build Coastguard Worker       : stream_(stream), close_(close) {
97*3ac0a46fSAndroid Build Coastguard Worker     *stream_ << open << "\n";
98*3ac0a46fSAndroid Build Coastguard Worker   }
99*3ac0a46fSAndroid Build Coastguard Worker 
~AutoClosedCommand()100*3ac0a46fSAndroid Build Coastguard Worker   virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; }
101*3ac0a46fSAndroid Build Coastguard Worker 
102*3ac0a46fSAndroid Build Coastguard Worker  private:
103*3ac0a46fSAndroid Build Coastguard Worker   UnownedPtr<fxcrt::ostringstream> const stream_;
104*3ac0a46fSAndroid Build Coastguard Worker   ByteString close_;
105*3ac0a46fSAndroid Build Coastguard Worker };
106*3ac0a46fSAndroid Build Coastguard Worker 
107*3ac0a46fSAndroid Build Coastguard Worker class AutoClosedQCommand final : public AutoClosedCommand {
108*3ac0a46fSAndroid Build Coastguard Worker  public:
AutoClosedQCommand(fxcrt::ostringstream * stream)109*3ac0a46fSAndroid Build Coastguard Worker   explicit AutoClosedQCommand(fxcrt::ostringstream* stream)
110*3ac0a46fSAndroid Build Coastguard Worker       : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {}
111*3ac0a46fSAndroid Build Coastguard Worker   ~AutoClosedQCommand() override = default;
112*3ac0a46fSAndroid Build Coastguard Worker };
113*3ac0a46fSAndroid Build Coastguard Worker 
WriteMove(fxcrt::ostringstream & stream,const CFX_PointF & point)114*3ac0a46fSAndroid Build Coastguard Worker void WriteMove(fxcrt::ostringstream& stream, const CFX_PointF& point) {
115*3ac0a46fSAndroid Build Coastguard Worker   WritePoint(stream, point) << " " << kMoveToOperator << "\n";
116*3ac0a46fSAndroid Build Coastguard Worker }
117*3ac0a46fSAndroid Build Coastguard Worker 
WriteLine(fxcrt::ostringstream & stream,const CFX_PointF & point)118*3ac0a46fSAndroid Build Coastguard Worker void WriteLine(fxcrt::ostringstream& stream, const CFX_PointF& point) {
119*3ac0a46fSAndroid Build Coastguard Worker   WritePoint(stream, point) << " " << kLineToOperator << "\n";
120*3ac0a46fSAndroid Build Coastguard Worker }
121*3ac0a46fSAndroid Build Coastguard Worker 
WriteClosedLoop(fxcrt::ostringstream & stream,pdfium::span<const CFX_PointF> points)122*3ac0a46fSAndroid Build Coastguard Worker void WriteClosedLoop(fxcrt::ostringstream& stream,
123*3ac0a46fSAndroid Build Coastguard Worker                      pdfium::span<const CFX_PointF> points) {
124*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(stream, points[0]);
125*3ac0a46fSAndroid Build Coastguard Worker   for (const auto& point : points.subspan(1))
126*3ac0a46fSAndroid Build Coastguard Worker     WriteLine(stream, point);
127*3ac0a46fSAndroid Build Coastguard Worker   WriteLine(stream, points[0]);
128*3ac0a46fSAndroid Build Coastguard Worker }
129*3ac0a46fSAndroid Build Coastguard Worker 
WriteBezierCurve(fxcrt::ostringstream & stream,const CFX_PointF & point1,const CFX_PointF & point2,const CFX_PointF & point3)130*3ac0a46fSAndroid Build Coastguard Worker void WriteBezierCurve(fxcrt::ostringstream& stream,
131*3ac0a46fSAndroid Build Coastguard Worker                       const CFX_PointF& point1,
132*3ac0a46fSAndroid Build Coastguard Worker                       const CFX_PointF& point2,
133*3ac0a46fSAndroid Build Coastguard Worker                       const CFX_PointF& point3) {
134*3ac0a46fSAndroid Build Coastguard Worker   WritePoint(stream, point1) << " ";
135*3ac0a46fSAndroid Build Coastguard Worker   WritePoint(stream, point2) << " ";
136*3ac0a46fSAndroid Build Coastguard Worker   WritePoint(stream, point3) << " " << kCurveToOperator << "\n";
137*3ac0a46fSAndroid Build Coastguard Worker }
138*3ac0a46fSAndroid Build Coastguard Worker 
WriteAppendRect(fxcrt::ostringstream & stream,const CFX_FloatRect & rect)139*3ac0a46fSAndroid Build Coastguard Worker void WriteAppendRect(fxcrt::ostringstream& stream, const CFX_FloatRect& rect) {
140*3ac0a46fSAndroid Build Coastguard Worker   WriteRect(stream, rect) << " " << kAppendRectOperator << "\n";
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
GetStrokeColorAppStream(const CFX_Color & color)143*3ac0a46fSAndroid Build Coastguard Worker ByteString GetStrokeColorAppStream(const CFX_Color& color) {
144*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sColorStream;
145*3ac0a46fSAndroid Build Coastguard Worker   switch (color.nColorType) {
146*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kTransparent:
147*3ac0a46fSAndroid Build Coastguard Worker       break;
148*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kGray:
149*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << kSetGrayStrokedOperator << "\n";
150*3ac0a46fSAndroid Build Coastguard Worker       break;
151*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kRGB:
152*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << color.fColor2 << " "
153*3ac0a46fSAndroid Build Coastguard Worker                    << color.fColor3 << " " << kSetRGBStrokedOperator << "\n";
154*3ac0a46fSAndroid Build Coastguard Worker       break;
155*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kCMYK:
156*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << color.fColor2 << " "
157*3ac0a46fSAndroid Build Coastguard Worker                    << color.fColor3 << " " << color.fColor4 << " "
158*3ac0a46fSAndroid Build Coastguard Worker                    << kSetCMKYStrokedOperator << "\n";
159*3ac0a46fSAndroid Build Coastguard Worker       break;
160*3ac0a46fSAndroid Build Coastguard Worker   }
161*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sColorStream);
162*3ac0a46fSAndroid Build Coastguard Worker }
163*3ac0a46fSAndroid Build Coastguard Worker 
GetFillColorAppStream(const CFX_Color & color)164*3ac0a46fSAndroid Build Coastguard Worker ByteString GetFillColorAppStream(const CFX_Color& color) {
165*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sColorStream;
166*3ac0a46fSAndroid Build Coastguard Worker   switch (color.nColorType) {
167*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kTransparent:
168*3ac0a46fSAndroid Build Coastguard Worker       break;
169*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kGray:
170*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << kSetGrayOperator << "\n";
171*3ac0a46fSAndroid Build Coastguard Worker       break;
172*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kRGB:
173*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << color.fColor2 << " "
174*3ac0a46fSAndroid Build Coastguard Worker                    << color.fColor3 << " " << kSetRGBOperator << "\n";
175*3ac0a46fSAndroid Build Coastguard Worker       break;
176*3ac0a46fSAndroid Build Coastguard Worker     case CFX_Color::Type::kCMYK:
177*3ac0a46fSAndroid Build Coastguard Worker       sColorStream << color.fColor1 << " " << color.fColor2 << " "
178*3ac0a46fSAndroid Build Coastguard Worker                    << color.fColor3 << " " << color.fColor4 << " "
179*3ac0a46fSAndroid Build Coastguard Worker                    << kSetCMYKOperator << "\n";
180*3ac0a46fSAndroid Build Coastguard Worker       break;
181*3ac0a46fSAndroid Build Coastguard Worker   }
182*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sColorStream);
183*3ac0a46fSAndroid Build Coastguard Worker }
184*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Check(const CFX_FloatRect & crBBox)185*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Check(const CFX_FloatRect& crBBox) {
186*3ac0a46fSAndroid Build Coastguard Worker   const float fWidth = crBBox.Width();
187*3ac0a46fSAndroid Build Coastguard Worker   const float fHeight = crBBox.Height();
188*3ac0a46fSAndroid Build Coastguard Worker 
189*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f),
190*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.29f, 0.40f)},
191*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f),
192*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.31f, 0.28f)},
193*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f),
194*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.77f, 0.67f)},
195*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f),
196*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.76f, 0.75f)},
197*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f),
198*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.68f, 0.75f)},
199*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f),
200*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.44f, 0.47f)},
201*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f),
202*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.41f, 0.58f)},
203*3ac0a46fSAndroid Build Coastguard Worker                           {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f),
204*3ac0a46fSAndroid Build Coastguard Worker                            CFX_PointF(0.30f, 0.56f)}};
205*3ac0a46fSAndroid Build Coastguard Worker 
206*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(pts); ++i) {
207*3ac0a46fSAndroid Build Coastguard Worker     for (size_t j = 0; j < std::size(pts[0]); ++j) {
208*3ac0a46fSAndroid Build Coastguard Worker       pts[i][j].x = pts[i][j].x * fWidth + crBBox.left;
209*3ac0a46fSAndroid Build Coastguard Worker       pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom;
210*3ac0a46fSAndroid Build Coastguard Worker     }
211*3ac0a46fSAndroid Build Coastguard Worker   }
212*3ac0a46fSAndroid Build Coastguard Worker 
213*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
214*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, pts[0][0]);
215*3ac0a46fSAndroid Build Coastguard Worker 
216*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(pts); ++i) {
217*3ac0a46fSAndroid Build Coastguard Worker     size_t nNext = i < std::size(pts) - 1 ? i + 1 : 0;
218*3ac0a46fSAndroid Build Coastguard Worker     const CFX_PointF& pt_next = pts[nNext][0];
219*3ac0a46fSAndroid Build Coastguard Worker 
220*3ac0a46fSAndroid Build Coastguard Worker     float px1 = pts[i][1].x - pts[i][0].x;
221*3ac0a46fSAndroid Build Coastguard Worker     float py1 = pts[i][1].y - pts[i][0].y;
222*3ac0a46fSAndroid Build Coastguard Worker     float px2 = pts[i][2].x - pt_next.x;
223*3ac0a46fSAndroid Build Coastguard Worker     float py2 = pts[i][2].y - pt_next.y;
224*3ac0a46fSAndroid Build Coastguard Worker 
225*3ac0a46fSAndroid Build Coastguard Worker     WriteBezierCurve(
226*3ac0a46fSAndroid Build Coastguard Worker         csAP,
227*3ac0a46fSAndroid Build Coastguard Worker         {pts[i][0].x + px1 * FXSYS_BEZIER, pts[i][0].y + py1 * FXSYS_BEZIER},
228*3ac0a46fSAndroid Build Coastguard Worker         {pt_next.x + px2 * FXSYS_BEZIER, pt_next.y + py2 * FXSYS_BEZIER},
229*3ac0a46fSAndroid Build Coastguard Worker         pt_next);
230*3ac0a46fSAndroid Build Coastguard Worker   }
231*3ac0a46fSAndroid Build Coastguard Worker 
232*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
233*3ac0a46fSAndroid Build Coastguard Worker }
234*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Circle(const CFX_FloatRect & crBBox)235*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Circle(const CFX_FloatRect& crBBox) {
236*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
237*3ac0a46fSAndroid Build Coastguard Worker 
238*3ac0a46fSAndroid Build Coastguard Worker   float fWidth = crBBox.Width();
239*3ac0a46fSAndroid Build Coastguard Worker   float fHeight = crBBox.Height();
240*3ac0a46fSAndroid Build Coastguard Worker 
241*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2);
242*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top);
243*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2);
244*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom);
245*3ac0a46fSAndroid Build Coastguard Worker 
246*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, pt1);
247*3ac0a46fSAndroid Build Coastguard Worker 
248*3ac0a46fSAndroid Build Coastguard Worker   float px = pt2.x - pt1.x;
249*3ac0a46fSAndroid Build Coastguard Worker   float py = pt2.y - pt1.y;
250*3ac0a46fSAndroid Build Coastguard Worker 
251*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt1.x, pt1.y + py * FXSYS_BEZIER},
252*3ac0a46fSAndroid Build Coastguard Worker                    {pt2.x - px * FXSYS_BEZIER, pt2.y}, pt2);
253*3ac0a46fSAndroid Build Coastguard Worker 
254*3ac0a46fSAndroid Build Coastguard Worker   px = pt3.x - pt2.x;
255*3ac0a46fSAndroid Build Coastguard Worker   py = pt2.y - pt3.y;
256*3ac0a46fSAndroid Build Coastguard Worker 
257*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt2.x + px * FXSYS_BEZIER, pt2.y},
258*3ac0a46fSAndroid Build Coastguard Worker                    {pt3.x, pt3.y + py * FXSYS_BEZIER}, pt3);
259*3ac0a46fSAndroid Build Coastguard Worker 
260*3ac0a46fSAndroid Build Coastguard Worker   px = pt3.x - pt4.x;
261*3ac0a46fSAndroid Build Coastguard Worker   py = pt3.y - pt4.y;
262*3ac0a46fSAndroid Build Coastguard Worker 
263*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt3.x, pt3.y - py * FXSYS_BEZIER},
264*3ac0a46fSAndroid Build Coastguard Worker                    {pt4.x + px * FXSYS_BEZIER, pt4.y}, pt4);
265*3ac0a46fSAndroid Build Coastguard Worker 
266*3ac0a46fSAndroid Build Coastguard Worker   px = pt4.x - pt1.x;
267*3ac0a46fSAndroid Build Coastguard Worker   py = pt1.y - pt4.y;
268*3ac0a46fSAndroid Build Coastguard Worker 
269*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt4.x - px * FXSYS_BEZIER, pt4.y},
270*3ac0a46fSAndroid Build Coastguard Worker                    {pt1.x, pt1.y - py * FXSYS_BEZIER}, pt1);
271*3ac0a46fSAndroid Build Coastguard Worker 
272*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
273*3ac0a46fSAndroid Build Coastguard Worker }
274*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Cross(const CFX_FloatRect & crBBox)275*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Cross(const CFX_FloatRect& crBBox) {
276*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
277*3ac0a46fSAndroid Build Coastguard Worker 
278*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, {crBBox.left, crBBox.top});
279*3ac0a46fSAndroid Build Coastguard Worker   WriteLine(csAP, {crBBox.right, crBBox.bottom});
280*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, {crBBox.left, crBBox.bottom});
281*3ac0a46fSAndroid Build Coastguard Worker   WriteLine(csAP, {crBBox.right, crBBox.top});
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
284*3ac0a46fSAndroid Build Coastguard Worker }
285*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Diamond(const CFX_FloatRect & crBBox)286*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) {
287*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
288*3ac0a46fSAndroid Build Coastguard Worker 
289*3ac0a46fSAndroid Build Coastguard Worker   float fWidth = crBBox.Width();
290*3ac0a46fSAndroid Build Coastguard Worker   float fHeight = crBBox.Height();
291*3ac0a46fSAndroid Build Coastguard Worker 
292*3ac0a46fSAndroid Build Coastguard Worker   const CFX_PointF points[] = {{crBBox.left, crBBox.bottom + fHeight / 2},
293*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.left + fWidth / 2, crBBox.top},
294*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.right, crBBox.bottom + fHeight / 2},
295*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.left + fWidth / 2, crBBox.bottom}};
296*3ac0a46fSAndroid Build Coastguard Worker   WriteClosedLoop(csAP, points);
297*3ac0a46fSAndroid Build Coastguard Worker 
298*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
299*3ac0a46fSAndroid Build Coastguard Worker }
300*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Square(const CFX_FloatRect & crBBox)301*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Square(const CFX_FloatRect& crBBox) {
302*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
303*3ac0a46fSAndroid Build Coastguard Worker 
304*3ac0a46fSAndroid Build Coastguard Worker   const CFX_PointF points[] = {{crBBox.left, crBBox.top},
305*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.right, crBBox.top},
306*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.right, crBBox.bottom},
307*3ac0a46fSAndroid Build Coastguard Worker                                {crBBox.left, crBBox.bottom}};
308*3ac0a46fSAndroid Build Coastguard Worker   WriteClosedLoop(csAP, points);
309*3ac0a46fSAndroid Build Coastguard Worker 
310*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
311*3ac0a46fSAndroid Build Coastguard Worker }
312*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_Star(const CFX_FloatRect & crBBox)313*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_Star(const CFX_FloatRect& crBBox) {
314*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
315*3ac0a46fSAndroid Build Coastguard Worker 
316*3ac0a46fSAndroid Build Coastguard Worker   float fRadius = (crBBox.top - crBBox.bottom) / (1 + cosf(FXSYS_PI / 5.0f));
317*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f,
318*3ac0a46fSAndroid Build Coastguard Worker                                    (crBBox.top + crBBox.bottom) / 2.0f);
319*3ac0a46fSAndroid Build Coastguard Worker 
320*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF points[5];
321*3ac0a46fSAndroid Build Coastguard Worker   float fAngle = FXSYS_PI / 10.0f;
322*3ac0a46fSAndroid Build Coastguard Worker   for (auto& point : points) {
323*3ac0a46fSAndroid Build Coastguard Worker     point =
324*3ac0a46fSAndroid Build Coastguard Worker         ptCenter + CFX_PointF(fRadius * cosf(fAngle), fRadius * sinf(fAngle));
325*3ac0a46fSAndroid Build Coastguard Worker     fAngle += FXSYS_PI * 2 / 5.0f;
326*3ac0a46fSAndroid Build Coastguard Worker   }
327*3ac0a46fSAndroid Build Coastguard Worker 
328*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, points[0]);
329*3ac0a46fSAndroid Build Coastguard Worker 
330*3ac0a46fSAndroid Build Coastguard Worker   int next = 0;
331*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(points); ++i) {
332*3ac0a46fSAndroid Build Coastguard Worker     next = (next + 2) % std::size(points);
333*3ac0a46fSAndroid Build Coastguard Worker     WriteLine(csAP, points[next]);
334*3ac0a46fSAndroid Build Coastguard Worker   }
335*3ac0a46fSAndroid Build Coastguard Worker 
336*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
337*3ac0a46fSAndroid Build Coastguard Worker }
338*3ac0a46fSAndroid Build Coastguard Worker 
GetAP_HalfCircle(const CFX_FloatRect & crBBox,float fRotate)339*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) {
340*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream csAP;
341*3ac0a46fSAndroid Build Coastguard Worker 
342*3ac0a46fSAndroid Build Coastguard Worker   float fWidth = crBBox.Width();
343*3ac0a46fSAndroid Build Coastguard Worker   float fHeight = crBBox.Height();
344*3ac0a46fSAndroid Build Coastguard Worker 
345*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt1(-fWidth / 2, 0);
346*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt2(0, fHeight / 2);
347*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF pt3(fWidth / 2, 0);
348*3ac0a46fSAndroid Build Coastguard Worker 
349*3ac0a46fSAndroid Build Coastguard Worker   CFX_Matrix rotate_matrix(cos(fRotate), sin(fRotate), -sin(fRotate),
350*3ac0a46fSAndroid Build Coastguard Worker                            cos(fRotate), crBBox.left + fWidth / 2,
351*3ac0a46fSAndroid Build Coastguard Worker                            crBBox.bottom + fHeight / 2);
352*3ac0a46fSAndroid Build Coastguard Worker   WriteMatrix(csAP, rotate_matrix) << " " << kConcatMatrixOperator << "\n";
353*3ac0a46fSAndroid Build Coastguard Worker 
354*3ac0a46fSAndroid Build Coastguard Worker   WriteMove(csAP, pt1);
355*3ac0a46fSAndroid Build Coastguard Worker 
356*3ac0a46fSAndroid Build Coastguard Worker   float px = pt2.x - pt1.x;
357*3ac0a46fSAndroid Build Coastguard Worker   float py = pt2.y - pt1.y;
358*3ac0a46fSAndroid Build Coastguard Worker 
359*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt1.x, pt1.y + py * FXSYS_BEZIER},
360*3ac0a46fSAndroid Build Coastguard Worker                    {pt2.x - px * FXSYS_BEZIER, pt2.y}, pt2);
361*3ac0a46fSAndroid Build Coastguard Worker 
362*3ac0a46fSAndroid Build Coastguard Worker   px = pt3.x - pt2.x;
363*3ac0a46fSAndroid Build Coastguard Worker   py = pt2.y - pt3.y;
364*3ac0a46fSAndroid Build Coastguard Worker 
365*3ac0a46fSAndroid Build Coastguard Worker   WriteBezierCurve(csAP, {pt2.x + px * FXSYS_BEZIER, pt2.y},
366*3ac0a46fSAndroid Build Coastguard Worker                    {pt3.x, pt3.y + py * FXSYS_BEZIER}, pt3);
367*3ac0a46fSAndroid Build Coastguard Worker 
368*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(csAP);
369*3ac0a46fSAndroid Build Coastguard Worker }
370*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Check(const CFX_FloatRect & rcBBox,const CFX_Color & crText)371*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox,
372*3ac0a46fSAndroid Build Coastguard Worker                               const CFX_Color& crText) {
373*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
374*3ac0a46fSAndroid Build Coastguard Worker   {
375*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
376*3ac0a46fSAndroid Build Coastguard Worker     sAP << GetFillColorAppStream(crText) << GetAP_Check(rcBBox) << kFillOperator
377*3ac0a46fSAndroid Build Coastguard Worker         << "\n";
378*3ac0a46fSAndroid Build Coastguard Worker   }
379*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
380*3ac0a46fSAndroid Build Coastguard Worker }
381*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Circle(const CFX_FloatRect & rcBBox,const CFX_Color & crText)382*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox,
383*3ac0a46fSAndroid Build Coastguard Worker                                const CFX_Color& crText) {
384*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
385*3ac0a46fSAndroid Build Coastguard Worker   {
386*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
387*3ac0a46fSAndroid Build Coastguard Worker     sAP << GetFillColorAppStream(crText) << GetAP_Circle(rcBBox)
388*3ac0a46fSAndroid Build Coastguard Worker         << kFillOperator << "\n";
389*3ac0a46fSAndroid Build Coastguard Worker   }
390*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
391*3ac0a46fSAndroid Build Coastguard Worker }
392*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Cross(const CFX_FloatRect & rcBBox,const CFX_Color & crText)393*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox,
394*3ac0a46fSAndroid Build Coastguard Worker                               const CFX_Color& crText) {
395*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
396*3ac0a46fSAndroid Build Coastguard Worker   {
397*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
398*3ac0a46fSAndroid Build Coastguard Worker     sAP << GetStrokeColorAppStream(crText) << GetAP_Cross(rcBBox)
399*3ac0a46fSAndroid Build Coastguard Worker         << kStrokeOperator << "\n";
400*3ac0a46fSAndroid Build Coastguard Worker   }
401*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
402*3ac0a46fSAndroid Build Coastguard Worker }
403*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Diamond(const CFX_FloatRect & rcBBox,const CFX_Color & crText)404*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
405*3ac0a46fSAndroid Build Coastguard Worker                                 const CFX_Color& crText) {
406*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
407*3ac0a46fSAndroid Build Coastguard Worker   {
408*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
409*3ac0a46fSAndroid Build Coastguard Worker     sAP << "1 " << kSetLineWidthOperator << "\n"
410*3ac0a46fSAndroid Build Coastguard Worker         << GetFillColorAppStream(crText) << GetAP_Diamond(rcBBox)
411*3ac0a46fSAndroid Build Coastguard Worker         << kFillOperator << "\n";
412*3ac0a46fSAndroid Build Coastguard Worker   }
413*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
414*3ac0a46fSAndroid Build Coastguard Worker }
415*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Square(const CFX_FloatRect & rcBBox,const CFX_Color & crText)416*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox,
417*3ac0a46fSAndroid Build Coastguard Worker                                const CFX_Color& crText) {
418*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
419*3ac0a46fSAndroid Build Coastguard Worker   {
420*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
421*3ac0a46fSAndroid Build Coastguard Worker     sAP << GetFillColorAppStream(crText) << GetAP_Square(rcBBox)
422*3ac0a46fSAndroid Build Coastguard Worker         << kFillOperator << "\n";
423*3ac0a46fSAndroid Build Coastguard Worker   }
424*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
425*3ac0a46fSAndroid Build Coastguard Worker }
426*3ac0a46fSAndroid Build Coastguard Worker 
GetAppStream_Star(const CFX_FloatRect & rcBBox,const CFX_Color & crText)427*3ac0a46fSAndroid Build Coastguard Worker ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox,
428*3ac0a46fSAndroid Build Coastguard Worker                              const CFX_Color& crText) {
429*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAP;
430*3ac0a46fSAndroid Build Coastguard Worker   {
431*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAP);
432*3ac0a46fSAndroid Build Coastguard Worker     sAP << GetFillColorAppStream(crText) << GetAP_Star(rcBBox) << kFillOperator
433*3ac0a46fSAndroid Build Coastguard Worker         << "\n";
434*3ac0a46fSAndroid Build Coastguard Worker   }
435*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAP);
436*3ac0a46fSAndroid Build Coastguard Worker }
437*3ac0a46fSAndroid Build Coastguard Worker 
GetCircleFillAppStream(const CFX_FloatRect & rect,const CFX_Color & color)438*3ac0a46fSAndroid Build Coastguard Worker ByteString GetCircleFillAppStream(const CFX_FloatRect& rect,
439*3ac0a46fSAndroid Build Coastguard Worker                                   const CFX_Color& color) {
440*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
441*3ac0a46fSAndroid Build Coastguard Worker   ByteString sColor = GetFillColorAppStream(color);
442*3ac0a46fSAndroid Build Coastguard Worker   if (sColor.GetLength() > 0) {
443*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
444*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n";
445*3ac0a46fSAndroid Build Coastguard Worker   }
446*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
447*3ac0a46fSAndroid Build Coastguard Worker }
448*3ac0a46fSAndroid Build Coastguard Worker 
GetCircleBorderAppStream(const CFX_FloatRect & rect,float fWidth,const CFX_Color & color,const CFX_Color & crLeftTop,const CFX_Color & crRightBottom,BorderStyle nStyle,const CPWL_Dash & dash)449*3ac0a46fSAndroid Build Coastguard Worker ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect,
450*3ac0a46fSAndroid Build Coastguard Worker                                     float fWidth,
451*3ac0a46fSAndroid Build Coastguard Worker                                     const CFX_Color& color,
452*3ac0a46fSAndroid Build Coastguard Worker                                     const CFX_Color& crLeftTop,
453*3ac0a46fSAndroid Build Coastguard Worker                                     const CFX_Color& crRightBottom,
454*3ac0a46fSAndroid Build Coastguard Worker                                     BorderStyle nStyle,
455*3ac0a46fSAndroid Build Coastguard Worker                                     const CPWL_Dash& dash) {
456*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
457*3ac0a46fSAndroid Build Coastguard Worker   ByteString sColor;
458*3ac0a46fSAndroid Build Coastguard Worker 
459*3ac0a46fSAndroid Build Coastguard Worker   if (fWidth > 0.0f) {
460*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
461*3ac0a46fSAndroid Build Coastguard Worker 
462*3ac0a46fSAndroid Build Coastguard Worker     float fHalfWidth = fWidth / 2.0f;
463*3ac0a46fSAndroid Build Coastguard Worker     CFX_FloatRect rect_by_2 = rect.GetDeflated(fHalfWidth, fHalfWidth);
464*3ac0a46fSAndroid Build Coastguard Worker 
465*3ac0a46fSAndroid Build Coastguard Worker     float div = fHalfWidth * 0.75f;
466*3ac0a46fSAndroid Build Coastguard Worker     CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div);
467*3ac0a46fSAndroid Build Coastguard Worker     switch (nStyle) {
468*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kSolid:
469*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kUnderline: {
470*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
471*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
472*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
473*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
474*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_Circle(rect_by_2) << " "
475*3ac0a46fSAndroid Build Coastguard Worker                      << kStrokeOperator << "\n";
476*3ac0a46fSAndroid Build Coastguard Worker         }
477*3ac0a46fSAndroid Build Coastguard Worker       } break;
478*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kDash: {
479*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
480*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
481*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
482*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
483*3ac0a46fSAndroid Build Coastguard Worker                      << "[" << dash.nDash << " " << dash.nGap << "] "
484*3ac0a46fSAndroid Build Coastguard Worker                      << dash.nPhase << " " << kSetDashOperator << "\n"
485*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_Circle(rect_by_2) << " "
486*3ac0a46fSAndroid Build Coastguard Worker                      << kStrokeOperator << "\n";
487*3ac0a46fSAndroid Build Coastguard Worker         }
488*3ac0a46fSAndroid Build Coastguard Worker       } break;
489*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kBeveled: {
490*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
491*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
492*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
493*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
494*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
495*3ac0a46fSAndroid Build Coastguard Worker                      << "\n";
496*3ac0a46fSAndroid Build Coastguard Worker         }
497*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(crLeftTop);
498*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
499*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
500*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
501*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_HalfCircle(rect_by_75, FXSYS_PI / 4.0f)
502*3ac0a46fSAndroid Build Coastguard Worker                      << " " << kStrokeOperator << "\n";
503*3ac0a46fSAndroid Build Coastguard Worker         }
504*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(crRightBottom);
505*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
506*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
507*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
508*3ac0a46fSAndroid Build Coastguard Worker                      << sColor
509*3ac0a46fSAndroid Build Coastguard Worker                      << GetAP_HalfCircle(rect_by_75, FXSYS_PI * 5 / 4.0f) << " "
510*3ac0a46fSAndroid Build Coastguard Worker                      << kStrokeOperator << "\n";
511*3ac0a46fSAndroid Build Coastguard Worker         }
512*3ac0a46fSAndroid Build Coastguard Worker       } break;
513*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kInset: {
514*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
515*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
516*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
517*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
518*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
519*3ac0a46fSAndroid Build Coastguard Worker                      << "\n";
520*3ac0a46fSAndroid Build Coastguard Worker         }
521*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(crLeftTop);
522*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
523*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
524*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
525*3ac0a46fSAndroid Build Coastguard Worker                      << sColor << GetAP_HalfCircle(rect_by_75, FXSYS_PI / 4.0f)
526*3ac0a46fSAndroid Build Coastguard Worker                      << " " << kStrokeOperator << "\n";
527*3ac0a46fSAndroid Build Coastguard Worker         }
528*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(crRightBottom);
529*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
530*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q2(&sAppStream);
531*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
532*3ac0a46fSAndroid Build Coastguard Worker                      << sColor
533*3ac0a46fSAndroid Build Coastguard Worker                      << GetAP_HalfCircle(rect_by_75, FXSYS_PI * 5 / 4.0f) << " "
534*3ac0a46fSAndroid Build Coastguard Worker                      << kStrokeOperator << "\n";
535*3ac0a46fSAndroid Build Coastguard Worker         }
536*3ac0a46fSAndroid Build Coastguard Worker       } break;
537*3ac0a46fSAndroid Build Coastguard Worker     }
538*3ac0a46fSAndroid Build Coastguard Worker   }
539*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
540*3ac0a46fSAndroid Build Coastguard Worker }
541*3ac0a46fSAndroid Build Coastguard Worker 
GetCheckBoxAppStream(const CFX_FloatRect & rcBBox,CheckStyle nStyle,const CFX_Color & crText)542*3ac0a46fSAndroid Build Coastguard Worker ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
543*3ac0a46fSAndroid Build Coastguard Worker                                 CheckStyle nStyle,
544*3ac0a46fSAndroid Build Coastguard Worker                                 const CFX_Color& crText) {
545*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
546*3ac0a46fSAndroid Build Coastguard Worker   switch (nStyle) {
547*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCheck:
548*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Check(rcCenter, crText);
549*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCircle:
550*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
551*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Circle(rcCenter, crText);
552*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCross:
553*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Cross(rcCenter, crText);
554*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kDiamond:
555*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
556*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Diamond(rcCenter, crText);
557*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kSquare:
558*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
559*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Square(rcCenter, crText);
560*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kStar:
561*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
562*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Star(rcCenter, crText);
563*3ac0a46fSAndroid Build Coastguard Worker   }
564*3ac0a46fSAndroid Build Coastguard Worker }
565*3ac0a46fSAndroid Build Coastguard Worker 
GetRadioButtonAppStream(const CFX_FloatRect & rcBBox,CheckStyle nStyle,const CFX_Color & crText)566*3ac0a46fSAndroid Build Coastguard Worker ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
567*3ac0a46fSAndroid Build Coastguard Worker                                    CheckStyle nStyle,
568*3ac0a46fSAndroid Build Coastguard Worker                                    const CFX_Color& crText) {
569*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
570*3ac0a46fSAndroid Build Coastguard Worker   switch (nStyle) {
571*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCheck:
572*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Check(rcCenter, crText);
573*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCircle:
574*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(1.0f / 2.0f);
575*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Circle(rcCenter, crText);
576*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kCross:
577*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Cross(rcCenter, crText);
578*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kDiamond:
579*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
580*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Diamond(rcCenter, crText);
581*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kSquare:
582*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
583*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Square(rcCenter, crText);
584*3ac0a46fSAndroid Build Coastguard Worker     case CheckStyle::kStar:
585*3ac0a46fSAndroid Build Coastguard Worker       rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
586*3ac0a46fSAndroid Build Coastguard Worker       return GetAppStream_Star(rcCenter, crText);
587*3ac0a46fSAndroid Build Coastguard Worker   }
588*3ac0a46fSAndroid Build Coastguard Worker }
589*3ac0a46fSAndroid Build Coastguard Worker 
GetFontSetString(IPVT_FontMap * pFontMap,int32_t nFontIndex,float fFontSize)590*3ac0a46fSAndroid Build Coastguard Worker ByteString GetFontSetString(IPVT_FontMap* pFontMap,
591*3ac0a46fSAndroid Build Coastguard Worker                             int32_t nFontIndex,
592*3ac0a46fSAndroid Build Coastguard Worker                             float fFontSize) {
593*3ac0a46fSAndroid Build Coastguard Worker   if (!pFontMap)
594*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
595*3ac0a46fSAndroid Build Coastguard Worker 
596*3ac0a46fSAndroid Build Coastguard Worker   ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
597*3ac0a46fSAndroid Build Coastguard Worker   if (sFontAlias.GetLength() <= 0 || fFontSize <= 0)
598*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
599*3ac0a46fSAndroid Build Coastguard Worker 
600*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sRet;
601*3ac0a46fSAndroid Build Coastguard Worker   sRet << "/" << sFontAlias << " " << fFontSize << " "
602*3ac0a46fSAndroid Build Coastguard Worker        << kSetTextFontAndSizeOperator << "\n";
603*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sRet);
604*3ac0a46fSAndroid Build Coastguard Worker }
605*3ac0a46fSAndroid Build Coastguard Worker 
GetWordRenderString(ByteStringView strWords)606*3ac0a46fSAndroid Build Coastguard Worker ByteString GetWordRenderString(ByteStringView strWords) {
607*3ac0a46fSAndroid Build Coastguard Worker   if (strWords.IsEmpty())
608*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
609*3ac0a46fSAndroid Build Coastguard Worker   return PDF_EncodeString(strWords) + " " + kShowTextOperator + "\n";
610*3ac0a46fSAndroid Build Coastguard Worker }
611*3ac0a46fSAndroid Build Coastguard Worker 
GetEditAppStream(CPWL_EditImpl * pEdit,const CFX_PointF & ptOffset,bool bContinuous,uint16_t SubWord)612*3ac0a46fSAndroid Build Coastguard Worker ByteString GetEditAppStream(CPWL_EditImpl* pEdit,
613*3ac0a46fSAndroid Build Coastguard Worker                             const CFX_PointF& ptOffset,
614*3ac0a46fSAndroid Build Coastguard Worker                             bool bContinuous,
615*3ac0a46fSAndroid Build Coastguard Worker                             uint16_t SubWord) {
616*3ac0a46fSAndroid Build Coastguard Worker   CPWL_EditImpl::Iterator* pIterator = pEdit->GetIterator();
617*3ac0a46fSAndroid Build Coastguard Worker   pIterator->SetAt(0);
618*3ac0a46fSAndroid Build Coastguard Worker 
619*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sEditStream;
620*3ac0a46fSAndroid Build Coastguard Worker   int32_t nCurFontIndex = -1;
621*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF ptOld;
622*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF ptNew;
623*3ac0a46fSAndroid Build Coastguard Worker   CPVT_WordPlace oldplace;
624*3ac0a46fSAndroid Build Coastguard Worker   ByteString sWords;
625*3ac0a46fSAndroid Build Coastguard Worker 
626*3ac0a46fSAndroid Build Coastguard Worker   while (pIterator->NextWord()) {
627*3ac0a46fSAndroid Build Coastguard Worker     CPVT_WordPlace place = pIterator->GetAt();
628*3ac0a46fSAndroid Build Coastguard Worker     if (bContinuous) {
629*3ac0a46fSAndroid Build Coastguard Worker       if (place.LineCmp(oldplace) != 0) {
630*3ac0a46fSAndroid Build Coastguard Worker         if (!sWords.IsEmpty()) {
631*3ac0a46fSAndroid Build Coastguard Worker           sEditStream << GetWordRenderString(sWords.AsStringView());
632*3ac0a46fSAndroid Build Coastguard Worker           sWords.clear();
633*3ac0a46fSAndroid Build Coastguard Worker         }
634*3ac0a46fSAndroid Build Coastguard Worker 
635*3ac0a46fSAndroid Build Coastguard Worker         CPVT_Word word;
636*3ac0a46fSAndroid Build Coastguard Worker         if (pIterator->GetWord(word)) {
637*3ac0a46fSAndroid Build Coastguard Worker           ptNew = CFX_PointF(word.ptWord.x + ptOffset.x,
638*3ac0a46fSAndroid Build Coastguard Worker                              word.ptWord.y + ptOffset.y);
639*3ac0a46fSAndroid Build Coastguard Worker         } else {
640*3ac0a46fSAndroid Build Coastguard Worker           CPVT_Line line;
641*3ac0a46fSAndroid Build Coastguard Worker           pIterator->GetLine(line);
642*3ac0a46fSAndroid Build Coastguard Worker           ptNew = CFX_PointF(line.ptLine.x + ptOffset.x,
643*3ac0a46fSAndroid Build Coastguard Worker                              line.ptLine.y + ptOffset.y);
644*3ac0a46fSAndroid Build Coastguard Worker         }
645*3ac0a46fSAndroid Build Coastguard Worker 
646*3ac0a46fSAndroid Build Coastguard Worker         if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
647*3ac0a46fSAndroid Build Coastguard Worker           WritePoint(sEditStream, {ptNew.x - ptOld.x, ptNew.y - ptOld.y})
648*3ac0a46fSAndroid Build Coastguard Worker               << " " << kMoveTextPositionOperator << "\n";
649*3ac0a46fSAndroid Build Coastguard Worker 
650*3ac0a46fSAndroid Build Coastguard Worker           ptOld = ptNew;
651*3ac0a46fSAndroid Build Coastguard Worker         }
652*3ac0a46fSAndroid Build Coastguard Worker       }
653*3ac0a46fSAndroid Build Coastguard Worker 
654*3ac0a46fSAndroid Build Coastguard Worker       CPVT_Word word;
655*3ac0a46fSAndroid Build Coastguard Worker       if (pIterator->GetWord(word)) {
656*3ac0a46fSAndroid Build Coastguard Worker         if (word.nFontIndex != nCurFontIndex) {
657*3ac0a46fSAndroid Build Coastguard Worker           if (!sWords.IsEmpty()) {
658*3ac0a46fSAndroid Build Coastguard Worker             sEditStream << GetWordRenderString(sWords.AsStringView());
659*3ac0a46fSAndroid Build Coastguard Worker             sWords.clear();
660*3ac0a46fSAndroid Build Coastguard Worker           }
661*3ac0a46fSAndroid Build Coastguard Worker           sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
662*3ac0a46fSAndroid Build Coastguard Worker                                           word.fFontSize);
663*3ac0a46fSAndroid Build Coastguard Worker           nCurFontIndex = word.nFontIndex;
664*3ac0a46fSAndroid Build Coastguard Worker         }
665*3ac0a46fSAndroid Build Coastguard Worker 
666*3ac0a46fSAndroid Build Coastguard Worker         sWords += pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord);
667*3ac0a46fSAndroid Build Coastguard Worker       }
668*3ac0a46fSAndroid Build Coastguard Worker       oldplace = place;
669*3ac0a46fSAndroid Build Coastguard Worker     } else {
670*3ac0a46fSAndroid Build Coastguard Worker       CPVT_Word word;
671*3ac0a46fSAndroid Build Coastguard Worker       if (pIterator->GetWord(word)) {
672*3ac0a46fSAndroid Build Coastguard Worker         ptNew =
673*3ac0a46fSAndroid Build Coastguard Worker             CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
674*3ac0a46fSAndroid Build Coastguard Worker 
675*3ac0a46fSAndroid Build Coastguard Worker         if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
676*3ac0a46fSAndroid Build Coastguard Worker           WritePoint(sEditStream, {ptNew.x - ptOld.x, ptNew.y - ptOld.y})
677*3ac0a46fSAndroid Build Coastguard Worker               << " " << kMoveTextPositionOperator << "\n";
678*3ac0a46fSAndroid Build Coastguard Worker           ptOld = ptNew;
679*3ac0a46fSAndroid Build Coastguard Worker         }
680*3ac0a46fSAndroid Build Coastguard Worker         if (word.nFontIndex != nCurFontIndex) {
681*3ac0a46fSAndroid Build Coastguard Worker           sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
682*3ac0a46fSAndroid Build Coastguard Worker                                           word.fFontSize);
683*3ac0a46fSAndroid Build Coastguard Worker           nCurFontIndex = word.nFontIndex;
684*3ac0a46fSAndroid Build Coastguard Worker         }
685*3ac0a46fSAndroid Build Coastguard Worker         sEditStream << GetWordRenderString(
686*3ac0a46fSAndroid Build Coastguard Worker             pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord)
687*3ac0a46fSAndroid Build Coastguard Worker                 .AsStringView());
688*3ac0a46fSAndroid Build Coastguard Worker       }
689*3ac0a46fSAndroid Build Coastguard Worker     }
690*3ac0a46fSAndroid Build Coastguard Worker   }
691*3ac0a46fSAndroid Build Coastguard Worker 
692*3ac0a46fSAndroid Build Coastguard Worker   if (!sWords.IsEmpty())
693*3ac0a46fSAndroid Build Coastguard Worker     sEditStream << GetWordRenderString(sWords.AsStringView());
694*3ac0a46fSAndroid Build Coastguard Worker 
695*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
696*3ac0a46fSAndroid Build Coastguard Worker   if (sEditStream.tellp() > 0) {
697*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << sEditStream.str();
698*3ac0a46fSAndroid Build Coastguard Worker   }
699*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
700*3ac0a46fSAndroid Build Coastguard Worker }
701*3ac0a46fSAndroid Build Coastguard Worker 
GenerateIconAppStream(CPDF_IconFit & fit,RetainPtr<CPDF_Stream> pIconStream,const CFX_FloatRect & rcIcon)702*3ac0a46fSAndroid Build Coastguard Worker ByteString GenerateIconAppStream(CPDF_IconFit& fit,
703*3ac0a46fSAndroid Build Coastguard Worker                                  RetainPtr<CPDF_Stream> pIconStream,
704*3ac0a46fSAndroid Build Coastguard Worker                                  const CFX_FloatRect& rcIcon) {
705*3ac0a46fSAndroid Build Coastguard Worker   if (rcIcon.IsEmpty() || !pIconStream)
706*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
707*3ac0a46fSAndroid Build Coastguard Worker 
708*3ac0a46fSAndroid Build Coastguard Worker   CPWL_Wnd::CreateParams cp(nullptr, nullptr, nullptr);
709*3ac0a46fSAndroid Build Coastguard Worker   cp.dwFlags = PWS_VISIBLE;
710*3ac0a46fSAndroid Build Coastguard Worker   auto pWnd = std::make_unique<CPWL_Wnd>(cp, nullptr);
711*3ac0a46fSAndroid Build Coastguard Worker   pWnd->Realize();
712*3ac0a46fSAndroid Build Coastguard Worker   if (!pWnd->Move(rcIcon, false, false))
713*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
714*3ac0a46fSAndroid Build Coastguard Worker 
715*3ac0a46fSAndroid Build Coastguard Worker   auto pPDFIcon = std::make_unique<CPDF_Icon>(std::move(pIconStream));
716*3ac0a46fSAndroid Build Coastguard Worker   ByteString sAlias = pPDFIcon->GetImageAlias();
717*3ac0a46fSAndroid Build Coastguard Worker   if (sAlias.GetLength() <= 0)
718*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
719*3ac0a46fSAndroid Build Coastguard Worker 
720*3ac0a46fSAndroid Build Coastguard Worker   const CFX_FloatRect rcPlate = pWnd->GetClientRect();
721*3ac0a46fSAndroid Build Coastguard Worker   const CFX_SizeF image_size = pPDFIcon->GetImageSize();
722*3ac0a46fSAndroid Build Coastguard Worker   const CFX_Matrix mt = pPDFIcon->GetImageMatrix().GetInverse();
723*3ac0a46fSAndroid Build Coastguard Worker   const CFX_VectorF scale = fit.GetScale(image_size, rcPlate);
724*3ac0a46fSAndroid Build Coastguard Worker   const CFX_VectorF offset = fit.GetImageOffset(image_size, scale, rcPlate);
725*3ac0a46fSAndroid Build Coastguard Worker 
726*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream str;
727*3ac0a46fSAndroid Build Coastguard Worker   {
728*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&str);
729*3ac0a46fSAndroid Build Coastguard Worker     WriteAppendRect(str, rcPlate);
730*3ac0a46fSAndroid Build Coastguard Worker     str << kSetNonZeroWindingClipOperator << " "
731*3ac0a46fSAndroid Build Coastguard Worker         << kEndPathNoFillOrStrokeOperator << "\n";
732*3ac0a46fSAndroid Build Coastguard Worker 
733*3ac0a46fSAndroid Build Coastguard Worker     CFX_Matrix scale_matrix(scale.x, 0, 0, scale.y, rcPlate.left + offset.x,
734*3ac0a46fSAndroid Build Coastguard Worker                             rcPlate.bottom + offset.y);
735*3ac0a46fSAndroid Build Coastguard Worker     WriteMatrix(str, scale_matrix) << " " << kConcatMatrixOperator << "\n";
736*3ac0a46fSAndroid Build Coastguard Worker     WriteMatrix(str, mt) << " " << kConcatMatrixOperator << "\n";
737*3ac0a46fSAndroid Build Coastguard Worker 
738*3ac0a46fSAndroid Build Coastguard Worker     str << "0 " << kSetGrayOperator << " 0 " << kSetGrayStrokedOperator << " 1 "
739*3ac0a46fSAndroid Build Coastguard Worker         << kSetLineWidthOperator << " /" << sAlias << " "
740*3ac0a46fSAndroid Build Coastguard Worker         << kInvokeNamedXObjectOperator << "\n";
741*3ac0a46fSAndroid Build Coastguard Worker   }
742*3ac0a46fSAndroid Build Coastguard Worker   pWnd->Destroy();
743*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(str);
744*3ac0a46fSAndroid Build Coastguard Worker }
745*3ac0a46fSAndroid Build Coastguard Worker 
GetPushButtonAppStream(const CFX_FloatRect & rcBBox,IPVT_FontMap * pFontMap,RetainPtr<CPDF_Stream> pIconStream,CPDF_IconFit & IconFit,const WideString & sLabel,const CFX_Color & crText,float fFontSize,ButtonStyle nLayOut)746*3ac0a46fSAndroid Build Coastguard Worker ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
747*3ac0a46fSAndroid Build Coastguard Worker                                   IPVT_FontMap* pFontMap,
748*3ac0a46fSAndroid Build Coastguard Worker                                   RetainPtr<CPDF_Stream> pIconStream,
749*3ac0a46fSAndroid Build Coastguard Worker                                   CPDF_IconFit& IconFit,
750*3ac0a46fSAndroid Build Coastguard Worker                                   const WideString& sLabel,
751*3ac0a46fSAndroid Build Coastguard Worker                                   const CFX_Color& crText,
752*3ac0a46fSAndroid Build Coastguard Worker                                   float fFontSize,
753*3ac0a46fSAndroid Build Coastguard Worker                                   ButtonStyle nLayOut) {
754*3ac0a46fSAndroid Build Coastguard Worker   const float fAutoFontScale = 1.0f / 3.0f;
755*3ac0a46fSAndroid Build Coastguard Worker 
756*3ac0a46fSAndroid Build Coastguard Worker   auto pEdit = std::make_unique<CPWL_EditImpl>();
757*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetFontMap(pFontMap);
758*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetAlignmentH(1);
759*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetAlignmentV(1);
760*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetMultiLine(false);
761*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetAutoReturn(false);
762*3ac0a46fSAndroid Build Coastguard Worker   if (FXSYS_IsFloatZero(fFontSize))
763*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetAutoFontSize(true);
764*3ac0a46fSAndroid Build Coastguard Worker   else
765*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetFontSize(fFontSize);
766*3ac0a46fSAndroid Build Coastguard Worker 
767*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Initialize();
768*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetText(sLabel);
769*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Paint();
770*3ac0a46fSAndroid Build Coastguard Worker 
771*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcLabelContent = pEdit->GetContentRect();
772*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcLabel;
773*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcIcon;
774*3ac0a46fSAndroid Build Coastguard Worker   float fWidth = 0.0f;
775*3ac0a46fSAndroid Build Coastguard Worker   float fHeight = 0.0f;
776*3ac0a46fSAndroid Build Coastguard Worker 
777*3ac0a46fSAndroid Build Coastguard Worker   switch (nLayOut) {
778*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kLabel:
779*3ac0a46fSAndroid Build Coastguard Worker       rcLabel = rcBBox;
780*3ac0a46fSAndroid Build Coastguard Worker       break;
781*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kIcon:
782*3ac0a46fSAndroid Build Coastguard Worker       rcIcon = rcBBox;
783*3ac0a46fSAndroid Build Coastguard Worker       break;
784*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kIconTopLabelBottom:
785*3ac0a46fSAndroid Build Coastguard Worker       if (pIconStream) {
786*3ac0a46fSAndroid Build Coastguard Worker         if (FXSYS_IsFloatZero(fFontSize)) {
787*3ac0a46fSAndroid Build Coastguard Worker           fHeight = rcBBox.Height();
788*3ac0a46fSAndroid Build Coastguard Worker           rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
789*3ac0a46fSAndroid Build Coastguard Worker                                   rcBBox.bottom + fHeight * fAutoFontScale);
790*3ac0a46fSAndroid Build Coastguard Worker           rcIcon =
791*3ac0a46fSAndroid Build Coastguard Worker               CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top);
792*3ac0a46fSAndroid Build Coastguard Worker         } else {
793*3ac0a46fSAndroid Build Coastguard Worker           fHeight = rcLabelContent.Height();
794*3ac0a46fSAndroid Build Coastguard Worker 
795*3ac0a46fSAndroid Build Coastguard Worker           if (rcBBox.bottom + fHeight > rcBBox.top) {
796*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = rcBBox;
797*3ac0a46fSAndroid Build Coastguard Worker           } else {
798*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
799*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.bottom + fHeight);
800*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right,
801*3ac0a46fSAndroid Build Coastguard Worker                                    rcBBox.top);
802*3ac0a46fSAndroid Build Coastguard Worker           }
803*3ac0a46fSAndroid Build Coastguard Worker         }
804*3ac0a46fSAndroid Build Coastguard Worker       } else {
805*3ac0a46fSAndroid Build Coastguard Worker         rcLabel = rcBBox;
806*3ac0a46fSAndroid Build Coastguard Worker       }
807*3ac0a46fSAndroid Build Coastguard Worker       break;
808*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kIconBottomLabelTop:
809*3ac0a46fSAndroid Build Coastguard Worker       if (pIconStream) {
810*3ac0a46fSAndroid Build Coastguard Worker         if (FXSYS_IsFloatZero(fFontSize)) {
811*3ac0a46fSAndroid Build Coastguard Worker           fHeight = rcBBox.Height();
812*3ac0a46fSAndroid Build Coastguard Worker           rcLabel =
813*3ac0a46fSAndroid Build Coastguard Worker               CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale,
814*3ac0a46fSAndroid Build Coastguard Worker                             rcBBox.right, rcBBox.top);
815*3ac0a46fSAndroid Build Coastguard Worker           rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
816*3ac0a46fSAndroid Build Coastguard Worker                                  rcLabel.bottom);
817*3ac0a46fSAndroid Build Coastguard Worker         } else {
818*3ac0a46fSAndroid Build Coastguard Worker           fHeight = rcLabelContent.Height();
819*3ac0a46fSAndroid Build Coastguard Worker 
820*3ac0a46fSAndroid Build Coastguard Worker           if (rcBBox.bottom + fHeight > rcBBox.top) {
821*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = rcBBox;
822*3ac0a46fSAndroid Build Coastguard Worker           } else {
823*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight,
824*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.right, rcBBox.top);
825*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
826*3ac0a46fSAndroid Build Coastguard Worker                                    rcLabel.bottom);
827*3ac0a46fSAndroid Build Coastguard Worker           }
828*3ac0a46fSAndroid Build Coastguard Worker         }
829*3ac0a46fSAndroid Build Coastguard Worker       } else {
830*3ac0a46fSAndroid Build Coastguard Worker         rcLabel = rcBBox;
831*3ac0a46fSAndroid Build Coastguard Worker       }
832*3ac0a46fSAndroid Build Coastguard Worker       break;
833*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kIconLeftLabelRight:
834*3ac0a46fSAndroid Build Coastguard Worker       if (pIconStream) {
835*3ac0a46fSAndroid Build Coastguard Worker         if (FXSYS_IsFloatZero(fFontSize)) {
836*3ac0a46fSAndroid Build Coastguard Worker           fWidth = rcBBox.right - rcBBox.left;
837*3ac0a46fSAndroid Build Coastguard Worker           if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
838*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale,
839*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.bottom, rcBBox.right, rcBBox.top);
840*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
841*3ac0a46fSAndroid Build Coastguard Worker                                    rcBBox.top);
842*3ac0a46fSAndroid Build Coastguard Worker           } else {
843*3ac0a46fSAndroid Build Coastguard Worker             if (rcLabelContent.Width() < fWidth) {
844*3ac0a46fSAndroid Build Coastguard Worker               rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(),
845*3ac0a46fSAndroid Build Coastguard Worker                                       rcBBox.bottom, rcBBox.right, rcBBox.top);
846*3ac0a46fSAndroid Build Coastguard Worker               rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
847*3ac0a46fSAndroid Build Coastguard Worker                                      rcBBox.top);
848*3ac0a46fSAndroid Build Coastguard Worker             } else {
849*3ac0a46fSAndroid Build Coastguard Worker               rcLabel = rcBBox;
850*3ac0a46fSAndroid Build Coastguard Worker             }
851*3ac0a46fSAndroid Build Coastguard Worker           }
852*3ac0a46fSAndroid Build Coastguard Worker         } else {
853*3ac0a46fSAndroid Build Coastguard Worker           fWidth = rcLabelContent.Width();
854*3ac0a46fSAndroid Build Coastguard Worker           if (rcBBox.left + fWidth > rcBBox.right) {
855*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = rcBBox;
856*3ac0a46fSAndroid Build Coastguard Worker           } else {
857*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom,
858*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.right, rcBBox.top);
859*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
860*3ac0a46fSAndroid Build Coastguard Worker                                    rcBBox.top);
861*3ac0a46fSAndroid Build Coastguard Worker           }
862*3ac0a46fSAndroid Build Coastguard Worker         }
863*3ac0a46fSAndroid Build Coastguard Worker       } else {
864*3ac0a46fSAndroid Build Coastguard Worker         rcLabel = rcBBox;
865*3ac0a46fSAndroid Build Coastguard Worker       }
866*3ac0a46fSAndroid Build Coastguard Worker       break;
867*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kIconRightLabelLeft:
868*3ac0a46fSAndroid Build Coastguard Worker       if (pIconStream) {
869*3ac0a46fSAndroid Build Coastguard Worker         if (FXSYS_IsFloatZero(fFontSize)) {
870*3ac0a46fSAndroid Build Coastguard Worker           fWidth = rcBBox.right - rcBBox.left;
871*3ac0a46fSAndroid Build Coastguard Worker           if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
872*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
873*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.left + fWidth * fAutoFontScale,
874*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.top);
875*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
876*3ac0a46fSAndroid Build Coastguard Worker                                    rcBBox.top);
877*3ac0a46fSAndroid Build Coastguard Worker           } else {
878*3ac0a46fSAndroid Build Coastguard Worker             if (rcLabelContent.Width() < fWidth) {
879*3ac0a46fSAndroid Build Coastguard Worker               rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
880*3ac0a46fSAndroid Build Coastguard Worker                                       rcBBox.left + rcLabelContent.Width(),
881*3ac0a46fSAndroid Build Coastguard Worker                                       rcBBox.top);
882*3ac0a46fSAndroid Build Coastguard Worker               rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
883*3ac0a46fSAndroid Build Coastguard Worker                                      rcBBox.top);
884*3ac0a46fSAndroid Build Coastguard Worker             } else {
885*3ac0a46fSAndroid Build Coastguard Worker               rcLabel = rcBBox;
886*3ac0a46fSAndroid Build Coastguard Worker             }
887*3ac0a46fSAndroid Build Coastguard Worker           }
888*3ac0a46fSAndroid Build Coastguard Worker         } else {
889*3ac0a46fSAndroid Build Coastguard Worker           fWidth = rcLabelContent.Width();
890*3ac0a46fSAndroid Build Coastguard Worker           if (rcBBox.left + fWidth > rcBBox.right) {
891*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = rcBBox;
892*3ac0a46fSAndroid Build Coastguard Worker           } else {
893*3ac0a46fSAndroid Build Coastguard Worker             rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
894*3ac0a46fSAndroid Build Coastguard Worker                                     rcBBox.left + fWidth, rcBBox.top);
895*3ac0a46fSAndroid Build Coastguard Worker             rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
896*3ac0a46fSAndroid Build Coastguard Worker                                    rcBBox.top);
897*3ac0a46fSAndroid Build Coastguard Worker           }
898*3ac0a46fSAndroid Build Coastguard Worker         }
899*3ac0a46fSAndroid Build Coastguard Worker       } else {
900*3ac0a46fSAndroid Build Coastguard Worker         rcLabel = rcBBox;
901*3ac0a46fSAndroid Build Coastguard Worker       }
902*3ac0a46fSAndroid Build Coastguard Worker       break;
903*3ac0a46fSAndroid Build Coastguard Worker     case ButtonStyle::kLabelOverIcon:
904*3ac0a46fSAndroid Build Coastguard Worker       rcLabel = rcBBox;
905*3ac0a46fSAndroid Build Coastguard Worker       rcIcon = rcBBox;
906*3ac0a46fSAndroid Build Coastguard Worker       break;
907*3ac0a46fSAndroid Build Coastguard Worker   }
908*3ac0a46fSAndroid Build Coastguard Worker 
909*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sTemp;
910*3ac0a46fSAndroid Build Coastguard Worker   sTemp << GenerateIconAppStream(IconFit, std::move(pIconStream), rcIcon);
911*3ac0a46fSAndroid Build Coastguard Worker 
912*3ac0a46fSAndroid Build Coastguard Worker   if (!rcLabel.IsEmpty()) {
913*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetPlateRect(rcLabel);
914*3ac0a46fSAndroid Build Coastguard Worker     pEdit->Paint();
915*3ac0a46fSAndroid Build Coastguard Worker     ByteString sEdit =
916*3ac0a46fSAndroid Build Coastguard Worker         GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f), true, 0);
917*3ac0a46fSAndroid Build Coastguard Worker     if (sEdit.GetLength() > 0) {
918*3ac0a46fSAndroid Build Coastguard Worker       AutoClosedCommand bt(&sTemp, kTextBeginOperator, kTextEndOperator);
919*3ac0a46fSAndroid Build Coastguard Worker       sTemp << GetFillColorAppStream(crText) << sEdit;
920*3ac0a46fSAndroid Build Coastguard Worker     }
921*3ac0a46fSAndroid Build Coastguard Worker   }
922*3ac0a46fSAndroid Build Coastguard Worker 
923*3ac0a46fSAndroid Build Coastguard Worker   if (sTemp.tellp() <= 0)
924*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
925*3ac0a46fSAndroid Build Coastguard Worker 
926*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
927*3ac0a46fSAndroid Build Coastguard Worker   {
928*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
929*3ac0a46fSAndroid Build Coastguard Worker     WriteAppendRect(sAppStream, rcBBox);
930*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << kSetNonZeroWindingClipOperator << " "
931*3ac0a46fSAndroid Build Coastguard Worker                << kEndPathNoFillOrStrokeOperator << "\n";
932*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << sTemp.str().c_str();
933*3ac0a46fSAndroid Build Coastguard Worker   }
934*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
935*3ac0a46fSAndroid Build Coastguard Worker }
936*3ac0a46fSAndroid Build Coastguard Worker 
GetBorderAppStreamInternal(const CFX_FloatRect & rect,float fWidth,const CFX_Color & color,const CFX_Color & crLeftTop,const CFX_Color & crRightBottom,BorderStyle nStyle,const CPWL_Dash & dash)937*3ac0a46fSAndroid Build Coastguard Worker ByteString GetBorderAppStreamInternal(const CFX_FloatRect& rect,
938*3ac0a46fSAndroid Build Coastguard Worker                                       float fWidth,
939*3ac0a46fSAndroid Build Coastguard Worker                                       const CFX_Color& color,
940*3ac0a46fSAndroid Build Coastguard Worker                                       const CFX_Color& crLeftTop,
941*3ac0a46fSAndroid Build Coastguard Worker                                       const CFX_Color& crRightBottom,
942*3ac0a46fSAndroid Build Coastguard Worker                                       BorderStyle nStyle,
943*3ac0a46fSAndroid Build Coastguard Worker                                       const CPWL_Dash& dash) {
944*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
945*3ac0a46fSAndroid Build Coastguard Worker   ByteString sColor;
946*3ac0a46fSAndroid Build Coastguard Worker 
947*3ac0a46fSAndroid Build Coastguard Worker   float fLeft = rect.left;
948*3ac0a46fSAndroid Build Coastguard Worker   float fRight = rect.right;
949*3ac0a46fSAndroid Build Coastguard Worker   float fTop = rect.top;
950*3ac0a46fSAndroid Build Coastguard Worker   float fBottom = rect.bottom;
951*3ac0a46fSAndroid Build Coastguard Worker 
952*3ac0a46fSAndroid Build Coastguard Worker   if (fWidth > 0.0f) {
953*3ac0a46fSAndroid Build Coastguard Worker     float fHalfWidth = fWidth / 2.0f;
954*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
955*3ac0a46fSAndroid Build Coastguard Worker 
956*3ac0a46fSAndroid Build Coastguard Worker     switch (nStyle) {
957*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kSolid:
958*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetFillColorAppStream(color);
959*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
960*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
961*3ac0a46fSAndroid Build Coastguard Worker           WriteAppendRect(sAppStream, {fLeft, fBottom, fRight, fTop});
962*3ac0a46fSAndroid Build Coastguard Worker           WriteAppendRect(sAppStream, {fLeft + fWidth, fBottom + fWidth,
963*3ac0a46fSAndroid Build Coastguard Worker                                        fRight - fWidth, fTop - fWidth});
964*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kFillEvenOddOperator << "\n";
965*3ac0a46fSAndroid Build Coastguard Worker         }
966*3ac0a46fSAndroid Build Coastguard Worker         break;
967*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kDash:
968*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
969*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
970*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
971*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fWidth << " " << kSetLineWidthOperator << " ["
972*3ac0a46fSAndroid Build Coastguard Worker                      << dash.nDash << " " << dash.nGap << "] " << dash.nPhase
973*3ac0a46fSAndroid Build Coastguard Worker                      << " " << kSetDashOperator << "\n";
974*3ac0a46fSAndroid Build Coastguard Worker           const CFX_PointF points[] = {
975*3ac0a46fSAndroid Build Coastguard Worker               {fLeft + fWidth / 2, fBottom + fWidth / 2},
976*3ac0a46fSAndroid Build Coastguard Worker               {fLeft + fWidth / 2, fTop - fWidth / 2},
977*3ac0a46fSAndroid Build Coastguard Worker               {fRight - fWidth / 2, fTop - fWidth / 2},
978*3ac0a46fSAndroid Build Coastguard Worker               {fRight - fWidth / 2, fBottom + fWidth / 2}};
979*3ac0a46fSAndroid Build Coastguard Worker           WriteClosedLoop(sAppStream, points);
980*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kStrokeOperator << "\n";
981*3ac0a46fSAndroid Build Coastguard Worker         }
982*3ac0a46fSAndroid Build Coastguard Worker         break;
983*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kBeveled:
984*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kInset:
985*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetFillColorAppStream(crLeftTop);
986*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
987*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
988*3ac0a46fSAndroid Build Coastguard Worker           WriteMove(sAppStream, {fLeft + fHalfWidth, fBottom + fHalfWidth});
989*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream, {fLeft + fHalfWidth, fTop - fHalfWidth});
990*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream, {fRight - fHalfWidth, fTop - fHalfWidth});
991*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
992*3ac0a46fSAndroid Build Coastguard Worker                     {fRight - fHalfWidth * 2, fTop - fHalfWidth * 2});
993*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
994*3ac0a46fSAndroid Build Coastguard Worker                     {fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2});
995*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
996*3ac0a46fSAndroid Build Coastguard Worker                     {fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2});
997*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kFillOperator << "\n";
998*3ac0a46fSAndroid Build Coastguard Worker         }
999*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetFillColorAppStream(crRightBottom);
1000*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
1001*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
1002*3ac0a46fSAndroid Build Coastguard Worker           WriteMove(sAppStream, {fRight - fHalfWidth, fTop - fHalfWidth});
1003*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream, {fRight - fHalfWidth, fBottom + fHalfWidth});
1004*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream, {fLeft + fHalfWidth, fBottom + fHalfWidth});
1005*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
1006*3ac0a46fSAndroid Build Coastguard Worker                     {fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2});
1007*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
1008*3ac0a46fSAndroid Build Coastguard Worker                     {fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2});
1009*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream,
1010*3ac0a46fSAndroid Build Coastguard Worker                     {fRight - fHalfWidth * 2, fTop - fHalfWidth * 2});
1011*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kFillOperator << "\n";
1012*3ac0a46fSAndroid Build Coastguard Worker         }
1013*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetFillColorAppStream(color);
1014*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
1015*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
1016*3ac0a46fSAndroid Build Coastguard Worker           WriteAppendRect(sAppStream, {fLeft, fBottom, fRight, fTop});
1017*3ac0a46fSAndroid Build Coastguard Worker           WriteAppendRect(sAppStream, {fLeft + fHalfWidth, fBottom + fHalfWidth,
1018*3ac0a46fSAndroid Build Coastguard Worker                                        fRight - fHalfWidth, fTop - fHalfWidth});
1019*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kFillEvenOddOperator << "\n";
1020*3ac0a46fSAndroid Build Coastguard Worker         }
1021*3ac0a46fSAndroid Build Coastguard Worker         break;
1022*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kUnderline:
1023*3ac0a46fSAndroid Build Coastguard Worker         sColor = GetStrokeColorAppStream(color);
1024*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
1025*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << sColor;
1026*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << fWidth << " " << kSetLineWidthOperator << "\n";
1027*3ac0a46fSAndroid Build Coastguard Worker           WriteMove(sAppStream, {fLeft, fBottom + fWidth / 2});
1028*3ac0a46fSAndroid Build Coastguard Worker           WriteLine(sAppStream, {fRight, fBottom + fWidth / 2});
1029*3ac0a46fSAndroid Build Coastguard Worker           sAppStream << kStrokeOperator << "\n";
1030*3ac0a46fSAndroid Build Coastguard Worker         }
1031*3ac0a46fSAndroid Build Coastguard Worker         break;
1032*3ac0a46fSAndroid Build Coastguard Worker     }
1033*3ac0a46fSAndroid Build Coastguard Worker   }
1034*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
1035*3ac0a46fSAndroid Build Coastguard Worker }
1036*3ac0a46fSAndroid Build Coastguard Worker 
GetDropButtonAppStream(const CFX_FloatRect & rcBBox)1037*3ac0a46fSAndroid Build Coastguard Worker ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
1038*3ac0a46fSAndroid Build Coastguard Worker   if (rcBBox.IsEmpty())
1039*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
1040*3ac0a46fSAndroid Build Coastguard Worker 
1041*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
1042*3ac0a46fSAndroid Build Coastguard Worker   {
1043*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
1044*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << GetFillColorAppStream(
1045*3ac0a46fSAndroid Build Coastguard Worker         CFX_Color(CFX_Color::Type::kRGB, 220.0f / 255.0f, 220.0f / 255.0f,
1046*3ac0a46fSAndroid Build Coastguard Worker                   220.0f / 255.0f));
1047*3ac0a46fSAndroid Build Coastguard Worker     WriteAppendRect(sAppStream, rcBBox);
1048*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << kFillOperator << "\n";
1049*3ac0a46fSAndroid Build Coastguard Worker   }
1050*3ac0a46fSAndroid Build Coastguard Worker 
1051*3ac0a46fSAndroid Build Coastguard Worker   {
1052*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
1053*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << GetBorderAppStreamInternal(
1054*3ac0a46fSAndroid Build Coastguard Worker         rcBBox, 2, CFX_Color(CFX_Color::Type::kGray, 0),
1055*3ac0a46fSAndroid Build Coastguard Worker         CFX_Color(CFX_Color::Type::kGray, 1),
1056*3ac0a46fSAndroid Build Coastguard Worker         CFX_Color(CFX_Color::Type::kGray, 0.5), BorderStyle::kBeveled,
1057*3ac0a46fSAndroid Build Coastguard Worker         CPWL_Dash(3, 0, 0));
1058*3ac0a46fSAndroid Build Coastguard Worker   }
1059*3ac0a46fSAndroid Build Coastguard Worker 
1060*3ac0a46fSAndroid Build Coastguard Worker   CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2,
1061*3ac0a46fSAndroid Build Coastguard Worker                                    (rcBBox.top + rcBBox.bottom) / 2);
1062*3ac0a46fSAndroid Build Coastguard Worker   if (FXSYS_IsFloatBigger(rcBBox.right - rcBBox.left, 6) &&
1063*3ac0a46fSAndroid Build Coastguard Worker       FXSYS_IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) {
1064*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
1065*3ac0a46fSAndroid Build Coastguard Worker     const CFX_PointF points[] = {{ptCenter.x - 3, ptCenter.y + 1.5f},
1066*3ac0a46fSAndroid Build Coastguard Worker                                  {ptCenter.x + 3, ptCenter.y + 1.5f},
1067*3ac0a46fSAndroid Build Coastguard Worker                                  {ptCenter.x, ptCenter.y - 1.5f}};
1068*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << " 0 " << kSetGrayOperator << "\n";
1069*3ac0a46fSAndroid Build Coastguard Worker     WriteClosedLoop(sAppStream, points);
1070*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << kFillOperator << "\n";
1071*3ac0a46fSAndroid Build Coastguard Worker   }
1072*3ac0a46fSAndroid Build Coastguard Worker 
1073*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
1074*3ac0a46fSAndroid Build Coastguard Worker }
1075*3ac0a46fSAndroid Build Coastguard Worker 
GetRectFillAppStream(const CFX_FloatRect & rect,const CFX_Color & color)1076*3ac0a46fSAndroid Build Coastguard Worker ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
1077*3ac0a46fSAndroid Build Coastguard Worker                                 const CFX_Color& color) {
1078*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sAppStream;
1079*3ac0a46fSAndroid Build Coastguard Worker   ByteString sColor = GetFillColorAppStream(color);
1080*3ac0a46fSAndroid Build Coastguard Worker   if (sColor.GetLength() > 0) {
1081*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sAppStream);
1082*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << sColor;
1083*3ac0a46fSAndroid Build Coastguard Worker     WriteAppendRect(sAppStream, rect);
1084*3ac0a46fSAndroid Build Coastguard Worker     sAppStream << kFillOperator << "\n";
1085*3ac0a46fSAndroid Build Coastguard Worker   }
1086*3ac0a46fSAndroid Build Coastguard Worker 
1087*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(sAppStream);
1088*3ac0a46fSAndroid Build Coastguard Worker }
1089*3ac0a46fSAndroid Build Coastguard Worker 
SetDefaultIconName(CPDF_Stream * pIcon,const char * name)1090*3ac0a46fSAndroid Build Coastguard Worker void SetDefaultIconName(CPDF_Stream* pIcon, const char* name) {
1091*3ac0a46fSAndroid Build Coastguard Worker   if (!pIcon)
1092*3ac0a46fSAndroid Build Coastguard Worker     return;
1093*3ac0a46fSAndroid Build Coastguard Worker 
1094*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pImageDict = pIcon->GetMutableDict();
1095*3ac0a46fSAndroid Build Coastguard Worker   if (!pImageDict)
1096*3ac0a46fSAndroid Build Coastguard Worker     return;
1097*3ac0a46fSAndroid Build Coastguard Worker 
1098*3ac0a46fSAndroid Build Coastguard Worker   if (pImageDict->KeyExist("Name"))
1099*3ac0a46fSAndroid Build Coastguard Worker     return;
1100*3ac0a46fSAndroid Build Coastguard Worker 
1101*3ac0a46fSAndroid Build Coastguard Worker   pImageDict->SetNewFor<CPDF_String>("Name", name, false);
1102*3ac0a46fSAndroid Build Coastguard Worker }
1103*3ac0a46fSAndroid Build Coastguard Worker 
CheckStyleFromCaption(const WideString & caption)1104*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CheckStyle> CheckStyleFromCaption(const WideString& caption) {
1105*3ac0a46fSAndroid Build Coastguard Worker   if (caption.IsEmpty())
1106*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
1107*3ac0a46fSAndroid Build Coastguard Worker 
1108*3ac0a46fSAndroid Build Coastguard Worker   // Character values are ZapfDingbats encodings of named glyphs.
1109*3ac0a46fSAndroid Build Coastguard Worker   switch (caption[0]) {
1110*3ac0a46fSAndroid Build Coastguard Worker     case L'4':
1111*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kCheck;
1112*3ac0a46fSAndroid Build Coastguard Worker     case L'8':
1113*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kCross;
1114*3ac0a46fSAndroid Build Coastguard Worker     case L'H':
1115*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kStar;
1116*3ac0a46fSAndroid Build Coastguard Worker     case L'l':
1117*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kCircle;
1118*3ac0a46fSAndroid Build Coastguard Worker     case L'n':
1119*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kSquare;
1120*3ac0a46fSAndroid Build Coastguard Worker     case L'u':
1121*3ac0a46fSAndroid Build Coastguard Worker       return CheckStyle::kDiamond;
1122*3ac0a46fSAndroid Build Coastguard Worker     default:
1123*3ac0a46fSAndroid Build Coastguard Worker       return absl::nullopt;
1124*3ac0a46fSAndroid Build Coastguard Worker   }
1125*3ac0a46fSAndroid Build Coastguard Worker }
1126*3ac0a46fSAndroid Build Coastguard Worker 
1127*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
1128*3ac0a46fSAndroid Build Coastguard Worker 
CPDFSDK_AppStream(CPDFSDK_Widget * widget,CPDF_Dictionary * dict)1129*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_AppStream::CPDFSDK_AppStream(CPDFSDK_Widget* widget,
1130*3ac0a46fSAndroid Build Coastguard Worker                                      CPDF_Dictionary* dict)
1131*3ac0a46fSAndroid Build Coastguard Worker     : widget_(widget), dict_(dict) {}
1132*3ac0a46fSAndroid Build Coastguard Worker 
1133*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_AppStream::~CPDFSDK_AppStream() = default;
1134*3ac0a46fSAndroid Build Coastguard Worker 
SetAsPushButton()1135*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsPushButton() {
1136*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1137*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1138*3ac0a46fSAndroid Build Coastguard Worker   ButtonStyle nLayout = ButtonStyle::kLabel;
1139*3ac0a46fSAndroid Build Coastguard Worker   switch (pControl->GetTextPosition()) {
1140*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_ICON:
1141*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kIcon;
1142*3ac0a46fSAndroid Build Coastguard Worker       break;
1143*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_BELOW:
1144*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kIconTopLabelBottom;
1145*3ac0a46fSAndroid Build Coastguard Worker       break;
1146*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_ABOVE:
1147*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kIconBottomLabelTop;
1148*3ac0a46fSAndroid Build Coastguard Worker       break;
1149*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_RIGHT:
1150*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kIconLeftLabelRight;
1151*3ac0a46fSAndroid Build Coastguard Worker       break;
1152*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_LEFT:
1153*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kIconRightLabelLeft;
1154*3ac0a46fSAndroid Build Coastguard Worker       break;
1155*3ac0a46fSAndroid Build Coastguard Worker     case TEXTPOS_OVERLAID:
1156*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kLabelOverIcon;
1157*3ac0a46fSAndroid Build Coastguard Worker       break;
1158*3ac0a46fSAndroid Build Coastguard Worker     default:
1159*3ac0a46fSAndroid Build Coastguard Worker       nLayout = ButtonStyle::kLabel;
1160*3ac0a46fSAndroid Build Coastguard Worker       break;
1161*3ac0a46fSAndroid Build Coastguard Worker   }
1162*3ac0a46fSAndroid Build Coastguard Worker 
1163*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBackground = pControl->GetOriginalBackgroundColor();
1164*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBorder = pControl->GetOriginalBorderColor();
1165*3ac0a46fSAndroid Build Coastguard Worker 
1166*3ac0a46fSAndroid Build Coastguard Worker   float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1167*3ac0a46fSAndroid Build Coastguard Worker   CPWL_Dash dsBorder(3, 0, 0);
1168*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crLeftTop;
1169*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crRightBottom;
1170*3ac0a46fSAndroid Build Coastguard Worker 
1171*3ac0a46fSAndroid Build Coastguard Worker   BorderStyle nBorderStyle = widget_->GetBorderStyle();
1172*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1173*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kDash:
1174*3ac0a46fSAndroid Build Coastguard Worker       dsBorder = CPWL_Dash(3, 3, 0);
1175*3ac0a46fSAndroid Build Coastguard Worker       break;
1176*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled:
1177*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1178*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 1);
1179*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crBackground / 2.0f;
1180*3ac0a46fSAndroid Build Coastguard Worker       break;
1181*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset:
1182*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1183*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0.5);
1184*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 0.75);
1185*3ac0a46fSAndroid Build Coastguard Worker       break;
1186*3ac0a46fSAndroid Build Coastguard Worker     default:
1187*3ac0a46fSAndroid Build Coastguard Worker       break;
1188*3ac0a46fSAndroid Build Coastguard Worker   }
1189*3ac0a46fSAndroid Build Coastguard Worker 
1190*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1191*3ac0a46fSAndroid Build Coastguard Worker   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1192*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CFX_Color> color = da.GetColor();
1193*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crText = color.value_or(CFX_Color(CFX_Color::Type::kGray, 0));
1194*3ac0a46fSAndroid Build Coastguard Worker 
1195*3ac0a46fSAndroid Build Coastguard Worker   float fFontSize;
1196*3ac0a46fSAndroid Build Coastguard Worker   ByteString csNameTag;
1197*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<ByteString> font = da.GetFont(&fFontSize);
1198*3ac0a46fSAndroid Build Coastguard Worker   if (font.has_value())
1199*3ac0a46fSAndroid Build Coastguard Worker     csNameTag = font.value();
1200*3ac0a46fSAndroid Build Coastguard Worker   else
1201*3ac0a46fSAndroid Build Coastguard Worker     fFontSize = 12.0f;
1202*3ac0a46fSAndroid Build Coastguard Worker 
1203*3ac0a46fSAndroid Build Coastguard Worker   WideString csWCaption;
1204*3ac0a46fSAndroid Build Coastguard Worker   WideString csNormalCaption;
1205*3ac0a46fSAndroid Build Coastguard Worker   WideString csRolloverCaption;
1206*3ac0a46fSAndroid Build Coastguard Worker   WideString csDownCaption;
1207*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kCA))
1208*3ac0a46fSAndroid Build Coastguard Worker     csNormalCaption = pControl->GetNormalCaption();
1209*3ac0a46fSAndroid Build Coastguard Worker 
1210*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kRC))
1211*3ac0a46fSAndroid Build Coastguard Worker     csRolloverCaption = pControl->GetRolloverCaption();
1212*3ac0a46fSAndroid Build Coastguard Worker 
1213*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kAC))
1214*3ac0a46fSAndroid Build Coastguard Worker     csDownCaption = pControl->GetDownCaption();
1215*3ac0a46fSAndroid Build Coastguard Worker 
1216*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pNormalIcon;
1217*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pRolloverIcon;
1218*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pDownIcon;
1219*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kI))
1220*3ac0a46fSAndroid Build Coastguard Worker     pNormalIcon = pControl->GetNormalIcon();
1221*3ac0a46fSAndroid Build Coastguard Worker 
1222*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kRI))
1223*3ac0a46fSAndroid Build Coastguard Worker     pRolloverIcon = pControl->GetRolloverIcon();
1224*3ac0a46fSAndroid Build Coastguard Worker 
1225*3ac0a46fSAndroid Build Coastguard Worker   if (pControl->HasMKEntry(pdfium::appearance::kIX))
1226*3ac0a46fSAndroid Build Coastguard Worker     pDownIcon = pControl->GetDownIcon();
1227*3ac0a46fSAndroid Build Coastguard Worker 
1228*3ac0a46fSAndroid Build Coastguard Worker   SetDefaultIconName(pNormalIcon.Get(), "ImgA");
1229*3ac0a46fSAndroid Build Coastguard Worker   SetDefaultIconName(pRolloverIcon.Get(), "ImgB");
1230*3ac0a46fSAndroid Build Coastguard Worker   SetDefaultIconName(pDownIcon.Get(), "ImgC");
1231*3ac0a46fSAndroid Build Coastguard Worker 
1232*3ac0a46fSAndroid Build Coastguard Worker   CPDF_IconFit iconFit = pControl->GetIconFit();
1233*3ac0a46fSAndroid Build Coastguard Worker   {
1234*3ac0a46fSAndroid Build Coastguard Worker     CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1235*3ac0a46fSAndroid Build Coastguard Worker                             widget_->GetPDFAnnot()->GetMutableAnnotDict(), "N");
1236*3ac0a46fSAndroid Build Coastguard Worker     ByteString csAP =
1237*3ac0a46fSAndroid Build Coastguard Worker         GetRectFillAppStream(rcWindow, crBackground) +
1238*3ac0a46fSAndroid Build Coastguard Worker         GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1239*3ac0a46fSAndroid Build Coastguard Worker                                    crRightBottom, nBorderStyle, dsBorder) +
1240*3ac0a46fSAndroid Build Coastguard Worker         GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1241*3ac0a46fSAndroid Build Coastguard Worker                                &font_map, pNormalIcon, iconFit, csNormalCaption,
1242*3ac0a46fSAndroid Build Coastguard Worker                                crText, fFontSize, nLayout);
1243*3ac0a46fSAndroid Build Coastguard Worker 
1244*3ac0a46fSAndroid Build Coastguard Worker     Write("N", csAP, ByteString());
1245*3ac0a46fSAndroid Build Coastguard Worker     if (pNormalIcon)
1246*3ac0a46fSAndroid Build Coastguard Worker       AddImage("N", pNormalIcon.Get());
1247*3ac0a46fSAndroid Build Coastguard Worker 
1248*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode();
1249*3ac0a46fSAndroid Build Coastguard Worker     if (eHLM != CPDF_FormControl::kPush && eHLM != CPDF_FormControl::kToggle) {
1250*3ac0a46fSAndroid Build Coastguard Worker       Remove("D");
1251*3ac0a46fSAndroid Build Coastguard Worker       Remove("R");
1252*3ac0a46fSAndroid Build Coastguard Worker       return;
1253*3ac0a46fSAndroid Build Coastguard Worker     }
1254*3ac0a46fSAndroid Build Coastguard Worker 
1255*3ac0a46fSAndroid Build Coastguard Worker     if (csRolloverCaption.IsEmpty() && !pRolloverIcon) {
1256*3ac0a46fSAndroid Build Coastguard Worker       csRolloverCaption = csNormalCaption;
1257*3ac0a46fSAndroid Build Coastguard Worker       pRolloverIcon = pNormalIcon;
1258*3ac0a46fSAndroid Build Coastguard Worker     }
1259*3ac0a46fSAndroid Build Coastguard Worker   }
1260*3ac0a46fSAndroid Build Coastguard Worker   {
1261*3ac0a46fSAndroid Build Coastguard Worker     CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1262*3ac0a46fSAndroid Build Coastguard Worker                             widget_->GetPDFAnnot()->GetMutableAnnotDict(), "R");
1263*3ac0a46fSAndroid Build Coastguard Worker     ByteString csAP =
1264*3ac0a46fSAndroid Build Coastguard Worker         GetRectFillAppStream(rcWindow, crBackground) +
1265*3ac0a46fSAndroid Build Coastguard Worker         GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1266*3ac0a46fSAndroid Build Coastguard Worker                                    crRightBottom, nBorderStyle, dsBorder) +
1267*3ac0a46fSAndroid Build Coastguard Worker         GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1268*3ac0a46fSAndroid Build Coastguard Worker                                &font_map, pRolloverIcon, iconFit,
1269*3ac0a46fSAndroid Build Coastguard Worker                                csRolloverCaption, crText, fFontSize, nLayout);
1270*3ac0a46fSAndroid Build Coastguard Worker 
1271*3ac0a46fSAndroid Build Coastguard Worker     Write("R", csAP, ByteString());
1272*3ac0a46fSAndroid Build Coastguard Worker     if (pRolloverIcon)
1273*3ac0a46fSAndroid Build Coastguard Worker       AddImage("R", pRolloverIcon.Get());
1274*3ac0a46fSAndroid Build Coastguard Worker 
1275*3ac0a46fSAndroid Build Coastguard Worker     if (csDownCaption.IsEmpty() && !pDownIcon) {
1276*3ac0a46fSAndroid Build Coastguard Worker       csDownCaption = csNormalCaption;
1277*3ac0a46fSAndroid Build Coastguard Worker       pDownIcon = pNormalIcon;
1278*3ac0a46fSAndroid Build Coastguard Worker     }
1279*3ac0a46fSAndroid Build Coastguard Worker 
1280*3ac0a46fSAndroid Build Coastguard Worker     switch (nBorderStyle) {
1281*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kBeveled: {
1282*3ac0a46fSAndroid Build Coastguard Worker         CFX_Color crTemp = crLeftTop;
1283*3ac0a46fSAndroid Build Coastguard Worker         crLeftTop = crRightBottom;
1284*3ac0a46fSAndroid Build Coastguard Worker         crRightBottom = crTemp;
1285*3ac0a46fSAndroid Build Coastguard Worker         break;
1286*3ac0a46fSAndroid Build Coastguard Worker       }
1287*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kInset: {
1288*3ac0a46fSAndroid Build Coastguard Worker         crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0);
1289*3ac0a46fSAndroid Build Coastguard Worker         crRightBottom = CFX_Color(CFX_Color::Type::kGray, 1);
1290*3ac0a46fSAndroid Build Coastguard Worker         break;
1291*3ac0a46fSAndroid Build Coastguard Worker       }
1292*3ac0a46fSAndroid Build Coastguard Worker       default:
1293*3ac0a46fSAndroid Build Coastguard Worker         break;
1294*3ac0a46fSAndroid Build Coastguard Worker     }
1295*3ac0a46fSAndroid Build Coastguard Worker   }
1296*3ac0a46fSAndroid Build Coastguard Worker   {
1297*3ac0a46fSAndroid Build Coastguard Worker     CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1298*3ac0a46fSAndroid Build Coastguard Worker                             widget_->GetPDFAnnot()->GetMutableAnnotDict(), "D");
1299*3ac0a46fSAndroid Build Coastguard Worker     ByteString csAP =
1300*3ac0a46fSAndroid Build Coastguard Worker         GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1301*3ac0a46fSAndroid Build Coastguard Worker         GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1302*3ac0a46fSAndroid Build Coastguard Worker                                    crRightBottom, nBorderStyle, dsBorder) +
1303*3ac0a46fSAndroid Build Coastguard Worker         GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1304*3ac0a46fSAndroid Build Coastguard Worker                                &font_map, pDownIcon, iconFit, csDownCaption,
1305*3ac0a46fSAndroid Build Coastguard Worker                                crText, fFontSize, nLayout);
1306*3ac0a46fSAndroid Build Coastguard Worker 
1307*3ac0a46fSAndroid Build Coastguard Worker     Write("D", csAP, ByteString());
1308*3ac0a46fSAndroid Build Coastguard Worker     if (pDownIcon)
1309*3ac0a46fSAndroid Build Coastguard Worker       AddImage("D", pDownIcon.Get());
1310*3ac0a46fSAndroid Build Coastguard Worker   }
1311*3ac0a46fSAndroid Build Coastguard Worker }
1312*3ac0a46fSAndroid Build Coastguard Worker 
SetAsCheckBox()1313*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsCheckBox() {
1314*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1315*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBackground = pControl->GetOriginalBackgroundColor();
1316*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBorder = pControl->GetOriginalBorderColor();
1317*3ac0a46fSAndroid Build Coastguard Worker   float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1318*3ac0a46fSAndroid Build Coastguard Worker   CPWL_Dash dsBorder(3, 0, 0);
1319*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crLeftTop;
1320*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crRightBottom;
1321*3ac0a46fSAndroid Build Coastguard Worker 
1322*3ac0a46fSAndroid Build Coastguard Worker   BorderStyle nBorderStyle = widget_->GetBorderStyle();
1323*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1324*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kDash:
1325*3ac0a46fSAndroid Build Coastguard Worker       dsBorder = CPWL_Dash(3, 3, 0);
1326*3ac0a46fSAndroid Build Coastguard Worker       break;
1327*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled:
1328*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1329*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 1);
1330*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crBackground / 2.0f;
1331*3ac0a46fSAndroid Build Coastguard Worker       break;
1332*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset:
1333*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1334*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0.5);
1335*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 0.75);
1336*3ac0a46fSAndroid Build Coastguard Worker       break;
1337*3ac0a46fSAndroid Build Coastguard Worker     default:
1338*3ac0a46fSAndroid Build Coastguard Worker       break;
1339*3ac0a46fSAndroid Build Coastguard Worker   }
1340*3ac0a46fSAndroid Build Coastguard Worker 
1341*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1342*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1343*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CFX_Color> color = pControl->GetDefaultAppearance().GetColor();
1344*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crText = color.value_or(CFX_Color());
1345*3ac0a46fSAndroid Build Coastguard Worker 
1346*3ac0a46fSAndroid Build Coastguard Worker   CheckStyle nStyle = CheckStyleFromCaption(pControl->GetNormalCaption())
1347*3ac0a46fSAndroid Build Coastguard Worker                           .value_or(CheckStyle::kCheck);
1348*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_N_ON =
1349*3ac0a46fSAndroid Build Coastguard Worker       GetRectFillAppStream(rcWindow, crBackground) +
1350*3ac0a46fSAndroid Build Coastguard Worker       GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1351*3ac0a46fSAndroid Build Coastguard Worker                                  crRightBottom, nBorderStyle, dsBorder);
1352*3ac0a46fSAndroid Build Coastguard Worker 
1353*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_N_OFF = csAP_N_ON;
1354*3ac0a46fSAndroid Build Coastguard Worker 
1355*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1356*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled: {
1357*3ac0a46fSAndroid Build Coastguard Worker       CFX_Color crTemp = crLeftTop;
1358*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = crRightBottom;
1359*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crTemp;
1360*3ac0a46fSAndroid Build Coastguard Worker       break;
1361*3ac0a46fSAndroid Build Coastguard Worker     }
1362*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset: {
1363*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0);
1364*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 1);
1365*3ac0a46fSAndroid Build Coastguard Worker       break;
1366*3ac0a46fSAndroid Build Coastguard Worker     }
1367*3ac0a46fSAndroid Build Coastguard Worker     default:
1368*3ac0a46fSAndroid Build Coastguard Worker       break;
1369*3ac0a46fSAndroid Build Coastguard Worker   }
1370*3ac0a46fSAndroid Build Coastguard Worker 
1371*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_D_ON =
1372*3ac0a46fSAndroid Build Coastguard Worker       GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1373*3ac0a46fSAndroid Build Coastguard Worker       GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1374*3ac0a46fSAndroid Build Coastguard Worker                                  crRightBottom, nBorderStyle, dsBorder);
1375*3ac0a46fSAndroid Build Coastguard Worker 
1376*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_D_OFF = csAP_D_ON;
1377*3ac0a46fSAndroid Build Coastguard Worker 
1378*3ac0a46fSAndroid Build Coastguard Worker   csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1379*3ac0a46fSAndroid Build Coastguard Worker   csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1380*3ac0a46fSAndroid Build Coastguard Worker 
1381*3ac0a46fSAndroid Build Coastguard Worker   Write("N", csAP_N_ON, pControl->GetCheckedAPState());
1382*3ac0a46fSAndroid Build Coastguard Worker   Write("N", csAP_N_OFF, "Off");
1383*3ac0a46fSAndroid Build Coastguard Worker 
1384*3ac0a46fSAndroid Build Coastguard Worker   Write("D", csAP_D_ON, pControl->GetCheckedAPState());
1385*3ac0a46fSAndroid Build Coastguard Worker   Write("D", csAP_D_OFF, "Off");
1386*3ac0a46fSAndroid Build Coastguard Worker 
1387*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAS = widget_->GetAppState();
1388*3ac0a46fSAndroid Build Coastguard Worker   if (csAS.IsEmpty())
1389*3ac0a46fSAndroid Build Coastguard Worker     widget_->SetAppStateOff();
1390*3ac0a46fSAndroid Build Coastguard Worker }
1391*3ac0a46fSAndroid Build Coastguard Worker 
SetAsRadioButton()1392*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsRadioButton() {
1393*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1394*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBackground = pControl->GetOriginalBackgroundColor();
1395*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBorder = pControl->GetOriginalBorderColor();
1396*3ac0a46fSAndroid Build Coastguard Worker   float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1397*3ac0a46fSAndroid Build Coastguard Worker   CPWL_Dash dsBorder(3, 0, 0);
1398*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crLeftTop;
1399*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crRightBottom;
1400*3ac0a46fSAndroid Build Coastguard Worker 
1401*3ac0a46fSAndroid Build Coastguard Worker   BorderStyle nBorderStyle = widget_->GetBorderStyle();
1402*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1403*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kDash:
1404*3ac0a46fSAndroid Build Coastguard Worker       dsBorder = CPWL_Dash(3, 3, 0);
1405*3ac0a46fSAndroid Build Coastguard Worker       break;
1406*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled:
1407*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1408*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 1);
1409*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crBackground / 2.0f;
1410*3ac0a46fSAndroid Build Coastguard Worker       break;
1411*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset:
1412*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1413*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0.5);
1414*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 0.75);
1415*3ac0a46fSAndroid Build Coastguard Worker       break;
1416*3ac0a46fSAndroid Build Coastguard Worker     default:
1417*3ac0a46fSAndroid Build Coastguard Worker       break;
1418*3ac0a46fSAndroid Build Coastguard Worker   }
1419*3ac0a46fSAndroid Build Coastguard Worker 
1420*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1421*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1422*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CFX_Color> color = pControl->GetDefaultAppearance().GetColor();
1423*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crText = color.value_or(CFX_Color());
1424*3ac0a46fSAndroid Build Coastguard Worker   CheckStyle nStyle = CheckStyleFromCaption(pControl->GetNormalCaption())
1425*3ac0a46fSAndroid Build Coastguard Worker                           .value_or(CheckStyle::kCircle);
1426*3ac0a46fSAndroid Build Coastguard Worker 
1427*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_N_ON;
1428*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f);
1429*3ac0a46fSAndroid Build Coastguard Worker   if (nStyle == CheckStyle::kCircle) {
1430*3ac0a46fSAndroid Build Coastguard Worker     if (nBorderStyle == BorderStyle::kBeveled) {
1431*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 1);
1432*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crBackground - 0.25f;
1433*3ac0a46fSAndroid Build Coastguard Worker     } else if (nBorderStyle == BorderStyle::kInset) {
1434*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0.5f);
1435*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 0.75f);
1436*3ac0a46fSAndroid Build Coastguard Worker     }
1437*3ac0a46fSAndroid Build Coastguard Worker 
1438*3ac0a46fSAndroid Build Coastguard Worker     csAP_N_ON =
1439*3ac0a46fSAndroid Build Coastguard Worker         GetCircleFillAppStream(rcCenter, crBackground) +
1440*3ac0a46fSAndroid Build Coastguard Worker         GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
1441*3ac0a46fSAndroid Build Coastguard Worker                                  crRightBottom, nBorderStyle, dsBorder);
1442*3ac0a46fSAndroid Build Coastguard Worker   } else {
1443*3ac0a46fSAndroid Build Coastguard Worker     csAP_N_ON =
1444*3ac0a46fSAndroid Build Coastguard Worker         GetRectFillAppStream(rcWindow, crBackground) +
1445*3ac0a46fSAndroid Build Coastguard Worker         GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1446*3ac0a46fSAndroid Build Coastguard Worker                                    crRightBottom, nBorderStyle, dsBorder);
1447*3ac0a46fSAndroid Build Coastguard Worker   }
1448*3ac0a46fSAndroid Build Coastguard Worker 
1449*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_N_OFF = csAP_N_ON;
1450*3ac0a46fSAndroid Build Coastguard Worker 
1451*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1452*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled: {
1453*3ac0a46fSAndroid Build Coastguard Worker       CFX_Color crTemp = crLeftTop;
1454*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = crRightBottom;
1455*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crTemp;
1456*3ac0a46fSAndroid Build Coastguard Worker       break;
1457*3ac0a46fSAndroid Build Coastguard Worker     }
1458*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset: {
1459*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0);
1460*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 1);
1461*3ac0a46fSAndroid Build Coastguard Worker       break;
1462*3ac0a46fSAndroid Build Coastguard Worker     }
1463*3ac0a46fSAndroid Build Coastguard Worker     default:
1464*3ac0a46fSAndroid Build Coastguard Worker       break;
1465*3ac0a46fSAndroid Build Coastguard Worker   }
1466*3ac0a46fSAndroid Build Coastguard Worker 
1467*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_D_ON;
1468*3ac0a46fSAndroid Build Coastguard Worker 
1469*3ac0a46fSAndroid Build Coastguard Worker   if (nStyle == CheckStyle::kCircle) {
1470*3ac0a46fSAndroid Build Coastguard Worker     CFX_Color crBK = crBackground - 0.25f;
1471*3ac0a46fSAndroid Build Coastguard Worker     if (nBorderStyle == BorderStyle::kBeveled) {
1472*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = crBackground - 0.25f;
1473*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 1);
1474*3ac0a46fSAndroid Build Coastguard Worker       crBK = crBackground;
1475*3ac0a46fSAndroid Build Coastguard Worker     } else if (nBorderStyle == BorderStyle::kInset) {
1476*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0);
1477*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 1);
1478*3ac0a46fSAndroid Build Coastguard Worker     }
1479*3ac0a46fSAndroid Build Coastguard Worker 
1480*3ac0a46fSAndroid Build Coastguard Worker     csAP_D_ON =
1481*3ac0a46fSAndroid Build Coastguard Worker         GetCircleFillAppStream(rcCenter, crBK) +
1482*3ac0a46fSAndroid Build Coastguard Worker         GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
1483*3ac0a46fSAndroid Build Coastguard Worker                                  crRightBottom, nBorderStyle, dsBorder);
1484*3ac0a46fSAndroid Build Coastguard Worker   } else {
1485*3ac0a46fSAndroid Build Coastguard Worker     csAP_D_ON =
1486*3ac0a46fSAndroid Build Coastguard Worker         GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1487*3ac0a46fSAndroid Build Coastguard Worker         GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1488*3ac0a46fSAndroid Build Coastguard Worker                                    crRightBottom, nBorderStyle, dsBorder);
1489*3ac0a46fSAndroid Build Coastguard Worker   }
1490*3ac0a46fSAndroid Build Coastguard Worker 
1491*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAP_D_OFF = csAP_D_ON;
1492*3ac0a46fSAndroid Build Coastguard Worker 
1493*3ac0a46fSAndroid Build Coastguard Worker   ByteString app_stream = GetRadioButtonAppStream(rcClient, nStyle, crText);
1494*3ac0a46fSAndroid Build Coastguard Worker   csAP_N_ON += app_stream;
1495*3ac0a46fSAndroid Build Coastguard Worker   csAP_D_ON += app_stream;
1496*3ac0a46fSAndroid Build Coastguard Worker 
1497*3ac0a46fSAndroid Build Coastguard Worker   Write("N", csAP_N_ON, pControl->GetCheckedAPState());
1498*3ac0a46fSAndroid Build Coastguard Worker   Write("N", csAP_N_OFF, "Off");
1499*3ac0a46fSAndroid Build Coastguard Worker 
1500*3ac0a46fSAndroid Build Coastguard Worker   Write("D", csAP_D_ON, pControl->GetCheckedAPState());
1501*3ac0a46fSAndroid Build Coastguard Worker   Write("D", csAP_D_OFF, "Off");
1502*3ac0a46fSAndroid Build Coastguard Worker 
1503*3ac0a46fSAndroid Build Coastguard Worker   ByteString csAS = widget_->GetAppState();
1504*3ac0a46fSAndroid Build Coastguard Worker   if (csAS.IsEmpty())
1505*3ac0a46fSAndroid Build Coastguard Worker     widget_->SetAppStateOff();
1506*3ac0a46fSAndroid Build Coastguard Worker }
1507*3ac0a46fSAndroid Build Coastguard Worker 
SetAsComboBox(absl::optional<WideString> sValue)1508*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsComboBox(absl::optional<WideString> sValue) {
1509*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1510*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pField = pControl->GetField();
1511*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sBody;
1512*3ac0a46fSAndroid Build Coastguard Worker 
1513*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = widget_->GetClientRect();
1514*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcButton = rcClient;
1515*3ac0a46fSAndroid Build Coastguard Worker   rcButton.left = rcButton.right - 13;
1516*3ac0a46fSAndroid Build Coastguard Worker   rcButton.Normalize();
1517*3ac0a46fSAndroid Build Coastguard Worker 
1518*3ac0a46fSAndroid Build Coastguard Worker   // Font map must outlive |pEdit|.
1519*3ac0a46fSAndroid Build Coastguard Worker   CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1520*3ac0a46fSAndroid Build Coastguard Worker                           widget_->GetPDFAnnot()->GetMutableAnnotDict(), "N");
1521*3ac0a46fSAndroid Build Coastguard Worker 
1522*3ac0a46fSAndroid Build Coastguard Worker   auto pEdit = std::make_unique<CPWL_EditImpl>();
1523*3ac0a46fSAndroid Build Coastguard Worker   pEdit->EnableRefresh(false);
1524*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetFontMap(&font_map);
1525*3ac0a46fSAndroid Build Coastguard Worker 
1526*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcEdit = rcClient;
1527*3ac0a46fSAndroid Build Coastguard Worker   rcEdit.right = rcButton.left;
1528*3ac0a46fSAndroid Build Coastguard Worker   rcEdit.Normalize();
1529*3ac0a46fSAndroid Build Coastguard Worker 
1530*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetPlateRect(rcEdit);
1531*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetAlignmentV(1);
1532*3ac0a46fSAndroid Build Coastguard Worker 
1533*3ac0a46fSAndroid Build Coastguard Worker   float fFontSize = widget_->GetFontSize();
1534*3ac0a46fSAndroid Build Coastguard Worker   if (FXSYS_IsFloatZero(fFontSize))
1535*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetAutoFontSize(true);
1536*3ac0a46fSAndroid Build Coastguard Worker   else
1537*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetFontSize(fFontSize);
1538*3ac0a46fSAndroid Build Coastguard Worker 
1539*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Initialize();
1540*3ac0a46fSAndroid Build Coastguard Worker   if (sValue.has_value()) {
1541*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetText(sValue.value());
1542*3ac0a46fSAndroid Build Coastguard Worker   } else {
1543*3ac0a46fSAndroid Build Coastguard Worker     int32_t nCurSel = pField->GetSelectedIndex(0);
1544*3ac0a46fSAndroid Build Coastguard Worker     if (nCurSel < 0) {
1545*3ac0a46fSAndroid Build Coastguard Worker       pEdit->SetText(pField->GetValue());
1546*3ac0a46fSAndroid Build Coastguard Worker     } else {
1547*3ac0a46fSAndroid Build Coastguard Worker       pEdit->SetText(pField->GetOptionLabel(nCurSel));
1548*3ac0a46fSAndroid Build Coastguard Worker     }
1549*3ac0a46fSAndroid Build Coastguard Worker   }
1550*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Paint();
1551*3ac0a46fSAndroid Build Coastguard Worker 
1552*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcContent = pEdit->GetContentRect();
1553*3ac0a46fSAndroid Build Coastguard Worker   ByteString sEdit = GetEditAppStream(pEdit.get(), CFX_PointF(), true, 0);
1554*3ac0a46fSAndroid Build Coastguard Worker   if (sEdit.GetLength() > 0) {
1555*3ac0a46fSAndroid Build Coastguard Worker     sBody << "/Tx ";
1556*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1557*3ac0a46fSAndroid Build Coastguard Worker                           kMarkedSequenceEndOperator);
1558*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sBody);
1559*3ac0a46fSAndroid Build Coastguard Worker 
1560*3ac0a46fSAndroid Build Coastguard Worker     if (rcContent.Width() > rcEdit.Width() ||
1561*3ac0a46fSAndroid Build Coastguard Worker         rcContent.Height() > rcEdit.Height()) {
1562*3ac0a46fSAndroid Build Coastguard Worker       WriteAppendRect(sBody, rcEdit);
1563*3ac0a46fSAndroid Build Coastguard Worker       sBody << kSetNonZeroWindingClipOperator << "\n"
1564*3ac0a46fSAndroid Build Coastguard Worker             << kEndPathNoFillOrStrokeOperator << "\n";
1565*3ac0a46fSAndroid Build Coastguard Worker     }
1566*3ac0a46fSAndroid Build Coastguard Worker 
1567*3ac0a46fSAndroid Build Coastguard Worker     CFX_Color crText = widget_->GetTextPWLColor();
1568*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
1569*3ac0a46fSAndroid Build Coastguard Worker     sBody << GetFillColorAppStream(crText) << sEdit;
1570*3ac0a46fSAndroid Build Coastguard Worker   }
1571*3ac0a46fSAndroid Build Coastguard Worker 
1572*3ac0a46fSAndroid Build Coastguard Worker   sBody << GetDropButtonAppStream(rcButton);
1573*3ac0a46fSAndroid Build Coastguard Worker   Write("N",
1574*3ac0a46fSAndroid Build Coastguard Worker         GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
1575*3ac0a46fSAndroid Build Coastguard Worker         ByteString());
1576*3ac0a46fSAndroid Build Coastguard Worker }
1577*3ac0a46fSAndroid Build Coastguard Worker 
SetAsListBox()1578*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsListBox() {
1579*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1580*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pField = pControl->GetField();
1581*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = widget_->GetClientRect();
1582*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sBody;
1583*3ac0a46fSAndroid Build Coastguard Worker 
1584*3ac0a46fSAndroid Build Coastguard Worker   // Font map must outlive |pEdit|.
1585*3ac0a46fSAndroid Build Coastguard Worker   CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1586*3ac0a46fSAndroid Build Coastguard Worker                           widget_->GetPDFAnnot()->GetMutableAnnotDict(), "N");
1587*3ac0a46fSAndroid Build Coastguard Worker 
1588*3ac0a46fSAndroid Build Coastguard Worker   auto pEdit = std::make_unique<CPWL_EditImpl>();
1589*3ac0a46fSAndroid Build Coastguard Worker   pEdit->EnableRefresh(false);
1590*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetFontMap(&font_map);
1591*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f));
1592*3ac0a46fSAndroid Build Coastguard Worker 
1593*3ac0a46fSAndroid Build Coastguard Worker   float fFontSize = widget_->GetFontSize();
1594*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetFontSize(FXSYS_IsFloatZero(fFontSize) ? 12.0f : fFontSize);
1595*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Initialize();
1596*3ac0a46fSAndroid Build Coastguard Worker 
1597*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sList;
1598*3ac0a46fSAndroid Build Coastguard Worker   float fy = rcClient.top;
1599*3ac0a46fSAndroid Build Coastguard Worker 
1600*3ac0a46fSAndroid Build Coastguard Worker   int32_t nTop = pField->GetTopVisibleIndex();
1601*3ac0a46fSAndroid Build Coastguard Worker   int32_t nCount = pField->CountOptions();
1602*3ac0a46fSAndroid Build Coastguard Worker   int32_t nSelCount = pField->CountSelectedItems();
1603*3ac0a46fSAndroid Build Coastguard Worker 
1604*3ac0a46fSAndroid Build Coastguard Worker   for (int32_t i = nTop; i < nCount; ++i) {
1605*3ac0a46fSAndroid Build Coastguard Worker     bool bSelected = false;
1606*3ac0a46fSAndroid Build Coastguard Worker     for (int32_t j = 0; j < nSelCount; ++j) {
1607*3ac0a46fSAndroid Build Coastguard Worker       if (pField->GetSelectedIndex(j) == i) {
1608*3ac0a46fSAndroid Build Coastguard Worker         bSelected = true;
1609*3ac0a46fSAndroid Build Coastguard Worker         break;
1610*3ac0a46fSAndroid Build Coastguard Worker       }
1611*3ac0a46fSAndroid Build Coastguard Worker     }
1612*3ac0a46fSAndroid Build Coastguard Worker 
1613*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetText(pField->GetOptionLabel(i));
1614*3ac0a46fSAndroid Build Coastguard Worker     pEdit->Paint();
1615*3ac0a46fSAndroid Build Coastguard Worker 
1616*3ac0a46fSAndroid Build Coastguard Worker     CFX_FloatRect rcContent = pEdit->GetContentRect();
1617*3ac0a46fSAndroid Build Coastguard Worker     float fItemHeight = rcContent.Height();
1618*3ac0a46fSAndroid Build Coastguard Worker 
1619*3ac0a46fSAndroid Build Coastguard Worker     if (bSelected) {
1620*3ac0a46fSAndroid Build Coastguard Worker       CFX_FloatRect rcItem =
1621*3ac0a46fSAndroid Build Coastguard Worker           CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
1622*3ac0a46fSAndroid Build Coastguard Worker       {
1623*3ac0a46fSAndroid Build Coastguard Worker         AutoClosedQCommand q(&sList);
1624*3ac0a46fSAndroid Build Coastguard Worker         sList << GetFillColorAppStream(CFX_Color(
1625*3ac0a46fSAndroid Build Coastguard Worker             CFX_Color::Type::kRGB, 0, 51.0f / 255.0f, 113.0f / 255.0f));
1626*3ac0a46fSAndroid Build Coastguard Worker         WriteAppendRect(sList, rcItem);
1627*3ac0a46fSAndroid Build Coastguard Worker         sList << kFillOperator << "\n";
1628*3ac0a46fSAndroid Build Coastguard Worker       }
1629*3ac0a46fSAndroid Build Coastguard Worker 
1630*3ac0a46fSAndroid Build Coastguard Worker       AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
1631*3ac0a46fSAndroid Build Coastguard Worker       sList << GetFillColorAppStream(CFX_Color(CFX_Color::Type::kGray, 1))
1632*3ac0a46fSAndroid Build Coastguard Worker             << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
1633*3ac0a46fSAndroid Build Coastguard Worker     } else {
1634*3ac0a46fSAndroid Build Coastguard Worker       CFX_Color crText = widget_->GetTextPWLColor();
1635*3ac0a46fSAndroid Build Coastguard Worker 
1636*3ac0a46fSAndroid Build Coastguard Worker       AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
1637*3ac0a46fSAndroid Build Coastguard Worker       sList << GetFillColorAppStream(crText)
1638*3ac0a46fSAndroid Build Coastguard Worker             << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
1639*3ac0a46fSAndroid Build Coastguard Worker     }
1640*3ac0a46fSAndroid Build Coastguard Worker 
1641*3ac0a46fSAndroid Build Coastguard Worker     fy -= fItemHeight;
1642*3ac0a46fSAndroid Build Coastguard Worker   }
1643*3ac0a46fSAndroid Build Coastguard Worker 
1644*3ac0a46fSAndroid Build Coastguard Worker   if (sList.tellp() > 0) {
1645*3ac0a46fSAndroid Build Coastguard Worker     sBody << "/Tx ";
1646*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1647*3ac0a46fSAndroid Build Coastguard Worker                           kMarkedSequenceEndOperator);
1648*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sBody);
1649*3ac0a46fSAndroid Build Coastguard Worker 
1650*3ac0a46fSAndroid Build Coastguard Worker     WriteAppendRect(sBody, rcClient);
1651*3ac0a46fSAndroid Build Coastguard Worker     sBody << kSetNonZeroWindingClipOperator << "\n"
1652*3ac0a46fSAndroid Build Coastguard Worker           << kEndPathNoFillOrStrokeOperator << "\n"
1653*3ac0a46fSAndroid Build Coastguard Worker           << sList.str();
1654*3ac0a46fSAndroid Build Coastguard Worker   }
1655*3ac0a46fSAndroid Build Coastguard Worker   Write("N",
1656*3ac0a46fSAndroid Build Coastguard Worker         GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
1657*3ac0a46fSAndroid Build Coastguard Worker         ByteString());
1658*3ac0a46fSAndroid Build Coastguard Worker }
1659*3ac0a46fSAndroid Build Coastguard Worker 
SetAsTextField(absl::optional<WideString> sValue)1660*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::SetAsTextField(absl::optional<WideString> sValue) {
1661*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormControl* pControl = widget_->GetFormControl();
1662*3ac0a46fSAndroid Build Coastguard Worker   CPDF_FormField* pField = pControl->GetField();
1663*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sBody;
1664*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream sLines;
1665*3ac0a46fSAndroid Build Coastguard Worker 
1666*3ac0a46fSAndroid Build Coastguard Worker   // Font map must outlive |pEdit|.
1667*3ac0a46fSAndroid Build Coastguard Worker   CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
1668*3ac0a46fSAndroid Build Coastguard Worker                           widget_->GetPDFAnnot()->GetMutableAnnotDict(), "N");
1669*3ac0a46fSAndroid Build Coastguard Worker 
1670*3ac0a46fSAndroid Build Coastguard Worker   auto pEdit = std::make_unique<CPWL_EditImpl>();
1671*3ac0a46fSAndroid Build Coastguard Worker   pEdit->EnableRefresh(false);
1672*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetFontMap(&font_map);
1673*3ac0a46fSAndroid Build Coastguard Worker 
1674*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcClient = widget_->GetClientRect();
1675*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetPlateRect(rcClient);
1676*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetAlignmentH(pControl->GetControlAlignment());
1677*3ac0a46fSAndroid Build Coastguard Worker 
1678*3ac0a46fSAndroid Build Coastguard Worker   uint32_t dwFieldFlags = pField->GetFieldFlags();
1679*3ac0a46fSAndroid Build Coastguard Worker   bool bMultiLine = dwFieldFlags & pdfium::form_flags::kTextMultiline;
1680*3ac0a46fSAndroid Build Coastguard Worker   if (bMultiLine) {
1681*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetMultiLine(true);
1682*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetAutoReturn(true);
1683*3ac0a46fSAndroid Build Coastguard Worker   } else {
1684*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetAlignmentV(1);
1685*3ac0a46fSAndroid Build Coastguard Worker   }
1686*3ac0a46fSAndroid Build Coastguard Worker 
1687*3ac0a46fSAndroid Build Coastguard Worker   uint16_t subWord = 0;
1688*3ac0a46fSAndroid Build Coastguard Worker   if (dwFieldFlags & pdfium::form_flags::kTextPassword) {
1689*3ac0a46fSAndroid Build Coastguard Worker     subWord = '*';
1690*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetPasswordChar(subWord);
1691*3ac0a46fSAndroid Build Coastguard Worker   }
1692*3ac0a46fSAndroid Build Coastguard Worker 
1693*3ac0a46fSAndroid Build Coastguard Worker   int nMaxLen = pField->GetMaxLen();
1694*3ac0a46fSAndroid Build Coastguard Worker   bool bCharArray = dwFieldFlags & pdfium::form_flags::kTextComb;
1695*3ac0a46fSAndroid Build Coastguard Worker   float fFontSize = widget_->GetFontSize();
1696*3ac0a46fSAndroid Build Coastguard Worker 
1697*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
1698*3ac0a46fSAndroid Build Coastguard Worker   if (!sValue.has_value() && widget_->GetMixXFAWidget())
1699*3ac0a46fSAndroid Build Coastguard Worker     sValue = widget_->GetValue();
1700*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
1701*3ac0a46fSAndroid Build Coastguard Worker 
1702*3ac0a46fSAndroid Build Coastguard Worker   if (nMaxLen > 0) {
1703*3ac0a46fSAndroid Build Coastguard Worker     if (bCharArray) {
1704*3ac0a46fSAndroid Build Coastguard Worker       pEdit->SetCharArray(nMaxLen);
1705*3ac0a46fSAndroid Build Coastguard Worker       if (FXSYS_IsFloatZero(fFontSize)) {
1706*3ac0a46fSAndroid Build Coastguard Worker         fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(
1707*3ac0a46fSAndroid Build Coastguard Worker             font_map.GetPDFFont(0).Get(), rcClient, nMaxLen);
1708*3ac0a46fSAndroid Build Coastguard Worker       }
1709*3ac0a46fSAndroid Build Coastguard Worker     } else {
1710*3ac0a46fSAndroid Build Coastguard Worker       if (sValue.has_value())
1711*3ac0a46fSAndroid Build Coastguard Worker         nMaxLen = pdfium::base::checked_cast<int>(sValue.value().GetLength());
1712*3ac0a46fSAndroid Build Coastguard Worker       pEdit->SetLimitChar(nMaxLen);
1713*3ac0a46fSAndroid Build Coastguard Worker     }
1714*3ac0a46fSAndroid Build Coastguard Worker   }
1715*3ac0a46fSAndroid Build Coastguard Worker 
1716*3ac0a46fSAndroid Build Coastguard Worker   if (FXSYS_IsFloatZero(fFontSize))
1717*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetAutoFontSize(true);
1718*3ac0a46fSAndroid Build Coastguard Worker   else
1719*3ac0a46fSAndroid Build Coastguard Worker     pEdit->SetFontSize(fFontSize);
1720*3ac0a46fSAndroid Build Coastguard Worker 
1721*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Initialize();
1722*3ac0a46fSAndroid Build Coastguard Worker   pEdit->SetText(sValue.value_or(pField->GetValue()));
1723*3ac0a46fSAndroid Build Coastguard Worker   pEdit->Paint();
1724*3ac0a46fSAndroid Build Coastguard Worker 
1725*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcContent = pEdit->GetContentRect();
1726*3ac0a46fSAndroid Build Coastguard Worker   ByteString sEdit =
1727*3ac0a46fSAndroid Build Coastguard Worker       GetEditAppStream(pEdit.get(), CFX_PointF(), !bCharArray, subWord);
1728*3ac0a46fSAndroid Build Coastguard Worker 
1729*3ac0a46fSAndroid Build Coastguard Worker   if (sEdit.GetLength() > 0) {
1730*3ac0a46fSAndroid Build Coastguard Worker     sBody << "/Tx ";
1731*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1732*3ac0a46fSAndroid Build Coastguard Worker                           kMarkedSequenceEndOperator);
1733*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedQCommand q(&sBody);
1734*3ac0a46fSAndroid Build Coastguard Worker 
1735*3ac0a46fSAndroid Build Coastguard Worker     if (rcContent.Width() > rcClient.Width() ||
1736*3ac0a46fSAndroid Build Coastguard Worker         rcContent.Height() > rcClient.Height()) {
1737*3ac0a46fSAndroid Build Coastguard Worker       WriteAppendRect(sBody, rcClient);
1738*3ac0a46fSAndroid Build Coastguard Worker       sBody << kSetNonZeroWindingClipOperator << "\n"
1739*3ac0a46fSAndroid Build Coastguard Worker             << kEndPathNoFillOrStrokeOperator << "\n";
1740*3ac0a46fSAndroid Build Coastguard Worker     }
1741*3ac0a46fSAndroid Build Coastguard Worker     CFX_Color crText = widget_->GetTextPWLColor();
1742*3ac0a46fSAndroid Build Coastguard Worker 
1743*3ac0a46fSAndroid Build Coastguard Worker     AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
1744*3ac0a46fSAndroid Build Coastguard Worker     sBody << GetFillColorAppStream(crText) << sEdit;
1745*3ac0a46fSAndroid Build Coastguard Worker   }
1746*3ac0a46fSAndroid Build Coastguard Worker 
1747*3ac0a46fSAndroid Build Coastguard Worker   if (bCharArray) {
1748*3ac0a46fSAndroid Build Coastguard Worker     switch (widget_->GetBorderStyle()) {
1749*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kSolid: {
1750*3ac0a46fSAndroid Build Coastguard Worker         ByteString sColor =
1751*3ac0a46fSAndroid Build Coastguard Worker             GetStrokeColorAppStream(widget_->GetBorderPWLColor());
1752*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
1753*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q(&sLines);
1754*3ac0a46fSAndroid Build Coastguard Worker           sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1755*3ac0a46fSAndroid Build Coastguard Worker                  << "\n"
1756*3ac0a46fSAndroid Build Coastguard Worker                  << GetStrokeColorAppStream(widget_->GetBorderPWLColor())
1757*3ac0a46fSAndroid Build Coastguard Worker                  << " 2 " << kSetLineCapStyleOperator << " 0 "
1758*3ac0a46fSAndroid Build Coastguard Worker                  << kSetLineJoinStyleOperator << "\n";
1759*3ac0a46fSAndroid Build Coastguard Worker 
1760*3ac0a46fSAndroid Build Coastguard Worker           const float width = rcClient.right - rcClient.left;
1761*3ac0a46fSAndroid Build Coastguard Worker           for (int32_t i = 1; i < nMaxLen; ++i) {
1762*3ac0a46fSAndroid Build Coastguard Worker             const float left = rcClient.left + (width / nMaxLen) * i;
1763*3ac0a46fSAndroid Build Coastguard Worker             WriteMove(sLines, {left, rcClient.bottom});
1764*3ac0a46fSAndroid Build Coastguard Worker             WriteLine(sLines, {left, rcClient.top});
1765*3ac0a46fSAndroid Build Coastguard Worker             sLines << kStrokeOperator << "\n";
1766*3ac0a46fSAndroid Build Coastguard Worker           }
1767*3ac0a46fSAndroid Build Coastguard Worker         }
1768*3ac0a46fSAndroid Build Coastguard Worker         break;
1769*3ac0a46fSAndroid Build Coastguard Worker       }
1770*3ac0a46fSAndroid Build Coastguard Worker       case BorderStyle::kDash: {
1771*3ac0a46fSAndroid Build Coastguard Worker         ByteString sColor =
1772*3ac0a46fSAndroid Build Coastguard Worker             GetStrokeColorAppStream(widget_->GetBorderPWLColor());
1773*3ac0a46fSAndroid Build Coastguard Worker         if (sColor.GetLength() > 0) {
1774*3ac0a46fSAndroid Build Coastguard Worker           CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
1775*3ac0a46fSAndroid Build Coastguard Worker           AutoClosedQCommand q(&sLines);
1776*3ac0a46fSAndroid Build Coastguard Worker           sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1777*3ac0a46fSAndroid Build Coastguard Worker                  << "\n"
1778*3ac0a46fSAndroid Build Coastguard Worker                  << GetStrokeColorAppStream(widget_->GetBorderPWLColor()) << "["
1779*3ac0a46fSAndroid Build Coastguard Worker                  << dsBorder.nDash << " " << dsBorder.nGap << "] "
1780*3ac0a46fSAndroid Build Coastguard Worker                  << dsBorder.nPhase << " " << kSetDashOperator << "\n";
1781*3ac0a46fSAndroid Build Coastguard Worker 
1782*3ac0a46fSAndroid Build Coastguard Worker           const float width = rcClient.right - rcClient.left;
1783*3ac0a46fSAndroid Build Coastguard Worker           for (int32_t i = 1; i < nMaxLen; ++i) {
1784*3ac0a46fSAndroid Build Coastguard Worker             const float left = rcClient.left + (width / nMaxLen) * i;
1785*3ac0a46fSAndroid Build Coastguard Worker             WriteMove(sLines, {left, rcClient.bottom});
1786*3ac0a46fSAndroid Build Coastguard Worker             WriteLine(sLines, {left, rcClient.top});
1787*3ac0a46fSAndroid Build Coastguard Worker             sLines << kStrokeOperator << "\n";
1788*3ac0a46fSAndroid Build Coastguard Worker           }
1789*3ac0a46fSAndroid Build Coastguard Worker         }
1790*3ac0a46fSAndroid Build Coastguard Worker         break;
1791*3ac0a46fSAndroid Build Coastguard Worker       }
1792*3ac0a46fSAndroid Build Coastguard Worker       default:
1793*3ac0a46fSAndroid Build Coastguard Worker         break;
1794*3ac0a46fSAndroid Build Coastguard Worker     }
1795*3ac0a46fSAndroid Build Coastguard Worker   }
1796*3ac0a46fSAndroid Build Coastguard Worker 
1797*3ac0a46fSAndroid Build Coastguard Worker   Write("N",
1798*3ac0a46fSAndroid Build Coastguard Worker         GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sLines) +
1799*3ac0a46fSAndroid Build Coastguard Worker             ByteString(sBody),
1800*3ac0a46fSAndroid Build Coastguard Worker         ByteString());
1801*3ac0a46fSAndroid Build Coastguard Worker }
1802*3ac0a46fSAndroid Build Coastguard Worker 
AddImage(const ByteString & sAPType,CPDF_Stream * pImage)1803*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::AddImage(const ByteString& sAPType,
1804*3ac0a46fSAndroid Build Coastguard Worker                                  CPDF_Stream* pImage) {
1805*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream = dict_->GetMutableStreamFor(sAPType);
1806*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pStreamDict = pStream->GetMutableDict();
1807*3ac0a46fSAndroid Build Coastguard Worker   ByteString sImageAlias = "IMG";
1808*3ac0a46fSAndroid Build Coastguard Worker 
1809*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Dictionary> pImageDict = pImage->GetDict();
1810*3ac0a46fSAndroid Build Coastguard Worker   if (pImageDict)
1811*3ac0a46fSAndroid Build Coastguard Worker     sImageAlias = pImageDict->GetByteStringFor("Name");
1812*3ac0a46fSAndroid Build Coastguard Worker 
1813*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pStreamResList =
1814*3ac0a46fSAndroid Build Coastguard Worker       pStreamDict->GetOrCreateDictFor("Resources");
1815*3ac0a46fSAndroid Build Coastguard Worker   auto pXObject = pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
1816*3ac0a46fSAndroid Build Coastguard Worker   pXObject->SetNewFor<CPDF_Reference>(sImageAlias,
1817*3ac0a46fSAndroid Build Coastguard Worker                                       widget_->GetPageView()->GetPDFDocument(),
1818*3ac0a46fSAndroid Build Coastguard Worker                                       pImage->GetObjNum());
1819*3ac0a46fSAndroid Build Coastguard Worker }
1820*3ac0a46fSAndroid Build Coastguard Worker 
Write(const ByteString & sAPType,const ByteString & sContents,const ByteString & sAPState)1821*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::Write(const ByteString& sAPType,
1822*3ac0a46fSAndroid Build Coastguard Worker                               const ByteString& sContents,
1823*3ac0a46fSAndroid Build Coastguard Worker                               const ByteString& sAPState) {
1824*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pParentDict;
1825*3ac0a46fSAndroid Build Coastguard Worker   ByteString key;
1826*3ac0a46fSAndroid Build Coastguard Worker   if (sAPState.IsEmpty()) {
1827*3ac0a46fSAndroid Build Coastguard Worker     pParentDict = dict_;
1828*3ac0a46fSAndroid Build Coastguard Worker     key = sAPType;
1829*3ac0a46fSAndroid Build Coastguard Worker   } else {
1830*3ac0a46fSAndroid Build Coastguard Worker     pParentDict = dict_->GetOrCreateDictFor(sAPType);
1831*3ac0a46fSAndroid Build Coastguard Worker     key = sAPState;
1832*3ac0a46fSAndroid Build Coastguard Worker   }
1833*3ac0a46fSAndroid Build Coastguard Worker 
1834*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pOrigStreamDict;
1835*3ac0a46fSAndroid Build Coastguard Worker 
1836*3ac0a46fSAndroid Build Coastguard Worker   // If `pStream` is created by CreateModifiedAPStream(), then it is safe to
1837*3ac0a46fSAndroid Build Coastguard Worker   // edit, as it is not shared.
1838*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Stream> pStream = pParentDict->GetMutableStreamFor(key);
1839*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument();
1840*3ac0a46fSAndroid Build Coastguard Worker   if (!doc->IsModifiedAPStream(pStream.Get())) {
1841*3ac0a46fSAndroid Build Coastguard Worker     if (pStream)
1842*3ac0a46fSAndroid Build Coastguard Worker       pOrigStreamDict = pStream->GetMutableDict();
1843*3ac0a46fSAndroid Build Coastguard Worker     pStream.Reset(doc->CreateModifiedAPStream());
1844*3ac0a46fSAndroid Build Coastguard Worker     pParentDict->SetNewFor<CPDF_Reference>(key, doc, pStream->GetObjNum());
1845*3ac0a46fSAndroid Build Coastguard Worker   }
1846*3ac0a46fSAndroid Build Coastguard Worker 
1847*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Dictionary> pStreamDict = pStream->GetMutableDict();
1848*3ac0a46fSAndroid Build Coastguard Worker   if (!pStreamDict) {
1849*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict = doc->New<CPDF_Dictionary>();
1850*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
1851*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
1852*3ac0a46fSAndroid Build Coastguard Worker     pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
1853*3ac0a46fSAndroid Build Coastguard Worker 
1854*3ac0a46fSAndroid Build Coastguard Worker     if (pOrigStreamDict) {
1855*3ac0a46fSAndroid Build Coastguard Worker       RetainPtr<const CPDF_Dictionary> pResources =
1856*3ac0a46fSAndroid Build Coastguard Worker           pOrigStreamDict->GetDictFor("Resources");
1857*3ac0a46fSAndroid Build Coastguard Worker       if (pResources)
1858*3ac0a46fSAndroid Build Coastguard Worker         pStreamDict->SetFor("Resources", pResources->Clone());
1859*3ac0a46fSAndroid Build Coastguard Worker     }
1860*3ac0a46fSAndroid Build Coastguard Worker 
1861*3ac0a46fSAndroid Build Coastguard Worker     pStream->InitStreamWithEmptyData(pStreamDict);
1862*3ac0a46fSAndroid Build Coastguard Worker   }
1863*3ac0a46fSAndroid Build Coastguard Worker   pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix());
1864*3ac0a46fSAndroid Build Coastguard Worker   pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect());
1865*3ac0a46fSAndroid Build Coastguard Worker   pStream->SetDataAndRemoveFilter(sContents.raw_span());
1866*3ac0a46fSAndroid Build Coastguard Worker }
1867*3ac0a46fSAndroid Build Coastguard Worker 
Remove(ByteStringView sAPType)1868*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_AppStream::Remove(ByteStringView sAPType) {
1869*3ac0a46fSAndroid Build Coastguard Worker   dict_->RemoveFor(sAPType);
1870*3ac0a46fSAndroid Build Coastguard Worker }
1871*3ac0a46fSAndroid Build Coastguard Worker 
GetBackgroundAppStream() const1872*3ac0a46fSAndroid Build Coastguard Worker ByteString CPDFSDK_AppStream::GetBackgroundAppStream() const {
1873*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBackground = widget_->GetFillPWLColor();
1874*3ac0a46fSAndroid Build Coastguard Worker   if (crBackground.nColorType != CFX_Color::Type::kTransparent)
1875*3ac0a46fSAndroid Build Coastguard Worker     return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground);
1876*3ac0a46fSAndroid Build Coastguard Worker 
1877*3ac0a46fSAndroid Build Coastguard Worker   return ByteString();
1878*3ac0a46fSAndroid Build Coastguard Worker }
1879*3ac0a46fSAndroid Build Coastguard Worker 
GetBorderAppStream() const1880*3ac0a46fSAndroid Build Coastguard Worker ByteString CPDFSDK_AppStream::GetBorderAppStream() const {
1881*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1882*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBorder = widget_->GetBorderPWLColor();
1883*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crBackground = widget_->GetFillPWLColor();
1884*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crLeftTop;
1885*3ac0a46fSAndroid Build Coastguard Worker   CFX_Color crRightBottom;
1886*3ac0a46fSAndroid Build Coastguard Worker 
1887*3ac0a46fSAndroid Build Coastguard Worker   float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1888*3ac0a46fSAndroid Build Coastguard Worker   CPWL_Dash dsBorder(3, 0, 0);
1889*3ac0a46fSAndroid Build Coastguard Worker 
1890*3ac0a46fSAndroid Build Coastguard Worker   BorderStyle nBorderStyle = widget_->GetBorderStyle();
1891*3ac0a46fSAndroid Build Coastguard Worker   switch (nBorderStyle) {
1892*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kDash:
1893*3ac0a46fSAndroid Build Coastguard Worker       dsBorder = CPWL_Dash(3, 3, 0);
1894*3ac0a46fSAndroid Build Coastguard Worker       break;
1895*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kBeveled:
1896*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1897*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 1);
1898*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = crBackground / 2.0f;
1899*3ac0a46fSAndroid Build Coastguard Worker       break;
1900*3ac0a46fSAndroid Build Coastguard Worker     case BorderStyle::kInset:
1901*3ac0a46fSAndroid Build Coastguard Worker       fBorderWidth *= 2;
1902*3ac0a46fSAndroid Build Coastguard Worker       crLeftTop = CFX_Color(CFX_Color::Type::kGray, 0.5);
1903*3ac0a46fSAndroid Build Coastguard Worker       crRightBottom = CFX_Color(CFX_Color::Type::kGray, 0.75);
1904*3ac0a46fSAndroid Build Coastguard Worker       break;
1905*3ac0a46fSAndroid Build Coastguard Worker     default:
1906*3ac0a46fSAndroid Build Coastguard Worker       break;
1907*3ac0a46fSAndroid Build Coastguard Worker   }
1908*3ac0a46fSAndroid Build Coastguard Worker 
1909*3ac0a46fSAndroid Build Coastguard Worker   return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1910*3ac0a46fSAndroid Build Coastguard Worker                                     crRightBottom, nBorderStyle, dsBorder);
1911*3ac0a46fSAndroid Build Coastguard Worker }
1912