You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ma...@apache.org on 2008/05/28 18:10:32 UTC

svn commit: r660998 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/fo/ src/java/org/apache/fop/fonts/ src/java/org/apache/fop/layoutmgr/inline/ test/layoutengine/standard-testcases/

Author: maxberger
Date: Wed May 28 09:10:32 2008
New Revision: 660998

URL: http://svn.apache.org/viewvc?rev=660998&view=rev
Log:
Implemented Font auto-selection word-by-word

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/FontSelector.java
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/block_font-autoselect.xml
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/FOText.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/FOText.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/FOText.java?rev=660998&r1=660997&r2=660998&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/FOText.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/FOText.java Wed May 28 09:10:32 2008
@@ -37,7 +37,7 @@
 /**
  * A text node (PCDATA) in the formatting object tree.
  *
- * Unfortunately the BufferManager implementatation holds
+ * Unfortunately the BufferManager implementation holds
  * onto references to the character data in this object
  * longer than the lifetime of the object itself, causing
  * excessive memory consumption and OOM errors.

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/FontSelector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/FontSelector.java?rev=660998&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/FontSelector.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/FontSelector.java Wed May 28 09:10:32 2008
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: FontCollection.java 654783 2008-05-09 12:30:40Z vhennebert $ */
+
+package org.apache.fop.fonts;
+
+import org.apache.fop.datatypes.PercentBaseContext;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.properties.CommonFont;
+
+/**
+ * Helper class for automatic font selection.
+ * <p>
+ * TODO: Check if this could be merged with another font class, such as
+ * {@link FontManager}.
+ */
+public final class FontSelector {
+    private FontSelector() {
+        // Static since this is an utility class.
+    }
+
+    private static Font selectFontForCharacter(char c, FONode fonode,
+            CommonFont commonFont, PercentBaseContext context) {
+        FontInfo fi = fonode.getFOEventHandler().getFontInfo();
+        FontTriplet[] fontkeys = commonFont.getFontState(fi);
+        for (int i = 0; i < fontkeys.length; i++) {
+            Font font = fi.getFontInstance(fontkeys[i], commonFont.fontSize
+                    .getValue(context));
+            if (font.hasChar(c)) {
+                return font;
+            }
+        }
+        return fi.getFontInstance(fontkeys[0], commonFont.fontSize
+                .getValue(context));
+
+    }
+
+    /**
+     * Selects a font which is able to display the given character.
+     * 
+     * @param fobj
+     *            a Character object containing the character and its
+     *            attributes.
+     * @param context
+     *            the Percent-based context needed for creating the actual font.
+     * @return a Font object.
+     */
+    public static Font selectFontForCharacter(Character fobj,
+            PercentBaseContext context) {
+        return FontSelector.selectFontForCharacter(fobj.getCharacter(), fobj,
+                fobj.getCommonFont(), context);
+    }
+
+    /**
+     * Selects a font which is able to display the given character.
+     * 
+     * @param c
+     *            character to find.
+     * @param text
+     *            the text object which contains the character
+     * @param context
+     *            the Percent-based context needed for creating the actual font.
+     * @return a Font object.
+     */
+    public static Font selectFontForCharacterInText(char c, FOText text,
+            PercentBaseContext context) {
+        return FontSelector.selectFontForCharacter(c, text, text
+                .getCommonFont(), context);
+    }
+
+    /**
+     * Selects a font which is able to display the most of the given characters.
+     * 
+     * @param textArray
+     *            Text to go through
+     * @param firstIndex
+     *            first index within text.
+     * @param breakIndex
+     *            last index +1 within text.
+     * @param text
+     *            the text object which contains the character
+     * @param context
+     *            the Percent-based context needed for creating the actual font.
+     * @return a Font object.
+     */
+    public static Font selectFontForCharactersInText(char[] textArray,
+            int firstIndex, int breakIndex, FOText text,
+            PercentBaseContext context) {
+        final FontInfo fi = text.getFOEventHandler().getFontInfo();
+        final CommonFont commonFont = text.getCommonFont();
+        final FontTriplet[] fontkeys = commonFont.getFontState(fi);
+        final int numFonts = fontkeys.length;
+        final Font[] fonts = new Font[numFonts];
+        final int[] fontCount = new int[numFonts];
+
+        for (int fontnum = 0; fontnum < numFonts; fontnum++) {
+            final Font font = fi.getFontInstance(fontkeys[fontnum],
+                    commonFont.fontSize.getValue(context));
+            fonts[fontnum] = font;
+            for (int pos = firstIndex; pos < breakIndex; pos++) {
+                if (font.hasChar(textArray[pos])) {
+                    fontCount[fontnum]++;
+                }
+            }
+
+            // quick fall through if all characters can be displayed
+            if (fontCount[fontnum] == (breakIndex - firstIndex)) {
+                return font;
+            }
+        }
+
+        Font font = fonts[0];
+        int max = fontCount[0];
+
+        for (int fontnum = 1; fontnum < numFonts; fontnum++) {
+            final int curCount = fontCount[fontnum];
+            if (curCount > max) {
+                font = fonts[fontnum];
+                max = curCount;
+            }
+        }
+        return font;
+    }
+
+}

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java?rev=660998&r1=660997&r2=660998&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java Wed May 28 09:10:32 2008
@@ -26,8 +26,7 @@
 import org.apache.fop.fo.flow.Character;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.fonts.FontSelector;
 import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
