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 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 >> >> >> >> >