Esempio n. 1
0
static void svg_font_on_load(GF_Node *handler, GF_DOM_Event *event, GF_Node *observer)
{
	GF_Compositor *compositor;
	GF_Font *font;
	assert(event->currentTarget->ptr_type==GF_DOM_EVENT_NODE);
	assert(gf_node_get_tag((GF_Node*)event->currentTarget->ptr)==TAG_SVG_font);
	font = gf_node_get_private((GF_Node*)event->currentTarget->ptr);
	font->not_loaded = 0;
	compositor = (GF_Compositor *)gf_node_get_private((GF_Node *)handler);

	/*brute-force signaling that all fonts have changed and texts must be recomputed*/
	compositor->reset_fonts = 1;
	gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
	compositor->fonts_pending--;
}
Esempio n. 2
0
void compositor_svg_video_modified(GF_Compositor *compositor, GF_Node *node)
{
	/*if href has been modified, stop the video (and associated audio if any) right away - we cannot wait for next traversal to
	process this as the video could be in a hidden subtree not traversed*/
	if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
		SVG_video_stack *st = (SVG_video_stack *)gf_node_get_private(node);
		/*WARNING - stack may be NULL at this point when inserting the video from script*/
		if (st && st->txh.is_open) {
			if (st->audio) {
				svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, st->audio, st->txh.owner);
				gf_node_unregister(st->audio, NULL);
				st->audio = NULL;
			}
			/*reset cached URL to avoid reopening the resource in the smil timing callback*/
			gf_sg_vrml_mf_reset(&st->txurl, GF_SG_VRML_MFURL);
			gf_sc_texture_stop(&st->txh);
		}
	}
	gf_node_dirty_set(node, 0, GF_FALSE);
	/*and force a redraw of next frame*/
	gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
}
Esempio n. 3
0
void svg_traverse_domtext(GF_Node *node, SVGAllAttributes *atts, GF_TraverseState *tr_state, GF_List *spans, GF_Node *anchor_node)
{
	GF_DOMText *dom_text = (GF_DOMText *)node;
	Fixed x, y;
	u32 i;
	Fixed x_anchor, *ptr;
	GF_Font *font;
	Fixed block_width;
	GF_FontManager *fm;
	GF_TextSpan *span;

	if (!dom_text->textContent) return;

	if (tr_state->in_svg_text_area) {
		svg_traverse_dom_text_area(node, atts, tr_state, spans);
		return;
	}

	fm = tr_state->visual->compositor->font_manager;
	if (!fm) return;

	font = svg_set_font(tr_state, fm);
	if (!font) return;
	if (font->not_loaded) {
		tr_state->visual->compositor->reset_fonts = GF_TRUE;
		tr_state->visual->compositor->skip_flush = 1;
		gf_sc_next_frame_state(tr_state->visual->compositor, GF_SC_DRAW_FRAME);
		return;
	}


	span = svg_get_text_span(fm, font, tr_state->svg_props->font_size->value, (tr_state->count_x>1), (tr_state->count_y>1), tr_state->count_rotate, atts, dom_text->textContent, atts->xml_lang ? *atts->xml_lang : NULL, tr_state);
	if (!span) return;

	i=0;
	/*
	if character position is given in (x, y) attributes, use it.
	Otherwise add text at tr_state->text_end_x.
	*/
	while ((i<span->nb_glyphs)
	        && ( (tr_state->count_x>1) || (tr_state->count_y>1) )
	      ) {
		//get x and y positions
		if (tr_state->count_x==0) {
			x = tr_state->text_end_x;
		} else {
			SVG_Coordinate *xc = (SVG_Coordinate *) gf_list_get(*tr_state->text_x, tr_state->chunk_index);
			x = xc->value;
			(tr_state->count_x)--;
		}
		if (tr_state->count_y==0) {
			y = tr_state->text_end_y;
		} else {
			SVG_Coordinate *yc = (SVG_Coordinate *) gf_list_get(*tr_state->text_y, tr_state->chunk_index);
			y = yc->value;
			(tr_state->count_y)--;
		}


		/*apply x-anchor*/
		ptr = (Fixed *)gf_list_get(tr_state->x_anchors, tr_state->chunk_index);
		x_anchor = ptr ? *ptr : 0;
		if (span->dx) span->dx[i] = x_anchor + x;
		else if (!i) span->off_x = x_anchor + x;
		if (span->dy) span->dy[i] = y;
		else span->off_y = y;

		if (tr_state->count_rotate) {
			SVG_Coordinate *rc = (SVG_Coordinate *) gf_list_get(*tr_state->text_rotate, tr_state->idx_rotate);
			span->rot[i] = gf_mulfix(GF_PI/180, rc->value);
			if (tr_state->idx_rotate+1<tr_state->count_rotate) tr_state->idx_rotate++;
		}

		/*update last glyph position*/
		block_width = (span->glyphs[i] ? span->glyphs[i]->horiz_advance : font->max_advance_h) * span->font_scale;
		tr_state->text_end_x = x+block_width;
		tr_state->text_end_y = y;
		(tr_state->chunk_index)++;
		i++;
	}

	/* no more positions, add remaining glyphs as a block*/
	if (i<span->nb_glyphs) {
		Fixed offset;
		if ((tr_state->count_x==1) && tr_state->text_x) {
			SVG_Coordinate *xc = (SVG_Coordinate *) gf_list_get(*tr_state->text_x, tr_state->chunk_index);
			tr_state->text_end_x = xc->value;
			(tr_state->count_x)--;
		}
		if ((tr_state->count_y==1) && tr_state->text_y) {
			SVG_Coordinate *yc = (SVG_Coordinate *) gf_list_get(*tr_state->text_y, tr_state->chunk_index);
			tr_state->text_end_y = yc->value;
			(tr_state->count_y)--;
		}

		x = tr_state->text_end_x;
		y = tr_state->text_end_y;

		/*apply x anchor*/
		ptr = (Fixed *)gf_list_get(tr_state->x_anchors, tr_state->chunk_index);
		x_anchor = ptr ? *ptr : 0;

		offset = x_anchor + x - (span->dx ? span->dx[i] : span->off_x);

		if (!span->dx && (tr_state->text_x || x_anchor)) span->off_x = x_anchor + x;
		if (!span->dy && tr_state->text_y) span->off_y = y;

		block_width = 0;
		while (i<span->nb_glyphs) {

			if (span->rot) {
				SVG_Coordinate *rc = (SVG_Coordinate *) gf_list_get(*tr_state->text_rotate, tr_state->idx_rotate);
				span->rot[i] = gf_mulfix(GF_PI/180, rc->value);
				if (tr_state->idx_rotate+1<tr_state->count_rotate) tr_state->idx_rotate++;
			}
			if (span->dx) span->dx[i] = offset + block_width;
			if (span->dy) span->dy[i] = y;
			block_width += (span->glyphs[i] ? span->glyphs[i]->horiz_advance : font->max_advance_h) * span->font_scale;

			i++;
		}
		tr_state->text_end_x += block_width;
	}

	/*add span path to list of spans*/
	gf_list_add(spans, span);
	span->anchor = anchor_node;
}
Esempio n. 4
0
GF_EXPORT
void gf_sc_invalidate(GF_Compositor *compositor, GF_Node *byObj)
{

	if (!byObj) {
		gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
		return;
	}
	switch (gf_node_get_tag(byObj)) {
#ifndef GPAC_DISABLE_VRML
	case TAG_MPEG4_AnimationStream: compositor_animationstream_modified(byObj); break;
	case TAG_MPEG4_AudioBuffer: compositor_audiobuffer_modified(byObj); break;
	case TAG_MPEG4_AudioSource: compositor_audiosource_modified(byObj); break;
	case TAG_MPEG4_AudioClip:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_AudioClip:
#endif
		compositor_audioclip_modified(byObj); break;
	case TAG_MPEG4_TimeSensor:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_TimeSensor:
#endif
		compositor_timesensor_modified(byObj); break;
	case TAG_MPEG4_ImageTexture:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_ImageTexture:
#endif
	case TAG_MPEG4_CacheTexture:
		compositor_imagetexture_modified(byObj); break;

	case TAG_MPEG4_MovieTexture:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_MovieTexture:
#endif
		compositor_movietexture_modified(byObj); break;

	case TAG_MPEG4_Background2D: compositor_background2d_modified(byObj); break;
#ifndef GPAC_DISABLE_3D
	case TAG_MPEG4_Background:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Background:
#endif
		compositor_background_modified(byObj); break;
#endif
	case TAG_MPEG4_Layout: compositor_layout_modified(compositor, byObj); break;
	case TAG_MPEG4_EnvironmentTest: compositor_envtest_modified(byObj); break;

#endif /*GPAC_DISABLE_VRML*/

#ifndef GPAC_DISABLE_SVG
	case TAG_SVG_video: compositor_svg_video_modified(compositor, byObj); break;
#endif /*GPAC_DISABLE_SVG*/

	default:
		/*for all nodes, invalidate parent graph - note we do that for sensors as well to force recomputing
		sensor list cached at grouping node level*/
		gf_node_dirty_set(byObj, 0, 1);
		gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
		break;
	}
}
void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state)
{
	Fixed sS, sT;
	u32 tx_tile;
	GF_STENCIL tx_raster;
	GF_Matrix2D mx_texture;
	GF_Rect orig_rc;
	GF_Raster2D *raster;

	if (! visual->CheckAttached(visual) ) return;

	raster = visual->compositor->rasterizer;

	if (!txh) txh = ctx->aspect.fill_texture;
	if (!txh) return;
	if (!txh->tx_io) {
		gf_node_dirty_set(txh->owner, 0, 1);

		txh->needs_refresh=1;
		return;
	}


	/*this is gradient draw*/
	if (txh->compute_gradient_matrix) {
		visual_2d_draw_gradient(visual, path, txh, ctx, tr_state, ext_mx, orig_bounds);
		return;
	}


#ifndef GPAC_DISABLE_3D
	if (visual->compositor->hybrid_opengl) {
		visual_2d_texture_path_opengl_auto(visual, path, txh, ctx, orig_bounds, ext_mx, tr_state);
		return;
	}
#endif

	if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
		GF_Window src, dst;
		visual_2d_fill_path(visual, ctx, NULL, tr_state, 0);

		/*if texture not ready, update the size before computing output rectangles */
		if (!txh->width || !txh->height) {
			gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
			/*in case the node is an MPEG-4 bitmap, force stack rebuild at next frame */
			gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1);
		}

		if (compositor_texture_rectangles(visual, txh, &ctx->bi->clip, &ctx->bi->unclip, &src, &dst, NULL, NULL)) {
			if (txh->stream && gf_mo_set_position(txh->stream, &src, &dst)) {
				gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
				/*force dirty flag to get called again*/
				gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1);
				gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME);
			}
		}



		return;
	}

	if (!gf_sc_texture_push_image(txh, 0, 1)) return;
	tx_raster = gf_sc_texture_get_stencil(txh);

	/*setup quality even for background (since quality concerns images)*/
	visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);

	/*get original bounds*/
	if (orig_bounds) {
		orig_rc = *orig_bounds;
	} else {
		gf_path_get_bounds(path, &orig_rc);
	}

	/*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
	sS = orig_rc.width / txh->width;
	sT = orig_rc.height / txh->height;

	gf_mx2d_init(mx_texture);
	gf_mx2d_add_scale(&mx_texture, sS, sT);

#ifndef GPAC_DISABLE_VRML
	/*apply texture transform*/
	if (ctx->flags & CTX_HAS_APPEARANCE) {
		GF_Matrix2D tex_trans;
		visual_2d_get_texture_transform(ctx->appear, txh, &tex_trans, (txh == ctx->aspect.fill_texture) ? 0 : 1, txh->width * sS, txh->height * sT);
		gf_mx2d_add_matrix(&mx_texture, &tex_trans);
	}