@@ -62,7 +61,7 @@
     /** {@inheritDoc} */
     public void initialize() {
         Character fobj = (Character)this.fobj;        
-        font = this.selectFontForCharacter(fobj);
+        font = FontSelector.selectFontForCharacter(fobj, this);
         SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing());
         letterSpaceIPD = ls.getSpace();
         hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font);
@@ -72,33 +71,6 @@
         chArea.setBaselineOffset(font.getAscender());
         setCurrentArea(chArea);
     }
-    
-    /**
-     * Selects a font which is able to display the given character.
-     * <p>
-     * Please note: this implements the font-selection-strategy
-     * character-by-character.
-     * <p>
-     * TODO: The same function could apply to other elements as well.
-     * 
-     * @param fobj
-     *            a Character object containing the character and its
-     *            attributed.
-     * @return a Font object.
-     */
-    private Font selectFontForCharacter(Character fobj) {
-        FontInfo fi = fobj.getFOEventHandler().getFontInfo();
-        FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
-        for (int i = 0; i < fontkeys.length; i++) {
-            font = fi.getFontInstance(fontkeys[i],
-                    fobj.getCommonFont().fontSize.getValue(this));
-            if (font.hasChar(fobj.getCharacter())) {
-                return font;
-            }
-        }
-        return fi.getFontInstance(fontkeys[0],
-                fobj.getCommonFont().fontSize.getValue(this));
-    }
 
     private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) {
         org.apache.fop.area.inline.TextArea text

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java?rev=660998&r1=660997&r2=660998&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Wed May 28 09:10:32 2008
@@ -32,6 +32,7 @@
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontSelector;
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthBox;
@@ -70,6 +71,7 @@
         private boolean isHyphenated;
         private boolean isSpace;
         private boolean breakOppAfter;
+        private final Font font;
 
         AreaInfo(short startIndex,
                         short breakIndex,
@@ -78,7 +80,8 @@
                         MinOptMax areaIPD,
                         boolean isHyphenated,
                         boolean isSpace,
-                        boolean breakOppAfter) {
+                        boolean breakOppAfter,
+                        Font font) {
             this.startIndex = startIndex;
             this.breakIndex = breakIndex;
             this.wordSpaceCount = wordSpaceCount;
@@ -87,6 +90,7 @@
             this.isHyphenated = isHyphenated;
             this.isSpace = isSpace;
             this.breakOppAfter = breakOppAfter;
+            this.font = font;
         }
 
         public String toString() {
@@ -97,6 +101,7 @@
                 + ", bidx=" + breakIndex
                 + ", hyph=" + isHyphenated
                 + ", space=" + isSpace
+                + ", font=" + font
                 + "]";
         }
 
@@ -139,7 +144,8 @@
 
     private static final char NEWLINE = '\n';
 
-    private Font font = null;
+    /** Font used for the space between words. */
+    private Font spaceFont = null;
     /** Start index of next TextArea */
     private short nextStart = 0;
     /** size of a space character (U+0020) glyph in current font */
@@ -150,10 +156,6 @@
     private int hyphIPD;
     /** 1/1 of word-spacing value */
     private SpaceVal ws;
-    /** 1/2 of word-spacing value */
-    private SpaceVal halfWS;
-    /** 1/2 of letter-spacing value */
-    private SpaceVal halfLS;
 
     private boolean hasChanged = false;
     private int returnedIndex = 0;
@@ -206,23 +208,19 @@
 
     /** {@inheritDoc} */
     public void initialize() {
-        FontInfo fi = foText.getFOEventHandler().getFontInfo();
-        FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi);
-        font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this));
+        
+        spaceFont = FontSelector.selectFontForCharacterInText(' ', foText, this);
 
         // With CID fonts, space isn't neccesary currentFontState.width(32)
