備忘録 JAVA

iTextで禁則処理

2013年3月13日

iTextで禁則処理を行おうとし、色々調べてみたが、なかなか情報がありませんでした。

なので、こちらこちらを参考に禁則処理を行うことにしました。

禁則処理文字列は禁則処理…文字コード一覧を基準にして作りました。

isSplitCharacterは文字列を1文字ずつ読み取り、その文字は折り返し可能かどうかの判断をしています。
(true…折り返し可能  false…折り返し不可)

今回、FontSelectorを使っていたので、単純にisSplitCharacterのオーバーライドはできませんでした。

なので、FontSelectorを継承したクラスを作成し、そのクラスにisSplitCharacterをオーバーライドしました。

iText1.3と2.1.7だと微妙にsetter getterの名前が変わっているのでバージョンによってコメントアウトをする必要があります。(25~28行目あたり)

import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.FontSelector;
import com.lowagie.text.pdf.PdfChunk;
import com.lowagie.text.*;
import java.util.ArrayList;
public class FontSelectorHyphenation extends FontSelector {
  public FontSelectorHyphenation() {
    fonts = new ArrayList();
  }
  public void addFont(Font font) {
    if (font.getBaseFont() != null) {
      fonts.add(font);
      return;
    } else {
      BaseFont basefont = font.getCalculatedBaseFont(true);
      //itext1.3
      // Font font1 = new Font(basefont, font.size(), font.getCalculatedStyle(), font.color());
      //itext2.1.7
      Font font1 = new Font(basefont, font.getSize(), font.getCalculatedStyle(), font.getColor());
      fonts.add(font1);
      return;
    }
  }
  public Paragraph Hyphenationparagraph(String s) {
    int i = fonts.size();
    if (i == 0) throw new IndexOutOfBoundsException("No font is defined.");
    char ac[] = s.toCharArray();
    int j = ac.length;
    StringBuffer stringbuffer = new StringBuffer();
    Object obj = null;
    int k = -1;
    //        Phrase phrase = new Phrase();
    Paragraph paragraph = new Paragraph();
    label0: for (int l = 0; l < j; l++) {
      char c = ac[l];
      if (c == '\n' || c == '\r') {
        stringbuffer.append(c);
        continue;
      }
      int i1 = 0;
      do {
        if (i1 >= i) continue label0;
        Font font = (Font) fonts.get(i1);
        if (font.getBaseFont().charExists(c)) {
          if (k == i1) {
            stringbuffer.append(c);
            continue label0;
          }
          if (stringbuffer.length() > 0 && k != -1) {
            Chunk chunk1 = new Chunk(stringbuffer.toString(), (Font) fonts.get(k));
            SplitCharacter splitcharacter = setSplitCharacter();
            chunk1.setSplitCharacter(splitcharacter);
            paragraph.add(chunk1);
            stringbuffer = new StringBuffer();
          }
          stringbuffer.append(c);
          k = i1;
          continue label0;
        }
        i1++;
      } while (true);
    }
    if (stringbuffer.length() > 0) {
      Chunk chunk = new Chunk(stringbuffer.toString(), (Font) fonts.get(k));
      SplitCharacter splitcharacter = setSplitCharacter();
      chunk.setSplitCharacter(splitcharacter);
      //phase.add(chunk);
      paragraph.add(chunk);
    }
    return paragraph;
  }
  private SplitCharacter setSplitCharacter() {
    return new SplitCharacter() {
      @Override
      public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
        //初期設定
        char c;
        if (ck == null) c = cc[current];
        else c = (char) ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
        char c2;
        if (ck == null) c2 = cc[current];
        else
        if (ck[Math.min(current + 1, ck.length - 1)] != null) {
          if (current + 1 < end) {
            c2 = (char) ck[Math.min(current + 1, ck.length - 1)].getUnicodeEquivalent(cc[current + 1]);
          } else {
            c2 = ' ';
          }
        } else {
          c2 = (char) ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
        }
        char c3;
        if (ck == null) c3 = cc[current];
        else
        if (ck[Math.min(current + 2, ck.length - 1)] != null) {
          if (current + 2 < end) {
            c3 = (char) ck[Math.min(current + 2, ck.length - 1)].getUnicodeEquivalent(cc[current + 2]);
          } else {
            c3 = ' ';
          }
        } else {
          c3 = (char) ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
        }
        char c11;
        if (ck == null) c11 = cc[current];
        else {
          int current_t = 0;
          if (current - 1 < 0) {
            current_t = current;
          } else {
            current_t = current - 1;
          }
          if (ck[Math.min(current_t, ck.length - 1)] != null) {
            c11 = (char) ck[Math.min(current_t, ck.length - 1)].getUnicodeEquivalent(cc[current_t]);
          } else {
            c11 = (char) ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
          }
        }
        //trueの場合は改行する。
        //falseの場合は改行しない。
        //一つ前の文字が英数字の場合の処理
        if (c11 >= 0x20 && c11 <= 0x7e) { //!から~まで
          if (c <= ' ' || c == '-') {
            return true;
          }
          //                    if (c < 0x2e80)
          return false;
        }
        if (c != c2 && c2 != c3) {
          //行頭文字
          switch (c) {
            //終わり括弧類
          case 0x002C: //,
            return false;
          case 0xFF0c: //,
            return false;
          case 0x0029: //)
            return false;
          case 0xFF09: //)
            return false;
          case 0x005D: //]
            return false;
          case 0xFF3D: //]
            return false;
          case 0xFF5D: //}
            return false;
          case 0x3001: //、
            return false;
          case 0x3015: //〕
            return false;
          case 0x3009: //〉
            return false;
          case 0x300B: //》
            return false;
          case 0x300D: //」
            return false;
          case 0x300F: //』
            return false;
          case 0x3011: //】
            return false;
          case 0x3019: //〙
            return false;
          case 0x3017: //〗
            return false;
          case 0x301F: //〟
            return false;
          case 0x2019: //'
            return false;
          case 0x201D: //"
            return false;
          case 0xFF60: //⦆
            return false;
          case 0x00BB: //»
            return false;
            //行頭禁則和字
          case 0x30FD: //ヽ
            return false;
          case 0x30FE: //ヾ
            return false;
          case 0x30FC: //ー
            return false;
          case 0x30A1: //ァ
            return false;
          case 0x30A3: //ィ
            return false;
          case 0x30A5: //ゥ
            return false;
          case 0x30A7: //ェ
            return false;
          case 0x30A9: //ォ
            return false;
          case 0x30C3: //ッ
            return false;
          case 0x30E3: //ャ
            return false;
          case 0x30E5: //ュ
            return false;
          case 0x30E7: //ョ
            return false;
          case 0x30EE: //ヮ
            return false;
          case 0x30F5: //ヵ
            return false;
          case 0x30F6: //ヶ
            return false;
          case 0x3041: //ぁ
            return false;
          case 0x3043: //ぃ
            return false;
          case 0x3045: //ぅ
            return false;
          case 0x3047: //ぇ
            return false;
          case 0x3049: //ぉ
            return false;
          case 0x3063: //っ
            return false;
          case 0x3083: //ゃ
            return false;
          case 0x3085: //ゅ
            return false;
          case 0x3087: //ょ
            return false;
          case 0x308E: //ゎ
            return false;
          case 0x3095: //ゕ
            return false;
          case 0x3096: //ゖ
            return false;
          case 0x31F0: //ㇰ
            return false;
          case 0x31F1: //ㇱ
            return false;
          case 0x31F2: //ㇲ
            return false;
          case 0x31F3: //ㇳ
            return false;
          case 0x31F4: //ㇴ
            return false;
          case 0x31F5: //ㇵ
            return false;
          case 0x31F6: //ㇶ
            return false;
          case 0x31F7: //ㇷ
            return false;
          case 0x31F8: //ㇸ
            return false;
          case 0x31F9: //ㇹ
            return false;
          case 0x31FA: //ㇺ
            return false;
          case 0x31FB: //ㇻ
            return false;
          case 0x31FC: //ㇼ
            return false;
          case 0x31FD: //ㇽ
            return false;
          case 0x31FE: //ㇾ
            return false;
          case 0x31FF: //ㇿ
            return false;
          case 0x3005: //々
            return false;
          case 0x303B: //〻
            return false;
            //ハイフン類
          case 0x2010: //‐
            return false;
          case 0x002D: //-
            return false;
          case 0x30A0: //゠
            return false;
          case 0x003D: //=
            return false;
          case 0xFF1D: //=
            return false;
          case 0x2013: //–
            return false;
          case 0x301C: //〜
            return false;
          case 0xFF5E: //~
            return false;
            //区切り約物
          case 0x003F: //?
            return false;
          case 0xFF1F: //?
            return false;
          case 0x0021: //!
            return false;
          case 0xFF01: //!
            return false;
          case 0x203C: //‼
            return false;
          case 0x2047: //⁇
            return false;
          case 0x2048: //⁈
            return false;
          case 0x2049: //⁉
            return false;
            //中点類
          case 0x30FB: //・
            return false;
          case 0x003A: //:
            return false;
          case 0xFF1A: //:
            return false;
          case 0x003B: //;
            return false;
          case 0xFF1B: //;
            return false;
            //句点類
          case 0x3002: //。
            return false;
          case 0x002E: //.
            return false;
          case 0xFF0E: //.
            return false;
          }
          switch (c2) {
            //終わり括弧類
          case 0x002C: //,
            return false;
          case 0xFF0c: //,
            return false;
          case 0x0029: //)
            return false;
          case 0xFF09: //)
            return false;
          case 0x005D: //]
            return false;
          case 0xFF3D: //]
            return false;
          case 0xFF5D: //}
            return false;
          case 0x3001: //、
            return false;
          case 0x3015: //〕
            return false;
          case 0x3009: //〉
            return false;
          case 0x300B: //》
            return false;
          case 0x300D: //」
            return false;
          case 0x300F: //』
            return false;
          case 0x3011: //】
            return false;
          case 0x3019: //〙
            return false;
          case 0x3017: //〗
            return false;
          case 0x301F: //〟
            return false;
          case 0x2019: //'
            return false;
          case 0x201D: //"
            return false;
          case 0xFF60: //⦆
            return false;
          case 0x00BB: //»
            return false;
            //行頭禁則和字
          case 0x30FD: //ヽ
            return false;
          case 0x30FE: //ヾ
            return false;
          case 0x30FC: //ー
            return false;
          case 0x30A1: //ァ
            return false;
          case 0x30A3: //ィ
            return false;
          case 0x30A5: //ゥ
            return false;
          case 0x30A7: //ェ
            return false;
          case 0x30A9: //ォ
            return false;
          case 0x30C3: //ッ
            return false;
          case 0x30E3: //ャ
            return false;
          case 0x30E5: //ュ
            return false;
          case 0x30E7: //ョ
            return false;
          case 0x30EE: //ヮ
            return false;
          case 0x30F5: //ヵ
            return false;
          case 0x30F6: //ヶ
            return false;
          case 0x3041: //ぁ
            return false;
          case 0x3043: //ぃ
            return false;
          case 0x3045: //ぅ
            return false;
          case 0x3047: //ぇ
            return false;
          case 0x3049: //ぉ
            return false;
          case 0x3063: //っ
            return false;
          case 0x3083: //ゃ
            return false;
          case 0x3085: //ゅ
            return false;
          case 0x3087: //ょ
            return false;
          case 0x308E: //ゎ
            return false;
          case 0x3095: //ゕ
            return false;
          case 0x3096: //ゖ
            return false;
          case 0x31F0: //ㇰ
            return false;
          case 0x31F1: //ㇱ
            return false;
          case 0x31F2: //ㇲ
            return false;
          case 0x31F3: //ㇳ
            return false;
          case 0x31F4: //ㇴ
            return false;
          case 0x31F5: //ㇵ
            return false;
          case 0x31F6: //ㇶ
            return false;
          case 0x31F7: //ㇷ
            return false;
          case 0x31F8: //ㇸ
            return false;
          case 0x31F9: //ㇹ
            return false;
          case 0x31FA: //ㇺ
            return false;
          case 0x31FB: //ㇻ
            return false;
          case 0x31FC: //ㇼ
            return false;
          case 0x31FD: //ㇽ
            return false;
          case 0x31FE: //ㇾ
            return false;
          case 0x31FF: //ㇿ
            return false;
          case 0x3005: //々
            return false;
          case 0x303B: //〻
            return false;
            //ハイフン類
          case 0x2010: //‐
            return false;
          case 0x002D: //-
            return false;
          case 0x30A0: //゠
            return false;
          case 0x003D: //=
            return false;
          case 0xFF1D: //=
            return false;
          case 0x2013: //–
            return false;
          case 0x301C: //〜
            return false;
          case 0xFF5E: //~
            return false;
            //区切り約物
          case 0x003F: //?
            return false;
          case 0xFF1F: //?
            return false;
          case 0x0021: //!
            return false;
          case 0xFF01: //!
            return false;
          case 0x203C: //‼
            return false;
          case 0x2047: //⁇
            return false;
          case 0x2048: //⁈
            return false;
          case 0x2049: //⁉
            return false;
            //中点類
          case 0x30FB: //・
            return false;
          case 0x003A: //:
            return false;
          case 0xFF1A: //:
            return false;
          case 0x003B: //;
            return false;
          case 0xFF1B: //;
            return false;
            //句点類
          case 0x3002: //。
            return false;
          case 0x002E: //.
            return false;
          case 0xFF0E: //.
            return false;
          }
        }
        //行末禁則文字
        switch (c) {
        case 0x0028: //(
          return false;
        case 0xFF08: //(
          return false;
        case 0xFF3B: //[
          return false;
        case 0x005B: //[
          return false;
        case 0xFF5B: //{
          return false;
        case 0x3014: //〔
          return false;
        case 0x3008: //〈
          return false;
        case 0x300A: //《
          return false;
        case 0x300C: //「
          return false;
        case 0x300E: //『
          return false;
        case 0x3010: //【
          return false;
        case 0x3018: //〘
          return false;
        case 0x3016: //〖
          return false;
        case 0x301D: //〝
          return false;
        case 0x2018: //'
          return false;
        case 0x201C: //"
          return false;
        case 0xFF5F: //⦅
          return false;
        case 0x00AB: //«
        }
        switch (c11) {
        case 0x0028: //(
          return false;
        case 0xFF08: //(
          return false;
        case 0xFF3B: //[
          return false;
        case 0x005B: //[
          return false;
        case 0xFF5B: //{
          return false;
        case 0x3014: //〔
          return false;
        case 0x3008: //〈
          return false;
        case 0x300A: //《
          return false;
        case 0x300C: //「
          return false;
        case 0x300E: //『
          return false;
        case 0x3010: //【
          return false;
        case 0x3018: //〘
          return false;
        case 0x3016: //〖
          return false;
        case 0x301D: //〝
          return false;
        case 0x2018: //'
          return false;
        case 0x201C: //"
          return false;
        case 0xFF5F: //⦅
          return false;
        case 0x00AB: //«
        }
        //分離禁則
        if (c == c2) {
          switch (c) {
          case 0x2014: //—
            return false;
          case 0x2026: //…
            return false;
          case 0x2025: //‥
            return false;
          case 0x3033: //〳
            return false;
          case 0x3034: //〴
            return false;
          case 0x3035: //〵
            return false;
          }
        }
        if (c == c11) {
          switch (c11) {
          case 0x2014: //—
            return false;
          case 0x2026: //…
            return false;
          case 0x2025: //‥
            return false;
          case 0x3033: //〳
            return false;
          case 0x3034: //〴
            return false;
          case 0x3035: //〵
            return false;
          }
        }
        if (c2 == c3) {
          switch (c2) {
          case 0x2014: //—
            return false;
          case 0x2026: //…
            return false;
          case 0x2025: //‥
            return false;
          case 0x3033: //〳
            return false;
          case 0x3034: //〴
            return false;
          case 0x3035: //〵
            return false;
          }
        }
        //                return ((c >= 0x2e80 && c < 0xd7a0)
        //                || (c >= 0xf900 && c < 0xfb00)
        //                || (c >= 0xfe30 && c < 0xfe50)
        //                || (c >= 0xff61 && c < 0xffa0));
        return true;
        //              return false; //折り返しさせないように、falseを返す
      }
    };
  }
  protected ArrayList fonts;
}

paragraph関数をHyphenationparagraphに変更すれば使えると思います。

【、あ、あ、あ、あ】等になると微妙に折り返し処理がおかしくなるが、ほぼ思った通りの動作になったからよしとるすかな……

-備忘録, JAVA
-, , , ,