外字への道 その4 2008/03/19


前回のコードが問題ありありだっあので、いろいろ修正。
1.文字列の処理が根本的にだめだった。
2.Java Web Start上でjavassistを使えるためのコードに修正。

javassistのバージョンは、CtMethodのメソッドのtoClassでProtectionDomainを引数にとれることができるものを使用しています。

どういうことをしているかといいますと、net.sf.jasperreports.engine.export.TextRendererクラスがロードされるまえに、TextRendererのrenderParagraphメソッドの振る舞いを変更するようにしてJasperReportsで外字を表示できるようにします。

このコードはJasperReportsだったら何でもよいというコードではなくて、JRGraphics2DExporterを使う場合で、さらにWindowsならば有効というコードです。
表示する文字が外字領域のものであれば、その文字を表示するための情報にフォントがEUDCを設定しています。


public class TestJasperUtils {

{

try {

javassist.ClassPool pool = javassist.ClassPool.getDefault();
javassist.CtClass myCtClass;
pool.appendClassPath(new javassist.LoaderClassPath(
TestJasperUtils.class.getClassLoader()));

myCtClass = pool
.get("net.sf.jasperreports.engine.export.TextRenderer");
javassist.CtMethod ctMethod = myCtClass
.getDeclaredMethod("renderParagraph");

StringBuffer buffer = new StringBuffer();
buffer.append(" {");
buffer.append(" java.text.AttributedCharacterIterator paragraph = null;");
buffer.append(" ");
buffer.append(" if ($3 == null)");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" \" \",");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + 1");
buffer.append(" ).getIterator().getAttributes()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + $3.length()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append("");
buffer.append(" java.awt.font.LineBreakMeasurer lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, net.sf.jasperreports.engine.export.TextRenderer.LINE_BREAK_FONT_RENDER_CONTEXT);");
buffer.append(" ");
buffer.append(" while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" int startIndex = lineMeasurer.getPosition();");
buffer.append(" ");
buffer.append("");
buffer.append(" java.awt.font.TextLayout layout = lineMeasurer.nextLayout(formatWidth);");
buffer.append("");
buffer.append(" if (isMinimizePrinterJobSize)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" java.text.AttributedString tmpText = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" );");
buffer.append(" java.text.AttributedCharacterIterator iter = tmpText.getIterator();");
buffer.append(" for(char c = iter.first(); c != java.text.CharacterIterator.DONE; c = iter.next()) {");
buffer.append(" java.util.Map map = new java.util.LinkedHashMap();");
buffer.append(" ");
buffer.append(" if(0xe000 <= c && c <= 0xf8ff){");
buffer.append(" int pos = iter.getIndex();");
buffer.append(" map.put(java.awt.font.TextAttribute.FAMILY, \"EUDC\");");
buffer.append(" tmpText.addAttributes(map, pos, pos+1);");
buffer.append(" continue;");
buffer.append(" } ");
buffer.append(" }");
buffer.append(" ");
buffer.append(" layout = new java.awt.font.TextLayout(tmpText.getIterator(), grx.getFontRenderContext());");
buffer.append(" ");
buffer.append(" }");
buffer.append("");
buffer.append(" float lineHeight = lineSpacingFactor * ");
buffer.append(" maxFontSizeFinder.findMaxFontSize(");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" ).getIterator(),");
buffer.append(" fontSize");
buffer.append(" );");
buffer.append("");
buffer.append(" if (drawPosY + lineHeight <= textHeight)");
buffer.append(" {");
buffer.append(" drawPosY += lineHeight;");
buffer.append(" ");
buffer.append(" switch (horizontalAlignment)");
buffer.append(" {");
buffer.append(" case 4 :");
buffer.append(" {");
buffer.append(" if (layout.isLeftToRight())");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" }");
buffer.append(" if (lineMeasurer.getPosition() < paragraph.getEndIndex())");
buffer.append(" {");
buffer.append(" layout = layout.getJustifiedLayout(formatWidth);");
buffer.append(" }");
buffer.append("");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 3 :");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 2 :");
buffer.append(" {");
buffer.append(" drawPosX = (formatWidth - layout.getAdvance()) / 2;");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 1 :;");
buffer.append(" default :");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" }");
buffer.append("");
buffer.append(" draw(layout);");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" isMaxHeightReached = true;");
buffer.append(" }");
buffer.append(" }");
buffer.append(" }");


ctMethod.setBody(new String(buffer));

myCtClass.toClass(TestJasperUtils.class.getClassLoader(),
TestJasperUtils.class.getProtectionDomain());

} catch (Exception e) {
e.printStackTrace();
} catch (Error e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}

}

: