From de9a93cb77ffc902fdf480c1b679d553c87b94e0 Mon Sep 17 00:00:00 2001 From: eschaeffer Date: Tue, 23 Jan 2001 16:01:48 +0000 Subject: [PATCH] add small-caps support. PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193977 13f79535-47bb-0310-9956-ffa450edef68 --- src/org/apache/fop/fo/FOText.java | 217 +++--- src/org/apache/fop/fo/flow/Block.java | 827 ++++++++++++----------- src/org/apache/fop/layout/BlockArea.java | 745 ++++++++++---------- src/org/apache/fop/layout/FontState.java | 128 ++-- 4 files changed, 998 insertions(+), 919 deletions(-) diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java index 19210c03e..debc06e14 100644 --- a/src/org/apache/fop/fo/FOText.java +++ b/src/org/apache/fop/fo/FOText.java @@ -1,35 +1,35 @@ /*-- $Id$ -- ============================================================================ - The Apache Software License, Version 1.1 + The Apache Software License, Version 1.1 ============================================================================ - Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. + this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must - include the following acknowledgment: "This product includes software - developed by the Apache Software Foundation (http://www.apache.org/)." - Alternately, this acknowledgment may appear in the software itself, if - and wherever such third-party acknowledgments normally appear. + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. 4. The names "FOP" and "Apache Software Foundation" must not be used to - endorse or promote products derived from this software without prior - written permission. For written permission, please contact - apache@apache.org. + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may - "Apache" appear in their name, without prior written permission of the - Apache Software Foundation. + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND @@ -65,92 +65,95 @@ import org.apache.fop.apps.FOPException; */ public class FOText extends FONode { - protected char[] ca; - protected int start; - protected int length; - - FontState fs; - float red; - float green; - float blue; - int wrapOption; - int whiteSpaceCollapse; - - // Textdecoration - protected boolean underlined = false; - protected boolean overlined = false; - protected boolean lineThrough = false; - - - public FOText(char[] chars, int s, int e, FObj parent) { - super(parent); - this.start = 0; - this.ca = new char[e - s]; - for (int i = s; i < e; i++) - this.ca[i - s] = chars[i]; - this.length = e - s; - } - - public void setUnderlined(boolean ul) { - this.underlined = ul; - } - - public boolean willCreateArea() - { - this.whiteSpaceCollapse = this.parent.properties.get( - "white-space-collapse").getEnum(); - if(this.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE && length > 0) { - return true; - } - for (int i = start; i < start + length; i++) { - char ch = ca[i]; - if (!((ch == ' ') || (ch == '\n') || (ch == '\r') || - (ch == '\t'))) { // whitespace - return true; - } - } - return false; - } - - public Status layout(Area area) throws FOPException { - if (!(area instanceof BlockArea)) { - MessageHandler.errorln("WARNING: text outside block area" + - new String(ca, start, length)); - return new Status(Status.OK); - } - if (this.marker == START) { - String fontFamily = - this.parent.properties.get("font-family").getString(); - String fontStyle = - this.parent.properties.get("font-style").getString(); - String fontWeight = - this.parent.properties.get("font-weight").getString(); - int fontSize = this.parent.properties.get( - "font-size").getLength().mvalue(); - - this.fs = new FontState(area.getFontInfo(), fontFamily, - fontStyle, fontWeight, fontSize); - - ColorType c = - this.parent.properties.get("color").getColorType(); - this.red = c.red(); - this.green = c.green(); - this.blue = c.blue(); - - this.wrapOption = - this.parent.properties.get("wrap-option").getEnum(); - this.whiteSpaceCollapse = this.parent.properties.get( - "white-space-collapse").getEnum(); - - this.marker = this.start; - } - int orig_start = this.marker; - this.marker = ((BlockArea) area).addText(fs, red, green, blue, - wrapOption, this.getLinkSet(), whiteSpaceCollapse, ca, - this.marker, length, underlined); - if (this.marker == -1) { - - + protected char[] ca; + protected int start; + protected int length; + + FontState fs; + float red; + float green; + float blue; + int wrapOption; + int whiteSpaceCollapse; + + // Textdecoration + protected boolean underlined = false; + protected boolean overlined = false; + protected boolean lineThrough = false; + + + public FOText(char[] chars, int s, int e, FObj parent) { + super(parent); + this.start = 0; + this.ca = new char[e - s]; + for (int i = s; i < e; i++) + this.ca[i - s] = chars[i]; + this.length = e - s; + } + + public void setUnderlined(boolean ul) { + this.underlined = ul; + } + + public boolean willCreateArea() + { + this.whiteSpaceCollapse = this.parent.properties.get( + "white-space-collapse").getEnum(); + if(this.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE && length > 0) { + return true; + } + for (int i = start; i < start + length; i++) { + char ch = ca[i]; + if (!((ch == ' ') || (ch == '\n') || (ch == '\r') || + (ch == '\t'))) { // whitespace + return true; + } + } + return false; + } + + public Status layout(Area area) throws FOPException { + if (!(area instanceof BlockArea)) { + MessageHandler.errorln("WARNING: text outside block area" + + new String(ca, start, length)); + return new Status(Status.OK); + } + if (this.marker == START) { + String fontFamily = + this.parent.properties.get("font-family").getString(); + String fontStyle = + this.parent.properties.get("font-style").getString(); + String fontWeight = + this.parent.properties.get("font-weight").getString(); + int fontSize = this.parent.properties.get( + "font-size").getLength().mvalue(); + // font-variant support + // added by Eric SCHAEFFER + int fontVariant = this.parent.properties.get("font-variant").getEnum(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize, fontVariant); + + ColorType c = + this.parent.properties.get("color").getColorType(); + this.red = c.red(); + this.green = c.green(); + this.blue = c.blue(); + + this.wrapOption = + this.parent.properties.get("wrap-option").getEnum(); + this.whiteSpaceCollapse = this.parent.properties.get( + "white-space-collapse").getEnum(); + + this.marker = this.start; + } + int orig_start = this.marker; + this.marker = ((BlockArea) area).addText(fs, red, green, blue, + wrapOption, this.getLinkSet(), whiteSpaceCollapse, ca, + this.marker, length, underlined); + if (this.marker == -1) { + + // commented out by Hani Elabed, 11/28/2000 // if this object has been laid out // successfully, leave it alone.... @@ -161,11 +164,11 @@ public class FOText extends FONode { // see LineArea.addText() //this.marker = 0; - return new Status(Status.OK); - } else if (this.marker != orig_start) { - return new Status(Status.AREA_FULL_SOME); - } else { - return new Status(Status.AREA_FULL_NONE); - } - } + return new Status(Status.OK); + } else if (this.marker != orig_start) { + return new Status(Status.AREA_FULL_SOME); + } else { + return new Status(Status.AREA_FULL_NONE); + } + } } diff --git a/src/org/apache/fop/fo/flow/Block.java b/src/org/apache/fop/fo/flow/Block.java index b4c10d109..f5f5f0417 100644 --- a/src/org/apache/fop/fo/flow/Block.java +++ b/src/org/apache/fop/fo/flow/Block.java @@ -1,35 +1,35 @@ /*-- $Id$ -- ============================================================================ - The Apache Software License, Version 1.1 + The Apache Software License, Version 1.1 ============================================================================ - Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. + this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must - include the following acknowledgment: "This product includes software - developed by the Apache Software Foundation (http://www.apache.org/)." - Alternately, this acknowledgment may appear in the software itself, if - and wherever such third-party acknowledgments normally appear. + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. 4. The names "FOP" and "Apache Software Foundation" must not be used to - endorse or promote products derived from this software without prior - written permission. For written permission, please contact - apache@apache.org. + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may - "Apache" appear in their name, without prior written permission of the - Apache Software Foundation. + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND @@ -61,402 +61,407 @@ import org.apache.fop.apps.FOPException; public class Block extends FObjMixed { - public static class Maker extends FObj.Maker { - public FObj make(FObj parent, - PropertyList propertyList) throws FOPException { - return new Block(parent, propertyList); - } - } - - public static FObj.Maker maker() { - return new Block.Maker(); - } - - FontState fs; - int align; - int alignLast; - int breakBefore; - int breakAfter; - int lineHeight; - int startIndent; - int endIndent; - int spaceBefore; - int spaceAfter; - int textIndent; - int keepWithNext; - ColorType backgroundColor; - int paddingTop; - int paddingBottom; - int paddingLeft; - int paddingRight; - int blockWidows; - int blockOrphans; - - String id; - - ColorType borderTopColor; - int borderTopWidth; - int borderTopStyle; - ColorType borderBottomColor; - int borderBottomWidth; - int borderBottomStyle; - ColorType borderLeftColor; - int borderLeftWidth; - int borderLeftStyle; - ColorType borderRightColor; - int borderRightWidth; - int borderRightStyle; - - int hyphenate; - char hyphenationChar; - int hyphenationPushCharacterCount; - int hyphenationRemainCharacterCount; - String language; - String country; + public static class Maker extends FObj.Maker { + public FObj make(FObj parent, + PropertyList propertyList) throws FOPException { + return new Block(parent, propertyList); + } + } + + public static FObj.Maker maker() { + return new Block.Maker(); + } + + FontState fs; + int align; + int alignLast; + int breakBefore; + int breakAfter; + int lineHeight; + int startIndent; + int endIndent; + int spaceBefore; + int spaceAfter; + int textIndent; + int keepWithNext; + ColorType backgroundColor; + int paddingTop; + int paddingBottom; + int paddingLeft; + int paddingRight; + int blockWidows; + int blockOrphans; + + String id; + + ColorType borderTopColor; + int borderTopWidth; + int borderTopStyle; + ColorType borderBottomColor; + int borderBottomWidth; + int borderBottomStyle; + ColorType borderLeftColor; + int borderLeftWidth; + int borderLeftStyle; + ColorType borderRightColor; + int borderRightWidth; + int borderRightStyle; + + int hyphenate; + char hyphenationChar; + int hyphenationPushCharacterCount; + int hyphenationRemainCharacterCount; + String language; + String country; int span; - - BlockArea blockArea; - - // this may be helpful on other FOs too - boolean anythingLaidOut = false; - - public Block(FObj parent, PropertyList propertyList) { - super(parent, propertyList); - this.name = "fo:block"; - this.span = this.properties.get("span").getEnum(); - } - - public Status layout(Area area) throws FOPException { - // MessageHandler.error(" b:LAY[" + marker + "] "); - - - if (this.marker == BREAK_AFTER) { - return new Status(Status.OK); - } - - if (this.marker == START) { - String fontFamily = - this.properties.get("font-family").getString(); - String fontStyle = - this.properties.get("font-style").getString(); - String fontWeight = - this.properties.get("font-weight").getString(); - int fontSize = - this.properties.get("font-size").getLength().mvalue(); - - this.fs = new FontState(area.getFontInfo(), fontFamily, - fontStyle, fontWeight, fontSize); - this.align = this.properties.get("text-align").getEnum(); - this.alignLast = - this.properties.get("text-align-last").getEnum(); - this.breakBefore = - this.properties.get("break-before").getEnum(); - this.breakAfter = this.properties.get("break-after").getEnum(); - this.lineHeight = this.properties.get( - "line-height").getLength().mvalue(); - this.startIndent = this.properties.get( - "start-indent").getLength().mvalue(); - this.endIndent = this.properties.get( - "end-indent").getLength().mvalue(); - this.spaceBefore = this.properties.get( - "space-before.optimum").getLength().mvalue(); - this.spaceAfter = this.properties.get( - "space-after.optimum").getLength().mvalue(); - this.textIndent = this.properties.get( - "text-indent").getLength().mvalue(); - this.keepWithNext = - this.properties.get("keep-with-next").getEnum(); - this.backgroundColor = this.properties.get( - "background-color").getColorType(); - this.paddingTop = - this.properties.get("padding").getLength().mvalue(); - - this.paddingLeft = this.paddingTop; - this.paddingRight = this.paddingTop; - this.paddingBottom = this.paddingTop; - if (this.paddingTop == 0) { - this.paddingTop = this.properties.get( - "padding-top").getLength().mvalue(); - this.paddingLeft = this.properties.get( - "padding-left").getLength().mvalue(); - this.paddingBottom = this.properties.get( - "padding-bottom").getLength().mvalue(); - this.paddingRight = this.properties.get( - "padding-right").getLength().mvalue(); - } - this.borderTopColor = - this.properties.get("border-color").getColorType(); - this.borderBottomColor = this.borderTopColor; - this.borderLeftColor = this.borderTopColor; - this.borderRightColor = this.borderTopColor; - if (this.borderTopColor == null) { - this.borderTopColor = this.properties.get( - "border-top-color").getColorType(); - this.borderBottomColor = this.properties.get( - "border-bottom-color").getColorType(); - this.borderLeftColor = this.properties.get( - "border-left-color").getColorType(); - this.borderRightColor = this.properties.get( - "border-right-color").getColorType(); - } - this.borderTopWidth = this.properties.get( - "border-width").getLength().mvalue(); - this.borderBottomWidth = this.borderTopWidth; - this.borderLeftWidth = this.borderTopWidth; - this.borderRightWidth = this.borderTopWidth; - if (this.borderTopWidth == 0) { - this.borderTopWidth = this.properties.get( - "border-top-width").getLength().mvalue(); - this.borderBottomWidth = this.properties.get( - "border-bottom-width").getLength().mvalue(); - this.borderLeftWidth = this.properties.get( - "border-left-width").getLength().mvalue(); - this.borderRightWidth = this.properties.get( - "border-right-width").getLength().mvalue(); - } - this.borderTopStyle = - this.properties.get("border-style").getEnum(); - this.borderBottomStyle = this.borderTopStyle; - this.borderLeftStyle = this.borderTopStyle; - this.borderRightStyle = this.borderTopStyle; - if (this.borderTopStyle == 0) { - this.borderTopStyle = - this.properties.get("border-top-style").getEnum(); - this.borderBottomStyle = this.properties.get( - "border-bottom-style").getEnum(); - this.borderLeftStyle = this.properties.get( - "border-left-style").getEnum(); - this.borderRightStyle = this.properties.get( - "border-right-style").getEnum(); - } - this.blockWidows = - this.properties.get("widows").getNumber().intValue(); - this.blockOrphans = - this.properties.get("orphans").getNumber().intValue(); - - this.hyphenate = this.properties.get("hyphenate").getEnum(); - this.hyphenationChar = this.properties.get("hyphenation-character").getCharacter(); - this.hyphenationPushCharacterCount = this.properties.get( - "hyphenation-push-character-count").getNumber(). - intValue(); - this.hyphenationRemainCharacterCount = this.properties.get( - "hyphenation-remain-character-count").getNumber(). - intValue(); - this.language = this.properties.get("language").getString(); - this.country = this.properties.get("country").getString(); - - this.id = this.properties.get("id").getString(); - - if (area instanceof BlockArea) { - area.end(); - } - if (this.isInLabel) { - startIndent += bodyIndent; - endIndent += (area.getAllocationWidth() - - distanceBetweenStarts - startIndent) + - labelSeparation; - } else if (this.isInListBody) { - startIndent += bodyIndent + distanceBetweenStarts; - } - - if(area.getIDReferences() != null) - area.getIDReferences().createID(id); - - this.marker = 0; - - if (breakBefore == BreakBefore.PAGE) { - return new Status(Status.FORCE_PAGE_BREAK); - } - - if (breakBefore == BreakBefore.ODD_PAGE) { - return new Status(Status.FORCE_PAGE_BREAK_ODD); - } - - if (breakBefore == BreakBefore.EVEN_PAGE) { - return new Status(Status.FORCE_PAGE_BREAK_EVEN); - } - - if (breakBefore == BreakBefore.COLUMN) { - return new Status(Status.FORCE_COLUMN_BREAK); - } - - int numChildren = this.children.size(); - for (int i = 0; i < numChildren; i++) { - FONode fo = (FONode) children.elementAt(i); - if (fo instanceof FOText) { - if (((FOText) fo).willCreateArea()) { - fo.setWidows(blockWidows); - break; - } else { - children.removeElementAt(i); - numChildren = this.children.size(); - i--; - } - } else { - fo.setWidows(blockWidows); - break; - } - } - - for (int i = numChildren - 1; i >= 0; i--) { - FONode fo = (FONode) children.elementAt(i); - if (fo instanceof FOText) { - if (((FOText) fo).willCreateArea()) { - fo.setOrphans(blockOrphans); - break; - } - } else { - fo.setOrphans(blockOrphans); - break; - } - } - } - - if ((spaceBefore != 0) && (this.marker == 0)) { - area.addDisplaySpace(spaceBefore); - } - - if (anythingLaidOut) { - this.textIndent = 0; - } - - if (marker == 0 && area.getIDReferences() != null) { - area.getIDReferences().configureID(id, area); - } - - int spaceLeft = area.spaceLeft(); - this.blockArea = new BlockArea(fs, area.getAllocationWidth(), - area.spaceLeft(), startIndent, endIndent, textIndent, - align, alignLast, lineHeight); - blockArea.setPage(area.getPage()); - blockArea.setBackgroundColor(backgroundColor); - blockArea.setPadding(paddingTop, paddingLeft, paddingBottom, - paddingRight); - blockArea.setBorderStyle(borderTopStyle, borderLeftStyle, - borderBottomStyle, borderRightStyle); - blockArea.setBorderWidth(borderTopWidth, borderLeftWidth, - borderBottomWidth, borderRightWidth); - blockArea.setBorderColor(borderTopColor, borderLeftColor, - borderBottomColor, borderRightColor); - blockArea.setHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - blockArea.start(); - - blockArea.setAbsoluteHeight(area.getAbsoluteHeight()); - blockArea.setIDReferences(area.getIDReferences()); - - blockArea.setTableCellXOffset(area.getTableCellXOffset()); - - int numChildren = this.children.size(); - for (int i = this.marker; i < numChildren; i++) { - FONode fo = (FONode) children.elementAt(i); - if (this.isInListBody) { - fo.setIsInListBody(); - fo.setDistanceBetweenStarts(this.distanceBetweenStarts); - fo.setBodyIndent(this.bodyIndent); - } - Status status; - if ((status = fo.layout(blockArea)).isIncomplete()) { - this.marker = i; - // this block was modified by - // Hani Elabed 11/27/2000 - //if ((i != 0) && (status.getCode() == Status.AREA_FULL_NONE)) - //{ - // status = new Status(Status.AREA_FULL_SOME); - //} - - // new block to replace the one above - // Hani Elabed 11/27/2000 - if (status.getCode() == Status.AREA_FULL_NONE) { - // something has already been laid out - if ((i != 0)) { - status = new Status(Status.AREA_FULL_SOME); - area.addChild(blockArea); - area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight()); - area.increaseHeight(blockArea.getHeight()); - area.setAbsoluteHeight( - blockArea.getAbsoluteHeight()); - anythingLaidOut = true; - - return status; - } else // i == 0 nothing was laid out.. - { - anythingLaidOut = false; - return status; - } - } - - //blockArea.end(); - area.addChild(blockArea); - area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight()); - area.increaseHeight(blockArea.getHeight()); - area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); - anythingLaidOut = true; - return status; - } - anythingLaidOut = true; - } - - blockArea.end(); - area.addChild(blockArea); - - /* should this be combined into above? */ - area.increaseHeight(blockArea.getHeight()); - - area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); - - if (spaceAfter != 0) { - area.addDisplaySpace(spaceAfter); - } - - if (area instanceof BlockArea) { - area.start(); - } - - if (breakAfter == BreakAfter.PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK); - } - - if (breakAfter == BreakAfter.ODD_PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK_ODD); - } - - if (breakAfter == BreakAfter.EVEN_PAGE) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_PAGE_BREAK_EVEN); - } - - if (breakAfter == BreakAfter.COLUMN) { - this.marker = BREAK_AFTER; - return new Status(Status.FORCE_COLUMN_BREAK); - } - - if (keepWithNext != 0) { - return new Status(Status.KEEP_WITH_NEXT); - } - - //MessageHandler.error(" b:OK" + marker + " "); - return new Status(Status.OK); - } - - public int getAreaHeight() { - return blockArea.getHeight(); - } - - - /** - * Return the content width of the boxes generated by this FO. - */ - public int getContentWidth() { - if (blockArea != null) - return blockArea.getContentWidth(); //getAllocationWidth()?? - else return 0; // not laid out yet - } - - public int getSpan() { - return this.span; - } + + BlockArea blockArea; + + // this may be helpful on other FOs too + boolean anythingLaidOut = false; + + public Block(FObj parent, PropertyList propertyList) { + super(parent, propertyList); + this.name = "fo:block"; + this.span = this.properties.get("span").getEnum(); + } + + public Status layout(Area area) throws FOPException { + // MessageHandler.error(" b:LAY[" + marker + "] "); + + + if (this.marker == BREAK_AFTER) { + return new Status(Status.OK); + } + + if (this.marker == START) { + String fontFamily = + this.properties.get("font-family").getString(); + String fontStyle = + this.properties.get("font-style").getString(); + String fontWeight = + this.properties.get("font-weight").getString(); + int fontSize = + this.properties.get("font-size").getLength().mvalue(); + + // font-variant support + // added by Eric SCHAEFFER + int fontVariant = + this.properties.get("font-variant").getEnum(); + + this.fs = new FontState(area.getFontInfo(), fontFamily, + fontStyle, fontWeight, fontSize, fontVariant); + this.align = this.properties.get("text-align").getEnum(); + this.alignLast = + this.properties.get("text-align-last").getEnum(); + this.breakBefore = + this.properties.get("break-before").getEnum(); + this.breakAfter = this.properties.get("break-after").getEnum(); + this.lineHeight = this.properties.get( + "line-height").getLength().mvalue(); + this.startIndent = this.properties.get( + "start-indent").getLength().mvalue(); + this.endIndent = this.properties.get( + "end-indent").getLength().mvalue(); + this.spaceBefore = this.properties.get( + "space-before.optimum").getLength().mvalue(); + this.spaceAfter = this.properties.get( + "space-after.optimum").getLength().mvalue(); + this.textIndent = this.properties.get( + "text-indent").getLength().mvalue(); + this.keepWithNext = + this.properties.get("keep-with-next").getEnum(); + this.backgroundColor = this.properties.get( + "background-color").getColorType(); + this.paddingTop = + this.properties.get("padding").getLength().mvalue(); + + this.paddingLeft = this.paddingTop; + this.paddingRight = this.paddingTop; + this.paddingBottom = this.paddingTop; + if (this.paddingTop == 0) { + this.paddingTop = this.properties.get( + "padding-top").getLength().mvalue(); + this.paddingLeft = this.properties.get( + "padding-left").getLength().mvalue(); + this.paddingBottom = this.properties.get( + "padding-bottom").getLength().mvalue(); + this.paddingRight = this.properties.get( + "padding-right").getLength().mvalue(); + } + this.borderTopColor = + this.properties.get("border-color").getColorType(); + this.borderBottomColor = this.borderTopColor; + this.borderLeftColor = this.borderTopColor; + this.borderRightColor = this.borderTopColor; + if (this.borderTopColor == null) { + this.borderTopColor = this.properties.get( + "border-top-color").getColorType(); + this.borderBottomColor = this.properties.get( + "border-bottom-color").getColorType(); + this.borderLeftColor = this.properties.get( + "border-left-color").getColorType(); + this.borderRightColor = this.properties.get( + "border-right-color").getColorType(); + } + this.borderTopWidth = this.properties.get( + "border-width").getLength().mvalue(); + this.borderBottomWidth = this.borderTopWidth; + this.borderLeftWidth = this.borderTopWidth; + this.borderRightWidth = this.borderTopWidth; + if (this.borderTopWidth == 0) { + this.borderTopWidth = this.properties.get( + "border-top-width").getLength().mvalue(); + this.borderBottomWidth = this.properties.get( + "border-bottom-width").getLength().mvalue(); + this.borderLeftWidth = this.properties.get( + "border-left-width").getLength().mvalue(); + this.borderRightWidth = this.properties.get( + "border-right-width").getLength().mvalue(); + } + this.borderTopStyle = + this.properties.get("border-style").getEnum(); + this.borderBottomStyle = this.borderTopStyle; + this.borderLeftStyle = this.borderTopStyle; + this.borderRightStyle = this.borderTopStyle; + if (this.borderTopStyle == 0) { + this.borderTopStyle = + this.properties.get("border-top-style").getEnum(); + this.borderBottomStyle = this.properties.get( + "border-bottom-style").getEnum(); + this.borderLeftStyle = this.properties.get( + "border-left-style").getEnum(); + this.borderRightStyle = this.properties.get( + "border-right-style").getEnum(); + } + this.blockWidows = + this.properties.get("widows").getNumber().intValue(); + this.blockOrphans = + this.properties.get("orphans").getNumber().intValue(); + + this.hyphenate = this.properties.get("hyphenate").getEnum(); + this.hyphenationChar = this.properties.get("hyphenation-character").getCharacter(); + this.hyphenationPushCharacterCount = this.properties.get( + "hyphenation-push-character-count").getNumber(). + intValue(); + this.hyphenationRemainCharacterCount = this.properties.get( + "hyphenation-remain-character-count").getNumber(). + intValue(); + this.language = this.properties.get("language").getString(); + this.country = this.properties.get("country").getString(); + + this.id = this.properties.get("id").getString(); + + if (area instanceof BlockArea) { + area.end(); + } + if (this.isInLabel) { + startIndent += bodyIndent; + endIndent += (area.getAllocationWidth() - + distanceBetweenStarts - startIndent) + + labelSeparation; + } else if (this.isInListBody) { + startIndent += bodyIndent + distanceBetweenStarts; + } + + if(area.getIDReferences() != null) + area.getIDReferences().createID(id); + + this.marker = 0; + + if (breakBefore == BreakBefore.PAGE) { + return new Status(Status.FORCE_PAGE_BREAK); + } + + if (breakBefore == BreakBefore.ODD_PAGE) { + return new Status(Status.FORCE_PAGE_BREAK_ODD); + } + + if (breakBefore == BreakBefore.EVEN_PAGE) { + return new Status(Status.FORCE_PAGE_BREAK_EVEN); + } + + if (breakBefore == BreakBefore.COLUMN) { + return new Status(Status.FORCE_COLUMN_BREAK); + } + + int numChildren = this.children.size(); + for (int i = 0; i < numChildren; i++) { + FONode fo = (FONode) children.elementAt(i); + if (fo instanceof FOText) { + if (((FOText) fo).willCreateArea()) { + fo.setWidows(blockWidows); + break; + } else { + children.removeElementAt(i); + numChildren = this.children.size(); + i--; + } + } else { + fo.setWidows(blockWidows); + break; + } + } + + for (int i = numChildren - 1; i >= 0; i--) { + FONode fo = (FONode) children.elementAt(i); + if (fo instanceof FOText) { + if (((FOText) fo).willCreateArea()) { + fo.setOrphans(blockOrphans); + break; + } + } else { + fo.setOrphans(blockOrphans); + break; + } + } + } + + if ((spaceBefore != 0) && (this.marker == 0)) { + area.addDisplaySpace(spaceBefore); + } + + if (anythingLaidOut) { + this.textIndent = 0; + } + + if (marker == 0 && area.getIDReferences() != null) { + area.getIDReferences().configureID(id, area); + } + + int spaceLeft = area.spaceLeft(); + this.blockArea = new BlockArea(fs, area.getAllocationWidth(), + area.spaceLeft(), startIndent, endIndent, textIndent, + align, alignLast, lineHeight); + blockArea.setPage(area.getPage()); + blockArea.setBackgroundColor(backgroundColor); + blockArea.setPadding(paddingTop, paddingLeft, paddingBottom, + paddingRight); + blockArea.setBorderStyle(borderTopStyle, borderLeftStyle, + borderBottomStyle, borderRightStyle); + blockArea.setBorderWidth(borderTopWidth, borderLeftWidth, + borderBottomWidth, borderRightWidth); + blockArea.setBorderColor(borderTopColor, borderLeftColor, + borderBottomColor, borderRightColor); + blockArea.setHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + blockArea.start(); + + blockArea.setAbsoluteHeight(area.getAbsoluteHeight()); + blockArea.setIDReferences(area.getIDReferences()); + + blockArea.setTableCellXOffset(area.getTableCellXOffset()); + + int numChildren = this.children.size(); + for (int i = this.marker; i < numChildren; i++) { + FONode fo = (FONode) children.elementAt(i); + if (this.isInListBody) { + fo.setIsInListBody(); + fo.setDistanceBetweenStarts(this.distanceBetweenStarts); + fo.setBodyIndent(this.bodyIndent); + } + Status status; + if ((status = fo.layout(blockArea)).isIncomplete()) { + this.marker = i; + // this block was modified by + // Hani Elabed 11/27/2000 + //if ((i != 0) && (status.getCode() == Status.AREA_FULL_NONE)) + //{ + // status = new Status(Status.AREA_FULL_SOME); + //} + + // new block to replace the one above + // Hani Elabed 11/27/2000 + if (status.getCode() == Status.AREA_FULL_NONE) { + // something has already been laid out + if ((i != 0)) { + status = new Status(Status.AREA_FULL_SOME); + area.addChild(blockArea); + area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight()); + area.increaseHeight(blockArea.getHeight()); + area.setAbsoluteHeight( + blockArea.getAbsoluteHeight()); + anythingLaidOut = true; + + return status; + } else // i == 0 nothing was laid out.. + { + anythingLaidOut = false; + return status; + } + } + + //blockArea.end(); + area.addChild(blockArea); + area.setMaxHeight(area.getMaxHeight() - spaceLeft + blockArea.getMaxHeight()); + area.increaseHeight(blockArea.getHeight()); + area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); + anythingLaidOut = true; + return status; + } + anythingLaidOut = true; + } + + blockArea.end(); + area.addChild(blockArea); + + /* should this be combined into above? */ + area.increaseHeight(blockArea.getHeight()); + + area.setAbsoluteHeight(blockArea.getAbsoluteHeight()); + + if (spaceAfter != 0) { + area.addDisplaySpace(spaceAfter); + } + + if (area instanceof BlockArea) { + area.start(); + } + + if (breakAfter == BreakAfter.PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK); + } + + if (breakAfter == BreakAfter.ODD_PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK_ODD); + } + + if (breakAfter == BreakAfter.EVEN_PAGE) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_PAGE_BREAK_EVEN); + } + + if (breakAfter == BreakAfter.COLUMN) { + this.marker = BREAK_AFTER; + return new Status(Status.FORCE_COLUMN_BREAK); + } + + if (keepWithNext != 0) { + return new Status(Status.KEEP_WITH_NEXT); + } + + //MessageHandler.error(" b:OK" + marker + " "); + return new Status(Status.OK); + } + + public int getAreaHeight() { + return blockArea.getHeight(); + } + + + /** + * Return the content width of the boxes generated by this FO. + */ + public int getContentWidth() { + if (blockArea != null) + return blockArea.getContentWidth(); //getAllocationWidth()?? + else return 0; // not laid out yet + } + + public int getSpan() { + return this.span; + } } diff --git a/src/org/apache/fop/layout/BlockArea.java b/src/org/apache/fop/layout/BlockArea.java index 20e877f9b..e114cee52 100644 --- a/src/org/apache/fop/layout/BlockArea.java +++ b/src/org/apache/fop/layout/BlockArea.java @@ -1,35 +1,35 @@ /*-- $Id$ -- ============================================================================ - The Apache Software License, Version 1.1 + The Apache Software License, Version 1.1 ============================================================================ - Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. + this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must - include the following acknowledgment: "This product includes software - developed by the Apache Software Foundation (http://www.apache.org/)." - Alternately, this acknowledgment may appear in the software itself, if - and wherever such third-party acknowledgments normally appear. + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. 4. The names "Fop" and "Apache Software Foundation" must not be used to - endorse or promote products derived from this software without prior - written permission. For written permission, please contact - apache@apache.org. + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. 5. Products derived from this software may not be called "Apache", nor may - "Apache" appear in their name, without prior written permission of the - Apache Software Foundation. + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND @@ -55,6 +55,7 @@ import org.apache.fop.render.Renderer; import org.apache.fop.fo.flow.*; import org.apache.fop.fo.*; import org.apache.fop.apps.*; +import org.apache.fop.fo.properties.*; // Java import java.util.Vector; @@ -63,332 +64,392 @@ import org.apache.fop.messaging.MessageHandler; public class BlockArea extends Area { - /* relative to area container */ - protected int startIndent; - protected int endIndent; - - /* first line startIndent modifier */ - protected int textIndent; - - protected int lineHeight; - - protected int halfLeading; - - - /* text-align of all but the last line */ - protected int align; - - /* text-align of the last line */ - protected int alignLastLine; - - protected LineArea currentLineArea; - protected LinkSet currentLinkSet; - - /* have any line areas been used? */ - protected boolean hasLines = false; - - /*hyphenation*/ - protected int hyphenate; - protected char hyphenationChar; - protected int hyphenationPushCharacterCount; - protected int hyphenationRemainCharacterCount; - protected String language; - protected String country; - - protected Vector pendingFootnotes = null; - - public BlockArea(FontState fontState, int allocationWidth, - int maxHeight, int startIndent, int endIndent, - int textIndent, int align, int alignLastLine, int lineHeight) { - super(fontState, allocationWidth, maxHeight); - - this.startIndent = startIndent; - this.endIndent = endIndent; - this.textIndent = textIndent; - this.contentRectangleWidth = - allocationWidth - startIndent - endIndent; - this.align = align; - this.alignLastLine = alignLastLine; - this.lineHeight = lineHeight; - - if (fontState != null) - this.halfLeading = (lineHeight - fontState.getFontSize()) / 2; - } - - public void render(Renderer renderer) { - renderer.renderBlockArea(this); - } - - public void addLineArea(LineArea la) { - if (!la.isEmpty()) { - this.addDisplaySpace(this.halfLeading); - int size = la.getHeight(); - this.addChild(la); - this.increaseHeight(size); - this.addDisplaySpace(this.halfLeading); - } - // add pending footnotes - if(pendingFootnotes != null) { - for(Enumeration e = pendingFootnotes.elements(); e.hasMoreElements(); ) { - FootnoteBody fb = (FootnoteBody)e.nextElement(); - Page page = getPage(); - if(!Footnote.layoutFootnote(page, fb, this)) { - page.addPendingFootnote(fb); - } - } - pendingFootnotes = null; - } - } - - public int addPageNumberCitation(FontState fontState, float red, - float green, float blue, int wrapOption, LinkSet ls, - int whiteSpaceCollapse, String refid) { - - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); - this.currentLineArea.changeHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - - - if (ls != null) { - this.currentLinkSet = ls; - ls.setYOffset(currentHeight); - } - - this.currentLineArea.addPageNumberCitation(refid, ls); - this.hasLines = true; - - return -1; - - } - - public int addText(FontState fontState, float red, float green, - float blue, int wrapOption, LinkSet ls, - int whiteSpaceCollapse, char data[], int start, int end, - boolean ul) { - int ts, te; - char[] ca; - - ts = start; - te = end; - ca = data; - - if (currentHeight + currentLineArea.getHeight() > maxHeight) { - return start; - } - - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); - this.currentLineArea.changeHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - if (ls != null) { - this.currentLinkSet = ls; - ls.setYOffset(currentHeight); - } - - ts = this.currentLineArea.addText(ca, ts, te, ls, ul); - this.hasLines = true; - - while (ts != -1) { - this.currentLineArea.align(this.align); - this.addLineArea(this.currentLineArea); - - this.currentLineArea = - new LineArea(fontState, lineHeight, halfLeading, - allocationWidth, startIndent, endIndent, - currentLineArea); - if (currentHeight + currentLineArea.getHeight() > - this.maxHeight) { - return ts; - } - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse( - whiteSpaceCollapse); - this.currentLineArea.changeHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - if (ls != null) { - ls.setYOffset(currentHeight); - } - - ts = this.currentLineArea.addText(ca, ts, te, ls, ul); - } - return -1; - } - - - /** - * adds a leader to current line area of containing block area - * the actual leader area is created in the line area - * - * @return int +1 for success and -1 for none - */ - public int addLeader(FontState fontState, float red, float green, - float blue, int leaderPattern, int leaderLengthMinimum, - int leaderLengthOptimum, int leaderLengthMaximum, - int ruleThickness, int ruleStyle, int leaderPatternWidth, - int leaderAlignment) { - - //this should start a new page - if (currentHeight + currentLineArea.getHeight() > maxHeight) { - return -1; - } - - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - - //check whether leader fits into the (rest of the) line - //using length.optimum to determine where to break the line as defined - // in the xsl:fo spec: "User agents may choose to use the value of 'leader-length.optimum' - // to determine where to break the line" (7.20.4) - //if leader is longer then create a new LineArea and put leader there - if (leaderLengthOptimum <= (this.getContentWidth() - - this.currentLineArea.finalWidth - - this.currentLineArea.pendingWidth)) { - this.currentLineArea.addLeader(leaderPattern, - leaderLengthMinimum, leaderLengthOptimum, - leaderLengthMaximum, ruleStyle, ruleThickness, - leaderPatternWidth, leaderAlignment); - } else { - //finish current line area and put it into children vector - this.currentLineArea.align(this.align); - this.addLineArea(this.currentLineArea); - - //create new line area - this.currentLineArea = - new LineArea(fontState, lineHeight, halfLeading, - allocationWidth, startIndent, endIndent, - currentLineArea); - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - - if (currentHeight + currentLineArea.getHeight() > - this.maxHeight) { - return -1; - } - - //check whether leader fits into LineArea at all, otherwise - //clip it (should honor the clip option of containing area) - if (leaderLengthMinimum <= - this.currentLineArea.getContentWidth()) { - this.currentLineArea.addLeader(leaderPattern, - leaderLengthMinimum, leaderLengthOptimum, - leaderLengthMaximum, ruleStyle, ruleThickness, - leaderPatternWidth, leaderAlignment); - } else { - MessageHandler.errorln("Leader doesn't fit into line, it will be clipped to fit."); - this.currentLineArea.addLeader(leaderPattern, - this.currentLineArea.getContentWidth() - - this.currentLineArea.finalWidth - - this.currentLineArea.pendingWidth, - leaderLengthOptimum, leaderLengthMaximum, - ruleStyle, ruleThickness, leaderPatternWidth, - leaderAlignment); - } - } - this.hasLines = true; - return 1; - } - - public void addCharacter(FontState fontState, float red, float green, - float blue, int wrapOption, LinkSet ls, - int whiteSpaceCollapse, char data, boolean ul) { - - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); - - if (ls != null) { - this.currentLinkSet = ls; - ls.setYOffset(currentHeight); - } - - int marker = this.currentLineArea.addCharacter(data, ls, ul); - //if character didn't fit into line, open a new one - if (marker == org.apache.fop.fo.flow.Character.DOESNOT_FIT) { - this.currentLineArea.align(this.align); - this.addLineArea(this.currentLineArea); - - this.currentLineArea = - new LineArea(fontState, lineHeight, halfLeading, - allocationWidth, startIndent, endIndent, - currentLineArea); - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse( - whiteSpaceCollapse); - if (ls != null) { - this.currentLinkSet = ls; - ls.setYOffset(currentHeight); - } - - this.currentLineArea.addCharacter(data, ls, ul); - } - this.hasLines = true; - } - - - public void end() { - if (this.hasLines) { - this.currentLineArea.addPending(); - this.currentLineArea.align(this.alignLastLine); - this.addLineArea(this.currentLineArea); - } - } - - public void start() { - currentLineArea = new LineArea(fontState, lineHeight, halfLeading, - allocationWidth, startIndent + textIndent, endIndent, null); - } - - public int getEndIndent() { - return endIndent; - } - - public int getStartIndent() { - return startIndent + paddingLeft + borderWidthLeft; - } - - public void setIndents(int startIndent, int endIndent) { - this.startIndent = startIndent; - this.endIndent = endIndent; - this.contentRectangleWidth = - allocationWidth - startIndent - endIndent; - } - - public int spaceLeft() { - return maxHeight - currentHeight; - } - - public int getHalfLeading() { - return halfLeading; - } - - public void setHyphenation(String language, String country, int hyphenate, char hyphenationChar, - int hyphenationPushCharacterCount, - int hyphenationRemainCharacterCount) { - this.language = language; - this.country = country; - this.hyphenate = hyphenate; - this.hyphenationChar = hyphenationChar; - this.hyphenationPushCharacterCount = hyphenationPushCharacterCount; - this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount; - } - - public void addFootnote(FootnoteBody fb) { - if(pendingFootnotes == null) { - pendingFootnotes = new Vector(); - } - pendingFootnotes.addElement(fb); - } + /* relative to area container */ + protected int startIndent; + protected int endIndent; + + /* first line startIndent modifier */ + protected int textIndent; + + protected int lineHeight; + + protected int halfLeading; + + + /* text-align of all but the last line */ + protected int align; + + /* text-align of the last line */ + protected int alignLastLine; + + protected LineArea currentLineArea; + protected LinkSet currentLinkSet; + + /* have any line areas been used? */ + protected boolean hasLines = false; + + /*hyphenation*/ + protected int hyphenate; + protected char hyphenationChar; + protected int hyphenationPushCharacterCount; + protected int hyphenationRemainCharacterCount; + protected String language; + protected String country; + + protected Vector pendingFootnotes = null; + + public BlockArea(FontState fontState, int allocationWidth, + int maxHeight, int startIndent, int endIndent, + int textIndent, int align, int alignLastLine, int lineHeight) { + super(fontState, allocationWidth, maxHeight); + + this.startIndent = startIndent; + this.endIndent = endIndent; + this.textIndent = textIndent; + this.contentRectangleWidth = + allocationWidth - startIndent - endIndent; + this.align = align; + this.alignLastLine = alignLastLine; + this.lineHeight = lineHeight; + + if (fontState != null) + this.halfLeading = (lineHeight - fontState.getFontSize()) / 2; + } + + public void render(Renderer renderer) { + renderer.renderBlockArea(this); + } + + public void addLineArea(LineArea la) { + if (!la.isEmpty()) { + this.addDisplaySpace(this.halfLeading); + int size = la.getHeight(); + this.addChild(la); + this.increaseHeight(size); + this.addDisplaySpace(this.halfLeading); + } + // add pending footnotes + if(pendingFootnotes != null) { + for(Enumeration e = pendingFootnotes.elements(); e.hasMoreElements(); ) { + FootnoteBody fb = (FootnoteBody)e.nextElement(); + Page page = getPage(); + if(!Footnote.layoutFootnote(page, fb, this)) { + page.addPendingFootnote(fb); + } + } + pendingFootnotes = null; + } + } + + public int addPageNumberCitation(FontState fontState, float red, + float green, float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, String refid) { + + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); + this.currentLineArea.changeHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + + + if (ls != null) { + this.currentLinkSet = ls; + ls.setYOffset(currentHeight); + } + + this.currentLineArea.addPageNumberCitation(refid, ls); + this.hasLines = true; + + return -1; + + } + + // font-variant support : addText is a wrapper for addRealText + // added by Eric SCHAEFFER + public int addText(FontState fontState, float red, float green, + float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, char data[], int start, int end, + boolean ul) { + if (fontState.getFontVariant() == FontVariant.SMALL_CAPS) { + FontState smallCapsFontState; + try { + int smallCapsFontHeight = (int) (((double) fontState.getFontSize()) * 0.8d); + smallCapsFontState = new FontState( + fontState.getFontInfo(), + fontState.getFontFamily(), + fontState.getFontStyle(), + fontState.getFontWeight(), + smallCapsFontHeight, + FontVariant.NORMAL); + } catch (FOPException ex) { + smallCapsFontState = fontState; + MessageHandler.errorln("Error creating small-caps FontState: " + ex.getMessage()); + } + + // parse text for upper/lower case and call addRealText + char c; + boolean isLowerCase; + int caseStart; + FontState fontStateToUse; + for (int i = start; i < end; ) { + caseStart = i; + c = data[i]; + isLowerCase = (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c)); + while (isLowerCase == (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c))) { + if (isLowerCase) { + data[i] = java.lang.Character.toUpperCase(c); + } + i++; + if (i == end) + break; + c = data[i]; + } + if (isLowerCase) { + fontStateToUse = smallCapsFontState; + } else { + fontStateToUse = fontState; + } + int index = this.addRealText(fontStateToUse, red, green, blue, wrapOption, ls, + whiteSpaceCollapse, data, caseStart, i, ul); + if (index != -1) { + return index; + } + } + + return -1; + } + + // font-variant normal + return this.addRealText(fontState, red, green, blue, wrapOption, ls, + whiteSpaceCollapse, data, start, end, ul); + } + + protected int addRealText(FontState fontState, float red, float green, + float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, char data[], int start, int end, + boolean ul) { + int ts, te; + char[] ca; + + ts = start; + te = end; + ca = data; + + if (currentHeight + currentLineArea.getHeight() > maxHeight) { + return start; + } + + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); + this.currentLineArea.changeHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + if (ls != null) { + this.currentLinkSet = ls; + ls.setYOffset(currentHeight); + } + + ts = this.currentLineArea.addText(ca, ts, te, ls, ul); + this.hasLines = true; + + while (ts != -1) { + this.currentLineArea.align(this.align); + this.addLineArea(this.currentLineArea); + + this.currentLineArea = + new LineArea(fontState, lineHeight, halfLeading, + allocationWidth, startIndent, endIndent, + currentLineArea); + if (currentHeight + currentLineArea.getHeight() > + this.maxHeight) { + return ts; + } + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse( + whiteSpaceCollapse); + this.currentLineArea.changeHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + if (ls != null) { + ls.setYOffset(currentHeight); + } + + ts = this.currentLineArea.addText(ca, ts, te, ls, ul); + } + return -1; + } + + + /** + * adds a leader to current line area of containing block area + * the actual leader area is created in the line area + * + * @return int +1 for success and -1 for none + */ + public int addLeader(FontState fontState, float red, float green, + float blue, int leaderPattern, int leaderLengthMinimum, + int leaderLengthOptimum, int leaderLengthMaximum, + int ruleThickness, int ruleStyle, int leaderPatternWidth, + int leaderAlignment) { + + //this should start a new page + if (currentHeight + currentLineArea.getHeight() > maxHeight) { + return -1; + } + + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + + //check whether leader fits into the (rest of the) line + //using length.optimum to determine where to break the line as defined + // in the xsl:fo spec: "User agents may choose to use the value of 'leader-length.optimum' + // to determine where to break the line" (7.20.4) + //if leader is longer then create a new LineArea and put leader there + if (leaderLengthOptimum <= (this.getContentWidth() - + this.currentLineArea.finalWidth - + this.currentLineArea.pendingWidth)) { + this.currentLineArea.addLeader(leaderPattern, + leaderLengthMinimum, leaderLengthOptimum, + leaderLengthMaximum, ruleStyle, ruleThickness, + leaderPatternWidth, leaderAlignment); + } else { + //finish current line area and put it into children vector + this.currentLineArea.align(this.align); + this.addLineArea(this.currentLineArea); + + //create new line area + this.currentLineArea = + new LineArea(fontState, lineHeight, halfLeading, + allocationWidth, startIndent, endIndent, + currentLineArea); + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + + if (currentHeight + currentLineArea.getHeight() > + this.maxHeight) { + return -1; + } + + //check whether leader fits into LineArea at all, otherwise + //clip it (should honor the clip option of containing area) + if (leaderLengthMinimum <= + this.currentLineArea.getContentWidth()) { + this.currentLineArea.addLeader(leaderPattern, + leaderLengthMinimum, leaderLengthOptimum, + leaderLengthMaximum, ruleStyle, ruleThickness, + leaderPatternWidth, leaderAlignment); + } else { + MessageHandler.errorln("Leader doesn't fit into line, it will be clipped to fit."); + this.currentLineArea.addLeader(leaderPattern, + this.currentLineArea.getContentWidth() - + this.currentLineArea.finalWidth - + this.currentLineArea.pendingWidth, + leaderLengthOptimum, leaderLengthMaximum, + ruleStyle, ruleThickness, leaderPatternWidth, + leaderAlignment); + } + } + this.hasLines = true; + return 1; + } + + public void addCharacter(FontState fontState, float red, float green, + float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, char data, boolean ul) { + + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); + + if (ls != null) { + this.currentLinkSet = ls; + ls.setYOffset(currentHeight); + } + + int marker = this.currentLineArea.addCharacter(data, ls, ul); + //if character didn't fit into line, open a new one + if (marker == org.apache.fop.fo.flow.Character.DOESNOT_FIT) { + this.currentLineArea.align(this.align); + this.addLineArea(this.currentLineArea); + + this.currentLineArea = + new LineArea(fontState, lineHeight, halfLeading, + allocationWidth, startIndent, endIndent, + currentLineArea); + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse( + whiteSpaceCollapse); + if (ls != null) { + this.currentLinkSet = ls; + ls.setYOffset(currentHeight); + } + + this.currentLineArea.addCharacter(data, ls, ul); + } + this.hasLines = true; + } + + + public void end() { + if (this.hasLines) { + this.currentLineArea.addPending(); + this.currentLineArea.align(this.alignLastLine); + this.addLineArea(this.currentLineArea); + } + } + + public void start() { + currentLineArea = new LineArea(fontState, lineHeight, halfLeading, + allocationWidth, startIndent + textIndent, endIndent, null); + } + + public int getEndIndent() { + return endIndent; + } + + public int getStartIndent() { + return startIndent + paddingLeft + borderWidthLeft; + } + + public void setIndents(int startIndent, int endIndent) { + this.startIndent = startIndent; + this.endIndent = endIndent; + this.contentRectangleWidth = + allocationWidth - startIndent - endIndent; + } + + public int spaceLeft() { + return maxHeight - currentHeight; + } + + public int getHalfLeading() { + return halfLeading; + } + + public void setHyphenation(String language, String country, int hyphenate, char hyphenationChar, + int hyphenationPushCharacterCount, + int hyphenationRemainCharacterCount) { + this.language = language; + this.country = country; + this.hyphenate = hyphenate; + this.hyphenationChar = hyphenationChar; + this.hyphenationPushCharacterCount = hyphenationPushCharacterCount; + this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount; + } + + public void addFootnote(FootnoteBody fb) { + if(pendingFootnotes == null) { + pendingFootnotes = new Vector(); + } + pendingFootnotes.addElement(fb); + } } diff --git a/src/org/apache/fop/layout/FontState.java b/src/org/apache/fop/layout/FontState.java index 55508dc70..3794db88a 100644 --- a/src/org/apache/fop/layout/FontState.java +++ b/src/org/apache/fop/layout/FontState.java @@ -1,36 +1,36 @@ -/*-- $Id$ -- +/*-- $Id$ -- ============================================================================ - The Apache Software License, Version 1.1 + The Apache Software License, Version 1.1 ============================================================================ - - Copyright (C) 1999 The Apache Software Foundation. All rights reserved. - + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. The end-user documentation included with the redistribution, if any, must - include the following acknowledgment: "This product includes software - developed by the Apache Software Foundation (http://www.apache.org/)." - Alternately, this acknowledgment may appear in the software itself, if - and wherever such third-party acknowledgments normally appear. - + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + 4. The names "Fop" and "Apache Software Foundation" must not be used to - endorse or promote products derived from this software without prior - written permission. For written permission, please contact - apache@apache.org. - + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + 5. Products derived from this software may not be called "Apache", nor may - "Apache" appear in their name, without prior written permission of the - Apache Software Foundation. - + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE @@ -41,28 +41,33 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by - James Tauber . For more information on the Apache + James Tauber . For more information on the Apache Software Foundation, please see . - + */ package org.apache.fop.layout; import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.properties.FontVariant; public class FontState { - - protected FontInfo fontInfo; - private String fontName; - private int fontSize; - private String fontFamily; - private String fontStyle; - private String fontWeight; - private FontMetric metric; - - public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize) throws FOPException { + + protected FontInfo fontInfo; + private String fontName; + private int fontSize; + private String fontFamily; + private String fontStyle; + private String fontWeight; + private FontMetric metric; + private int fontVariant; + + public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize) throws FOPException { + this(fontInfo, fontFamily, fontStyle, fontWeight, fontSize, FontVariant.NORMAL); + } + public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize, int fontVariant) throws FOPException { this.fontInfo = fontInfo; this.fontFamily = fontFamily; this.fontStyle = fontStyle; @@ -70,50 +75,55 @@ public class FontState { this.fontSize = fontSize; this.fontName = fontInfo.fontLookup(fontFamily,fontStyle,fontWeight); this.metric = fontInfo.getMetricsFor(fontName); - } + this.fontVariant = fontVariant; + } - public int getAscender() { + public int getAscender() { return metric.getAscender(fontSize) / 1000; - } + } - public int getCapHeight() { + public int getCapHeight() { return metric.getCapHeight(fontSize) / 1000; - } + } - public int getDescender() { + public int getDescender() { return metric.getDescender(fontSize) / 1000; - } + } - public String getFontName() { + public String getFontName() { return this.fontName; - } + } - public int getFontSize() { + public int getFontSize() { return this.fontSize; - } + } - public String getFontWeight() { + public String getFontWeight() { return this.fontWeight; - } + } - public String getFontFamily() { + public String getFontFamily() { return this.fontFamily; - } + } - public String getFontStyle() { + public String getFontStyle() { return this.fontStyle; - } + } + + public int getFontVariant() { + return this.fontVariant; + } - public FontInfo getFontInfo() { + public FontInfo getFontInfo() { return this.fontInfo; - } + } - public int getXHeight() { + public int getXHeight() { return metric.getXHeight(fontSize) / 1000; - } + } - public int width(int charnum) { + public int width(int charnum) { // returns width of given character number in millipoints return (metric.width(charnum, fontSize) / 1000); - } + } } -- 2.39.5