Re: upcoming change to IFPainter.drawText()

2010-08-31 Thread Vincent Hennebert
Hi Glenn,

A dedicated class with meaningful fields (e.g., xPlacement, xAdvance)
would probably be preferable to an array of 4 int. This would be safer
and easier to understand and use.

For the rest, that sounds good.

Vincent


Glenn Adams wrote:
 Folks,
 
 I'd like to mention a change I will implement on IFPainter#drawText method
 in order to accommodate complex scripts (as well as non-complex script usage
 in a variety of written languages). I'm bringing this up now so there can be
 discussion ahead of time if needed.
 
 Basically, the change is to generalize the int[] dx parameter to be a two
 dimensional array of glyph placement/advancement adjustments.
 
 The current interface is:
 
 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
 String text) throws IFException;
 
 The modified method interface would read as follows:
 
 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][]
 adjustments, String text) throws IFException;
 
 The adjustments array is optional (in which case it is null). If non-null,
 it is effectively typed as int[][4], i.e., an array of int[4] arrays, where
 the four elements of each row are:
 
 a[0] = x placement adjustment
 a[1] = y placement adjustment
 a[2] = x advance adjustment
 a[3] = y advance adjustment
 
 The [x,y] placement adjustments are added to the current point to determine
 the effective glyph (char) origin, and the [x,y] advance adjustments are
 applied to the current point after rendering the glyph (char) and performing
 the default (implicit) advance.
 
 To be more explicit, the algorithm using these adjustments is effectively as
 follows (ignoring word and letter spacing for the moment):
 
 int curPointX = x;
 int curPointY = y;
 for ( int i = 0, n = glyphs.length; i  n; i++ ) {
   int g = glyphs [ i ];
   int gx = curPointX;
   int gy = curPointY;
   int[] a = ( adjustments != null ) ? adjustments[i] : null;
   if ( a != null ) {
 gx += a[0];
 gy += a[1];
   }
   drawGlyph ( g, gx, gy );
   curPointX += font.getGlyphAdvanceX ( g );
   curPointY += font.getGlyphAdvanceY ( g );
   if ( a != null ) {
 curPointX += a[2];
 curPointY += a[3];
   }
 }
 
 It is mandatory to provide this generality in order to support not only
 complex scripts, but also non-complex scripts (e.g, Latin, Greek, Cyrillic,
 CJK, etc) when used with non-spacing marks (in many written languages) and
 also for other advanced typographic effects.
 
 Attached is a simple example of the use of this feature in order to adjust
 the placement (and advance) of U+064E ARABIC FATHA and U+0650 ARABIC KASRA,
 respectively, the upper and lower non-spacing marks shown in this example.
 
 Regards,
 Glenn
 


upcoming change to IFPainter.drawText()

2010-08-30 Thread Glenn Adams
Folks,

I'd like to mention a change I will implement on IFPainter#drawText method
in order to accommodate complex scripts (as well as non-complex script usage
in a variety of written languages). I'm bringing this up now so there can be
discussion ahead of time if needed.

Basically, the change is to generalize the int[] dx parameter to be a two
dimensional array of glyph placement/advancement adjustments.

The current interface is:

void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
String text) throws IFException;

The modified method interface would read as follows:

void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][]
adjustments, String text) throws IFException;

The adjustments array is optional (in which case it is null). If non-null,
it is effectively typed as int[][4], i.e., an array of int[4] arrays, where
the four elements of each row are:

a[0] = x placement adjustment
a[1] = y placement adjustment
a[2] = x advance adjustment
a[3] = y advance adjustment

The [x,y] placement adjustments are added to the current point to determine
the effective glyph (char) origin, and the [x,y] advance adjustments are
applied to the current point after rendering the glyph (char) and performing
the default (implicit) advance.

To be more explicit, the algorithm using these adjustments is effectively as
follows (ignoring word and letter spacing for the moment):

int curPointX = x;
int curPointY = y;
for ( int i = 0, n = glyphs.length; i  n; i++ ) {
  int g = glyphs [ i ];
  int gx = curPointX;
  int gy = curPointY;
  int[] a = ( adjustments != null ) ? adjustments[i] : null;
  if ( a != null ) {
gx += a[0];
gy += a[1];
  }
  drawGlyph ( g, gx, gy );
  curPointX += font.getGlyphAdvanceX ( g );
  curPointY += font.getGlyphAdvanceY ( g );
  if ( a != null ) {
curPointX += a[2];
curPointY += a[3];
  }
}

It is mandatory to provide this generality in order to support not only
complex scripts, but also non-complex scripts (e.g, Latin, Greek, Cyrillic,
CJK, etc) when used with non-spacing marks (in many written languages) and
also for other advanced typographic effects.