-        spaceCharIPD = font.getCharWidth(' ');
+        spaceCharIPD = spaceFont.getCharWidth(' ');
         // Use hyphenationChar property
-        hyphIPD = foText.getCommonHyphenation().getHyphIPD(font);
+        
+        // TODO: Use hyphen based on actual font used!
+        hyphIPD = foText.getCommonHyphenation().getHyphIPD(spaceFont);
 
         SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing());
-        halfLS = new SpaceVal(MinOptMax.multiply(ls.getSpace(), 0.5),
-                ls.isConditional(), ls.isForcing(), ls.getPrecedence());
 
-        ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, font);
-        // Make half-space: <space> on either side of a word-space)
-        halfWS = new SpaceVal(MinOptMax.multiply(ws.getSpace(), 0.5),
-                ws.isConditional(), ws.isForcing(), ws.getPrecedence());
+        ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, spaceFont);
 
         // letter space applies only to consecutive non-space characters,
         // while word space applies to space characters;
@@ -255,7 +253,7 @@
     public void addAreas(PositionIterator posIter, LayoutContext context) {
 
         // Add word areas
-        AreaInfo ai = null;
+        AreaInfo ai; 
         int wordSpaceCount = 0;
         int letterSpaceCount = 0;
         int firstAreaInfoIndex = -1;
@@ -265,6 +263,7 @@
         /* On first area created, add any leading space.
          * Calculate word-space stretch value.
          */
+        AreaInfo lastAi = null;
         while (posIter.hasNext()) {
             LeafPosition tbpNext = (LeafPosition) posIter.next();
             if (tbpNext == null) {
@@ -272,18 +271,38 @@
             }
             if (tbpNext.getLeafPos() != -1) {
                 ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos());
-                if (firstAreaInfoIndex == -1) {
+                if (lastAi == null || ai.font != lastAi.font) {
+                    if (lastAi != null) {
+                        this.addAreaInfoAreas(lastAi, wordSpaceCount,
+                                letterSpaceCount, firstAreaInfoIndex,
+                                lastAreaInfoIndex, realWidth, context);
+                    }
                     firstAreaInfoIndex = tbpNext.getLeafPos();
-                }
+                    wordSpaceCount = 0;
+                    letterSpaceCount = 0;
+                    realWidth = new MinOptMax(0);                    
+                } 
                 wordSpaceCount += ai.wordSpaceCount;
                 letterSpaceCount += ai.letterSpaceCount;
                 realWidth.add(ai.areaIPD);
                 lastAreaInfoIndex = tbpNext.getLeafPos();
+                lastAi = ai;
             }
         }
-        if (ai == null) {
-            return;
+        if (lastAi != null) {
+            this.addAreaInfoAreas(lastAi, wordSpaceCount, letterSpaceCount,
+                    firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context);
         }
+    }
+        
+    private void addAreaInfoAreas(AreaInfo ai, int wordSpaceCount,
+            int letterSpaceCount, int firstAreaInfoIndex,
+            int lastAreaInfoIndex, MinOptMax realWidth, LayoutContext context) {
+        
+        // TODO: These two statements (if, for) where like this before my recent
+        // changes. However, it seems as if they should use the AreaInfo from
+        // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai.
+        // This needs to be checked.
         int textLength = ai.breakIndex - ai.startIndex;
         if (ai.letterSpaceCount == textLength && !ai.isHyphenated
                    && context.isLastArea()) {
@@ -353,9 +372,8 @@
         }
 
         TextArea t = createTextArea(realWidth, totalAdjust, context,
-                                    wordSpaceIPD.opt - spaceCharIPD,
-                                    firstAreaInfoIndex, lastAreaInfoIndex,
-                                    context.isLastArea());
+                wordSpaceIPD.opt - spaceCharIPD, firstAreaInfoIndex,
+                lastAreaInfoIndex, context.isLastArea(), ai.font);
 
         // wordSpaceDim is computed in relation to wordSpaceIPD.opt
         // but the renderer needs to know the adjustment in relation
@@ -391,11 +409,12 @@
      * @param firstIndex the index of the first AreaInfo used for the TextArea
      * @param lastIndex the index of the last AreaInfo used for the TextArea
      * @param isLastArea is this TextArea the last in a line?
+     * @param font Font to be used in this particular TextArea
      * @return the new text area
      */
     protected TextArea createTextArea(MinOptMax width, int adjust,
-                                      LayoutContext context, int spaceDiff,
-                                      int firstIndex, int lastIndex, boolean isLastArea) {
+            LayoutContext context, int spaceDiff, int firstIndex,
+            int lastIndex, boolean isLastArea, Font font) {
         TextArea textArea;
         if (context.getIPDAdjust() == 0.0) {
             // create just a TextArea
@@ -409,6 +428,7 @@
         }
         textArea.setIPD(width.opt + adjust);
         textArea.setBPD(font.getAscender() - font.getDescender());
+        
         textArea.setBaselineOffset(font.getAscender());
         if (textArea.getBPD() == alignmentContext.getHeight()) {
             textArea.setOffset(0);
@@ -548,6 +568,9 @@
                     while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) {
                         lastIndex--;
                     }
+                    final Font font = FontSelector
+                            .selectFontForCharactersInText(textArray,
+                                    thisStart, lastIndex, foText, this);
                     int wordLength = lastIndex - thisStart;
                     boolean kerning = font.hasKerning();
                     MinOptMax wordIPD = new MinOptMax(0);
@@ -592,8 +615,9 @@
 
                     // create the AreaInfo object
                     ai = new AreaInfo(thisStart, lastIndex, (short) 0,
-                            (short) iLetterSpaces,
-                            wordIPD, textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity);
+                            (short) iLetterSpaces, wordIPD,
+                            textArray[lastIndex] == CharUtilities.SOFT_HYPHEN,
+                            false, breakOpportunity, font);
                     prevAi = ai;
                     vecAreaInfo.add(ai);
                     tempStart = nextStart;
@@ -610,8 +634,9 @@
                     // create the AreaInfo object
                     ai = new AreaInfo(thisStart, nextStart,
                             (short) (nextStart - thisStart), (short) 0,
-                            MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart),
-                            false, true, breakOpportunity);
+                            MinOptMax.multiply(wordSpaceIPD, nextStart
+                                    - thisStart), false, true,
+                            breakOpportunity, spaceFont);
                     vecAreaInfo.add(ai);
                     prevAi = ai;
 
@@ -647,15 +672,17 @@
                 // preserved space or non-breaking space:
                 // create the AreaInfo object
                 ai = new AreaInfo(nextStart, (short) (nextStart + 1),
-                        (short) 1, (short) 0,
-                        wordSpaceIPD, false, true, breakOpportunity);
+                        (short) 1, (short) 0, wordSpaceIPD, false, true,
+                        breakOpportunity, spaceFont);
                 thisStart = (short) (nextStart + 1);
             } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) {
                 // create the AreaInfo object
+                final Font font = FontSelector.selectFontForCharacterInText(ch,
+                        foText, this);
                 MinOptMax ipd = new MinOptMax(font.getCharWidth(ch));
                 ai = new AreaInfo(nextStart, (short) (nextStart + 1),
-                        (short) 0, (short) 0,
-                        ipd, false, true, breakOpportunity);
+                        (short) 0, (short) 0, ipd, false, true,
+                        breakOpportunity, font);
                 thisStart = (short) (nextStart + 1);
             } else if (ch == NEWLINE) {
                 // linefeed; this can happen when linefeed-treatment="preserve"
@@ -673,6 +700,8 @@
                 lastIndex--;
             }
             int wordLength = lastIndex - thisStart;
