OFD 文本页与搜索
本节介绍 TextPage 的文本提取、TextSearch 的页面内与全文档搜索,以及 TextPageSelect 的选区分析能力,适用于全文检索、复制文本、按字符遍历与选区高亮等场景。
任务场景
- 从 OFD 页面提取纯文本或按字符遍历。
- 在单页或整个 OFD 文件包内搜索指定关键字并获取命中矩形。
- 根据页面坐标定义选区,获取选中字符串与高亮矩形(具体 UI 由应用实现)。
API 概览
| 功能 | C++ API(foxit::ofd) | 核心参数 / 描述 |
|---|---|---|
| 文本页 | TextPage | 构造参数为 OFDPage;GetText、GetCharInfoCount、GetCharInfo |
| 字符信息 | TextPageCharInfo | char_code、rect(字符外接矩形) |
| 文本导出 | TextPage::ExportToFile | 将整页文本导出到文件 |
| 文本搜索 | TextSearch | 构造:TextSearch(OFDPackage, keyword) 全包搜索;TextSearch(OFDPage, keyword) 单页搜索 |
| 搜索结果 | TextSearchResultInfo | page_index、rect_size、char_info_size 等 |
| 命中矩形 | TextSearch::GetResultRect | 按结果索引与矩形索引取得 FX_RECT |
| 文本选区 | TextPageSelect | 构造参数为 OFDPage;SetMode、SetRange、GetText、GetRect |
提取页面文本
TextPage 由 OFDPage 构造。可调用 GetText 获取指定范围的文本,或使用 GetCharInfoCount、GetCharInfo 按字符访问位置与 Unicode 编码;也可通过 ExportToFile 将整页文本导出到文件。
c++
#include "ofd/fs_ofdpackage.h"
#include "ofd/fs_ofddoc.h"
#include "ofd/fs_ofdpage.h"
#include "ofd/fs_ofdtextpage.h"
using namespace foxit;
using namespace foxit::ofd;
void ExtractOFDPageText(const wchar_t* input_file) {
OFDPackage package(input_file);
if (package.IsEmpty() || package.GetDocumentCount() <= 0) {
return;
}
OFDDoc doc = package.LoadDocument(0, "");
if (doc.IsEmpty() || doc.GetPageCount() <= 0) {
return;
}
OFDPage page = doc.GetPage(0);
if (page.IsEmpty()) {
return;
}
TextPage text_page(page);
if (text_page.IsEmpty()) {
return;
}
int char_count = text_page.GetCharInfoCount();
if (char_count <= 0) {
return;
}
String text = text_page.GetText(0, char_count);
TextPageCharInfo first_char = text_page.GetCharInfo(0);
float char_left = first_char.rect.left;
uint32 char_code = first_char.char_code;
}
java
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.OFDPackage;
import com.foxit.sdk.ofd.OFDPage;
import com.foxit.sdk.ofd.TextPage;
import com.foxit.sdk.ofd.TextPageCharInfo;
public class OFDTextExtract {
public static void extractOFDPageText(String inputFile) throws Exception {
OFDPackage pkg = new OFDPackage(inputFile);
if (pkg.isEmpty() || pkg.getDocumentCount() <= 0) {
return;
}
OFDDoc doc = pkg.loadDocument(0, null);
if (doc.isEmpty() || doc.getPageCount() <= 0) {
return;
}
OFDPage page = doc.getPage(0);
if (page.isEmpty()) {
return;
}
TextPage textPage = new TextPage(page);
if (textPage.isEmpty()) {
return;
}
int charCount = textPage.getCharInfoCount();
if (charCount <= 0) {
return;
}
String text = textPage.getText(0, charCount);
TextPageCharInfo firstChar = textPage.getCharInfo(0);
}
}
页面内搜索
TextSearch 在构造时传入关键字并完成搜索。可通过 OFDPackage 搜索整个文件包内所有文档与页面,也可通过 OFDPage 限定在当前页内搜索。
构造完成后,调用 GetResultCount 获取命中总数,通过 GetResult 读取每条结果的页码、矩形数量等元信息;使用 GetResultRect 获取命中矩形(用于高亮绘制),GetResultCenter 获取中心点(用于视图跳转)。多页场景下还可使用 GetResultCountInPage 与 GetResultCenterInPage 按页遍历结果。
c++
#include "ofd/fs_ofdpackage.h"
#include "ofd/fs_ofddoc.h"
#include "ofd/fs_ofdpage.h"
#include "ofd/fs_ofdtextsearch.h"
using namespace foxit;
using namespace foxit::ofd;
void SearchInOFDPackage(const wchar_t* input_file, const char* keyword) {
OFDPackage package(input_file);
if (package.IsEmpty()) {
return;
}
TextSearch search(package, String(keyword));
if (search.IsEmpty()) {
return;
}
int result_count = search.GetResultCount();
for (int i = 0; i < result_count; ++i) {
TextSearchResultInfo info = search.GetResult(i);
int page_index = info.page_index;
for (int j = 0; j < info.rect_size; ++j) {
FX_RECT rect = search.GetResultRect(i, j);
}
PointF center = search.GetResultCenter(i);
}
}
void SearchInOFDPage(OFDPage& page, const char* keyword) {
if (page.IsEmpty()) {
return;
}
TextSearch search(page, String(keyword));
if (search.IsEmpty()) {
return;
}
int result_count = search.GetResultCount();
for (int i = 0; i < result_count; ++i) {
TextSearchResultInfo info = search.GetResult(i);
PointF center = search.GetResultCenter(i);
}
}
java
import com.foxit.sdk.common.fxcrt.PointF;
import com.foxit.sdk.common.fxcrt.RectI;
import com.foxit.sdk.ofd.OFDDoc;
import com.foxit.sdk.ofd.OFDPackage;
import com.foxit.sdk.ofd.OFDPage;
import com.foxit.sdk.ofd.TextSearch;
import com.foxit.sdk.ofd.TextSearchResultInfo;
public class OFDTextSearchExample {
public static void searchInOFDPackage(String inputFile, String keyword) throws Exception {
OFDPackage pkg = new OFDPackage(inputFile);
if (pkg.isEmpty()) {
return;
}
TextSearch search = new TextSearch(pkg, keyword);
if (search.isEmpty()) {
return;
}
int resultCount = search.getResultCount();
for (int i = 0; i < resultCount; i++) {
TextSearchResultInfo info = search.getResult(i);
int pageIndex = info.getPage_index();
for (int j = 0; j < info.getRect_size(); j++) {
RectI rect = search.getResultRect(i, j);
}
PointF center = search.getResultCenter(i);
}
}
public static void searchInOFDPage(OFDPage page, String keyword) throws Exception {
if (page.isEmpty()) {
return;
}
TextSearch search = new TextSearch(page, keyword);
if (search.isEmpty()) {
return;
}
int resultCount = search.getResultCount();
for (int i = 0; i < resultCount; i++) {
TextSearchResultInfo info = search.getResult(i);
PointF center = search.getResultCenter(i);
}
}
}
文本选择与交互
TextPageSelect 由 OFDPage 构造,用于根据页面坐标计算选区。通过 SetMode 切换选择模式:e_ModeRectBox(矩形框选)或 e_ModeParagraph(段落选择);调用 SetRange 传入起点与终点坐标后,可通过 GetText 获取选中字符串,通过 GetRectCount 与 GetRect 获取高亮矩形列表。
c++
#include "ofd/fs_ofdpage.h"
#include "ofd/fs_ofdtextpage.h"
using namespace foxit;
using namespace foxit::ofd;
void SelectTextInOFDPage(OFDPage& page) {
if (page.IsEmpty()) {
return;
}
TextPageSelect text_select(page);
if (text_select.IsEmpty()) {
return;
}
text_select.SetMode(TextPageSelect::e_ModeRectBox);
text_select.SetRange(PointF(0.0f, 0.0f), PointF(100.0f, 100.0f));
String selected_text = text_select.GetText();
int rect_count = text_select.GetRectCount();
for (int i = 0; i < rect_count; ++i) {
RectF highlight_rect = text_select.GetRect(i);
}
}
java
import com.foxit.sdk.common.fxcrt.PointF;
import com.foxit.sdk.common.fxcrt.RectF;
import com.foxit.sdk.ofd.OFDPage;
import com.foxit.sdk.ofd.TextPageSelect;
public class OFDTextSelectExample {
public static void selectTextInOFDPage(OFDPage page) throws Exception {
if (page.isEmpty()) {
return;
}
TextPageSelect textSelect = new TextPageSelect(page);
if (textSelect.isEmpty()) {
return;
}
textSelect.setMode(TextPageSelect.e_ModeRectBox);
textSelect.setRange(new PointF(0.0f, 0.0f), new PointF(100.0f, 100.0f));
String selectedText = textSelect.getText();
int rectCount = textSelect.getRectCount();
for (int i = 0; i < rectCount; i++) {
RectF highlightRect = textSelect.getRect(i);
}
}
}
段落选择模式下,将 SetMode 的参数改为 e_ModeParagraph(Java:TextPageSelect.e_ModeParagraph),再调用 SetRange 即可按段落规则扩展选区。
注意事项
- 文本提取结果依赖 OFD 内嵌文本与版面结构,扫描件或纯路径文本可能无法得到完整字符串。
TextSearch在构造时即完成搜索;关键字不存在时GetResultCount返回0。GetResultRect返回的矩形坐标系与页面坐标一致,绘制高亮前请结合页面显示矩阵进行变换,详见 OFD 渲染。- 选区坐标为页面坐标(单位与 OFD 页面一致),应用层需将鼠标/触摸位置转换为页面坐标后再调用
SetRange。