| /* |
| * 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.area; |
| |
| import java.util.List; |
| |
| import org.apache.fop.fo.Constants; |
| import org.apache.fop.traits.WritingModeTraitsGetter; |
| |
| /** |
| * The span-reference-area. |
| * This is a block-area with 0 border and padding that is stacked |
| * within the main-reference-area |
| * This object holds one or more normal-flow-reference-area children |
| * based on the column-count trait in effect for this span. |
| * See fo:region-body definition in the XSL Rec for more information. |
| */ |
| public class Span extends Area { |
| |
| private static final long serialVersionUID = -5551430053660081549L; |
| |
| // the list of flow reference areas in this span area |
| private List<NormalFlow> flowAreas; |
| private int colCount; |
| private int colGap; |
| private int colWidth; // width for each normal flow, calculated value |
| private int curFlowIdx; // n-f-r-a currently being processed, zero-based |
| |
| /** |
| * Create a span area with the number of columns for this span area. |
| * |
| * @param colCount the number of columns in the span |
| * @param colGap the column gap between each column |
| * @param ipd the total ipd of the span |
| */ |
| public Span(int colCount, int colGap, int ipd) { |
| addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); |
| this.colCount = colCount; |
| this.colGap = colGap; |
| this.ipd = ipd; |
| curFlowIdx = 0; |
| createNormalFlows(); |
| } |
| |
| /** |
| * Create the normal flows for this Span |
| */ |
| private void createNormalFlows() { |
| flowAreas = new java.util.ArrayList<NormalFlow>(colCount); |
| colWidth = (ipd - ((colCount - 1) * colGap)) / colCount; |
| |
| for (int i = 0; i < colCount; i++) { |
| NormalFlow newFlow = new NormalFlow(colWidth); |
| flowAreas.add(newFlow); |
| } |
| } |
| |
| /** |
| * Get the column count for this span area. |
| * |
| * @return the number of columns defined for this span area |
| */ |
| public int getColumnCount() { |
| return colCount; |
| } |
| |
| /** |
| * Get the column gap for this span area. |
| * |
| * @return the column gap for this span area |
| */ |
| public int getColumnGap() { |
| return colGap; |
| } |
| |
| /** |
| * Get the width of a single column within this Span |
| * |
| * @return the width of a single column |
| */ |
| public int getColumnWidth() { |
| return colWidth; |
| } |
| |
| /** |
| * Get the height of this span area. |
| * |
| * @return the height of this span area |
| */ |
| public int getHeight() { |
| return getBPD(); |
| } |
| |
| |
| /** |
| * Get the normal flow area for a particular column. |
| * |
| * @param colRequested the zero-based column number of the flow |
| * @return the flow area for the requested column |
| */ |
| public NormalFlow getNormalFlow(int colRequested) { |
| if (colRequested >= 0 && colRequested < colCount) { |
| return flowAreas.get(colRequested); |
| } else { // internal error |
| throw new IllegalArgumentException("Invalid column number " |
| + colRequested + " requested; only 0-" + (colCount - 1) |
| + " available."); |
| } |
| } |
| |
| /** |
| * Get the NormalFlow area currently being processed |
| * |
| * @return the current NormalFlow |
| */ |
| public NormalFlow getCurrentFlow() { |
| return getNormalFlow(curFlowIdx); |
| } |
| |
| /** @return the index of the current normal flow */ |
| public int getCurrentFlowIndex() { |
| return curFlowIdx; |
| } |
| |
| /** |
| * Indicate to the Span that the next column is being |
| * processed. |
| * |
| * @return the new NormalFlow (in the next column) |
| */ |
| public NormalFlow moveToNextFlow() { |
| if (hasMoreFlows()) { |
| curFlowIdx++; |
| return getNormalFlow(curFlowIdx); |
| } else { |
| throw new IllegalStateException("(Internal error.) No more flows left in span."); |
| } |
| } |
| |
| /** |
| * Indicates if the Span has unprocessed flows. |
| * |
| * @return true if Span can increment to the next flow, |
| * false otherwise. |
| */ |
| public boolean hasMoreFlows() { |
| return (curFlowIdx < colCount - 1); |
| } |
| |
| /** |
| * Called to notify the span that all its flows have been fully generated so it can update |
| * its own BPD extent. |
| */ |
| public void notifyFlowsFinished() { |
| int maxFlowBPD = Integer.MIN_VALUE; |
| for (int i = 0; i < colCount; i++) { |
| maxFlowBPD = Math.max(maxFlowBPD, getNormalFlow(i).getAllocBPD()); |
| } |
| bpd = maxFlowBPD; |
| } |
| |
| /** |
| * Indicates whether any child areas have been added to this span area. |
| * |
| * This is achieved by looping through each flow. |
| * @return true if no child areas have been added yet. |
| */ |
| public boolean isEmpty() { |
| int areaCount = 0; |
| for (int i = 0; i < getColumnCount(); i++) { |
| NormalFlow flow = getNormalFlow(i); |
| if (flow != null) { |
| if (flow.getChildAreas() != null) { |
| areaCount += flow.getChildAreas().size(); |
| } |
| } |
| } |
| return (areaCount == 0); |
| } |
| |
| /** |
| * Sets the writing mode traits for the main reference area of |
| * this span area. |
| * @param wmtg a WM traits getter |
| */ |
| public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { |
| switch (wmtg.getColumnProgressionDirection().getEnumValue()) { |
| case Constants.EN_RL: |
| setBidiLevel(1); |
| for (NormalFlow flowArea1 : flowAreas) { |
| flowArea1.setBidiLevel(1); |
| } |
| break; |
| default: |
| resetBidiLevel(); |
| for (NormalFlow flowArea : flowAreas) { |
| flowArea.resetBidiLevel(); |
| } |
| break; |
| } |
| addTrait(Trait.INLINE_PROGRESSION_DIRECTION, wmtg.getInlineProgressionDirection()); |
| addTrait(Trait.BLOCK_PROGRESSION_DIRECTION, wmtg.getBlockProgressionDirection()); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String toString() { |
| StringBuffer sb = new StringBuffer(super.toString()); |
| if (colCount > 1) { |
| sb.append(" {colCount=").append(colCount); |
| sb.append(", colWidth=").append(colWidth); |
| sb.append(", curFlowIdx=").append(this.curFlowIdx); |
| sb.append("}"); |
| } |
| return sb.toString(); |
| } |
| |
| } |
| |