KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layoutmgr > inline > AlignmentContext


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: AlignmentContext.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.layoutmgr.inline;
21
22 import org.apache.fop.datatypes.Length;
23 import org.apache.fop.datatypes.LengthBase;
24 import org.apache.fop.datatypes.SimplePercentBaseContext;
25 import org.apache.fop.fo.Constants;
26 import org.apache.fop.fonts.Font;
27
28 /**
29  * The alignment context is carried within a LayoutContext and as
30  * part of the Knuth Inline elements to facilitate proper line building.
31  * All measurements are in mpt.
32  */

33 public class AlignmentContext implements Constants {
34
35     /** The height or BPD of this context */
36     private int areaHeight;
37     /** The computed line-height property value applicable */
38     private int lineHeight;
39     /** The distance in BPD from the top of the box to the alignmentPoint */
40     private int alignmentPoint;
41     /** The baseline shift value in effect */
42     private int baselineShiftValue;
43     /** The computed alignment baseline identifier */
44     private int alignmentBaselineIdentifier;
45     /** The x height */
46     private int xHeight;
47     private ScaledBaselineTable scaledBaselineTable = null;
48     private ScaledBaselineTable actualBaselineTable = null;
49     private AlignmentContext parentAlignmentContext = null;
50     
51     /**
52      * Creates a new instance of AlignmentContext
53      * for graphics areas.
54      * @param height the total height of the area
55      * @param alignmentAdjust the alignment-adjust property
56      * @param alignmentBaseline the alignment-baseline property
57      * @param baselineShift the baseline-shift property
58      * @param dominantBaseline the dominant-baseline property
59      * @param parentAlignmentContext the parent alignment context
60      */

61     public AlignmentContext(int height
62                             , Length alignmentAdjust
63                             , int alignmentBaseline
64                             , Length baselineShift
65                             , int dominantBaseline
66                             , AlignmentContext parentAlignmentContext) {
67         
68         this.areaHeight = height;
69         this.lineHeight = height;
70         this.xHeight = height;
71         this.parentAlignmentContext = parentAlignmentContext;
72         this.scaledBaselineTable = parentAlignmentContext.getScaledBaselineTable();
73         setAlignmentBaselineIdentifier(alignmentBaseline
74                                        , parentAlignmentContext.getDominantBaselineIdentifier());
75         setBaselineShift(baselineShift);
76         int dominantBaselineIdentifier = parentAlignmentContext.getDominantBaselineIdentifier();
77         boolean newScaledBaselineTableRequired = false;
78         if (baselineShiftValue != 0) {
79             newScaledBaselineTableRequired = true;
80         }
81         switch (dominantBaseline) {
82             case EN_AUTO:
83                 newScaledBaselineTableRequired = baselineShiftValue != 0;
84                 break;
85             case EN_USE_SCRIPT: // TODO
86
break;
87             case EN_NO_CHANGE:
88                 break;
89             case EN_RESET_SIZE:
90                 newScaledBaselineTableRequired = true;
91                 break;
92             default:
93                 newScaledBaselineTableRequired = true;
94                 dominantBaselineIdentifier = dominantBaseline;
95                 break;
96         }
97         actualBaselineTable = ScaledBaselineTableFactory.makeGraphicsScaledBaselineTable(
98                                                             height,
99                                                             dominantBaselineIdentifier,
100                                                             scaledBaselineTable.getWritingMode());
101         if (newScaledBaselineTableRequired) {
102             scaledBaselineTable = ScaledBaselineTableFactory.makeGraphicsScaledBaselineTable(
103                                                             height,
104                                                             dominantBaselineIdentifier,
105                                                             scaledBaselineTable.getWritingMode());
106         }
107         setAlignmentAdjust(alignmentAdjust);
108     }
109     
110     /**
111      * Creates a new instance of AlignmentContext
112      * @param font the font
113      * @param lineHeight the computed value of the lineHeight property
114      * @param alignmentAdjust the alignment-adjust property
115      * @param alignmentBaseline the alignment-baseline property
116      * @param baselineShift the baseline-shift property
117      * @param dominantBaseline the dominant-baseline property
118      * @param parentAlignmentContext the parent alignment context
119      */

120     public AlignmentContext(Font font
121                             , int lineHeight
122                             , Length alignmentAdjust
123                             , int alignmentBaseline
124                             , Length baselineShift
125                             , int dominantBaseline
126                             , AlignmentContext parentAlignmentContext) {
127         this.areaHeight = font.getAscender() - font.getDescender();
128         this.lineHeight = lineHeight;
129         this.parentAlignmentContext = parentAlignmentContext;
130         this.scaledBaselineTable = parentAlignmentContext.getScaledBaselineTable();
131         this.xHeight = font.getXHeight();
132         setAlignmentBaselineIdentifier(alignmentBaseline
133                                        , parentAlignmentContext.getDominantBaselineIdentifier());
134         setBaselineShift(baselineShift);
135         int dominantBaselineIdentifier = parentAlignmentContext.getDominantBaselineIdentifier();
136         boolean newScaledBaselineTableRequired = false;
137         if (baselineShiftValue != 0) {
138             newScaledBaselineTableRequired = true;
139         }
140         switch (dominantBaseline) {
141             case EN_AUTO:
142                 newScaledBaselineTableRequired = baselineShiftValue != 0;
143                 break;
144             case EN_USE_SCRIPT: // TODO
145
break;
146             case EN_NO_CHANGE:
147                 break;
148             case EN_RESET_SIZE:
149                 newScaledBaselineTableRequired = true;
150                 break;
151             default:
152                 newScaledBaselineTableRequired = true;
153                 dominantBaselineIdentifier = dominantBaseline;
154                 break;
155         }
156         actualBaselineTable = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font,
157                                                             dominantBaselineIdentifier,
158                                                             scaledBaselineTable.getWritingMode());
159         if (newScaledBaselineTableRequired) {
160             scaledBaselineTable = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font,
161                                     dominantBaselineIdentifier,
162                                     scaledBaselineTable.getWritingMode());
163         }
164         setAlignmentAdjust(alignmentAdjust);
165     }
166     
167     /**
168      * Creates a new instance of AlignmentContext based simply
169      * on the font and the writing mode.
170      * @param font the font
171      * @param lineHeight the computed value of the lineHeight property
172      * @param writingMode the current writing mode
173      */

