前回の iText の ColumnText で段組配置 にアイコンを追加してみた。


サンプルソースコード(ColumnsSample2.java)


import java.io.*;
 
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
 
public class ColumnsSample2 {
 
  // The texts by
  //
  // - The Wonderful Wizard of Oz by L. Frank Baum - Project Gutenberg
  //   http://www.gutenberg.org/etext/55  
  
  private static String icons[] = {
    "0.png",
    "1.png",
    "2.png",
    "3.png",
    "4.png",
    "5.png",
    "6.png",
    "7.png",
  };
 
  private static String headings[] = {
    "Introduction",
    "1. The Cyclone",
    "2. The Council with the Munchkins",
    "3. How Dorothy Saved the Scarecrow",
    "4. The Road Through the Forest",
    "5. The Rescue of the Tin Woodman",
    "6. The Cowardly Lion",
    "7. The Journey to the Great Oz",
  };
 
  private static String texts[] = {
    "Folklore, legends, myths and fairy tales have followed childhood through the ages, for every healthy youngster has a wholesome and instinctive love for stories fantastic, marvelous and manifestly unreal. The winged fairies of Grimm and Andersen have brought more happiness to childish hearts than all other human creations.",
    "Dorothy lived in the midst of the great Kansas prairies, with Uncle Henry, who was a farmer, and Aunt Em, who was the farmer's wife.",
    "She was awakened by a shock, so sudden and severe that if Dorothy had not been lying on the soft bed she might have been hurt.",
    "When Dorothy was left alone she began to feel hungry.",
    "After a few hours the road began to be rough, and the walking grew so difficult that the Scarecrow often stumbled over the yellow bricks, which were here very uneven.",
    "When Dorothy awoke the sun was shining through the trees and Toto had long been out chasing birds around him and squirrels.",
    "All this time Dorothy and her companions had been walking through the thick woods.",
    "They were obliged to camp out that night under a large tree in the forest, for there were no houses near.",
  };
 
  public static void main(String[] args) throws Exception {
    
    Document doc = new Document(PageSize.A6, 10, 10, 10, 10);
    PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream("20070804_columns2.pdf"));
 
    float gutter = 20; // 列と列のスペース
    int numColumns = 2; // 列の数
    float fullWidth = doc.right() - doc.left(); // 描画範囲
    float columnWidth = (fullWidth - (numColumns - 1) * gutter) / numColumns; // 列の幅
    float columnLeft[] = new float[numColumns]; // 列の左端の位置
    for(int i=0; i<numColumns; i++){
      columnLeft[i] = doc.left() + (columnWidth + gutter) * i;
    }
    
    // フォント
    float headingFontSize = 14.0f;
    Font font4Heading =
      FontFactory.getFont(
        FontFactory.TIMES_ROMAN,
        headingFontSize,
        Font.BOLD,
        new java.awt.Color(255, 0, 0));
    Font font4Text = FontFactory.getFont(FontFactory.TIMES_ROMAN, 11);
    
    // Document#open
    doc.open();
 
    // 列の区切りとなる縦線を描画
    PdfContentByte cb = writer.getDirectContent();
    for(int i=1; i<numColumns; i++){
      float x = columnLeft[i] - gutter / 2.0f;
      cb.moveTo(x, doc.top());
      cb.lineTo(x, doc.bottom());
    }
    cb.stroke();
 
    // 描画位置の道標: まずは文書の上の方をセットする
    float currentY = doc.top();
    ColumnText ct = new ColumnText(cb);
    ct.setYLine(currentY);
 
    // アイコン画像を適切なサイズにするための値
    final float iconHeight = font4Heading.getBaseFont().getAscentPoint("Ag", headingFontSize);
    System.out.println("IconHeight=" + iconHeight);// IconHeight=9.660001
    
    // タイトルと文章を追加していく
    for(int i=0; i<headings.length; i++) {
      // アイコン画像
      Image img = getImage(icons[i], iconHeight);
      Chunk cimg = new Chunk(img, 0, 0);
      // Phrase オブジェクトに追加してから ColumnText に入れるのが無難だと思う
      Phrase phrase = new Phrase();
      phrase.add(cimg);
      phrase.add(new Chunk(headings[i], font4Heading));
      phrase.add(Chunk.NEWLINE);
      phrase.add(new Chunk(texts[i], font4Text));
      phrase.add(Chunk.NEWLINE);
      phrase.add(Chunk.NEWLINE);
      ct.addElement(phrase);
      // Image を add された Chunk を ColumnText#addElement に追加すると、
      // その後に ColumnText#addText した Chunk が表示されなかった。
      // ColumnText#addElement で Chunk を追加すると表示はされたが、
      // 画像とテキスト Chunk の間に改行が入ってしまった。
      //ct.addElement(cimg);
      //ct.addElement(new Chunk(headings[i] + "\n", font4Heading));
      //ct.addText(new Chunk(headings[i] + "\n", font4Heading));
      //ct.addText(new Chunk(texts[i] + "\n\n", font4Text));
    }
 
    // 現在描画中の列のインデックス
    int currentColumn = 0;
    
    // 最初の列を作る
    {
      float llx = columnLeft[currentColumn];
      float lly = doc.bottom();
      float urx = columnLeft[currentColumn] + columnWidth;
      float ury = currentY;
      float leading = 15.0f;
      int alignment = Element.ALIGN_LEFT;
      ct.setSimpleColumn(llx, lly, urx, ury, leading, alignment);
    }
 
    while(true){
      
      // テキストを書き出す
      int rc = ct.go();
      
      // すべてのテキストが収まった
      if((rc & ColumnText.NO_MORE_TEXT) != 0){
        break;
      }
      
      // テキストが列の範囲内に収まらなかったので、新しく列を作る必要がある
      currentColumn++;
      
      // 最後の列にも収まらなかったのでアキラメ
      if(currentColumn >= numColumns){
        break;
      }
 
      // 新しく列を作る
      float llx = columnLeft[currentColumn];
      float lly = doc.bottom();
      float urx = columnLeft[currentColumn] + columnWidth;
      float ury = currentY;
      float leading = 15.0f;
      int alignment = Element.ALIGN_LEFT;
      ct.setSimpleColumn(llx, lly, urx, ury, leading, alignment);
    }
    
    doc.close();
  }
  
  private static Image getImage(String file, float newHeight) throws Exception {
    
    com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(file);
    float percent = newHeight / image.getHeight() * 100.0f;
    image.scalePercent(percent);
    return image;
  }
}

出力したPDFファイル -> 20070804_columns2.pdf
各章のタイトルの文字の高さに合わせたアイコンをうまいぐあいに配置している。

文章は The Wonderful Wizard of Oz by L. Frank Baum - Project Gutenberg を拝借。
アイコンはパブリック・ドメインな famfamfam.com: Mini Icons を拝借。

tags: zlashdot Java Java PDF iText

Posted by NI-Lab. (@nilab)