package com.ximple.io.dgn7;
|
|
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;
|
import org.apache.log4j.Logger;
|
|
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;
|
|
/**
|
* TextElement
|
*
|
* @author Ulysses
|
* @version 0.1
|
* @since 2006/5/18
|
*/
|
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 */
|
|
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() {
|
if (raw.length < 31) return false;
|
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 (30 + num / 2 > raw.length) {
|
logger.warn("getTextLength() too long.");
|
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);
|
}
|
}
|
}
|