174     public AlignmentContext(Font font, int lineHeight, int writingMode) {
175         this.areaHeight = font.getAscender() - font.getDescender();
176         this.lineHeight = lineHeight;
177         this.xHeight = font.getXHeight();
178         this.parentAlignmentContext = null;
179         this.scaledBaselineTable
180                     = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font, writingMode);
181         this.actualBaselineTable = scaledBaselineTable;
182         this.alignmentBaselineIdentifier = getDominantBaselineIdentifier();
183         this.alignmentPoint = font.getAscender();
184         this.baselineShiftValue = 0;
185     }
186     
187     /**
188      * Returns the alignment point for this context.
189      * This is the point on the start edge of the area this context
190      * applies to measured from the before edge of the area.
191      * @return the default alignment point
192      */

193     public int getAlignmentPoint() {
194         return alignmentPoint;
195     }
196
197     /**
198      * Returns the current value of baseline shift in effect.
199      * @return the baseline shift
200      */

201     public int getBaselineShiftValue() {
202         return baselineShiftValue;
203     }
204
205     /**
206      * Returns the current alignment baseline identifier
207      * @return the alignment baseline identifier
208      */

209     public int getAlignmentBaselineIdentifier() {
210         return alignmentBaselineIdentifier;
211     }
212
213     /**
214      * Sets the current alignment baseline identifer. For
215      * alignment-baseline values of "auto" and "baseline" this
216      * method does the conversion into the appropriate computed
217      * value assuming script is "auto" and the fo is not fo:character.
218      * @param alignmentBaseline the alignment-baseline property
219      * @param parentDominantBaselineIdentifier the dominant baseline of the parent fo
220      */

221     private void setAlignmentBaselineIdentifier(int alignmentBaseline
222                                                , int parentDominantBaselineIdentifier) {
223         switch (alignmentBaseline) {
224             case EN_AUTO: // fall through
225
case EN_BASELINE:
226                 this.alignmentBaselineIdentifier = parentDominantBaselineIdentifier;
227                 break;
228             case EN_BEFORE_EDGE:
229             case EN_TEXT_BEFORE_EDGE:
230             case EN_CENTRAL:
231             case EN_MIDDLE:
232             case EN_AFTER_EDGE:
233             case EN_TEXT_AFTER_EDGE:
234             case EN_IDEOGRAPHIC:
235             case EN_ALPHABETIC:
236             case EN_HANGING:
237             case EN_MATHEMATICAL:
238                 this.alignmentBaselineIdentifier = alignmentBaseline;
239                 break;
240         }
241     }
242
243     /**
244      * Sets the current alignment baseline identifer. For
245      * alignment-baseline values of "auto" and "baseline" this
246      * method does the conversion into the appropriate computed
247      * value assuming script is "auto" and the fo is not fo:character.
248      * @param alignmentAdjust the alignment-adjust property
249      */

