かえでBlog

色々なことを徒然と……

iTextで禁則処理

      2015/05/18

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, 備忘録 , , , ,