+            final Font font = FontSelector.selectFontForCharactersInText(
+                    textArray, thisStart, lastIndex, foText, this);
             boolean kerning = font.hasKerning();
             MinOptMax wordIPD = new MinOptMax(0);
             for (int i = thisStart; i < lastIndex; i++) {
@@ -703,9 +732,8 @@
             wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces));
 
             // create the AreaInfo object
-            ai = new AreaInfo(thisStart, (short)lastIndex, (short) 0,
-                    (short) iLetterSpaces,
-                    wordIPD, false, false, false);
+            ai = new AreaInfo(thisStart, (short) lastIndex, (short) 0,
+                    (short) iLetterSpaces, wordIPD, false, false, false, font);
             vecAreaInfo.add(ai);
             tempStart = nextStart;
 
@@ -715,9 +743,9 @@
             ai = null;
         } else if (inWhitespace) {
             ai = new AreaInfo(thisStart, (short) (nextStart),
-                    (short) (nextStart - thisStart), (short) 0,
-                    MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart),
-                    false, true, true);
+                    (short) (nextStart - thisStart), (short) 0, MinOptMax
+                            .multiply(wordSpaceIPD, nextStart - thisStart),
+                    false, true, true, spaceFont);
             vecAreaInfo.add(ai);
 
             // create the elements
@@ -828,6 +856,7 @@
         int startIndex = ai.startIndex;
         int stopIndex;
         boolean nothingChanged = true;
+        final Font font = ai.font;
 
         while (startIndex < ai.breakIndex) {
             MinOptMax newIPD = new MinOptMax(0);
@@ -881,15 +910,12 @@
                 if (changeList == null) {
                     changeList = new LinkedList();
                 }
-                changeList.add
-                    (new PendingChange
-                     (new AreaInfo((short) startIndex, (short) stopIndex,
-                                   (short) 0,
-                                   (short) (isWordEnd
-                                            ? (stopIndex - startIndex - 1)
-                                            : (stopIndex - startIndex)),
-                                   newIPD, hyphenFollows, false, false),
-                      ((LeafPosition) pos).getLeafPos()));
+                changeList.add(new PendingChange(new AreaInfo(
+                        (short) startIndex, (short) stopIndex, (short) 0,
+                        (short) (isWordEnd ? (stopIndex - startIndex - 1)
+                                : (stopIndex - startIndex)), newIPD,
+                        hyphenFollows, false, false, font),
+                        ((LeafPosition) pos).getLeafPos()));
                 nothingChanged = false;
             }
             startIndex = stopIndex;

Added: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/block_font-autoselect.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/block_font-autoselect.xml?rev=660998&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/block_font-autoselect.xml (added)
+++ xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/block_font-autoselect.xml Wed May 28 09:10:32 2008
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id: block_font-family.xml 627324 2008-02-13 09:35:01Z maxberger $ -->
+<testcase>
+  <info>
+    <p>
+      This test checks the font auto selection.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="210mm" page-height="297mm">
+          <fo:region-body/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="normal" white-space-collapse="true">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block>font-family not given</fo:block>
+          <fo:block>this text contains a &#x2211; symbol in the middle</fo:block>
+          <fo:block>mixed contents should be</fo:block>
+          <fo:block>&#x2211;&#x2211;text</fo:block>
+          <fo:block>&#x2211;&#x2211;&#x2211;&#x2211;text</fo:block>
+          <fo:block>&#x2211;&#x2211;&#x2211;&#x2211;sym</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="sans-serif" xpath="//flow/block[1]/lineArea/text/@font-name"/>
+    <eval expected="sans-serif" xpath="//flow/block[2]/lineArea/text[1]/@font-name"/>
+    <eval expected="Symbol" xpath="//flow/block[2]/lineArea/text[2]/@font-name"/>
+    <eval expected="sans-serif" xpath="//flow/block[2]/lineArea/text[3]/@font-name"/>
+    <eval expected="sans-serif" xpath="//flow/block[3]/lineArea/text[1]/@font-name"/>
+    <eval expected="sans-serif" xpath="//flow/block[4]/lineArea/text[1]/@font-name"/>
+    <eval expected="sans-serif" xpath="//flow/block[5]/lineArea/text[1]/@font-name"/>
+    <eval expected="Symbol" xpath="//flow/block[6]/lineArea/text[1]/@font-name"/>
+  </checks>
+</testcase>



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org


