import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
private class TextUtil {
private static final int INITIAL_BUFFER_SIZE = 16;
- private int[][] dp = new int[INITIAL_BUFFER_SIZE][4];
- // private int lastDPPos = 0; // TBD - not yet used
+ private int[][] dp = new int[INITIAL_BUFFER_SIZE][];
private final StringBuffer text = new StringBuffer();
private int startx;
private int starty;
if (idx > dp.length - 1) {
int newSize = Math.max(dp.length, idx + 1) + INITIAL_BUFFER_SIZE;
int[][] newDP = new int[newSize][];
- // reuse prior PA[0]...PA[dp.length-1]
+ // reuse prior DP[0]...DP[dp.length-1]
System.arraycopy(dp, 0, newDP, 0, dp.length);
- // populate new PA[dp.length]...PA[newDP.length-1]
- for ( int i = dp.length, n = newDP.length; i < n; i++ ) {
- newDP[i] = new int[4];
- }
+ // switch to new DP, leaving DP[dp.length]...DP[newDP.length-1] unpopulated
dp = newDP;
}
+ if ( dp[idx - 1] == null ) {
+ dp[idx - 1] = new int[4];
+ }
IFUtil.adjustPA ( dp[idx - 1], pa );
- // lastDPPos = idx;
}
}
if (text.length() > 0) {
text.setLength(0);
for ( int i = 0, n = dp.length; i < n; i++ ) {
- Arrays.fill(dp[i], 0);
+ dp[i] = null;
}
- // lastDPPos = 0;
}
}
int i = ( tl < pl ) ? tl : pl;
while ( i > 0 ) {
int[] pa = dp [ i - 1 ];
- if ( !IFUtil.isPAIdentity ( pa ) ) {
+ if ( ( pa != null ) && !IFUtil.isPAIdentity ( pa ) ) {
break;
} else {
i--;
if ( dp != null ) {
dx = new int [ count ];
for ( int i = 0, n = count; i < n; i++ ) {
- dx [ i ] = dp [ i ] [ 0 ]; // xPlaAdjust[i]
+ if ( dp [ i ] != null ) {
+ dx [ i ] = dp [ i ] [ 0 ]; // xPlaAdjust[i]
+ }
}
} else {
dx = null;
} else {
for ( int i = 0, n = dp.length; i < n; i++ ) {
int[] pa = dp[i];
- if ( pa[0] != pa[2] ) {
+ if ( ( pa != null ) && ( pa[0] != pa[2] ) ) {
return false;
}
}
if ( ( dp == null ) || ( offset > dp.length ) || ( ( offset + count ) > dp.length ) ) {
throw new IllegalArgumentException();
} else {
- int[][] dpNew = new int [ count ] [ 4 ];
+ int[][] dpNew = new int [ count ] [];
for ( int i = 0, n = count; i < n; i++ ) {
- int[] paDst = dpNew [ i ];
int[] paSrc = dp [ i + offset ];
- for ( int k = 0; k < 4; k++ ) {
- paDst [ k ] = paSrc [ k ];
+ if ( paSrc != null ) {
+ int[] paDst = new int [ 4 ];
+ for ( int k = 0; k < 4; k++ ) {
+ paDst [ k ] = paSrc [ k ];
+ }
+ dpNew [ i ] = paDst;
}
}
return dpNew;
int fs = state.getFontSize();
float fsPoints = fs / 1000f;
Font f = getFontInfo().getFontInstance(triplet, fs);
- // String fn = f.getFontName();
PDFTextUtil tu = generator.getTextUtil();
double xc = 0f;
double yc = 0f;
generator.updateCharacterSpacing ( letterSpacing / 1000f );
for ( int i = 0, n = text.length(); i < n; i++ ) {
char ch = text.charAt ( i );
- int[] pa = ( i < dp.length ) ? dp [ i ] : paZero;
+ int[] pa = ( ( i >= dp.length ) || ( dp[i] == null ) ) ? paZero : dp[i];
double xo = xc + pa[0];
double yo = yc + pa[1];
double xa = f.getCharWidth(ch) + maybeWordOffsetX ( wox, ch, null );
sb.append ( na );
for ( int i = 0; i < na; i++ ) {
int[] pa = dp [ i ];
- for ( int k = 0; k < 4; k++ ) {
- int a = pa [ k ];
- if ( a != 0 ) {
- encodeNextAdjustment ( sb, nz, a );
- nz = 0;
- } else {
- nz++;
+ if ( pa != null ) {
+ for ( int k = 0; k < 4; k++ ) {
+ int a = pa [ k ];
+ if ( a != 0 ) {
+ encodeNextAdjustment ( sb, nz, a );
+ nz = 0;
+ } else {
+ nz++;
+ }
}
+ } else {
+ nz += 4;
}
}
encodeNextAdjustment ( sb, nz, 0 );
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Fonts" dev="GA" type="fix" fixes-bug="FOP-2195">
+ Use sparse arrays for position adjustments.
+ </action>
<action context="Fonts" dev="GA" type="fix" fixes-bug="FOP-2194">
Optimize lazy font load invocation for hot methods.
</action>