iText + HTMLWorker - Как изменить шрифт по умолчанию? - PullRequest
10 голосов
/ 08 февраля 2011

Мне нужно создать файл 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) на eg. Arial Bold во всем PDF документе?

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

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

Редактировать:

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);

Ответы [ 5 ]

2 голосов
/ 08 февраля 2011

Идея № 1

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

String fontName = BaseFont.HELVETICA;

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

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

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

Другой вариант: XSLT

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

Наконец: зарегистрируйте 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);

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

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


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

  1. Явно запрашивает "Helvetica".

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

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

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

1 голос
/ 23 января 2017

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

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/"));

образец: SamplePDF

1 голос
/ 13 апреля 2014

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

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

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

0 голосов
/ 26 мая 2014

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

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

надежда помогает вам

0 голосов
/ 31 марта 2014

защищенный void pdfButton_Click (отправитель объекта, EventArgs e) { Список showCourses = новый список (); CourseManager aCourseManager = new 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);
        }

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...