Java 使用PDFBOX编写阿拉伯语字符 更新1

Java 使用PDFBOX编写阿拉伯语字符 更新1,java,pdfbox,Java,Pdfbox,我正在尝试使用pdfbox在pdf文档中写入一些阿拉伯字符。结果我得到了一些奇怪的角色。您可以在下面找到我用于测试的代码片段。请注意,相同的代码用于打印拉丁字符,没有任何问题 public static void main(String[] args) throws Exception { PDDocument document = new PDDocument(); PDPage page = new PDPage(PDPage.PAGE_SIZE_A4); doc

我正在尝试使用pdfbox在pdf文档中写入一些阿拉伯字符。结果我得到了一些奇怪的角色。您可以在下面找到我用于测试的代码片段。请注意,相同的代码用于打印拉丁字符,没有任何问题

public static void main(String[] args) throws Exception {

    PDDocument document = new PDDocument();

    PDPage page = new PDPage(PDPage.PAGE_SIZE_A4);
    document.addPage(page);

    PDPageContentStream stream = new PDPageContentStream(document, page,true, true);

    //Use of a unicode font
    PDFont font = PDTrueTypeFont.loadTTF(document,"C:/arialuni.ttf");

    font.setFontEncoding(new WinAnsiEncoding());

    stream.setFont(font, 12);
    stream.beginText();

    stream.moveTextPositionByAmount(40, 600);

    stream.drawString("سي ججس ححسيب حسججسيبنم حح ");
    stream.endText();
    stream.close();
    document.save("c:\\resultpdf.pdf");
    document.close();

}
谢谢你的帮助。我尝试了从微软网站下载的Unicode字体,但仍然有相同的结果

  • 更新2
  • 通过使用'drawUnicodeString'方法和'loadTTF'方法,我从 我能写阿拉伯字符,但它们是断开连接的,从左到右排列。以下是两种方法“drawUnicodeString”和“loadTTF”

    public void drawUnicodeString(String text) throws IOException {
        COSString string = new COSString();
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            string.append(c >> 8);
            string.append(c & 0xff);
        }
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        string.writePDF(buffer);
        appendRawCommands(buffer.toByteArray());
        appendRawCommands(32);
        appendRawCommands(getISOBytes("Tj\n"));
    }
    
    
    public static PDType0Font loadTTF(PDDocument doc, InputStream is)
            throws IOException {
        /* Load the font which we will convert to Type0 font. */
        PDTrueTypeFont pdTtf = PDTrueTypeFont.loadTTF(doc, is);
    
        TrueTypeFont ttf = pdTtf.getTTFFont();
        CMAPEncodingEntry unicodeMap = null;
        for (CMAPEncodingEntry candidate : ttf.getCMAP().getCmaps()) {
            if (candidate.getPlatformId() == CMAPTable.PLATFORM_WINDOWS
                    && candidate.getPlatformEncodingId() == CMAPTable.ENCODING_UNICODE) {
                unicodeMap = candidate;
                break;
            }
        }
        if (unicodeMap == null) {
            throw new RuntimeException(
                    "To use as CIDFont, the TTF must have a Windows platform Unicode encoding");
        }
        float scaling = 1000f / ttf.getHeader().getUnitsPerEm();
    
        MyPDCIDFontType2Font pdCidFont2 = new MyPDCIDFontType2Font();
        pdCidFont2.setBaseFont(pdTtf.getBaseFont());
        pdCidFont2.setFontDescriptor((PDFontDescriptorDictionary) pdTtf
                .getFontDescriptor());
        /* Fixme -- should determine the minimum and maximum charcode in the map */
        int[] cid2gid = new int[65536];
        List<Float> widths = new ArrayList<Float>();
        int[] widthValues = ttf.getHorizontalMetrics().getAdvanceWidth();
        for (int i = 0; i < cid2gid.length; i++) {
            int glyph = unicodeMap.getGlyphId(i);
            cid2gid[i] = glyph;
            widths.add((float) i);
            widths.add((float) i);
            widths.add(widthValues[glyph] * scaling);
        }
        pdCidFont2.setCidToGid(cid2gid);
        pdCidFont2.setWidths(widths);
        pdCidFont2.setDefaultWidth(widths.get(0).longValue());
    
        /* Now construct the type0 font that we actually return */
        myType0Font pdFont0 = new myType0Font();
        pdFont0.setDescendantFont(pdCidFont2);
        pdFont0.setDescendantFonts(new COSObject(pdCidFont2.getCOSObject()));
        pdFont0.setEncoding(COSName.IDENTITY_H);
    
        pdFont0.setBaseFont(pdTtf.getBaseFont());
    
        // pdfont0.setToUnicode(COSName.IDENTITY_H); XXX how to express identity
        // mapping as ToUnicode program? */
        return pdFont0;
    }
    
    public void destring(字符串文本)引发IOException{
    余弦字符串=新余弦();
    对于(int i=0;i>8);
    追加字符串(c&0xff);
    }
    ByteArrayOutputStream缓冲区=新建ByteArrayOutputStream();
    writePDF(缓冲区);
    appendRawCommands(buffer.toByteArray());
    附加命令(32);
    AppendRaw命令(getISOBytes(“Tj\n”));
    }
    公共静态PDType0Font loadTTF(PDDocument文档,InputStream为)
    抛出IOException{
    /*加载我们将转换为Type0字体的字体*/
    PDTrueTypeFont pdTtf=PDTrueTypeFont.loadTTF(单据,is);
    TrueTypeFont ttf=pdTtf.gettFont();
    CMAPEncodingEntry unicodeMap=null;
    对于(CMAPEncodingEntry候选:ttf.getCMAP().getCmaps()){
    if(candidate.getPlatformId()==CMAPTable.PLATFORM\u窗口
    &&candidate.getPlatformEncodingId()=cMatable.ENCODING_UNICODE){
    unicodeMap=候选人;
    打破
    }
    }
    if(unicodeMap==null){
    抛出新的运行时异常(
    “要用作CIDFont,TTF必须具有Windows平台Unicode编码”);
    }
    浮点缩放=1000f/ttf.getHeader().getUnitsPrem();
    MyPDCIDFontType2Font pdCidFont2=新的MyPDCIDFontType2Font();
    pdcdfont2.setBaseFont(pdTtf.getBaseFont());
    pdCidFont2.setFontDescriptor((PDFontDescriptorDictionary)pdTtf
    .getFontDescriptor());
    /*Fixme——应该确定映射中的最小和最大字符码*/
    int[]cid2gid=新int[65536];
    列表宽度=新的ArrayList();
    int[]widthValues=ttf.getHorizontalMetrics().getAdvanceWidth();
    对于(int i=0;i
    下面是打印的字符:


    我不知道为什么这些字符断开连接

    我建议您尝试将ICU4J JAR添加到项目中:

    可以通过应用和来编写阿拉伯语。(差异文件附在问题说明中)
    我希望修补程序将应用于2.0版。

    我不熟悉PDFBox,但我认为问题在于:
    font.setFontEncoding(新的WinAnScienceODing())设置unicode编码而不是ansi编码。尝试使用本文档中的每个
    编码实现:两个问题。1) 
    PDPageContentStream.drawString()
    无法正确处理任何代码点超过255的Unicode字符,请参见欧元符号中出现的奇怪字符;2) (如@Rafael所述)
    winansienceoding
    不包括阿拉伯语字符;但我仍然有相同的结果:PdfDocEncoding PdfDocEncoding=newpdfdocencoding();WinAnsionoding WinAnsionoding=新建WinAnsionoding();PDFDOCENCODE pdfEncode=新的PDFDOCENCODE();StandardEncoding StandardEncoding=新的StandardEncoding();类型1编码t1=新类型1编码(128);WinAnsionODing en=新的WinAnsionODing();在这里的例子中;他们将“byte[]commands=“(x)Tj”.getBytes();”。值“(x)Tj”从何处获得?我将JAR添加到我的项目中,但这并不能解决问题