Re: svn commit: r660998 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/fo/ src/java/org/apache/fop/fonts/ src/java/org/apache/fop/layoutmgr/inline/ test/layoutengine/standard-testcases/

Posted by Max Berger <ma...@berger.name>.
Andreas,

just to follow up and show that I have not forgotten your recent  
email :)

Am 29.05.2008 um 19:01 schrieb Andreas Delmelle:
>> There is still an open issue: When the font is changed, the metrics
>> for the line are not. E.g. when i have something like
>>
>> test SIGMA test
>> <fo:block>test  &#x2211; test</fo:block>
>>
>> the SIGMA character is set lower than it should be. At this time I  
>> was
>> unable to find the cause of this behavior. Maybe someone has a hint  
>> as
>> to why this happens?
>
> To further investigate, compare the behavior with:
>
> <fo:block>test  <fo:inline font-family="Symbol">&#x2211;</fo:inline>  
> test</fo:block>
> <fo:block>test  <fo:character font-family="Symbol"  
> character="&#x2211;" /> test</fo:block>
>
> The fo:inline or fo:character trigger the creation of a new  
> org.apache.fop.layoutmgr.inline.AlignmentContext, which is taken  
> into account by the LineLayoutManager associated to the fo:block.
> That context is used to determine the alignment point for the  
> content of the fo:inline vis-à-vis the dominant-baseline of the  
> enclosing line.
>
> The above would expand to:
>
> <fo:block alignment-adjust="auto"
>          alignment-baseline="auto"
>          baseline-shift="baseline"
>          dominant-baseline="auto">
>  test  <fo:inline font-family="Symbol"
>                  alignment-adjust="auto"
>                  alignment-baseline="auto"
>                  baseline-shift="baseline"
>                  dominant-baseline="auto">&#x2211;</fo:inline> test
> </fo:block>
>
> (analogously for the fo:character)
>
> Strictly following the XSL-FO Rec, the behavior for the initial  
> sample should be identical to using a fo:character, so most likely,  
> something similar should happen when the font is switched in the  
> TextLayoutManager internally. TextLayoutManager.AreaInfo does not  
> carry a reference to any AlignmentContext like  
> LeafNodeLayoutManager.AreaInfo. Instead the used AlignmentContext is  
> always the one passed by the parent.
> (see TextLayoutManager.getNextKnuthElements(), third line in the  
> method:
>  alignmentContext = context.getAlignmentContext()

This is definitely the right place, thanks for pointing this out!

>
>  -> that context is used in addElementsForAWordFragment() when  
> creating the corresponding KnuthInlineBox)
>
> If we can simply make sure that each box gets the alignment context  
> appropriate for the font used for the word-fragment, that should  
> suffice.
> This could be done either by passing the AlignmentContext via the  
> AreaInfo, as is done in the superclass, or by having the TextLM hold  
> a reference to a collection of AlignmentContexts (one for each  
> effectively used font), and use the appropriate one when creating  
> the boxes.

I tried this, and it failed. At this point, there are too many  
variables called "aligmnmentContext". The superclass (LeafNodeManager)  
has one, TextLayoutManager has one, and LNM has a function  
"makeAlignmentContext" which is supposed to be overridden to supply a  
new AlignmentContext. This is confusing and needs to be cleaned up.  
I'll try investigating here.

I've tried modifying the alignmentContext by creating a child algnment  
context, and even by creating a direct clone (copying of all  
attributes) of the parent alignment context, and it always failed the  
testsuite. So at this point I belive there are some calles to setters  
which throw it off.

> HTH!
>
> Cheers
>
> Andreas

Max

Re: svn commit: r660998 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/fo/ src/java/org/apache/fop/fonts/ src/java/org/apache/fop/layoutmgr/inline/ test/layoutengine/standard-testcases/

