blob: d5d3e5edbed29117ec40071a8489bb16a4d23e68 [file] [log] [blame]
/*
* 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.inline;
import org.apache.fop.fo.Constants;
/**
* The FOP specific incarnation of the XSL-FO scaled baseline table.
* All baseline tables are scaled to the font size of the font they
* apply to. This class uses a coordinate system with its origin
* where the dominant baseline intersects the start edge of the box.
* All measurements are in mpt.
*/
final class ScaledBaselineTable {
private static final float HANGING_BASELINE_FACTOR = 0.8f;
private static final float MATHEMATICAL_BASELINE_FACTOR = 0.5f;
private final int altitude;
private final int depth;
private final int xHeight;
private final int dominantBaselineIdentifier;
private final int writingMode;
private final int dominantBaselineOffset;
private int beforeEdgeOffset;
private int afterEdgeOffset;
/**
*
* Creates a new instance of BasicScaledBaselineTable for the given
* altitude, depth, xHeight, baseline and writing mode.
* @param altitude the height of the box or the font ascender
* @param depth the font descender or 0
* @param xHeight the font xHeight
* @param dominantBaselineIdentifier the dominant baseline given as an integer constant
* @param writingMode the writing mode given as an integer constant
*/
ScaledBaselineTable(int altitude,
int depth,
int xHeight,
int dominantBaselineIdentifier,
int writingMode) {
this.altitude = altitude;
this.depth = depth;
this.xHeight = xHeight;
this.dominantBaselineIdentifier = dominantBaselineIdentifier;
this.writingMode = writingMode;
this.dominantBaselineOffset = getBaselineDefaultOffset(this.dominantBaselineIdentifier);
this.beforeEdgeOffset = altitude - dominantBaselineOffset;
this.afterEdgeOffset = depth - dominantBaselineOffset;
}
/**
* Return the dominant baseline for this baseline table.
* @return the dominant baseline
*/
int getDominantBaselineIdentifier() {
return this.dominantBaselineIdentifier;
}
/**
* Return the writing mode for this baseline table.
* @return the writing mode
*/
int getWritingMode() {
return this.writingMode;
}
/**
* Return the offset of the given baseline from the dominant baseline.
*
* @param baselineIdentifier a baseline identifier
* @return the offset from the dominant baseline
*/
int getBaseline(int baselineIdentifier) {
int offset = 0;
if (!isHorizontalWritingMode()) {
switch (baselineIdentifier) {
case Constants.EN_TOP:
case Constants.EN_TEXT_TOP:
case Constants.EN_TEXT_BOTTOM:
case Constants.EN_BOTTOM:
throw new IllegalArgumentException("Baseline " + baselineIdentifier
+ " only supported for horizontal writing modes");
default: // TODO
}
}
switch (baselineIdentifier) {
case Constants.EN_TOP: // fall through
case Constants.EN_BEFORE_EDGE:
offset = beforeEdgeOffset;
break;
case Constants.EN_TEXT_TOP:
case Constants.EN_TEXT_BEFORE_EDGE:
case Constants.EN_HANGING:
case Constants.EN_CENTRAL:
case Constants.EN_MIDDLE:
case Constants.EN_MATHEMATICAL:
case Constants.EN_ALPHABETIC:
case Constants.EN_IDEOGRAPHIC:
case Constants.EN_TEXT_BOTTOM:
case Constants.EN_TEXT_AFTER_EDGE:
offset = getBaselineDefaultOffset(baselineIdentifier) - dominantBaselineOffset;
break;
case Constants.EN_BOTTOM: // fall through
case Constants.EN_AFTER_EDGE:
offset = afterEdgeOffset;
break;
default: throw new IllegalArgumentException(String.valueOf(baselineIdentifier));
}
return offset;
}
private boolean isHorizontalWritingMode() {
return writingMode == Constants.EN_LR_TB || writingMode == Constants.EN_RL_TB;
}
/**
* Return the baseline offset measured from the font's default
* baseline for the given baseline.
* @param baselineIdentifier the baseline identifier
* @return the baseline offset
*/
private int getBaselineDefaultOffset(int baselineIdentifier) {
int offset = 0;
switch (baselineIdentifier) {
case Constants.EN_TEXT_BEFORE_EDGE:
offset = altitude;
break;
case Constants.EN_HANGING:
offset = Math.round(altitude * HANGING_BASELINE_FACTOR);
break;
case Constants.EN_CENTRAL:
offset = (altitude - depth) / 2 + depth;
break;
case Constants.EN_MIDDLE:
offset = xHeight / 2;
break;
case Constants.EN_MATHEMATICAL:
offset = Math.round(altitude * MATHEMATICAL_BASELINE_FACTOR);
break;
case Constants.EN_ALPHABETIC:
offset = 0;
break;
case Constants.EN_IDEOGRAPHIC: // Fall through
case Constants.EN_TEXT_AFTER_EDGE:
offset = depth;
break;
default: throw new IllegalArgumentException(String.valueOf(baselineIdentifier));
}
return offset;
}
/**
* Sets the position of the before and after baselines.
* This is usually only done for line areas. For other
* areas the position of the before and after baselines
* are fixed when the table is constructed.
* @param beforeBaseline the offset of the before-edge baseline from the dominant baseline
* @param afterBaseline the offset of the after-edge baseline from the dominant baseline
*/
void setBeforeAndAfterBaselines(int beforeBaseline, int afterBaseline) {
beforeEdgeOffset = beforeBaseline;
afterEdgeOffset = afterBaseline;
}
/**
* Return a new baseline table for the given baseline based
* on the current baseline table.
* @param baselineIdentifier the baseline identifer
* @return a new baseline with the new baseline
*/
ScaledBaselineTable deriveScaledBaselineTable(int baselineIdentifier) {
ScaledBaselineTable bac = new ScaledBaselineTable(altitude, depth, xHeight,
baselineIdentifier, this.writingMode);
return bac;
}
}