static int node_count_siblings_check(dom_node *node, bool check_name, dom_string *name) { dom_node_type type; int ret = 0; dom_exception exc; if (node == NULL) return 0; exc = dom_node_get_node_type(node, &type); if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE)) { return 0; } if (check_name) { dom_string *node_name = NULL; exc = dom_node_get_node_name(node, &node_name); if ((exc == DOM_NO_ERR) && (node_name != NULL)) { if (dom_string_caseless_isequal(name, node_name)) { ret = 1; } dom_string_unref(node_name); } } else { ret = 1; } return ret; }
/** * Callback to determine if a node is the root node of the document. * * \param pw HTML document * \param node DOM node * \param match Pointer to location to receive result * \return CSS_OK. * * \post \a match will contain true if the node matches and false otherwise. */ css_error node_is_root(void *pw, void *node, bool *match) { dom_node *n = node; dom_node *parent; dom_node_type type; dom_exception err; err = dom_node_get_parent_node(n, &parent); if (err != DOM_NO_ERR) { return CSS_NOMEM; } if (parent != NULL) { err = dom_node_get_node_type(parent, &type); dom_node_unref(parent); if (err != DOM_NO_ERR) return CSS_NOMEM; if (type != DOM_DOCUMENT_NODE) { *match = false; return CSS_OK; } } *match = true; return CSS_OK; }
/** * Callback to find a named sibling node. * * \param pw HTML document * \param node DOM node * \param qname Node name to search for * \param sibling Pointer to location to receive sibling * \return CSS_OK. * * \post \a sibling will contain the result, or NULL if there is no match */ css_error named_sibling_node(void *pw, void *node, const css_qname *qname, void **sibling) { dom_node *n = node; dom_node *prev; dom_exception err; *sibling = NULL; /* Find sibling element */ err = dom_node_get_previous_sibling(n, &n); if (err != DOM_NO_ERR) return CSS_OK; while (n != NULL) { dom_node_type type; err = dom_node_get_node_type(n, &type); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_OK; } if (type == DOM_ELEMENT_NODE) break; err = dom_node_get_previous_sibling(n, &prev); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_OK; } dom_node_unref(n); n = prev; } if (n != NULL) { dom_string *name; err = dom_node_get_node_name(n, &name); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_OK; } dom_node_unref(n); if (dom_string_caseless_lwc_isequal(name, qname->name)) { *sibling = n; } dom_string_unref(name); } return CSS_OK; }
/** * Callback to retrieve the preceding sibling of a node. * * \param pw HTML document * \param node DOM node * \param sibling Pointer to location to receive sibling * \return CSS_OK. * * \post \a sibling will contain the result, or NULL if there is no match */ css_error sibling_node(void *pw, void *node, void **sibling) { dom_node *n = node; dom_node *prev; dom_exception err; *sibling = NULL; /* Find sibling element */ err = dom_node_get_previous_sibling(n, &n); if (err != DOM_NO_ERR) return CSS_OK; while (n != NULL) { dom_node_type type; err = dom_node_get_node_type(n, &type); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_OK; } if (type == DOM_ELEMENT_NODE) break; err = dom_node_get_previous_sibling(n, &prev); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_OK; } dom_node_unref(n); n = prev; } if (n != NULL) { /** \todo Sort out reference counting */ dom_node_unref(n); *sibling = n; } return CSS_OK; }
static hubbub_error get_parent(void *parser, void *node, bool element_only, void **result) { dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; dom_exception err; struct dom_node *parent; dom_node_type type = DOM_NODE_TYPE_COUNT; err = dom_node_get_parent_node((struct dom_node *) node, &parent); if (err != DOM_NO_ERR) { dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, "Error in dom_node_get_parent"); return HUBBUB_UNKNOWN; } if (element_only == false) { *result = parent; return HUBBUB_OK; } err = dom_node_get_node_type(parent, &type); if (err != DOM_NO_ERR) { dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, "Error in dom_node_get_type"); goto fail; } if (type == DOM_ELEMENT_NODE) { *result = parent; return HUBBUB_OK; } else { *result = NULL; dom_node_unref(parent); return HUBBUB_OK; } return HUBBUB_OK; fail: dom_node_unref(parent); return HUBBUB_UNKNOWN; }
/** * Callback to determine if a node is empty. * * \param pw HTML document * \param node DOM node * \param match Pointer to location to receive result * \return CSS_OK. * * \post \a match will contain true if the node is empty and false otherwise. */ css_error node_is_empty(void *pw, void *node, bool *match) { dom_node *n = node, *next; dom_exception err; *match = true; err = dom_node_get_first_child(n, &n); if (err != DOM_NO_ERR) { return CSS_BADPARM; } while (n != NULL) { dom_node_type ntype; err = dom_node_get_node_type(n, &ntype); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_BADPARM; } if (ntype == DOM_ELEMENT_NODE || ntype == DOM_TEXT_NODE) { *match = false; dom_node_unref(n); break; } err = dom_node_get_next_sibling(n, &next); if (err != DOM_NO_ERR) { dom_node_unref(n); return CSS_BADPARM; } dom_node_unref(n); n = next; } return CSS_OK; }
svgtiny_code svgtiny_parse_svg(dom_element *svg, struct svgtiny_parse_state state) { float x, y, width, height; dom_string *view_box; dom_element *child; dom_exception exc; svgtiny_setup_state_local(&state); svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(svg, &state); svgtiny_parse_font_attributes(svg, &state); exc = dom_element_get_attribute(svg, state.interned_viewBox, &view_box); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (view_box) { char *s = strndup(dom_string_data(view_box), dom_string_byte_length(view_box)); float min_x, min_y, vwidth, vheight; if (sscanf(s, "%f,%f,%f,%f", &min_x, &min_y, &vwidth, &vheight) == 4 || sscanf(s, "%f %f %f %f", &min_x, &min_y, &vwidth, &vheight) == 4) { state.ctm.a = (float) state.viewport_width / vwidth; state.ctm.d = (float) state.viewport_height / vheight; state.ctm.e += -min_x * state.ctm.a; state.ctm.f += -min_y * state.ctm.d; } free(s); dom_string_unref(view_box); } svgtiny_parse_transform_attributes(svg, &state); exc = dom_node_get_first_child(svg, (dom_node **) (void *) &child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } while (child != NULL) { dom_element *next; dom_node_type nodetype; svgtiny_code code = svgtiny_OK; exc = dom_node_get_node_type(child, &nodetype); if (exc != DOM_NO_ERR) { dom_node_unref(child); return svgtiny_LIBDOM_ERROR; } if (nodetype == DOM_ELEMENT_NODE) { dom_string *nodename; exc = dom_node_get_node_name(child, &nodename); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (dom_string_caseless_isequal(state.interned_svg, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_g, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_a, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_path, nodename)) code = svgtiny_parse_path(child, state); else if (dom_string_caseless_isequal(state.interned_rect, nodename)) code = svgtiny_parse_rect(child, state); else if (dom_string_caseless_isequal(state.interned_circle, nodename)) code = svgtiny_parse_circle(child, state); else if (dom_string_caseless_isequal(state.interned_ellipse, nodename)) code = svgtiny_parse_ellipse(child, state); else if (dom_string_caseless_isequal(state.interned_line, nodename)) code = svgtiny_parse_line(child, state); else if (dom_string_caseless_isequal(state.interned_polyline, nodename)) code = svgtiny_parse_poly(child, state, false); else if (dom_string_caseless_isequal(state.interned_polygon, nodename)) code = svgtiny_parse_poly(child, state, true); else if (dom_string_caseless_isequal(state.interned_text, nodename)) code = svgtiny_parse_text(child, state); dom_string_unref(nodename); } if (code != svgtiny_OK) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return code; } exc = dom_node_get_next_sibling(child, (dom_node **) (void *) &next); dom_node_unref(child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } child = next; } svgtiny_cleanup_state_local(&state); return svgtiny_OK; }
svgtiny_code svgtiny_parse_text(dom_element *text, struct svgtiny_parse_state state) { float x, y, width, height; float px, py; dom_node *child; dom_exception exc; svgtiny_setup_state_local(&state); svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); svgtiny_parse_font_attributes(text, &state); svgtiny_parse_transform_attributes(text, &state); px = state.ctm.a * x + state.ctm.c * y + state.ctm.e; py = state.ctm.b * x + state.ctm.d * y + state.ctm.f; /* state.ctm.e = px - state.origin_x; */ /* state.ctm.f = py - state.origin_y; */ /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ exc = dom_node_get_first_child(text, &child); if (exc != DOM_NO_ERR) { return svgtiny_LIBDOM_ERROR; svgtiny_cleanup_state_local(&state); } while (child != NULL) { dom_node *next; dom_node_type nodetype; svgtiny_code code = svgtiny_OK; exc = dom_node_get_node_type(child, &nodetype); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (nodetype == DOM_ELEMENT_NODE) { dom_string *nodename; exc = dom_node_get_node_name(child, &nodename); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (dom_string_caseless_isequal(nodename, state.interned_tspan)) code = svgtiny_parse_text((dom_element *)child, state); dom_string_unref(nodename); } else if (nodetype == DOM_TEXT_NODE) { struct svgtiny_shape *shape = svgtiny_add_shape(&state); dom_string *content; if (shape == NULL) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_OUT_OF_MEMORY; } exc = dom_text_get_whole_text(child, &content); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (content != NULL) { shape->text = strndup(dom_string_data(content), dom_string_byte_length(content)); dom_string_unref(content); } else { shape->text = strdup(""); } shape->text_x = px; shape->text_y = py; state.diagram->shape_count++; } if (code != svgtiny_OK) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return code; } exc = dom_node_get_next_sibling(child, &next); dom_node_unref(child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } child = next; } svgtiny_cleanup_state_local(&state); return svgtiny_OK; }
static bool save_complete_node_handler(dom_node *node, save_complete_event_type event_type, void *ctxin) { save_complete_ctx *ctx = ctxin; dom_node_type type; dom_exception error; utf8_convert_ret ret; error = dom_node_get_node_type(node, &type); if (error != DOM_NO_ERR) return false; if (type == DOM_ELEMENT_NODE) { return save_complete_handle_element(ctx, node, event_type); } else if (type == DOM_TEXT_NODE || type == DOM_COMMENT_NODE) { if (event_type != EVENT_ENTER) return true; if (ctx->iter_state != STATE_IN_STYLE) { /* Emit text content */ dom_string *text; const char *text_data; size_t text_len; error = dom_characterdata_get_data(node, &text); if (error != DOM_NO_ERR) { return false; } if (type == DOM_COMMENT_NODE) fwrite("<!--", 1, sizeof("<!--") - 1, ctx->fp); if (text != NULL) { char *escaped; text_data = dom_string_data(text); text_len = dom_string_byte_length(text); ret = utf8_to_html(text_data, "UTF-8", text_len, &escaped); if (ret != UTF8_CONVERT_OK) return false; fwrite(escaped, sizeof(*escaped), strlen(escaped), ctx->fp); free(escaped); dom_string_unref(text); } if (type == DOM_COMMENT_NODE) { fwrite("-->", 1, sizeof("-->") - 1, ctx->fp); } } } else if (type == DOM_DOCUMENT_TYPE_NODE) { dom_string *name; const char *name_data; size_t name_len; if (event_type != EVENT_ENTER) return true; error = dom_document_type_get_name(node, &name); if (error != DOM_NO_ERR) return false; if (name == NULL) return true; name_data = dom_string_data(name); name_len = dom_string_byte_length(name); fputs("<!DOCTYPE ", ctx->fp); fwrite(name_data, sizeof(*name_data), name_len, ctx->fp); dom_string_unref(name); error = dom_document_type_get_public_id(node, &name); if (error != DOM_NO_ERR) return false; if (name != NULL) { name_data = dom_string_data(name); name_len = dom_string_byte_length(name); if (name_len > 0) fprintf(ctx->fp, " PUBLIC \"%.*s\"", (int) name_len, name_data); dom_string_unref(name); } error = dom_document_type_get_system_id(node, &name); if (error != DOM_NO_ERR) return false; if (name != NULL) { name_data = dom_string_data(name); name_len = dom_string_byte_length(name); if (name_len > 0) fprintf(ctx->fp, " \"%.*s\"", (int) name_len, name_data); dom_string_unref(name); } fputc('>', ctx->fp); } else if (type == DOM_DOCUMENT_NODE) { /* Do nothing */ } else { LOG(("Unhandled node type: %d", type)); } return true; }