lout-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Margin kerning, patch #2


From: Ludovic Courtès
Subject: Margin kerning, patch #2
Date: Fri, 01 Jul 2005 15:03:12 +0200
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

Hello,

address@hidden (Ludovic Courtès) writes:

> Another solution might be to add heuristics to avoid margin-kerning
> glyphs that are "unreasonably wide".  "Unreasonably wide" could be
> defined as "wider than `x'" for instance.  This same heuristic could be
> applied to subsequent characters also.  For instance, a quote followed
> by a comma may be narrower than `x' and therefore eligible as a whole
> for margin kerning.  On the contrary, the ellipsis glyph may be too wide
> and will never be margin-kerned.

I implemented the idea above which is actually based on Jeff's
suggestion.  So now, subsequent "small" glyphs can be margin-kerned,
i.e. margin kerning is not limited to one character. Additionally,
characters "too wide" (i.e. wider than `x'), like ellipses, are not
margin-kerned.

How this impacts the sample I posted can be seen here:

  http://www.laas.fr/~lcourtes/software/lout/margin-kerning-test.pdf
  http://www.laas.fr/~lcourtes/software/lout/margin-kerning-test.old.pdf

For the sake of readability and maintainability, I've also separated the
margin kerning code.

Below is a brand new patch against Lout 3.30 + the ligature patch.
Please, let me know whether this looks good on actual documents.

Thanks,
Ludovic.



--- orig/externs.h
+++ mod/externs.h
@@ -574,6 +574,8 @@
 #define        STR_BREAK_NOLAST        AsciiToFull("unbreakablelast")
 #define        STR_BREAK_LAST          AsciiToFull("breakablelast")
 #define        STR_BREAK_SETOUTDENT    AsciiToFull("setoutdent")
+#define STR_BREAK_MARGINKERNING AsciiToFull("marginkerning")
+#define STR_BREAK_NOMARGINKERNING AsciiToFull("nomarginkerning")
 
 #define STR_SPACE_LOUT         AsciiToFull("lout")
 #define STR_SPACE_COMPRESS     AsciiToFull("compress")
@@ -674,6 +676,7 @@
   BOOLEAN      onobreaklast    : 1;    /* no break after last line of para  */
   BOOLEAN      obaselinemark   : 1;    /* baseline metrics                  */
   BOOLEAN      oligatures      : 1;    /* use ligatures                     */
+  BOOLEAN       omarginkerning  : 1;    /* perform margin kerning            */
 } STYLE;
 
 #define        line_gap(x)     (x).osu1.oline_gap
@@ -695,35 +698,37 @@
 #define        nobreaklast(x)  (x).onobreaklast
 #define        baselinemark(x) (x).obaselinemark
 #define        ligatures(x)    (x).oligatures
+#define marginkerning(x) (x).omarginkerning
 #define        yunit(x)        (x).oyunit
 #define        zunit(x)        (x).ozunit
 #define        outdent_len(x)  (x).ooutdent_len
 #define        smallcaps_len(x)(x).osmallcaps_len
 
