7#include "core/fpdfdoc/cpdf_generateap.h"
13#include "constants/annotation_common.h"
14#include "constants/appearance.h"
15#include "constants/font_encodings.h"
16#include "constants/form_fields.h"
17#include "core/fpdfapi/edit/cpdf_contentstream_write_utils.h"
18#include "core/fpdfapi/font/cpdf_font.h"
19#include "core/fpdfapi/page/cpdf_docpagedata.h"
20#include "core/fpdfapi/parser/cpdf_array.h"
21#include "core/fpdfapi/parser/cpdf_boolean.h"
22#include "core/fpdfapi/parser/cpdf_dictionary.h"
23#include "core/fpdfapi/parser/cpdf_document.h"
24#include "core/fpdfapi/parser/cpdf_name.h"
25#include "core/fpdfapi/parser/cpdf_number.h"
26#include "core/fpdfapi/parser/cpdf_reference.h"
27#include "core/fpdfapi/parser/cpdf_stream.h"
28#include "core/fpdfapi/parser/cpdf_string.h"
29#include "core/fpdfapi/parser/fpdf_parser_decode.h"
30#include "core/fpdfapi/parser/fpdf_parser_utility.h"
31#include "core/fpdfdoc/cpdf_annot.h"
32#include "core/fpdfdoc/cpdf_color_utils.h"
33#include "core/fpdfdoc/cpdf_defaultappearance.h"
34#include "core/fpdfdoc/cpdf_formfield.h"
35#include "core/fpdfdoc/cpvt_fontmap.h"
36#include "core/fpdfdoc/cpvt_variabletext.h"
37#include "core/fpdfdoc/cpvt_word.h"
38#include "core/fxcrt/fx_string_wrappers.h"
39#include "core/fxge/cfx_renderdevice.h"
44 CPVT_Dash(int32_t dash, int32_t gap, int32_t phase)
45 : nDash(dash), nGap(gap), nPhase(phase) {}
52enum class PaintOperation { kStroke, kFill };
68 if (pPDFFont->GetBaseFontName() ==
"Symbol" ||
69 pPDFFont->GetBaseFontName() ==
"ZapfDingbats") {
74 uint32_t dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
76 pPDFFont->AppendChar(&sWord, dwCharCode);
82 if (strWords.IsEmpty())
84 return PDF_EncodeString(strWords) +
" Tj\n";
90 fxcrt::ostringstream sRet;
93 if (sFontAlias.GetLength() > 0 && fFontSize > 0) {
94 sRet <<
"/" << sFontAlias <<
" ";
95 WriteFloat(sRet, fFontSize) <<
" Tf\n";
106 fxcrt::ostringstream sEditStream;
107 fxcrt::ostringstream sLineStream;
110 int32_t nCurFontIndex = -1;
118 if (!sWords.IsEmpty()) {
119 sLineStream << GetWordRenderString(sWords.AsStringView());
120 sEditStream << sLineStream.str();
126 ptNew =
CFX_PointF(word.ptWord.x + ptOffset.x,
127 word.ptWord.y + ptOffset.y);
131 ptNew =
CFX_PointF(line.ptLine.x + ptOffset.x,
132 line.ptLine.y + ptOffset.y);
134 if (ptNew != ptOld) {
135 WritePoint(sLineStream, ptNew - ptOld) <<
" Td\n";
142 if (!sWords.IsEmpty()) {
143 sLineStream << GetWordRenderString(sWords.AsStringView());
146 sLineStream << GetFontSetString(pFontMap, word
.nFontIndex,
150 sWords
+= GetPDFWordString(pFontMap, nCurFontIndex, word
.Word, SubWord);
157 CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
158 if (ptNew != ptOld) {
159 WritePoint(sEditStream, ptNew - ptOld) <<
" Td\n";
163 sEditStream << GetFontSetString(pFontMap, word
.nFontIndex,
167 sEditStream << GetWordRenderString(
168 GetPDFWordString(pFontMap, nCurFontIndex, word
.Word, SubWord)
173 if (!sWords.IsEmpty()) {
174 sLineStream << GetWordRenderString(sWords.AsStringView());
175 sEditStream << sLineStream.str();
181 fxcrt::ostringstream sColorStream;
184 WriteFloat(sColorStream, color
.fColor1) <<
" ";
185 WriteFloat(sColorStream, color
.fColor2) <<
" ";
186 WriteFloat(sColorStream, color
.fColor3) <<
" ";
187 sColorStream << (nOperation == PaintOperation::kStroke ?
"RG" :
"rg")
191 WriteFloat(sColorStream, color
.fColor1) <<
" ";
192 sColorStream << (nOperation == PaintOperation::kStroke ?
"G" :
"g")
196 WriteFloat(sColorStream, color
.fColor1) <<
" ";
197 WriteFloat(sColorStream, color
.fColor2) <<
" ";
198 WriteFloat(sColorStream, color
.fColor3) <<
" ";
199 WriteFloat(sColorStream, color
.fColor4) <<
" ";
200 sColorStream << (nOperation == PaintOperation::kStroke ?
"K" :
"k")
215 const CPVT_Dash& dash) {
216 fxcrt::ostringstream sAppStream;
218 const float fLeft = rect
.left;
219 const float fRight = rect
.right;
220 const float fTop = rect
.top;
221 const float fBottom = rect
.bottom;
223 const float half_width = width / 2.0f;
226 sColor
= GenerateColorAP(color, PaintOperation::kFill);
227 if (sColor.GetLength() > 0) {
228 sAppStream << sColor;
229 WriteRect(sAppStream, rect) <<
" re\n";
232 WriteRect(sAppStream, inner_rect) <<
" re f*\n";
236 sColor
= GenerateColorAP(color, PaintOperation::kStroke);
237 if (sColor.GetLength() > 0) {
238 sAppStream << sColor;
239 WriteFloat(sAppStream, width)
240 <<
" w [" << dash.nDash <<
" " << dash.nGap <<
"] " << dash.nPhase
242 WritePoint(sAppStream, {fLeft + half_width, fBottom + half_width})
244 WritePoint(sAppStream, {fLeft + half_width, fTop - half_width})
246 WritePoint(sAppStream, {fRight - half_width, fTop - half_width})
248 WritePoint(sAppStream, {fRight - half_width, fBottom + half_width})
250 WritePoint(sAppStream, {fLeft + half_width, fBottom + half_width})
256 sColor
= GenerateColorAP(crLeftTop, PaintOperation::kFill);
257 if (sColor.GetLength() > 0) {
258 sAppStream << sColor;
259 WritePoint(sAppStream, {fLeft + half_width, fBottom + half_width})
261 WritePoint(sAppStream, {fLeft + half_width, fTop - half_width})
263 WritePoint(sAppStream, {fRight - half_width, fTop - half_width})
265 WritePoint(sAppStream, {fRight - width, fTop - width}) <<
" l\n";
266 WritePoint(sAppStream, {fLeft + width, fTop - width}) <<
" l\n";
267 WritePoint(sAppStream, {fLeft + width, fBottom + width}) <<
" l f\n";
269 sColor
= GenerateColorAP(crRightBottom, PaintOperation::kFill);
270 if (sColor.GetLength() > 0) {
271 sAppStream << sColor;
272 WritePoint(sAppStream, {fRight - half_width, fTop - half_width})
274 WritePoint(sAppStream, {fRight - half_width, fBottom + half_width})
276 WritePoint(sAppStream, {fLeft + half_width, fBottom + half_width})
278 WritePoint(sAppStream, {fLeft + width, fBottom + width}) <<
" l\n";
279 WritePoint(sAppStream, {fRight - width, fBottom + width}) <<
" l\n";
280 WritePoint(sAppStream, {fRight - width, fTop - width}) <<
" l f\n";
282 sColor
= GenerateColorAP(color, PaintOperation::kFill);
283 if (sColor.GetLength() > 0) {
284 sAppStream << sColor;
285 WriteRect(sAppStream, rect) <<
" re\n";
288 WriteRect(sAppStream, inner_rect) <<
" re f*\n";
292 sColor
= GenerateColorAP(color, PaintOperation::kStroke);
293 if (sColor.GetLength() > 0) {
294 sAppStream << sColor;
295 WriteFloat(sAppStream, width) <<
" w\n";
296 WritePoint(sAppStream, {fLeft, fBottom + half_width}) <<
" m\n";
297 WritePoint(sAppStream, {fRight, fBottom + half_width}) <<
" l S\n";
307 PaintOperation nOperation) {
310 return GenerateColorAP(color, nOperation);
313 return GenerateColorAP(crDefaultColor, nOperation);
318 if (pBorderStyleDict && pBorderStyleDict->KeyExist(
"W"))
319 return pBorderStyleDict->GetFloatFor(
"W");
322 if (pBorderArray && pBorderArray->size() > 2)
323 return pBorderArray->GetFloatAt(2);
330 if (pBorderStyleDict && pBorderStyleDict->GetByteStringFor(
"S") ==
"D")
331 return pBorderStyleDict->GetArrayFor(
"D");
334 pDict->GetArrayFor(pdfium::annotation::kBorder);
335 if (pBorderArray && pBorderArray->size() == 4)
336 return pBorderArray->GetArrayAt(3);
343 if (!pDashArray || pDashArray->IsEmpty())
347 size_t pDashArrayCount = std::min<size_t>(pDashArray->size(), 10);
348 fxcrt::ostringstream sDashStream;
351 for (size_t i = 0; i < pDashArrayCount; ++i)
352 WriteFloat(sDashStream, pDashArray->GetFloatAt(i)) <<
" ";
353 sDashStream <<
"] 0 d\n";
366 CPVT_FontMap map(pDoc,
nullptr,
std::move(pDefFont), sFontName);
381 if (sContent.IsEmpty())
387 return ByteString{
"BT\n", sColorAP.AsStringView(), sContent.AsStringView(),
393 font_dict->SetNewFor<CPDF_Name>(
"Type",
"Font");
394 font_dict->SetNewFor<CPDF_Name>(
"Subtype",
"Type1");
396 font_dict->SetNewFor<CPDF_Name>(
"Encoding",
404 uint32_t font_dict_obj_num) {
406 resource_font_dict->SetNewFor<CPDF_Reference>(font_name, doc,
408 return resource_font_dict;
411ByteString GetPaintOperatorString(
bool bIsStrokeRect,
bool bIsFillRect) {
413 return bIsFillRect ?
"b" :
"s";
414 return bIsFillRect ?
"f" :
"n";
418 fxcrt::ostringstream sAppStream;
420 PaintOperation::kFill);
422 PaintOperation::kStroke);
424 constexpr int kBorderWidth = 1;
425 sAppStream << kBorderWidth <<
" w\n";
427 constexpr float kHalfWidth = kBorderWidth / 2.0f;
428 constexpr int kTipDelta = 4;
432 outerRect1
.bottom += kTipDelta;
435 outerRect2
.left += kTipDelta;
438 float outerRect2Middle = (outerRect2
.left + outerRect2
.right) / 2;
441 WritePoint(sAppStream, {outerRect1
.left, outerRect1
.bottom}) <<
" m\n";
442 WritePoint(sAppStream, {outerRect1
.left, outerRect1
.top}) <<
" l\n";
443 WritePoint(sAppStream, {outerRect1
.right, outerRect1
.top}) <<
" l\n";
444 WritePoint(sAppStream, {outerRect1
.right, outerRect1
.bottom}) <<
" l\n";
445 WritePoint(sAppStream, {outerRect2
.right, outerRect2
.bottom}) <<
" l\n";
446 WritePoint(sAppStream, {outerRect2Middle, outerRect2
.top}) <<
" l\n";
447 WritePoint(sAppStream, {outerRect2
.left, outerRect2
.bottom}) <<
" l\n";
448 WritePoint(sAppStream, {outerRect1
.left, outerRect1
.bottom}) <<
" l\n";
452 const float fXDelta = 2;
453 const float fYDelta = (lineRect
.top - lineRect
.bottom) / 4;
455 lineRect
.left += fXDelta;
456 lineRect
.right -= fXDelta;
457 for (
int i = 0; i < 3; ++i) {
458 lineRect
.top -= fYDelta;
459 WritePoint(sAppStream, {lineRect
.left, lineRect
.top}) <<
" m\n";
460 WritePoint(sAppStream, {lineRect
.right, lineRect
.top}) <<
" l\n";
462 sAppStream <<
"B*\n";
473 pGSDict->SetNewFor<CPDF_Name>(
"Type",
"ExtGState");
476 pGSDict->SetNewFor<CPDF_Number>(
"CA", fOpacity);
477 pGSDict->SetNewFor<CPDF_Number>(
"ca", fOpacity);
478 pGSDict->SetNewFor<CPDF_Boolean>(
"AIS",
false);
479 pGSDict->SetNewFor<CPDF_Name>(
"BM", sBlendMode);
481 auto pExtGStateDict =
483 pExtGStateDict->SetFor(sExtGSDictName, pGSDict);
484 return pExtGStateDict;
493 pResourceDict->SetFor(
"ExtGState", pExtGStateDict);
494 if (pResourceFontDict)
495 pResourceDict->SetFor(
"Font", pResourceFontDict);
496 return pResourceDict;
501 fxcrt::ostringstream* app_stream,
503 bool is_text_markup_annotation) {
505 stream_dict->SetNewFor<CPDF_Number>(
"FormType", 1);
506 stream_dict->SetNewFor<CPDF_Name>(
"Type",
"XObject");
507 stream_dict->SetNewFor<CPDF_Name>(
"Subtype",
"Form");
513 stream_dict->SetRectFor(
"BBox", rect);
514 stream_dict->SetFor(
"Resources",
std::move(resource_dict));
516 auto normal_stream = doc->NewIndirect<CPDF_Stream>(
std::move(stream_dict));
517 normal_stream->SetDataFromStringstream(app_stream);
520 annot_dict->GetOrCreateDictFor(pdfium::annotation::kAP);
521 ap_dict->SetNewFor<CPDF_Reference>(
"N", doc, normal_stream->GetObjNum());
525 fxcrt::ostringstream sAppStream;
527 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
530 sAppStream << GetColorStringWithDefault(
532 PaintOperation::kFill);
534 sAppStream << GetColorStringWithDefault(
538 float fBorderWidth = GetBorderWidth(pAnnotDict);
539 bool bIsStrokeRect = fBorderWidth > 0;
542 sAppStream << fBorderWidth <<
" w ";
543 sAppStream << GetDashPatternString(pAnnotDict);
556 const float fMiddleX = (rect
.left + rect
.right) / 2;
557 const float fMiddleY = (rect
.top + rect
.bottom) / 2;
562 const float fL = 0.5523f;
563 const float fDeltaX = fL * rect
.Width() / 2.0;
564 const float fDeltaY = fL * rect
.Height() / 2.0;
567 sAppStream << fMiddleX <<
" " << rect
.top <<
" m\n";
569 sAppStream << fMiddleX + fDeltaX <<
" " << rect
.top <<
" " << rect
.right
570 <<
" " << fMiddleY + fDeltaY <<
" " << rect
.right <<
" "
571 << fMiddleY <<
" c\n";
573 sAppStream << rect
.right <<
" " << fMiddleY - fDeltaY <<
" "
574 << fMiddleX + fDeltaX <<
" " << rect
.bottom <<
" " << fMiddleX
575 <<
" " << rect
.bottom <<
" c\n";
577 sAppStream << fMiddleX - fDeltaX <<
" " << rect
.bottom <<
" " << rect
.left
578 <<
" " << fMiddleY - fDeltaY <<
" " << rect
.left <<
" " << fMiddleY
581 sAppStream << rect
.left <<
" " << fMiddleY + fDeltaY <<
" "
582 << fMiddleX - fDeltaX <<
" " << rect
.top <<
" " << fMiddleX <<
" "
583 << rect
.top <<
" c\n";
585 bool bIsFillRect = pInteriorColor && !pInteriorColor->IsEmpty();
586 sAppStream << GetPaintOperatorString(bIsStrokeRect, bIsFillRect) <<
"\n";
588 auto pExtGStateDict =
589 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
591 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
592 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
598 fxcrt::ostringstream sAppStream;
600 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
602 sAppStream << GetColorStringWithDefault(
608 size_t nQuadPointCount = CPDF_Annot::QuadPointCount(pArray.Get());
609 for (size_t i = 0; i < nQuadPointCount; ++i) {
610 CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict, i);
613 sAppStream << rect
.left <<
" " << rect
.top <<
" m " << rect
.right <<
" "
615 <<
" l " << rect
.left <<
" " << rect
.bottom <<
" l h f\n";
619 auto pExtGStateDict =
620 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Multiply");
622 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
623 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
631 if (!pInkList || pInkList->IsEmpty())
634 float fBorderWidth = GetBorderWidth(pAnnotDict);
635 const bool bIsStroke = fBorderWidth > 0;
640 fxcrt::ostringstream sAppStream;
641 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
642 sAppStream << GetColorStringWithDefault(
646 sAppStream << fBorderWidth <<
" w ";
647 sAppStream << GetDashPatternString(pAnnotDict);
655 for (size_t i = 0; i < pInkList->size(); i++) {
657 if (!pInkCoordList || pInkCoordList->size() < 2)
660 sAppStream << pInkCoordList->GetFloatAt(0) <<
" "
661 << pInkCoordList->GetFloatAt(1) <<
" m ";
663 for (size_t j = 0; j < pInkCoordList->size() - 1; j += 2) {
664 sAppStream << pInkCoordList->GetFloatAt(j) <<
" "
665 << pInkCoordList->GetFloatAt(j + 1) <<
" l ";
671 auto pExtGStateDict =
672 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
674 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
675 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
681 fxcrt::ostringstream sAppStream;
683 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
686 const float fNoteLength = 20;
691 sAppStream << GenerateTextSymbolAP(noteRect);
693 auto pExtGStateDict =
694 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
696 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
697 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
703 fxcrt::ostringstream sAppStream;
705 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
707 sAppStream << GetColorStringWithDefault(
713 static constexpr int kLineWidth = 1;
714 sAppStream << kLineWidth <<
" w ";
715 size_t nQuadPointCount = CPDF_Annot::QuadPointCount(pArray.Get());
716 for (size_t i = 0; i < nQuadPointCount; ++i) {
717 CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict, i);
719 sAppStream << rect
.left <<
" " << rect
.bottom + kLineWidth <<
" m "
720 << rect
.right <<
" " << rect
.bottom + kLineWidth <<
" l S\n";
724 auto pExtGStateDict =
725 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
727 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
728 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
734 fxcrt::ostringstream sAppStream;
736 sAppStream <<
"/" << sExtGSDictName <<
" gs\n";
739 PaintOperation::kFill);
741 PaintOperation::kStroke);
743 const float fBorderWidth = 1;
744 sAppStream << fBorderWidth <<
" w\n";
761 GenerateResourceFontDict(pDoc, font_name, font_dict->GetObjNum());
763 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
765 pDoc, std::move(pExtGStateDict), std::move(resource_font_dict));
767 sAppStream << GetPopupContentsString(pDoc, *pAnnotDict,
std::move(pDefFont),
769 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
776 fxcrt::ostringstream sAppStream;
777 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
780 sAppStream << GetColorStringWithDefault(
782 PaintOperation::kFill);
784 sAppStream << GetColorStringWithDefault(
788 float fBorderWidth = GetBorderWidth(pAnnotDict);
789 const bool bIsStrokeRect = fBorderWidth > 0;
791 sAppStream << fBorderWidth <<
" w ";
792 sAppStream << GetDashPatternString(pAnnotDict);
805 const bool bIsFillRect = pInteriorColor && (pInteriorColor->size() > 0);
808 << GetPaintOperatorString(bIsStrokeRect, bIsFillRect) <<
"\n";
810 auto pExtGStateDict =
811 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
813 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
814 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
820 fxcrt::ostringstream sAppStream;
822 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
824 sAppStream << GetColorStringWithDefault(
830 static constexpr int kLineWidth = 1;
831 static constexpr int kDelta = 2;
832 sAppStream << kLineWidth <<
" w ";
833 size_t nQuadPointCount = CPDF_Annot::QuadPointCount(pArray.Get());
834 for (size_t i = 0; i < nQuadPointCount; ++i) {
835 CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict, i);
838 const float fTop = rect
.bottom + kDelta;
839 const float fBottom = rect
.bottom;
840 sAppStream << rect
.left <<
" " << fTop <<
" m ";
842 float fX = rect
.left + kDelta;
843 bool isUpwards =
false;
845 sAppStream << fX <<
" " << (isUpwards ? fTop : fBottom) <<
" l ";
847 isUpwards = !isUpwards;
850 float fRemainder = rect
.right - (fX - kDelta);
852 sAppStream << rect
.right <<
" " << fBottom + fRemainder <<
" l ";
854 sAppStream << rect
.right <<
" " << fTop - fRemainder <<
" l ";
860 auto pExtGStateDict =
861 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
863 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
864 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
870 fxcrt::ostringstream sAppStream;
872 sAppStream <<
"/" << sExtGSDictName <<
" gs ";
874 sAppStream << GetColorStringWithDefault(
880 size_t nQuadPointCount = CPDF_Annot::QuadPointCount(pArray.Get());
881 for (size_t i = 0; i < nQuadPointCount; ++i) {
882 CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict, i);
886 constexpr int kLineWidth = 1;
887 sAppStream << kLineWidth <<
" w " << rect
.left <<
" " << fY <<
" m "
888 << rect
.right <<
" " << fY <<
" l S\n";
892 auto pExtGStateDict =
893 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName,
"Normal");
895 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
896 GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream,
std::move(pResourceDict),
912 pRootDict->GetMutableDictFor(
"AcroForm");
918 CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"DA");
920 DA = pDAObj->GetString();
922 DA = pFormDict->GetByteStringFor(
"DA");
929 std::optional<
ByteString> font = appearance.GetFont(&fFontSize);
930 if (!font.has_value())
941 if (!ValidateFontResourceDict(pDRFontDict.Get()))
945 pDRFontDict->GetMutableDictFor(font_name);
947 pFontDict = GenerateFallbackFontDict(pDoc);
948 pDRFontDict->SetNewFor<CPDF_Reference>(font_name, pDoc,
949 pFontDict->GetObjNum());
963 switch (nRotate % 360) {
987 float fBorderWidth = 1;
988 CPVT_Dash dsBorder(3, 0, 0);
991 if (RetainPtr<
const CPDF_Dictionary> pBSDict = pAnnotDict->GetDictFor(
"BS")) {
992 if (pBSDict->KeyExist(
"W"))
993 fBorderWidth = pBSDict->GetFloatFor(
"W");
995 if (RetainPtr<
const CPDF_Array> pArray = pBSDict->GetArrayFor(
"D")) {
996 dsBorder = CPVT_Dash(pArray->GetIntegerAt(0), pArray->GetIntegerAt(1),
997 pArray->GetIntegerAt(2));
999 if (pBSDict->GetByteStringFor(
"S").GetLength()) {
1000 switch (pBSDict->GetByteStringFor(
"S")[0]) {
1029 pMKDict->GetArrayFor(pdfium::appearance::kBC);
1036 fxcrt::ostringstream sAppStream;
1037 ByteString sBG = GenerateColorAP(crBG, PaintOperation::kFill);
1038 if (sBG.GetLength() > 0) {
1039 sAppStream <<
"q\n" << sBG;
1040 WriteRect(sAppStream, rcBBox) <<
" re f\nQ\n";
1043 GenerateBorderAP(rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom,
1044 nBorderStyle, dsBorder);
1045 if (sBorderStream.GetLength() > 0)
1046 sAppStream <<
"q\n" << sBorderStream <<
"Q\n";
1050 rcBBox
.right - fBorderWidth
, rcBBox
.top - fBorderWidth
);
1054 pAnnotDict->GetOrCreateDictFor(pdfium::annotation::kAP);
1055 RetainPtr<CPDF_Stream> pNormalStream = pAPDict->GetMutableStreamFor(
"N");
1057 if (pNormalStream) {
1058 pStreamDict = pNormalStream->GetMutableDict();
1060 pStreamDict->GetMutableDictFor(
"Resources");
1061 if (pStreamResList) {
1063 pStreamResList->GetMutableDictFor(
"Font");
1064 if (pStreamResFontList) {
1065 if (!ValidateFontResourceDict(pStreamResFontList.Get()))
1068 pStreamResFontList = pStreamResList->SetNewFor<
CPDF_Dictionary>(
"Font");
1070 if (!pStreamResFontList->KeyExist(font_name)) {
1071 pStreamResFontList->SetNewFor<CPDF_Reference>(font_name, pDoc,
1072 pFontDict->GetObjNum());
1075 pStreamDict->SetFor(
"Resources", pFormDict->GetDictFor(
"DR")->Clone());
1077 pStreamDict->SetMatrixFor(
"Matrix", matrix);
1078 pStreamDict->SetRectFor(
"BBox", rcBBox);
1082 pAPDict->SetNewFor<CPDF_Reference>(
"N", pDoc, pNormalStream->GetObjNum());
1085 pDoc, pStreamDict ? pStreamDict->GetMutableDictFor(
"Resources") :
nullptr,
1086 std::move(pDefFont), font_name);
1092 pAnnotDict, pdfium::form_fields::kV);
1095 CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"Q");
1096 int32_t nAlign = pQ ? pQ->GetInteger() : 0;
1098 pAnnotDict, pdfium::form_fields::kFf);
1099 uint32_t dwFlags = pFf ? pFf->GetInteger() : 0;
1101 CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"MaxLen");
1102 uint32_t dwMaxLen = pMaxLen ? pMaxLen->GetInteger() : 0;
1111 bool bMultiLine = (dwFlags >> 12) & 1;
1116 uint16_t subWord = 0;
1117 if ((dwFlags >> 13) & 1) {
1121 bool bCharArray = (dwFlags >> 24) & 1;
1137 !bCharArray, subWord);
1138 if (sBody.GetLength() > 0) {
1139 sAppStream <<
"/Tx BMC\n"
1143 WriteRect(sAppStream, rcBody) <<
" re\nW\nn\n";
1145 sAppStream <<
"BT\n"
1146 << GenerateColorAP(crText, PaintOperation::kFill) << sBody
1154 pAnnotDict, pdfium::form_fields::kV);
1174 CFX_PointF(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f);
1177 if (sEdit.GetLength() > 0) {
1178 sAppStream <<
"/Tx BMC\nq\n";
1179 WriteRect(sAppStream, rcEdit) <<
" re\nW\nn\n";
1180 sAppStream <<
"BT\n"
1181 << GenerateColorAP(crText, PaintOperation::kFill) << sEdit
1187 220.0f / 255.0f
, 220.0f / 255.0f
),
1188 PaintOperation::kFill);
1189 if (sButton.GetLength() > 0 && !rcButton
.IsEmpty()) {
1190 sAppStream <<
"q\n" << sButton;
1191 WriteRect(sAppStream, rcButton) <<
" re f\n";
1192 sAppStream <<
"Q\n";
1198 if (sButtonBorder.GetLength() > 0)
1199 sAppStream <<
"q\n" << sButtonBorder <<
"Q\n";
1201 CFX_PointF ptCenter = CFX_PointF((rcButton.left + rcButton.right) / 2,
1202 (rcButton.top + rcButton.bottom) / 2);
1207 WritePoint(sAppStream, {ptCenter.x - 3, ptCenter.y + 1.5f}) <<
" m\n";
1208 WritePoint(sAppStream, {ptCenter.x + 3, ptCenter.y + 1.5f}) <<
" l\n";
1209 WritePoint(sAppStream, {ptCenter.x, ptCenter.y - 1.5f}) <<
" l\n";
1210 WritePoint(sAppStream, {ptCenter.x - 3, ptCenter.y + 1.5f})
1212 sAppStream << sButton <<
"Q\n";
1219 ToArray(CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"Opt"));
1221 ToArray(CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"I"));
1223 CPDF_FormField::GetFieldAttrForDict(pAnnotDict,
"TI");
1224 int32_t nTop = pTi ? pTi->GetInteger() : 0;
1225 fxcrt::ostringstream sBody;
1227 float fy = rcBody
.top;
1228 for (size_t i = nTop, sz = pOpts->size(); i < sz; i++) {
1232 if (RetainPtr<
const CPDF_Object> pOpt = pOpts->GetDirectObjectAt(i)) {
1234 if (pOpt->IsString()) {
1235 swItem = pOpt->GetUnicodeText();
1236 }
else if (
const CPDF_Array* pArray = pOpt->AsArray()) {
1237 RetainPtr<
const CPDF_Object> pDirectObj =
1238 pArray->GetDirectObjectAt(1);
1240 swItem = pDirectObj->GetUnicodeText();
1242 bool bSelected =
false;
1244 for (size_t s = 0, ssz = pSels->size(); s < ssz; s++) {
1245 int value = pSels->GetIntegerAt(s);
1246 if (value >= 0 && i ==
static_cast<size_t>(value)) {
1252 CPVT_VariableText vt(&prd);
1254 CFX_FloatRect(rcBody.left, 0.0f, rcBody.right, 0.0f));
1260 float fItemHeight = vt.GetContentRect().Height();
1262 CFX_FloatRect rcItem = CFX_FloatRect(
1263 rcBody.left, fy - fItemHeight, rcBody.right, fy);
1266 CFX_Color(CFX_Color::Type::kRGB, 0, 51.0f / 255.0f,
1268 PaintOperation::kFill);
1269 WriteRect(sBody, rcItem) <<
" re f\nQ\n";
1271 << GenerateColorAP(CFX_Color(CFX_Color::Type::kGray, 1),
1272 PaintOperation::kFill)
1273 << GenerateEditAP(&map, vt.GetIterator(),
1274 CFX_PointF(0.0f, fy),
true, 0)
1278 << GenerateColorAP(crText, PaintOperation::kFill)
1279 << GenerateEditAP(&map, vt.GetIterator(),
1280 CFX_PointF(0.0f, fy),
true, 0)
1287 if (sBody.tellp() > 0) {
1288 sAppStream <<
"/Tx BMC\nq\n";
1289 WriteRect(sAppStream, rcBody) <<
" re\nW\nn\n"
1290 << sBody.str() <<
"Q\nEMC\n";
1299 pNormalStream->SetDataFromStringstreamAndRemoveFilter(&sAppStream);
1300 pStreamDict = pNormalStream->GetMutableDict();
1301 pStreamDict->SetMatrixFor(
"Matrix", matrix);
1302 pStreamDict->SetRectFor(
"BBox", rcBBox);
1304 pStreamDict->GetMutableDictFor(
"Resources");
1305 if (!pStreamResList) {
1306 pStreamDict->SetFor(
"Resources", pFormDict->GetDictFor(
"DR")->Clone());
1311 pStreamResList->GetMutableDictFor(
"Font");
1312 if (pStreamResFontList) {
1313 if (!ValidateFontResourceDict(pStreamResFontList.Get()))
1316 pStreamResFontList = pStreamResList->SetNewFor<
CPDF_Dictionary>(
"Font");
1319 if (!pStreamResFontList->KeyExist(font_name)) {
1320 pStreamResFontList->SetNewFor<CPDF_Reference>(font_name, pDoc,
1321 pFontDict->GetObjNum());
1328 auto pExtGStateDict = GenerateExtGStateDict(*pAnnotDict,
"GS",
"Normal");
1329 auto pResourceDict =
1330 GenerateResourceDict(pDoc, std::move(pExtGStateDict),
nullptr);
1332 fxcrt::ostringstream sStream;
1333 GenerateAndSetAPDict(pDoc, pAnnotDict, &sStream,
std::move(pResourceDict),
1343 return GenerateCircleAP(pDoc, pAnnotDict);
1345 return GenerateHighlightAP(pDoc, pAnnotDict);
1347 return GenerateInkAP(pDoc, pAnnotDict);
1349 return GeneratePopupAP(pDoc, pAnnotDict);
1351 return GenerateSquareAP(pDoc, pAnnotDict);
1353 return GenerateSquigglyAP(pDoc, pAnnotDict);
1355 return GenerateStrikeOutAP(pDoc, pAnnotDict);
1357 return GenerateTextAP(pDoc, pAnnotDict);
1359 return GenerateUnderlineAP(pDoc, pAnnotDict);
fxcrt::ByteString ByteString
constexpr CFX_FloatRect(float l, float b, float r, float t)
void Inflate(float x, float y)
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
void Deflate(float x, float y)
static const char kDefaultAnsiFontName[]
constexpr CFX_Matrix()=default
CFX_Matrix & operator=(const CFX_Matrix &other)=default
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
static CFX_FloatRect BoundingRectFromQuadPoints(const CPDF_Dictionary *pAnnotDict)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
CPDF_DefaultAppearance(const ByteString &csDA)
bool KeyExist(const ByteString &key) const
float GetFloatFor(const ByteString &key) const
WideString GetUnicodeTextFor(const ByteString &key) const
void SetRectFor(const ByteString &key, const CFX_FloatRect &rect)
RetainPtr< const CPDF_Array > GetArrayFor(const ByteString &key) const
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
CFX_FloatRect GetRectFor(const ByteString &key) const
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
static constexpr uint32_t kInvalidCharCode
static bool GenerateAnnotAP(CPDF_Document *pDoc, CPDF_Dictionary *pAnnotDict, CPDF_Annot::Subtype subtype)
static void GenerateEmptyAP(CPDF_Document *pDoc, CPDF_Dictionary *pAnnotDict)
static void GenerateFormAP(CPDF_Document *pDoc, CPDF_Dictionary *pAnnotDict, FormType type)
void SetAt(int32_t nWordIndex)
bool GetWord(CPVT_Word &word) const
bool GetLine(CPVT_Line &line) const
const CPVT_WordPlace & GetWordPlace() const
void SetPlateRect(const CFX_FloatRect &rect)
void SetLimitChar(int32_t nLimitChar)
CFX_FloatRect GetContentRect() const
CPVT_VariableText(Provider *Provider)
void SetText(const WideString &text)
CPVT_VariableText::Iterator * GetIterator()
void SetCharArray(int32_t nCharArray)
void SetAlignment(int32_t nFormat)
void SetMultiLine(bool bMultiLine)
void SetAutoFontSize(bool bAuto)
void SetFontSize(float fFontSize)
void SetAutoReturn(bool bAuto)
void SetPasswordChar(uint16_t wSubWord)
virtual ByteString GetPDFFontAlias(int32_t nFontIndex)=0
static ByteString Format(const char *pFormat,...)
ByteString & operator+=(const ByteString &str)
ByteString & operator=(ByteString &&that) noexcept
WideString & operator+=(const WideString &str)
WideString & operator+=(wchar_t ch)
CFX_PTemplate< float > CFX_PointF
#define FXSYS_IsFloatBigger(fa, fb)
#define FXSYS_IsFloatZero(f)
#define FXSYS_IsFloatSmaller(fa, fb)
CFX_Color CFXColorFromArray(const CPDF_Array &array)
CFX_Color CFXColorFromString(const ByteString &str)
const char kWinAnsiEncoding[]
fxcrt::ByteStringView ByteStringView
CFX_Color & operator=(const CFX_Color &that)=default
constexpr CFX_Color(Type type=CFX_Color::Type::kTransparent, float color1=0.0f, float color2=0.0f, float color3=0.0f, float color4=0.0f)
int32_t LineCmp(const CPVT_WordPlace &wp) const
fxcrt::WideString WideString