LandscapeだとFontMetricsが間違った大きさを返すによる不具合の対策です。代替の方法を使用します。
getHeight()がゼロだったら代替にgetFont().getSize()の値を使うというもの。行間分が少ない可能性もあるが、下方向に空白がついている分であることが多いので均等割付では大きな影響はないだろう。上寄せ、下寄せでは文字がくっつく傾向にあるが許容範囲。
プレビューと微妙に異なる可能性があるが、Linuxでなければ出現しないバグなので大きな影響はないだろう。
FontMetrics fm = g.getFontMetrics(); float mojih = fm.getHeight(); float ascent = fm.getAscent(); if (mojih==0 ) { mojih = fm.getFont().getSize(); ascent = mojih * 0.9f; }
書ける範囲の文字列や余白と同様に、コンストラクタで計算しておいて、メソッドで使います。
大きな変更ではありません。
package print01; import java.awt.Graphics2D; import java.awt.Font; import java.awt.FontMetrics; import java.awt.image.BufferedImage; public class AjustStringT { String kp, nbf; int cpct, idxbgn, newcpbgn, nbfcp; float fmwm, remm; float aidamm = 0f; Graphics2D g; FontMetrics fm; float mm2pt = 72/25.4f; float pt2mm = 25.4f/72; float dscinpt, ascent, mojih; //dscinpt = fm.getDescent()); boolean debug = false; /** wakuhaba に入る mojiretsu を計算 */ public AjustStringT(Graphics2D g, String mojiretsu, float wakuhaba) { this(g,mojiretsu,wakuhaba,0); } /** wakuhaba に入る mojiretsu を計算 ただし、kaishiichi 以降の文字列を対象にする */ public AjustStringT(Graphics2D g, String mojiretsu, float wakuhaba, int kaishiichi) { this.g = g; kp = (mojiretsu!=null)? mojiretsu:""; //nullなら"" fmwm = (wakuhaba>=0)?wakuhaba:0; //負なら0 fm = g.getFontMetrics(); mojih = fm.getHeight(); ascent = fm.getAscent(); if (mojih==0 ) { mojih = fm.getFont().getSize(); ascent = mojih * 0.9f; } cpct = kp.codePointCount(0,kp.length()); //kpのcp数 if (0>kaishiichi) kaishiichi=0; //負なら0 if (cpct>kaishiichi){ //cpをindexに換算 idxbgn = kp.offsetByCodePoints(0,kaishiichi); nbf = kp.substring(idxbgn); }else{ //開始位置が文字列をはみ出していたら idxbgn = kaishiichi-cpct+kp.length(); nbf = ""; } if(debug)System.out.println("cpct="+cpct+" /kaishiichi="+kaishiichi+" /idxbgn="+idxbgn+" /nbf="+nbf);//test nbfcp = nbf.codePointCount(0, nbf.length()); remm = fmwm - mojih*pt2mm*nbfcp; //あまりを計算 newcpbgn = kaishiichi + nbfcp; //書いた後の次の文字を計算 if(debug)System.out.println( "nbf="+nbf+" /remm="+remm +" /nbf.length()="+nbf.length()+" /newcpbgn="+newcpbgn);//test while(0>remm && !nbf.isEmpty()) { int newendidx = nbf.offsetByCodePoints(nbf.length(), -1); //一つ前のindexを求める nbf = nbf.substring(0,newendidx); nbfcp = nbf.codePointCount(0, nbf.length()); remm = fmwm - mojih*pt2mm*nbfcp; newcpbgn = kaishiichi + nbfcp; if(debug)System.out.println( "nbf="+nbf+" /remm="+remm +" /nbf.length()="+nbf.length()+" /newcpbgn="+newcpbgn);//test } //ascent = fm.getAscent(); } public static void main( String[] args ) { BufferedImage buffimg = new BufferedImage(400,300,BufferedImage.TYPE_INT_RGB); Graphics2D g = buffimg.createGraphics(); g.setFont(new Font(Font.SERIF, Font.PLAIN, 10)); float wakuhaba = (args.length>0) ? Float.parseFloat(args[0]):10f; int kaishiichi = (args.length>1) ? Integer.parseInt(args[1]):0; String mojitachi="東a西𠀋南ア北"; System.out.println("文字列="+mojitachi+" /枠幅(mm)="+wakuhaba+" /開始番号(0-)="+kaishiichi); AjustStringT ast = new AjustStringT(g, mojitachi,wakuhaba,kaishiichi); } public boolean hasNext(){ return cpct>newcpbgn; } public int getNextPt(){ int retval = -1; if (cpct>newcpbgn) retval=newcpbgn; return retval; } public float getLastRemm(){ return remm; } /**縦書きを左寄せのように上に詰める。hmを中心線にする */ public void drawTop(float hm, float vm) { //float vpp = fm.getHeight(); -> mojih int nbflen = nbf.length(); //int nbfcplen = nbf.codePointCount(0,nbflen); int i=0; int nexti = 0; int cpcti = 0; float fontwd; while (nbflen>i){ nexti = nbf.offsetByCodePoints(i,1); fontwd = fm.stringWidth(nbf.substring(i,nexti)); g.drawString(nbf.substring(i,nexti),hm*mm2pt-fontwd/2,vm*mm2pt+mojih*cpcti+ascent); i=nexti; cpcti++; } } /**縦書きを右寄せのように下に詰める。hmを中心線にする */ public void drawBottom(float hm, float vm) { //float vpp = fm.getHeight();->mojih int nbflen = nbf.length(); //int nbfcplen = nbf.codePointCount(0,nbflen); int i=0; int nexti = 0; int cpcti = 0; float fontwd; while (nbflen>i){ nexti = nbf.offsetByCodePoints(i,1); fontwd = fm.stringWidth(nbf.substring(i,nexti)); g.drawString(nbf.substring(i,nexti),hm*mm2pt-fontwd/2,(vm+remm)*mm2pt+mojih*cpcti+ascent); i=nexti; cpcti++; } } /**縦の均等割付 hmを中心線にする */ public void drawTtoB(float hm, float vm) { //float vpp = fm.getHeight(); -> mojih int nbflen = nbf.length(); int nbfcplen = nbf.codePointCount(0,nbflen); if (nbfcplen!=1){ aidamm = remm/(nbfcplen-1); int i=0; int nexti = 0; int cpcti = 0; float fontwd; while (nbflen>i){ nexti = nbf.offsetByCodePoints(i,1); fontwd = fm.stringWidth(nbf.substring(i,nexti)); g.drawString(nbf.substring(i,nexti),hm*mm2pt-fontwd/2,(vm+aidamm*cpcti)*mm2pt+mojih*cpcti+ascent); i=nexti; cpcti++; } }else{ g.drawString(nbf,hm*mm2pt,(vm+remm/2)*mm2pt+ascent); } } }
部分的に横の均等割付の縦位置を決めるのにgetHeight()を使っていたので同様の対策をします
float mojih = g2.getFontMetrics().getHeight(); float ascent = g2.getFontMetrics().getAscent(); if (mojih==0 ) { mojih = g2.getFontMetrics().getFont().getSize(); ascent = mojih * 0.9f; }
必要な部分は2つでした。各科目の高さ
float padbtm = (vptch-mojih*pt2mm)/2;
最上部の項目の部分の横書き
kp = new AjustString(g2, "科目", hwkm-10f); kp.drawKintou(hbas+5f,vthtop+(vtdtop-vthtop)/2+mojih*pt2mm/2);
これも大きくはありませんが AjustStringT.java への変更です。fm.getHeight()で得られた文字の高さは行間要素を含むことが多く、大きめになります。縦書きの場合は多少文字がくっついたとしても、詰め込みたいこともあります。
そこで、fm.getFont().getSize() で得られる高さを常用する高さとし、"height"という文字列の引数が与えられ、なおかつfm.getHeight()が0でない時だけ fm.getHeight() の値を使うことにします。通常は"height"以外の文字列を与えてください。
public AjustStringT(Graphics2D g, String mojiretsu, float wakuhaba, int kaishiichi) { this.g = g; kp = (mojiretsu!=null)? mojiretsu:""; //nullなら"" fmwm = (wakuhaba>=0)?wakuhaba:0; //負なら0 fm = g.getFontMetrics(); mojih = fm.getHeight(); ascent = fm.getAscent(); if (mojih==0 ) { mojih = fm.getFont().getSize(); ascent = mojih * 0.9f; } cpct = kp.codePointCount(0,kp.length()); //kpのcp数
public AjustStringB(Graphics2D g, String mojiretsu, float wakuhaba, int kaishiichi, String tatef) { this.g = g; kp = (mojiretsu!=null)? mojiretsu:""; //nullなら"" fmwm = (wakuhaba>=0)?wakuhaba:0; //負なら0 fm = g.getFontMetrics(); mojih = fm.getFont().getSize(); ascent = mojih * 0.9f; if (tatef.equals("height") && fm.getHeight()!=0) { mojih = fm.getHeight(); ascent = fm.getAscent(); } cpct = kp.codePointCount(0,kp.length()); //kpのcp数
呼び出す方も引数を合わせる
kp = new AjustString(g2, "科目", hwkm-10f, "any"); kp.drawKintou(hbas+5f,vthtop+(vtdtop-vthtop)/2+mojih*pt2mm/2);