blob: 7d7f172f2f2560ef85ce3c15fee7684aabb9553e [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"
Dan Sinclaircb2ea422017-07-19 15:24:49 -040029
30namespace {
31
Dan Sinclair14ddd422017-07-20 11:07:00 -040032// Checkbox & radiobutton styles.
33enum class CheckStyle { kCheck = 0, kCircle, kCross, kDiamond, kSquare, kStar };
34
35// Pushbutton layout styles.
36enum class ButtonStyle {
37 kLabel = 0,
38 kIcon,
39 kIconTopLabelBottom,
40 kIconBottomLabelTop,
41 kIconLeftLabelRight,
42 kIconRightLabelLeft,
43 kLabelOverIcon
44};
45
Dan Sinclairbeef5e42017-07-24 10:32:05 -040046const char kAppendRectOperator[] = "re";
47const char kConcatMatrixOperator[] = "cm";
48const char kCurveToOperator[] = "c";
49const char kEndPathNoFillOrStrokeOperator[] = "n";
50const char kFillOperator[] = "f";
51const char kFillEvenOddOperator[] = "f*";
52const char kInvokeNamedXObjectOperator[] = "Do";
53const char kLineToOperator[] = "l";
54const char kMarkedSequenceBeginOperator[] = "BMC";
55const char kMarkedSequenceEndOperator[] = "EMC";
56const char kMoveTextPositionOperator[] = "Td";
57const char kMoveToOperator[] = "m";
58const char kSetCharacterSpacingOperator[] = "Tc";
59const char kSetCMYKOperator[] = "k";
60const char kSetCMKYStrokedOperator[] = "K";
61const char kSetDashOperator[] = "d";
62const char kSetGrayOperator[] = "g";
63const char kSetGrayStrokedOperator[] = "G";
64const char kSetLineCapStyleOperator[] = "J";
65const char kSetLineJoinStyleOperator[] = "j";
66const char kSetLineWidthOperator[] = "w";
67const char kSetNonZeroWindingClipOperator[] = "W";
68const char kSetRGBOperator[] = "rg";
69const char kSetRGBStrokedOperator[] = "RG";
70const char kSetTextFontAndSizeOperator[] = "Tf";
71const char kSetTextScaleHorizontalOperator[] = "Tz";
72const 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
95class AutoClosedQCommand : public AutoClosedCommand {
96 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) {
107 case COLORTYPE_RGB:
108 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;
113 case COLORTYPE_GRAY:
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;
119 case COLORTYPE_CMYK:
120 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) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400132 const float fWidth = crBBox.right - crBBox.left;
133 const float fHeight = crBBox.top - crBBox.bottom;
134
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
183 float fWidth = crBBox.right - crBBox.left;
184 float fHeight = crBBox.top - crBBox.bottom;
185
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
239 float fWidth = crBBox.right - crBBox.left;
240 float fHeight = crBBox.top - crBBox.bottom;
241
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
301 float fWidth = crBBox.right - crBBox.left;
302 float fHeight = crBBox.top - crBBox.bottom;
303
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:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400517 rcCenter.Scale(2.0f / 3.0f);
518 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:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400522 rcCenter.Scale(2.0f / 3.0f);
523 return GetAppStream_Diamond(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400524 case CheckStyle::kSquare:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400525 rcCenter.Scale(2.0f / 3.0f);
526 return GetAppStream_Square(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400527 case CheckStyle::kStar:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400528 rcCenter.Scale(2.0f / 3.0f);
529 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:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400542 rcCenter.Scale(1.0f / 2.0f);
543 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:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400547 rcCenter.Scale(2.0f / 3.0f);
548 return GetAppStream_Diamond(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400549 case CheckStyle::kSquare:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400550 rcCenter.Scale(2.0f / 3.0f);
551 return GetAppStream_Square(rcCenter, crText);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400552 case CheckStyle::kStar:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400553 rcCenter.Scale(2.0f / 3.0f);
554 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) {
670 int32_t nHorzScale = pEdit->GetHorzScale();
671 if (nHorzScale != 100) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400672 sAppStream << nHorzScale << " " << kSetTextScaleHorizontalOperator
673 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400674 }
675
676 float fCharSpace = pEdit->GetCharSpace();
677 if (!IsFloatZero(fCharSpace)) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400678 sAppStream << fCharSpace << " " << kSetCharacterSpacingOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400679 }
680
681 sAppStream << sEditStream.str();
682 }
683
Ryan Harrison275e2602017-09-18 14:23:18 -0400684 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400685}
686
Ryan Harrison275e2602017-09-18 14:23:18 -0400687ByteString GenerateIconAppStream(CPDF_IconFit& fit,
688 CPDF_Stream* pIconStream,
689 const CFX_FloatRect& rcIcon) {
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400690 if (rcIcon.IsEmpty() || !pIconStream)
Ryan Harrison275e2602017-09-18 14:23:18 -0400691 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400692
693 CPWL_Icon icon;
Tom Sepezbf157302017-09-15 13:26:32 -0700694 CPWL_Wnd::CreateParams cp;
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400695 cp.dwFlags = PWS_VISIBLE;
696 icon.Create(cp);
697 icon.SetIconFit(&fit);
698 icon.SetPDFStream(pIconStream);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400699 if (!icon.Move(rcIcon, false, false))
700 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400701
Ryan Harrison275e2602017-09-18 14:23:18 -0400702 ByteString sAlias = icon.GetImageAlias();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400703 if (sAlias.GetLength() <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400704 return ByteString();
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400705
706 CFX_FloatRect rcPlate = icon.GetClientRect();
707 CFX_Matrix mt = icon.GetImageMatrix().GetInverse();
708
709 float fHScale;
710 float fVScale;
711 std::tie(fHScale, fVScale) = icon.GetScale();
712
713 float fx;
714 float fy;
715 std::tie(fx, fy) = icon.GetImageOffset();
716
717 std::ostringstream str;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400718 {
719 AutoClosedQCommand q(&str);
720 str << rcPlate.left << " " << rcPlate.bottom << " "
721 << rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400722 << " " << kAppendRectOperator << " " << kSetNonZeroWindingClipOperator
723 << " " << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400724
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400725 str << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400726 << rcPlate.bottom + fy << " " << kConcatMatrixOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400727 str << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " " << mt.e
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400728 << " " << mt.f << " " << kConcatMatrixOperator << "\n";
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400729
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400730 str << "0 " << kSetGrayOperator << " 0 " << kSetGrayStrokedOperator << " 1 "
731 << kSetLineWidthOperator << " /" << sAlias << " "
732 << kInvokeNamedXObjectOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400733 }
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400734 icon.Destroy();
735
Ryan Harrison275e2602017-09-18 14:23:18 -0400736 return ByteString(str);
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400737}
738
Ryan Harrison275e2602017-09-18 14:23:18 -0400739ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
740 IPVT_FontMap* pFontMap,
741 CPDF_Stream* pIconStream,
742 CPDF_IconFit& IconFit,
743 const WideString& sLabel,
744 const CFX_Color& crText,
745 float fFontSize,
746 ButtonStyle nLayOut) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400747 const float fAutoFontScale = 1.0f / 3.0f;
748
Dan Sinclair6b0158f2017-07-24 09:42:55 -0400749 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400750 pEdit->SetFontMap(pFontMap);
751 pEdit->SetAlignmentH(1, true);
752 pEdit->SetAlignmentV(1, true);
753 pEdit->SetMultiLine(false, true);
754 pEdit->SetAutoReturn(false, true);
755 if (IsFloatZero(fFontSize))
756 pEdit->SetAutoFontSize(true, true);
757 else
758 pEdit->SetFontSize(fFontSize);
759
760 pEdit->Initialize();
761 pEdit->SetText(sLabel);
762
763 CFX_FloatRect rcLabelContent = pEdit->GetContentRect();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400764 CFX_FloatRect rcLabel;
765 CFX_FloatRect rcIcon;
766 float fWidth = 0.0f;
767 float fHeight = 0.0f;
768
769 switch (nLayOut) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400770 case ButtonStyle::kLabel:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400771 rcLabel = rcBBox;
772 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400773 case ButtonStyle::kIcon:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400774 rcIcon = rcBBox;
775 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400776 case ButtonStyle::kIconTopLabelBottom:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400777 if (pIconStream) {
778 if (IsFloatZero(fFontSize)) {
779 fHeight = rcBBox.top - rcBBox.bottom;
780 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
781 rcBBox.bottom + fHeight * fAutoFontScale);
782 rcIcon =
783 CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top);
784 } else {
785 fHeight = rcLabelContent.Height();
786
787 if (rcBBox.bottom + fHeight > rcBBox.top) {
788 rcLabel = rcBBox;
789 } else {
790 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
791 rcBBox.bottom + fHeight);
792 rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right,
793 rcBBox.top);
794 }
795 }
796 } else {
797 rcLabel = rcBBox;
798 }
799 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400800 case ButtonStyle::kIconBottomLabelTop:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400801 if (pIconStream) {
802 if (IsFloatZero(fFontSize)) {
803 fHeight = rcBBox.top - rcBBox.bottom;
804 rcLabel =
805 CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale,
806 rcBBox.right, rcBBox.top);
807 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
808 rcLabel.bottom);
809 } else {
810 fHeight = rcLabelContent.Height();
811
812 if (rcBBox.bottom + fHeight > rcBBox.top) {
813 rcLabel = rcBBox;
814 } else {
815 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight,
816 rcBBox.right, rcBBox.top);
817 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
818 rcLabel.bottom);
819 }
820 }
821 } else {
822 rcLabel = rcBBox;
823 }
824 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400825 case ButtonStyle::kIconLeftLabelRight:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400826 if (pIconStream) {
827 if (IsFloatZero(fFontSize)) {
828 fWidth = rcBBox.right - rcBBox.left;
829 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
830 rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale,
831 rcBBox.bottom, rcBBox.right, rcBBox.top);
832 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
833 rcBBox.top);
834 } else {
835 if (rcLabelContent.Width() < fWidth) {
836 rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(),
837 rcBBox.bottom, rcBBox.right, rcBBox.top);
838 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
839 rcBBox.top);
840 } else {
841 rcLabel = rcBBox;
842 }
843 }
844 } else {
845 fWidth = rcLabelContent.Width();
846 if (rcBBox.left + fWidth > rcBBox.right) {
847 rcLabel = rcBBox;
848 } else {
849 rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom,
850 rcBBox.right, rcBBox.top);
851 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
852 rcBBox.top);
853 }
854 }
855 } else {
856 rcLabel = rcBBox;
857 }
858 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400859 case ButtonStyle::kIconRightLabelLeft:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400860 if (pIconStream) {
861 if (IsFloatZero(fFontSize)) {
862 fWidth = rcBBox.right - rcBBox.left;
863 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
864 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
865 rcBBox.left + fWidth * fAutoFontScale,
866 rcBBox.top);
867 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
868 rcBBox.top);
869 } else {
870 if (rcLabelContent.Width() < fWidth) {
871 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
872 rcBBox.left + rcLabelContent.Width(),
873 rcBBox.top);
874 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
875 rcBBox.top);
876 } else {
877 rcLabel = rcBBox;
878 }
879 }
880 } else {
881 fWidth = rcLabelContent.Width();
882 if (rcBBox.left + fWidth > rcBBox.right) {
883 rcLabel = rcBBox;
884 } else {
885 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
886 rcBBox.left + fWidth, rcBBox.top);
887 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
888 rcBBox.top);
889 }
890 }
891 } else {
892 rcLabel = rcBBox;
893 }
894 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400895 case ButtonStyle::kLabelOverIcon:
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400896 rcLabel = rcBBox;
897 rcIcon = rcBBox;
898 break;
899 }
900
901 std::ostringstream sTemp;
Dan Sinclairdc11ec82017-07-20 11:08:03 -0400902 sTemp << GenerateIconAppStream(IconFit, pIconStream, rcIcon);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400903
904 if (!rcLabel.IsEmpty()) {
905 pEdit->SetPlateRect(rcLabel);
Ryan Harrison275e2602017-09-18 14:23:18 -0400906 ByteString sEdit =
Dan Sinclair14ddd422017-07-20 11:07:00 -0400907 GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f), true, 0);
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400908 if (sEdit.GetLength() > 0) {
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400909 AutoClosedCommand bt(&sTemp, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400910 sTemp << GetColorAppStream(crText, true) << sEdit;
911 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400912 }
913
914 if (sTemp.tellp() <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400915 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400916
917 std::ostringstream sAppStream;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400918 {
919 AutoClosedQCommand q(&sAppStream);
920 sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
921 << rcBBox.right - rcBBox.left << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400922 << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator
923 << " " << kSetNonZeroWindingClipOperator << " "
924 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400925 sAppStream << sTemp.str().c_str();
926 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400927 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -0400928}
929
Ryan Harrison275e2602017-09-18 14:23:18 -0400930ByteString GetBorderAppStreamInternal(const CFX_FloatRect& rect,
931 float fWidth,
932 const CFX_Color& color,
933 const CFX_Color& crLeftTop,
934 const CFX_Color& crRightBottom,
935 BorderStyle nStyle,
936 const CPWL_Dash& dash) {
Dan Sinclair14ddd422017-07-20 11:07:00 -0400937 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -0400938 ByteString sColor;
Dan Sinclair14ddd422017-07-20 11:07:00 -0400939
940 float fLeft = rect.left;
941 float fRight = rect.right;
942 float fTop = rect.top;
943 float fBottom = rect.bottom;
944
945 if (fWidth > 0.0f) {
946 float fHalfWidth = fWidth / 2.0f;
Dan Sinclaire03f8b12017-07-20 11:08:21 -0400947 AutoClosedQCommand q(&sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -0400948
949 switch (nStyle) {
950 default:
951 case BorderStyle::SOLID:
952 sColor = GetColorAppStream(color, true);
953 if (sColor.GetLength() > 0) {
954 sAppStream << sColor;
955 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400956 << fTop - fBottom << " " << kAppendRectOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400957 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
958 << fRight - fLeft - fWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400959 << fTop - fBottom - fWidth * 2 << " "
960 << kAppendRectOperator << "\n";
961 sAppStream << kFillEvenOddOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400962 }
963 break;
964 case BorderStyle::DASH:
965 sColor = GetColorAppStream(color, false);
966 if (sColor.GetLength() > 0) {
967 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400968 sAppStream << fWidth << " " << kSetLineWidthOperator << " ["
969 << dash.nDash << " " << dash.nGap << "] " << dash.nPhase
970 << " " << kSetDashOperator << "\n";
971 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
972 << kMoveToOperator << "\n";
973 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " "
974 << kLineToOperator << "\n";
975 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " "
976 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400977 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400978 << " " << kLineToOperator << "\n";
979 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
980 << kLineToOperator << " " << kStrokeOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400981 }
982 break;
983 case BorderStyle::BEVELED:
984 case BorderStyle::INSET:
985 sColor = GetColorAppStream(crLeftTop, true);
986 if (sColor.GetLength() > 0) {
987 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400988 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
989 << kMoveToOperator << "\n";
990 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " "
991 << kLineToOperator << "\n";
992 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
993 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400994 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400995 << " " << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400996 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400997 << " " << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -0400998 sAppStream << fLeft + fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -0400999 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
1000 << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001001 }
1002
1003 sColor = GetColorAppStream(crRightBottom, true);
1004 if (sColor.GetLength() > 0) {
1005 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001006 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
1007 << kMoveToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001008 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001009 << " " << kLineToOperator << "\n";
1010 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
1011 << kLineToOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001012 sAppStream << fLeft + fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001013 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
1014 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001015 sAppStream << fRight - fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001016 << fBottom + fHalfWidth * 2 << " " << kLineToOperator
1017 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001018 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001019 << " " << kLineToOperator << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001020 }
1021
1022 sColor = GetColorAppStream(color, true);
1023 if (sColor.GetLength() > 0) {
1024 sAppStream << sColor;
1025 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001026 << fTop - fBottom << " " << kAppendRectOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001027 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
1028 << fRight - fLeft - fHalfWidth * 2 << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001029 << fTop - fBottom - fHalfWidth * 2 << " "
1030 << kAppendRectOperator << " " << kFillEvenOddOperator
1031 << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001032 }
1033 break;
1034 case BorderStyle::UNDERLINE:
1035 sColor = GetColorAppStream(color, false);
1036 if (sColor.GetLength() > 0) {
1037 sAppStream << sColor;
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001038 sAppStream << fWidth << " " << kSetLineWidthOperator << "\n";
1039 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " "
1040 << kMoveToOperator << "\n";
1041 sAppStream << fRight << " " << fBottom + fWidth / 2 << " "
1042 << kLineToOperator << " " << kStrokeOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001043 }
1044 break;
1045 }
Dan Sinclair14ddd422017-07-20 11:07:00 -04001046 }
1047
Ryan Harrison275e2602017-09-18 14:23:18 -04001048 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001049}
1050
Ryan Harrison275e2602017-09-18 14:23:18 -04001051ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001052 if (rcBBox.IsEmpty())
Ryan Harrison275e2602017-09-18 14:23:18 -04001053 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001054
1055 std::ostringstream sAppStream;
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001056 {
1057 AutoClosedQCommand q(&sAppStream);
1058 sAppStream << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 220.0f / 255.0f,
1059 220.0f / 255.0f, 220.0f / 255.0f),
1060 true)
1061 << rcBBox.left << " " << rcBBox.bottom << " "
1062 << rcBBox.right - rcBBox.left << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001063 << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator
1064 << " " << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001065 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001066
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001067 {
1068 AutoClosedQCommand q(&sAppStream);
1069 sAppStream << GetBorderAppStreamInternal(
1070 rcBBox, 2, CFX_Color(COLORTYPE_GRAY, 0), CFX_Color(COLORTYPE_GRAY, 1),
1071 CFX_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED,
1072 CPWL_Dash(3, 0, 0));
1073 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001074
1075 CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2,
1076 (rcBBox.top + rcBBox.bottom) / 2);
1077 if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) &&
1078 IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001079 AutoClosedQCommand q(&sAppStream);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001080 sAppStream << " 0 " << kSetGrayOperator << "\n"
1081 << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
1082 << kMoveToOperator << "\n"
1083 << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " "
1084 << kLineToOperator << "\n"
1085 << ptCenter.x << " " << ptCenter.y - 1.5f << " "
1086 << kLineToOperator << "\n"
1087 << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
1088 << kLineToOperator << " " << kFillOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001089 }
1090
Ryan Harrison275e2602017-09-18 14:23:18 -04001091 return ByteString(sAppStream);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001092}
1093
Ryan Harrison275e2602017-09-18 14:23:18 -04001094ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
1095 const CFX_Color& color) {
Dan Sinclair14ddd422017-07-20 11:07:00 -04001096 std::ostringstream sAppStream;
Ryan Harrison275e2602017-09-18 14:23:18 -04001097 ByteString sColor = GetColorAppStream(color, true);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001098 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001099 AutoClosedQCommand q(&sAppStream);
1100 sAppStream << sColor << rect.left << " " << rect.bottom << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001101 << rect.right - rect.left << " " << rect.top - rect.bottom << " "
1102 << kAppendRectOperator << " " << kFillOperator << "\n";
Dan Sinclair14ddd422017-07-20 11:07:00 -04001103 }
1104
Ryan Harrison275e2602017-09-18 14:23:18 -04001105 return ByteString(sAppStream);
Dan Sinclair14ddd422017-07-20 11:07:00 -04001106}
1107
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001108} // namespace
1109
1110CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict)
1111 : widget_(widget), dict_(dict) {}
1112
1113CPWL_AppStream::~CPWL_AppStream() {}
1114
1115void CPWL_AppStream::SetAsPushButton() {
1116 CPDF_FormControl* pControl = widget_->GetFormControl();
1117 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
Dan Sinclair14ddd422017-07-20 11:07:00 -04001118 ButtonStyle nLayout = ButtonStyle::kLabel;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001119 switch (pControl->GetTextPosition()) {
1120 case TEXTPOS_ICON:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001121 nLayout = ButtonStyle::kIcon;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001122 break;
1123 case TEXTPOS_BELOW:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001124 nLayout = ButtonStyle::kIconTopLabelBottom;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001125 break;
1126 case TEXTPOS_ABOVE:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001127 nLayout = ButtonStyle::kIconBottomLabelTop;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001128 break;
1129 case TEXTPOS_RIGHT:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001130 nLayout = ButtonStyle::kIconLeftLabelRight;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001131 break;
1132 case TEXTPOS_LEFT:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001133 nLayout = ButtonStyle::kIconRightLabelLeft;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001134 break;
1135 case TEXTPOS_OVERLAID:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001136 nLayout = ButtonStyle::kLabelOverIcon;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001137 break;
1138 default:
Dan Sinclair14ddd422017-07-20 11:07:00 -04001139 nLayout = ButtonStyle::kLabel;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001140 break;
1141 }
1142
1143 CFX_Color crBackground;
1144 CFX_Color crBorder;
1145 int iColorType;
1146 float fc[4];
1147 pControl->GetOriginalBackgroundColor(iColorType, fc);
1148 if (iColorType > 0)
1149 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1150
1151 pControl->GetOriginalBorderColor(iColorType, fc);
1152 if (iColorType > 0)
1153 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1154
1155 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1156 CPWL_Dash dsBorder(3, 0, 0);
1157 CFX_Color crLeftTop;
1158 CFX_Color crRightBottom;
1159
1160 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1161 switch (nBorderStyle) {
1162 case BorderStyle::DASH:
1163 dsBorder = CPWL_Dash(3, 3, 0);
1164 break;
1165 case BorderStyle::BEVELED:
1166 fBorderWidth *= 2;
1167 crLeftTop = CFX_Color(COLORTYPE_GRAY, 1);
1168 crRightBottom = crBackground / 2.0f;
1169 break;
1170 case BorderStyle::INSET:
1171 fBorderWidth *= 2;
1172 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5);
1173 crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75);
1174 break;
1175 default:
1176 break;
1177 }
1178
1179 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1180 CFX_Color crText(COLORTYPE_GRAY, 0);
Ryan Harrison275e2602017-09-18 14:23:18 -04001181 ByteString csNameTag;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001182 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1183 if (da.HasColor()) {
1184 da.GetColor(iColorType, fc);
1185 crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1186 }
1187 float fFontSize = 12.0f;
1188 if (da.HasFont())
1189 csNameTag = da.GetFont(&fFontSize);
1190
Ryan Harrison275e2602017-09-18 14:23:18 -04001191 WideString csWCaption;
1192 WideString csNormalCaption;
1193 WideString csRolloverCaption;
1194 WideString csDownCaption;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001195 if (pControl->HasMKEntry("CA"))
1196 csNormalCaption = pControl->GetNormalCaption();
1197
1198 if (pControl->HasMKEntry("RC"))
1199 csRolloverCaption = pControl->GetRolloverCaption();
1200
1201 if (pControl->HasMKEntry("AC"))
1202 csDownCaption = pControl->GetDownCaption();
1203
1204 CPDF_Stream* pNormalIcon = nullptr;
1205 CPDF_Stream* pRolloverIcon = nullptr;
1206 CPDF_Stream* pDownIcon = nullptr;
1207 if (pControl->HasMKEntry("I"))
1208 pNormalIcon = pControl->GetNormalIcon();
1209
1210 if (pControl->HasMKEntry("RI"))
1211 pRolloverIcon = pControl->GetRolloverIcon();
1212
1213 if (pControl->HasMKEntry("IX"))
1214 pDownIcon = pControl->GetDownIcon();
1215
1216 if (pNormalIcon) {
1217 if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) {
1218 if (pImageDict->GetStringFor("Name").IsEmpty())
1219 pImageDict->SetNewFor<CPDF_String>("Name", "ImgA", false);
1220 }
1221 }
1222
1223 if (pRolloverIcon) {
1224 if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
1225 if (pImageDict->GetStringFor("Name").IsEmpty())
1226 pImageDict->SetNewFor<CPDF_String>("Name", "ImgB", false);
1227 }
1228 }
1229
1230 if (pDownIcon) {
1231 if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
1232 if (pImageDict->GetStringFor("Name").IsEmpty())
1233 pImageDict->SetNewFor<CPDF_String>("Name", "ImgC", false);
1234 }
1235 }
1236
1237 CPDF_IconFit iconFit = pControl->GetIconFit();
1238
1239 CBA_FontMap font_map(
1240 widget_.Get(),
1241 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
1242 font_map.SetAPType("N");
1243
Ryan Harrison275e2602017-09-18 14:23:18 -04001244 ByteString csAP =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001245 GetRectFillAppStream(rcWindow, crBackground) +
1246 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1247 crRightBottom, nBorderStyle, dsBorder) +
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001248 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1249 &font_map, pNormalIcon, iconFit, csNormalCaption,
1250 crText, fFontSize, nLayout);
1251
1252 Write("N", csAP, "");
1253 if (pNormalIcon)
1254 AddImage("N", pNormalIcon);
1255
1256 CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode();
1257 if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) {
1258 if (csRolloverCaption.IsEmpty() && !pRolloverIcon) {
1259 csRolloverCaption = csNormalCaption;
1260 pRolloverIcon = pNormalIcon;
1261 }
1262
1263 font_map.SetAPType("R");
1264
1265 csAP =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001266 GetRectFillAppStream(rcWindow, crBackground) +
1267 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1268 crRightBottom, nBorderStyle, dsBorder) +
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001269 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1270 &font_map, pRolloverIcon, iconFit,
1271 csRolloverCaption, crText, fFontSize, nLayout);
1272
1273 Write("R", csAP, "");
1274 if (pRolloverIcon)
1275 AddImage("R", pRolloverIcon);
1276
1277 if (csDownCaption.IsEmpty() && !pDownIcon) {
1278 csDownCaption = csNormalCaption;
1279 pDownIcon = pNormalIcon;
1280 }
1281
1282 switch (nBorderStyle) {
1283 case BorderStyle::BEVELED: {
1284 CFX_Color crTemp = crLeftTop;
1285 crLeftTop = crRightBottom;
1286 crRightBottom = crTemp;
1287 break;
1288 }
1289 case BorderStyle::INSET: {
1290 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0);
1291 crRightBottom = CFX_Color(COLORTYPE_GRAY, 1);
1292 break;
1293 }
1294 default:
1295 break;
1296 }
1297
1298 font_map.SetAPType("D");
1299
Dan Sinclair14ddd422017-07-20 11:07:00 -04001300 csAP =
1301 GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1302 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1303 crRightBottom, nBorderStyle, dsBorder) +
1304 GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient,
1305 &font_map, pDownIcon, iconFit, csDownCaption,
1306 crText, fFontSize, nLayout);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001307
1308 Write("D", csAP, "");
1309 if (pDownIcon)
1310 AddImage("D", pDownIcon);
1311 } else {
1312 Remove("D");
1313 Remove("R");
1314 }
1315}
1316
1317void CPWL_AppStream::SetAsCheckBox() {
1318 CPDF_FormControl* pControl = widget_->GetFormControl();
1319 CFX_Color crBackground, crBorder, crText;
1320 int iColorType;
1321 float fc[4];
1322
1323 pControl->GetOriginalBackgroundColor(iColorType, fc);
1324 if (iColorType > 0)
1325 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1326
1327 pControl->GetOriginalBorderColor(iColorType, fc);
1328 if (iColorType > 0)
1329 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1330
1331 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1332 CPWL_Dash dsBorder(3, 0, 0);
1333 CFX_Color crLeftTop, crRightBottom;
1334
1335 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1336 switch (nBorderStyle) {
1337 case BorderStyle::DASH:
1338 dsBorder = CPWL_Dash(3, 3, 0);
1339 break;
1340 case BorderStyle::BEVELED:
1341 fBorderWidth *= 2;
1342 crLeftTop = CFX_Color(COLORTYPE_GRAY, 1);
1343 crRightBottom = crBackground / 2.0f;
1344 break;
1345 case BorderStyle::INSET:
1346 fBorderWidth *= 2;
1347 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5);
1348 crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75);
1349 break;
1350 default:
1351 break;
1352 }
1353
1354 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1355 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1356 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1357 if (da.HasColor()) {
1358 da.GetColor(iColorType, fc);
1359 crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1360 }
1361
Dan Sinclair14ddd422017-07-20 11:07:00 -04001362 CheckStyle nStyle = CheckStyle::kCheck;
Ryan Harrison275e2602017-09-18 14:23:18 -04001363 WideString csWCaption = pControl->GetNormalCaption();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001364 if (csWCaption.GetLength() > 0) {
1365 switch (csWCaption[0]) {
1366 case L'l':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001367 nStyle = CheckStyle::kCircle;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001368 break;
1369 case L'8':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001370 nStyle = CheckStyle::kCross;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001371 break;
1372 case L'u':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001373 nStyle = CheckStyle::kDiamond;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001374 break;
1375 case L'n':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001376 nStyle = CheckStyle::kSquare;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001377 break;
1378 case L'H':
Dan Sinclair14ddd422017-07-20 11:07:00 -04001379 nStyle = CheckStyle::kStar;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001380 break;
Dan Sinclair14ddd422017-07-20 11:07:00 -04001381 case L'4':
1382 default:
1383 nStyle = CheckStyle::kCheck;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001384 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001385 }
1386
Ryan Harrison275e2602017-09-18 14:23:18 -04001387 ByteString csAP_N_ON =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001388 GetRectFillAppStream(rcWindow, crBackground) +
1389 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1390 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001391
Ryan Harrison275e2602017-09-18 14:23:18 -04001392 ByteString csAP_N_OFF = csAP_N_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001393
1394 switch (nBorderStyle) {
1395 case BorderStyle::BEVELED: {
1396 CFX_Color crTemp = crLeftTop;
1397 crLeftTop = crRightBottom;
1398 crRightBottom = crTemp;
1399 break;
1400 }
1401 case BorderStyle::INSET: {
1402 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0);
1403 crRightBottom = CFX_Color(COLORTYPE_GRAY, 1);
1404 break;
1405 }
1406 default:
1407 break;
1408 }
1409
Ryan Harrison275e2602017-09-18 14:23:18 -04001410 ByteString csAP_D_ON =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001411 GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
1412 GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1413 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001414
Ryan Harrison275e2602017-09-18 14:23:18 -04001415 ByteString csAP_D_OFF = csAP_D_ON;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001416
1417 csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1418 csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText);
1419
1420 Write("N", csAP_N_ON, pControl->GetCheckedAPState());
1421 Write("N", csAP_N_OFF, "Off");
1422
1423 Write("D", csAP_D_ON, pControl->GetCheckedAPState());
1424 Write("D", csAP_D_OFF, "Off");
1425
Ryan Harrison275e2602017-09-18 14:23:18 -04001426 ByteString csAS = widget_->GetAppState();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001427 if (csAS.IsEmpty())
1428 widget_->SetAppState("Off");
1429}
1430
1431void CPWL_AppStream::SetAsRadioButton() {
1432 CPDF_FormControl* pControl = widget_->GetFormControl();
1433 CFX_Color crBackground;
1434 CFX_Color crBorder;
1435 CFX_Color crText;
1436 int iColorType;
1437 float fc[4];
1438
1439 pControl->GetOriginalBackgroundColor(iColorType, fc);
1440 if (iColorType > 0)
1441 crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1442
1443 pControl->GetOriginalBorderColor(iColorType, fc);
1444 if (iColorType > 0)
1445 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1446
1447 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1448 CPWL_Dash dsBorder(3, 0, 0);
1449 CFX_Color crLeftTop;
1450 CFX_Color crRightBottom;
1451 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1452 switch (nBorderStyle) {
1453 case BorderStyle::DASH:
1454 dsBorder = CPWL_Dash(3, 3, 0);
1455 break;
1456 case BorderStyle::BEVELED:
1457 fBorderWidth *= 2;
1458 crLeftTop = CFX_Color(COLORTYPE_GRAY, 1);
1459 crRightBottom = crBackground / 2.0f;
1460 break;
1461 case BorderStyle::INSET:
1462 fBorderWidth *= 2;
1463 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5);
1464 crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75);
1465 break;
1466 default:
1467 break;
1468 }
1469
1470 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1471 CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
1472 CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1473 if (da.HasColor()) {
1474 da.GetColor(iColorType, fc);
1475 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) {
1507 crLeftTop = CFX_Color(COLORTYPE_GRAY, 1);
1508 crRightBottom = crBackground - 0.25f;
1509 } else if (nBorderStyle == BorderStyle::INSET) {
1510 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5f);
1511 crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75f);
1512 }
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: {
1535 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0);
1536 crRightBottom = CFX_Color(COLORTYPE_GRAY, 1);
1537 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;
1549 crRightBottom = CFX_Color(COLORTYPE_GRAY, 1);
1550 crBK = crBackground;
1551 } else if (nBorderStyle == BorderStyle::INSET) {
1552 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0);
1553 crRightBottom = CFX_Color(COLORTYPE_GRAY, 1);
1554 }
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
Dan Sinclair6b0158f2017-07-24 09:42:55 -04001593 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001594 pEdit->EnableRefresh(false);
1595
1596 CBA_FontMap font_map(
1597 widget_.Get(),
1598 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
1599 pEdit->SetFontMap(&font_map);
1600
1601 CFX_FloatRect rcEdit = rcClient;
1602 rcEdit.right = rcButton.left;
1603 rcEdit.Normalize();
1604
1605 pEdit->SetPlateRect(rcEdit);
1606 pEdit->SetAlignmentV(1, true);
1607
1608 float fFontSize = widget_->GetFontSize();
1609 if (IsFloatZero(fFontSize))
1610 pEdit->SetAutoFontSize(true, true);
1611 else
1612 pEdit->SetFontSize(fFontSize);
1613
1614 pEdit->Initialize();
1615
1616 if (sValue) {
1617 pEdit->SetText(*sValue);
1618 } else {
1619 int32_t nCurSel = pField->GetSelectedIndex(0);
1620 if (nCurSel < 0)
1621 pEdit->SetText(pField->GetValue());
1622 else
1623 pEdit->SetText(pField->GetOptionLabel(nCurSel));
1624 }
1625
1626 CFX_FloatRect rcContent = pEdit->GetContentRect();
Ryan Harrison275e2602017-09-18 14:23:18 -04001627 ByteString sEdit = GetEditAppStream(pEdit.get(), CFX_PointF(), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001628 if (sEdit.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001629 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001630 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1631 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001632 AutoClosedQCommand q(&sBody);
1633
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001634 if (rcContent.Width() > rcEdit.Width() ||
1635 rcContent.Height() > rcEdit.Height()) {
1636 sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001637 << " " << rcEdit.Height() << " " << kAppendRectOperator << "\n"
1638 << kSetNonZeroWindingClipOperator << "\n"
1639 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001640 }
1641
1642 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001643 AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001644 sBody << GetColorAppStream(crText, true) << sEdit;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001645 }
1646
1647 sBody << GetDropButtonAppStream(rcButton);
1648 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001649 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001650 "");
1651}
1652
1653void CPWL_AppStream::SetAsListBox() {
1654 CPDF_FormControl* pControl = widget_->GetFormControl();
1655 CPDF_FormField* pField = pControl->GetField();
1656 CFX_FloatRect rcClient = widget_->GetClientRect();
1657 std::ostringstream sBody;
1658
Dan Sinclair6b0158f2017-07-24 09:42:55 -04001659 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001660 pEdit->EnableRefresh(false);
1661
1662 CBA_FontMap font_map(
1663 widget_.Get(),
1664 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
1665 pEdit->SetFontMap(&font_map);
1666 pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f));
1667
1668 float fFontSize = widget_->GetFontSize();
1669 pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize);
1670 pEdit->Initialize();
1671
1672 std::ostringstream sList;
1673 float fy = rcClient.top;
1674
1675 int32_t nTop = pField->GetTopVisibleIndex();
1676 int32_t nCount = pField->CountOptions();
1677 int32_t nSelCount = pField->CountSelectedItems();
1678
1679 for (int32_t i = nTop; i < nCount; ++i) {
1680 bool bSelected = false;
1681 for (int32_t j = 0; j < nSelCount; ++j) {
1682 if (pField->GetSelectedIndex(j) == i) {
1683 bSelected = true;
1684 break;
1685 }
1686 }
1687
1688 pEdit->SetText(pField->GetOptionLabel(i));
1689
1690 CFX_FloatRect rcContent = pEdit->GetContentRect();
1691 float fItemHeight = rcContent.Height();
1692
1693 if (bSelected) {
1694 CFX_FloatRect rcItem =
1695 CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001696 {
1697 AutoClosedQCommand q(&sList);
1698 sList << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f,
1699 113.0f / 255.0f),
1700 true)
1701 << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001702 << " " << rcItem.Height() << " " << kAppendRectOperator << " "
1703 << kFillOperator << "\n";
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001704 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001705
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001706 AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001707 sList << GetColorAppStream(CFX_Color(COLORTYPE_GRAY, 1), true)
1708 << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001709 } else {
1710 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001711
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001712 AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001713 sList << GetColorAppStream(crText, true)
1714 << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001715 }
1716
1717 fy -= fItemHeight;
1718 }
1719
1720 if (sList.tellp() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001721 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001722 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1723 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001724 AutoClosedQCommand q(&sBody);
1725
1726 sBody << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001727 << " " << rcClient.Height() << " " << kAppendRectOperator << "\n"
1728 << kSetNonZeroWindingClipOperator << "\n"
1729 << kEndPathNoFillOrStrokeOperator << "\n"
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001730 << sList.str();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001731 }
1732 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001733 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001734 "");
1735}
1736
Ryan Harrison275e2602017-09-18 14:23:18 -04001737void CPWL_AppStream::SetAsTextField(const WideString* sValue) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001738 CPDF_FormControl* pControl = widget_->GetFormControl();
1739 CPDF_FormField* pField = pControl->GetField();
1740 std::ostringstream sBody;
1741 std::ostringstream sLines;
1742
Dan Sinclair6b0158f2017-07-24 09:42:55 -04001743 auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001744 pEdit->EnableRefresh(false);
1745
1746 CBA_FontMap font_map(
1747 widget_.Get(),
1748 widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
1749 pEdit->SetFontMap(&font_map);
1750
1751 CFX_FloatRect rcClient = widget_->GetClientRect();
1752 pEdit->SetPlateRect(rcClient);
1753 pEdit->SetAlignmentH(pControl->GetControlAlignment(), true);
1754
1755 uint32_t dwFieldFlags = pField->GetFieldFlags();
1756 bool bMultiLine = (dwFieldFlags >> 12) & 1;
1757 if (bMultiLine) {
1758 pEdit->SetMultiLine(true, true);
1759 pEdit->SetAutoReturn(true, true);
1760 } else {
1761 pEdit->SetAlignmentV(1, true);
1762 }
1763
1764 uint16_t subWord = 0;
1765 if ((dwFieldFlags >> 13) & 1) {
1766 subWord = '*';
1767 pEdit->SetPasswordChar(subWord, true);
1768 }
1769
1770 int nMaxLen = pField->GetMaxLen();
1771 bool bCharArray = (dwFieldFlags >> 24) & 1;
1772 float fFontSize = widget_->GetFontSize();
1773
1774#ifdef PDF_ENABLE_XFA
Ryan Harrison275e2602017-09-18 14:23:18 -04001775 WideString sValueTmp;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001776 if (!sValue && widget_->GetMixXFAWidget()) {
1777 sValueTmp = widget_->GetValue(true);
1778 sValue = &sValueTmp;
1779 }
1780#endif // PDF_ENABLE_XFA
1781
1782 if (nMaxLen > 0) {
1783 if (bCharArray) {
1784 pEdit->SetCharArray(nMaxLen);
1785
1786 if (IsFloatZero(fFontSize)) {
1787 fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0),
1788 rcClient, nMaxLen);
1789 }
1790 } else {
1791 if (sValue)
1792 nMaxLen = sValue->GetLength();
1793 pEdit->SetLimitChar(nMaxLen);
1794 }
1795 }
1796
1797 if (IsFloatZero(fFontSize))
1798 pEdit->SetAutoFontSize(true, true);
1799 else
1800 pEdit->SetFontSize(fFontSize);
1801
1802 pEdit->Initialize();
1803 pEdit->SetText(sValue ? *sValue : pField->GetValue());
1804
1805 CFX_FloatRect rcContent = pEdit->GetContentRect();
Ryan Harrison275e2602017-09-18 14:23:18 -04001806 ByteString sEdit =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001807 GetEditAppStream(pEdit.get(), CFX_PointF(), !bCharArray, subWord);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001808
1809 if (sEdit.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001810 sBody << "/Tx ";
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001811 AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
1812 kMarkedSequenceEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001813 AutoClosedQCommand q(&sBody);
1814
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001815 if (rcContent.Width() > rcClient.Width() ||
1816 rcContent.Height() > rcClient.Height()) {
1817 sBody << rcClient.left << " " << rcClient.bottom << " "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001818 << rcClient.Width() << " " << rcClient.Height() << " "
1819 << kAppendRectOperator << "\n"
1820 << kSetNonZeroWindingClipOperator << "\n"
1821 << kEndPathNoFillOrStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001822 }
1823 CFX_Color crText = widget_->GetTextPWLColor();
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001824
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001825 AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001826 sBody << GetColorAppStream(crText, true) << sEdit;
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001827 }
1828
1829 if (bCharArray) {
1830 switch (widget_->GetBorderStyle()) {
1831 case BorderStyle::SOLID: {
Ryan Harrison275e2602017-09-18 14:23:18 -04001832 ByteString sColor =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001833 GetColorAppStream(widget_->GetBorderPWLColor(), false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001834 if (sColor.GetLength() > 0) {
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001835 AutoClosedQCommand q(&sLines);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001836 sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1837 << "\n"
Dan Sinclair14ddd422017-07-20 11:07:00 -04001838 << GetColorAppStream(widget_->GetBorderPWLColor(), false)
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001839 << " 2 " << kSetLineCapStyleOperator << " 0 "
1840 << kSetLineJoinStyleOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001841
1842 for (int32_t i = 1; i < nMaxLen; ++i) {
1843 sLines << rcClient.left +
1844 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001845 << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001846 << rcClient.left +
1847 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001848 << " " << rcClient.top << " " << kLineToOperator << " "
1849 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001850 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001851 }
1852 break;
1853 }
1854 case BorderStyle::DASH: {
Ryan Harrison275e2602017-09-18 14:23:18 -04001855 ByteString sColor =
Dan Sinclair14ddd422017-07-20 11:07:00 -04001856 GetColorAppStream(widget_->GetBorderPWLColor(), false);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001857 if (sColor.GetLength() > 0) {
1858 CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
Dan Sinclaire03f8b12017-07-20 11:08:21 -04001859 AutoClosedQCommand q(&sLines);
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001860 sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
1861 << "\n"
Dan Sinclair14ddd422017-07-20 11:07:00 -04001862 << GetColorAppStream(widget_->GetBorderPWLColor(), false)
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001863 << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001864 << dsBorder.nPhase << " " << kSetDashOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001865
1866 for (int32_t i = 1; i < nMaxLen; ++i) {
1867 sLines << rcClient.left +
1868 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001869 << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001870 << rcClient.left +
1871 ((rcClient.right - rcClient.left) / nMaxLen) * i
Dan Sinclairbeef5e42017-07-24 10:32:05 -04001872 << " " << rcClient.top << " " << kLineToOperator << " "
1873 << kStrokeOperator << "\n";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001874 }
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001875 }
1876 break;
1877 }
1878 default:
1879 break;
1880 }
1881 }
1882
1883 Write("N",
Ryan Harrison275e2602017-09-18 14:23:18 -04001884 GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sLines) +
1885 ByteString(sBody),
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001886 "");
1887}
1888
Ryan Harrison275e2602017-09-18 14:23:18 -04001889void CPWL_AppStream::AddImage(const ByteString& sAPType, CPDF_Stream* pImage) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001890 CPDF_Stream* pStream = dict_->GetStreamFor(sAPType);
1891 CPDF_Dictionary* pStreamDict = pStream->GetDict();
Ryan Harrison275e2602017-09-18 14:23:18 -04001892 ByteString sImageAlias = "IMG";
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001893
1894 if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
1895 sImageAlias = pImageDict->GetStringFor("Name");
1896 if (sImageAlias.IsEmpty())
1897 sImageAlias = "IMG";
1898 }
1899
1900 CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
1901 if (!pStreamResList)
1902 pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
1903
1904 CPDF_Dictionary* pXObject =
1905 pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
1906 pXObject->SetNewFor<CPDF_Reference>(sImageAlias,
1907 widget_->GetPageView()->GetPDFDocument(),
1908 pImage->GetObjNum());
1909}
1910
Ryan Harrison275e2602017-09-18 14:23:18 -04001911void CPWL_AppStream::Write(const ByteString& sAPType,
1912 const ByteString& sContents,
1913 const ByteString& sAPState) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001914 CPDF_Stream* pStream = nullptr;
1915 CPDF_Dictionary* pParentDict = nullptr;
1916 if (sAPState.IsEmpty()) {
1917 pParentDict = dict_.Get();
1918 pStream = dict_->GetStreamFor(sAPType);
1919 } else {
1920 CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType);
1921 if (!pAPTypeDict)
1922 pAPTypeDict = dict_->SetNewFor<CPDF_Dictionary>(sAPType);
1923
1924 pParentDict = pAPTypeDict;
1925 pStream = pAPTypeDict->GetStreamFor(sAPState);
1926 }
1927
1928 if (!pStream) {
1929 CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument();
1930 pStream = doc->NewIndirect<CPDF_Stream>();
1931 pParentDict->SetNewFor<CPDF_Reference>(sAPType, doc, pStream->GetObjNum());
1932 }
1933
1934 CPDF_Dictionary* pStreamDict = pStream->GetDict();
1935 if (!pStreamDict) {
1936 auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>(
1937 widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool());
1938 pStreamDict = pNewDict.get();
1939 pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
1940 pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
1941 pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
1942 pStream->InitStream(nullptr, 0, std::move(pNewDict));
1943 }
1944 pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix());
1945 pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect());
Artem Strygin90555e02017-07-28 19:41:59 +03001946 pStream->SetDataAndRemoveFilter((uint8_t*)(sContents.c_str()),
1947 sContents.GetLength());
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001948}
1949
Ryan Harrison275e2602017-09-18 14:23:18 -04001950void CPWL_AppStream::Remove(const ByteString& sAPType) {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001951 dict_->RemoveFor(sAPType);
1952}
1953
Ryan Harrison275e2602017-09-18 14:23:18 -04001954ByteString CPWL_AppStream::GetBackgroundAppStream() const {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001955 CFX_Color crBackground = widget_->GetFillPWLColor();
1956 if (crBackground.nColorType != COLORTYPE_TRANSPARENT)
Dan Sinclair14ddd422017-07-20 11:07:00 -04001957 return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001958
Ryan Harrison275e2602017-09-18 14:23:18 -04001959 return ByteString();
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001960}
1961
Ryan Harrison275e2602017-09-18 14:23:18 -04001962ByteString CPWL_AppStream::GetBorderAppStream() const {
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001963 CFX_FloatRect rcWindow = widget_->GetRotatedRect();
1964 CFX_Color crBorder = widget_->GetBorderPWLColor();
1965 CFX_Color crBackground = widget_->GetFillPWLColor();
1966 CFX_Color crLeftTop;
1967 CFX_Color crRightBottom;
1968
1969 float fBorderWidth = static_cast<float>(widget_->GetBorderWidth());
1970 CPWL_Dash dsBorder(3, 0, 0);
1971
1972 BorderStyle nBorderStyle = widget_->GetBorderStyle();
1973 switch (nBorderStyle) {
1974 case BorderStyle::DASH:
1975 dsBorder = CPWL_Dash(3, 3, 0);
1976 break;
1977 case BorderStyle::BEVELED:
1978 fBorderWidth *= 2;
1979 crLeftTop = CFX_Color(COLORTYPE_GRAY, 1);
1980 crRightBottom = crBackground / 2.0f;
1981 break;
1982 case BorderStyle::INSET:
1983 fBorderWidth *= 2;
1984 crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5);
1985 crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75);
1986 break;
1987 default:
1988 break;
1989 }
1990
Dan Sinclair14ddd422017-07-20 11:07:00 -04001991 return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
1992 crRightBottom, nBorderStyle, dsBorder);
Dan Sinclaircb2ea422017-07-19 15:24:49 -04001993}