Как использовать iText, чтобы добавить водяной знак, используя встроенный шрифт - PullRequest
3 голосов
/ 03 февраля 2011

У меня есть несколько документов pdf / a с некоторыми встроенными шрифтами, теперь я должен постобработать эти документы, используя iText, чтобы добавить водяной знак.

Я знаю, что с помощью iText можно встроить шрифт:

BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);

но я хотел бы использовать шрифт, который уже встроен в документ, для добавления текстового водяного знака (что-то вроде «SAMPLE COPY»).

Как я могу это сделать?

Ответы [ 3 ]

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

То, что вы хотите, это DocumentFont.Вы не можете создавать их напрямую, конструктор является частным пакетом, но BaseFont.createFont(PRIndirectReference) сделает свое дело.

Так что вам просто нужно получить PRIndirectReference для шрифта, который вы хотите."PR" приходят из PdfReader.Есть два способа найти шрифт, который вы ищете, и получить ссылку на него:

1) Перечислять каждый объект в PdfReader, отфильтровывая все, что не является PRStream, оттуда отбрасывая все, чтоне /Type /Font, а ищет шрифт с правильным именем.

public PRIndirectReference findNamedFont( PdfReader myReader, String desiredFontName) {
  int objNum = 0;
  PdfObject curObj;
  do {
    //The "Release" version doesn't keep a reference 
    //to the object so it can be GC'd later.  Quite Handy 
    //when dealing with Really Big PDFs.
    curObj = myReader.getPdfObjectRelease( objNum++ );
    if (curObj instanceof PRStream) {
      PRStream stream = (PRStream)curObj;
      PdfName type = stream.getAsName(PdfName.TYPE);
      if (PdfName.FONT.equals(type)) {
        PdfString fontName = stream.getAsString(PdfName.BASEFONT);
        if (desiredFontName.equals(fontName.toString())) {
          return curObj.getIndRef();
        }
      }
    }
  } while (curObj != null);
return null;
}  

2) Изучайте словари ресурсов ваших страниц /Font <<>>, ищите шрифт с правильным именем.Имейте в виду, что у ресурсов формы XObject есть свои собственные ресурсы, которые вы должны проверить по следующему адресу:

public PRIndirectReference findFontInPage(PdfReader reader, String desiredName, int i) {

  PdfDictionary page = reader.getPageN(i); 
  return findFontInResources(page.getAsDict(PdfName.RESOURCES), desiredName);
}   

public PRIndirectReference findFontInResources(PdfDictionary resources, String desiredName) {
  if (resources != null) {
    PdfDictionary fonts = resources.getAsDict(PdfName.FONTS);
    if (fonts != null) {
      for (PdfName curFontName : fonts.keySet()) {
        PRStream curFont (PRStream)= fonts.getAsStream(curFontName);
        if (desiredName.equals(curFont.getAsString(PdfName.BASEFONT).toString()) {
          return (PRIndirectReference) curFont.getIndirectReference();
        }
      }
    }
    PdfDictionary xobjs = resources.getAsDict(PdfName.XOBJECTS);
    if (xobjs != null) {
      for (PdfName curXObjName : xobjs.keySet()) {
        PRStream curXObj = (PRStream)xobjs.getAsStream(curXObjName);
        if (curXObj != null && PdfName.FORM.equals(curXObj.getAsName(PdfName.SUBTYPE)) {
          PdfDictionary resources = curXObj.getAsDict(PdfName.RESOURCES);
          PRIndirectReference ref = findFontInResources(resources, desiredName);
          if (ref != null) {
            return ref;
          }
        }
      }
    }
  }
  return null;
}

Любой из них даст вам PRIndirectReference, который вы ищете.Затем вы звоните BaseFont.createFont(myPRRef), и у вас будет DocumentFont, что вам нужно.Первый метод найдет любой шрифт в PDF, тогда как второй найдет только те шрифты, которые фактически используются.

Кроме того, для заданных шрифтов должен быть тег «6-random-letters-plus-sign»добавляется к имени шрифта.НЕ используйте подмножество шрифтов.Используемые символы могут не входить в подмножество, что приводит к тому, что я называю проблемой «arry ole».Звучит красиво и грязно, но на самом деле это было просто имя нашего продавца: «Гарри Воле» пропустил буквы в верхнем регистре, потому что я подменил какой-то шрифт, которого у меня не должно быть Many Moons Ago.

PS: никогдавставлять подмножества шрифтов, которые вы собираетесь использовать в поле формы.Нет, Буэно.

Обычный отказ от "я написал весь этот код в поле для ответов здесь" применяется, но я написал много такого рода кода, так что он может просто работать "из коробки".Скрестить пальцы.;)

1 голос
/ 03 февраля 2011

Совершенно другой подход: используйте Line Art вместо Text.

Если вы создаете объект PdfGraphics2D «только для штриховой графики» из overContent страницы, вы можете использовать шрифт AWT и вам не нужно беспокоиться о встраивании ввсе.С относительно короткой строкой вам не нужно беспокоиться о том, что размер PDF-файла может взорваться.

PdfContentByte overcontent = stamper.getOverContent(1);
Graphics2D g2d = overcontent.createGraphicsShapes(pageWid, pageHei);

drawStuffToTheGraphic(g2d);

g2d.dispose();

Это приведет к «тексту», который фактически является штриховым рисунком.Его нельзя выбрать, найти и т. Д. Это может быть хорошо или плохо, в зависимости от того, что вы ищете.

0 голосов
/ 03 февраля 2011

Используя обычный jPod (BSD, SourceForge), вы можете опираться на пример «Водяной знак». WIth

PDFontTools.getFonts(doc)

Вы можете перечислить шрифты и затем использовать один из них в методе "createForm" ...

...