blob: 8ced563161f2290fe33d2fc8aada5258fe40037f [file] [log] [blame]
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001// Copyright 2017 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairc411eb92017-07-25 09:39:30 -04007#include "fpdfsdk/pwl/cpwl_appstream.h"
Dan Sinclaircb2ea422017-07-19 15:24:49 -04008
9#include <utility>
10
11#include "core/fpdfapi/parser/cpdf_dictionary.h"
12#include "core/fpdfapi/parser/cpdf_document.h"
13#include "core/fpdfapi/parser/cpdf_name.h"
14#include "core/fpdfapi/parser/cpdf_number.h"
15#include "core/fpdfapi/parser/cpdf_reference.h"
16#include "core/fpdfapi/parser/cpdf_stream.h"
17#include "core/fpdfapi/parser/cpdf_string.h"
Dan Sinclair14ddd422017-07-20 11:07:00 -040018#include "core/fpdfapi/parser/fpdf_parser_decode.h"
19#include "core/fpdfdoc/cpvt_word.h"
Dan Sinclaircb2ea422017-07-19 15:24:49 -040020#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
21#include "fpdfsdk/cpdfsdk_interform.h"
22#include "fpdfsdk/cpdfsdk_pageview.h"
23#include "fpdfsdk/cpdfsdk_widget.h"
24#include "fpdfsdk/formfiller/cba_fontmap.h"
Dan Sinclairc411eb92017-07-25 09:39:30 -040025#include "fpdfsdk/pwl/cpwl_edit.h"
26#include "fpdfsdk/pwl/cpwl_edit_impl.h"
27#include "fpdfsdk/pwl/cpwl_icon.h"
28#include "fpdfsdk/pwl/cpwl_wnd.h"
Lei Zhang99f5bbb2018-10-09 21:31:28 +000029#include "third_party/base/ptr_util.h"
Dan Sinclaircb2ea422017-07-19 15:24:49 -040030
31namespace {
32
Dan Sinclair14ddd422017-07-20 11:07:00 -040033// Checkbox & radiobutton styles.
34enum class CheckStyle { kCheck = 0, kCircle, kCross, kDiamond, kSquare, kStar };
35
36// Pushbutton layout styles.
37enum class ButtonStyle {
38 kLabel = 0,
39 kIcon,
40 kIconTopLabelBottom,
41 kIconBottomLabelTop,
42 kIconLeftLabelRight,
43 kIconRightLabelLeft,
44 kLabelOverIcon
45};
46
Dan Sinclairbeef5e42017-07-24 10:32:05 -040047const char kAppendRectOperator[] = "re";
48const char kConcatMatrixOperator[] = "cm";
49const char kCurveToOperator[] = "c";
50const char kEndPathNoFillOrStrokeOperator[] = "n";
51const char kFillOperator[] = "f";
52const char kFillEvenOddOperator[] = "f*";
53const char kInvokeNamedXObjectOperator[] = "Do";
54const char kLineToOperator[] = "l";
55const char kMarkedSequenceBeginOperator[] = "BMC";
56const char kMarkedSequenceEndOperator[] = "EMC";
57const char kMoveTextPositionOperator[] = "Td";
58const char kMoveToOperator[] = "m";
59const char kSetCharacterSpacingOperator[] = "Tc";
60const char kSetCMYKOperator[] = "k";
61const char kSetCMKYStrokedOperator[] = "K";
62const char kSetDashOperator[] = "d";
63const char kSetGrayOperator[] = "g";
64const char kSetGrayStrokedOperator[] = "G";
65const char kSetLineCapStyleOperator[] = "J";
66const char kSetLineJoinStyleOperator[] = "j";
67const char kSetLineWidthOperator[] = "w";
68const char kSetNonZeroWindingClipOperator[] = "W";
69const char kSetRGBOperator[] = "rg";
70const char kSetRGBStrokedOperator[] = "RG";
71const char kSetTextFontAndSizeOperator[] = "Tf";
Dan Sinclairbeef5e42017-07-24 10:32:05 -040072const char kShowTextOperator[] = "Tj";
73const char kStateRestoreOperator[] = "Q";
74const char kStateSaveOperator[] = "q";
75const char kStrokeOperator[] = "S";
76const char kTextBeginOperator[] = "BT";
77const char kTextEndOperator[] = "ET";
78
Dan Sinclaire03f8b12017-07-20 11:08:21 -040079class AutoClosedCommand {
80 public:
81 AutoClosedCommand(std::ostringstream* stream,
Ryan Harrison275e2602017-09-18 14:23:18 -040082 ByteString open,
83 ByteString close)
Dan Sinclaire03f8b12017-07-20 11:08:21 -040084 : stream_(stream), close_(close) {
85 *stream_ << open << "\n";
86 }
87
88 virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; }
89
90 private:
91 std::ostringstream* stream_;
Ryan Harrison275e2602017-09-18 14:23:18 -040092 ByteString close_;
Dan Sinclaire03f8b12017-07-20 11:08:21 -040093};
94
Tom Sepez55865452018-08-27 20:18:04 +000095class AutoClosedQCommand final : public AutoClosedCommand {
Dan Sinclaire03f8b12017-07-20 11:08:21 -040096 public:
97 explicit AutoClosedQCommand(std::ostringstream* stream)
Dan Sinclairbeef5e42017-07-24 10:32:05 -040098 : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {}
Dan Sinclaire03f8b12017-07-20 11:08:21 -040099 ~AutoClosedQCommand() override {}
100};
101
Ryan Harrison275e2602017-09-18 14:23:18 -0400102ByteString GetColorAppStream(const CFX_Color& color,
103 const bool& bFillOrStroke) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400104 std::ostringstream sColorStream;
105
106 switch (color.nColorType) {
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400107 case CFX_Color::kRGB:
Dan Sinclair14ddd422017-07-20 11:07:00 -0400108 sColorStream << color.fColor1 << " " << color.fColor2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400109 << color.fColor3 << " "
110 << (bFillOrStroke ? kSetRGBOperator : kSetRGBStrokedOperator)
Dan Sinclair14ddd422017-07-20 11:07:00 -0400111 << "\n";
112 break;
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400113 case CFX_Color::kGray:
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400114 sColorStream << color.fColor1 << " "
115 << (bFillOrStroke ? kSetGrayOperator
116 : kSetGrayStrokedOperator)
Dan Sinclair14ddd422017-07-20 11:07:00 -0400117 << "\n";
118 break;
Dan Sinclair8e7f9322017-10-16 11:35:42 -0400119 case CFX_Color::kCMYK:
Dan Sinclair14ddd422017-07-20 11:07:00 -0400120 sColorStream << color.fColor1 << " " << color.fColor2 << " "
121 << color.fColor3 << " " << color.fColor4 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400122 << (bFillOrStroke ? kSetCMYKOperator
123 : kSetCMKYStrokedOperator)
124 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400125 break;
126 }
127
Ryan Harrison275e2602017-09-18 14:23:18 -0400128 return ByteString(sColorStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400129}
130
Ryan Harrison275e2602017-09-18 14:23:18 -0400131ByteString GetAP_Check(const CFX_FloatRect& crBBox) {
Lei Zhang98758892018-03-15 15:02:22 +0000132 const float fWidth = crBBox.Width();
133 const float fHeight = crBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400134
135 CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f),
136 CFX_PointF(0.29f, 0.40f)},
137 {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f),
138 CFX_PointF(0.31f, 0.28f)},
139 {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f),
140 CFX_PointF(0.77f, 0.67f)},
141 {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f),
142 CFX_PointF(0.76f, 0.75f)},
143 {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f),
144 CFX_PointF(0.68f, 0.75f)},
145 {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f),
146 CFX_PointF(0.44f, 0.47f)},
147 {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f),
148 CFX_PointF(0.41f, 0.58f)},
149 {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f),
150 CFX_PointF(0.30f, 0.56f)}};
151
152 for (size_t i = 0; i < FX_ArraySize(pts); ++i) {
153 for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) {
154 pts[i][j].x = pts[i][j].x * fWidth + crBBox.left;
155 pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom;
156 }
157 }
158
159 std::ostringstream csAP;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400160 csAP << pts[0][0].x << " " << pts[0][0].y << " " << kMoveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400161
162 for (size_t i = 0; i < FX_ArraySize(pts); ++i) {
163 size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0;
164
165 float px1 = pts[i][1].x - pts[i][0].x;
166 float py1 = pts[i][1].y - pts[i][0].y;
167 float px2 = pts[i][2].x - pts[nNext][0].x;
168 float py2 = pts[i][2].y - pts[nNext][0].y;
169
170 csAP << pts[i][0].x + px1 * FX_BEZIER << " "
171 << pts[i][0].y + py1 * FX_BEZIER << " "
172 << pts[nNext][0].x + px2 * FX_BEZIER << " "
173 << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400174 << pts[nNext][0].y << " " << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400175 }
176
Ryan Harrison275e2602017-09-18 14:23:18 -0400177 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400178}
179
Ryan Harrison275e2602017-09-18 14:23:18 -0400180ByteString GetAP_Circle(const CFX_FloatRect& crBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400181 std::ostringstream csAP;
182
Lei Zhang98758892018-03-15 15:02:22 +0000183 float fWidth = crBBox.Width();
184 float fHeight = crBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400185
186 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2);
187 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top);
188 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2);
189 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom);
190
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400191 csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400192
193 float px = pt2.x - pt1.x;
194 float py = pt2.y - pt1.y;
195
196 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " "
197 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400198 << " " << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400199
200 px = pt3.x - pt2.x;
201 py = pt2.y - pt3.y;
202
203 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400204 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " "
205 << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400206
207 px = pt3.x - pt4.x;
208 py = pt3.y - pt4.y;
209
210 csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " "
211 << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400212 << " " << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400213
214 px = pt4.x - pt1.x;
215 py = pt1.y - pt4.y;
216
217 csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400218 << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " "
219 << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400220
Ryan Harrison275e2602017-09-18 14:23:18 -0400221 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400222}
223
Ryan Harrison275e2602017-09-18 14:23:18 -0400224ByteString GetAP_Cross(const CFX_FloatRect& crBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400225 std::ostringstream csAP;
226
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400227 csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
228 csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator
229 << "\n";
230 csAP << crBBox.left << " " << crBBox.bottom << " " << kMoveToOperator << "\n";
231 csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400232
Ryan Harrison275e2602017-09-18 14:23:18 -0400233 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400234}
235
Ryan Harrison275e2602017-09-18 14:23:18 -0400236ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400237 std::ostringstream csAP;
238
Lei Zhang98758892018-03-15 15:02:22 +0000239 float fWidth = crBBox.Width();
240 float fHeight = crBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400241
242 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2);
243 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top);
244 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2);
245 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom);
246
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400247 csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n";
248 csAP << pt2.x << " " << pt2.y << " " << kLineToOperator << "\n";
249 csAP << pt3.x << " " << pt3.y << " " << kLineToOperator << "\n";
250 csAP << pt4.x << " " << pt4.y << " " << kLineToOperator << "\n";
251 csAP << pt1.x << " " << pt1.y << " " << kLineToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400252
Ryan Harrison275e2602017-09-18 14:23:18 -0400253 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400254}
255
Ryan Harrison275e2602017-09-18 14:23:18 -0400256ByteString GetAP_Square(const CFX_FloatRect& crBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400257 std::ostringstream csAP;
258
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400259 csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
260 csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n";
261 csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator
262 << "\n";
263 csAP << crBBox.left << " " << crBBox.bottom << " " << kLineToOperator << "\n";
264 csAP << crBBox.left << " " << crBBox.top << " " << kLineToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400265
Ryan Harrison275e2602017-09-18 14:23:18 -0400266 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400267}
268
Ryan Harrison275e2602017-09-18 14:23:18 -0400269ByteString GetAP_Star(const CFX_FloatRect& crBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400270 std::ostringstream csAP;
271
272 float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f));
273 CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f,
274 (crBBox.top + crBBox.bottom) / 2.0f);
275
276 float px[5];
277 float py[5];
278 float fAngel = FX_PI / 10.0f;
279 for (int32_t i = 0; i < 5; i++) {
280 px[i] = ptCenter.x + fRadius * (float)cos(fAngel);
281 py[i] = ptCenter.y + fRadius * (float)sin(fAngel);
282 fAngel += FX_PI * 2 / 5.0f;
283 }
284
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400285 csAP << px[0] << " " << py[0] << " " << kMoveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400286
287 int32_t nNext = 0;
288 for (int32_t j = 0; j < 5; j++) {
289 nNext += 2;
290 if (nNext >= 5)
291 nNext -= 5;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400292 csAP << px[nNext] << " " << py[nNext] << " " << kLineToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400293 }
294
Ryan Harrison275e2602017-09-18 14:23:18 -0400295 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400296}
297
Ryan Harrison275e2602017-09-18 14:23:18 -0400298ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400299 std::ostringstream csAP;
300
Lei Zhang98758892018-03-15 15:02:22 +0000301 float fWidth = crBBox.Width();
302 float fHeight = crBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400303
304 CFX_PointF pt1(-fWidth / 2, 0);
305 CFX_PointF pt2(0, fHeight / 2);
306 CFX_PointF pt3(fWidth / 2, 0);
307
308 float px;
309 float py;
310
311 csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " "
312 << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400313 << crBBox.bottom + fHeight / 2 << " " << kConcatMatrixOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400314
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400315 csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400316
317 px = pt2.x - pt1.x;
318 py = pt2.y - pt1.y;
319
320 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " "
321 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400322 << " " << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400323
324 px = pt3.x - pt2.x;
325 py = pt2.y - pt3.y;
326
327 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400328 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " "
329 << kCurveToOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400330
Ryan Harrison275e2602017-09-18 14:23:18 -0400331 return ByteString(csAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400332}
333
Ryan Harrison275e2602017-09-18 14:23:18 -0400334ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox,
335 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400336 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400337 {
338 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400339 sAP << GetColorAppStream(crText, true) << GetAP_Check(rcBBox)
340 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400341 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400342 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400343}
344
Ryan Harrison275e2602017-09-18 14:23:18 -0400345ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox,
346 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400347 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400348 {
349 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400350 sAP << GetColorAppStream(crText, true) << GetAP_Circle(rcBBox)
351 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400352 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400353 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400354}
355
Ryan Harrison275e2602017-09-18 14:23:18 -0400356ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox,
357 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400358 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400359 {
360 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400361 sAP << GetColorAppStream(crText, false) << GetAP_Cross(rcBBox)
362 << kStrokeOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400363 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400364 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400365}
366
Ryan Harrison275e2602017-09-18 14:23:18 -0400367ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
368 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400369 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400370 {
371 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400372 sAP << "1 " << kSetLineWidthOperator << "\n"
373 << GetColorAppStream(crText, true) << GetAP_Diamond(rcBBox)
374 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400375 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400376 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400377}
378
Ryan Harrison275e2602017-09-18 14:23:18 -0400379ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox,
380 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400381 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400382 {
383 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400384 sAP << GetColorAppStream(crText, true) << GetAP_Square(rcBBox)
385 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400386 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400387 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400388}
389
Ryan Harrison275e2602017-09-18 14:23:18 -0400390ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox,
391 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400392 std::ostringstream sAP;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400393 {
394 AutoClosedQCommand q(&sAP);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400395 sAP << GetColorAppStream(crText, true) << GetAP_Star(rcBBox)
396 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400397 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400398 return ByteString(sAP);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400399}
400
Ryan Harrison275e2602017-09-18 14:23:18 -0400401ByteString GetCircleFillAppStream(const CFX_FloatRect& rect,
402 const CFX_Color& color) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400403 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -0400404 ByteString sColor = GetColorAppStream(color, true);
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400405 if (sColor.GetLength() > 0) {
406 AutoClosedQCommand q(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400407 sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400408 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400409 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400410}
411
Ryan Harrison275e2602017-09-18 14:23:18 -0400412ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect,
413 float fWidth,
414 const CFX_Color& color,
415 const CFX_Color& crLeftTop,
416 const CFX_Color& crRightBottom,
417 BorderStyle nStyle,
418 const CPWL_Dash& dash) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400419 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -0400420 ByteString sColor;
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400421
422 if (fWidth > 0.0f) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400423 AutoClosedQCommand q(&sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400424
425 float fHalfWidth = fWidth / 2.0f;
426 CFX_FloatRect rect_by_2 = rect.GetDeflated(fHalfWidth, fHalfWidth);
427
428 float div = fHalfWidth * 0.75f;
429 CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div);
430 switch (nStyle) {
431 default:
432 case BorderStyle::SOLID:
433 case BorderStyle::UNDERLINE: {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400434 sColor = GetColorAppStream(color, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400435 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400436 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400437 sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
438 << sColor << GetAP_Circle(rect_by_2) << " "
439 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400440 }
441 } break;
442 case BorderStyle::DASH: {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400443 sColor = GetColorAppStream(color, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400444 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400445 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400446 sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400447 << "[" << dash.nDash << " " << dash.nGap << "] "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400448 << dash.nPhase << " " << kSetDashOperator << "\n"
449 << sColor << GetAP_Circle(rect_by_2) << " "
450 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400451 }
452 } break;
453 case BorderStyle::BEVELED: {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400454 sColor = GetColorAppStream(color, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400455 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400456 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400457 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
458 << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
459 << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400460 }
461
Dan Sinclair14ddd422017-07-20 11:07:00 -0400462 sColor = GetColorAppStream(crLeftTop, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400463 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400464 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400465 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400466 << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f)
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400467 << " " << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400468 }
469
Dan Sinclair14ddd422017-07-20 11:07:00 -0400470 sColor = GetColorAppStream(crRightBottom, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400471 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400472 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400473 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400474 << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f)
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400475 << " " << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400476 }
477 } break;
478 case BorderStyle::INSET: {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400479 sColor = GetColorAppStream(color, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400480 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400481 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400482 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
483 << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
484 << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400485 }
486
Dan Sinclair14ddd422017-07-20 11:07:00 -0400487 sColor = GetColorAppStream(crLeftTop, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400488 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400489 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400490 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400491 << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f)
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400492 << " " << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400493 }
494
Dan Sinclair14ddd422017-07-20 11:07:00 -0400495 sColor = GetColorAppStream(crRightBottom, false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400496 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400497 AutoClosedQCommand q2(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400498 sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400499 << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f)
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400500 << " " << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400501 }
502 } break;
503 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400504 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400505 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400506}
507
Ryan Harrison275e2602017-09-18 14:23:18 -0400508ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
509 CheckStyle nStyle,
510 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400511 CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
512 switch (nStyle) {
513 default:
Dan Sinclair14ddd422017-07-20 11:07:00 -0400514 case CheckStyle::kCheck:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400515 return GetAppStream_Check(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400516 case CheckStyle::kCircle:
Lei Zhangb6254e82017-12-01 19:50:51 +0000517 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400518 return GetAppStream_Circle(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400519 case CheckStyle::kCross:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400520 return GetAppStream_Cross(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400521 case CheckStyle::kDiamond:
Lei Zhangb6254e82017-12-01 19:50:51 +0000522 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400523 return GetAppStream_Diamond(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400524 case CheckStyle::kSquare:
Lei Zhangb6254e82017-12-01 19:50:51 +0000525 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400526 return GetAppStream_Square(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400527 case CheckStyle::kStar:
Lei Zhangb6254e82017-12-01 19:50:51 +0000528 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400529 return GetAppStream_Star(rcCenter, crText);
530 }
531}
532
Ryan Harrison275e2602017-09-18 14:23:18 -0400533ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
534 CheckStyle nStyle,
535 const CFX_Color& crText) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400536 CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
537 switch (nStyle) {
538 default:
Dan Sinclair14ddd422017-07-20 11:07:00 -0400539 case CheckStyle::kCheck:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400540 return GetAppStream_Check(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400541 case CheckStyle::kCircle:
Lei Zhangb6254e82017-12-01 19:50:51 +0000542 rcCenter.ScaleFromCenterPoint(1.0f / 2.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400543 return GetAppStream_Circle(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400544 case CheckStyle::kCross:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400545 return GetAppStream_Cross(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400546 case CheckStyle::kDiamond:
Lei Zhangb6254e82017-12-01 19:50:51 +0000547 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400548 return GetAppStream_Diamond(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400549 case CheckStyle::kSquare:
Lei Zhangb6254e82017-12-01 19:50:51 +0000550 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400551 return GetAppStream_Square(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400552 case CheckStyle::kStar:
Lei Zhangb6254e82017-12-01 19:50:51 +0000553 rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400554 return GetAppStream_Star(rcCenter, crText);
555 }
556}
557
Ryan Harrison275e2602017-09-18 14:23:18 -0400558ByteString GetFontSetString(IPVT_FontMap* pFontMap,
559 int32_t nFontIndex,
560 float fFontSize) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400561 if (!pFontMap)
Ryan Harrison275e2602017-09-18 14:23:18 -0400562 return ByteString();
Dan Sinclair14ddd422017-07-20 11:07:00 -0400563
Ryan Harrison275e2602017-09-18 14:23:18 -0400564 ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400565 if (sFontAlias.GetLength() <= 0 || fFontSize <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400566 return ByteString();
Dan Sinclair14ddd422017-07-20 11:07:00 -0400567
568 std::ostringstream sRet;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400569 sRet << "/" << sFontAlias << " " << fFontSize << " "
570 << kSetTextFontAndSizeOperator << "\n";
Ryan Harrison275e2602017-09-18 14:23:18 -0400571 return ByteString(sRet);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400572}
573
Ryan Harrison275e2602017-09-18 14:23:18 -0400574ByteString GetWordRenderString(const ByteString& strWords) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400575 if (strWords.GetLength() > 0) {
576 return PDF_EncodeString(strWords, false) + " " + kShowTextOperator + "\n";
577 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400578 return ByteString();
Dan Sinclair14ddd422017-07-20 11:07:00 -0400579}
580
Ryan Harrison275e2602017-09-18 14:23:18 -0400581ByteString GetEditAppStream(CPWL_EditImpl* pEdit,
582 const CFX_PointF& ptOffset,
583 bool bContinuous,
584 uint16_t SubWord) {
Dan Sinclair6b0158f2017-07-24 09:42:55 -0400585 CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator();
Dan Sinclair14ddd422017-07-20 11:07:00 -0400586 pIterator->SetAt(0);
587
588 std::ostringstream sEditStream;
589 std::ostringstream sWords;
590 int32_t nCurFontIndex = -1;
591 CFX_PointF ptOld;
592 CFX_PointF ptNew;
593 CPVT_WordPlace oldplace;
594
595 while (pIterator->NextWord()) {
596 CPVT_WordPlace place = pIterator->GetAt();
597 if (bContinuous) {
598 if (place.LineCmp(oldplace) != 0) {
599 if (sWords.tellp() > 0) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400600 sEditStream << GetWordRenderString(ByteString(sWords));
Dan Sinclair14ddd422017-07-20 11:07:00 -0400601 sWords.str("");
602 }
603
604 CPVT_Word word;
605 if (pIterator->GetWord(word)) {
606 ptNew = CFX_PointF(word.ptWord.x + ptOffset.x,
607 word.ptWord.y + ptOffset.y);
608 } else {
609 CPVT_Line line;
610 pIterator->GetLine(line);
611 ptNew = CFX_PointF(line.ptLine.x + ptOffset.x,
612 line.ptLine.y + ptOffset.y);
613 }
614
615 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400616 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " "
617 << kMoveTextPositionOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400618
619 ptOld = ptNew;
620 }
621 }
622
623 CPVT_Word word;
624 if (pIterator->GetWord(word)) {
625 if (word.nFontIndex != nCurFontIndex) {
626 if (sWords.tellp() > 0) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400627 sEditStream << GetWordRenderString(ByteString(sWords));
Dan Sinclair14ddd422017-07-20 11:07:00 -0400628 sWords.str("");
629 }
630 sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
631 word.fFontSize);
632 nCurFontIndex = word.nFontIndex;
633 }
634
Dan Sinclairc08dc392017-07-24 08:57:35 -0400635 sWords << pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400636 }
637
638 oldplace = place;
639 } else {
640 CPVT_Word word;
641 if (pIterator->GetWord(word)) {
642 ptNew =
643 CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
644
645 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400646 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " "
647 << kMoveTextPositionOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400648 ptOld = ptNew;
649 }
650
651 if (word.nFontIndex != nCurFontIndex) {
652 sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
653 word.fFontSize);
654 nCurFontIndex = word.nFontIndex;
655 }
656
Dan Sinclairc08dc392017-07-24 08:57:35 -0400657 sEditStream << GetWordRenderString(
658 pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord));
Dan Sinclair14ddd422017-07-20 11:07:00 -0400659 }
660 }
661 }
662
663 if (sWords.tellp() > 0) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400664 sEditStream << GetWordRenderString(ByteString(sWords));
Dan Sinclair14ddd422017-07-20 11:07:00 -0400665 sWords.str("");
666 }
667
668 std::ostringstream sAppStream;
669 if (sEditStream.tellp() > 0) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400670 float fCharSpace = pEdit->GetCharSpace();
Tom Sepez7cabaf12018-10-04 21:13:59 +0000671 if (!IsFloatZero(fCharSpace))
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400672 sAppStream << fCharSpace << " " << kSetCharacterSpacingOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400673
674 sAppStream << sEditStream.str();
675 }
676
Ryan Harrison275e2602017-09-18 14:23:18 -0400677 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400678}
679
Ryan Harrison275e2602017-09-18 14:23:18 -0400680ByteString GenerateIconAppStream(CPDF_IconFit& fit,
681 CPDF_Stream* pIconStream,
682 const CFX_FloatRect& rcIcon) {
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400683 if (rcIcon.IsEmpty() || !pIconStream)
Ryan Harrison275e2602017-09-18 14:23:18 -0400684 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400685
686 CPWL_Icon icon;
Tom Sepezbf157302017-09-15 13:26:32 -0700687 CPWL_Wnd::CreateParams cp;
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400688 cp.dwFlags = PWS_VISIBLE;
689 icon.Create(cp);
690 icon.SetIconFit(&fit);
691 icon.SetPDFStream(pIconStream);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400692 if (!icon.Move(rcIcon, false, false))
693 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400694
Ryan Harrison275e2602017-09-18 14:23:18 -0400695 ByteString sAlias = icon.GetImageAlias();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400696 if (sAlias.GetLength() <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400697 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400698
699 CFX_FloatRect rcPlate = icon.GetClientRect();
700 CFX_Matrix mt = icon.GetImageMatrix().GetInverse();
701
702 float fHScale;
703 float fVScale;
704 std::tie(fHScale, fVScale) = icon.GetScale();
705
706 float fx;
707 float fy;
708 std::tie(fx, fy) = icon.GetImageOffset();
709
710 std::ostringstream str;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400711 {
712 AutoClosedQCommand q(&str);
713 str << rcPlate.left << " " << rcPlate.bottom << " "
714 << rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400715 << " " << kAppendRectOperator << " " << kSetNonZeroWindingClipOperator
716 << " " << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400717
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400718 str << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400719 << rcPlate.bottom + fy << " " << kConcatMatrixOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400720 str << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " " << mt.e
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400721 << " " << mt.f << " " << kConcatMatrixOperator << "\n";
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400722
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400723 str << "0 " << kSetGrayOperator << " 0 " << kSetGrayStrokedOperator << " 1 "
724 << kSetLineWidthOperator << " /" << sAlias << " "
725 << kInvokeNamedXObjectOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400726 }
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400727 icon.Destroy();
728
Ryan Harrison275e2602017-09-18 14:23:18 -0400729 return ByteString(str);
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400730}
731
Ryan Harrison275e2602017-09-18 14:23:18 -0400732ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
733 IPVT_FontMap* pFontMap,
734 CPDF_Stream* pIconStream,
735 CPDF_IconFit& IconFit,
736 const WideString& sLabel,
737 const CFX_Color& crText,
738 float fFontSize,
739 ButtonStyle nLayOut) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400740 const float fAutoFontScale = 1.0f / 3.0f;
741
Dan Sinclair6b0158f2017-07-24 09:42:55 -0400742 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400743 pEdit->SetFontMap(pFontMap);
744 pEdit->SetAlignmentH(1, true);
745 pEdit->SetAlignmentV(1, true);
746 pEdit->SetMultiLine(false, true);
747 pEdit->SetAutoReturn(false, true);
748 if (IsFloatZero(fFontSize))
749 pEdit->SetAutoFontSize(true, true);
750 else
751 pEdit->SetFontSize(fFontSize);
752
753 pEdit->Initialize();
754 pEdit->SetText(sLabel);
755
756 CFX_FloatRect rcLabelContent = pEdit->GetContentRect();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400757 CFX_FloatRect rcLabel;
758 CFX_FloatRect rcIcon;
759 float fWidth = 0.0f;
760 float fHeight = 0.0f;
761
762 switch (nLayOut) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400763 case ButtonStyle::kLabel:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400764 rcLabel = rcBBox;
765 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400766 case ButtonStyle::kIcon:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400767 rcIcon = rcBBox;
768 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400769 case ButtonStyle::kIconTopLabelBottom:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400770 if (pIconStream) {
771 if (IsFloatZero(fFontSize)) {
Lei Zhang98758892018-03-15 15:02:22 +0000772 fHeight = rcBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400773 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
774 rcBBox.bottom + fHeight * fAutoFontScale);
775 rcIcon =
776 CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top);
777 } else {
778 fHeight = rcLabelContent.Height();
779
780 if (rcBBox.bottom + fHeight > rcBBox.top) {
781 rcLabel = rcBBox;
782 } else {
783 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
784 rcBBox.bottom + fHeight);
785 rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right,
786 rcBBox.top);
787 }
788 }
789 } else {
790 rcLabel = rcBBox;
791 }
792 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400793 case ButtonStyle::kIconBottomLabelTop:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400794 if (pIconStream) {
795 if (IsFloatZero(fFontSize)) {
Lei Zhang98758892018-03-15 15:02:22 +0000796 fHeight = rcBBox.Height();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400797 rcLabel =
798 CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale,
799 rcBBox.right, rcBBox.top);
800 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
801 rcLabel.bottom);
802 } else {
803 fHeight = rcLabelContent.Height();
804
805 if (rcBBox.bottom + fHeight > rcBBox.top) {
806 rcLabel = rcBBox;
807 } else {
808 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight,
809 rcBBox.right, rcBBox.top);
810 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
811 rcLabel.bottom);
812 }
813 }
814 } else {
815 rcLabel = rcBBox;
816 }
817 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400818 case ButtonStyle::kIconLeftLabelRight:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400819 if (pIconStream) {
820 if (IsFloatZero(fFontSize)) {
821 fWidth = rcBBox.right - rcBBox.left;
822 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
823 rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale,
824 rcBBox.bottom, rcBBox.right, rcBBox.top);
825 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
826 rcBBox.top);
827 } else {
828 if (rcLabelContent.Width() < fWidth) {
829 rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(),
830 rcBBox.bottom, rcBBox.right, rcBBox.top);
831 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
832 rcBBox.top);
833 } else {
834 rcLabel = rcBBox;
835 }
836 }
837 } else {
838 fWidth = rcLabelContent.Width();
839 if (rcBBox.left + fWidth > rcBBox.right) {
840 rcLabel = rcBBox;
841 } else {
842 rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom,
843 rcBBox.right, rcBBox.top);
844 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
845 rcBBox.top);
846 }
847 }
848 } else {
849 rcLabel = rcBBox;
850 }
851 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400852 case ButtonStyle::kIconRightLabelLeft:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400853 if (pIconStream) {
854 if (IsFloatZero(fFontSize)) {
855 fWidth = rcBBox.right - rcBBox.left;
856 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
857 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
858 rcBBox.left + fWidth * fAutoFontScale,
859 rcBBox.top);
860 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
861 rcBBox.top);
862 } else {
863 if (rcLabelContent.Width() < fWidth) {
864 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
865 rcBBox.left + rcLabelContent.Width(),
866 rcBBox.top);
867 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
868 rcBBox.top);
869 } else {
870 rcLabel = rcBBox;
871 }
872 }
873 } else {
874 fWidth = rcLabelContent.Width();
875 if (rcBBox.left + fWidth > rcBBox.right) {
876 rcLabel = rcBBox;
877 } else {
878 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
879 rcBBox.left + fWidth, rcBBox.top);
880 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
881 rcBBox.top);
882 }
883 }
884 } else {
885 rcLabel = rcBBox;
886 }
887 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400888 case ButtonStyle::kLabelOverIcon:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400889 rcLabel = rcBBox;
890 rcIcon = rcBBox;
891 break;
892 }
893
894 std::ostringstream sTemp;
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400895 sTemp << GenerateIconAppStream(IconFit, pIconStream, rcIcon);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400896
897 if (!rcLabel.IsEmpty()) {
898 pEdit->SetPlateRect(rcLabel);
Ryan Harrison275e2602017-09-18 14:23:18 -0400899 ByteString sEdit =
Dan Sinclair14ddd422017-07-20 11:07:00 -0400900 GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f), true, 0);
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400901 if (sEdit.GetLength() > 0) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400902 AutoClosedCommand bt(&sTemp, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400903 sTemp << GetColorAppStream(crText, true) << sEdit;
904 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400905 }
906
907 if (sTemp.tellp() <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400908 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400909
910 std::ostringstream sAppStream;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400911 {
912 AutoClosedQCommand q(&sAppStream);
913 sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
914 << rcBBox.right - rcBBox.left << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400915 << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator
916 << " " << kSetNonZeroWindingClipOperator << " "
917 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400918 sAppStream << sTemp.str().c_str();
919 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400920 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400921}
922
Ryan Harrison275e2602017-09-18 14:23:18 -0400923ByteString GetBorderAppStreamInternal(const CFX_FloatRect& rect,
924 float fWidth,
925 const CFX_Color& color,
926 const CFX_Color& crLeftTop,
927 const CFX_Color& crRightBottom,
928 BorderStyle nStyle,
929 const CPWL_Dash& dash) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400930 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -0400931 ByteString sColor;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400932
933 float fLeft = rect.left;
934 float fRight = rect.right;
935 float fTop = rect.top;
936 float fBottom = rect.bottom;
937
938 if (fWidth > 0.0f) {
939 float fHalfWidth = fWidth / 2.0f;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400940 AutoClosedQCommand q(&sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400941
942 switch (nStyle) {
943 default:
944 case BorderStyle::SOLID:
945 sColor = GetColorAppStream(color, true);
946 if (sColor.GetLength() > 0) {
947 sAppStream << sColor;
948 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400949 << fTop - fBottom << " " << kAppendRectOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400950 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
951 << fRight - fLeft - fWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400952 << fTop - fBottom - fWidth * 2 << " "
953 << kAppendRectOperator << "\n";
954 sAppStream << kFillEvenOddOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400955 }
956 break;
957 case BorderStyle::DASH:
958 sColor = GetColorAppStream(color, false);
959 if (sColor.GetLength() > 0) {
960 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400961 sAppStream << fWidth << " " << kSetLineWidthOperator << " ["
962 << dash.nDash << " " << dash.nGap << "] " << dash.nPhase
963 << " " << kSetDashOperator << "\n";
964 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
965 << kMoveToOperator << "\n";
966 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " "
967 << kLineToOperator << "\n";
968 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " "
969 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400970 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400971 << " " << kLineToOperator << "\n";
972 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
973 << kLineToOperator << " " << kStrokeOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400974 }
975 break;
976 case BorderStyle::BEVELED:
977 case BorderStyle::INSET:
978 sColor = GetColorAppStream(crLeftTop, true);
979 if (sColor.GetLength() > 0) {
980 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400981 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
982 << kMoveToOperator << "\n";
983 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " "
984 << kLineToOperator << "\n";
985 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
986 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400987 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400988 << " " << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400989 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400990 << " " << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400991 sAppStream << fLeft + fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400992 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
993 << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400994 }
995
996 sColor = GetColorAppStream(crRightBottom, true);
997 if (sColor.GetLength() > 0) {
998 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400999 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
1000 << kMoveToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001001 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001002 << " " << kLineToOperator << "\n";
1003 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
1004 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001005 sAppStream << fLeft + fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001006 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
1007 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001008 sAppStream << fRight - fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001009 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
1010 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001011 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001012 << " " << kLineToOperator << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001013 }
1014
1015 sColor = GetColorAppStream(color, true);
1016 if (sColor.GetLength() > 0) {
1017 sAppStream << sColor;
1018 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001019 << fTop - fBottom << " " << kAppendRectOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001020 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
1021 << fRight - fLeft - fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001022 << fTop - fBottom - fHalfWidth * 2 << " "
1023 << kAppendRectOperator << " " << kFillEvenOddOperator
1024 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001025 }
1026 break;
1027 case BorderStyle::UNDERLINE:
1028 sColor = GetColorAppStream(color, false);
1029 if (sColor.GetLength() > 0) {
1030 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001031 sAppStream << fWidth << " " << kSetLineWidthOperator << "\n";
1032 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " "
1033 << kMoveToOperator << "\n";
1034 sAppStream << fRight << " " << fBottom + fWidth / 2 << " "
1035 << kLineToOperator << " " << kStrokeOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001036 }
1037 break;
1038 }
Dan Sinclair14ddd422017-07-20 11:07:00 -04001039 }
1040
Ryan Harrison275e2602017-09-18 14:23:18 -04001041 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001042}
1043
Ryan Harrison275e2602017-09-18 14:23:18 -04001044ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001045 if (rcBBox.IsEmpty())
Ryan Harrison275e2602017-09-18 14:23:18 -04001046 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001047
1048 std::ostringstream sAppStream;
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001049 {
1050 AutoClosedQCommand q(&sAppStream);
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001051 sAppStream << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f,
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001052 220.0f / 255.0f, 220.0f / 255.0f),
1053 true)
1054 << rcBBox.left << " " << rcBBox.bottom << " "
1055 << rcBBox.right - rcBBox.left << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001056 << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator
1057 << " " << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001058 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001059
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001060 {
1061 AutoClosedQCommand q(&sAppStream);
1062 sAppStream << GetBorderAppStreamInternal(
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001063 rcBBox, 2, CFX_Color(CFX_Color::kGray, 0),
1064 CFX_Color(CFX_Color::kGray, 1), CFX_Color(CFX_Color::kGray, 0.5),
1065 BorderStyle::BEVELED, CPWL_Dash(3, 0, 0));
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001066 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001067
1068 CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2,
1069 (rcBBox.top + rcBBox.bottom) / 2);
1070 if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) &&
1071 IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001072 AutoClosedQCommand q(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001073 sAppStream << " 0 " << kSetGrayOperator << "\n"
1074 << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
1075 << kMoveToOperator << "\n"
1076 << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " "
1077 << kLineToOperator << "\n"
1078 << ptCenter.x << " " << ptCenter.y - 1.5f << " "
1079 << kLineToOperator << "\n"
1080 << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
1081 << kLineToOperator << " " << kFillOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001082 }
1083
Ryan Harrison275e2602017-09-18 14:23:18 -04001084 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001085}
1086
Ryan Harrison275e2602017-09-18 14:23:18 -04001087ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
1088 const CFX_Color& color) {
Dan Sinclair14ddd422017-07-20 11:07:00 -04001089 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -04001090 ByteString sColor = GetColorAppStream(color, true);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001091 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001092 AutoClosedQCommand q(&sAppStream);
1093 sAppStream << sColor << rect.left << " " << rect.bottom << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001094 << rect.right - rect.left << " " << rect.top - rect.bottom << " "
1095 << kAppendRectOperator << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001096 }
1097
Ryan Harrison275e2602017-09-18 14:23:18 -04001098 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001099}
1100
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001101} // namespace
1102
1103CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict)
1104 : widget_(widget), dict_(dict) {}
1105
1106CPWL_AppStream::~CPWL_AppStream() {}
1107
1108void CPWL_AppStream::SetAsPushButton() {
1109 CPDF_FormControl* pControl = widget_->GetFormControl();
1110 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
Dan Sinclair14ddd422017-07-20 11:07:00 -04001111 ButtonStyle nLayout = ButtonStyle::kLabel;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001112 switch (pControl->GetTextPosition()) {
1113 case TEXTPOS_ICON:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001114 nLayout = ButtonStyle::kIcon;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001115 break;
1116 case TEXTPOS_BELOW:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001117 nLayout = ButtonStyle::kIconTopLabelBottom;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001118 break;
1119 case TEXTPOS_ABOVE:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001120 nLayout = ButtonStyle::kIconBottomLabelTop;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001121 break;
1122 case TEXTPOS_RIGHT:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001123 nLayout = ButtonStyle::kIconLeftLabelRight;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001124 break;
1125 case TEXTPOS_LEFT:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001126 nLayout = ButtonStyle::kIconRightLabelLeft;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001127 break;
1128 case TEXTPOS_OVERLAID:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001129 nLayout = ButtonStyle::kLabelOverIcon;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001130 break;
1131 default:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001132 nLayout = ButtonStyle::kLabel;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001133 break;
1134 }
1135
1136 CFX_Color crBackground;
1137 CFX_Color crBorder;
1138 int iColorType;
1139 float fc[4];
1140 pControl->GetOriginalBackgroundColor(iColorType, fc);
1141 if (iColorType > 0)
1142 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1143
1144 pControl->GetOriginalBorderColor(iColorType, fc);
1145 if (iColorType > 0)
1146 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1147
1148 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1149 CPWL_Dash dsBorder(3, 0, 0);
1150 CFX_Color crLeftTop;
1151 CFX_Color crRightBottom;
1152
1153 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1154 switch (nBorderStyle) {
1155 case BorderStyle::DASH:
1156 dsBorder = CPWL_Dash(3, 3, 0);
1157 break;
1158 case BorderStyle::BEVELED:
1159 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001160 crLeftTop = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001161 crRightBottom = crBackground / 2.0f;
1162 break;
1163 case BorderStyle::INSET:
1164 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001165 crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
1166 crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001167 break;
1168 default:
1169 break;
1170 }
1171
1172 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001173 CFX_Color crText(CFX_Color::kGray, 0);
Ryan Harrison275e2602017-09-18 14:23:18 -04001174 ByteString csNameTag;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001175 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
Dan Sinclair28bb2f22018-04-03 19:52:27 +00001176 Optional<CFX_Color::Type> color = da.GetColor(fc);
1177 if (color) {
1178 iColorType = *color;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001179 crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1180 }
Dan Sinclair4c22dd52018-04-03 19:10:51 +00001181
1182 float fFontSize;
1183 Optional<ByteString> font = da.GetFont(&fFontSize);
1184 if (font)
1185 csNameTag = *font;
1186 else
1187 fFontSize = 12.0f;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001188
Ryan Harrison275e2602017-09-18 14:23:18 -04001189 WideString csWCaption;
1190 WideString csNormalCaption;
1191 WideString csRolloverCaption;
1192 WideString csDownCaption;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001193 if (pControl->HasMKEntry("CA"))
1194 csNormalCaption = pControl->GetNormalCaption();
1195
1196 if (pControl->HasMKEntry("RC"))
1197 csRolloverCaption = pControl->GetRolloverCaption();
1198
1199 if (pControl->HasMKEntry("AC"))
1200 csDownCaption = pControl->GetDownCaption();
1201
1202 CPDF_Stream* pNormalIcon = nullptr;
1203 CPDF_Stream* pRolloverIcon = nullptr;
1204 CPDF_Stream* pDownIcon = nullptr;
1205 if (pControl->HasMKEntry("I"))
1206 pNormalIcon = pControl->GetNormalIcon();
1207
1208 if (pControl->HasMKEntry("RI"))
1209 pRolloverIcon = pControl->GetRolloverIcon();
1210
1211 if (pControl->HasMKEntry("IX"))
1212 pDownIcon = pControl->GetDownIcon();
1213
1214 if (pNormalIcon) {
1215 if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) {
1216 if (pImageDict->GetStringFor("Name").IsEmpty())
1217 pImageDict->SetNewFor<CPDF_String>("Name", "ImgA", false);
1218 }
1219 }
1220
1221 if (pRolloverIcon) {
1222 if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
1223 if (pImageDict->GetStringFor("Name").IsEmpty())
1224 pImageDict->SetNewFor<CPDF_String>("Name", "ImgB", false);
1225 }
1226 }
1227
1228 if (pDownIcon) {
1229 if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
1230 if (pImageDict->GetStringFor("Name").IsEmpty())
1231 pImageDict->SetNewFor<CPDF_String>("Name", "ImgC", false);
1232 }
1233 }
1234
1235 CPDF_IconFit iconFit = pControl->GetIconFit();
1236
1237 CBA_FontMap font_map(
1238 widget_.Get(),
1239 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
1240 font_map.SetAPType("N");
1241
Ryan Harrison275e2602017-09-18 14:23:18 -04001242 ByteString csAP =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001243 GetRectFillAppStream(rcWindow, crBackground) +
1244 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1245 crRightBottom, nBorderStyle, dsBorder) +
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001246 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1247 &font_map, pNormalIcon, iconFit, csNormalCaption,
1248 crText, fFontSize, nLayout);
1249
1250 Write("N", csAP, "");
1251 if (pNormalIcon)
1252 AddImage("N", pNormalIcon);
1253
1254 CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode();
1255 if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) {
1256 if (csRolloverCaption.IsEmpty() && !pRolloverIcon) {
1257 csRolloverCaption = csNormalCaption;
1258 pRolloverIcon = pNormalIcon;
1259 }
1260
1261 font_map.SetAPType("R");
1262
1263 csAP =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001264 GetRectFillAppStream(rcWindow, crBackground) +
1265 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1266 crRightBottom, nBorderStyle, dsBorder) +
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001267 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1268 &font_map, pRolloverIcon, iconFit,
1269 csRolloverCaption, crText, fFontSize, nLayout);
1270
1271 Write("R", csAP, "");
1272 if (pRolloverIcon)
1273 AddImage("R", pRolloverIcon);
1274
1275 if (csDownCaption.IsEmpty() && !pDownIcon) {
1276 csDownCaption = csNormalCaption;
1277 pDownIcon = pNormalIcon;
1278 }
1279
1280 switch (nBorderStyle) {
1281 case BorderStyle::BEVELED: {
1282 CFX_Color crTemp = crLeftTop;
1283 crLeftTop = crRightBottom;
1284 crRightBottom = crTemp;
1285 break;
1286 }
1287 case BorderStyle::INSET: {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001288 crLeftTop = CFX_Color(CFX_Color::kGray, 0);
1289 crRightBottom = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001290 break;
1291 }
1292 default:
1293 break;
1294 }
1295
1296 font_map.SetAPType("D");
1297
Dan Sinclair14ddd422017-07-20 11:07:00 -04001298 csAP =
1299 GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1300 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1301 crRightBottom, nBorderStyle, dsBorder) +
1302 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1303 &font_map, pDownIcon, iconFit, csDownCaption,
1304 crText, fFontSize, nLayout);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001305
1306 Write("D", csAP, "");
1307 if (pDownIcon)
1308 AddImage("D", pDownIcon);
1309 } else {
1310 Remove("D");
1311 Remove("R");
1312 }
1313}
1314
1315void CPWL_AppStream::SetAsCheckBox() {
1316 CPDF_FormControl* pControl = widget_->GetFormControl();
1317 CFX_Color crBackground, crBorder, crText;
1318 int iColorType;
1319 float fc[4];
1320
1321 pControl->GetOriginalBackgroundColor(iColorType, fc);
1322 if (iColorType > 0)
1323 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1324
1325 pControl->GetOriginalBorderColor(iColorType, fc);
1326 if (iColorType > 0)
1327 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1328
1329 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1330 CPWL_Dash dsBorder(3, 0, 0);
1331 CFX_Color crLeftTop, crRightBottom;
1332
1333 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1334 switch (nBorderStyle) {
1335 case BorderStyle::DASH:
1336 dsBorder = CPWL_Dash(3, 3, 0);
1337 break;
1338 case BorderStyle::BEVELED:
1339 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001340 crLeftTop = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001341 crRightBottom = crBackground / 2.0f;
1342 break;
1343 case BorderStyle::INSET:
1344 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001345 crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
1346 crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001347 break;
1348 default:
1349 break;
1350 }
1351
1352 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1353 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1354 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
Dan Sinclair28bb2f22018-04-03 19:52:27 +00001355 Optional<CFX_Color::Type> color = da.GetColor(fc);
1356 if (color) {
1357 iColorType = *color;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001358 crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1359 }
1360
Dan Sinclair14ddd422017-07-20 11:07:00 -04001361 CheckStyle nStyle = CheckStyle::kCheck;
Ryan Harrison275e2602017-09-18 14:23:18 -04001362 WideString csWCaption = pControl->GetNormalCaption();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001363 if (csWCaption.GetLength() > 0) {
1364 switch (csWCaption[0]) {
1365 case L'l':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001366 nStyle = CheckStyle::kCircle;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001367 break;
1368 case L'8':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001369 nStyle = CheckStyle::kCross;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001370 break;
1371 case L'u':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001372 nStyle = CheckStyle::kDiamond;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001373 break;
1374 case L'n':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001375 nStyle = CheckStyle::kSquare;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001376 break;
1377 case L'H':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001378 nStyle = CheckStyle::kStar;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001379 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -04001380 case L'4':
1381 default:
1382 nStyle = CheckStyle::kCheck;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001383 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001384 }
1385
Ryan Harrison275e2602017-09-18 14:23:18 -04001386 ByteString csAP_N_ON =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001387 GetRectFillAppStream(rcWindow, crBackground) +
1388 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1389 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001390
Ryan Harrison275e2602017-09-18 14:23:18 -04001391 ByteString csAP_N_OFF = csAP_N_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001392
1393 switch (nBorderStyle) {
1394 case BorderStyle::BEVELED: {
1395 CFX_Color crTemp = crLeftTop;
1396 crLeftTop = crRightBottom;
1397 crRightBottom = crTemp;
1398 break;
1399 }
1400 case BorderStyle::INSET: {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001401 crLeftTop = CFX_Color(CFX_Color::kGray, 0);
1402 crRightBottom = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001403 break;
1404 }
1405 default:
1406 break;
1407 }
1408
Ryan Harrison275e2602017-09-18 14:23:18 -04001409 ByteString csAP_D_ON =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001410 GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1411 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1412 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001413
Ryan Harrison275e2602017-09-18 14:23:18 -04001414 ByteString csAP_D_OFF = csAP_D_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001415
1416 csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1417 csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1418
1419 Write("N", csAP_N_ON, pControl->GetCheckedAPState());
1420 Write("N", csAP_N_OFF, "Off");
1421
1422 Write("D", csAP_D_ON, pControl->GetCheckedAPState());
1423 Write("D", csAP_D_OFF, "Off");
1424
Ryan Harrison275e2602017-09-18 14:23:18 -04001425 ByteString csAS = widget_->GetAppState();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001426 if (csAS.IsEmpty())
1427 widget_->SetAppState("Off");
1428}
1429
1430void CPWL_AppStream::SetAsRadioButton() {
1431 CPDF_FormControl* pControl = widget_->GetFormControl();
1432 CFX_Color crBackground;
1433 CFX_Color crBorder;
1434 CFX_Color crText;
1435 int iColorType;
1436 float fc[4];
1437
1438 pControl->GetOriginalBackgroundColor(iColorType, fc);
1439 if (iColorType > 0)
1440 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1441
1442 pControl->GetOriginalBorderColor(iColorType, fc);
1443 if (iColorType > 0)
1444 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1445
1446 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1447 CPWL_Dash dsBorder(3, 0, 0);
1448 CFX_Color crLeftTop;
1449 CFX_Color crRightBottom;
1450 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1451 switch (nBorderStyle) {
1452 case BorderStyle::DASH:
1453 dsBorder = CPWL_Dash(3, 3, 0);
1454 break;
1455 case BorderStyle::BEVELED:
1456 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001457 crLeftTop = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001458 crRightBottom = crBackground / 2.0f;
1459 break;
1460 case BorderStyle::INSET:
1461 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001462 crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
1463 crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001464 break;
1465 default:
1466 break;
1467 }
1468
1469 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1470 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1471 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
Dan Sinclair28bb2f22018-04-03 19:52:27 +00001472 Optional<CFX_Color::Type> color = da.GetColor(fc);
1473 if (color) {
1474 iColorType = *color;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001475 crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1476 }
1477
Dan Sinclair14ddd422017-07-20 11:07:00 -04001478 CheckStyle nStyle = CheckStyle::kCircle;
Ryan Harrison275e2602017-09-18 14:23:18 -04001479 WideString csWCaption = pControl->GetNormalCaption();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001480 if (csWCaption.GetLength() > 0) {
1481 switch (csWCaption[0]) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001482 case L'8':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001483 nStyle = CheckStyle::kCross;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001484 break;
1485 case L'u':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001486 nStyle = CheckStyle::kDiamond;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001487 break;
1488 case L'n':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001489 nStyle = CheckStyle::kSquare;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001490 break;
1491 case L'H':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001492 nStyle = CheckStyle::kStar;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001493 break;
1494 case L'4':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001495 nStyle = CheckStyle::kCheck;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001496 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -04001497 case L'l':
1498 default:
1499 nStyle = CheckStyle::kCircle;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001500 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001501 }
1502
Ryan Harrison275e2602017-09-18 14:23:18 -04001503 ByteString csAP_N_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001504 CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001505 if (nStyle == CheckStyle::kCircle) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001506 if (nBorderStyle == BorderStyle::BEVELED) {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001507 crLeftTop = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001508 crRightBottom = crBackground - 0.25f;
1509 } else if (nBorderStyle == BorderStyle::INSET) {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001510 crLeftTop = CFX_Color(CFX_Color::kGray, 0.5f);
1511 crRightBottom = CFX_Color(CFX_Color::kGray, 0.75f);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001512 }
1513
1514 csAP_N_ON =
1515 GetCircleFillAppStream(rcCenter, crBackground) +
1516 GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
1517 crRightBottom, nBorderStyle, dsBorder);
1518 } else {
Dan Sinclair14ddd422017-07-20 11:07:00 -04001519 csAP_N_ON =
1520 GetRectFillAppStream(rcWindow, crBackground) +
1521 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1522 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001523 }
1524
Ryan Harrison275e2602017-09-18 14:23:18 -04001525 ByteString csAP_N_OFF = csAP_N_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001526
1527 switch (nBorderStyle) {
1528 case BorderStyle::BEVELED: {
1529 CFX_Color crTemp = crLeftTop;
1530 crLeftTop = crRightBottom;
1531 crRightBottom = crTemp;
1532 break;
1533 }
1534 case BorderStyle::INSET: {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001535 crLeftTop = CFX_Color(CFX_Color::kGray, 0);
1536 crRightBottom = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001537 break;
1538 }
1539 default:
1540 break;
1541 }
1542
Ryan Harrison275e2602017-09-18 14:23:18 -04001543 ByteString csAP_D_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001544
Dan Sinclair14ddd422017-07-20 11:07:00 -04001545 if (nStyle == CheckStyle::kCircle) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001546 CFX_Color crBK = crBackground - 0.25f;
1547 if (nBorderStyle == BorderStyle::BEVELED) {
1548 crLeftTop = crBackground - 0.25f;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001549 crRightBottom = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001550 crBK = crBackground;
1551 } else if (nBorderStyle == BorderStyle::INSET) {
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001552 crLeftTop = CFX_Color(CFX_Color::kGray, 0);
1553 crRightBottom = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001554 }
1555
1556 csAP_D_ON =
1557 GetCircleFillAppStream(rcCenter, crBK) +
1558 GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
1559 crRightBottom, nBorderStyle, dsBorder);
1560 } else {
1561 csAP_D_ON =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001562 GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1563 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1564 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001565 }
1566
Ryan Harrison275e2602017-09-18 14:23:18 -04001567 ByteString csAP_D_OFF = csAP_D_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001568
1569 csAP_N_ON += GetRadioButtonAppStream(rcClient, nStyle, crText);
1570 csAP_D_ON += GetRadioButtonAppStream(rcClient, nStyle, crText);
1571
1572 Write("N", csAP_N_ON, pControl->GetCheckedAPState());
1573 Write("N", csAP_N_OFF, "Off");
1574
1575 Write("D", csAP_D_ON, pControl->GetCheckedAPState());
1576 Write("D", csAP_D_OFF, "Off");
1577
Ryan Harrison275e2602017-09-18 14:23:18 -04001578 ByteString csAS = widget_->GetAppState();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001579 if (csAS.IsEmpty())
1580 widget_->SetAppState("Off");
1581}
1582
Ryan Harrison275e2602017-09-18 14:23:18 -04001583void CPWL_AppStream::SetAsComboBox(const WideString* sValue) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001584 CPDF_FormControl* pControl = widget_->GetFormControl();
1585 CPDF_FormField* pField = pControl->GetField();
1586 std::ostringstream sBody;
1587
1588 CFX_FloatRect rcClient = widget_->GetClientRect();
1589 CFX_FloatRect rcButton = rcClient;
1590 rcButton.left = rcButton.right - 13;
1591 rcButton.Normalize();
1592
Tom Sepezae386362018-08-21 23:10:51 +00001593 // Font map must outlive |pEdit|.
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001594 CBA_FontMap font_map(
1595 widget_.Get(),
1596 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
Tom Sepezae386362018-08-21 23:10:51 +00001597
1598 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
1599 pEdit->EnableRefresh(false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001600 pEdit->SetFontMap(&font_map);
1601
1602 CFX_FloatRect rcEdit = rcClient;
1603 rcEdit.right = rcButton.left;
1604 rcEdit.Normalize();
1605
1606 pEdit->SetPlateRect(rcEdit);
1607 pEdit->SetAlignmentV(1, true);
1608
1609 float fFontSize = widget_->GetFontSize();
1610 if (IsFloatZero(fFontSize))
1611 pEdit->SetAutoFontSize(true, true);
1612 else
1613 pEdit->SetFontSize(fFontSize);
1614
1615 pEdit->Initialize();
1616
1617 if (sValue) {
1618 pEdit->SetText(*sValue);
1619 } else {
1620 int32_t nCurSel = pField->GetSelectedIndex(0);
1621 if (nCurSel < 0)
1622 pEdit->SetText(pField->GetValue());
1623 else
1624 pEdit->SetText(pField->GetOptionLabel(nCurSel));
1625 }
1626
1627 CFX_FloatRect rcContent = pEdit->GetContentRect();
Ryan Harrison275e2602017-09-18 14:23:18 -04001628 ByteString sEdit = GetEditAppStream(pEdit.get(), CFX_PointF(), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001629 if (sEdit.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001630 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001631 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1632 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001633 AutoClosedQCommand q(&sBody);
1634
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001635 if (rcContent.Width() > rcEdit.Width() ||
1636 rcContent.Height() > rcEdit.Height()) {
1637 sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001638 << " " << rcEdit.Height() << " " << kAppendRectOperator << "\n"
1639 << kSetNonZeroWindingClipOperator << "\n"
1640 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001641 }
1642
1643 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001644 AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001645 sBody << GetColorAppStream(crText, true) << sEdit;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001646 }
1647
1648 sBody << GetDropButtonAppStream(rcButton);
1649 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001650 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001651 "");
1652}
1653
1654void CPWL_AppStream::SetAsListBox() {
1655 CPDF_FormControl* pControl = widget_->GetFormControl();
1656 CPDF_FormField* pField = pControl->GetField();
1657 CFX_FloatRect rcClient = widget_->GetClientRect();
1658 std::ostringstream sBody;
1659
Tom Sepezae386362018-08-21 23:10:51 +00001660 // Font map must outlive |pEdit|.
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001661 CBA_FontMap font_map(
1662 widget_.Get(),
1663 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
Tom Sepezae386362018-08-21 23:10:51 +00001664
1665 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
1666 pEdit->EnableRefresh(false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001667 pEdit->SetFontMap(&font_map);
1668 pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f));
1669
1670 float fFontSize = widget_->GetFontSize();
1671 pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize);
1672 pEdit->Initialize();
1673
1674 std::ostringstream sList;
1675 float fy = rcClient.top;
1676
1677 int32_t nTop = pField->GetTopVisibleIndex();
1678 int32_t nCount = pField->CountOptions();
1679 int32_t nSelCount = pField->CountSelectedItems();
1680
1681 for (int32_t i = nTop; i < nCount; ++i) {
1682 bool bSelected = false;
1683 for (int32_t j = 0; j < nSelCount; ++j) {
1684 if (pField->GetSelectedIndex(j) == i) {
1685 bSelected = true;
1686 break;
1687 }
1688 }
1689
1690 pEdit->SetText(pField->GetOptionLabel(i));
1691
1692 CFX_FloatRect rcContent = pEdit->GetContentRect();
1693 float fItemHeight = rcContent.Height();
1694
1695 if (bSelected) {
1696 CFX_FloatRect rcItem =
1697 CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001698 {
1699 AutoClosedQCommand q(&sList);
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001700 sList << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 0, 51.0f / 255.0f,
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001701 113.0f / 255.0f),
1702 true)
1703 << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001704 << " " << rcItem.Height() << " " << kAppendRectOperator << " "
1705 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001706 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001707
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001708 AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001709 sList << GetColorAppStream(CFX_Color(CFX_Color::kGray, 1), true)
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001710 << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001711 } else {
1712 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001713
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001714 AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001715 sList << GetColorAppStream(crText, true)
1716 << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001717 }
1718
1719 fy -= fItemHeight;
1720 }
1721
1722 if (sList.tellp() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001723 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001724 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1725 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001726 AutoClosedQCommand q(&sBody);
1727
1728 sBody << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001729 << " " << rcClient.Height() << " " << kAppendRectOperator << "\n"
1730 << kSetNonZeroWindingClipOperator << "\n"
1731 << kEndPathNoFillOrStrokeOperator << "\n"
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001732 << sList.str();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001733 }
1734 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001735 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001736 "");
1737}
1738
Ryan Harrison275e2602017-09-18 14:23:18 -04001739void CPWL_AppStream::SetAsTextField(const WideString* sValue) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001740 CPDF_FormControl* pControl = widget_->GetFormControl();
1741 CPDF_FormField* pField = pControl->GetField();
1742 std::ostringstream sBody;
1743 std::ostringstream sLines;
1744
Tom Sepezae386362018-08-21 23:10:51 +00001745 // Font map must outlive |pEdit|.
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001746 CBA_FontMap font_map(
1747 widget_.Get(),
1748 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
Tom Sepezae386362018-08-21 23:10:51 +00001749
1750 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
1751 pEdit->EnableRefresh(false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001752 pEdit->SetFontMap(&font_map);
1753
1754 CFX_FloatRect rcClient = widget_->GetClientRect();
1755 pEdit->SetPlateRect(rcClient);
1756 pEdit->SetAlignmentH(pControl->GetControlAlignment(), true);
1757
1758 uint32_t dwFieldFlags = pField->GetFieldFlags();
1759 bool bMultiLine = (dwFieldFlags >> 12) & 1;
1760 if (bMultiLine) {
1761 pEdit->SetMultiLine(true, true);
1762 pEdit->SetAutoReturn(true, true);
1763 } else {
1764 pEdit->SetAlignmentV(1, true);
1765 }
1766
1767 uint16_t subWord = 0;
1768 if ((dwFieldFlags >> 13) & 1) {
1769 subWord = '*';
1770 pEdit->SetPasswordChar(subWord, true);
1771 }
1772
1773 int nMaxLen = pField->GetMaxLen();
1774 bool bCharArray = (dwFieldFlags >> 24) & 1;
1775 float fFontSize = widget_->GetFontSize();
1776
1777#ifdef PDF_ENABLE_XFA
Ryan Harrison275e2602017-09-18 14:23:18 -04001778 WideString sValueTmp;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001779 if (!sValue && widget_->GetMixXFAWidget()) {
Tom Sepez5f032992018-06-13 16:14:26 +00001780 sValueTmp = widget_->GetValue();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001781 sValue = &sValueTmp;
1782 }
1783#endif // PDF_ENABLE_XFA
1784
1785 if (nMaxLen > 0) {
1786 if (bCharArray) {
1787 pEdit->SetCharArray(nMaxLen);
1788
1789 if (IsFloatZero(fFontSize)) {
1790 fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0),
1791 rcClient, nMaxLen);
1792 }
1793 } else {
1794 if (sValue)
1795 nMaxLen = sValue->GetLength();
1796 pEdit->SetLimitChar(nMaxLen);
1797 }
1798 }
1799
1800 if (IsFloatZero(fFontSize))
1801 pEdit->SetAutoFontSize(true, true);
1802 else
1803 pEdit->SetFontSize(fFontSize);
1804
1805 pEdit->Initialize();
1806 pEdit->SetText(sValue ? *sValue : pField->GetValue());
1807
1808 CFX_FloatRect rcContent = pEdit->GetContentRect();
Ryan Harrison275e2602017-09-18 14:23:18 -04001809 ByteString sEdit =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001810 GetEditAppStream(pEdit.get(), CFX_PointF(), !bCharArray, subWord);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001811
1812 if (sEdit.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001813 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001814 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1815 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001816 AutoClosedQCommand q(&sBody);
1817
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001818 if (rcContent.Width() > rcClient.Width() ||
1819 rcContent.Height() > rcClient.Height()) {
1820 sBody << rcClient.left << " " << rcClient.bottom << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001821 << rcClient.Width() << " " << rcClient.Height() << " "
1822 << kAppendRectOperator << "\n"
1823 << kSetNonZeroWindingClipOperator << "\n"
1824 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001825 }
1826 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001827
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001828 AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001829 sBody << GetColorAppStream(crText, true) << sEdit;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001830 }
1831
1832 if (bCharArray) {
1833 switch (widget_->GetBorderStyle()) {
1834 case BorderStyle::SOLID: {
Ryan Harrison275e2602017-09-18 14:23:18 -04001835 ByteString sColor =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001836 GetColorAppStream(widget_->GetBorderPWLColor(), false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001837 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001838 AutoClosedQCommand q(&sLines);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001839 sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1840 << "\n"
Dan Sinclair14ddd422017-07-20 11:07:00 -04001841 << GetColorAppStream(widget_->GetBorderPWLColor(), false)
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001842 << " 2 " << kSetLineCapStyleOperator << " 0 "
1843 << kSetLineJoinStyleOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001844
1845 for (int32_t i = 1; i < nMaxLen; ++i) {
1846 sLines << rcClient.left +
1847 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001848 << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001849 << rcClient.left +
1850 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001851 << " " << rcClient.top << " " << kLineToOperator << " "
1852 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001853 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001854 }
1855 break;
1856 }
1857 case BorderStyle::DASH: {
Ryan Harrison275e2602017-09-18 14:23:18 -04001858 ByteString sColor =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001859 GetColorAppStream(widget_->GetBorderPWLColor(), false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001860 if (sColor.GetLength() > 0) {
1861 CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001862 AutoClosedQCommand q(&sLines);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001863 sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1864 << "\n"
Dan Sinclair14ddd422017-07-20 11:07:00 -04001865 << GetColorAppStream(widget_->GetBorderPWLColor(), false)
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001866 << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001867 << dsBorder.nPhase << " " << kSetDashOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001868
1869 for (int32_t i = 1; i < nMaxLen; ++i) {
1870 sLines << rcClient.left +
1871 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001872 << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001873 << rcClient.left +
1874 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001875 << " " << rcClient.top << " " << kLineToOperator << " "
1876 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001877 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001878 }
1879 break;
1880 }
1881 default:
1882 break;
1883 }
1884 }
1885
1886 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001887 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sLines) +
1888 ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001889 "");
1890}
1891
Ryan Harrison275e2602017-09-18 14:23:18 -04001892void CPWL_AppStream::AddImage(const ByteString& sAPType, CPDF_Stream* pImage) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001893 CPDF_Stream* pStream = dict_->GetStreamFor(sAPType);
1894 CPDF_Dictionary* pStreamDict = pStream->GetDict();
Ryan Harrison275e2602017-09-18 14:23:18 -04001895 ByteString sImageAlias = "IMG";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001896
1897 if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
1898 sImageAlias = pImageDict->GetStringFor("Name");
1899 if (sImageAlias.IsEmpty())
1900 sImageAlias = "IMG";
1901 }
1902
1903 CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
1904 if (!pStreamResList)
1905 pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
1906
1907 CPDF_Dictionary* pXObject =
1908 pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
Artem Stryginfb727262018-06-11 18:19:57 +00001909 pXObject->SetFor(sImageAlias, pImage->MakeReference(
1910 widget_->GetPageView()->GetPDFDocument()));
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001911}
1912
Ryan Harrison275e2602017-09-18 14:23:18 -04001913void CPWL_AppStream::Write(const ByteString& sAPType,
1914 const ByteString& sContents,
1915 const ByteString& sAPState) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001916 CPDF_Stream* pStream = nullptr;
1917 CPDF_Dictionary* pParentDict = nullptr;
1918 if (sAPState.IsEmpty()) {
1919 pParentDict = dict_.Get();
1920 pStream = dict_->GetStreamFor(sAPType);
1921 } else {
1922 CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType);
1923 if (!pAPTypeDict)
1924 pAPTypeDict = dict_->SetNewFor<CPDF_Dictionary>(sAPType);
1925
1926 pParentDict = pAPTypeDict;
1927 pStream = pAPTypeDict->GetStreamFor(sAPState);
1928 }
1929
1930 if (!pStream) {
1931 CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument();
1932 pStream = doc->NewIndirect<CPDF_Stream>();
Artem Stryginfb727262018-06-11 18:19:57 +00001933 pParentDict->SetFor(sAPType, pStream->MakeReference(doc));
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001934 }
1935
1936 CPDF_Dictionary* pStreamDict = pStream->GetDict();
1937 if (!pStreamDict) {
1938 auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>(
1939 widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool());
1940 pStreamDict = pNewDict.get();
1941 pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
1942 pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
1943 pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
Tom Sepez367ed462018-08-23 23:52:53 +00001944 pStream->InitStream({}, std::move(pNewDict));
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001945 }
1946 pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix());
1947 pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect());
Tom Sepez367ed462018-08-23 23:52:53 +00001948 pStream->SetDataAndRemoveFilter(sContents.AsRawSpan());
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001949}
1950
Ryan Harrison275e2602017-09-18 14:23:18 -04001951void CPWL_AppStream::Remove(const ByteString& sAPType) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001952 dict_->RemoveFor(sAPType);
1953}
1954
Ryan Harrison275e2602017-09-18 14:23:18 -04001955ByteString CPWL_AppStream::GetBackgroundAppStream() const {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001956 CFX_Color crBackground = widget_->GetFillPWLColor();
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001957 if (crBackground.nColorType != CFX_Color::kTransparent)
Dan Sinclair14ddd422017-07-20 11:07:00 -04001958 return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001959
Ryan Harrison275e2602017-09-18 14:23:18 -04001960 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001961}
1962
Ryan Harrison275e2602017-09-18 14:23:18 -04001963ByteString CPWL_AppStream::GetBorderAppStream() const {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001964 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1965 CFX_Color crBorder = widget_->GetBorderPWLColor();
1966 CFX_Color crBackground = widget_->GetFillPWLColor();
1967 CFX_Color crLeftTop;
1968 CFX_Color crRightBottom;
1969
1970 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1971 CPWL_Dash dsBorder(3, 0, 0);
1972
1973 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1974 switch (nBorderStyle) {
1975 case BorderStyle::DASH:
1976 dsBorder = CPWL_Dash(3, 3, 0);
1977 break;
1978 case BorderStyle::BEVELED:
1979 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001980 crLeftTop = CFX_Color(CFX_Color::kGray, 1);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001981 crRightBottom = crBackground / 2.0f;
1982 break;
1983 case BorderStyle::INSET:
1984 fBorderWidth *= 2;
Dan Sinclair8e7f9322017-10-16 11:35:42 -04001985 crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
1986 crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001987 break;
1988 default:
1989 break;
1990 }
1991
Dan Sinclair14ddd422017-07-20 11:07:00 -04001992 return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1993 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001994}