/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* (C) Copyright IBM Corp. 1998-2003, All Rights Reserved
*
*/
final class TextLine {
static final class TextLineMetrics {
public final float ascent;
public final float descent;
public final float leading;
public final float advance;
float descent,
float leading,
float advance) {
}
}
private float[] fBaselineOffsets;
private char[] fChars;
private int fCharsStart;
private int fCharsLimit;
private boolean fIsDirectionLTR;
private boolean isSimple;
float[] baselineOffsets,
char[] chars,
int charsStart,
int charsLimit,
int[] charLogicalOrder,
byte[] charLevels,
boolean isDirectionLTR) {
init();
}
private void checkCtorArgs() {
int checkCharCount = 0;
}
if (checkCharCount != this.characterCount()) {
throw new IllegalArgumentException("Invalid TextLine! " +
"char count is different from " +
"sum of char counts of components.");
}
}
private void init() {
// first, we need to check for graphic components on the TOP or BOTTOM baselines. So
// we perform the work that used to be in getMetrics here.
float ascent = 0;
float descent = 0;
float leading = 0;
float advance = 0;
// ascent + descent must not be less than this value
float maxGraphicHeight = 0;
float maxGraphicHeightWithLeading = 0;
// walk through EGA's
boolean fitTopAndBottomGraphics = false;
isSimple = true;
tlc = fComponents[i];
if (baseline >= 0) {
}
else {
fitTopAndBottomGraphics = true;
}
}
if (fitTopAndBottomGraphics) {
}
}
}
// we now know enough to compute the locs, but we need the final loc
// for the advance before we can create the metrics object
if (fitTopAndBottomGraphics) {
// we have top or bottom baselines, so expand the baselines array
// full offsets are needed by CoreMetrics.effectiveBaselineOffset
fBaselineOffsets = new float[] {
fBaselineOffsets[0],
fBaselineOffsets[1],
fBaselineOffsets[2],
};
}
float x = 0;
float y = 0;
boolean needPath = false;
// 1) compute the area of overlap - min effective ascent and min effective descent
// 2) compute the x positions along italic angle of ascent and descent for left and right
// 3) compute maximum left - right, adjust right position by this value
// this is a crude form of kerning between textcomponents
// note glyphvectors preposition glyphs based on offset,
// so tl doesn't need to adjust glyphvector position
// 1)
// pb += pcm.ssOffset;
// cb += cm.ssOffset;
// 2)
// 3)
x += dx;
y = cb;
} else {
// no italic adjustment for x, but still need to compute y
}
locs[n] = x;
locs[n+1] = y;
x += tlc.getAdvance();
}
// do we want italic padding at the right of the line?
float d;
} else {
}
d *= pcm.italicAngle;
x += d;
}
// locs[locs.length - 1] = 0; // final offset is always back on baseline
// ok, build fMetrics since we have the final advance
advance = x;
// build path if we need it
if (needPath) {
isSimple = false;
}
pt.y = 0;
}
}
}
}
}
}
// if we have a matching frc, set it to null so we don't have to test it
// for each component
}
// only cache integral locations with the default frc, this is a bit strict
return result;
}
// couldn't use cache, or didn't have it, so compute
if (isSimple) { // all glyphvectors with no decorations, no layout path
} else {
}
}
}
}
} else { // draw and test
final int MARGIN = 3;
}
}
if (canCache) {
}
return result;
}
int l = -1, t = -1, r = w, b = h;
{
// get top
int[] buf = new int[w];
loop: while (++t < h) {
if (buf[i] != -1) {
break loop;
}
}
}
}
// get bottom
{
int[] buf = new int[w];
loop: while (--b > t) {
if (buf[i] != -1) {
break loop;
}
}
}
++b;
}
// get left
{
loop: while (++l < r) {
for (int i = t; i < b; ++i) {
if (v != -1) {
break loop;
}
}
}
}
// get right
{
loop: while (--r > l) {
for (int i = t; i < b; ++i) {
if (v != -1) {
break loop;
}
}
}
++r;
}
return new Rectangle(l, t, r-l, b-t);
}
private abstract static class Function {
int componentIndex,
int indexInArray);
}
int componentIndex,
int indexInArray) {
}
};
int componentIndex,
int indexInArray) {
}
};
int componentIndex,
int indexInArray) {
}
};
int componentIndex,
int indexInArray) {
// charPos is relative to the component - adjust for
// baseline
}
};
public int characterCount() {
return fCharsLimit - fCharsStart;
}
public boolean isDirectionLTR() {
return fIsDirectionLTR;
}
return fMetrics;
}
if (fCharLogicalOrder == null) {
return visualIndex;
}
if (fCharVisualOrder == null) {
}
return fCharVisualOrder[visualIndex];
}
return (fCharLogicalOrder == null)?
}
}
}
}
}
}
}
if (logicalIndex < 0) {
throw new IllegalArgumentException("Negative logicalIndex.");
}
throw new IllegalArgumentException("logicalIndex too large.");
}
int currentTlc = 0;
int tlcStart = 0;
int tlcLimit = 0;
do {
if (tlcLimit > logicalIndex) {
break;
}
++currentTlc;
}
}
}
}
if (logicalIndex < 0) {
throw new IllegalArgumentException("Negative logicalIndex.");
}
int tlcStart = 0;
if (tlcLimit > logicalIndex) {
}
else {
}
}
throw new IllegalArgumentException("logicalIndex too large.");
}
}
}
}
return getCharXPosition(logicalIndex);
}
return applyFunctionAtIndex(logicalIndex, f);
}
if (offset < 0) {
throw new IllegalArgumentException("Negative offset.");
}
int tlcStart = 0;
}
else {
}
}
throw new IllegalArgumentException("logicalIndex too large.");
}
/**
* map a component visual index to the logical index.
*/
if (fComponentVisualOrder == null) {
return vi;
}
return fComponentVisualOrder[vi];
}
/**
* map a component logical index to the visual index.
*/
if (fComponentVisualOrder == null) {
return li;
}
if (fComponentVisualOrder[i] == li) {
return i;
}
}
}
if (logicalIndex < 0) {
throw new IllegalArgumentException("Negative logicalIndex.");
}
int tlcStart = 0;
if (tlcLimit > logicalIndex) {
int vi = getComponentVisualIndex(i);
return chBounds;
}
else {
}
}
throw new IllegalArgumentException("logicalIndex too large.");
}
}
}
} else {
pt.x += x;
pt.y += y;
} else {
}
}
}
}
/**
* Return the union of the visual bounds of all the components.
* This incorporates the path. It does not include logical
* bounds (used by carets).
*/
} else {
} else {
}
}
result = r;
} else {
}
}
}
return result;
}
float x = locs[n];
float y = locs[n+1];
}
}
}
}
return dstShape;
}
public int hashCode() {
}
}
}
/**
* Create a TextLine from the text. The Font must be able to
* display all of the text.
* attributes==null is equivalent to using an empty Map for
* attributes
*/
char[] chars,
Map attributes) {
boolean isDirectionLTR = true;
boolean requiresBidi = false;
if (attributes != null) {
}
requiresBidi = true;
embs = new byte[characterCount];
}
}
}
// dlf: get baseRot from font for now???
if (!requiresBidi) {
}
if (requiresBidi) {
: values.getRunDirection();
if (!bidi.isLeftToRight()) {
}
}
frc,
0);
numComponents -= 1;
}
components = temp;
}
}
return newComponents;
}
/**
* Returns an array in logical order of the TextLineComponents on
* the text in the given range, with the given attributes.
*/
int runLimit,
char[] chars,
int[] charsLtoV,
byte[] levels,
int numComponents) {
do {
do {
int lmCount;
}
else {
}
}
} while (pos < chunkLimit);
return components;
}
/**
* Returns an array (in logical order) of the TextLineComponents representing
* the text. The components are both logically and visually contiguous.
*/
char[] chars,
int textStart,
int textLimit,
int[] charsLtoV,
byte[] levels,
int numComponents = 0;
do {
if (graphicOrFont instanceof GraphicAttribute) {
// AffineTransform baseRot = styledParagraph.getBaselineRotationAt(pos);
// !!! For now, let's assign runs of text with both fonts and graphic attributes
// a null rotation (e.g. the baseline rotation goes away when a graphic
// is applied.
do {
pos = chunkLimit;
}
}
else {
frc,
numComponents -= 1;
}
}
}
else {
}
return components;
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
boolean isDirectionLTR,
float[] baselineOffsets) {
}
}
/**
* Compute the components order from the given components array and
* logical-to-visual character mapping. May return null if canonical.
*/
int[] charsLtoV) {
/*
* Create a visual ordering for the glyph sets. The important thing
* here is that the values have the proper rank with respect to
* each other, not the exact values. For example, the first glyph
* set that appears visually should have the lowest value. The last
* should have the highest value. The values are then normalized
* to map 1-1 with positions in glyphs.
*
*/
int[] componentOrder = null;
int gStart = 0;
}
}
return componentOrder;
}
/**
* Create a TextLine from the text. chars is just the text in the iterator.
*/
char[] chars,
float[] baselineOffsets) {
if (bidi.isLeftToRight()) {
}
boolean isDirectionLTR = true;
}
}
/*
* A utility to get a range of text that is both logically and visually
* contiguous.
* If the entire range is ok, return limit, otherwise return the first
* directional change after start. We could do better than this, but
* it doesn't seem worth it at the moment.
private static int firstVisualChunk(int order[], byte direction[],
int start, int limit)
{
if (order != null) {
int min = order[start];
int max = order[start];
int count = limit - start;
for (int i = start + 1; i < limit; i++) {
min = Math.min(min, order[i]);
max = Math.max(max, order[i]);
if (max - min >= count) {
if (direction != null) {
byte baseLevel = direction[start];
for (int j = start + 1; j < i; j++) {
if (direction[j] != baseLevel) {
return j;
}
}
}
return i;
}
}
}
return limit;
}
*/
/**
* When this returns, the ACI's current position will be at the start of the
* first run which does NOT contain a GraphicAttribute. If no such run exists
* the ACI's position will be at the end, and this method will return false.
*/
return true;
}
}
return false;
}
}
return baselineOffsets;
}
}
}
}
return null;
}
/*
* The new version requires that chunks be at the same level.
*/
{
return start;
}
return limit;
}
/*
* create a new line with characters between charStart and charLimit
* justified using the provided width and ratio.
*/
public TextLine getJustifiedLine(float justificationWidth, float justifyRatio, int justStart, int justLimit) {
float leftHang = 0;
float adv = 0;
float justifyDelta = 0;
boolean rejustify = false;
do {
// all characters outside the justification range must be in the base direction
// of the layout, otherwise justification makes no sense.
// get the actual justification delta
// generate an array of GlyphJustificationInfo records to pass to
// the justifier. Array is visually ordered.
// get positions that each component will be using
int infoCount = 0;
}
// get justification infos
int compStart = 0;
break;
}
}
}
// records are visually ordered, and contiguous, so start and end are
// simply the places where we didn't fetch records
int infoStart = 0;
++infoStart;
}
--infoLimit;
}
// invoke justifier on the records
boolean canRejustify = rejustify == false;
boolean wantRejustify = false;
boolean[] flags = new boolean[1];
// apply justification deltas
compStart = 0;
break;
}
}
}
} while (rejustify);
}
// return the sum of the advances of text between the logical start and limit
float advance = 0;
int tlcStart = 0;
break;
}
}
}
return advance;
}
return lp;
}
}