Posted by Andreas Delmelle <an...@telenet.be>.
On May 29, 2008, at 13:47, Max Berger wrote:

Hi Max

> Just some comments on this work:
>
> - it implements a word-by-word selection as the "auto" font-selection
> strategy. It will always pick the first font, which is able to display
> the most characters in a word. This behavior needs to be documented
> (I'll do that)
> - character-by-character is still TDB. I am currently thinking about
> creating breaks within one word if the font changes, then most of this
> implementation could be reused (and a font-change is a break in the
> word anyways)

Good work! Thanks for getting FOP this far already.

> There is still an open issue: When the font is changed, the metrics
> for the line are not. E.g. when i have something like
>
> test SIGMA test
> <fo:block>test  &#x2211; test</fo:block>
>
> the SIGMA character is set lower than it should be. At this time I was
> unable to find the cause of this behavior. Maybe someone has a hint as
> to why this happens?

To further investigate, compare the behavior with:

<fo:block>test  <fo:inline font-family="Symbol">&#x2211;</fo:inline>  
test</fo:block>
<fo:block>test  <fo:character font-family="Symbol"  
character="&#x2211;" /> test</fo:block>

The fo:inline or fo:character trigger the creation of a new  
org.apache.fop.layoutmgr.inline.AlignmentContext, which is taken into  
account by the LineLayoutManager associated to the fo:block.
That context is used to determine the alignment point for the content  
of the fo:inline vis-à-vis the dominant-baseline of the enclosing line.

The above would expand to:

<fo:block alignment-adjust="auto"
           alignment-baseline="auto"
           baseline-shift="baseline"
           dominant-baseline="auto">
   test  <fo:inline font-family="Symbol"
                   alignment-adjust="auto"
                   alignment-baseline="auto"
                   baseline-shift="baseline"
                   dominant-baseline="auto">&#x2211;</fo:inline> test
</fo:block>

(analogously for the fo:character)

Strictly following the XSL-FO Rec, the behavior for the initial  
sample should be identical to using a fo:character, so most likely,  
something similar should happen when the font is switched in the  
TextLayoutManager internally. TextLayoutManager.AreaInfo does not  
carry a reference to any AlignmentContext like  
LeafNodeLayoutManager.AreaInfo. Instead the used AlignmentContext is  
always the one passed by the parent.
(see TextLayoutManager.getNextKnuthElements(), third line in the method:
   alignmentContext = context.getAlignmentContext()
   -> that context is used in addElementsForAWordFragment() when  
creating the corresponding KnuthInlineBox)

If we can simply make sure that each box gets the alignment context  
appropriate for the font used for the word-fragment, that should  
suffice.
This could be done either by passing the AlignmentContext via the  
AreaInfo, as is done in the superclass, or by having the TextLM hold  
a reference to a collection of AlignmentContexts (one for each  
effectively used font), and use the appropriate one when creating the  
boxes.



HTH!

Cheers

Andreas

Re: svn commit: r660998 - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/fo/ src/java/org/apache/fop/fonts/ src/java/org/apache/fop/layoutmgr/inline/ test/layoutengine/standard-testcases/

Posted by Max Berger <ma...@berger.name>.
Dear Fop-devs,

Just some comments on this work:

- it implements a word-by-word selection as the "auto" font-selection
strategy. It will always pick the first font, which is able to display
the most characters in a word. This behavior needs to be documented
(I'll do that)
- character-by-character is still TDB. I am currently thinking about
creating breaks within one word if the font changes, then most of this
implementation could be reused (and a font-change is a break in the
word anyways)

There is still an open issue: When the font is changed, the metrics
for the line are not. E.g. when i have something like

test SIGMA test
<fo:block>test  &#x2211; test</fo:block>

the SIGMA character is set lower than it should be. At this time I was
unable to find the cause of this behavior. Maybe someone has a hint as
to why this happens?

Max

2008/5/28  <ma...@apache.org>:
> Author: maxberger
> Date: Wed May 28 09:10:32 2008
> New Revision: 660998
>
> URL: http://svn.apache.org/viewvc?rev=660998&view=rev
> Log:
> Implemented Font auto-selection word-by-word
>