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 }