LCOV - code coverage report
Current view: top level - compositor - mpeg4_bitmap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 132 138 95.7 %
Date: 2021-04-29 23:48:07 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : 
      28             : #include "nodes_stacks.h"
      29             : #include "visual_manager.h"
      30             : #include "texturing.h"
      31             : 
      32             : #ifndef GPAC_DISABLE_VRML
      33             : 
      34             : typedef struct _bitmap_stack
      35             : {
      36             :         Drawable s_graph;
      37             :         /*cached size for 3D mode*/
      38             :         SFVec2f size, scale;
      39             :         u32 prev_tx_w, prev_tx_h;
      40             :         GF_Rect rc, unclip_rc;
      41             : } BitmapStack;
      42             : 
      43             : 
      44             : 
      45        8076 : static void Bitmap_BuildGraph(GF_Node *node, BitmapStack *st, GF_TraverseState *tr_state, GF_Rect *out_rc, Bool notify_changes)
      46             : {
      47             :         GF_TextureHandler *txh;
      48             :         Fixed sx, sy;
      49             :         SFVec2f size;
      50             : 
      51             :         M_Bitmap *bmp = (M_Bitmap *)node;
      52             : 
      53       15667 :         if (!tr_state->appear) return;
      54        7982 :         if (! ((M_Appearance *)tr_state->appear)->texture) return;
      55        7934 :         txh = gf_sc_texture_get_handler( ((M_Appearance *)tr_state->appear)->texture );
      56             :         /*bitmap not ready*/
      57        7934 :         if (!txh || !txh->width || !txh->height
      58             : #ifndef GPAC_DISABLE_3D
      59        6929 :                 || (tr_state->visual->type_3d && !txh->tx_io)
      60             : #endif
      61             :            ) {
      62        1005 :                 if (notify_changes) gf_node_dirty_set(node, 0, 1);
      63             :                 return;
      64             :         }
      65             :         /*no change in scale and same texture size*/
      66        6929 :         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)) {
      67        6444 :                 *out_rc = st->rc;
      68        6444 :                 gf_node_dirty_clear(node, 0);
      69        6444 :                 return;
      70             :         }
      71             : 
      72         485 :         st->prev_tx_w = txh->width;
      73         485 :         st->prev_tx_h = txh->height;
      74             : 
      75         485 :         sx = bmp->scale.x;
      76         485 :         if (sx<0) sx = FIX_ONE;
      77         485 :         sy = bmp->scale.y;
      78         485 :         if (sy<0) sy = FIX_ONE;
      79         485 :         st->scale = bmp->scale;
      80             : 
      81         485 :         compositor_adjust_scale(txh->owner, &sx, &sy);
      82             : 
      83             :         /*check size change*/
      84         485 :         size.x = gf_mulfix(INT2FIX(txh->width),sx);
      85         485 :         size.y =  gf_mulfix(INT2FIX(txh->height),sy);
      86             :         /*if we have a PAR update it!!*/
      87         485 :         if (txh->pixel_ar) {
      88          13 :                 u32 n = (txh->pixel_ar>>16) & 0xFFFF;
      89          13 :                 u32 d = (txh->pixel_ar) & 0xFFFF;
      90          13 :                 size.x = gf_mulfix(INT2FIX( (txh->width * n) / d),sx);
      91             :         }
      92             : 
      93             : 
      94             :         /*we're in meter metrics*/
      95         485 :         if (!tr_state->pixel_metrics) {
      96           3 :                 size.x = gf_divfix(size.x, tr_state->min_hsize);
      97           3 :                 size.y = gf_divfix(size.y, tr_state->min_hsize);
      98             :         }
      99         485 :         *out_rc = st->rc = gf_rect_center(size.x, size.y);
     100             : 
     101         485 :         gf_node_dirty_clear(node, 0);
     102             : 
     103         485 :         if ((st->size.x==size.x) && (st->size.y==size.y)) return;
     104         485 :         st->size = size;
     105             : 
     106             :         /*change in size*/
     107         485 :         if (notify_changes) gf_node_dirty_set(node, 0, 1);
     108             : 
     109             :         /*get size with scale*/
     110         485 :         drawable_reset_path(&st->s_graph);
     111         485 :         gf_path_add_rect_center(st->s_graph.path, 0, 0, st->size.x, st->size.y);
     112             : }
     113             : 
     114             : #ifndef GPAC_DISABLE_3D
     115         771 : static void draw_bitmap_3d(GF_Node *node, GF_TraverseState *tr_state)
     116             : {
     117             :         GF_Node *appear;
     118             :         DrawAspect2D asp;
     119             :         GF_ColorKey keyColor;
     120         771 :         BitmapStack *st = (BitmapStack *)gf_node_get_private(node);
     121             :         M_Bitmap *bmp = (M_Bitmap *)node;
     122             : 
     123             :         /*no choice but to update the graph since a bitmap may be used with several textures ...*/
     124         771 :         Bitmap_BuildGraph(node, st, tr_state, &tr_state->bounds, 0);
     125             : 
     126             :         memset(&asp, 0, sizeof(DrawAspect2D));
     127         771 :         drawable_get_aspect_2d_mpeg4(node, &asp, tr_state);
     128             : 
     129         771 :         appear = tr_state->override_appearance ? tr_state->override_appearance : tr_state->appear;
     130             :         /*check for material key materialKey*/
     131         771 :         if (appear) {
     132             :                 M_Appearance *app = (M_Appearance *)appear;
     133         681 :                 if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
     134          46 :                         M_MaterialKey*mk = (M_MaterialKey*)app->material;
     135          46 :                         if (mk->isKeyed) {
     136          46 :                                 keyColor.r = FIX2INT(mk->keyColor.red * 255);
     137          46 :                                 keyColor.g = FIX2INT(mk->keyColor.green * 255);
     138          46 :                                 keyColor.b = FIX2INT(mk->keyColor.blue * 255);
     139          46 :                                 keyColor.alpha = FIX2INT( (FIX_ONE - mk->transparency) * 255);
     140          46 :                                 keyColor.low = FIX2INT(mk->lowThreshold * 255);
     141          46 :                                 keyColor.high = FIX2INT(mk->highThreshold * 255);
     142          46 :                                 tr_state->col_key = &keyColor;
     143             :                         }
     144             :                 }
     145             :         }
     146             : 
     147         771 :         compositor_3d_draw_bitmap(&st->s_graph, &asp, tr_state, st->size.x, st->size.y, bmp->scale.x, bmp->scale.y);
     148             : 
     149         771 :         tr_state->col_key = NULL;
     150         771 : }
     151             : #endif
     152             : 
     153        5897 : static void draw_bitmap_2d(GF_Node *node, GF_TraverseState *tr_state)
     154             : {
     155             :         GF_ColorKey keyColor;
     156        5897 :         DrawableContext *ctx = tr_state->ctx;
     157        5897 :         BitmapStack *st = (BitmapStack *) gf_node_get_private(node);
     158             : 
     159             : 
     160             :         /*bitmaps are NEVER rotated (forbidden in spec). In case a rotation was done we still display (reset the skew components)*/
     161        5897 :         ctx->transform.m[1] = ctx->transform.m[3] = 0;
     162             : 
     163             :         /*check for material key materialKey*/
     164        5897 :         if (ctx->appear) {
     165             :                 M_Appearance *app = (M_Appearance *)ctx->appear;
     166        5897 :                 if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
     167         121 :                         M_MaterialKey*mk = (M_MaterialKey*)app->material;
     168         121 :                         if (mk->isKeyed) {
     169         121 :                                 keyColor.r = FIX2INT(mk->keyColor.red * 255);
     170         121 :                                 keyColor.g = FIX2INT(mk->keyColor.green * 255);
     171         121 :                                 keyColor.b = FIX2INT(mk->keyColor.blue * 255);
     172         121 :                                 keyColor.alpha = FIX2INT( (FIX_ONE - mk->transparency) * 255);
     173         121 :                                 keyColor.low = FIX2INT(mk->lowThreshold * 255);
     174         121 :                                 keyColor.high = FIX2INT(mk->highThreshold * 255);
     175         121 :                                 tr_state->col_key = &keyColor;
     176             : 
     177             :                         }
     178             :                 }
     179             :         }
     180             : 
     181             :         /*no HW, fall back to the graphics driver*/
     182        5897 :         if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx)) {
     183             :                 GF_Matrix2D _mat;
     184         331 :                 GF_Rect rc = gf_rect_center(ctx->bi->unclip.width, ctx->bi->unclip.height);
     185         331 :                 gf_mx2d_copy(_mat, ctx->transform);
     186         331 :                 gf_mx2d_inverse(&_mat);
     187         331 :                 gf_mx2d_apply_rect(&_mat, &rc);
     188         331 :                 if ((st->unclip_rc.width != rc.width) || (st->unclip_rc.height != rc.height)) {
     189         116 :                         drawable_reset_path(&st->s_graph);
     190         116 :                         gf_path_add_rect_center(st->s_graph.path, 0, 0, rc.width, rc.height);
     191         116 :                         st->unclip_rc = rc;
     192             :                 }
     193         331 :                 ctx->flags |= CTX_NO_ANTIALIAS;
     194         331 :                 visual_2d_texture_path(tr_state->visual, st->s_graph.path, ctx, tr_state);
     195             :         }
     196        5897 :         tr_state->col_key = NULL;
     197        5897 : }
     198             : 
     199       14924 : static void TraverseBitmap(GF_Node *node, void *rs, Bool is_destroy)
     200             : {
     201             :         GF_Rect rc;
     202             :         Bool rectangle_check_adaptation(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state);
     203             :         DrawableContext *ctx;
     204       14924 :         BitmapStack *st = (BitmapStack *)gf_node_get_private(node);
     205             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     206             : 
     207       14924 :         if (is_destroy) {
     208         272 :                 drawable_del_ex(&st->s_graph, gf_sc_get_compositor(node), GF_TRUE);
     209         272 :                 gf_free(st);
     210         272 :                 return;
     211             :         }
     212       14652 :         if (! rectangle_check_adaptation(node, &st->s_graph, tr_state))
     213             :                 return;
     214             : 
     215       14652 :         switch (tr_state->traversing_mode) {
     216        5897 :         case TRAVERSE_DRAW_2D:
     217        5897 :                 draw_bitmap_2d(node, tr_state);
     218        5897 :                 return;
     219             : #ifndef GPAC_DISABLE_3D
     220         771 :         case TRAVERSE_DRAW_3D:
     221         771 :                 draw_bitmap_3d(node, tr_state);
     222         771 :                 return;
     223             : #endif
     224         679 :         case TRAVERSE_PICK:
     225             :                 //drawable_pick(st->graph, tr_state);
     226         679 :                 vrml_drawable_pick(&st->s_graph, tr_state);
     227         679 :                 return;
     228         172 :         case TRAVERSE_GET_BOUNDS:
     229         172 :                 Bitmap_BuildGraph(node, st, tr_state, &tr_state->bounds,
     230             : #ifndef GPAC_DISABLE_3D
     231         172 :                                   tr_state->visual->type_3d ? 1 : 0
     232             : #else
     233             :                                   0
     234             : #endif
     235             :                                  );
     236             : 
     237         172 :                 return;
     238        7133 :         case TRAVERSE_SORT:
     239             : #ifndef GPAC_DISABLE_3D
     240        7133 :                 if (tr_state->visual->type_3d) return;
     241             : #endif
     242             :                 break;
     243             :         default:
     244             :                 return;
     245             :         }
     246             : 
     247             :         memset(&rc, 0, sizeof(rc));
     248        7133 :         Bitmap_BuildGraph(node, st, tr_state, &rc, 1);
     249        7133 :         if (!rc.width || !rc.height) return;
     250             : 
     251        6153 :         ctx = drawable_init_context_mpeg4(&st->s_graph, tr_state);
     252        6153 :         if (!ctx || !ctx->aspect.fill_texture ) {
     253           0 :                 visual_2d_remove_last_context(tr_state->visual);
     254           0 :                 return;
     255             :         }
     256             : 
     257             : 
     258             :         /*even if set this is not true*/
     259        6153 :         ctx->aspect.pen_props.width = 0;
     260        6153 :         ctx->flags |= CTX_NO_ANTIALIAS;
     261             : 
     262        6153 :         ctx->flags &= ~CTX_IS_TRANSPARENT;
     263             :         /*if clipper then transparent*/
     264             : 
     265        6153 :         if (ctx->aspect.fill_texture->transparent) {
     266         315 :                 ctx->flags |= CTX_IS_TRANSPARENT;
     267             :         } else {
     268        5838 :                 M_Appearance *app = (M_Appearance *)ctx->appear;
     269        5838 :                 if ( app->material && (gf_node_get_tag((GF_Node *)app->material)==TAG_MPEG4_MaterialKey) ) {
     270         121 :                         if (((M_MaterialKey*)app->material)->isKeyed) {
     271         121 :                                 if (((M_MaterialKey*)app->material)->transparency==FIX_ONE) {
     272           0 :                                         visual_2d_remove_last_context(tr_state->visual);
     273           0 :                                         return;
     274             :                                 }
     275         121 :                                 ctx->flags |= CTX_IS_TRANSPARENT;
     276             :                         }
     277             :                 }
     278        5717 :                 else if (!tr_state->color_mat.identity) {
     279           0 :                         ctx->flags |= CTX_IS_TRANSPARENT;
     280             :                 } else {
     281        5717 :                         u8 alpha = GF_COL_A(ctx->aspect.fill_color);
     282             :                         /*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
     283        5717 :                         if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color);
     284        5717 :                         if (alpha < 0xFF) ctx->flags |= CTX_IS_TRANSPARENT;
     285             :                 }
     286             :         }
     287             : 
     288             :         /*bounds are stored when building graph*/
     289        6153 :         drawable_finalize_sort(ctx, tr_state, &rc);
     290             : }
     291             : 
     292             : 
     293         272 : void compositor_init_bitmap(GF_Compositor  *compositor, GF_Node *node)
     294             : {
     295             :         BitmapStack *st;
     296         272 :         GF_SAFEALLOC(st, BitmapStack);
     297         272 :         if (!st) {
     298           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate bitmap stack\n"));
     299             :                 return;
     300             :         }
     301         272 :         drawable_init_ex(&st->s_graph);
     302         272 :         st->s_graph.node = node;
     303         272 :         st->s_graph.flags = DRAWABLE_USE_TRAVERSE_DRAW;
     304         272 :         gf_node_set_private(node, st);
     305         272 :         gf_node_set_callback_function(node, TraverseBitmap);
     306             : }
     307             : 
     308             : #endif
     309             : 

Generated by: LCOV version 1.13