rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
{
    RsvgNodeChars *self;

    if (!ch || !len)
        return;

    if (ctx->priv->currentnode) {
        RsvgNodeType type = RSVG_NODE_TYPE (ctx->priv->currentnode);
        if (type == RSVG_NODE_TYPE_TSPAN ||
            type == RSVG_NODE_TYPE_TEXT) {
            guint i;

            /* find the last CHARS node in the text or tspan node, so that we
               can coalesce the text, and thus avoid screwing up the Pango layouts */
            self = NULL;
            for (i = 0; i < ctx->priv->currentnode->children->len; i++) {
                RsvgNode *node = g_ptr_array_index (ctx->priv->currentnode->children, i);
                if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
                    self = (RsvgNodeChars*)node;
                }
                else if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_TSPAN) {
                    self = NULL;
                }
            }

            if (self != NULL) {
                if (!g_utf8_validate ((char *) ch, len, NULL)) {
                    char *utf8;
                    utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
                    g_string_append (self->contents, utf8);
                    g_free (utf8);
                } else {
                    g_string_append_len (self->contents, (char *)ch, len);
                }

                return;
            }
        }
    }

    self = rsvg_new_node_chars ((char *) ch, len);

    rsvg_defs_register_memory (ctx->priv->defs, (RsvgNode *) self);
    if (ctx->priv->currentnode)
        rsvg_node_group_pack (ctx->priv->currentnode, (RsvgNode *) self);
}
rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
{
    RsvgNodeChars *self;

    if (!ch || !len)
        return;

    if (ctx->priv->currentnode) {
        RsvgNodeType type = RSVG_NODE_TYPE (ctx->priv->currentnode);
        if (type == RSVG_NODE_TYPE_TSPAN ||
            type == RSVG_NODE_TYPE_TEXT) {
            guint i;

             
            self = NULL;
            for (i = 0; i < ctx->priv->currentnode->children->len; i++) {
                RsvgNode *node = g_ptr_array_index (ctx->priv->currentnode->children, i);
                if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
                    self = (RsvgNodeChars*)node;
                }
                else if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_TSPAN) {
                    self = NULL;
                }
            }

            if (self != NULL) {
                if (!g_utf8_validate ((char *) ch, len, NULL)) {
                    char *utf8;
                    utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
                    g_string_append (self->contents, utf8);
                    g_free (utf8);
                } else {
                    g_string_append_len (self->contents, (char *)ch, len);
                }

                return;
            }
        }
    }

    self = rsvg_new_node_chars ((char *) ch, len);

    rsvg_defs_register_memory (ctx->priv->defs, (RsvgNode *) self);
    if (ctx->priv->currentnode)
        rsvg_node_group_pack (ctx->priv->currentnode, (RsvgNode *) self);
}