Tôi đang sử dụng PoDoFo để trích xuất các chuyển vị ký tự nhằm cập nhật chính xác ma trận văn bản. Đây là một đoạn mã của tôi:
PdfString str, ucode_str;
std::stack *stack;
const PdfFontMetrics *f_metrics;
...
/*Chuyển chuỗi sang UTF8 */
str = stack->top().GetString();
ucode_str = ts->font->GetEncoding()->ConvertToUnicode(str, ts->font);
ngăn xếp->pop();
c_str = (char *) ucode_str.GetStringUtf8().c_str();
/* Số liệu phông chữ để có được độ dịch chuyển ký tự */
f_metrics = ts->font->GetFontMetrics();
for (j = 0; j < strlen(c_str); j++) {
str_w = f_metrics->CharWidth(c_str[j]);
/* Điều chỉnh ma trận văn bản bằng str_w */
...
}
Nó hoạt động với một số tệp PDF (str_w
Chứa các chiều rộng hữu ích), nhưng không hoạt động với các tệp khác. Trong những trường hợp này,str_w
包含 0,0
. Tôi đã kiểm tra PoDoFo 0,9,5
Mã nguồn, đã tìm thấy CharWidth()
là dành cho Số liệu phông chữ Pdf
Được thực hiện bởi tất cả các lớp con.
Tôi có thiếu điều gì quan trọng trong quá trình chuyển đổi chuỗi này không?
Cập nhật ngày 4 tháng 8 năm 2017
@mkl đã thực hiện rất tốt việc xem xét mã của PoDoFo. Tuy nhiên, tôi nhận ra rằng tôi phải lấy một số thông số khác. Nói chính xác hơn, tôi cần mộtđơn vị không gian văn bảnbày tỏchiều rộng glyph(参见Tài liệu tham khảo PDF 1.7,5.1.3 Định vị và chỉ báo Glyph),但是 CharWidth()
是在 PdfFontMetricsObject.cpp
được thực hiện trong, ví dụ:
double PdfFontMetricsObject::CharWidth(unsigned char c) const
{
if (c >= m_nĐầu tiên && c <= m_nCuối &&
c - m_nFirst < static_cast(m_width.GetSize())) {
gấp đôi dWidth = m_width[c - m_nFirst].GetReal();
return (dWidth * m_matrix.front().GetReal() * this->GetFontSize() + this->GetFontCharSpace()) * this->GetFontScale() / 100.0;
}
nếu (m_missingWidth != NULL)
trả về m_missingWidth->GetReal();
khác
trả về m_dDefWidth;
}
Chiều rộng được tính bằng cách sử dụng các hệ số nhân bổ sung (chẳng hạn như cỡ chữ, khoảng cách ký tự, v.v.). tất cả những gì tôi thực sự cần là dWidth * m_matrix.front().GetReal()
. Vì vậy tôi quyết định triển khai từ cùng một tệp GetGlyphWidth(int c)
,例如:
gấp đôi PdfFontMetricsObject::GetGlyphWidth(int c) const
{
if (c >= m_nĐầu tiên && c <= m_nCuối &&
c - m_nFirst < static_cast(m_width.GetSize())) {
gấp đôi dWidth = m_width[c - m_nFirst].GetReal();
trả về dWidth * m_matrix.front().GetReal();
}
trả về 0,0;
}
và gọi cái này thay vì cái đầu tiên trong danh sách CharWidth()
.
Nếu tôi hiểu chính xác mã Podofo (tôi thực sự không phải là chuyên gia về Podofo...),Đối tượng số liệu phông chữ Pdf
Lớp được sử dụng để thể hiện các đặc tả phông chữ có trong các tệp PDF hiện có:
/** Tạo đối tượng số liệu phông chữ dựa trên PdfObject hiện có
*
* \param pObject một đối tượng mô tả phông chữ hiện có
* \param pEncoding một PdfEncoding sẽ KHÔNG thuộc sở hữu của PdfFontMetricsObject
*/
PdfFontMetricsObject( PdfObject* pFont, PdfObject* pDescriptor, const PdfEncoding* const pEncoding );
Đây là phương phápCharWidth
Đây là cách nó đạt được:
double PdfFontMetricsObject::CharWidth( unsigned char c ) const
{
if( c >= m_nĐầu tiên && c <= m_nCuối cùng
&& c - m_nFirst < static_cast(m_width.GetSize()) )
{
gấp đôi dWidth = m_width[c - m_nFirst].GetReal();
return (dWidth * m_matrix.front().GetReal() * this->GetFontSize() + this->GetFontCharSpace()) * this->GetFontScale() / 100.0;
}
if( m_missingWidth != NULL )
trả về m_missingWidth->GetReal ();
khác
trả về m_dDefWidth;
}
Đặc biệt là nhìn thấy các thông số c
Mã hóa không dựa trên mã hóa phông chữ mà được để tra cứu trong mảng độ rộng. Do đó, có vẻ như đầu vào dự kiến cho phương thức này không phải là mã ký tự ASCII hoặc ANSI mà là ID glyph thô.
Mặt khác, mã của bạn đã chuyển đổi ID glyph thành Unicode trong UTF-8, vì vậy về cơ bản nó đang cố tra cứu bằng mã ký tự ANSI.
Điều này sẽ khớp với tài liệu mẫu, bảng mã phông chữ điển hình trong tệp PDF xử lý lỗi như sau
28 0 đối tượng
<<
/sự khác biệt[0/B/G/W/a/d/e/f/g 9/i/l/n/o/p/r/dấu cách/t/w]
/BaseEncoding/MacRomanEncoding
/Loại/Mã hóa
>>
endobj
Mã Glyph bắt đầu từ 0 (đầu tiênchar) đến 17 (LastChar),hoặc
12 0 đối tượng
<<
/Sự khác biệt[1/A/B/C/D/F/I/L/M/N/O/P/R/T/U/a/c/d
/độ/e/tám/f/năm/bốn/g/h
27/i/l/m/n/o/one/p/parenleft/parenright
/thời gian/r/đã đăng ký/s/dấu cách
/t/ba/hai/u/w/zero]
/BaseEncoding/MacRomanEncoding
/Loại/Mã hóa
>>
endobj
Mã Glyph bắt đầu từ 1 (đầu tiênchar) đến 46 (LastChar).
Vì vậy, các mã hóa này xử lý mã glyph cho tất cả các glyph bắt buộc bắt đầu từ 0 và không thực sự bao gồm nhiều glyph đó
Do đó, đối với tất cả các giá trị ký tự lớn hơn 17 hoặc lớn hơn 46,CharWidth
sẽ trở lại 0
, có nghĩa là tất cả (trong trường hợp trước) hoặc hầu hết (trong trường hợp sau) các ký tự không điều khiển ANSI.
Mặt khác, mã hóa phông chữ điển hình trong tệp PDF được xử lý đúng cách sẽ trông như thế này:
1511 0 đối tượng
<<
/Loại/Mã hóa
/BaseEncoding/WinAnsiEncoding
/Sự khác biệt[
1/Đồng bằng/Theta
8/Phi
11/ff/fi/fl/ffi
39/trích dẫn
]
>>
endobj
Mã Glyph bắt đầu từ 1 (đầu tiênchar) đến 122 (LastChar).
Các mã hóa này về cơ bản là WinAnsiEncoding, một lượng nhỏ nội dung đã được thêm vào các giá trị thấp hơn, đặc biệt là các giá trị ký tự điều khiển.
Vì vậy, những gì bạn có thể làm là lặp đi lặp lại str
Mã Glyph trong (cho phép bạn gọi CharWidth
) và chuyển đổi chúng riêng lẻ sang Unicode nếu cần trước tiên bằng cách str
Chuyển đổi sang Unicode ucode_str
, sau đó lặp lại ucode_str
Các ký tự ANSI trong .
Tôi là một lập trình viên xuất sắc, rất giỏi!