Attached is a simple example of the use of this feature in order to adjust
the placement (and advance) of U+064E ARABIC FATHA and U+0650 ARABIC KASRA,
respectively, the upper and lower non-spacing marks shown in this example.

Regards,
Glenn


test.pdf
Description: Adobe PDF document


Re: upcoming change to IFPainter.drawText()

2010-08-30 Thread Glenn Adams
Perhaps it is useful to indicate how the existing dx[] adjustments map into
the more generalized gpos[][] adjustments. Given a dx[] array or a gpos[][]
array or neither, they are reconciled as follows:

int[][] reconcileAdjustments(int[] dx, int[][] gpos) {
  if ( dx == null ) {
return gpos;
  } else {
if ( gpos == null ) {
  gpos = new int[dx.length][4];
 }
for ( int i = 0; i  dx.length; i++ ) {
  int d = dx[i];
  if ( dx != 0 ) {
gpos[i][0] += d; // reconcile x placement adjustment


gpos[i][2] += d; // reconcile x advance adjustment


  }
}
  }
}

The current semantics of dx[i] cause the current point to be adjusted to
curPointX + dx[i] prior to rendering glyph[i], after which the implicit x
advancement (width) of glyph[i] is added to curPointX. In the reconciliation
of dx[] and gpos[][] above, dx[i] is added to both the x placement
adjustment and the x advance adjustment of glyph[i], the net effect of which
is that the x origin of glyph[i] is translated by dx[i], and then the
current point x coordinate is advanced by the sum of the implicit glyph
advancement and the x advance adjustment. Together, these yield the same
behavior as presently indicated by the non-generalized form of drawText.

There are a number of places in the existing code where this reconciliation
could take place, including:

(1) just prior to creating a word area, in which case a word area would
carry only the gpos[][] adjustments;
(2) just prior to calling IFPainter.drawText, i.e., in
IFRenderer.TextUtil.flush();

In both cases, the externalized, AT form of WordArea changes. In case (1),
the letter-adjust attribute is effectively merged into a new
position-adjustattribute, with
letter-adjust being removed. In case (2), a new position-adjust attribute is
added to hold gpos[][], but the existing letter-adjust attribute is retained
as is.

I have tentatively decided to use case (2), since this does not create any
test regressions for the handful of tests that make reference to the
letter-adjust attribute. It could always be moved further back, e.g., to
(1), at a future date.

Comments?

G.

On Mon, Aug 30, 2010 at 8:19 PM, Glenn Adams gl...@skynav.com wrote:

 Folks,

 I'd like to mention a change I will implement on IFPainter#drawText method
 in order to accommodate complex scripts (as well as non-complex script usage
 in a variety of written languages). I'm bringing this up now so there can be
 discussion ahead of time if needed.

 Basically, the change is to generalize the int[] dx parameter to be a two
 dimensional array of glyph placement/advancement adjustments.

 The current interface is:

 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
 String text) throws IFException;

 The modified method interface would read as follows:

 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][]
 adjustments, String text) throws IFException;

 The adjustments array is optional (in which case it is null). If non-null,
 it is effectively typed as int[][4], i.e., an array of int[4] arrays, where
 the four elements of each row are:

 a[0] = x placement adjustment
 a[1] = y placement adjustment
 a[2] = x advance adjustment
 a[3] = y advance adjustment

 The [x,y] placement adjustments are added to the current point to determine
 the effective glyph (char) origin, and the [x,y] advance adjustments are
 applied to the current point after rendering the glyph (char) and performing
 the default (implicit) advance.

 To be more explicit, the algorithm using these adjustments is effectively
 as follows (ignoring word and letter spacing for the moment):

 int curPointX = x;
 int curPointY = y;
 for ( int i = 0, n = glyphs.length; i  n; i++ ) {
   int g = glyphs [ i ];
   int gx = curPointX;
   int gy = curPointY;
   int[] a = ( adjustments != null ) ? adjustments[i] : null;
   if ( a != null ) {
 gx += a[0];
 gy += a[1];
   }
   drawGlyph ( g, gx, gy );
   curPointX += font.getGlyphAdvanceX ( g );
   curPointY += font.getGlyphAdvanceY ( g );
   if ( a != null ) {
 curPointX += a[2];
 curPointY += a[3];
   }
 }

 It is mandatory to provide this generality in order to support not only
 complex scripts, but also non-complex scripts (e.g, Latin, Greek, Cyrillic,
 CJK, etc) when used with non-spacing marks (in many written languages) and
 also for other advanced typographic effects.

 Attached is a simple example of the use of this feature in order to adjust
 the placement (and advance) of U+064E ARABIC FATHA and U+0650 ARABIC KASRA,
 respectively, the upper and lower non-spacing marks shown in this example.

 Regards,
 Glenn






Re: upcoming change to IFPainter.drawText()

2010-08-30 Thread Glenn Adams
Oops, that code snippet should read:

