00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <string.h>
00028 #include "cr-box.h"
00029
00030
00031
00032
00033
00034
00035
00036 static enum CRStatus
00037 cr_box_construct (CRBox *a_this, CRStyle *a_style,
00038 gboolean a_set_default_style) ;
00039
00040 static enum CRStatus
00041 cr_box_edge_to_string (CRBoxEdge *a_this,
00042 gulong a_nb_indent,
00043 GString **a_string) ;
00044
00045 static enum CRBoxType
00046 cr_box_guess_type (CRStyle *a_style) ;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 static enum CRBoxType
00059 cr_box_guess_type (CRStyle *a_style)
00060 {
00061 enum CRBoxType box_type = BOX_TYPE_INLINE ;
00062
00063 if (!a_style)
00064 return box_type ;
00065
00066 switch (a_style->display)
00067 {
00068 case DISPLAY_NONE:
00069 break ;
00070
00071 case DISPLAY_INLINE:
00072 case DISPLAY_MARKER:
00073 box_type = BOX_TYPE_INLINE ;
00074 break ;
00075
00076 case DISPLAY_BLOCK:
00077 case DISPLAY_LIST_ITEM:
00078 case DISPLAY_TABLE:
00079 case DISPLAY_INLINE_TABLE:
00080 case DISPLAY_TABLE_ROW_GROUP:
00081 case DISPLAY_TABLE_HEADER_GROUP:
00082 case DISPLAY_TABLE_FOOTER_GROUP:
00083 case DISPLAY_TABLE_ROW:
00084 case DISPLAY_TABLE_COLUMN_GROUP:
00085 case DISPLAY_TABLE_COLUMN:
00086 case DISPLAY_TABLE_CELL:
00087 case DISPLAY_TABLE_CAPTION:
00088 box_type = BOX_TYPE_BLOCK ;
00089 break ;
00090
00091 case DISPLAY_COMPACT:
00092 box_type = BOX_TYPE_COMPACT ;
00093 break ;
00094
00095 case DISPLAY_RUN_IN:
00096 box_type = BOX_TYPE_RUN_IN ;
00097 break ;
00098
00099 case DISPLAY_INHERIT:
00100 if (a_style->parent_style)
00101 box_type =
00102 cr_box_guess_type (a_style->parent_style) ;
00103 break ;
00104
00105 default:
00106 box_type = BOX_TYPE_INLINE ;
00107 break ;
00108 }
00109
00110 return box_type ;
00111 }
00112
00113
00114 static enum CRStatus
00115 cr_box_construct (CRBox *a_this, CRStyle *a_style,
00116 gboolean a_set_default_style)
00117 {
00118 CRStyle *style = a_style ;
00119
00120 if (!style && a_set_default_style == TRUE)
00121 {
00122 style = cr_style_new () ;
00123 if (!style)
00124 {
00125 cr_utils_trace_info
00126 ("Could not create style object") ;
00127 cr_utils_trace_info ("System may be out of memory") ;
00128 return CR_ERROR ;
00129 }
00130 }
00131
00132 a_this->style = style ;
00133 if (a_this->style)
00134 cr_style_ref (a_this->style) ;
00135 a_this->type = cr_box_guess_type (a_this->style) ;
00136
00137 return CR_OK ;
00138 }
00139
00140
00141
00142 static enum CRStatus
00143 cr_box_edge_to_string (CRBoxEdge *a_this,
00144 gulong a_nb_indent,
00145 GString **a_string)
00146 {
00147 GString *result = NULL ;
00148
00149 if (*a_string)
00150 {
00151 result = *a_string ;
00152 }
00153 else
00154 {
00155 result = g_string_new (NULL) ;
00156 if (!result)
00157 {
00158 cr_utils_trace_info ("Out of memory") ;
00159 return CR_ERROR ;
00160 }
00161 }
00162
00163 cr_utils_dump_n_chars2 (' ', result,
00164 a_nb_indent) ;
00165 g_string_append_printf (result, "(%ld, %ld)\n",
00166 (long int)a_this->x,
00167 (long int) a_this->y) ;
00168 cr_utils_dump_n_chars2 (' ', result,
00169 a_nb_indent) ;
00170 g_string_append_printf (result, "width: %ld\n",
00171 (long int)a_this->width) ;
00172
00173 cr_utils_dump_n_chars2 (' ', result,
00174 a_nb_indent) ;
00175 g_string_append_printf (result, "max-width: %ld\n",
00176 (long int)a_this->max_width) ;
00177
00178 cr_utils_dump_n_chars2 (' ',
00179 result, a_nb_indent) ;
00180 g_string_append_printf (result, "height: %ld\n",
00181 (long int)a_this->height) ;
00182 cr_utils_dump_n_chars2 (' ',
00183 result, a_nb_indent) ;
00184 g_string_append_printf (result, "x_offset: %ld\n",
00185 (long int)a_this->x_offset) ;
00186 cr_utils_dump_n_chars2 (' ', result,
00187 a_nb_indent) ;
00188 g_string_append_printf (result, "y_offset: %ld\n",
00189 (long int)a_this->y_offset) ;
00190
00191 return CR_OK ;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 CRBoxData *
00204 cr_box_data_new (xmlNode *a_node)
00205 {
00206 CRBoxData *result = NULL ;
00207
00208 result = g_try_malloc (sizeof (CRBoxData)) ;
00209 if (!result)
00210 {
00211 cr_utils_trace_info ("Out of memory") ;
00212 return NULL;
00213 }
00214 memset (result, 0, sizeof (CRBoxData)) ;
00215 result->xml_node = a_node ;
00216 return result ;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 void
00226 cr_box_data_destroy (CRBoxData *a_this)
00227 {
00228 if (!a_this)
00229 return ;
00230
00231 g_free (a_this) ;
00232 }
00233
00234
00235
00236
00237
00238
00239 CRBoxContent *
00240 cr_box_content_new_from_text (guchar *a_text)
00241 {
00242 CRBoxContent *result = NULL ;
00243
00244 g_return_val_if_fail (a_text, NULL) ;
00245
00246 result = g_try_malloc (sizeof (CRBoxContent)) ;
00247 if (!result)
00248 {
00249 cr_utils_trace_info ("Out of memory") ;
00250 return NULL ;
00251 }
00252 memset (result, 0, sizeof (CRBoxContent)) ;
00253 result->u.text = g_strdup (a_text) ;
00254 result->type = TEXT_CONTENT_TYPE ;
00255 return result ;
00256 }
00257
00258
00259
00260
00261
00262
00263 void
00264 cr_box_content_destroy (CRBoxContent *a_this)
00265 {
00266 if (!a_this)
00267 return ;
00268
00269 switch (a_this->type)
00270 {
00271 case TEXT_CONTENT_TYPE:
00272 if (a_this->u.text)
00273 {
00274 g_free (a_this->u.text) ;
00275 a_this->u.text = NULL ;
00276 }
00277 break ;
00278
00279 default:
00280 cr_utils_trace_info ("Unrecognized box content type") ;
00281 cr_utils_trace_info ("This seems to be a mem leak") ;
00282 break ;
00283 }
00284
00285 g_free (a_this) ;
00286 return ;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 CRBoxModel *
00298 cr_box_model_new (void)
00299 {
00300 CRBoxModel *result = NULL ;
00301
00302 result = g_try_malloc (sizeof (CRBoxModel)) ;
00303 if (!result)
00304 {
00305 cr_utils_trace_info ("Out of memory") ;
00306 return NULL ;
00307 }
00308
00309 memset (result, 0, sizeof (CRBoxModel)) ;
00310
00311 cr_box_construct (&result->box, NULL, FALSE) ;
00312
00313 ((CRBox*)result)->type = BOX_TYPE_BOX_MODEL ;
00314 ((CRBox*)result)->box_model = result ;
00315
00316 return result ;
00317 }
00318
00319
00320 void
00321 cr_box_model_destroy (CRBoxModel *a_this)
00322 {
00323 g_return_if_fail (a_this) ;
00324
00325 cr_box_destroy (&a_this->box) ;
00326
00327 g_free (a_this) ;
00328 }
00329
00330
00331 void
00332 cr_box_model_ref (CRBoxModel *a_this)
00333 {
00334 if (a_this && a_this->ref_count)
00335 {
00336 a_this->ref_count ++ ;
00337 }
00338 }
00339
00340 gboolean
00341 cr_box_model_unref (CRBoxModel *a_this)
00342 {
00343 if (a_this && a_this->ref_count)
00344 {
00345 a_this->ref_count -- ;
00346 }
00347
00348 if (a_this && a_this->ref_count == 0)
00349 {
00350 cr_box_model_destroy (a_this) ;
00351 return TRUE ;
00352 }
00353
00354 return FALSE ;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 CRBox *
00364 cr_box_new (CRStyle *a_style, gboolean a_default_style)
00365 {
00366 CRBox *result = NULL ;
00367
00368 result = g_try_malloc (sizeof (CRBox)) ;
00369 if (!result)
00370 {
00371 cr_utils_trace_info ("Out of memory") ;
00372 goto error ;
00373 }
00374 memset (result, 0, sizeof (CRBox)) ;
00375
00376 if (cr_box_construct (result, a_style, a_default_style) == CR_OK)
00377 return result ;
00378
00379 error:
00380 if (result)
00381 {
00382 cr_box_destroy (result) ;
00383 result = NULL ;
00384 }
00385
00386 return NULL ;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395 enum CRStatus
00396 cr_box_append_child (CRBox *a_this, CRBox *a_to_append)
00397 {
00398 CRBox * cur = NULL ;
00399
00400 g_return_val_if_fail (a_this
00401 && a_this->box_model
00402 && a_to_append, CR_BAD_PARAM_ERROR) ;
00403
00404 if (!a_this->children)
00405 {
00406 a_this->children = a_to_append ;
00407 a_to_append->prev = NULL ;
00408 a_to_append->parent = a_this ;
00409 a_to_append->box_model = a_this->box_model ;
00410 return CR_OK ;
00411 }
00412
00413 for (cur = a_this->children ; cur && cur->next ; cur = cur->next)
00414 ;
00415
00416 cur->next = a_to_append ;
00417 a_to_append->prev = cur ;
00418 a_to_append->parent = a_this ;
00419 a_to_append->box_model = a_this->box_model ;
00420
00421 return CR_OK ;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431 enum CRStatus
00432 cr_box_insert_sibling (CRBox *a_prev,
00433 CRBox *a_next,
00434 CRBox *a_to_insert)
00435 {
00436 g_return_val_if_fail (a_prev && a_prev->parent
00437 && a_next && a_prev->next == a_next
00438 && a_next->parent == a_prev->parent
00439 && a_prev->box_model
00440 && a_prev->box_model == a_next->box_model
00441 && a_to_insert
00442 && a_to_insert->parent != a_prev->parent,
00443 CR_BAD_PARAM_ERROR) ;
00444
00445 a_prev->next = a_to_insert ;
00446 a_to_insert->prev = a_prev ;
00447 a_to_insert->next = a_next ;
00448 a_next->prev = a_to_insert ;
00449 a_to_insert->parent = a_prev->parent ;
00450 a_to_insert->box_model = a_prev->box_model ;
00451
00452 return CR_OK ;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 enum CRStatus
00462 cr_box_to_string (CRBox *a_this,
00463 gulong a_nb_indent,
00464 GString **a_string)
00465 {
00466 GString *result = NULL ;
00467 CRBox *cur_box = NULL ;
00468
00469 g_return_val_if_fail (a_this && a_string,
00470 CR_BAD_PARAM_ERROR) ;
00471
00472 if (*a_string)
00473 {
00474 result = *a_string ;
00475 }
00476 else
00477 {
00478 result = g_string_new (NULL) ;
00479 if (!result)
00480 {
00481 cr_utils_trace_info ("Out of memory") ;
00482 return CR_ERROR ;
00483 }
00484 *a_string = result ;
00485 }
00486
00487 for (cur_box = a_this ; cur_box ; cur_box = cur_box->next)
00488 {
00489 if (cur_box->prev || cur_box->parent)
00490 g_string_append_printf (result, "\n\n") ;
00491
00492 cr_utils_dump_n_chars2 (' ', result, a_nb_indent) ;
00493
00494 switch (cur_box->type)
00495 {
00496 case BOX_TYPE_BLOCK:
00497 g_string_append_printf (result, "BLOCK") ;
00498 break ;
00499
00500 case BOX_TYPE_ANONYMOUS_BLOCK:
00501 g_string_append_printf (result, "ANONYMOUS BLOCK") ;
00502 break ;
00503
00504 case BOX_TYPE_INLINE:
00505 g_string_append_printf (result, "INLINE") ;
00506 break ;
00507
00508 case BOX_TYPE_ANONYMOUS_INLINE:
00509 g_string_append_printf (result, "ANONYMOUS INLINE") ;
00510 break ;
00511
00512 case BOX_TYPE_COMPACT:
00513 g_string_append_printf (result, "COMPACT") ;
00514 break ;
00515
00516 case BOX_TYPE_RUN_IN:
00517 g_string_append_printf (result, "RUN IN") ;
00518 break ;
00519
00520 case BOX_TYPE_BOX_MODEL:
00521 g_string_append_printf (result, "Root") ;
00522 break ;
00523
00524 default:
00525 g_string_append_printf (result, "UNKNOWN") ;
00526 break ;
00527 }
00528
00529 g_string_append_printf (result, " box\n") ;
00530 cr_utils_dump_n_chars2 (' ', result, a_nb_indent) ;
00531 g_string_append_printf (result, "{") ;
00532
00533 if (cur_box->box_data && cur_box->box_data->xml_node)
00534 {
00535 switch (cur_box->box_data->xml_node->type)
00536 {
00537 case XML_ELEMENT_NODE:
00538 cr_utils_dump_n_chars2
00539 (' ', result, a_nb_indent) ;
00540 g_string_append_printf
00541 (result, "xml-node-name: %s\n",
00542 cur_box->box_data->xml_node->name) ;
00543 break ;
00544
00545 case XML_TEXT_NODE:
00546 cr_utils_dump_n_chars2
00547 (' ', result, a_nb_indent) ;
00548 g_string_append_printf
00549 (result, "xml-text-node\n") ;
00550 break ;
00551
00552 default:
00553 break ;
00554 }
00555 }
00556
00557 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00558 g_string_append_printf (result, "/*****%s begin*****/\n",
00559 "outer_edge") ;
00560 cr_box_edge_to_string (&cur_box->outer_edge,
00561 a_nb_indent + 2, &result) ;
00562 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00563 g_string_append_printf (result, "/*****%s end*****/\n",
00564 "outer_edge") ;
00565
00566 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00567 g_string_append_printf (result, "/*****%s begin*****/\n",
00568 "border_edge") ;
00569 cr_box_edge_to_string (&cur_box->border_edge,
00570 a_nb_indent + 2, &result) ;
00571 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00572 g_string_append_printf (result, "/*****%s end*****/\n",
00573 "border_edge") ;
00574
00575 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00576 g_string_append_printf (result, "/*****%s begin*****/\n",
00577 "padding_edge") ;
00578 cr_box_edge_to_string (&cur_box->padding_edge,
00579 a_nb_indent + 2, &result) ;
00580 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00581 g_string_append_printf (result, "/*****%s end*****/\n",
00582 "padding_edge") ;
00583
00584 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00585 g_string_append_printf (result, "/*****%s begin*****/\n",
00586 "inner_edge") ;
00587 cr_box_edge_to_string (&cur_box->inner_edge,
00588 a_nb_indent + 2, &result) ;
00589 cr_utils_dump_n_chars2 (' ', result, a_nb_indent + 2) ;
00590 g_string_append_printf (result, "/*****%s end*****/\n",
00591 "inner_edge") ;
00592
00593 if (cur_box->children)
00594 {
00595 g_string_append_printf (result, "\n") ;
00596 cr_box_to_string (cur_box->children,
00597 a_nb_indent + 2, &result) ;
00598 }
00599
00600 g_string_append_printf (result, "\n") ;
00601 cr_utils_dump_n_chars2 (' ', result, a_nb_indent) ;
00602 g_string_append_printf (result, "}\n") ;
00603 }
00604
00605 return CR_OK ;
00606 }
00607
00608 enum CRStatus
00609 cr_box_dump_to_file (CRBox *a_this,
00610 gulong a_nb_indent,
00611 FILE *a_filep)
00612 {
00613 GString *str = NULL ;
00614 enum CRStatus status = CR_OK ;
00615
00616 g_return_val_if_fail (a_this && a_filep,
00617 CR_BAD_PARAM_ERROR) ;
00618
00619 status = cr_box_to_string (a_this, a_nb_indent, &str) ;
00620
00621 if (status != CR_OK)
00622 {
00623 cr_utils_trace_info ("An error occured "
00624 "during in memory serialisation") ;
00625 goto cleanup ;
00626 }
00627
00628 if (!str || !str->str)
00629 {
00630 cr_utils_trace_info ("Error: Box could not be serialised") ;
00631 goto cleanup ;
00632 }
00633
00634 if (!fwrite (str->str, 1, str->len, a_filep))
00635 {
00636 cr_utils_trace_info ("An error occured during"
00637 "serialisation into file") ;
00638 status = CR_ERROR ;
00639 goto cleanup ;
00640 }
00641
00642 status = CR_OK ;
00643
00644 cleanup:
00645
00646 if (str)
00647 {
00648 g_string_free (str, TRUE) ;
00649 str = NULL ;
00650 }
00651 return status ;
00652 }
00653
00654
00655
00656
00657
00658 enum CRStatus
00659 cr_box_ref (CRBox *a_this)
00660 {
00661 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
00662
00663 a_this->ref_count ++ ;
00664
00665 return TRUE ;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 gboolean
00677 cr_box_unref (CRBox *a_this)
00678 {
00679 g_return_val_if_fail (a_this, FALSE) ;
00680
00681 if (a_this->ref_count)
00682 a_this->ref_count -- ;
00683
00684 if (a_this->ref_count == 0)
00685 {
00686 cr_box_destroy (a_this) ;
00687 return TRUE ;
00688 }
00689
00690 return FALSE ;
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700 void
00701 cr_box_destroy (CRBox *a_this)
00702
00703 {
00704 CRBox *cur_box = NULL ;
00705
00706 g_return_if_fail (a_this) ;
00707
00708 for (cur_box = a_this; cur_box && cur_box->next ;
00709 cur_box = cur_box->next) ;
00710
00711 for (; cur_box ; cur_box = cur_box->prev)
00712 {
00713 if (cur_box->content)
00714 {
00715 cr_box_content_destroy (cur_box->content) ;
00716 cur_box->content = NULL ;
00717 }
00718
00719 if (cur_box->style)
00720 {
00721 cr_style_unref (cur_box->style) ;
00722 cur_box->style = NULL ;
00723 }
00724
00725 if (cur_box->next)
00726 {
00727 g_free (cur_box->next) ;
00728 cur_box->next = NULL ;
00729 }
00730
00731 if (cur_box->children)
00732 {
00733 cr_box_destroy (cur_box->children) ;
00734 g_free (cur_box->children) ;
00735 cur_box->children = NULL ;
00736 }
00737 }
00738 }
00739