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

Reply via email to