int[][] reconcileAdjustments(int[] dx, int[][] gpos) {
  if ( dx == null ) {
return gpos;
  } else {
if ( gpos == null ) {
  gpos = new int[dx.length][4];
}
for ( int i = 0; i  dx.length; i++ ) {
  int d = dx[i];
  if ( *d* != 0 ) {
gpos[i][0] += d; // reconcile x placement adjustment
gpos[i][2] += d; // reconcile x advance adjustment
  }
}
  }
}


On Tue, Aug 31, 2010 at 4:51 AM, Glenn Adams gl...@skynav.com wrote:

 Perhaps it is useful to indicate how the existing dx[] adjustments map into
 the more generalized gpos[][] adjustments. Given a dx[] array or a gpos[][]
 array or neither, they are reconciled as follows:

 int[][] reconcileAdjustments(int[] dx, int[][] gpos) {
   if ( dx == null ) {
 return gpos;
   } else {
 if ( gpos == null ) {
   gpos = new int[dx.length][4];
  }
 for ( int i = 0; i  dx.length; i++ ) {
   int d = dx[i];
   if ( dx != 0 ) {
 gpos[i][0] += d; // reconcile x placement adjustment


 gpos[i][2] += d; // reconcile x advance adjustment


   }
 }
   }
 }

 The current semantics of dx[i] cause the current point to be adjusted to
 curPointX + dx[i] prior to rendering glyph[i], after which the implicit x
 advancement (width) of glyph[i] is added to curPointX. In the reconciliation
 of dx[] and gpos[][] above, dx[i] is added to both the x placement
 adjustment and the x advance adjustment of glyph[i], the net effect of which
 is that the x origin of glyph[i] is translated by dx[i], and then the
 current point x coordinate is advanced by the sum of the implicit glyph
 advancement and the x advance adjustment. Together, these yield the same
 behavior as presently indicated by the non-generalized form of drawText.

 There are a number of places in the existing code where this reconciliation
 could take place, including:

 (1) just prior to creating a word area, in which case a word area would
 carry only the gpos[][] adjustments;
 (2) just prior to calling IFPainter.drawText, i.e., in
 IFRenderer.TextUtil.flush();

 In both cases, the externalized, AT form of WordArea changes. In case (1),
 the letter-adjust attribute is effectively merged into a new
 position-adjust attribute, with letter-adjust being removed. In case (2),
 a new position-adjust attribute is added to hold gpos[][], but the
 existing letter-adjust attribute is retained as is.

 I have tentatively decided to use case (2), since this does not create any
 test regressions for the handful of tests that make reference to the
 letter-adjust attribute. It could always be moved further back, e.g., to
 (1), at a future date.

 Comments?

 G.

 On Mon, Aug 30, 2010 at 8:19 PM, Glenn Adams gl...@skynav.com wrote:

 Folks,

 I'd like to mention a change I will implement on IFPainter#drawText method
 in order to accommodate complex scripts (as well as non-complex script usage
 in a variety of written languages). I'm bringing this up now so there can be
 discussion ahead of time if needed.

 Basically, the change is to generalize the int[] dx parameter to be a two
 dimensional array of glyph placement/advancement adjustments.

 The current interface is:

 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
 String text) throws IFException;

 The modified method interface would read as follows:

 void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][]
 adjustments, String text) throws IFException;

 The adjustments array is optional (in which case it is null). If non-null,
 it is effectively typed as int[][4], i.e., an array of int[4] arrays, where
 the four elements of each row are:

 a[0] = x placement adjustment
 a[1] = y placement adjustment
 a[2] = x advance adjustment
 a[3] = y advance adjustment

 The [x,y] placement adjustments are added to the current point to
 determine the effective glyph (char) origin, and the [x,y] advance
 adjustments are applied to the current point after rendering the glyph
 (char) and performing the default (implicit) advance.

 To be more explicit, the algorithm using these adjustments is effectively
 as follows (ignoring word and letter spacing for the moment):

 int curPointX = x;
 int curPointY = y;
 for ( int i = 0, n = glyphs.length; i  n; i++ ) {
   int g = glyphs [ i ];
   int gx = curPointX;
   int gy = curPointY;
   int[] a = ( adjustments != null ) ? adjustments[i] : null;
   if ( a != null ) {
 gx += a[0];
 gy += a[1];
   }
   drawGlyph ( g, gx, gy );
   curPointX += font.getGlyphAdvanceX ( g );
   curPointY += font.getGlyphAdvanceY ( g );
   if ( a != null ) {
 curPointX += a[2];
 curPointY += a[3];
   }
 }

 It is mandatory to provide this generality in order to support not only
 complex scripts, but also non-complex scripts (e.g, Latin, Greek, Cyrillic,
 CJK, etc) when used with non-spacing marks (in many written languages) and
 also for other advanced typographic effects.

 Attached is a