📄 fstextconstructor.java
字号:
char currentChar = (char) characterCode;
if (font.canDisplay(currentChar))
{
GlyphVector glyphVector = font.createGlyphVector(fontContext,
new char[] { currentChar });
Rectangle2D bounds = glyphVector.getGlyphOutline(0).getBounds2D();
x = Math.min(bounds.getX(), x);
y = Math.min(bounds.getY(), y);
w = Math.max(bounds.getWidth(), w);
h = Math.max(bounds.getHeight(), h);
glyphIndex++;
}
characterCode++;
}
return new Rectangle2D.Double(x, y, w, h);
}
/*
* Convert the outline of the glyph into a Flash shape.
*
* Values returned are expressed in pixels.
*/
private FSShape convertShape(Shape glyph)
{
PathIterator pathIter = glyph.getPathIterator(null);
FSShapeConstructor path = new FSShapeConstructor();
double[] coords = new double[6];
int xOrigin = 0;
int yOrigin = 0;
int currentX = 0;
int currentY = 0;
while (!pathIter.isDone())
{
int segmentType = pathIter.currentSegment(coords);
int p1 = (int) (coords[0]);
int p2 = (int) (coords[1]);
int p3 = (int) (coords[2]);
int p4 = (int) (coords[3]);
int p5 = (int) (coords[4]);
int p6 = (int) (coords[5]);
switch (segmentType)
{
case PathIterator.SEG_MOVETO:
path.closePath();
path.move(p1, p2);
break;
case PathIterator.SEG_LINETO:
path.line(p1, p2);
break;
case PathIterator.SEG_QUADTO:
path.curve(p1, p2, p3, p4);
break;
case PathIterator.SEG_CUBICTO:
path.curve(p1, p2, p3, p4, p5, p6);
break;
case PathIterator.SEG_CLOSE:
path.closePath();
break;
}
pathIter.next();
}
if (path.objects.size() > 0)
{
FSShapeStyle style = (FSShapeStyle)path.objects.get(0);
style.setLineStyle(0);
style.setAltFillStyle(1);
}
return path.shape();
}
/*
Generate the bounding rectangle for the text.
*/
private FSBounds boundsForText(int[] glyphIndices, int[] advances, int fontSize)
{
float scaleEMSquare = fontSize / 1024.0f;
int minX = 0;
int maxX = 0;
int minY = 0;
int maxY = 0;
boolean any = false;
int advance = 0;
for (int i = 0; i < glyphIndices.length; i++)
{
ArrayList array = null;
/* Patch added as there are null Glyphs decoded from the font. */
if (glyphTable[orderTable[glyphIndices[i]]] == null)
array = glyphTable[missingGlyph].shape.getObjects();
else
array = glyphTable[orderTable[glyphIndices[i]]].shape.getObjects();
/* end of patch */
int x = advance;
int y = 0;
for (Iterator j = array.iterator(); j.hasNext();)
{
FSTransformObject currentObject = (FSTransformObject) j.next();
if (currentObject instanceof FSShapeStyle)
{
FSShapeStyle style = (FSShapeStyle) currentObject;
x = advance + style.getMoveX();
y = style.getMoveY();
}
else if (currentObject instanceof FSLine)
{
FSLine line = (FSLine) currentObject;
x += line.getX();
y += line.getY();
}
else if (currentObject instanceof FSCurve)
{
FSCurve curve = (FSCurve) currentObject;
x += (curve.getControlX() + curve.getAnchorX());
y += (curve.getControlY() + curve.getAnchorY());
}
if (any) {
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
} else {
minX = maxX = x;
minY = maxY = y;
any = true;
}
}
advance += advances[i] / scaleEMSquare;
}
minX = (int) (minX * scaleEMSquare);
maxX = (int) (maxX * scaleEMSquare);
minY = (int) (minY * scaleEMSquare) + scaleBaseline(scaleEMSquare);
maxY = (int) (maxY * scaleEMSquare) + scaleBaseline(scaleEMSquare);
return new FSBounds(minX, minY, maxX, maxY);
}
/*
Generate and array of FSCharacter objects from the glyph codes and advances.
*/
private ArrayList charactersForGlyphs(int[] codes, int[] advances)
{
ArrayList characters = new ArrayList(codes.length);
for (int i = 0; i < codes.length; i++)
characters.add(new FSCharacter(codes[i], advances[i]));
return characters;
}
/*
Indicates whether or not this FSTextConstructor can display a specified Unicode character.
This method returns true if the character can be displayed, false if not.
*/
private boolean canDisplay(char c)
{
boolean canDisplay = false;
if (c < characterTable.length && characterTable[c] != 0)
canDisplay = true;
return canDisplay;
}
/*
Return an array of indexes into the array of glyphs that represent each of the characters
in the string.
*/
private int[] glyphIndicesForString(String aString)
{
int[] glyphCodes = new int[aString.length()];
for (int i = 0; i < aString.length(); i++)
{
char character = aString.charAt(i);
int glyphIndex = characterTable[character];
int index = 0;
for (index=0; index<65536; index++)
{
if (orderTable[index] == glyphIndex)
break;
else if (orderTable[index] == -1)
{
orderTable[index] = (short)glyphIndex;
break;
}
}
glyphCodes[i] = index;
}
return glyphCodes;
}
/*
Return an array of advances for the glyphs that represent each of the characters in the string
*/
private int[] advancesForGlyphIndices(int[] glyphCodes, float scaleFactor)
{
int[] glyphAdvances = new int[glyphCodes.length];
for (int i=0; i<glyphCodes.length; i++)
{
int index = orderTable[glyphCodes[i]];
glyphAdvances[i] = (int) (glyphTable[index].advance * scaleFactor);
}
return glyphAdvances;
}
/*
Return a new baseline scaled according to the new font size.
*/
private int scaleBaseline(float scaleFactor)
{
int newBaseline = (int) (baseline * scaleFactor);
newBaseline += (20 - (newBaseline % 20));
return newBaseline;
}
private byte[] dataFromFile(String filename) throws FileNotFoundException, IOException
{
File aFile = new File(filename);
FileInputStream imageContents = null;
byte[] bytes = new byte[(int)aFile.length()];
imageContents = new FileInputStream(aFile);
imageContents.read(bytes);
imageContents.close();
return bytes;
}
private void decodeOpenTypeFont(String fontName) throws IOException, DataFormatException
{
FSCoder coder = new FSCoder(FSCoder.BIG_ENDIAN, dataFromFile(fontName));
float version = coder.readFixedBits(32, 16);
int tableCount = coder.readWord(2, false);
int searchRange = coder.readWord(2, false);
int entrySelector = coder.readWord(2, false);
int rangeShift = coder.readWord(2, false);
int os_2Offset = 0;
int headOffset = 0;
int hheaOffset = 0;
int maxpOffset = 0;
int locaOffset = 0;
int cmapOffset = 0;
int glyfOffset = 0;
int hmtxOffset = 0;
int nameOffset = 0;
int os_2Length = 0;
int headLength = 0;
int hheaLength = 0;
int maxpLength = 0;
int locaLength = 0;
int cmapLength = 0;
int hmtxLength = 0;
int nameLength = 0;
int glyfLength = 0;
int chunkType = 0;
int checksum = 0;
int offset = 0;
int length = 0;
for (int i=0; i<tableCount; i++)
{
chunkType = coder.readWord(4, false);
checksum = coder.readWord(4, false);
offset = coder.readWord(4, false) << 3;
length = coder.readWord(4, false);
/*
* Chunks are encoded in ascending alphabetical order so
* the location of the tables is mapped before they are
* decoded since the glyphs come before the loca or maxp
* table which identify how many glyphs are encoded.
*/
switch (chunkType)
{
case OS_2: os_2Offset = offset; os_2Length = length; break;
case CMAP: cmapOffset = offset; cmapLength = length; break;
case GLYF: glyfOffset = offset; glyfLength = length; break;
case HEAD: headOffset = offset; headLength = length; break;
case HHEA: hheaOffset = offset; hheaLength = length; break;
case HMTX: hmtxOffset = offset; hmtxLength = length; break;
case LOCA: locaOffset = offset; locaLength = length; break;
case MAXP: maxpOffset = offset; maxpLength = length; break;
case NAME: nameOffset = offset; nameLength = length; break;
default: break;
}
}
int bytesRead = 0;
if (maxpOffset != 0) { coder.setPointer(maxpOffset); decodeMAXP(coder); bytesRead = (coder.getPointer() - maxpOffset) >> 3; }
if (os_2Offset != 0) { coder.setPointer(os_2Offset); decodeOS_2(coder); bytesRead = (coder.getPointer() - os_2Offset) >> 3; }
if (headOffset != 0) { coder.setPointer(headOffset); decodeHEAD(coder); bytesRead = (coder.getPointer() - headOffset) >> 3; }
if (hheaOffset != 0) { coder.setPointer(hheaOffset); decodeHHEA(coder); bytesRead = (coder.getPointer() - hheaOffset) >> 3; }
if (nameOffset != 0) { coder.setPointer(nameOffset); decodeNAME(coder); bytesRead = (coder.getPointer() - nameOffset) >> 3; }
glyphTable = new FSGlyph[numberOfGlyphs];
// Decode glyphs first so objects will be created.
if (locaOffset != 0) { coder.setPointer(locaOffset); decodeGlyphs(coder, glyfOffset); bytesRead = (coder.getPointer() - locaOffset) >> 3; }
if (hmtxOffset != 0) { coder.setPointer(hmtxOffset); decodeHMTX(coder); bytesRead = (coder.getPointer() - hmtxOffset) >> 3; }
if (cmapOffset != 0) { coder.setPointer(cmapOffset); decodeCMAP(coder); bytesRead = (coder.getPointer() - cmapOffset) >> 3; }
orderTable[0] = characterTable[(short)' '];
for (int i=0; i<characterTable.length; i++)
{
if (characterTable[i] >= glyphTable.length)
characterTable[i] = (short)missingGlyph;
}
/*
* Change the space character so no shape is drawn.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -