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