-#define StyleCopy(x, y)                                                        
\
-( GapCopy(line_gap(x), line_gap(y)),                                   \
-  hyph_style(x) = hyph_style(y),                                       \
-  fill_style(x) = fill_style(y),                                       \
-  display_style(x) = display_style(y),                                 \
-  small_caps(x) = small_caps(y),                                       \
-  GapCopy(space_gap(x), space_gap(y)),                                 \
-  font(x) = font(y),                                                   \
-  colour(x) = colour(y),                                               \
-  texture(x) = texture(y),                                             \
-  outline(x) = outline(y),                                             \
-  language(x) = language(y),                                           \
-  nobreakfirst(x) = nobreakfirst(y),                                   \
-  nobreaklast(x) = nobreaklast(y),                                     \
-  baselinemark(x) = baselinemark(y),                                   \
-  ligatures(x) = ligatures(y),                                         \
-  vadjust(x) = vadjust(y),                                             \
-  hadjust(x) = hadjust(y),                                             \
-  padjust(x) = padjust(y),                                             \
-  space_style(x) = space_style(y),                                     \
-  yunit(x) = yunit(y),                                                 \
-  zunit(x) = zunit(y),                                                 \
-  outdent_len(x) = outdent_len(y),                                     \
-  smallcaps_len(x) = smallcaps_len(y)                                  \
+#define StyleCopy(x, y)                                \
+( GapCopy(line_gap(x), line_gap(y)),           \
+  hyph_style(x) = hyph_style(y),               \
+  fill_style(x) = fill_style(y),               \
+  display_style(x) = display_style(y),         \
+  small_caps(x) = small_caps(y),               \
+  GapCopy(space_gap(x), space_gap(y)),         \
+  font(x) = font(y),                           \
+  colour(x) = colour(y),                       \
+  texture(x) = texture(y),                     \
+  outline(x) = outline(y),                     \
+  language(x) = language(y),                   \
+  nobreakfirst(x) = nobreakfirst(y),           \
+  nobreaklast(x) = nobreaklast(y),             \
+  marginkerning(x) = marginkerning(y),         \
+  baselinemark(x) = baselinemark(y),           \
+  ligatures(x) = ligatures(y),                 \
+  vadjust(x) = vadjust(y),                     \
+  hadjust(x) = hadjust(y),                     \
+  padjust(x) = padjust(y),                     \
+  space_style(x) = space_style(y),             \
+  yunit(x) = yunit(y),                         \
+  zunit(x) = zunit(y),                         \
+  outdent_len(x) = outdent_len(y),             \
+  smallcaps_len(x) = smallcaps_len(y)          \
 )
 
 
@@ -3379,6 +3384,8 @@
 extern void      FontAdvanceCurrentPage(void);
 extern void      FontPageUsed(OBJECT face);
 extern BOOLEAN   FontNeeded(FILE *fp);
+extern  FULL_LENGTH FontGlyphHeight(FONT_NUM fnum, FULL_CHAR chr);
+extern  FULL_LENGTH FontGlyphWidth(FONT_NUM fnum, FULL_CHAR chr);
 
 /*****  z38.c    Character Mappings    **************************************/
 extern MAP_VEC   MapTable[];


--- orig/z07.c
+++ mod/z07.c
@@ -136,6 +136,17 @@
 { OBJECT res;
   NewWord(res, typ, StringLength(str), pos);
   StringCopy(string(res), str);
+
+  word_font(res) = 0;
+  word_colour(res) = 0;
+  word_texture(res) = 0;
+  word_outline(res) = 0;
+  word_language(res) = 0;
+  word_baselinemark(res) = 0;
+  word_ligatures(res) = 0;
+  word_hyph(res) = 0;
+  underline(res) = 0;
+
   FposCopy(fpos(res), *pos);
   debug4(DOS, DDD, "MakeWord(%s, %s, %s) returning %s",
     Image(typ), str, EchoFilePos(pos), EchoObject(res));


--- orig/z11.c
+++ mod/z11.c
@@ -84,6 +84,7 @@
   sprintf(buff, ":C%d:P%d", colour(*style), texture(*style));
   StringCat(res, AsciiToFull(buff));
   StringCat(res, AsciiToFull("]"));
+  /* FIXME:  Handle `marginkerning'.  */
   return res;
 } /* end EchoStyle */
 #endif
@@ -212,6 +213,10 @@
        nobreaklast(*style) = TRUE;
     else if( StringEqual(string(x), STR_BREAK_LAST) )
        nobreaklast(*style) = FALSE;
+    else if( StringEqual(string(x), STR_BREAK_MARGINKERNING) )
+        marginkerning(*style) = TRUE;
+    else if( StringEqual(string(x), STR_BREAK_NOMARGINKERNING) )
+        marginkerning(*style) = FALSE;
     else Error(11, 5, "found unknown option to %s symbol (%s)",
           WARN, &fpos(x), KW_BREAK, string(x));
   }


