문제

내 프로그램은 요청에 따라 비교적 간단한 PDF 문서를 생성하지만 Kanji 또는 Odd Math Symber와 같은 유니 코드 문자에 문제가 있습니다. PDF에 일반 문자열을 작성하려면 괄호 안에 놓습니다.

(something)

Octal 코드로 캐릭터를 탈출 할 수있는 옵션도 있습니다.

(\527)

그러나 이것은 최대 512 자만 이어집니다. 더 높은 캐릭터를 인코딩하거나 탈출하는 방법은 무엇입니까? 바이트 스트림과 육각형 인코딩 문자열에 대한 언급을 보았지만 내가 읽은 참조 중 어느 것도 실제로 어떻게 해야하는지 말해주지 않는 것 같습니다.


편집하다: 또는 저를 위해 일을 할 좋은 Java PDF 라이브러리를 지적하십시오. 내가 현재 사용하고있는 것은 gnujpdf의 버전입니다 (원래 저자가 AWOL이 발생한 것처럼 보이기 때문에 몇 가지 버그를 수정 한 것), AWT 그래픽 인터페이스에 대해 프로그래밍 할 수 있으며 이상적으로는 모든 교체가해야합니다. 똑같다.

대안은 HTML-> PDF 또는 HTML과 매우 유사한 단락 및 상자를 기반으로 한 프로그래밍 모델 인 것 같습니다. itext는 후자의 예입니다. 이것은 기존 코드를 다시 작성하는 것을 의미하며, 그들이 배치 할 때 나에게 동일한 유연성을 줄 것이라고 확신하지는 않습니다.


편집 2 : 나는 전에는 알지 못했지만 ITEXT 라이브러리에는 Graphics2D API가 있으며 유니 코드를 완벽하게 처리하는 것처럼 보이므로 내가 사용할 것입니다. 질문에 대한 질문에 대한 답은 아니지만 문제를 해결합니다.


편집 3 : itext는 나를 위해 잘 작동합니다. 나는 교훈이 무의미하게 어려워 보이는 무언가에 직면했을 때, 당신보다 그것에 대해 더 많이 아는 사람을 찾는 것 같아요.

도움이 되었습니까?

해결책

