001 /*
002 * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: ScriptSupport.java,v d02878fc1d01 2009/09/08 12:35:02 max $ */
018
019 package net.sourceforge.jeuclid.elements.presentation.script;
020
021 import java.awt.geom.Dimension2D;
022
023 import net.sourceforge.jeuclid.LayoutContext;
024 import net.sourceforge.jeuclid.elements.JEuclidElement;
025 import net.sourceforge.jeuclid.elements.support.Dimension2DImpl;
026 import net.sourceforge.jeuclid.elements.support.ElementListSupport;
027 import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
028 import net.sourceforge.jeuclid.layout.LayoutInfo;
029 import net.sourceforge.jeuclid.layout.LayoutStage;
030 import net.sourceforge.jeuclid.layout.LayoutView;
031
032 /**
033 * Support class for script elements.
034 *
035 * @see AbstractSubSuper
036 * @see AbstractUnderOver
037 * @version $Revision: d02878fc1d01 $
038 */
039 public final class ScriptSupport {
040 /** Default Constructor. */
041 private ScriptSupport() {
042 // Empty on purpose.
043 }
044
045 /**
046 * Info for baseline shifts.
047 *
048 * @version $Revision: d02878fc1d01 $
049 */
050 static class ShiftInfo {
051 private float superShift;
052
053 private float subShift;
054
055 /**
056 * Creates a new ShiftInfo object.
057 *
058 * @param sub
059 * subShift.
060 * @param sup
061 * superShift.
062 */
063 protected ShiftInfo(final float sub, final float sup) {
064 this.superShift = sup;
065 this.subShift = sub;
066 }
067
068 /**
069 * Getter method for superShift.
070 *
071 * @return the superShift
072 */
073 public float getSuperShift() {
074 return this.superShift;
075 }
076
077 /**
078 * Getter method for subShift.
079 *
080 * @return the subShift
081 */
082 public float getSubShift() {
083 return this.subShift;
084 }
085
086 /**
087 * Adjust this shift to contain the max shift from current shit and
088 * other info.
089 *
090 * @param otherInfo
091 * other info to use.
092 */
093 public void max(final ShiftInfo otherInfo) {
094 this.subShift = Math.max(this.subShift, otherInfo.subShift);
095 this.superShift = Math.max(this.superShift, otherInfo.superShift);
096 }
097
098 }
099
100 // CHECKSTYLE:OFF
101 // More than 7 parameters. But only used internally, so that's ok.
102 static void layout(final LayoutView view, final LayoutInfo info,
103 final LayoutStage stage, final LayoutContext now,
104 final JEuclidElement parent, final JEuclidElement base,
105 final JEuclidElement sub, final JEuclidElement sup,
106 final String subScriptShift, final String superScriptShift) {
107 // CHECKSTYLE:ON
108 final LayoutInfo baseInfo = view.getInfo(base);
109 final float width = baseInfo.getWidth(stage);
110
111 final LayoutInfo subInfo = view.getInfo(sub);
112 final LayoutInfo superInfo = view.getInfo(sup);
113
114 final ShiftInfo shiftInfo = ScriptSupport.calculateScriptShfits(stage,
115 now, subScriptShift, superScriptShift, baseInfo, subInfo,
116 superInfo);
117
118 if (subInfo != null) {
119 subInfo.moveTo(width, shiftInfo.getSubShift(), stage);
120 }
121 if (superInfo != null) {
122 superInfo.moveTo(width, -shiftInfo.getSuperShift(), stage);
123 }
124
125 final Dimension2D borderLeftTop = new Dimension2DImpl(0.0f, 0.0f);
126 final Dimension2D borderRightBottom = new Dimension2DImpl(0.0f, 0.0f);
127 ElementListSupport.fillInfoFromChildren(view, info, parent, stage,
128 borderLeftTop, borderRightBottom);
129 info.setStretchAscent(baseInfo.getStretchAscent());
130 info.setStretchDescent(baseInfo.getStretchDescent());
131 }
132
133 static ShiftInfo calculateScriptShfits(final LayoutStage stage,
134 final LayoutContext now, final String subScriptShift,
135 final String superScriptShift, final LayoutInfo baseInfo,
136 final LayoutInfo subInfo, final LayoutInfo superInfo) {
137 float subShift = 0.0f;
138 float superShift = 0.0f;
139 if (subInfo != null) {
140 subShift = Math.max(baseInfo.getDescentHeight(stage)
141 + (subInfo.getAscentHeight(stage) - subInfo
142 .getDescentHeight(stage)) / 2.0f, AttributesHelper
143 .convertSizeToPt(subScriptShift, now, AttributesHelper.PT));
144 }
145 if (superInfo != null) {
146 superShift = Math.max(baseInfo.getAscentHeight(stage)
147 - (superInfo.getAscentHeight(stage) - superInfo
148 .getDescentHeight(stage)) / 2.0f,
149 AttributesHelper.convertSizeToPt(superScriptShift, now,
150 AttributesHelper.PT));
151 }
152 if ((subInfo != null) && (superInfo != null)) {
153 final float topSub = -subShift + subInfo.getAscentHeight(stage)
154 + 1.0f;
155 final float bottomSuper = superShift
156 - superInfo.getDescentHeight(stage) - 1.0f;
157
158 final float overlap = Math.max(0.0f, topSub - bottomSuper);
159 final float overlapShift = overlap / 2.0f;
160
161 superShift += overlapShift;
162 subShift += overlapShift;
163 }
164 return new ShiftInfo(subShift, superShift);
165 }
166
167 }