1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.foRenderer.figures;
13
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 import org.apache.fop.area.Area;
20 import org.apache.fop.area.Block;
21 import org.apache.fop.area.BlockViewport;
22 import org.apache.fop.area.Footnote;
23 import org.apache.fop.area.LineArea;
24 import org.apache.fop.area.MainReference;
25 import org.apache.fop.area.NormalFlow;
26 import org.apache.fop.area.RegionViewport;
27 import org.apache.fop.area.Span;
28 import org.apache.fop.area.inline.FilledArea;
29 import org.apache.fop.area.inline.ForeignObject;
30 import org.apache.fop.area.inline.InlineParent;
31 import org.apache.fop.area.inline.Leader;
32 import org.apache.fop.area.inline.Space;
33 import org.apache.fop.area.inline.TextArea;
34 import org.apache.fop.area.inline.UnresolvedPageNumber;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.draw2d.geometry.Rectangle;
37
38 import sk.uniba.euromath.EuroMath;
39 import sk.uniba.euromath.foRenderer.Draw2dRenderer;
40
41 /***
42 * @author TV Created on 14.1.2004
43 *
44 * Main controller in process of building GEF's figure hierarchy representing
45 * visual page.
46 *
47 * Sequentially converts Area objects produced by FOP layout mechanisms into
48 * Figure objects. Creation traversal: preorder.
49 *
50 * Clients communicate with factory through <code>build(Area)</code> method
51 */
52
53
54
55
56
57 public class FOPFigureFactory {
58
59 private static final Map<Class<Area>, Class<FOPFigureBuilder>> builderClasses = new HashMap<Class<Area>, Class<FOPFigureBuilder>>();
60
61 static {
62 registerBuilder(Block.class, BlockFigureBuilder.class);
63 registerBuilder(BlockViewport.class, BlockFigureBuilder.class);
64 registerBuilder(FilledArea.class,
65 InlineParentFigureBuilder.class);
66 registerBuilder(Footnote.class, FootnoteFigureBuilder.class);
67 registerBuilder(NormalFlow.class, FlowFigureBuilder.class);
68 registerBuilder(InlineParent.class,
69 InlineParentFigureBuilder.class);
70 registerBuilder(Leader.class, InlineFigureBuilder.class);
71 registerBuilder(LineArea.class, LineAreaBuilder.class);
72 registerBuilder(MainReference.class, MainReferenceBuilder.class);
73 registerBuilder(RegionViewport.class, RegionFigureBuilder.class);
74 registerBuilder(Space.class, InlineFigureBuilder.class);
75 registerBuilder(Span.class, SpanFigureBuilder.class);
76 registerBuilder(TextArea.class, TextAreaBuilder.class);
77 registerBuilder(UnresolvedPageNumber.class,
78 TextAreaBuilder.class);
79
80
81
82 registerBuilder(ForeignObject.class, ForeignObjectBuilder.class);
83 }
84
85 private Map builders;
86
87 private Map orphanRegister;
88
89 /***
90 * Stores sequence of created Figures. This is used when finding last
91 * created figure of some class.
92 */
93 private List<FOPFigure> figureSequence;
94
95 private final Draw2dRenderer renderer;
96
97 private Rectangle locData = null;
98
99 /***
100 * Constructor Creates and inits internal data members and sets state
101 * provider
102 *
103 * @param stateProvider
104 * IRenderingStateProvider
105 */
106 public FOPFigureFactory(Draw2dRenderer renderer) {
107 this.renderer = renderer;
108 createInternals();
109 reset();
110 }
111
112 /***
113 * Adds figure to sequence of created figures
114 *
115 * @param f
116 * FOPFigure to add
117 */
118 private void addFigureToSequence(FOPFigure f) {
119 this.figureSequence.add(f);
120 }
121
122 /***
123 * Finds in context of <code>input</code> a <code>builder</code> and
124 * that builds the figure
125 *
126 * @param input
127 * Object from that the resulting figure is builed
128 * @return FOPFigure
129 */
130 protected FOPFigure build(Object input) {
131 if (input == null) {
132 throw new IllegalArgumentException(
133 "FOP Figure Factory: input cannot be null.");
134 }
135 FOPFigureBuilder builder = getBuilder(input.getClass());
136 FOPFigure result = null;
137
138 if (builder != null) {
139
140 if (locData != null)
141 result = builder.build(input, locData.x,
142 locData.y, locData.width,
143 locData.height);
144 else
145 result = builder.build(input);
146
147 refreshInternals(result, builder);
148
149 } else {
150
151 return createUnknown(input);
152 }
153 return result;
154 }
155
156 /***
157 * Builds a FOPFigure to the <code>area</code>. Use it when size and
158 * placement of the figure is left on the builder, that counts it from
159 * <code>renderingStateProvider</code>
160 *
161 * @param area
162 * Area from FO area tree
163 * @return FOPFigure
164 */
165 public FOPFigure buildFigure(Area area) {
166 storeLocationData(0, 0, 0, 0);
167 return build(area);
168 }
169
170 /***
171 * Builds a FOPFigure to the <code>area</code>. Use it when size and
172 * placement of the figure is depends on <code>rect</code>
173 *
174 * @param area
175 * Area from FO area tree
176 * @param rect
177 * defines bounds of the Figure
178 * @return FOPFigure
179 */
180 public FOPFigure buildFigure(Area area, Rectangle rect) {
181 storeLocationData(rect.x, rect.y, rect.width, rect.height);
182 return build(area);
183 }
184
185 private void createInternals() {
186 builders = new HashMap();
187 figureSequence = new ArrayList<FOPFigure>();
188 orphanRegister = new HashMap();
189 }
190
191 protected FOPFigure createUnknown(Object input) {
192 return new UnsupportedFigure(input);
193 }
194
195
196
197
198
199 public FOPFigureBuilder getBuilder(Class areaClass) {
200 if (!builders.containsKey(areaClass)) {
201 FOPFigureBuilder newBuilder = initBuilder(areaClass);
202 if (newBuilder != null) {
203 builders.put(areaClass, newBuilder);
204 } else {
205 String msg = "Builder for class "
206 + areaClass.getName()
207 + " is not registered.";
208 EuroMath.log(IStatus.WARNING, 0, msg, null);
209 }
210 }
211 return (FOPFigureBuilder) builders.get(areaClass);
212 }
213
214 public FOPFigure getLastFigure(Class clazz) {
215 for (int i = figureSequence.size() - 1; i >= 0; i--) {
216 Object obj = figureSequence.get(i);
217 if (obj.getClass() == clazz) {
218 return (FOPFigure) obj;
219 }
220 }
221 return null;
222 }
223
224 protected void hookChildrenAreas(FOPFigure figure, List children) {
225 if (children != null) {
226 for (int i = 0; i < children.size(); i++) {
227 orphanRegister.put(children.get(i), figure);
228 }
229 }
230 }
231
232 protected FOPFigureBuilder initBuilder(Class areaClass) {
233 FOPFigureBuilder b = null;
234 try {
235 final Class<FOPFigureBuilder> bClass = builderClasses
236 .get(areaClass);
237 if (bClass == null)
238 throw new IllegalArgumentException(
239 "No figure builder for "
240 + areaClass
241 .getName());
242 b = bClass.newInstance();
243
244 b.setFactory(this);
245 b.setRenderingState(this.renderer);
246 } catch (Exception e) {
247 throw new RuntimeException(e);
248 }
249 return b;
250 }
251
252 protected void initialize() {
253 orphanRegister.clear();
254 figureSequence.clear();
255 }
256
257 protected void log(Exception exc) {
258 EuroMath.log(IStatus.WARNING, 0, "log", exc);
259 }
260
261 private int convertFontHeight(int millipoints) {
262 float result = (float) millipoints / 1000.0f;
263
264 return Math.round(result
265 }
266
267 protected void refreshInternals(FOPFigure figure,
268 FOPFigureBuilder builder) {
269 addFigureToSequence(figure);
270 hookChildrenAreas(figure, builder.getChildrenAreas());
271 sendInfoToParent(figure);
272 }
273
274 public static void registerBuilder(Class areaClass, Class builderClass) {
275 builderClasses.put(areaClass, builderClass);
276 }
277
278 /***
279 * All internal data are destroyed.
280 *
281 */
282 public void reset() {
283 initialize();
284 }
285
286 protected void storeLocationData(int x, int y, int w, int h) {
287 locData = null;
288 if ((x != 0) || (y != 0) || (w != 0) || (h != 0)) {
289 locData = new Rectangle(x, y, w, h);
290 }
291 }
292
293 protected void sendInfoToParent(FOPFigure newFigure) {
294 Object area = newFigure.getArea();
295
296
297
298
299 if (orphanRegister.containsKey(area)) {
300 FOPFigure parent = (FOPFigure) orphanRegister.get(area);
301 parent.add(newFigure);
302 orphanRegister.remove(area);
303 }
304 }
305
306
307
308
309 protected int convert(int milipoints) {
310 return FOFigureUtils.mps2pxs(milipoints);
311 }
312
313
314
315
316
317
318
319
320
321
322
323 public Draw2dRenderer getRenderer() {
324 return this.renderer;
325 }
326 }