간단한 대답은 간단한 대답이 없다는 것입니다. PDF 사양을 살펴보면 텍스트 디스플레이의 메커니즘에 전념하는 전체 장과 그 장이 표시됩니다. 회사에 대한 모든 PDF 지원을 구현했으며 텍스트를 처리하는 것이 가장 복잡한 운동 부분이었습니다. PDF 파일에 대한 매우 구체적인 특수 목적 요구 사항이 없다면 발견 한 솔루션 (제 3 자 라이브러리를 사용하여 작업을 수행합니다.

다른 팁

3 장의 PDF 참조에서 이것은 유니 코드에 대해 말하는 것입니다.

텍스트 문자열은 pdfdocencoding 또는 유니 코드 문자 인코딩에서 인코딩됩니다. pdfdocencoding은 ISO 라틴 1 인코딩의 슈퍼 세트이며 부록 D에 문서화되어 있습니다. 유니 코드는 유니 코드 컨소시엄에 의해 유니 코드 표준에 설명되어 있습니다 (참고 문헌 참조). 유니 코드로 인코딩 된 텍스트 문자열의 경우, 처음 두 바이트는 254이어야합니다. 유니 코드 표준에 지정됩니다. (이 메커니즘은 Pdfdocencoding을 사용하여 문자열을 시작하는 것을 배제합니다.

Algoman의 대답입니다 잘못된 많은 것들에서. 너 ~할 수 있다 유니 코드가있는 PDF 문서를 작성하고 로켓 과학은 아니지만 일부 작업이 필요합니다. 예, 그는 옳습니다. 한 글꼴에 255 개 이상의 문자를 사용하려면 복합 글꼴 (CIDFONT) PDF 객체를 만들어야합니다. 그런 다음 Cidfont의 Descendatfont 항목으로 사용하려는 실제 Truetype 글꼴을 언급합니다. 트릭은 그 후에 당신이 사용해야한다는 것입니다. 글리프 지수 문자 코드 대신 글꼴의. 이 인덱스 맵을 얻으려면 구문 분석해야합니다 cmap 글꼴 섹션 - 글꼴의 내용을 가져옵니다. GetFontData TTF 사양에 따라 기능하고 손을 잡습니다. 그리고 그게 다야! 방금 해냈고 이제 유니 코드 PDF가 있습니다!

구문 분석을위한 샘플 코드 cmap 섹션은 여기에 있습니다. https://support.microsoft.com/en-us/kb/241020

그리고 예, @user2373071이 지적하거나 사용자가 PDF를 검색하거나 복사 텍스트를 검색 할 수 없을 때 잊어 버리지 마십시오.

Dredkinked가 지적했듯이 페이지 컨텐츠 스트림에서 유니 코드 문자 값 대신 Glyph 지수를 사용해야합니다. 이것은 PDF에 유니 코드 텍스트를 표시하기에 충분하지만 유니 코드 텍스트는 검색 할 수 없습니다. 텍스트를 검색 할 수 있거나 복사 /붙여 넣기 작업을하려면 A /Tounicode 스트림도 포함해야합니다. 이 스트림은 문서의 각 글리프를 실제 유니 코드 문자로 변환해야합니다.

PDF 사양의 부록 D (995 페이지)를 참조하십시오. PDF 소비자 애플리케이션에서 사전 정의 된 글꼴 및 문자 세트가 제한되어 있습니다. 다른 문자를 표시하려면 글꼴이 포함 된 글꼴을 포함해야합니다. 파일 크기를 줄이기 위해 필요한 문자만을 포함하여 글꼴의 서브 세트 만 포함하는 것이 바람직합니다. 또한 PDF에 유니 코드 문자를 표시하기 위해 노력하고 있으며 주요한 번거 로움입니다.

pdfbox 또는 itext를 확인하십시오.

http://www.adobe.com/devnet/pdf/pdf_reference.html

나는 지금이 주제에 대해 며칠 동안 일해 왔으며 내가 배운 것은 유니 코드가 PDF에서는 불가능하다는 것입니다. 2 바이트 문자를 사용하여 Plinth가 설명하는 방식은 CID-Fonts에서만 작동합니다.

겉보기에는 CID-Fonts가 PDF 내부 구성물이며 실제로는 글꼴이 아닙니다. 그래픽 서브 루틴과 비슷해 보입니다.

PDF에서 유니 코드를 사용합니다 곧장

  1. 일반 글꼴을 CID -Fonts로 변환해야 할 것입니다. 아마도 매우 어려울 것입니다. 원래 글꼴 (?)에서 그래픽 루틴을 생성하고 문자 메트릭을 추출해야합니다.
  2. 정상 글꼴과 같은 CID -Fonts를 사용할 수 없습니다. 정상 글꼴을로드하고 확장하는 방식으로로드하거나 확장 할 수 없습니다.
  3. 또한 2 바이트 문자는 전체 유니 코드 공간을 다루지 않습니다.

IMHO,이 점이 유니 코드를 사용하는 것은 절대적으로 불가능하게 만듭니다. 곧장.



내가 지금하고있는 일은 캐릭터를 사용하는 것입니다. 간접적으로 다음과 같은 방식으로 : 모든 글꼴의 경우, C ++에서는 코드 페지 (및 빠른 조회를위한 조회 테이블)를 생성합니다.

std::map<std::string, std::vector<wchar_t> > Codepage;
std::map<std::string, std::map<wchar_t, int> > LookupTable;

그런 다음 페이지에 유니 코드 스트링을 넣고 싶을 때마다 캐릭터를 반복하고 조회 테이블에서 찾아보십시오. 새로운 경우 코드 페이지에 다음과 같은 코드 페이지에 추가합니다.

for(std::wstring::const_iterator i = str.begin(); i != str.end(); i++)
{                
    if(LookupTable[fontname].find(*i) == LookupTable[fontname].end())
    {
        LookupTable[fontname][*i] = Codepage[fontname].size();
        Codepage[fontname].push_back(*i);
    }
}

그런 다음 원래 문자열의 문자가 다음과 같은 코드 페지의 위치로 대체되는 새 문자열을 생성합니다.

static std::string hex = "0123456789ABCDEF";
std::string result = "<";
for(std::wstring::const_iterator i = str.begin(); i != str.end(); i++)
{                
    int id = LookupTable[fontname][*i] + 1;
    result += hex[(id & 0x00F0) >> 4];
    result += hex[(id & 0x000F)];
}
result += ">";

예를 들어, "H 유로 세계!" <010203030405040703080905가 될 수 있습니다. 이제 TJ 연산자를 평소와 같이 사용하여 해당 문자열을 PDF에 넣고 인쇄 할 수 있습니다 ...

그러나 이제 문제가 있습니다. PDF는 01의 "h"를 의미한다는 것을 알지 못합니다.이 문제를 해결하려면 PDF 파일에 코드 페지를 포함시켜야합니다. 이것은 an을 추가하여 수행됩니다 /부호화 글꼴 객체로 설정하고 설정합니다 차이

"H € llo 세계!" 예를 들어이 글꼴 객체가 작동합니다.

5 0 obj 
<<
    /F1
    <<
        /Type /Font
        /Subtype /Type1
        /BaseFont /Times-Roman
        /Encoding
        <<
          /Type /Encoding
          /Differences [ 1 /H /Euro /l /o /space /W /r /d /exclam ]
        >>
    >> 
>>
endobj 

이 코드로 생성합니다.

ObjectOffsets.push_back(stream->tellp()); // xrefs entry
(*stream) << ObjectCounter++ << " 0 obj \n<<\n";
int fontid = 1;
for(std::list<std::string>::iterator i = Fonts.begin(); i != Fonts.end(); i++)
{
    (*stream) << "  /F" << fontid++ << " << /Type /Font /Subtype /Type1 /BaseFont /" << *i;

    (*stream) << " /Encoding << /Type /Encoding /Differences [ 1 \n";
    for(std::vector<wchar_t>::iterator j = Codepage[*i].begin(); j != Codepage[*i].end(); j++)
        (*stream) << "    /" << GlyphName(*j) << "\n";
    (*stream) << "  ] >>";

    (*stream) << " >> \n";
}
(*stream) << ">>\n";
(*stream) << "endobj \n\n";

글로벌 글꼴 등록을 사용합니다. 전체 PDF 문서에서 동일한 글꼴 이름 /f1, /f2를 사용합니다. 동일한 글꼴 등록 객체가 참조됩니다 /자원 모든 페이지의 입력. 이 작업을 다르게 수행하는 경우 (예 : 페이지 당 하나의 글꼴 등록을 사용하는 경우) - 상황에 코드를 조정해야 할 수도 있습니다 ...

그렇다면 글리프의 이름을 어떻게 찾습니까 ( "€", /fortam for "!"등에 대한 /유로)? 위의 코드에서는 단순히 "glyphname (*j)"을 호출하여 수행됩니다. 이 방법을 찾은 목록 에서이 방법을 생성했습니다.

http://www.jdawiseman.com/papers/trivia/character-entities.html

그리고 이렇게 보입니다

const std::string GlyphName(wchar_t UnicodeCodepoint)
{
    switch(UnicodeCodepoint)
    {
        case 0x00A0: return "nonbreakingspace";
        case 0x00A1: return "exclamdown";
        case 0x00A2: return "cent";
        ...
    }
}

주요 문제 나는 열린 것입니다 최대 254 개의 다른 문자를 사용하는 한만 작동합니다. 같은 글꼴에서. 254 개 이상의 다른 문자를 사용하려면 동일한 글꼴에 대해 여러 코드 페지를 만들어야합니다.

PDF 내부에는 다른 코드 페지가 다른 글꼴로 표시되므로 코드 페지를 전환하려면 글꼴을 전환해야합니다. 이는 이론적으로 PDF를 꽤 많이 날려 버릴 수 있지만, 나는 그와 함께 살 수 있습니다 ...

나는 PDF 전문가가 아니며 (Ferruccio가 말했듯이) Adobe의 PDF 사양은 모든 것을 말해야하지만 생각이 내 마음에 나타났습니다.

필요한 모든 캐릭터를 지원하는 글꼴을 사용하고 있습니까?

응용 프로그램에서 우리는 HTML 페이지 (타사 라이브러리 포함)에서 PDF를 생성하고 키릴 캐릭터 에이 문제가있었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top