250     private void setAlignmentAdjust(Length alignmentAdjust) {
251         int beforeEdge = actualBaselineTable.getBaseline(EN_BEFORE_EDGE);
252         switch (alignmentAdjust.getEnum()) {
253             case EN_AUTO:
254                 alignmentPoint = beforeEdge
255                                     - actualBaselineTable.getBaseline(alignmentBaselineIdentifier);
256                 break;
257             case EN_BASELINE:
258                 alignmentPoint = beforeEdge;
259                 break;
260             case EN_BEFORE_EDGE:
261             case EN_TEXT_BEFORE_EDGE:
262             case EN_CENTRAL:
263             case EN_MIDDLE:
264             case EN_AFTER_EDGE:
265             case EN_TEXT_AFTER_EDGE:
266             case EN_IDEOGRAPHIC:
267             case EN_ALPHABETIC:
268             case EN_HANGING:
269             case EN_MATHEMATICAL:
270                 alignmentPoint = beforeEdge
271                                     - actualBaselineTable.getBaseline(alignmentAdjust.getEnum());
272                 break;
273             default:
274                 alignmentPoint = beforeEdge
275                     + alignmentAdjust.getValue(new SimplePercentBaseContext(null
276                                                         , LengthBase.ALIGNMENT_ADJUST
277                                                         , lineHeight));
278                 break;
279         }
280     }
281
282     /**
283      * Return the scaled baseline table for this context.
284      * @return the scaled baseline table
285      */

286     public ScaledBaselineTable getScaledBaselineTable() {
287         return this.scaledBaselineTable;
288     }
289
290     /**
291      * Return the dominant baseline identifier.
292      * @return the dominant baseline identifier
293      */

294     public int getDominantBaselineIdentifier() {
295         return scaledBaselineTable.getDominantBaselineIdentifier();
296     }
297     
298     /**
299      * Return the writing mode.
300      * @return the writing mode
301      */

302     public int getWritingMode() {
303         return scaledBaselineTable.getWritingMode();
304     }
305     
306     /**
307      * Calculates the baseline shift value based on the baseline-shift
308      * property value.
309      * @param baselineShift the baseline shift property value
310      * @return the computed baseline shift value
311      */

312     private void setBaselineShift(Length baselineShift) {
313         baselineShiftValue = 0;
314         ScaledBaselineTable sbt = null;
315         switch (baselineShift.getEnum()) {
316             case EN_BASELINE: //Nothing to do
317
break;
318             case EN_SUB:
319                 baselineShiftValue = Math.round(-(xHeight / 2)
320                                 + parentAlignmentContext.getActualBaselineOffset(EN_ALPHABETIC)
321                                 );
322                 break;
323             case EN_SUPER:
324                 baselineShiftValue = Math.round(parentAlignmentContext.getXHeight()
325                                 + parentAlignmentContext.getActualBaselineOffset(EN_ALPHABETIC)
326                                 );
327                 break;
328             case 0: // A <length> or <percentage> value
329
baselineShiftValue = baselineShift.getValue(
330                     new SimplePercentBaseContext(null
331                                                 , LengthBase.CUSTOM_BASE
332                                                 , parentAlignmentContext.getLineHeight()));
333                 break;
334         }
335     }
336
337     /**
338      * Return the parent alignment context.
339      * @return the parent alignment context
340      */

341     public AlignmentContext getParentAlignmentContext() {
342         return parentAlignmentContext;
343     }
344
345     /**
346      * Return the offset between the current dominant baseline and
347      * the parent dominant baseline.
348      * @return the offset in shift direction
349      */

350     public int getBaselineOffset() {
351         if (parentAlignmentContext == null) {
352             return 0;
353         }
354         return parentAlignmentContext.getScaledBaselineTable()
355                                     .getBaseline(alignmentBaselineIdentifier)
356                 - scaledBaselineTable
357                     .deriveScaledBaselineTable(parentAlignmentContext.getDominantBaselineIdentifier())
358                     .getBaseline(alignmentBaselineIdentifier)
359                 - scaledBaselineTable
360                     .getBaseline(parentAlignmentContext.getDominantBaselineIdentifier())
361                 + baselineShiftValue;
362     }
363
364     /**
365      * Return the offset between the current dominant baseline and
366      * the outermost parent dominant baseline.
367      * @return the offet in shift direction
368      */

369     public int getTotalBaselineOffset() {
370         int offset = 0;
371         if (parentAlignmentContext != null) {
372             offset = getBaselineOffset() + parentAlignmentContext.getTotalBaselineOffset();
373         }
374         return offset;
375     }
376
377     /**
378      * Return the offset between the alignment baseline and
379      * the outermost parent dominant baseline.
380      * @return the offset in shift direction
381      */

