package com.ximple.io.dgn7; import java.awt.geom.AffineTransform; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import org.apache.log4j.Logger; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateList; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.ximple.util.DgnUtility; /** * TextElement * * @author Ulysses * @version 0.1 * @since 2006/5/18 上午 11:45:29 */ public class TextElement extends Element implements GeometryConverter { private static final Logger logger = Logger.getLogger(TextElement.class); public static final int ED_CENTERJUSTIFICATION = 0; // Enter data field center justification public static final int ED_LEFTJUSTIFICATION = 0; // Enter data field left justification public static final int ED_RIGHTJUSTIFICATION = 0; public static final int TXTJUST_LT = 0; /* Left Top */ public static final int TXTJUST_LC = 1; /* Left Center */ public static final int TXTJUST_LB = 2; /* Left Bottom */ public static final int TXTJUST_LMT = 3; /* Left Margin Top */ public static final int TXTJUST_LMC = 4; /* Left Margin Center */ public static final int TXTJUST_LMB = 5; /* Left Margin Bottom */ public static final int TXTJUST_CT = 6; /* Center Top */ public static final int TXTJUST_CC = 7; /* Center Center */ public static final int TXTJUST_CB = 8; /* Center Bottom */ public static final int TXTJUST_RMT = 9; /* Right Margin Top */ public static final int TXTJUST_RMC = 10; /* Right Margin Center */ public static final int TXTJUST_RMB = 11; /* Right Margin Bottom */ public static final int TXTJUST_RT = 12; /* Right Top */ public static final int TXTJUST_RC = 13; /* Right Center */ public static final int TXTJUST_RB = 14; /* Right Bottom */ public static final int TXTJUST_LU = 15; /* Left Cap */ public static final int TXTJUST_LD = 16; /* Left Descender */ public static final int TXTJUST_LMU = 17; /* Left Margin Cap */ public static final int TXTJUST_LMD = 18; /* Left Margin Descender */ public static final int TXTJUST_CU = 19; /* Center Cap */ public static final int TXTJUST_CD = 20; /* Center Descender */ public static final int TXTJUST_RMU = 21; /* Right Margin Cap */ public static final int TXTJUST_RMD = 22; /* Right Margin Descender */ public static final int TXTJUST_RU = 23; /* Right Cap */ public static final int TXTJUST_RD = 24; /* Right Descender */ public static final int TXTJUST_NONE = 127;/* no justfication */ public TextElement(byte[] raw) { super(raw); } public Coordinate getOrigin() { int x = (raw[25] << 16 & 0xffff0000); x += raw[26] & 0x0000ffff; double dx = DgnUtility.converUnitToCoord(x); int y = (raw[27] << 16 & 0xffff0000); y += raw[28] & 0x0000ffff; double dy = DgnUtility.converUnitToCoord(y); return new Coordinate(dx, dy); } public int getFontIndex() { return (int) raw[18] & 0x00000000ff; } public boolean hasSlant() { return true; } public boolean hasUnderline() { return true; } public boolean isFixedWidthSpacing() { return true; } public boolean isPlanar() { return true; } public boolean isVertical() { return true; } public double getTextHeight() { int height = ((raw[21] << 16) & 0xffff0000); height += raw[22] & 0x0000ffff; return DgnUtility.converIntToDouble(height); } public double getTextWidth() { int length = (raw[19] << 16 & 0xffff0000); length += raw[20] & 0x0000ffff; return DgnUtility.converIntToDouble(length); } public int getJustification() { return ((raw[18] >>> 8) & 0x00000000ff); } public double getRotationAngle() { int totation = ((raw[23] & 0x0000ffff) << 16) | (raw[24] & 0x0000ffff); return DgnUtility.converIntToRotation(totation); } public boolean isChinese() { int isChinese = raw[30] & 0x0000ffff; return (isChinese == 0xfdff); } public int getTextLength() { int num = raw[29]; if (isChinese()) { num = (num / 2) - 1; } return num; } public String getText() { StringBuilder val = new StringBuilder(); char[] temp; int num = getTextLength(); if (num < 0) { logger.warn("getTextLength() return Negative Value."); return ""; } if (!isChinese()) { temp = new char[num]; for (int i = 0; i < temp.length; i++) { if ((i % 2) == 0) { temp[i] = (char) (raw[30 + (int) (i / 2)] & (short) 0x00ff); } else { temp[i] = (char) ((raw[30 + (int) (i / 2)] >> 8) & (short) 0x00ff); } val.append(temp[i]); } } else { byte[] strRaw = new byte[num * 2]; for (int i = 0; i < num; i++) { short charValue = raw[i + 31]; byte hi = (byte) (charValue >>> 8); byte lo = (byte) charValue; strRaw[i * 2] = hi; strRaw[i * 2 + 1] = lo; } try { Charset charsetBig5 = Charset.forName("Big5"); CharsetDecoder decoder = charsetBig5.newDecoder(); CharBuffer cb = decoder.decode(ByteBuffer.wrap(strRaw)); val.append(cb); } catch (CharacterCodingException e) { logger.warn(e.getMessage(), e); return val.toString(); } finally { // rawBuffer.position(pos); // rawBuffer.order(order); } } return val.toString(); } protected byte[] convertDBCSToUnicode(byte[] buffer) { byte[] charBuffer = new byte[4]; charBuffer[0] = (byte) ((byte) ((buffer[1] & 0xc0) >>> 6) | 0xc0); charBuffer[1] = (byte) (buffer[1] & 0x3f | 0x80); charBuffer[2] = (byte) ((byte) ((buffer[0] & 0xc0) >>> 6) | 0xc0); charBuffer[3] = (byte) (buffer[0] & 0x3f | 0x80); return charBuffer; } public Geometry toGeometry(GeometryFactory factory) { return factory.createPoint(getUserOrigin()); } public Geometry toAnchorGeometry(GeometryFactory factory) { if (getText() == null) { return factory.createMultiPoint(new Coordinate[]{}); } return factory.createMultiPoint(toAnchorCoordinates()); } public Coordinate[] toAnchorCoordinates() { CoordinateList result = new CoordinateList(); int len = getText().trim().length(); if (len == 0) return result.toCoordinateArray(); double width = getUserWidth(); double height = getUserHeight(); double angle = Math.toRadians(getRotationAngle()); AffineTransform at = new AffineTransform(); at.translate(width, height); Coordinate p = getOrigin(); at.setToRotation(angle, p.x, p.y); at.scale(1, 1); for (int i = 0; i < len; i++) { double[] srcPt = new double[2]; double[] dstPt = new double[2]; srcPt[0] = p.x + width * i; srcPt[1] = p.y; at.transform(srcPt, 0, dstPt, 0, 1); result.add(new Coordinate(dstPt[0], dstPt[1]), false); } return result.toCoordinateArray(); } private double getUserWidth() { int just = getJustification(); // Envelope range = getRange(); // case -1 // double width = (range.getWidth()); // case -1 // double width = this.getTextWidth() * this.getTextLength() * 1000.0; // case -2 double width = (this.getTextWidth() * this.getTextLength()); switch (just) { case TXTJUST_LT: case TXTJUST_LC: case TXTJUST_LB: width = 0; break; case TXTJUST_CT: case TXTJUST_CC: case TXTJUST_CB: width = width / 2; break; case TXTJUST_RT: case TXTJUST_RC: case TXTJUST_RB: break; } return width; } private double getUserHeight() { int just = getJustification(); double height = getTextHeight(); switch (just) { case TXTJUST_LB: case TXTJUST_CB: case TXTJUST_RB: // bottom height = 0; break; case TXTJUST_LC: case TXTJUST_CC: case TXTJUST_RC: // center height = height / 2; break; case TXTJUST_LT: case TXTJUST_CT: case TXTJUST_RT: // height break; } return height; } public Coordinate getUserOrigin() { double width = getUserWidth(); double height = getUserHeight(); double angle = Math.toRadians(getRotationAngle()); AffineTransform at = new AffineTransform(); at.translate(width, height); Coordinate p = getOrigin(); at.setToRotation(angle, p.x, p.y); at.scale(1, 1); double[] srcPt = new double[2]; double[] dstPt = new double[2]; srcPt[0] = p.x + width; srcPt[1] = p.y + height; at.transform(srcPt, 0, dstPt, 0, 1); return new Coordinate(dstPt[0], dstPt[1]); } public Object clone() throws CloneNotSupportedException { int pos = this.rawBuffer.position(); this.rawBuffer.position(0); byte[] rawBytes = this.rawBuffer.array(); byte[] otherRaw = new byte[rawBytes.length]; System.arraycopy(rawBytes, 0, otherRaw, 0, rawBytes.length); this.rawBuffer.position(pos); TextElement other = new TextElement(otherRaw); return other; } public static class ElementHandler extends Element.ElementHandler { private static ElementHandler instance = null; public ElementHandler() { super(ElementType.TEXT); } public static IElementHandler getInstance() { if (instance == null) { instance = new ElementHandler(); } return instance; } protected Element createElement(byte[] raw) { return new TextElement(raw); } } }