IText + HTMLWorker - Как изменить шрифт по умолчанию?

Мне нужно создать PDF файл из источника HTML. В настоящее время я справляюсь с проблемой относительно специальных (польских) символов в выходном файле, точно с их отсутствием.

Источник HTML:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<table width="100%" border="0.5" align="center" cellpadding="0" style="border-collapse:collapse; border:1px solid black; font-family:Arial, Helvetica, sans-serif; font-size:16px">
  <tr>
    <td align="center" ><b>Test: ąęłóćńśŁÓŃĆŻŹąśżźłęó</b></td>
  </tr>
</table>

Источник Java:

Document document = new Document(PageSize.A4, 38, 38, 50, 38);  
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("iTextExample.pdf"));  
document.open();  
HTMLWorker htmlWorker = new HTMLWorker(document);  
htmlWorker.parse(new StringReader(readFileAsString("index.html")));  
document.close();


public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) {
            throw new IOException("File " + filePath + " too large, was " + len + " bytes.");
        }
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

Мой вопрос: как изменить шрифт по умолчанию (Helvetica), например. Arial Bold в целом PDF-документе?

Я тестировал множество примеров, связанных с StyleSheet, и никто из них не работал. Я должен изменить шрифт по умолчанию, потому что нет польских символов - что решение, на которое я надеюсь, будет работать.

Спасибо за любую помощь!

Изменить:

My FontProvider:  
    class defaultFontProvider extends FontFactoryImp {

    private String _default;

    public defaultFontProvider(String def) {
        _default = def;
    }

    public Font getFont(String fontName, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
        if (fontName == null || size == 0) {
            fontName = _default;
        }

        return super.getFont(fontName, encoding, embedded, size, style, color, cached);
    }
    }

В приведенном выше коде встроен arial.ttf, который в порядке, но как сделать его шрифтом по умолчанию (вместо Helvetica) для всего документа.

Тогда..

        Map<String,Object> providers = new HashMap<String, Object>();

        defaultFontProvider dfp = new defaultFontProvider("arial.ttf");


        providers.put(HTMLWorker.FONT_PROVIDER, dfp);

        HTMLWorker htmlWorker = new HTMLWorker(document);
        htmlWorker.setProviders(providers);

Ответ 1

Идея № 1

На ум сразу приходит ответ: измените iText. В частности, Font.getCalculatedBaseFont, строка 644.

String fontName = BaseFont.HELVETICA;

На самом деле, я не думаю, что это сработает, если вы также не измените способ создания шрифтов... Строка 712

cfont = BaseFont.createFont(fontName, encoding, false);

Если шрифт не является "базой 14", вы должны указать путь к файлу шрифта, а не простое имя шрифта.

Другая опция: XSLT

Преобразуйте ввод таким образом, чтобы вы добавляли определение шрифта в стиль любого node, который содержит текст.

Наконец: зарегистрируйте fontProvider

Вы можете сидеть поверх FontFactoryImp и просто отображать пустые строки на выбранный вами шрифт.

class DefaultFontProvider extends FontFactoryImp {
  private String default;
  public DefaultFontProvider(String def) {
    default = def;
  }

  // I believe this is the correct override, but there are quite a few others.
  public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
    if (fontName == null || fontName.size() == 0) {
      fontName = default;
    }
    return super.getFont(fontName, encoding, embedded, size, style, color, cached);
  }
}


Map<String,Object> providers = new HashMap<String, Object)();
providers.put(HTMLWorker.FONT_PROVIDER, new DefaultFontProvider("Arial Bold"));

myHTMLWorker.setProviders(providers);

Это выглядит как самая технически разумная идея. Это написано для недавно выпущенной версии iText версии 5.0.6. Предыдущие версии устанавливали поставщика шрифтов с помощью setInterfaceProps(). "Провайдеры" - это скорее изменение имени, чем что-либо еще на этом этапе. Я подозреваю, что в 5.1 больше не будет.

PS: FontFactoryImp имеет двух публичных членов, которые могут вас заинтересовать: defaultEncoding и defaultEmbedding. Вы должны иметь возможность настроить defaultEncoding на что-то более польское. Я рекомендую "Identity-H" (aka BaseFont.IDENTITY_H), но это заставляет все ваши шрифты быть встроенными подмножествами, игнорируя при этом defaultEmbedding и делая ваши файлы немного большими, чем если бы шрифты вообще не были встроены.


Две возможные проблемы:

  • Явно запрашиваю "Helvetica".

    Конечно, я предлагаю начинку System.out.println(("Requested font: " + fontName); в начало вашей функции getFont. Это позволит вам увидеть все вызовы шрифтов и убедиться, что все ваши шрифты заменены правильно. В этом случае вы можете просто проверить его и заменить на _default.

  • Ваш fontFactory может не найти ничего для "Arial Bold" и поэтому возвращается к умолчанию (Helvetica снова).

    Думаю, вам нужно позвонить dfp.registerDirectories(). Это выведет все шрифты на несколько разных ОС и позволит вам ссылаться на них по имени шрифта, а не по пути (именно это должен делать FontFactoryImp).

Ответ 2

В вашем теге стиля, возможно, вы можете использовать CSS3 для изменения шрифта:

<style>
@font-face {
font-family: myFont;
src: url(Filename);
}
</style>

Не уверен, что это то, о чем вы просили.

Ответ 3

Он не будет использовать шрифт по умолчанию, а только те теги, в которых вы будете применять.

E.g. <Body>

Добавить свойство стиля в тег html

<tag style="font-family: Arial Unicode MS, FreeSans; font-size:16px; font-weight: normal; >Здраво दी फोंट डाउनलोड Ravi Parekh! </tag>

Примечание. Система должна найти ARIALUNI в XMLWorkerFontProvider

XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(html.getBytes(Charset.forName("UTF-8"))), null,Charset.forName("UTF-8"), new XMLWorkerFontProvider("/fonts/"));

sample: SamplePDF

Ответ 4

Если вы хотите использовать другой шрифт в формате pdf, включите в него пакет шрифтов у меня проблема, некоторые турецкие символы не печатаются в формате pdf, поэтому я включаю пакет шрифтов в pdf и моя проблема решается,

здесь вы можете увидеть пример кода: - здесь

Надежда поможет вам

Ответ 5

protected void pdfButton_Click (отправитель объекта, EventArgs e)       {           Список showCourses = новый List();           CourseManager aCourseManager = новый CourseManager();           int departmentId = Convert.ToInt16 (departmentDropDownList.Text);           int semesterId = Convert.ToInt16 (semesterDropDownList.Text);           showCourses = aCourseManager.GetScheduleCoursesByDepartmentIdAndSemester(departmentId, semesterId);

        Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
        string pdfFilePath = Server.MapPath("CoursePdf.pdf");
        PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream(pdfFilePath, FileMode.Create));
        doc.Open(); //Open Document to write
        iTextSharp.text.Font font8 = FontFactory.GetFont("ARIAL", 7);
        string heading = " \t\t                                          Course Schedule Details for Department: " +
                                departmentDropDownList.SelectedItem;
        Paragraph reportHeading = new Paragraph(heading);
        if (showCourses != null)
        {
            PdfPTable PdfTable = new PdfPTable(6);
            PdfPCell PdfPCell = null;
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Course Code", font8)));
            PdfTable.AddCell(PdfPCell);
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Course Name", font8)));
            PdfTable.AddCell(PdfPCell);
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Semester Name", font8)));
            PdfTable.AddCell(PdfPCell);
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Course Credit", font8)));
            PdfTable.AddCell(PdfPCell);
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Assign To", font8)));
            PdfTable.AddCell(PdfPCell);
            PdfPCell = new PdfPCell(new Phrase(new Chunk("Schedule", font8)));
            PdfTable.AddCell(PdfPCell);

            foreach (ShowCourse aCourse in showCourses)
            {
                PdfPCell = new PdfPCell(new Phrase(new Chunk(aCourse.courseCode, font8)));
                PdfTable.AddCell(PdfPCell);
                PdfPCell = new PdfPCell(new Phrase(new Chunk(aCourse.courseName, font8)));
                PdfTable.AddCell(PdfPCell);
                PdfPCell = new PdfPCell(new Phrase(new Chunk(aCourse.semesterName, font8)));
                PdfTable.AddCell(PdfPCell);
                PdfPCell = new PdfPCell(new Phrase(new Chunk((aCourse.credit).ToString(), font8)));
                PdfTable.AddCell(PdfPCell);
                PdfPCell = new PdfPCell(new Phrase(new Chunk(aCourse.teacherName , font8)));
                PdfTable.AddCell(PdfPCell);
                PdfPCell = new PdfPCell(new Phrase(new Chunk(aCourse.schedule, font8)));
                PdfTable.AddCell(PdfPCell);
            }
            PdfTable.SpacingBefore = 15f; // Give some space after the text or it m
            doc.Add(reportHeading); // add paragraph to the document
            doc.Add(PdfTable); // add pdf table to the document
            doc.Close();
            // string pdfPath = Server.MapPath("~/SomePDFFile.pdf");
            WebClient client = new WebClient();
            Byte[] buffer = client.DownloadData(pdfFilePath);
            Response.ContentType = "application/pdf";
            Response.AddHeader("content-length", buffer.Length.ToString());
            Response.BinaryWrite(buffer);
        }

    }