xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_text.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdf_text.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <algorithm>
10*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
11*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
12*3ac0a46fSAndroid Build Coastguard Worker 
13*3ac0a46fSAndroid Build Coastguard Worker #include "build/build_config.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/font/cpdf_font.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_page.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_textobject.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_viewerpreferences.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdftext/cpdf_linkextract.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdftext/cpdf_textpage.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdftext/cpdf_textpagefind.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_helpers.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check_op.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/numerics/safe_conversions.h"
25*3ac0a46fSAndroid Build Coastguard Worker 
26*3ac0a46fSAndroid Build Coastguard Worker namespace {
27*3ac0a46fSAndroid Build Coastguard Worker 
28*3ac0a46fSAndroid Build Coastguard Worker constexpr size_t kBytesPerCharacter = sizeof(unsigned short);
29*3ac0a46fSAndroid Build Coastguard Worker 
GetTextPageForValidIndex(FPDF_TEXTPAGE text_page,int index)30*3ac0a46fSAndroid Build Coastguard Worker CPDF_TextPage* GetTextPageForValidIndex(FPDF_TEXTPAGE text_page, int index) {
31*3ac0a46fSAndroid Build Coastguard Worker   if (!text_page || index < 0)
32*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
35*3ac0a46fSAndroid Build Coastguard Worker   return static_cast<size_t>(index) < textpage->size() ? textpage : nullptr;
36*3ac0a46fSAndroid Build Coastguard Worker }
37*3ac0a46fSAndroid Build Coastguard Worker 
38*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
39*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_LoadPage(FPDF_PAGE page)40*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_TEXTPAGE FPDF_CALLCONV FPDFText_LoadPage(FPDF_PAGE page) {
41*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
42*3ac0a46fSAndroid Build Coastguard Worker   if (!pPDFPage)
43*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker   CPDF_ViewerPreferences viewRef(pPDFPage->GetDocument());
46*3ac0a46fSAndroid Build Coastguard Worker   auto textpage =
47*3ac0a46fSAndroid Build Coastguard Worker       std::make_unique<CPDF_TextPage>(pPDFPage, viewRef.IsDirectionR2L());
48*3ac0a46fSAndroid Build Coastguard Worker 
49*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
50*3ac0a46fSAndroid Build Coastguard Worker   return FPDFTextPageFromCPDFTextPage(textpage.release());
51*3ac0a46fSAndroid Build Coastguard Worker }
52*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_ClosePage(FPDF_TEXTPAGE text_page)53*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT void FPDF_CALLCONV FPDFText_ClosePage(FPDF_TEXTPAGE text_page) {
54*3ac0a46fSAndroid Build Coastguard Worker   // PDFium takes ownership.
55*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CPDF_TextPage> textpage_deleter(
56*3ac0a46fSAndroid Build Coastguard Worker       CPDFTextPageFromFPDFTextPage(text_page));
57*3ac0a46fSAndroid Build Coastguard Worker }
58*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_CountChars(FPDF_TEXTPAGE text_page)59*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountChars(FPDF_TEXTPAGE text_page) {
60*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
61*3ac0a46fSAndroid Build Coastguard Worker   return textpage ? textpage->CountChars() : -1;
62*3ac0a46fSAndroid Build Coastguard Worker }
63*3ac0a46fSAndroid Build Coastguard Worker 
64*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned int FPDF_CALLCONV
FPDFText_GetUnicode(FPDF_TEXTPAGE text_page,int index)65*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, int index) {
66*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
67*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
68*3ac0a46fSAndroid Build Coastguard Worker     return 0;
69*3ac0a46fSAndroid Build Coastguard Worker 
70*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
71*3ac0a46fSAndroid Build Coastguard Worker   return charinfo.m_Unicode;
72*3ac0a46fSAndroid Build Coastguard Worker }
73*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_IsGenerated(FPDF_TEXTPAGE text_page,int index)74*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_IsGenerated(FPDF_TEXTPAGE text_page,
75*3ac0a46fSAndroid Build Coastguard Worker                                                    int index) {
76*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
77*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
78*3ac0a46fSAndroid Build Coastguard Worker     return -1;
79*3ac0a46fSAndroid Build Coastguard Worker 
80*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
81*3ac0a46fSAndroid Build Coastguard Worker   return charinfo.m_CharType == CPDF_TextPage::CharType::kGenerated ? 1 : 0;
82*3ac0a46fSAndroid Build Coastguard Worker }
83*3ac0a46fSAndroid Build Coastguard Worker 
84*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFText_HasUnicodeMapError(FPDF_TEXTPAGE text_page,int index)85*3ac0a46fSAndroid Build Coastguard Worker FPDFText_HasUnicodeMapError(FPDF_TEXTPAGE text_page, int index) {
86*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
87*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
88*3ac0a46fSAndroid Build Coastguard Worker     return -1;
89*3ac0a46fSAndroid Build Coastguard Worker 
90*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
91*3ac0a46fSAndroid Build Coastguard Worker   return charinfo.m_CharType == CPDF_TextPage::CharType::kNotUnicode;
92*3ac0a46fSAndroid Build Coastguard Worker }
93*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetFontSize(FPDF_TEXTPAGE text_page,int index)94*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetFontSize(FPDF_TEXTPAGE text_page,
95*3ac0a46fSAndroid Build Coastguard Worker                                                       int index) {
96*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
97*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
98*3ac0a46fSAndroid Build Coastguard Worker     return 0;
99*3ac0a46fSAndroid Build Coastguard Worker 
100*3ac0a46fSAndroid Build Coastguard Worker   return textpage->GetCharFontSize(index);
101*3ac0a46fSAndroid Build Coastguard Worker }
102*3ac0a46fSAndroid Build Coastguard Worker 
103*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFText_GetFontInfo(FPDF_TEXTPAGE text_page,int index,void * buffer,unsigned long buflen,int * flags)104*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetFontInfo(FPDF_TEXTPAGE text_page,
105*3ac0a46fSAndroid Build Coastguard Worker                      int index,
106*3ac0a46fSAndroid Build Coastguard Worker                      void* buffer,
107*3ac0a46fSAndroid Build Coastguard Worker                      unsigned long buflen,
108*3ac0a46fSAndroid Build Coastguard Worker                      int* flags) {
109*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
110*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
111*3ac0a46fSAndroid Build Coastguard Worker     return 0;
112*3ac0a46fSAndroid Build Coastguard Worker 
113*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
114*3ac0a46fSAndroid Build Coastguard Worker   if (!charinfo.m_pTextObj)
115*3ac0a46fSAndroid Build Coastguard Worker     return 0;
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CPDF_Font> font = charinfo.m_pTextObj->GetFont();
118*3ac0a46fSAndroid Build Coastguard Worker   if (flags)
119*3ac0a46fSAndroid Build Coastguard Worker     *flags = font->GetFontFlags();
120*3ac0a46fSAndroid Build Coastguard Worker 
121*3ac0a46fSAndroid Build Coastguard Worker   ByteString basefont = font->GetBaseFontName();
122*3ac0a46fSAndroid Build Coastguard Worker   const unsigned long length =
123*3ac0a46fSAndroid Build Coastguard Worker       pdfium::base::checked_cast<unsigned long>(basefont.GetLength() + 1);
124*3ac0a46fSAndroid Build Coastguard Worker   if (buffer && buflen >= length)
125*3ac0a46fSAndroid Build Coastguard Worker     memcpy(buffer, basefont.c_str(), length);
126*3ac0a46fSAndroid Build Coastguard Worker 
127*3ac0a46fSAndroid Build Coastguard Worker   return length;
128*3ac0a46fSAndroid Build Coastguard Worker }
129*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetFontWeight(FPDF_TEXTPAGE text_page,int index)130*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetFontWeight(FPDF_TEXTPAGE text_page,
131*3ac0a46fSAndroid Build Coastguard Worker                                                      int index) {
132*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
133*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
134*3ac0a46fSAndroid Build Coastguard Worker     return -1;
135*3ac0a46fSAndroid Build Coastguard Worker 
136*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
137*3ac0a46fSAndroid Build Coastguard Worker   if (!charinfo.m_pTextObj)
138*3ac0a46fSAndroid Build Coastguard Worker     return -1;
139*3ac0a46fSAndroid Build Coastguard Worker 
140*3ac0a46fSAndroid Build Coastguard Worker   return charinfo.m_pTextObj->GetFont()->GetFontWeight();
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
143*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_TEXT_RENDERMODE FPDF_CALLCONV
FPDFText_GetTextRenderMode(FPDF_TEXTPAGE text_page,int index)144*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetTextRenderMode(FPDF_TEXTPAGE text_page, int index) {
145*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
146*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
147*3ac0a46fSAndroid Build Coastguard Worker     return FPDF_TEXTRENDERMODE_UNKNOWN;
148*3ac0a46fSAndroid Build Coastguard Worker 
149*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
150*3ac0a46fSAndroid Build Coastguard Worker   if (!charinfo.m_pTextObj)
151*3ac0a46fSAndroid Build Coastguard Worker     return FPDF_TEXTRENDERMODE_UNKNOWN;
152*3ac0a46fSAndroid Build Coastguard Worker 
153*3ac0a46fSAndroid Build Coastguard Worker   return static_cast<FPDF_TEXT_RENDERMODE>(
154*3ac0a46fSAndroid Build Coastguard Worker       charinfo.m_pTextObj->GetTextRenderMode());
155*3ac0a46fSAndroid Build Coastguard Worker }
156*3ac0a46fSAndroid Build Coastguard Worker 
157*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFText_GetFillColor(FPDF_TEXTPAGE text_page,int index,unsigned int * R,unsigned int * G,unsigned int * B,unsigned int * A)158*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetFillColor(FPDF_TEXTPAGE text_page,
159*3ac0a46fSAndroid Build Coastguard Worker                       int index,
160*3ac0a46fSAndroid Build Coastguard Worker                       unsigned int* R,
161*3ac0a46fSAndroid Build Coastguard Worker                       unsigned int* G,
162*3ac0a46fSAndroid Build Coastguard Worker                       unsigned int* B,
163*3ac0a46fSAndroid Build Coastguard Worker                       unsigned int* A) {
164*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
165*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage || !R || !G || !B || !A)
166*3ac0a46fSAndroid Build Coastguard Worker     return false;
167*3ac0a46fSAndroid Build Coastguard Worker 
168*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
169*3ac0a46fSAndroid Build Coastguard Worker   if (!charinfo.m_pTextObj)
170*3ac0a46fSAndroid Build Coastguard Worker     return false;
171*3ac0a46fSAndroid Build Coastguard Worker 
172*3ac0a46fSAndroid Build Coastguard Worker   FX_COLORREF fill_color = charinfo.m_pTextObj->m_ColorState.GetFillColorRef();
173*3ac0a46fSAndroid Build Coastguard Worker   *R = FXSYS_GetRValue(fill_color);
174*3ac0a46fSAndroid Build Coastguard Worker   *G = FXSYS_GetGValue(fill_color);
175*3ac0a46fSAndroid Build Coastguard Worker   *B = FXSYS_GetBValue(fill_color);
176*3ac0a46fSAndroid Build Coastguard Worker   *A = FXSYS_GetUnsignedAlpha(
177*3ac0a46fSAndroid Build Coastguard Worker       charinfo.m_pTextObj->m_GeneralState.GetFillAlpha());
178*3ac0a46fSAndroid Build Coastguard Worker   return true;
179*3ac0a46fSAndroid Build Coastguard Worker }
180*3ac0a46fSAndroid Build Coastguard Worker 
181*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFText_GetStrokeColor(FPDF_TEXTPAGE text_page,int index,unsigned int * R,unsigned int * G,unsigned int * B,unsigned int * A)182*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetStrokeColor(FPDF_TEXTPAGE text_page,
183*3ac0a46fSAndroid Build Coastguard Worker                         int index,
184*3ac0a46fSAndroid Build Coastguard Worker                         unsigned int* R,
185*3ac0a46fSAndroid Build Coastguard Worker                         unsigned int* G,
186*3ac0a46fSAndroid Build Coastguard Worker                         unsigned int* B,
187*3ac0a46fSAndroid Build Coastguard Worker                         unsigned int* A) {
188*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
189*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage || !R || !G || !B || !A)
190*3ac0a46fSAndroid Build Coastguard Worker     return false;
191*3ac0a46fSAndroid Build Coastguard Worker 
192*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
193*3ac0a46fSAndroid Build Coastguard Worker   if (!charinfo.m_pTextObj)
194*3ac0a46fSAndroid Build Coastguard Worker     return false;
195*3ac0a46fSAndroid Build Coastguard Worker 
196*3ac0a46fSAndroid Build Coastguard Worker   FX_COLORREF stroke_color =
197*3ac0a46fSAndroid Build Coastguard Worker       charinfo.m_pTextObj->m_ColorState.GetStrokeColorRef();
198*3ac0a46fSAndroid Build Coastguard Worker   *R = FXSYS_GetRValue(stroke_color);
199*3ac0a46fSAndroid Build Coastguard Worker   *G = FXSYS_GetGValue(stroke_color);
200*3ac0a46fSAndroid Build Coastguard Worker   *B = FXSYS_GetBValue(stroke_color);
201*3ac0a46fSAndroid Build Coastguard Worker   *A = FXSYS_GetUnsignedAlpha(
202*3ac0a46fSAndroid Build Coastguard Worker       charinfo.m_pTextObj->m_GeneralState.GetStrokeAlpha());
203*3ac0a46fSAndroid Build Coastguard Worker   return true;
204*3ac0a46fSAndroid Build Coastguard Worker }
205*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,int index)206*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT float FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,
207*3ac0a46fSAndroid Build Coastguard Worker                                                       int index) {
208*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
209*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
210*3ac0a46fSAndroid Build Coastguard Worker     return -1.0f;
211*3ac0a46fSAndroid Build Coastguard Worker 
212*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
213*3ac0a46fSAndroid Build Coastguard Worker   // On the left is our current Matrix and on the right a generic rotation
214*3ac0a46fSAndroid Build Coastguard Worker   // matrix for our coordinate space.
215*3ac0a46fSAndroid Build Coastguard Worker   // | a  b  0 |    | cos(t)  -sin(t)  0 |
216*3ac0a46fSAndroid Build Coastguard Worker   // | c  d  0 |    | sin(t)   cos(t)  0 |
217*3ac0a46fSAndroid Build Coastguard Worker   // | e  f  1 |    |   0        0     1 |
218*3ac0a46fSAndroid Build Coastguard Worker   // Calculate the angle of the vector
219*3ac0a46fSAndroid Build Coastguard Worker   float angle = atan2f(charinfo.m_Matrix.c, charinfo.m_Matrix.a);
220*3ac0a46fSAndroid Build Coastguard Worker   if (angle < 0)
221*3ac0a46fSAndroid Build Coastguard Worker     angle = 2 * FXSYS_PI + angle;
222*3ac0a46fSAndroid Build Coastguard Worker 
223*3ac0a46fSAndroid Build Coastguard Worker   return angle;
224*3ac0a46fSAndroid Build Coastguard Worker }
225*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetCharBox(FPDF_TEXTPAGE text_page,int index,double * left,double * right,double * bottom,double * top)226*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharBox(FPDF_TEXTPAGE text_page,
227*3ac0a46fSAndroid Build Coastguard Worker                                                         int index,
228*3ac0a46fSAndroid Build Coastguard Worker                                                         double* left,
229*3ac0a46fSAndroid Build Coastguard Worker                                                         double* right,
230*3ac0a46fSAndroid Build Coastguard Worker                                                         double* bottom,
231*3ac0a46fSAndroid Build Coastguard Worker                                                         double* top) {
232*3ac0a46fSAndroid Build Coastguard Worker   if (!left || !right || !bottom || !top)
233*3ac0a46fSAndroid Build Coastguard Worker     return false;
234*3ac0a46fSAndroid Build Coastguard Worker 
235*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
236*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
237*3ac0a46fSAndroid Build Coastguard Worker     return false;
238*3ac0a46fSAndroid Build Coastguard Worker 
239*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
240*3ac0a46fSAndroid Build Coastguard Worker   *left = charinfo.m_CharBox.left;
241*3ac0a46fSAndroid Build Coastguard Worker   *right = charinfo.m_CharBox.right;
242*3ac0a46fSAndroid Build Coastguard Worker   *bottom = charinfo.m_CharBox.bottom;
243*3ac0a46fSAndroid Build Coastguard Worker   *top = charinfo.m_CharBox.top;
244*3ac0a46fSAndroid Build Coastguard Worker   return true;
245*3ac0a46fSAndroid Build Coastguard Worker }
246*3ac0a46fSAndroid Build Coastguard Worker 
247*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page,int index,FS_RECTF * rect)248*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page, int index, FS_RECTF* rect) {
249*3ac0a46fSAndroid Build Coastguard Worker   if (!rect)
250*3ac0a46fSAndroid Build Coastguard Worker     return false;
251*3ac0a46fSAndroid Build Coastguard Worker 
252*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
253*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
254*3ac0a46fSAndroid Build Coastguard Worker     return false;
255*3ac0a46fSAndroid Build Coastguard Worker 
256*3ac0a46fSAndroid Build Coastguard Worker   *rect = FSRectFFromCFXFloatRect(textpage->GetCharLooseBounds(index));
257*3ac0a46fSAndroid Build Coastguard Worker   return true;
258*3ac0a46fSAndroid Build Coastguard Worker }
259*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetMatrix(FPDF_TEXTPAGE text_page,int index,FS_MATRIX * matrix)260*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetMatrix(FPDF_TEXTPAGE text_page,
261*3ac0a46fSAndroid Build Coastguard Worker                                                        int index,
262*3ac0a46fSAndroid Build Coastguard Worker                                                        FS_MATRIX* matrix) {
263*3ac0a46fSAndroid Build Coastguard Worker   if (!matrix)
264*3ac0a46fSAndroid Build Coastguard Worker     return false;
265*3ac0a46fSAndroid Build Coastguard Worker 
266*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
267*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
268*3ac0a46fSAndroid Build Coastguard Worker     return false;
269*3ac0a46fSAndroid Build Coastguard Worker 
270*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
271*3ac0a46fSAndroid Build Coastguard Worker   *matrix = FSMatrixFromCFXMatrix(charinfo.m_Matrix);
272*3ac0a46fSAndroid Build Coastguard Worker   return true;
273*3ac0a46fSAndroid Build Coastguard Worker }
274*3ac0a46fSAndroid Build Coastguard Worker 
275*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page,int index,double * x,double * y)276*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page,
277*3ac0a46fSAndroid Build Coastguard Worker                        int index,
278*3ac0a46fSAndroid Build Coastguard Worker                        double* x,
279*3ac0a46fSAndroid Build Coastguard Worker                        double* y) {
280*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
281*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
282*3ac0a46fSAndroid Build Coastguard Worker     return false;
283*3ac0a46fSAndroid Build Coastguard Worker 
284*3ac0a46fSAndroid Build Coastguard Worker   const CPDF_TextPage::CharInfo& charinfo = textpage->GetCharInfo(index);
285*3ac0a46fSAndroid Build Coastguard Worker   *x = charinfo.m_Origin.x;
286*3ac0a46fSAndroid Build Coastguard Worker   *y = charinfo.m_Origin.y;
287*3ac0a46fSAndroid Build Coastguard Worker   return true;
288*3ac0a46fSAndroid Build Coastguard Worker }
289*3ac0a46fSAndroid Build Coastguard Worker 
290*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page,double x,double y,double xTolerance,double yTolerance)291*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page,
292*3ac0a46fSAndroid Build Coastguard Worker                            double x,
293*3ac0a46fSAndroid Build Coastguard Worker                            double y,
294*3ac0a46fSAndroid Build Coastguard Worker                            double xTolerance,
295*3ac0a46fSAndroid Build Coastguard Worker                            double yTolerance) {
296*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
297*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
298*3ac0a46fSAndroid Build Coastguard Worker     return -3;
299*3ac0a46fSAndroid Build Coastguard Worker 
300*3ac0a46fSAndroid Build Coastguard Worker   return textpage->GetIndexAtPos(
301*3ac0a46fSAndroid Build Coastguard Worker       CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
302*3ac0a46fSAndroid Build Coastguard Worker       CFX_SizeF(static_cast<float>(xTolerance),
303*3ac0a46fSAndroid Build Coastguard Worker                 static_cast<float>(yTolerance)));
304*3ac0a46fSAndroid Build Coastguard Worker }
305*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetText(FPDF_TEXTPAGE page,int start_index,int char_count,unsigned short * result)306*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetText(FPDF_TEXTPAGE page,
307*3ac0a46fSAndroid Build Coastguard Worker                                                int start_index,
308*3ac0a46fSAndroid Build Coastguard Worker                                                int char_count,
309*3ac0a46fSAndroid Build Coastguard Worker                                                unsigned short* result) {
310*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(page);
311*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage || start_index < 0 || char_count < 0 || !result)
312*3ac0a46fSAndroid Build Coastguard Worker     return 0;
313*3ac0a46fSAndroid Build Coastguard Worker 
314*3ac0a46fSAndroid Build Coastguard Worker   int char_available = textpage->CountChars() - start_index;
315*3ac0a46fSAndroid Build Coastguard Worker   if (char_available <= 0)
316*3ac0a46fSAndroid Build Coastguard Worker     return 0;
317*3ac0a46fSAndroid Build Coastguard Worker 
318*3ac0a46fSAndroid Build Coastguard Worker   char_count = std::min(char_count, char_available);
319*3ac0a46fSAndroid Build Coastguard Worker   if (char_count == 0) {
320*3ac0a46fSAndroid Build Coastguard Worker     // Writing out "", which has a character count of 1 due to the NUL.
321*3ac0a46fSAndroid Build Coastguard Worker     *result = '\0';
322*3ac0a46fSAndroid Build Coastguard Worker     return 1;
323*3ac0a46fSAndroid Build Coastguard Worker   }
324*3ac0a46fSAndroid Build Coastguard Worker 
325*3ac0a46fSAndroid Build Coastguard Worker   WideString str = textpage->GetPageText(start_index, char_count);
326*3ac0a46fSAndroid Build Coastguard Worker 
327*3ac0a46fSAndroid Build Coastguard Worker   if (str.GetLength() > static_cast<size_t>(char_count))
328*3ac0a46fSAndroid Build Coastguard Worker     str = str.First(static_cast<size_t>(char_count));
329*3ac0a46fSAndroid Build Coastguard Worker 
330*3ac0a46fSAndroid Build Coastguard Worker   // UFT16LE_Encode doesn't handle surrogate pairs properly, so it is expected
331*3ac0a46fSAndroid Build Coastguard Worker   // the number of items to stay the same.
332*3ac0a46fSAndroid Build Coastguard Worker   ByteString byte_str = str.ToUTF16LE();
333*3ac0a46fSAndroid Build Coastguard Worker   size_t byte_str_len = byte_str.GetLength();
334*3ac0a46fSAndroid Build Coastguard Worker   size_t ret_count = byte_str_len / kBytesPerCharacter;
335*3ac0a46fSAndroid Build Coastguard Worker 
336*3ac0a46fSAndroid Build Coastguard Worker   // +1 to account for the NUL terminator.
337*3ac0a46fSAndroid Build Coastguard Worker   DCHECK_LE(ret_count, static_cast<size_t>(char_count) + 1);
338*3ac0a46fSAndroid Build Coastguard Worker 
339*3ac0a46fSAndroid Build Coastguard Worker   memcpy(result, byte_str.c_str(), byte_str_len);
340*3ac0a46fSAndroid Build Coastguard Worker   return pdfium::base::checked_cast<int>(ret_count);
341*3ac0a46fSAndroid Build Coastguard Worker }
342*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_CountRects(FPDF_TEXTPAGE text_page,int start,int count)343*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountRects(FPDF_TEXTPAGE text_page,
344*3ac0a46fSAndroid Build Coastguard Worker                                                   int start,
345*3ac0a46fSAndroid Build Coastguard Worker                                                   int count) {
346*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
347*3ac0a46fSAndroid Build Coastguard Worker   return textpage ? textpage->CountRects(start, count) : 0;
348*3ac0a46fSAndroid Build Coastguard Worker }
349*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetRect(FPDF_TEXTPAGE text_page,int rect_index,double * left,double * top,double * right,double * bottom)350*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetRect(FPDF_TEXTPAGE text_page,
351*3ac0a46fSAndroid Build Coastguard Worker                                                      int rect_index,
352*3ac0a46fSAndroid Build Coastguard Worker                                                      double* left,
353*3ac0a46fSAndroid Build Coastguard Worker                                                      double* top,
354*3ac0a46fSAndroid Build Coastguard Worker                                                      double* right,
355*3ac0a46fSAndroid Build Coastguard Worker                                                      double* bottom) {
356*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
357*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
358*3ac0a46fSAndroid Build Coastguard Worker     return false;
359*3ac0a46fSAndroid Build Coastguard Worker 
360*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rect;
361*3ac0a46fSAndroid Build Coastguard Worker   bool result = textpage->GetRect(rect_index, &rect);
362*3ac0a46fSAndroid Build Coastguard Worker 
363*3ac0a46fSAndroid Build Coastguard Worker   *left = rect.left;
364*3ac0a46fSAndroid Build Coastguard Worker   *top = rect.top;
365*3ac0a46fSAndroid Build Coastguard Worker   *right = rect.right;
366*3ac0a46fSAndroid Build Coastguard Worker   *bottom = rect.bottom;
367*3ac0a46fSAndroid Build Coastguard Worker   return result;
368*3ac0a46fSAndroid Build Coastguard Worker }
369*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page,double left,double top,double right,double bottom,unsigned short * buffer,int buflen)370*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page,
371*3ac0a46fSAndroid Build Coastguard Worker                                                       double left,
372*3ac0a46fSAndroid Build Coastguard Worker                                                       double top,
373*3ac0a46fSAndroid Build Coastguard Worker                                                       double right,
374*3ac0a46fSAndroid Build Coastguard Worker                                                       double bottom,
375*3ac0a46fSAndroid Build Coastguard Worker                                                       unsigned short* buffer,
376*3ac0a46fSAndroid Build Coastguard Worker                                                       int buflen) {
377*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
378*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
379*3ac0a46fSAndroid Build Coastguard Worker     return 0;
380*3ac0a46fSAndroid Build Coastguard Worker 
381*3ac0a46fSAndroid Build Coastguard Worker   CFX_FloatRect rect((float)left, (float)bottom, (float)right, (float)top);
382*3ac0a46fSAndroid Build Coastguard Worker   WideString str = textpage->GetTextByRect(rect);
383*3ac0a46fSAndroid Build Coastguard Worker 
384*3ac0a46fSAndroid Build Coastguard Worker   if (buflen <= 0 || !buffer)
385*3ac0a46fSAndroid Build Coastguard Worker     return pdfium::base::checked_cast<int>(str.GetLength());
386*3ac0a46fSAndroid Build Coastguard Worker 
387*3ac0a46fSAndroid Build Coastguard Worker   ByteString cbUTF16Str = str.ToUTF16LE();
388*3ac0a46fSAndroid Build Coastguard Worker   int len = pdfium::base::checked_cast<int>(cbUTF16Str.GetLength()) /
389*3ac0a46fSAndroid Build Coastguard Worker             sizeof(unsigned short);
390*3ac0a46fSAndroid Build Coastguard Worker   int size = buflen > len ? len : buflen;
391*3ac0a46fSAndroid Build Coastguard Worker   memcpy(buffer, cbUTF16Str.c_str(), size * sizeof(unsigned short));
392*3ac0a46fSAndroid Build Coastguard Worker   cbUTF16Str.ReleaseBuffer(size * sizeof(unsigned short));
393*3ac0a46fSAndroid Build Coastguard Worker   return size;
394*3ac0a46fSAndroid Build Coastguard Worker }
395*3ac0a46fSAndroid Build Coastguard Worker 
396*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_SCHHANDLE FPDF_CALLCONV
FPDFText_FindStart(FPDF_TEXTPAGE text_page,FPDF_WIDESTRING findwhat,unsigned long flags,int start_index)397*3ac0a46fSAndroid Build Coastguard Worker FPDFText_FindStart(FPDF_TEXTPAGE text_page,
398*3ac0a46fSAndroid Build Coastguard Worker                    FPDF_WIDESTRING findwhat,
399*3ac0a46fSAndroid Build Coastguard Worker                    unsigned long flags,
400*3ac0a46fSAndroid Build Coastguard Worker                    int start_index) {
401*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
402*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
403*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
404*3ac0a46fSAndroid Build Coastguard Worker 
405*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPageFind::Options options;
406*3ac0a46fSAndroid Build Coastguard Worker   options.bMatchCase = !!(flags & FPDF_MATCHCASE);
407*3ac0a46fSAndroid Build Coastguard Worker   options.bMatchWholeWord = !!(flags & FPDF_MATCHWHOLEWORD);
408*3ac0a46fSAndroid Build Coastguard Worker   options.bConsecutive = !!(flags & FPDF_CONSECUTIVE);
409*3ac0a46fSAndroid Build Coastguard Worker   auto find = CPDF_TextPageFind::Create(
410*3ac0a46fSAndroid Build Coastguard Worker       textpage, WideStringFromFPDFWideString(findwhat), options,
411*3ac0a46fSAndroid Build Coastguard Worker       start_index >= 0 ? absl::optional<size_t>(start_index) : absl::nullopt);
412*3ac0a46fSAndroid Build Coastguard Worker 
413*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
414*3ac0a46fSAndroid Build Coastguard Worker   return FPDFSchHandleFromCPDFTextPageFind(find.release());
415*3ac0a46fSAndroid Build Coastguard Worker }
416*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_FindNext(FPDF_SCHHANDLE handle)417*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindNext(FPDF_SCHHANDLE handle) {
418*3ac0a46fSAndroid Build Coastguard Worker   if (!handle)
419*3ac0a46fSAndroid Build Coastguard Worker     return false;
420*3ac0a46fSAndroid Build Coastguard Worker 
421*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPageFind* textpageFind = CPDFTextPageFindFromFPDFSchHandle(handle);
422*3ac0a46fSAndroid Build Coastguard Worker   return textpageFind->FindNext();
423*3ac0a46fSAndroid Build Coastguard Worker }
424*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_FindPrev(FPDF_SCHHANDLE handle)425*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindPrev(FPDF_SCHHANDLE handle) {
426*3ac0a46fSAndroid Build Coastguard Worker   if (!handle)
427*3ac0a46fSAndroid Build Coastguard Worker     return false;
428*3ac0a46fSAndroid Build Coastguard Worker 
429*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPageFind* textpageFind = CPDFTextPageFindFromFPDFSchHandle(handle);
430*3ac0a46fSAndroid Build Coastguard Worker   return textpageFind->FindPrev();
431*3ac0a46fSAndroid Build Coastguard Worker }
432*3ac0a46fSAndroid Build Coastguard Worker 
433*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle)434*3ac0a46fSAndroid Build Coastguard Worker FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) {
435*3ac0a46fSAndroid Build Coastguard Worker   if (!handle)
436*3ac0a46fSAndroid Build Coastguard Worker     return 0;
437*3ac0a46fSAndroid Build Coastguard Worker 
438*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPageFind* textpageFind = CPDFTextPageFindFromFPDFSchHandle(handle);
439*3ac0a46fSAndroid Build Coastguard Worker   return textpageFind->GetCurOrder();
440*3ac0a46fSAndroid Build Coastguard Worker }
441*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_GetSchCount(FPDF_SCHHANDLE handle)442*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetSchCount(FPDF_SCHHANDLE handle) {
443*3ac0a46fSAndroid Build Coastguard Worker   if (!handle)
444*3ac0a46fSAndroid Build Coastguard Worker     return 0;
445*3ac0a46fSAndroid Build Coastguard Worker 
446*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPageFind* textpageFind = CPDFTextPageFindFromFPDFSchHandle(handle);
447*3ac0a46fSAndroid Build Coastguard Worker   return textpageFind->GetMatchedCount();
448*3ac0a46fSAndroid Build Coastguard Worker }
449*3ac0a46fSAndroid Build Coastguard Worker 
FPDFText_FindClose(FPDF_SCHHANDLE handle)450*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT void FPDF_CALLCONV FPDFText_FindClose(FPDF_SCHHANDLE handle) {
451*3ac0a46fSAndroid Build Coastguard Worker   if (!handle)
452*3ac0a46fSAndroid Build Coastguard Worker     return;
453*3ac0a46fSAndroid Build Coastguard Worker 
454*3ac0a46fSAndroid Build Coastguard Worker   // Take ownership back from caller and destroy.
455*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CPDF_TextPageFind> textpageFind(
456*3ac0a46fSAndroid Build Coastguard Worker       CPDFTextPageFindFromFPDFSchHandle(handle));
457*3ac0a46fSAndroid Build Coastguard Worker }
458*3ac0a46fSAndroid Build Coastguard Worker 
459*3ac0a46fSAndroid Build Coastguard Worker // web link
460*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_PAGELINK FPDF_CALLCONV
FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page)461*3ac0a46fSAndroid Build Coastguard Worker FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) {
462*3ac0a46fSAndroid Build Coastguard Worker   CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
463*3ac0a46fSAndroid Build Coastguard Worker   if (!textpage)
464*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
465*3ac0a46fSAndroid Build Coastguard Worker 
466*3ac0a46fSAndroid Build Coastguard Worker   auto pagelink = std::make_unique<CPDF_LinkExtract>(textpage);
467*3ac0a46fSAndroid Build Coastguard Worker   pagelink->ExtractLinks();
468*3ac0a46fSAndroid Build Coastguard Worker 
469*3ac0a46fSAndroid Build Coastguard Worker   // Caller takes ownership.
470*3ac0a46fSAndroid Build Coastguard Worker   return FPDFPageLinkFromCPDFLinkExtract(pagelink.release());
471*3ac0a46fSAndroid Build Coastguard Worker }
472*3ac0a46fSAndroid Build Coastguard Worker 
FPDFLink_CountWebLinks(FPDF_PAGELINK link_page)473*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) {
474*3ac0a46fSAndroid Build Coastguard Worker   if (!link_page)
475*3ac0a46fSAndroid Build Coastguard Worker     return 0;
476*3ac0a46fSAndroid Build Coastguard Worker 
477*3ac0a46fSAndroid Build Coastguard Worker   CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
478*3ac0a46fSAndroid Build Coastguard Worker   return pdfium::base::checked_cast<int>(pageLink->CountLinks());
479*3ac0a46fSAndroid Build Coastguard Worker }
480*3ac0a46fSAndroid Build Coastguard Worker 
FPDFLink_GetURL(FPDF_PAGELINK link_page,int link_index,unsigned short * buffer,int buflen)481*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetURL(FPDF_PAGELINK link_page,
482*3ac0a46fSAndroid Build Coastguard Worker                                               int link_index,
483*3ac0a46fSAndroid Build Coastguard Worker                                               unsigned short* buffer,
484*3ac0a46fSAndroid Build Coastguard Worker                                               int buflen) {
485*3ac0a46fSAndroid Build Coastguard Worker   WideString wsUrl(L"");
486*3ac0a46fSAndroid Build Coastguard Worker   if (link_page && link_index >= 0) {
487*3ac0a46fSAndroid Build Coastguard Worker     CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
488*3ac0a46fSAndroid Build Coastguard Worker     wsUrl = pageLink->GetURL(link_index);
489*3ac0a46fSAndroid Build Coastguard Worker   }
490*3ac0a46fSAndroid Build Coastguard Worker   ByteString cbUTF16URL = wsUrl.ToUTF16LE();
491*3ac0a46fSAndroid Build Coastguard Worker   int required = pdfium::base::checked_cast<int>(cbUTF16URL.GetLength() /
492*3ac0a46fSAndroid Build Coastguard Worker                                                  sizeof(unsigned short));
493*3ac0a46fSAndroid Build Coastguard Worker   if (!buffer || buflen <= 0)
494*3ac0a46fSAndroid Build Coastguard Worker     return required;
495*3ac0a46fSAndroid Build Coastguard Worker 
496*3ac0a46fSAndroid Build Coastguard Worker   int size = std::min(required, buflen);
497*3ac0a46fSAndroid Build Coastguard Worker   if (size > 0) {
498*3ac0a46fSAndroid Build Coastguard Worker     int buf_size = size * sizeof(unsigned short);
499*3ac0a46fSAndroid Build Coastguard Worker     memcpy(buffer, cbUTF16URL.c_str(), buf_size);
500*3ac0a46fSAndroid Build Coastguard Worker   }
501*3ac0a46fSAndroid Build Coastguard Worker   return size;
502*3ac0a46fSAndroid Build Coastguard Worker }
503*3ac0a46fSAndroid Build Coastguard Worker 
FPDFLink_CountRects(FPDF_PAGELINK link_page,int link_index)504*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountRects(FPDF_PAGELINK link_page,
505*3ac0a46fSAndroid Build Coastguard Worker                                                   int link_index) {
506*3ac0a46fSAndroid Build Coastguard Worker   if (!link_page || link_index < 0)
507*3ac0a46fSAndroid Build Coastguard Worker     return 0;
508*3ac0a46fSAndroid Build Coastguard Worker 
509*3ac0a46fSAndroid Build Coastguard Worker   CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
510*3ac0a46fSAndroid Build Coastguard Worker   return fxcrt::CollectionSize<int>(pageLink->GetRects(link_index));
511*3ac0a46fSAndroid Build Coastguard Worker }
512*3ac0a46fSAndroid Build Coastguard Worker 
FPDFLink_GetRect(FPDF_PAGELINK link_page,int link_index,int rect_index,double * left,double * top,double * right,double * bottom)513*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetRect(FPDF_PAGELINK link_page,
514*3ac0a46fSAndroid Build Coastguard Worker                                                      int link_index,
515*3ac0a46fSAndroid Build Coastguard Worker                                                      int rect_index,
516*3ac0a46fSAndroid Build Coastguard Worker                                                      double* left,
517*3ac0a46fSAndroid Build Coastguard Worker                                                      double* top,
518*3ac0a46fSAndroid Build Coastguard Worker                                                      double* right,
519*3ac0a46fSAndroid Build Coastguard Worker                                                      double* bottom) {
520*3ac0a46fSAndroid Build Coastguard Worker   if (!link_page || link_index < 0 || rect_index < 0)
521*3ac0a46fSAndroid Build Coastguard Worker     return false;
522*3ac0a46fSAndroid Build Coastguard Worker 
523*3ac0a46fSAndroid Build Coastguard Worker   CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
524*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CFX_FloatRect> rectArray = pageLink->GetRects(link_index);
525*3ac0a46fSAndroid Build Coastguard Worker   if (rect_index >= fxcrt::CollectionSize<int>(rectArray))
526*3ac0a46fSAndroid Build Coastguard Worker     return false;
527*3ac0a46fSAndroid Build Coastguard Worker 
528*3ac0a46fSAndroid Build Coastguard Worker   *left = rectArray[rect_index].left;
529*3ac0a46fSAndroid Build Coastguard Worker   *right = rectArray[rect_index].right;
530*3ac0a46fSAndroid Build Coastguard Worker   *top = rectArray[rect_index].top;
531*3ac0a46fSAndroid Build Coastguard Worker   *bottom = rectArray[rect_index].bottom;
532*3ac0a46fSAndroid Build Coastguard Worker   return true;
533*3ac0a46fSAndroid Build Coastguard Worker }
534*3ac0a46fSAndroid Build Coastguard Worker 
535*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFLink_GetTextRange(FPDF_PAGELINK link_page,int link_index,int * start_char_index,int * char_count)536*3ac0a46fSAndroid Build Coastguard Worker FPDFLink_GetTextRange(FPDF_PAGELINK link_page,
537*3ac0a46fSAndroid Build Coastguard Worker                       int link_index,
538*3ac0a46fSAndroid Build Coastguard Worker                       int* start_char_index,
539*3ac0a46fSAndroid Build Coastguard Worker                       int* char_count) {
540*3ac0a46fSAndroid Build Coastguard Worker   if (!link_page || link_index < 0)
541*3ac0a46fSAndroid Build Coastguard Worker     return false;
542*3ac0a46fSAndroid Build Coastguard Worker 
543*3ac0a46fSAndroid Build Coastguard Worker   CPDF_LinkExtract* page_link = CPDFLinkExtractFromFPDFPageLink(link_page);
544*3ac0a46fSAndroid Build Coastguard Worker   auto maybe_range = page_link->GetTextRange(link_index);
545*3ac0a46fSAndroid Build Coastguard Worker   if (!maybe_range.has_value())
546*3ac0a46fSAndroid Build Coastguard Worker     return false;
547*3ac0a46fSAndroid Build Coastguard Worker 
548*3ac0a46fSAndroid Build Coastguard Worker   *start_char_index =
549*3ac0a46fSAndroid Build Coastguard Worker       pdfium::base::checked_cast<int>(maybe_range.value().m_Start);
550*3ac0a46fSAndroid Build Coastguard Worker   *char_count = pdfium::base::checked_cast<int>(maybe_range.value().m_Count);
551*3ac0a46fSAndroid Build Coastguard Worker   return true;
552*3ac0a46fSAndroid Build Coastguard Worker }
553*3ac0a46fSAndroid Build Coastguard Worker 
FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page)554*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT void FPDF_CALLCONV FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page) {
555*3ac0a46fSAndroid Build Coastguard Worker   delete CPDFLinkExtractFromFPDFPageLink(link_page);
556*3ac0a46fSAndroid Build Coastguard Worker }
557