1 /* Fo
2 * fo-area-table-cell.c: Area object for 'table-cell' formatting objects
3 *
4 * Copyright (C) 2001 Sun Microsystems
5 * Copyright (C) 2007-2009 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include "fo-utils.h"
11 #include "fo-area-table-cell-private.h"
12 #include "fo-area-table-cell-proxy.h"
13 #include "fo/fo-block-fo.h"
14 #include "fo/fo-table-cell.h"
15 #include "property/fo-property-block-progression-dimension.h"
16 #include "property/fo-property-inline-progression-dimension.h"
17 #include "property/fo-property-keep-with-next.h"
18 #include "property/fo-property-keep-with-previous.h"
19 #include "property/fo-property-keep-with-next-within-column.h"
20 #include "property/fo-property-keep-with-next-within-page.h"
21 #include "property/fo-property-keep-with-previous-within-column.h"
22 #include "property/fo-property-keep-with-previous-within-page.h"
23
24 static void fo_area_table_cell_class_init (FoAreaTableCellClass *klass);
25 static void fo_area_table_cell_finalize (GObject *object);
26
27 static void fo_area_table_cell_debug_dump_properties (FoArea *area,
28 gint depth);
29 static FoArea* fo_area_table_cell_size_request (FoArea *child);
30 static FoArea* fo_area_table_cell_split_before_height (FoArea *area,
31 gdouble max_height);
32 static gboolean fo_area_table_cell_split_before_height_check (FoArea *area,
33 gdouble max_height);
34 static void fo_area_table_cell_size_adjust (FoArea *area,
35 gpointer data);
36
37 static void fo_area_table_cell_set_or_split (FoArea *area,
38 gpointer data);
39 static void fo_area_table_cell_update_after_clone (FoArea *clone,
40 FoArea *original);
41
42 static gpointer parent_class;
43
44 /**
45 * fo_area_table_cell_get_type:
46 *
47 * Register the #FoAreaTableCell object type.
48 *
49 * Return value: #GType value of the #FoAreaTableCell object type.
50 **/
51 GType
fo_area_table_cell_get_type(void)52 fo_area_table_cell_get_type (void)
53 {
54 static GType object_type = 0;
55
56 if (!object_type)
57 {
58 static const GTypeInfo object_info =
59 {
60 sizeof (FoAreaTableCellClass),
61 (GBaseInitFunc) NULL,
62 (GBaseFinalizeFunc) NULL,
63 (GClassInitFunc) fo_area_table_cell_class_init,
64 NULL, /* class_finalize */
65 NULL, /* class_data */
66 sizeof (FoAreaTableCell),
67 0, /* n_preallocs */
68 NULL, /* instance_init */
69 NULL /* value_table */
70 };
71
72 object_type = g_type_register_static (FO_TYPE_AREA_REFERENCE,
73 "FoAreaTableCell",
74 &object_info, 0);
75 }
76
77 return object_type;
78 }
79
80 static void
fo_area_table_cell_class_init(FoAreaTableCellClass * klass)81 fo_area_table_cell_class_init (FoAreaTableCellClass *klass)
82 {
83 GObjectClass *object_class = G_OBJECT_CLASS (klass);
84
85 parent_class = g_type_class_peek_parent (klass);
86
87 object_class->finalize = fo_area_table_cell_finalize;
88
89 FO_AREA_CLASS (klass)->debug_dump_properties = fo_area_table_cell_debug_dump_properties;
90 FO_AREA_CLASS (klass)->size_request = fo_area_table_cell_size_request;
91 FO_AREA_CLASS (klass)->split_before_height = fo_area_table_cell_split_before_height;
92 FO_AREA_CLASS (klass)->split_before_height_check = fo_area_table_cell_split_before_height_check;
93 FO_AREA_CLASS (klass)->update_after_clone =
94 fo_area_table_cell_update_after_clone;
95 }
96
97 static void
fo_area_table_cell_finalize(GObject * object)98 fo_area_table_cell_finalize (GObject *object)
99 {
100 FoAreaTableCell *fo_area_table_cell;
101
102 fo_area_table_cell = FO_AREA_TABLE_CELL (object);
103
104 G_OBJECT_CLASS (parent_class)->finalize (object);
105 }
106
107
108 /**
109 * fo_area_table_cell_new:
110 *
111 * Creates a new #FoAreaTableCell initialized to default value.
112 *
113 * Return value: the new #FoAreaTableCell
114 **/
115 FoArea*
fo_area_table_cell_new(void)116 fo_area_table_cell_new (void)
117 {
118 return FO_AREA (g_object_new (fo_area_table_cell_get_type (), NULL));
119 }
120
121
122 /**
123 * fo_area_table_cell_debug_dump_properties:
124 * @area: The #FoArea object
125 * @depth: Indent level to add to the output
126 *
127 * Logs the value of each significant property of @area then calls
128 * debug_dump_properties method of parent class.
129 **/
130 void
fo_area_table_cell_debug_dump_properties(FoArea * area,gint depth)131 fo_area_table_cell_debug_dump_properties (FoArea *area,
132 gint depth)
133 {
134 FoAreaTableCell *table_cell;
135 gchar *indent = g_strnfill (depth * 2, ' ');
136
137 g_return_if_fail (area != NULL);
138 g_return_if_fail (FO_IS_AREA_TABLE_CELL (area));
139
140 table_cell = FO_AREA_TABLE_CELL (area);
141
142 g_free (indent);
143 FO_AREA_CLASS (parent_class)->debug_dump_properties (area, depth + 1);
144 }
145
146 /**
147 * fo_area_table_cell_size_adjust:
148 * @area: #FoArea node to be placed within parent
149 * @data: Not used
150 *
151 * Place @area within its parent and adjust the parent's next-x and
152 * next-y properties accordingly.
153 **/
154 void
fo_area_table_cell_size_adjust(FoArea * area,gpointer data G_GNUC_UNUSED)155 fo_area_table_cell_size_adjust (FoArea *area,
156 gpointer data G_GNUC_UNUSED)
157 {
158 g_return_if_fail (FO_IS_AREA (area));
159 g_return_if_fail (FO_IS_AREA_TABLE_CELL (fo_area_parent (area)));
160
161 FoArea *table_cell = fo_area_parent (area);
162
163 fo_area_area_set_x (area,
164 fo_area_get_next_x (table_cell) +
165 fo_area_area_get_start_indent (area));
166 fo_area_area_set_y (area,
167 fo_area_get_next_y (table_cell) -
168 fo_area_area_get_space_before (area));
169 fo_area_set_next_x (table_cell,
170 fo_area_area_get_border_before (table_cell) +
171 fo_area_area_get_padding_before (table_cell));
172 fo_area_set_next_y (table_cell,
173 fo_area_get_next_y (table_cell) -
174 fo_area_area_get_height (area));
175 fo_area_set_available_height (area,
176 fo_area_area_get_height (area));
177 fo_area_set_available_width (area,
178 fo_area_get_child_available_ipdim (table_cell));
179 }
180
181 /**
182 * fo_area_table_cell_set_or_split:
183 * @area: #FoArea to be either placed within the parent area or split
184 * into two areas
185 * @data: Not used
186 *
187 *
188 **/
189 void
fo_area_table_cell_set_or_split(FoArea * area,gpointer data G_GNUC_UNUSED)190 fo_area_table_cell_set_or_split (FoArea *area,
191 gpointer data G_GNUC_UNUSED)
192 {
193 FoArea *table_cell;
194 gdouble table_cell_child_available_bpdim;
195
196 g_return_if_fail (FO_IS_AREA (area));
197 g_return_if_fail (FO_IS_AREA_TABLE_CELL (fo_area_parent (area)));
198
199 table_cell = fo_area_parent (area);
200 table_cell_child_available_bpdim = fo_area_get_child_available_bpdim (table_cell);
201
202 if ((table_cell_child_available_bpdim -
203 (fo_area_get_next_y (table_cell) -
204 fo_area_area_get_height (area))) >= 0)
205 {
206 fo_area_area_set_x (area,
207 fo_area_get_next_x (table_cell) +
208 fo_area_area_get_start_indent (area));
209 fo_area_area_set_y (area,
210 fo_area_get_next_y (table_cell));
211 fo_area_set_next_x (table_cell,
212 fo_area_area_get_border_before (table_cell) +
213 fo_area_area_get_padding_before (table_cell));
214 fo_area_set_next_y (table_cell,
215 fo_area_get_next_y (table_cell) -
216 fo_area_area_get_height (area));
217 fo_area_set_available_height (area,
218 fo_area_area_get_height (area));
219 fo_area_set_available_width (area,
220 fo_area_get_child_available_ipdim (table_cell));
221 }
222 else
223 {
224 #if defined(LIBFO_DEBUG) && 1
225 g_message ("table_cell_set_or_split:: splitting:: child: %s; generated by: %s",
226 fo_object_debug_sprintf (area) ,
227 fo_object_debug_sprintf (area->generated_by));
228 #endif
229 area = fo_area_split_before_height (area,
230 table_cell_child_available_bpdim -
231 fo_area_area_get_height (table_cell));
232 table_cell = fo_area_parent (area);
233 table_cell_child_available_bpdim = fo_area_get_child_available_bpdim (table_cell);
234 }
235 }
236
237 /**
238 * fo_area_table_cell_size_request:
239 * @child: Child area
240 *
241 * Check that the parent area of @child has sufficient space for
242 * @child. If not enough space, request that the parent has
243 * sufficient space allocated for it, then adjust @child and its
244 * siblings as necessary to fit into the resized parent area.
245 *
246 * Return value: Pointer to the last area generated from @child after
247 * any reallocation and resizing
248 **/
249 FoArea*
fo_area_table_cell_size_request(FoArea * child)250 fo_area_table_cell_size_request (FoArea *child)
251 {
252 g_return_val_if_fail (child != NULL, NULL);
253 g_return_val_if_fail (FO_IS_AREA_AREA (child), NULL);
254 g_return_val_if_fail (!FO_AREA_IS_ROOT (child), NULL);
255 g_return_val_if_fail (fo_area_parent (child) != NULL, NULL);
256 g_return_val_if_fail (FO_IS_AREA_TABLE_CELL (fo_area_parent (child)), NULL);
257
258 /* The area that is the return value of this procedure. */
259 FoArea *return_child;
260 /* Used when determining the return value. */
261 FoArea *child_original_next_part = child->next_part;
262
263 /* The table cell containing the area that issued this request. */
264 FoArea *table_cell = fo_area_parent (child);
265 /* The length available for all children of this table cell. */
266 gdouble table_cell_child_available_bpdim =
267 fo_area_get_child_available_bpdim (table_cell);
268
269 /* Find the total height of all children. */
270 gdouble total_child_height = 0.0;
271 fo_area_children_foreach (table_cell,
272 G_TRAVERSE_ALL,
273 &fo_area_accumulate_height,
274 &total_child_height);
275
276 /* Ideally, this table cell would be just big enough for its borders
277 and padding plus the height needed for its children. */
278 gdouble table_cell_target_height =
279 total_child_height +
280 fo_area_area_get_border_before (table_cell) +
281 fo_area_area_get_padding_before (table_cell) +
282 fo_area_area_get_padding_after (table_cell) +
283 fo_area_area_get_border_after (table_cell);
284
285 /* The FoFo that generated this table cell may have set the allowed
286 height. */
287 FoDatatype *fo_cell_bpdim =
288 fo_property_get_value (fo_table_cell_get_block_progression_dimension (table_cell->generated_by));
289
290 gdouble table_cell_use_height = 0.0;
291 if (FO_IS_LENGTH_RANGE (fo_cell_bpdim))
292 {
293 FoDatatype *min_datatype =
294 fo_length_range_get_minimum (fo_cell_bpdim);
295 FoDatatype *opt_datatype =
296 fo_length_range_get_optimum (fo_cell_bpdim);
297 FoDatatype *max_datatype =
298 fo_length_range_get_maximum (fo_cell_bpdim);
299
300 if (FO_IS_LENGTH (min_datatype) &&
301 table_cell_target_height <= fo_length_get_value (min_datatype))
302 {
303 table_cell_use_height = fo_length_get_value (min_datatype);
304
305 #if defined(LIBFO_DEBUG) && 0
306 g_message ("table_cell_size_request:: target: %g; min: %g",
307 table_cell_target_height,
308 fo_length_get_value (min_datatype));
309 #endif
310 }
311 else if (FO_IS_LENGTH (opt_datatype) &&
312 table_cell_target_height < fo_length_get_value (opt_datatype))
313 {
314 table_cell_use_height = fo_length_get_value (opt_datatype);
315
316 #if defined(LIBFO_DEBUG) && 0
317 g_message ("table_cell_size_request:: target: %g; opt: %g",
318 table_cell_target_height,
319 fo_length_get_value (opt_datatype));
320 #endif
321 }
322 else if (FO_IS_LENGTH (max_datatype) &&
323 fo_length_get_value (max_datatype) < table_cell_target_height)
324 {
325 table_cell_use_height = fo_length_get_value (max_datatype);
326
327 #if defined(LIBFO_DEBUG) && 0
328 g_message ("table_cell_size_request:: target: %g; max: %g",
329 table_cell_target_height,
330 fo_length_get_value (max_datatype));
331 #endif
332 }
333 else
334 {
335 table_cell_use_height = table_cell_target_height;
336 }
337 }
338 else
339 {
340 /* The 'block_progression_dimension' property should only ever
341 be a length-range. */
342 g_assert_not_reached ();
343 }
344
345 /* The available height may be less than what is required (or what
346 is allowed by the FoFo). */
347 if (table_cell_child_available_bpdim < table_cell_use_height)
348 {
349 /* Set the height to what we want, and then let the parent area
350 work out what the available height should be. */
351 fo_area_area_set_height (table_cell,
352 table_cell_use_height);
353 table_cell = fo_area_size_request (table_cell);
354
355 /* The row will have set this cell's available height.
356 If there are other cells in the row that need more height,
357 the available height may have been more than requested. */
358 fo_area_area_set_height (table_cell,
359 fo_area_get_available_height (table_cell));
360
361 table_cell_child_available_bpdim =
362 MAX (fo_area_get_available_height (table_cell) -
363 fo_area_area_get_border_before (table_cell) -
364 fo_area_area_get_padding_before (table_cell) -
365 fo_area_area_get_padding_after (table_cell) -
366 fo_area_area_get_border_after (table_cell),
367 0);
368 fo_area_set_child_available_bpdim (table_cell,
369 table_cell_child_available_bpdim);
370 }
371
372 /* Work out the total child height again because this area's parent
373 area may have adjusted the children. */
374 total_child_height = 0.0;
375 fo_area_children_foreach (table_cell,
376 G_TRAVERSE_ALL,
377 &fo_area_accumulate_height,
378 &total_child_height);
379
380 /* Work out the new target height. */
381 table_cell_target_height =
382 total_child_height +
383 fo_area_area_get_border_before (table_cell) +
384 fo_area_area_get_padding_before (table_cell) +
385 fo_area_area_get_padding_after (table_cell) +
386 fo_area_area_get_border_after (table_cell);
387
388 /* In the absence of 'display-align', the first child is placed just
389 inside the borders and padding of this table cell. */
390 fo_area_set_next_x (table_cell,
391 fo_area_area_get_border_start (table_cell) +
392 fo_area_area_get_padding_start (table_cell));
393 fo_area_set_next_y (table_cell,
394 - (fo_area_area_get_border_before (table_cell) +
395 fo_area_area_get_padding_before (table_cell)));
396
397 if (table_cell_target_height <= table_cell_child_available_bpdim)
398 {
399 FoDatatype *fo_cell_display_align =
400 fo_property_get_value (fo_table_cell_get_display_align (table_cell->generated_by));
401
402 FoEnumEnum display_align =
403 fo_enum_get_value (fo_cell_display_align);
404
405 gdouble next_y;
406 switch (display_align)
407 {
408 case FO_ENUM_ENUM_AUTO:
409 /* Treat as 'before' while 'relative-align' is
410 unimplemented. */
411 case FO_ENUM_ENUM_BEFORE:
412 next_y =
413 - (fo_area_area_get_border_before (table_cell) +
414 fo_area_area_get_padding_before (table_cell));
415 break;
416 case FO_ENUM_ENUM_CENTER:
417 next_y =
418 - (fo_area_area_get_border_before (table_cell) +
419 fo_area_area_get_padding_before (table_cell) +
420 (table_cell_child_available_bpdim -
421 total_child_height) / 2.0);
422 break;
423 case FO_ENUM_ENUM_AFTER:
424 next_y =
425 - (fo_area_area_get_border_before (table_cell) +
426 fo_area_area_get_padding_before (table_cell) +
427 (table_cell_child_available_bpdim -
428 total_child_height));
429 break;
430 default:
431 g_assert_not_reached ();
432 }
433 fo_area_set_next_y (table_cell,
434 next_y);
435 /* Since the children all fit within the allowed height, adjust
436 their sizes and positions in sequence. */
437 fo_area_children_foreach (table_cell,
438 G_TRAVERSE_ALL,
439 &fo_area_table_cell_size_adjust,
440 NULL);
441 }
442 else
443 {
444 /* Since the children don't all fit, place the ones that fit in
445 the available height, and split at or before the allowed
446 height. */
447 fo_area_children_foreach (table_cell,
448 G_TRAVERSE_ALL,
449 &fo_area_table_cell_set_or_split,
450 NULL);
451 #if defined(LIBFO_DEBUG) && 0
452 g_message ("table_cell_size_request (%p):: total > available:: return:: table_cell->last: %s; generated by: %s",
453 child,
454 fo_object_debug_sprintf (fo_area_last_child (table_cell)),
455 fo_object_debug_sprintf (fo_area_last_child (table_cell)->generated_by));
456 #endif
457 }
458
459 /* The result will be the current child unless the child has been
460 split, in which case the result is the portion after the last
461 split. */
462 return_child = child;
463
464 while ((return_child->next_part != NULL) &&
465 (return_child->next_part != child_original_next_part))
466 {
467 return_child = return_child->next_part;
468 }
469
470 return return_child;
471 }
472
473 /* return the new area containing what comes after the split */
474 /* leave @area as area remaining after split */
475 FoArea*
fo_area_table_cell_split_before_height(FoArea * area,gdouble max_height)476 fo_area_table_cell_split_before_height (FoArea *area,
477 gdouble max_height)
478 {
479 FoArea *use_child_area;
480 gdouble minus_child_y = 0.0;
481 gdouble child_height = 0.0;
482
483 g_return_val_if_fail (FO_IS_AREA_TABLE_CELL (area), NULL);
484 g_return_val_if_fail (fo_area_n_children (area) > 0, NULL);
485 g_return_val_if_fail (max_height > 0, NULL);
486
487 /* if the current area is less than max height, then no new area */
488 if (fo_area_area_get_height (area) < max_height)
489 return NULL;
490
491 use_child_area = fo_area_first_child (area);
492
493 while (use_child_area)
494 {
495 minus_child_y = -fo_area_area_get_y (use_child_area);
496 child_height = fo_area_area_get_height (use_child_area);
497
498 if (minus_child_y + child_height >= max_height)
499 break;
500 else
501 use_child_area = fo_area_next_sibling (use_child_area);
502 }
503
504 #if defined(LIBFO_DEBUG) && 1
505 g_message ("table_cell_split_before_height:: splitting: area: %s; generated by: %s; y: %f; height: %f",
506 fo_object_debug_sprintf (use_child_area),
507 fo_object_debug_sprintf (fo_area_get_generated_by (use_child_area)),
508 fo_area_area_get_y (use_child_area),
509 fo_area_area_get_height (use_child_area));
510 #endif
511
512 if (use_child_area == NULL)
513 return NULL;
514
515 if (minus_child_y >= max_height)
516 {
517 /* max_height falls before use_child_area, i.e. in space between areas */
518
519 if (use_child_area == fo_area_first_child (area))
520 {
521 return NULL;
522 }
523 else
524 {
525 FoFo *child_fo =
526 fo_area_get_generated_by (use_child_area);
527 FoDatatype *child_kwpwp_datatype =
528 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
529 FoDatatype *child_kwpwc_datatype =
530 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
531
532 FoFo *prev_child_fo =
533 fo_area_get_generated_by (fo_area_prev_sibling (use_child_area));
534 FoDatatype *prev_child_kwnwp_datatype =
535 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
536 FoDatatype *prev_child_kwnwc_datatype =
537 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
538
539 /* FIXME: Need to handle integer keeps */
540 if ((FO_IS_ENUM (prev_child_kwnwp_datatype) &&
541 fo_enum_get_value (prev_child_kwnwp_datatype) == FO_ENUM_ENUM_AUTO) &&
542 (FO_IS_ENUM (prev_child_kwnwc_datatype) &&
543 fo_enum_get_value (prev_child_kwnwc_datatype) == FO_ENUM_ENUM_AUTO) &&
544 (FO_IS_ENUM (child_kwpwp_datatype) &&
545 fo_enum_get_value (child_kwpwp_datatype) == FO_ENUM_ENUM_AUTO) &&
546 (FO_IS_ENUM (child_kwpwc_datatype) &&
547 fo_enum_get_value (child_kwpwc_datatype) == FO_ENUM_ENUM_AUTO))
548 {
549 /* If got to here, all relevant keeps are 'auto' */
550 FoArea *clone = fo_area_clone (area);
551
552 fo_area_unlink_with_next_siblings (use_child_area);
553 fo_area_insert_with_next_siblings (clone, 0, use_child_area);
554
555 return clone;
556 }
557 else
558 {
559 gdouble minus_prev_y =
560 fo_area_area_get_y (fo_area_prev_sibling (use_child_area));
561 gdouble prev_height =
562 fo_area_area_get_height (fo_area_prev_sibling (use_child_area));
563 /* If can't split between use_child_area and previous, maybe
564 can split at lower height */
565 return fo_area_table_cell_split_before_height (area,
566 minus_prev_y +
567 prev_height);
568 }
569 }
570 }
571 else
572 {
573 /* max_height falls within use_child_area */
574 gboolean child_can_split = fo_area_split_before_height_check (use_child_area,
575 max_height -
576 minus_child_y);
577
578 if (child_can_split)
579 {
580 FoArea *clone = fo_area_clone (area);
581 FoArea *split_child = fo_area_split_before_height (use_child_area,
582 max_height -
583 minus_child_y);
584 fo_area_unlink_with_next_siblings (split_child);
585 fo_area_insert_with_next_siblings (clone, 0, split_child);
586
587 return clone;
588 }
589 else
590 {
591 /* If can't split use_child_area, maybe
592 can split at lower height */
593 return fo_area_table_cell_split_before_height (area,
594 minus_child_y);
595 }
596 }
597 }
598
599 /* return the new area containing what comes after the split */
600 /* leave @area as area remaining after split */
601 gboolean
fo_area_table_cell_split_before_height_check(FoArea * area,gdouble max_height)602 fo_area_table_cell_split_before_height_check (FoArea *area,
603 gdouble max_height)
604 {
605 FoArea *use_child_area;
606 gdouble minus_child_y = 0.0;
607 gdouble child_height = 0.0;
608
609 g_return_val_if_fail (FO_IS_AREA_TABLE_CELL (area), FALSE);
610 g_return_val_if_fail (fo_area_n_children (area) > 0, FALSE);
611 /* FIXME: Getting max_height value of '-0'. */
612 g_return_val_if_fail (max_height >= 0, FALSE);
613
614 /* if the current area is less than max height, then no new area */
615 if (fo_area_area_get_height (area) < max_height)
616 return FALSE;
617
618 use_child_area = fo_area_first_child (area);
619
620 while (use_child_area)
621 {
622 minus_child_y = -fo_area_area_get_y (use_child_area);
623 child_height = fo_area_area_get_height (use_child_area);
624
625 if (minus_child_y + child_height >= max_height)
626 break;
627 else
628 use_child_area = fo_area_next_sibling (use_child_area);
629 }
630
631 #if defined(LIBFO_DEBUG) && 1
632 g_message ("table_cell_split_before_height_check:: splitting: area: %s; generated by: %s; y: %f; height: %f",
633 fo_object_debug_sprintf (use_child_area),
634 fo_object_debug_sprintf (fo_area_get_generated_by (use_child_area)),
635 fo_area_area_get_y (use_child_area),
636 fo_area_area_get_height (use_child_area));
637 #endif
638
639 if (use_child_area == NULL)
640 return FALSE;
641
642 if (minus_child_y >= max_height)
643 {
644 /* max_height falls before use_child_area, i.e. in space between areas */
645
646 if (use_child_area == fo_area_first_child (area))
647 {
648 return FALSE;
649 }
650 else
651 {
652 FoFo *child_fo =
653 fo_area_get_generated_by (use_child_area);
654 FoDatatype *child_kwpwp_datatype =
655 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
656 FoDatatype *child_kwpwc_datatype =
657 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
658
659 FoFo *prev_child_fo =
660 fo_area_get_generated_by (fo_area_prev_sibling (use_child_area));
661 FoDatatype *prev_child_kwnwp_datatype =
662 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
663 FoDatatype *prev_child_kwnwc_datatype =
664 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
665
666 /* FIXME: Need to handle integer keeps */
667 if ((FO_IS_ENUM (prev_child_kwnwp_datatype) &&
668 fo_enum_get_value (prev_child_kwnwp_datatype) == FO_ENUM_ENUM_AUTO) &&
669 (FO_IS_ENUM (prev_child_kwnwc_datatype) &&
670 fo_enum_get_value (prev_child_kwnwc_datatype) == FO_ENUM_ENUM_AUTO) &&
671 (FO_IS_ENUM (child_kwpwp_datatype) &&
672 fo_enum_get_value (child_kwpwp_datatype) == FO_ENUM_ENUM_AUTO) &&
673 (FO_IS_ENUM (child_kwpwc_datatype) &&
674 fo_enum_get_value (child_kwpwc_datatype) == FO_ENUM_ENUM_AUTO))
675 {
676 /* If got to here, all relevant keeps are 'auto' */
677 return TRUE;
678 }
679 else
680 {
681 gdouble minus_prev_y =
682 fo_area_area_get_y (fo_area_prev_sibling (use_child_area));
683 gdouble prev_height =
684 fo_area_area_get_height (fo_area_prev_sibling (use_child_area));
685 /* If can't split between use_child_area and previous, maybe
686 can split at lower height */
687 return fo_area_table_cell_split_before_height_check (area,
688 minus_prev_y +
689 prev_height);
690 }
691 }
692 }
693 else
694 {
695 /* max_height falls within use_child_area */
696 gboolean child_can_split = fo_area_split_before_height_check (use_child_area,
697 max_height -
698 minus_child_y);
699
700 if (child_can_split)
701 {
702 return TRUE;
703 }
704 else
705 {
706 /* If can't split use_child_area, maybe
707 can split at lower height */
708 return fo_area_table_cell_split_before_height_check (area,
709 minus_child_y);
710 }
711 }
712 }
713
714 /**
715 * fo_area_table_cell_update_after_clone:
716 * @clone: New object cloned from @original
717 * @original: Original area object
718 *
719 * Update the #FoAreaTableCell-specific instance variables of @clone to
720 * match those of @original.
721 **/
722 void
fo_area_table_cell_update_after_clone(FoArea * clone,FoArea * original)723 fo_area_table_cell_update_after_clone (FoArea *clone,
724 FoArea *original)
725 {
726 FO_AREA_CLASS (parent_class)->update_after_clone (clone, original);
727
728 fo_area_set_child_available_ipdim (clone,
729 fo_area_get_child_available_ipdim (original));
730 fo_area_area_set_width (clone,
731 fo_area_area_get_width (original));
732
733 }
734