This source file includes following definitions.
- Bitmap_BuildGraph
- draw_bitmap_3d
- draw_bitmap_2d
- TraverseBitmap
- compositor_init_bitmap
#include "nodes_stacks.h"
#include "visual_manager.h"
#include "texturing.h"
#ifndef GPAC_DISABLE_VRML
typedef struct _bitmap_stack
{
Drawable *graph;
SFVec2f size, scale;
u32 prev_tx_w, prev_tx_h;
GF_Rect rc;
} BitmapStack;
static void Bitmap_BuildGraph(GF_Node *node, BitmapStack *st, GF_TraverseState *tr_state, GF_Rect *out_rc, Bool notify_changes)
{
GF_TextureHandler *txh;
Fixed sx, sy;
SFVec2f size;
M_Bitmap *bmp = (M_Bitmap *)node;
if (!tr_state->appear) return;
if (! ((M_Appearance *)tr_state->appear)->texture) return;
txh = gf_sc_texture_get_handler( ((M_Appearance *)tr_state->appear)->texture );
if (!txh || !txh->width || !txh->height
#ifndef GPAC_DISABLE_3D
|| (tr_state->visual->type_3d && !txh->tx_io)
#endif
) {
if (notify_changes) gf_node_dirty_set(node, 0, 1);
return;
}
if ((st->scale.x==bmp->scale.x) && (st->scale.y==bmp->scale.y) && (st->prev_tx_w == txh->width) && (st->prev_tx_h == txh->height)) {
*out_rc = st->rc;
gf_node_dirty_clear(node, 0);
return;
}
st->prev_tx_w = txh->width;
st->prev_tx_h = txh->height;
sx = bmp->scale.x;
if (sx<0) sx = FIX_ONE;
sy = bmp->scale.y;
if (sy<0) sy = FIX_ONE;
st->scale = bmp->scale;
compositor_adjust_scale(txh->owner, &sx, &sy);
size.x = gf_mulfix(INT2FIX(txh->width),sx);
size.y = gf_mulfix(INT2FIX(txh->height),sy);
if (txh->pixel_ar) {
u32 n = (txh->pixel_ar>>16) & 0xFFFF;
u32 d = (txh->pixel_ar) & 0xFFFF;
size.x = gf_mulfix(INT2FIX( (txh->width * n) / d),sx);
}
if (!tr_state->pixel_metrics) {
size.x = gf_divfix(size.x, tr_state->min_hsize);
size.y = gf_divfix(size.y, tr_state->min_hsize);
}
*out_rc = st->rc = gf_rect_center(size.x, size.y);
gf_node_dirty_clear(node, 0);
if ((st->size.x==size.x) && (st->size.y==size.y)) return;
st->size = size;
if (notify_changes) gf_node_dirty_set(node, 0, 1);
drawable_reset_path(st->graph);
gf_path_add_rect_center(st->graph->path, 0, 0, st->size.x, st->size.y);
}
#ifndef GPAC_DISABLE_3D
static void draw_bitmap_3d(GF_Node *node, GF_TraverseState *tr_state)
{
GF_Node *appear;
DrawAspect2D asp;
GF_ColorKey keyColor;
BitmapStack *st = (BitmapStack *)gf_node_get_private(node);
M_Bitmap *bmp = (M_Bitmap *)node;
Bitmap_BuildGraph(node, st, tr_state, &tr_state->bounds, 0);
memset(&asp, 0, sizeof(DrawAspect2D));
drawable_get_aspect_2d_mpeg4(node, &asp, tr_state);
appear = tr_state->override_appearance ? tr_state->override_appearance : tr_state->appear;
if (appear) {
M_Appearance *app = (M_Appearance *)appear;
if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
M_MaterialKey*mk = (M_MaterialKey*)app->material;
if (mk->isKeyed) {
keyColor.r = FIX2INT(mk->keyColor.red * 255);
keyColor.g = FIX2INT(mk->keyColor.green * 255);
keyColor.b = FIX2INT(mk->keyColor.blue * 255);
keyColor.alpha = FIX2INT( (FIX_ONE - mk->transparency) * 255);
keyColor.low = FIX2INT(mk->lowThreshold * 255);
keyColor.high = FIX2INT(mk->highThreshold * 255);
tr_state->col_key = &keyColor;
}
}
}
compositor_3d_draw_bitmap(st->graph, &asp, tr_state, st->size.x, st->size.y, bmp->scale.x, bmp->scale.y);
tr_state->col_key = NULL;
}
#endif
static void draw_bitmap_2d(GF_Node *node, GF_TraverseState *tr_state)
{
GF_ColorKey keyColor;
DrawableContext *ctx = tr_state->ctx;
BitmapStack *st = (BitmapStack *) gf_node_get_private(node);
ctx->transform.m[1] = ctx->transform.m[3] = 0;
if (ctx->appear) {
M_Appearance *app = (M_Appearance *)ctx->appear;
if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
M_MaterialKey*mk = (M_MaterialKey*)app->material;
if (mk->isKeyed) {
keyColor.r = FIX2INT(mk->keyColor.red * 255);
keyColor.g = FIX2INT(mk->keyColor.green * 255);
keyColor.b = FIX2INT(mk->keyColor.blue * 255);
keyColor.alpha = FIX2INT( (FIX_ONE - mk->transparency) * 255);
keyColor.low = FIX2INT(mk->lowThreshold * 255);
keyColor.high = FIX2INT(mk->highThreshold * 255);
tr_state->col_key = &keyColor;
}
}
}
if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx)) {
GF_Matrix2D _mat;
GF_Rect rc = gf_rect_center(ctx->bi->unclip.width, ctx->bi->unclip.height);
gf_mx2d_copy(_mat, ctx->transform);
gf_mx2d_inverse(&_mat);
gf_mx2d_apply_rect(&_mat, &rc);
drawable_reset_path(st->graph);
gf_path_add_rect_center(st->graph->path, 0, 0, rc.width, rc.height);
ctx->flags |= CTX_NO_ANTIALIAS;
visual_2d_texture_path(tr_state->visual, st->graph->path, ctx, tr_state);
}
tr_state->col_key = NULL;
}
static void TraverseBitmap(GF_Node *node, void *rs, Bool is_destroy)
{
GF_Rect rc;
DrawableContext *ctx;
BitmapStack *st = (BitmapStack *)gf_node_get_private(node);
GF_TraverseState *tr_state = (GF_TraverseState *)rs;
if (is_destroy) {
drawable_del(st->graph);
gf_free(st);
return;
}
switch (tr_state->traversing_mode) {
case TRAVERSE_DRAW_2D:
draw_bitmap_2d(node, tr_state);
return;
#ifndef GPAC_DISABLE_3D
case TRAVERSE_DRAW_3D:
draw_bitmap_3d(node, tr_state);
return;
#endif
case TRAVERSE_PICK:
vrml_drawable_pick(st->graph, tr_state);
return;
case TRAVERSE_GET_BOUNDS:
Bitmap_BuildGraph(node, st, tr_state, &tr_state->bounds,
#ifndef GPAC_DISABLE_3D
tr_state->visual->type_3d ? 1 : 0
#else
0
#endif
);
return;
case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
if (tr_state->visual->type_3d) return;
#endif
break;
default:
return;
}
memset(&rc, 0, sizeof(rc));
Bitmap_BuildGraph(node, st, tr_state, &rc, 1);
if (!rc.width || !rc.height) return;
ctx = drawable_init_context_mpeg4(st->graph, tr_state);
if (!ctx || !ctx->aspect.fill_texture ) {
visual_2d_remove_last_context(tr_state->visual);
return;
}
ctx->aspect.pen_props.width = 0;
ctx->flags |= CTX_NO_ANTIALIAS;
ctx->flags &= ~CTX_IS_TRANSPARENT;
if (ctx->aspect.fill_texture->transparent) {
ctx->flags |= CTX_IS_TRANSPARENT;
} else {
M_Appearance *app = (M_Appearance *)ctx->appear;
if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
if (((M_MaterialKey*)app->material)->isKeyed) {
if (((M_MaterialKey*)app->material)->transparency==FIX_ONE) {
visual_2d_remove_last_context(tr_state->visual);
return;
}
ctx->flags |= CTX_IS_TRANSPARENT;
}
}
else if (!tr_state->color_mat.identity) {
ctx->flags |= CTX_IS_TRANSPARENT;
} else {
u8 alpha = GF_COL_A(ctx->aspect.fill_color);
if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color);
if (alpha < 0xFF) ctx->flags |= CTX_IS_TRANSPARENT;
}
}
drawable_finalize_sort(ctx, tr_state, &rc);
}
void compositor_init_bitmap(GF_Compositor *compositor, GF_Node *node)
{
BitmapStack *st;
GF_SAFEALLOC(st, BitmapStack);
if (!st) {
GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate bitmap stack\n"));
return;
}
st->graph = drawable_new();
st->graph->node = node;
st->graph->flags = DRAWABLE_USE_TRAVERSE_DRAW;
gf_node_set_private(node, st);
gf_node_set_callback_function(node, TraverseBitmap);
}
#endif