#endif

	/*move to bottom-left corner of bounds */
	gf_mx2d_add_translation(&mx_texture, (orig_rc.x), (orig_rc.y - orig_rc.height));

	if (ext_mx) gf_mx2d_add_matrix(&mx_texture, ext_mx);

	/*move to final coordinate system (except background which is built directly in final coord system)*/
	if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&mx_texture, &ctx->transform);

	/*set path transform*/
	raster->stencil_set_matrix(tx_raster, &mx_texture);


	tx_tile = 0;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T;
	if (ctx->flags & CTX_FLIPED_COORDS)
		tx_tile |= GF_TEXTURE_FLIP;
	raster->stencil_set_tiling(tx_raster, (GF_TextureTiling) tx_tile);

	if (!(ctx->flags & CTX_IS_BACKGROUND) ) {
		u8 a = GF_COL_A(ctx->aspect.fill_color);
		if (!a) a = GF_COL_A(ctx->aspect.line_color);
		/*texture alpha scale is the original material transparency, NOT the one after color transform*/
		raster->stencil_set_alpha(tx_raster, a );
		raster->stencil_set_color_matrix(tx_raster, ctx->col_mat);

		raster->surface_set_matrix(visual->raster_surface, &ctx->transform);
	} else {
		raster->surface_set_matrix(visual->raster_surface, NULL);
	}
	txh->flags |= GF_SR_TEXTURE_USED;

	/*push path & draw*/
	raster->surface_set_path(visual->raster_surface, path);
	visual_2d_fill_path(visual, ctx, tx_raster, tr_state, 0);
	raster->surface_set_path(visual->raster_surface, NULL);



	ctx->flags |= CTX_PATH_FILLED;
}