--- orig/z14.c
+++ mod/z14.c
@@ -176,7 +176,7 @@
                                                                        \
   /* set right link and calculate badness of the new interval */       \
   if( rlink != x )                                                     \
-  {                                                                    \
+  {                                                                    \
     assert( Up(newg) == LastUp(newg), "MoveRightToGap: newg!" );       \
     /* set save_space(newg) now so that it is OK to forget right */    \
     debug0(DOF, DDD, "  MoveRightToGap setting save_space(newg)");     \
@@ -211,7 +211,7 @@
     { if( hyph_allowed )                                               \
       {                                                                        
\
        /* hyphenation is allowed, so add hyph_word to nat_width */     \
-       if( is_word(type(right)) &&                                     \
+       if( is_word(type(right)) &&                                     \
         !(string(right)[StringLength(string(right))-1] == CH_HYPHEN) ) \
         {                                                              \
          /* make sure hyph_word exists and is of the right font */     \
@@ -234,7 +234,8 @@
          }                                                             \
                                                                        \
          mode(gap(newg)) = ADD_HYPH;                                   \
-         I.nat_width += size(hyph_word, COLM);                         \
+         if( marginkerning(save_style(x)) == FALSE )                   \
+           I.nat_width += size(hyph_word, COLM);                       \
          debug0(DOF, DDD, "   adding hyph_word from nat_width");       \
         }                                                              \
       }                                                                        
\
@@ -256,7 +257,7 @@
   if( unbreakable_at_right )  I.class = UNBREAKABLE_RIGHT;             \
   else if( I.class == TIGHT && mode(gap(newg)) == TAB_MODE )           \
     I.class = TOO_TIGHT, I.badness = TOO_TIGHT_BAD;                    \
-  debug0(DOF, DDD, "MoveRightToGap returning.");                               
\
+  debug0(DOF, DDD, "MoveRightToGap returning.");                       \
 }
 
 /*@::IntervalInit(), IntervalShiftRightEnd()@*********************************/
@@ -300,7 +301,7 @@
 /*                                                                           */
 /*****************************************************************************/
 
-#define IntervalShiftRightEnd(I, x, hyph_word, max_width, etc_width)   \
+#define IntervalShiftRightEnd(I, x, hyph_word, max_width, etc_width)   \
 { OBJECT rlink, g, right = nilobj;                                     \
   assert( I.class != AT_END, "IntervalShiftRightEnd: AT_END!" );       \
   rlink = I.rlink;                                                     \
@@ -317,7 +318,9 @@
     /* if hyphenation case, must take away width of hyph_word */       \
     /* and increase the badness to discourage breaks at this point */  \
     if( mode(gap(g)) == ADD_HYPH )                                     \
-    { I.nat_width -= size(hyph_word,COLM);                             \
+    { if( marginkerning(save_style(x)) == FALSE )                      \
+        I.nat_width -= size(hyph_word,COLM);                           \
+                                                                       \
       save_badness(g) += HYPH_BAD_INCR;                                        
\
       debug0(DOF, DDD, "   subtracting hyph_word from nat_width");     \
     }                                                                  \
@@ -496,6 +499,237 @@
 #endif
 
 
+/* Return true if CHAR's glyph height in font FONTNUM is "small".  A glyph's
+   height is considered small when it is lower than or equal to three fourth
+   of the height of the glyph for `x'.  Initially, I considered that anything
+   strictly smaller than `x' would be enough, but some fonts (namely
+   Palatino) have a glyph for `v' which is slightly smaller than that for
+   `x', hence weird results.  */
+#define SmallGlyphHeight(_fontnum, _char)              \
+  ((FontGlyphHeight((_fontnum), (_char)))              \
+   <= (3 * (FontGlyphHeight((_fontnum), 'x') >> 2)))
+
+
+/address@hidden ()@*****************************************************/
+/*                                                                           */
+/*  Perform left margin kerning of word FIRST_ON_LINE, whose parent is       */
+/*  PARENT.  If FIRST_ON_LINE's first glyph(s) deserve margin kerning, then  */
+/*  a new word object containing this/these glyph(s) is prepended to         */
+/*  FIRST_ON_LINE in PARENT.                                                 */
+/*                                                                           */
+/*****************************************************************************/
+static void KernWordLeftMargin(OBJECT first_on_line, OBJECT parent)
+{
+  /* It's a word: look at its first characters' glyph height.  */
+  FONT_NUM font;
+  FULL_CHAR *word_content, *wordp;
+  FULL_CHAR kerned_glyphs[20];
+  FULL_LENGTH kerned_glyphs_width = 0;
+  unsigned kerned_glyph_count = 0, word_len;
+
+  assert( is_word( type(first_on_line) ), "KernWordLeftMargin");
+
+  font = word_font(first_on_line);
+  word_content = string(first_on_line);
+  word_len = StringLength(word_content);
+
+  if(font >= 1)
+  {
+    /* Determine how many subsequent characters beginning WORD_CONTENT
+       deserve margin kerning.  Glyphs wider than the glyph for `x' will
+       _not_ be kerned at all, and only up to the width of the glyph for `x'
+       can be protruded in other cases.  */
+    FULL_LENGTH x_width = FontGlyphWidth(font, 'x');
+
+    for(wordp = word_content;
+       (*wordp) && (SmallGlyphHeight(font, *wordp));
+       wordp++, kerned_glyph_count++)
+    {
+      FULL_LENGTH glyph_width;
+
+      glyph_width = FontGlyphWidth(font, *wordp);
+      if(kerned_glyphs_width + glyph_width > x_width)
+       break;
+      if(kerned_glyph_count >= sizeof(kerned_glyphs))
+       break;
+
+      kerned_glyphs_width += glyph_width;
+      kerned_glyphs[kerned_glyph_count] = *wordp;
+    }
+
+    kerned_glyphs[kerned_glyph_count] = '\0';
+  }
+
+  if(kerned_glyph_count > 0)
+  { OBJECT z;
+    FULL_CHAR *unacc = NULL;
+    FULL_LENGTH glyph_width;
+
+    debug2(DOF, DD, "   margin-kerning %u glyph from "
+          "word \"%s\" (left margin)",
+          kerned_glyph_count, word_content);
+
+    /* Get font information.  */
+    if(finfo[font].font_table)
+    {
+      MAPPING m;
+      m = font_mapping(finfo[font].font_table);
+      unacc = MapTable[m]->map[MAP_UNACCENTED];
+    }
+
+    /* Add the first characters.  */
+    z = MakeWord(WORD, kerned_glyphs, &fpos(first_on_line));
+    word_font(z) = word_font(first_on_line);
+    word_colour(z) = word_colour(first_on_line);
+    word_texture(z) = word_texture(first_on_line);
+    word_outline(z) = word_outline(first_on_line);
+    word_language(z) = word_language(first_on_line);
+    word_baselinemark(z) = word_baselinemark(first_on_line);
+    word_ligatures(z) = word_ligatures(first_on_line);
+    word_hyph(z) = hyph_style(save_style(z)) == HYPH_ON;
+    underline(z) = underline(first_on_line);
+    FontWordSize(z);
+
+    /* Make it zero-width.
+       FIXME:  This awful trick allows Z to expand outside of the
+       paragraph itself while still appearing as having a null
+       width.  */
+    glyph_width = size(z, COLM);
+    back(z, COLM) = -glyph_width;
+    fwd(z, COLM) = glyph_width;
+    Link(parent, z);
+
+    /* Add a zero-width gap object.  */
+    New(z, GAP_OBJ);
+    vspace(z) = 0;
+    if ((word_content[kerned_glyph_count]) && (unacc))
+      hspace(z) = FontKernLength(font, unacc,
+                                word_content[kerned_glyph_count - 1],
+                                word_content[kerned_glyph_count]);
+    else
+      hspace(z) = 0;
+    underline(z) = underline(first_on_line);
+    SetGap(gap(z), TRUE, FALSE, TRUE, FIXED_UNIT, EDGE_MODE, 0);
+    Link(parent, z);
+
+    /* Remove the first char from FIRST_ON_LINE and recompute its
+       size.  */
+    {
+      unsigned s;
+      for (s = 0; s < word_len - kerned_glyph_count; s++)
+       word_content[s] = word_content[s + kerned_glyph_count];
+      word_content[word_len - kerned_glyph_count] = '\0';
+    }
+    FontWordSize(first_on_line);
+  }
+}
+
+/address@hidden ()@*****************************************************/
+/*                                                                           */
+/*  Perform right margin kerning of word LAST_ON_LINE, whose parent is       */
+/*  PARENT.  If LAST_ON_LINE's first glyph(s) deserve margin kerning, then   */
+/*  a new word object containing this/these glyph(s) is prepended to         */
+/*  LAST_ON_LINE in PARENT.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+static void KernWordRightMargin(OBJECT last_on_line, OBJECT parent)
+{
+  FONT_NUM  font;
+  FULL_CHAR *word_content, *wordp;
+  FULL_CHAR kerned_glyphs[20];
+  FULL_LENGTH kerned_glyphs_width = 0;
+  unsigned kerned_glyph_count = 0, word_len;
+
+  assert( is_word( type(last_on_line) ), "KernWordRightMargin");
+
+  font = word_font(last_on_line);
+  word_content = string(last_on_line);
+  word_len = StringLength(word_content);
+
+  if(font >= 1)
+  {
+    /* Determine how many subsequent characters ending WORD_CONTENT deserve
+       margin kerning.  Glyphs wider than the glyph for `x' will _not_ be
+       kerned at all, and only up to the width of the glyph for `x' can be
+       protruded in other cases.  */
+    FULL_LENGTH x_width = FontGlyphWidth(font, 'x');
+
+    for(wordp = &word_content[word_len - 1];
+       (wordp >= word_content) && (SmallGlyphHeight(font, *wordp));
+       wordp--, kerned_glyph_count++)
+    {
+      FULL_LENGTH glyph_width;
+
+      glyph_width = FontGlyphWidth(font, *wordp);
+      if(kerned_glyphs_width + glyph_width > x_width)
+       break;
+      if(kerned_glyph_count >= sizeof(kerned_glyphs))
+       break;
+
+      kerned_glyphs_width += glyph_width;
+      kerned_glyphs[kerned_glyph_count] = *wordp;
+    }
+
+    kerned_glyphs[kerned_glyph_count] = '\0';
+  }
+
+  if(kerned_glyph_count > 0)
+  { OBJECT z;
+    FULL_CHAR *unacc = NULL;
+
+    /* Get font information.  */
+    if (finfo[font].font_table)
+    {
+      MAPPING m;
+      m = font_mapping(finfo[font].font_table);
+      unacc = MapTable[m]->map[MAP_UNACCENTED];
+    }
+
+    debug2(DOF, DD, "   margin-kerning %u glyph from "
+          "word \"%s\" (right margin)",
+          kerned_glyph_count, word_content);
+
+    /* Add a zero-width gap object.  */
+    New(z, GAP_OBJ);
+    vspace(z) = 0;
+    if((word_len > 1) && (unacc))
+      hspace(z) = FontKernLength(font, unacc,
+                                word_content[word_len - kerned_glyph_count - 
1],
+                                word_content[word_len - kerned_glyph_count]);
+    else
+      hspace(z) = 0;
+    underline(z) = underline(last_on_line);
+    SetGap(gap(z), TRUE, FALSE, TRUE, FIXED_UNIT, EDGE_MODE, 0);
+    Link(parent, z);
+
+    /* Add the last characters.  */
+    z = MakeWord(WORD, &word_content[word_len - kerned_glyph_count],
+                &fpos(last_on_line));
+    word_font(z) = word_font(last_on_line);
+    word_colour(z) = word_colour(last_on_line);
+    word_texture(z) = word_texture(last_on_line);
+    word_outline(z) = word_outline(last_on_line);
+    word_language(z) = word_language(last_on_line);
+    word_baselinemark(z) = word_baselinemark(last_on_line);
+    word_ligatures(z) = word_ligatures(last_on_line);
+    word_hyph(z) = hyph_style(save_style(last_on_line)) == HYPH_ON;
+    underline(z) = underline(last_on_line);
+
+    FontWordSize(z);
+
+    /* Make it zero-width.  */
+    fwd(z, COLM) = 0;
+    back(z, COLM) = 0;
+
+    /* Remove the last char from LAST_ON_LINE and recompute its
+       size.  */
+    word_content[word_len - kerned_glyph_count] = '\0';
+    FontWordSize(last_on_line);
+
+    Link(parent, z);
+  }
+}
+
 /*@::FillObject()@************************************************************/
 /*                                                                           */
 /*  FillObject(x, c, multi, can_hyphenate, allow_shrink, extend_unbreakable, */
@@ -748,6 +982,18 @@
       back(y, COLM) = 0;
       fwd(y, COLM) = max_width;
 
+      if( marginkerning( save_style(x) ) )
+      { /* Margin kerning: look at this line's first character.  */
+       OBJECT first_on_line, parent;
+
+       /* Get the first object on this line.  */
+       parent = NextDown(llink);
+       Child(first_on_line, parent);
+
+       if( is_word( type(first_on_line) ) )
+         KernWordLeftMargin(first_on_line, parent);
+      }
+
       /* if outdented paragraphs, add 2.0f @Wide & to front of new line */
       if( display_style(save_style(x)) == DISPLAY_OUTDENT ||
           display_style(save_style(x)) == DISPLAY_ORAGGED )
@@ -784,17 +1030,37 @@
       Child(lgap, llink);
       if( mode(gap(lgap)) == ADD_HYPH )
       { OBJECT z, tmp;
+        FONT_NUM font;
+       FULL_CHAR *unacc = NULL, *word_content;
+       unsigned word_len;
 
        /* find word hyphen attaches to, since need its underline and font */
        Child(tmp, PrevDown(LastDown(x)));  /* last is lgap, so one before */
        debug2(DOF, D, "tmp = %s %s", Image(type(tmp)), EchoObject(tmp));
        assert(is_word(type(tmp)), "FillObject: !is_word(type(tmp))!");
+       word_content = string(tmp);
+       word_len = StringLength(word_content);
+
+       /* get font information */
+       font = word_font(tmp);
+       if (finfo[font].font_table)
+         {
+           MAPPING m;
+           m = font_mapping(finfo[font].font_table);
+           unacc = MapTable[m]->map[MAP_UNACCENTED];
+         }
 
        /* add zero-width gap object */
         New(z, GAP_OBJ);
        debug0(DOF, DD, "   adding hyphen");
        debug0(DOF, DD, "");
-       hspace(z) = vspace(z) = 0;
+       vspace(z) = 0;
+       if (unacc)
+         hspace(z) = FontKernLength(font, unacc,
+                                    word_content[word_len - 1], CH_HYPHEN);
+       else
+         hspace(z) = 0;
+
        underline(z) = underline(tmp);
        SetGap(gap(z), TRUE, FALSE, TRUE, FIXED_UNIT, EDGE_MODE, 0);
        Link(x, z);
@@ -810,9 +1076,27 @@
        word_ligatures(z) = word_ligatures(tmp);
        word_hyph(z) = hyph_style(save_style(x)) == HYPH_ON;
        underline(z) = underline(tmp);
+
        FontWordSize(z);
+       if( marginkerning(save_style(x)) )
+       {
+         /* Margin kerning: set the hyphen's width to zero.  */
+         back(z, COLM) = 0;
+         fwd(z, COLM) = 0;
+       }
+
        Link(x, z);
       }
+      else if( marginkerning(save_style(x)) )
+      {
+       /* Margin kerning: look at the height of this line's last char.  */
+       OBJECT last_on_line;
+
+       /* Get the last object on this line.  */
+       Child(last_on_line, PrevDown(LastDown(x)));
+       if( is_word(type(last_on_line)) )
+         KernWordRightMargin(last_on_line, x);
+      }
 
       /* attach y to res, recycle lgap for gap separating the two lines */
       Link(NextDown(res), y);
@@ -906,7 +1190,7 @@
                word_baselinemark(prev) == word_baselinemark(next) &&
                word_ligatures(prev) == word_ligatures(next) &&
                underline(prev) == underline(next) )
-           { 
+           {
              debug2(DOF, DD, "joining %s with %s", EchoObject(prev),
                EchoObject(next));
              typ = type(prev) == QWORD || type(next) == QWORD ? QWORD : WORD;
@@ -919,7 +1203,9 @@
              word_baselinemark(tmp) = word_baselinemark(prev);
              word_ligatures(tmp) = word_ligatures(prev);
              word_hyph(tmp) = word_hyph(prev);
+
              FontWordSize(tmp);
+
              underline(tmp) = underline(prev);
              MoveLink(ylink, tmp, CHILD);
              DisposeChild(Up(prev));


--- orig/z18.c
+++ mod/z18.c
@@ -89,6 +89,7 @@
   smallcaps_len(InitialStyle)   = 0.7 * FR;            /* i.e. 0.7 scale    */
   nobreakfirst(InitialStyle)   = FALSE;
   nobreaklast(InitialStyle)    = FALSE;
+  marginkerning(InitialStyle)   = FALSE;                /* disabled by dft   */
   baselinemark(InitialStyle)   = FALSE;                /* i.e. not baseline */
   ligatures(InitialStyle)      = TRUE;                 /* i.e. ligatures    */
 

--- orig/z37.c
+++ mod/z37.c
@@ -1984,3 +1984,44 @@
   }
   return first_need;
 } /* end FontNeeded */
+
+
+/* FIXME:  Obviously, the next two functions should rather be inlined.  */
+
+/*@::FontGlyphHeight()@*******************************************************/
+/*                                                                           */
+/*  SHORT_LENGTH FontGlyphHeight(fnum, chr)                                  */
+/*                                                                           */
+/*  Return the height of the glyph that corresponds to character chr in      */
+/*  font fnum.                                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+FULL_LENGTH FontGlyphHeight(FONT_NUM fnum, FULL_CHAR chr)
+{
+  struct metrics *fnt;
+
+  assert ((fnum >= 1) && (fnum <= font_count), "FontGlyphHeight");
+
+  fnt = finfo[fnum].size_table;
+  return (fnt ? fnt[chr].up - fnt[chr].down : 0);
+}
+
+/*@::FontGlyphWidth()@*******************************************************/
+/*                                                                           */
+/*  SHORT_LENGTH FontGlyphWidth(fnum, chr)                                  */
+/*                                                                           */
+/*  Return the width of the glyph that corresponds to character chr in      */
+/*  font fnum.                                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+FULL_LENGTH FontGlyphWidth(FONT_NUM fnum, FULL_CHAR chr)
+{
+  struct metrics *fnt;
+
+  assert ((fnum >= 1) && (fnum <= font_count), "FontGlyphWidth");
+
+  fnt = finfo[fnum].size_table;
+  return (fnt ? fnt[chr].right - fnt[chr].left : 0);
+}


--- orig/z46.c
+++ mod/z46.c
@@ -180,7 +180,10 @@
   New(opt_constraints(hd), ACAT);
   StyleCopy(save_style(opt_components(hd)), *style);
   if( gall_dir(hd) == ROWM )
+  {
     hyph_style(save_style(opt_components(hd))) = HYPH_OFF;
+    marginkerning(save_style(opt_components(hd))) = 0;
+  }
 
   debug0(DOG, D, "SetOptimize returning:");
   ifdebug(DOG, D, DebugOptimize(hd));



reply via email to

[Prev in Thread] Current Thread [Next in Thread]