123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- /*
- * 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$ */
-
- package org.apache.fop.layoutmgr;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
- import org.apache.fop.accessibility.StructureTreeElement;
- import org.apache.fop.area.Area;
- import org.apache.fop.area.Trait;
- import org.apache.fop.datatypes.LengthBase;
- import org.apache.fop.datatypes.PercentBaseContext;
- import org.apache.fop.datatypes.SimplePercentBaseContext;
- import org.apache.fop.fo.Constants;
- import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
- import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
- import org.apache.fop.fo.properties.CommonMarginBlock;
- import org.apache.fop.fo.properties.CommonTextDecoration;
- import org.apache.fop.fonts.Font;
- import org.apache.fop.traits.BorderProps;
- import org.apache.fop.traits.MinOptMax;
-
- /**
- * This is a helper class used for setting common traits on areas.
- */
- public final class TraitSetter {
-
- private TraitSetter() {
- }
-
- /** logger */
- private static final Log LOG = LogFactory.getLog(TraitSetter.class);
-
- /**
- * Sets border and padding traits on areas.
- *
- * @param area area to set the traits on
- * @param bpProps border and padding properties
- * @param isNotFirst True if the area is not the first area
- * @param isNotLast True if the area is not the last area
- * @param context Property evaluation context
- */
- public static void setBorderPaddingTraits(Area area,
- CommonBorderPaddingBackground bpProps, boolean isNotFirst, boolean isNotLast,
- PercentBaseContext context) {
- int padding;
- padding = bpProps.getPadding(CommonBorderPaddingBackground.START, isNotFirst, context);
- if (padding > 0) {
- area.addTrait(Trait.PADDING_START, padding);
- }
- padding = bpProps.getPadding(CommonBorderPaddingBackground.END, isNotLast, context);
- if (padding > 0) {
- area.addTrait(Trait.PADDING_END, padding);
- }
- padding = bpProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, context);
- if (padding > 0) {
- area.addTrait(Trait.PADDING_BEFORE, padding);
- }
- padding = bpProps.getPadding(CommonBorderPaddingBackground.AFTER, false, context);
- if (padding > 0) {
- area.addTrait(Trait.PADDING_AFTER, padding);
- }
-
- addBorderTrait(area, bpProps, isNotFirst,
- CommonBorderPaddingBackground.START,
- BorderProps.SEPARATE, Trait.BORDER_START);
-
- addBorderTrait(area, bpProps, isNotLast,
- CommonBorderPaddingBackground.END,
- BorderProps.SEPARATE, Trait.BORDER_END);
-
- addBorderTrait(area, bpProps, false,
- CommonBorderPaddingBackground.BEFORE,
- BorderProps.SEPARATE, Trait.BORDER_BEFORE);
-
- addBorderTrait(area, bpProps, false,
- CommonBorderPaddingBackground.AFTER,
- BorderProps.SEPARATE, Trait.BORDER_AFTER);
- }
-
- /*
- * Sets border traits on an area.
- *
- * @param area area to set the traits on
- * @param bpProps border and padding properties
- * @param mode the border paint mode (see BorderProps)
- */
- private static void addBorderTrait(Area area,
- CommonBorderPaddingBackground bpProps,
- boolean discard, int side, int mode,
- Integer trait) {
- int borderWidth = bpProps.getBorderWidth(side, discard);
- if (borderWidth > 0) {
- area.addTrait(trait,
- new BorderProps(bpProps.getBorderStyle(side),
- borderWidth, bpProps.getBorderColor(side),
- mode));
- }
- }
-
- /**
- * Add borders to an area. Note: this method also adds unconditional padding. Don't use!
- * Layout managers that create areas with borders can use this to
- * add the borders to the area.
- * @param area the area to set the traits on.
- * @param borderProps border properties
- * @param context Property evaluation context
- * @deprecated Call the other addBorders() method and addPadding separately.
- */
- public static void addBorders(Area area, CommonBorderPaddingBackground borderProps,
- PercentBaseContext context) {
- BorderProps bps = getBorderProps(borderProps, CommonBorderPaddingBackground.BEFORE);
- if (bps != null) {
- area.addTrait(Trait.BORDER_BEFORE, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.AFTER);
- if (bps != null) {
- area.addTrait(Trait.BORDER_AFTER, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.START);
- if (bps != null) {
- area.addTrait(Trait.BORDER_START, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.END);
- if (bps != null) {
- area.addTrait(Trait.BORDER_END, bps);
- }
-
- addPadding(area, borderProps, context);
- }
-
- /**
- * Add borders to an area.
- * Layout managers that create areas with borders can use this to
- * add the borders to the area.
- * @param area the area to set the traits on.
- * @param borderProps border properties
- * @param discardBefore true if the before border should be discarded
- * @param discardAfter true if the after border should be discarded
- * @param discardStart true if the start border should be discarded
- * @param discardEnd true if the end border should be discarded
- * @param context Property evaluation context
- */
- //TODO: remove evaluation context; unused, since border-widths are always absolute lengths
- public static void addBorders(Area area, CommonBorderPaddingBackground borderProps,
- boolean discardBefore, boolean discardAfter,
- boolean discardStart, boolean discardEnd,
- PercentBaseContext context) {
- BorderProps bps = getBorderProps(borderProps, CommonBorderPaddingBackground.BEFORE);
- if (bps != null && !discardBefore) {
- area.addTrait(Trait.BORDER_BEFORE, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.AFTER);
- if (bps != null && !discardAfter) {
- area.addTrait(Trait.BORDER_AFTER, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.START);
- if (bps != null && !discardStart) {
- area.addTrait(Trait.BORDER_START, bps);
- }
- bps = getBorderProps(borderProps, CommonBorderPaddingBackground.END);
- if (bps != null && !discardEnd) {
- area.addTrait(Trait.BORDER_END, bps);
- }
- }
-
- /**
- * Add borders to an area for the collapsing border model in tables.
- * Layout managers that create areas with borders can use this to
- * add the borders to the area.
- * @param area the area to set the traits on.
- * @param borderBefore the resolved before border
- * @param borderAfter the resolved after border
- * @param borderStart the resolved start border
- * @param borderEnd the resolved end border
- * @param outer 4 boolean values indicating if the side represents the
- * table's outer border. Order: before, after, start, end
- */
- public static void addCollapsingBorders(Area area,
- BorderInfo borderBefore, BorderInfo borderAfter,
- BorderInfo borderStart, BorderInfo borderEnd,
- boolean[] outer) {
- BorderProps bps = getCollapsingBorderProps(borderBefore, outer[0]);
- if (bps != null) {
- area.addTrait(Trait.BORDER_BEFORE, bps);
- }
- bps = getCollapsingBorderProps(borderAfter, outer[1]);
- if (bps != null) {
- area.addTrait(Trait.BORDER_AFTER, bps);
- }
- bps = getCollapsingBorderProps(borderStart, outer[2]);
- if (bps != null) {
- area.addTrait(Trait.BORDER_START, bps);
- }
- bps = getCollapsingBorderProps(borderEnd, outer[3]);
- if (bps != null) {
- area.addTrait(Trait.BORDER_END, bps);
- }
- }
-
- private static void addPadding(Area area, CommonBorderPaddingBackground bordProps,
- PercentBaseContext context) {
- addPadding(area, bordProps, false, false, false, false, context);
- }
-
- /**
- * Add padding to an area.
- * Layout managers that create areas with padding can use this to
- * add the borders to the area.
- * @param area the area to set the traits on.
- * @param bordProps border and padding properties
- * @param discardBefore true if the before padding should be discarded
- * @param discardAfter true if the after padding should be discarded
- * @param discardStart true if the start padding should be discarded
- * @param discardEnd true if the end padding should be discarded
- * @param context Property evaluation context
- */
- public static void addPadding(Area area, CommonBorderPaddingBackground bordProps,
- boolean discardBefore, boolean discardAfter,
- boolean discardStart, boolean discardEnd,
- PercentBaseContext context) {
- int padding = bordProps.getPadding(CommonBorderPaddingBackground.BEFORE,
- discardBefore, context);
- if (padding != 0) {
- area.addTrait(Trait.PADDING_BEFORE, padding);
- }
-
- padding = bordProps.getPadding(CommonBorderPaddingBackground.AFTER,
- discardAfter, context);
- if (padding != 0) {
- area.addTrait(Trait.PADDING_AFTER, padding);
- }
-
- padding = bordProps.getPadding(CommonBorderPaddingBackground.START,
- discardStart, context);
- if (padding != 0) {
- area.addTrait(Trait.PADDING_START, padding);
- }
-
- padding = bordProps.getPadding(CommonBorderPaddingBackground.END,
- discardEnd, context);
- if (padding != 0) {
- area.addTrait(Trait.PADDING_END, padding);
- }
-
- }
-
- private static BorderProps getBorderProps(CommonBorderPaddingBackground bordProps, int side) {
- int width = bordProps.getBorderWidth(side, false);
- if (width != 0) {
- BorderProps bps;
- bps = new BorderProps(bordProps.getBorderStyle(side),
- width,
- bordProps.getBorderColor(side),
- BorderProps.SEPARATE);
- return bps;
- } else {
- return null;
- }
- }
-
- private static BorderProps getCollapsingBorderProps(BorderInfo borderInfo, boolean outer) {
- assert borderInfo != null;
- int width = borderInfo.getRetainedWidth();
- if (width != 0) {
- return new BorderProps(borderInfo.getStyle(), width, borderInfo.getColor(),
- (outer ? BorderProps.COLLAPSE_OUTER : BorderProps.COLLAPSE_INNER));
- } else {
- return null;
- }
- }
-
- /**
- * Add background to an area. This method is mainly used by table-related layout
- * managers to add background for column, body or row. Since the area corresponding to
- * border-separation must be filled with the table's background, for every cell an
- * additional area with the same dimensions is created to hold the background for the
- * corresponding column/body/row. An additional shift must then be added to
- * background-position-horizontal/vertical to ensure the background images are
- * correctly placed. Indeed the placement of images must be made WRT the
- * column/body/row and not the cell.
- *
- * <p>Note: The area's IPD and BPD must be set before calling this method.</p>
- *
- * <p>TODO the regular
- * {@link #addBackground(Area, CommonBorderPaddingBackground, PercentBaseContext)}
- * method should be used instead, and a means to retrieve the original area's
- * dimensions must be found.</p>
- *
- * <p>TODO the placement of images in the x- or y-direction will be incorrect if
- * background-repeat is set for that direction.</p>
- *
- * @param area the area to set the traits on
- * @param backProps the background properties
- * @param context Property evaluation context
- * @param ipdShift horizontal shift to affect to the background, in addition to the
- * value of the background-position-horizontal property
- * @param bpdShift vertical shift to affect to the background, in addition to the
- * value of the background-position-vertical property
- * @param referenceIPD value to use as a reference for percentage calculation
- * @param referenceBPD value to use as a reference for percentage calculation
- */
- public static void addBackground(Area area,
- CommonBorderPaddingBackground backProps,
- PercentBaseContext context,
- int ipdShift, int bpdShift, int referenceIPD, int referenceBPD) {
- if (!backProps.hasBackground()) {
- return;
- }
- Trait.Background back = new Trait.Background();
- back.setColor(backProps.backgroundColor);
-
- if (backProps.getImageInfo() != null) {
- back.setURL(backProps.backgroundImage);
- back.setImageInfo(backProps.getImageInfo());
- back.setRepeat(backProps.backgroundRepeat);
- if (backProps.backgroundPositionHorizontal != null) {
- if (back.getRepeat() == Constants.EN_NOREPEAT
- || back.getRepeat() == Constants.EN_REPEATY) {
- if (area.getIPD() > 0) {
- PercentBaseContext refContext = new SimplePercentBaseContext(context,
- LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL,
- (referenceIPD - back.getImageInfo().getSize().getWidthMpt()));
-
- back.setHoriz(ipdShift
- + backProps.backgroundPositionHorizontal.getValue(refContext));
- } else {
- // TODO Area IPD has to be set for this to work
- LOG.warn("Horizontal background image positioning ignored"
- + " because the IPD was not set on the area."
- + " (Yes, it's a bug in FOP)");
- }
- }
- }
- if (backProps.backgroundPositionVertical != null) {
- if (back.getRepeat() == Constants.EN_NOREPEAT
- || back.getRepeat() == Constants.EN_REPEATX) {
- if (area.getBPD() > 0) {
- PercentBaseContext refContext = new SimplePercentBaseContext(context,
- LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL,
- (referenceBPD - back.getImageInfo().getSize().getHeightMpt()));
- back.setVertical(bpdShift
- + backProps.backgroundPositionVertical.getValue(refContext));
- } else {
- // TODO Area BPD has to be set for this to work
- LOG.warn("Vertical background image positioning ignored"
- + " because the BPD was not set on the area."
- + " (Yes, it's a bug in FOP)");
- }
- }
- }
- }
-
- area.addTrait(Trait.BACKGROUND, back);
- }
-
- /**
- * Add background to an area.
- * Layout managers that create areas with a background can use this to
- * add the background to the area.
- * Note: The area's IPD and BPD must be set before calling this method.
- * @param area the area to set the traits on
- * @param backProps the background properties
- * @param context Property evaluation context
- */
- public static void addBackground(Area area,
- CommonBorderPaddingBackground backProps,
- PercentBaseContext context) {
- if (!backProps.hasBackground()) {
- return;
- }
- Trait.Background back = new Trait.Background();
- back.setColor(backProps.backgroundColor);
-
- if (backProps.getImageInfo() != null) {
- back.setURL(backProps.backgroundImage);
- back.setImageInfo(backProps.getImageInfo());
- back.setRepeat(backProps.backgroundRepeat);
- if (backProps.backgroundPositionHorizontal != null) {
- if (back.getRepeat() == Constants.EN_NOREPEAT
- || back.getRepeat() == Constants.EN_REPEATY) {
- if (area.getIPD() > 0) {
- int width = area.getIPD();
- width += backProps.getPaddingStart(false, context);
- width += backProps.getPaddingEnd(false, context);
- int imageWidthMpt = back.getImageInfo().getSize().getWidthMpt();
- int lengthBaseValue = width - imageWidthMpt;
- SimplePercentBaseContext simplePercentBaseContext
- = new SimplePercentBaseContext(context,
- LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL,
- lengthBaseValue);
- int horizontal = backProps.backgroundPositionHorizontal.getValue(
- simplePercentBaseContext);
- back.setHoriz(horizontal);
- } else {
- //TODO Area IPD has to be set for this to work
- LOG.warn("Horizontal background image positioning ignored"
- + " because the IPD was not set on the area."
- + " (Yes, it's a bug in FOP)");
- }
- }
- }
- if (backProps.backgroundPositionVertical != null) {
- if (back.getRepeat() == Constants.EN_NOREPEAT
- || back.getRepeat() == Constants.EN_REPEATX) {
- if (area.getBPD() > 0) {
- int height = area.getBPD();
- height += backProps.getPaddingBefore(false, context);
- height += backProps.getPaddingAfter(false, context);
- int imageHeightMpt = back.getImageInfo().getSize().getHeightMpt();
- int lengthBaseValue = height - imageHeightMpt;
- SimplePercentBaseContext simplePercentBaseContext
- = new SimplePercentBaseContext(context,
- LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL,
- lengthBaseValue);
- int vertical = backProps.backgroundPositionVertical.getValue(
- simplePercentBaseContext);
- back.setVertical(vertical);
- } else {
- //TODO Area BPD has to be set for this to work
- LOG.warn("Vertical background image positioning ignored"
- + " because the BPD was not set on the area."
- + " (Yes, it's a bug in FOP)");
- }
- }
- }
- }
-
- area.addTrait(Trait.BACKGROUND, back);
- }
-
- /**
- * Add space to a block area.
- * Layout managers that create block areas can use this to add space
- * outside of the border rectangle to the area.
- * @param area the area to set the traits on.
- * @param bpProps the border, padding and background properties
- * @param startIndent the effective start-indent value
- * @param endIndent the effective end-indent value
- * @param context the context for evaluation of percentages
- */
- public static void addMargins(Area area,
- CommonBorderPaddingBackground bpProps,
- int startIndent, int endIndent,
- PercentBaseContext context) {
- if (startIndent != 0) {
- area.addTrait(Trait.START_INDENT, startIndent);
- }
-
- int spaceStart = startIndent
- - bpProps.getBorderStartWidth(false)
- - bpProps.getPaddingStart(false, context);
- if (spaceStart != 0) {
- area.addTrait(Trait.SPACE_START, spaceStart);
- }
-
- if (endIndent != 0) {
- area.addTrait(Trait.END_INDENT, endIndent);
- }
- int spaceEnd = endIndent
- - bpProps.getBorderEndWidth(false)
- - bpProps.getPaddingEnd(false, context);
- if (spaceEnd != 0) {
- area.addTrait(Trait.SPACE_END, spaceEnd);
- }
- }
-
- /**
- * Add space to a block area.
- * Layout managers that create block areas can use this to add space
- * outside of the border rectangle to the area.
- * @param area the area to set the traits on.
- * @param bpProps the border, padding and background properties
- * @param marginProps the margin properties.
- * @param context the context for evaluation of percentages
- */
- public static void addMargins(Area area,
- CommonBorderPaddingBackground bpProps,
- CommonMarginBlock marginProps,
- PercentBaseContext context) {
- int startIndent = marginProps.startIndent.getValue(context);
- int endIndent = marginProps.endIndent.getValue(context);
- addMargins(area, bpProps, startIndent, endIndent, context);
- }
-
- /**
- * Returns the effective space length of a resolved space specifier based on the adjustment
- * value.
- * @param adjust the adjustment value
- * @param space the space specifier
- * @return the effective space length
- */
- public static int getEffectiveSpace(double adjust, MinOptMax space) {
- if (space == null) {
- return 0;
- } else {
- int spaceOpt = space.getOpt();
- if (adjust > 0) {
- spaceOpt += (int) (adjust * space.getStretch());
- } else {
- spaceOpt += (int) (adjust * space.getShrink());
- }
- return spaceOpt;
- }
- }
-
- /**
- * Adds traits for space-before and space-after to an area.
- * @param area the target area
- * @param adjust the adjustment value
- * @param spaceBefore the space-before space specifier
- * @param spaceAfter the space-after space specifier
- */
- public static void addSpaceBeforeAfter(Area area, double adjust, MinOptMax spaceBefore,
- MinOptMax spaceAfter) {
- addSpaceTrait(area, Trait.SPACE_BEFORE, spaceBefore, adjust);
- addSpaceTrait(area, Trait.SPACE_AFTER, spaceAfter, adjust);
- }
-
- private static void addSpaceTrait(Area area, Integer spaceTrait,
- MinOptMax space, double adjust) {
- int effectiveSpace = getEffectiveSpace(adjust, space);
- if (effectiveSpace != 0) {
- area.addTrait(spaceTrait, effectiveSpace);
- }
- }
-
- /**
- * Sets the traits for breaks on an area.
- * @param area the area to set the traits on.
- * @param breakBefore the value for break-before
- * @param breakAfter the value for break-after
- */
- public static void addBreaks(Area area, int breakBefore, int breakAfter) {
- /* Currently disabled as these traits are never used by the renderers
- area.addTrait(Trait.BREAK_AFTER, new Integer(breakAfter));
- area.addTrait(Trait.BREAK_BEFORE, new Integer(breakBefore));
- */
- }
-
- /**
- * Adds font traits to an area
- * @param area the target are
- * @param font the font to use
- */
- public static void addFontTraits(Area area, Font font) {
- area.addTrait(Trait.FONT, font.getFontTriplet());
- area.addTrait(Trait.FONT_SIZE, font.getFontSize());
- }
-
- /**
- * Adds the text-decoration traits to the area.
- * @param area the area to set the traits on
- * @param deco the text decorations
- */
- public static void addTextDecoration(Area area, CommonTextDecoration deco) {
- //TODO Finish text-decoration
- if (deco != null) {
- if (deco.hasUnderline()) {
- area.addTrait(Trait.UNDERLINE, Boolean.TRUE);
- area.addTrait(Trait.UNDERLINE_COLOR, deco.getUnderlineColor());
- }
- if (deco.hasOverline()) {
- area.addTrait(Trait.OVERLINE, Boolean.TRUE);
- area.addTrait(Trait.OVERLINE_COLOR, deco.getOverlineColor());
- }
- if (deco.hasLineThrough()) {
- area.addTrait(Trait.LINETHROUGH, Boolean.TRUE);
- area.addTrait(Trait.LINETHROUGH_COLOR, deco.getLineThroughColor());
- }
- if (deco.isBlinking()) {
- area.addTrait(Trait.BLINK, Boolean.TRUE);
- }
- }
- }
-
- /**
- * Sets the structure tree element associated to the given area.
- *
- * @param area the area to set the traits on
- * @param structureTreeElement the element the area is associated to in the document structure
- */
- public static void addStructureTreeElement(Area area, StructureTreeElement structureTreeElement) {
- if (structureTreeElement != null) {
- area.addTrait(Trait.STRUCTURE_TREE_ELEMENT, structureTreeElement);
- }
- }
-
- /**
- * Sets the producer's ID as a trait on the area. This can be used to track back the
- * generating FO node.
- * @param area the area to set the traits on
- * @param id the ID to set
- */
- public static void setProducerID(Area area, String id) {
- if (id != null && id.length() > 0) {
- area.addTrait(Trait.PROD_ID, id);
- }
- }
- }
|