382     public int getTotalAlignmentBaselineOffset() {
383         return getTotalAlignmentBaselineOffset(alignmentBaselineIdentifier);
384     }
385
386     /**
387      * Return the offset between the given alignment baseline and
388      * the outermost parent dominant baseline.
389      * @param alignmentBaselineId the alignment baseline
390      * @return the offset
391      */

392     public int getTotalAlignmentBaselineOffset(int alignmentBaselineId) {
393         int offset = baselineShiftValue;
394         if (parentAlignmentContext != null) {
395             offset = parentAlignmentContext.getTotalBaselineOffset()
396                     + parentAlignmentContext.getScaledBaselineTable()
397                         .getBaseline(alignmentBaselineId)
398                     + baselineShiftValue;
399         }
400         return offset;
401     }
402
403     /**
404      * Return the offset between the dominant baseline and
405      * the given actual baseline
406      * @param baselineIdentifier the baseline
407      * @return the offset
408      */

409     public int getActualBaselineOffset(int baselineIdentifier) {
410         // This is the offset from the dominant baseline to the alignment baseline
411
int offset = getTotalAlignmentBaselineOffset() - getTotalBaselineOffset();
412         // Add the offset to the actual baseline we want
413
offset += actualBaselineTable.deriveScaledBaselineTable(alignmentBaselineIdentifier)
414                     .getBaseline(baselineIdentifier);
415         return offset;
416     }
417
418     /**
419      * Return the offset the outermost parent dominant baseline
420      * and the top of this box.
421      * @return the offset
422      */

423     private int getTotalTopOffset() {
424         int offset = getTotalAlignmentBaselineOffset() + getAltitude();
425         return offset;
426     }
427
428     /**
429      * Return the total height of the context.
430      * @return the height
431      */

432     public int getHeight() {
433         return areaHeight;
434     }
435     
436     /**
437      * Return the line height of the context.
438      * @return the height
439      */

440     public int getLineHeight() {
441         return lineHeight;
442     }
443     
444     /**
445      * The altitude of the context that is the height above the
446      * alignment point.
447      * @return the altitude
448      */

449     public int getAltitude() {
450         return alignmentPoint;
451     }
452
453     /**
454      * The depth of the context that is the height below
455      * alignment point.
456      * @return the altitude
457      */

458     public int getDepth() {
459         return getHeight() - alignmentPoint;
460     }
461     
462     /**
463      * The x height of the context.
464      * @return the x height
465      */

466     public int getXHeight() {
467         return this.xHeight;
468     }
469     
470     /**
471      * Resizes the line as specified. Assumes that the new alignment point
472      * is on the dominant baseline, that is this function should be called for
473      * line areas only.
474      * @param newLineHeight the new height of the line
475      * @param newAlignmentPoint the new alignment point
476      */

477     public void resizeLine(int newLineHeight, int newAlignmentPoint) {
478         areaHeight = newLineHeight;
479         alignmentPoint = newAlignmentPoint;
480         scaledBaselineTable.setBeforeAndAfterBaselines(alignmentPoint
481                                                         , alignmentPoint - areaHeight);
482     }
483     
484     /**
485      * Returns the offset from the before-edge of the parent to
486      * this context.
487      * @return the offset for rendering
488      */

489     public int getOffset() {
490         int offset = 0;
491         if (parentAlignmentContext != null) {
492             offset = parentAlignmentContext.getTotalTopOffset() - getTotalTopOffset();
493         } else {
494             offset = getAltitude() - scaledBaselineTable.getBaseline(EN_TEXT_BEFORE_EDGE);
495         }
496         return offset;
497     }
498     
499     /**
500      * Returns an indication if we still use the initial baseline table.
501      * The initial baseline table is the table generated by the Line LM.
502      * @return true if this is still the initial baseline table
503      */

504     public boolean usesInitialBaselineTable() {
505         return parentAlignmentContext == null
506                || (scaledBaselineTable == parentAlignmentContext.getScaledBaselineTable()
507                     && parentAlignmentContext.usesInitialBaselineTable());
508     }
509     
510     private boolean isHorizontalWritingMode() {
511         return (getWritingMode() == EN_LR_TB || getWritingMode() == EN_RL_TB);
512     }
513     
514     /** @see java.lang.Object#toString() */
515     public String JavaDoc toString() {
516         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(64);
517         sb.append("ah=" + areaHeight);
518         sb.append(" lp=" + lineHeight);
519         sb.append(" ap=" + alignmentPoint);
520         sb.append(" ab=" + alignmentBaselineIdentifier);
521         sb.append(" bs=" + baselineShiftValue);
522         return sb.toString();
523     }
524     
525 }
526
Popular Tags