~wpf-math-dev/wpf-math/devel

« back to all changes in this revision

Viewing changes to WpfMath/FractionAtom.cs

  • Committer: Alex Regueiro
  • Date: 2010-06-05 23:00:18 UTC
  • Revision ID: alexreg@gmail.com-20100605230018-wk0jl38tjcla09yh
Put all classes in library in WpfMath namespace.
Added RenderToBitmap method on TexRenderer.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
using System.Linq;
4
4
using System.Text;
5
5
 
6
 
// Atom representing fraction, with or without separation line.
7
 
internal class FractionAtom : Atom
 
6
namespace WpfMath
8
7
{
9
 
    private static TexAlignment CheckAlignment(TexAlignment alignment)
10
 
    {
11
 
        if (alignment == TexAlignment.Left || alignment == TexAlignment.Right)
12
 
            return alignment;
13
 
        else
14
 
            return TexAlignment.Center;
15
 
    }
16
 
 
17
 
    private TexAlignment numeratorAlignment;
18
 
    private TexAlignment denominatorAlignment;
19
 
 
20
 
    private double lineThickness;
21
 
    private TexUnit lineThicknessUnit;
22
 
 
23
 
    private bool useDefaultThickness;
24
 
    private double? lineRelativeThickness;
25
 
 
26
 
    public FractionAtom(Atom numerator, Atom denominator, double relativeThickness,
27
 
        TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
28
 
        : this(numerator, denominator, true, numeratorAlignment, denominatorAlignment)
29
 
    {
30
 
        this.lineRelativeThickness = relativeThickness;
31
 
    }
32
 
 
33
 
    public FractionAtom(Atom numerator, Atom denominator, bool drawLine,
34
 
        TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
35
 
        : this(numerator, denominator, drawLine)
36
 
    {
37
 
        this.numeratorAlignment = CheckAlignment(numeratorAlignment);
38
 
        this.denominatorAlignment = CheckAlignment(denominatorAlignment);
39
 
    }
40
 
 
41
 
    public FractionAtom(Atom numerator, Atom denominator, bool drawLine)
42
 
        : this(numerator, denominator, drawLine, TexUnit.Pixel, 0d)
43
 
    {
44
 
    }
45
 
 
46
 
    public FractionAtom(Atom numerator, Atom denominator, TexUnit unit, double thickness,
47
 
        TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
48
 
        : this(numerator, denominator, unit, thickness)
49
 
    {
50
 
        this.numeratorAlignment = CheckAlignment(numeratorAlignment);
51
 
        this.denominatorAlignment = CheckAlignment(denominatorAlignment);
52
 
    }
53
 
 
54
 
    public FractionAtom(Atom numerator, Atom denominator, TexUnit unit, double thickness)
55
 
        : this(numerator, denominator, false, unit, thickness)
56
 
    {
57
 
    }
58
 
 
59
 
    protected FractionAtom(Atom numerator, Atom denominator, bool useDefaultThickness, TexUnit unit, double thickness)
60
 
    {
61
 
        SpaceAtom.CheckUnit(unit);
62
 
 
63
 
        this.Type = TexAtomType.Inner;
64
 
        this.Numerator = numerator;
65
 
        this.Denominator = denominator;
66
 
        this.numeratorAlignment = TexAlignment.Center;
67
 
        this.denominatorAlignment = TexAlignment.Center;
68
 
        this.useDefaultThickness = useDefaultThickness;
69
 
        this.lineThicknessUnit = unit;
70
 
        this.lineThickness = thickness;
71
 
    }
72
 
 
73
 
    public Atom Numerator
74
 
    {
75
 
        get;
76
 
        private set;
77
 
    }
78
 
 
79
 
    public Atom Denominator
80
 
    {
81
 
        get;
82
 
        private set;
83
 
    }
84
 
 
85
 
    public override Box CreateBox(TexEnvironment environment)
86
 
    {
87
 
        var texFont = environment.TexFont;
88
 
        var style = environment.Style;
89
 
 
90
 
        // set thickness to default if default value should be used
91
 
        double lineHeight;
92
 
        var defaultLineThickness = texFont.GetDefaultLineThickness(style);
93
 
        if (this.useDefaultThickness)
94
 
            lineHeight = this.lineRelativeThickness.HasValue ? this.lineRelativeThickness.Value * defaultLineThickness :
95
 
                defaultLineThickness;
96
 
        else
97
 
            lineHeight = new SpaceAtom(this.lineThicknessUnit, 0, this.lineThickness, 0).CreateBox(environment).Height;
98
 
 
99
 
        // Create boxes for numerator and demoninator atoms, and make them of equal width.
100
 
        var numeratorBox = this.Numerator == null ? StrutBox.Empty :
101
 
            this.Numerator.CreateBox(environment.GetNumeratorStyle());
102
 
        var denominatorBox = this.Denominator == null ? StrutBox.Empty :
103
 
            this.Denominator.CreateBox(environment.GetDenominatorStyle());
104
 
 
105
 
        if (numeratorBox.Width < denominatorBox.Width)
106
 
            numeratorBox = new HorizontalBox(numeratorBox, denominatorBox.Width, numeratorAlignment);
107
 
        else
108
 
            denominatorBox = new HorizontalBox(denominatorBox, numeratorBox.Width, denominatorAlignment);
109
 
 
110
 
        // Calculate preliminary shift-up and shift-down amounts.
111
 
        double shiftUp, shiftDown;
112
 
        if (style < TexStyle.Text)
113
 
        {
114
 
            shiftUp = texFont.GetNum1(style);
115
 
            shiftDown = texFont.GetDenom1(style);
116
 
        }
117
 
        else
118
 
        {
119
 
            shiftDown = texFont.GetDenom2(style);
 
8
    // Atom representing fraction, with or without separation line.
 
9
    internal class FractionAtom : Atom
 
10
    {
 
11
        private static TexAlignment CheckAlignment(TexAlignment alignment)
 
12
        {
 
13
            if (alignment == TexAlignment.Left || alignment == TexAlignment.Right)
 
14
                return alignment;
 
15
            else
 
16
                return TexAlignment.Center;
 
17
        }
 
18
 
 
19
        private TexAlignment numeratorAlignment;
 
20
        private TexAlignment denominatorAlignment;
 
21
 
 
22
        private double lineThickness;
 
23
        private TexUnit lineThicknessUnit;
 
24
 
 
25
        private bool useDefaultThickness;
 
26
        private double? lineRelativeThickness;
 
27
 
 
28
        public FractionAtom(Atom numerator, Atom denominator, double relativeThickness,
 
29
            TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
 
30
            : this(numerator, denominator, true, numeratorAlignment, denominatorAlignment)
 
31
        {
 
32
            this.lineRelativeThickness = relativeThickness;
 
33
        }
 
34
 
 
35
        public FractionAtom(Atom numerator, Atom denominator, bool drawLine,
 
36
            TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
 
37
            : this(numerator, denominator, drawLine)
 
38
        {
 
39
            this.numeratorAlignment = CheckAlignment(numeratorAlignment);
 
40
            this.denominatorAlignment = CheckAlignment(denominatorAlignment);
 
41
        }
 
42
 
 
43
        public FractionAtom(Atom numerator, Atom denominator, bool drawLine)
 
44
            : this(numerator, denominator, drawLine, TexUnit.Pixel, 0d)
 
45
        {
 
46
        }
 
47
 
 
48
        public FractionAtom(Atom numerator, Atom denominator, TexUnit unit, double thickness,
 
49
            TexAlignment numeratorAlignment, TexAlignment denominatorAlignment)
 
50
            : this(numerator, denominator, unit, thickness)
 
51
        {
 
52
            this.numeratorAlignment = CheckAlignment(numeratorAlignment);
 
53
            this.denominatorAlignment = CheckAlignment(denominatorAlignment);
 
54
        }
 
55
 
 
56
        public FractionAtom(Atom numerator, Atom denominator, TexUnit unit, double thickness)
 
57
            : this(numerator, denominator, false, unit, thickness)
 
58
        {
 
59
        }
 
60
 
 
61
        protected FractionAtom(Atom numerator, Atom denominator, bool useDefaultThickness, TexUnit unit, double thickness)
 
62
        {
 
63
            WpfMath.SpaceAtom.CheckUnit(unit);
 
64
 
 
65
            this.Type = TexAtomType.Inner;
 
66
            this.Numerator = numerator;
 
67
            this.Denominator = denominator;
 
68
            this.numeratorAlignment = TexAlignment.Center;
 
69
            this.denominatorAlignment = TexAlignment.Center;
 
70
            this.useDefaultThickness = useDefaultThickness;
 
71
            this.lineThicknessUnit = unit;
 
72
            this.lineThickness = thickness;
 
73
        }
 
74
 
 
75
        public Atom Numerator
 
76
        {
 
77
            get;
 
78
            private set;
 
79
        }
 
80
 
 
81
        public Atom Denominator
 
82
        {
 
83
            get;
 
84
            private set;
 
85
        }
 
86
 
 
87
        public override Box CreateBox(WpfMath.TexEnvironment environment)
 
88
        {
 
89
            var texFont = environment.TexFont;
 
90
            var style = environment.Style;
 
91
 
 
92
            // set thickness to default if default value should be used
 
93
            double lineHeight;
 
94
            var defaultLineThickness = texFont.GetDefaultLineThickness(style);
 
95
            if (this.useDefaultThickness)
 
96
                lineHeight = this.lineRelativeThickness.HasValue ? this.lineRelativeThickness.Value * defaultLineThickness :
 
97
                    defaultLineThickness;
 
98
            else
 
99
                lineHeight = new WpfMath.SpaceAtom(this.lineThicknessUnit, 0, this.lineThickness, 0).CreateBox(environment).Height;
 
100
 
 
101
            // Create boxes for numerator and demoninator atoms, and make them of equal width.
 
102
            var numeratorBox = this.Numerator == null ? WpfMath.StrutBox.Empty :
 
103
                this.Numerator.CreateBox(environment.GetNumeratorStyle());
 
104
            var denominatorBox = this.Denominator == null ? WpfMath.StrutBox.Empty :
 
105
                this.Denominator.CreateBox(environment.GetDenominatorStyle());
 
106
 
 
107
            if (numeratorBox.Width < denominatorBox.Width)
 
108
                numeratorBox = new WpfMath.HorizontalBox(numeratorBox, denominatorBox.Width, numeratorAlignment);
 
109
            else
 
110
                denominatorBox = new WpfMath.HorizontalBox(denominatorBox, numeratorBox.Width, denominatorAlignment);
 
111
 
 
112
            // Calculate preliminary shift-up and shift-down amounts.
 
113
            double shiftUp, shiftDown;
 
114
            if (style < TexStyle.Text)
 
115
            {
 
116
                shiftUp = texFont.GetNum1(style);
 
117
                shiftDown = texFont.GetDenom1(style);
 
118
            }
 
119
            else
 
120
            {
 
121
                shiftDown = texFont.GetDenom2(style);
 
122
                if (lineHeight > 0)
 
123
                    shiftUp = texFont.GetNum2(style);
 
124
                else
 
125
                    shiftUp = texFont.GetNum3(style);
 
126
            }
 
127
 
 
128
            // Create result box.
 
129
            var resultBox = new WpfMath.VerticalBox();
 
130
 
 
131
            // add box for numerator.
 
132
            resultBox.Add(numeratorBox);
 
133
 
 
134
            // Calculate clearance and adjust shift amounts.
 
135
            var axis = texFont.GetAxisHeight(style);
 
136
 
120
137
            if (lineHeight > 0)
121
 
                shiftUp = texFont.GetNum2(style);
122
 
            else
123
 
                shiftUp = texFont.GetNum3(style);
124
 
        }
125
 
 
126
 
        // Create result box.
127
 
        var resultBox = new VerticalBox();
128
 
 
129
 
        // add box for numerator.
130
 
        resultBox.Add(numeratorBox);
131
 
 
132
 
        // Calculate clearance and adjust shift amounts.
133
 
        var axis = texFont.GetAxisHeight(style);
134
 
 
135
 
        if (lineHeight > 0)
136
 
        {
137
 
            // Draw fraction line.
138
 
 
139
 
            // Calculate clearance amount.
140
 
            double clearance;
141
 
            if (style < TexStyle.Text)
142
 
                clearance = 3 * lineHeight;
143
 
            else
144
 
                clearance = lineHeight;
145
 
 
146
 
            // Adjust shift amounts.
147
 
            var delta = lineHeight / 2;
148
 
            var kern1 = shiftUp - numeratorBox.Depth - (axis + delta);
149
 
            var kern2 = axis - delta - (denominatorBox.Height - shiftDown);
150
 
            var delta1 = clearance - kern1;
151
 
            var delta2 = clearance - kern2;
152
 
            if (delta1 > 0)
153
 
            {
154
 
                shiftUp += delta1;
155
 
                kern1 += delta1;
156
 
            }
157
 
            if (delta2 > 0)
158
 
            {
159
 
                shiftDown += delta2;
160
 
                kern2 += delta2;
161
 
            }
162
 
 
163
 
            resultBox.Add(new StrutBox(0, kern1, 0, 0));
164
 
            resultBox.Add(new HorizontalRule(lineHeight, numeratorBox.Width, 0));
165
 
            resultBox.Add(new StrutBox(0, kern2, 0, 0));
166
 
        }
167
 
        else
168
 
        {
169
 
            // Do not draw fraction line.
170
 
 
171
 
            // Calculate clearance amount.
172
 
            double clearance;
173
 
            if (style < TexStyle.Text)
174
 
                clearance = 7 * defaultLineThickness;
175
 
            else
176
 
                clearance = 3 * defaultLineThickness;
177
 
 
178
 
            // Adjust shift amounts.
179
 
            var kern = shiftUp - numeratorBox.Depth - (denominatorBox.Height - shiftDown);
180
 
            var delta = (clearance - kern) / 2;
181
 
            if (delta > 0)
182
 
            {
183
 
                shiftUp += delta;
184
 
                shiftDown += delta;
185
 
                kern += 2 * delta;
186
 
            }
187
 
 
188
 
            resultBox.Add(new StrutBox(0, kern, 0, 0));
189
 
        }
190
 
 
191
 
        // add box for denominator.
192
 
        resultBox.Add(denominatorBox);
193
 
 
194
 
        // Adjust height and depth of result box.
195
 
        resultBox.Height = shiftUp + numeratorBox.Height;
196
 
        resultBox.Depth = shiftDown + denominatorBox.Depth;
197
 
 
198
 
        return resultBox;
 
138
            {
 
139
                // Draw fraction line.
 
140
 
 
141
                // Calculate clearance amount.
 
142
                double clearance;
 
143
                if (style < TexStyle.Text)
 
144
                    clearance = 3 * lineHeight;
 
145
                else
 
146
                    clearance = lineHeight;
 
147
 
 
148
                // Adjust shift amounts.
 
149
                var delta = lineHeight / 2;
 
150
                var kern1 = shiftUp - numeratorBox.Depth - (axis + delta);
 
151
                var kern2 = axis - delta - (denominatorBox.Height - shiftDown);
 
152
                var delta1 = clearance - kern1;
 
153
                var delta2 = clearance - kern2;
 
154
                if (delta1 > 0)
 
155
                {
 
156
                    shiftUp += delta1;
 
157
                    kern1 += delta1;
 
158
                }
 
159
                if (delta2 > 0)
 
160
                {
 
161
                    shiftDown += delta2;
 
162
                    kern2 += delta2;
 
163
                }
 
164
 
 
165
                resultBox.Add(new WpfMath.StrutBox(0, kern1, 0, 0));
 
166
                resultBox.Add(new WpfMath.HorizontalRule(lineHeight, numeratorBox.Width, 0));
 
167
                resultBox.Add(new WpfMath.StrutBox(0, kern2, 0, 0));
 
168
            }
 
169
            else
 
170
            {
 
171
                // Do not draw fraction line.
 
172
 
 
173
                // Calculate clearance amount.
 
174
                double clearance;
 
175
                if (style < TexStyle.Text)
 
176
                    clearance = 7 * defaultLineThickness;
 
177
                else
 
178
                    clearance = 3 * defaultLineThickness;
 
179
 
 
180
                // Adjust shift amounts.
 
181
                var kern = shiftUp - numeratorBox.Depth - (denominatorBox.Height - shiftDown);
 
182
                var delta = (clearance - kern) / 2;
 
183
                if (delta > 0)
 
184
                {
 
185
                    shiftUp += delta;
 
186
                    shiftDown += delta;
 
187
                    kern += 2 * delta;
 
188
                }
 
189
 
 
190
                resultBox.Add(new WpfMath.StrutBox(0, kern, 0, 0));
 
191
            }
 
192
 
 
193
            // add box for denominator.
 
194
            resultBox.Add(denominatorBox);
 
195
 
 
196
            // Adjust height and depth of result box.
 
197
            resultBox.Height = shiftUp + numeratorBox.Height;
 
198
            resultBox.Depth = shiftDown + denominatorBox.Depth;
 
199
 
 
200
            return resultBox;
 
201
        }
199
202
    }
200
203
}