PDFBoxのカレントマスターをチェック

しばらく見ないうちにPDFBoxが大改造されていて(メジャーバージョンアップのため後方互換を考えないのだろう)、CJKFontとUnicodeTTFにも大影響である。

でまずCMap.javaからみていったら、いきなり何かおかしい。`codeToCid`はコンテンツの文字コードからCIDに変換するためのマップのはずなのに、なぜかCIDから文字コードへのマップになっている。単なるバグかと思ったら、テストコードもこれにあわせてCIDから文字コードへの変換をチェックしているので、意図的だと思われる。 しかし、`CMap#toCID(int code)`メソッドをみれば、引数`code`が`codeToCid`を引くときはCID、`codeToCidRanges`を引くときは文字コードと解釈されるので、あきらかに勘違いだと思うが、さてどうしたものか。

2014.11.25 追記

よく見たらパースの順番が逆になっていて、これで正しいことが判明した。ただ、CMapParserでcodeとcidという単語を逆に使っていると思われる。私の英語力の問題かPDF仕様書の理解が間違っているのか?

CMap.java

void addCIDMapping(int code, int cid)
{
    codeToCid.put(cid, code);
}

void addCIDRange(char from, char to, int cid)
{
    codeToCidRanges.add(0, new CIDRange(from, to, cid));
}

public int toCID(int code)
{
    if (codeToCid.containsKey(code))
    {
        return codeToCid.get(code);
    }
    else
    {
        for (CIDRange range : codeToCidRanges)
        {
            int ch = range.map((char)code);
            if (ch != -1)
            {
                return ch;
            }
        }
        return 0;
    }
}

CIDRange.java

public int map(char ch) {
        if (from <= ch && ch <= to) {
            return cid + (ch - from);
        } else {
            return -1;
        }
}

CMapParser.java

else if (op.op.equals("begincidchar"))
{
    Number cosCount = (Number) previousToken;
    for (int j = 0; j < cosCount.intValue(); j++)
    {
      Object nextToken = parseNextToken(cmapStream);
            ...
      byte[] inputCode = (byte[]) nextToken;
      int mappedCode = (Integer) parseNextToken(cmapStream);
      int mappedCID = createIntFromBytes(inputCode);
      result.addCIDMapping(mappedCode, mappedCID);
    }
}
else if (op.op.equals("begincidrange"))
{
    int numberOfLines = (Integer) previousToken;
    for (int n = 0; n < numberOfLines; n++)
    {
        Object nextToken = parseNextToken(cmapStream);
                ...
        byte[] startCode = (byte[]) nextToken;
        int start = createIntFromBytes(startCode);
        byte[] endCode = (byte[]) parseNextToken(cmapStream);
        int end = createIntFromBytes(endCode);
        int mappedCode = (Integer) parseNextToken(cmapStream);
        if (startCode.length <= 2 && endCode.length <= 2)
        {
            result.addCIDRange((char) start, (char) end, mappedCode);
        }
        ...
    }
}

TestCMapParser.java

// CID mappings
int cid1 = 65;
assertEquals("CID 65 from cidrange <0000> <00ff> 0 ", 65, cMap.toCID(cid1));

int cid2 = 280;
int strCID2 = 0x0118;
assertEquals("CID 280 from cidrange <0100> <01ff> 256", strCID2, cMap.toCID(cid2));

int cid3 = 520;
int strCID3 = 0x0208;
assertEquals("CID 520 from cidchar <0208> 520", strCID3, cMap.toCID(cid3));

CMapTest リソース

3 begincidchar
<0200> 512
<0208> 520
<020A> 522
endcidchar

2 begincidrange
<0000> <00ff> 0
<0100> <01ff> 256
endcidrange

プロフィール
新着エントリ
アーカイブ