1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.elements.presentation.script;
20
21 import java.awt.geom.Dimension2D;
22
23 import net.sourceforge.jeuclid.LayoutContext;
24 import net.sourceforge.jeuclid.elements.JEuclidElement;
25 import net.sourceforge.jeuclid.elements.support.Dimension2DImpl;
26 import net.sourceforge.jeuclid.elements.support.ElementListSupport;
27 import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
28 import net.sourceforge.jeuclid.layout.LayoutInfo;
29 import net.sourceforge.jeuclid.layout.LayoutStage;
30 import net.sourceforge.jeuclid.layout.LayoutView;
31
32
33
34
35
36
37
38
39 public final class ScriptSupport {
40
41 private ScriptSupport() {
42
43 }
44
45
46
47
48
49
50 static class ShiftInfo {
51 private float superShift;
52
53 private float subShift;
54
55
56
57
58
59
60
61
62
63 protected ShiftInfo(final float sub, final float sup) {
64 this.superShift = sup;
65 this.subShift = sub;
66 }
67
68
69
70
71
72
73 public float getSuperShift() {
74 return this.superShift;
75 }
76
77
78
79
80
81
82 public float getSubShift() {
83 return this.subShift;
84 }
85
86
87
88
89
90
91
92
93 public void max(final ShiftInfo otherInfo) {
94 this.subShift = Math.max(this.subShift, otherInfo.subShift);
95 this.superShift = Math.max(this.superShift, otherInfo.superShift);
96 }
97
98 }
99
100
101
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
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 }